1 /*
2  *  Single source autogenerated distributable for Duktape 2.6.0.
3  *
4  *  Git commit fffa346eff06a8764b02c31d4336f63a773a95c3 (v2.6.0).
5  *  Git branch v2-maintenance.
6  *
7  *  See Duktape AUTHORS.rst and LICENSE.txt for copyright and
8  *  licensing information.
9  */
10 
11 /* LICENSE.txt */
12 /*
13 *  ===============
14 *  Duktape license
15 *  ===============
16 *
17 *  (http://opensource.org/licenses/MIT)
18 *
19 *  Copyright (c) 2013-2019 by Duktape authors (see AUTHORS.rst)
20 *
21 *  Permission is hereby granted, free of charge, to any person obtaining a copy
22 *  of this software and associated documentation files (the "Software"), to deal
23 *  in the Software without restriction, including without limitation the rights
24 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25 *  copies of the Software, and to permit persons to whom the Software is
26 *  furnished to do so, subject to the following conditions:
27 *
28 *  The above copyright notice and this permission notice shall be included in
29 *  all copies or substantial portions of the Software.
30 *
31 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37 *  THE SOFTWARE.
38 */
39 
40 /* AUTHORS.rst */
41 /*
42 *  ===============
43 *  Duktape authors
44 *  ===============
45 *
46 *  Copyright
47 *  =========
48 *
49 *  Duktape copyrights are held by its authors.  Each author has a copyright
50 *  to their contribution, and agrees to irrevocably license the contribution
51 *  under the Duktape ``LICENSE.txt``.
52 *
53 *  Authors
54 *  =======
55 *
56 *  Please include an e-mail address, a link to your GitHub profile, or something
57 *  similar to allow your contribution to be identified accurately.
58 *
59 *  The following people have contributed code, website contents, or Wiki contents,
60 *  and agreed to irrevocably license their contributions under the Duktape
61 *  ``LICENSE.txt`` (in order of appearance):
62 *
63 *  * Sami Vaarala <sami.vaarala@iki.fi>
64 *  * Niki Dobrev
65 *  * Andreas \u00d6man <andreas@lonelycoder.com>
66 *  * L\u00e1szl\u00f3 Lang\u00f3 <llango.u-szeged@partner.samsung.com>
67 *  * Legimet <legimet.calc@gmail.com>
68 *  * Karl Skomski <karl@skomski.com>
69 *  * Bruce Pascoe <fatcerberus1@gmail.com>
70 *  * Ren\u00e9 Hollander <rene@rene8888.at>
71 *  * Julien Hamaide (https://github.com/crazyjul)
72 *  * Sebastian G\u00f6tte (https://github.com/jaseg)
73 *  * Tomasz Magulski (https://github.com/magul)
74 *  * \D. Bohdan (https://github.com/dbohdan)
75 *  * Ond\u0159ej Jirman (https://github.com/megous)
76 *  * Sa\u00fal Ibarra Corretg\u00e9 <saghul@gmail.com>
77 *  * Jeremy HU <huxingyi@msn.com>
78 *  * Ole Andr\u00e9 Vadla Ravn\u00e5s (https://github.com/oleavr)
79 *  * Harold Brenes (https://github.com/harold-b)
80 *  * Oliver Crow (https://github.com/ocrow)
81 *  * Jakub Ch\u0142api\u0144ski (https://github.com/jchlapinski)
82 *  * Brett Vickers (https://github.com/beevik)
83 *  * Dominik Okwieka (https://github.com/okitec)
84 *  * Remko Tron\u00e7on (https://el-tramo.be)
85 *  * Romero Malaquias (rbsm@ic.ufal.br)
86 *  * Michael Drake <michael.drake@codethink.co.uk>
87 *  * Steven Don (https://github.com/shdon)
88 *  * Simon Stone (https://github.com/sstone1)
89 *  * \J. McC. (https://github.com/jmhmccr)
90 *  * Jakub Nowakowski (https://github.com/jimvonmoon)
91 *  * Tommy Nguyen (https://github.com/tn0502)
92 *  * Fabrice Fontaine (https://github.com/ffontaine)
93 *  * Christopher Hiller (https://github.com/boneskull)
94 *  * Gonzalo Diethelm (https://github.com/gonzus)
95 *  * Michal Kasperek (https://github.com/michalkas)
96 *  * Andrew Janke (https://github.com/apjanke)
97 *  * Steve Fan (https://github.com/stevefan1999)
98 *  * Edward Betts (https://github.com/edwardbetts)
99 *  * Ozhan Duz (https://github.com/webfolderio)
100 *  * Akos Kiss (https://github.com/akosthekiss)
101 *  * TheBrokenRail (https://github.com/TheBrokenRail)
102 *  * Jesse Doyle (https://github.com/jessedoyle)
103 *  * Gero Kuehn (https://github.com/dc6jgk)
104 *  * James Swift (https://github.com/phraemer)
105 *  * Luis de Bethencourt (https://github.com/luisbg)
106 *  * Ian Whyman (https://github.com/v00d00)
107 *  * Rick Sayre (https://github.com/whorfin)
108 *
109 *  Other contributions
110 *  ===================
111 *
112 *  The following people have contributed something other than code (e.g. reported
113 *  bugs, provided ideas, etc; roughly in order of appearance):
114 *
115 *  * Greg Burns
116 *  * Anthony Rabine
117 *  * Carlos Costa
118 *  * Aur\u00e9lien Bouilland
119 *  * Preet Desai (Pris Matic)
120 *  * judofyr (http://www.reddit.com/user/judofyr)
121 *  * Jason Woofenden
122 *  * Micha\u0142 Przyby\u015b
123 *  * Anthony Howe
124 *  * Conrad Pankoff
125 *  * Jim Schimpf
126 *  * Rajaran Gaunker (https://github.com/zimbabao)
127 *  * Andreas \u00d6man
128 *  * Doug Sanden
129 *  * Josh Engebretson (https://github.com/JoshEngebretson)
130 *  * Remo Eichenberger (https://github.com/remoe)
131 *  * Mamod Mehyar (https://github.com/mamod)
132 *  * David Demelier (https://github.com/markand)
133 *  * Tim Caswell (https://github.com/creationix)
134 *  * Mitchell Blank Jr (https://github.com/mitchblank)
135 *  * https://github.com/yushli
136 *  * Seo Sanghyeon (https://github.com/sanxiyn)
137 *  * Han ChoongWoo (https://github.com/tunz)
138 *  * Joshua Peek (https://github.com/josh)
139 *  * Bruce E. Pascoe (https://github.com/fatcerberus)
140 *  * https://github.com/Kelledin
141 *  * https://github.com/sstruchtrup
142 *  * Michael Drake (https://github.com/tlsa)
143 *  * https://github.com/chris-y
144 *  * Laurent Zubiaur (https://github.com/lzubiaur)
145 *  * Neil Kolban (https://github.com/nkolban)
146 *  * Wilhelm Wanecek (https://github.com/wanecek)
147 *  * Andrew Janke (https://github.com/apjanke)
148 *  * Unamer (https://github.com/unamer)
149 *  * Karl Dahlke (eklhad@gmail.com)
150 *
151 *  If you are accidentally missing from this list, send me an e-mail
152 *  (``sami.vaarala@iki.fi``) and I'll fix the omission.
153 */
154 
155 #line 1 "duk_replacements.c"
156 /*
157  *  Replacements for missing platform functions.
158  *
159  *  Unlike the originals, fpclassify() and signbit() replacements don't
160  *  work on any floating point types, only doubles.  The C typing here
161  *  mimics the standard prototypes.
162  */
163 
164 /* #include duk_internal.h */
165 #line 1 "duk_internal.h"
166 /*
167  *  Top-level include file to be used for all (internal) source files.
168  *
169  *  Source files should not include individual header files, as they
170  *  have not been designed to be individually included.
171  */
172 
173 #if !defined(DUK_INTERNAL_H_INCLUDED)
174 #define DUK_INTERNAL_H_INCLUDED
175 
176 /*
177  *  The 'duktape.h' header provides the public API, but also handles all
178  *  compiler and platform specific feature detection, Duktape feature
179  *  resolution, inclusion of system headers, etc.  These have been merged
180  *  because the public API is also dependent on e.g. detecting appropriate
181  *  C types which is quite platform/compiler specific especially for a non-C99
182  *  build.  The public API is also dependent on the resolved feature set.
183  *
184  *  Some actions taken by the merged header (such as including system headers)
185  *  are not appropriate for building a user application.  The define
186  *  DUK_COMPILING_DUKTAPE allows the merged header to skip/include some
187  *  sections depending on what is being built.
188  */
189 
190 #define DUK_COMPILING_DUKTAPE
191 #include "duktape.h"
192 
193 /*
194  *  Duktape includes (other than duk_features.h)
195  *
196  *  The header files expect to be included in an order which satisfies header
197  *  dependencies correctly (the headers themselves don't include any other
198  *  includes).  Forward declarations are used to break circular struct/typedef
199  *  dependencies.
200  */
201 
202 /* #include duk_dblunion.h */
203 #line 1 "duk_dblunion.h"
204 /*
205  *  Union to access IEEE double memory representation, indexes for double
206  *  memory representation, and some macros for double manipulation.
207  *
208  *  Also used by packed duk_tval.  Use a union for bit manipulation to
209  *  minimize aliasing issues in practice.  The C99 standard does not
210  *  guarantee that this should work, but it's a very widely supported
211  *  practice for low level manipulation.
212  *
213  *  IEEE double format summary:
214  *
215  *    seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
216  *       A        B        C        D        E        F        G        H
217  *
218  *    s       sign bit
219  *    eee...  exponent field
220  *    fff...  fraction
221  *
222  *  See http://en.wikipedia.org/wiki/Double_precision_floating-point_format.
223  *
224  *  NaNs are represented as exponent 0x7ff and mantissa != 0.  The NaN is a
225  *  signaling NaN when the highest bit of the mantissa is zero, and a quiet
226  *  NaN when the highest bit is set.
227  *
228  *  At least three memory layouts are relevant here:
229  *
230  *    A B C D E F G H    Big endian (e.g. 68k)           DUK_USE_DOUBLE_BE
231  *    H G F E D C B A    Little endian (e.g. x86)        DUK_USE_DOUBLE_LE
232  *    D C B A H G F E    Mixed endian (e.g. ARM FPA)     DUK_USE_DOUBLE_ME
233  *
234  *  Legacy ARM (FPA) is a special case: ARM double values are in mixed
235  *  endian format while ARM duk_uint64_t values are in standard little endian
236  *  format (H G F E D C B A).  When a double is read as a duk_uint64_t
237  *  from memory, the register will contain the (logical) value
238  *  E F G H A B C D.  This requires some special handling below.
239  *  See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0056d/Bcfhgcgd.html.
240  *
241  *  Indexes of various types (8-bit, 16-bit, 32-bit) in memory relative to
242  *  the logical (big endian) order:
243  *
244  *  byte order      duk_uint8_t    duk_uint16_t     duk_uint32_t
245  *    BE             01234567         0123               01
246  *    LE             76543210         3210               10
247  *    ME (ARM)       32107654         1032               01
248  *
249  *  Some processors may alter NaN values in a floating point load+store.
250  *  For instance, on X86 a FLD + FSTP may convert a signaling NaN to a
251  *  quiet one.  This is catastrophic when NaN space is used in packed
252  *  duk_tval values.  See: misc/clang_aliasing.c.
253  */
254 
255 #if !defined(DUK_DBLUNION_H_INCLUDED)
256 #define DUK_DBLUNION_H_INCLUDED
257 
258 /*
259  *  Union for accessing double parts, also serves as packed duk_tval
260  */
261 
262 union duk_double_union {
263 	double d;
264 	float f[2];
265 #if defined(DUK_USE_64BIT_OPS)
266 	duk_uint64_t ull[1];
267 #endif
268 	duk_uint32_t ui[2];
269 	duk_uint16_t us[4];
270 	duk_uint8_t uc[8];
271 #if defined(DUK_USE_PACKED_TVAL)
272 	void *vp[2];  /* used by packed duk_tval, assumes sizeof(void *) == 4 */
273 #endif
274 };
275 
276 typedef union duk_double_union duk_double_union;
277 
278 /*
279  *  Indexes of various types with respect to big endian (logical) layout
280  */
281 
282 #if defined(DUK_USE_DOUBLE_LE)
283 #if defined(DUK_USE_64BIT_OPS)
284 #define DUK_DBL_IDX_ULL0   0
285 #endif
286 #define DUK_DBL_IDX_UI0    1
287 #define DUK_DBL_IDX_UI1    0
288 #define DUK_DBL_IDX_US0    3
289 #define DUK_DBL_IDX_US1    2
290 #define DUK_DBL_IDX_US2    1
291 #define DUK_DBL_IDX_US3    0
292 #define DUK_DBL_IDX_UC0    7
293 #define DUK_DBL_IDX_UC1    6
294 #define DUK_DBL_IDX_UC2    5
295 #define DUK_DBL_IDX_UC3    4
296 #define DUK_DBL_IDX_UC4    3
297 #define DUK_DBL_IDX_UC5    2
298 #define DUK_DBL_IDX_UC6    1
299 #define DUK_DBL_IDX_UC7    0
300 #define DUK_DBL_IDX_VP0    DUK_DBL_IDX_UI0  /* packed tval */
301 #define DUK_DBL_IDX_VP1    DUK_DBL_IDX_UI1  /* packed tval */
302 #elif defined(DUK_USE_DOUBLE_BE)
303 #if defined(DUK_USE_64BIT_OPS)
304 #define DUK_DBL_IDX_ULL0   0
305 #endif
306 #define DUK_DBL_IDX_UI0    0
307 #define DUK_DBL_IDX_UI1    1
308 #define DUK_DBL_IDX_US0    0
309 #define DUK_DBL_IDX_US1    1
310 #define DUK_DBL_IDX_US2    2
311 #define DUK_DBL_IDX_US3    3
312 #define DUK_DBL_IDX_UC0    0
313 #define DUK_DBL_IDX_UC1    1
314 #define DUK_DBL_IDX_UC2    2
315 #define DUK_DBL_IDX_UC3    3
316 #define DUK_DBL_IDX_UC4    4
317 #define DUK_DBL_IDX_UC5    5
318 #define DUK_DBL_IDX_UC6    6
319 #define DUK_DBL_IDX_UC7    7
320 #define DUK_DBL_IDX_VP0    DUK_DBL_IDX_UI0  /* packed tval */
321 #define DUK_DBL_IDX_VP1    DUK_DBL_IDX_UI1  /* packed tval */
322 #elif defined(DUK_USE_DOUBLE_ME)
323 #if defined(DUK_USE_64BIT_OPS)
324 #define DUK_DBL_IDX_ULL0   0  /* not directly applicable, byte order differs from a double */
325 #endif
326 #define DUK_DBL_IDX_UI0    0
327 #define DUK_DBL_IDX_UI1    1
328 #define DUK_DBL_IDX_US0    1
329 #define DUK_DBL_IDX_US1    0
330 #define DUK_DBL_IDX_US2    3
331 #define DUK_DBL_IDX_US3    2
332 #define DUK_DBL_IDX_UC0    3
333 #define DUK_DBL_IDX_UC1    2
334 #define DUK_DBL_IDX_UC2    1
335 #define DUK_DBL_IDX_UC3    0
336 #define DUK_DBL_IDX_UC4    7
337 #define DUK_DBL_IDX_UC5    6
338 #define DUK_DBL_IDX_UC6    5
339 #define DUK_DBL_IDX_UC7    4
340 #define DUK_DBL_IDX_VP0    DUK_DBL_IDX_UI0  /* packed tval */
341 #define DUK_DBL_IDX_VP1    DUK_DBL_IDX_UI1  /* packed tval */
342 #else
343 #error internal error
344 #endif
345 
346 /*
347  *  Helper macros for reading/writing memory representation parts, used
348  *  by duk_numconv.c and duk_tval.h.
349  */
350 
351 #define DUK_DBLUNION_SET_DOUBLE(u,v)  do {  \
352 		(u)->d = (v); \
353 	} while (0)
354 
355 #define DUK_DBLUNION_SET_HIGH32(u,v)  do {  \
356 		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) (v); \
357 	} while (0)
358 
359 #if defined(DUK_USE_64BIT_OPS)
360 #if defined(DUK_USE_DOUBLE_ME)
361 #define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v)  do { \
362 		(u)->ull[DUK_DBL_IDX_ULL0] = (duk_uint64_t) (v); \
363 	} while (0)
364 #else
365 #define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v)  do { \
366 		(u)->ull[DUK_DBL_IDX_ULL0] = ((duk_uint64_t) (v)) << 32; \
367 	} while (0)
368 #endif
369 #else  /* DUK_USE_64BIT_OPS */
370 #define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v)  do { \
371 		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) (v); \
372 		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) 0; \
373 	} while (0)
374 #endif  /* DUK_USE_64BIT_OPS */
375 
376 #define DUK_DBLUNION_SET_LOW32(u,v)  do {  \
377 		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (v); \
378 	} while (0)
379 
380 #define DUK_DBLUNION_GET_DOUBLE(u)  ((u)->d)
381 #define DUK_DBLUNION_GET_HIGH32(u)  ((u)->ui[DUK_DBL_IDX_UI0])
382 #define DUK_DBLUNION_GET_LOW32(u)   ((u)->ui[DUK_DBL_IDX_UI1])
383 
384 #if defined(DUK_USE_64BIT_OPS)
385 #if defined(DUK_USE_DOUBLE_ME)
386 #define DUK_DBLUNION_SET_UINT64(u,v)  do { \
387 		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) ((v) >> 32); \
388 		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (v); \
389 	} while (0)
390 #define DUK_DBLUNION_GET_UINT64(u) \
391 	((((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI0]) << 32) | \
392 	 ((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI1]))
393 #else
394 #define DUK_DBLUNION_SET_UINT64(u,v)  do { \
395 		(u)->ull[DUK_DBL_IDX_ULL0] = (duk_uint64_t) (v); \
396 	} while (0)
397 #define DUK_DBLUNION_GET_UINT64(u)  ((u)->ull[DUK_DBL_IDX_ULL0])
398 #endif
399 #define DUK_DBLUNION_SET_INT64(u,v) DUK_DBLUNION_SET_UINT64((u), (duk_uint64_t) (v))
400 #define DUK_DBLUNION_GET_INT64(u)   ((duk_int64_t) DUK_DBLUNION_GET_UINT64((u)))
401 #endif  /* DUK_USE_64BIT_OPS */
402 
403 /*
404  *  Double NaN manipulation macros related to NaN normalization needed when
405  *  using the packed duk_tval representation.  NaN normalization is necessary
406  *  to keep double values compatible with the duk_tval format.
407  *
408  *  When packed duk_tval is used, the NaN space is used to store pointers
409  *  and other tagged values in addition to NaNs.  Actual NaNs are normalized
410  *  to a specific quiet NaN.  The macros below are used by the implementation
411  *  to check and normalize NaN values when they might be created.  The macros
412  *  are essentially NOPs when the non-packed duk_tval representation is used.
413  *
414  *  A FULL check is exact and checks all bits.  A NOTFULL check is used by
415  *  the packed duk_tval and works correctly for all NaNs except those that
416  *  begin with 0x7ff0.  Since the 'normalized NaN' values used with packed
417  *  duk_tval begin with 0x7ff8, the partial check is reliable when packed
418  *  duk_tval is used.  The 0x7ff8 prefix means the normalized NaN will be a
419  *  quiet NaN regardless of its remaining lower bits.
420  *
421  *  The ME variant below is specifically for ARM byte order, which has the
422  *  feature that while doubles have a mixed byte order (32107654), unsigned
423  *  long long values has a little endian byte order (76543210).  When writing
424  *  a logical double value through a ULL pointer, the 32-bit words need to be
425  *  swapped; hence the #if defined()s below for ULL writes with DUK_USE_DOUBLE_ME.
426  *  This is not full ARM support but suffices for some environments.
427  */
428 
429 #if defined(DUK_USE_64BIT_OPS)
430 #if defined(DUK_USE_DOUBLE_ME)
431 /* Macros for 64-bit ops + mixed endian doubles. */
432 #define DUK__DBLUNION_SET_NAN_FULL(u)  do { \
433 		(u)->ull[DUK_DBL_IDX_ULL0] = DUK_U64_CONSTANT(0x000000007ff80000); \
434 	} while (0)
435 #define DUK__DBLUNION_IS_NAN_FULL(u) \
436 	((((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000)) && \
437 	 ((((u)->ull[DUK_DBL_IDX_ULL0]) & DUK_U64_CONSTANT(0xffffffff000fffff)) != 0))
438 #define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \
439 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x000000007ff80000))
440 #define DUK__DBLUNION_IS_ANYINF(u) \
441 	(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0xffffffff7fffffff)) == DUK_U64_CONSTANT(0x000000007ff00000))
442 #define DUK__DBLUNION_IS_POSINF(u) \
443 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x000000007ff00000))
444 #define DUK__DBLUNION_IS_NEGINF(u) \
445 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x00000000fff00000))
446 #define DUK__DBLUNION_IS_ANYZERO(u) \
447 	(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0xffffffff7fffffff)) == DUK_U64_CONSTANT(0x0000000000000000))
448 #define DUK__DBLUNION_IS_POSZERO(u) \
449 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000000000000))
450 #define DUK__DBLUNION_IS_NEGZERO(u) \
451 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000080000000))
452 #else
453 /* Macros for 64-bit ops + big/little endian doubles. */
454 #define DUK__DBLUNION_SET_NAN_FULL(u)  do { \
455 		(u)->ull[DUK_DBL_IDX_ULL0] = DUK_U64_CONSTANT(0x7ff8000000000000); \
456 	} while (0)
457 #define DUK__DBLUNION_IS_NAN_FULL(u) \
458 	((((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000)) && \
459 	 ((((u)->ull[DUK_DBL_IDX_ULL0]) & DUK_U64_CONSTANT(0x000fffffffffffff)) != 0))
460 #define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \
461 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x7ff8000000000000))
462 #define DUK__DBLUNION_IS_ANYINF(u) \
463 	(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7fffffffffffffff)) == DUK_U64_CONSTANT(0x7ff0000000000000))
464 #define DUK__DBLUNION_IS_POSINF(u) \
465 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x7ff0000000000000))
466 #define DUK__DBLUNION_IS_NEGINF(u) \
467 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0xfff0000000000000))
468 #define DUK__DBLUNION_IS_ANYZERO(u) \
469 	(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7fffffffffffffff)) == DUK_U64_CONSTANT(0x0000000000000000))
470 #define DUK__DBLUNION_IS_POSZERO(u) \
471 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000000000000))
472 #define DUK__DBLUNION_IS_NEGZERO(u) \
473 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x8000000000000000))
474 #endif
475 #else  /* DUK_USE_64BIT_OPS */
476 /* Macros for no 64-bit ops, any endianness. */
477 #define DUK__DBLUNION_SET_NAN_FULL(u)  do { \
478 		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) 0x7ff80000UL; \
479 		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) 0x00000000UL; \
480 	} while (0)
481 #define DUK__DBLUNION_IS_NAN_FULL(u) \
482 	((((u)->ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL) && \
483 	 (((u)->ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) != 0 || \
484           (u)->ui[DUK_DBL_IDX_UI1] != 0))
485 #define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \
486 	(((u)->ui[DUK_DBL_IDX_UI0] == 0x7ff80000UL) && \
487 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
488 #define DUK__DBLUNION_IS_ANYINF(u) \
489 	((((u)->ui[DUK_DBL_IDX_UI0] & 0x7fffffffUL) == 0x7ff00000UL) && \
490 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
491 #define DUK__DBLUNION_IS_POSINF(u) \
492 	(((u)->ui[DUK_DBL_IDX_UI0] == 0x7ff00000UL) && \
493 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
494 #define DUK__DBLUNION_IS_NEGINF(u) \
495 	(((u)->ui[DUK_DBL_IDX_UI0] == 0xfff00000UL) && \
496 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
497 #define DUK__DBLUNION_IS_ANYZERO(u) \
498 	((((u)->ui[DUK_DBL_IDX_UI0] & 0x7fffffffUL) == 0x00000000UL) && \
499 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
500 #define DUK__DBLUNION_IS_POSZERO(u) \
501 	(((u)->ui[DUK_DBL_IDX_UI0] == 0x00000000UL) && \
502 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
503 #define DUK__DBLUNION_IS_NEGZERO(u) \
504 	(((u)->ui[DUK_DBL_IDX_UI0] == 0x80000000UL) && \
505 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
506 #endif  /* DUK_USE_64BIT_OPS */
507 
508 #define DUK__DBLUNION_SET_NAN_NOTFULL(u)  do { \
509 		(u)->us[DUK_DBL_IDX_US0] = 0x7ff8UL; \
510 	} while (0)
511 
512 #define DUK__DBLUNION_IS_NAN_NOTFULL(u) \
513 	/* E == 0x7ff, topmost four bits of F != 0 => assume NaN */ \
514 	((((u)->us[DUK_DBL_IDX_US0] & 0x7ff0UL) == 0x7ff0UL) && \
515 	 (((u)->us[DUK_DBL_IDX_US0] & 0x000fUL) != 0x0000UL))
516 
517 #define DUK__DBLUNION_IS_NORMALIZED_NAN_NOTFULL(u) \
518 	/* E == 0x7ff, F == 8 => normalized NaN */ \
519 	((u)->us[DUK_DBL_IDX_US0] == 0x7ff8UL)
520 
521 #define DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL(u)  do { \
522 		if (DUK__DBLUNION_IS_NAN_FULL((u))) { \
523 			DUK__DBLUNION_SET_NAN_FULL((u)); \
524 		} \
525 	} while (0)
526 
527 #define DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL(u)  do { \
528 		/* Check must be full. */ \
529 		if (DUK__DBLUNION_IS_NAN_FULL((u))) { \
530 			DUK__DBLUNION_SET_NAN_NOTFULL((u)); \
531 		} \
532 	} while (0)
533 
534 /* Concrete macros for NaN handling used by the implementation internals.
535  * Chosen so that they match the duk_tval representation: with a packed
536  * duk_tval, ensure NaNs are properly normalized; with a non-packed duk_tval
537  * these are essentially NOPs.
538  */
539 
540 #if defined(DUK_USE_PACKED_TVAL)
541 #define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)  DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL((u))
542 #define DUK_DBLUNION_IS_NAN(u)               DUK__DBLUNION_IS_NAN_FULL((u))
543 #define DUK_DBLUNION_IS_NORMALIZED_NAN(u)    DUK__DBLUNION_IS_NORMALIZED_NAN_FULL((u))
544 #define DUK_DBLUNION_SET_NAN(d)              DUK__DBLUNION_SET_NAN_FULL((d))
545 #if 0
546 #define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)  DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL((u))
547 #define DUK_DBLUNION_IS_NAN(u)               DUK__DBLUNION_IS_NAN_NOTFULL((u))
548 #define DUK_DBLUNION_IS_NORMALIZED_NAN(u)    DUK__DBLUNION_IS_NORMALIZED_NAN_NOTFULL((u))
549 #define DUK_DBLUNION_SET_NAN(d)              DUK__DBLUNION_SET_NAN_NOTFULL((d))
550 #endif
551 #define DUK_DBLUNION_IS_NORMALIZED(u) \
552 	(!DUK_DBLUNION_IS_NAN((u)) ||  /* either not a NaN */ \
553 	 DUK_DBLUNION_IS_NORMALIZED_NAN((u)))  /* or is a normalized NaN */
554 #else  /* DUK_USE_PACKED_TVAL */
555 #define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)  /* nop: no need to normalize */
556 #define DUK_DBLUNION_IS_NAN(u)               DUK__DBLUNION_IS_NAN_FULL((u))  /* (DUK_ISNAN((u)->d)) */
557 #define DUK_DBLUNION_IS_NORMALIZED_NAN(u)    DUK__DBLUNION_IS_NAN_FULL((u))  /* (DUK_ISNAN((u)->d)) */
558 #define DUK_DBLUNION_IS_NORMALIZED(u)        1  /* all doubles are considered normalized */
559 #define DUK_DBLUNION_SET_NAN(u)  do { \
560 		/* in non-packed representation we don't care about which NaN is used */ \
561 		(u)->d = DUK_DOUBLE_NAN; \
562 	} while (0)
563 #endif  /* DUK_USE_PACKED_TVAL */
564 
565 #define DUK_DBLUNION_IS_ANYINF(u) DUK__DBLUNION_IS_ANYINF((u))
566 #define DUK_DBLUNION_IS_POSINF(u) DUK__DBLUNION_IS_POSINF((u))
567 #define DUK_DBLUNION_IS_NEGINF(u) DUK__DBLUNION_IS_NEGINF((u))
568 
569 #define DUK_DBLUNION_IS_ANYZERO(u) DUK__DBLUNION_IS_ANYZERO((u))
570 #define DUK_DBLUNION_IS_POSZERO(u) DUK__DBLUNION_IS_POSZERO((u))
571 #define DUK_DBLUNION_IS_NEGZERO(u) DUK__DBLUNION_IS_NEGZERO((u))
572 
573 /* XXX: native 64-bit byteswaps when available */
574 
575 /* 64-bit byteswap, same operation independent of target endianness. */
576 #define DUK_DBLUNION_BSWAP64(u) do { \
577 		duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
578 		duk__bswaptmp1 = (u)->ui[0]; \
579 		duk__bswaptmp2 = (u)->ui[1]; \
580 		duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
581 		duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
582 		(u)->ui[0] = duk__bswaptmp2; \
583 		(u)->ui[1] = duk__bswaptmp1; \
584 	} while (0)
585 
586 /* Byteswap an IEEE double in the duk_double_union from host to network
587  * order.  For a big endian target this is a no-op.
588  */
589 #if defined(DUK_USE_DOUBLE_LE)
590 #define DUK_DBLUNION_DOUBLE_HTON(u) do { \
591 		duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
592 		duk__bswaptmp1 = (u)->ui[0]; \
593 		duk__bswaptmp2 = (u)->ui[1]; \
594 		duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
595 		duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
596 		(u)->ui[0] = duk__bswaptmp2; \
597 		(u)->ui[1] = duk__bswaptmp1; \
598 	} while (0)
599 #elif defined(DUK_USE_DOUBLE_ME)
600 #define DUK_DBLUNION_DOUBLE_HTON(u) do { \
601 		duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
602 		duk__bswaptmp1 = (u)->ui[0]; \
603 		duk__bswaptmp2 = (u)->ui[1]; \
604 		duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
605 		duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
606 		(u)->ui[0] = duk__bswaptmp1; \
607 		(u)->ui[1] = duk__bswaptmp2; \
608 	} while (0)
609 #elif defined(DUK_USE_DOUBLE_BE)
610 #define DUK_DBLUNION_DOUBLE_HTON(u) do { } while (0)
611 #else
612 #error internal error, double endianness insane
613 #endif
614 
615 /* Reverse operation is the same. */
616 #define DUK_DBLUNION_DOUBLE_NTOH(u) DUK_DBLUNION_DOUBLE_HTON((u))
617 
618 /* Some sign bit helpers. */
619 #if defined(DUK_USE_64BIT_OPS)
620 #define DUK_DBLUNION_HAS_SIGNBIT(u) (((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x8000000000000000)) != 0)
621 #define DUK_DBLUNION_GET_SIGNBIT(u) (((u)->ull[DUK_DBL_IDX_ULL0] >> 63U))
622 #else
623 #define DUK_DBLUNION_HAS_SIGNBIT(u) (((u)->ui[DUK_DBL_IDX_UI0] & 0x80000000UL) != 0)
624 #define DUK_DBLUNION_GET_SIGNBIT(u) (((u)->ui[DUK_DBL_IDX_UI0] >> 31U))
625 #endif
626 
627 #endif  /* DUK_DBLUNION_H_INCLUDED */
628 /* #include duk_fltunion.h */
629 #line 1 "duk_fltunion.h"
630 /*
631  *  Union to access IEEE float memory representation.
632  */
633 
634 #if !defined(DUK_FLTUNION_H_INCLUDED)
635 #define DUK_FLTUNION_H_INCLUDED
636 
637 /* #include duk_internal.h -> already included */
638 
639 union duk_float_union {
640 	float f;
641 	duk_uint32_t ui[1];
642 	duk_uint16_t us[2];
643 	duk_uint8_t uc[4];
644 };
645 
646 typedef union duk_float_union duk_float_union;
647 
648 #if defined(DUK_USE_DOUBLE_LE) || defined(DUK_USE_DOUBLE_ME)
649 #define DUK_FLT_IDX_UI0    0
650 #define DUK_FLT_IDX_US0    1
651 #define DUK_FLT_IDX_US1    0
652 #define DUK_FLT_IDX_UC0    3
653 #define DUK_FLT_IDX_UC1    2
654 #define DUK_FLT_IDX_UC2    1
655 #define DUK_FLT_IDX_UC3    0
656 #elif defined(DUK_USE_DOUBLE_BE)
657 #define DUK_FLT_IDX_UI0    0
658 #define DUK_FLT_IDX_US0    0
659 #define DUK_FLT_IDX_US1    1
660 #define DUK_FLT_IDX_UC0    0
661 #define DUK_FLT_IDX_UC1    1
662 #define DUK_FLT_IDX_UC2    2
663 #define DUK_FLT_IDX_UC3    3
664 #else
665 #error internal error
666 #endif
667 
668 #endif  /* DUK_FLTUNION_H_INCLUDED */
669 /* #include duk_replacements.h */
670 #line 1 "duk_replacements.h"
671 #if !defined(DUK_REPLACEMENTS_H_INCLUDED)
672 #define DUK_REPLACEMENTS_H_INCLUDED
673 
674 #if !defined(DUK_SINGLE_FILE)
675 #if defined(DUK_USE_COMPUTED_INFINITY)
676 DUK_INTERNAL_DECL double duk_computed_infinity;
677 #endif
678 #if defined(DUK_USE_COMPUTED_NAN)
679 DUK_INTERNAL_DECL double duk_computed_nan;
680 #endif
681 #endif  /* !DUK_SINGLE_FILE */
682 
683 #if defined(DUK_USE_REPL_FPCLASSIFY)
684 DUK_INTERNAL_DECL int duk_repl_fpclassify(double x);
685 #endif
686 #if defined(DUK_USE_REPL_SIGNBIT)
687 DUK_INTERNAL_DECL int duk_repl_signbit(double x);
688 #endif
689 #if defined(DUK_USE_REPL_ISFINITE)
690 DUK_INTERNAL_DECL int duk_repl_isfinite(double x);
691 #endif
692 #if defined(DUK_USE_REPL_ISNAN)
693 DUK_INTERNAL_DECL int duk_repl_isnan(double x);
694 #endif
695 #if defined(DUK_USE_REPL_ISINF)
696 DUK_INTERNAL_DECL int duk_repl_isinf(double x);
697 #endif
698 
699 #endif  /* DUK_REPLACEMENTS_H_INCLUDED */
700 /* #include duk_jmpbuf.h */
701 #line 1 "duk_jmpbuf.h"
702 /*
703  *  Wrapper for jmp_buf.
704  *
705  *  This is used because jmp_buf is an array type for backward compatibility.
706  *  Wrapping jmp_buf in a struct makes pointer references, sizeof, etc,
707  *  behave more intuitively.
708  *
709  *  http://en.wikipedia.org/wiki/Setjmp.h#Member_types
710  */
711 
712 #if !defined(DUK_JMPBUF_H_INCLUDED)
713 #define DUK_JMPBUF_H_INCLUDED
714 
715 #if defined(DUK_USE_CPP_EXCEPTIONS)
716 struct duk_jmpbuf {
717 	duk_small_int_t dummy;  /* unused */
718 };
719 #else
720 struct duk_jmpbuf {
721 	DUK_JMPBUF_TYPE jb;
722 };
723 #endif
724 
725 #endif  /* DUK_JMPBUF_H_INCLUDED */
726 /* #include duk_exception.h */
727 #line 1 "duk_exception.h"
728 /*
729  *  Exceptions for Duktape internal throws when C++ exceptions are used
730  *  for long control transfers.
731  */
732 
733 #if !defined(DUK_EXCEPTION_H_INCLUDED)
734 #define DUK_EXCEPTION_H_INCLUDED
735 
736 #if defined(DUK_USE_CPP_EXCEPTIONS)
737 /* Internal exception used as a setjmp-longjmp replacement.  User code should
738  * NEVER see or catch this exception, so it doesn't inherit from any base
739  * class which should minimize the chance of user code accidentally catching
740  * the exception.
741  */
742 class duk_internal_exception {
743 	/* intentionally empty */
744 };
745 
746 /* Fatal error, thrown as a specific C++ exception with C++ exceptions
747  * enabled.  It is unsafe to continue; doing so may cause crashes or memory
748  * leaks.  This is intended to be either uncaught, or caught by user code
749  * aware of the "unsafe to continue" semantics.
750  */
751 class duk_fatal_exception : public virtual std::runtime_error {
752  public:
duk_fatal_exception(const char * message)753 	duk_fatal_exception(const char *message) : std::runtime_error(message) {}
754 };
755 #endif
756 
757 #endif  /* DUK_EXCEPTION_H_INCLUDED */
758 /* #include duk_forwdecl.h */
759 #line 1 "duk_forwdecl.h"
760 /*
761  *  Forward declarations for all Duktape structures.
762  */
763 
764 #if !defined(DUK_FORWDECL_H_INCLUDED)
765 #define DUK_FORWDECL_H_INCLUDED
766 
767 /*
768  *  Forward declarations
769  */
770 
771 #if defined(DUK_USE_CPP_EXCEPTIONS)
772 class duk_internal_exception;
773 #else
774 struct duk_jmpbuf;
775 #endif
776 
777 /* duk_tval intentionally skipped */
778 struct duk_heaphdr;
779 struct duk_heaphdr_string;
780 struct duk_harray;
781 struct duk_hstring;
782 struct duk_hstring_external;
783 struct duk_hobject;
784 struct duk_hcompfunc;
785 struct duk_hnatfunc;
786 struct duk_hboundfunc;
787 struct duk_hthread;
788 struct duk_hbufobj;
789 struct duk_hdecenv;
790 struct duk_hobjenv;
791 struct duk_hproxy;
792 struct duk_hbuffer;
793 struct duk_hbuffer_fixed;
794 struct duk_hbuffer_dynamic;
795 struct duk_hbuffer_external;
796 
797 struct duk_propaccessor;
798 union duk_propvalue;
799 struct duk_propdesc;
800 
801 struct duk_heap;
802 struct duk_breakpoint;
803 
804 struct duk_activation;
805 struct duk_catcher;
806 struct duk_ljstate;
807 struct duk_strcache_entry;
808 struct duk_litcache_entry;
809 struct duk_strtab_entry;
810 
811 #if defined(DUK_USE_DEBUG)
812 struct duk_fixedbuffer;
813 #endif
814 
815 struct duk_bitdecoder_ctx;
816 struct duk_bitencoder_ctx;
817 struct duk_bufwriter_ctx;
818 
819 struct duk_token;
820 struct duk_re_token;
821 struct duk_lexer_point;
822 struct duk_lexer_ctx;
823 struct duk_lexer_codepoint;
824 
825 struct duk_compiler_instr;
826 struct duk_compiler_func;
827 struct duk_compiler_ctx;
828 
829 struct duk_re_matcher_ctx;
830 struct duk_re_compiler_ctx;
831 
832 #if defined(DUK_USE_CPP_EXCEPTIONS)
833 /* no typedef */
834 #else
835 typedef struct duk_jmpbuf duk_jmpbuf;
836 #endif
837 
838 /* duk_tval intentionally skipped */
839 typedef struct duk_heaphdr duk_heaphdr;
840 typedef struct duk_heaphdr_string duk_heaphdr_string;
841 typedef struct duk_harray duk_harray;
842 typedef struct duk_hstring duk_hstring;
843 typedef struct duk_hstring_external duk_hstring_external;
844 typedef struct duk_hobject duk_hobject;
845 typedef struct duk_hcompfunc duk_hcompfunc;
846 typedef struct duk_hnatfunc duk_hnatfunc;
847 typedef struct duk_hboundfunc duk_hboundfunc;
848 typedef struct duk_hthread duk_hthread;
849 typedef struct duk_hbufobj duk_hbufobj;
850 typedef struct duk_hdecenv duk_hdecenv;
851 typedef struct duk_hobjenv duk_hobjenv;
852 typedef struct duk_hproxy duk_hproxy;
853 typedef struct duk_hbuffer duk_hbuffer;
854 typedef struct duk_hbuffer_fixed duk_hbuffer_fixed;
855 typedef struct duk_hbuffer_dynamic duk_hbuffer_dynamic;
856 typedef struct duk_hbuffer_external duk_hbuffer_external;
857 
858 typedef struct duk_propaccessor duk_propaccessor;
859 typedef union duk_propvalue duk_propvalue;
860 typedef struct duk_propdesc duk_propdesc;
861 
862 typedef struct duk_heap duk_heap;
863 typedef struct duk_breakpoint duk_breakpoint;
864 
865 typedef struct duk_activation duk_activation;
866 typedef struct duk_catcher duk_catcher;
867 typedef struct duk_ljstate duk_ljstate;
868 typedef struct duk_strcache_entry duk_strcache_entry;
869 typedef struct duk_litcache_entry duk_litcache_entry;
870 typedef struct duk_strtab_entry duk_strtab_entry;
871 
872 #if defined(DUK_USE_DEBUG)
873 typedef struct duk_fixedbuffer duk_fixedbuffer;
874 #endif
875 
876 typedef struct duk_bitdecoder_ctx duk_bitdecoder_ctx;
877 typedef struct duk_bitencoder_ctx duk_bitencoder_ctx;
878 typedef struct duk_bufwriter_ctx duk_bufwriter_ctx;
879 
880 typedef struct duk_token duk_token;
881 typedef struct duk_re_token duk_re_token;
882 typedef struct duk_lexer_point duk_lexer_point;
883 typedef struct duk_lexer_ctx duk_lexer_ctx;
884 typedef struct duk_lexer_codepoint duk_lexer_codepoint;
885 
886 typedef struct duk_compiler_instr duk_compiler_instr;
887 typedef struct duk_compiler_func duk_compiler_func;
888 typedef struct duk_compiler_ctx duk_compiler_ctx;
889 
890 typedef struct duk_re_matcher_ctx duk_re_matcher_ctx;
891 typedef struct duk_re_compiler_ctx duk_re_compiler_ctx;
892 
893 #endif  /* DUK_FORWDECL_H_INCLUDED */
894 /* #include duk_tval.h */
895 #line 1 "duk_tval.h"
896 /*
897  *  Tagged type definition (duk_tval) and accessor macros.
898  *
899  *  Access all fields through the accessor macros, as the representation
900  *  is quite tricky.
901  *
902  *  There are two packed type alternatives: an 8-byte representation
903  *  based on an IEEE double (preferred for compactness), and a 12-byte
904  *  representation (portability).  The latter is needed also in e.g.
905  *  64-bit environments (it usually pads to 16 bytes per value).
906  *
907  *  Selecting the tagged type format involves many trade-offs (memory
908  *  use, size and performance of generated code, portability, etc).
909  *
910  *  NB: because macro arguments are often expressions, macros should
911  *  avoid evaluating their argument more than once.
912  */
913 
914 #if !defined(DUK_TVAL_H_INCLUDED)
915 #define DUK_TVAL_H_INCLUDED
916 
917 /* sanity */
918 #if !defined(DUK_USE_DOUBLE_LE) && !defined(DUK_USE_DOUBLE_ME) && !defined(DUK_USE_DOUBLE_BE)
919 #error unsupported: cannot determine byte order variant
920 #endif
921 
922 #if defined(DUK_USE_PACKED_TVAL)
923 /* ======================================================================== */
924 
925 /*
926  *  Packed 8-byte representation
927  */
928 
929 /* use duk_double_union as duk_tval directly */
930 typedef union duk_double_union duk_tval;
931 typedef struct {
932 	duk_uint16_t a;
933 	duk_uint16_t b;
934 	duk_uint16_t c;
935 	duk_uint16_t d;
936 } duk_tval_unused;
937 
938 /* tags */
939 #define DUK_TAG_NORMALIZED_NAN    0x7ff8UL   /* the NaN variant we use */
940 /* avoid tag 0xfff0, no risk of confusion with negative infinity */
941 #define DUK_TAG_MIN               0xfff1UL
942 #if defined(DUK_USE_FASTINT)
943 #define DUK_TAG_FASTINT           0xfff1UL   /* embed: integer value */
944 #endif
945 #define DUK_TAG_UNUSED            0xfff2UL   /* marker; not actual tagged value */
946 #define DUK_TAG_UNDEFINED         0xfff3UL   /* embed: nothing */
947 #define DUK_TAG_NULL              0xfff4UL   /* embed: nothing */
948 #define DUK_TAG_BOOLEAN           0xfff5UL   /* embed: 0 or 1 (false or true) */
949 /* DUK_TAG_NUMBER would logically go here, but it has multiple 'tags' */
950 #define DUK_TAG_POINTER           0xfff6UL   /* embed: void ptr */
951 #define DUK_TAG_LIGHTFUNC         0xfff7UL   /* embed: func ptr */
952 #define DUK_TAG_STRING            0xfff8UL   /* embed: duk_hstring ptr */
953 #define DUK_TAG_OBJECT            0xfff9UL   /* embed: duk_hobject ptr */
954 #define DUK_TAG_BUFFER            0xfffaUL   /* embed: duk_hbuffer ptr */
955 #define DUK_TAG_MAX               0xfffaUL
956 
957 /* for convenience */
958 #define DUK_XTAG_BOOLEAN_FALSE    0xfff50000UL
959 #define DUK_XTAG_BOOLEAN_TRUE     0xfff50001UL
960 
961 #define DUK_TVAL_IS_VALID_TAG(tv) \
962 	(DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)
963 
964 /* DUK_TVAL_UNUSED initializer for duk_tval_unused, works for any endianness. */
965 #define DUK_TVAL_UNUSED_INITIALIZER() \
966 	{ DUK_TAG_UNUSED, DUK_TAG_UNUSED, DUK_TAG_UNUSED, DUK_TAG_UNUSED }
967 
968 /* two casts to avoid gcc warning: "warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]" */
969 #if defined(DUK_USE_64BIT_OPS)
970 #if defined(DUK_USE_DOUBLE_ME)
971 #define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \
972 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 16) | (((duk_uint64_t) (duk_uint32_t) (h)) << 32); \
973 	} while (0)
974 #else
975 #define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \
976 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 48) | ((duk_uint64_t) (duk_uint32_t) (h)); \
977 	} while (0)
978 #endif
979 #else  /* DUK_USE_64BIT_OPS */
980 #define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \
981 		duk_tval *duk__tv; \
982 		duk__tv = (tv); \
983 		duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) (tag)) << 16; \
984 		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (h); \
985 	} while (0)
986 #endif  /* DUK_USE_64BIT_OPS */
987 
988 #if defined(DUK_USE_64BIT_OPS)
989 /* Double casting for pointer to avoid gcc warning (cast from pointer to integer of different size) */
990 #if defined(DUK_USE_DOUBLE_ME)
991 #define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
992 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 16) | \
993 		                              ((duk_uint64_t) (flags)) | \
994 		                              (((duk_uint64_t) (duk_uint32_t) (fp)) << 32); \
995 	} while (0)
996 #else
997 #define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
998 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 48) | \
999 		                              (((duk_uint64_t) (flags)) << 32) | \
1000 		                              ((duk_uint64_t) (duk_uint32_t) (fp)); \
1001 	} while (0)
1002 #endif
1003 #else  /* DUK_USE_64BIT_OPS */
1004 #define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
1005 		duk_tval *duk__tv; \
1006 		duk__tv = (tv); \
1007 		duk__tv->ui[DUK_DBL_IDX_UI0] = (((duk_uint32_t) DUK_TAG_LIGHTFUNC) << 16) | ((duk_uint32_t) (flags)); \
1008 		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (fp); \
1009 	} while (0)
1010 #endif  /* DUK_USE_64BIT_OPS */
1011 
1012 #if defined(DUK_USE_FASTINT)
1013 /* Note: masking is done for 'i' to deal with negative numbers correctly */
1014 #if defined(DUK_USE_DOUBLE_ME)
1015 #define DUK__TVAL_SET_I48(tv,i)  do { \
1016 		duk_tval *duk__tv; \
1017 		duk__tv = (tv); \
1018 		duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16 | (((duk_uint32_t) ((i) >> 32)) & 0x0000ffffUL); \
1019 		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
1020 	} while (0)
1021 #define DUK__TVAL_SET_U32(tv,i)  do { \
1022 		duk_tval *duk__tv; \
1023 		duk__tv = (tv); \
1024 		duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16; \
1025 		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
1026 	} while (0)
1027 #else
1028 #define DUK__TVAL_SET_I48(tv,i)  do { \
1029 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (((duk_uint64_t) (i)) & DUK_U64_CONSTANT(0x0000ffffffffffff)); \
1030 	} while (0)
1031 #define DUK__TVAL_SET_U32(tv,i)  do { \
1032 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (duk_uint64_t) (i); \
1033 	} while (0)
1034 #endif
1035 
1036 /* This needs to go through a cast because sign extension is needed. */
1037 #define DUK__TVAL_SET_I32(tv,i)  do { \
1038 		duk_int64_t duk__tmp = (duk_int64_t) (i); \
1039 		DUK_TVAL_SET_I48((tv), duk__tmp); \
1040 	} while (0)
1041 
1042 /* XXX: Clumsy sign extend and masking of 16 topmost bits. */
1043 #if defined(DUK_USE_DOUBLE_ME)
1044 #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)
1045 #else
1046 #define DUK__TVAL_GET_FASTINT(tv)      ((((duk_int64_t) (tv)->ull[DUK_DBL_IDX_ULL0]) << 16) >> 16)
1047 #endif
1048 #define DUK__TVAL_GET_FASTINT_U32(tv)  ((tv)->ui[DUK_DBL_IDX_UI1])
1049 #define DUK__TVAL_GET_FASTINT_I32(tv)  ((duk_int32_t) (tv)->ui[DUK_DBL_IDX_UI1])
1050 #endif  /* DUK_USE_FASTINT */
1051 
1052 #define DUK_TVAL_SET_UNDEFINED(tv)  do { \
1053 		(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNDEFINED; \
1054 	} while (0)
1055 #define DUK_TVAL_SET_UNUSED(tv)  do { \
1056 		(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNUSED; \
1057 	} while (0)
1058 #define DUK_TVAL_SET_NULL(tv)  do { \
1059 		(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_NULL; \
1060 	} while (0)
1061 
1062 #define DUK_TVAL_SET_BOOLEAN(tv,val)         DUK_DBLUNION_SET_HIGH32((tv), (((duk_uint32_t) DUK_TAG_BOOLEAN) << 16) | ((duk_uint32_t) (val)))
1063 
1064 #define DUK_TVAL_SET_NAN(tv)                 DUK_DBLUNION_SET_NAN_FULL((tv))
1065 
1066 /* Assumes that caller has normalized NaNs, otherwise trouble ahead. */
1067 #if defined(DUK_USE_FASTINT)
1068 #define DUK_TVAL_SET_DOUBLE(tv,d)  do { \
1069 		duk_double_t duk__dblval; \
1070 		duk__dblval = (d); \
1071 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
1072 		DUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \
1073 	} while (0)
1074 #define DUK_TVAL_SET_I48(tv,i)               DUK__TVAL_SET_I48((tv), (i))
1075 #define DUK_TVAL_SET_I32(tv,i)               DUK__TVAL_SET_I32((tv), (i))
1076 #define DUK_TVAL_SET_U32(tv,i)               DUK__TVAL_SET_U32((tv), (i))
1077 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d)  duk_tval_set_number_chkfast_fast((tv), (d))
1078 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d)  duk_tval_set_number_chkfast_slow((tv), (d))
1079 #define DUK_TVAL_SET_NUMBER(tv,d)            DUK_TVAL_SET_DOUBLE((tv), (d))
1080 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { \
1081 		duk_tval *duk__tv; \
1082 		duk_double_t duk__d; \
1083 		duk__tv = (tv); \
1084 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1085 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1086 			DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \
1087 		} \
1088 	} while (0)
1089 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { \
1090 		duk_tval *duk__tv; \
1091 		duk_double_t duk__d; \
1092 		duk__tv = (tv); \
1093 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1094 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1095 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \
1096 		} \
1097 	} while (0)
1098 #else  /* DUK_USE_FASTINT */
1099 #define DUK_TVAL_SET_DOUBLE(tv,d)  do { \
1100 		duk_double_t duk__dblval; \
1101 		duk__dblval = (d); \
1102 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
1103 		DUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \
1104 	} while (0)
1105 #define DUK_TVAL_SET_I48(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))  /* XXX: fast int-to-double */
1106 #define DUK_TVAL_SET_I32(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
1107 #define DUK_TVAL_SET_U32(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
1108 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d)    DUK_TVAL_SET_DOUBLE((tv), (d))
1109 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d)    DUK_TVAL_SET_DOUBLE((tv), (d))
1110 #define DUK_TVAL_SET_NUMBER(tv,d)            DUK_TVAL_SET_DOUBLE((tv), (d))
1111 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { } while (0)
1112 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { } while (0)
1113 #endif  /* DUK_USE_FASTINT */
1114 
1115 #define DUK_TVAL_SET_FASTINT(tv,i)           DUK_TVAL_SET_I48((tv), (i))  /* alias */
1116 
1117 #define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags)  DUK__TVAL_SET_LIGHTFUNC((tv), (fp), (flags))
1118 #define DUK_TVAL_SET_STRING(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_STRING)
1119 #define DUK_TVAL_SET_OBJECT(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_OBJECT)
1120 #define DUK_TVAL_SET_BUFFER(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_BUFFER)
1121 #define DUK_TVAL_SET_POINTER(tv,p)           DUK__TVAL_SET_TAGGEDPOINTER((tv), (p), DUK_TAG_POINTER)
1122 
1123 #define DUK_TVAL_SET_TVAL(tv,x)              do { *(tv) = *(x); } while (0)
1124 
1125 /* getters */
1126 #define DUK_TVAL_GET_BOOLEAN(tv)             ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US1])
1127 #if defined(DUK_USE_FASTINT)
1128 #define DUK_TVAL_GET_DOUBLE(tv)              ((tv)->d)
1129 #define DUK_TVAL_GET_FASTINT(tv)             DUK__TVAL_GET_FASTINT((tv))
1130 #define DUK_TVAL_GET_FASTINT_U32(tv)         DUK__TVAL_GET_FASTINT_U32((tv))
1131 #define DUK_TVAL_GET_FASTINT_I32(tv)         DUK__TVAL_GET_FASTINT_I32((tv))
1132 #define DUK_TVAL_GET_NUMBER(tv)              duk_tval_get_number_packed((tv))
1133 #else
1134 #define DUK_TVAL_GET_NUMBER(tv)              ((tv)->d)
1135 #define DUK_TVAL_GET_DOUBLE(tv)              ((tv)->d)
1136 #endif
1137 #define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags)  do { \
1138 		(out_flags) = (tv)->ui[DUK_DBL_IDX_UI0] & 0xffffUL; \
1139 		(out_fp) = (duk_c_function) (tv)->ui[DUK_DBL_IDX_UI1]; \
1140 	} while (0)
1141 #define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv)   ((duk_c_function) ((tv)->ui[DUK_DBL_IDX_UI1]))
1142 #define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv)     (((duk_small_uint_t) (tv)->ui[DUK_DBL_IDX_UI0]) & 0xffffUL)
1143 #define DUK_TVAL_GET_STRING(tv)              ((duk_hstring *) (tv)->vp[DUK_DBL_IDX_VP1])
1144 #define DUK_TVAL_GET_OBJECT(tv)              ((duk_hobject *) (tv)->vp[DUK_DBL_IDX_VP1])
1145 #define DUK_TVAL_GET_BUFFER(tv)              ((duk_hbuffer *) (tv)->vp[DUK_DBL_IDX_VP1])
1146 #define DUK_TVAL_GET_POINTER(tv)             ((void *) (tv)->vp[DUK_DBL_IDX_VP1])
1147 #define DUK_TVAL_GET_HEAPHDR(tv)             ((duk_heaphdr *) (tv)->vp[DUK_DBL_IDX_VP1])
1148 
1149 /* decoding */
1150 #define DUK_TVAL_GET_TAG(tv)                 ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US0])
1151 
1152 #define DUK_TVAL_IS_UNDEFINED(tv)            (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNDEFINED)
1153 #define DUK_TVAL_IS_UNUSED(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNUSED)
1154 #define DUK_TVAL_IS_NULL(tv)                 (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_NULL)
1155 #define DUK_TVAL_IS_BOOLEAN(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BOOLEAN)
1156 #define DUK_TVAL_IS_BOOLEAN_TRUE(tv)         ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_TRUE)
1157 #define DUK_TVAL_IS_BOOLEAN_FALSE(tv)        ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_FALSE)
1158 #define DUK_TVAL_IS_LIGHTFUNC(tv)            (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_LIGHTFUNC)
1159 #define DUK_TVAL_IS_STRING(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_STRING)
1160 #define DUK_TVAL_IS_OBJECT(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_OBJECT)
1161 #define DUK_TVAL_IS_BUFFER(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BUFFER)
1162 #define DUK_TVAL_IS_POINTER(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_POINTER)
1163 #if defined(DUK_USE_FASTINT)
1164 /* 0xfff0 is -Infinity */
1165 #define DUK_TVAL_IS_DOUBLE(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)
1166 #define DUK_TVAL_IS_FASTINT(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_FASTINT)
1167 #define DUK_TVAL_IS_NUMBER(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff1UL)
1168 #else
1169 #define DUK_TVAL_IS_NUMBER(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)
1170 #define DUK_TVAL_IS_DOUBLE(tv)               DUK_TVAL_IS_NUMBER((tv))
1171 #endif
1172 
1173 /* This is performance critical because it appears in every DECREF. */
1174 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv)       (DUK_TVAL_GET_TAG((tv)) >= DUK_TAG_STRING)
1175 
1176 #if defined(DUK_USE_FASTINT)
1177 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_packed(duk_tval *tv);
1178 #endif
1179 
1180 #else  /* DUK_USE_PACKED_TVAL */
1181 /* ======================================================================== */
1182 
1183 /*
1184  *  Portable 12-byte representation
1185  */
1186 
1187 /* Note: not initializing all bytes is normally not an issue: Duktape won't
1188  * read or use the uninitialized bytes so valgrind won't issue warnings.
1189  * In some special cases a harmless valgrind warning may be issued though.
1190  * For example, the DumpHeap debugger command writes out a compiled function's
1191  * 'data' area as is, including any uninitialized bytes, which causes a
1192  * valgrind warning.
1193  */
1194 
1195 typedef struct duk_tval_struct duk_tval;
1196 
1197 struct duk_tval_struct {
1198 	duk_small_uint_t t;
1199 	duk_small_uint_t v_extra;
1200 	union {
1201 		duk_double_t d;
1202 		duk_small_int_t i;
1203 #if defined(DUK_USE_FASTINT)
1204 		duk_int64_t fi;  /* if present, forces 16-byte duk_tval */
1205 #endif
1206 		void *voidptr;
1207 		duk_hstring *hstring;
1208 		duk_hobject *hobject;
1209 		duk_hcompfunc *hcompfunc;
1210 		duk_hnatfunc *hnatfunc;
1211 		duk_hthread *hthread;
1212 		duk_hbuffer *hbuffer;
1213 		duk_heaphdr *heaphdr;
1214 		duk_c_function lightfunc;
1215 	} v;
1216 };
1217 
1218 typedef struct {
1219 	duk_small_uint_t t;
1220 	duk_small_uint_t v_extra;
1221 	/* The rest of the fields don't matter except for debug dumps and such
1222 	 * for which a partial initializer may trigger out-ot-bounds memory
1223 	 * reads.  Include a double field which is usually as large or larger
1224 	 * than pointers (not always however).
1225 	 */
1226 	duk_double_t d;
1227 } duk_tval_unused;
1228 
1229 #define DUK_TVAL_UNUSED_INITIALIZER() \
1230 	{ DUK_TAG_UNUSED, 0, 0.0 }
1231 
1232 #define DUK_TAG_MIN                   0
1233 #define DUK_TAG_NUMBER                0  /* DUK_TAG_NUMBER only defined for non-packed duk_tval */
1234 #if defined(DUK_USE_FASTINT)
1235 #define DUK_TAG_FASTINT               1
1236 #endif
1237 #define DUK_TAG_UNDEFINED             2
1238 #define DUK_TAG_NULL                  3
1239 #define DUK_TAG_BOOLEAN               4
1240 #define DUK_TAG_POINTER               5
1241 #define DUK_TAG_LIGHTFUNC             6
1242 #define DUK_TAG_UNUSED                7  /* marker; not actual tagged type */
1243 #define DUK_TAG_STRING                8  /* first heap allocated, match bit boundary */
1244 #define DUK_TAG_OBJECT                9
1245 #define DUK_TAG_BUFFER                10
1246 #define DUK_TAG_MAX                   10
1247 
1248 #define DUK_TVAL_IS_VALID_TAG(tv) \
1249 	(DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)
1250 
1251 /* DUK_TAG_NUMBER is intentionally first, as it is the default clause in code
1252  * to support the 8-byte representation.  Further, it is a non-heap-allocated
1253  * type so it should come before DUK_TAG_STRING.  Finally, it should not break
1254  * the tag value ranges covered by case-clauses in a switch-case.
1255  */
1256 
1257 /* setters */
1258 #define DUK_TVAL_SET_UNDEFINED(tv)  do { \
1259 		duk_tval *duk__tv; \
1260 		duk__tv = (tv); \
1261 		duk__tv->t = DUK_TAG_UNDEFINED; \
1262 	} while (0)
1263 
1264 #define DUK_TVAL_SET_UNUSED(tv)  do { \
1265 		duk_tval *duk__tv; \
1266 		duk__tv = (tv); \
1267 		duk__tv->t = DUK_TAG_UNUSED; \
1268 	} while (0)
1269 
1270 #define DUK_TVAL_SET_NULL(tv)  do { \
1271 		duk_tval *duk__tv; \
1272 		duk__tv = (tv); \
1273 		duk__tv->t = DUK_TAG_NULL; \
1274 	} while (0)
1275 
1276 #define DUK_TVAL_SET_BOOLEAN(tv,val)  do { \
1277 		duk_tval *duk__tv; \
1278 		duk__tv = (tv); \
1279 		duk__tv->t = DUK_TAG_BOOLEAN; \
1280 		duk__tv->v.i = (duk_small_int_t) (val); \
1281 	} while (0)
1282 
1283 #if defined(DUK_USE_FASTINT)
1284 #define DUK_TVAL_SET_DOUBLE(tv,val)  do { \
1285 		duk_tval *duk__tv; \
1286 		duk_double_t duk__dblval; \
1287 		duk__dblval = (val); \
1288 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); /* nop for unpacked duk_tval */ \
1289 		duk__tv = (tv); \
1290 		duk__tv->t = DUK_TAG_NUMBER; \
1291 		duk__tv->v.d = duk__dblval; \
1292 	} while (0)
1293 #define DUK_TVAL_SET_I48(tv,val)  do { \
1294 		duk_tval *duk__tv; \
1295 		duk__tv = (tv); \
1296 		duk__tv->t = DUK_TAG_FASTINT; \
1297 		duk__tv->v.fi = (val); \
1298 	} while (0)
1299 #define DUK_TVAL_SET_U32(tv,val)  do { \
1300 		duk_tval *duk__tv; \
1301 		duk__tv = (tv); \
1302 		duk__tv->t = DUK_TAG_FASTINT; \
1303 		duk__tv->v.fi = (duk_int64_t) (val); \
1304 	} while (0)
1305 #define DUK_TVAL_SET_I32(tv,val)  do { \
1306 		duk_tval *duk__tv; \
1307 		duk__tv = (tv); \
1308 		duk__tv->t = DUK_TAG_FASTINT; \
1309 		duk__tv->v.fi = (duk_int64_t) (val); \
1310 	} while (0)
1311 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \
1312 	duk_tval_set_number_chkfast_fast((tv), (d))
1313 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \
1314 	duk_tval_set_number_chkfast_slow((tv), (d))
1315 #define DUK_TVAL_SET_NUMBER(tv,val) \
1316 	DUK_TVAL_SET_DOUBLE((tv), (val))
1317 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { \
1318 		duk_tval *duk__tv; \
1319 		duk_double_t duk__d; \
1320 		duk__tv = (tv); \
1321 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1322 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1323 			DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \
1324 		} \
1325 	} while (0)
1326 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { \
1327 		duk_tval *duk__tv; \
1328 		duk_double_t duk__d; \
1329 		duk__tv = (tv); \
1330 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1331 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1332 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \
1333 		} \
1334 	} while (0)
1335 #else  /* DUK_USE_FASTINT */
1336 #define DUK_TVAL_SET_DOUBLE(tv,d) \
1337 	DUK_TVAL_SET_NUMBER((tv), (d))
1338 #define DUK_TVAL_SET_I48(tv,val) \
1339 	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))  /* XXX: fast int-to-double */
1340 #define DUK_TVAL_SET_U32(tv,val) \
1341 	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
1342 #define DUK_TVAL_SET_I32(tv,val) \
1343 	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
1344 #define DUK_TVAL_SET_NUMBER(tv,val)  do { \
1345 		duk_tval *duk__tv; \
1346 		duk_double_t duk__dblval; \
1347 		duk__dblval = (val); \
1348 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); /* nop for unpacked duk_tval */ \
1349 		duk__tv = (tv); \
1350 		duk__tv->t = DUK_TAG_NUMBER; \
1351 		duk__tv->v.d = duk__dblval; \
1352 	} while (0)
1353 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \
1354 	DUK_TVAL_SET_NUMBER((tv), (d))
1355 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \
1356 	DUK_TVAL_SET_NUMBER((tv), (d))
1357 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { } while (0)
1358 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { } while (0)
1359 #endif  /* DUK_USE_FASTINT */
1360 
1361 #define DUK_TVAL_SET_FASTINT(tv,i) \
1362 	DUK_TVAL_SET_I48((tv), (i))  /* alias */
1363 
1364 #define DUK_TVAL_SET_POINTER(tv,hptr)  do { \
1365 		duk_tval *duk__tv; \
1366 		duk__tv = (tv); \
1367 		duk__tv->t = DUK_TAG_POINTER; \
1368 		duk__tv->v.voidptr = (hptr); \
1369 	} while (0)
1370 
1371 #define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
1372 		duk_tval *duk__tv; \
1373 		duk__tv = (tv); \
1374 		duk__tv->t = DUK_TAG_LIGHTFUNC; \
1375 		duk__tv->v_extra = (flags); \
1376 		duk__tv->v.lightfunc = (duk_c_function) (fp); \
1377 	} while (0)
1378 
1379 #define DUK_TVAL_SET_STRING(tv,hptr)  do { \
1380 		duk_tval *duk__tv; \
1381 		duk__tv = (tv); \
1382 		duk__tv->t = DUK_TAG_STRING; \
1383 		duk__tv->v.hstring = (hptr); \
1384 	} while (0)
1385 
1386 #define DUK_TVAL_SET_OBJECT(tv,hptr)  do { \
1387 		duk_tval *duk__tv; \
1388 		duk__tv = (tv); \
1389 		duk__tv->t = DUK_TAG_OBJECT; \
1390 		duk__tv->v.hobject = (hptr); \
1391 	} while (0)
1392 
1393 #define DUK_TVAL_SET_BUFFER(tv,hptr)  do { \
1394 		duk_tval *duk__tv; \
1395 		duk__tv = (tv); \
1396 		duk__tv->t = DUK_TAG_BUFFER; \
1397 		duk__tv->v.hbuffer = (hptr); \
1398 	} while (0)
1399 
1400 #define DUK_TVAL_SET_NAN(tv)  do { \
1401 		/* in non-packed representation we don't care about which NaN is used */ \
1402 		duk_tval *duk__tv; \
1403 		duk__tv = (tv); \
1404 		duk__tv->t = DUK_TAG_NUMBER; \
1405 		duk__tv->v.d = DUK_DOUBLE_NAN; \
1406 	} while (0)
1407 
1408 #define DUK_TVAL_SET_TVAL(tv,x)            do { *(tv) = *(x); } while (0)
1409 
1410 /* getters */
1411 #define DUK_TVAL_GET_BOOLEAN(tv)           ((duk_small_uint_t) (tv)->v.i)
1412 #if defined(DUK_USE_FASTINT)
1413 #define DUK_TVAL_GET_DOUBLE(tv)            ((tv)->v.d)
1414 #define DUK_TVAL_GET_FASTINT(tv)           ((tv)->v.fi)
1415 #define DUK_TVAL_GET_FASTINT_U32(tv)       ((duk_uint32_t) ((tv)->v.fi))
1416 #define DUK_TVAL_GET_FASTINT_I32(tv)       ((duk_int32_t) ((tv)->v.fi))
1417 #if 0
1418 #define DUK_TVAL_GET_NUMBER(tv)            (DUK_TVAL_IS_FASTINT((tv)) ? \
1419                                                (duk_double_t) DUK_TVAL_GET_FASTINT((tv)) : \
1420                                                DUK_TVAL_GET_DOUBLE((tv)))
1421 #define DUK_TVAL_GET_NUMBER(tv)            duk_tval_get_number_unpacked((tv))
1422 #else
1423 /* This seems reasonable overall. */
1424 #define DUK_TVAL_GET_NUMBER(tv)            (DUK_TVAL_IS_FASTINT((tv)) ? \
1425                                                duk_tval_get_number_unpacked_fastint((tv)) : \
1426                                                DUK_TVAL_GET_DOUBLE((tv)))
1427 #endif
1428 #else
1429 #define DUK_TVAL_GET_NUMBER(tv)            ((tv)->v.d)
1430 #define DUK_TVAL_GET_DOUBLE(tv)            ((tv)->v.d)
1431 #endif  /* DUK_USE_FASTINT */
1432 #define DUK_TVAL_GET_POINTER(tv)           ((tv)->v.voidptr)
1433 #define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags)  do { \
1434 		(out_flags) = (duk_uint32_t) (tv)->v_extra; \
1435 		(out_fp) = (tv)->v.lightfunc; \
1436 	} while (0)
1437 #define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((tv)->v.lightfunc)
1438 #define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv)   ((duk_small_uint_t) ((tv)->v_extra))
1439 #define DUK_TVAL_GET_STRING(tv)            ((tv)->v.hstring)
1440 #define DUK_TVAL_GET_OBJECT(tv)            ((tv)->v.hobject)
1441 #define DUK_TVAL_GET_BUFFER(tv)            ((tv)->v.hbuffer)
1442 #define DUK_TVAL_GET_HEAPHDR(tv)           ((tv)->v.heaphdr)
1443 
1444 /* decoding */
1445 #define DUK_TVAL_GET_TAG(tv)               ((tv)->t)
1446 #define DUK_TVAL_IS_UNDEFINED(tv)          ((tv)->t == DUK_TAG_UNDEFINED)
1447 #define DUK_TVAL_IS_UNUSED(tv)             ((tv)->t == DUK_TAG_UNUSED)
1448 #define DUK_TVAL_IS_NULL(tv)               ((tv)->t == DUK_TAG_NULL)
1449 #define DUK_TVAL_IS_BOOLEAN(tv)            ((tv)->t == DUK_TAG_BOOLEAN)
1450 #define DUK_TVAL_IS_BOOLEAN_TRUE(tv)       (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i != 0))
1451 #define DUK_TVAL_IS_BOOLEAN_FALSE(tv)      (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i == 0))
1452 #if defined(DUK_USE_FASTINT)
1453 #define DUK_TVAL_IS_DOUBLE(tv)             ((tv)->t == DUK_TAG_NUMBER)
1454 #define DUK_TVAL_IS_FASTINT(tv)            ((tv)->t == DUK_TAG_FASTINT)
1455 #define DUK_TVAL_IS_NUMBER(tv)             ((tv)->t == DUK_TAG_NUMBER || \
1456                                             (tv)->t == DUK_TAG_FASTINT)
1457 #else
1458 #define DUK_TVAL_IS_NUMBER(tv)             ((tv)->t == DUK_TAG_NUMBER)
1459 #define DUK_TVAL_IS_DOUBLE(tv)             DUK_TVAL_IS_NUMBER((tv))
1460 #endif  /* DUK_USE_FASTINT */
1461 #define DUK_TVAL_IS_POINTER(tv)            ((tv)->t == DUK_TAG_POINTER)
1462 #define DUK_TVAL_IS_LIGHTFUNC(tv)          ((tv)->t == DUK_TAG_LIGHTFUNC)
1463 #define DUK_TVAL_IS_STRING(tv)             ((tv)->t == DUK_TAG_STRING)
1464 #define DUK_TVAL_IS_OBJECT(tv)             ((tv)->t == DUK_TAG_OBJECT)
1465 #define DUK_TVAL_IS_BUFFER(tv)             ((tv)->t == DUK_TAG_BUFFER)
1466 
1467 /* This is performance critical because it's needed for every DECREF.
1468  * Take advantage of the fact that the first heap allocated tag is 8,
1469  * so that bit 3 is set for all heap allocated tags (and never set for
1470  * non-heap-allocated tags).
1471  */
1472 #if 0
1473 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv)     ((tv)->t >= DUK_TAG_STRING)
1474 #endif
1475 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv)     ((tv)->t & 0x08)
1476 
1477 #if defined(DUK_USE_FASTINT)
1478 #if 0
1479 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked(duk_tval *tv);
1480 #endif
1481 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv);
1482 #endif
1483 
1484 #endif  /* DUK_USE_PACKED_TVAL */
1485 
1486 /*
1487  *  Convenience (independent of representation)
1488  */
1489 
1490 #define DUK_TVAL_SET_BOOLEAN_TRUE(tv)        DUK_TVAL_SET_BOOLEAN((tv), 1)
1491 #define DUK_TVAL_SET_BOOLEAN_FALSE(tv)       DUK_TVAL_SET_BOOLEAN((tv), 0)
1492 
1493 #define DUK_TVAL_STRING_IS_SYMBOL(tv) \
1494 	DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING((tv)))
1495 
1496 /* Lightfunc flags packing and unpacking. */
1497 /* Sign extend: 0x0000##00 -> 0x##000000 -> sign extend to 0xssssss##.
1498  * Avoid signed shifts due to portability limitations.
1499  */
1500 #define DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags) \
1501 	((duk_int32_t) (duk_int8_t) (((duk_uint16_t) (lf_flags)) >> 8))
1502 #define DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags) \
1503 	(((lf_flags) >> 4) & 0x0fU)
1504 #define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags) \
1505 	((lf_flags) & 0x0fU)
1506 #define DUK_LFUNC_FLAGS_PACK(magic,length,nargs) \
1507 	((((duk_small_uint_t) (magic)) & 0xffU) << 8) | ((length) << 4) | (nargs)
1508 
1509 #define DUK_LFUNC_NARGS_VARARGS             0x0f   /* varargs marker */
1510 #define DUK_LFUNC_NARGS_MIN                 0x00
1511 #define DUK_LFUNC_NARGS_MAX                 0x0e   /* max, excl. varargs marker */
1512 #define DUK_LFUNC_LENGTH_MIN                0x00
1513 #define DUK_LFUNC_LENGTH_MAX                0x0f
1514 #define DUK_LFUNC_MAGIC_MIN                 (-0x80)
1515 #define DUK_LFUNC_MAGIC_MAX                 0x7f
1516 
1517 /* fastint constants etc */
1518 #if defined(DUK_USE_FASTINT)
1519 #define DUK_FASTINT_MIN           (DUK_I64_CONSTANT(-0x800000000000))
1520 #define DUK_FASTINT_MAX           (DUK_I64_CONSTANT(0x7fffffffffff))
1521 #define DUK_FASTINT_BITS          48
1522 
1523 DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x);
1524 DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x);
1525 #endif
1526 
1527 #if defined(DUK_USE_ASSERTIONS)
1528 DUK_INTERNAL_DECL void duk_tval_assert_valid(duk_tval *tv);
1529 #define DUK_TVAL_ASSERT_VALID(tv)  do { duk_tval_assert_valid((tv)); } while (0)
1530 #else
1531 #define DUK_TVAL_ASSERT_VALID(tv)  do {} while (0)
1532 #endif
1533 
1534 #endif  /* DUK_TVAL_H_INCLUDED */
1535 /* #include duk_builtins.h */
1536 #line 1 "duk_builtins.h"
1537 /*
1538  *  Automatically generated by genbuiltins.py, do not edit!
1539  */
1540 
1541 #if !defined(DUK_BUILTINS_H_INCLUDED)
1542 #define DUK_BUILTINS_H_INCLUDED
1543 
1544 #if defined(DUK_USE_ROM_STRINGS)
1545 #error ROM support not enabled, rerun configure.py with --rom-support
1546 #else  /* DUK_USE_ROM_STRINGS */
1547 #define DUK_STRIDX_UC_UNDEFINED                                       0                              /* 'Undefined' */
1548 #define DUK_HEAP_STRING_UC_UNDEFINED(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_UNDEFINED)
1549 #define DUK_HTHREAD_STRING_UC_UNDEFINED(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_UNDEFINED)
1550 #define DUK_STRIDX_UC_NULL                                            1                              /* 'Null' */
1551 #define DUK_HEAP_STRING_UC_NULL(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NULL)
1552 #define DUK_HTHREAD_STRING_UC_NULL(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NULL)
1553 #define DUK_STRIDX_UC_SYMBOL                                          2                              /* 'Symbol' */
1554 #define DUK_HEAP_STRING_UC_SYMBOL(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_SYMBOL)
1555 #define DUK_HTHREAD_STRING_UC_SYMBOL(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_SYMBOL)
1556 #define DUK_STRIDX_UC_ARGUMENTS                                       3                              /* 'Arguments' */
1557 #define DUK_HEAP_STRING_UC_ARGUMENTS(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ARGUMENTS)
1558 #define DUK_HTHREAD_STRING_UC_ARGUMENTS(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ARGUMENTS)
1559 #define DUK_STRIDX_UC_OBJECT                                          4                              /* 'Object' */
1560 #define DUK_HEAP_STRING_UC_OBJECT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_OBJECT)
1561 #define DUK_HTHREAD_STRING_UC_OBJECT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_OBJECT)
1562 #define DUK_STRIDX_UC_FUNCTION                                        5                              /* 'Function' */
1563 #define DUK_HEAP_STRING_UC_FUNCTION(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_FUNCTION)
1564 #define DUK_HTHREAD_STRING_UC_FUNCTION(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_FUNCTION)
1565 #define DUK_STRIDX_UC_ARRAY                                           6                              /* 'Array' */
1566 #define DUK_HEAP_STRING_UC_ARRAY(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ARRAY)
1567 #define DUK_HTHREAD_STRING_UC_ARRAY(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ARRAY)
1568 #define DUK_STRIDX_UC_STRING                                          7                              /* 'String' */
1569 #define DUK_HEAP_STRING_UC_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_STRING)
1570 #define DUK_HTHREAD_STRING_UC_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_STRING)
1571 #define DUK_STRIDX_UC_BOOLEAN                                         8                              /* 'Boolean' */
1572 #define DUK_HEAP_STRING_UC_BOOLEAN(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BOOLEAN)
1573 #define DUK_HTHREAD_STRING_UC_BOOLEAN(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BOOLEAN)
1574 #define DUK_STRIDX_UC_NUMBER                                          9                              /* 'Number' */
1575 #define DUK_HEAP_STRING_UC_NUMBER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NUMBER)
1576 #define DUK_HTHREAD_STRING_UC_NUMBER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NUMBER)
1577 #define DUK_STRIDX_UC_DATE                                            10                             /* 'Date' */
1578 #define DUK_HEAP_STRING_UC_DATE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_DATE)
1579 #define DUK_HTHREAD_STRING_UC_DATE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_DATE)
1580 #define DUK_STRIDX_REG_EXP                                            11                             /* 'RegExp' */
1581 #define DUK_HEAP_STRING_REG_EXP(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REG_EXP)
1582 #define DUK_HTHREAD_STRING_REG_EXP(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_REG_EXP)
1583 #define DUK_STRIDX_UC_ERROR                                           12                             /* 'Error' */
1584 #define DUK_HEAP_STRING_UC_ERROR(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ERROR)
1585 #define DUK_HTHREAD_STRING_UC_ERROR(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ERROR)
1586 #define DUK_STRIDX_MATH                                               13                             /* 'Math' */
1587 #define DUK_HEAP_STRING_MATH(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MATH)
1588 #define DUK_HTHREAD_STRING_MATH(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MATH)
1589 #define DUK_STRIDX_JSON                                               14                             /* 'JSON' */
1590 #define DUK_HEAP_STRING_JSON(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON)
1591 #define DUK_HTHREAD_STRING_JSON(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON)
1592 #define DUK_STRIDX_EMPTY_STRING                                       15                             /* '' */
1593 #define DUK_HEAP_STRING_EMPTY_STRING(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EMPTY_STRING)
1594 #define DUK_HTHREAD_STRING_EMPTY_STRING(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EMPTY_STRING)
1595 #define DUK_STRIDX_ARRAY_BUFFER                                       16                             /* 'ArrayBuffer' */
1596 #define DUK_HEAP_STRING_ARRAY_BUFFER(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY_BUFFER)
1597 #define DUK_HTHREAD_STRING_ARRAY_BUFFER(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY_BUFFER)
1598 #define DUK_STRIDX_DATA_VIEW                                          17                             /* 'DataView' */
1599 #define DUK_HEAP_STRING_DATA_VIEW(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA_VIEW)
1600 #define DUK_HTHREAD_STRING_DATA_VIEW(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA_VIEW)
1601 #define DUK_STRIDX_INT8_ARRAY                                         18                             /* 'Int8Array' */
1602 #define DUK_HEAP_STRING_INT8_ARRAY(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT8_ARRAY)
1603 #define DUK_HTHREAD_STRING_INT8_ARRAY(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT8_ARRAY)
1604 #define DUK_STRIDX_UINT8_ARRAY                                        19                             /* 'Uint8Array' */
1605 #define DUK_HEAP_STRING_UINT8_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_ARRAY)
1606 #define DUK_HTHREAD_STRING_UINT8_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_ARRAY)
1607 #define DUK_STRIDX_UINT8_CLAMPED_ARRAY                                20                             /* 'Uint8ClampedArray' */
1608 #define DUK_HEAP_STRING_UINT8_CLAMPED_ARRAY(heap)                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
1609 #define DUK_HTHREAD_STRING_UINT8_CLAMPED_ARRAY(thr)                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
1610 #define DUK_STRIDX_INT16_ARRAY                                        21                             /* 'Int16Array' */
1611 #define DUK_HEAP_STRING_INT16_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT16_ARRAY)
1612 #define DUK_HTHREAD_STRING_INT16_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT16_ARRAY)
1613 #define DUK_STRIDX_UINT16_ARRAY                                       22                             /* 'Uint16Array' */
1614 #define DUK_HEAP_STRING_UINT16_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT16_ARRAY)
1615 #define DUK_HTHREAD_STRING_UINT16_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT16_ARRAY)
1616 #define DUK_STRIDX_INT32_ARRAY                                        23                             /* 'Int32Array' */
1617 #define DUK_HEAP_STRING_INT32_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT32_ARRAY)
1618 #define DUK_HTHREAD_STRING_INT32_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT32_ARRAY)
1619 #define DUK_STRIDX_UINT32_ARRAY                                       24                             /* 'Uint32Array' */
1620 #define DUK_HEAP_STRING_UINT32_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT32_ARRAY)
1621 #define DUK_HTHREAD_STRING_UINT32_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT32_ARRAY)
1622 #define DUK_STRIDX_FLOAT32_ARRAY                                      25                             /* 'Float32Array' */
1623 #define DUK_HEAP_STRING_FLOAT32_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT32_ARRAY)
1624 #define DUK_HTHREAD_STRING_FLOAT32_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT32_ARRAY)
1625 #define DUK_STRIDX_FLOAT64_ARRAY                                      26                             /* 'Float64Array' */
1626 #define DUK_HEAP_STRING_FLOAT64_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT64_ARRAY)
1627 #define DUK_HTHREAD_STRING_FLOAT64_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT64_ARRAY)
1628 #define DUK_STRIDX_GLOBAL                                             27                             /* 'global' */
1629 #define DUK_HEAP_STRING_GLOBAL(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GLOBAL)
1630 #define DUK_HTHREAD_STRING_GLOBAL(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GLOBAL)
1631 #define DUK_STRIDX_OBJ_ENV                                            28                             /* 'ObjEnv' */
1632 #define DUK_HEAP_STRING_OBJ_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OBJ_ENV)
1633 #define DUK_HTHREAD_STRING_OBJ_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OBJ_ENV)
1634 #define DUK_STRIDX_DEC_ENV                                            29                             /* 'DecEnv' */
1635 #define DUK_HEAP_STRING_DEC_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEC_ENV)
1636 #define DUK_HTHREAD_STRING_DEC_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEC_ENV)
1637 #define DUK_STRIDX_UC_BUFFER                                          30                             /* 'Buffer' */
1638 #define DUK_HEAP_STRING_UC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER)
1639 #define DUK_HTHREAD_STRING_UC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER)
1640 #define DUK_STRIDX_UC_POINTER                                         31                             /* 'Pointer' */
1641 #define DUK_HEAP_STRING_UC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_POINTER)
1642 #define DUK_HTHREAD_STRING_UC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_POINTER)
1643 #define DUK_STRIDX_UC_THREAD                                          32                             /* 'Thread' */
1644 #define DUK_HEAP_STRING_UC_THREAD(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_THREAD)
1645 #define DUK_HTHREAD_STRING_UC_THREAD(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_THREAD)
1646 #define DUK_STRIDX_EVAL                                               33                             /* 'eval' */
1647 #define DUK_HEAP_STRING_EVAL(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EVAL)
1648 #define DUK_HTHREAD_STRING_EVAL(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EVAL)
1649 #define DUK_STRIDX_VALUE                                              34                             /* 'value' */
1650 #define DUK_HEAP_STRING_VALUE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE)
1651 #define DUK_HTHREAD_STRING_VALUE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE)
1652 #define DUK_STRIDX_WRITABLE                                           35                             /* 'writable' */
1653 #define DUK_HEAP_STRING_WRITABLE(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITABLE)
1654 #define DUK_HTHREAD_STRING_WRITABLE(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITABLE)
1655 #define DUK_STRIDX_CONFIGURABLE                                       36                             /* 'configurable' */
1656 #define DUK_HEAP_STRING_CONFIGURABLE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONFIGURABLE)
1657 #define DUK_HTHREAD_STRING_CONFIGURABLE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONFIGURABLE)
1658 #define DUK_STRIDX_ENUMERABLE                                         37                             /* 'enumerable' */
1659 #define DUK_HEAP_STRING_ENUMERABLE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUMERABLE)
1660 #define DUK_HTHREAD_STRING_ENUMERABLE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUMERABLE)
1661 #define DUK_STRIDX_JOIN                                               38                             /* 'join' */
1662 #define DUK_HEAP_STRING_JOIN(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JOIN)
1663 #define DUK_HTHREAD_STRING_JOIN(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JOIN)
1664 #define DUK_STRIDX_TO_LOCALE_STRING                                   39                             /* 'toLocaleString' */
1665 #define DUK_HEAP_STRING_TO_LOCALE_STRING(heap)                        DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_LOCALE_STRING)
1666 #define DUK_HTHREAD_STRING_TO_LOCALE_STRING(thr)                      DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_LOCALE_STRING)
1667 #define DUK_STRIDX_VALUE_OF                                           40                             /* 'valueOf' */
1668 #define DUK_HEAP_STRING_VALUE_OF(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE_OF)
1669 #define DUK_HTHREAD_STRING_VALUE_OF(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE_OF)
1670 #define DUK_STRIDX_TO_UTC_STRING                                      41                             /* 'toUTCString' */
1671 #define DUK_HEAP_STRING_TO_UTC_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_UTC_STRING)
1672 #define DUK_HTHREAD_STRING_TO_UTC_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_UTC_STRING)
1673 #define DUK_STRIDX_TO_ISO_STRING                                      42                             /* 'toISOString' */
1674 #define DUK_HEAP_STRING_TO_ISO_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_ISO_STRING)
1675 #define DUK_HTHREAD_STRING_TO_ISO_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_ISO_STRING)
1676 #define DUK_STRIDX_TO_GMT_STRING                                      43                             /* 'toGMTString' */
1677 #define DUK_HEAP_STRING_TO_GMT_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_GMT_STRING)
1678 #define DUK_HTHREAD_STRING_TO_GMT_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_GMT_STRING)
1679 #define DUK_STRIDX_SOURCE                                             44                             /* 'source' */
1680 #define DUK_HEAP_STRING_SOURCE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SOURCE)
1681 #define DUK_HTHREAD_STRING_SOURCE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SOURCE)
1682 #define DUK_STRIDX_IGNORE_CASE                                        45                             /* 'ignoreCase' */
1683 #define DUK_HEAP_STRING_IGNORE_CASE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IGNORE_CASE)
1684 #define DUK_HTHREAD_STRING_IGNORE_CASE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IGNORE_CASE)
1685 #define DUK_STRIDX_MULTILINE                                          46                             /* 'multiline' */
1686 #define DUK_HEAP_STRING_MULTILINE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MULTILINE)
1687 #define DUK_HTHREAD_STRING_MULTILINE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MULTILINE)
1688 #define DUK_STRIDX_LAST_INDEX                                         47                             /* 'lastIndex' */
1689 #define DUK_HEAP_STRING_LAST_INDEX(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LAST_INDEX)
1690 #define DUK_HTHREAD_STRING_LAST_INDEX(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LAST_INDEX)
1691 #define DUK_STRIDX_FLAGS                                              48                             /* 'flags' */
1692 #define DUK_HEAP_STRING_FLAGS(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLAGS)
1693 #define DUK_HTHREAD_STRING_FLAGS(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLAGS)
1694 #define DUK_STRIDX_INDEX                                              49                             /* 'index' */
1695 #define DUK_HEAP_STRING_INDEX(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INDEX)
1696 #define DUK_HTHREAD_STRING_INDEX(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INDEX)
1697 #define DUK_STRIDX_PROTOTYPE                                          50                             /* 'prototype' */
1698 #define DUK_HEAP_STRING_PROTOTYPE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTOTYPE)
1699 #define DUK_HTHREAD_STRING_PROTOTYPE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTOTYPE)
1700 #define DUK_STRIDX_CONSTRUCTOR                                        51                             /* 'constructor' */
1701 #define DUK_HEAP_STRING_CONSTRUCTOR(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCTOR)
1702 #define DUK_HTHREAD_STRING_CONSTRUCTOR(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCTOR)
1703 #define DUK_STRIDX_MESSAGE                                            52                             /* 'message' */
1704 #define DUK_HEAP_STRING_MESSAGE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MESSAGE)
1705 #define DUK_HTHREAD_STRING_MESSAGE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MESSAGE)
1706 #define DUK_STRIDX_LC_BOOLEAN                                         53                             /* 'boolean' */
1707 #define DUK_HEAP_STRING_LC_BOOLEAN(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BOOLEAN)
1708 #define DUK_HTHREAD_STRING_LC_BOOLEAN(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BOOLEAN)
1709 #define DUK_STRIDX_LC_NUMBER                                          54                             /* 'number' */
1710 #define DUK_HEAP_STRING_LC_NUMBER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NUMBER)
1711 #define DUK_HTHREAD_STRING_LC_NUMBER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NUMBER)
1712 #define DUK_STRIDX_LC_STRING                                          55                             /* 'string' */
1713 #define DUK_HEAP_STRING_LC_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_STRING)
1714 #define DUK_HTHREAD_STRING_LC_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_STRING)
1715 #define DUK_STRIDX_LC_SYMBOL                                          56                             /* 'symbol' */
1716 #define DUK_HEAP_STRING_LC_SYMBOL(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_SYMBOL)
1717 #define DUK_HTHREAD_STRING_LC_SYMBOL(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_SYMBOL)
1718 #define DUK_STRIDX_LC_OBJECT                                          57                             /* 'object' */
1719 #define DUK_HEAP_STRING_LC_OBJECT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_OBJECT)
1720 #define DUK_HTHREAD_STRING_LC_OBJECT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_OBJECT)
1721 #define DUK_STRIDX_LC_UNDEFINED                                       58                             /* 'undefined' */
1722 #define DUK_HEAP_STRING_LC_UNDEFINED(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_UNDEFINED)
1723 #define DUK_HTHREAD_STRING_LC_UNDEFINED(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_UNDEFINED)
1724 #define DUK_STRIDX_NAN                                                59                             /* 'NaN' */
1725 #define DUK_HEAP_STRING_NAN(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAN)
1726 #define DUK_HTHREAD_STRING_NAN(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAN)
1727 #define DUK_STRIDX_INFINITY                                           60                             /* 'Infinity' */
1728 #define DUK_HEAP_STRING_INFINITY(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INFINITY)
1729 #define DUK_HTHREAD_STRING_INFINITY(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INFINITY)
1730 #define DUK_STRIDX_MINUS_INFINITY                                     61                             /* '-Infinity' */
1731 #define DUK_HEAP_STRING_MINUS_INFINITY(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_INFINITY)
1732 #define DUK_HTHREAD_STRING_MINUS_INFINITY(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_INFINITY)
1733 #define DUK_STRIDX_MINUS_ZERO                                         62                             /* '-0' */
1734 #define DUK_HEAP_STRING_MINUS_ZERO(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_ZERO)
1735 #define DUK_HTHREAD_STRING_MINUS_ZERO(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_ZERO)
1736 #define DUK_STRIDX_COMMA                                              63                             /* ',' */
1737 #define DUK_HEAP_STRING_COMMA(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMMA)
1738 #define DUK_HTHREAD_STRING_COMMA(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMMA)
1739 #define DUK_STRIDX_NEWLINE_4SPACE                                     64                             /* '\n    ' */
1740 #define DUK_HEAP_STRING_NEWLINE_4SPACE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEWLINE_4SPACE)
1741 #define DUK_HTHREAD_STRING_NEWLINE_4SPACE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEWLINE_4SPACE)
1742 #define DUK_STRIDX_BRACKETED_ELLIPSIS                                 65                             /* '[...]' */
1743 #define DUK_HEAP_STRING_BRACKETED_ELLIPSIS(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BRACKETED_ELLIPSIS)
1744 #define DUK_HTHREAD_STRING_BRACKETED_ELLIPSIS(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BRACKETED_ELLIPSIS)
1745 #define DUK_STRIDX_INVALID_DATE                                       66                             /* 'Invalid Date' */
1746 #define DUK_HEAP_STRING_INVALID_DATE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INVALID_DATE)
1747 #define DUK_HTHREAD_STRING_INVALID_DATE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INVALID_DATE)
1748 #define DUK_STRIDX_LC_ARGUMENTS                                       67                             /* 'arguments' */
1749 #define DUK_HEAP_STRING_LC_ARGUMENTS(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_ARGUMENTS)
1750 #define DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_ARGUMENTS)
1751 #define DUK_STRIDX_CALLEE                                             68                             /* 'callee' */
1752 #define DUK_HEAP_STRING_CALLEE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLEE)
1753 #define DUK_HTHREAD_STRING_CALLEE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLEE)
1754 #define DUK_STRIDX_CALLER                                             69                             /* 'caller' */
1755 #define DUK_HEAP_STRING_CALLER(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLER)
1756 #define DUK_HTHREAD_STRING_CALLER(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLER)
1757 #define DUK_STRIDX_APPLY                                              70                             /* 'apply' */
1758 #define DUK_HEAP_STRING_APPLY(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_APPLY)
1759 #define DUK_HTHREAD_STRING_APPLY(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_APPLY)
1760 #define DUK_STRIDX_CONSTRUCT                                          71                             /* 'construct' */
1761 #define DUK_HEAP_STRING_CONSTRUCT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCT)
1762 #define DUK_HTHREAD_STRING_CONSTRUCT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCT)
1763 #define DUK_STRIDX_DELETE_PROPERTY                                    72                             /* 'deleteProperty' */
1764 #define DUK_HEAP_STRING_DELETE_PROPERTY(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE_PROPERTY)
1765 #define DUK_HTHREAD_STRING_DELETE_PROPERTY(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE_PROPERTY)
1766 #define DUK_STRIDX_GET                                                73                             /* 'get' */
1767 #define DUK_HEAP_STRING_GET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET)
1768 #define DUK_HTHREAD_STRING_GET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET)
1769 #define DUK_STRIDX_HAS                                                74                             /* 'has' */
1770 #define DUK_HEAP_STRING_HAS(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HAS)
1771 #define DUK_HTHREAD_STRING_HAS(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HAS)
1772 #define DUK_STRIDX_OWN_KEYS                                           75                             /* 'ownKeys' */
1773 #define DUK_HEAP_STRING_OWN_KEYS(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OWN_KEYS)
1774 #define DUK_HTHREAD_STRING_OWN_KEYS(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OWN_KEYS)
1775 #define DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE                      76                             /* '\x81Symbol.toPrimitive\xff' */
1776 #define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_TO_PRIMITIVE(heap)           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)
1777 #define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_TO_PRIMITIVE(thr)         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)
1778 #define DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE                      77                             /* '\x81Symbol.hasInstance\xff' */
1779 #define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_HAS_INSTANCE(heap)           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)
1780 #define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_HAS_INSTANCE(thr)         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)
1781 #define DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG                     78                             /* '\x81Symbol.toStringTag\xff' */
1782 #define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_TO_STRING_TAG(heap)          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG)
1783 #define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_TO_STRING_TAG(thr)        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG)
1784 #define DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE              79                             /* '\x81Symbol.isConcatSpreadable\xff' */
1785 #define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE(heap)   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE)
1786 #define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE(thr)  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE)
1787 #define DUK_STRIDX_SET_PROTOTYPE_OF                                   80                             /* 'setPrototypeOf' */
1788 #define DUK_HEAP_STRING_SET_PROTOTYPE_OF(heap)                        DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_PROTOTYPE_OF)
1789 #define DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr)                      DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_PROTOTYPE_OF)
1790 #define DUK_STRIDX___PROTO__                                          81                             /* '__proto__' */
1791 #define DUK_HEAP_STRING___PROTO__(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX___PROTO__)
1792 #define DUK_HTHREAD_STRING___PROTO__(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX___PROTO__)
1793 #define DUK_STRIDX_TO_STRING                                          82                             /* 'toString' */
1794 #define DUK_HEAP_STRING_TO_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_STRING)
1795 #define DUK_HTHREAD_STRING_TO_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_STRING)
1796 #define DUK_STRIDX_TO_JSON                                            83                             /* 'toJSON' */
1797 #define DUK_HEAP_STRING_TO_JSON(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_JSON)
1798 #define DUK_HTHREAD_STRING_TO_JSON(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_JSON)
1799 #define DUK_STRIDX_TYPE                                               84                             /* 'type' */
1800 #define DUK_HEAP_STRING_TYPE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPE)
1801 #define DUK_HTHREAD_STRING_TYPE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPE)
1802 #define DUK_STRIDX_DATA                                               85                             /* 'data' */
1803 #define DUK_HEAP_STRING_DATA(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA)
1804 #define DUK_HTHREAD_STRING_DATA(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA)
1805 #define DUK_STRIDX_LC_BUFFER                                          86                             /* 'buffer' */
1806 #define DUK_HEAP_STRING_LC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER)
1807 #define DUK_HTHREAD_STRING_LC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER)
1808 #define DUK_STRIDX_LENGTH                                             87                             /* 'length' */
1809 #define DUK_HEAP_STRING_LENGTH(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LENGTH)
1810 #define DUK_HTHREAD_STRING_LENGTH(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LENGTH)
1811 #define DUK_STRIDX_SET                                                88                             /* 'set' */
1812 #define DUK_HEAP_STRING_SET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET)
1813 #define DUK_HTHREAD_STRING_SET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET)
1814 #define DUK_STRIDX_STACK                                              89                             /* 'stack' */
1815 #define DUK_HEAP_STRING_STACK(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STACK)
1816 #define DUK_HTHREAD_STRING_STACK(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STACK)
1817 #define DUK_STRIDX_PC                                                 90                             /* 'pc' */
1818 #define DUK_HEAP_STRING_PC(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PC)
1819 #define DUK_HTHREAD_STRING_PC(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PC)
1820 #define DUK_STRIDX_LINE_NUMBER                                        91                             /* 'lineNumber' */
1821 #define DUK_HEAP_STRING_LINE_NUMBER(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER)
1822 #define DUK_HTHREAD_STRING_LINE_NUMBER(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LINE_NUMBER)
1823 #define DUK_STRIDX_INT_TRACEDATA                                      92                             /* '\x82Tracedata' */
1824 #define DUK_HEAP_STRING_INT_TRACEDATA(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA)
1825 #define DUK_HTHREAD_STRING_INT_TRACEDATA(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA)
1826 #define DUK_STRIDX_NAME                                               93                             /* 'name' */
1827 #define DUK_HEAP_STRING_NAME(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAME)
1828 #define DUK_HTHREAD_STRING_NAME(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAME)
1829 #define DUK_STRIDX_FILE_NAME                                          94                             /* 'fileName' */
1830 #define DUK_HEAP_STRING_FILE_NAME(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILE_NAME)
1831 #define DUK_HTHREAD_STRING_FILE_NAME(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILE_NAME)
1832 #define DUK_STRIDX_LC_POINTER                                         95                             /* 'pointer' */
1833 #define DUK_HEAP_STRING_LC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER)
1834 #define DUK_HTHREAD_STRING_LC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER)
1835 #define DUK_STRIDX_INT_TARGET                                         96                             /* '\x82Target' */
1836 #define DUK_HEAP_STRING_INT_TARGET(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TARGET)
1837 #define DUK_HTHREAD_STRING_INT_TARGET(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TARGET)
1838 #define DUK_STRIDX_INT_NEXT                                           97                             /* '\x82Next' */
1839 #define DUK_HEAP_STRING_INT_NEXT(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_NEXT)
1840 #define DUK_HTHREAD_STRING_INT_NEXT(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_NEXT)
1841 #define DUK_STRIDX_INT_BYTECODE                                       98                             /* '\x82Bytecode' */
1842 #define DUK_HEAP_STRING_INT_BYTECODE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_BYTECODE)
1843 #define DUK_HTHREAD_STRING_INT_BYTECODE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_BYTECODE)
1844 #define DUK_STRIDX_INT_FORMALS                                        99                             /* '\x82Formals' */
1845 #define DUK_HEAP_STRING_INT_FORMALS(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FORMALS)
1846 #define DUK_HTHREAD_STRING_INT_FORMALS(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FORMALS)
1847 #define DUK_STRIDX_INT_VARMAP                                         100                            /* '\x82Varmap' */
1848 #define DUK_HEAP_STRING_INT_VARMAP(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARMAP)
1849 #define DUK_HTHREAD_STRING_INT_VARMAP(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARMAP)
1850 #define DUK_STRIDX_INT_SOURCE                                         101                            /* '\x82Source' */
1851 #define DUK_HEAP_STRING_INT_SOURCE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_SOURCE)
1852 #define DUK_HTHREAD_STRING_INT_SOURCE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_SOURCE)
1853 #define DUK_STRIDX_INT_PC2LINE                                        102                            /* '\x82Pc2line' */
1854 #define DUK_HEAP_STRING_INT_PC2LINE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_PC2LINE)
1855 #define DUK_HTHREAD_STRING_INT_PC2LINE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_PC2LINE)
1856 #define DUK_STRIDX_INT_MAP                                            103                            /* '\x82Map' */
1857 #define DUK_HEAP_STRING_INT_MAP(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_MAP)
1858 #define DUK_HTHREAD_STRING_INT_MAP(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_MAP)
1859 #define DUK_STRIDX_INT_VARENV                                         104                            /* '\x82Varenv' */
1860 #define DUK_HEAP_STRING_INT_VARENV(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARENV)
1861 #define DUK_HTHREAD_STRING_INT_VARENV(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARENV)
1862 #define DUK_STRIDX_INT_FINALIZER                                      105                            /* '\x82Finalizer' */
1863 #define DUK_HEAP_STRING_INT_FINALIZER(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FINALIZER)
1864 #define DUK_HTHREAD_STRING_INT_FINALIZER(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FINALIZER)
1865 #define DUK_STRIDX_INT_VALUE                                          106                            /* '\x82Value' */
1866 #define DUK_HEAP_STRING_INT_VALUE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VALUE)
1867 #define DUK_HTHREAD_STRING_INT_VALUE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE)
1868 #define DUK_STRIDX_COMPILE                                            107                            /* 'compile' */
1869 #define DUK_HEAP_STRING_COMPILE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPILE)
1870 #define DUK_HTHREAD_STRING_COMPILE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPILE)
1871 #define DUK_STRIDX_INPUT                                              108                            /* 'input' */
1872 #define DUK_HEAP_STRING_INPUT(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INPUT)
1873 #define DUK_HTHREAD_STRING_INPUT(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INPUT)
1874 #define DUK_STRIDX_ERR_CREATE                                         109                            /* 'errCreate' */
1875 #define DUK_HEAP_STRING_ERR_CREATE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_CREATE)
1876 #define DUK_HTHREAD_STRING_ERR_CREATE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_CREATE)
1877 #define DUK_STRIDX_ERR_THROW                                          110                            /* 'errThrow' */
1878 #define DUK_HEAP_STRING_ERR_THROW(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_THROW)
1879 #define DUK_HTHREAD_STRING_ERR_THROW(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_THROW)
1880 #define DUK_STRIDX_ENV                                                111                            /* 'env' */
1881 #define DUK_HEAP_STRING_ENV(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENV)
1882 #define DUK_HTHREAD_STRING_ENV(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENV)
1883 #define DUK_STRIDX_HEX                                                112                            /* 'hex' */
1884 #define DUK_HEAP_STRING_HEX(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HEX)
1885 #define DUK_HTHREAD_STRING_HEX(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HEX)
1886 #define DUK_STRIDX_BASE64                                             113                            /* 'base64' */
1887 #define DUK_HEAP_STRING_BASE64(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BASE64)
1888 #define DUK_HTHREAD_STRING_BASE64(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BASE64)
1889 #define DUK_STRIDX_JX                                                 114                            /* 'jx' */
1890 #define DUK_HEAP_STRING_JX(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JX)
1891 #define DUK_HTHREAD_STRING_JX(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JX)
1892 #define DUK_STRIDX_JC                                                 115                            /* 'jc' */
1893 #define DUK_HEAP_STRING_JC(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JC)
1894 #define DUK_HTHREAD_STRING_JC(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JC)
1895 #define DUK_STRIDX_JSON_EXT_UNDEFINED                                 116                            /* '{"_undef":true}' */
1896 #define DUK_HEAP_STRING_JSON_EXT_UNDEFINED(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_UNDEFINED)
1897 #define DUK_HTHREAD_STRING_JSON_EXT_UNDEFINED(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_UNDEFINED)
1898 #define DUK_STRIDX_JSON_EXT_NAN                                       117                            /* '{"_nan":true}' */
1899 #define DUK_HEAP_STRING_JSON_EXT_NAN(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NAN)
1900 #define DUK_HTHREAD_STRING_JSON_EXT_NAN(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NAN)
1901 #define DUK_STRIDX_JSON_EXT_POSINF                                    118                            /* '{"_inf":true}' */
1902 #define DUK_HEAP_STRING_JSON_EXT_POSINF(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_POSINF)
1903 #define DUK_HTHREAD_STRING_JSON_EXT_POSINF(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_POSINF)
1904 #define DUK_STRIDX_JSON_EXT_NEGINF                                    119                            /* '{"_ninf":true}' */
1905 #define DUK_HEAP_STRING_JSON_EXT_NEGINF(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NEGINF)
1906 #define DUK_HTHREAD_STRING_JSON_EXT_NEGINF(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NEGINF)
1907 #define DUK_STRIDX_JSON_EXT_FUNCTION1                                 120                            /* '{"_func":true}' */
1908 #define DUK_HEAP_STRING_JSON_EXT_FUNCTION1(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION1)
1909 #define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION1(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION1)
1910 #define DUK_STRIDX_JSON_EXT_FUNCTION2                                 121                            /* '{_func:true}' */
1911 #define DUK_HEAP_STRING_JSON_EXT_FUNCTION2(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION2)
1912 #define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION2(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION2)
1913 #define DUK_STRIDX_BREAK                                              122                            /* 'break' */
1914 #define DUK_HEAP_STRING_BREAK(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BREAK)
1915 #define DUK_HTHREAD_STRING_BREAK(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BREAK)
1916 #define DUK_STRIDX_CASE                                               123                            /* 'case' */
1917 #define DUK_HEAP_STRING_CASE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CASE)
1918 #define DUK_HTHREAD_STRING_CASE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CASE)
1919 #define DUK_STRIDX_CATCH                                              124                            /* 'catch' */
1920 #define DUK_HEAP_STRING_CATCH(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CATCH)
1921 #define DUK_HTHREAD_STRING_CATCH(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CATCH)
1922 #define DUK_STRIDX_CONTINUE                                           125                            /* 'continue' */
1923 #define DUK_HEAP_STRING_CONTINUE(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONTINUE)
1924 #define DUK_HTHREAD_STRING_CONTINUE(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONTINUE)
1925 #define DUK_STRIDX_DEBUGGER                                           126                            /* 'debugger' */
1926 #define DUK_HEAP_STRING_DEBUGGER(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEBUGGER)
1927 #define DUK_HTHREAD_STRING_DEBUGGER(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEBUGGER)
1928 #define DUK_STRIDX_DEFAULT                                            127                            /* 'default' */
1929 #define DUK_HEAP_STRING_DEFAULT(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEFAULT)
1930 #define DUK_HTHREAD_STRING_DEFAULT(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEFAULT)
1931 #define DUK_STRIDX_DELETE                                             128                            /* 'delete' */
1932 #define DUK_HEAP_STRING_DELETE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE)
1933 #define DUK_HTHREAD_STRING_DELETE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE)
1934 #define DUK_STRIDX_DO                                                 129                            /* 'do' */
1935 #define DUK_HEAP_STRING_DO(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DO)
1936 #define DUK_HTHREAD_STRING_DO(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DO)
1937 #define DUK_STRIDX_ELSE                                               130                            /* 'else' */
1938 #define DUK_HEAP_STRING_ELSE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ELSE)
1939 #define DUK_HTHREAD_STRING_ELSE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ELSE)
1940 #define DUK_STRIDX_FINALLY                                            131                            /* 'finally' */
1941 #define DUK_HEAP_STRING_FINALLY(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FINALLY)
1942 #define DUK_HTHREAD_STRING_FINALLY(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FINALLY)
1943 #define DUK_STRIDX_FOR                                                132                            /* 'for' */
1944 #define DUK_HEAP_STRING_FOR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FOR)
1945 #define DUK_HTHREAD_STRING_FOR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FOR)
1946 #define DUK_STRIDX_LC_FUNCTION                                        133                            /* 'function' */
1947 #define DUK_HEAP_STRING_LC_FUNCTION(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_FUNCTION)
1948 #define DUK_HTHREAD_STRING_LC_FUNCTION(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_FUNCTION)
1949 #define DUK_STRIDX_IF                                                 134                            /* 'if' */
1950 #define DUK_HEAP_STRING_IF(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IF)
1951 #define DUK_HTHREAD_STRING_IF(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IF)
1952 #define DUK_STRIDX_IN                                                 135                            /* 'in' */
1953 #define DUK_HEAP_STRING_IN(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IN)
1954 #define DUK_HTHREAD_STRING_IN(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IN)
1955 #define DUK_STRIDX_INSTANCEOF                                         136                            /* 'instanceof' */
1956 #define DUK_HEAP_STRING_INSTANCEOF(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INSTANCEOF)
1957 #define DUK_HTHREAD_STRING_INSTANCEOF(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INSTANCEOF)
1958 #define DUK_STRIDX_NEW                                                137                            /* 'new' */
1959 #define DUK_HEAP_STRING_NEW(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEW)
1960 #define DUK_HTHREAD_STRING_NEW(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEW)
1961 #define DUK_STRIDX_RETURN                                             138                            /* 'return' */
1962 #define DUK_HEAP_STRING_RETURN(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RETURN)
1963 #define DUK_HTHREAD_STRING_RETURN(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RETURN)
1964 #define DUK_STRIDX_SWITCH                                             139                            /* 'switch' */
1965 #define DUK_HEAP_STRING_SWITCH(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SWITCH)
1966 #define DUK_HTHREAD_STRING_SWITCH(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SWITCH)
1967 #define DUK_STRIDX_THIS                                               140                            /* 'this' */
1968 #define DUK_HEAP_STRING_THIS(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THIS)
1969 #define DUK_HTHREAD_STRING_THIS(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THIS)
1970 #define DUK_STRIDX_THROW                                              141                            /* 'throw' */
1971 #define DUK_HEAP_STRING_THROW(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THROW)
1972 #define DUK_HTHREAD_STRING_THROW(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW)
1973 #define DUK_STRIDX_TRY                                                142                            /* 'try' */
1974 #define DUK_HEAP_STRING_TRY(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRY)
1975 #define DUK_HTHREAD_STRING_TRY(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRY)
1976 #define DUK_STRIDX_TYPEOF                                             143                            /* 'typeof' */
1977 #define DUK_HEAP_STRING_TYPEOF(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPEOF)
1978 #define DUK_HTHREAD_STRING_TYPEOF(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF)
1979 #define DUK_STRIDX_VAR                                                144                            /* 'var' */
1980 #define DUK_HEAP_STRING_VAR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VAR)
1981 #define DUK_HTHREAD_STRING_VAR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VAR)
1982 #define DUK_STRIDX_CONST                                              145                            /* 'const' */
1983 #define DUK_HEAP_STRING_CONST(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST)
1984 #define DUK_HTHREAD_STRING_CONST(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST)
1985 #define DUK_STRIDX_VOID                                               146                            /* 'void' */
1986 #define DUK_HEAP_STRING_VOID(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VOID)
1987 #define DUK_HTHREAD_STRING_VOID(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VOID)
1988 #define DUK_STRIDX_WHILE                                              147                            /* 'while' */
1989 #define DUK_HEAP_STRING_WHILE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE)
1990 #define DUK_HTHREAD_STRING_WHILE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WHILE)
1991 #define DUK_STRIDX_WITH                                               148                            /* 'with' */
1992 #define DUK_HEAP_STRING_WITH(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WITH)
1993 #define DUK_HTHREAD_STRING_WITH(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH)
1994 #define DUK_STRIDX_CLASS                                              149                            /* 'class' */
1995 #define DUK_HEAP_STRING_CLASS(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLASS)
1996 #define DUK_HTHREAD_STRING_CLASS(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLASS)
1997 #define DUK_STRIDX_ENUM                                               150                            /* 'enum' */
1998 #define DUK_HEAP_STRING_ENUM(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUM)
1999 #define DUK_HTHREAD_STRING_ENUM(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUM)
2000 #define DUK_STRIDX_EXPORT                                             151                            /* 'export' */
2001 #define DUK_HEAP_STRING_EXPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT)
2002 #define DUK_HTHREAD_STRING_EXPORT(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORT)
2003 #define DUK_STRIDX_EXTENDS                                            152                            /* 'extends' */
2004 #define DUK_HEAP_STRING_EXTENDS(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXTENDS)
2005 #define DUK_HTHREAD_STRING_EXTENDS(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXTENDS)
2006 #define DUK_STRIDX_IMPORT                                             153                            /* 'import' */
2007 #define DUK_HEAP_STRING_IMPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPORT)
2008 #define DUK_HTHREAD_STRING_IMPORT(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPORT)
2009 #define DUK_STRIDX_SUPER                                              154                            /* 'super' */
2010 #define DUK_HEAP_STRING_SUPER(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUPER)
2011 #define DUK_HTHREAD_STRING_SUPER(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUPER)
2012 #define DUK_STRIDX_LC_NULL                                            155                            /* 'null' */
2013 #define DUK_HEAP_STRING_LC_NULL(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NULL)
2014 #define DUK_HTHREAD_STRING_LC_NULL(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NULL)
2015 #define DUK_STRIDX_TRUE                                               156                            /* 'true' */
2016 #define DUK_HEAP_STRING_TRUE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRUE)
2017 #define DUK_HTHREAD_STRING_TRUE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRUE)
2018 #define DUK_STRIDX_FALSE                                              157                            /* 'false' */
2019 #define DUK_HEAP_STRING_FALSE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FALSE)
2020 #define DUK_HTHREAD_STRING_FALSE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FALSE)
2021 #define DUK_STRIDX_IMPLEMENTS                                         158                            /* 'implements' */
2022 #define DUK_HEAP_STRING_IMPLEMENTS(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPLEMENTS)
2023 #define DUK_HTHREAD_STRING_IMPLEMENTS(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPLEMENTS)
2024 #define DUK_STRIDX_INTERFACE                                          159                            /* 'interface' */
2025 #define DUK_HEAP_STRING_INTERFACE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INTERFACE)
2026 #define DUK_HTHREAD_STRING_INTERFACE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INTERFACE)
2027 #define DUK_STRIDX_LET                                                160                            /* 'let' */
2028 #define DUK_HEAP_STRING_LET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LET)
2029 #define DUK_HTHREAD_STRING_LET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LET)
2030 #define DUK_STRIDX_PACKAGE                                            161                            /* 'package' */
2031 #define DUK_HEAP_STRING_PACKAGE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PACKAGE)
2032 #define DUK_HTHREAD_STRING_PACKAGE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PACKAGE)
2033 #define DUK_STRIDX_PRIVATE                                            162                            /* 'private' */
2034 #define DUK_HEAP_STRING_PRIVATE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PRIVATE)
2035 #define DUK_HTHREAD_STRING_PRIVATE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PRIVATE)
2036 #define DUK_STRIDX_PROTECTED                                          163                            /* 'protected' */
2037 #define DUK_HEAP_STRING_PROTECTED(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTECTED)
2038 #define DUK_HTHREAD_STRING_PROTECTED(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTECTED)
2039 #define DUK_STRIDX_PUBLIC                                             164                            /* 'public' */
2040 #define DUK_HEAP_STRING_PUBLIC(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PUBLIC)
2041 #define DUK_HTHREAD_STRING_PUBLIC(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PUBLIC)
2042 #define DUK_STRIDX_STATIC                                             165                            /* 'static' */
2043 #define DUK_HEAP_STRING_STATIC(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STATIC)
2044 #define DUK_HTHREAD_STRING_STATIC(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STATIC)
2045 #define DUK_STRIDX_YIELD                                              166                            /* 'yield' */
2046 #define DUK_HEAP_STRING_YIELD(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD)
2047 #define DUK_HTHREAD_STRING_YIELD(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD)
2048 
2049 #define DUK_HEAP_NUM_STRINGS                                          167
2050 #define DUK_STRIDX_START_RESERVED                                     122
2051 #define DUK_STRIDX_START_STRICT_RESERVED                              158
2052 #define DUK_STRIDX_END_RESERVED                                       167                            /* exclusive endpoint */
2053 
2054 /* To convert a heap stridx to a token number, subtract
2055  * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
2056  */
2057 #if !defined(DUK_SINGLE_FILE)
2058 DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[972];
2059 #endif  /* !DUK_SINGLE_FILE */
2060 #define DUK_STRDATA_MAX_STRLEN                                        27
2061 #define DUK_STRDATA_DATA_LENGTH                                       972
2062 #endif  /* DUK_USE_ROM_STRINGS */
2063 
2064 #if defined(DUK_USE_ROM_OBJECTS)
2065 #error RAM support not enabled, rerun configure.py with --ram-support
2066 #else  /* DUK_USE_ROM_OBJECTS */
2067 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor(duk_context *ctx);
2068 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_constructor(duk_context *ctx);
2069 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_context *ctx);
2070 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor(duk_context *ctx);
2071 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor(duk_context *ctx);
2072 DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx);
2073 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_constructor(duk_context *ctx);
2074 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor(duk_context *ctx);
2075 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx);
2076 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx);
2077 DUK_INTERNAL_DECL duk_ret_t duk_bi_type_error_thrower(duk_context *ctx);
2078 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx);
2079 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx);
2080 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_constructor(duk_context *ctx);
2081 DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_constructor(duk_context *ctx);
2082 DUK_INTERNAL_DECL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx);
2083 DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_constructor_shared(duk_context *ctx);
2084 DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx);
2085 DUK_INTERNAL_DECL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx);
2086 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx);
2087 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx);
2088 DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_constructor(duk_context *ctx);
2089 DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_constructor(duk_context *ctx);
2090 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_eval(duk_context *ctx);
2091 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx);
2092 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx);
2093 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx);
2094 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx);
2095 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx);
2096 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx);
2097 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_escape(duk_context *ctx);
2098 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx);
2099 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx);
2100 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx);
2101 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_context *ctx);
2102 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx);
2103 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_assign(duk_context *ctx);
2104 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_create(duk_context *ctx);
2105 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_property(duk_context *ctx);
2106 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx);
2107 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx);
2108 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx);
2109 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_context *ctx);
2110 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx);
2111 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is(duk_context *ctx);
2112 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx);
2113 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_context *ctx);
2114 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx);
2115 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_has_own_property(duk_context *ctx);
2116 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_context *ctx);
2117 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx);
2118 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_defineaccessor(duk_context *ctx);
2119 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_lookupaccessor(duk_context *ctx);
2120 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx);
2121 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx);
2122 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx);
2123 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx);
2124 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_hasinstance(duk_context *ctx);
2125 DUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_length(duk_context *ctx);
2126 DUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_name(duk_context *ctx);
2127 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx);
2128 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx);
2129 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx);
2130 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx);
2131 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx);
2132 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_push(duk_context *ctx);
2133 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reverse(duk_context *ctx);
2134 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx);
2135 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx);
2136 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx);
2137 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx);
2138 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx);
2139 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx);
2140 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx);
2141 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx);
2142 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx);
2143 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_code_point(duk_context *ctx);
2144 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_to_string(duk_context *ctx);
2145 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_at(duk_context *ctx);
2146 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_code_at(duk_context *ctx);
2147 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_concat(duk_context *ctx);
2148 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_context *ctx);
2149 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_locale_compare(duk_context *ctx);
2150 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_match(duk_context *ctx);
2151 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx);
2152 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx);
2153 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_slice(duk_context *ctx);
2154 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_split(duk_context *ctx);
2155 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substring(duk_context *ctx);
2156 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_context *ctx);
2157 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_trim(duk_context *ctx);
2158 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_repeat(duk_context *ctx);
2159 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_context *ctx);
2160 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_includes(duk_context *ctx);
2161 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx);
2162 DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx);
2163 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_check_shared(duk_context *ctx);
2164 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx);
2165 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx);
2166 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx);
2167 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_fixed(duk_context *ctx);
2168 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx);
2169 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_precision(duk_context *ctx);
2170 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx);
2171 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx);
2172 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_now(duk_context *ctx);
2173 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_context *ctx);
2174 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx);
2175 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx);
2176 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx);
2177 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx);
2178 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx);
2179 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx);
2180 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_toprimitive(duk_context *ctx);
2181 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx);
2182 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx);
2183 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_tostring(duk_context *ctx);
2184 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_flags(duk_context *ctx);
2185 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_context *ctx);
2186 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx);
2187 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_setter(duk_context *ctx);
2188 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx);
2189 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_setter(duk_context *ctx);
2190 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx);
2191 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_context *ctx);
2192 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx);
2193 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx);
2194 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx);
2195 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_clz32(duk_context *ctx);
2196 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_hypot(duk_context *ctx);
2197 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_imul(duk_context *ctx);
2198 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_max(duk_context *ctx);
2199 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_min(duk_context *ctx);
2200 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_random(duk_context *ctx);
2201 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_sign(duk_context *ctx);
2202 DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_parse(duk_context *ctx);
2203 DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_stringify(duk_context *ctx);
2204 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx);
2205 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_act(duk_context *ctx);
2206 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx);
2207 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx);
2208 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx);
2209 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx);
2210 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx);
2211 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_yield(duk_context *ctx);
2212 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_resume(duk_context *ctx);
2213 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_current(duk_context *ctx);
2214 DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_context *ctx);
2215 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_apply(duk_context *ctx);
2216 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_construct(duk_context *ctx);
2217 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_delete_property(duk_context *ctx);
2218 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_get(duk_context *ctx);
2219 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_has(duk_context *ctx);
2220 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_set(duk_context *ctx);
2221 DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_key_for(duk_context *ctx);
2222 DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_tostring_shared(duk_context *ctx);
2223 DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_toprimitive(duk_context *ctx);
2224 DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx);
2225 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_context *ctx);
2226 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx);
2227 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_context *ctx);
2228 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_buffer_getter(duk_context *ctx);
2229 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx);
2230 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx);
2231 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_set(duk_context *ctx);
2232 DUK_INTERNAL_DECL duk_ret_t duk_bi_uint8array_allocplain(duk_context *ctx);
2233 DUK_INTERNAL_DECL duk_ret_t duk_bi_uint8array_plainof(duk_context *ctx);
2234 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx);
2235 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx);
2236 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx);
2237 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx);
2238 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx);
2239 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx);
2240 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx);
2241 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx);
2242 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx);
2243 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx);
2244 DUK_INTERNAL_DECL duk_ret_t duk_bi_cbor_encode(duk_context *ctx);
2245 DUK_INTERNAL_DECL duk_ret_t duk_bi_cbor_decode(duk_context *ctx);
2246 DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_context *ctx);
2247 DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encode(duk_context *ctx);
2248 DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_context *ctx);
2249 DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_context *ctx);
2250 DUK_INTERNAL_DECL duk_ret_t duk_bi_performance_now(duk_context *ctx);
2251 #if !defined(DUK_SINGLE_FILE)
2252 DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[185];
2253 #endif  /* !DUK_SINGLE_FILE */
2254 #define DUK_BIDX_GLOBAL                                               0
2255 #define DUK_BIDX_GLOBAL_ENV                                           1
2256 #define DUK_BIDX_OBJECT_CONSTRUCTOR                                   2
2257 #define DUK_BIDX_OBJECT_PROTOTYPE                                     3
2258 #define DUK_BIDX_FUNCTION_CONSTRUCTOR                                 4
2259 #define DUK_BIDX_FUNCTION_PROTOTYPE                                   5
2260 #define DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE                            6
2261 #define DUK_BIDX_ARRAY_CONSTRUCTOR                                    7
2262 #define DUK_BIDX_ARRAY_PROTOTYPE                                      8
2263 #define DUK_BIDX_STRING_CONSTRUCTOR                                   9
2264 #define DUK_BIDX_STRING_PROTOTYPE                                     10
2265 #define DUK_BIDX_BOOLEAN_CONSTRUCTOR                                  11
2266 #define DUK_BIDX_BOOLEAN_PROTOTYPE                                    12
2267 #define DUK_BIDX_NUMBER_CONSTRUCTOR                                   13
2268 #define DUK_BIDX_NUMBER_PROTOTYPE                                     14
2269 #define DUK_BIDX_DATE_CONSTRUCTOR                                     15
2270 #define DUK_BIDX_DATE_PROTOTYPE                                       16
2271 #define DUK_BIDX_REGEXP_CONSTRUCTOR                                   17
2272 #define DUK_BIDX_REGEXP_PROTOTYPE                                     18
2273 #define DUK_BIDX_ERROR_CONSTRUCTOR                                    19
2274 #define DUK_BIDX_ERROR_PROTOTYPE                                      20
2275 #define DUK_BIDX_EVAL_ERROR_CONSTRUCTOR                               21
2276 #define DUK_BIDX_EVAL_ERROR_PROTOTYPE                                 22
2277 #define DUK_BIDX_RANGE_ERROR_CONSTRUCTOR                              23
2278 #define DUK_BIDX_RANGE_ERROR_PROTOTYPE                                24
2279 #define DUK_BIDX_REFERENCE_ERROR_CONSTRUCTOR                          25
2280 #define DUK_BIDX_REFERENCE_ERROR_PROTOTYPE                            26
2281 #define DUK_BIDX_SYNTAX_ERROR_CONSTRUCTOR                             27
2282 #define DUK_BIDX_SYNTAX_ERROR_PROTOTYPE                               28
2283 #define DUK_BIDX_TYPE_ERROR_CONSTRUCTOR                               29
2284 #define DUK_BIDX_TYPE_ERROR_PROTOTYPE                                 30
2285 #define DUK_BIDX_URI_ERROR_CONSTRUCTOR                                31
2286 #define DUK_BIDX_URI_ERROR_PROTOTYPE                                  32
2287 #define DUK_BIDX_TYPE_ERROR_THROWER                                   33
2288 #define DUK_BIDX_DUKTAPE                                              34
2289 #define DUK_BIDX_THREAD_PROTOTYPE                                     35
2290 #define DUK_BIDX_POINTER_PROTOTYPE                                    36
2291 #define DUK_BIDX_DOUBLE_ERROR                                         37
2292 #define DUK_BIDX_SYMBOL_PROTOTYPE                                     38
2293 #define DUK_BIDX_ARRAYBUFFER_PROTOTYPE                                39
2294 #define DUK_BIDX_DATAVIEW_PROTOTYPE                                   40
2295 #define DUK_BIDX_INT8ARRAY_PROTOTYPE                                  41
2296 #define DUK_BIDX_UINT8ARRAY_PROTOTYPE                                 42
2297 #define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE                          43
2298 #define DUK_BIDX_INT16ARRAY_PROTOTYPE                                 44
2299 #define DUK_BIDX_UINT16ARRAY_PROTOTYPE                                45
2300 #define DUK_BIDX_INT32ARRAY_PROTOTYPE                                 46
2301 #define DUK_BIDX_UINT32ARRAY_PROTOTYPE                                47
2302 #define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE                               48
2303 #define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE                               49
2304 #define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE                              50
2305 #define DUK_NUM_BUILTINS                                              51
2306 #define DUK_NUM_BIDX_BUILTINS                                         51
2307 #define DUK_NUM_ALL_BUILTINS                                          80
2308 #if defined(DUK_USE_DOUBLE_LE)
2309 #if !defined(DUK_SINGLE_FILE)
2310 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4281];
2311 #endif  /* !DUK_SINGLE_FILE */
2312 #define DUK_BUILTINS_DATA_LENGTH                                      4281
2313 #elif defined(DUK_USE_DOUBLE_BE)
2314 #if !defined(DUK_SINGLE_FILE)
2315 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4281];
2316 #endif  /* !DUK_SINGLE_FILE */
2317 #define DUK_BUILTINS_DATA_LENGTH                                      4281
2318 #elif defined(DUK_USE_DOUBLE_ME)
2319 #if !defined(DUK_SINGLE_FILE)
2320 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4281];
2321 #endif  /* !DUK_SINGLE_FILE */
2322 #define DUK_BUILTINS_DATA_LENGTH                                      4281
2323 #else
2324 #error invalid endianness defines
2325 #endif
2326 #endif  /* DUK_USE_ROM_OBJECTS */
2327 #endif  /* DUK_BUILTINS_H_INCLUDED */
2328 #line 45 "duk_internal.h"
2329 
2330 /* #include duk_util.h */
2331 #line 1 "duk_util.h"
2332 /*
2333  *  Utilities
2334  */
2335 
2336 #if !defined(DUK_UTIL_H_INCLUDED)
2337 #define DUK_UTIL_H_INCLUDED
2338 
2339 #if defined(DUK_USE_GET_RANDOM_DOUBLE)
2340 #define DUK_UTIL_GET_RANDOM_DOUBLE(thr) DUK_USE_GET_RANDOM_DOUBLE((thr)->heap_udata)
2341 #else
2342 #define DUK_UTIL_GET_RANDOM_DOUBLE(thr) duk_util_tinyrandom_get_double(thr)
2343 #endif
2344 
2345 /*
2346  *  Some useful constants
2347  */
2348 
2349 #define DUK_DOUBLE_2TO32     4294967296.0
2350 #define DUK_DOUBLE_2TO31     2147483648.0
2351 #define DUK_DOUBLE_LOG2E     1.4426950408889634
2352 #define DUK_DOUBLE_LOG10E    0.4342944819032518
2353 
2354 /*
2355  *  Endian conversion
2356  */
2357 
2358 #if defined(DUK_USE_INTEGER_LE)
2359 #define DUK_HTON32(x) DUK_BSWAP32((x))
2360 #define DUK_NTOH32(x) DUK_BSWAP32((x))
2361 #define DUK_HTON16(x) DUK_BSWAP16((x))
2362 #define DUK_NTOH16(x) DUK_BSWAP16((x))
2363 #elif defined(DUK_USE_INTEGER_BE)
2364 #define DUK_HTON32(x) (x)
2365 #define DUK_NTOH32(x) (x)
2366 #define DUK_HTON16(x) (x)
2367 #define DUK_NTOH16(x) (x)
2368 #else
2369 #error internal error, endianness defines broken
2370 #endif
2371 
2372 /*
2373  *  Bitstream decoder
2374  */
2375 
2376 struct duk_bitdecoder_ctx {
2377 	const duk_uint8_t *data;
2378 	duk_size_t offset;
2379 	duk_size_t length;
2380 	duk_uint32_t currval;
2381 	duk_small_int_t currbits;
2382 };
2383 
2384 #define DUK_BD_BITPACKED_STRING_MAXLEN 256
2385 
2386 /*
2387  *  Bitstream encoder
2388  */
2389 
2390 struct duk_bitencoder_ctx {
2391 	duk_uint8_t *data;
2392 	duk_size_t offset;
2393 	duk_size_t length;
2394 	duk_uint32_t currval;
2395 	duk_small_int_t currbits;
2396 	duk_small_int_t truncated;
2397 };
2398 
2399 /*
2400  *  Raw write/read macros for big endian, unaligned basic values.
2401  *  Caller ensures there's enough space.  The INC macro variants
2402  *  update the pointer argument automatically.
2403  */
2404 
2405 #define DUK_RAW_WRITE_U8(ptr,val)  do { \
2406 		*(ptr) = (duk_uint8_t) (val); \
2407 	} while (0)
2408 #define DUK_RAW_WRITE_U16_BE(ptr,val) duk_raw_write_u16_be((ptr), (duk_uint16_t) (val))
2409 #define DUK_RAW_WRITE_U32_BE(ptr,val) duk_raw_write_u32_be((ptr), (duk_uint32_t) (val))
2410 #define DUK_RAW_WRITE_FLOAT_BE(ptr,val) duk_raw_write_float_be((ptr), (duk_float_t) (val))
2411 #define DUK_RAW_WRITE_DOUBLE_BE(ptr,val) duk_raw_write_double_be((ptr), (duk_double_t) (val))
2412 #define DUK_RAW_WRITE_XUTF8(ptr,val) duk_raw_write_xutf8((ptr), (duk_ucodepoint_t) (val))
2413 
2414 #define DUK_RAW_WRITEINC_U8(ptr,val)  do { \
2415 		*(ptr)++ = (duk_uint8_t) (val); \
2416 	} while (0)
2417 #define DUK_RAW_WRITEINC_U16_BE(ptr,val) duk_raw_writeinc_u16_be(&(ptr), (duk_uint16_t) (val))
2418 #define DUK_RAW_WRITEINC_U32_BE(ptr,val) duk_raw_writeinc_u32_be(&(ptr), (duk_uint32_t) (val))
2419 #define DUK_RAW_WRITEINC_FLOAT_BE(ptr,val) duk_raw_writeinc_float_be(&(ptr), (duk_float_t) (val))
2420 #define DUK_RAW_WRITEINC_DOUBLE_BE(ptr,val) duk_raw_writeinc_double_be(&(ptr), (duk_double_t) (val))
2421 #define DUK_RAW_WRITEINC_XUTF8(ptr,val) duk_raw_writeinc_xutf8(&(ptr), (duk_ucodepoint_t) (val))
2422 #define DUK_RAW_WRITEINC_CESU8(ptr,val) duk_raw_writeinc_cesu8(&(ptr), (duk_ucodepoint_t) (val))
2423 
2424 #define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)))
2425 #define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be((ptr));
2426 #define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be((ptr));
2427 #define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be((ptr));
2428 
2429 #define DUK_RAW_READINC_U8(ptr) ((duk_uint8_t) (*(ptr)++))
2430 #define DUK_RAW_READINC_U16_BE(ptr) duk_raw_readinc_u16_be(&(ptr));
2431 #define DUK_RAW_READINC_U32_BE(ptr) duk_raw_readinc_u32_be(&(ptr));
2432 #define DUK_RAW_READINC_DOUBLE_BE(ptr) duk_raw_readinc_double_be(&(ptr));
2433 
2434 /*
2435  *  Double and float byte order operations.
2436  */
2437 
2438 DUK_INTERNAL_DECL void duk_dblunion_host_to_little(duk_double_union *u);
2439 DUK_INTERNAL_DECL void duk_dblunion_little_to_host(duk_double_union *u);
2440 DUK_INTERNAL_DECL void duk_dblunion_host_to_big(duk_double_union *u);
2441 DUK_INTERNAL_DECL void duk_dblunion_big_to_host(duk_double_union *u);
2442 DUK_INTERNAL_DECL void duk_fltunion_host_to_big(duk_float_union *u);
2443 DUK_INTERNAL_DECL void duk_fltunion_big_to_host(duk_float_union *u);
2444 
2445 /*
2446  *  Buffer writer (dynamic buffer only)
2447  *
2448  *  Helper for writing to a dynamic buffer with a concept of a "slack" area
2449  *  to reduce resizes.  You can ensure there is enough space beforehand and
2450  *  then write for a while without further checks, relying on a stable data
2451  *  pointer.  Slack handling is automatic so call sites only indicate how
2452  *  much data they need right now.
2453  *
2454  *  There are several ways to write using bufwriter.  The best approach
2455  *  depends mainly on how much performance matters over code footprint.
2456  *  The key issues are (1) ensuring there is space and (2) keeping the
2457  *  pointers consistent.  Fast code should ensure space for multiple writes
2458  *  with one ensure call.  Fastest inner loop code can temporarily borrow
2459  *  the 'p' pointer but must write it back eventually.
2460  *
2461  *  Be careful to ensure all macro arguments (other than static pointers like
2462  *  'thr' and 'bw_ctx') are evaluated exactly once, using temporaries if
2463  *  necessary (if that's not possible, there should be a note near the macro).
2464  *  Buffer write arguments often contain arithmetic etc so this is
2465  *  particularly important here.
2466  */
2467 
2468 /* XXX: Migrate bufwriter and other read/write helpers to its own header? */
2469 
2470 struct duk_bufwriter_ctx {
2471 	duk_uint8_t *p;
2472 	duk_uint8_t *p_base;
2473 	duk_uint8_t *p_limit;
2474 	duk_hbuffer_dynamic *buf;
2475 };
2476 
2477 #if defined(DUK_USE_PREFER_SIZE)
2478 #define DUK_BW_SLACK_ADD           64
2479 #define DUK_BW_SLACK_SHIFT         4    /* 2^4 -> 1/16 = 6.25% slack */
2480 #else
2481 #define DUK_BW_SLACK_ADD           64
2482 #define DUK_BW_SLACK_SHIFT         2    /* 2^2 -> 1/4 = 25% slack */
2483 #endif
2484 
2485 /* Initialization and finalization (compaction), converting to other types. */
2486 
2487 #define DUK_BW_INIT_PUSHBUF(thr,bw_ctx,sz) do { \
2488 		duk_bw_init_pushbuf((thr), (bw_ctx), (sz)); \
2489 	} while (0)
2490 #define DUK_BW_INIT_WITHBUF(thr,bw_ctx,buf) do { \
2491 		duk_bw_init((thr), (bw_ctx), (buf)); \
2492 	} while (0)
2493 #define DUK_BW_COMPACT(thr,bw_ctx) do { \
2494 		/* Make underlying buffer compact to match DUK_BW_GET_SIZE(). */ \
2495 		duk_bw_compact((thr), (bw_ctx)); \
2496 	} while (0)
2497 #define DUK_BW_PUSH_AS_STRING(thr,bw_ctx) do { \
2498 		duk_push_lstring((thr), \
2499 		                 (const char *) (bw_ctx)->p_base, \
2500 		                 (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
2501 	} while (0)
2502 
2503 /* Pointers may be NULL for a while when 'buf' size is zero and before any
2504  * ENSURE calls have been made.  Once an ENSURE has been made, the pointers
2505  * are required to be non-NULL so that it's always valid to use memcpy() and
2506  * memmove(), even for zero size.
2507  */
2508 #if defined(DUK_USE_ASSERTIONS)
2509 DUK_INTERNAL_DECL void duk_bw_assert_valid(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx);
2510 #define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx)  (duk_bw_assert_valid((thr), (bw_ctx)))
2511 #define DUK_BW_ASSERT_VALID(thr,bw_ctx)  do { duk_bw_assert_valid((thr), (bw_ctx)); } while (0)
2512 #else
2513 #define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx)  DUK_ASSERT_EXPR(1)
2514 #define DUK_BW_ASSERT_VALID(thr,bw_ctx)  do {} while (0)
2515 #endif
2516 
2517 /* Working with the pointer and current size. */
2518 
2519 #define DUK_BW_GET_PTR(thr,bw_ctx) \
2520 	((bw_ctx)->p)
2521 #define DUK_BW_SET_PTR(thr,bw_ctx,ptr) do { \
2522 		(bw_ctx)->p = (ptr); \
2523 	} while (0)
2524 #define DUK_BW_ADD_PTR(thr,bw_ctx,delta) do { \
2525 		(bw_ctx)->p += (delta); \
2526 	} while (0)
2527 #define DUK_BW_GET_BASEPTR(thr,bw_ctx) \
2528 	((bw_ctx)->p_base)
2529 #define DUK_BW_GET_LIMITPTR(thr,bw_ctx) \
2530 	((bw_ctx)->p_limit)
2531 #define DUK_BW_GET_SIZE(thr,bw_ctx) \
2532 	((duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base))
2533 #define DUK_BW_SET_SIZE(thr,bw_ctx,sz) do { \
2534 		DUK_ASSERT((duk_size_t) (sz) <= (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
2535 		(bw_ctx)->p = (bw_ctx)->p_base + (sz); \
2536 	} while (0)
2537 #define DUK_BW_RESET_SIZE(thr,bw_ctx) do { \
2538 		/* Reset to zero size, keep current limit. */ \
2539 		(bw_ctx)->p = (bw_ctx)->p_base; \
2540 	} while (0)
2541 #define DUK_BW_GET_BUFFER(thr,bw_ctx) \
2542 	((bw_ctx)->buf)
2543 
2544 /* Ensuring (reserving) space. */
2545 
2546 #define DUK_BW_ENSURE(thr,bw_ctx,sz) do { \
2547 		duk_size_t duk__sz, duk__space; \
2548 		DUK_BW_ASSERT_VALID((thr), (bw_ctx)); \
2549 		duk__sz = (sz); \
2550 		duk__space = (duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p); \
2551 		if (duk__space < duk__sz) { \
2552 			(void) duk_bw_resize((thr), (bw_ctx), duk__sz); \
2553 		} \
2554 	} while (0)
2555 /* NOTE: Multiple evaluation of 'ptr' in this macro. */
2556 /* XXX: Rework to use an always-inline function? */
2557 #define DUK_BW_ENSURE_RAW(thr,bw_ctx,sz,ptr) \
2558 	(((duk_size_t) ((bw_ctx)->p_limit - (ptr)) >= (sz)) ? \
2559 	 (ptr) : \
2560 	 ((bw_ctx)->p = (ptr), duk_bw_resize((thr),(bw_ctx),(sz))))
2561 #define DUK_BW_ENSURE_GETPTR(thr,bw_ctx,sz) \
2562 	DUK_BW_ENSURE_RAW((thr), (bw_ctx), (sz), (bw_ctx)->p)
2563 #define DUK_BW_ASSERT_SPACE_EXPR(thr,bw_ctx,sz) \
2564 	(DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)), \
2565 	 DUK_ASSERT_EXPR((duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p) >= (duk_size_t) (sz)))
2566 #define DUK_BW_ASSERT_SPACE(thr,bw_ctx,sz) do { \
2567 		DUK_BW_ASSERT_SPACE_EXPR((thr), (bw_ctx), (sz)); \
2568 	} while (0)
2569 
2570 /* Miscellaneous. */
2571 
2572 #define DUK_BW_SETPTR_AND_COMPACT(thr,bw_ctx,ptr) do { \
2573 		(bw_ctx)->p = (ptr); \
2574 		duk_bw_compact((thr), (bw_ctx)); \
2575 	} while (0)
2576 
2577 /* Fast write calls which assume you control the slack beforehand.
2578  * Multibyte write variants exist and use a temporary write pointer
2579  * because byte writes alias with anything: with a stored pointer
2580  * explicit pointer load/stores get generated (e.g. gcc -Os).
2581  */
2582 
2583 #define DUK_BW_WRITE_RAW_U8(thr,bw_ctx,val) do { \
2584 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 1); \
2585 		*(bw_ctx)->p++ = (duk_uint8_t) (val); \
2586 	} while (0)
2587 #define DUK_BW_WRITE_RAW_U8_2(thr,bw_ctx,val1,val2) do { \
2588 		duk_uint8_t *duk__p; \
2589 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 2); \
2590 		duk__p = (bw_ctx)->p; \
2591 		*duk__p++ = (duk_uint8_t) (val1); \
2592 		*duk__p++ = (duk_uint8_t) (val2); \
2593 		(bw_ctx)->p = duk__p; \
2594 	} while (0)
2595 #define DUK_BW_WRITE_RAW_U8_3(thr,bw_ctx,val1,val2,val3) do { \
2596 		duk_uint8_t *duk__p; \
2597 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 3); \
2598 		duk__p = (bw_ctx)->p; \
2599 		*duk__p++ = (duk_uint8_t) (val1); \
2600 		*duk__p++ = (duk_uint8_t) (val2); \
2601 		*duk__p++ = (duk_uint8_t) (val3); \
2602 		(bw_ctx)->p = duk__p; \
2603 	} while (0)
2604 #define DUK_BW_WRITE_RAW_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
2605 		duk_uint8_t *duk__p; \
2606 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 4); \
2607 		duk__p = (bw_ctx)->p; \
2608 		*duk__p++ = (duk_uint8_t) (val1); \
2609 		*duk__p++ = (duk_uint8_t) (val2); \
2610 		*duk__p++ = (duk_uint8_t) (val3); \
2611 		*duk__p++ = (duk_uint8_t) (val4); \
2612 		(bw_ctx)->p = duk__p; \
2613 	} while (0)
2614 #define DUK_BW_WRITE_RAW_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
2615 		duk_uint8_t *duk__p; \
2616 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 5); \
2617 		duk__p = (bw_ctx)->p; \
2618 		*duk__p++ = (duk_uint8_t) (val1); \
2619 		*duk__p++ = (duk_uint8_t) (val2); \
2620 		*duk__p++ = (duk_uint8_t) (val3); \
2621 		*duk__p++ = (duk_uint8_t) (val4); \
2622 		*duk__p++ = (duk_uint8_t) (val5); \
2623 		(bw_ctx)->p = duk__p; \
2624 	} while (0)
2625 #define DUK_BW_WRITE_RAW_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
2626 		duk_uint8_t *duk__p; \
2627 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 6); \
2628 		duk__p = (bw_ctx)->p; \
2629 		*duk__p++ = (duk_uint8_t) (val1); \
2630 		*duk__p++ = (duk_uint8_t) (val2); \
2631 		*duk__p++ = (duk_uint8_t) (val3); \
2632 		*duk__p++ = (duk_uint8_t) (val4); \
2633 		*duk__p++ = (duk_uint8_t) (val5); \
2634 		*duk__p++ = (duk_uint8_t) (val6); \
2635 		(bw_ctx)->p = duk__p; \
2636 	} while (0)
2637 #define DUK_BW_WRITE_RAW_XUTF8(thr,bw_ctx,cp) do { \
2638 		duk_ucodepoint_t duk__cp; \
2639 		duk_small_int_t duk__enc_len; \
2640 		duk__cp = (duk_ucodepoint_t) (cp); \
2641 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_xutf8_length(duk__cp)); \
2642 		duk__enc_len = duk_unicode_encode_xutf8(duk__cp, (bw_ctx)->p); \
2643 		(bw_ctx)->p += duk__enc_len; \
2644 	} while (0)
2645 #define DUK_BW_WRITE_RAW_CESU8(thr,bw_ctx,cp) do { \
2646 		duk_ucodepoint_t duk__cp; \
2647 		duk_small_int_t duk__enc_len; \
2648 		duk__cp = (duk_ucodepoint_t) (cp); \
2649 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_cesu8_length(duk__cp)); \
2650 		duk__enc_len = duk_unicode_encode_cesu8(duk__cp, (bw_ctx)->p); \
2651 		(bw_ctx)->p += duk__enc_len; \
2652 	} while (0)
2653 /* XXX: add temporary duk__p pointer here too; sharing */
2654 /* XXX: avoid unsafe variants */
2655 #define DUK_BW_WRITE_RAW_BYTES(thr,bw_ctx,valptr,valsz) do { \
2656 		const void *duk__valptr; \
2657 		duk_size_t duk__valsz; \
2658 		duk__valptr = (const void *) (valptr); \
2659 		duk__valsz = (duk_size_t) (valsz); \
2660 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
2661 		(bw_ctx)->p += duk__valsz; \
2662 	} while (0)
2663 #define DUK_BW_WRITE_RAW_CSTRING(thr,bw_ctx,val) do { \
2664 		const duk_uint8_t *duk__val; \
2665 		duk_size_t duk__val_len; \
2666 		duk__val = (const duk_uint8_t *) (val); \
2667 		duk__val_len = DUK_STRLEN((const char *) duk__val); \
2668 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
2669 		(bw_ctx)->p += duk__val_len; \
2670 	} while (0)
2671 #define DUK_BW_WRITE_RAW_HSTRING(thr,bw_ctx,val) do { \
2672 		duk_size_t duk__val_len; \
2673 		duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
2674 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
2675 		(bw_ctx)->p += duk__val_len; \
2676 	} while (0)
2677 #define DUK_BW_WRITE_RAW_HBUFFER(thr,bw_ctx,val) do { \
2678 		duk_size_t duk__val_len; \
2679 		duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
2680 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2681 		(bw_ctx)->p += duk__val_len; \
2682 	} while (0)
2683 #define DUK_BW_WRITE_RAW_HBUFFER_FIXED(thr,bw_ctx,val) do { \
2684 		duk_size_t duk__val_len; \
2685 		duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
2686 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2687 		(bw_ctx)->p += duk__val_len; \
2688 	} while (0)
2689 #define DUK_BW_WRITE_RAW_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
2690 		duk_size_t duk__val_len; \
2691 		duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
2692 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2693 		(bw_ctx)->p += duk__val_len; \
2694 	} while (0)
2695 
2696 /* Append bytes from a slice already in the buffer. */
2697 #define DUK_BW_WRITE_RAW_SLICE(thr,bw,dst_off,dst_len) \
2698 	duk_bw_write_raw_slice((thr), (bw), (dst_off), (dst_len))
2699 
2700 /* Insert bytes in the middle of the buffer from an external buffer. */
2701 #define DUK_BW_INSERT_RAW_BYTES(thr,bw,dst_off,buf,len) \
2702 	duk_bw_insert_raw_bytes((thr), (bw), (dst_off), (buf), (len))
2703 
2704 /* Insert bytes in the middle of the buffer from a slice already
2705  * in the buffer.  Source offset is interpreted "before" the operation.
2706  */
2707 #define DUK_BW_INSERT_RAW_SLICE(thr,bw,dst_off,src_off,len) \
2708 	duk_bw_insert_raw_slice((thr), (bw), (dst_off), (src_off), (len))
2709 
2710 /* Insert a reserved area somewhere in the buffer; caller fills it.
2711  * Evaluates to a (duk_uint_t *) pointing to the start of the reserved
2712  * area for convenience.
2713  */
2714 #define DUK_BW_INSERT_RAW_AREA(thr,bw,off,len) \
2715 	duk_bw_insert_raw_area((thr), (bw), (off), (len))
2716 
2717 /* Remove a slice from inside buffer. */
2718 #define DUK_BW_REMOVE_RAW_SLICE(thr,bw,off,len) \
2719 	duk_bw_remove_raw_slice((thr), (bw), (off), (len))
2720 
2721 /* Safe write calls which will ensure space first. */
2722 
2723 #define DUK_BW_WRITE_ENSURE_U8(thr,bw_ctx,val) do { \
2724 		DUK_BW_ENSURE((thr), (bw_ctx), 1); \
2725 		DUK_BW_WRITE_RAW_U8((thr), (bw_ctx), (val)); \
2726 	} while (0)
2727 #define DUK_BW_WRITE_ENSURE_U8_2(thr,bw_ctx,val1,val2) do { \
2728 		DUK_BW_ENSURE((thr), (bw_ctx), 2); \
2729 		DUK_BW_WRITE_RAW_U8_2((thr), (bw_ctx), (val1), (val2)); \
2730 	} while (0)
2731 #define DUK_BW_WRITE_ENSURE_U8_3(thr,bw_ctx,val1,val2,val3) do { \
2732 		DUK_BW_ENSURE((thr), (bw_ctx), 3); \
2733 		DUK_BW_WRITE_RAW_U8_3((thr), (bw_ctx), (val1), (val2), (val3)); \
2734 	} while (0)
2735 #define DUK_BW_WRITE_ENSURE_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
2736 		DUK_BW_ENSURE((thr), (bw_ctx), 4); \
2737 		DUK_BW_WRITE_RAW_U8_4((thr), (bw_ctx), (val1), (val2), (val3), (val4)); \
2738 	} while (0)
2739 #define DUK_BW_WRITE_ENSURE_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
2740 		DUK_BW_ENSURE((thr), (bw_ctx), 5); \
2741 		DUK_BW_WRITE_RAW_U8_5((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5)); \
2742 	} while (0)
2743 #define DUK_BW_WRITE_ENSURE_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
2744 		DUK_BW_ENSURE((thr), (bw_ctx), 6); \
2745 		DUK_BW_WRITE_RAW_U8_6((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5), (val6)); \
2746 	} while (0)
2747 #define DUK_BW_WRITE_ENSURE_XUTF8(thr,bw_ctx,cp) do { \
2748 		DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_XUTF8_LENGTH); \
2749 		DUK_BW_WRITE_RAW_XUTF8((thr), (bw_ctx), (cp)); \
2750 	} while (0)
2751 #define DUK_BW_WRITE_ENSURE_CESU8(thr,bw_ctx,cp) do { \
2752 		DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_CESU8_LENGTH); \
2753 		DUK_BW_WRITE_RAW_CESU8((thr), (bw_ctx), (cp)); \
2754 	} while (0)
2755 /* XXX: add temporary duk__p pointer here too; sharing */
2756 /* XXX: avoid unsafe */
2757 #define DUK_BW_WRITE_ENSURE_BYTES(thr,bw_ctx,valptr,valsz) do { \
2758 		const void *duk__valptr; \
2759 		duk_size_t duk__valsz; \
2760 		duk__valptr = (const void *) (valptr); \
2761 		duk__valsz = (duk_size_t) (valsz); \
2762 		DUK_BW_ENSURE((thr), (bw_ctx), duk__valsz); \
2763 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
2764 		(bw_ctx)->p += duk__valsz; \
2765 	} while (0)
2766 #define DUK_BW_WRITE_ENSURE_CSTRING(thr,bw_ctx,val) do { \
2767 		const duk_uint8_t *duk__val; \
2768 		duk_size_t duk__val_len; \
2769 		duk__val = (const duk_uint8_t *) (val); \
2770 		duk__val_len = DUK_STRLEN((const char *) duk__val); \
2771 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2772 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
2773 		(bw_ctx)->p += duk__val_len; \
2774 	} while (0)
2775 #define DUK_BW_WRITE_ENSURE_HSTRING(thr,bw_ctx,val) do { \
2776 		duk_size_t duk__val_len; \
2777 		duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
2778 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2779 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
2780 		(bw_ctx)->p += duk__val_len; \
2781 	} while (0)
2782 #define DUK_BW_WRITE_ENSURE_HBUFFER(thr,bw_ctx,val) do { \
2783 		duk_size_t duk__val_len; \
2784 		duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
2785 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2786 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2787 		(bw_ctx)->p += duk__val_len; \
2788 	} while (0)
2789 #define DUK_BW_WRITE_ENSURE_HBUFFER_FIXED(thr,bw_ctx,val) do { \
2790 		duk_size_t duk__val_len; \
2791 		duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
2792 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2793 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2794 		(bw_ctx)->p += duk__val_len; \
2795 	} while (0)
2796 #define DUK_BW_WRITE_ENSURE_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
2797 		duk_size_t duk__val_len; \
2798 		duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
2799 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2800 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2801 		(bw_ctx)->p += duk__val_len; \
2802 	} while (0)
2803 
2804 #define DUK_BW_WRITE_ENSURE_SLICE(thr,bw,dst_off,dst_len) \
2805 	duk_bw_write_ensure_slice((thr), (bw), (dst_off), (dst_len))
2806 #define DUK_BW_INSERT_ENSURE_BYTES(thr,bw,dst_off,buf,len) \
2807 	duk_bw_insert_ensure_bytes((thr), (bw), (dst_off), (buf), (len))
2808 #define DUK_BW_INSERT_ENSURE_SLICE(thr,bw,dst_off,src_off,len) \
2809 	duk_bw_insert_ensure_slice((thr), (bw), (dst_off), (src_off), (len))
2810 #define DUK_BW_INSERT_ENSURE_AREA(thr,bw,off,len) \
2811 	/* Evaluates to (duk_uint8_t *) pointing to start of area. */ \
2812 	duk_bw_insert_ensure_area((thr), (bw), (off), (len))
2813 #define DUK_BW_REMOVE_ENSURE_SLICE(thr,bw,off,len) \
2814 	/* No difference between raw/ensure because the buffer shrinks. */ \
2815 	DUK_BW_REMOVE_RAW_SLICE((thr), (bw), (off), (len))
2816 
2817 /*
2818  *  Externs and prototypes
2819  */
2820 
2821 #if !defined(DUK_SINGLE_FILE)
2822 DUK_INTERNAL_DECL const duk_uint8_t duk_lc_digits[36];
2823 DUK_INTERNAL_DECL const duk_uint8_t duk_uc_nybbles[16];
2824 DUK_INTERNAL_DECL const duk_int8_t duk_hex_dectab[256];
2825 #if defined(DUK_USE_HEX_FASTPATH)
2826 DUK_INTERNAL_DECL const duk_int16_t duk_hex_dectab_shift4[256];
2827 DUK_INTERNAL_DECL const duk_uint16_t duk_hex_enctab[256];
2828 #endif
2829 #endif  /* !DUK_SINGLE_FILE */
2830 
2831 /* Note: assumes that duk_util_probe_steps size is 32 */
2832 #if defined(DUK_USE_HOBJECT_HASH_PART)
2833 #if !defined(DUK_SINGLE_FILE)
2834 DUK_INTERNAL_DECL duk_uint8_t duk_util_probe_steps[32];
2835 #endif  /* !DUK_SINGLE_FILE */
2836 #endif
2837 
2838 #if defined(DUK_USE_STRHASH_DENSE)
2839 DUK_INTERNAL_DECL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed);
2840 #endif
2841 
2842 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits);
2843 DUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx);
2844 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value);
2845 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);
2846 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx);
2847 DUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx *bd, duk_uint8_t *out);
2848 
2849 DUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits);
2850 DUK_INTERNAL_DECL void duk_be_finish(duk_bitencoder_ctx *ctx);
2851 
2852 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
2853 DUK_INTERNAL_DECL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr);
2854 DUK_INTERNAL_DECL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr);
2855 #endif
2856 
2857 DUK_INTERNAL_DECL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf);
2858 DUK_INTERNAL_DECL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size);
2859 DUK_INTERNAL_DECL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz);
2860 DUK_INTERNAL_DECL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx);
2861 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);
2862 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);
2863 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);
2864 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);
2865 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);
2866 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);
2867 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);
2868 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);
2869 DUK_INTERNAL_DECL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);
2870 /* No duk_bw_remove_ensure_slice(), functionality would be identical. */
2871 
2872 DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(const duk_uint8_t *p);
2873 DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(const duk_uint8_t *p);
2874 DUK_INTERNAL_DECL duk_float_t duk_raw_read_float_be(const duk_uint8_t *p);
2875 DUK_INTERNAL_DECL duk_double_t duk_raw_read_double_be(const duk_uint8_t *p);
2876 DUK_INTERNAL_DECL duk_uint16_t duk_raw_readinc_u16_be(const duk_uint8_t **p);
2877 DUK_INTERNAL_DECL duk_uint32_t duk_raw_readinc_u32_be(const duk_uint8_t **p);
2878 DUK_INTERNAL_DECL duk_float_t duk_raw_readinc_float_be(const duk_uint8_t **p);
2879 DUK_INTERNAL_DECL duk_double_t duk_raw_readinc_double_be(const duk_uint8_t **p);
2880 DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t *p, duk_uint16_t val);
2881 DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t *p, duk_uint32_t val);
2882 DUK_INTERNAL_DECL void duk_raw_write_float_be(duk_uint8_t *p, duk_float_t val);
2883 DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t *p, duk_double_t val);
2884 DUK_INTERNAL_DECL duk_small_int_t duk_raw_write_xutf8(duk_uint8_t *p, duk_ucodepoint_t val);
2885 DUK_INTERNAL_DECL duk_small_int_t duk_raw_write_cesu8(duk_uint8_t *p, duk_ucodepoint_t val);
2886 DUK_INTERNAL_DECL void duk_raw_writeinc_u16_be(duk_uint8_t **p, duk_uint16_t val);
2887 DUK_INTERNAL_DECL void duk_raw_writeinc_u32_be(duk_uint8_t **p, duk_uint32_t val);
2888 DUK_INTERNAL_DECL void duk_raw_writeinc_float_be(duk_uint8_t **p, duk_float_t val);
2889 DUK_INTERNAL_DECL void duk_raw_writeinc_double_be(duk_uint8_t **p, duk_double_t val);
2890 DUK_INTERNAL_DECL void duk_raw_writeinc_xutf8(duk_uint8_t **p, duk_ucodepoint_t val);
2891 DUK_INTERNAL_DECL void duk_raw_writeinc_cesu8(duk_uint8_t **p, duk_ucodepoint_t val);
2892 
2893 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* For now only needed by the debugger. */
2894 DUK_INTERNAL_DECL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len);
2895 #endif
2896 
2897 /* memcpy(), memmove() etc wrappers.  The plain variants like duk_memcpy()
2898  * assume C99+ and 'src' and 'dst' pointers must be non-NULL even when the
2899  * operation size is zero.  The unsafe variants like duk_memcpy_safe() deal
2900  * with the zero size case explicitly, and allow NULL pointers in that case
2901  * (which is undefined behavior in C99+).  For the majority of actual targets
2902  * a NULL pointer with a zero length is fine in practice.  These wrappers are
2903  * macros to force inlining; because there are hundreds of call sites, even a
2904  * few extra bytes per call site adds up to ~1kB footprint.
2905  */
2906 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
2907 #define duk_memcpy(dst,src,len)  do { \
2908 		void *duk__dst = (dst); \
2909 		const void *duk__src = (src); \
2910 		duk_size_t duk__len = (len); \
2911 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2912 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2913 		(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
2914 	} while (0)
2915 #define duk_memcpy_unsafe(dst,src,len)  duk_memcpy((dst), (src), (len))
2916 #define duk_memmove(dst,src,len)  do { \
2917 		void *duk__dst = (dst); \
2918 		const void *duk__src = (src); \
2919 		duk_size_t duk__len = (len); \
2920 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2921 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2922 		(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
2923 	} while (0)
2924 #define duk_memmove_unsafe(dst,src,len)  duk_memmove((dst), (src), (len))
2925 #define duk_memset(dst,val,len)  do { \
2926 		void *duk__dst = (dst); \
2927 		duk_small_int_t duk__val = (val); \
2928 		duk_size_t duk__len = (len); \
2929 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2930 		(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
2931 	} while (0)
2932 #define duk_memset_unsafe(dst,val,len)  duk_memset((dst), (val), (len))
2933 #define duk_memzero(dst,len)  do { \
2934 		void *duk__dst = (dst); \
2935 		duk_size_t duk__len = (len); \
2936 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2937 		(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
2938 	} while (0)
2939 #define duk_memzero_unsafe(dst,len)  duk_memzero((dst), (len))
2940 #else  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
2941 #define duk_memcpy(dst,src,len)  do { \
2942 		void *duk__dst = (dst); \
2943 		const void *duk__src = (src); \
2944 		duk_size_t duk__len = (len); \
2945 		DUK_ASSERT(duk__dst != NULL); \
2946 		DUK_ASSERT(duk__src != NULL); \
2947 		(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
2948 	} while (0)
2949 #define duk_memcpy_unsafe(dst,src,len)  do { \
2950 		void *duk__dst = (dst); \
2951 		const void *duk__src = (src); \
2952 		duk_size_t duk__len = (len); \
2953 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2954 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2955 		if (DUK_LIKELY(duk__len > 0U)) { \
2956 			DUK_ASSERT(duk__dst != NULL); \
2957 			DUK_ASSERT(duk__src != NULL); \
2958 			(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
2959 		} \
2960 	} while (0)
2961 #define duk_memmove(dst,src,len)  do { \
2962 		void *duk__dst = (dst); \
2963 		const void *duk__src = (src); \
2964 		duk_size_t duk__len = (len); \
2965 		DUK_ASSERT(duk__dst != NULL); \
2966 		DUK_ASSERT(duk__src != NULL); \
2967 		(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
2968 	} while (0)
2969 #define duk_memmove_unsafe(dst,src,len)  do { \
2970 		void *duk__dst = (dst); \
2971 		const void *duk__src = (src); \
2972 		duk_size_t duk__len = (len); \
2973 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2974 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2975 		if (DUK_LIKELY(duk__len > 0U)) { \
2976 			DUK_ASSERT(duk__dst != NULL); \
2977 			DUK_ASSERT(duk__src != NULL); \
2978 			(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
2979 		} \
2980 	} while (0)
2981 #define duk_memset(dst,val,len)  do { \
2982 		void *duk__dst = (dst); \
2983 		duk_small_int_t duk__val = (val); \
2984 		duk_size_t duk__len = (len); \
2985 		DUK_ASSERT(duk__dst != NULL); \
2986 		(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
2987 	} while (0)
2988 #define duk_memset_unsafe(dst,val,len)  do { \
2989 		void *duk__dst = (dst); \
2990 		duk_small_int_t duk__val = (val); \
2991 		duk_size_t duk__len = (len); \
2992 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2993 		if (DUK_LIKELY(duk__len > 0U)) { \
2994 			DUK_ASSERT(duk__dst != NULL); \
2995 			(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
2996 		} \
2997 	} while (0)
2998 #define duk_memzero(dst,len)  do { \
2999 		void *duk__dst = (dst); \
3000 		duk_size_t duk__len = (len); \
3001 		DUK_ASSERT(duk__dst != NULL); \
3002 		(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
3003 	} while (0)
3004 #define duk_memzero_unsafe(dst,len)  do { \
3005 		void *duk__dst = (dst); \
3006 		duk_size_t duk__len = (len); \
3007 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
3008 		if (DUK_LIKELY(duk__len > 0U)) { \
3009 			DUK_ASSERT(duk__dst != NULL); \
3010 			(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
3011 		} \
3012 	} while (0)
3013 #endif  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
3014 
3015 DUK_INTERNAL_DECL duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len);
3016 DUK_INTERNAL_DECL duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len);
3017 
3018 DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival);
3019 DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival);
3020 DUK_INTERNAL_DECL duk_bool_t duk_double_is_anyinf(duk_double_t x);
3021 DUK_INTERNAL_DECL duk_bool_t duk_double_is_posinf(duk_double_t x);
3022 DUK_INTERNAL_DECL duk_bool_t duk_double_is_neginf(duk_double_t x);
3023 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan(duk_double_t x);
3024 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x);
3025 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x);
3026 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x);
3027 DUK_INTERNAL_DECL duk_small_uint_t duk_double_signbit(duk_double_t x);
3028 DUK_INTERNAL_DECL duk_double_t duk_double_trunc_towards_zero(duk_double_t x);
3029 DUK_INTERNAL_DECL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y);
3030 DUK_INTERNAL_DECL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y);
3031 DUK_INTERNAL_DECL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y);
3032 DUK_INTERNAL_DECL duk_bool_t duk_double_is_finite(duk_double_t x);
3033 DUK_INTERNAL_DECL duk_bool_t duk_double_is_integer(duk_double_t x);
3034 DUK_INTERNAL_DECL duk_bool_t duk_double_is_safe_integer(duk_double_t x);
3035 
3036 DUK_INTERNAL_DECL duk_double_t duk_double_div(duk_double_t x, duk_double_t y);
3037 DUK_INTERNAL_DECL duk_int_t duk_double_to_int_t(duk_double_t x);
3038 DUK_INTERNAL_DECL duk_uint_t duk_double_to_uint_t(duk_double_t x);
3039 DUK_INTERNAL_DECL duk_int32_t duk_double_to_int32_t(duk_double_t x);
3040 DUK_INTERNAL_DECL duk_uint32_t duk_double_to_uint32_t(duk_double_t x);
3041 DUK_INTERNAL_DECL duk_float_t duk_double_to_float_t(duk_double_t x);
3042 DUK_INTERNAL_DECL duk_bool_t duk_double_equals(duk_double_t x, duk_double_t y);
3043 DUK_INTERNAL_DECL duk_bool_t duk_float_equals(duk_float_t x, duk_float_t y);
3044 
3045 /*
3046  *  Miscellaneous
3047  */
3048 
3049 /* Example: x     = 0x10 = 0b00010000
3050  *          x - 1 = 0x0f = 0b00001111
3051  *          x & (x - 1) == 0
3052  *
3053  *          x     = 0x07 = 0b00000111
3054  *          x - 1 = 0x06 = 0b00000110
3055  *          x & (x - 1) != 0
3056  *
3057  * However, incorrectly true for x == 0 so check for that explicitly.
3058  */
3059 #define DUK_IS_POWER_OF_TWO(x) \
3060 	((x) != 0U && ((x) & ((x) - 1U)) == 0U)
3061 
3062 #endif  /* DUK_UTIL_H_INCLUDED */
3063 /* #include duk_strings.h */
3064 #line 1 "duk_strings.h"
3065 /*
3066  *  Shared string macros.
3067  *
3068  *  Using shared macros helps minimize strings data size because it's easy
3069  *  to check if an existing string could be used.  String constants don't
3070  *  need to be all defined here; defining a string here makes sense if there's
3071  *  a high chance the string could be reused.  Also, using macros allows
3072  *  a call site express the exact string needed, but the macro may map to an
3073  *  approximate string to reduce unique string count.  Macros can also be
3074  *  more easily tuned for low memory targets than #if defined()s throughout
3075  *  the code base.
3076  *
3077  *  Because format strings behave differently in the call site (they need to
3078  *  be followed by format arguments), they use a special prefix DUK_STR_FMT_.
3079  *
3080  *  On some compilers using explicit shared strings is preferable; on others
3081  *  it may be better to use straight literals because the compiler will combine
3082  *  them anyway, and such strings won't end up unnecessarily in a symbol table.
3083  */
3084 
3085 #if !defined(DUK_ERRMSG_H_INCLUDED)
3086 #define DUK_ERRMSG_H_INCLUDED
3087 
3088 /* Mostly API and built-in method related */
3089 #define DUK_STR_INTERNAL_ERROR                   "internal error"
3090 #define DUK_STR_UNSUPPORTED                      "unsupported"
3091 #define DUK_STR_INVALID_COUNT                    "invalid count"
3092 #define DUK_STR_INVALID_ARGS                     "invalid args"
3093 #define DUK_STR_INVALID_STATE                    "invalid state"
3094 #define DUK_STR_INVALID_INPUT                    "invalid input"
3095 #define DUK_STR_INVALID_LENGTH                   "invalid length"
3096 #define DUK_STR_NOT_CONSTRUCTABLE                "not constructable"
3097 #define DUK_STR_CONSTRUCT_ONLY                   "constructor requires 'new'"
3098 #define DUK_STR_NOT_CALLABLE                     "not callable"
3099 #define DUK_STR_NOT_EXTENSIBLE                   "not extensible"
3100 #define DUK_STR_NOT_WRITABLE                     "not writable"
3101 #define DUK_STR_NOT_CONFIGURABLE                 "not configurable"
3102 #define DUK_STR_INVALID_CONTEXT                  "invalid context"
3103 #define DUK_STR_INVALID_INDEX                    "invalid args"
3104 #define DUK_STR_PUSH_BEYOND_ALLOC_STACK          "cannot push beyond allocated stack"
3105 #define DUK_STR_NOT_UNDEFINED                    "unexpected type"
3106 #define DUK_STR_NOT_NULL                         "unexpected type"
3107 #define DUK_STR_NOT_BOOLEAN                      "unexpected type"
3108 #define DUK_STR_NOT_NUMBER                       "unexpected type"
3109 #define DUK_STR_NOT_STRING                       "unexpected type"
3110 #define DUK_STR_NOT_OBJECT                       "unexpected type"
3111 #define DUK_STR_NOT_POINTER                      "unexpected type"
3112 #define DUK_STR_NOT_BUFFER                       "not buffer"  /* still in use with verbose messages */
3113 #define DUK_STR_UNEXPECTED_TYPE                  "unexpected type"
3114 #define DUK_STR_NOT_THREAD                       "unexpected type"
3115 #define DUK_STR_NOT_COMPFUNC                     "unexpected type"
3116 #define DUK_STR_NOT_NATFUNC                      "unexpected type"
3117 #define DUK_STR_NOT_C_FUNCTION                   "unexpected type"
3118 #define DUK_STR_NOT_FUNCTION                     "unexpected type"
3119 #define DUK_STR_NOT_REGEXP                       "unexpected type"
3120 #define DUK_STR_TOPRIMITIVE_FAILED               "coercion to primitive failed"
3121 #define DUK_STR_NUMBER_OUTSIDE_RANGE             "number outside range"
3122 #define DUK_STR_NOT_OBJECT_COERCIBLE             "not object coercible"
3123 #define DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL      "cannot number coerce Symbol"
3124 #define DUK_STR_CANNOT_STRING_COERCE_SYMBOL      "cannot string coerce Symbol"
3125 #define DUK_STR_STRING_TOO_LONG                  "string too long"
3126 #define DUK_STR_BUFFER_TOO_LONG                  "buffer too long"
3127 #define DUK_STR_ALLOC_FAILED                     "alloc failed"
3128 #define DUK_STR_WRONG_BUFFER_TYPE                "wrong buffer type"
3129 #define DUK_STR_BASE64_ENCODE_FAILED             "base64 encode failed"
3130 #define DUK_STR_SOURCE_DECODE_FAILED             "source decode failed"
3131 #define DUK_STR_UTF8_DECODE_FAILED               "utf-8 decode failed"
3132 #define DUK_STR_BASE64_DECODE_FAILED             "base64 decode failed"
3133 #define DUK_STR_HEX_DECODE_FAILED                "hex decode failed"
3134 #define DUK_STR_INVALID_BYTECODE                 "invalid bytecode"
3135 #define DUK_STR_NO_SOURCECODE                    "no sourcecode"
3136 #define DUK_STR_RESULT_TOO_LONG                  "result too long"
3137 #define DUK_STR_INVALID_CFUNC_RC                 "invalid C function rc"
3138 #define DUK_STR_INVALID_INSTANCEOF_RVAL          "invalid instanceof rval"
3139 #define DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO  "instanceof rval has no .prototype"
3140 
3141 /* JSON */
3142 #define DUK_STR_FMT_PTR                          "%p"
3143 #define DUK_STR_FMT_INVALID_JSON                 "invalid json (at offset %ld)"
3144 #define DUK_STR_CYCLIC_INPUT                     "cyclic input"
3145 
3146 /* Generic codec */
3147 #define DUK_STR_DEC_RECLIMIT                     "decode recursion limit"
3148 #define DUK_STR_ENC_RECLIMIT                     "encode recursion limit"
3149 
3150 /* Object property access */
3151 #define DUK_STR_INVALID_BASE                     "invalid base value"
3152 #define DUK_STR_STRICT_CALLER_READ               "cannot read strict 'caller'"
3153 #define DUK_STR_PROXY_REJECTED                   "proxy rejected"
3154 #define DUK_STR_INVALID_ARRAY_LENGTH             "invalid array length"
3155 #define DUK_STR_SETTER_UNDEFINED                 "setter undefined"
3156 #define DUK_STR_INVALID_DESCRIPTOR               "invalid descriptor"
3157 
3158 /* Proxy */
3159 #define DUK_STR_PROXY_REVOKED                    "proxy revoked"
3160 #define DUK_STR_INVALID_TRAP_RESULT              "invalid trap result"
3161 
3162 /* Variables */
3163 
3164 /* Lexer */
3165 #define DUK_STR_INVALID_ESCAPE                   "invalid escape"
3166 #define DUK_STR_UNTERMINATED_STRING              "unterminated string"
3167 #define DUK_STR_UNTERMINATED_COMMENT             "unterminated comment"
3168 #define DUK_STR_UNTERMINATED_REGEXP              "unterminated regexp"
3169 #define DUK_STR_TOKEN_LIMIT                      "token limit"
3170 #define DUK_STR_REGEXP_SUPPORT_DISABLED          "regexp support disabled"
3171 #define DUK_STR_INVALID_NUMBER_LITERAL           "invalid number literal"
3172 #define DUK_STR_INVALID_TOKEN                    "invalid token"
3173 
3174 /* Compiler */
3175 #define DUK_STR_PARSE_ERROR                      "parse error"
3176 #define DUK_STR_DUPLICATE_LABEL                  "duplicate label"
3177 #define DUK_STR_INVALID_LABEL                    "invalid label"
3178 #define DUK_STR_INVALID_ARRAY_LITERAL            "invalid array literal"
3179 #define DUK_STR_INVALID_OBJECT_LITERAL           "invalid object literal"
3180 #define DUK_STR_INVALID_VAR_DECLARATION          "invalid variable declaration"
3181 #define DUK_STR_CANNOT_DELETE_IDENTIFIER         "cannot delete identifier"
3182 #define DUK_STR_INVALID_EXPRESSION               "invalid expression"
3183 #define DUK_STR_INVALID_LVALUE                   "invalid lvalue"
3184 #define DUK_STR_INVALID_NEWTARGET                "invalid new.target"
3185 #define DUK_STR_EXPECTED_IDENTIFIER              "expected identifier"
3186 #define DUK_STR_EMPTY_EXPR_NOT_ALLOWED           "empty expression not allowed"
3187 #define DUK_STR_INVALID_FOR                      "invalid for statement"
3188 #define DUK_STR_INVALID_SWITCH                   "invalid switch statement"
3189 #define DUK_STR_INVALID_BREAK_CONT_LABEL         "invalid break/continue label"
3190 #define DUK_STR_INVALID_RETURN                   "invalid return"
3191 #define DUK_STR_INVALID_TRY                      "invalid try"
3192 #define DUK_STR_INVALID_THROW                    "invalid throw"
3193 #define DUK_STR_WITH_IN_STRICT_MODE              "with in strict mode"
3194 #define DUK_STR_FUNC_STMT_NOT_ALLOWED            "function statement not allowed"
3195 #define DUK_STR_UNTERMINATED_STMT                "unterminated statement"
3196 #define DUK_STR_INVALID_ARG_NAME                 "invalid argument name"
3197 #define DUK_STR_INVALID_FUNC_NAME                "invalid function name"
3198 #define DUK_STR_INVALID_GETSET_NAME              "invalid getter/setter name"
3199 #define DUK_STR_FUNC_NAME_REQUIRED               "function name required"
3200 
3201 /* RegExp */
3202 #define DUK_STR_INVALID_QUANTIFIER               "invalid regexp quantifier"
3203 #define DUK_STR_INVALID_QUANTIFIER_NO_ATOM       "quantifier without preceding atom"
3204 #define DUK_STR_INVALID_QUANTIFIER_VALUES        "quantifier values invalid (qmin > qmax)"
3205 #define DUK_STR_QUANTIFIER_TOO_MANY_COPIES       "quantifier requires too many atom copies"
3206 #define DUK_STR_UNEXPECTED_CLOSING_PAREN         "unexpected closing parenthesis"
3207 #define DUK_STR_UNEXPECTED_END_OF_PATTERN        "unexpected end of pattern"
3208 #define DUK_STR_UNEXPECTED_REGEXP_TOKEN          "unexpected token in regexp"
3209 #define DUK_STR_INVALID_REGEXP_FLAGS             "invalid regexp flags"
3210 #define DUK_STR_INVALID_REGEXP_ESCAPE            "invalid regexp escape"
3211 #define DUK_STR_INVALID_BACKREFS                 "invalid backreference(s)"
3212 #define DUK_STR_INVALID_REGEXP_CHARACTER         "invalid regexp character"
3213 #define DUK_STR_INVALID_REGEXP_GROUP             "invalid regexp group"
3214 #define DUK_STR_UNTERMINATED_CHARCLASS           "unterminated character class"
3215 #define DUK_STR_INVALID_RANGE                    "invalid range"
3216 
3217 /* Limits */
3218 #define DUK_STR_VALSTACK_LIMIT                   "valstack limit"
3219 #define DUK_STR_CALLSTACK_LIMIT                  "callstack limit"
3220 #define DUK_STR_PROTOTYPE_CHAIN_LIMIT            "prototype chain limit"
3221 #define DUK_STR_BOUND_CHAIN_LIMIT                "function call bound chain limit"
3222 #define DUK_STR_NATIVE_STACK_LIMIT               "C stack depth limit"
3223 #define DUK_STR_COMPILER_RECURSION_LIMIT         "compiler recursion limit"
3224 #define DUK_STR_BYTECODE_LIMIT                   "bytecode limit"
3225 #define DUK_STR_REG_LIMIT                        "register limit"
3226 #define DUK_STR_TEMP_LIMIT                       "temp limit"
3227 #define DUK_STR_CONST_LIMIT                      "const limit"
3228 #define DUK_STR_FUNC_LIMIT                       "function limit"
3229 #define DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT  "regexp compiler recursion limit"
3230 #define DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT  "regexp executor recursion limit"
3231 #define DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT       "regexp step limit"
3232 
3233 #endif  /* DUK_ERRMSG_H_INCLUDED */
3234 /* #include duk_js_bytecode.h */
3235 #line 1 "duk_js_bytecode.h"
3236 /*
3237  *  ECMAScript bytecode
3238  */
3239 
3240 #if !defined(DUK_JS_BYTECODE_H_INCLUDED)
3241 #define DUK_JS_BYTECODE_H_INCLUDED
3242 
3243 /*
3244  *  Bytecode instruction layout
3245  *  ===========================
3246  *
3247  *  Instructions are unsigned 32-bit integers divided as follows:
3248  *
3249  *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
3250  *  !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!
3251  *  +-----------------------------------------------+---------------+
3252  *  !       C       !       B       !       A       !       OP      !
3253  *  +-----------------------------------------------+---------------+
3254  *
3255  *  OP (8 bits):  opcode (DUK_OP_*), access should be fastest
3256  *                consecutive opcodes allocated when opcode needs flags
3257  *   A (8 bits):  typically a target register number
3258  *   B (8 bits):  typically first source register/constant number
3259  *   C (8 bits):  typically second source register/constant number
3260  *
3261  *  Some instructions combine BC or ABC together for larger parameter values.
3262  *  Signed integers (e.g. jump offsets) are encoded as unsigned, with an
3263  *  opcode specific bias.
3264  *
3265  *  Some opcodes have flags which are handled by allocating consecutive
3266  *  opcodes to make space for 1-N flags.  Flags can also be e.g. in the 'A'
3267  *  field when there's room for the specific opcode.
3268  *
3269  *  For example, if three flags were needed, they could be allocated from
3270  *  the opcode field as follows:
3271  *
3272  *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
3273  *  !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!
3274  *  +-----------------------------------------------+---------------+
3275  *  !       C       !       B       !       A       !    OP   !Z!Y!X!
3276  *  +-----------------------------------------------+---------------+
3277  *
3278  *  Some opcodes accept a reg/const argument which is handled by allocating
3279  *  flags in the OP field, see DUK_BC_ISREG() and DUK_BC_ISCONST().  The
3280  *  following convention is shared by most opcodes, so that the compiler
3281  *  can handle reg/const flagging without opcode specific code paths:
3282  *
3283  *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
3284  *  !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!
3285  *  +-----------------------------------------------+---------------+
3286  *  !       C       !       B       !       A       !     OP    !Y!X!
3287  *  +-----------------------------------------------+---------------+
3288  *
3289  *    X  1=B is const, 0=B is reg
3290  *    Y  1=C is const, 0=C is reg
3291  *
3292  *    In effect OP, OP + 1, OP + 2, and OP + 3 are allocated from the
3293  *    8-bit opcode space for a single logical opcode.  The base opcode
3294  *    number should be divisible by 4.  If the opcode is called 'FOO'
3295  *    the following opcode constants would be defined:
3296  *
3297  *      DUK_OP_FOO     100       // base opcode number
3298  *      DUK_OP_FOO_RR  100       // FOO, B=reg, C=reg
3299  *      DUK_OP_FOO_CR  101       // FOO, B=const, C=reg
3300  *      DUK_OP_FOO_RC  102       // FOO, B=reg, C=const
3301  *      DUK_OP_FOO_CC  103       // FOO, B=const, C=const
3302  *
3303  *  If only B or C is a reg/const, the unused opcode combinations can be
3304  *  used for other opcodes (which take no reg/const argument).  However,
3305  *  such opcode values are initially reserved, at least while opcode space
3306  *  is available.  For example, if 'BAR' uses B for a register field and
3307  *  C is a reg/const:
3308  *
3309  *      DUK_OP_BAR            116    // base opcode number
3310  *      DUK_OP_BAR_RR         116    // BAR, B=reg, C=reg
3311  *      DUK_OP_BAR_CR_UNUSED  117    // unused, could be repurposed
3312  *      DUK_OP_BAR_RC         118    // BAR, B=reg, C=const
3313  *      DUK_OP_BAR_CC_UNUSED  119    // unused, could be repurposed
3314  *
3315  *  Macro naming is a bit misleading, e.g. "ABC" in macro name but the
3316  *  field layout is concretely "CBA" in the register.
3317  */
3318 
3319 typedef duk_uint32_t duk_instr_t;
3320 
3321 #define DUK_BC_SHIFT_OP             0
3322 #define DUK_BC_SHIFT_A              8
3323 #define DUK_BC_SHIFT_B              16
3324 #define DUK_BC_SHIFT_C              24
3325 #define DUK_BC_SHIFT_BC             DUK_BC_SHIFT_B
3326 #define DUK_BC_SHIFT_ABC            DUK_BC_SHIFT_A
3327 
3328 #define DUK_BC_UNSHIFTED_MASK_OP    0xffUL
3329 #define DUK_BC_UNSHIFTED_MASK_A     0xffUL
3330 #define DUK_BC_UNSHIFTED_MASK_B     0xffUL
3331 #define DUK_BC_UNSHIFTED_MASK_C     0xffUL
3332 #define DUK_BC_UNSHIFTED_MASK_BC    0xffffUL
3333 #define DUK_BC_UNSHIFTED_MASK_ABC   0xffffffUL
3334 
3335 #define DUK_BC_SHIFTED_MASK_OP      (DUK_BC_UNSHIFTED_MASK_OP << DUK_BC_SHIFT_OP)
3336 #define DUK_BC_SHIFTED_MASK_A       (DUK_BC_UNSHIFTED_MASK_A << DUK_BC_SHIFT_A)
3337 #define DUK_BC_SHIFTED_MASK_B       (DUK_BC_UNSHIFTED_MASK_B << DUK_BC_SHIFT_B)
3338 #define DUK_BC_SHIFTED_MASK_C       (DUK_BC_UNSHIFTED_MASK_C << DUK_BC_SHIFT_C)
3339 #define DUK_BC_SHIFTED_MASK_BC      (DUK_BC_UNSHIFTED_MASK_BC << DUK_BC_SHIFT_BC)
3340 #define DUK_BC_SHIFTED_MASK_ABC     (DUK_BC_UNSHIFTED_MASK_ABC << DUK_BC_SHIFT_ABC)
3341 
3342 #define DUK_DEC_OP(x)               ((x) & 0xffUL)
3343 #define DUK_DEC_A(x)                (((x) >> 8) & 0xffUL)
3344 #define DUK_DEC_B(x)                (((x) >> 16) & 0xffUL)
3345 #define DUK_DEC_C(x)                (((x) >> 24) & 0xffUL)
3346 #define DUK_DEC_BC(x)               (((x) >> 16) & 0xffffUL)
3347 #define DUK_DEC_ABC(x)              (((x) >> 8) & 0xffffffUL)
3348 
3349 #define DUK_ENC_OP(op)              ((duk_instr_t) (op))
3350 #define DUK_ENC_OP_ABC(op,abc)      ((duk_instr_t) ( \
3351                                         (((duk_instr_t) (abc)) << 8) | \
3352                                         ((duk_instr_t) (op)) \
3353                                     ))
3354 #define DUK_ENC_OP_A_BC(op,a,bc)    ((duk_instr_t) ( \
3355                                         (((duk_instr_t) (bc)) << 16) | \
3356                                         (((duk_instr_t) (a)) << 8) | \
3357                                         ((duk_instr_t) (op)) \
3358                                     ))
3359 #define DUK_ENC_OP_A_B_C(op,a,b,c)  ((duk_instr_t) ( \
3360                                         (((duk_instr_t) (c)) << 24) | \
3361                                         (((duk_instr_t) (b)) << 16) | \
3362                                         (((duk_instr_t) (a)) << 8) | \
3363                                         ((duk_instr_t) (op)) \
3364                                     ))
3365 #define DUK_ENC_OP_A_B(op,a,b)      DUK_ENC_OP_A_B_C((op),(a),(b),0)
3366 #define DUK_ENC_OP_A(op,a)          DUK_ENC_OP_A_B_C((op),(a),0,0)
3367 #define DUK_ENC_OP_BC(op,bc)        DUK_ENC_OP_A_BC((op),0,(bc))
3368 
3369 /* Get opcode base value with B/C reg/const flags cleared. */
3370 #define DUK_BC_NOREGCONST_OP(op)    ((op) & 0xfc)
3371 
3372 /* Constants should be signed so that signed arithmetic involving them
3373  * won't cause values to be coerced accidentally to unsigned.
3374  */
3375 #define DUK_BC_OP_MIN               0
3376 #define DUK_BC_OP_MAX               0xffL
3377 #define DUK_BC_A_MIN                0
3378 #define DUK_BC_A_MAX                0xffL
3379 #define DUK_BC_B_MIN                0
3380 #define DUK_BC_B_MAX                0xffL
3381 #define DUK_BC_C_MIN                0
3382 #define DUK_BC_C_MAX                0xffL
3383 #define DUK_BC_BC_MIN               0
3384 #define DUK_BC_BC_MAX               0xffffL
3385 #define DUK_BC_ABC_MIN              0
3386 #define DUK_BC_ABC_MAX              0xffffffL
3387 
3388 /* Masks for B/C reg/const indicator in opcode field. */
3389 #define DUK_BC_REGCONST_B           (0x01UL)
3390 #define DUK_BC_REGCONST_C           (0x02UL)
3391 
3392 /* Misc. masks for opcode field. */
3393 #define DUK_BC_INCDECP_FLAG_DEC     (0x04UL)
3394 #define DUK_BC_INCDECP_FLAG_POST    (0x08UL)
3395 
3396 /* Opcodes. */
3397 #define DUK_OP_LDREG                0
3398 #define DUK_OP_STREG                1
3399 #define DUK_OP_JUMP                 2
3400 #define DUK_OP_LDCONST              3
3401 #define DUK_OP_LDINT                4
3402 #define DUK_OP_LDINTX               5
3403 #define DUK_OP_LDTHIS               6
3404 #define DUK_OP_LDUNDEF              7
3405 #define DUK_OP_LDNULL               8
3406 #define DUK_OP_LDTRUE               9
3407 #define DUK_OP_LDFALSE              10
3408 #define DUK_OP_GETVAR               11
3409 #define DUK_OP_BNOT                 12
3410 #define DUK_OP_LNOT                 13
3411 #define DUK_OP_UNM                  14
3412 #define DUK_OP_UNP                  15
3413 #define DUK_OP_EQ                   16
3414 #define DUK_OP_EQ_RR                16
3415 #define DUK_OP_EQ_CR                17
3416 #define DUK_OP_EQ_RC                18
3417 #define DUK_OP_EQ_CC                19
3418 #define DUK_OP_NEQ                  20
3419 #define DUK_OP_NEQ_RR               20
3420 #define DUK_OP_NEQ_CR               21
3421 #define DUK_OP_NEQ_RC               22
3422 #define DUK_OP_NEQ_CC               23
3423 #define DUK_OP_SEQ                  24
3424 #define DUK_OP_SEQ_RR               24
3425 #define DUK_OP_SEQ_CR               25
3426 #define DUK_OP_SEQ_RC               26
3427 #define DUK_OP_SEQ_CC               27
3428 #define DUK_OP_SNEQ                 28
3429 #define DUK_OP_SNEQ_RR              28
3430 #define DUK_OP_SNEQ_CR              29
3431 #define DUK_OP_SNEQ_RC              30
3432 #define DUK_OP_SNEQ_CC              31
3433 #define DUK_OP_GT                   32
3434 #define DUK_OP_GT_RR                32
3435 #define DUK_OP_GT_CR                33
3436 #define DUK_OP_GT_RC                34
3437 #define DUK_OP_GT_CC                35
3438 #define DUK_OP_GE                   36
3439 #define DUK_OP_GE_RR                36
3440 #define DUK_OP_GE_CR                37
3441 #define DUK_OP_GE_RC                38
3442 #define DUK_OP_GE_CC                39
3443 #define DUK_OP_LT                   40
3444 #define DUK_OP_LT_RR                40
3445 #define DUK_OP_LT_CR                41
3446 #define DUK_OP_LT_RC                42
3447 #define DUK_OP_LT_CC                43
3448 #define DUK_OP_LE                   44
3449 #define DUK_OP_LE_RR                44
3450 #define DUK_OP_LE_CR                45
3451 #define DUK_OP_LE_RC                46
3452 #define DUK_OP_LE_CC                47
3453 #define DUK_OP_IFTRUE               48
3454 #define DUK_OP_IFTRUE_R             48
3455 #define DUK_OP_IFTRUE_C             49
3456 #define DUK_OP_IFFALSE              50
3457 #define DUK_OP_IFFALSE_R            50
3458 #define DUK_OP_IFFALSE_C            51
3459 #define DUK_OP_ADD                  52
3460 #define DUK_OP_ADD_RR               52
3461 #define DUK_OP_ADD_CR               53
3462 #define DUK_OP_ADD_RC               54
3463 #define DUK_OP_ADD_CC               55
3464 #define DUK_OP_SUB                  56
3465 #define DUK_OP_SUB_RR               56
3466 #define DUK_OP_SUB_CR               57
3467 #define DUK_OP_SUB_RC               58
3468 #define DUK_OP_SUB_CC               59
3469 #define DUK_OP_MUL                  60
3470 #define DUK_OP_MUL_RR               60
3471 #define DUK_OP_MUL_CR               61
3472 #define DUK_OP_MUL_RC               62
3473 #define DUK_OP_MUL_CC               63
3474 #define DUK_OP_DIV                  64
3475 #define DUK_OP_DIV_RR               64
3476 #define DUK_OP_DIV_CR               65
3477 #define DUK_OP_DIV_RC               66
3478 #define DUK_OP_DIV_CC               67
3479 #define DUK_OP_MOD                  68
3480 #define DUK_OP_MOD_RR               68
3481 #define DUK_OP_MOD_CR               69
3482 #define DUK_OP_MOD_RC               70
3483 #define DUK_OP_MOD_CC               71
3484 #define DUK_OP_EXP                  72
3485 #define DUK_OP_EXP_RR               72
3486 #define DUK_OP_EXP_CR               73
3487 #define DUK_OP_EXP_RC               74
3488 #define DUK_OP_EXP_CC               75
3489 #define DUK_OP_BAND                 76
3490 #define DUK_OP_BAND_RR              76
3491 #define DUK_OP_BAND_CR              77
3492 #define DUK_OP_BAND_RC              78
3493 #define DUK_OP_BAND_CC              79
3494 #define DUK_OP_BOR                  80
3495 #define DUK_OP_BOR_RR               80
3496 #define DUK_OP_BOR_CR               81
3497 #define DUK_OP_BOR_RC               82
3498 #define DUK_OP_BOR_CC               83
3499 #define DUK_OP_BXOR                 84
3500 #define DUK_OP_BXOR_RR              84
3501 #define DUK_OP_BXOR_CR              85
3502 #define DUK_OP_BXOR_RC              86
3503 #define DUK_OP_BXOR_CC              87
3504 #define DUK_OP_BASL                 88
3505 #define DUK_OP_BASL_RR              88
3506 #define DUK_OP_BASL_CR              89
3507 #define DUK_OP_BASL_RC              90
3508 #define DUK_OP_BASL_CC              91
3509 #define DUK_OP_BLSR                 92
3510 #define DUK_OP_BLSR_RR              92
3511 #define DUK_OP_BLSR_CR              93
3512 #define DUK_OP_BLSR_RC              94
3513 #define DUK_OP_BLSR_CC              95
3514 #define DUK_OP_BASR                 96
3515 #define DUK_OP_BASR_RR              96
3516 #define DUK_OP_BASR_CR              97
3517 #define DUK_OP_BASR_RC              98
3518 #define DUK_OP_BASR_CC              99
3519 #define DUK_OP_INSTOF               100
3520 #define DUK_OP_INSTOF_RR            100
3521 #define DUK_OP_INSTOF_CR            101
3522 #define DUK_OP_INSTOF_RC            102
3523 #define DUK_OP_INSTOF_CC            103
3524 #define DUK_OP_IN                   104
3525 #define DUK_OP_IN_RR                104
3526 #define DUK_OP_IN_CR                105
3527 #define DUK_OP_IN_RC                106
3528 #define DUK_OP_IN_CC                107
3529 #define DUK_OP_GETPROP              108
3530 #define DUK_OP_GETPROP_RR           108
3531 #define DUK_OP_GETPROP_CR           109
3532 #define DUK_OP_GETPROP_RC           110
3533 #define DUK_OP_GETPROP_CC           111
3534 #define DUK_OP_PUTPROP              112
3535 #define DUK_OP_PUTPROP_RR           112
3536 #define DUK_OP_PUTPROP_CR           113
3537 #define DUK_OP_PUTPROP_RC           114
3538 #define DUK_OP_PUTPROP_CC           115
3539 #define DUK_OP_DELPROP              116
3540 #define DUK_OP_DELPROP_RR           116
3541 #define DUK_OP_DELPROP_CR_UNUSED    117  /* unused now */
3542 #define DUK_OP_DELPROP_RC           118
3543 #define DUK_OP_DELPROP_CC_UNUSED    119  /* unused now */
3544 #define DUK_OP_PREINCR              120  /* pre/post opcode values have constraints, */
3545 #define DUK_OP_PREDECR              121  /* see duk_js_executor.c and duk_js_compiler.c. */
3546 #define DUK_OP_POSTINCR             122
3547 #define DUK_OP_POSTDECR             123
3548 #define DUK_OP_PREINCV              124
3549 #define DUK_OP_PREDECV              125
3550 #define DUK_OP_POSTINCV             126
3551 #define DUK_OP_POSTDECV             127
3552 #define DUK_OP_PREINCP              128  /* pre/post inc/dec prop opcodes have constraints */
3553 #define DUK_OP_PREINCP_RR           128
3554 #define DUK_OP_PREINCP_CR           129
3555 #define DUK_OP_PREINCP_RC           130
3556 #define DUK_OP_PREINCP_CC           131
3557 #define DUK_OP_PREDECP              132
3558 #define DUK_OP_PREDECP_RR           132
3559 #define DUK_OP_PREDECP_CR           133
3560 #define DUK_OP_PREDECP_RC           134
3561 #define DUK_OP_PREDECP_CC           135
3562 #define DUK_OP_POSTINCP             136
3563 #define DUK_OP_POSTINCP_RR          136
3564 #define DUK_OP_POSTINCP_CR          137
3565 #define DUK_OP_POSTINCP_RC          138
3566 #define DUK_OP_POSTINCP_CC          139
3567 #define DUK_OP_POSTDECP             140
3568 #define DUK_OP_POSTDECP_RR          140
3569 #define DUK_OP_POSTDECP_CR          141
3570 #define DUK_OP_POSTDECP_RC          142
3571 #define DUK_OP_POSTDECP_CC          143
3572 #define DUK_OP_DECLVAR              144
3573 #define DUK_OP_DECLVAR_RR           144
3574 #define DUK_OP_DECLVAR_CR           145
3575 #define DUK_OP_DECLVAR_RC           146
3576 #define DUK_OP_DECLVAR_CC           147
3577 #define DUK_OP_REGEXP               148
3578 #define DUK_OP_REGEXP_RR            148
3579 #define DUK_OP_REGEXP_CR            149
3580 #define DUK_OP_REGEXP_RC            150
3581 #define DUK_OP_REGEXP_CC            151
3582 #define DUK_OP_CLOSURE              152
3583 #define DUK_OP_TYPEOF               153
3584 #define DUK_OP_TYPEOFID             154
3585 #define DUK_OP_PUTVAR               155
3586 #define DUK_OP_DELVAR               156
3587 #define DUK_OP_RETREG               157
3588 #define DUK_OP_RETUNDEF             158
3589 #define DUK_OP_RETCONST             159
3590 #define DUK_OP_RETCONSTN            160  /* return const without incref (e.g. number) */
3591 #define DUK_OP_LABEL                161
3592 #define DUK_OP_ENDLABEL             162
3593 #define DUK_OP_BREAK                163
3594 #define DUK_OP_CONTINUE             164
3595 #define DUK_OP_TRYCATCH             165
3596 #define DUK_OP_ENDTRY               166
3597 #define DUK_OP_ENDCATCH             167
3598 #define DUK_OP_ENDFIN               168
3599 #define DUK_OP_THROW                169
3600 #define DUK_OP_INVLHS               170
3601 #define DUK_OP_CSREG                171
3602 #define DUK_OP_CSVAR                172
3603 #define DUK_OP_CSVAR_RR             172
3604 #define DUK_OP_CSVAR_CR             173
3605 #define DUK_OP_CSVAR_RC             174
3606 #define DUK_OP_CSVAR_CC             175
3607 #define DUK_OP_CALL0                176  /* DUK_OP_CALL0 & 0x0F must be zero. */
3608 #define DUK_OP_CALL1                177
3609 #define DUK_OP_CALL2                178
3610 #define DUK_OP_CALL3                179
3611 #define DUK_OP_CALL4                180
3612 #define DUK_OP_CALL5                181
3613 #define DUK_OP_CALL6                182
3614 #define DUK_OP_CALL7                183
3615 #define DUK_OP_CALL8                184
3616 #define DUK_OP_CALL9                185
3617 #define DUK_OP_CALL10               186
3618 #define DUK_OP_CALL11               187
3619 #define DUK_OP_CALL12               188
3620 #define DUK_OP_CALL13               189
3621 #define DUK_OP_CALL14               190
3622 #define DUK_OP_CALL15               191
3623 #define DUK_OP_NEWOBJ               192
3624 #define DUK_OP_NEWARR               193
3625 #define DUK_OP_MPUTOBJ              194
3626 #define DUK_OP_MPUTOBJI             195
3627 #define DUK_OP_INITSET              196
3628 #define DUK_OP_INITGET              197
3629 #define DUK_OP_MPUTARR              198
3630 #define DUK_OP_MPUTARRI             199
3631 #define DUK_OP_SETALEN              200
3632 #define DUK_OP_INITENUM             201
3633 #define DUK_OP_NEXTENUM             202
3634 #define DUK_OP_NEWTARGET            203
3635 #define DUK_OP_DEBUGGER             204
3636 #define DUK_OP_NOP                  205
3637 #define DUK_OP_INVALID              206
3638 #define DUK_OP_UNUSED207            207
3639 #define DUK_OP_GETPROPC             208
3640 #define DUK_OP_GETPROPC_RR          208
3641 #define DUK_OP_GETPROPC_CR          209
3642 #define DUK_OP_GETPROPC_RC          210
3643 #define DUK_OP_GETPROPC_CC          211
3644 #define DUK_OP_UNUSED212            212
3645 #define DUK_OP_UNUSED213            213
3646 #define DUK_OP_UNUSED214            214
3647 #define DUK_OP_UNUSED215            215
3648 #define DUK_OP_UNUSED216            216
3649 #define DUK_OP_UNUSED217            217
3650 #define DUK_OP_UNUSED218            218
3651 #define DUK_OP_UNUSED219            219
3652 #define DUK_OP_UNUSED220            220
3653 #define DUK_OP_UNUSED221            221
3654 #define DUK_OP_UNUSED222            222
3655 #define DUK_OP_UNUSED223            223
3656 #define DUK_OP_UNUSED224            224
3657 #define DUK_OP_UNUSED225            225
3658 #define DUK_OP_UNUSED226            226
3659 #define DUK_OP_UNUSED227            227
3660 #define DUK_OP_UNUSED228            228
3661 #define DUK_OP_UNUSED229            229
3662 #define DUK_OP_UNUSED230            230
3663 #define DUK_OP_UNUSED231            231
3664 #define DUK_OP_UNUSED232            232
3665 #define DUK_OP_UNUSED233            233
3666 #define DUK_OP_UNUSED234            234
3667 #define DUK_OP_UNUSED235            235
3668 #define DUK_OP_UNUSED236            236
3669 #define DUK_OP_UNUSED237            237
3670 #define DUK_OP_UNUSED238            238
3671 #define DUK_OP_UNUSED239            239
3672 #define DUK_OP_UNUSED240            240
3673 #define DUK_OP_UNUSED241            241
3674 #define DUK_OP_UNUSED242            242
3675 #define DUK_OP_UNUSED243            243
3676 #define DUK_OP_UNUSED244            244
3677 #define DUK_OP_UNUSED245            245
3678 #define DUK_OP_UNUSED246            246
3679 #define DUK_OP_UNUSED247            247
3680 #define DUK_OP_UNUSED248            248
3681 #define DUK_OP_UNUSED249            249
3682 #define DUK_OP_UNUSED250            250
3683 #define DUK_OP_UNUSED251            251
3684 #define DUK_OP_UNUSED252            252
3685 #define DUK_OP_UNUSED253            253
3686 #define DUK_OP_UNUSED254            254
3687 #define DUK_OP_UNUSED255            255
3688 #define DUK_OP_NONE                 256  /* dummy value used as marker (doesn't fit in 8-bit field) */
3689 
3690 /* XXX: Allocate flags from opcode field?  Would take 16 opcode slots
3691  * but avoids shuffling in more cases.  Maybe not worth it.
3692  */
3693 /* DUK_OP_TRYCATCH flags in A. */
3694 #define DUK_BC_TRYCATCH_FLAG_HAVE_CATCH     (1U << 0)
3695 #define DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY   (1U << 1)
3696 #define DUK_BC_TRYCATCH_FLAG_CATCH_BINDING  (1U << 2)
3697 #define DUK_BC_TRYCATCH_FLAG_WITH_BINDING   (1U << 3)
3698 
3699 /* DUK_OP_DECLVAR flags in A; bottom bits are reserved for propdesc flags
3700  * (DUK_PROPDESC_FLAG_XXX).
3701  */
3702 #define DUK_BC_DECLVAR_FLAG_FUNC_DECL       (1U << 4)  /* function declaration */
3703 
3704 /* DUK_OP_CALLn flags, part of opcode field.  Three lowest bits must match
3705  * DUK_CALL_FLAG_xxx directly.
3706  */
3707 #define DUK_BC_CALL_FLAG_TAILCALL           (1U << 0)
3708 #define DUK_BC_CALL_FLAG_CONSTRUCT          (1U << 1)
3709 #define DUK_BC_CALL_FLAG_CALLED_AS_EVAL     (1U << 2)
3710 #define DUK_BC_CALL_FLAG_INDIRECT           (1U << 3)
3711 
3712 /* Misc constants and helper macros. */
3713 #define DUK_BC_LDINT_BIAS           (1L << 15)
3714 #define DUK_BC_LDINTX_SHIFT         16
3715 #define DUK_BC_JUMP_BIAS            (1L << 23)
3716 
3717 #endif  /* DUK_JS_BYTECODE_H_INCLUDED */
3718 /* #include duk_lexer.h */
3719 #line 1 "duk_lexer.h"
3720 /*
3721  *  Lexer defines.
3722  */
3723 
3724 #if !defined(DUK_LEXER_H_INCLUDED)
3725 #define DUK_LEXER_H_INCLUDED
3726 
3727 typedef void (*duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct);
3728 
3729 /*
3730  *  A token is interpreted as any possible production of InputElementDiv
3731  *  and InputElementRegExp, see E5 Section 7 in its entirety.  Note that
3732  *  the E5 "Token" production does not cover all actual tokens of the
3733  *  language (which is explicitly stated in the specification, Section 7.5).
3734  *  Null and boolean literals are defined as part of both ReservedWord
3735  *  (E5 Section 7.6.1) and Literal (E5 Section 7.8) productions.  Here,
3736  *  null and boolean values have literal tokens, and are not reserved
3737  *  words.
3738  *
3739  *  Decimal literal negative/positive sign is -not- part of DUK_TOK_NUMBER.
3740  *  The number tokens always have a non-negative value.  The unary minus
3741  *  operator in "-1.0" is optimized during compilation to yield a single
3742  *  negative constant.
3743  *
3744  *  Token numbering is free except that reserved words are required to be
3745  *  in a continuous range and in a particular order.  See genstrings.py.
3746  */
3747 
3748 #define DUK_LEXER_INITCTX(ctx)        duk_lexer_initctx((ctx))
3749 
3750 #define DUK_LEXER_SETPOINT(ctx,pt)    duk_lexer_setpoint((ctx), (pt))
3751 
3752 #define DUK_LEXER_GETPOINT(ctx,pt)    duk_lexer_getpoint((ctx), (pt))
3753 
3754 /* Currently 6 characters of lookup are actually needed (duk_lexer.c). */
3755 #define DUK_LEXER_WINDOW_SIZE                     6
3756 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
3757 #define DUK_LEXER_BUFFER_SIZE                     64
3758 #endif
3759 
3760 #define DUK_TOK_MINVAL                            0
3761 
3762 /* returned after EOF (infinite amount) */
3763 #define DUK_TOK_EOF                               0
3764 
3765 /* identifier names (E5 Section 7.6) */
3766 #define DUK_TOK_IDENTIFIER                        1
3767 
3768 /* reserved words: keywords */
3769 #define DUK_TOK_START_RESERVED                    2
3770 #define DUK_TOK_BREAK                             2
3771 #define DUK_TOK_CASE                              3
3772 #define DUK_TOK_CATCH                             4
3773 #define DUK_TOK_CONTINUE                          5
3774 #define DUK_TOK_DEBUGGER                          6
3775 #define DUK_TOK_DEFAULT                           7
3776 #define DUK_TOK_DELETE                            8
3777 #define DUK_TOK_DO                                9
3778 #define DUK_TOK_ELSE                              10
3779 #define DUK_TOK_FINALLY                           11
3780 #define DUK_TOK_FOR                               12
3781 #define DUK_TOK_FUNCTION                          13
3782 #define DUK_TOK_IF                                14
3783 #define DUK_TOK_IN                                15
3784 #define DUK_TOK_INSTANCEOF                        16
3785 #define DUK_TOK_NEW                               17
3786 #define DUK_TOK_RETURN                            18
3787 #define DUK_TOK_SWITCH                            19
3788 #define DUK_TOK_THIS                              20
3789 #define DUK_TOK_THROW                             21
3790 #define DUK_TOK_TRY                               22
3791 #define DUK_TOK_TYPEOF                            23
3792 #define DUK_TOK_VAR                               24
3793 #define DUK_TOK_CONST                             25
3794 #define DUK_TOK_VOID                              26
3795 #define DUK_TOK_WHILE                             27
3796 #define DUK_TOK_WITH                              28
3797 
3798 /* reserved words: future reserved words */
3799 #define DUK_TOK_CLASS                             29
3800 #define DUK_TOK_ENUM                              30
3801 #define DUK_TOK_EXPORT                            31
3802 #define DUK_TOK_EXTENDS                           32
3803 #define DUK_TOK_IMPORT                            33
3804 #define DUK_TOK_SUPER                             34
3805 
3806 /* "null", "true", and "false" are always reserved words.
3807  * Note that "get" and "set" are not!
3808  */
3809 #define DUK_TOK_NULL                              35
3810 #define DUK_TOK_TRUE                              36
3811 #define DUK_TOK_FALSE                             37
3812 
3813 /* reserved words: additional future reserved words in strict mode */
3814 #define DUK_TOK_START_STRICT_RESERVED             38  /* inclusive */
3815 #define DUK_TOK_IMPLEMENTS                        38
3816 #define DUK_TOK_INTERFACE                         39
3817 #define DUK_TOK_LET                               40
3818 #define DUK_TOK_PACKAGE                           41
3819 #define DUK_TOK_PRIVATE                           42
3820 #define DUK_TOK_PROTECTED                         43
3821 #define DUK_TOK_PUBLIC                            44
3822 #define DUK_TOK_STATIC                            45
3823 #define DUK_TOK_YIELD                             46
3824 
3825 #define DUK_TOK_END_RESERVED                      47  /* exclusive */
3826 
3827 /* "get" and "set" are tokens but NOT ReservedWords.  They are currently
3828  * parsed and identifiers and these defines are actually now unused.
3829  */
3830 #define DUK_TOK_GET                               47
3831 #define DUK_TOK_SET                               48
3832 
3833 /* punctuators (unlike the spec, also includes "/" and "/=") */
3834 #define DUK_TOK_LCURLY                            49
3835 #define DUK_TOK_RCURLY                            50
3836 #define DUK_TOK_LBRACKET                          51
3837 #define DUK_TOK_RBRACKET                          52
3838 #define DUK_TOK_LPAREN                            53
3839 #define DUK_TOK_RPAREN                            54
3840 #define DUK_TOK_PERIOD                            55
3841 #define DUK_TOK_SEMICOLON                         56
3842 #define DUK_TOK_COMMA                             57
3843 #define DUK_TOK_LT                                58
3844 #define DUK_TOK_GT                                59
3845 #define DUK_TOK_LE                                60
3846 #define DUK_TOK_GE                                61
3847 #define DUK_TOK_EQ                                62
3848 #define DUK_TOK_NEQ                               63
3849 #define DUK_TOK_SEQ                               64
3850 #define DUK_TOK_SNEQ                              65
3851 #define DUK_TOK_ADD                               66
3852 #define DUK_TOK_SUB                               67
3853 #define DUK_TOK_MUL                               68
3854 #define DUK_TOK_DIV                               69
3855 #define DUK_TOK_MOD                               70
3856 #define DUK_TOK_EXP                               71
3857 #define DUK_TOK_INCREMENT                         72
3858 #define DUK_TOK_DECREMENT                         73
3859 #define DUK_TOK_ALSHIFT                           74   /* named "arithmetic" because result is signed */
3860 #define DUK_TOK_ARSHIFT                           75
3861 #define DUK_TOK_RSHIFT                            76
3862 #define DUK_TOK_BAND                              77
3863 #define DUK_TOK_BOR                               78
3864 #define DUK_TOK_BXOR                              79
3865 #define DUK_TOK_LNOT                              80
3866 #define DUK_TOK_BNOT                              81
3867 #define DUK_TOK_LAND                              82
3868 #define DUK_TOK_LOR                               83
3869 #define DUK_TOK_QUESTION                          84
3870 #define DUK_TOK_COLON                             85
3871 #define DUK_TOK_EQUALSIGN                         86
3872 #define DUK_TOK_ADD_EQ                            87
3873 #define DUK_TOK_SUB_EQ                            88
3874 #define DUK_TOK_MUL_EQ                            89
3875 #define DUK_TOK_DIV_EQ                            90
3876 #define DUK_TOK_MOD_EQ                            91
3877 #define DUK_TOK_EXP_EQ                            92
3878 #define DUK_TOK_ALSHIFT_EQ                        93
3879 #define DUK_TOK_ARSHIFT_EQ                        94
3880 #define DUK_TOK_RSHIFT_EQ                         95
3881 #define DUK_TOK_BAND_EQ                           96
3882 #define DUK_TOK_BOR_EQ                            97
3883 #define DUK_TOK_BXOR_EQ                           98
3884 
3885 /* literals (E5 Section 7.8), except null, true, false, which are treated
3886  * like reserved words (above).
3887  */
3888 #define DUK_TOK_NUMBER                            99
3889 #define DUK_TOK_STRING                            100
3890 #define DUK_TOK_REGEXP                            101
3891 
3892 #define DUK_TOK_MAXVAL                            101  /* inclusive */
3893 
3894 #define DUK_TOK_INVALID                           DUK_SMALL_UINT_MAX
3895 
3896 /* Convert heap string index to a token (reserved words) */
3897 #define DUK_STRIDX_TO_TOK(x)                        ((x) - DUK_STRIDX_START_RESERVED + DUK_TOK_START_RESERVED)
3898 
3899 /* Sanity check */
3900 #if (DUK_TOK_MAXVAL > 255)
3901 #error DUK_TOK_MAXVAL too large, code assumes it fits into 8 bits
3902 #endif
3903 
3904 /* Sanity checks for string and token defines */
3905 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_BREAK) != DUK_TOK_BREAK)
3906 #error mismatch in token defines
3907 #endif
3908 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CASE) != DUK_TOK_CASE)
3909 #error mismatch in token defines
3910 #endif
3911 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CATCH) != DUK_TOK_CATCH)
3912 #error mismatch in token defines
3913 #endif
3914 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONTINUE) != DUK_TOK_CONTINUE)
3915 #error mismatch in token defines
3916 #endif
3917 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEBUGGER) != DUK_TOK_DEBUGGER)
3918 #error mismatch in token defines
3919 #endif
3920 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEFAULT) != DUK_TOK_DEFAULT)
3921 #error mismatch in token defines
3922 #endif
3923 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DELETE) != DUK_TOK_DELETE)
3924 #error mismatch in token defines
3925 #endif
3926 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DO) != DUK_TOK_DO)
3927 #error mismatch in token defines
3928 #endif
3929 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ELSE) != DUK_TOK_ELSE)
3930 #error mismatch in token defines
3931 #endif
3932 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FINALLY) != DUK_TOK_FINALLY)
3933 #error mismatch in token defines
3934 #endif
3935 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FOR) != DUK_TOK_FOR)
3936 #error mismatch in token defines
3937 #endif
3938 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_FUNCTION) != DUK_TOK_FUNCTION)
3939 #error mismatch in token defines
3940 #endif
3941 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IF) != DUK_TOK_IF)
3942 #error mismatch in token defines
3943 #endif
3944 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IN) != DUK_TOK_IN)
3945 #error mismatch in token defines
3946 #endif
3947 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INSTANCEOF) != DUK_TOK_INSTANCEOF)
3948 #error mismatch in token defines
3949 #endif
3950 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_NEW) != DUK_TOK_NEW)
3951 #error mismatch in token defines
3952 #endif
3953 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_RETURN) != DUK_TOK_RETURN)
3954 #error mismatch in token defines
3955 #endif
3956 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SWITCH) != DUK_TOK_SWITCH)
3957 #error mismatch in token defines
3958 #endif
3959 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THIS) != DUK_TOK_THIS)
3960 #error mismatch in token defines
3961 #endif
3962 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THROW) != DUK_TOK_THROW)
3963 #error mismatch in token defines
3964 #endif
3965 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRY) != DUK_TOK_TRY)
3966 #error mismatch in token defines
3967 #endif
3968 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TYPEOF) != DUK_TOK_TYPEOF)
3969 #error mismatch in token defines
3970 #endif
3971 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VAR) != DUK_TOK_VAR)
3972 #error mismatch in token defines
3973 #endif
3974 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VOID) != DUK_TOK_VOID)
3975 #error mismatch in token defines
3976 #endif
3977 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WHILE) != DUK_TOK_WHILE)
3978 #error mismatch in token defines
3979 #endif
3980 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WITH) != DUK_TOK_WITH)
3981 #error mismatch in token defines
3982 #endif
3983 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CLASS) != DUK_TOK_CLASS)
3984 #error mismatch in token defines
3985 #endif
3986 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONST) != DUK_TOK_CONST)
3987 #error mismatch in token defines
3988 #endif
3989 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ENUM) != DUK_TOK_ENUM)
3990 #error mismatch in token defines
3991 #endif
3992 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXPORT) != DUK_TOK_EXPORT)
3993 #error mismatch in token defines
3994 #endif
3995 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXTENDS) != DUK_TOK_EXTENDS)
3996 #error mismatch in token defines
3997 #endif
3998 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPORT) != DUK_TOK_IMPORT)
3999 #error mismatch in token defines
4000 #endif
4001 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SUPER) != DUK_TOK_SUPER)
4002 #error mismatch in token defines
4003 #endif
4004 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_NULL) != DUK_TOK_NULL)
4005 #error mismatch in token defines
4006 #endif
4007 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRUE) != DUK_TOK_TRUE)
4008 #error mismatch in token defines
4009 #endif
4010 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FALSE) != DUK_TOK_FALSE)
4011 #error mismatch in token defines
4012 #endif
4013 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPLEMENTS) != DUK_TOK_IMPLEMENTS)
4014 #error mismatch in token defines
4015 #endif
4016 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INTERFACE) != DUK_TOK_INTERFACE)
4017 #error mismatch in token defines
4018 #endif
4019 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LET) != DUK_TOK_LET)
4020 #error mismatch in token defines
4021 #endif
4022 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PACKAGE) != DUK_TOK_PACKAGE)
4023 #error mismatch in token defines
4024 #endif
4025 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PRIVATE) != DUK_TOK_PRIVATE)
4026 #error mismatch in token defines
4027 #endif
4028 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PROTECTED) != DUK_TOK_PROTECTED)
4029 #error mismatch in token defines
4030 #endif
4031 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PUBLIC) != DUK_TOK_PUBLIC)
4032 #error mismatch in token defines
4033 #endif
4034 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_STATIC) != DUK_TOK_STATIC)
4035 #error mismatch in token defines
4036 #endif
4037 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_YIELD) != DUK_TOK_YIELD)
4038 #error mismatch in token defines
4039 #endif
4040 
4041 /* Regexp tokens */
4042 #define DUK_RETOK_EOF                              0
4043 #define DUK_RETOK_DISJUNCTION                      1
4044 #define DUK_RETOK_QUANTIFIER                       2
4045 #define DUK_RETOK_ASSERT_START                     3
4046 #define DUK_RETOK_ASSERT_END                       4
4047 #define DUK_RETOK_ASSERT_WORD_BOUNDARY             5
4048 #define DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY         6
4049 #define DUK_RETOK_ASSERT_START_POS_LOOKAHEAD       7
4050 #define DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD       8
4051 #define DUK_RETOK_ATOM_PERIOD                      9
4052 #define DUK_RETOK_ATOM_CHAR                        10
4053 #define DUK_RETOK_ATOM_DIGIT                       11  /* assumptions in regexp compiler */
4054 #define DUK_RETOK_ATOM_NOT_DIGIT                   12  /* -""- */
4055 #define DUK_RETOK_ATOM_WHITE                       13  /* -""- */
4056 #define DUK_RETOK_ATOM_NOT_WHITE                   14  /* -""- */
4057 #define DUK_RETOK_ATOM_WORD_CHAR                   15  /* -""- */
4058 #define DUK_RETOK_ATOM_NOT_WORD_CHAR               16  /* -""- */
4059 #define DUK_RETOK_ATOM_BACKREFERENCE               17
4060 #define DUK_RETOK_ATOM_START_CAPTURE_GROUP         18
4061 #define DUK_RETOK_ATOM_START_NONCAPTURE_GROUP      19
4062 #define DUK_RETOK_ATOM_START_CHARCLASS             20
4063 #define DUK_RETOK_ATOM_START_CHARCLASS_INVERTED    21
4064 #define DUK_RETOK_ATOM_END_GROUP                   22
4065 
4066 /* Constants for duk_lexer_ctx.buf. */
4067 #define DUK_LEXER_TEMP_BUF_LIMIT                   256
4068 
4069 /* A token value.  Can be memcpy()'d, but note that slot1/slot2 values are on the valstack.
4070  * Some fields (like num, str1, str2) are only valid for specific token types and may have
4071  * stale values otherwise.
4072  */
4073 struct duk_token {
4074 	duk_small_uint_t t;           /* token type (with reserved word identification) */
4075 	duk_small_uint_t t_nores;     /* token type (with reserved words as DUK_TOK_IDENTIFER) */
4076 	duk_double_t num;             /* numeric value of token */
4077 	duk_hstring *str1;            /* string 1 of token (borrowed, stored to ctx->slot1_idx) */
4078 	duk_hstring *str2;            /* string 2 of token (borrowed, stored to ctx->slot2_idx) */
4079 	duk_size_t start_offset;      /* start byte offset of token in lexer input */
4080 	duk_int_t start_line;         /* start line of token (first char) */
4081 	duk_int_t num_escapes;        /* number of escapes and line continuations (for directive prologue) */
4082 	duk_bool_t lineterm;          /* token was preceded by a lineterm */
4083 	duk_bool_t allow_auto_semi;   /* token allows automatic semicolon insertion (eof or preceded by newline) */
4084 };
4085 
4086 #define DUK_RE_QUANTIFIER_INFINITE         ((duk_uint32_t) 0xffffffffUL)
4087 
4088 /* A regexp token value. */
4089 struct duk_re_token {
4090 	duk_small_uint_t t;          /* token type */
4091 	duk_small_uint_t greedy;
4092 	duk_uint32_t num;            /* numeric value (character, count) */
4093 	duk_uint32_t qmin;
4094 	duk_uint32_t qmax;
4095 };
4096 
4097 /* A structure for 'snapshotting' a point for rewinding */
4098 struct duk_lexer_point {
4099 	duk_size_t offset;
4100 	duk_int_t line;
4101 };
4102 
4103 /* Lexer codepoint with additional info like offset/line number */
4104 struct duk_lexer_codepoint {
4105 	duk_codepoint_t codepoint;
4106 	duk_size_t offset;
4107 	duk_int_t line;
4108 };
4109 
4110 /* Lexer context.  Same context is used for ECMAScript and Regexp parsing. */
4111 struct duk_lexer_ctx {
4112 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
4113 	duk_lexer_codepoint *window; /* unicode code points, window[0] is always next, points to 'buffer' */
4114 	duk_lexer_codepoint buffer[DUK_LEXER_BUFFER_SIZE];
4115 #else
4116 	duk_lexer_codepoint window[DUK_LEXER_WINDOW_SIZE]; /* unicode code points, window[0] is always next */
4117 #endif
4118 
4119 	duk_hthread *thr;                              /* thread; minimizes argument passing */
4120 
4121 	const duk_uint8_t *input;                      /* input string (may be a user pointer) */
4122 	duk_size_t input_length;                       /* input byte length */
4123 	duk_size_t input_offset;                       /* input offset for window leading edge (not window[0]) */
4124 	duk_int_t input_line;                          /* input linenumber at input_offset (not window[0]), init to 1 */
4125 
4126 	duk_idx_t slot1_idx;                           /* valstack slot for 1st token value */
4127 	duk_idx_t slot2_idx;                           /* valstack slot for 2nd token value */
4128 	duk_idx_t buf_idx;                             /* valstack slot for temp buffer */
4129 	duk_hbuffer_dynamic *buf;                      /* temp accumulation buffer */
4130 	duk_bufwriter_ctx bw;                          /* bufwriter for temp accumulation */
4131 
4132 	duk_int_t token_count;                         /* number of tokens parsed */
4133 	duk_int_t token_limit;                         /* maximum token count before error (sanity backstop) */
4134 
4135 	duk_small_uint_t flags;                        /* lexer flags, use compiler flag defines for now */
4136 };
4137 
4138 /*
4139  *  Prototypes
4140  */
4141 
4142 DUK_INTERNAL_DECL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx);
4143 
4144 DUK_INTERNAL_DECL void duk_lexer_getpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt);
4145 DUK_INTERNAL_DECL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt);
4146 
4147 DUK_INTERNAL_DECL
4148 void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
4149                                       duk_token *out_token,
4150                                       duk_bool_t strict_mode,
4151                                       duk_bool_t regexp_mode);
4152 #if defined(DUK_USE_REGEXP_SUPPORT)
4153 DUK_INTERNAL_DECL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token);
4154 DUK_INTERNAL_DECL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata);
4155 #endif  /* DUK_USE_REGEXP_SUPPORT */
4156 
4157 #endif  /* DUK_LEXER_H_INCLUDED */
4158 /* #include duk_js_compiler.h */
4159 #line 1 "duk_js_compiler.h"
4160 /*
4161  *  ECMAScript compiler.
4162  */
4163 
4164 #if !defined(DUK_JS_COMPILER_H_INCLUDED)
4165 #define DUK_JS_COMPILER_H_INCLUDED
4166 
4167 /* ECMAScript compiler limits */
4168 #define DUK_COMPILER_TOKEN_LIMIT           100000000L  /* 1e8: protects against deeply nested inner functions */
4169 
4170 /* maximum loopcount for peephole optimization */
4171 #define DUK_COMPILER_PEEPHOLE_MAXITER      3
4172 
4173 /* maximum bytecode length in instructions */
4174 #define DUK_COMPILER_MAX_BYTECODE_LENGTH   (256L * 1024L * 1024L)  /* 1 GB */
4175 
4176 /*
4177  *  Compiler intermediate values
4178  *
4179  *  Intermediate values describe either plain values (e.g. strings or
4180  *  numbers) or binary operations which have not yet been coerced into
4181  *  either a left-hand-side or right-hand-side role (e.g. object property).
4182  */
4183 
4184 #define DUK_IVAL_NONE          0   /* no value */
4185 #define DUK_IVAL_PLAIN         1   /* register, constant, or value */
4186 #define DUK_IVAL_ARITH         2   /* binary arithmetic; DUK_OP_ADD, DUK_OP_EQ, other binary ops */
4187 #define DUK_IVAL_PROP          3   /* property access */
4188 #define DUK_IVAL_VAR           4   /* variable access */
4189 
4190 #define DUK_ISPEC_NONE         0   /* no value */
4191 #define DUK_ISPEC_VALUE        1   /* value resides in 'valstack_idx' */
4192 #define DUK_ISPEC_REGCONST     2   /* value resides in a register or constant */
4193 
4194 /* Bit mask which indicates that a regconst is a constant instead of a register.
4195  * Chosen so that when a regconst is cast to duk_int32_t, all consts are
4196  * negative values.
4197  */
4198 #define DUK_REGCONST_CONST_MARKER    DUK_INT32_MIN  /* = -0x80000000 */
4199 
4200 /* Type to represent a reg/const reference during compilation, with <0
4201  * indicating a constant.  Some call sites also use -1 to indicate 'none'.
4202  */
4203 typedef duk_int32_t duk_regconst_t;
4204 
4205 typedef struct {
4206 	duk_small_uint_t t;          /* DUK_ISPEC_XXX */
4207 	duk_regconst_t regconst;
4208 	duk_idx_t valstack_idx;      /* always set; points to a reserved valstack slot */
4209 } duk_ispec;
4210 
4211 typedef struct {
4212 	/*
4213 	 *  PLAIN: x1
4214 	 *  ARITH: x1 <op> x2
4215 	 *  PROP: x1.x2
4216 	 *  VAR: x1 (name)
4217 	 */
4218 
4219 	/* XXX: can be optimized for smaller footprint esp. on 32-bit environments */
4220 	duk_small_uint_t t;          /* DUK_IVAL_XXX */
4221 	duk_small_uint_t op;         /* bytecode opcode for binary ops */
4222 	duk_ispec x1;
4223 	duk_ispec x2;
4224 } duk_ivalue;
4225 
4226 /*
4227  *  Bytecode instruction representation during compilation
4228  *
4229  *  Contains the actual instruction and (optionally) debug info.
4230  */
4231 
4232 struct duk_compiler_instr {
4233 	duk_instr_t ins;
4234 #if defined(DUK_USE_PC2LINE)
4235 	duk_uint32_t line;
4236 #endif
4237 };
4238 
4239 /*
4240  *  Compiler state
4241  */
4242 
4243 #define DUK_LABEL_FLAG_ALLOW_BREAK       (1U << 0)
4244 #define DUK_LABEL_FLAG_ALLOW_CONTINUE    (1U << 1)
4245 
4246 #define DUK_DECL_TYPE_VAR                0
4247 #define DUK_DECL_TYPE_FUNC               1
4248 
4249 /* XXX: optimize to 16 bytes */
4250 typedef struct {
4251 	duk_small_uint_t flags;
4252 	duk_int_t label_id;          /* numeric label_id (-1 reserved as marker) */
4253 	duk_hstring *h_label;        /* borrowed label name */
4254 	duk_int_t catch_depth;       /* catch depth at point of definition */
4255 	duk_int_t pc_label;          /* pc of label statement:
4256 	                              * pc+1: break jump site
4257 	                              * pc+2: continue jump site
4258 	                              */
4259 
4260 	/* Fast jumps (which avoid longjmp) jump directly to the jump sites
4261 	 * which are always known even while the iteration/switch statement
4262 	 * is still being parsed.  A final peephole pass "straightens out"
4263 	 * the jumps.
4264 	 */
4265 } duk_labelinfo;
4266 
4267 /* Compiling state of one function, eventually converted to duk_hcompfunc */
4268 struct duk_compiler_func {
4269 	/* These pointers are at the start of the struct so that they pack
4270 	 * nicely.  Mixing pointers and integer values is bad on some
4271 	 * platforms (e.g. if int is 32 bits and pointers are 64 bits).
4272 	 */
4273 
4274 	duk_bufwriter_ctx bw_code;          /* bufwriter for code */
4275 
4276 	duk_hstring *h_name;                /* function name (borrowed reference), ends up in _name */
4277 	/* h_code: held in bw_code */
4278 	duk_hobject *h_consts;              /* array */
4279 	duk_hobject *h_funcs;               /* array of function templates: [func1, offset1, line1, func2, offset2, line2]
4280 	                                     * offset/line points to closing brace to allow skipping on pass 2
4281 	                                     */
4282 	duk_hobject *h_decls;               /* array of declarations: [ name1, val1, name2, val2, ... ]
4283 	                                     * valN = (typeN) | (fnum << 8), where fnum is inner func number (0 for vars)
4284 	                                     * record function and variable declarations in pass 1
4285 	                                     */
4286 	duk_hobject *h_labelnames;          /* array of active label names */
4287 	duk_hbuffer_dynamic *h_labelinfos;  /* C array of duk_labelinfo */
4288 	duk_hobject *h_argnames;            /* array of formal argument names (-> _Formals) */
4289 	duk_hobject *h_varmap;              /* variable map for pass 2 (identifier -> register number or null (unmapped)) */
4290 
4291 	/* Value stack indices for tracking objects. */
4292 	/* code_idx: not needed */
4293 	duk_idx_t consts_idx;
4294 	duk_idx_t funcs_idx;
4295 	duk_idx_t decls_idx;
4296 	duk_idx_t labelnames_idx;
4297 	duk_idx_t labelinfos_idx;
4298 	duk_idx_t argnames_idx;
4299 	duk_idx_t varmap_idx;
4300 
4301 	/* Temp reg handling. */
4302 	duk_regconst_t temp_first;           /* first register that is a temporary (below: variables) */
4303 	duk_regconst_t temp_next;            /* next temporary register to allocate */
4304 	duk_regconst_t temp_max;             /* highest value of temp_reg (temp_max - 1 is highest used reg) */
4305 
4306 	/* Shuffle registers if large number of regs/consts. */
4307 	duk_regconst_t shuffle1;
4308 	duk_regconst_t shuffle2;
4309 	duk_regconst_t shuffle3;
4310 
4311 	/* Stats for current expression being parsed. */
4312 	duk_int_t nud_count;
4313 	duk_int_t led_count;
4314 	duk_int_t paren_level;              /* parenthesis count, 0 = top level */
4315 	duk_bool_t expr_lhs;                /* expression is left-hand-side compatible */
4316 	duk_bool_t allow_in;                /* current paren level allows 'in' token */
4317 
4318 	/* Misc. */
4319 	duk_int_t stmt_next;                /* statement id allocation (running counter) */
4320 	duk_int_t label_next;               /* label id allocation (running counter) */
4321 	duk_int_t catch_depth;              /* catch stack depth */
4322 	duk_int_t with_depth;               /* with stack depth (affects identifier lookups) */
4323 	duk_int_t fnum_next;                /* inner function numbering */
4324 	duk_int_t num_formals;              /* number of formal arguments */
4325 	duk_regconst_t reg_stmt_value;      /* register for writing value of 'non-empty' statements (global or eval code), -1 is marker */
4326 #if defined(DUK_USE_DEBUGGER_SUPPORT)
4327 	duk_int_t min_line;                 /* XXX: typing (duk_hcompfunc has duk_uint32_t) */
4328 	duk_int_t max_line;
4329 #endif
4330 
4331 	/* Status booleans. */
4332 	duk_uint8_t is_function;             /* is an actual function (not global/eval code) */
4333 	duk_uint8_t is_eval;                 /* is eval code */
4334 	duk_uint8_t is_global;               /* is global code */
4335 	duk_uint8_t is_namebinding;          /* needs a name binding */
4336 	duk_uint8_t is_constructable;        /* result is constructable */
4337 	duk_uint8_t is_setget;               /* is a setter/getter */
4338 	duk_uint8_t is_strict;               /* function is strict */
4339 	duk_uint8_t is_notail;               /* function must not be tail called */
4340 	duk_uint8_t in_directive_prologue;   /* parsing in "directive prologue", recognize directives */
4341 	duk_uint8_t in_scanning;             /* parsing in "scanning" phase (first pass) */
4342 	duk_uint8_t may_direct_eval;         /* function may call direct eval */
4343 	duk_uint8_t id_access_arguments;     /* function refers to 'arguments' identifier */
4344 	duk_uint8_t id_access_slow;          /* function makes one or more slow path accesses that won't match own static variables */
4345 	duk_uint8_t id_access_slow_own;      /* function makes one or more slow path accesses that may match own static variables */
4346 	duk_uint8_t is_arguments_shadowed;   /* argument/function declaration shadows 'arguments' */
4347 	duk_uint8_t needs_shuffle;           /* function needs shuffle registers */
4348 	duk_uint8_t reject_regexp_in_adv;    /* reject RegExp literal on next advance() call; needed for handling IdentifierName productions */
4349 	duk_uint8_t allow_regexp_in_adv;     /* allow RegExp literal on next advance() call */
4350 };
4351 
4352 struct duk_compiler_ctx {
4353 	duk_hthread *thr;
4354 
4355 	/* filename being compiled (ends up in functions' '_filename' property) */
4356 	duk_hstring *h_filename;            /* borrowed reference */
4357 
4358 	/* lexing (tokenization) state (contains two valstack slot indices) */
4359 	duk_lexer_ctx lex;
4360 
4361 	/* current and previous token for parsing */
4362 	duk_token prev_token;
4363 	duk_token curr_token;
4364 	duk_idx_t tok11_idx;                /* curr_token slot1 (matches 'lex' slot1_idx) */
4365 	duk_idx_t tok12_idx;                /* curr_token slot2 (matches 'lex' slot2_idx) */
4366 	duk_idx_t tok21_idx;                /* prev_token slot1 */
4367 	duk_idx_t tok22_idx;                /* prev_token slot2 */
4368 
4369 	/* recursion limit */
4370 	duk_int_t recursion_depth;
4371 	duk_int_t recursion_limit;
4372 
4373 	/* code emission temporary */
4374 	duk_int_t emit_jumpslot_pc;
4375 
4376 	/* current function being compiled (embedded instead of pointer for more compact access) */
4377 	duk_compiler_func curr_func;
4378 };
4379 
4380 /*
4381  *  Prototypes
4382  */
4383 
4384 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);
4385 
4386 #endif  /* DUK_JS_COMPILER_H_INCLUDED */
4387 /* #include duk_regexp.h */
4388 #line 1 "duk_regexp.h"
4389 /*
4390  *  Regular expression structs, constants, and bytecode defines.
4391  */
4392 
4393 #if !defined(DUK_REGEXP_H_INCLUDED)
4394 #define DUK_REGEXP_H_INCLUDED
4395 
4396 /* maximum bytecode copies for {n,m} quantifiers */
4397 #define DUK_RE_MAX_ATOM_COPIES             1000
4398 
4399 /* regexp compilation limits */
4400 #define DUK_RE_COMPILE_TOKEN_LIMIT         100000000L   /* 1e8 */
4401 
4402 /* regexp execution limits */
4403 #define DUK_RE_EXECUTE_STEPS_LIMIT         1000000000L  /* 1e9 */
4404 
4405 /* regexp opcodes */
4406 #define DUK_REOP_MATCH                     1
4407 #define DUK_REOP_CHAR                      2
4408 #define DUK_REOP_PERIOD                    3
4409 #define DUK_REOP_RANGES                    4
4410 #define DUK_REOP_INVRANGES                 5
4411 #define DUK_REOP_JUMP                      6
4412 #define DUK_REOP_SPLIT1                    7
4413 #define DUK_REOP_SPLIT2                    8
4414 #define DUK_REOP_SQMINIMAL                 9
4415 #define DUK_REOP_SQGREEDY                  10
4416 #define DUK_REOP_SAVE                      11
4417 #define DUK_REOP_WIPERANGE                 12
4418 #define DUK_REOP_LOOKPOS                   13
4419 #define DUK_REOP_LOOKNEG                   14
4420 #define DUK_REOP_BACKREFERENCE             15
4421 #define DUK_REOP_ASSERT_START              16
4422 #define DUK_REOP_ASSERT_END                17
4423 #define DUK_REOP_ASSERT_WORD_BOUNDARY      18
4424 #define DUK_REOP_ASSERT_NOT_WORD_BOUNDARY  19
4425 
4426 /* flags */
4427 #define DUK_RE_FLAG_GLOBAL                 (1U << 0)
4428 #define DUK_RE_FLAG_IGNORE_CASE            (1U << 1)
4429 #define DUK_RE_FLAG_MULTILINE              (1U << 2)
4430 
4431 struct duk_re_matcher_ctx {
4432 	duk_hthread *thr;
4433 
4434 	duk_uint32_t re_flags;
4435 	const duk_uint8_t *input;
4436 	const duk_uint8_t *input_end;
4437 	const duk_uint8_t *bytecode;
4438 	const duk_uint8_t *bytecode_end;
4439 	const duk_uint8_t **saved;  /* allocated from valstack (fixed buffer) */
4440 	duk_uint32_t nsaved;
4441 	duk_uint32_t recursion_depth;
4442 	duk_uint32_t recursion_limit;
4443 	duk_uint32_t steps_count;
4444 	duk_uint32_t steps_limit;
4445 };
4446 
4447 struct duk_re_compiler_ctx {
4448 	duk_hthread *thr;
4449 
4450 	duk_uint32_t re_flags;
4451 	duk_lexer_ctx lex;
4452 	duk_re_token curr_token;
4453 	duk_bufwriter_ctx bw;
4454 	duk_uint32_t captures;  /* highest capture number emitted so far (used as: ++captures) */
4455 	duk_uint32_t highest_backref;
4456 	duk_uint32_t recursion_depth;
4457 	duk_uint32_t recursion_limit;
4458 	duk_uint32_t nranges;  /* internal temporary value, used for char classes */
4459 };
4460 
4461 /*
4462  *  Prototypes
4463  */
4464 
4465 #if defined(DUK_USE_REGEXP_SUPPORT)
4466 DUK_INTERNAL_DECL void duk_regexp_compile(duk_hthread *thr);
4467 DUK_INTERNAL_DECL void duk_regexp_create_instance(duk_hthread *thr);
4468 DUK_INTERNAL_DECL void duk_regexp_match(duk_hthread *thr);
4469 DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr);  /* hacky helper for String.prototype.split() */
4470 #endif
4471 
4472 #endif  /* DUK_REGEXP_H_INCLUDED */
4473 /* #include duk_heaphdr.h */
4474 #line 1 "duk_heaphdr.h"
4475 /*
4476  *  Heap header definition and assorted macros, including ref counting.
4477  *  Access all fields through the accessor macros.
4478  */
4479 
4480 #if !defined(DUK_HEAPHDR_H_INCLUDED)
4481 #define DUK_HEAPHDR_H_INCLUDED
4482 
4483 /*
4484  *  Common heap header
4485  *
4486  *  All heap objects share the same flags and refcount fields.  Objects other
4487  *  than strings also need to have a single or double linked list pointers
4488  *  for insertion into the "heap allocated" list.  Strings have single linked
4489  *  list pointers for string table chaining.
4490  *
4491  *  Technically, 'h_refcount' must be wide enough to guarantee that it cannot
4492  *  wrap; otherwise objects might be freed incorrectly after wrapping.  The
4493  *  default refcount field is 32 bits even on 64-bit systems: while that's in
4494  *  theory incorrect, the Duktape heap needs to be larger than 64GB for the
4495  *  count to actually wrap (assuming 16-byte duk_tvals).  This is very unlikely
4496  *  to ever be an issue, but if it is, disabling DUK_USE_REFCOUNT32 causes
4497  *  Duktape to use size_t for refcounts which should always be safe.
4498  *
4499  *  Heap header size on 32-bit platforms: 8 bytes without reference counting,
4500  *  16 bytes with reference counting.
4501  *
4502  *  Note that 'raw' macros such as DUK_HEAPHDR_GET_REFCOUNT() are not
4503  *  defined without DUK_USE_REFERENCE_COUNTING, so caller must #if defined()
4504  *  around them.
4505  */
4506 
4507 /* XXX: macro for shared header fields (avoids some padding issues) */
4508 
4509 struct duk_heaphdr {
4510 	duk_uint32_t h_flags;
4511 
4512 #if defined(DUK_USE_REFERENCE_COUNTING)
4513 #if defined(DUK_USE_ASSERTIONS)
4514 	/* When assertions enabled, used by mark-and-sweep for refcount
4515 	 * validation.  Largest reasonable type; also detects overflows.
4516 	 */
4517 	duk_size_t h_assert_refcount;
4518 #endif
4519 #if defined(DUK_USE_REFCOUNT16)
4520 	duk_uint16_t h_refcount;
4521 #elif defined(DUK_USE_REFCOUNT32)
4522 	duk_uint32_t h_refcount;
4523 #else
4524 	duk_size_t h_refcount;
4525 #endif
4526 #endif  /* DUK_USE_REFERENCE_COUNTING */
4527 
4528 #if defined(DUK_USE_HEAPPTR16)
4529 	duk_uint16_t h_next16;
4530 #else
4531 	duk_heaphdr *h_next;
4532 #endif
4533 
4534 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
4535 	/* refcounting requires direct heap frees, which in turn requires a dual linked heap */
4536 #if defined(DUK_USE_HEAPPTR16)
4537 	duk_uint16_t h_prev16;
4538 #else
4539 	duk_heaphdr *h_prev;
4540 #endif
4541 #endif
4542 
4543 	/* When DUK_USE_HEAPPTR16 (and DUK_USE_REFCOUNT16) is in use, the
4544 	 * struct won't align nicely to 4 bytes.  This 16-bit extra field
4545 	 * is added to make the alignment clean; the field can be used by
4546 	 * heap objects when 16-bit packing is used.  This field is now
4547 	 * conditional to DUK_USE_HEAPPTR16 only, but it is intended to be
4548 	 * used with DUK_USE_REFCOUNT16 and DUK_USE_DOUBLE_LINKED_HEAP;
4549 	 * this only matter to low memory environments anyway.
4550 	 */
4551 #if defined(DUK_USE_HEAPPTR16)
4552 	duk_uint16_t h_extra16;
4553 #endif
4554 };
4555 
4556 struct duk_heaphdr_string {
4557 	/* 16 bits would be enough for shared heaphdr flags and duk_hstring
4558 	 * flags.  The initial parts of duk_heaphdr_string and duk_heaphdr
4559 	 * must match so changing the flags field size here would be quite
4560 	 * awkward.  However, to minimize struct size, we can pack at least
4561 	 * 16 bits of duk_hstring data into the flags field.
4562 	 */
4563 	duk_uint32_t h_flags;
4564 
4565 #if defined(DUK_USE_REFERENCE_COUNTING)
4566 #if defined(DUK_USE_ASSERTIONS)
4567 	/* When assertions enabled, used by mark-and-sweep for refcount
4568 	 * validation.  Largest reasonable type; also detects overflows.
4569 	 */
4570 	duk_size_t h_assert_refcount;
4571 #endif
4572 #if defined(DUK_USE_REFCOUNT16)
4573 	duk_uint16_t h_refcount;
4574 	duk_uint16_t h_strextra16;  /* round out to 8 bytes */
4575 #elif defined(DUK_USE_REFCOUNT32)
4576 	duk_uint32_t h_refcount;
4577 #else
4578 	duk_size_t h_refcount;
4579 #endif
4580 #else
4581 	duk_uint16_t h_strextra16;
4582 #endif  /* DUK_USE_REFERENCE_COUNTING */
4583 
4584 	duk_hstring *h_next;
4585 	/* No 'h_prev' pointer for strings. */
4586 };
4587 
4588 #define DUK_HEAPHDR_FLAGS_TYPE_MASK      0x00000003UL
4589 #define DUK_HEAPHDR_FLAGS_FLAG_MASK      (~DUK_HEAPHDR_FLAGS_TYPE_MASK)
4590 
4591                                              /* 2 bits for heap type */
4592 #define DUK_HEAPHDR_FLAGS_HEAP_START     2   /* 5 heap flags */
4593 #define DUK_HEAPHDR_FLAGS_USER_START     7   /* 25 user flags */
4594 
4595 #define DUK_HEAPHDR_HEAP_FLAG_NUMBER(n)  (DUK_HEAPHDR_FLAGS_HEAP_START + (n))
4596 #define DUK_HEAPHDR_USER_FLAG_NUMBER(n)  (DUK_HEAPHDR_FLAGS_USER_START + (n))
4597 #define DUK_HEAPHDR_HEAP_FLAG(n)         (1UL << (DUK_HEAPHDR_FLAGS_HEAP_START + (n)))
4598 #define DUK_HEAPHDR_USER_FLAG(n)         (1UL << (DUK_HEAPHDR_FLAGS_USER_START + (n)))
4599 
4600 #define DUK_HEAPHDR_FLAG_REACHABLE       DUK_HEAPHDR_HEAP_FLAG(0)  /* mark-and-sweep: reachable */
4601 #define DUK_HEAPHDR_FLAG_TEMPROOT        DUK_HEAPHDR_HEAP_FLAG(1)  /* mark-and-sweep: children not processed */
4602 #define DUK_HEAPHDR_FLAG_FINALIZABLE     DUK_HEAPHDR_HEAP_FLAG(2)  /* mark-and-sweep: finalizable (on current pass) */
4603 #define DUK_HEAPHDR_FLAG_FINALIZED       DUK_HEAPHDR_HEAP_FLAG(3)  /* mark-and-sweep: finalized (on previous pass) */
4604 #define DUK_HEAPHDR_FLAG_READONLY        DUK_HEAPHDR_HEAP_FLAG(4)  /* read-only object, in code section */
4605 
4606 #define DUK_HTYPE_MIN                    0
4607 #define DUK_HTYPE_STRING                 0
4608 #define DUK_HTYPE_OBJECT                 1
4609 #define DUK_HTYPE_BUFFER                 2
4610 #define DUK_HTYPE_MAX                    2
4611 
4612 #if defined(DUK_USE_HEAPPTR16)
4613 #define DUK_HEAPHDR_GET_NEXT(heap,h) \
4614 	((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_next16))
4615 #define DUK_HEAPHDR_SET_NEXT(heap,h,val)   do { \
4616 		(h)->h_next16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) val); \
4617 	} while (0)
4618 #else
4619 #define DUK_HEAPHDR_GET_NEXT(heap,h)  ((h)->h_next)
4620 #define DUK_HEAPHDR_SET_NEXT(heap,h,val)   do { \
4621 		(h)->h_next = (val); \
4622 	} while (0)
4623 #endif
4624 
4625 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
4626 #if defined(DUK_USE_HEAPPTR16)
4627 #define DUK_HEAPHDR_GET_PREV(heap,h) \
4628 	((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_prev16))
4629 #define DUK_HEAPHDR_SET_PREV(heap,h,val)   do { \
4630 		(h)->h_prev16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (val)); \
4631 	} while (0)
4632 #else
4633 #define DUK_HEAPHDR_GET_PREV(heap,h)       ((h)->h_prev)
4634 #define DUK_HEAPHDR_SET_PREV(heap,h,val)   do { \
4635 		(h)->h_prev = (val); \
4636 	} while (0)
4637 #endif
4638 #endif
4639 
4640 #if defined(DUK_USE_REFERENCE_COUNTING)
4641 #define DUK_HEAPHDR_GET_REFCOUNT(h)   ((h)->h_refcount)
4642 #define DUK_HEAPHDR_SET_REFCOUNT(h,val)  do { \
4643 		(h)->h_refcount = (val); \
4644 		DUK_ASSERT((h)->h_refcount == (val));  /* No truncation. */ \
4645 	} while (0)
4646 #define DUK_HEAPHDR_PREINC_REFCOUNT(h)  (++(h)->h_refcount)  /* result: updated refcount */
4647 #define DUK_HEAPHDR_PREDEC_REFCOUNT(h)  (--(h)->h_refcount)  /* result: updated refcount */
4648 #else
4649 /* refcount macros not defined without refcounting, caller must #if defined() now */
4650 #endif  /* DUK_USE_REFERENCE_COUNTING */
4651 
4652 /*
4653  *  Note: type is treated as a field separate from flags, so some masking is
4654  *  involved in the macros below.
4655  */
4656 
4657 #define DUK_HEAPHDR_GET_FLAGS_RAW(h)  ((h)->h_flags)
4658 #define DUK_HEAPHDR_SET_FLAGS_RAW(h,val)  do { \
4659 		(h)->h_flags = (val); } \
4660 	}
4661 #define DUK_HEAPHDR_GET_FLAGS(h)      ((h)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK)
4662 #define DUK_HEAPHDR_SET_FLAGS(h,val)  do { \
4663 		(h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) | (val); \
4664 	} while (0)
4665 #define DUK_HEAPHDR_GET_TYPE(h)       ((h)->h_flags & DUK_HEAPHDR_FLAGS_TYPE_MASK)
4666 #define DUK_HEAPHDR_SET_TYPE(h,val)   do { \
4667 		(h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_TYPE_MASK)) | (val); \
4668 	} while (0)
4669 
4670 /* Comparison for type >= DUK_HTYPE_MIN skipped; because DUK_HTYPE_MIN is zero
4671  * and the comparison is unsigned, it's always true and generates warnings.
4672  */
4673 #define DUK_HEAPHDR_HTYPE_VALID(h)    ( \
4674 	DUK_HEAPHDR_GET_TYPE((h)) <= DUK_HTYPE_MAX \
4675 	)
4676 
4677 #define DUK_HEAPHDR_SET_TYPE_AND_FLAGS(h,tval,fval)  do { \
4678 		(h)->h_flags = ((tval) & DUK_HEAPHDR_FLAGS_TYPE_MASK) | \
4679 		               ((fval) & DUK_HEAPHDR_FLAGS_FLAG_MASK); \
4680 	} while (0)
4681 
4682 #define DUK_HEAPHDR_SET_FLAG_BITS(h,bits)  do { \
4683 		DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
4684 		(h)->h_flags |= (bits); \
4685 	} while (0)
4686 
4687 #define DUK_HEAPHDR_CLEAR_FLAG_BITS(h,bits)  do { \
4688 		DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
4689 		(h)->h_flags &= ~((bits)); \
4690 	} while (0)
4691 
4692 #define DUK_HEAPHDR_CHECK_FLAG_BITS(h,bits)  (((h)->h_flags & (bits)) != 0)
4693 
4694 #define DUK_HEAPHDR_SET_REACHABLE(h)      DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
4695 #define DUK_HEAPHDR_CLEAR_REACHABLE(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
4696 #define DUK_HEAPHDR_HAS_REACHABLE(h)      DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
4697 
4698 #define DUK_HEAPHDR_SET_TEMPROOT(h)       DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
4699 #define DUK_HEAPHDR_CLEAR_TEMPROOT(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
4700 #define DUK_HEAPHDR_HAS_TEMPROOT(h)       DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
4701 
4702 #define DUK_HEAPHDR_SET_FINALIZABLE(h)    DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
4703 #define DUK_HEAPHDR_CLEAR_FINALIZABLE(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
4704 #define DUK_HEAPHDR_HAS_FINALIZABLE(h)    DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
4705 
4706 #define DUK_HEAPHDR_SET_FINALIZED(h)      DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
4707 #define DUK_HEAPHDR_CLEAR_FINALIZED(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
4708 #define DUK_HEAPHDR_HAS_FINALIZED(h)      DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
4709 
4710 #define DUK_HEAPHDR_SET_READONLY(h)       DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
4711 #define DUK_HEAPHDR_CLEAR_READONLY(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
4712 #define DUK_HEAPHDR_HAS_READONLY(h)       DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
4713 
4714 /* get or set a range of flags; m=first bit number, n=number of bits */
4715 #define DUK_HEAPHDR_GET_FLAG_RANGE(h,m,n)  (((h)->h_flags >> (m)) & ((1UL << (n)) - 1UL))
4716 
4717 #define DUK_HEAPHDR_SET_FLAG_RANGE(h,m,n,v)  do { \
4718 		(h)->h_flags = \
4719 			((h)->h_flags & (~(((1UL << (n)) - 1UL) << (m)))) \
4720 			| ((v) << (m)); \
4721 	} while (0)
4722 
4723 /* init pointer fields to null */
4724 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
4725 #define DUK_HEAPHDR_INIT_NULLS(h)       do { \
4726 		DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
4727 		DUK_HEAPHDR_SET_PREV((h), (void *) NULL); \
4728 	} while (0)
4729 #else
4730 #define DUK_HEAPHDR_INIT_NULLS(h)       do { \
4731 		DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
4732 	} while (0)
4733 #endif
4734 
4735 #define DUK_HEAPHDR_STRING_INIT_NULLS(h)  do { \
4736 		(h)->h_next = NULL; \
4737 	} while (0)
4738 
4739 /*
4740  *  Type tests
4741  */
4742 
4743 /* Take advantage of the fact that for DUK_HTYPE_xxx numbers the lowest bit
4744  * is only set for DUK_HTYPE_OBJECT (= 1).
4745  */
4746 #if 0
4747 #define DUK_HEAPHDR_IS_OBJECT(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_OBJECT)
4748 #endif
4749 #define DUK_HEAPHDR_IS_OBJECT(h) ((h)->h_flags & 0x01UL)
4750 #define DUK_HEAPHDR_IS_STRING(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_STRING)
4751 #define DUK_HEAPHDR_IS_BUFFER(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_BUFFER)
4752 
4753 /*
4754  *  Assert helpers
4755  */
4756 
4757 /* Check that prev/next links are consistent: if e.g. h->prev is != NULL,
4758  * h->prev->next should point back to h.
4759  */
4760 #if defined(DUK_USE_ASSERTIONS)
4761 DUK_INTERNAL_DECL void duk_heaphdr_assert_valid_subclassed(duk_heaphdr *h);
4762 DUK_INTERNAL_DECL void duk_heaphdr_assert_links(duk_heap *heap, duk_heaphdr *h);
4763 DUK_INTERNAL_DECL void duk_heaphdr_assert_valid(duk_heaphdr *h);
4764 #define DUK_HEAPHDR_ASSERT_LINKS(heap,h)  do { duk_heaphdr_assert_links((heap), (h)); } while (0)
4765 #define DUK_HEAPHDR_ASSERT_VALID(h)  do { duk_heaphdr_assert_valid((h)); } while (0)
4766 #else
4767 #define DUK_HEAPHDR_ASSERT_LINKS(heap,h)  do {} while (0)
4768 #define DUK_HEAPHDR_ASSERT_VALID(h)  do {} while (0)
4769 #endif
4770 
4771 #endif  /* DUK_HEAPHDR_H_INCLUDED */
4772 /* #include duk_refcount.h */
4773 #line 1 "duk_refcount.h"
4774 /*
4775  *  Reference counting helper macros.  The macros take a thread argument
4776  *  and must thus always be executed in a specific thread context.  The
4777  *  thread argument is not really needed anymore: DECREF can operate with
4778  *  a heap pointer only, and INCREF needs neither.
4779  */
4780 
4781 #if !defined(DUK_REFCOUNT_H_INCLUDED)
4782 #define DUK_REFCOUNT_H_INCLUDED
4783 
4784 #if defined(DUK_USE_REFERENCE_COUNTING)
4785 
4786 #if defined(DUK_USE_ROM_OBJECTS)
4787 /* With ROM objects "needs refcount update" is true when the value is
4788  * heap allocated and is not a ROM object.
4789  */
4790 /* XXX: double evaluation for 'tv' argument. */
4791 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) \
4792 	(DUK_TVAL_IS_HEAP_ALLOCATED((tv)) && !DUK_HEAPHDR_HAS_READONLY(DUK_TVAL_GET_HEAPHDR((tv))))
4793 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)  (!DUK_HEAPHDR_HAS_READONLY((h)))
4794 #else  /* DUK_USE_ROM_OBJECTS */
4795 /* Without ROM objects "needs refcount update" == is heap allocated. */
4796 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)    DUK_TVAL_IS_HEAP_ALLOCATED((tv))
4797 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)  1
4798 #endif  /* DUK_USE_ROM_OBJECTS */
4799 
4800 /* Fast variants, inline refcount operations except for refzero handling.
4801  * Can be used explicitly when speed is always more important than size.
4802  * For a good compiler and a single file build, these are basically the
4803  * same as a forced inline.
4804  */
4805 #define DUK_TVAL_INCREF_FAST(thr,tv) do { \
4806 		duk_tval *duk__tv = (tv); \
4807 		DUK_ASSERT(duk__tv != NULL); \
4808 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
4809 			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
4810 			DUK_ASSERT(duk__h != NULL); \
4811 			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4812 			DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
4813 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0);  /* No wrapping. */ \
4814 		} \
4815 	} while (0)
4816 #define DUK_TVAL_DECREF_FAST(thr,tv) do { \
4817 		duk_tval *duk__tv = (tv); \
4818 		DUK_ASSERT(duk__tv != NULL); \
4819 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
4820 			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
4821 			DUK_ASSERT(duk__h != NULL); \
4822 			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4823 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4824 			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4825 				duk_heaphdr_refzero((thr), duk__h); \
4826 			} \
4827 		} \
4828 	} while (0)
4829 #define DUK_TVAL_DECREF_NORZ_FAST(thr,tv) do { \
4830 		duk_tval *duk__tv = (tv); \
4831 		DUK_ASSERT(duk__tv != NULL); \
4832 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
4833 			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
4834 			DUK_ASSERT(duk__h != NULL); \
4835 			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4836 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4837 			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4838 				duk_heaphdr_refzero_norz((thr), duk__h); \
4839 			} \
4840 		} \
4841 	} while (0)
4842 #define DUK_HEAPHDR_INCREF_FAST(thr,h) do { \
4843 		duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
4844 		DUK_ASSERT(duk__h != NULL); \
4845 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4846 		if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
4847 			DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
4848 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0);  /* No wrapping. */ \
4849 		} \
4850 	} while (0)
4851 #define DUK_HEAPHDR_DECREF_FAST_RAW(thr,h,rzcall,rzcast) do { \
4852 		duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
4853 		DUK_ASSERT(duk__h != NULL); \
4854 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4855 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4856 		if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
4857 			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4858 				(rzcall)((thr), (rzcast) duk__h); \
4859 			} \
4860 		} \
4861 	} while (0)
4862 #define DUK_HEAPHDR_DECREF_FAST(thr,h) \
4863 	DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero,duk_heaphdr *)
4864 #define DUK_HEAPHDR_DECREF_NORZ_FAST(thr,h) \
4865 	DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero_norz,duk_heaphdr *)
4866 
4867 /* Slow variants, call to a helper to reduce code size.
4868  * Can be used explicitly when size is always more important than speed.
4869  */
4870 #define DUK_TVAL_INCREF_SLOW(thr,tv)         do { duk_tval_incref((tv)); } while (0)
4871 #define DUK_TVAL_DECREF_SLOW(thr,tv)         do { duk_tval_decref((thr), (tv)); } while (0)
4872 #define DUK_TVAL_DECREF_NORZ_SLOW(thr,tv)    do { duk_tval_decref_norz((thr), (tv)); } while (0)
4873 #define DUK_HEAPHDR_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4874 #define DUK_HEAPHDR_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4875 #define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4876 #define DUK_HSTRING_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4877 #define DUK_HSTRING_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4878 #define DUK_HSTRING_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4879 #define DUK_HBUFFER_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4880 #define DUK_HBUFFER_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4881 #define DUK_HBUFFER_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4882 #define DUK_HOBJECT_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4883 #define DUK_HOBJECT_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4884 #define DUK_HOBJECT_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4885 
4886 /* Default variants.  Selection depends on speed/size preference.
4887  * Concretely: with gcc 4.8.1 -Os x64 the difference in final binary
4888  * is about +1kB for _FAST variants.
4889  */
4890 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
4891 /* XXX: It would be nice to specialize for specific duk_hobject subtypes
4892  * but current refzero queue handling prevents that.
4893  */
4894 #define DUK_TVAL_INCREF(thr,tv)                DUK_TVAL_INCREF_FAST((thr),(tv))
4895 #define DUK_TVAL_DECREF(thr,tv)                DUK_TVAL_DECREF_FAST((thr),(tv))
4896 #define DUK_TVAL_DECREF_NORZ(thr,tv)           DUK_TVAL_DECREF_NORZ_FAST((thr),(tv))
4897 #define DUK_HEAPHDR_INCREF(thr,h)              DUK_HEAPHDR_INCREF_FAST((thr),(h))
4898 #define DUK_HEAPHDR_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero,duk_heaphdr *)
4899 #define DUK_HEAPHDR_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero_norz,duk_heaphdr *)
4900 #define DUK_HSTRING_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4901 #define DUK_HSTRING_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hstring_refzero,duk_hstring *)
4902 #define DUK_HSTRING_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hstring_refzero,duk_hstring *)  /* no 'norz' variant */
4903 #define DUK_HOBJECT_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4904 #define DUK_HOBJECT_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4905 #define DUK_HOBJECT_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4906 #define DUK_HBUFFER_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4907 #define DUK_HBUFFER_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hbuffer_refzero,duk_hbuffer *)
4908 #define DUK_HBUFFER_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hbuffer_refzero,duk_hbuffer *)  /* no 'norz' variant */
4909 #define DUK_HCOMPFUNC_INCREF(thr,h)            DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4910 #define DUK_HCOMPFUNC_DECREF(thr,h)            DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4911 #define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4912 #define DUK_HNATFUNC_INCREF(thr,h)             DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4913 #define DUK_HNATFUNC_DECREF(thr,h)             DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4914 #define DUK_HNATFUNC_DECREF_NORZ(thr,h)        DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4915 #define DUK_HBUFOBJ_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4916 #define DUK_HBUFOBJ_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4917 #define DUK_HBUFOBJ_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4918 #define DUK_HTHREAD_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4919 #define DUK_HTHREAD_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4920 #define DUK_HTHREAD_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4921 #else
4922 #define DUK_TVAL_INCREF(thr,tv)                DUK_TVAL_INCREF_SLOW((thr),(tv))
4923 #define DUK_TVAL_DECREF(thr,tv)                DUK_TVAL_DECREF_SLOW((thr),(tv))
4924 #define DUK_TVAL_DECREF_NORZ(thr,tv)           DUK_TVAL_DECREF_NORZ_SLOW((thr),(tv))
4925 #define DUK_HEAPHDR_INCREF(thr,h)              DUK_HEAPHDR_INCREF_SLOW((thr),(h))
4926 #define DUK_HEAPHDR_DECREF(thr,h)              DUK_HEAPHDR_DECREF_SLOW((thr),(h))
4927 #define DUK_HEAPHDR_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_NORZ_SLOW((thr),(h))
4928 #define DUK_HSTRING_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4929 #define DUK_HSTRING_DECREF(thr,h)              DUK_HSTRING_DECREF_SLOW((thr),(h))
4930 #define DUK_HSTRING_DECREF_NORZ(thr,h)         DUK_HSTRING_DECREF_NORZ_SLOW((thr),(h))
4931 #define DUK_HOBJECT_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4932 #define DUK_HOBJECT_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(h))
4933 #define DUK_HOBJECT_DECREF_NORZ(thr,h)         DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(h))
4934 #define DUK_HBUFFER_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4935 #define DUK_HBUFFER_DECREF(thr,h)              DUK_HBUFFER_DECREF_SLOW((thr),(h))
4936 #define DUK_HBUFFER_DECREF_NORZ(thr,h)         DUK_HBUFFER_DECREF_NORZ_SLOW((thr),(h))
4937 #define DUK_HCOMPFUNC_INCREF(thr,h)            DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4938 #define DUK_HCOMPFUNC_DECREF(thr,h)            DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4939 #define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4940 #define DUK_HNATFUNC_INCREF(thr,h)             DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4941 #define DUK_HNATFUNC_DECREF(thr,h)             DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4942 #define DUK_HNATFUNC_DECREF_NORZ(thr,h)        DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4943 #define DUK_HBUFOBJ_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4944 #define DUK_HBUFOBJ_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4945 #define DUK_HBUFOB_DECREF_NORZ(thr,h)          DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4946 #define DUK_HTHREAD_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4947 #define DUK_HTHREAD_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4948 #define DUK_HTHREAD_DECREF_NORZ(thr,h)         DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4949 #endif
4950 
4951 /* Convenience for some situations; the above macros don't allow NULLs
4952  * for performance reasons.  Macros cover only actually needed cases.
4953  */
4954 #define DUK_HEAPHDR_INCREF_ALLOWNULL(thr,h) do { \
4955 		if ((h) != NULL) { \
4956 			DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h)); \
4957 		} \
4958 	} while (0)
4959 #define DUK_HEAPHDR_DECREF_ALLOWNULL(thr,h) do { \
4960 		if ((h) != NULL) { \
4961 			DUK_HEAPHDR_DECREF((thr), (duk_heaphdr *) (h)); \
4962 		} \
4963 	} while (0)
4964 #define DUK_HEAPHDR_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4965 		if ((h) != NULL) { \
4966 			DUK_HEAPHDR_DECREF_NORZ((thr), (duk_heaphdr *) (h)); \
4967 		} \
4968 	} while (0)
4969 #define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do { \
4970 		if ((h) != NULL) { \
4971 			DUK_HOBJECT_INCREF((thr), (h)); \
4972 		} \
4973 	} while (0)
4974 #define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do { \
4975 		if ((h) != NULL) { \
4976 			DUK_HOBJECT_DECREF((thr), (h)); \
4977 		} \
4978 	} while (0)
4979 #define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4980 		if ((h) != NULL) { \
4981 			DUK_HOBJECT_DECREF_NORZ((thr), (h)); \
4982 		} \
4983 	} while (0)
4984 #define DUK_HBUFFER_INCREF_ALLOWNULL(thr,h) do { \
4985 		if ((h) != NULL) { \
4986 			DUK_HBUFFER_INCREF((thr), (h)); \
4987 		} \
4988 	} while (0)
4989 #define DUK_HBUFFER_DECREF_ALLOWNULL(thr,h) do { \
4990 		if ((h) != NULL) { \
4991 			DUK_HBUFFER_DECREF((thr), (h)); \
4992 		} \
4993 	} while (0)
4994 #define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4995 		if ((h) != NULL) { \
4996 			DUK_HBUFFER_DECREF_NORZ((thr), (h)); \
4997 		} \
4998 	} while (0)
4999 #define DUK_HTHREAD_INCREF_ALLOWNULL(thr,h) do { \
5000 		if ((h) != NULL) { \
5001 			DUK_HTHREAD_INCREF((thr), (h)); \
5002 		} \
5003 	} while (0)
5004 #define DUK_HTHREAD_DECREF_ALLOWNULL(thr,h) do { \
5005 		if ((h) != NULL) { \
5006 			DUK_HTHREAD_DECREF((thr), (h)); \
5007 		} \
5008 	} while (0)
5009 #define DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr,h) do { \
5010 		if ((h) != NULL) { \
5011 			DUK_HTHREAD_DECREF_NORZ((thr), (h)); \
5012 		} \
5013 	} while (0)
5014 
5015 /* Called after one or more DECREF NORZ calls to handle pending side effects.
5016  * At present DECREF NORZ does freeing inline but doesn't execute finalizers,
5017  * so these macros check for pending finalizers and execute them.  The FAST
5018  * variant is performance critical.
5019  */
5020 #if defined(DUK_USE_FINALIZER_SUPPORT)
5021 #define DUK_REFZERO_CHECK_FAST(thr) do { \
5022 		duk_refzero_check_fast((thr)); \
5023 	} while (0)
5024 #define DUK_REFZERO_CHECK_SLOW(thr) do { \
5025 		duk_refzero_check_slow((thr)); \
5026 	} while (0)
5027 #else  /* DUK_USE_FINALIZER_SUPPORT */
5028 #define DUK_REFZERO_CHECK_FAST(thr) do { } while (0)
5029 #define DUK_REFZERO_CHECK_SLOW(thr) do { } while (0)
5030 #endif  /* DUK_USE_FINALIZER_SUPPORT */
5031 
5032 /*
5033  *  Macros to set a duk_tval and update refcount of the target (decref the
5034  *  old value and incref the new value if necessary).  This is both performance
5035  *  and footprint critical; any changes made should be measured for size/speed.
5036  */
5037 
5038 #define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
5039 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5040 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5041 		DUK_TVAL_SET_UNDEFINED(tv__dst); \
5042 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5043 	} while (0)
5044 
5045 #define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0(thr,tvptr_dst) do { \
5046 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5047 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5048 		DUK_TVAL_SET_UNDEFINED(tv__dst); \
5049 		DUK_TVAL_DECREF_NORZ((thr), &tv__tmp); \
5050 	} while (0)
5051 
5052 #define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
5053 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5054 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5055 		DUK_TVAL_SET_UNUSED(tv__dst); \
5056 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5057 	} while (0)
5058 
5059 #define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
5060 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5061 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5062 		DUK_TVAL_SET_NULL(tv__dst); \
5063 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5064 	} while (0)
5065 
5066 #define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5067 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5068 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5069 		DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
5070 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5071 	} while (0)
5072 
5073 #define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5074 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5075 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5076 		DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
5077 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5078 	} while (0)
5079 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5080 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5081 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5082 		DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \
5083 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5084 	} while (0)
5085 #define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5086 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5087 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5088 		DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
5089 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5090 	} while (0)
5091 #define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
5092 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5093 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5094 		DUK_TVAL_SET_NAN(tv__dst); \
5095 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5096 	} while (0)
5097 #if defined(DUK_USE_FASTINT)
5098 #define DUK_TVAL_SET_I48_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5099 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5100 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5101 		DUK_TVAL_SET_I48(tv__dst, (newval)); \
5102 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5103 	} while (0)
5104 #define DUK_TVAL_SET_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5105 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5106 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5107 		DUK_TVAL_SET_I32(tv__dst, (newval)); \
5108 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5109 	} while (0)
5110 #define DUK_TVAL_SET_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5111 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5112 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5113 		DUK_TVAL_SET_U32(tv__dst, (newval)); \
5114 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5115 	} while (0)
5116 #else
5117 #define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
5118 	DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
5119 #endif  /* DUK_USE_FASTINT */
5120 
5121 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
5122 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5123 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5124 		DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
5125 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5126 	} while (0)
5127 
5128 #define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5129 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5130 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5131 		DUK_TVAL_SET_STRING(tv__dst, (newval)); \
5132 		DUK_HSTRING_INCREF((thr), (newval)); \
5133 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5134 	} while (0)
5135 
5136 #define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5137 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5138 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5139 		DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
5140 		DUK_HOBJECT_INCREF((thr), (newval)); \
5141 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5142 	} while (0)
5143 
5144 #define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5145 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5146 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5147 		DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
5148 		DUK_HBUFFER_INCREF((thr), (newval)); \
5149 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5150 	} while (0)
5151 
5152 #define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5153 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5154 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5155 		DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
5156 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5157 	} while (0)
5158 
5159 /* DUK_TVAL_SET_TVAL_UPDREF() is used a lot in executor, property lookups,
5160  * etc, so it's very important for performance.  Measure when changing.
5161  *
5162  * NOTE: the source and destination duk_tval pointers may be the same, and
5163  * the macros MUST deal with that correctly.
5164  */
5165 
5166 /* Original idiom used, minimal code size. */
5167 #define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
5168 		duk_tval *tv__dst, *tv__src; duk_tval tv__tmp; \
5169 		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
5170 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5171 		DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5172 		DUK_TVAL_INCREF((thr), tv__src); \
5173 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5174 	} while (0)
5175 
5176 /* Faster alternative: avoid making a temporary copy of tvptr_dst and use
5177  * fast incref/decref macros.
5178  */
5179 #define DUK_TVAL_SET_TVAL_UPDREF_ALT1(thr,tvptr_dst,tvptr_src) do { \
5180 		duk_tval *tv__dst, *tv__src; duk_heaphdr *h__obj; \
5181 		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
5182 		DUK_TVAL_INCREF_FAST((thr), tv__src); \
5183 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv__dst)) { \
5184 			h__obj = DUK_TVAL_GET_HEAPHDR(tv__dst); \
5185 			DUK_ASSERT(h__obj != NULL); \
5186 			DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5187 			DUK_HEAPHDR_DECREF_FAST((thr), h__obj);  /* side effects */ \
5188 		} else { \
5189 			DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5190 		} \
5191 	} while (0)
5192 
5193 /* XXX: no optimized variants yet */
5194 #define DUK_TVAL_SET_UNDEFINED_UPDREF         DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
5195 #define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ    DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0
5196 #define DUK_TVAL_SET_UNUSED_UPDREF            DUK_TVAL_SET_UNUSED_UPDREF_ALT0
5197 #define DUK_TVAL_SET_NULL_UPDREF              DUK_TVAL_SET_NULL_UPDREF_ALT0
5198 #define DUK_TVAL_SET_BOOLEAN_UPDREF           DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
5199 #define DUK_TVAL_SET_NUMBER_UPDREF            DUK_TVAL_SET_NUMBER_UPDREF_ALT0
5200 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF    DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
5201 #define DUK_TVAL_SET_DOUBLE_UPDREF            DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
5202 #define DUK_TVAL_SET_NAN_UPDREF               DUK_TVAL_SET_NAN_UPDREF_ALT0
5203 #if defined(DUK_USE_FASTINT)
5204 #define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_I48_UPDREF_ALT0
5205 #define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_I32_UPDREF_ALT0
5206 #define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_U32_UPDREF_ALT0
5207 #else
5208 #define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF  /* XXX: fast int-to-double */
5209 #define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5210 #define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5211 #endif  /* DUK_USE_FASTINT */
5212 #define DUK_TVAL_SET_FASTINT_UPDREF           DUK_TVAL_SET_I48_UPDREF  /* convenience */
5213 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF         DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
5214 #define DUK_TVAL_SET_STRING_UPDREF            DUK_TVAL_SET_STRING_UPDREF_ALT0
5215 #define DUK_TVAL_SET_OBJECT_UPDREF            DUK_TVAL_SET_OBJECT_UPDREF_ALT0
5216 #define DUK_TVAL_SET_BUFFER_UPDREF            DUK_TVAL_SET_BUFFER_UPDREF_ALT0
5217 #define DUK_TVAL_SET_POINTER_UPDREF           DUK_TVAL_SET_POINTER_UPDREF_ALT0
5218 
5219 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
5220 /* Optimized for speed. */
5221 #define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT1
5222 #define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT1
5223 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5224 #else
5225 /* Optimized for size. */
5226 #define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT0
5227 #define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5228 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5229 #endif
5230 
5231 #else  /* DUK_USE_REFERENCE_COUNTING */
5232 
5233 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)     0
5234 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)   0
5235 
5236 #define DUK_TVAL_INCREF_FAST(thr,v)            do {} while (0) /* nop */
5237 #define DUK_TVAL_DECREF_FAST(thr,v)            do {} while (0) /* nop */
5238 #define DUK_TVAL_DECREF_NORZ_FAST(thr,v)       do {} while (0) /* nop */
5239 #define DUK_TVAL_INCREF_SLOW(thr,v)            do {} while (0) /* nop */
5240 #define DUK_TVAL_DECREF_SLOW(thr,v)            do {} while (0) /* nop */
5241 #define DUK_TVAL_DECREF_NORZ_SLOW(thr,v)       do {} while (0) /* nop */
5242 #define DUK_TVAL_INCREF(thr,v)                 do {} while (0) /* nop */
5243 #define DUK_TVAL_DECREF(thr,v)                 do {} while (0) /* nop */
5244 #define DUK_TVAL_DECREF_NORZ(thr,v)            do {} while (0) /* nop */
5245 #define DUK_HEAPHDR_INCREF_FAST(thr,h)         do {} while (0) /* nop */
5246 #define DUK_HEAPHDR_DECREF_FAST(thr,h)         do {} while (0) /* nop */
5247 #define DUK_HEAPHDR_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
5248 #define DUK_HEAPHDR_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
5249 #define DUK_HEAPHDR_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
5250 #define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
5251 #define DUK_HEAPHDR_INCREF(thr,h)              do {} while (0) /* nop */
5252 #define DUK_HEAPHDR_DECREF(thr,h)              do {} while (0) /* nop */
5253 #define DUK_HEAPHDR_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5254 #define DUK_HSTRING_INCREF_FAST(thr,h)         do {} while (0) /* nop */
5255 #define DUK_HSTRING_DECREF_FAST(thr,h)         do {} while (0) /* nop */
5256 #define DUK_HSTRING_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
5257 #define DUK_HSTRING_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
5258 #define DUK_HSTRING_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
5259 #define DUK_HSTRING_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
5260 #define DUK_HSTRING_INCREF(thr,h)              do {} while (0) /* nop */
5261 #define DUK_HSTRING_DECREF(thr,h)              do {} while (0) /* nop */
5262 #define DUK_HSTRING_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5263 #define DUK_HOBJECT_INCREF_FAST(thr,h)         do {} while (0) /* nop */
5264 #define DUK_HOBJECT_DECREF_FAST(thr,h)         do {} while (0) /* nop */
5265 #define DUK_HOBJECT_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
5266 #define DUK_HOBJECT_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
5267 #define DUK_HOBJECT_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
5268 #define DUK_HOBJECT_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
5269 #define DUK_HOBJECT_INCREF(thr,h)              do {} while (0) /* nop */
5270 #define DUK_HOBJECT_DECREF(thr,h)              do {} while (0) /* nop */
5271 #define DUK_HOBJECT_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5272 #define DUK_HBUFFER_INCREF_FAST(thr,h)         do {} while (0) /* nop */
5273 #define DUK_HBUFFER_DECREF_FAST(thr,h)         do {} while (0) /* nop */
5274 #define DUK_HBUFFER_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
5275 #define DUK_HBUFFER_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
5276 #define DUK_HBUFFER_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
5277 #define DUK_HBUFFER_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
5278 #define DUK_HBUFFER_INCREF(thr,h)              do {} while (0) /* nop */
5279 #define DUK_HBUFFER_DECREF(thr,h)              do {} while (0) /* nop */
5280 #define DUK_HBUFFER_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5281 
5282 #define DUK_HCOMPFUNC_INCREF(thr,h)            do {} while (0) /* nop */
5283 #define DUK_HCOMPFUNC_DECREF(thr,h)            do {} while (0) /* nop */
5284 #define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       do {} while (0) /* nop */
5285 #define DUK_HNATFUNC_INCREF(thr,h)             do {} while (0) /* nop */
5286 #define DUK_HNATFUNC_DECREF(thr,h)             do {} while (0) /* nop */
5287 #define DUK_HNATFUNC_DECREF_NORZ(thr,h)        do {} while (0) /* nop */
5288 #define DUK_HBUFOBJ_INCREF(thr,h)              do {} while (0) /* nop */
5289 #define DUK_HBUFOBJ_DECREF(thr,h)              do {} while (0) /* nop */
5290 #define DUK_HBUFOBJ_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5291 #define DUK_HTHREAD_INCREF(thr,h)              do {} while (0) /* nop */
5292 #define DUK_HTHREAD_DECREF(thr,h)              do {} while (0) /* nop */
5293 #define DUK_HTHREAD_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5294 #define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
5295 #define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
5296 #define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr,h)  do {} while (0) /* nop */
5297 #define DUK_HBUFFER_INCREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
5298 #define DUK_HBUFFER_DECREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
5299 #define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr,h)  do {} while (0) /* nop */
5300 
5301 #define DUK_REFZERO_CHECK_FAST(thr)            do {} while (0) /* nop */
5302 #define DUK_REFZERO_CHECK_SLOW(thr)            do {} while (0) /* nop */
5303 
5304 #define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
5305 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5306 		DUK_TVAL_SET_UNDEFINED(tv__dst); \
5307 		DUK_UNREF((thr)); \
5308 	} while (0)
5309 
5310 #define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
5311 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5312 		DUK_TVAL_SET_UNUSED(tv__dst); \
5313 		DUK_UNREF((thr)); \
5314 	} while (0)
5315 
5316 #define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
5317 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5318 		DUK_TVAL_SET_NULL(tv__dst); \
5319 		DUK_UNREF((thr)); \
5320 	} while (0)
5321 
5322 #define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5323 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5324 		DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
5325 		DUK_UNREF((thr)); \
5326 	} while (0)
5327 
5328 #define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5329 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5330 		DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
5331 		DUK_UNREF((thr)); \
5332 	} while (0)
5333 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5334 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5335 		DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \
5336 		DUK_UNREF((thr)); \
5337 	} while (0)
5338 #define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5339 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5340 		DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
5341 		DUK_UNREF((thr)); \
5342 	} while (0)
5343 #define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
5344 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5345 		DUK_TVAL_SET_NAN(tv__dst); \
5346 		DUK_UNREF((thr)); \
5347 	} while (0)
5348 #if defined(DUK_USE_FASTINT)
5349 #define DUK_TVAL_SET_I48_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5350 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5351 		DUK_TVAL_SET_I48(tv__dst, (newval)); \
5352 		DUK_UNREF((thr)); \
5353 	} while (0)
5354 #define DUK_TVAL_SET_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5355 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5356 		DUK_TVAL_SET_I32(tv__dst, (newval)); \
5357 		DUK_UNREF((thr)); \
5358 	} while (0)
5359 #define DUK_TVAL_SET_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5360 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5361 		DUK_TVAL_SET_U32(tv__dst, (newval)); \
5362 		DUK_UNREF((thr)); \
5363 	} while (0)
5364 #else
5365 #define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
5366 	DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
5367 #endif  /* DUK_USE_FASTINT */
5368 
5369 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
5370 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5371 		DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
5372 		DUK_UNREF((thr)); \
5373 	} while (0)
5374 
5375 #define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5376 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5377 		DUK_TVAL_SET_STRING(tv__dst, (newval)); \
5378 		DUK_UNREF((thr)); \
5379 	} while (0)
5380 
5381 #define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5382 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5383 		DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
5384 		DUK_UNREF((thr)); \
5385 	} while (0)
5386 
5387 #define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5388 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5389 		DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
5390 		DUK_UNREF((thr)); \
5391 	} while (0)
5392 
5393 #define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5394 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5395 		DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
5396 		DUK_UNREF((thr)); \
5397 	} while (0)
5398 
5399 #define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
5400 		duk_tval *tv__dst, *tv__src; \
5401 		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
5402 		DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5403 		DUK_UNREF((thr)); \
5404 	} while (0)
5405 
5406 #define DUK_TVAL_SET_UNDEFINED_UPDREF         DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
5407 #define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ    DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
5408 #define DUK_TVAL_SET_UNUSED_UPDREF            DUK_TVAL_SET_UNUSED_UPDREF_ALT0
5409 #define DUK_TVAL_SET_NULL_UPDREF              DUK_TVAL_SET_NULL_UPDREF_ALT0
5410 #define DUK_TVAL_SET_BOOLEAN_UPDREF           DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
5411 #define DUK_TVAL_SET_NUMBER_UPDREF            DUK_TVAL_SET_NUMBER_UPDREF_ALT0
5412 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF    DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
5413 #define DUK_TVAL_SET_DOUBLE_UPDREF            DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
5414 #define DUK_TVAL_SET_NAN_UPDREF               DUK_TVAL_SET_NAN_UPDREF_ALT0
5415 #if defined(DUK_USE_FASTINT)
5416 #define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_I48_UPDREF_ALT0
5417 #define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_I32_UPDREF_ALT0
5418 #define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_U32_UPDREF_ALT0
5419 #else
5420 #define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF  /* XXX: fast-int-to-double */
5421 #define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5422 #define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5423 #endif  /* DUK_USE_FASTINT */
5424 #define DUK_TVAL_SET_FASTINT_UPDREF           DUK_TVAL_SET_I48_UPDREF  /* convenience */
5425 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF         DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
5426 #define DUK_TVAL_SET_STRING_UPDREF            DUK_TVAL_SET_STRING_UPDREF_ALT0
5427 #define DUK_TVAL_SET_OBJECT_UPDREF            DUK_TVAL_SET_OBJECT_UPDREF_ALT0
5428 #define DUK_TVAL_SET_BUFFER_UPDREF            DUK_TVAL_SET_BUFFER_UPDREF_ALT0
5429 #define DUK_TVAL_SET_POINTER_UPDREF           DUK_TVAL_SET_POINTER_UPDREF_ALT0
5430 
5431 #define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT0
5432 #define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5433 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5434 
5435 #endif  /* DUK_USE_REFERENCE_COUNTING */
5436 
5437 /*
5438  *  Some convenience macros that don't have optimized implementations now.
5439  */
5440 
5441 #define DUK_TVAL_SET_TVAL_UPDREF_NORZ(thr,tv_dst,tv_src) do { \
5442 		duk_hthread *duk__thr = (thr); \
5443 		duk_tval *duk__dst = (tv_dst); \
5444 		duk_tval *duk__src = (tv_src); \
5445 		DUK_UNREF(duk__thr); \
5446 		DUK_TVAL_DECREF_NORZ(thr, duk__dst); \
5447 		DUK_TVAL_SET_TVAL(duk__dst, duk__src); \
5448 		DUK_TVAL_INCREF(thr, duk__dst); \
5449 	} while (0)
5450 
5451 #define DUK_TVAL_SET_U32_UPDREF_NORZ(thr,tv_dst,val) do { \
5452 		duk_hthread *duk__thr = (thr); \
5453 		duk_tval *duk__dst = (tv_dst); \
5454 		duk_uint32_t duk__val = (duk_uint32_t) (val); \
5455 		DUK_UNREF(duk__thr); \
5456 		DUK_TVAL_DECREF_NORZ(thr, duk__dst); \
5457 		DUK_TVAL_SET_U32(duk__dst, duk__val); \
5458 	} while (0)
5459 
5460 /*
5461  *  Prototypes
5462  */
5463 
5464 #if defined(DUK_USE_REFERENCE_COUNTING)
5465 #if defined(DUK_USE_FINALIZER_SUPPORT)
5466 DUK_INTERNAL_DECL void duk_refzero_check_slow(duk_hthread *thr);
5467 DUK_INTERNAL_DECL void duk_refzero_check_fast(duk_hthread *thr);
5468 #endif
5469 DUK_INTERNAL_DECL void duk_heaphdr_refcount_finalize_norz(duk_heap *heap, duk_heaphdr *hdr);
5470 DUK_INTERNAL_DECL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject *h);
5471 #if 0  /* Not needed: fast path handles inline; slow path uses duk_heaphdr_decref() which is needed anyway. */
5472 DUK_INTERNAL_DECL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h);
5473 DUK_INTERNAL_DECL void duk_hstring_decref_norz(duk_hthread *thr, duk_hstring *h);
5474 DUK_INTERNAL_DECL void duk_hbuffer_decref(duk_hthread *thr, duk_hbuffer *h);
5475 DUK_INTERNAL_DECL void duk_hbuffer_decref_norz(duk_hthread *thr, duk_hbuffer *h);
5476 DUK_INTERNAL_DECL void duk_hobject_decref(duk_hthread *thr, duk_hobject *h);
5477 DUK_INTERNAL_DECL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h);
5478 #endif
5479 DUK_INTERNAL_DECL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h);
5480 DUK_INTERNAL_DECL void duk_heaphdr_refzero_norz(duk_hthread *thr, duk_heaphdr *h);
5481 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
5482 DUK_INTERNAL_DECL void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h);  /* no 'norz' variant */
5483 DUK_INTERNAL_DECL void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h);  /* no 'norz' variant */
5484 DUK_INTERNAL_DECL void duk_hobject_refzero(duk_hthread *thr, duk_hobject *h);
5485 DUK_INTERNAL_DECL void duk_hobject_refzero_norz(duk_hthread *thr, duk_hobject *h);
5486 #else
5487 DUK_INTERNAL_DECL void duk_tval_incref(duk_tval *tv);
5488 DUK_INTERNAL_DECL void duk_tval_decref(duk_hthread *thr, duk_tval *tv);
5489 DUK_INTERNAL_DECL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv);
5490 DUK_INTERNAL_DECL void duk_heaphdr_incref(duk_heaphdr *h);
5491 DUK_INTERNAL_DECL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h);
5492 DUK_INTERNAL_DECL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h);
5493 #endif
5494 #else  /* DUK_USE_REFERENCE_COUNTING */
5495 /* no refcounting */
5496 #endif  /* DUK_USE_REFERENCE_COUNTING */
5497 
5498 #endif  /* DUK_REFCOUNT_H_INCLUDED */
5499 /* #include duk_api_internal.h */
5500 #line 1 "duk_api_internal.h"
5501 /*
5502  *  Internal API calls which have (stack and other) semantics similar
5503  *  to the public API.
5504  */
5505 
5506 #if !defined(DUK_API_INTERNAL_H_INCLUDED)
5507 #define DUK_API_INTERNAL_H_INCLUDED
5508 
5509 /* Inline macro helpers. */
5510 #if defined(DUK_USE_PREFER_SIZE)
5511 #define DUK_INLINE_PERF
5512 #define DUK_ALWAYS_INLINE_PERF
5513 #define DUK_NOINLINE_PERF
5514 #else
5515 #define DUK_INLINE_PERF DUK_INLINE
5516 #define DUK_ALWAYS_INLINE_PERF DUK_ALWAYS_INLINE
5517 #define DUK_NOINLINE_PERF DUK_NOINLINE
5518 #endif
5519 
5520 /* Inline macro helpers, for bytecode executor. */
5521 #if defined(DUK_USE_EXEC_PREFER_SIZE)
5522 #define DUK_EXEC_INLINE_PERF
5523 #define DUK_EXEC_ALWAYS_INLINE_PERF
5524 #define DUK_EXEC_NOINLINE_PERF
5525 #else
5526 #define DUK_EXEC_INLINE_PERF DUK_INLINE
5527 #define DUK_EXEC_ALWAYS_INLINE_PERF DUK_ALWAYS_INLINE
5528 #define DUK_EXEC_NOINLINE_PERF DUK_NOINLINE
5529 #endif
5530 
5531 /* duk_push_sprintf constants */
5532 #define DUK_PUSH_SPRINTF_INITIAL_SIZE  256L
5533 #define DUK_PUSH_SPRINTF_SANITY_LIMIT  (1L * 1024L * 1024L * 1024L)
5534 
5535 /* Flag ORed to err_code to indicate __FILE__ / __LINE__ is not
5536  * blamed as source of error for error fileName / lineNumber.
5537  */
5538 #define DUK_ERRCODE_FLAG_NOBLAME_FILELINE  (1L << 24)
5539 
5540 /* Current convention is to use duk_size_t for value stack sizes and global indices,
5541  * and duk_idx_t for local frame indices.
5542  */
5543 DUK_INTERNAL_DECL void duk_valstack_grow_check_throw(duk_hthread *thr, duk_size_t min_bytes);
5544 DUK_INTERNAL_DECL duk_bool_t duk_valstack_grow_check_nothrow(duk_hthread *thr, duk_size_t min_bytes);
5545 DUK_INTERNAL_DECL void duk_valstack_shrink_check_nothrow(duk_hthread *thr, duk_bool_t snug);
5546 
5547 DUK_INTERNAL_DECL void duk_copy_tvals_incref(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_size_t count);
5548 
5549 DUK_INTERNAL_DECL duk_tval *duk_reserve_gap(duk_hthread *thr, duk_idx_t idx_base, duk_idx_t count);
5550 
5551 DUK_INTERNAL_DECL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx);
5552 DUK_INTERNAL_DECL void duk_set_top_and_wipe(duk_hthread *thr, duk_idx_t top, duk_idx_t idx_wipe_start);
5553 
5554 DUK_INTERNAL_DECL void duk_dup_0(duk_hthread *thr);
5555 DUK_INTERNAL_DECL void duk_dup_1(duk_hthread *thr);
5556 DUK_INTERNAL_DECL void duk_dup_2(duk_hthread *thr);
5557 /* duk_dup_m1() would be same as duk_dup_top() */
5558 DUK_INTERNAL_DECL void duk_dup_m2(duk_hthread *thr);
5559 DUK_INTERNAL_DECL void duk_dup_m3(duk_hthread *thr);
5560 DUK_INTERNAL_DECL void duk_dup_m4(duk_hthread *thr);
5561 
5562 DUK_INTERNAL_DECL void duk_remove_unsafe(duk_hthread *thr, duk_idx_t idx);
5563 DUK_INTERNAL_DECL void duk_remove_m2(duk_hthread *thr);
5564 DUK_INTERNAL_DECL void duk_remove_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);
5565 DUK_INTERNAL_DECL void duk_remove_n_unsafe(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);
5566 
5567 DUK_INTERNAL_DECL duk_int_t duk_get_type_tval(duk_tval *tv);
5568 DUK_INTERNAL_DECL duk_uint_t duk_get_type_mask_tval(duk_tval *tv);
5569 
5570 #if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
5571 DUK_INTERNAL_DECL const char *duk_get_type_name(duk_hthread *thr, duk_idx_t idx);
5572 #endif
5573 DUK_INTERNAL_DECL duk_small_uint_t duk_get_class_number(duk_hthread *thr, duk_idx_t idx);
5574 
5575 DUK_INTERNAL_DECL duk_tval *duk_get_tval(duk_hthread *thr, duk_idx_t idx);
5576 DUK_INTERNAL_DECL duk_tval *duk_get_tval_or_unused(duk_hthread *thr, duk_idx_t idx);
5577 DUK_INTERNAL_DECL duk_tval *duk_require_tval(duk_hthread *thr, duk_idx_t idx);
5578 DUK_INTERNAL_DECL void duk_push_tval(duk_hthread *thr, duk_tval *tv);
5579 
5580 /* Push the current 'this' binding; throw TypeError if binding is not object
5581  * coercible (CheckObjectCoercible).
5582  */
5583 DUK_INTERNAL_DECL void duk_push_this_check_object_coercible(duk_hthread *thr);
5584 
5585 /* duk_push_this() + CheckObjectCoercible() + duk_to_object() */
5586 DUK_INTERNAL_DECL duk_hobject *duk_push_this_coercible_to_object(duk_hthread *thr);
5587 
5588 /* duk_push_this() + CheckObjectCoercible() + duk_to_string() */
5589 DUK_INTERNAL_DECL duk_hstring *duk_push_this_coercible_to_string(duk_hthread *thr);
5590 
5591 DUK_INTERNAL_DECL duk_hstring *duk_push_uint_to_hstring(duk_hthread *thr, duk_uint_t i);
5592 
5593 /* Get a borrowed duk_tval pointer to the current 'this' binding.  Caller must
5594  * make sure there's an active callstack entry.  Note that the returned pointer
5595  * is unstable with regards to side effects.
5596  */
5597 DUK_INTERNAL_DECL duk_tval *duk_get_borrowed_this_tval(duk_hthread *thr);
5598 
5599 /* XXX: add fastint support? */
5600 #define duk_push_u64(thr,val) \
5601 	duk_push_number((thr), (duk_double_t) (val))
5602 #define duk_push_i64(thr,val) \
5603 	duk_push_number((thr), (duk_double_t) (val))
5604 
5605 /* duk_push_(u)int() is guaranteed to support at least (un)signed 32-bit range */
5606 #define duk_push_u32(thr,val) \
5607 	duk_push_uint((thr), (duk_uint_t) (val))
5608 #define duk_push_i32(thr,val) \
5609 	duk_push_int((thr), (duk_int_t) (val))
5610 
5611 /* sometimes stack and array indices need to go on the stack */
5612 #define duk_push_idx(thr,val) \
5613 	duk_push_int((thr), (duk_int_t) (val))
5614 #define duk_push_uarridx(thr,val) \
5615 	duk_push_uint((thr), (duk_uint_t) (val))
5616 #define duk_push_size_t(thr,val) \
5617 	duk_push_uint((thr), (duk_uint_t) (val))  /* XXX: assumed to fit for now */
5618 
5619 DUK_INTERNAL_DECL duk_bool_t duk_is_string_notsymbol(duk_hthread *thr, duk_idx_t idx);
5620 
5621 DUK_INTERNAL_DECL duk_bool_t duk_is_callable_tval(duk_hthread *thr, duk_tval *tv);
5622 
5623 DUK_INTERNAL_DECL duk_bool_t duk_is_bare_object(duk_hthread *thr, duk_idx_t idx);
5624 
5625 DUK_INTERNAL_DECL duk_hstring *duk_get_hstring(duk_hthread *thr, duk_idx_t idx);
5626 DUK_INTERNAL_DECL duk_hstring *duk_get_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx);
5627 DUK_INTERNAL_DECL const char *duk_get_string_notsymbol(duk_hthread *thr, duk_idx_t idx);
5628 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject(duk_hthread *thr, duk_idx_t idx);
5629 DUK_INTERNAL_DECL duk_hbuffer *duk_get_hbuffer(duk_hthread *thr, duk_idx_t idx);
5630 DUK_INTERNAL_DECL duk_hthread *duk_get_hthread(duk_hthread *thr, duk_idx_t idx);
5631 DUK_INTERNAL_DECL duk_hcompfunc *duk_get_hcompfunc(duk_hthread *thr, duk_idx_t idx);
5632 DUK_INTERNAL_DECL duk_hnatfunc *duk_get_hnatfunc(duk_hthread *thr, duk_idx_t idx);
5633 
5634 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);
5635 
5636 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum);
5637 
5638 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
5639 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
5640 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_accept_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
5641 #define duk_require_hobject_promote_lfunc(thr,idx) \
5642 	duk_require_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC)
5643 #define duk_get_hobject_promote_lfunc(thr,idx) \
5644 	duk_get_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC)
5645 
5646 #if 0  /*unused*/
5647 DUK_INTERNAL_DECL void *duk_get_voidptr(duk_hthread *thr, duk_idx_t idx);
5648 #endif
5649 
5650 DUK_INTERNAL_DECL duk_hstring *duk_known_hstring(duk_hthread *thr, duk_idx_t idx);
5651 DUK_INTERNAL_DECL duk_hobject *duk_known_hobject(duk_hthread *thr, duk_idx_t idx);
5652 DUK_INTERNAL_DECL duk_hbuffer *duk_known_hbuffer(duk_hthread *thr, duk_idx_t idx);
5653 DUK_INTERNAL_DECL duk_hcompfunc *duk_known_hcompfunc(duk_hthread *thr, duk_idx_t idx);
5654 DUK_INTERNAL_DECL duk_hnatfunc *duk_known_hnatfunc(duk_hthread *thr, duk_idx_t idx);
5655 
5656 DUK_INTERNAL_DECL duk_double_t duk_to_number_tval(duk_hthread *thr, duk_tval *tv);
5657 
5658 DUK_INTERNAL_DECL duk_hstring *duk_to_hstring(duk_hthread *thr, duk_idx_t idx);
5659 DUK_INTERNAL_DECL duk_hstring *duk_to_hstring_m1(duk_hthread *thr);
5660 DUK_INTERNAL_DECL duk_hstring *duk_to_hstring_acceptsymbol(duk_hthread *thr, duk_idx_t idx);
5661 
5662 DUK_INTERNAL_DECL duk_hobject *duk_to_hobject(duk_hthread *thr, duk_idx_t idx);
5663 
5664 DUK_INTERNAL_DECL duk_double_t duk_to_number_m1(duk_hthread *thr);
5665 DUK_INTERNAL_DECL duk_double_t duk_to_number_m2(duk_hthread *thr);
5666 
5667 DUK_INTERNAL_DECL duk_bool_t duk_to_boolean_top_pop(duk_hthread *thr);
5668 
5669 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* only needed by debugger for now */
5670 DUK_INTERNAL_DECL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx);
5671 #endif
5672 DUK_INTERNAL_DECL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects);
5673 
5674 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 */
5675 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);
5676 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);
5677 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
5678 DUK_INTERNAL_DECL duk_uint8_t duk_to_uint8clamped(duk_hthread *thr, duk_idx_t idx);
5679 #endif
5680 DUK_INTERNAL_DECL duk_hstring *duk_to_property_key_hstring(duk_hthread *thr, duk_idx_t idx);
5681 
5682 DUK_INTERNAL_DECL duk_hstring *duk_require_hstring(duk_hthread *thr, duk_idx_t idx);
5683 DUK_INTERNAL_DECL duk_hstring *duk_require_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx);
5684 DUK_INTERNAL_DECL const char *duk_require_lstring_notsymbol(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len);
5685 DUK_INTERNAL_DECL const char *duk_require_string_notsymbol(duk_hthread *thr, duk_idx_t idx);
5686 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject(duk_hthread *thr, duk_idx_t idx);
5687 DUK_INTERNAL_DECL duk_hbuffer *duk_require_hbuffer(duk_hthread *thr, duk_idx_t idx);
5688 DUK_INTERNAL_DECL duk_hthread *duk_require_hthread(duk_hthread *thr, duk_idx_t idx);
5689 DUK_INTERNAL_DECL duk_hcompfunc *duk_require_hcompfunc(duk_hthread *thr, duk_idx_t idx);
5690 DUK_INTERNAL_DECL duk_hnatfunc *duk_require_hnatfunc(duk_hthread *thr, duk_idx_t idx);
5691 
5692 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum);
5693 
5694 DUK_INTERNAL_DECL void duk_push_hstring(duk_hthread *thr, duk_hstring *h);
5695 DUK_INTERNAL_DECL void duk_push_hstring_stridx(duk_hthread *thr, duk_small_uint_t stridx);
5696 DUK_INTERNAL_DECL void duk_push_hstring_empty(duk_hthread *thr);
5697 DUK_INTERNAL_DECL void duk_push_hobject(duk_hthread *thr, duk_hobject *h);
5698 DUK_INTERNAL_DECL void duk_push_hbuffer(duk_hthread *thr, duk_hbuffer *h);
5699 #define duk_push_hthread(thr,h) \
5700 	duk_push_hobject((thr), (duk_hobject *) (h))
5701 #define duk_push_hnatfunc(thr,h) \
5702 	duk_push_hobject((thr), (duk_hobject *) (h))
5703 DUK_INTERNAL_DECL void duk_push_hobject_bidx(duk_hthread *thr, duk_small_int_t builtin_idx);
5704 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);
5705 DUK_INTERNAL_DECL duk_hobject *duk_push_object_helper_proto(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_hobject *proto);
5706 DUK_INTERNAL_DECL duk_hcompfunc *duk_push_hcompfunc(duk_hthread *thr);
5707 DUK_INTERNAL_DECL duk_hboundfunc *duk_push_hboundfunc(duk_hthread *thr);
5708 DUK_INTERNAL_DECL void duk_push_c_function_builtin(duk_hthread *thr, duk_c_function func, duk_int_t nargs);
5709 DUK_INTERNAL_DECL void duk_push_c_function_builtin_noconstruct(duk_hthread *thr, duk_c_function func, duk_int_t nargs);
5710 
5711 /* XXX: duk_push_harray() and duk_push_hcompfunc() are inconsistent with
5712  * duk_push_hobject() etc which don't create a new value.
5713  */
5714 DUK_INTERNAL_DECL duk_harray *duk_push_harray(duk_hthread *thr);
5715 DUK_INTERNAL_DECL duk_harray *duk_push_harray_with_size(duk_hthread *thr, duk_uint32_t size);
5716 DUK_INTERNAL_DECL duk_tval *duk_push_harray_with_size_outptr(duk_hthread *thr, duk_uint32_t size);
5717 
5718 DUK_INTERNAL_DECL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, duk_size_t sz);
5719 DUK_INTERNAL_DECL void duk_push_lightfunc_name_raw(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags);
5720 DUK_INTERNAL_DECL void duk_push_lightfunc_name(duk_hthread *thr, duk_tval *tv);
5721 DUK_INTERNAL_DECL void duk_push_lightfunc_tostring(duk_hthread *thr, duk_tval *tv);
5722 #if 0  /* not used yet */
5723 DUK_INTERNAL_DECL void duk_push_hnatfunc_name(duk_hthread *thr, duk_hnatfunc *h);
5724 #endif
5725 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
5726 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);
5727 #endif
5728 
5729 DUK_INTERNAL_DECL void *duk_push_fixed_buffer_nozero(duk_hthread *thr, duk_size_t len);
5730 DUK_INTERNAL_DECL void *duk_push_fixed_buffer_zero(duk_hthread *thr, duk_size_t len);
5731 
5732 DUK_INTERNAL_DECL const char *duk_push_string_readable(duk_hthread *thr, duk_idx_t idx);
5733 DUK_INTERNAL_DECL const char *duk_push_string_tval_readable(duk_hthread *thr, duk_tval *tv);
5734 DUK_INTERNAL_DECL const char *duk_push_string_tval_readable_error(duk_hthread *thr, duk_tval *tv);
5735 
5736 /* The duk_xxx_prop_stridx_short() variants expect their arguments to be short
5737  * enough to be packed into a single 32-bit integer argument.  Argument limits
5738  * vary per call; typically 16 bits are assigned to the signed value stack index
5739  * and the stridx.  In practice these work well for footprint with constant
5740  * arguments and such call sites are also easiest to verify to be correct.
5741  */
5742 
5743 DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [val] */
5744 DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5745 #define duk_get_prop_stridx_short(thr,obj_idx,stridx) \
5746 	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
5747 	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
5748 	 duk_get_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5749 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);  /* [] -> [] */
5750 
5751 DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop(duk_hthread *thr, duk_idx_t obj_idx);
5752 DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);
5753 DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5754 #define duk_xget_owndataprop_stridx_short(thr,obj_idx,stridx) \
5755 	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
5756 	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
5757 	 duk_xget_owndataprop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5758 
5759 DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [val] -> [] */
5760 DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5761 #define duk_put_prop_stridx_short(thr,obj_idx,stridx) \
5762 	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
5763 	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
5764 	 duk_put_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5765 
5766 DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [] */
5767 #if 0  /* Too few call sites to be useful. */
5768 DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5769 #define duk_del_prop_stridx_short(thr,obj_idx,stridx) \
5770 	(DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \
5771 	 DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \
5772 	 duk_del_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5773 #endif
5774 #define duk_del_prop_stridx_short(thr,obj_idx,stridx) \
5775 	duk_del_prop_stridx((thr), (obj_idx), (stridx))
5776 
5777 DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [] */
5778 #if 0  /* Too few call sites to be useful. */
5779 DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5780 #define duk_has_prop_stridx_short(thr,obj_idx,stridx) \
5781 	(DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \
5782 	 DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \
5783 	 duk_has_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5784 #endif
5785 #define duk_has_prop_stridx_short(thr,obj_idx,stridx) \
5786 	duk_has_prop_stridx((thr), (obj_idx), (stridx))
5787 
5788 DUK_INTERNAL_DECL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t desc_flags);  /* [key val] -> [] */
5789 
5790 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] -> [] */
5791 
5792 /* XXX: Because stridx and desc_flags have a limited range, this call could
5793  * always pack stridx and desc_flags into a single argument.
5794  */
5795 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] -> [] */
5796 DUK_INTERNAL_DECL void duk_xdef_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5797 #define duk_xdef_prop_stridx_short(thr,obj_idx,stridx,desc_flags) \
5798 	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x80L && (duk_int_t) (obj_idx) <= 0x7fL), \
5799 	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
5800 	 DUK_ASSERT_EXPR((duk_int_t) (desc_flags) >= 0 && (duk_int_t) (desc_flags) <= 0xffL), \
5801 	 duk_xdef_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 24) + (((duk_uint_t) (stridx)) << 8) + (duk_uint_t) (desc_flags)))
5802 
5803 #define duk_xdef_prop_wec(thr,obj_idx) \
5804 	duk_xdef_prop((thr), (obj_idx), DUK_PROPDESC_FLAGS_WEC)
5805 #define duk_xdef_prop_index_wec(thr,obj_idx,arr_idx) \
5806 	duk_xdef_prop_index((thr), (obj_idx), (arr_idx), DUK_PROPDESC_FLAGS_WEC)
5807 #define duk_xdef_prop_stridx_wec(thr,obj_idx,stridx) \
5808 	duk_xdef_prop_stridx((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)
5809 #define duk_xdef_prop_stridx_short_wec(thr,obj_idx,stridx) \
5810 	duk_xdef_prop_stridx_short((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)
5811 
5812 #if 0  /*unused*/
5813 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);  /* [] -> [] */
5814 #endif
5815 
5816 DUK_INTERNAL_DECL void duk_xdef_prop_stridx_thrower(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);  /* [] -> [] */
5817 
5818 DUK_INTERNAL_DECL duk_bool_t duk_get_method_stridx(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t stridx);
5819 
5820 DUK_INTERNAL_DECL void duk_pack(duk_hthread *thr, duk_idx_t count);
5821 DUK_INTERNAL_DECL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx);
5822 #if 0
5823 DUK_INTERNAL_DECL void duk_unpack(duk_hthread *thr);
5824 #endif
5825 
5826 DUK_INTERNAL_DECL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstring *h);
5827 
5828 DUK_INTERNAL_DECL void duk_resolve_nonbound_function(duk_hthread *thr);
5829 
5830 DUK_INTERNAL_DECL duk_idx_t duk_get_top_require_min(duk_hthread *thr, duk_idx_t min_top);
5831 DUK_INTERNAL_DECL duk_idx_t duk_get_top_index_unsafe(duk_hthread *thr);
5832 
5833 DUK_INTERNAL_DECL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count);
5834 DUK_INTERNAL_DECL void duk_pop_unsafe(duk_hthread *thr);
5835 DUK_INTERNAL_DECL void duk_pop_2_unsafe(duk_hthread *thr);
5836 DUK_INTERNAL_DECL void duk_pop_3_unsafe(duk_hthread *thr);
5837 DUK_INTERNAL_DECL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count);
5838 DUK_INTERNAL_DECL void duk_pop_nodecref_unsafe(duk_hthread *thr);
5839 DUK_INTERNAL_DECL void duk_pop_2_nodecref_unsafe(duk_hthread *thr);
5840 DUK_INTERNAL_DECL void duk_pop_3_nodecref_unsafe(duk_hthread *thr);
5841 DUK_INTERNAL_DECL void duk_pop_undefined(duk_hthread *thr);
5842 
5843 DUK_INTERNAL_DECL void duk_compact_m1(duk_hthread *thr);
5844 
5845 DUK_INTERNAL_DECL void duk_seal_freeze_raw(duk_hthread *thr, duk_idx_t obj_idx, duk_bool_t is_freeze);
5846 
5847 DUK_INTERNAL_DECL void duk_insert_undefined(duk_hthread *thr, duk_idx_t idx);
5848 DUK_INTERNAL_DECL void duk_insert_undefined_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);
5849 
5850 DUK_INTERNAL_DECL void duk_concat_2(duk_hthread *thr);
5851 
5852 DUK_INTERNAL_DECL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags);
5853 
5854 #if defined(DUK_USE_SYMBOL_BUILTIN)
5855 DUK_INTERNAL_DECL void duk_to_primitive_ordinary(duk_hthread *thr, duk_idx_t idx, duk_int_t hint);
5856 #endif
5857 
5858 DUK_INTERNAL_DECL void duk_clear_prototype(duk_hthread *thr, duk_idx_t idx);
5859 
5860 /* Raw internal valstack access macros: access is unsafe so call site
5861  * must have a guarantee that the index is valid.  When that is the case,
5862  * using these macro results in faster and smaller code than duk_get_tval().
5863  * Both 'ctx' and 'idx' are evaluted multiple times, but only for asserts.
5864  */
5865 #define DUK_ASSERT_VALID_NEGIDX(thr,idx) \
5866 	(DUK_ASSERT_EXPR((duk_int_t) (idx) < 0), DUK_ASSERT_EXPR(duk_is_valid_index((thr), (idx))))
5867 #define DUK_ASSERT_VALID_POSIDX(thr,idx) \
5868 	(DUK_ASSERT_EXPR((duk_int_t) (idx) >= 0), DUK_ASSERT_EXPR(duk_is_valid_index((thr), (idx))))
5869 #define DUK_GET_TVAL_NEGIDX(thr,idx) \
5870 	(DUK_ASSERT_VALID_NEGIDX((thr),(idx)), ((duk_hthread *) (thr))->valstack_top + (idx))
5871 #define DUK_GET_TVAL_POSIDX(thr,idx) \
5872 	(DUK_ASSERT_VALID_POSIDX((thr),(idx)), ((duk_hthread *) (thr))->valstack_bottom + (idx))
5873 #define DUK_GET_HOBJECT_NEGIDX(thr,idx) \
5874 	(DUK_ASSERT_VALID_NEGIDX((thr),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_top + (idx)))
5875 #define DUK_GET_HOBJECT_POSIDX(thr,idx) \
5876 	(DUK_ASSERT_VALID_POSIDX((thr),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_bottom + (idx)))
5877 
5878 #define DUK_GET_THIS_TVAL_PTR(thr) \
5879 	(DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \
5880 	 (thr)->valstack_bottom - 1)
5881 
5882 DUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr);
5883 DUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time_nofrac(duk_hthread *thr);
5884 DUK_INTERNAL_DECL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr);
5885 
5886 #endif  /* DUK_API_INTERNAL_H_INCLUDED */
5887 /* #include duk_hstring.h */
5888 #line 1 "duk_hstring.h"
5889 /*
5890  *  Heap string representation.
5891  *
5892  *  Strings are byte sequences ordinarily stored in extended UTF-8 format,
5893  *  allowing values larger than the official UTF-8 range (used internally)
5894  *  and also allowing UTF-8 encoding of surrogate pairs (CESU-8 format).
5895  *  Strings may also be invalid UTF-8 altogether which is the case e.g. with
5896  *  strings used as internal property names and raw buffers converted to
5897  *  strings.  In such cases the 'clen' field contains an inaccurate value.
5898  *
5899  *  ECMAScript requires support for 32-bit long strings.  However, since each
5900  *  16-bit codepoint can take 3 bytes in CESU-8, this representation can only
5901  *  support about 1.4G codepoint long strings in extreme cases.  This is not
5902  *  really a practical issue.
5903  */
5904 
5905 #if !defined(DUK_HSTRING_H_INCLUDED)
5906 #define DUK_HSTRING_H_INCLUDED
5907 
5908 /* Impose a maximum string length for now.  Restricted artificially to
5909  * ensure adding a heap header length won't overflow size_t.  The limit
5910  * should be synchronized with DUK_HBUFFER_MAX_BYTELEN.
5911  *
5912  * E5.1 makes provisions to support strings longer than 4G characters.
5913  * This limit should be eliminated on 64-bit platforms (and increased
5914  * closer to maximum support on 32-bit platforms).
5915  */
5916 
5917 #if defined(DUK_USE_STRLEN16)
5918 #define DUK_HSTRING_MAX_BYTELEN                     (0x0000ffffUL)
5919 #else
5920 #define DUK_HSTRING_MAX_BYTELEN                     (0x7fffffffUL)
5921 #endif
5922 
5923 /* XXX: could add flags for "is valid CESU-8" (ECMAScript compatible strings),
5924  * "is valid UTF-8", "is valid extended UTF-8" (internal strings are not,
5925  * regexp bytecode is), and "contains non-BMP characters".  These are not
5926  * needed right now.
5927  */
5928 
5929 /* With lowmem builds the high 16 bits of duk_heaphdr are used for other
5930  * purposes, so this leaves 7 duk_heaphdr flags and 9 duk_hstring flags.
5931  */
5932 #define DUK_HSTRING_FLAG_ASCII                      DUK_HEAPHDR_USER_FLAG(0)  /* string is ASCII, clen == blen */
5933 #define DUK_HSTRING_FLAG_ARRIDX                     DUK_HEAPHDR_USER_FLAG(1)  /* string is a valid array index */
5934 #define DUK_HSTRING_FLAG_SYMBOL                     DUK_HEAPHDR_USER_FLAG(2)  /* string is a symbol (invalid utf-8) */
5935 #define DUK_HSTRING_FLAG_HIDDEN                     DUK_HEAPHDR_USER_FLAG(3)  /* string is a hidden symbol (implies symbol, Duktape 1.x internal string) */
5936 #define DUK_HSTRING_FLAG_RESERVED_WORD              DUK_HEAPHDR_USER_FLAG(4)  /* string is a reserved word (non-strict) */
5937 #define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD       DUK_HEAPHDR_USER_FLAG(5)  /* string is a reserved word (strict) */
5938 #define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS          DUK_HEAPHDR_USER_FLAG(6)  /* string is 'eval' or 'arguments' */
5939 #define DUK_HSTRING_FLAG_EXTDATA                    DUK_HEAPHDR_USER_FLAG(7)  /* string data is external (duk_hstring_external) */
5940 #define DUK_HSTRING_FLAG_PINNED_LITERAL             DUK_HEAPHDR_USER_FLAG(8)  /* string is a literal, and pinned */
5941 
5942 #define DUK_HSTRING_HAS_ASCII(x)                    DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
5943 #define DUK_HSTRING_HAS_ARRIDX(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
5944 #define DUK_HSTRING_HAS_SYMBOL(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
5945 #define DUK_HSTRING_HAS_HIDDEN(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
5946 #define DUK_HSTRING_HAS_RESERVED_WORD(x)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
5947 #define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
5948 #define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
5949 #define DUK_HSTRING_HAS_EXTDATA(x)                  DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
5950 #define DUK_HSTRING_HAS_PINNED_LITERAL(x)           DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
5951 
5952 #define DUK_HSTRING_SET_ASCII(x)                    DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
5953 #define DUK_HSTRING_SET_ARRIDX(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
5954 #define DUK_HSTRING_SET_SYMBOL(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
5955 #define DUK_HSTRING_SET_HIDDEN(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
5956 #define DUK_HSTRING_SET_RESERVED_WORD(x)            DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
5957 #define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x)     DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
5958 #define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x)        DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
5959 #define DUK_HSTRING_SET_EXTDATA(x)                  DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
5960 #define DUK_HSTRING_SET_PINNED_LITERAL(x)           DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
5961 
5962 #define DUK_HSTRING_CLEAR_ASCII(x)                  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
5963 #define DUK_HSTRING_CLEAR_ARRIDX(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
5964 #define DUK_HSTRING_CLEAR_SYMBOL(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
5965 #define DUK_HSTRING_CLEAR_HIDDEN(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
5966 #define DUK_HSTRING_CLEAR_RESERVED_WORD(x)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
5967 #define DUK_HSTRING_CLEAR_STRICT_RESERVED_WORD(x)   DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
5968 #define DUK_HSTRING_CLEAR_EVAL_OR_ARGUMENTS(x)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
5969 #define DUK_HSTRING_CLEAR_EXTDATA(x)                DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
5970 #define DUK_HSTRING_CLEAR_PINNED_LITERAL(x)         DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
5971 
5972 #if 0  /* Slightly smaller code without explicit flag, but explicit flag
5973         * is very useful when 'clen' is dropped.
5974         */
5975 #define DUK_HSTRING_IS_ASCII(x)                     (DUK_HSTRING_GET_BYTELEN((x)) == DUK_HSTRING_GET_CHARLEN((x)))
5976 #endif
5977 #define DUK_HSTRING_IS_ASCII(x)                     DUK_HSTRING_HAS_ASCII((x))  /* lazily set! */
5978 #define DUK_HSTRING_IS_EMPTY(x)                     (DUK_HSTRING_GET_BYTELEN((x)) == 0)
5979 
5980 #if defined(DUK_USE_STRHASH16)
5981 #define DUK_HSTRING_GET_HASH(x)                     ((x)->hdr.h_flags >> 16)
5982 #define DUK_HSTRING_SET_HASH(x,v) do { \
5983 		(x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | ((v) << 16); \
5984 	} while (0)
5985 #else
5986 #define DUK_HSTRING_GET_HASH(x)                     ((x)->hash)
5987 #define DUK_HSTRING_SET_HASH(x,v) do { \
5988 		(x)->hash = (v); \
5989 	} while (0)
5990 #endif
5991 
5992 #if defined(DUK_USE_STRLEN16)
5993 #define DUK_HSTRING_GET_BYTELEN(x)                  ((x)->hdr.h_strextra16)
5994 #define DUK_HSTRING_SET_BYTELEN(x,v) do { \
5995 		(x)->hdr.h_strextra16 = (v); \
5996 	} while (0)
5997 #if defined(DUK_USE_HSTRING_CLEN)
5998 #define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))
5999 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
6000 		(x)->clen16 = (v); \
6001 	} while (0)
6002 #else
6003 #define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))
6004 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
6005 		DUK_ASSERT(0);  /* should never be called */ \
6006 	} while (0)
6007 #endif
6008 #else
6009 #define DUK_HSTRING_GET_BYTELEN(x)                  ((x)->blen)
6010 #define DUK_HSTRING_SET_BYTELEN(x,v) do { \
6011 		(x)->blen = (v); \
6012 	} while (0)
6013 #define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))
6014 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
6015 		(x)->clen = (v); \
6016 	} while (0)
6017 #endif
6018 
6019 #if defined(DUK_USE_HSTRING_EXTDATA)
6020 #define DUK_HSTRING_GET_EXTDATA(x) \
6021 	((x)->extdata)
6022 #define DUK_HSTRING_GET_DATA(x) \
6023 	(DUK_HSTRING_HAS_EXTDATA((x)) ? \
6024 		DUK_HSTRING_GET_EXTDATA((const duk_hstring_external *) (x)) : ((const duk_uint8_t *) ((x) + 1)))
6025 #else
6026 #define DUK_HSTRING_GET_DATA(x) \
6027 	((const duk_uint8_t *) ((x) + 1))
6028 #endif
6029 
6030 #define DUK_HSTRING_GET_DATA_END(x) \
6031 	(DUK_HSTRING_GET_DATA((x)) + (x)->blen)
6032 
6033 /* Marker value; in E5 2^32-1 is not a valid array index (2^32-2 is highest
6034  * valid).
6035  */
6036 #define DUK_HSTRING_NO_ARRAY_INDEX  (0xffffffffUL)
6037 
6038 #if defined(DUK_USE_HSTRING_ARRIDX)
6039 #define DUK_HSTRING_GET_ARRIDX_FAST(h)  ((h)->arridx)
6040 #define DUK_HSTRING_GET_ARRIDX_SLOW(h)  ((h)->arridx)
6041 #else
6042 /* Get array index related to string (or return DUK_HSTRING_NO_ARRAY_INDEX);
6043  * avoids helper call if string has no array index value.
6044  */
6045 #define DUK_HSTRING_GET_ARRIDX_FAST(h)  \
6046 	(DUK_HSTRING_HAS_ARRIDX((h)) ? duk_js_to_arrayindex_hstring_fast_known((h)) : DUK_HSTRING_NO_ARRAY_INDEX)
6047 
6048 /* Slower but more compact variant. */
6049 #define DUK_HSTRING_GET_ARRIDX_SLOW(h)  \
6050 	(duk_js_to_arrayindex_hstring_fast((h)))
6051 #endif
6052 
6053 /* XXX: these actually fit into duk_hstring */
6054 #define DUK_SYMBOL_TYPE_HIDDEN 0
6055 #define DUK_SYMBOL_TYPE_GLOBAL 1
6056 #define DUK_SYMBOL_TYPE_LOCAL 2
6057 #define DUK_SYMBOL_TYPE_WELLKNOWN 3
6058 
6059 /* Assertion for duk_hstring validity. */
6060 #if defined(DUK_USE_ASSERTIONS)
6061 DUK_INTERNAL_DECL void duk_hstring_assert_valid(duk_hstring *h);
6062 #define DUK_HSTRING_ASSERT_VALID(h)  do { duk_hstring_assert_valid((h)); } while (0)
6063 #else
6064 #define DUK_HSTRING_ASSERT_VALID(h)  do {} while (0)
6065 #endif
6066 
6067 /*
6068  *  Misc
6069  */
6070 
6071 struct duk_hstring {
6072 	/* Smaller heaphdr than for other objects, because strings are held
6073 	 * in string intern table which requires no link pointers.  Much of
6074 	 * the 32-bit flags field is unused by flags, so we can stuff a 16-bit
6075 	 * field in there.
6076 	 */
6077 	duk_heaphdr_string hdr;
6078 
6079 	/* String hash. */
6080 #if defined(DUK_USE_STRHASH16)
6081 	/* If 16-bit hash is in use, stuff it into duk_heaphdr_string flags. */
6082 #else
6083 	duk_uint32_t hash;
6084 #endif
6085 
6086 	/* Precomputed array index (or DUK_HSTRING_NO_ARRAY_INDEX). */
6087 #if defined(DUK_USE_HSTRING_ARRIDX)
6088 	duk_uarridx_t arridx;
6089 #endif
6090 
6091 	/* Length in bytes (not counting NUL term). */
6092 #if defined(DUK_USE_STRLEN16)
6093 	/* placed in duk_heaphdr_string */
6094 #else
6095 	duk_uint32_t blen;
6096 #endif
6097 
6098 	/* Length in codepoints (must be E5 compatible). */
6099 #if defined(DUK_USE_STRLEN16)
6100 #if defined(DUK_USE_HSTRING_CLEN)
6101 	duk_uint16_t clen16;
6102 #else
6103 	/* computed live */
6104 #endif
6105 #else
6106 	duk_uint32_t clen;
6107 #endif
6108 
6109 	/*
6110 	 *  String data of 'blen+1' bytes follows (+1 for NUL termination
6111 	 *  convenience for C API).  No alignment needs to be guaranteed
6112 	 *  for strings, but fields above should guarantee alignment-by-4
6113 	 *  (but not alignment-by-8).
6114 	 */
6115 };
6116 
6117 /* The external string struct is defined even when the feature is inactive. */
6118 struct duk_hstring_external {
6119 	duk_hstring str;
6120 
6121 	/*
6122 	 *  For an external string, the NUL-terminated string data is stored
6123 	 *  externally.  The user must guarantee that data behind this pointer
6124 	 *  doesn't change while it's used.
6125 	 */
6126 
6127 	const duk_uint8_t *extdata;
6128 };
6129 
6130 /*
6131  *  Prototypes
6132  */
6133 
6134 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);
6135 DUK_INTERNAL_DECL duk_bool_t duk_hstring_equals_ascii_cstring(duk_hstring *h, const char *cstr);
6136 DUK_INTERNAL_DECL duk_size_t duk_hstring_get_charlen(duk_hstring *h);
6137 #if !defined(DUK_USE_HSTRING_LAZY_CLEN)
6138 DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h);
6139 #endif
6140 
6141 #endif  /* DUK_HSTRING_H_INCLUDED */
6142 /* #include duk_hobject.h */
6143 #line 1 "duk_hobject.h"
6144 /*
6145  *  Heap object representation.
6146  *
6147  *  Heap objects are used for ECMAScript objects, arrays, and functions,
6148  *  but also for internal control like declarative and object environment
6149  *  records.  Compiled functions, native functions, and threads are also
6150  *  objects but with an extended C struct.
6151  *
6152  *  Objects provide the required ECMAScript semantics and exotic behaviors
6153  *  especially for property access.
6154  *
6155  *  Properties are stored in three conceptual parts:
6156  *
6157  *    1. A linear 'entry part' contains ordered key-value-attributes triples
6158  *       and is the main method of string properties.
6159  *
6160  *    2. An optional linear 'array part' is used for array objects to store a
6161  *       (dense) range of [0,N[ array indexed entries with default attributes
6162  *       (writable, enumerable, configurable).  If the array part would become
6163  *       sparse or non-default attributes are required, the array part is
6164  *       abandoned and moved to the 'entry part'.
6165  *
6166  *    3. An optional 'hash part' is used to optimize lookups of the entry
6167  *       part; it is used only for objects with sufficiently many properties
6168  *       and can be abandoned without loss of information.
6169  *
6170  *  These three conceptual parts are stored in a single memory allocated area.
6171  *  This minimizes memory allocation overhead but also means that all three
6172  *  parts are resized together, and makes property access a bit complicated.
6173  */
6174 
6175 #if !defined(DUK_HOBJECT_H_INCLUDED)
6176 #define DUK_HOBJECT_H_INCLUDED
6177 
6178 /* Object flags.  Make sure this stays in sync with debugger object
6179  * inspection code.
6180  */
6181 
6182 /* XXX: some flags are object subtype specific (e.g. common to all function
6183  * subtypes, duk_harray, etc) and could be reused for different subtypes.
6184  */
6185 #define DUK_HOBJECT_FLAG_EXTENSIBLE            DUK_HEAPHDR_USER_FLAG(0)   /* object is extensible */
6186 #define DUK_HOBJECT_FLAG_CONSTRUCTABLE         DUK_HEAPHDR_USER_FLAG(1)   /* object is constructable */
6187 #define DUK_HOBJECT_FLAG_CALLABLE              DUK_HEAPHDR_USER_FLAG(2)   /* object is callable */
6188 #define DUK_HOBJECT_FLAG_BOUNDFUNC             DUK_HEAPHDR_USER_FLAG(3)   /* object established using Function.prototype.bind() */
6189 #define DUK_HOBJECT_FLAG_COMPFUNC              DUK_HEAPHDR_USER_FLAG(4)   /* object is a compiled function (duk_hcompfunc) */
6190 #define DUK_HOBJECT_FLAG_NATFUNC               DUK_HEAPHDR_USER_FLAG(5)   /* object is a native function (duk_hnatfunc) */
6191 #define DUK_HOBJECT_FLAG_BUFOBJ                DUK_HEAPHDR_USER_FLAG(6)   /* object is a buffer object (duk_hbufobj) (always exotic) */
6192 #define DUK_HOBJECT_FLAG_FASTREFS              DUK_HEAPHDR_USER_FLAG(7)   /* object has no fields needing DECREF/marking beyond base duk_hobject header */
6193 #define DUK_HOBJECT_FLAG_ARRAY_PART            DUK_HEAPHDR_USER_FLAG(8)   /* object has an array part (a_size may still be 0) */
6194 #define DUK_HOBJECT_FLAG_STRICT                DUK_HEAPHDR_USER_FLAG(9)   /* function: function object is strict */
6195 #define DUK_HOBJECT_FLAG_NOTAIL                DUK_HEAPHDR_USER_FLAG(10)  /* function: function must not be tail called */
6196 #define DUK_HOBJECT_FLAG_NEWENV                DUK_HEAPHDR_USER_FLAG(11)  /* function: create new environment when called (see duk_hcompfunc) */
6197 #define DUK_HOBJECT_FLAG_NAMEBINDING           DUK_HEAPHDR_USER_FLAG(12)  /* function: create binding for func name (function templates only, used for named function expressions) */
6198 #define DUK_HOBJECT_FLAG_CREATEARGS            DUK_HEAPHDR_USER_FLAG(13)  /* function: create an arguments object on function call */
6199 #define DUK_HOBJECT_FLAG_HAVE_FINALIZER        DUK_HEAPHDR_USER_FLAG(14)  /* object has a callable (own) finalizer property */
6200 #define DUK_HOBJECT_FLAG_EXOTIC_ARRAY          DUK_HEAPHDR_USER_FLAG(15)  /* 'Array' object, array length and index exotic behavior */
6201 #define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ      DUK_HEAPHDR_USER_FLAG(16)  /* 'String' object, array index exotic behavior */
6202 #define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS      DUK_HEAPHDR_USER_FLAG(17)  /* 'Arguments' object and has arguments exotic behavior (non-strict callee) */
6203 #define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ       DUK_HEAPHDR_USER_FLAG(18)  /* 'Proxy' object */
6204 #define DUK_HOBJECT_FLAG_SPECIAL_CALL          DUK_HEAPHDR_USER_FLAG(19)  /* special casing in call behavior, for .call(), .apply(), etc. */
6205 
6206 #define DUK_HOBJECT_FLAG_CLASS_BASE            DUK_HEAPHDR_USER_FLAG_NUMBER(20)
6207 #define DUK_HOBJECT_FLAG_CLASS_BITS            5
6208 
6209 #define DUK_HOBJECT_GET_CLASS_NUMBER(h)        \
6210 	DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS)
6211 #define DUK_HOBJECT_SET_CLASS_NUMBER(h,v)      \
6212 	DUK_HEAPHDR_SET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS, (v))
6213 
6214 #define DUK_HOBJECT_GET_CLASS_MASK(h)          \
6215 	(1UL << DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS))
6216 
6217 /* Macro for creating flag initializer from a class number.
6218  * Unsigned type cast is needed to avoid warnings about coercing
6219  * a signed integer to an unsigned one; the largest class values
6220  * have the highest bit (bit 31) set which causes this.
6221  */
6222 #define DUK_HOBJECT_CLASS_AS_FLAGS(v)          (((duk_uint_t) (v)) << DUK_HOBJECT_FLAG_CLASS_BASE)
6223 
6224 /* E5 Section 8.6.2 + custom classes */
6225 #define DUK_HOBJECT_CLASS_NONE                 0
6226 #define DUK_HOBJECT_CLASS_OBJECT               1
6227 #define DUK_HOBJECT_CLASS_ARRAY                2
6228 #define DUK_HOBJECT_CLASS_FUNCTION             3
6229 #define DUK_HOBJECT_CLASS_ARGUMENTS            4
6230 #define DUK_HOBJECT_CLASS_BOOLEAN              5
6231 #define DUK_HOBJECT_CLASS_DATE                 6
6232 #define DUK_HOBJECT_CLASS_ERROR                7
6233 #define DUK_HOBJECT_CLASS_JSON                 8
6234 #define DUK_HOBJECT_CLASS_MATH                 9
6235 #define DUK_HOBJECT_CLASS_NUMBER               10
6236 #define DUK_HOBJECT_CLASS_REGEXP               11
6237 #define DUK_HOBJECT_CLASS_STRING               12
6238 #define DUK_HOBJECT_CLASS_GLOBAL               13
6239 #define DUK_HOBJECT_CLASS_SYMBOL               14
6240 #define DUK_HOBJECT_CLASS_OBJENV               15  /* custom */
6241 #define DUK_HOBJECT_CLASS_DECENV               16  /* custom */
6242 #define DUK_HOBJECT_CLASS_POINTER              17  /* custom */
6243 #define DUK_HOBJECT_CLASS_THREAD               18  /* custom; implies DUK_HOBJECT_IS_THREAD */
6244 #define DUK_HOBJECT_CLASS_BUFOBJ_MIN           19
6245 #define DUK_HOBJECT_CLASS_ARRAYBUFFER          19  /* implies DUK_HOBJECT_IS_BUFOBJ */
6246 #define DUK_HOBJECT_CLASS_DATAVIEW             20
6247 #define DUK_HOBJECT_CLASS_INT8ARRAY            21
6248 #define DUK_HOBJECT_CLASS_UINT8ARRAY           22
6249 #define DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY    23
6250 #define DUK_HOBJECT_CLASS_INT16ARRAY           24
6251 #define DUK_HOBJECT_CLASS_UINT16ARRAY          25
6252 #define DUK_HOBJECT_CLASS_INT32ARRAY           26
6253 #define DUK_HOBJECT_CLASS_UINT32ARRAY          27
6254 #define DUK_HOBJECT_CLASS_FLOAT32ARRAY         28
6255 #define DUK_HOBJECT_CLASS_FLOAT64ARRAY         29
6256 #define DUK_HOBJECT_CLASS_BUFOBJ_MAX           29
6257 #define DUK_HOBJECT_CLASS_MAX                  29
6258 
6259 /* Class masks. */
6260 #define DUK_HOBJECT_CMASK_ALL                  ((1UL << (DUK_HOBJECT_CLASS_MAX + 1)) - 1UL)
6261 #define DUK_HOBJECT_CMASK_NONE                 (1UL << DUK_HOBJECT_CLASS_NONE)
6262 #define DUK_HOBJECT_CMASK_ARGUMENTS            (1UL << DUK_HOBJECT_CLASS_ARGUMENTS)
6263 #define DUK_HOBJECT_CMASK_ARRAY                (1UL << DUK_HOBJECT_CLASS_ARRAY)
6264 #define DUK_HOBJECT_CMASK_BOOLEAN              (1UL << DUK_HOBJECT_CLASS_BOOLEAN)
6265 #define DUK_HOBJECT_CMASK_DATE                 (1UL << DUK_HOBJECT_CLASS_DATE)
6266 #define DUK_HOBJECT_CMASK_ERROR                (1UL << DUK_HOBJECT_CLASS_ERROR)
6267 #define DUK_HOBJECT_CMASK_FUNCTION             (1UL << DUK_HOBJECT_CLASS_FUNCTION)
6268 #define DUK_HOBJECT_CMASK_JSON                 (1UL << DUK_HOBJECT_CLASS_JSON)
6269 #define DUK_HOBJECT_CMASK_MATH                 (1UL << DUK_HOBJECT_CLASS_MATH)
6270 #define DUK_HOBJECT_CMASK_NUMBER               (1UL << DUK_HOBJECT_CLASS_NUMBER)
6271 #define DUK_HOBJECT_CMASK_OBJECT               (1UL << DUK_HOBJECT_CLASS_OBJECT)
6272 #define DUK_HOBJECT_CMASK_REGEXP               (1UL << DUK_HOBJECT_CLASS_REGEXP)
6273 #define DUK_HOBJECT_CMASK_STRING               (1UL << DUK_HOBJECT_CLASS_STRING)
6274 #define DUK_HOBJECT_CMASK_GLOBAL               (1UL << DUK_HOBJECT_CLASS_GLOBAL)
6275 #define DUK_HOBJECT_CMASK_SYMBOL               (1UL << DUK_HOBJECT_CLASS_SYMBOL)
6276 #define DUK_HOBJECT_CMASK_OBJENV               (1UL << DUK_HOBJECT_CLASS_OBJENV)
6277 #define DUK_HOBJECT_CMASK_DECENV               (1UL << DUK_HOBJECT_CLASS_DECENV)
6278 #define DUK_HOBJECT_CMASK_POINTER              (1UL << DUK_HOBJECT_CLASS_POINTER)
6279 #define DUK_HOBJECT_CMASK_ARRAYBUFFER          (1UL << DUK_HOBJECT_CLASS_ARRAYBUFFER)
6280 #define DUK_HOBJECT_CMASK_DATAVIEW             (1UL << DUK_HOBJECT_CLASS_DATAVIEW)
6281 #define DUK_HOBJECT_CMASK_INT8ARRAY            (1UL << DUK_HOBJECT_CLASS_INT8ARRAY)
6282 #define DUK_HOBJECT_CMASK_UINT8ARRAY           (1UL << DUK_HOBJECT_CLASS_UINT8ARRAY)
6283 #define DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY    (1UL << DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY)
6284 #define DUK_HOBJECT_CMASK_INT16ARRAY           (1UL << DUK_HOBJECT_CLASS_INT16ARRAY)
6285 #define DUK_HOBJECT_CMASK_UINT16ARRAY          (1UL << DUK_HOBJECT_CLASS_UINT16ARRAY)
6286 #define DUK_HOBJECT_CMASK_INT32ARRAY           (1UL << DUK_HOBJECT_CLASS_INT32ARRAY)
6287 #define DUK_HOBJECT_CMASK_UINT32ARRAY          (1UL << DUK_HOBJECT_CLASS_UINT32ARRAY)
6288 #define DUK_HOBJECT_CMASK_FLOAT32ARRAY         (1UL << DUK_HOBJECT_CLASS_FLOAT32ARRAY)
6289 #define DUK_HOBJECT_CMASK_FLOAT64ARRAY         (1UL << DUK_HOBJECT_CLASS_FLOAT64ARRAY)
6290 
6291 #define DUK_HOBJECT_CMASK_ALL_BUFOBJS \
6292 	(DUK_HOBJECT_CMASK_ARRAYBUFFER | \
6293 	 DUK_HOBJECT_CMASK_DATAVIEW | \
6294 	 DUK_HOBJECT_CMASK_INT8ARRAY | \
6295 	 DUK_HOBJECT_CMASK_UINT8ARRAY | \
6296 	 DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY | \
6297 	 DUK_HOBJECT_CMASK_INT16ARRAY | \
6298 	 DUK_HOBJECT_CMASK_UINT16ARRAY | \
6299 	 DUK_HOBJECT_CMASK_INT32ARRAY | \
6300 	 DUK_HOBJECT_CMASK_UINT32ARRAY | \
6301 	 DUK_HOBJECT_CMASK_FLOAT32ARRAY | \
6302 	 DUK_HOBJECT_CMASK_FLOAT64ARRAY)
6303 
6304 #define DUK_HOBJECT_IS_OBJENV(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_OBJENV)
6305 #define DUK_HOBJECT_IS_DECENV(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DECENV)
6306 #define DUK_HOBJECT_IS_ENV(h)                  (DUK_HOBJECT_IS_OBJENV((h)) || DUK_HOBJECT_IS_DECENV((h)))
6307 #define DUK_HOBJECT_IS_ARRAY(h)                DUK_HOBJECT_HAS_EXOTIC_ARRAY((h))  /* Rely on class Array <=> exotic Array */
6308 #define DUK_HOBJECT_IS_BOUNDFUNC(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6309 #define DUK_HOBJECT_IS_COMPFUNC(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6310 #define DUK_HOBJECT_IS_NATFUNC(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6311 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6312 #define DUK_HOBJECT_IS_BUFOBJ(h)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6313 #else
6314 #define DUK_HOBJECT_IS_BUFOBJ(h)               0
6315 #endif
6316 #define DUK_HOBJECT_IS_THREAD(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_THREAD)
6317 #if defined(DUK_USE_ES6_PROXY)
6318 #define DUK_HOBJECT_IS_PROXY(h)                DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((h))
6319 #else
6320 #define DUK_HOBJECT_IS_PROXY(h)                0
6321 #endif
6322 
6323 #define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
6324                                                         DUK_HOBJECT_FLAG_COMPFUNC | \
6325                                                         DUK_HOBJECT_FLAG_NATFUNC)
6326 
6327 #define DUK_HOBJECT_IS_FUNCTION(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
6328                                                         DUK_HOBJECT_FLAG_BOUNDFUNC | \
6329                                                         DUK_HOBJECT_FLAG_COMPFUNC | \
6330                                                         DUK_HOBJECT_FLAG_NATFUNC)
6331 
6332 #define DUK_HOBJECT_IS_CALLABLE(h)             DUK_HOBJECT_HAS_CALLABLE((h))
6333 
6334 /* Object has any exotic behavior(s). */
6335 #define DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS      (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
6336                                                 DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS | \
6337                                                 DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
6338                                                 DUK_HOBJECT_FLAG_BUFOBJ | \
6339                                                 DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6340 #define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS)
6341 
6342 /* Object has any virtual properties (not counting Proxy behavior). */
6343 #define DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS     (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
6344                                                 DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
6345                                                 DUK_HOBJECT_FLAG_BUFOBJ)
6346 #define DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(h)  DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS)
6347 
6348 #define DUK_HOBJECT_HAS_EXTENSIBLE(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
6349 #define DUK_HOBJECT_HAS_CONSTRUCTABLE(h)       DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
6350 #define DUK_HOBJECT_HAS_CALLABLE(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
6351 #define DUK_HOBJECT_HAS_BOUNDFUNC(h)           DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6352 #define DUK_HOBJECT_HAS_COMPFUNC(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6353 #define DUK_HOBJECT_HAS_NATFUNC(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6354 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6355 #define DUK_HOBJECT_HAS_BUFOBJ(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6356 #else
6357 #define DUK_HOBJECT_HAS_BUFOBJ(h)              0
6358 #endif
6359 #define DUK_HOBJECT_HAS_FASTREFS(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
6360 #define DUK_HOBJECT_HAS_ARRAY_PART(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
6361 #define DUK_HOBJECT_HAS_STRICT(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
6362 #define DUK_HOBJECT_HAS_NOTAIL(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
6363 #define DUK_HOBJECT_HAS_NEWENV(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
6364 #define DUK_HOBJECT_HAS_NAMEBINDING(h)         DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
6365 #define DUK_HOBJECT_HAS_CREATEARGS(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
6366 #define DUK_HOBJECT_HAS_HAVE_FINALIZER(h)      DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
6367 #define DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
6368 #define DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
6369 #define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
6370 #if defined(DUK_USE_ES6_PROXY)
6371 #define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6372 #else
6373 #define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)     0
6374 #endif
6375 #define DUK_HOBJECT_HAS_SPECIAL_CALL(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
6376 
6377 #define DUK_HOBJECT_SET_EXTENSIBLE(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
6378 #define DUK_HOBJECT_SET_CONSTRUCTABLE(h)       DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
6379 #define DUK_HOBJECT_SET_CALLABLE(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
6380 #define DUK_HOBJECT_SET_BOUNDFUNC(h)           DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6381 #define DUK_HOBJECT_SET_COMPFUNC(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6382 #define DUK_HOBJECT_SET_NATFUNC(h)             DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6383 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6384 #define DUK_HOBJECT_SET_BUFOBJ(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6385 #endif
6386 #define DUK_HOBJECT_SET_FASTREFS(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
6387 #define DUK_HOBJECT_SET_ARRAY_PART(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
6388 #define DUK_HOBJECT_SET_STRICT(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
6389 #define DUK_HOBJECT_SET_NOTAIL(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
6390 #define DUK_HOBJECT_SET_NEWENV(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
6391 #define DUK_HOBJECT_SET_NAMEBINDING(h)         DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
6392 #define DUK_HOBJECT_SET_CREATEARGS(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
6393 #define DUK_HOBJECT_SET_HAVE_FINALIZER(h)      DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
6394 #define DUK_HOBJECT_SET_EXOTIC_ARRAY(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
6395 #define DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
6396 #define DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
6397 #if defined(DUK_USE_ES6_PROXY)
6398 #define DUK_HOBJECT_SET_EXOTIC_PROXYOBJ(h)     DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6399 #endif
6400 #define DUK_HOBJECT_SET_SPECIAL_CALL(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
6401 
6402 #define DUK_HOBJECT_CLEAR_EXTENSIBLE(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
6403 #define DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
6404 #define DUK_HOBJECT_CLEAR_CALLABLE(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
6405 #define DUK_HOBJECT_CLEAR_BOUNDFUNC(h)         DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6406 #define DUK_HOBJECT_CLEAR_COMPFUNC(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6407 #define DUK_HOBJECT_CLEAR_NATFUNC(h)           DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6408 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6409 #define DUK_HOBJECT_CLEAR_BUFOBJ(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6410 #endif
6411 #define DUK_HOBJECT_CLEAR_FASTREFS(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
6412 #define DUK_HOBJECT_CLEAR_ARRAY_PART(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
6413 #define DUK_HOBJECT_CLEAR_STRICT(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
6414 #define DUK_HOBJECT_CLEAR_NOTAIL(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
6415 #define DUK_HOBJECT_CLEAR_NEWENV(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
6416 #define DUK_HOBJECT_CLEAR_NAMEBINDING(h)       DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
6417 #define DUK_HOBJECT_CLEAR_CREATEARGS(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
6418 #define DUK_HOBJECT_CLEAR_HAVE_FINALIZER(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
6419 #define DUK_HOBJECT_CLEAR_EXOTIC_ARRAY(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
6420 #define DUK_HOBJECT_CLEAR_EXOTIC_STRINGOBJ(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
6421 #define DUK_HOBJECT_CLEAR_EXOTIC_ARGUMENTS(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
6422 #if defined(DUK_USE_ES6_PROXY)
6423 #define DUK_HOBJECT_CLEAR_EXOTIC_PROXYOBJ(h)   DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6424 #endif
6425 #define DUK_HOBJECT_CLEAR_SPECIAL_CALL(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
6426 
6427 /* Object can/cannot use FASTREFS, i.e. has no strong reference fields beyond
6428  * duk_hobject base header.  This is used just for asserts so doesn't need to
6429  * be optimized.
6430  */
6431 #define DUK_HOBJECT_PROHIBITS_FASTREFS(h) \
6432 	(DUK_HOBJECT_IS_COMPFUNC((h)) || DUK_HOBJECT_IS_DECENV((h)) || DUK_HOBJECT_IS_OBJENV((h)) || \
6433 	 DUK_HOBJECT_IS_BUFOBJ((h)) || DUK_HOBJECT_IS_THREAD((h)) || DUK_HOBJECT_IS_PROXY((h)) || \
6434 	 DUK_HOBJECT_IS_BOUNDFUNC((h)))
6435 #define DUK_HOBJECT_ALLOWS_FASTREFS(h) (!DUK_HOBJECT_PROHIBITS_FASTREFS((h)))
6436 
6437 /* Flags used for property attributes in duk_propdesc and packed flags.
6438  * Must fit into 8 bits.
6439  */
6440 #define DUK_PROPDESC_FLAG_WRITABLE              (1U << 0)    /* E5 Section 8.6.1 */
6441 #define DUK_PROPDESC_FLAG_ENUMERABLE            (1U << 1)    /* E5 Section 8.6.1 */
6442 #define DUK_PROPDESC_FLAG_CONFIGURABLE          (1U << 2)    /* E5 Section 8.6.1 */
6443 #define DUK_PROPDESC_FLAG_ACCESSOR              (1U << 3)    /* accessor */
6444 #define DUK_PROPDESC_FLAG_VIRTUAL               (1U << 4)    /* property is virtual: used in duk_propdesc, never stored
6445                                                              * (used by e.g. buffer virtual properties)
6446                                                              */
6447 #define DUK_PROPDESC_FLAGS_MASK                 (DUK_PROPDESC_FLAG_WRITABLE | \
6448                                                  DUK_PROPDESC_FLAG_ENUMERABLE | \
6449                                                  DUK_PROPDESC_FLAG_CONFIGURABLE | \
6450                                                  DUK_PROPDESC_FLAG_ACCESSOR)
6451 
6452 /* Additional flags which are passed in the same flags argument as property
6453  * flags but are not stored in object properties.
6454  */
6455 #define DUK_PROPDESC_FLAG_NO_OVERWRITE          (1U << 4)    /* internal define property: skip write silently if exists */
6456 
6457 /* Convenience defines for property attributes. */
6458 #define DUK_PROPDESC_FLAGS_NONE                 0
6459 #define DUK_PROPDESC_FLAGS_W                    (DUK_PROPDESC_FLAG_WRITABLE)
6460 #define DUK_PROPDESC_FLAGS_E                    (DUK_PROPDESC_FLAG_ENUMERABLE)
6461 #define DUK_PROPDESC_FLAGS_C                    (DUK_PROPDESC_FLAG_CONFIGURABLE)
6462 #define DUK_PROPDESC_FLAGS_WE                   (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE)
6463 #define DUK_PROPDESC_FLAGS_WC                   (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
6464 #define DUK_PROPDESC_FLAGS_EC                   (DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
6465 #define DUK_PROPDESC_FLAGS_WEC                  (DUK_PROPDESC_FLAG_WRITABLE | \
6466                                                  DUK_PROPDESC_FLAG_ENUMERABLE | \
6467                                                  DUK_PROPDESC_FLAG_CONFIGURABLE)
6468 
6469 /* Flags for duk_hobject_get_own_propdesc() and variants. */
6470 #define DUK_GETDESC_FLAG_PUSH_VALUE          (1U << 0)  /* push value to stack */
6471 #define DUK_GETDESC_FLAG_IGNORE_PROTOLOOP    (1U << 1)  /* don't throw for prototype loop */
6472 
6473 /*
6474  *  Macro for object validity check
6475  *
6476  *  Assert for currently guaranteed relations between flags, for instance.
6477  */
6478 
6479 #if defined(DUK_USE_ASSERTIONS)
6480 DUK_INTERNAL_DECL void duk_hobject_assert_valid(duk_hobject *h);
6481 #define DUK_HOBJECT_ASSERT_VALID(h)  do { duk_hobject_assert_valid((h)); } while (0)
6482 #else
6483 #define DUK_HOBJECT_ASSERT_VALID(h)  do {} while (0)
6484 #endif
6485 
6486 /*
6487  *  Macros to access the 'props' allocation.
6488  */
6489 
6490 #if defined(DUK_USE_HEAPPTR16)
6491 #define DUK_HOBJECT_GET_PROPS(heap,h) \
6492 	((duk_uint8_t *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (h))->h_extra16))
6493 #define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
6494 		((duk_heaphdr *) (h))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
6495 	} while (0)
6496 #else
6497 #define DUK_HOBJECT_GET_PROPS(heap,h) \
6498 	((h)->props)
6499 #define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
6500 		(h)->props = (duk_uint8_t *) (x); \
6501 	} while (0)
6502 #endif
6503 
6504 #if defined(DUK_USE_HOBJECT_LAYOUT_1)
6505 /* LAYOUT 1 */
6506 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
6507 	((duk_hstring **) (void *) ( \
6508 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
6509 	))
6510 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
6511 	((duk_propvalue *) (void *) ( \
6512 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6513 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_hstring *) \
6514 	))
6515 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
6516 	((duk_uint8_t *) (void *) ( \
6517 		DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
6518 	))
6519 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
6520 	((duk_tval *) (void *) ( \
6521 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6522 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) \
6523 	))
6524 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
6525 	((duk_uint32_t *) (void *) ( \
6526 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6527 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6528 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
6529 	))
6530 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
6531 	( \
6532 		(n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6533 		(n_arr) * sizeof(duk_tval) + \
6534 		(n_hash) * sizeof(duk_uint32_t) \
6535 	)
6536 #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 { \
6537 		(set_e_k) = (duk_hstring **) (void *) (p_base); \
6538 		(set_e_pv) = (duk_propvalue *) (void *) ((set_e_k) + (n_ent)); \
6539 		(set_e_f) = (duk_uint8_t *) (void *) ((set_e_pv) + (n_ent)); \
6540 		(set_a) = (duk_tval *) (void *) ((set_e_f) + (n_ent)); \
6541 		(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
6542 	} while (0)
6543 #elif defined(DUK_USE_HOBJECT_LAYOUT_2)
6544 /* LAYOUT 2 */
6545 #if (DUK_USE_ALIGN_BY == 4)
6546 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((4 - (e_sz)) & 0x03)
6547 #elif (DUK_USE_ALIGN_BY == 8)
6548 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((8 - (e_sz)) & 0x07)
6549 #elif (DUK_USE_ALIGN_BY == 1)
6550 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) 0
6551 #else
6552 #error invalid DUK_USE_ALIGN_BY
6553 #endif
6554 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
6555 	((duk_hstring **) (void *) ( \
6556 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6557 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
6558 	))
6559 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
6560 	((duk_propvalue *) (void *) ( \
6561 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
6562 	))
6563 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
6564 	((duk_uint8_t *) (void *) ( \
6565 		DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
6566 	))
6567 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
6568 	((duk_tval *) (void *) ( \
6569 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6570 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6571 			DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) \
6572 	))
6573 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
6574 	((duk_uint32_t *) (void *) ( \
6575 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6576 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6577 			DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) + \
6578 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
6579 	))
6580 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
6581 	( \
6582 		(n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6583 		DUK_HOBJECT_E_FLAG_PADDING((n_ent)) + \
6584 		(n_arr) * sizeof(duk_tval) + \
6585 		(n_hash) * sizeof(duk_uint32_t) \
6586 	)
6587 #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 { \
6588 		(set_e_pv) = (duk_propvalue *) (void *) (p_base); \
6589 		(set_e_k) = (duk_hstring **) (void *) ((set_e_pv) + (n_ent)); \
6590 		(set_e_f) = (duk_uint8_t *) (void *) ((set_e_k) + (n_ent)); \
6591 		(set_a) = (duk_tval *) (void *) (((duk_uint8_t *) (set_e_f)) + \
6592 		                                 sizeof(duk_uint8_t) * (n_ent) + \
6593 		                                 DUK_HOBJECT_E_FLAG_PADDING((n_ent))); \
6594 		(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
6595 	} while (0)
6596 #elif defined(DUK_USE_HOBJECT_LAYOUT_3)
6597 /* LAYOUT 3 */
6598 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
6599 	((duk_hstring **) (void *) ( \
6600 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6601 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) + \
6602 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
6603 	))
6604 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
6605 	((duk_propvalue *) (void *) ( \
6606 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
6607 	))
6608 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
6609 	((duk_uint8_t *) (void *) ( \
6610 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6611 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
6612 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) + \
6613 			DUK_HOBJECT_GET_HSIZE((h)) * sizeof(duk_uint32_t) \
6614 	))
6615 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
6616 	((duk_tval *) (void *) ( \
6617 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6618 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
6619 	))
6620 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
6621 	((duk_uint32_t *) (void *) ( \
6622 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6623 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
6624 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
6625 	))
6626 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
6627 	( \
6628 		(n_ent) * (sizeof(duk_propvalue) + sizeof(duk_hstring *) + sizeof(duk_uint8_t)) + \
6629 		(n_arr) * sizeof(duk_tval) + \
6630 		(n_hash) * sizeof(duk_uint32_t) \
6631 	)
6632 #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 { \
6633 		(set_e_pv) = (duk_propvalue *) (void *) (p_base); \
6634 		(set_a) = (duk_tval *) (void *) ((set_e_pv) + (n_ent)); \
6635 		(set_e_k) = (duk_hstring **) (void *) ((set_a) + (n_arr)); \
6636 		(set_h) = (duk_uint32_t *) (void *) ((set_e_k) + (n_ent)); \
6637 		(set_e_f) = (duk_uint8_t *) (void *) ((set_h) + (n_hash)); \
6638 	} while (0)
6639 #else
6640 #error invalid hobject layout defines
6641 #endif  /* hobject property layout */
6642 
6643 #define DUK_HOBJECT_P_ALLOC_SIZE(h) \
6644 	DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE((h)), DUK_HOBJECT_GET_ASIZE((h)), DUK_HOBJECT_GET_HSIZE((h)))
6645 
6646 #define DUK_HOBJECT_E_GET_KEY(heap,h,i)              (DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
6647 #define DUK_HOBJECT_E_GET_KEY_PTR(heap,h,i)          (&DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
6648 #define DUK_HOBJECT_E_GET_VALUE(heap,h,i)            (DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
6649 #define DUK_HOBJECT_E_GET_VALUE_PTR(heap,h,i)        (&DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
6650 #define DUK_HOBJECT_E_GET_VALUE_TVAL(heap,h,i)       (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
6651 #define DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap,h,i)   (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
6652 #define DUK_HOBJECT_E_GET_VALUE_GETTER(heap,h,i)     (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
6653 #define DUK_HOBJECT_E_GET_VALUE_GETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
6654 #define DUK_HOBJECT_E_GET_VALUE_SETTER(heap,h,i)     (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
6655 #define DUK_HOBJECT_E_GET_VALUE_SETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
6656 #define DUK_HOBJECT_E_GET_FLAGS(heap,h,i)            (DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
6657 #define DUK_HOBJECT_E_GET_FLAGS_PTR(heap,h,i)        (&DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
6658 #define DUK_HOBJECT_A_GET_VALUE(heap,h,i)            (DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
6659 #define DUK_HOBJECT_A_GET_VALUE_PTR(heap,h,i)        (&DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
6660 #define DUK_HOBJECT_H_GET_INDEX(heap,h,i)            (DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
6661 #define DUK_HOBJECT_H_GET_INDEX_PTR(heap,h,i)        (&DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
6662 
6663 #define DUK_HOBJECT_E_SET_KEY(heap,h,i,k)  do { \
6664 		DUK_HOBJECT_E_GET_KEY((heap), (h), (i)) = (k); \
6665 	} while (0)
6666 #define DUK_HOBJECT_E_SET_VALUE(heap,h,i,v)  do { \
6667 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)) = (v); \
6668 	} while (0)
6669 #define DUK_HOBJECT_E_SET_VALUE_TVAL(heap,h,i,v)  do { \
6670 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v = (v); \
6671 	} while (0)
6672 #define DUK_HOBJECT_E_SET_VALUE_GETTER(heap,h,i,v)  do { \
6673 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get = (v); \
6674 	} while (0)
6675 #define DUK_HOBJECT_E_SET_VALUE_SETTER(heap,h,i,v)  do { \
6676 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set = (v); \
6677 	} while (0)
6678 #define DUK_HOBJECT_E_SET_FLAGS(heap,h,i,f)  do { \
6679 		DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) = (duk_uint8_t) (f); \
6680 	} while (0)
6681 #define DUK_HOBJECT_A_SET_VALUE(heap,h,i,v)  do { \
6682 		DUK_HOBJECT_A_GET_VALUE((heap), (h), (i)) = (v); \
6683 	} while (0)
6684 #define DUK_HOBJECT_A_SET_VALUE_TVAL(heap,h,i,v) \
6685 	DUK_HOBJECT_A_SET_VALUE((heap), (h), (i), (v))  /* alias for above */
6686 #define DUK_HOBJECT_H_SET_INDEX(heap,h,i,v)  do { \
6687 		DUK_HOBJECT_H_GET_INDEX((heap), (h), (i)) = (v); \
6688 	} while (0)
6689 
6690 #define DUK_HOBJECT_E_SET_FLAG_BITS(heap,h,i,mask)  do { \
6691 		DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] |= (mask); \
6692 	} while (0)
6693 
6694 #define DUK_HOBJECT_E_CLEAR_FLAG_BITS(heap,h,i,mask)  do { \
6695 		DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] &= ~(mask); \
6696 	} while (0)
6697 
6698 #define DUK_HOBJECT_E_SLOT_IS_WRITABLE(heap,h,i)     ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_WRITABLE) != 0)
6699 #define DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(heap,h,i)   ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
6700 #define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
6701 #define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap,h,i)     ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
6702 
6703 #define DUK_HOBJECT_E_SLOT_SET_WRITABLE(heap,h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
6704 #define DUK_HOBJECT_E_SLOT_SET_ENUMERABLE(heap,h,i)      DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
6705 #define DUK_HOBJECT_E_SLOT_SET_CONFIGURABLE(heap,h,i)    DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
6706 #define DUK_HOBJECT_E_SLOT_SET_ACCESSOR(heap,h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
6707 
6708 #define DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(heap,h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
6709 #define DUK_HOBJECT_E_SLOT_CLEAR_ENUMERABLE(heap,h,i)    DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
6710 #define DUK_HOBJECT_E_SLOT_CLEAR_CONFIGURABLE(heap,h,i)  DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
6711 #define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(heap,h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
6712 
6713 #define DUK_PROPDESC_IS_WRITABLE(p)             (((p)->flags & DUK_PROPDESC_FLAG_WRITABLE) != 0)
6714 #define DUK_PROPDESC_IS_ENUMERABLE(p)           (((p)->flags & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
6715 #define DUK_PROPDESC_IS_CONFIGURABLE(p)         (((p)->flags & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
6716 #define DUK_PROPDESC_IS_ACCESSOR(p)             (((p)->flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
6717 
6718 #define DUK_HOBJECT_HASHIDX_UNUSED              0xffffffffUL
6719 #define DUK_HOBJECT_HASHIDX_DELETED             0xfffffffeUL
6720 
6721 /*
6722  *  Macros for accessing size fields
6723  */
6724 
6725 #if defined(DUK_USE_OBJSIZES16)
6726 #define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size16)
6727 #define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size16 = (v); } while (0)
6728 #define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next16)
6729 #define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next16 = (v); } while (0)
6730 #define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next16++)
6731 #define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size16)
6732 #define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size16 = (v); } while (0)
6733 #if defined(DUK_USE_HOBJECT_HASH_PART)
6734 #define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size16)
6735 #define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size16 = (v); } while (0)
6736 #else
6737 #define DUK_HOBJECT_GET_HSIZE(h) 0
6738 #define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
6739 #endif
6740 #else
6741 #define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size)
6742 #define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size = (v); } while (0)
6743 #define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next)
6744 #define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next = (v); } while (0)
6745 #define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next++)
6746 #define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size)
6747 #define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size = (v); } while (0)
6748 #if defined(DUK_USE_HOBJECT_HASH_PART)
6749 #define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size)
6750 #define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size = (v); } while (0)
6751 #else
6752 #define DUK_HOBJECT_GET_HSIZE(h) 0
6753 #define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
6754 #endif
6755 #endif
6756 
6757 /*
6758  *  Misc
6759  */
6760 
6761 /* Maximum prototype traversal depth.  Sanity limit which handles e.g.
6762  * prototype loops (even complex ones like 1->2->3->4->2->3->4->2->3->4).
6763  */
6764 #define DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY      10000L
6765 
6766 /*
6767  *  ECMAScript [[Class]]
6768  */
6769 
6770 /* range check not necessary because all 4-bit values are mapped */
6771 #define DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(n)  duk_class_number_to_stridx[(n)]
6772 
6773 #define DUK_HOBJECT_GET_CLASS_STRING(heap,h)          \
6774 	DUK_HEAP_GET_STRING( \
6775 		(heap), \
6776 		DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(DUK_HOBJECT_GET_CLASS_NUMBER((h))) \
6777 	)
6778 
6779 /*
6780  *  Macros for property handling
6781  */
6782 
6783 #if defined(DUK_USE_HEAPPTR16)
6784 #define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
6785 	((duk_hobject *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->prototype16))
6786 #define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
6787 		(h)->prototype16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
6788 	} while (0)
6789 #else
6790 #define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
6791 	((h)->prototype)
6792 #define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
6793 		(h)->prototype = (x); \
6794 	} while (0)
6795 #endif
6796 
6797 /* Set prototype, DECREF earlier value, INCREF new value (tolerating NULLs). */
6798 #define DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr,h,p)       duk_hobject_set_prototype_updref((thr), (h), (p))
6799 
6800 /* Set initial prototype, assume NULL previous prototype, INCREF new value,
6801  * tolerate NULL.
6802  */
6803 #define DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr,h,proto) do { \
6804 		duk_hthread *duk__thr = (thr); \
6805 		duk_hobject *duk__obj = (h); \
6806 		duk_hobject *duk__proto = (proto); \
6807 		DUK_UNREF(duk__thr); \
6808 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(duk__thr->heap, duk__obj) == NULL); \
6809 		DUK_HOBJECT_SET_PROTOTYPE(duk__thr->heap, duk__obj, duk__proto); \
6810 		DUK_HOBJECT_INCREF_ALLOWNULL(duk__thr, duk__proto); \
6811 	} while (0)
6812 
6813 /*
6814  *  Finalizer check
6815  */
6816 
6817 #if defined(DUK_USE_HEAPPTR16)
6818 #define DUK_HOBJECT_HAS_FINALIZER_FAST(heap,h) duk_hobject_has_finalizer_fast_raw((heap), (h))
6819 #else
6820 #define DUK_HOBJECT_HAS_FINALIZER_FAST(heap,h) duk_hobject_has_finalizer_fast_raw((h))
6821 #endif
6822 
6823 /*
6824  *  Resizing and hash behavior
6825  */
6826 
6827 /* Sanity limit on max number of properties (allocated, not necessarily used).
6828  * This is somewhat arbitrary, but if we're close to 2**32 properties some
6829  * algorithms will fail (e.g. hash size selection, next prime selection).
6830  * Also, we use negative array/entry table indices to indicate 'not found',
6831  * so anything above 0x80000000 will cause trouble now.
6832  */
6833 #if defined(DUK_USE_OBJSIZES16)
6834 #define DUK_HOBJECT_MAX_PROPERTIES       0x0000ffffUL
6835 #else
6836 #define DUK_HOBJECT_MAX_PROPERTIES       0x3fffffffUL   /* 2**30-1 ~= 1G properties */
6837 #endif
6838 
6839 /* internal align target for props allocation, must be 2*n for some n */
6840 #if (DUK_USE_ALIGN_BY == 4)
6841 #define DUK_HOBJECT_ALIGN_TARGET         4
6842 #elif (DUK_USE_ALIGN_BY == 8)
6843 #define DUK_HOBJECT_ALIGN_TARGET         8
6844 #elif (DUK_USE_ALIGN_BY == 1)
6845 #define DUK_HOBJECT_ALIGN_TARGET         1
6846 #else
6847 #error invalid DUK_USE_ALIGN_BY
6848 #endif
6849 
6850 /*
6851  *  PC-to-line constants
6852  */
6853 
6854 #define DUK_PC2LINE_SKIP    64
6855 
6856 /* maximum length for a SKIP-1 diffstream: 35 bits per entry, rounded up to bytes */
6857 #define DUK_PC2LINE_MAX_DIFF_LENGTH    (((DUK_PC2LINE_SKIP - 1) * 35 + 7) / 8)
6858 
6859 /*
6860  *  Struct defs
6861  */
6862 
6863 struct duk_propaccessor {
6864 	duk_hobject *get;
6865 	duk_hobject *set;
6866 };
6867 
6868 union duk_propvalue {
6869 	/* The get/set pointers could be 16-bit pointer compressed but it
6870 	 * would make no difference on 32-bit platforms because duk_tval is
6871 	 * 8 bytes or more anyway.
6872 	 */
6873 	duk_tval v;
6874 	duk_propaccessor a;
6875 };
6876 
6877 struct duk_propdesc {
6878 	/* read-only values 'lifted' for ease of use */
6879 	duk_small_uint_t flags;
6880 	duk_hobject *get;
6881 	duk_hobject *set;
6882 
6883 	/* for updating (all are set to < 0 for virtual properties) */
6884 	duk_int_t e_idx;  /* prop index in 'entry part', < 0 if not there */
6885 	duk_int_t h_idx;  /* prop index in 'hash part', < 0 if not there */
6886 	duk_int_t a_idx;  /* prop index in 'array part', < 0 if not there */
6887 };
6888 
6889 struct duk_hobject {
6890 	duk_heaphdr hdr;
6891 
6892 	/*
6893 	 *  'props' contains {key,value,flags} entries, optional array entries, and
6894 	 *  an optional hash lookup table for non-array entries in a single 'sliced'
6895 	 *  allocation.  There are several layout options, which differ slightly in
6896 	 *  generated code size/speed and alignment/padding; duk_features.h selects
6897 	 *  the layout used.
6898 	 *
6899 	 *  Layout 1 (DUK_USE_HOBJECT_LAYOUT_1):
6900 	 *
6901 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
6902 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
6903 	 *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_next gc reachable)
6904 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
6905 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
6906 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
6907 	 *
6908 	 *  Layout 2 (DUK_USE_HOBJECT_LAYOUT_2):
6909 	 *
6910 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
6911 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
6912 	 *    e_size * sizeof(duk_uint8_t) + pad     bytes of   entry flags (e_next gc reachable)
6913 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
6914 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
6915 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
6916 	 *
6917 	 *  Layout 3 (DUK_USE_HOBJECT_LAYOUT_3):
6918 	 *
6919 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
6920 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
6921 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
6922 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
6923 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
6924 	 *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_next gc reachable)
6925 	 *
6926 	 *  In layout 1, the 'e_next' count is rounded to 4 or 8 on platforms
6927 	 *  requiring 4 or 8 byte alignment.  This ensures proper alignment
6928 	 *  for the entries, at the cost of memory footprint.  However, it's
6929 	 *  probably preferable to use another layout on such platforms instead.
6930 	 *
6931 	 *  In layout 2, the key and value parts are swapped to avoid padding
6932 	 *  the key array on platforms requiring alignment by 8.  The flags part
6933 	 *  is padded to get alignment for array entries.  The 'e_next' count does
6934 	 *  not need to be rounded as in layout 1.
6935 	 *
6936 	 *  In layout 3, entry values and array values are always aligned properly,
6937 	 *  and assuming pointers are at most 8 bytes, so are the entry keys.  Hash
6938 	 *  indices will be properly aligned (assuming pointers are at least 4 bytes).
6939 	 *  Finally, flags don't need additional alignment.  This layout provides
6940 	 *  compact allocations without padding (even on platforms with alignment
6941 	 *  requirements) at the cost of a bit slower lookups.
6942 	 *
6943 	 *  Objects with few keys don't have a hash index; keys are looked up linearly,
6944 	 *  which is cache efficient because the keys are consecutive.  Larger objects
6945 	 *  have a hash index part which contains integer indexes to the entries part.
6946 	 *
6947 	 *  A single allocation reduces memory allocation overhead but requires more
6948 	 *  work when any part needs to be resized.  A sliced allocation for entries
6949 	 *  makes linear key matching faster on most platforms (more locality) and
6950 	 *  skimps on flags size (which would be followed by 3 bytes of padding in
6951 	 *  most architectures if entries were placed in a struct).
6952 	 *
6953 	 *  'props' also contains internal properties distinguished with a non-BMP
6954 	 *  prefix.  Often used properties should be placed early in 'props' whenever
6955 	 *  possible to make accessing them as fast a possible.
6956 	 */
6957 
6958 #if defined(DUK_USE_HEAPPTR16)
6959 	/* Located in duk_heaphdr h_extra16.  Subclasses of duk_hobject (like
6960 	 * duk_hcompfunc) are not free to use h_extra16 for this reason.
6961 	 */
6962 #else
6963 	duk_uint8_t *props;
6964 #endif
6965 
6966 	/* prototype: the only internal property lifted outside 'e' as it is so central */
6967 #if defined(DUK_USE_HEAPPTR16)
6968 	duk_uint16_t prototype16;
6969 #else
6970 	duk_hobject *prototype;
6971 #endif
6972 
6973 #if defined(DUK_USE_OBJSIZES16)
6974 	duk_uint16_t e_size16;
6975 	duk_uint16_t e_next16;
6976 	duk_uint16_t a_size16;
6977 #if defined(DUK_USE_HOBJECT_HASH_PART)
6978 	duk_uint16_t h_size16;
6979 #endif
6980 #else
6981 	duk_uint32_t e_size;  /* entry part size */
6982 	duk_uint32_t e_next;  /* index for next new key ([0,e_next[ are gc reachable) */
6983 	duk_uint32_t a_size;  /* array part size (entirely gc reachable) */
6984 #if defined(DUK_USE_HOBJECT_HASH_PART)
6985 	duk_uint32_t h_size;  /* hash part size or 0 if unused */
6986 #endif
6987 #endif
6988 };
6989 
6990 /*
6991  *  Exposed data
6992  */
6993 
6994 #if !defined(DUK_SINGLE_FILE)
6995 DUK_INTERNAL_DECL duk_uint8_t duk_class_number_to_stridx[32];
6996 #endif  /* !DUK_SINGLE_FILE */
6997 
6998 /*
6999  *  Prototypes
7000  */
7001 
7002 /* alloc and init */
7003 DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags);
7004 DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
7005 DUK_INTERNAL_DECL duk_harray *duk_harray_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
7006 DUK_INTERNAL_DECL duk_hcompfunc *duk_hcompfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
7007 DUK_INTERNAL_DECL duk_hnatfunc *duk_hnatfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
7008 DUK_INTERNAL_DECL duk_hboundfunc *duk_hboundfunc_alloc(duk_heap *heap, duk_uint_t hobject_flags);
7009 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
7010 DUK_INTERNAL_DECL duk_hbufobj *duk_hbufobj_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
7011 #endif
7012 DUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags);
7013 DUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
7014 DUK_INTERNAL_DECL duk_hdecenv *duk_hdecenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
7015 DUK_INTERNAL_DECL duk_hobjenv *duk_hobjenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
7016 DUK_INTERNAL_DECL duk_hproxy *duk_hproxy_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
7017 
7018 /* resize */
7019 DUK_INTERNAL_DECL void duk_hobject_realloc_props(duk_hthread *thr,
7020                                                  duk_hobject *obj,
7021                                                  duk_uint32_t new_e_size,
7022                                                  duk_uint32_t new_a_size,
7023                                                  duk_uint32_t new_h_size,
7024                                                  duk_bool_t abandon_array);
7025 DUK_INTERNAL_DECL void duk_hobject_resize_entrypart(duk_hthread *thr,
7026                                                     duk_hobject *obj,
7027                                                     duk_uint32_t new_e_size);
7028 #if 0  /*unused*/
7029 DUK_INTERNAL_DECL void duk_hobject_resize_arraypart(duk_hthread *thr,
7030                                                     duk_hobject *obj,
7031                                                     duk_uint32_t new_a_size);
7032 #endif
7033 
7034 /* low-level property functions */
7035 DUK_INTERNAL_DECL duk_bool_t duk_hobject_find_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx);
7036 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key);
7037 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_entry_tval_ptr_stridx(duk_heap *heap, duk_hobject *obj, duk_small_uint_t stridx);
7038 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_uint_t *out_attrs);
7039 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i);
7040 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);
7041 
7042 /* core property functions */
7043 DUK_INTERNAL_DECL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
7044 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);
7045 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);
7046 DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
7047 
7048 /* internal property functions */
7049 #define DUK_DELPROP_FLAG_THROW  (1U << 0)
7050 #define DUK_DELPROP_FLAG_FORCE  (1U << 1)
7051 DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
7052 DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key);
7053 DUK_INTERNAL_DECL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
7054 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);
7055 DUK_INTERNAL_DECL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj);
7056 #if defined(DUK_USE_HEAPPTR16)
7057 DUK_INTERNAL_DECL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_heap *heap, duk_hobject *obj);
7058 #else
7059 DUK_INTERNAL_DECL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_hobject *obj);
7060 #endif
7061 
7062 /* helpers for defineProperty() and defineProperties() */
7063 DUK_INTERNAL_DECL void duk_hobject_prepare_property_descriptor(duk_hthread *thr,
7064                                                                duk_idx_t idx_in,
7065                                                                duk_uint_t *out_defprop_flags,
7066                                                                duk_idx_t *out_idx_value,
7067                                                                duk_hobject **out_getter,
7068                                                                duk_hobject **out_setter);
7069 DUK_INTERNAL_DECL duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
7070                                                                 duk_uint_t defprop_flags,
7071                                                                 duk_hobject *obj,
7072                                                                 duk_hstring *key,
7073                                                                 duk_idx_t idx_value,
7074                                                                 duk_hobject *get,
7075                                                                 duk_hobject *set,
7076                                                                 duk_bool_t throw_flag);
7077 
7078 /* Object built-in methods */
7079 DUK_INTERNAL_DECL void duk_hobject_object_get_own_property_descriptor(duk_hthread *thr, duk_idx_t obj_idx);
7080 DUK_INTERNAL_DECL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze);
7081 DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen);
7082 DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_ownprop_helper(duk_hthread *thr, duk_small_uint_t required_desc_flags);
7083 
7084 /* internal properties */
7085 DUK_INTERNAL_DECL duk_tval *duk_hobject_get_internal_value_tval_ptr(duk_heap *heap, duk_hobject *obj);
7086 DUK_INTERNAL_DECL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj);
7087 DUK_INTERNAL_DECL duk_harray *duk_hobject_get_formals(duk_hthread *thr, duk_hobject *obj);
7088 DUK_INTERNAL_DECL duk_hobject *duk_hobject_get_varmap(duk_hthread *thr, duk_hobject *obj);
7089 
7090 /* hobject management functions */
7091 DUK_INTERNAL_DECL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj);
7092 
7093 /* ES2015 proxy */
7094 #if defined(DUK_USE_ES6_PROXY)
7095 DUK_INTERNAL_DECL duk_bool_t duk_hobject_proxy_check(duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler);
7096 DUK_INTERNAL_DECL duk_hobject *duk_hobject_resolve_proxy_target(duk_hobject *obj);
7097 #endif
7098 
7099 /* enumeration */
7100 DUK_INTERNAL_DECL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint_t enum_flags);
7101 DUK_INTERNAL_DECL duk_ret_t duk_hobject_get_enumerated_keys(duk_hthread *thr, duk_small_uint_t enum_flags);
7102 DUK_INTERNAL_DECL duk_bool_t duk_hobject_enumerator_next(duk_hthread *thr, duk_bool_t get_value);
7103 
7104 /* macros */
7105 DUK_INTERNAL_DECL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p);
7106 
7107 /* pc2line */
7108 #if defined(DUK_USE_PC2LINE)
7109 DUK_INTERNAL_DECL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length);
7110 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_idx_t idx_func, duk_uint_fast32_t pc);
7111 #endif
7112 
7113 /* misc */
7114 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);
7115 
7116 #if !defined(DUK_USE_OBJECT_BUILTIN)
7117 /* These declarations are needed when related built-in is disabled and
7118  * genbuiltins.py won't automatically emit the declerations.
7119  */
7120 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_hthread *thr);
7121 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_hthread *thr);
7122 #endif
7123 
7124 #endif  /* DUK_HOBJECT_H_INCLUDED */
7125 /* #include duk_hcompfunc.h */
7126 #line 1 "duk_hcompfunc.h"
7127 /*
7128  *  Heap compiled function (ECMAScript function) representation.
7129  *
7130  *  There is a single data buffer containing the ECMAScript function's
7131  *  bytecode, constants, and inner functions.
7132  */
7133 
7134 #if !defined(DUK_HCOMPFUNC_H_INCLUDED)
7135 #define DUK_HCOMPFUNC_H_INCLUDED
7136 
7137 /*
7138  *  Field accessor macros
7139  */
7140 
7141 /* XXX: casts could be improved, especially for GET/SET DATA */
7142 
7143 #if defined(DUK_USE_HEAPPTR16)
7144 #define DUK_HCOMPFUNC_GET_DATA(heap,h) \
7145 	((duk_hbuffer_fixed *) (void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16))
7146 #define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \
7147 		(h)->data16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7148 	} while (0)
7149 #define DUK_HCOMPFUNC_GET_FUNCS(heap,h)  \
7150 	((duk_hobject **) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->funcs16)))
7151 #define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v)  do { \
7152 		(h)->funcs16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7153 	} while (0)
7154 #define DUK_HCOMPFUNC_GET_BYTECODE(heap,h)  \
7155 	((duk_instr_t *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->bytecode16)))
7156 #define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v)  do { \
7157 		(h)->bytecode16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7158 	} while (0)
7159 #define DUK_HCOMPFUNC_GET_LEXENV(heap,h)  \
7160 	((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->lex_env16)))
7161 #define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v)  do { \
7162 		(h)->lex_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7163 	} while (0)
7164 #define DUK_HCOMPFUNC_GET_VARENV(heap,h)  \
7165 	((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->var_env16)))
7166 #define DUK_HCOMPFUNC_SET_VARENV(heap,h,v)  do { \
7167 		(h)->var_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7168 	} while (0)
7169 #else
7170 #define DUK_HCOMPFUNC_GET_DATA(heap,h)  ((duk_hbuffer_fixed *) (void *) (h)->data)
7171 #define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \
7172 		(h)->data = (duk_hbuffer *) (v); \
7173 	} while (0)
7174 #define DUK_HCOMPFUNC_GET_FUNCS(heap,h)  ((h)->funcs)
7175 #define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v)  do { \
7176 		(h)->funcs = (v); \
7177 	} while (0)
7178 #define DUK_HCOMPFUNC_GET_BYTECODE(heap,h)  ((h)->bytecode)
7179 #define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v)  do { \
7180 		(h)->bytecode = (v); \
7181 	} while (0)
7182 #define DUK_HCOMPFUNC_GET_LEXENV(heap,h)  ((h)->lex_env)
7183 #define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v)  do { \
7184 		(h)->lex_env = (v); \
7185 	} while (0)
7186 #define DUK_HCOMPFUNC_GET_VARENV(heap,h)  ((h)->var_env)
7187 #define DUK_HCOMPFUNC_SET_VARENV(heap,h,v)  do { \
7188 		(h)->var_env = (v); \
7189 	} while (0)
7190 #endif
7191 
7192 /*
7193  *  Accessor macros for function specific data areas
7194  */
7195 
7196 /* Note: assumes 'data' is always a fixed buffer */
7197 #define DUK_HCOMPFUNC_GET_BUFFER_BASE(heap,h)  \
7198 	DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h)))
7199 
7200 #define DUK_HCOMPFUNC_GET_CONSTS_BASE(heap,h)  \
7201 	((duk_tval *) (void *) DUK_HCOMPFUNC_GET_BUFFER_BASE((heap), (h)))
7202 
7203 #define DUK_HCOMPFUNC_GET_FUNCS_BASE(heap,h)  \
7204 	DUK_HCOMPFUNC_GET_FUNCS((heap), (h))
7205 
7206 #define DUK_HCOMPFUNC_GET_CODE_BASE(heap,h)  \
7207 	DUK_HCOMPFUNC_GET_BYTECODE((heap), (h))
7208 
7209 #define DUK_HCOMPFUNC_GET_CONSTS_END(heap,h)  \
7210 	((duk_tval *) (void *) DUK_HCOMPFUNC_GET_FUNCS((heap), (h)))
7211 
7212 #define DUK_HCOMPFUNC_GET_FUNCS_END(heap,h)  \
7213 	((duk_hobject **) (void *) DUK_HCOMPFUNC_GET_BYTECODE((heap), (h)))
7214 
7215 /* XXX: double evaluation of DUK_HCOMPFUNC_GET_DATA() */
7216 #define DUK_HCOMPFUNC_GET_CODE_END(heap,h)  \
7217 	((duk_instr_t *) (void *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h))) + \
7218 	                DUK_HBUFFER_GET_SIZE((duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA((heap), h))))
7219 
7220 #define DUK_HCOMPFUNC_GET_CONSTS_SIZE(heap,h)  \
7221 	( \
7222 	 (duk_size_t) \
7223 	 ( \
7224 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_END((heap), (h))) - \
7225 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_BASE((heap), (h))) \
7226 	 ) \
7227 	)
7228 
7229 #define DUK_HCOMPFUNC_GET_FUNCS_SIZE(heap,h)  \
7230 	( \
7231 	 (duk_size_t) \
7232 	 ( \
7233 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_END((heap), (h))) - \
7234 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_BASE((heap), (h))) \
7235 	 ) \
7236 	)
7237 
7238 #define DUK_HCOMPFUNC_GET_CODE_SIZE(heap,h)  \
7239 	( \
7240 	 (duk_size_t) \
7241 	 ( \
7242 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_END((heap),(h))) - \
7243 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_BASE((heap),(h))) \
7244 	 ) \
7245 	)
7246 
7247 #define DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap,h)  \
7248 	((duk_size_t) (DUK_HCOMPFUNC_GET_CONSTS_SIZE((heap), (h)) / sizeof(duk_tval)))
7249 
7250 #define DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap,h)  \
7251 	((duk_size_t) (DUK_HCOMPFUNC_GET_FUNCS_SIZE((heap), (h)) / sizeof(duk_hobject *)))
7252 
7253 #define DUK_HCOMPFUNC_GET_CODE_COUNT(heap,h)  \
7254 	((duk_size_t) (DUK_HCOMPFUNC_GET_CODE_SIZE((heap), (h)) / sizeof(duk_instr_t)))
7255 
7256 /*
7257  *  Validity assert
7258  */
7259 
7260 #if defined(DUK_USE_ASSERTIONS)
7261 DUK_INTERNAL_DECL void duk_hcompfunc_assert_valid(duk_hcompfunc *h);
7262 #define DUK_HCOMPFUNC_ASSERT_VALID(h)  do { duk_hcompfunc_assert_valid((h)); } while (0)
7263 #else
7264 #define DUK_HCOMPFUNC_ASSERT_VALID(h)  do {} while (0)
7265 #endif
7266 
7267 /*
7268  *  Main struct
7269  */
7270 
7271 struct duk_hcompfunc {
7272 	/* shared object part */
7273 	duk_hobject obj;
7274 
7275 	/*
7276 	 *  Pointers to function data area for faster access.  Function
7277 	 *  data is a buffer shared between all closures of the same
7278 	 *  "template" function.  The data buffer is always fixed (non-
7279 	 *  dynamic, hence stable), with a layout as follows:
7280 	 *
7281 	 *    constants (duk_tval)
7282 	 *    inner functions (duk_hobject *)
7283 	 *    bytecode (duk_instr_t)
7284 	 *
7285 	 *  Note: bytecode end address can be computed from 'data' buffer
7286 	 *  size.  It is not strictly necessary functionally, assuming
7287 	 *  bytecode never jumps outside its allocated area.  However,
7288 	 *  it's a safety/robustness feature for avoiding the chance of
7289 	 *  executing random data as bytecode due to a compiler error.
7290 	 *
7291 	 *  Note: values in the data buffer must be incref'd (they will
7292 	 *  be decref'd on release) for every compiledfunction referring
7293 	 *  to the 'data' element.
7294 	 */
7295 
7296 	/* Data area, fixed allocation, stable data ptrs. */
7297 #if defined(DUK_USE_HEAPPTR16)
7298 	duk_uint16_t data16;
7299 #else
7300 	duk_hbuffer *data;
7301 #endif
7302 
7303 	/* No need for constants pointer (= same as data).
7304 	 *
7305 	 * When using 16-bit packing alignment to 4 is nice.  'funcs' will be
7306 	 * 4-byte aligned because 'constants' are duk_tvals.  For now the
7307 	 * inner function pointers are not compressed, so that 'bytecode' will
7308 	 * also be 4-byte aligned.
7309 	 */
7310 #if defined(DUK_USE_HEAPPTR16)
7311 	duk_uint16_t funcs16;
7312 	duk_uint16_t bytecode16;
7313 #else
7314 	duk_hobject **funcs;
7315 	duk_instr_t *bytecode;
7316 #endif
7317 
7318 	/* Lexenv: lexical environment of closure, NULL for templates.
7319 	 * Varenv: variable environment of closure, NULL for templates.
7320 	 */
7321 #if defined(DUK_USE_HEAPPTR16)
7322 	duk_uint16_t lex_env16;
7323 	duk_uint16_t var_env16;
7324 #else
7325 	duk_hobject *lex_env;
7326 	duk_hobject *var_env;
7327 #endif
7328 
7329 	/*
7330 	 *  'nregs' registers are allocated on function entry, at most 'nargs'
7331 	 *  are initialized to arguments, and the rest to undefined.  Arguments
7332 	 *  above 'nregs' are not mapped to registers.  All registers in the
7333 	 *  active stack range must be initialized because they are GC reachable.
7334 	 *  'nargs' is needed so that if the function is given more than 'nargs'
7335 	 *  arguments, the additional arguments do not 'clobber' registers
7336 	 *  beyond 'nregs' which must be consistently initialized to undefined.
7337 	 *
7338 	 *  Usually there is no need to know which registers are mapped to
7339 	 *  local variables.  Registers may be allocated to variable in any
7340 	 *  way (even including gaps).  However, a register-variable mapping
7341 	 *  must be the same for the duration of the function execution and
7342 	 *  the register cannot be used for anything else.
7343 	 *
7344 	 *  When looking up variables by name, the '_Varmap' map is used.
7345 	 *  When an activation closes, registers mapped to arguments are
7346 	 *  copied into the environment record based on the same map.  The
7347 	 *  reverse map (from register to variable) is not currently needed
7348 	 *  at run time, except for debugging, so it is not maintained.
7349 	 */
7350 
7351 	duk_uint16_t nregs;                /* regs to allocate */
7352 	duk_uint16_t nargs;                /* number of arguments allocated to regs */
7353 
7354 	/*
7355 	 *  Additional control information is placed into the object itself
7356 	 *  as internal properties to avoid unnecessary fields for the
7357 	 *  majority of functions.  The compiler tries to omit internal
7358 	 *  control fields when possible.
7359 	 *
7360 	 *  Function templates:
7361 	 *
7362 	 *    {
7363 	 *      name: "func",    // declaration, named function expressions
7364 	 *      fileName: <debug info for creating nice errors>
7365 	 *      _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
7366 	 *      _Formals: [ "arg1", "arg2" ],
7367 	 *      _Source: "function func(arg1, arg2) { ... }",
7368 	 *      _Pc2line: <debug info for pc-to-line mapping>,
7369 	 *    }
7370 	 *
7371 	 *  Function instances:
7372 	 *
7373 	 *    {
7374 	 *      length: 2,
7375 	 *      prototype: { constructor: <func> },
7376 	 *      caller: <thrower>,
7377 	 *      arguments: <thrower>,
7378 	 *      name: "func",    // declaration, named function expressions
7379 	 *      fileName: <debug info for creating nice errors>
7380 	 *      _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
7381 	 *      _Formals: [ "arg1", "arg2" ],
7382 	 *      _Source: "function func(arg1, arg2) { ... }",
7383 	 *      _Pc2line: <debug info for pc-to-line mapping>,
7384 	 *    }
7385 	 *
7386 	 *  More detailed description of these properties can be found
7387 	 *  in the documentation.
7388 	 */
7389 
7390 #if defined(DUK_USE_DEBUGGER_SUPPORT)
7391 	/* Line number range for function.  Needed during debugging to
7392 	 * determine active breakpoints.
7393 	 */
7394 	duk_uint32_t start_line;
7395 	duk_uint32_t end_line;
7396 #endif
7397 };
7398 
7399 #endif  /* DUK_HCOMPFUNC_H_INCLUDED */
7400 /* #include duk_hnatfunc.h */
7401 #line 1 "duk_hnatfunc.h"
7402 /*
7403  *  Heap native function representation.
7404  */
7405 
7406 #if !defined(DUK_HNATFUNC_H_INCLUDED)
7407 #define DUK_HNATFUNC_H_INCLUDED
7408 
7409 #if defined(DUK_USE_ASSERTIONS)
7410 DUK_INTERNAL_DECL void duk_hnatfunc_assert_valid(duk_hnatfunc *h);
7411 #define DUK_HNATFUNC_ASSERT_VALID(h)  do { duk_hnatfunc_assert_valid((h)); } while (0)
7412 #else
7413 #define DUK_HNATFUNC_ASSERT_VALID(h)  do {} while (0)
7414 #endif
7415 
7416 #define DUK_HNATFUNC_NARGS_VARARGS  ((duk_int16_t) -1)
7417 #define DUK_HNATFUNC_NARGS_MAX      ((duk_int16_t) 0x7fff)
7418 
7419 struct duk_hnatfunc {
7420 	/* shared object part */
7421 	duk_hobject obj;
7422 
7423 	duk_c_function func;
7424 	duk_int16_t nargs;
7425 	duk_int16_t magic;
7426 
7427 	/* The 'magic' field allows an opaque 16-bit field to be accessed by the
7428 	 * Duktape/C function.  This allows, for instance, the same native function
7429 	 * to be used for a set of very similar functions, with the 'magic' field
7430 	 * providing the necessary non-argument flags / values to guide the behavior
7431 	 * of the native function.  The value is signed on purpose: it is easier to
7432 	 * convert a signed value to unsigned (simply AND with 0xffff) than vice
7433 	 * versa.
7434 	 *
7435 	 * Note: cannot place nargs/magic into the heaphdr flags, because
7436 	 * duk_hobject takes almost all flags already.
7437 	 */
7438 };
7439 
7440 #endif  /* DUK_HNATFUNC_H_INCLUDED */
7441 /* #include duk_hboundfunc.h */
7442 #line 1 "duk_hboundfunc.h"
7443 /*
7444  *  Bound function representation.
7445  */
7446 
7447 #if !defined(DUK_HBOUNDFUNC_H_INCLUDED)
7448 #define DUK_HBOUNDFUNC_H_INCLUDED
7449 
7450 /* Artificial limit for args length.  Ensures arithmetic won't overflow
7451  * 32 bits when combining bound functions.
7452  */
7453 #define DUK_HBOUNDFUNC_MAX_ARGS 0x20000000UL
7454 
7455 #if defined(DUK_USE_ASSERTIONS)
7456 DUK_INTERNAL_DECL void duk_hboundfunc_assert_valid(duk_hboundfunc *h);
7457 #define DUK_HBOUNDFUNC_ASSERT_VALID(h)  do { duk_hboundfunc_assert_valid((h)); } while (0)
7458 #else
7459 #define DUK_HBOUNDFUNC_ASSERT_VALID(h)  do {} while (0)
7460 #endif
7461 
7462 struct duk_hboundfunc {
7463 	/* Shared object part. */
7464 	duk_hobject obj;
7465 
7466 	/* Final target function, stored as duk_tval so that lightfunc can be
7467 	 * represented too.
7468 	 */
7469 	duk_tval target;
7470 
7471 	/* This binding. */
7472 	duk_tval this_binding;
7473 
7474 	/* Arguments to prepend. */
7475 	duk_tval *args;  /* Separate allocation. */
7476 	duk_idx_t nargs;
7477 };
7478 
7479 #endif  /* DUK_HBOUNDFUNC_H_INCLUDED */
7480 /* #include duk_hbufobj.h */
7481 #line 1 "duk_hbufobj.h"
7482 /*
7483  *  Heap Buffer object representation.  Used for all Buffer variants.
7484  */
7485 
7486 #if !defined(DUK_HBUFOBJ_H_INCLUDED)
7487 #define DUK_HBUFOBJ_H_INCLUDED
7488 
7489 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
7490 
7491 /* All element accessors are host endian now (driven by TypedArray spec). */
7492 #define DUK_HBUFOBJ_ELEM_UINT8           0
7493 #define DUK_HBUFOBJ_ELEM_UINT8CLAMPED    1
7494 #define DUK_HBUFOBJ_ELEM_INT8            2
7495 #define DUK_HBUFOBJ_ELEM_UINT16          3
7496 #define DUK_HBUFOBJ_ELEM_INT16           4
7497 #define DUK_HBUFOBJ_ELEM_UINT32          5
7498 #define DUK_HBUFOBJ_ELEM_INT32           6
7499 #define DUK_HBUFOBJ_ELEM_FLOAT32         7
7500 #define DUK_HBUFOBJ_ELEM_FLOAT64         8
7501 #define DUK_HBUFOBJ_ELEM_MAX             8
7502 
7503 #if defined(DUK_USE_ASSERTIONS)
7504 DUK_INTERNAL_DECL void duk_hbufobj_assert_valid(duk_hbufobj *h);
7505 #define DUK_HBUFOBJ_ASSERT_VALID(h)  do { duk_hbufobj_assert_valid((h)); } while (0)
7506 #else
7507 #define DUK_HBUFOBJ_ASSERT_VALID(h)  do {} while (0)
7508 #endif
7509 
7510 /* Get the current data pointer (caller must ensure buf != NULL) as a
7511  * duk_uint8_t ptr.  Note that the result may be NULL if the underlying
7512  * buffer has zero size and is not a fixed buffer.
7513  */
7514 #define DUK_HBUFOBJ_GET_SLICE_BASE(heap,h) \
7515 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7516 	(((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR((heap), (h)->buf)) + (h)->offset))
7517 
7518 /* True if slice is full, i.e. offset is zero and length covers the entire
7519  * buffer.  This status may change independently of the duk_hbufobj if
7520  * the underlying buffer is dynamic and changes without the hbufobj
7521  * being changed.
7522  */
7523 #define DUK_HBUFOBJ_FULL_SLICE(h) \
7524 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7525 	((h)->offset == 0 && (h)->length == DUK_HBUFFER_GET_SIZE((h)->buf)))
7526 
7527 /* Validate that the whole slice [0,length[ is contained in the underlying
7528  * buffer.  Caller must ensure 'buf' != NULL.
7529  */
7530 #define DUK_HBUFOBJ_VALID_SLICE(h) \
7531 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7532 	((h)->offset + (h)->length <= DUK_HBUFFER_GET_SIZE((h)->buf)))
7533 
7534 /* Validate byte read/write for virtual 'offset', i.e. check that the
7535  * offset, taking into account h->offset, is within the underlying
7536  * buffer size.  This is a safety check which is needed to ensure
7537  * that even a misconfigured duk_hbufobj never causes memory unsafe
7538  * behavior (e.g. if an underlying dynamic buffer changes after being
7539  * setup).  Caller must ensure 'buf' != NULL.
7540  */
7541 #define DUK_HBUFOBJ_VALID_BYTEOFFSET_INCL(h,off) \
7542 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7543 	((h)->offset + (off) < DUK_HBUFFER_GET_SIZE((h)->buf)))
7544 
7545 #define DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h,off) \
7546 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7547 	((h)->offset + (off) <= DUK_HBUFFER_GET_SIZE((h)->buf)))
7548 
7549 /* Clamp an input byte length (already assumed to be within the nominal
7550  * duk_hbufobj 'length') to the current dynamic buffer limits to yield
7551  * a byte length limit that's safe for memory accesses.  This value can
7552  * be invalidated by any side effect because it may trigger a user
7553  * callback that resizes the underlying buffer.
7554  */
7555 #define DUK_HBUFOBJ_CLAMP_BYTELENGTH(h,len) \
7556 	(DUK_ASSERT_EXPR((h) != NULL), \
7557 	duk_hbufobj_clamp_bytelength((h), (len)))
7558 
7559 /* Typed arrays have virtual indices, ArrayBuffer and DataView do not. */
7560 #define DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h)  ((h)->is_typedarray)
7561 
7562 struct duk_hbufobj {
7563 	/* Shared object part. */
7564 	duk_hobject obj;
7565 
7566 	/* Underlying buffer (refcounted), may be NULL. */
7567 	duk_hbuffer *buf;
7568 
7569 	/* .buffer reference to an ArrayBuffer, may be NULL. */
7570 	duk_hobject *buf_prop;
7571 
7572 	/* Slice and accessor information.
7573 	 *
7574 	 * Because the underlying buffer may be dynamic, these may be
7575 	 * invalidated by the buffer being modified so that both offset
7576 	 * and length should be validated before every access.  Behavior
7577 	 * when the underlying buffer has changed doesn't need to be clean:
7578 	 * virtual 'length' doesn't need to be affected, reads can return
7579 	 * zero/NaN, and writes can be ignored.
7580 	 *
7581 	 * Note that a data pointer cannot be precomputed because 'buf' may
7582 	 * be dynamic and its pointer unstable.
7583 	 */
7584 
7585 	duk_uint_t offset;       /* byte offset to buf */
7586 	duk_uint_t length;       /* byte index limit for element access, exclusive */
7587 	duk_uint8_t shift;       /* element size shift:
7588 	                          *   0 = u8/i8
7589 	                          *   1 = u16/i16
7590 	                          *   2 = u32/i32/float
7591 	                          *   3 = double
7592 	                          */
7593 	duk_uint8_t elem_type;   /* element type */
7594 	duk_uint8_t is_typedarray;
7595 };
7596 
7597 DUK_INTERNAL_DECL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_uint_t len);
7598 DUK_INTERNAL_DECL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_hbuffer *h_buf);
7599 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);
7600 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);
7601 DUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx);
7602 
7603 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
7604 
7605 /* nothing */
7606 
7607 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
7608 #endif  /* DUK_HBUFOBJ_H_INCLUDED */
7609 /* #include duk_hthread.h */
7610 #line 1 "duk_hthread.h"
7611 /*
7612  *  Heap thread object representation.
7613  *
7614  *  duk_hthread is also the 'context' for public API functions via a
7615  *  different typedef.  Most API calls operate on the topmost frame
7616  *  of the value stack only.
7617  */
7618 
7619 #if !defined(DUK_HTHREAD_H_INCLUDED)
7620 #define DUK_HTHREAD_H_INCLUDED
7621 
7622 /*
7623  *  Stack constants
7624  */
7625 
7626 /* Initial valstack size, roughly 0.7kiB. */
7627 #define DUK_VALSTACK_INITIAL_SIZE       96U
7628 
7629 /* Internal extra elements assumed on function entry, always added to
7630  * user-defined 'extra' for e.g. the duk_check_stack() call.
7631  */
7632 #define DUK_VALSTACK_INTERNAL_EXTRA     32U
7633 
7634 /* Number of elements guaranteed to be user accessible (in addition to call
7635  * arguments) on Duktape/C function entry.  This is the major public API
7636  * commitment.
7637  */
7638 #define DUK_VALSTACK_API_ENTRY_MINIMUM  DUK_API_ENTRY_STACK
7639 
7640 /*
7641  *  Activation defines
7642  */
7643 
7644 #define DUK_ACT_FLAG_STRICT             (1U << 0)  /* function executes in strict mode */
7645 #define DUK_ACT_FLAG_TAILCALLED         (1U << 1)  /* activation has tail called one or more times */
7646 #define DUK_ACT_FLAG_CONSTRUCT          (1U << 2)  /* function executes as a constructor (called via "new") */
7647 #define DUK_ACT_FLAG_PREVENT_YIELD      (1U << 3)  /* activation prevents yield (native call or "new") */
7648 #define DUK_ACT_FLAG_DIRECT_EVAL        (1U << 4)  /* activation is a direct eval call */
7649 #define DUK_ACT_FLAG_CONSTRUCT_PROXY    (1U << 5)  /* activation is for Proxy 'construct' call, special return value handling */
7650 #define DUK_ACT_FLAG_BREAKPOINT_ACTIVE  (1U << 6)  /* activation has active breakpoint(s) */
7651 
7652 #define DUK_ACT_GET_FUNC(act)           ((act)->func)
7653 
7654 /*
7655  *  Flags for __FILE__ / __LINE__ registered into tracedata
7656  */
7657 
7658 #define DUK_TB_FLAG_NOBLAME_FILELINE    (1U << 0)  /* don't report __FILE__ / __LINE__ as fileName/lineNumber */
7659 
7660 /*
7661  *  Catcher defines
7662  */
7663 
7664 /* XXX: remove catcher type entirely */
7665 
7666 /* flags field: LLLLLLFT, L = label (24 bits), F = flags (4 bits), T = type (4 bits) */
7667 #define DUK_CAT_TYPE_MASK            0x0000000fUL
7668 #define DUK_CAT_TYPE_BITS            4
7669 #define DUK_CAT_LABEL_MASK           0xffffff00UL
7670 #define DUK_CAT_LABEL_BITS           24
7671 #define DUK_CAT_LABEL_SHIFT          8
7672 
7673 #define DUK_CAT_FLAG_CATCH_ENABLED          (1U << 4)   /* catch part will catch */
7674 #define DUK_CAT_FLAG_FINALLY_ENABLED        (1U << 5)   /* finally part will catch */
7675 #define DUK_CAT_FLAG_CATCH_BINDING_ENABLED  (1U << 6)   /* request to create catch binding */
7676 #define DUK_CAT_FLAG_LEXENV_ACTIVE          (1U << 7)   /* catch or with binding is currently active */
7677 
7678 #define DUK_CAT_TYPE_UNKNOWN         0
7679 #define DUK_CAT_TYPE_TCF             1
7680 #define DUK_CAT_TYPE_LABEL           2
7681 
7682 #define DUK_CAT_GET_TYPE(c)          ((c)->flags & DUK_CAT_TYPE_MASK)
7683 #define DUK_CAT_GET_LABEL(c)         (((c)->flags & DUK_CAT_LABEL_MASK) >> DUK_CAT_LABEL_SHIFT)
7684 
7685 #define DUK_CAT_HAS_CATCH_ENABLED(c)           ((c)->flags & DUK_CAT_FLAG_CATCH_ENABLED)
7686 #define DUK_CAT_HAS_FINALLY_ENABLED(c)         ((c)->flags & DUK_CAT_FLAG_FINALLY_ENABLED)
7687 #define DUK_CAT_HAS_CATCH_BINDING_ENABLED(c)   ((c)->flags & DUK_CAT_FLAG_CATCH_BINDING_ENABLED)
7688 #define DUK_CAT_HAS_LEXENV_ACTIVE(c)           ((c)->flags & DUK_CAT_FLAG_LEXENV_ACTIVE)
7689 
7690 #define DUK_CAT_SET_CATCH_ENABLED(c)    do { \
7691 		(c)->flags |= DUK_CAT_FLAG_CATCH_ENABLED; \
7692 	} while (0)
7693 #define DUK_CAT_SET_FINALLY_ENABLED(c)  do { \
7694 		(c)->flags |= DUK_CAT_FLAG_FINALLY_ENABLED; \
7695 	} while (0)
7696 #define DUK_CAT_SET_CATCH_BINDING_ENABLED(c)    do { \
7697 		(c)->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
7698 	} while (0)
7699 #define DUK_CAT_SET_LEXENV_ACTIVE(c)    do { \
7700 		(c)->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE; \
7701 	} while (0)
7702 
7703 #define DUK_CAT_CLEAR_CATCH_ENABLED(c)    do { \
7704 		(c)->flags &= ~DUK_CAT_FLAG_CATCH_ENABLED; \
7705 	} while (0)
7706 #define DUK_CAT_CLEAR_FINALLY_ENABLED(c)  do { \
7707 		(c)->flags &= ~DUK_CAT_FLAG_FINALLY_ENABLED; \
7708 	} while (0)
7709 #define DUK_CAT_CLEAR_CATCH_BINDING_ENABLED(c)    do { \
7710 		(c)->flags &= ~DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
7711 	} while (0)
7712 #define DUK_CAT_CLEAR_LEXENV_ACTIVE(c)    do { \
7713 		(c)->flags &= ~DUK_CAT_FLAG_LEXENV_ACTIVE; \
7714 	} while (0)
7715 
7716 /*
7717  *  Thread defines
7718  */
7719 
7720 #if defined(DUK_USE_ROM_STRINGS)
7721 #define DUK_HTHREAD_GET_STRING(thr,idx) \
7722 	((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
7723 #else  /* DUK_USE_ROM_STRINGS */
7724 #if defined(DUK_USE_HEAPPTR16)
7725 #define DUK_HTHREAD_GET_STRING(thr,idx) \
7726 	((duk_hstring *) DUK_USE_HEAPPTR_DEC16((thr)->heap->heap_udata, (thr)->strs16[(idx)]))
7727 #else
7728 #define DUK_HTHREAD_GET_STRING(thr,idx) \
7729 	((thr)->strs[(idx)])
7730 #endif
7731 #endif  /* DUK_USE_ROM_STRINGS */
7732 
7733 /* values for the state field */
7734 #define DUK_HTHREAD_STATE_INACTIVE     1   /* thread not currently running */
7735 #define DUK_HTHREAD_STATE_RUNNING      2   /* thread currently running (only one at a time) */
7736 #define DUK_HTHREAD_STATE_RESUMED      3   /* thread resumed another thread (active but not running) */
7737 #define DUK_HTHREAD_STATE_YIELDED      4   /* thread has yielded */
7738 #define DUK_HTHREAD_STATE_TERMINATED   5   /* thread has terminated */
7739 
7740 /* Executor interrupt default interval when nothing else requires a
7741  * smaller value.  The default interval must be small enough to allow
7742  * for reasonable execution timeout checking but large enough to keep
7743  * impact on execution performance low.
7744  */
7745 #if defined(DUK_USE_INTERRUPT_COUNTER)
7746 #define DUK_HTHREAD_INTCTR_DEFAULT     (256L * 1024L)
7747 #endif
7748 
7749 /*
7750  *  Assert context is valid: non-NULL pointer, fields look sane.
7751  *
7752  *  This is used by public API call entrypoints to catch invalid 'ctx' pointers
7753  *  as early as possible; invalid 'ctx' pointers cause very odd and difficult to
7754  *  diagnose behavior so it's worth checking even when the check is not 100%.
7755  */
7756 
7757 #if defined(DUK_USE_ASSERTIONS)
7758 /* Assertions for internals. */
7759 DUK_INTERNAL_DECL void duk_hthread_assert_valid(duk_hthread *thr);
7760 #define DUK_HTHREAD_ASSERT_VALID(thr)  do { duk_hthread_assert_valid((thr)); } while (0)
7761 
7762 /* Assertions for public API calls; a bit stronger. */
7763 DUK_INTERNAL_DECL void duk_ctx_assert_valid(duk_hthread *thr);
7764 #define DUK_CTX_ASSERT_VALID(thr)  do { duk_ctx_assert_valid((thr)); } while (0)
7765 #else
7766 #define DUK_HTHREAD_ASSERT_VALID(thr)  do {} while (0)
7767 #define DUK_CTX_ASSERT_VALID(thr)  do {} while (0)
7768 #endif
7769 
7770 /* Assertions for API call entry specifically.  Checks 'ctx' but also may
7771  * check internal state (e.g. not in a debugger transport callback).
7772  */
7773 #define DUK_ASSERT_API_ENTRY(thr) do { \
7774 		DUK_CTX_ASSERT_VALID((thr)); \
7775 		DUK_ASSERT((thr)->heap != NULL); \
7776 		DUK_ASSERT((thr)->heap->dbg_calling_transport == 0); \
7777 	} while (0)
7778 
7779 /*
7780  *  Assertion helpers.
7781  */
7782 
7783 #define DUK_ASSERT_STRIDX_VALID(val) \
7784 	DUK_ASSERT((duk_uint_t) (val) < DUK_HEAP_NUM_STRINGS)
7785 
7786 #define DUK_ASSERT_BIDX_VALID(val) \
7787 	DUK_ASSERT((duk_uint_t) (val) < DUK_NUM_BUILTINS)
7788 
7789 /*
7790  *  Misc
7791  */
7792 
7793 /* Fast access to 'this' binding.  Assumes there's a call in progress. */
7794 #define DUK_HTHREAD_THIS_PTR(thr) \
7795 	(DUK_ASSERT_EXPR((thr) != NULL), \
7796 	 DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \
7797 	 (thr)->valstack_bottom - 1)
7798 
7799 /*
7800  *  Struct defines
7801  */
7802 
7803 /* Fields are ordered for alignment/packing. */
7804 struct duk_activation {
7805 	duk_tval tv_func;       /* borrowed: full duk_tval for function being executed; for lightfuncs */
7806 	duk_hobject *func;      /* borrowed: function being executed; for bound function calls, this is the final, real function, NULL for lightfuncs */
7807 	duk_activation *parent; /* previous (parent) activation (or NULL if none) */
7808 	duk_hobject *var_env;   /* current variable environment (may be NULL if delayed) */
7809 	duk_hobject *lex_env;   /* current lexical environment (may be NULL if delayed) */
7810 	duk_catcher *cat;       /* current catcher (or NULL) */
7811 
7812 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
7813 	/* Previous value of 'func' caller, restored when unwound.  Only in use
7814 	 * when 'func' is non-strict.
7815 	 */
7816 	duk_hobject *prev_caller;
7817 #endif
7818 
7819 	duk_instr_t *curr_pc;   /* next instruction to execute (points to 'func' bytecode, stable pointer), NULL for native calls */
7820 
7821 	/* bottom_byteoff and retval_byteoff are only used for book-keeping
7822 	 * of ECMAScript-initiated calls, to allow returning to an ECMAScript
7823 	 * function properly.
7824 	 */
7825 
7826 	/* Bottom of valstack for this activation, used to reset
7827 	 * valstack_bottom on return; offset is absolute.  There's
7828 	 * no need to track 'top' because native call handling deals
7829 	 * with that using locals, and for ECMAScript returns 'nregs'
7830 	 * indicates the necessary top.
7831 	 */
7832 	duk_size_t bottom_byteoff;
7833 
7834 	/* Return value when returning to this activation (points to caller
7835 	 * reg, not callee reg); offset is absolute (only set if activation is
7836 	 * not topmost).
7837 	 *
7838 	 * Note: bottom_byteoff is always set, while retval_byteoff is only
7839 	 * applicable for activations below the topmost one.  Currently
7840 	 * retval_byteoff for the topmost activation is considered garbage
7841 	 * (and it not initialized on entry or cleared on return; may contain
7842 	 * previous or garbage values).
7843 	 */
7844 	duk_size_t retval_byteoff;
7845 
7846 	/* Current 'this' binding is the value just below bottom.
7847 	 * Previously, 'this' binding was handled with an index to the
7848 	 * (calling) valstack.  This works for everything except tail
7849 	 * calls, which must not "accumulate" valstack temps.
7850 	 */
7851 
7852 	/* Value stack reserve (valstack_end) byte offset to be restored
7853 	 * when returning to this activation.  Only used by the bytecode
7854 	 * executor.
7855 	 */
7856 	duk_size_t reserve_byteoff;
7857 
7858 #if defined(DUK_USE_DEBUGGER_SUPPORT)
7859 	duk_uint32_t prev_line; /* needed for stepping */
7860 #endif
7861 
7862 	duk_small_uint_t flags;
7863 };
7864 
7865 struct duk_catcher {
7866 	duk_catcher *parent;            /* previous (parent) catcher (or NULL if none) */
7867 	duk_hstring *h_varname;         /* borrowed reference to catch variable name (or NULL if none) */
7868 	                                /* (reference is valid as long activation exists) */
7869 	duk_instr_t *pc_base;           /* resume execution from pc_base or pc_base+1 (points to 'func' bytecode, stable pointer) */
7870 	duk_size_t idx_base;            /* idx_base and idx_base+1 get completion value and type */
7871 	duk_uint32_t flags;             /* type and control flags, label number */
7872 	/* XXX: could pack 'flags' and 'idx_base' to same value in practice,
7873 	 * on 32-bit targets this would make duk_catcher 16 bytes.
7874 	 */
7875 };
7876 
7877 struct duk_hthread {
7878 	/* Shared object part */
7879 	duk_hobject obj;
7880 
7881 	/* Pointer to bytecode executor's 'curr_pc' variable.  Used to copy
7882 	 * the current PC back into the topmost activation when activation
7883 	 * state is about to change (or "syncing" is otherwise needed).  This
7884 	 * is rather awkward but important for performance, see execution.rst.
7885 	 */
7886 	duk_instr_t **ptr_curr_pc;
7887 
7888 	/* Backpointers. */
7889 	duk_heap *heap;
7890 
7891 	/* Current strictness flag: affects API calls. */
7892 	duk_uint8_t strict;
7893 
7894 	/* Thread state. */
7895 	duk_uint8_t state;
7896 	duk_uint8_t unused1;
7897 	duk_uint8_t unused2;
7898 
7899 	/* XXX: Valstack and callstack are currently assumed to have non-NULL
7900 	 * pointers.  Relaxing this would not lead to big benefits (except
7901 	 * perhaps for terminated threads).
7902 	 */
7903 
7904 	/* Value stack: these are expressed as pointers for faster stack
7905 	 * manipulation.  [valstack,valstack_top[ is GC-reachable,
7906 	 * [valstack_top,valstack_alloc_end[ is not GC-reachable but kept
7907 	 * initialized as 'undefined'.  [valstack,valstack_end[ is the
7908 	 * guaranteed/reserved space and the valstack cannot be resized to
7909 	 * a smaller size.  [valstack_end,valstack_alloc_end[ is currently
7910 	 * allocated slack that can be used to grow the current guaranteed
7911 	 * space but may be shrunk away without notice.
7912 	 *
7913 	 *
7914 	 * <----------------------- guaranteed --->
7915 	 *                                        <---- slack --->
7916 	 *               <--- frame --->
7917 	 * .-------------+=============+----------+--------------.
7918 	 * |xxxxxxxxxxxxx|yyyyyyyyyyyyy|uuuuuuuuuu|uuuuuuuuuuuuuu|
7919 	 * `-------------+=============+----------+--------------'
7920 	 *
7921 	 * ^             ^             ^          ^              ^
7922 	 * |             |             |          |              |
7923 	 * valstack      bottom        top        end            alloc_end
7924 	 *
7925 	 *     xxx = arbitrary values, below current frame
7926 	 *     yyy = arbitrary values, inside current frame
7927 	 *     uuu = outside active value stack, initialized to 'undefined'
7928 	 */
7929 	duk_tval *valstack;                     /* start of valstack allocation */
7930 	duk_tval *valstack_end;                 /* end of valstack reservation/guarantee (exclusive) */
7931 	duk_tval *valstack_alloc_end;           /* end of valstack allocation */
7932 	duk_tval *valstack_bottom;              /* bottom of current frame */
7933 	duk_tval *valstack_top;                 /* top of current frame (exclusive) */
7934 
7935 	/* Call stack, represented as a linked list starting from the current
7936 	 * activation (or NULL if nothing is active).
7937 	 */
7938 	duk_activation *callstack_curr;         /* current activation (or NULL if none) */
7939 	duk_size_t callstack_top;               /* number of activation records in callstack (0 if none) */
7940 	duk_size_t callstack_preventcount;      /* number of activation records in callstack preventing a yield */
7941 
7942 	/* Yield/resume book-keeping. */
7943 	duk_hthread *resumer;                   /* who resumed us (if any) */
7944 
7945 	/* Current compiler state (if any), used for augmenting SyntaxErrors. */
7946 	duk_compiler_ctx *compile_ctx;
7947 
7948 #if defined(DUK_USE_INTERRUPT_COUNTER)
7949 	/* Interrupt counter for triggering a slow path check for execution
7950 	 * timeout, debugger interaction such as breakpoints, etc.  The value
7951 	 * is valid for the current running thread, and both the init and
7952 	 * counter values are copied whenever a thread switch occurs.  It's
7953 	 * important for the counter to be conveniently accessible for the
7954 	 * bytecode executor inner loop for performance reasons.
7955 	 */
7956 	duk_int_t interrupt_counter;    /* countdown state */
7957 	duk_int_t interrupt_init;       /* start value for current countdown */
7958 #endif
7959 
7960 	/* Builtin-objects; may or may not be shared with other threads,
7961 	 * threads existing in different "compartments" will have different
7962 	 * built-ins.  Must be stored on a per-thread basis because there
7963 	 * is no intermediate structure for a thread group / compartment.
7964 	 * This takes quite a lot of space, currently 43x4 = 172 bytes on
7965 	 * 32-bit platforms.
7966 	 *
7967 	 * In some cases the builtins array could be ROM based, but it's
7968 	 * sometimes edited (e.g. for sandboxing) so it's better to keep
7969 	 * this array in RAM.
7970 	 */
7971 	duk_hobject *builtins[DUK_NUM_BUILTINS];
7972 
7973 	/* Convenience copies from heap/vm for faster access. */
7974 #if defined(DUK_USE_ROM_STRINGS)
7975 	/* No field needed when strings are in ROM. */
7976 #else
7977 #if defined(DUK_USE_HEAPPTR16)
7978 	duk_uint16_t *strs16;
7979 #else
7980 	duk_hstring **strs;
7981 #endif
7982 #endif
7983 };
7984 
7985 /*
7986  *  Prototypes
7987  */
7988 
7989 DUK_INTERNAL_DECL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to);
7990 DUK_INTERNAL_DECL void duk_hthread_create_builtin_objects(duk_hthread *thr);
7991 DUK_INTERNAL_DECL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr);
7992 DUK_INTERNAL_DECL void duk_hthread_terminate(duk_hthread *thr);
7993 
7994 DUK_INTERNAL_DECL duk_activation *duk_hthread_activation_alloc(duk_hthread *thr);
7995 DUK_INTERNAL_DECL void duk_hthread_activation_free(duk_hthread *thr, duk_activation *act);
7996 DUK_INTERNAL_DECL void duk_hthread_activation_unwind_norz(duk_hthread *thr);
7997 DUK_INTERNAL_DECL void duk_hthread_activation_unwind_reuse_norz(duk_hthread *thr);
7998 DUK_INTERNAL_DECL duk_activation *duk_hthread_get_activation_for_level(duk_hthread *thr, duk_int_t level);
7999 
8000 DUK_INTERNAL_DECL duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr);
8001 DUK_INTERNAL_DECL void duk_hthread_catcher_free(duk_hthread *thr, duk_catcher *cat);
8002 DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_norz(duk_hthread *thr, duk_activation *act);
8003 DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_nolexenv_norz(duk_hthread *thr, duk_activation *act);
8004 
8005 #if defined(DUK_USE_FINALIZER_TORTURE)
8006 DUK_INTERNAL_DECL void duk_hthread_valstack_torture_realloc(duk_hthread *thr);
8007 #endif
8008 
8009 DUK_INTERNAL_DECL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud);  /* indirect allocs */
8010 
8011 #if defined(DUK_USE_DEBUGGER_SUPPORT)
8012 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act);
8013 #endif
8014 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act);
8015 DUK_INTERNAL_DECL void duk_hthread_sync_currpc(duk_hthread *thr);
8016 DUK_INTERNAL_DECL void duk_hthread_sync_and_null_currpc(duk_hthread *thr);
8017 
8018 #endif  /* DUK_HTHREAD_H_INCLUDED */
8019 /* #include duk_harray.h */
8020 #line 1 "duk_harray.h"
8021 /*
8022  *  Array object representation, used for actual Array instances.
8023  *
8024  *  All objects with the exotic array behavior (which must coincide with having
8025  *  internal class array) MUST be duk_harrays.  No other object can be a
8026  *  duk_harray.  However, duk_harrays may not always have an array part.
8027  */
8028 
8029 #if !defined(DUK_HARRAY_H_INCLUDED)
8030 #define DUK_HARRAY_H_INCLUDED
8031 
8032 #if defined(DUK_USE_ASSERTIONS)
8033 DUK_INTERNAL_DECL void duk_harray_assert_valid(duk_harray *h);
8034 #define DUK_HARRAY_ASSERT_VALID(h)  do { duk_harray_assert_valid((h)); } while (0)
8035 #else
8036 #define DUK_HARRAY_ASSERT_VALID(h)  do {} while (0)
8037 #endif
8038 
8039 #define DUK_HARRAY_LENGTH_WRITABLE(h)         (!(h)->length_nonwritable)
8040 #define DUK_HARRAY_LENGTH_NONWRITABLE(h)      ((h)->length_nonwritable)
8041 #define DUK_HARRAY_SET_LENGTH_WRITABLE(h)     do { (h)->length_nonwritable = 0; } while (0)
8042 #define DUK_HARRAY_SET_LENGTH_NONWRITABLE(h)  do { (h)->length_nonwritable = 1; } while (0)
8043 
8044 struct duk_harray {
8045 	/* Shared object part. */
8046 	duk_hobject obj;
8047 
8048 	/* Array .length.
8049 	 *
8050 	 * At present Array .length may be smaller, equal, or even larger
8051 	 * than the allocated underlying array part.  Fast path code must
8052 	 * always take this into account carefully.
8053 	 */
8054 	duk_uint32_t length;
8055 
8056 	/* Array .length property attributes.  The property is always
8057 	 * non-enumerable and non-configurable.  It's initially writable
8058 	 * but per Object.defineProperty() rules it can be made non-writable
8059 	 * even if it is non-configurable.  Thus we need to track the
8060 	 * writability explicitly.
8061 	 *
8062 	 * XXX: this field to be eliminated and moved into duk_hobject
8063 	 * flags field to save space.
8064 	 */
8065 	duk_bool_t length_nonwritable;
8066 };
8067 
8068 #endif  /* DUK_HARRAY_H_INCLUDED */
8069 /* #include duk_henv.h */
8070 #line 1 "duk_henv.h"
8071 /*
8072  *  Environment object representation.
8073  */
8074 
8075 #if !defined(DUK_HENV_H_INCLUDED)
8076 #define DUK_HENV_H_INCLUDED
8077 
8078 #if defined(DUK_USE_ASSERTIONS)
8079 DUK_INTERNAL_DECL void duk_hdecenv_assert_valid(duk_hdecenv *h);
8080 DUK_INTERNAL_DECL void duk_hobjenv_assert_valid(duk_hobjenv *h);
8081 #define DUK_HDECENV_ASSERT_VALID(h)  do { duk_hdecenv_assert_valid((h)); } while (0)
8082 #define DUK_HOBJENV_ASSERT_VALID(h)  do { duk_hobjenv_assert_valid((h)); } while (0)
8083 #else
8084 #define DUK_HDECENV_ASSERT_VALID(h)  do {} while (0)
8085 #define DUK_HOBJENV_ASSERT_VALID(h)  do {} while (0)
8086 #endif
8087 
8088 struct duk_hdecenv {
8089 	/* Shared object part. */
8090 	duk_hobject obj;
8091 
8092 	/* These control variables provide enough information to access live
8093 	 * variables for a closure that is still open.  If thread == NULL,
8094 	 * the record is closed and the identifiers are in the property table.
8095 	 */
8096 	duk_hthread *thread;
8097 	duk_hobject *varmap;
8098 	duk_size_t regbase_byteoff;
8099 };
8100 
8101 struct duk_hobjenv {
8102 	/* Shared object part. */
8103 	duk_hobject obj;
8104 
8105 	/* Target object and 'this' binding for object binding. */
8106 	duk_hobject *target;
8107 
8108 	/* The 'target' object is used as a this binding in only some object
8109 	 * environments.  For example, the global environment does not provide
8110 	 * a this binding, but a with statement does.
8111 	 */
8112 	duk_bool_t has_this;
8113 };
8114 
8115 #endif  /* DUK_HENV_H_INCLUDED */
8116 /* #include duk_hbuffer.h */
8117 #line 1 "duk_hbuffer.h"
8118 /*
8119  *  Heap buffer representation.
8120  *
8121  *  Heap allocated user data buffer which is either:
8122  *
8123  *    1. A fixed size buffer (data follows header statically)
8124  *    2. A dynamic size buffer (data pointer follows header)
8125  *
8126  *  The data pointer for a variable size buffer of zero size may be NULL.
8127  */
8128 
8129 #if !defined(DUK_HBUFFER_H_INCLUDED)
8130 #define DUK_HBUFFER_H_INCLUDED
8131 
8132 /*
8133  *  Flags
8134  *
8135  *  Fixed buffer:     0
8136  *  Dynamic buffer:   DUK_HBUFFER_FLAG_DYNAMIC
8137  *  External buffer:  DUK_HBUFFER_FLAG_DYNAMIC | DUK_HBUFFER_FLAG_EXTERNAL
8138  */
8139 
8140 #define DUK_HBUFFER_FLAG_DYNAMIC                  DUK_HEAPHDR_USER_FLAG(0)    /* buffer is behind a pointer, dynamic or external */
8141 #define DUK_HBUFFER_FLAG_EXTERNAL                 DUK_HEAPHDR_USER_FLAG(1)    /* buffer pointer is to an externally allocated buffer */
8142 
8143 #define DUK_HBUFFER_HAS_DYNAMIC(x)                DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
8144 #define DUK_HBUFFER_HAS_EXTERNAL(x)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
8145 
8146 #define DUK_HBUFFER_SET_DYNAMIC(x)                DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
8147 #define DUK_HBUFFER_SET_EXTERNAL(x)               DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
8148 
8149 #define DUK_HBUFFER_CLEAR_DYNAMIC(x)              DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
8150 #define DUK_HBUFFER_CLEAR_EXTERNAL(x)             DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
8151 
8152 /*
8153  *  Misc defines
8154  */
8155 
8156 /* Impose a maximum buffer length for now.  Restricted artificially to
8157  * ensure resize computations or adding a heap header length won't
8158  * overflow size_t and that a signed duk_int_t can hold a buffer
8159  * length.  The limit should be synchronized with DUK_HSTRING_MAX_BYTELEN.
8160  */
8161 
8162 #if defined(DUK_USE_BUFLEN16)
8163 #define DUK_HBUFFER_MAX_BYTELEN                   (0x0000ffffUL)
8164 #else
8165 /* Intentionally not 0x7fffffffUL; at least JSON code expects that
8166  * 2*len + 2 fits in 32 bits.
8167  */
8168 #define DUK_HBUFFER_MAX_BYTELEN                   (0x7ffffffeUL)
8169 #endif
8170 
8171 /*
8172  *  Field access
8173  */
8174 
8175 #if defined(DUK_USE_BUFLEN16)
8176 /* size stored in duk_heaphdr unused flag bits */
8177 #define DUK_HBUFFER_GET_SIZE(x)     ((x)->hdr.h_flags >> 16)
8178 #define DUK_HBUFFER_SET_SIZE(x,v)   do { \
8179 		duk_size_t duk__v; \
8180 		duk__v = (v); \
8181 		DUK_ASSERT(duk__v <= 0xffffUL); \
8182 		(x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | (((duk_uint32_t) duk__v) << 16); \
8183 	} while (0)
8184 #define DUK_HBUFFER_ADD_SIZE(x,dv)  do { \
8185 		(x)->hdr.h_flags += ((dv) << 16); \
8186 	} while (0)
8187 #define DUK_HBUFFER_SUB_SIZE(x,dv)  do { \
8188 		(x)->hdr.h_flags -= ((dv) << 16); \
8189 	} while (0)
8190 #else
8191 #define DUK_HBUFFER_GET_SIZE(x)     (((duk_hbuffer *) (x))->size)
8192 #define DUK_HBUFFER_SET_SIZE(x,v)   do { \
8193 		((duk_hbuffer *) (x))->size = (v); \
8194 	} while (0)
8195 #define DUK_HBUFFER_ADD_SIZE(x,dv)  do { \
8196 		(x)->size += (dv); \
8197 	} while (0)
8198 #define DUK_HBUFFER_SUB_SIZE(x,dv)  do { \
8199 		(x)->size -= (dv); \
8200 	} while (0)
8201 #endif
8202 
8203 #define DUK_HBUFFER_FIXED_GET_SIZE(x)       DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
8204 #define DUK_HBUFFER_FIXED_SET_SIZE(x,v)     DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x))
8205 
8206 #define DUK_HBUFFER_DYNAMIC_GET_SIZE(x)     DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
8207 #define DUK_HBUFFER_DYNAMIC_SET_SIZE(x,v)   DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
8208 #define DUK_HBUFFER_DYNAMIC_ADD_SIZE(x,dv)  DUK_HBUFFER_ADD_SIZE((duk_hbuffer *) (x), (dv))
8209 #define DUK_HBUFFER_DYNAMIC_SUB_SIZE(x,dv)  DUK_HBUFFER_SUB_SIZE((duk_hbuffer *) (x), (dv))
8210 
8211 #define DUK_HBUFFER_EXTERNAL_GET_SIZE(x)    DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
8212 #define DUK_HBUFFER_EXTERNAL_SET_SIZE(x,v)  DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
8213 
8214 #define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap,x)    ((duk_uint8_t *) (((duk_hbuffer_fixed *) (void *) (x)) + 1))
8215 
8216 #if defined(DUK_USE_HEAPPTR16)
8217 #define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) \
8218 	((void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (x))->h_extra16))
8219 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v)     do { \
8220 		((duk_heaphdr *) (x))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
8221 	} while (0)
8222 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x)  do { \
8223 		((duk_heaphdr *) (x))->h_extra16 = 0;  /* assume 0 <=> NULL */ \
8224 	} while (0)
8225 #else
8226 #define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x)       ((x)->curr_alloc)
8227 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v)     do { \
8228 		(x)->curr_alloc = (void *) (v); \
8229 	} while (0)
8230 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x)  do { \
8231 		(x)->curr_alloc = (void *) NULL; \
8232 	} while (0)
8233 #endif
8234 
8235 /* No pointer compression because pointer is potentially outside of
8236  * Duktape heap.
8237  */
8238 #if defined(DUK_USE_HEAPPTR16)
8239 #define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
8240 	((void *) (x)->curr_alloc)
8241 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v)     do { \
8242 		(x)->curr_alloc = (void *) (v); \
8243 	} while (0)
8244 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x)  do { \
8245 		(x)->curr_alloc = (void *) NULL; \
8246 	} while (0)
8247 #else
8248 #define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
8249 	((void *) (x)->curr_alloc)
8250 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v)     do { \
8251 		(x)->curr_alloc = (void *) (v); \
8252 	} while (0)
8253 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x)  do { \
8254 		(x)->curr_alloc = (void *) NULL; \
8255 	} while (0)
8256 #endif
8257 
8258 /* Get a pointer to the current buffer contents (matching current allocation
8259  * size).  May be NULL for zero size dynamic/external buffer.
8260  */
8261 #if defined(DUK_USE_HEAPPTR16)
8262 #define DUK_HBUFFER_GET_DATA_PTR(heap,x)  ( \
8263 	DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
8264 		( \
8265 			DUK_HBUFFER_HAS_EXTERNAL((x)) ? \
8266 				DUK_HBUFFER_EXTERNAL_GET_DATA_PTR((heap), (duk_hbuffer_external *) (x)) : \
8267 				DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) \
8268 		) : \
8269 		DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (void *) (x)) \
8270 	)
8271 #else
8272 /* Without heap pointer compression duk_hbuffer_dynamic and duk_hbuffer_external
8273  * have the same layout so checking for fixed vs. dynamic (or external) is enough.
8274  */
8275 #define DUK_HBUFFER_GET_DATA_PTR(heap,x)  ( \
8276 	DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
8277 		DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) : \
8278 		DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (void *) (x)) \
8279 	)
8280 #endif
8281 
8282 /* Validity assert. */
8283 #if defined(DUK_USE_ASSERTIONS)
8284 DUK_INTERNAL_DECL void duk_hbuffer_assert_valid(duk_hbuffer *h);
8285 #define DUK_HBUFFER_ASSERT_VALID(h)  do { duk_hbuffer_assert_valid((h)); } while (0)
8286 #else
8287 #define DUK_HBUFFER_ASSERT_VALID(h)  do {} while (0)
8288 #endif
8289 
8290 /*
8291  *  Structs
8292  */
8293 
8294 /* Shared prefix for all buffer types. */
8295 struct duk_hbuffer {
8296 	duk_heaphdr hdr;
8297 
8298 	/* It's not strictly necessary to track the current size, but
8299 	 * it is useful for writing robust native code.
8300 	 */
8301 
8302 	/* Current size. */
8303 #if defined(DUK_USE_BUFLEN16)
8304 	/* Stored in duk_heaphdr unused flags. */
8305 #else
8306 	duk_size_t size;
8307 #endif
8308 
8309 	/*
8310 	 *  Data following the header depends on the DUK_HBUFFER_FLAG_DYNAMIC
8311 	 *  flag.
8312 	 *
8313 	 *  If the flag is clear (the buffer is a fixed size one), the buffer
8314 	 *  data follows the header directly, consisting of 'size' bytes.
8315 	 *
8316 	 *  If the flag is set, the actual buffer is allocated separately, and
8317 	 *  a few control fields follow the header.  Specifically:
8318 	 *
8319 	 *    - a "void *" pointing to the current allocation
8320 	 *    - a duk_size_t indicating the full allocated size (always >= 'size')
8321 	 *
8322 	 *  If DUK_HBUFFER_FLAG_EXTERNAL is set, the buffer has been allocated
8323 	 *  by user code, so that Duktape won't be able to resize it and won't
8324 	 *  free it.  This allows buffers to point to e.g. an externally
8325 	 *  allocated structure such as a frame buffer.
8326 	 *
8327 	 *  Unlike strings, no terminator byte (NUL) is guaranteed after the
8328 	 *  data.  This would be convenient, but would pad aligned user buffers
8329 	 *  unnecessarily upwards in size.  For instance, if user code requested
8330 	 *  a 64-byte dynamic buffer, 65 bytes would actually be allocated which
8331 	 *  would then potentially round upwards to perhaps 68 or 72 bytes.
8332 	 */
8333 };
8334 
8335 /* Fixed buffer; data follows struct, with proper alignment guaranteed by
8336  * struct size.
8337  */
8338 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
8339 #pragma pack(push, 8)
8340 #endif
8341 struct duk_hbuffer_fixed {
8342 	/* A union is used here as a portable struct size / alignment trick:
8343 	 * by adding a 32-bit or a 64-bit (unused) union member, the size of
8344 	 * the struct is effectively forced to be a multiple of 4 or 8 bytes
8345 	 * (respectively) without increasing the size of the struct unless
8346 	 * necessary.
8347 	 */
8348 	union {
8349 		struct {
8350 			duk_heaphdr hdr;
8351 #if defined(DUK_USE_BUFLEN16)
8352 			/* Stored in duk_heaphdr unused flags. */
8353 #else
8354 			duk_size_t size;
8355 #endif
8356 		} s;
8357 #if (DUK_USE_ALIGN_BY == 4)
8358 		duk_uint32_t dummy_for_align4;
8359 #elif (DUK_USE_ALIGN_BY == 8)
8360 		duk_double_t dummy_for_align8_1;
8361 #if defined(DUK_USE_64BIT_OPS)
8362 		duk_uint64_t dummy_for_align8_2;
8363 #endif
8364 #elif (DUK_USE_ALIGN_BY == 1)
8365 		/* no extra padding */
8366 #else
8367 #error invalid DUK_USE_ALIGN_BY
8368 #endif
8369 	} u;
8370 
8371 	/*
8372 	 *  Data follows the struct header.  The struct size is padded by the
8373 	 *  compiler based on the struct members.  This guarantees that the
8374 	 *  buffer data will be aligned-by-4 but not necessarily aligned-by-8.
8375 	 *
8376 	 *  On platforms where alignment does not matter, the struct padding
8377 	 *  could be removed (if there is any).  On platforms where alignment
8378 	 *  by 8 is required, the struct size must be forced to be a multiple
8379 	 *  of 8 by some means.  Without it, some user code may break, and also
8380 	 *  Duktape itself breaks (e.g. the compiler stores duk_tvals in a
8381 	 *  dynamic buffer).
8382 	 */
8383 }
8384 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR)
8385 __attribute__ ((aligned (8)))
8386 #elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR)
8387 __attribute__ ((aligned (8)))
8388 #endif
8389 ;
8390 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
8391 #pragma pack(pop)
8392 #endif
8393 
8394 /* Dynamic buffer with 'curr_alloc' pointing to a dynamic area allocated using
8395  * heap allocation primitives.  Also used for external buffers when low memory
8396  * options are not used.
8397  */
8398 struct duk_hbuffer_dynamic {
8399 	duk_heaphdr hdr;
8400 
8401 #if defined(DUK_USE_BUFLEN16)
8402 	/* Stored in duk_heaphdr unused flags. */
8403 #else
8404 	duk_size_t size;
8405 #endif
8406 
8407 #if defined(DUK_USE_HEAPPTR16)
8408 	/* Stored in duk_heaphdr h_extra16. */
8409 #else
8410 	void *curr_alloc;  /* may be NULL if alloc_size == 0 */
8411 #endif
8412 
8413 	/*
8414 	 *  Allocation size for 'curr_alloc' is alloc_size.  There is no
8415 	 *  automatic NUL terminator for buffers (see above for rationale).
8416 	 *
8417 	 *  'curr_alloc' is explicitly allocated with heap allocation
8418 	 *  primitives and will thus always have alignment suitable for
8419 	 *  e.g. duk_tval and an IEEE double.
8420 	 */
8421 };
8422 
8423 /* External buffer with 'curr_alloc' managed by user code and pointing to an
8424  * arbitrary address.  When heap pointer compression is not used, this struct
8425  * has the same layout as duk_hbuffer_dynamic.
8426  */
8427 struct duk_hbuffer_external {
8428 	duk_heaphdr hdr;
8429 
8430 #if defined(DUK_USE_BUFLEN16)
8431 	/* Stored in duk_heaphdr unused flags. */
8432 #else
8433 	duk_size_t size;
8434 #endif
8435 
8436 	/* Cannot be compressed as a heap pointer because may point to
8437 	 * an arbitrary address.
8438 	 */
8439 	void *curr_alloc;  /* may be NULL if alloc_size == 0 */
8440 };
8441 
8442 /*
8443  *  Prototypes
8444  */
8445 
8446 DUK_INTERNAL_DECL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata);
8447 DUK_INTERNAL_DECL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud);  /* indirect allocs */
8448 
8449 /* dynamic buffer ops */
8450 DUK_INTERNAL_DECL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size);
8451 DUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf);
8452 
8453 #endif  /* DUK_HBUFFER_H_INCLUDED */
8454 /* #include duk_hproxy.h */
8455 #line 1 "duk_hproxy.h"
8456 /*
8457  *  Proxy object representation.
8458  */
8459 
8460 #if !defined(DUK_HPROXY_H_INCLUDED)
8461 #define DUK_HPROXY_H_INCLUDED
8462 
8463 #if defined(DUK_USE_ASSERTIONS)
8464 DUK_INTERNAL_DECL void duk_hproxy_assert_valid(duk_hproxy *h);
8465 #define DUK_HPROXY_ASSERT_VALID(h)  do { duk_hproxy_assert_valid((h)); } while (0)
8466 #else
8467 #define DUK_HPROXY_ASSERT_VALID(h)  do {} while (0)
8468 #endif
8469 
8470 struct duk_hproxy {
8471 	/* Shared object part. */
8472 	duk_hobject obj;
8473 
8474 	/* Proxy target object. */
8475 	duk_hobject *target;
8476 
8477 	/* Proxy handlers (traps). */
8478 	duk_hobject *handler;
8479 };
8480 
8481 #endif  /* DUK_HPROXY_H_INCLUDED */
8482 /* #include duk_heap.h */
8483 #line 1 "duk_heap.h"
8484 /*
8485  *  Heap structure.
8486  *
8487  *  Heap contains allocated heap objects, interned strings, and built-in
8488  *  strings for one or more threads.
8489  */
8490 
8491 #if !defined(DUK_HEAP_H_INCLUDED)
8492 #define DUK_HEAP_H_INCLUDED
8493 
8494 /* alloc function typedefs in duktape.h */
8495 
8496 /*
8497  *  Heap flags
8498  */
8499 
8500 #define DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED            (1U << 0)  /* mark-and-sweep marking reached a recursion limit and must use multi-pass marking */
8501 #define DUK_HEAP_FLAG_INTERRUPT_RUNNING                        (1U << 1)  /* executor interrupt running (used to avoid nested interrupts) */
8502 #define DUK_HEAP_FLAG_FINALIZER_NORESCUE                       (1U << 2)  /* heap destruction ongoing, finalizer rescue no longer possible */
8503 #define DUK_HEAP_FLAG_DEBUGGER_PAUSED                          (1U << 3)  /* debugger is paused: talk with debug client until step/resume */
8504 
8505 #define DUK__HEAP_HAS_FLAGS(heap,bits)               ((heap)->flags & (bits))
8506 #define DUK__HEAP_SET_FLAGS(heap,bits)  do { \
8507 		(heap)->flags |= (bits); \
8508 	} while (0)
8509 #define DUK__HEAP_CLEAR_FLAGS(heap,bits)  do { \
8510 		(heap)->flags &= ~(bits); \
8511 	} while (0)
8512 
8513 #define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)   DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
8514 #define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap)               DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
8515 #define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap)              DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
8516 #define DUK_HEAP_HAS_DEBUGGER_PAUSED(heap)                 DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
8517 
8518 #define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap)   DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
8519 #define DUK_HEAP_SET_INTERRUPT_RUNNING(heap)               DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
8520 #define DUK_HEAP_SET_FINALIZER_NORESCUE(heap)              DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
8521 #define DUK_HEAP_SET_DEBUGGER_PAUSED(heap)                 DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
8522 
8523 #define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
8524 #define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap)             DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
8525 #define DUK_HEAP_CLEAR_FINALIZER_NORESCUE(heap)            DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
8526 #define DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap)               DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
8527 
8528 /*
8529  *  Longjmp types, also double as identifying continuation type for a rethrow (in 'finally')
8530  */
8531 
8532 #define DUK_LJ_TYPE_UNKNOWN      0    /* unused */
8533 #define DUK_LJ_TYPE_THROW        1    /* value1 -> error object */
8534 #define DUK_LJ_TYPE_YIELD        2    /* value1 -> yield value, iserror -> error / normal */
8535 #define DUK_LJ_TYPE_RESUME       3    /* value1 -> resume value, value2 -> resumee thread, iserror -> error/normal */
8536 #define DUK_LJ_TYPE_BREAK        4    /* value1 -> label number, pseudo-type to indicate a break continuation (for ENDFIN) */
8537 #define DUK_LJ_TYPE_CONTINUE     5    /* value1 -> label number, pseudo-type to indicate a continue continuation (for ENDFIN) */
8538 #define DUK_LJ_TYPE_RETURN       6    /* value1 -> return value, pseudo-type to indicate a return continuation (for ENDFIN) */
8539 #define DUK_LJ_TYPE_NORMAL       7    /* no value, pseudo-type to indicate a normal continuation (for ENDFIN) */
8540 
8541 /*
8542  *  Mark-and-sweep flags
8543  *
8544  *  These are separate from heap level flags now but could be merged.
8545  *  The heap structure only contains a 'base mark-and-sweep flags'
8546  *  field and the GC caller can impose further flags.
8547  */
8548 
8549 /* Emergency mark-and-sweep: try extra hard, even at the cost of
8550  * performance.
8551  */
8552 #define DUK_MS_FLAG_EMERGENCY                (1U << 0)
8553 
8554 /* Postpone rescue decisions for reachable objects with FINALIZED set.
8555  * Used during finalize_list processing to avoid incorrect rescue
8556  * decisions due to finalize_list being a reachability root.
8557  */
8558 #define DUK_MS_FLAG_POSTPONE_RESCUE          (1U << 1)
8559 
8560 /* Don't compact objects; needed during object property table resize
8561  * to prevent a recursive resize.  It would suffice to protect only the
8562  * current object being resized, but this is not yet implemented.
8563  */
8564 #define DUK_MS_FLAG_NO_OBJECT_COMPACTION     (1U << 2)
8565 
8566 /*
8567  *  Thread switching
8568  *
8569  *  To switch heap->curr_thread, use the macro below so that interrupt counters
8570  *  get updated correctly.  The macro allows a NULL target thread because that
8571  *  happens e.g. in call handling.
8572  */
8573 
8574 #if defined(DUK_USE_INTERRUPT_COUNTER)
8575 #define DUK_HEAP_SWITCH_THREAD(heap,newthr)  duk_heap_switch_thread((heap), (newthr))
8576 #else
8577 #define DUK_HEAP_SWITCH_THREAD(heap,newthr)  do { \
8578 		(heap)->curr_thread = (newthr); \
8579 	} while (0)
8580 #endif
8581 
8582 /*
8583  *  Stats
8584  */
8585 
8586 #if defined(DUK_USE_DEBUG)
8587 #define DUK_STATS_INC(heap,fieldname) do { \
8588 		(heap)->fieldname += 1; \
8589 	} while (0)
8590 #else
8591 #define DUK_STATS_INC(heap,fieldname) do {} while (0)
8592 #endif
8593 
8594 /*
8595  *  Other heap related defines
8596  */
8597 
8598 /* Mark-and-sweep interval is relative to combined count of objects and
8599  * strings kept in the heap during the latest mark-and-sweep pass.
8600  * Fixed point .8 multiplier and .0 adder.  Trigger count (interval) is
8601  * decreased by each (re)allocation attempt (regardless of size), and each
8602  * refzero processed object.
8603  *
8604  * 'SKIP' indicates how many (re)allocations to wait until a retry if
8605  * GC is skipped because there is no thread do it with yet (happens
8606  * only during init phases).
8607  */
8608 #if defined(DUK_USE_REFERENCE_COUNTING)
8609 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT              12800L  /* 50x heap size */
8610 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD               1024L
8611 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP              256L
8612 #else
8613 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT              256L    /* 1x heap size */
8614 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD               1024L
8615 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP              256L
8616 #endif
8617 
8618 /* GC torture. */
8619 #if defined(DUK_USE_GC_TORTURE)
8620 #define DUK_GC_TORTURE(heap) do { duk_heap_mark_and_sweep((heap), 0); } while (0)
8621 #else
8622 #define DUK_GC_TORTURE(heap) do { } while (0)
8623 #endif
8624 
8625 /* Stringcache is used for speeding up char-offset-to-byte-offset
8626  * translations for non-ASCII strings.
8627  */
8628 #define DUK_HEAP_STRCACHE_SIZE                            4
8629 #define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT                16  /* strings up to the this length are not cached */
8630 
8631 /* Some list management macros. */
8632 #define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap,hdr)     duk_heap_insert_into_heap_allocated((heap), (hdr))
8633 #if defined(DUK_USE_REFERENCE_COUNTING)
8634 #define DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap,hdr)     duk_heap_remove_from_heap_allocated((heap), (hdr))
8635 #endif
8636 #if defined(DUK_USE_FINALIZER_SUPPORT)
8637 #define DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap,hdr)      duk_heap_insert_into_finalize_list((heap), (hdr))
8638 #define DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(heap,hdr)      duk_heap_remove_from_finalize_list((heap), (hdr))
8639 #endif
8640 
8641 /*
8642  *  Built-in strings
8643  */
8644 
8645 /* heap string indices are autogenerated in duk_strings.h */
8646 #if defined(DUK_USE_ROM_STRINGS)
8647 #define DUK_HEAP_GET_STRING(heap,idx) \
8648 	((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
8649 #else  /* DUK_USE_ROM_STRINGS */
8650 #if defined(DUK_USE_HEAPPTR16)
8651 #define DUK_HEAP_GET_STRING(heap,idx) \
8652 	((duk_hstring *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (heap)->strs16[(idx)]))
8653 #else
8654 #define DUK_HEAP_GET_STRING(heap,idx) \
8655 	((heap)->strs[(idx)])
8656 #endif
8657 #endif  /* DUK_USE_ROM_STRINGS */
8658 
8659 /*
8660  *  Raw memory calls: relative to heap, but no GC interaction
8661  */
8662 
8663 #define DUK_ALLOC_RAW(heap,size) \
8664 	((heap)->alloc_func((heap)->heap_udata, (size)))
8665 
8666 #define DUK_REALLOC_RAW(heap,ptr,newsize) \
8667 	((heap)->realloc_func((heap)->heap_udata, (void *) (ptr), (newsize)))
8668 
8669 #define DUK_FREE_RAW(heap,ptr) \
8670 	((heap)->free_func((heap)->heap_udata, (void *) (ptr)))
8671 
8672 /*
8673  *  Memory calls: relative to heap, GC interaction, but no error throwing.
8674  *
8675  *  XXX: Currently a mark-and-sweep triggered by memory allocation will run
8676  *  using the heap->heap_thread.  This thread is also used for running
8677  *  mark-and-sweep finalization; this is not ideal because it breaks the
8678  *  isolation between multiple global environments.
8679  *
8680  *  Notes:
8681  *
8682  *    - DUK_FREE() is required to ignore NULL and any other possible return
8683  *      value of a zero-sized alloc/realloc (same as ANSI C free()).
8684  *
8685  *    - There is no DUK_REALLOC_ZEROED because we don't assume to know the
8686  *      old size.  Caller must zero the reallocated memory.
8687  *
8688  *    - DUK_REALLOC_INDIRECT() must be used when a mark-and-sweep triggered
8689  *      by an allocation failure might invalidate the original 'ptr', thus
8690  *      causing a realloc retry to use an invalid pointer.  Example: we're
8691  *      reallocating the value stack and a finalizer resizes the same value
8692  *      stack during mark-and-sweep.  The indirect variant requests for the
8693  *      current location of the pointer being reallocated using a callback
8694  *      right before every realloc attempt; this circuitous approach is used
8695  *      to avoid strict aliasing issues in a more straightforward indirect
8696  *      pointer (void **) approach.  Note: the pointer in the storage
8697  *      location is read but is NOT updated; the caller must do that.
8698  */
8699 
8700 /* callback for indirect reallocs, request for current pointer */
8701 typedef void *(*duk_mem_getptr)(duk_heap *heap, void *ud);
8702 
8703 #define DUK_ALLOC(heap,size)                            duk_heap_mem_alloc((heap), (size))
8704 #define DUK_ALLOC_ZEROED(heap,size)                     duk_heap_mem_alloc_zeroed((heap), (size))
8705 #define DUK_REALLOC(heap,ptr,newsize)                   duk_heap_mem_realloc((heap), (ptr), (newsize))
8706 #define DUK_REALLOC_INDIRECT(heap,cb,ud,newsize)        duk_heap_mem_realloc_indirect((heap), (cb), (ud), (newsize))
8707 #define DUK_FREE(heap,ptr)                              duk_heap_mem_free((heap), (ptr))
8708 
8709 /*
8710  *  Checked allocation, relative to a thread
8711  *
8712  *  DUK_FREE_CHECKED() doesn't actually throw, but accepts a 'thr' argument
8713  *  for convenience.
8714  */
8715 
8716 #define DUK_ALLOC_CHECKED(thr,size)                     duk_heap_mem_alloc_checked((thr), (size))
8717 #define DUK_ALLOC_CHECKED_ZEROED(thr,size)              duk_heap_mem_alloc_checked_zeroed((thr), (size))
8718 #define DUK_FREE_CHECKED(thr,ptr)                       duk_heap_mem_free((thr)->heap, (ptr))
8719 
8720 /*
8721  *  Memory constants
8722  */
8723 
8724 #define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT           10  /* Retry allocation after mark-and-sweep for this
8725                                                               * many times.  A single mark-and-sweep round is
8726                                                               * not guaranteed to free all unreferenced memory
8727                                                               * because of finalization (in fact, ANY number of
8728                                                               * rounds is strictly not enough).
8729                                                               */
8730 
8731 #define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT  3  /* Starting from this round, use emergency mode
8732                                                               * for mark-and-sweep.
8733                                                               */
8734 
8735 /*
8736  *  Debugger support
8737  */
8738 
8739 /* Maximum number of breakpoints.  Only breakpoints that are set are
8740  * consulted so increasing this has no performance impact.
8741  */
8742 #define DUK_HEAP_MAX_BREAKPOINTS          16
8743 
8744 /* Opcode interval for a Date-based status/peek rate limit check.  Only
8745  * relevant when debugger is attached.  Requesting a timestamp may be a
8746  * slow operation on some platforms so this shouldn't be too low.  On the
8747  * other hand a high value makes Duktape react to a pause request slowly.
8748  */
8749 #define DUK_HEAP_DBG_RATELIMIT_OPCODES    4000
8750 
8751 /* Milliseconds between status notify and transport peeks. */
8752 #define DUK_HEAP_DBG_RATELIMIT_MILLISECS  200
8753 
8754 /* Debugger pause flags. */
8755 #define DUK_PAUSE_FLAG_ONE_OPCODE        (1U << 0)   /* pause when a single opcode has been executed */
8756 #define DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE (1U << 1)   /* one opcode pause actually active; artifact of current implementation */
8757 #define DUK_PAUSE_FLAG_LINE_CHANGE       (1U << 2)   /* pause when current line number changes */
8758 #define DUK_PAUSE_FLAG_FUNC_ENTRY        (1U << 3)   /* pause when entering a function */
8759 #define DUK_PAUSE_FLAG_FUNC_EXIT         (1U << 4)   /* pause when exiting current function */
8760 #define DUK_PAUSE_FLAG_CAUGHT_ERROR      (1U << 5)   /* pause when about to throw an error that is caught */
8761 #define DUK_PAUSE_FLAG_UNCAUGHT_ERROR    (1U << 6)   /* pause when about to throw an error that won't be caught */
8762 
8763 struct duk_breakpoint {
8764 	duk_hstring *filename;
8765 	duk_uint32_t line;
8766 };
8767 
8768 /*
8769  *  String cache should ideally be at duk_hthread level, but that would
8770  *  cause string finalization to slow down relative to the number of
8771  *  threads; string finalization must check the string cache for "weak"
8772  *  references to the string being finalized to avoid dead pointers.
8773  *
8774  *  Thus, string caches are now at the heap level now.
8775  */
8776 
8777 struct duk_strcache_entry {
8778 	duk_hstring *h;
8779 	duk_uint32_t bidx;
8780 	duk_uint32_t cidx;
8781 };
8782 
8783 /*
8784  *  Longjmp state, contains the information needed to perform a longjmp.
8785  *  Longjmp related values are written to value1, value2, and iserror.
8786  */
8787 
8788 struct duk_ljstate {
8789 	duk_jmpbuf *jmpbuf_ptr;   /* current setjmp() catchpoint */
8790 	duk_small_uint_t type;    /* longjmp type */
8791 	duk_bool_t iserror;       /* isError flag for yield */
8792 	duk_tval value1;          /* 1st related value (type specific) */
8793 	duk_tval value2;          /* 2nd related value (type specific) */
8794 };
8795 
8796 #define DUK_ASSERT_LJSTATE_UNSET(heap) do { \
8797 		DUK_ASSERT(heap != NULL); \
8798 		DUK_ASSERT(heap->lj.type == DUK_LJ_TYPE_UNKNOWN); \
8799 		DUK_ASSERT(heap->lj.iserror == 0); \
8800 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&heap->lj.value1)); \
8801 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&heap->lj.value2)); \
8802 	} while (0)
8803 #define DUK_ASSERT_LJSTATE_SET(heap) do { \
8804 		DUK_ASSERT(heap != NULL); \
8805 		DUK_ASSERT(heap->lj.type != DUK_LJ_TYPE_UNKNOWN); \
8806 	} while (0)
8807 
8808 /*
8809  *  Literal intern cache
8810  */
8811 
8812 struct duk_litcache_entry {
8813 	const duk_uint8_t *addr;
8814 	duk_hstring *h;
8815 };
8816 
8817 /*
8818  *  Main heap structure
8819  */
8820 
8821 #if defined(DUK_USE_ASSERTIONS)
8822 DUK_INTERNAL_DECL void duk_heap_assert_valid(duk_heap *heap);
8823 #define DUK_HEAP_ASSERT_VALID(heap)  do { duk_heap_assert_valid((heap)); } while (0)
8824 #else
8825 #define DUK_HEAP_ASSERT_VALID(heap)  do {} while (0)
8826 #endif
8827 
8828 struct duk_heap {
8829 	duk_small_uint_t flags;
8830 
8831 	/* Allocator functions. */
8832 	duk_alloc_function alloc_func;
8833 	duk_realloc_function realloc_func;
8834 	duk_free_function free_func;
8835 
8836 	/* Heap udata, used for allocator functions but also for other heap
8837 	 * level callbacks like fatal function, pointer compression, etc.
8838 	 */
8839 	void *heap_udata;
8840 
8841 	/* Fatal error handling, called e.g. when a longjmp() is needed but
8842 	 * lj.jmpbuf_ptr is NULL.  fatal_func must never return; it's not
8843 	 * declared as "noreturn" because doing that for typedefs is a bit
8844 	 * challenging portability-wise.
8845 	 */
8846 	duk_fatal_function fatal_func;
8847 
8848 	/* Main list of allocated heap objects.  Objects are either here,
8849 	 * in finalize_list waiting for processing, or in refzero_list
8850 	 * temporarily while a DECREF refzero cascade finishes.
8851 	 */
8852 	duk_heaphdr *heap_allocated;
8853 
8854 	/* Temporary work list for freeing a cascade of objects when a DECREF
8855 	 * (or DECREF_NORZ) encounters a zero refcount.  Using a work list
8856 	 * allows fixed C stack size when refcounts go to zero for a chain of
8857 	 * objects.  Outside of DECREF this is always a NULL because DECREF is
8858 	 * processed without side effects (only memory free calls).
8859 	 */
8860 #if defined(DUK_USE_REFERENCE_COUNTING)
8861 	duk_heaphdr *refzero_list;
8862 #endif
8863 
8864 #if defined(DUK_USE_FINALIZER_SUPPORT)
8865 	/* Work list for objects to be finalized. */
8866 	duk_heaphdr *finalize_list;
8867 #if defined(DUK_USE_ASSERTIONS)
8868 	/* Object whose finalizer is executing right now (no nesting). */
8869 	duk_heaphdr *currently_finalizing;
8870 #endif
8871 #endif
8872 
8873 	/* Freelist for duk_activations and duk_catchers. */
8874 #if defined(DUK_USE_CACHE_ACTIVATION)
8875 	duk_activation *activation_free;
8876 #endif
8877 #if defined(DUK_USE_CACHE_CATCHER)
8878 	duk_catcher *catcher_free;
8879 #endif
8880 
8881 	/* Voluntary mark-and-sweep trigger counter.  Intentionally signed
8882 	 * because we continue decreasing the value when voluntary GC cannot
8883 	 * run.
8884 	 */
8885 #if defined(DUK_USE_VOLUNTARY_GC)
8886 	duk_int_t ms_trigger_counter;
8887 #endif
8888 
8889 	/* Mark-and-sweep recursion control: too deep recursion causes
8890 	 * multi-pass processing to avoid growing C stack without bound.
8891 	 */
8892 	duk_uint_t ms_recursion_depth;
8893 
8894 	/* Mark-and-sweep flags automatically active (used for critical sections). */
8895 	duk_small_uint_t ms_base_flags;
8896 
8897 	/* Mark-and-sweep running flag.  Prevents re-entry, and also causes
8898 	 * refzero events to be ignored (= objects won't be queued to refzero_list).
8899 	 *
8900 	 * 0: mark-and-sweep not running
8901 	 * 1: mark-and-sweep is running
8902 	 * 2: heap destruction active or debugger active, prevent mark-and-sweep
8903 	 *    and refzero processing (but mark-and-sweep not itself running)
8904 	 */
8905 	duk_uint_t ms_running;
8906 
8907 	/* Mark-and-sweep prevent count, stacking.  Used to avoid M&S side
8908 	 * effects (besides finalizers which are controlled separately) such
8909 	 * as compacting the string table or object property tables.  This
8910 	 * is also bumped when ms_running is set to prevent recursive re-entry.
8911 	 * Can also be bumped when mark-and-sweep is not running.
8912 	 */
8913 	duk_uint_t ms_prevent_count;
8914 
8915 	/* Finalizer processing prevent count, stacking.  Bumped when finalizers
8916 	 * are processed to prevent recursive finalizer processing (first call site
8917 	 * processing finalizers handles all finalizers until the list is empty).
8918 	 * Can also be bumped explicitly to prevent finalizer execution.
8919 	 */
8920 	duk_uint_t pf_prevent_count;
8921 
8922 	/* When processing finalize_list, don't actually run finalizers but
8923 	 * queue finalizable objects back to heap_allocated as is.  This is
8924 	 * used during heap destruction to deal with finalizers that keep
8925 	 * on creating more finalizable garbage.
8926 	 */
8927 	duk_uint_t pf_skip_finalizers;
8928 
8929 #if defined(DUK_USE_ASSERTIONS)
8930 	/* Set when we're in a critical path where an error throw would cause
8931 	 * e.g. sandboxing/protected call violations or state corruption.  This
8932 	 * is just used for asserts.
8933 	 */
8934 	duk_bool_t error_not_allowed;
8935 #endif
8936 
8937 #if defined(DUK_USE_ASSERTIONS)
8938 	/* Set when heap is still being initialized, helps with writing
8939 	 * some assertions.
8940 	 */
8941 	duk_bool_t heap_initializing;
8942 #endif
8943 
8944 	/* Marker for detecting internal "double faults", errors thrown when
8945 	 * we're trying to create an error object, see duk_error_throw.c.
8946 	 */
8947 	duk_bool_t creating_error;
8948 
8949 	/* Marker for indicating we're calling a user error augmentation
8950 	 * (errCreate/errThrow) function.  Errors created/thrown during
8951 	 * such a call are not augmented.
8952 	 */
8953 #if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
8954 	duk_bool_t augmenting_error;
8955 #endif
8956 
8957 	/* Longjmp state. */
8958 	duk_ljstate lj;
8959 
8960 	/* Heap thread, used internally and for finalization. */
8961 	duk_hthread *heap_thread;
8962 
8963 	/* Current running thread. */
8964 	duk_hthread *curr_thread;
8965 
8966 	/* Heap level "stash" object (e.g., various reachability roots). */
8967 	duk_hobject *heap_object;
8968 
8969 	/* duk_handle_call / duk_handle_safe_call recursion depth limiting */
8970 	duk_int_t call_recursion_depth;
8971 	duk_int_t call_recursion_limit;
8972 
8973 	/* Mix-in value for computing string hashes; should be reasonably unpredictable. */
8974 	duk_uint32_t hash_seed;
8975 
8976 	/* Random number state for duk_util_tinyrandom.c. */
8977 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
8978 #if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
8979 	duk_uint32_t rnd_state;  /* State for Shamir's three-op algorithm */
8980 #else
8981 	duk_uint64_t rnd_state[2];  /* State for xoroshiro128+ */
8982 #endif
8983 #endif
8984 
8985 	/* Counter for unique local symbol creation. */
8986 	/* XXX: When 64-bit types are available, it would be more efficient to
8987 	 * use a duk_uint64_t at least for incrementing but maybe also for
8988 	 * string formatting in the Symbol constructor.
8989 	 */
8990 	duk_uint32_t sym_counter[2];
8991 
8992 	/* For manual debugging: instruction count based on executor and
8993 	 * interrupt counter book-keeping.  Inspect debug logs to see how
8994 	 * they match up.
8995 	 */
8996 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
8997 	duk_int_t inst_count_exec;
8998 	duk_int_t inst_count_interrupt;
8999 #endif
9000 
9001 	/* Debugger state. */
9002 #if defined(DUK_USE_DEBUGGER_SUPPORT)
9003 	/* Callbacks and udata; dbg_read_cb != NULL is used to indicate attached state. */
9004 	duk_debug_read_function dbg_read_cb;                /* required, NULL implies detached */
9005 	duk_debug_write_function dbg_write_cb;              /* required */
9006 	duk_debug_peek_function dbg_peek_cb;
9007 	duk_debug_read_flush_function dbg_read_flush_cb;
9008 	duk_debug_write_flush_function dbg_write_flush_cb;
9009 	duk_debug_request_function dbg_request_cb;
9010 	duk_debug_detached_function dbg_detached_cb;
9011 	void *dbg_udata;
9012 
9013 	/* The following are only relevant when debugger is attached. */
9014 	duk_bool_t dbg_processing;              /* currently processing messages or breakpoints: don't enter message processing recursively (e.g. no breakpoints when processing debugger eval) */
9015 	duk_bool_t dbg_state_dirty;             /* resend state next time executor is about to run */
9016 	duk_bool_t dbg_force_restart;           /* force executor restart to recheck breakpoints; used to handle function returns (see GH-303) */
9017 	duk_bool_t dbg_detaching;               /* debugger detaching; used to avoid calling detach handler recursively */
9018 	duk_small_uint_t dbg_pause_flags;       /* flags for automatic pause behavior */
9019 	duk_activation *dbg_pause_act;          /* activation related to pause behavior (pause on line change, function entry/exit) */
9020 	duk_uint32_t dbg_pause_startline;       /* starting line number for line change related pause behavior */
9021 	duk_breakpoint dbg_breakpoints[DUK_HEAP_MAX_BREAKPOINTS];  /* breakpoints: [0,breakpoint_count[ gc reachable */
9022 	duk_small_uint_t dbg_breakpoint_count;
9023 	duk_breakpoint *dbg_breakpoints_active[DUK_HEAP_MAX_BREAKPOINTS + 1];  /* currently active breakpoints: NULL term, borrowed pointers */
9024 	/* XXX: make active breakpoints actual copies instead of pointers? */
9025 
9026 	/* These are for rate limiting Status notifications and transport peeking. */
9027 	duk_uint_t dbg_exec_counter;            /* cumulative opcode execution count (overflows are OK) */
9028 	duk_uint_t dbg_last_counter;            /* value of dbg_exec_counter when we last did a Date-based check */
9029 	duk_double_t dbg_last_time;             /* time when status/peek was last done (Date-based rate limit) */
9030 
9031 	/* Used to support single-byte stream lookahead. */
9032 	duk_bool_t dbg_have_next_byte;
9033 	duk_uint8_t dbg_next_byte;
9034 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
9035 #if defined(DUK_USE_ASSERTIONS)
9036 	duk_bool_t dbg_calling_transport;       /* transport call in progress, calling into Duktape forbidden */
9037 #endif
9038 
9039 	/* String intern table (weak refs). */
9040 #if defined(DUK_USE_STRTAB_PTRCOMP)
9041 	duk_uint16_t *strtable16;
9042 #else
9043 	duk_hstring **strtable;
9044 #endif
9045 	duk_uint32_t st_mask;    /* mask for lookup, st_size - 1 */
9046 	duk_uint32_t st_size;    /* stringtable size */
9047 #if (DUK_USE_STRTAB_MINSIZE != DUK_USE_STRTAB_MAXSIZE)
9048 	duk_uint32_t st_count;   /* string count for resize load factor checks */
9049 #endif
9050 	duk_bool_t st_resizing;  /* string table is being resized; avoid recursive resize */
9051 
9052 	/* String access cache (codepoint offset -> byte offset) for fast string
9053 	 * character looping; 'weak' reference which needs special handling in GC.
9054 	 */
9055 	duk_strcache_entry strcache[DUK_HEAP_STRCACHE_SIZE];
9056 
9057 #if defined(DUK_USE_LITCACHE_SIZE)
9058 	/* Literal intern cache.  When enabled, strings interned as literals
9059 	 * (e.g. duk_push_literal()) will be pinned and cached for the lifetime
9060 	 * of the heap.
9061 	 */
9062 	duk_litcache_entry litcache[DUK_USE_LITCACHE_SIZE];
9063 #endif
9064 
9065 	/* Built-in strings. */
9066 #if defined(DUK_USE_ROM_STRINGS)
9067 	/* No field needed when strings are in ROM. */
9068 #else
9069 #if defined(DUK_USE_HEAPPTR16)
9070 	duk_uint16_t strs16[DUK_HEAP_NUM_STRINGS];
9071 #else
9072 	duk_hstring *strs[DUK_HEAP_NUM_STRINGS];
9073 #endif
9074 #endif
9075 
9076 	/* Stats. */
9077 #if defined(DUK_USE_DEBUG)
9078 	duk_int_t stats_exec_opcodes;
9079 	duk_int_t stats_exec_interrupt;
9080 	duk_int_t stats_exec_throw;
9081 	duk_int_t stats_call_all;
9082 	duk_int_t stats_call_tailcall;
9083 	duk_int_t stats_call_ecmatoecma;
9084 	duk_int_t stats_safecall_all;
9085 	duk_int_t stats_safecall_nothrow;
9086 	duk_int_t stats_safecall_throw;
9087 	duk_int_t stats_ms_try_count;
9088 	duk_int_t stats_ms_skip_count;
9089 	duk_int_t stats_ms_emergency_count;
9090 	duk_int_t stats_strtab_intern_hit;
9091 	duk_int_t stats_strtab_intern_miss;
9092 	duk_int_t stats_strtab_resize_check;
9093 	duk_int_t stats_strtab_resize_grow;
9094 	duk_int_t stats_strtab_resize_shrink;
9095 	duk_int_t stats_strtab_litcache_hit;
9096 	duk_int_t stats_strtab_litcache_miss;
9097 	duk_int_t stats_strtab_litcache_pin;
9098 	duk_int_t stats_object_realloc_props;
9099 	duk_int_t stats_object_abandon_array;
9100 	duk_int_t stats_getownpropdesc_count;
9101 	duk_int_t stats_getownpropdesc_hit;
9102 	duk_int_t stats_getownpropdesc_miss;
9103 	duk_int_t stats_getpropdesc_count;
9104 	duk_int_t stats_getpropdesc_hit;
9105 	duk_int_t stats_getpropdesc_miss;
9106 	duk_int_t stats_getprop_all;
9107 	duk_int_t stats_getprop_arrayidx;
9108 	duk_int_t stats_getprop_bufobjidx;
9109 	duk_int_t stats_getprop_bufferidx;
9110 	duk_int_t stats_getprop_bufferlen;
9111 	duk_int_t stats_getprop_stringidx;
9112 	duk_int_t stats_getprop_stringlen;
9113 	duk_int_t stats_getprop_proxy;
9114 	duk_int_t stats_getprop_arguments;
9115 	duk_int_t stats_putprop_all;
9116 	duk_int_t stats_putprop_arrayidx;
9117 	duk_int_t stats_putprop_bufobjidx;
9118 	duk_int_t stats_putprop_bufferidx;
9119 	duk_int_t stats_putprop_proxy;
9120 	duk_int_t stats_getvar_all;
9121 	duk_int_t stats_putvar_all;
9122 	duk_int_t stats_envrec_delayedcreate;
9123 	duk_int_t stats_envrec_create;
9124 	duk_int_t stats_envrec_newenv;
9125 	duk_int_t stats_envrec_oldenv;
9126 	duk_int_t stats_envrec_pushclosure;
9127 #endif
9128 };
9129 
9130 /*
9131  *  Prototypes
9132  */
9133 
9134 DUK_INTERNAL_DECL
9135 duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
9136                          duk_realloc_function realloc_func,
9137                          duk_free_function free_func,
9138                          void *heap_udata,
9139                          duk_fatal_function fatal_func);
9140 DUK_INTERNAL_DECL void duk_heap_free(duk_heap *heap);
9141 DUK_INTERNAL_DECL void duk_free_hobject(duk_heap *heap, duk_hobject *h);
9142 DUK_INTERNAL_DECL void duk_free_hbuffer(duk_heap *heap, duk_hbuffer *h);
9143 DUK_INTERNAL_DECL void duk_free_hstring(duk_heap *heap, duk_hstring *h);
9144 DUK_INTERNAL_DECL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr);
9145 
9146 DUK_INTERNAL_DECL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);
9147 #if defined(DUK_USE_REFERENCE_COUNTING)
9148 DUK_INTERNAL_DECL void duk_heap_remove_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);
9149 #endif
9150 #if defined(DUK_USE_FINALIZER_SUPPORT)
9151 DUK_INTERNAL_DECL void duk_heap_insert_into_finalize_list(duk_heap *heap, duk_heaphdr *hdr);
9152 DUK_INTERNAL_DECL void duk_heap_remove_from_finalize_list(duk_heap *heap, duk_heaphdr *hdr);
9153 #endif
9154 #if defined(DUK_USE_ASSERTIONS)
9155 DUK_INTERNAL_DECL duk_bool_t duk_heap_in_heap_allocated(duk_heap *heap, duk_heaphdr *ptr);
9156 #endif
9157 #if defined(DUK_USE_INTERRUPT_COUNTER)
9158 DUK_INTERNAL_DECL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr);
9159 #endif
9160 
9161 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen);
9162 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t len);
9163 #if defined(DUK_USE_LITCACHE_SIZE)
9164 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_literal_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen);
9165 #endif
9166 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_u32(duk_heap *heap, duk_uint32_t val);
9167 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_u32_checked(duk_hthread *thr, duk_uint32_t val);
9168 #if defined(DUK_USE_REFERENCE_COUNTING)
9169 DUK_INTERNAL_DECL void duk_heap_strtable_unlink(duk_heap *heap, duk_hstring *h);
9170 #endif
9171 DUK_INTERNAL_DECL void duk_heap_strtable_unlink_prev(duk_heap *heap, duk_hstring *h, duk_hstring *prev);
9172 DUK_INTERNAL_DECL void duk_heap_strtable_force_resize(duk_heap *heap);
9173 DUK_INTERNAL void duk_heap_strtable_free(duk_heap *heap);
9174 #if defined(DUK_USE_DEBUG)
9175 DUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap);
9176 #endif
9177 
9178 DUK_INTERNAL_DECL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h);
9179 DUK_INTERNAL_DECL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset);
9180 
9181 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
9182 DUK_INTERNAL_DECL void *duk_default_alloc_function(void *udata, duk_size_t size);
9183 DUK_INTERNAL_DECL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize);
9184 DUK_INTERNAL_DECL void duk_default_free_function(void *udata, void *ptr);
9185 #endif
9186 
9187 DUK_INTERNAL_DECL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size);
9188 DUK_INTERNAL_DECL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size);
9189 DUK_INTERNAL_DECL void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size);
9190 DUK_INTERNAL_DECL void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size);
9191 DUK_INTERNAL_DECL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize);
9192 DUK_INTERNAL_DECL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize);
9193 DUK_INTERNAL_DECL void duk_heap_mem_free(duk_heap *heap, void *ptr);
9194 
9195 DUK_INTERNAL_DECL void duk_heap_free_freelists(duk_heap *heap);
9196 
9197 #if defined(DUK_USE_FINALIZER_SUPPORT)
9198 DUK_INTERNAL_DECL void duk_heap_run_finalizer(duk_heap *heap, duk_hobject *obj);
9199 DUK_INTERNAL_DECL void duk_heap_process_finalize_list(duk_heap *heap);
9200 #endif  /* DUK_USE_FINALIZER_SUPPORT */
9201 
9202 DUK_INTERNAL_DECL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags);
9203 
9204 DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len);
9205 
9206 #endif  /* DUK_HEAP_H_INCLUDED */
9207 /* #include duk_debugger.h */
9208 #line 1 "duk_debugger.h"
9209 #if !defined(DUK_DEBUGGER_H_INCLUDED)
9210 #define DUK_DEBUGGER_H_INCLUDED
9211 
9212 /* Debugger protocol version is defined in the public API header. */
9213 
9214 /* Initial bytes for markers. */
9215 #define DUK_DBG_IB_EOM                   0x00
9216 #define DUK_DBG_IB_REQUEST               0x01
9217 #define DUK_DBG_IB_REPLY                 0x02
9218 #define DUK_DBG_IB_ERROR                 0x03
9219 #define DUK_DBG_IB_NOTIFY                0x04
9220 
9221 /* Other initial bytes. */
9222 #define DUK_DBG_IB_INT4                  0x10
9223 #define DUK_DBG_IB_STR4                  0x11
9224 #define DUK_DBG_IB_STR2                  0x12
9225 #define DUK_DBG_IB_BUF4                  0x13
9226 #define DUK_DBG_IB_BUF2                  0x14
9227 #define DUK_DBG_IB_UNUSED                0x15
9228 #define DUK_DBG_IB_UNDEFINED             0x16
9229 #define DUK_DBG_IB_NULL                  0x17
9230 #define DUK_DBG_IB_TRUE                  0x18
9231 #define DUK_DBG_IB_FALSE                 0x19
9232 #define DUK_DBG_IB_NUMBER                0x1a
9233 #define DUK_DBG_IB_OBJECT                0x1b
9234 #define DUK_DBG_IB_POINTER               0x1c
9235 #define DUK_DBG_IB_LIGHTFUNC             0x1d
9236 #define DUK_DBG_IB_HEAPPTR               0x1e
9237 /* The short string/integer initial bytes starting from 0x60 don't have
9238  * defines now.
9239  */
9240 
9241 /* Error codes. */
9242 #define DUK_DBG_ERR_UNKNOWN              0x00
9243 #define DUK_DBG_ERR_UNSUPPORTED          0x01
9244 #define DUK_DBG_ERR_TOOMANY              0x02
9245 #define DUK_DBG_ERR_NOTFOUND             0x03
9246 #define DUK_DBG_ERR_APPLICATION          0x04
9247 
9248 /* Commands and notifys initiated by Duktape. */
9249 #define DUK_DBG_CMD_STATUS               0x01
9250 #define DUK_DBG_CMD_UNUSED_2             0x02  /* Duktape 1.x: print notify */
9251 #define DUK_DBG_CMD_UNUSED_3             0x03  /* Duktape 1.x: alert notify */
9252 #define DUK_DBG_CMD_UNUSED_4             0x04  /* Duktape 1.x: log notify */
9253 #define DUK_DBG_CMD_THROW                0x05
9254 #define DUK_DBG_CMD_DETACHING            0x06
9255 #define DUK_DBG_CMD_APPNOTIFY            0x07
9256 
9257 /* Commands initiated by debug client. */
9258 #define DUK_DBG_CMD_BASICINFO            0x10
9259 #define DUK_DBG_CMD_TRIGGERSTATUS        0x11
9260 #define DUK_DBG_CMD_PAUSE                0x12
9261 #define DUK_DBG_CMD_RESUME               0x13
9262 #define DUK_DBG_CMD_STEPINTO             0x14
9263 #define DUK_DBG_CMD_STEPOVER             0x15
9264 #define DUK_DBG_CMD_STEPOUT              0x16
9265 #define DUK_DBG_CMD_LISTBREAK            0x17
9266 #define DUK_DBG_CMD_ADDBREAK             0x18
9267 #define DUK_DBG_CMD_DELBREAK             0x19
9268 #define DUK_DBG_CMD_GETVAR               0x1a
9269 #define DUK_DBG_CMD_PUTVAR               0x1b
9270 #define DUK_DBG_CMD_GETCALLSTACK         0x1c
9271 #define DUK_DBG_CMD_GETLOCALS            0x1d
9272 #define DUK_DBG_CMD_EVAL                 0x1e
9273 #define DUK_DBG_CMD_DETACH               0x1f
9274 #define DUK_DBG_CMD_DUMPHEAP             0x20
9275 #define DUK_DBG_CMD_GETBYTECODE          0x21
9276 #define DUK_DBG_CMD_APPREQUEST           0x22
9277 #define DUK_DBG_CMD_GETHEAPOBJINFO       0x23
9278 #define DUK_DBG_CMD_GETOBJPROPDESC       0x24
9279 #define DUK_DBG_CMD_GETOBJPROPDESCRANGE  0x25
9280 
9281 /* The low 8 bits map directly to duk_hobject.h DUK_PROPDESC_FLAG_xxx.
9282  * The remaining flags are specific to the debugger.
9283  */
9284 #define DUK_DBG_PROPFLAG_SYMBOL          (1U << 8)
9285 #define DUK_DBG_PROPFLAG_HIDDEN          (1U << 9)
9286 
9287 #if defined(DUK_USE_DEBUGGER_SUPPORT)
9288 DUK_INTERNAL_DECL void duk_debug_do_detach(duk_heap *heap);
9289 
9290 DUK_INTERNAL_DECL duk_bool_t duk_debug_read_peek(duk_hthread *thr);
9291 DUK_INTERNAL_DECL void duk_debug_write_flush(duk_hthread *thr);
9292 
9293 DUK_INTERNAL_DECL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length);
9294 DUK_INTERNAL_DECL void duk_debug_skip_byte(duk_hthread *thr);
9295 
9296 DUK_INTERNAL_DECL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length);
9297 DUK_INTERNAL_DECL duk_uint8_t duk_debug_read_byte(duk_hthread *thr);
9298 DUK_INTERNAL_DECL duk_int32_t duk_debug_read_int(duk_hthread *thr);
9299 DUK_INTERNAL_DECL duk_hstring *duk_debug_read_hstring(duk_hthread *thr);
9300 /* XXX: exposed duk_debug_read_pointer */
9301 /* XXX: exposed duk_debug_read_buffer */
9302 /* XXX: exposed duk_debug_read_hbuffer */
9303 #if 0
9304 DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr);
9305 #endif
9306 #if defined(DUK_USE_DEBUGGER_INSPECT)
9307 DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr);
9308 #endif
9309 DUK_INTERNAL_DECL duk_tval *duk_debug_read_tval(duk_hthread *thr);
9310 
9311 DUK_INTERNAL_DECL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length);
9312 DUK_INTERNAL_DECL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x);
9313 DUK_INTERNAL_DECL void duk_debug_write_unused(duk_hthread *thr);
9314 DUK_INTERNAL_DECL void duk_debug_write_undefined(duk_hthread *thr);
9315 #if defined(DUK_USE_DEBUGGER_INSPECT)
9316 DUK_INTERNAL_DECL void duk_debug_write_null(duk_hthread *thr);
9317 #endif
9318 DUK_INTERNAL_DECL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val);
9319 DUK_INTERNAL_DECL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x);
9320 DUK_INTERNAL_DECL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x);
9321 DUK_INTERNAL_DECL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length);
9322 DUK_INTERNAL_DECL void duk_debug_write_cstring(duk_hthread *thr, const char *data);
9323 DUK_INTERNAL_DECL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h);
9324 DUK_INTERNAL_DECL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length);
9325 DUK_INTERNAL_DECL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h);
9326 DUK_INTERNAL_DECL void duk_debug_write_pointer(duk_hthread *thr, void *ptr);
9327 #if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
9328 DUK_INTERNAL_DECL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h);
9329 #endif
9330 DUK_INTERNAL_DECL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj);
9331 DUK_INTERNAL_DECL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv);
9332 #if 0  /* unused */
9333 DUK_INTERNAL_DECL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command);
9334 #endif
9335 DUK_INTERNAL_DECL void duk_debug_write_reply(duk_hthread *thr);
9336 DUK_INTERNAL_DECL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg);
9337 DUK_INTERNAL_DECL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command);
9338 DUK_INTERNAL_DECL void duk_debug_write_eom(duk_hthread *thr);
9339 
9340 DUK_INTERNAL_DECL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr);
9341 DUK_INTERNAL_DECL void duk_debug_send_status(duk_hthread *thr);
9342 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
9343 DUK_INTERNAL_DECL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal);
9344 #endif
9345 
9346 DUK_INTERNAL_DECL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc);
9347 DUK_INTERNAL_DECL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block);
9348 
9349 DUK_INTERNAL_DECL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line);
9350 DUK_INTERNAL_DECL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index);
9351 
9352 DUK_INTERNAL_DECL duk_bool_t duk_debug_is_attached(duk_heap *heap);
9353 DUK_INTERNAL_DECL duk_bool_t duk_debug_is_paused(duk_heap *heap);
9354 DUK_INTERNAL_DECL void duk_debug_set_paused(duk_heap *heap);
9355 DUK_INTERNAL_DECL void duk_debug_clear_paused(duk_heap *heap);
9356 DUK_INTERNAL_DECL void duk_debug_clear_pause_state(duk_heap *heap);
9357 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
9358 
9359 #endif  /* DUK_DEBUGGER_H_INCLUDED */
9360 /* #include duk_debug.h */
9361 #line 1 "duk_debug.h"
9362 /*
9363  *  Debugging macros, DUK_DPRINT() and its variants in particular.
9364  *
9365  *  DUK_DPRINT() allows formatted debug prints, and supports standard
9366  *  and Duktape specific formatters.  See duk_debug_vsnprintf.c for details.
9367  *
9368  *  DUK_D(x), DUK_DD(x), and DUK_DDD(x) are used together with log macros
9369  *  for technical reasons.  They are concretely used to hide 'x' from the
9370  *  compiler when the corresponding log level is disabled.  This allows
9371  *  clean builds on non-C99 compilers, at the cost of more verbose code.
9372  *  Examples:
9373  *
9374  *    DUK_D(DUK_DPRINT("foo"));
9375  *    DUK_DD(DUK_DDPRINT("foo"));
9376  *    DUK_DDD(DUK_DDDPRINT("foo"));
9377  *
9378  *  This approach is preferable to the old "double parentheses" hack because
9379  *  double parentheses make the C99 solution worse: __FILE__ and __LINE__ can
9380  *  no longer be added transparently without going through globals, which
9381  *  works poorly with threading.
9382  */
9383 
9384 #if !defined(DUK_DEBUG_H_INCLUDED)
9385 #define DUK_DEBUG_H_INCLUDED
9386 
9387 #if defined(DUK_USE_DEBUG)
9388 
9389 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
9390 #define DUK_D(x) x
9391 #else
9392 #define DUK_D(x) do { } while (0) /* omit */
9393 #endif
9394 
9395 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
9396 #define DUK_DD(x) x
9397 #else
9398 #define DUK_DD(x) do { } while (0) /* omit */
9399 #endif
9400 
9401 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
9402 #define DUK_DDD(x) x
9403 #else
9404 #define DUK_DDD(x) do { } while (0) /* omit */
9405 #endif
9406 
9407 /*
9408  *  Exposed debug macros: debugging enabled
9409  */
9410 
9411 #if defined(DUK_USE_VARIADIC_MACROS)
9412 
9413 /* Note: combining __FILE__, __LINE__, and __func__ into fmt would be
9414  * possible compile time, but waste some space with shared function names.
9415  */
9416 #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__);
9417 
9418 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
9419 #define DUK_DPRINT(...)          DUK__DEBUG_LOG(DUK_LEVEL_DEBUG, __VA_ARGS__)
9420 #else
9421 #define DUK_DPRINT(...)
9422 #endif
9423 
9424 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
9425 #define DUK_DDPRINT(...)         DUK__DEBUG_LOG(DUK_LEVEL_DDEBUG, __VA_ARGS__)
9426 #else
9427 #define DUK_DDPRINT(...)
9428 #endif
9429 
9430 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
9431 #define DUK_DDDPRINT(...)        DUK__DEBUG_LOG(DUK_LEVEL_DDDEBUG, __VA_ARGS__)
9432 #else
9433 #define DUK_DDDPRINT(...)
9434 #endif
9435 
9436 #else  /* DUK_USE_VARIADIC_MACROS */
9437 
9438 #define DUK__DEBUG_STASH(lev)    \
9439 	(void) DUK_SNPRINTF(duk_debug_file_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FILE_MACRO), \
9440 	(void) (duk_debug_file_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), \
9441 	(void) (duk_debug_line_stash = (duk_int_t) DUK_LINE_MACRO), \
9442 	(void) DUK_SNPRINTF(duk_debug_func_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FUNC_MACRO), \
9443 	(void) (duk_debug_func_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), \
9444 	(void) (duk_debug_level_stash = (lev))
9445 
9446 /* Without variadic macros resort to comma expression trickery to handle debug
9447  * prints.  This generates a lot of harmless warnings.  These hacks are not
9448  * needed normally because DUK_D() and friends will hide the entire debug log
9449  * statement from the compiler.
9450  */
9451 
9452 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
9453 #define DUK_DPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DEBUG), (void) duk_debug_log  /* args go here in parens */
9454 #else
9455 #define DUK_DPRINT  0 && /* args go here as a comma expression in parens */
9456 #endif
9457 
9458 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
9459 #define DUK_DDPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DDEBUG), (void) duk_debug_log  /* args go here in parens */
9460 #else
9461 #define DUK_DDPRINT  0 && /* args */
9462 #endif
9463 
9464 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
9465 #define DUK_DDDPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DDDEBUG), (void) duk_debug_log  /* args go here in parens */
9466 #else
9467 #define DUK_DDDPRINT  0 && /* args */
9468 #endif
9469 
9470 #endif  /* DUK_USE_VARIADIC_MACROS */
9471 
9472 #else  /* DUK_USE_DEBUG */
9473 
9474 /*
9475  *  Exposed debug macros: debugging disabled
9476  */
9477 
9478 #define DUK_D(x) do { } while (0) /* omit */
9479 #define DUK_DD(x) do { } while (0) /* omit */
9480 #define DUK_DDD(x) do { } while (0) /* omit */
9481 
9482 #if defined(DUK_USE_VARIADIC_MACROS)
9483 
9484 #define DUK_DPRINT(...)
9485 #define DUK_DDPRINT(...)
9486 #define DUK_DDDPRINT(...)
9487 
9488 #else  /* DUK_USE_VARIADIC_MACROS */
9489 
9490 #define DUK_DPRINT    0 && /* args go here as a comma expression in parens */
9491 #define DUK_DDPRINT   0 && /* args */
9492 #define DUK_DDDPRINT  0 && /* args */
9493 
9494 #endif  /* DUK_USE_VARIADIC_MACROS */
9495 
9496 #endif  /* DUK_USE_DEBUG */
9497 
9498 /*
9499  *  Structs
9500  */
9501 
9502 #if defined(DUK_USE_DEBUG)
9503 struct duk_fixedbuffer {
9504 	duk_uint8_t *buffer;
9505 	duk_size_t length;
9506 	duk_size_t offset;
9507 	duk_bool_t truncated;
9508 };
9509 #endif
9510 
9511 /*
9512  *  Prototypes
9513  */
9514 
9515 #if defined(DUK_USE_DEBUG)
9516 DUK_INTERNAL_DECL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap);
9517 #if 0  /*unused*/
9518 DUK_INTERNAL_DECL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...);
9519 #endif
9520 DUK_INTERNAL_DECL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size);
9521 
9522 #if defined(DUK_USE_VARIADIC_MACROS)
9523 DUK_INTERNAL_DECL void duk_debug_log(duk_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...);
9524 #else  /* DUK_USE_VARIADIC_MACROS */
9525 /* parameter passing, not thread safe */
9526 #define DUK_DEBUG_STASH_SIZE  128
9527 #if !defined(DUK_SINGLE_FILE)
9528 DUK_INTERNAL_DECL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
9529 DUK_INTERNAL_DECL duk_int_t duk_debug_line_stash;
9530 DUK_INTERNAL_DECL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
9531 DUK_INTERNAL_DECL duk_int_t duk_debug_level_stash;
9532 #endif
9533 DUK_INTERNAL_DECL void duk_debug_log(const char *fmt, ...);
9534 #endif  /* DUK_USE_VARIADIC_MACROS */
9535 
9536 DUK_INTERNAL_DECL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length);
9537 DUK_INTERNAL_DECL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x);
9538 DUK_INTERNAL_DECL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x);
9539 DUK_INTERNAL_DECL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...);
9540 DUK_INTERNAL_DECL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size);
9541 DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
9542 
9543 #endif  /* DUK_USE_DEBUG */
9544 
9545 #endif  /* DUK_DEBUG_H_INCLUDED */
9546 /* #include duk_error.h */
9547 #line 1 "duk_error.h"
9548 /*
9549  *  Error handling macros, assertion macro, error codes.
9550  *
9551  *  There are three types of 'errors':
9552  *
9553  *    1. Ordinary errors relative to a thread, cause a longjmp, catchable.
9554  *    2. Fatal errors relative to a heap, cause fatal handler to be called.
9555  *    3. Fatal errors without context, cause the default (not heap specific)
9556  *       fatal handler to be called.
9557  *
9558  *  Fatal errors without context are used by debug code such as assertions.
9559  *  By providing a fatal error handler for a Duktape heap, user code can
9560  *  avoid fatal errors without context in non-debug builds.
9561  */
9562 
9563 #if !defined(DUK_ERROR_H_INCLUDED)
9564 #define DUK_ERROR_H_INCLUDED
9565 
9566 /*
9567  *  Error codes: defined in duktape.h
9568  *
9569  *  Error codes are used as a shorthand to throw exceptions from inside
9570  *  the implementation.  The appropriate ECMAScript object is constructed
9571  *  based on the code.  ECMAScript code throws objects directly.  The error
9572  *  codes are defined in the public API header because they are also used
9573  *  by calling code.
9574  */
9575 
9576 /*
9577  *  Normal error
9578  *
9579  *  Normal error is thrown with a longjmp() through the current setjmp()
9580  *  catchpoint record in the duk_heap.  The 'curr_thread' of the duk_heap
9581  *  identifies the throwing thread.
9582  *
9583  *  Error formatting is usually unnecessary.  The error macros provide a
9584  *  zero argument version (no formatting) and separate macros for small
9585  *  argument counts.  Variadic macros are not used to avoid portability
9586  *  issues and avoid the need for stash-based workarounds when they're not
9587  *  available.  Vararg calls are avoided for non-formatted error calls
9588  *  because vararg call sites are larger than normal, and there are a lot
9589  *  of call sites with no formatting.
9590  *
9591  *  Note that special formatting provided by debug macros is NOT available.
9592  *
9593  *  The _RAW variants allow the caller to specify file and line.  This makes
9594  *  it easier to write checked calls which want to use the call site of the
9595  *  checked function, not the error macro call inside the checked function.
9596  */
9597 
9598 #if defined(DUK_USE_VERBOSE_ERRORS)
9599 
9600 /* Because there are quite many call sites, pack error code (require at most
9601  * 8-bit) into a single argument.
9602  */
9603 #define DUK_ERROR(thr,err,msg) do { \
9604 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9605 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9606 		duk_err_handle_error((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
9607 	} while (0)
9608 #define DUK_ERROR_RAW(thr,file,line,err,msg) do { \
9609 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9610 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9611 		duk_err_handle_error((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
9612 	} while (0)
9613 
9614 #define DUK_ERROR_FMT1(thr,err,fmt,arg1) do { \
9615 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9616 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9617 		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
9618 	} while (0)
9619 #define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) do { \
9620 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9621 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9622 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
9623 	} while (0)
9624 
9625 #define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) do { \
9626 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9627 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9628 		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
9629 	} while (0)
9630 #define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) do { \
9631 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9632 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9633 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
9634 	} while (0)
9635 
9636 #define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) do { \
9637 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9638 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9639 		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
9640 	} while (0)
9641 #define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) do { \
9642 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9643 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9644 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
9645 	} while (0)
9646 
9647 #define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) do { \
9648 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9649 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9650 		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)); \
9651 	} while (0)
9652 #define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) do { \
9653 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9654 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9655 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3), (arg4)); \
9656 	} while (0)
9657 
9658 #else  /* DUK_USE_VERBOSE_ERRORS */
9659 
9660 #define DUK_ERROR(thr,err,msg)                    duk_err_handle_error((thr), (err))
9661 #define DUK_ERROR_RAW(thr,file,line,err,msg)      duk_err_handle_error((thr), (err))
9662 
9663 #define DUK_ERROR_FMT1(thr,err,fmt,arg1) DUK_ERROR((thr),(err),(fmt))
9664 #define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
9665 
9666 #define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) DUK_ERROR((thr),(err),(fmt))
9667 #define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
9668 
9669 #define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) DUK_ERROR((thr),(err),(fmt))
9670 #define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
9671 
9672 #define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR((thr),(err),(fmt))
9673 #define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
9674 
9675 #endif  /* DUK_USE_VERBOSE_ERRORS */
9676 
9677 /*
9678  *  Fatal error without context
9679  *
9680  *  The macro is an expression to make it compatible with DUK_ASSERT_EXPR().
9681  */
9682 
9683 #define DUK_FATAL_WITHOUT_CONTEXT(msg) \
9684 	duk_default_fatal_handler(NULL, (msg))
9685 
9686 /*
9687  *  Error throwing helpers
9688  *
9689  *  The goal is to provide verbose and configurable error messages.  Call
9690  *  sites should be clean in source code and compile to a small footprint.
9691  *  Small footprint is also useful for performance because small cold paths
9692  *  reduce code cache pressure.  Adding macros here only makes sense if there
9693  *  are enough call sites to get concrete benefits.
9694  *
9695  *  DUK_ERROR_xxx() macros are generic and can be used anywhere.
9696  *
9697  *  DUK_DCERROR_xxx() macros can only be used in Duktape/C functions where
9698  *  the "return DUK_RET_xxx;" shorthand is available for low memory targets.
9699  *  The DUK_DCERROR_xxx() macros always either throw or perform a
9700  *  'return DUK_RET_xxx' from the calling function.
9701  */
9702 
9703 #if defined(DUK_USE_VERBOSE_ERRORS)
9704 /* Verbose errors with key/value summaries (non-paranoid) or without key/value
9705  * summaries (paranoid, for some security sensitive environments), the paranoid
9706  * vs. non-paranoid distinction affects only a few specific errors.
9707  */
9708 #if defined(DUK_USE_PARANOID_ERRORS)
9709 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
9710 		duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx), (expectname)); \
9711 	} while (0)
9712 #else  /* DUK_USE_PARANOID_ERRORS */
9713 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
9714 		duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx), (expectname)); \
9715 	} while (0)
9716 #endif  /* DUK_USE_PARANOID_ERRORS */
9717 
9718 #define DUK_ERROR_INTERNAL(thr) do { \
9719 		duk_err_error_internal((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9720 	} while (0)
9721 #define DUK_DCERROR_INTERNAL(thr) do { \
9722 		DUK_ERROR_INTERNAL((thr)); \
9723 		return 0; \
9724 	} while (0)
9725 #define DUK_ERROR_ALLOC_FAILED(thr) do { \
9726 		duk_err_error_alloc_failed((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9727 	} while (0)
9728 #define DUK_ERROR_UNSUPPORTED(thr) do { \
9729 		DUK_ERROR((thr), DUK_ERR_ERROR, DUK_STR_UNSUPPORTED); \
9730 	} while (0)
9731 #define DUK_DCERROR_UNSUPPORTED(thr) do { \
9732 		DUK_ERROR_UNSUPPORTED((thr)); \
9733 		return 0; \
9734 	} while (0)
9735 #define DUK_ERROR_ERROR(thr,msg) do { \
9736 		duk_err_error((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
9737 	} while (0)
9738 #define DUK_ERROR_RANGE_INDEX(thr,idx) do { \
9739 		duk_err_range_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx)); \
9740 	} while (0)
9741 #define DUK_ERROR_RANGE_PUSH_BEYOND(thr) do { \
9742 		duk_err_range_push_beyond((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9743 	} while (0)
9744 #define DUK_ERROR_RANGE_INVALID_ARGS(thr) do { \
9745 		DUK_ERROR_RANGE((thr), DUK_STR_INVALID_ARGS); \
9746 	} while (0)
9747 #define DUK_DCERROR_RANGE_INVALID_ARGS(thr) do { \
9748 		DUK_ERROR_RANGE_INVALID_ARGS((thr)); \
9749 		return 0; \
9750 	} while (0)
9751 #define DUK_ERROR_RANGE_INVALID_COUNT(thr) do { \
9752 		DUK_ERROR_RANGE((thr), DUK_STR_INVALID_COUNT); \
9753 	} while (0)
9754 #define DUK_DCERROR_RANGE_INVALID_COUNT(thr) do { \
9755 		DUK_ERROR_RANGE_INVALID_COUNT((thr)); \
9756 		return 0; \
9757 	} while (0)
9758 #define DUK_ERROR_RANGE_INVALID_LENGTH(thr) do { \
9759 		DUK_ERROR_RANGE((thr), DUK_STR_INVALID_LENGTH); \
9760 	} while (0)
9761 #define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) do { \
9762 		DUK_ERROR_RANGE_INVALID_LENGTH((thr)); \
9763 		return 0; \
9764 	} while (0)
9765 #define DUK_ERROR_RANGE(thr,msg) do { \
9766 		duk_err_range((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
9767 	} while (0)
9768 #define DUK_ERROR_EVAL(thr,msg) do { \
9769 		DUK_ERROR((thr), DUK_ERR_EVAL_ERROR, (msg)); \
9770 	} while (0)
9771 #define DUK_ERROR_REFERENCE(thr,msg) do { \
9772 		DUK_ERROR((thr), DUK_ERR_REFERENCE_ERROR, (msg)); \
9773 	} while (0)
9774 #define DUK_ERROR_SYNTAX(thr,msg) do { \
9775 		DUK_ERROR((thr), DUK_ERR_SYNTAX_ERROR, (msg)); \
9776 	} while (0)
9777 #define DUK_ERROR_TYPE_INVALID_ARGS(thr) do { \
9778 		duk_err_type_invalid_args((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9779 	} while (0)
9780 #define DUK_DCERROR_TYPE_INVALID_ARGS(thr) do { \
9781 		DUK_ERROR_TYPE_INVALID_ARGS((thr)); \
9782 		return 0; \
9783 	} while (0)
9784 #define DUK_ERROR_TYPE_INVALID_STATE(thr) do { \
9785 		duk_err_type_invalid_state((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9786 	} while (0)
9787 #define DUK_DCERROR_TYPE_INVALID_STATE(thr) do { \
9788 		DUK_ERROR_TYPE_INVALID_STATE((thr)); \
9789 		return 0; \
9790 	} while (0)
9791 #define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9792 		duk_err_type_invalid_trap_result((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9793 	} while (0)
9794 #define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9795 		DUK_ERROR_TYPE((thr), DUK_STR_INVALID_TRAP_RESULT); \
9796 	} while (0)
9797 #define DUK_ERROR_TYPE(thr,msg) do { \
9798 		DUK_ERROR((thr), DUK_ERR_TYPE_ERROR, (msg)); \
9799 	} while (0)
9800 #define DUK_ERROR_URI(thr,msg) do { \
9801 		DUK_ERROR((thr), DUK_ERR_URI_ERROR, (msg)); \
9802 	} while (0)
9803 #else  /* DUK_USE_VERBOSE_ERRORS */
9804 /* Non-verbose errors for low memory targets: no file, line, or message. */
9805 
9806 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
9807 		duk_err_type((thr)); \
9808 	} while (0)
9809 
9810 #define DUK_ERROR_INTERNAL(thr) do { \
9811 		duk_err_error((thr)); \
9812 	} while (0)
9813 #define DUK_DCERROR_INTERNAL(thr) do { \
9814 		DUK_UNREF((thr)); \
9815 		return DUK_RET_ERROR; \
9816 	} while (0)
9817 #define DUK_ERROR_ALLOC_FAILED(thr) do { \
9818 		duk_err_error((thr)); \
9819 	} while (0)
9820 #define DUK_ERROR_UNSUPPORTED(thr) do { \
9821 		duk_err_error((thr)); \
9822 	} while (0)
9823 #define DUK_DCERROR_UNSUPPORTED(thr) do { \
9824 		DUK_UNREF((thr)); \
9825 		return DUK_RET_ERROR; \
9826 	} while (0)
9827 #define DUK_ERROR_ERROR(thr,msg) do { \
9828 		duk_err_error((thr)); \
9829 	} while (0)
9830 #define DUK_ERROR_RANGE_INDEX(thr,idx) do { \
9831 		duk_err_range((thr)); \
9832 	} while (0)
9833 #define DUK_ERROR_RANGE_PUSH_BEYOND(thr) do { \
9834 		duk_err_range((thr)); \
9835 	} while (0)
9836 #define DUK_ERROR_RANGE_INVALID_ARGS(thr) do { \
9837 		duk_err_range((thr)); \
9838 	} while (0)
9839 #define DUK_DCERROR_RANGE_INVALID_ARGS(thr) do { \
9840 		DUK_UNREF((thr)); \
9841 		return DUK_RET_RANGE_ERROR; \
9842 	} while (0)
9843 #define DUK_ERROR_RANGE_INVALID_COUNT(thr) do { \
9844 		duk_err_range((thr)); \
9845 	} while (0)
9846 #define DUK_DCERROR_RANGE_INVALID_COUNT(thr) do { \
9847 		DUK_UNREF((thr)); \
9848 		return DUK_RET_RANGE_ERROR; \
9849 	} while (0)
9850 #define DUK_ERROR_RANGE_INVALID_LENGTH(thr) do { \
9851 		duk_err_range((thr)); \
9852 	} while (0)
9853 #define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) do { \
9854 		DUK_UNREF((thr)); \
9855 		return DUK_RET_RANGE_ERROR; \
9856 	} while (0)
9857 #define DUK_ERROR_RANGE(thr,msg) do { \
9858 		duk_err_range((thr)); \
9859 	} while (0)
9860 #define DUK_ERROR_EVAL(thr,msg) do { \
9861 		duk_err_eval((thr)); \
9862 	} while (0)
9863 #define DUK_ERROR_REFERENCE(thr,msg) do { \
9864 		duk_err_reference((thr)); \
9865 	} while (0)
9866 #define DUK_ERROR_SYNTAX(thr,msg) do { \
9867 		duk_err_syntax((thr)); \
9868 	} while (0)
9869 #define DUK_ERROR_TYPE_INVALID_ARGS(thr) do { \
9870 		duk_err_type((thr)); \
9871 	} while (0)
9872 #define DUK_DCERROR_TYPE_INVALID_ARGS(thr) do { \
9873 		DUK_UNREF((thr)); \
9874 		return DUK_RET_TYPE_ERROR; \
9875 	} while (0)
9876 #define DUK_ERROR_TYPE_INVALID_STATE(thr) do { \
9877 		duk_err_type((thr)); \
9878 	} while (0)
9879 #define DUK_DCERROR_TYPE_INVALID_STATE(thr) do { \
9880 		duk_err_type((thr)); \
9881 	} while (0)
9882 #define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9883 		duk_err_type((thr)); \
9884 	} while (0)
9885 #define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9886 		DUK_UNREF((thr)); \
9887 		return DUK_RET_TYPE_ERROR; \
9888 	} while (0)
9889 #define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9890 		duk_err_type((thr)); \
9891 	} while (0)
9892 #define DUK_ERROR_TYPE(thr,msg) do { \
9893 		duk_err_type((thr)); \
9894 	} while (0)
9895 #define DUK_ERROR_URI(thr,msg) do { \
9896 		duk_err_uri((thr)); \
9897 	} while (0)
9898 #endif  /* DUK_USE_VERBOSE_ERRORS */
9899 
9900 /*
9901  *  Assert macro: failure causes a fatal error.
9902  *
9903  *  NOTE: since the assert macro doesn't take a heap/context argument, there's
9904  *  no way to look up a heap/context specific fatal error handler which may have
9905  *  been given by the application.  Instead, assertion failures always use the
9906  *  internal default fatal error handler; it can be replaced via duk_config.h
9907  *  and then applies to all Duktape heaps.
9908  */
9909 
9910 #if defined(DUK_USE_ASSERTIONS)
9911 
9912 /* The message should be a compile time constant without formatting (less risk);
9913  * we don't care about assertion text size because they're not used in production
9914  * builds.
9915  */
9916 #define DUK_ASSERT(x)  do { \
9917 	if (!(x)) { \
9918 		DUK_FATAL_WITHOUT_CONTEXT("assertion failed: " #x \
9919 			" (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"); \
9920 	} \
9921 	} while (0)
9922 
9923 /* Assertion compatible inside a comma expression, evaluates to void. */
9924 #define DUK_ASSERT_EXPR(x) \
9925 	((void) ((x) ? 0 : (DUK_FATAL_WITHOUT_CONTEXT("assertion failed: " #x \
9926 				" (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"), 0)))
9927 
9928 #else  /* DUK_USE_ASSERTIONS */
9929 
9930 #define DUK_ASSERT(x)  do { /* assertion omitted */ } while (0)
9931 
9932 #define DUK_ASSERT_EXPR(x)  ((void) 0)
9933 
9934 #endif  /* DUK_USE_ASSERTIONS */
9935 
9936 /* this variant is used when an assert would generate a compile warning by
9937  * being always true (e.g. >= 0 comparison for an unsigned value
9938  */
9939 #define DUK_ASSERT_DISABLE(x)  do { /* assertion disabled */ } while (0)
9940 
9941 /*
9942  *  Assertion helpers
9943  */
9944 
9945 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
9946 #define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h)  do { \
9947 		DUK_ASSERT((h) == NULL || DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) (h)) > 0); \
9948 	} while (0)
9949 #define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv)  do { \
9950 		if ((tv) != NULL && DUK_TVAL_IS_HEAP_ALLOCATED((tv))) { \
9951 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(DUK_TVAL_GET_HEAPHDR((tv))) > 0); \
9952 		} \
9953 	} while (0)
9954 #else
9955 #define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h)  /* no refcount check */
9956 #define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv)    /* no refcount check */
9957 #endif
9958 
9959 #define DUK_ASSERT_TOP(ctx,n)  DUK_ASSERT((duk_idx_t) duk_get_top((ctx)) == (duk_idx_t) (n))
9960 
9961 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_PACKED_TVAL)
9962 #define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)  do { \
9963 		duk_double_union duk__assert_tmp_du; \
9964 		duk__assert_tmp_du.d = (dval); \
9965 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&duk__assert_tmp_du)); \
9966 	} while (0)
9967 #else
9968 #define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)  /* nop */
9969 #endif
9970 
9971 #define DUK_ASSERT_VS_SPACE(thr) \
9972 	DUK_ASSERT(thr->valstack_top < thr->valstack_end)
9973 
9974 /*
9975  *  Helper to initialize a memory area (e.g. struct) with garbage when
9976  *  assertions enabled.
9977  */
9978 
9979 #if defined(DUK_USE_ASSERTIONS)
9980 #define DUK_ASSERT_SET_GARBAGE(ptr,size) do { \
9981 		duk_memset_unsafe((void *) (ptr), 0x5a, size); \
9982 	} while (0)
9983 #else
9984 #define DUK_ASSERT_SET_GARBAGE(ptr,size) do {} while (0)
9985 #endif
9986 
9987 /*
9988  *  Helper for valstack space
9989  *
9990  *  Caller of DUK_ASSERT_VALSTACK_SPACE() estimates the number of free stack entries
9991  *  required for its own use, and any child calls which are not (a) Duktape API calls
9992  *  or (b) Duktape calls which involve extending the valstack (e.g. getter call).
9993  */
9994 
9995 #define DUK_VALSTACK_ASSERT_EXTRA  5  /* this is added to checks to allow for Duktape
9996                                        * API calls in addition to function's own use
9997                                        */
9998 #if defined(DUK_USE_ASSERTIONS)
9999 #define DUK_ASSERT_VALSTACK_SPACE(thr,n)   do { \
10000 		DUK_ASSERT((thr) != NULL); \
10001 		DUK_ASSERT((thr)->valstack_end - (thr)->valstack_top >= (n) + DUK_VALSTACK_ASSERT_EXTRA); \
10002 	} while (0)
10003 #else
10004 #define DUK_ASSERT_VALSTACK_SPACE(thr,n)   /* no valstack space check */
10005 #endif
10006 
10007 /*
10008  *  Prototypes
10009  */
10010 
10011 #if defined(DUK_USE_VERBOSE_ERRORS)
10012 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));
10013 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, ...));
10014 #else  /* DUK_USE_VERBOSE_ERRORS */
10015 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code));
10016 #endif  /* DUK_USE_VERBOSE_ERRORS */
10017 
10018 #if defined(DUK_USE_VERBOSE_ERRORS)
10019 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));
10020 #else
10021 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code));
10022 #endif
10023 
10024 DUK_NORETURN(DUK_INTERNAL_DECL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc));
10025 
10026 #define DUK_AUGMENT_FLAG_NOBLAME_FILELINE  (1U << 0)  /* if set, don't blame C file/line for .fileName and .lineNumber */
10027 #define DUK_AUGMENT_FLAG_SKIP_ONE          (1U << 1)  /* if set, skip topmost activation in traceback construction */
10028 
10029 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
10030 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);
10031 #endif
10032 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
10033 DUK_INTERNAL_DECL void duk_err_augment_error_throw(duk_hthread *thr);
10034 #endif
10035 
10036 #if defined(DUK_USE_VERBOSE_ERRORS)
10037 #if defined(DUK_USE_PARANOID_ERRORS)
10038 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));
10039 #else
10040 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));
10041 #endif
10042 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber));
10043 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error_alloc_failed(duk_hthread *thr, const char *filename, duk_int_t linenumber));
10044 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
10045 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx));
10046 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range_push_beyond(duk_hthread *thr, const char *filename, duk_int_t linenumber));
10047 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
10048 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_args(duk_hthread *thr, const char *filename, duk_int_t linenumber));
10049 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_state(duk_hthread *thr, const char *filename, duk_int_t linenumber));
10050 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_trap_result(duk_hthread *thr, const char *filename, duk_int_t linenumber));
10051 #else  /* DUK_VERBOSE_ERRORS */
10052 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error(duk_hthread *thr));
10053 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr));
10054 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_eval(duk_hthread *thr));
10055 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_reference(duk_hthread *thr));
10056 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_syntax(duk_hthread *thr));
10057 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type(duk_hthread *thr));
10058 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_uri(duk_hthread *thr));
10059 #endif /* DUK_VERBOSE_ERRORS */
10060 
10061 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_longjmp(duk_hthread *thr));
10062 
10063 DUK_NORETURN(DUK_INTERNAL_DECL void duk_default_fatal_handler(void *udata, const char *msg));
10064 
10065 DUK_INTERNAL_DECL void duk_err_setup_ljstate1(duk_hthread *thr, duk_small_uint_t lj_type, duk_tval *tv_val);
10066 #if defined(DUK_USE_DEBUGGER_SUPPORT)
10067 DUK_INTERNAL_DECL void duk_err_check_debugger_integration(duk_hthread *thr);
10068 #endif
10069 
10070 DUK_INTERNAL_DECL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t err_code);
10071 
10072 #endif  /* DUK_ERROR_H_INCLUDED */
10073 /* #include duk_unicode.h */
10074 #line 1 "duk_unicode.h"
10075 /*
10076  *  Unicode helpers
10077  */
10078 
10079 #if !defined(DUK_UNICODE_H_INCLUDED)
10080 #define DUK_UNICODE_H_INCLUDED
10081 
10082 /*
10083  *  UTF-8 / XUTF-8 / CESU-8 constants
10084  */
10085 
10086 #define DUK_UNICODE_MAX_XUTF8_LENGTH      7   /* up to 36 bit codepoints */
10087 #define DUK_UNICODE_MAX_XUTF8_BMP_LENGTH  3   /* all codepoints up to U+FFFF */
10088 #define DUK_UNICODE_MAX_CESU8_LENGTH      6   /* all codepoints up to U+10FFFF */
10089 #define DUK_UNICODE_MAX_CESU8_BMP_LENGTH  3   /* all codepoints up to U+FFFF */
10090 
10091 /*
10092  *  Useful Unicode codepoints
10093  *
10094  *  Integer constants must be signed to avoid unexpected coercions
10095  *  in comparisons.
10096  */
10097 
10098 #define DUK_UNICODE_CP_ZWNJ                   0x200cL  /* zero-width non-joiner */
10099 #define DUK_UNICODE_CP_ZWJ                    0x200dL  /* zero-width joiner */
10100 #define DUK_UNICODE_CP_REPLACEMENT_CHARACTER  0xfffdL  /* http://en.wikipedia.org/wiki/Replacement_character#Replacement_character */
10101 
10102 /*
10103  *  ASCII character constants
10104  *
10105  *  C character literals like 'x' have a platform specific value and do
10106  *  not match ASCII (UTF-8) values on e.g. EBCDIC platforms.  So, use
10107  *  these (admittedly awkward) constants instead.  These constants must
10108  *  also have signed values to avoid unexpected coercions in comparisons.
10109  *
10110  *  http://en.wikipedia.org/wiki/ASCII
10111  */
10112 
10113 #define DUK_ASC_NUL              0x00
10114 #define DUK_ASC_SOH              0x01
10115 #define DUK_ASC_STX              0x02
10116 #define DUK_ASC_ETX              0x03
10117 #define DUK_ASC_EOT              0x04
10118 #define DUK_ASC_ENQ              0x05
10119 #define DUK_ASC_ACK              0x06
10120 #define DUK_ASC_BEL              0x07
10121 #define DUK_ASC_BS               0x08
10122 #define DUK_ASC_HT               0x09
10123 #define DUK_ASC_LF               0x0a
10124 #define DUK_ASC_VT               0x0b
10125 #define DUK_ASC_FF               0x0c
10126 #define DUK_ASC_CR               0x0d
10127 #define DUK_ASC_SO               0x0e
10128 #define DUK_ASC_SI               0x0f
10129 #define DUK_ASC_DLE              0x10
10130 #define DUK_ASC_DC1              0x11
10131 #define DUK_ASC_DC2              0x12
10132 #define DUK_ASC_DC3              0x13
10133 #define DUK_ASC_DC4              0x14
10134 #define DUK_ASC_NAK              0x15
10135 #define DUK_ASC_SYN              0x16
10136 #define DUK_ASC_ETB              0x17
10137 #define DUK_ASC_CAN              0x18
10138 #define DUK_ASC_EM               0x19
10139 #define DUK_ASC_SUB              0x1a
10140 #define DUK_ASC_ESC              0x1b
10141 #define DUK_ASC_FS               0x1c
10142 #define DUK_ASC_GS               0x1d
10143 #define DUK_ASC_RS               0x1e
10144 #define DUK_ASC_US               0x1f
10145 #define DUK_ASC_SPACE            0x20
10146 #define DUK_ASC_EXCLAMATION      0x21
10147 #define DUK_ASC_DOUBLEQUOTE      0x22
10148 #define DUK_ASC_HASH             0x23
10149 #define DUK_ASC_DOLLAR           0x24
10150 #define DUK_ASC_PERCENT          0x25
10151 #define DUK_ASC_AMP              0x26
10152 #define DUK_ASC_SINGLEQUOTE      0x27
10153 #define DUK_ASC_LPAREN           0x28
10154 #define DUK_ASC_RPAREN           0x29
10155 #define DUK_ASC_STAR             0x2a
10156 #define DUK_ASC_PLUS             0x2b
10157 #define DUK_ASC_COMMA            0x2c
10158 #define DUK_ASC_MINUS            0x2d
10159 #define DUK_ASC_PERIOD           0x2e
10160 #define DUK_ASC_SLASH            0x2f
10161 #define DUK_ASC_0                0x30
10162 #define DUK_ASC_1                0x31
10163 #define DUK_ASC_2                0x32
10164 #define DUK_ASC_3                0x33
10165 #define DUK_ASC_4                0x34
10166 #define DUK_ASC_5                0x35
10167 #define DUK_ASC_6                0x36
10168 #define DUK_ASC_7                0x37
10169 #define DUK_ASC_8                0x38
10170 #define DUK_ASC_9                0x39
10171 #define DUK_ASC_COLON            0x3a
10172 #define DUK_ASC_SEMICOLON        0x3b
10173 #define DUK_ASC_LANGLE           0x3c
10174 #define DUK_ASC_EQUALS           0x3d
10175 #define DUK_ASC_RANGLE           0x3e
10176 #define DUK_ASC_QUESTION         0x3f
10177 #define DUK_ASC_ATSIGN           0x40
10178 #define DUK_ASC_UC_A             0x41
10179 #define DUK_ASC_UC_B             0x42
10180 #define DUK_ASC_UC_C             0x43
10181 #define DUK_ASC_UC_D             0x44
10182 #define DUK_ASC_UC_E             0x45
10183 #define DUK_ASC_UC_F             0x46
10184 #define DUK_ASC_UC_G             0x47
10185 #define DUK_ASC_UC_H             0x48
10186 #define DUK_ASC_UC_I             0x49
10187 #define DUK_ASC_UC_J             0x4a
10188 #define DUK_ASC_UC_K             0x4b
10189 #define DUK_ASC_UC_L             0x4c
10190 #define DUK_ASC_UC_M             0x4d
10191 #define DUK_ASC_UC_N             0x4e
10192 #define DUK_ASC_UC_O             0x4f
10193 #define DUK_ASC_UC_P             0x50
10194 #define DUK_ASC_UC_Q             0x51
10195 #define DUK_ASC_UC_R             0x52
10196 #define DUK_ASC_UC_S             0x53
10197 #define DUK_ASC_UC_T             0x54
10198 #define DUK_ASC_UC_U             0x55
10199 #define DUK_ASC_UC_V             0x56
10200 #define DUK_ASC_UC_W             0x57
10201 #define DUK_ASC_UC_X             0x58
10202 #define DUK_ASC_UC_Y             0x59
10203 #define DUK_ASC_UC_Z             0x5a
10204 #define DUK_ASC_LBRACKET         0x5b
10205 #define DUK_ASC_BACKSLASH        0x5c
10206 #define DUK_ASC_RBRACKET         0x5d
10207 #define DUK_ASC_CARET            0x5e
10208 #define DUK_ASC_UNDERSCORE       0x5f
10209 #define DUK_ASC_GRAVE            0x60
10210 #define DUK_ASC_LC_A             0x61
10211 #define DUK_ASC_LC_B             0x62
10212 #define DUK_ASC_LC_C             0x63
10213 #define DUK_ASC_LC_D             0x64
10214 #define DUK_ASC_LC_E             0x65
10215 #define DUK_ASC_LC_F             0x66
10216 #define DUK_ASC_LC_G             0x67
10217 #define DUK_ASC_LC_H             0x68
10218 #define DUK_ASC_LC_I             0x69
10219 #define DUK_ASC_LC_J             0x6a
10220 #define DUK_ASC_LC_K             0x6b
10221 #define DUK_ASC_LC_L             0x6c
10222 #define DUK_ASC_LC_M             0x6d
10223 #define DUK_ASC_LC_N             0x6e
10224 #define DUK_ASC_LC_O             0x6f
10225 #define DUK_ASC_LC_P             0x70
10226 #define DUK_ASC_LC_Q             0x71
10227 #define DUK_ASC_LC_R             0x72
10228 #define DUK_ASC_LC_S             0x73
10229 #define DUK_ASC_LC_T             0x74
10230 #define DUK_ASC_LC_U             0x75
10231 #define DUK_ASC_LC_V             0x76
10232 #define DUK_ASC_LC_W             0x77
10233 #define DUK_ASC_LC_X             0x78
10234 #define DUK_ASC_LC_Y             0x79
10235 #define DUK_ASC_LC_Z             0x7a
10236 #define DUK_ASC_LCURLY           0x7b
10237 #define DUK_ASC_PIPE             0x7c
10238 #define DUK_ASC_RCURLY           0x7d
10239 #define DUK_ASC_TILDE            0x7e
10240 #define DUK_ASC_DEL              0x7f
10241 
10242 /*
10243  *  Miscellaneous
10244  */
10245 
10246 /* Uppercase A is 0x41, lowercase a is 0x61; OR 0x20 to convert uppercase
10247  * to lowercase.
10248  */
10249 #define DUK_LOWERCASE_CHAR_ASCII(x)  ((x) | 0x20)
10250 
10251 /*
10252  *  Unicode tables
10253  */
10254 
10255 #if defined(DUK_USE_SOURCE_NONBMP)
10256 /*
10257  *  Automatically generated by extract_chars.py, do not edit!
10258  */
10259 
10260 extern const duk_uint8_t duk_unicode_ids_noa[1116];
10261 #else
10262 /*
10263  *  Automatically generated by extract_chars.py, do not edit!
10264  */
10265 
10266 extern const duk_uint8_t duk_unicode_ids_noabmp[625];
10267 #endif
10268 
10269 #if defined(DUK_USE_SOURCE_NONBMP)
10270 /*
10271  *  Automatically generated by extract_chars.py, do not edit!
10272  */
10273 
10274 extern const duk_uint8_t duk_unicode_ids_m_let_noa[42];
10275 #else
10276 /*
10277  *  Automatically generated by extract_chars.py, do not edit!
10278  */
10279 
10280 extern const duk_uint8_t duk_unicode_ids_m_let_noabmp[24];
10281 #endif
10282 
10283 #if defined(DUK_USE_SOURCE_NONBMP)
10284 /*
10285  *  Automatically generated by extract_chars.py, do not edit!
10286  */
10287 
10288 extern const duk_uint8_t duk_unicode_idp_m_ids_noa[576];
10289 #else
10290 /*
10291  *  Automatically generated by extract_chars.py, do not edit!
10292  */
10293 
10294 extern const duk_uint8_t duk_unicode_idp_m_ids_noabmp[358];
10295 #endif
10296 
10297 /*
10298  *  Automatically generated by extract_caseconv.py, do not edit!
10299  */
10300 
10301 extern const duk_uint8_t duk_unicode_caseconv_uc[1411];
10302 extern const duk_uint8_t duk_unicode_caseconv_lc[706];
10303 
10304 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
10305 /*
10306  *  Automatically generated by extract_caseconv.py, do not edit!
10307  */
10308 
10309 extern const duk_uint16_t duk_unicode_re_canon_lookup[65536];
10310 #endif
10311 
10312 #if defined(DUK_USE_REGEXP_CANON_BITMAP)
10313 /*
10314  *  Automatically generated by extract_caseconv.py, do not edit!
10315  */
10316 
10317 #define DUK_CANON_BITMAP_BLKSIZE                                      32
10318 #define DUK_CANON_BITMAP_BLKSHIFT                                     5
10319 #define DUK_CANON_BITMAP_BLKMASK                                      31
10320 extern const duk_uint8_t duk_unicode_re_canon_bitmap[256];
10321 #endif
10322 
10323 /*
10324  *  Extern
10325  */
10326 
10327 /* duk_unicode_support.c */
10328 #if !defined(DUK_SINGLE_FILE)
10329 DUK_INTERNAL_DECL const duk_uint8_t duk_unicode_xutf8_markers[7];
10330 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_digit[2];
10331 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_white[22];
10332 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_wordchar[8];
10333 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_digit[4];
10334 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_white[24];
10335 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10];
10336 DUK_INTERNAL_DECL const duk_int8_t duk_is_idchar_tab[128];
10337 #endif  /* !DUK_SINGLE_FILE */
10338 
10339 /*
10340  *  Prototypes
10341  */
10342 
10343 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp);
10344 #if defined(DUK_USE_ASSERTIONS)
10345 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp);
10346 #endif
10347 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out);
10348 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out);
10349 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);
10350 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);
10351 DUK_INTERNAL_DECL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen);
10352 DUK_INTERNAL_DECL duk_bool_t duk_unicode_is_utf8_compatible(const duk_uint8_t *buf, duk_size_t len);
10353 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp);
10354 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp);
10355 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp);
10356 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp);
10357 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp);
10358 DUK_INTERNAL_DECL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase);
10359 #if defined(DUK_USE_REGEXP_SUPPORT)
10360 DUK_INTERNAL_DECL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp);
10361 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp);
10362 #endif
10363 
10364 #endif  /* DUK_UNICODE_H_INCLUDED */
10365 /* #include duk_json.h */
10366 #line 1 "duk_json.h"
10367 /*
10368  *  Defines for JSON, especially duk_bi_json.c.
10369  */
10370 
10371 #if !defined(DUK_JSON_H_INCLUDED)
10372 #define DUK_JSON_H_INCLUDED
10373 
10374 /* Encoding/decoding flags */
10375 #define DUK_JSON_FLAG_ASCII_ONLY              (1U << 0)  /* escape any non-ASCII characters */
10376 #define DUK_JSON_FLAG_AVOID_KEY_QUOTES        (1U << 1)  /* avoid key quotes when key is an ASCII Identifier */
10377 #define DUK_JSON_FLAG_EXT_CUSTOM              (1U << 2)  /* extended types: custom encoding */
10378 #define DUK_JSON_FLAG_EXT_COMPATIBLE          (1U << 3)  /* extended types: compatible encoding */
10379 
10380 /* How much stack to require on entry to object/array encode */
10381 #define DUK_JSON_ENC_REQSTACK                 32
10382 
10383 /* How much stack to require on entry to object/array decode */
10384 #define DUK_JSON_DEC_REQSTACK                 32
10385 
10386 /* How large a loop detection stack to use */
10387 #define DUK_JSON_ENC_LOOPARRAY                64
10388 
10389 /* Encoding state.  Heap object references are all borrowed. */
10390 typedef struct {
10391 	duk_hthread *thr;
10392 	duk_bufwriter_ctx bw;        /* output bufwriter */
10393 	duk_hobject *h_replacer;     /* replacer function */
10394 	duk_hstring *h_gap;          /* gap (if empty string, NULL) */
10395 	duk_idx_t idx_proplist;      /* explicit PropertyList */
10396 	duk_idx_t idx_loop;          /* valstack index of loop detection object */
10397 	duk_small_uint_t flags;
10398 	duk_small_uint_t flag_ascii_only;
10399 	duk_small_uint_t flag_avoid_key_quotes;
10400 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
10401 	duk_small_uint_t flag_ext_custom;
10402 	duk_small_uint_t flag_ext_compatible;
10403 	duk_small_uint_t flag_ext_custom_or_compatible;
10404 #endif
10405 	duk_uint_t recursion_depth;
10406 	duk_uint_t recursion_limit;
10407 	duk_uint_t mask_for_undefined;      /* type bit mask: types which certainly produce 'undefined' */
10408 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
10409 	duk_small_uint_t stridx_custom_undefined;
10410 	duk_small_uint_t stridx_custom_nan;
10411 	duk_small_uint_t stridx_custom_neginf;
10412 	duk_small_uint_t stridx_custom_posinf;
10413 	duk_small_uint_t stridx_custom_function;
10414 #endif
10415 	duk_hobject *visiting[DUK_JSON_ENC_LOOPARRAY];  /* indexed by recursion_depth */
10416 } duk_json_enc_ctx;
10417 
10418 typedef struct {
10419 	duk_hthread *thr;
10420 	const duk_uint8_t *p;
10421 	const duk_uint8_t *p_start;
10422 	const duk_uint8_t *p_end;
10423 	duk_idx_t idx_reviver;
10424 	duk_small_uint_t flags;
10425 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
10426 	duk_small_uint_t flag_ext_custom;
10427 	duk_small_uint_t flag_ext_compatible;
10428 	duk_small_uint_t flag_ext_custom_or_compatible;
10429 #endif
10430 	duk_int_t recursion_depth;
10431 	duk_int_t recursion_limit;
10432 } duk_json_dec_ctx;
10433 
10434 #endif  /* DUK_JSON_H_INCLUDED */
10435 /* #include duk_js.h */
10436 #line 1 "duk_js.h"
10437 /*
10438  *  ECMAScript execution, support primitives.
10439  */
10440 
10441 #if !defined(DUK_JS_H_INCLUDED)
10442 #define DUK_JS_H_INCLUDED
10443 
10444 /* Flags for call handling.  Lowest flags must match bytecode DUK_BC_CALL_FLAG_xxx 1:1. */
10445 #define DUK_CALL_FLAG_TAILCALL                 (1U << 0)  /* setup for a tail call */
10446 #define DUK_CALL_FLAG_CONSTRUCT                (1U << 1)  /* constructor call (i.e. called as 'new Foo()') */
10447 #define DUK_CALL_FLAG_CALLED_AS_EVAL           (1U << 2)  /* call was made using the identifier 'eval' */
10448 #define DUK_CALL_FLAG_ALLOW_ECMATOECMA         (1U << 3)  /* ecma-to-ecma call with executor reuse is possible */
10449 #define DUK_CALL_FLAG_DIRECT_EVAL              (1U << 4)  /* call is a direct eval call */
10450 #define DUK_CALL_FLAG_CONSTRUCT_PROXY          (1U << 5)  /* handled via 'construct' proxy trap, check return value invariant(s) */
10451 #define DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED (1U << 6)  /* prototype of 'default instance' updated, temporary flag in call handling */
10452 
10453 /* Flags for duk_js_equals_helper(). */
10454 #define DUK_EQUALS_FLAG_SAMEVALUE            (1U << 0)  /* use SameValue instead of non-strict equality */
10455 #define DUK_EQUALS_FLAG_STRICT               (1U << 1)  /* use strict equality instead of non-strict equality */
10456 
10457 /* Flags for duk_js_compare_helper(). */
10458 #define DUK_COMPARE_FLAG_NEGATE              (1U << 0)  /* negate result */
10459 #define DUK_COMPARE_FLAG_EVAL_LEFT_FIRST     (1U << 1)  /* eval left argument first */
10460 
10461 /* conversions, coercions, comparison, etc */
10462 DUK_INTERNAL_DECL duk_bool_t duk_js_toboolean(duk_tval *tv);
10463 DUK_INTERNAL_DECL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv);
10464 DUK_INTERNAL_DECL duk_double_t duk_js_tointeger_number(duk_double_t x);
10465 DUK_INTERNAL_DECL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv);
10466 DUK_INTERNAL_DECL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv);
10467 DUK_INTERNAL_DECL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv);
10468 DUK_INTERNAL_DECL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv);
10469 DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_string(const duk_uint8_t *str, duk_uint32_t blen);
10470 #if !defined(DUK_USE_HSTRING_ARRIDX)
10471 DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_hstring_fast_known(duk_hstring *h);
10472 DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h);
10473 #endif
10474 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);
10475 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);
10476 DUK_INTERNAL_DECL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2);
10477 #if 0  /* unused */
10478 DUK_INTERNAL_DECL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2);
10479 #endif
10480 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);
10481 DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
10482 #if defined(DUK_USE_SYMBOL_BUILTIN)
10483 DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof_ordinary(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
10484 #endif
10485 DUK_INTERNAL_DECL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
10486 DUK_INTERNAL_DECL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x);
10487 DUK_INTERNAL_DECL duk_bool_t duk_js_isarray_hobject(duk_hobject *h);
10488 DUK_INTERNAL_DECL duk_bool_t duk_js_isarray(duk_tval *tv);
10489 
10490 /* arithmetic */
10491 DUK_INTERNAL_DECL double duk_js_arith_pow(double x, double y);
10492 DUK_INTERNAL_DECL double duk_js_arith_mod(double x, double y);
10493 
10494 #define duk_js_equals(thr,tv_x,tv_y) \
10495 	duk_js_equals_helper((thr), (tv_x), (tv_y), 0)
10496 #define duk_js_strict_equals(tv_x,tv_y) \
10497 	duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_STRICT)
10498 #define duk_js_samevalue(tv_x,tv_y) \
10499 	duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_SAMEVALUE)
10500 
10501 /* E5 Sections 11.8.1, 11.8.5; x < y */
10502 #define duk_js_lessthan(thr,tv_x,tv_y) \
10503 	duk_js_compare_helper((thr), (tv_x), (tv_Y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
10504 
10505 /* E5 Sections 11.8.2, 11.8.5; x > y  -->  y < x */
10506 #define duk_js_greaterthan(thr,tv_x,tv_y) \
10507 	duk_js_compare_helper((thr), (tv_y), (tv_x), 0)
10508 
10509 /* E5 Sections 11.8.3, 11.8.5; x <= y  -->  not (x > y)  -->  not (y < x) */
10510 #define duk_js_lessthanorequal(thr,tv_x,tv_y) \
10511 	duk_js_compare_helper((thr), (tv_y), (tv_x), DUK_COMPARE_FLAG_NEGATE)
10512 
10513 /* E5 Sections 11.8.4, 11.8.5; x >= y  -->  not (x < y) */
10514 #define duk_js_greaterthanorequal(thr,tv_x,tv_y) \
10515 	duk_js_compare_helper((thr), (tv_x), (tv_y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
10516 
10517 /* identifiers and environment handling */
10518 #if 0  /*unused*/
10519 DUK_INTERNAL duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
10520 #endif
10521 DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_bool_t throw_flag);
10522 DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_bool_t throw_flag);
10523 DUK_INTERNAL_DECL void duk_js_putvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_tval *val, duk_bool_t strict);
10524 DUK_INTERNAL_DECL void duk_js_putvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_bool_t strict);
10525 #if 0  /*unused*/
10526 DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
10527 #endif
10528 DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name);
10529 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);
10530 DUK_INTERNAL_DECL void duk_js_init_activation_environment_records_delayed(duk_hthread *thr, duk_activation *act);
10531 DUK_INTERNAL_DECL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env);
10532 DUK_INTERNAL_DECL duk_hobject *duk_create_activation_environment_record(duk_hthread *thr, duk_hobject *func, duk_size_t bottom_byteoff);
10533 DUK_INTERNAL_DECL void duk_js_push_closure(duk_hthread *thr,
10534                                            duk_hcompfunc *fun_temp,
10535                                            duk_hobject *outer_var_env,
10536                                            duk_hobject *outer_lex_env,
10537                                            duk_bool_t add_auto_proto);
10538 
10539 /* call handling */
10540 DUK_INTERNAL_DECL void duk_native_stack_check(duk_hthread *thr);
10541 DUK_INTERNAL_DECL duk_int_t duk_handle_call_unprotected(duk_hthread *thr, duk_idx_t idx_func, duk_small_uint_t call_flags);
10542 DUK_INTERNAL_DECL duk_int_t duk_handle_call_unprotected_nargs(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags);
10543 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);
10544 DUK_INTERNAL_DECL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uint_t proxy_invariant);
10545 #if defined(DUK_USE_VERBOSE_ERRORS)
10546 DUK_INTERNAL_DECL void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_base, duk_tval *tv_key);
10547 #endif
10548 
10549 /* bytecode execution */
10550 DUK_INTERNAL_DECL void duk_js_execute_bytecode(duk_hthread *exec_thr);
10551 
10552 #endif  /* DUK_JS_H_INCLUDED */
10553 /* #include duk_numconv.h */
10554 #line 1 "duk_numconv.h"
10555 /*
10556  *  Number-to-string conversion.  The semantics of these is very tightly
10557  *  bound with the ECMAScript semantics required for call sites.
10558  */
10559 
10560 #if !defined(DUK_NUMCONV_H_INCLUDED)
10561 #define DUK_NUMCONV_H_INCLUDED
10562 
10563 /* Output a specified number of digits instead of using the shortest
10564  * form.  Used for toPrecision() and toFixed().
10565  */
10566 #define DUK_N2S_FLAG_FIXED_FORMAT         (1U << 0)
10567 
10568 /* Force exponential format.  Used for toExponential(). */
10569 #define DUK_N2S_FLAG_FORCE_EXP            (1U << 1)
10570 
10571 /* If number would need zero padding (for whole number part), use
10572  * exponential format instead.  E.g. if input number is 12300, 3
10573  * digits are generated ("123"), output "1.23e+4" instead of "12300".
10574  * Used for toPrecision().
10575  */
10576 #define DUK_N2S_FLAG_NO_ZERO_PAD          (1U << 2)
10577 
10578 /* Digit count indicates number of fractions (i.e. an absolute
10579  * digit index instead of a relative one).  Used together with
10580  * DUK_N2S_FLAG_FIXED_FORMAT for toFixed().
10581  */
10582 #define DUK_N2S_FLAG_FRACTION_DIGITS      (1U << 3)
10583 
10584 /*
10585  *  String-to-number conversion
10586  */
10587 
10588 /* Maximum exponent value when parsing numbers.  This is not strictly
10589  * compliant as there should be no upper limit, but as we parse the
10590  * exponent without a bigint, impose some limit.  The limit should be
10591  * small enough that multiplying it (or limit-1 to be precise) won't
10592  * overflow signed 32-bit integer range.  Exponent is only parsed with
10593  * radix 10, but with maximum radix (36) a safe limit is:
10594  * (10000000*36).toString(16) -> '15752a00'
10595  */
10596 #define DUK_S2N_MAX_EXPONENT              10000000L
10597 
10598 /* Trim white space (= allow leading and trailing whitespace) */
10599 #define DUK_S2N_FLAG_TRIM_WHITE           (1U << 0)
10600 
10601 /* Allow exponent */
10602 #define DUK_S2N_FLAG_ALLOW_EXP            (1U << 1)
10603 
10604 /* Allow trailing garbage (e.g. treat "123foo" as "123) */
10605 #define DUK_S2N_FLAG_ALLOW_GARBAGE        (1U << 2)
10606 
10607 /* Allow leading plus sign */
10608 #define DUK_S2N_FLAG_ALLOW_PLUS           (1U << 3)
10609 
10610 /* Allow leading minus sign */
10611 #define DUK_S2N_FLAG_ALLOW_MINUS          (1U << 4)
10612 
10613 /* Allow 'Infinity' */
10614 #define DUK_S2N_FLAG_ALLOW_INF            (1U << 5)
10615 
10616 /* Allow fraction part */
10617 #define DUK_S2N_FLAG_ALLOW_FRAC           (1U << 6)
10618 
10619 /* Allow naked fraction (e.g. ".123") */
10620 #define DUK_S2N_FLAG_ALLOW_NAKED_FRAC     (1U << 7)
10621 
10622 /* Allow empty fraction (e.g. "123.") */
10623 #define DUK_S2N_FLAG_ALLOW_EMPTY_FRAC     (1U << 8)
10624 
10625 /* Allow empty string to be interpreted as 0 */
10626 #define DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO  (1U << 9)
10627 
10628 /* Allow leading zeroes (e.g. "0123" -> "123") */
10629 #define DUK_S2N_FLAG_ALLOW_LEADING_ZERO   (1U << 10)
10630 
10631 /* Allow automatic detection of hex base ("0x" or "0X" prefix),
10632  * overrides radix argument and forces integer mode.
10633  */
10634 #define DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT   (1U << 11)
10635 
10636 /* Allow automatic detection of legacy octal base ("0n"),
10637  * overrides radix argument and forces integer mode.
10638  */
10639 #define DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT   (1U << 12)
10640 
10641 /* Allow automatic detection of ES2015 octal base ("0o123"),
10642  * overrides radix argument and forces integer mode.
10643  */
10644 #define DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT   (1U << 13)
10645 
10646 /* Allow automatic detection of ES2015 binary base ("0b10001"),
10647  * overrides radix argument and forces integer mode.
10648  */
10649 #define DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT   (1U << 14)
10650 
10651 /*
10652  *  Prototypes
10653  */
10654 
10655 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);
10656 DUK_INTERNAL_DECL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags);
10657 
10658 #endif  /* DUK_NUMCONV_H_INCLUDED */
10659 /* #include duk_bi_protos.h */
10660 #line 1 "duk_bi_protos.h"
10661 /*
10662  *  Prototypes for built-in functions not automatically covered by the
10663  *  header declarations emitted by genbuiltins.py.
10664  */
10665 
10666 #if !defined(DUK_BUILTIN_PROTOS_H_INCLUDED)
10667 #define DUK_BUILTIN_PROTOS_H_INCLUDED
10668 
10669 /* Buffer size needed for ISO 8601 formatting.
10670  * Accurate value is 32 + 1 for NUL termination:
10671  *   >>> len('+123456-01-23T12:34:56.123+12:34')
10672  *   32
10673  * Include additional space to be safe.
10674  */
10675 #define  DUK_BI_DATE_ISO8601_BUFSIZE  40
10676 
10677 /* Helpers exposed for internal use */
10678 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);
10679 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags);
10680 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year);
10681 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x);
10682 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t year);
10683 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x);
10684 /* Built-in providers */
10685 #if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
10686 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_gettimeofday(void);
10687 #endif
10688 #if defined(DUK_USE_DATE_NOW_TIME)
10689 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_time(void);
10690 #endif
10691 #if defined(DUK_USE_DATE_NOW_WINDOWS)
10692 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows(void);
10693 #endif
10694 #if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
10695 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows_subms(void);
10696 #endif
10697 #if defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S) || defined(DUK_USE_DATE_TZO_GMTIME)
10698 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d);
10699 #endif
10700 #if defined(DUK_USE_DATE_TZO_WINDOWS)
10701 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d);
10702 #endif
10703 #if defined(DUK_USE_DATE_TZO_WINDOWS_NO_DST)
10704 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d);
10705 #endif
10706 #if defined(DUK_USE_DATE_PRS_STRPTIME)
10707 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr, const char *str);
10708 #endif
10709 #if defined(DUK_USE_DATE_PRS_GETDATE)
10710 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const char *str);
10711 #endif
10712 #if defined(DUK_USE_DATE_FMT_STRFTIME)
10713 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);
10714 #endif
10715 
10716 #if defined(DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME)
10717 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_monotonic_time_clock_gettime(void);
10718 #endif
10719 #if defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC)
10720 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_monotonic_time_windows_qpc(void);
10721 #endif
10722 
10723 DUK_INTERNAL_DECL
10724 void duk_bi_json_parse_helper(duk_hthread *thr,
10725                               duk_idx_t idx_value,
10726                               duk_idx_t idx_reviver,
10727                               duk_small_uint_t flags);
10728 DUK_INTERNAL_DECL
10729 void duk_bi_json_stringify_helper(duk_hthread *thr,
10730                                   duk_idx_t idx_value,
10731                                   duk_idx_t idx_replacer,
10732                                   duk_idx_t idx_space,
10733                                   duk_small_uint_t flags);
10734 
10735 DUK_INTERNAL_DECL duk_ret_t duk_textdecoder_decode_utf8_nodejs(duk_hthread *thr);
10736 
10737 #if defined(DUK_USE_ES6_PROXY)
10738 DUK_INTERNAL_DECL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h_proxy_target, duk_uint_t flags);
10739 #endif
10740 
10741 #endif  /* DUK_BUILTIN_PROTOS_H_INCLUDED */
10742 /* #include duk_selftest.h */
10743 #line 1 "duk_selftest.h"
10744 /*
10745  *  Selftest code
10746  */
10747 
10748 #if !defined(DUK_SELFTEST_H_INCLUDED)
10749 #define DUK_SELFTEST_H_INCLUDED
10750 
10751 #if defined(DUK_USE_SELF_TESTS)
10752 DUK_INTERNAL_DECL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_func,
10753                                                     duk_realloc_function realloc_func,
10754                                                     duk_free_function free_func,
10755                                                     void *udata);
10756 #endif
10757 
10758 #endif  /* DUK_SELFTEST_H_INCLUDED */
10759 #line 76 "duk_internal.h"
10760 
10761 #endif  /* DUK_INTERNAL_H_INCLUDED */
10762 #line 10 "duk_replacements.c"
10763 
10764 #if defined(DUK_USE_COMPUTED_NAN)
10765 DUK_INTERNAL double duk_computed_nan;
10766 #endif
10767 
10768 #if defined(DUK_USE_COMPUTED_INFINITY)
10769 DUK_INTERNAL double duk_computed_infinity;
10770 #endif
10771 
10772 #if defined(DUK_USE_REPL_FPCLASSIFY)
duk_repl_fpclassify(double x)10773 DUK_INTERNAL int duk_repl_fpclassify(double x) {
10774 	duk_double_union u;
10775 	duk_uint_fast16_t expt;
10776 	duk_small_int_t mzero;
10777 
10778 	u.d = x;
10779 	expt = (duk_uint_fast16_t) (u.us[DUK_DBL_IDX_US0] & 0x7ff0UL);
10780 	if (expt > 0x0000UL && expt < 0x7ff0UL) {
10781 		/* expt values [0x001,0x7fe] = normal */
10782 		return DUK_FP_NORMAL;
10783 	}
10784 
10785 	mzero = (u.ui[DUK_DBL_IDX_UI1] == 0 && (u.ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) == 0);
10786 	if (expt == 0x0000UL) {
10787 		/* expt 0x000 is zero/subnormal */
10788 		if (mzero) {
10789 			return DUK_FP_ZERO;
10790 		} else {
10791 			return DUK_FP_SUBNORMAL;
10792 		}
10793 	} else {
10794 		/* expt 0xfff is infinite/nan */
10795 		if (mzero) {
10796 			return DUK_FP_INFINITE;
10797 		} else {
10798 			return DUK_FP_NAN;
10799 		}
10800 	}
10801 }
10802 #endif
10803 
10804 #if defined(DUK_USE_REPL_SIGNBIT)
duk_repl_signbit(double x)10805 DUK_INTERNAL int duk_repl_signbit(double x) {
10806 	duk_double_union u;
10807 	u.d = x;
10808 	return (int) (u.uc[DUK_DBL_IDX_UC0] & 0x80UL);
10809 }
10810 #endif
10811 
10812 #if defined(DUK_USE_REPL_ISFINITE)
duk_repl_isfinite(double x)10813 DUK_INTERNAL int duk_repl_isfinite(double x) {
10814 	int c = DUK_FPCLASSIFY(x);
10815 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
10816 		return 0;
10817 	} else {
10818 		return 1;
10819 	}
10820 }
10821 #endif
10822 
10823 #if defined(DUK_USE_REPL_ISNAN)
duk_repl_isnan(double x)10824 DUK_INTERNAL int duk_repl_isnan(double x) {
10825 	int c = DUK_FPCLASSIFY(x);
10826 	return (c == DUK_FP_NAN);
10827 }
10828 #endif
10829 
10830 #if defined(DUK_USE_REPL_ISINF)
duk_repl_isinf(double x)10831 DUK_INTERNAL int duk_repl_isinf(double x) {
10832 	int c = DUK_FPCLASSIFY(x);
10833 	return (c == DUK_FP_INFINITE);
10834 }
10835 #endif
10836 #line 1 "duk_debug_macros.c"
10837 /*
10838  *  Debugging macro calls.
10839  */
10840 
10841 /* #include duk_internal.h -> already included */
10842 
10843 #if defined(DUK_USE_DEBUG)
10844 
10845 /*
10846  *  Debugging enabled
10847  */
10848 
10849 #include <stdio.h>
10850 #include <stdlib.h>
10851 #include <stdarg.h>
10852 
10853 #if !defined(DUK_USE_DEBUG_WRITE)
10854 #error debugging enabled (DUK_USE_DEBUG) but DUK_USE_DEBUG_WRITE not defined
10855 #endif
10856 
10857 #define DUK__DEBUG_BUFSIZE  DUK_USE_DEBUG_BUFSIZE
10858 
10859 #if defined(DUK_USE_VARIADIC_MACROS)
10860 
duk_debug_log(duk_int_t level,const char * file,duk_int_t line,const char * func,const char * fmt,...)10861 DUK_INTERNAL void duk_debug_log(duk_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...) {
10862 	va_list ap;
10863 	long arg_level;
10864 	const char *arg_file;
10865 	long arg_line;
10866 	const char *arg_func;
10867 	const char *arg_msg;
10868 	char buf[DUK__DEBUG_BUFSIZE];
10869 
10870 	va_start(ap, fmt);
10871 
10872 	duk_memzero((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);
10873 	duk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
10874 
10875 	arg_level = (long) level;
10876 	arg_file = (const char *) file;
10877 	arg_line = (long) line;
10878 	arg_func = (const char *) func;
10879 	arg_msg = (const char *) buf;
10880 	DUK_USE_DEBUG_WRITE(arg_level, arg_file, arg_line, arg_func, arg_msg);
10881 
10882 	va_end(ap);
10883 }
10884 
10885 #else  /* DUK_USE_VARIADIC_MACROS */
10886 
10887 DUK_INTERNAL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
10888 DUK_INTERNAL duk_int_t duk_debug_line_stash;
10889 DUK_INTERNAL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
10890 DUK_INTERNAL duk_int_t duk_debug_level_stash;
10891 
duk_debug_log(const char * fmt,...)10892 DUK_INTERNAL void duk_debug_log(const char *fmt, ...) {
10893 	va_list ap;
10894 	long arg_level;
10895 	const char *arg_file;
10896 	long arg_line;
10897 	const char *arg_func;
10898 	const char *arg_msg;
10899 	char buf[DUK__DEBUG_BUFSIZE];
10900 
10901 	va_start(ap, fmt);
10902 
10903 	duk_memzero((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);
10904 	duk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
10905 
10906 	arg_level = (long) duk_debug_level_stash;
10907 	arg_file = (const char *) duk_debug_file_stash;
10908 	arg_line = (long) duk_debug_line_stash;
10909 	arg_func = (const char *) duk_debug_func_stash;
10910 	arg_msg = (const char *) buf;
10911 	DUK_USE_DEBUG_WRITE(arg_level, arg_file, arg_line, arg_func, arg_msg);
10912 
10913 	va_end(ap);
10914 }
10915 
10916 #endif  /* DUK_USE_VARIADIC_MACROS */
10917 
10918 #else  /* DUK_USE_DEBUG */
10919 
10920 /*
10921  *  Debugging disabled
10922  */
10923 
10924 #endif  /* DUK_USE_DEBUG */
10925 
10926 /* automatic undefs */
10927 #undef DUK__DEBUG_BUFSIZE
10928 #line 1 "duk_builtins.c"
10929 /*
10930  *  Automatically generated by genbuiltins.py, do not edit!
10931  */
10932 
10933 /* #include duk_internal.h -> already included */
10934 
10935 #if defined(DUK_USE_ASSERTIONS)
10936 #define DUK__REFCINIT(refc) 0 /*h_assert_refcount*/, (refc) /*actual*/
10937 #else
10938 #define DUK__REFCINIT(refc) (refc) /*actual*/
10939 #endif
10940 
10941 #if defined(DUK_USE_ROM_STRINGS)
10942 #error ROM support not enabled, rerun configure.py with --rom-support
10943 #else  /* DUK_USE_ROM_STRINGS */
10944 DUK_INTERNAL const duk_uint8_t duk_strings_data[972] = {
10945 79,40,209,144,168,105,6,78,54,139,89,185,44,48,46,90,120,8,154,140,35,103,
10946 35,113,193,73,5,52,112,180,104,166,135,52,188,4,98,12,27,146,156,80,211,31,
10947 129,115,150,64,52,220,109,24,18,68,156,24,38,67,114,36,55,9,119,151,132,
10948 140,93,18,113,128,153,201,212,201,205,2,248,8,196,24,224,104,82,146,40,224,
10949 193,48,114,168,37,147,196,54,123,28,4,98,12,43,148,67,103,177,192,70,32,
10950 196,121,68,54,123,28,18,192,199,144,124,4,98,12,43,136,108,244,117,184,8,
10951 196,24,95,40,134,207,71,91,128,140,65,133,113,13,158,158,151,1,24,131,11,
10952 229,16,217,233,233,112,17,136,48,206,21,110,4,244,244,184,8,196,24,103,10,
10953 183,2,122,218,156,4,98,12,24,203,112,64,179,113,193,79,8,218,155,131,32,
10954 184,70,212,220,13,10,82,68,252,123,144,217,146,38,228,207,18,0,100,37,64,
10955 178,212,11,161,17,104,162,96,10,200,193,57,165,65,169,16,5,100,81,27,70,18,
10956 32,10,200,68,185,13,116,221,197,184,64,89,57,41,197,13,49,234,5,208,156,
10957 113,87,55,118,147,20,187,56,161,166,92,221,212,73,210,236,226,134,153,115,
10958 119,76,201,203,179,138,26,99,73,212,136,136,164,25,174,137,56,32,72,137,
10959 101,23,52,45,13,34,86,9,79,136,104,201,114,149,96,52,138,134,140,151,75,
10960 226,233,186,120,121,22,39,54,83,141,5,55,68,236,36,164,3,16,225,115,150,64,
10961 52,205,163,2,72,154,83,138,26,99,75,12,11,150,103,5,36,20,211,70,140,133,
10962 67,72,49,241,160,227,81,196,52,168,106,39,132,252,183,136,105,80,212,79,2,
10963 249,110,128,126,88,95,133,109,237,237,237,151,235,127,46,249,119,203,190,
10964 186,206,33,181,2,208,61,190,12,19,34,65,19,81,132,108,228,97,1,107,33,12,
10965 32,45,100,137,64,247,175,9,19,155,41,198,130,155,134,69,146,100,227,226,
10966 231,146,51,192,204,73,140,224,145,221,102,241,68,196,169,248,30,75,12,11,
10967 151,242,233,187,143,138,24,137,162,164,255,253,63,3,201,97,129,114,254,92,
10968 112,75,136,108,166,6,136,159,255,167,224,121,44,48,46,95,203,166,238,74,
10969 113,67,77,201,128,223,255,223,224,121,44,48,46,95,203,145,46,9,205,16,39,
10970 201,62,36,0,192,21,147,255,238,145,39,199,197,211,116,240,242,113,197,78,
10971 214,211,226,233,187,107,105,19,119,37,56,161,166,52,221,212,201,205,36,240,
10972 242,16,96,152,12,26,20,164,137,150,70,154,103,28,137,50,202,96,18,132,241,
10973 41,104,105,56,218,48,36,138,183,57,56,128,68,24,38,2,52,12,34,10,133,147,
10974 141,3,8,119,185,13,153,34,125,206,76,17,49,38,93,206,52,151,154,119,56,28,
10975 76,130,112,200,141,206,21,209,96,23,35,238,114,160,139,0,243,238,114,78,
10976 164,68,68,110,113,226,210,90,26,66,110,113,128,121,247,57,80,68,141,170,
10977 183,56,84,52,11,70,73,19,110,114,160,93,8,113,57,143,66,200,84,53,244,154,
10978 73,24,240,81,32,38,68,18,49,228,207,23,88,100,109,70,114,92,193,4,137,173,
10979 168,36,220,73,19,247,247,182,168,209,144,187,223,58,156,104,79,190,183,127,
10980 123,105,160,110,247,206,167,26,19,239,173,223,222,218,67,75,189,243,169,
10981 198,132,251,235,183,247,182,154,134,151,123,231,83,141,9,247,215,111,239,
10982 109,22,141,22,247,206,167,26,19,239,172,223,218,45,26,47,157,78,52,39,223,
10983 74,24,144,10,32,129,34,20,64,152,142,129,57,179,67,104,68,12,129,161,140,
10984 72,156,100,40,40,185,152,100,89,38,65,13,196,34,228,67,149,13,2,215,129,
10985 149,209,65,104,209,77,14,104,144,81,33,170,67,101,48,52,68,113,70,210,88,
10986 209,36,233,22,154,86,68,196,114,76,232,145,102,120,186,195,156,112,105,225,
10987 228,113,71,80,68,162,115,101,50,85,200,25,108,116,44,132,178,38,114,137,96,
10988 148,136,70,209,134,37,222,232,204,228,188,200,209,200,200,99,221,25,150,84,
10989 121,34,70,209,107,36,227,66,20,160,92,136,164,49,235,35,8,217,201,40,108,
10990 201,18,128,68,26,201,51,188,2,80,12,67,190,40,168,38,68,190,46,153,5,50,12,
10991 207,160,86,129,26,83,4,208,34,225,4,88,192,
10992 };
10993 #endif  /* DUK_USE_ROM_STRINGS */
10994 
10995 #if defined(DUK_USE_ROM_OBJECTS)
10996 #error ROM support not enabled, rerun configure.py with --rom-support
10997 #else  /* DUK_USE_ROM_OBJECTS */
10998 /* native functions: 185 */
10999 DUK_INTERNAL const duk_c_function duk_bi_native_functions[185] = {
11000 	NULL,
11001 	duk_bi_array_constructor,
11002 	duk_bi_array_constructor_is_array,
11003 	duk_bi_array_prototype_concat,
11004 	duk_bi_array_prototype_indexof_shared,
11005 	duk_bi_array_prototype_iter_shared,
11006 	duk_bi_array_prototype_join_shared,
11007 	duk_bi_array_prototype_pop,
11008 	duk_bi_array_prototype_push,
11009 	duk_bi_array_prototype_reduce_shared,
11010 	duk_bi_array_prototype_reverse,
11011 	duk_bi_array_prototype_shift,
11012 	duk_bi_array_prototype_slice,
11013 	duk_bi_array_prototype_sort,
11014 	duk_bi_array_prototype_splice,
11015 	duk_bi_array_prototype_to_string,
11016 	duk_bi_array_prototype_unshift,
11017 	duk_bi_arraybuffer_constructor,
11018 	duk_bi_arraybuffer_isview,
11019 	duk_bi_boolean_constructor,
11020 	duk_bi_boolean_prototype_tostring_shared,
11021 	duk_bi_buffer_compare_shared,
11022 	duk_bi_buffer_readfield,
11023 	duk_bi_buffer_slice_shared,
11024 	duk_bi_buffer_writefield,
11025 	duk_bi_cbor_decode,
11026 	duk_bi_cbor_encode,
11027 	duk_bi_dataview_constructor,
11028 	duk_bi_date_constructor,
11029 	duk_bi_date_constructor_now,
11030 	duk_bi_date_constructor_parse,
11031 	duk_bi_date_constructor_utc,
11032 	duk_bi_date_prototype_get_shared,
11033 	duk_bi_date_prototype_get_timezone_offset,
11034 	duk_bi_date_prototype_set_shared,
11035 	duk_bi_date_prototype_set_time,
11036 	duk_bi_date_prototype_to_json,
11037 	duk_bi_date_prototype_toprimitive,
11038 	duk_bi_date_prototype_tostring_shared,
11039 	duk_bi_date_prototype_value_of,
11040 	duk_bi_duktape_object_act,
11041 	duk_bi_duktape_object_compact,
11042 	duk_bi_duktape_object_dec,
11043 	duk_bi_duktape_object_enc,
11044 	duk_bi_duktape_object_fin,
11045 	duk_bi_duktape_object_gc,
11046 	duk_bi_duktape_object_info,
11047 	duk_bi_error_constructor_shared,
11048 	duk_bi_error_prototype_filename_getter,
11049 	duk_bi_error_prototype_filename_setter,
11050 	duk_bi_error_prototype_linenumber_getter,
11051 	duk_bi_error_prototype_linenumber_setter,
11052 	duk_bi_error_prototype_stack_getter,
11053 	duk_bi_error_prototype_stack_setter,
11054 	duk_bi_error_prototype_to_string,
11055 	duk_bi_function_constructor,
11056 	duk_bi_function_prototype,
11057 	duk_bi_function_prototype_apply,
11058 	duk_bi_function_prototype_bind,
11059 	duk_bi_function_prototype_call,
11060 	duk_bi_function_prototype_hasinstance,
11061 	duk_bi_function_prototype_to_string,
11062 	duk_bi_global_object_decode_uri,
11063 	duk_bi_global_object_decode_uri_component,
11064 	duk_bi_global_object_encode_uri,
11065 	duk_bi_global_object_encode_uri_component,
11066 	duk_bi_global_object_escape,
11067 	duk_bi_global_object_eval,
11068 	duk_bi_global_object_is_finite,
11069 	duk_bi_global_object_is_nan,
11070 	duk_bi_global_object_parse_float,
11071 	duk_bi_global_object_parse_int,
11072 	duk_bi_global_object_unescape,
11073 	duk_bi_json_object_parse,
11074 	duk_bi_json_object_stringify,
11075 	duk_bi_math_object_clz32,
11076 	duk_bi_math_object_hypot,
11077 	duk_bi_math_object_imul,
11078 	duk_bi_math_object_max,
11079 	duk_bi_math_object_min,
11080 	duk_bi_math_object_onearg_shared,
11081 	duk_bi_math_object_random,
11082 	duk_bi_math_object_sign,
11083 	duk_bi_math_object_twoarg_shared,
11084 	duk_bi_native_function_length,
11085 	duk_bi_native_function_name,
11086 	duk_bi_nodejs_buffer_byte_length,
11087 	duk_bi_nodejs_buffer_concat,
11088 	duk_bi_nodejs_buffer_constructor,
11089 	duk_bi_nodejs_buffer_copy,
11090 	duk_bi_nodejs_buffer_fill,
11091 	duk_bi_nodejs_buffer_is_buffer,
11092 	duk_bi_nodejs_buffer_is_encoding,
11093 	duk_bi_nodejs_buffer_tojson,
11094 	duk_bi_nodejs_buffer_tostring,
11095 	duk_bi_nodejs_buffer_write,
11096 	duk_bi_number_check_shared,
11097 	duk_bi_number_constructor,
11098 	duk_bi_number_prototype_to_exponential,
11099 	duk_bi_number_prototype_to_fixed,
11100 	duk_bi_number_prototype_to_locale_string,
11101 	duk_bi_number_prototype_to_precision,
11102 	duk_bi_number_prototype_to_string,
11103 	duk_bi_number_prototype_value_of,
11104 	duk_bi_object_constructor,
11105 	duk_bi_object_constructor_assign,
11106 	duk_bi_object_constructor_create,
11107 	duk_bi_object_constructor_define_properties,
11108 	duk_bi_object_constructor_define_property,
11109 	duk_bi_object_constructor_get_own_property_descriptor,
11110 	duk_bi_object_constructor_is,
11111 	duk_bi_object_constructor_is_extensible,
11112 	duk_bi_object_constructor_is_sealed_frozen_shared,
11113 	duk_bi_object_constructor_keys_shared,
11114 	duk_bi_object_constructor_prevent_extensions,
11115 	duk_bi_object_constructor_seal_freeze_shared,
11116 	duk_bi_object_getprototype_shared,
11117 	duk_bi_object_prototype_defineaccessor,
11118 	duk_bi_object_prototype_has_own_property,
11119 	duk_bi_object_prototype_is_prototype_of,
11120 	duk_bi_object_prototype_lookupaccessor,
11121 	duk_bi_object_prototype_property_is_enumerable,
11122 	duk_bi_object_prototype_to_locale_string,
11123 	duk_bi_object_prototype_to_string,
11124 	duk_bi_object_prototype_value_of,
11125 	duk_bi_object_setprototype_shared,
11126 	duk_bi_performance_now,
11127 	duk_bi_pointer_constructor,
11128 	duk_bi_pointer_prototype_tostring_shared,
11129 	duk_bi_proxy_constructor,
11130 	duk_bi_reflect_apply,
11131 	duk_bi_reflect_construct,
11132 	duk_bi_reflect_object_delete_property,
11133 	duk_bi_reflect_object_get,
11134 	duk_bi_reflect_object_has,
11135 	duk_bi_reflect_object_set,
11136 	duk_bi_regexp_constructor,
11137 	duk_bi_regexp_prototype_exec,
11138 	duk_bi_regexp_prototype_flags,
11139 	duk_bi_regexp_prototype_shared_getter,
11140 	duk_bi_regexp_prototype_test,
11141 	duk_bi_regexp_prototype_tostring,
11142 	duk_bi_string_constructor,
11143 	duk_bi_string_constructor_from_char_code,
11144 	duk_bi_string_constructor_from_code_point,
11145 	duk_bi_string_prototype_caseconv_shared,
11146 	duk_bi_string_prototype_char_at,
11147 	duk_bi_string_prototype_char_code_at,
11148 	duk_bi_string_prototype_concat,
11149 	duk_bi_string_prototype_includes,
11150 	duk_bi_string_prototype_indexof_shared,
11151 	duk_bi_string_prototype_locale_compare,
11152 	duk_bi_string_prototype_match,
11153 	duk_bi_string_prototype_repeat,
11154 	duk_bi_string_prototype_replace,
11155 	duk_bi_string_prototype_search,
11156 	duk_bi_string_prototype_slice,
11157 	duk_bi_string_prototype_split,
11158 	duk_bi_string_prototype_startswith_endswith,
11159 	duk_bi_string_prototype_substr,
11160 	duk_bi_string_prototype_substring,
11161 	duk_bi_string_prototype_to_string,
11162 	duk_bi_string_prototype_trim,
11163 	duk_bi_symbol_constructor_shared,
11164 	duk_bi_symbol_key_for,
11165 	duk_bi_symbol_toprimitive,
11166 	duk_bi_symbol_tostring_shared,
11167 	duk_bi_textdecoder_constructor,
11168 	duk_bi_textdecoder_prototype_decode,
11169 	duk_bi_textdecoder_prototype_shared_getter,
11170 	duk_bi_textencoder_constructor,
11171 	duk_bi_textencoder_prototype_encode,
11172 	duk_bi_textencoder_prototype_encoding_getter,
11173 	duk_bi_thread_constructor,
11174 	duk_bi_thread_current,
11175 	duk_bi_thread_resume,
11176 	duk_bi_thread_yield,
11177 	duk_bi_type_error_thrower,
11178 	duk_bi_typedarray_buffer_getter,
11179 	duk_bi_typedarray_bytelength_getter,
11180 	duk_bi_typedarray_byteoffset_getter,
11181 	duk_bi_typedarray_constructor,
11182 	duk_bi_typedarray_set,
11183 	duk_bi_uint8array_allocplain,
11184 	duk_bi_uint8array_plainof,
11185 };
11186 #if defined(DUK_USE_DOUBLE_LE)
11187 DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = {
11188 144,148,105,226,32,68,52,228,254,12,104,202,37,132,52,167,194,138,105,245,
11189 124,57,28,211,57,18,64,52,239,126,44,138,111,175,241,164,19,87,145,30,33,
11190 167,22,145,159,8,211,139,9,225,42,5,240,145,139,163,163,8,211,139,10,228,
11191 64,211,19,132,140,93,29,56,70,156,88,119,34,66,146,36,104,137,194,70,46,
11192 142,172,35,78,44,47,146,195,102,11,240,145,139,163,175,8,211,139,9,228,240,
11193 242,112,145,139,163,179,8,211,139,8,237,34,130,118,49,116,118,225,26,48,0,
11194 1,98,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
11195 33,8,66,26,180,105,97,167,68,150,34,33,154,112,0,1,91,247,35,79,111,237,
11196 198,174,232,47,31,23,95,17,13,31,249,96,211,49,50,53,214,77,141,24,0,0,181,
11197 10,228,240,242,15,128,140,65,128,134,188,0,0,90,167,97,181,224,0,2,213,62,
11198 53,224,0,2,213,66,237,120,0,0,181,81,204,107,192,0,5,170,150,67,94,0,0,45,
11199 84,245,90,240,0,1,106,169,162,215,128,0,11,85,93,150,188,0,0,90,171,111,53,
11200 109,22,162,26,48,0,1,84,23,201,146,243,225,26,39,12,145,136,104,192,0,5,61,
11201 11,228,201,121,240,100,19,134,72,196,33,195,14,40,203,112,64,190,76,232,
11202 145,153,136,0,0,0,0,0,0,31,15,249,152,0,0,0,0,0,0,30,15,249,120,144,13,96,
11203 155,194,56,80,206,36,67,141,20,228,70,57,81,206,100,131,156,39,132,168,23,
11204 194,70,46,137,208,21,200,129,166,39,9,24,186,39,72,119,34,66,146,36,104,
11205 137,194,70,46,137,212,23,201,97,179,5,248,72,197,209,58,194,121,60,60,156,
11206 36,98,232,157,129,29,164,80,78,198,46,137,218,146,121,25,71,146,9,209,5,
11207 209,61,48,126,14,138,152,30,67,186,23,143,139,175,131,202,135,228,72,85,
11208 144,83,60,179,30,94,209,233,102,30,98,105,230,103,30,114,121,231,104,30,
11209 122,137,231,233,30,130,153,232,106,30,138,169,232,235,30,144,67,193,25,19,
11210 136,108,207,30,41,224,140,137,194,173,192,153,228,5,242,100,188,248,70,137,
11211 195,36,79,78,47,147,37,231,193,144,78,25,34,122,145,111,36,74,232,176,13,
11212 17,61,234,226,93,207,148,160,84,75,141,7,27,161,32,33,18,225,80,212,76,154,
11213 2,2,70,65,56,100,237,34,140,209,2,67,32,156,50,118,145,64,186,230,61,205,
11214 35,103,155,32,36,141,19,134,78,210,40,206,16,36,70,137,195,39,105,20,11,
11215 174,99,220,210,54,121,210,1,137,33,1,228,207,16,17,70,146,66,3,201,164,32,
11216 0,65,112,152,56,196,159,31,23,77,211,195,201,199,23,160,72,214,246,81,6,12,
11217 73,241,214,111,31,23,60,145,158,56,50,72,81,67,230,232,242,80,19,49,39,199,
11218 89,188,124,92,242,70,120,227,64,194,75,154,72,12,9,73,6,111,21,120,12,40,
11219 144,19,39,25,0,225,144,168,105,56,248,185,228,140,241,200,96,64,100,42,26,
11220 78,62,46,121,35,52,18,92,116,1,36,64,47,158,64,49,98,66,100,156,242,65,23,
11221 196,149,35,103,194,94,100,108,144,230,203,156,64,66,37,201,16,11,32,249,
11222 132,4,34,92,44,93,146,55,152,72,24,137,112,151,153,27,36,5,100,229,144,8,
11223 162,98,92,210,5,76,73,241,214,111,31,23,60,145,158,57,44,48,46,92,185,164,
11224 160,72,151,41,0,50,107,179,244,59,36,93,127,92,6,19,172,3,11,216,0,56,224,
11225 151,29,102,241,241,115,201,25,227,164,64,106,37,199,197,211,116,240,242,
11226 113,197,233,144,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,84,
11227 129,13,173,161,144,168,105,56,98,78,100,142,214,215,69,1,13,173,161,144,
11228 168,105,57,34,78,100,142,214,215,69,16,67,107,105,110,114,168,254,24,147,
11229 153,35,181,181,212,32,67,107,105,110,114,168,254,72,147,153,35,181,181,212,
11230 36,65,130,3,144,8,26,252,200,13,30,85,16,16,64,90,242,231,192,64,161,163,
11231 203,31,26,172,193,17,4,23,105,159,96,27,172,251,16,32,196,4,14,137,112,17,
11232 136,48,164,28,134,80,215,202,1,132,130,8,12,39,52,64,155,31,24,56,36,1,189,
11233 207,132,0,35,233,35,195,62,3,196,149,36,100,72,160,2,200,232,44,227,0,11,
11234 37,160,68,142,128,36,157,25,200,32,26,79,90,4,73,43,192,122,54,71,65,103,
11235 44,248,14,134,140,151,227,138,231,208,45,96,148,248,134,140,151,227,138,
11236 231,240,1,255,254,10,74,146,56,128,104,4,147,152,72,6,144,28,174,143,8,1,
11237 30,1,165,3,96,31,0,211,3,21,11,153,35,0,211,131,68,131,160,137,16,250,5,
11238 196,131,160,137,200,160,199,156,67,248,0,255,255,65,140,10,48,177,115,56,
11239 35,130,60,19,134,79,89,240,52,177,115,56,39,12,156,123,144,217,251,15,135,
11240 34,167,30,20,170,154,255,232,12,47,244,0,97,28,17,224,39,238,32,40,71,4,
11241 120,39,12,156,4,253,228,5,137,195,39,30,228,54,124,4,253,228,128,194,115,
11242 68,9,252,15,128,232,104,201,126,56,191,35,64,90,193,41,241,13,25,47,199,23,
11243 228,105,3,86,225,1,100,224,156,199,130,36,249,144,10,192,76,71,250,16,15,
11244 18,61,96,17,62,200,3,72,128,136,143,247,32,22,75,64,137,248,64,22,79,90,39,
11245 249,64,38,84,12,167,20,52,223,196,2,230,238,45,214,36,120,32,72,158,208,4,
11246 102,238,45,194,2,201,197,186,196,143,4,9,19,218,0,92,221,202,61,228,143,4,
11247 9,19,218,8,35,55,113,110,16,22,78,81,239,36,120,32,72,158,208,64,73,197,12,
11248 255,0,13,18,60,128,159,212,128,169,76,17,156,185,100,76,255,163,64,65,26,
11249 57,114,200,153,255,70,144,33,13,18,232,50,75,226,104,6,149,3,41,199,246,
11250 130,12,128,28,142,156,120,203,175,158,8,194,207,1,6,81,20,79,88,11,237,84,
11251 11,161,32,127,255,255,255,255,255,247,191,137,235,16,221,170,129,116,36,0,
11252 16,0,0,0,0,0,0,12,196,0,0,0,0,0,0,15,135,242,61,123,164,137,162,164,218,67,
11253 74,134,162,120,128,0,0,0,0,0,1,224,254,71,173,33,129,52,84,155,72,105,80,
11254 212,79,16,0,0,0,0,0,0,60,63,195,244,143,146,22,230,192,0,0,0,0,0,0,176,60,
11255 33,214,2,251,82,1,73,180,134,204,134,36,96,127,255,255,255,255,255,159,161,
11256 144,235,16,221,169,0,164,218,67,102,67,18,48,63,255,255,255,255,255,207,
11257 240,196,60,17,145,56,134,204,241,226,158,8,200,156,42,220,9,158,65,196,34,
11258 92,42,26,137,147,120,64,74,37,196,54,100,49,35,188,36,5,68,184,208,113,187,
11259 194,80,212,75,146,1,73,196,54,100,49,35,188,38,57,37,56,240,0,0,0,0,0,0,0,
11260 0,32,235,248,68,48,156,2,24,94,24,0,243,119,10,139,144,123,242,3,102,238,
11261 18,239,115,72,217,160,11,223,16,23,55,113,241,32,145,36,57,188,18,16,102,3,
11262 5,120,35,34,89,32,15,180,152,173,127,0,218,235,88,0,228,180,227,200,0,0,0,
11263 0,0,0,248,127,197,107,240,64,6,77,220,24,38,78,74,113,67,77,130,4,12,155,
11264 185,52,48,156,148,226,134,155,4,10,194,96,129,132,166,238,45,194,2,201,193,
11265 130,100,228,167,20,52,216,32,113,41,187,139,112,128,178,114,104,97,57,41,
11266 197,13,54,8,32,48,216,32,130,195,224,130,19,97,124,134,23,6,0,57,137,62,77,
11267 12,38,12,0,179,18,124,45,22,190,96,128,141,176,134,28,98,79,180,152,139,
11268 218,45,124,193,1,27,97,16,32,196,159,24,230,204,246,194,40,89,137,62,210,
11269 98,103,92,217,158,216,70,7,49,39,193,130,100,182,17,194,140,73,246,147,16,
11270 250,9,146,216,72,6,49,39,193,131,22,194,72,73,137,62,210,98,31,65,139,97,
11271 40,32,196,159,14,234,70,86,194,88,89,137,62,210,98,63,93,72,202,216,76,10,
11272 49,39,198,33,180,153,37,108,38,134,152,147,237,38,38,117,13,164,201,43,97,
11273 56,40,196,159,36,65,57,163,149,176,158,26,98,79,180,152,165,210,9,205,28,
11274 173,133,0,243,18,124,98,22,180,72,130,115,71,43,97,68,72,196,159,105,49,51,
11275 168,90,209,34,9,205,28,173,133,33,19,18,124,154,24,76,185,164,227,138,89,
11276 18,119,0,7,145,39,201,161,132,188,64,124,137,62,49,11,90,36,65,57,163,149,
11277 210,166,37,34,79,180,152,153,212,45,104,145,4,230,142,87,74,160,84,137,62,
11278 72,130,115,71,43,171,234,134,200,147,237,38,41,116,130,115,71,43,171,235,5,
11279 72,147,227,16,218,76,146,186,254,184,108,137,62,210,98,103,80,218,76,146,
11280 186,254,192,68,137,62,29,212,140,174,207,178,23,34,79,180,152,143,215,82,
11281 50,187,62,208,60,137,62,12,19,37,210,182,21,34,79,180,152,135,208,76,151,
11282 74,224,68,137,62,49,205,153,238,175,186,23,34,79,180,152,153,215,54,103,
11283 186,190,240,92,137,62,22,139,95,48,64,70,235,251,225,210,36,251,73,136,189,
11284 162,215,204,16,17,186,255,2,14,98,79,152,32,35,108,48,64,242,36,249,130,2,
11285 55,75,6,212,224,72,200,51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,
11286 48,98,115,249,201,117,243,249,195,21,159,206,38,47,63,156,86,8,75,144,94,
11287 82,1,38,73,79,208,67,95,233,1,6,128,14,79,129,186,40,249,18,149,182,207,
11288 144,200,155,188,248,204,105,184,207,142,199,137,175,201,0,159,72,10,5,21,
11289 221,10,120,74,129,124,36,98,232,228,74,81,62,160,20,10,107,186,21,114,32,
11290 105,137,194,70,46,142,68,165,19,235,1,64,170,187,161,119,34,66,146,36,104,
11291 137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35,
11292 23,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165,
11293 19,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,
11294 72,115,96,0,0,0,0,0,15,106,32,91,60,165,195,201,194,8,134,149,216,162,0,
11295 192,41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176,
11296 195,192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20,
11297 1,119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219,
11298 36,98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0,
11299 0,83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1,
11300 102,8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48,
11301 20,28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179,
11302 216,162,152,192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,
11303 81,76,104,73,137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,
11304 166,56,36,196,159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,
11305 20,188,20,98,79,133,91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,
11306 68,137,62,81,13,158,197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,
11307 159,40,134,207,71,90,155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,
11308 67,103,167,165,77,174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,
11309 173,192,158,182,165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,
11310 140,35,103,0,0,0,0,0,0,3,192,252,206,25,228,35,208,226,100,150,211,201,29,
11311 162,44,140,35,103,0,0,0,0,0,0,3,192,252,206,25,244,35,208,226,100,150,211,
11312 201,29,162,44,140,35,103,0,0,0,0,0,0,3,192,252,206,26,4,35,208,226,100,150,
11313 211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,1,0,206,26,20,35,208,226,100,
11314 150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,1,0,206,26,36,35,208,226,
11315 100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,52,35,208,
11316 226,100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,68,35,
11317 208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,84,
11318 35,208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,129,0,195,
11319 154,99,16,38,36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,
11320 25,18,0,125,162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,
11321 235,116,36,162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,
11322 196,54,122,58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,
11323 200,144,3,237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,
11324 213,146,138,77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,
11325 183,2,125,89,40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,
11326 221,64,172,157,89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,
11327 31,104,142,182,125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,
11328 18,0,124,67,103,213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,
11329 59,68,117,179,216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,
11330 39,104,142,182,122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,
11331 73,77,162,6,90,40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,
11332 61,29,110,132,148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,
11333 67,109,20,76,157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,
11334 167,165,213,146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,
11335 68,201,194,173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,
11336 193,182,138,38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,
11337 178,116,36,166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,
11338 157,162,58,217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,
11339 81,50,113,13,159,66,74,113,97,175,221,48,216,110,64,4,42,22,189,179,0,196,
11340 133,0,185,80,32,28,78,99,193,18,80,36,4,19,159,141,172,0,178,90,4,74,73,0,
11341 22,209,68,201,187,129,4,2,8,3,132,64,60,36,6,149,113,72,176,171,240,84,0,
11342 157,91,116,116,32,11,42,218,221,216,181,129,32,3,234,219,165,3,188,231,235,
11343 249,8,187,152,252,47,86,227,105,18,7,244,17,91,42,56,175,185,248,110,173,
11344 198,209,208,36,0,238,82,97,87,188,189,179,240,93,122,32,12,22,162,42,125,
11345 144,132,160,7,236,161,25,232,237,105,64,205,59,127,102,158,160,230,63,11,
11346 217,66,51,210,129,154,118,254,205,61,65,236,127,171,197,34,168,48,6,90,194,
11347 1,0,39,75,88,72,8,9,33,186,194,80,64,76,13,214,19,2,130,96,110,150,189,0,
11348 65,6,51,214,20,128,65,17,11,214,19,130,137,121,211,210,211,144,6,39,75,88,
11349 80,0,201,119,235,10,8,41,86,231,71,88,80,129,79,135,186,122,133,224,34,25,
11350 69,234,80,3,91,141,172,40,96,139,113,180,181,133,36,21,110,54,142,134,176,
11351 165,1,176,23,213,47,0,216,134,234,215,128,111,117,181,232,128,209,3,70,230,
11352 107,64,5,139,168,209,235,10,32,36,144,102,235,136,3,146,27,172,40,160,146,
11353 132,103,172,40,192,115,3,117,133,28,22,113,163,69,172,41,103,1,66,188,17,
11354 145,52,168,4,202,113,67,76,130,227,76,194,13,240,108,0,0,83,224,0,2,193,0,
11355 104,146,84,97,48,0,1,94,192,56,169,24,145,179,192,0,5,112,8,56,16,32,128,
11356 56,18,52,125,230,86,147,190,140,28,50,21,13,39,31,23,60,145,158,57,12,141,
11357 47,129,6,155,194,188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,
11358 15,155,163,201,68,14,49,39,199,197,211,116,240,242,113,197,232,18,180,254,
11359 36,3,17,46,18,243,35,100,128,172,156,178,70,163,154,76,34,248,146,164,108,
11360 248,75,204,141,146,28,217,115,137,27,95,27,241,173,236,162,160,224,200,2,
11361 206,9,113,13,148,192,209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,
11362 178,66,213,136,68,201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,
11363 38,232,255,252,92,221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,
11364 38,3,66,213,47,135,254,72,12,162,99,133,116,112,0,1,72,66,14,16,16,50,37,
11365 202,160,150,154,66,14,20,8,57,192,28,24,80,113,50,113,100,105,166,120,248,
11366 0,0,179,1,65,196,201,199,20,178,36,227,224,0,2,208,54,113,240,0,1,100,11,
11367 181,192,0,5,178,1,18,160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,
11368 121,35,180,69,145,132,108,224,0,0,0,0,0,0,120,31,153,188,56,132,122,28,76,
11369 146,218,121,35,180,69,145,132,108,224,0,0,0,0,0,0,120,31,168,160,45,110,23,
11370 30,176,33,184,0,0,183,32,29,235,2,27,199,23,0,0,23,4,51,120,129,8,244,56,
11371 153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,240,63,51,120,145,8,244,
11372 56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,120,161,8,
11373 244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,120,177,
11374 8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,120,
11375 193,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,
11376 120,209,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,
11377 51,120,225,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,32,
11378 64,32,227,194,0,97,57,162,4,246,104,5,34,92,35,68,225,161,166,220,16,16,
11379 137,112,52,41,73,29,185,1,65,196,201,197,145,166,153,246,72,3,137,204,120,
11380 34,74,8,199,1,67,17,162,112,201,84,128,97,144,78,25,42,16,131,169,1,205,66,
11381 8,35,68,225,161,166,239,128,0,10,192,64,196,104,156,50,96,0,2,172,73,240,
11382 117,96,57,170,97,4,104,156,52,52,221,240,0,1,82,1,74,9,129,125,240,0,1,82,
11383 32,148,25,174,137,58,23,51,190,0,0,42,69,64,195,32,156,50,96,0,2,160,81,
11384 238,2,3,107,173,218,3,192,
11385 };
11386 #elif defined(DUK_USE_DOUBLE_BE)
11387 DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = {
11388 144,148,105,226,32,68,52,228,254,12,104,202,37,132,52,167,194,138,105,245,
11389 124,57,28,211,57,18,64,52,239,126,44,138,111,175,241,164,19,87,145,30,33,
11390 167,22,145,159,8,211,139,9,225,42,5,240,145,139,163,163,8,211,139,10,228,
11391 64,211,19,132,140,93,29,56,70,156,88,119,34,66,146,36,104,137,194,70,46,
11392 142,172,35,78,44,47,146,195,102,11,240,145,139,163,175,8,211,139,9,228,240,
11393 242,112,145,139,163,179,8,211,139,8,237,34,130,118,49,116,118,225,26,48,0,
11394 1,98,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
11395 33,8,66,26,180,105,97,167,68,150,34,33,154,112,0,1,91,247,35,79,111,237,
11396 198,174,232,47,31,23,95,17,13,31,249,96,211,49,50,53,214,77,141,24,0,0,181,
11397 10,228,240,242,15,128,140,65,128,134,188,0,0,90,167,97,181,224,0,2,213,62,
11398 53,224,0,2,213,66,237,120,0,0,181,81,204,107,192,0,5,170,150,67,94,0,0,45,
11399 84,245,90,240,0,1,106,169,162,215,128,0,11,85,93,150,188,0,0,90,171,111,53,
11400 109,22,162,26,48,0,1,84,23,201,146,243,225,26,39,12,145,136,104,192,0,5,61,
11401 11,228,201,121,240,100,19,134,72,196,33,195,14,40,203,112,64,190,76,232,
11402 145,153,136,15,255,0,0,0,0,0,0,25,152,15,254,0,0,0,0,0,0,25,120,144,13,96,
11403 155,194,56,80,206,36,67,141,20,228,70,57,81,206,100,131,156,39,132,168,23,
11404 194,70,46,137,208,21,200,129,166,39,9,24,186,39,72,119,34,66,146,36,104,
11405 137,194,70,46,137,212,23,201,97,179,5,248,72,197,209,58,194,121,60,60,156,
11406 36,98,232,157,129,29,164,80,78,198,46,137,218,146,121,25,71,146,9,209,5,
11407 209,61,48,126,14,138,152,30,67,186,23,143,139,175,131,202,135,228,72,85,
11408 144,83,60,179,30,94,209,233,102,30,98,105,230,103,30,114,121,231,104,30,
11409 122,137,231,233,30,130,153,232,106,30,138,169,232,235,30,144,67,193,25,19,
11410 136,108,207,30,41,224,140,137,194,173,192,153,228,5,242,100,188,248,70,137,
11411 195,36,79,78,47,147,37,231,193,144,78,25,34,122,145,111,36,74,232,176,13,
11412 17,61,234,226,93,207,148,160,84,75,141,7,27,161,32,33,18,225,80,212,76,154,
11413 2,2,70,65,56,100,237,34,140,209,2,67,32,156,50,118,145,64,186,230,61,205,
11414 35,103,155,32,36,141,19,134,78,210,40,206,16,36,70,137,195,39,105,20,11,
11415 174,99,220,210,54,121,210,1,137,33,1,228,207,16,17,70,146,66,3,201,164,32,
11416 0,65,112,152,56,196,159,31,23,77,211,195,201,199,23,160,72,214,246,81,6,12,
11417 73,241,214,111,31,23,60,145,158,56,50,72,81,67,230,232,242,80,19,49,39,199,
11418 89,188,124,92,242,70,120,227,64,194,75,154,72,12,9,73,6,111,21,120,12,40,
11419 144,19,39,25,0,225,144,168,105,56,248,185,228,140,241,200,96,64,100,42,26,
11420 78,62,46,121,35,52,18,92,116,1,36,64,47,158,64,49,98,66,100,156,242,65,23,
11421 196,149,35,103,194,94,100,108,144,230,203,156,64,66,37,201,16,11,32,249,
11422 132,4,34,92,44,93,146,55,152,72,24,137,112,151,153,27,36,5,100,229,144,8,
11423 162,98,92,210,5,76,73,241,214,111,31,23,60,145,158,57,44,48,46,92,185,164,
11424 160,72,151,41,0,50,107,179,244,59,36,93,127,92,6,19,172,3,11,216,0,56,224,
11425 151,29,102,241,241,115,201,25,227,164,64,106,37,199,197,211,116,240,242,
11426 113,197,233,144,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,84,
11427 129,13,173,161,144,168,105,56,98,78,100,142,214,215,69,1,13,173,161,144,
11428 168,105,57,34,78,100,142,214,215,69,16,67,107,105,110,114,168,254,24,147,
11429 153,35,181,181,212,32,67,107,105,110,114,168,254,72,147,153,35,181,181,212,
11430 36,65,130,3,144,8,26,252,200,13,30,85,16,16,64,90,242,231,192,64,161,163,
11431 203,31,26,172,193,17,4,23,105,159,96,27,172,251,16,32,196,4,14,137,112,17,
11432 136,48,164,28,134,80,215,202,1,132,130,8,12,39,52,64,155,31,24,56,36,1,189,
11433 207,132,0,35,233,35,195,62,3,196,149,36,100,72,160,2,200,232,44,227,0,11,
11434 37,160,68,142,128,36,157,25,200,32,26,79,90,4,73,43,192,122,54,71,65,103,
11435 44,248,14,134,140,151,227,138,231,208,45,96,148,248,134,140,151,227,138,
11436 231,240,1,255,254,10,74,146,56,128,104,4,147,152,72,6,144,28,174,143,8,1,
11437 30,1,165,3,96,31,0,211,3,21,11,153,35,0,211,131,68,131,160,137,16,250,5,
11438 196,131,160,137,200,160,199,156,67,248,0,255,255,65,140,10,48,177,115,56,
11439 35,130,60,19,134,79,89,240,52,177,115,56,39,12,156,123,144,217,251,15,135,
11440 34,167,30,20,170,154,255,232,12,47,244,0,97,28,17,224,39,238,32,40,71,4,
11441 120,39,12,156,4,253,228,5,137,195,39,30,228,54,124,4,253,228,128,194,115,
11442 68,9,252,15,128,232,104,201,126,56,191,35,64,90,193,41,241,13,25,47,199,23,
11443 228,105,3,86,225,1,100,224,156,199,130,36,249,144,10,192,76,71,250,16,15,
11444 18,61,96,17,62,200,3,72,128,136,143,247,32,22,75,64,137,248,64,22,79,90,39,
11445 249,64,38,84,12,167,20,52,223,196,2,230,238,45,214,36,120,32,72,158,208,4,
11446 102,238,45,194,2,201,197,186,196,143,4,9,19,218,0,92,221,202,61,228,143,4,
11447 9,19,218,8,35,55,113,110,16,22,78,81,239,36,120,32,72,158,208,64,73,197,12,
11448 255,0,13,18,60,128,159,212,128,169,76,17,156,185,100,76,255,163,64,65,26,
11449 57,114,200,153,255,70,144,33,13,18,232,50,75,226,104,6,149,3,41,199,246,
11450 130,12,128,28,142,156,120,203,175,158,8,194,207,1,6,81,20,79,88,11,237,84,
11451 11,161,32,63,247,255,255,255,255,255,255,137,235,16,221,170,129,116,36,0,0,
11452 0,0,0,0,0,0,28,196,7,255,128,0,0,0,0,0,2,61,123,164,137,162,164,218,67,74,
11453 134,162,120,128,255,224,0,0,0,0,0,0,71,173,33,129,52,84,155,72,105,80,212,
11454 79,16,63,252,0,0,0,0,0,0,3,244,143,146,22,230,192,60,176,0,0,0,0,0,0,33,
11455 214,2,251,82,1,73,180,134,204,134,36,96,33,159,255,255,255,255,255,255,144,
11456 235,16,221,169,0,164,218,67,102,67,18,48,48,207,255,255,255,255,255,255,
11457 196,60,17,145,56,134,204,241,226,158,8,200,156,42,220,9,158,65,196,34,92,
11458 42,26,137,147,120,64,74,37,196,54,100,49,35,188,36,5,68,184,208,113,187,
11459 194,80,212,75,146,1,73,196,54,100,49,35,188,38,57,37,56,240,0,0,0,0,0,0,0,
11460 0,32,235,248,68,48,156,2,24,94,24,0,243,119,10,139,144,123,242,3,102,238,
11461 18,239,115,72,217,160,11,223,16,23,55,113,241,32,145,36,57,188,18,16,102,3,
11462 5,120,35,34,89,32,15,180,152,173,127,0,218,235,88,0,228,180,227,200,127,
11463 248,0,0,0,0,0,0,197,107,240,64,6,77,220,24,38,78,74,113,67,77,130,4,12,155,
11464 185,52,48,156,148,226,134,155,4,10,194,96,129,132,166,238,45,194,2,201,193,
11465 130,100,228,167,20,52,216,32,113,41,187,139,112,128,178,114,104,97,57,41,
11466 197,13,54,8,32,48,216,32,130,195,224,130,19,97,124,134,23,6,0,57,137,62,77,
11467 12,38,12,0,179,18,124,45,22,190,96,128,141,176,134,28,98,79,180,152,139,
11468 218,45,124,193,1,27,97,16,32,196,159,24,230,204,246,194,40,89,137,62,210,
11469 98,103,92,217,158,216,70,7,49,39,193,130,100,182,17,194,140,73,246,147,16,
11470 250,9,146,216,72,6,49,39,193,131,22,194,72,73,137,62,210,98,31,65,139,97,
11471 40,32,196,159,14,234,70,86,194,88,89,137,62,210,98,63,93,72,202,216,76,10,
11472 49,39,198,33,180,153,37,108,38,134,152,147,237,38,38,117,13,164,201,43,97,
11473 56,40,196,159,36,65,57,163,149,176,158,26,98,79,180,152,165,210,9,205,28,
11474 173,133,0,243,18,124,98,22,180,72,130,115,71,43,97,68,72,196,159,105,49,51,
11475 168,90,209,34,9,205,28,173,133,33,19,18,124,154,24,76,185,164,227,138,89,
11476 18,119,0,7,145,39,201,161,132,188,64,124,137,62,49,11,90,36,65,57,163,149,
11477 210,166,37,34,79,180,152,153,212,45,104,145,4,230,142,87,74,160,84,137,62,
11478 72,130,115,71,43,171,234,134,200,147,237,38,41,116,130,115,71,43,171,235,5,
11479 72,147,227,16,218,76,146,186,254,184,108,137,62,210,98,103,80,218,76,146,
11480 186,254,192,68,137,62,29,212,140,174,207,178,23,34,79,180,152,143,215,82,
11481 50,187,62,208,60,137,62,12,19,37,210,182,21,34,79,180,152,135,208,76,151,
11482 74,224,68,137,62,49,205,153,238,175,186,23,34,79,180,152,153,215,54,103,
11483 186,190,240,92,137,62,22,139,95,48,64,70,235,251,225,210,36,251,73,136,189,
11484 162,215,204,16,17,186,255,2,14,98,79,152,32,35,108,48,64,242,36,249,130,2,
11485 55,75,6,212,224,72,200,51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,
11486 48,98,115,249,201,117,243,249,195,21,159,206,38,47,63,156,86,8,75,144,94,
11487 82,1,38,73,79,208,67,95,233,1,6,128,14,79,129,186,40,249,18,149,182,207,
11488 144,200,155,188,248,204,105,184,207,142,199,137,175,201,0,159,72,10,5,21,
11489 221,10,120,74,129,124,36,98,232,228,74,81,62,160,20,10,107,186,21,114,32,
11490 105,137,194,70,46,142,68,165,19,235,1,64,170,187,161,119,34,66,146,36,104,
11491 137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35,
11492 23,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165,
11493 19,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,
11494 72,115,96,32,106,15,0,0,0,0,0,91,60,165,195,201,194,8,134,149,216,162,0,
11495 192,41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176,
11496 195,192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20,
11497 1,119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219,
11498 36,98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0,
11499 0,83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1,
11500 102,8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48,
11501 20,28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179,
11502 216,162,152,192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,
11503 81,76,104,73,137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,
11504 166,56,36,196,159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,
11505 20,188,20,98,79,133,91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,
11506 68,137,62,81,13,158,197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,
11507 159,40,134,207,71,90,155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,
11508 67,103,167,165,77,174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,
11509 173,192,158,182,165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,
11510 140,35,103,0,255,192,0,0,0,0,0,0,206,25,228,35,208,226,100,150,211,201,29,
11511 162,44,140,35,103,0,255,192,0,0,0,0,0,0,206,25,244,35,208,226,100,150,211,
11512 201,29,162,44,140,35,103,0,255,192,0,0,0,0,0,0,206,26,4,35,208,226,100,150,
11513 211,201,29,162,44,140,35,103,1,0,0,0,0,0,0,0,0,206,26,20,35,208,226,100,
11514 150,211,201,29,162,44,140,35,103,1,0,0,0,0,0,0,0,0,206,26,36,35,208,226,
11515 100,150,211,201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,52,35,208,
11516 226,100,150,211,201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,68,35,
11517 208,226,100,150,211,201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,84,
11518 35,208,226,100,150,211,201,29,162,44,140,35,103,1,0,128,0,0,0,0,0,0,195,
11519 154,99,16,38,36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,
11520 25,18,0,125,162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,
11521 235,116,36,162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,
11522 196,54,122,58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,
11523 200,144,3,237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,
11524 213,146,138,77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,
11525 183,2,125,89,40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,
11526 221,64,172,157,89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,
11527 31,104,142,182,125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,
11528 18,0,124,67,103,213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,
11529 59,68,117,179,216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,
11530 39,104,142,182,122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,
11531 73,77,162,6,90,40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,
11532 61,29,110,132,148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,
11533 67,109,20,76,157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,
11534 167,165,213,146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,
11535 68,201,194,173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,
11536 193,182,138,38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,
11537 178,116,36,166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,
11538 157,162,58,217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,
11539 81,50,113,13,159,66,74,113,97,175,221,48,216,110,64,4,42,22,189,179,0,196,
11540 133,0,185,80,32,28,78,99,193,18,80,36,4,19,159,141,172,0,178,90,4,74,73,0,
11541 22,209,68,201,187,129,4,2,8,3,132,64,60,36,4,0,91,240,168,177,69,118,144,
11542 157,91,116,116,32,32,1,53,216,221,218,170,139,3,234,219,165,0,255,152,185,
11543 11,251,232,231,188,47,86,227,105,18,1,255,184,170,59,41,92,23,240,110,173,
11544 198,209,208,36,3,253,188,183,177,82,110,80,224,93,122,32,32,4,144,253,170,
11545 34,22,140,7,236,161,25,232,237,105,64,63,230,160,158,102,127,59,205,11,217,
11546 66,51,210,128,127,237,65,60,204,254,119,155,171,197,34,168,48,6,90,194,1,0,
11547 39,75,88,72,8,9,33,186,194,80,64,76,13,214,19,2,130,96,110,150,189,0,65,6,
11548 51,214,20,128,65,17,11,214,19,130,137,121,211,210,211,144,6,39,75,88,80,0,
11549 201,119,235,10,8,41,86,231,71,88,80,129,79,135,186,122,133,224,34,25,69,
11550 234,80,3,91,141,172,40,96,139,113,180,181,133,36,21,110,54,142,134,176,165,
11551 1,176,23,213,47,0,216,134,234,215,128,111,117,181,232,128,209,3,70,230,107,
11552 64,5,139,168,209,235,10,32,36,144,102,235,136,3,146,27,172,40,160,146,132,
11553 103,172,40,192,115,3,117,133,28,22,113,163,69,172,41,103,1,66,188,17,145,
11554 52,168,4,202,113,67,76,130,227,76,194,13,240,108,0,0,83,224,0,2,193,0,104,
11555 146,84,97,48,0,1,94,192,56,169,24,145,179,192,0,5,112,8,56,16,32,128,56,18,
11556 52,125,230,86,147,190,140,28,50,21,13,39,31,23,60,145,158,57,12,141,47,129,
11557 6,155,194,188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,
11558 163,201,68,14,49,39,199,197,211,116,240,242,113,197,232,18,180,254,36,3,17,
11559 46,18,243,35,100,128,172,156,178,70,163,154,76,34,248,146,164,108,248,75,
11560 204,141,146,28,217,115,137,27,95,27,241,173,236,162,160,224,200,2,206,9,
11561 113,13,148,192,209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,178,
11562 66,213,136,68,201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,38,
11563 232,255,252,92,221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,38,
11564 3,66,213,47,135,254,72,12,162,99,133,116,112,0,1,72,66,14,16,16,50,37,202,
11565 160,150,154,66,14,20,8,57,192,28,24,80,113,50,113,100,105,166,120,248,0,0,
11566 179,1,65,196,201,199,20,178,36,227,224,0,2,208,54,113,240,0,1,100,11,181,
11567 192,0,5,178,1,18,160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,121,
11568 35,180,69,145,132,108,224,31,248,0,0,0,0,0,0,25,188,56,132,122,28,76,146,
11569 218,121,35,180,69,145,132,108,224,31,248,0,0,0,0,0,0,40,160,45,110,23,30,
11570 176,33,184,0,0,183,32,29,235,2,27,199,23,0,0,23,4,51,120,129,8,244,56,153,
11571 37,180,242,71,104,139,35,8,217,192,63,240,0,0,0,0,0,0,51,120,145,8,244,56,
11572 153,37,180,242,71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,120,161,8,244,
11573 56,153,37,180,242,71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,120,177,8,
11574 244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,120,193,
11575 8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,120,
11576 209,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,
11577 120,225,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,32,0,0,0,0,0,0,
11578 32,227,194,0,97,57,162,4,246,104,5,34,92,35,68,225,161,166,220,16,16,137,
11579 112,52,41,73,29,185,1,65,196,201,197,145,166,153,246,72,3,137,204,120,34,
11580 74,8,199,1,67,17,162,112,201,84,128,97,144,78,25,42,16,131,169,1,205,66,8,
11581 35,68,225,161,166,239,128,0,10,192,64,196,104,156,50,96,0,2,172,73,240,117,
11582 96,57,170,97,4,104,156,52,52,221,240,0,1,82,1,74,9,129,125,240,0,1,82,32,
11583 148,25,174,137,58,23,51,190,0,0,42,69,64,195,32,156,50,96,0,2,160,81,238,2,
11584 3,107,173,218,3,192,
11585 };
11586 #elif defined(DUK_USE_DOUBLE_ME)
11587 DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = {
11588 144,148,105,226,32,68,52,228,254,12,104,202,37,132,52,167,194,138,105,245,
11589 124,57,28,211,57,18,64,52,239,126,44,138,111,175,241,164,19,87,145,30,33,
11590 167,22,145,159,8,211,139,9,225,42,5,240,145,139,163,163,8,211,139,10,228,
11591 64,211,19,132,140,93,29,56,70,156,88,119,34,66,146,36,104,137,194,70,46,
11592 142,172,35,78,44,47,146,195,102,11,240,145,139,163,175,8,211,139,9,228,240,
11593 242,112,145,139,163,179,8,211,139,8,237,34,130,118,49,116,118,225,26,48,0,
11594 1,98,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
11595 33,8,66,26,180,105,97,167,68,150,34,33,154,112,0,1,91,247,35,79,111,237,
11596 198,174,232,47,31,23,95,17,13,31,249,96,211,49,50,53,214,77,141,24,0,0,181,
11597 10,228,240,242,15,128,140,65,128,134,188,0,0,90,167,97,181,224,0,2,213,62,
11598 53,224,0,2,213,66,237,120,0,0,181,81,204,107,192,0,5,170,150,67,94,0,0,45,
11599 84,245,90,240,0,1,106,169,162,215,128,0,11,85,93,150,188,0,0,90,171,111,53,
11600 109,22,162,26,48,0,1,84,23,201,146,243,225,26,39,12,145,136,104,192,0,5,61,
11601 11,228,201,121,240,100,19,134,72,196,33,195,14,40,203,112,64,190,76,232,
11602 145,153,136,0,0,31,15,224,0,0,0,25,152,0,0,30,15,224,0,0,0,25,120,144,13,
11603 96,155,194,56,80,206,36,67,141,20,228,70,57,81,206,100,131,156,39,132,168,
11604 23,194,70,46,137,208,21,200,129,166,39,9,24,186,39,72,119,34,66,146,36,104,
11605 137,194,70,46,137,212,23,201,97,179,5,248,72,197,209,58,194,121,60,60,156,
11606 36,98,232,157,129,29,164,80,78,198,46,137,218,146,121,25,71,146,9,209,5,
11607 209,61,48,126,14,138,152,30,67,186,23,143,139,175,131,202,135,228,72,85,
11608 144,83,60,179,30,94,209,233,102,30,98,105,230,103,30,114,121,231,104,30,
11609 122,137,231,233,30,130,153,232,106,30,138,169,232,235,30,144,67,193,25,19,
11610 136,108,207,30,41,224,140,137,194,173,192,153,228,5,242,100,188,248,70,137,
11611 195,36,79,78,47,147,37,231,193,144,78,25,34,122,145,111,36,74,232,176,13,
11612 17,61,234,226,93,207,148,160,84,75,141,7,27,161,32,33,18,225,80,212,76,154,
11613 2,2,70,65,56,100,237,34,140,209,2,67,32,156,50,118,145,64,186,230,61,205,
11614 35,103,155,32,36,141,19,134,78,210,40,206,16,36,70,137,195,39,105,20,11,
11615 174,99,220,210,54,121,210,1,137,33,1,228,207,16,17,70,146,66,3,201,164,32,
11616 0,65,112,152,56,196,159,31,23,77,211,195,201,199,23,160,72,214,246,81,6,12,
11617 73,241,214,111,31,23,60,145,158,56,50,72,81,67,230,232,242,80,19,49,39,199,
11618 89,188,124,92,242,70,120,227,64,194,75,154,72,12,9,73,6,111,21,120,12,40,
11619 144,19,39,25,0,225,144,168,105,56,248,185,228,140,241,200,96,64,100,42,26,
11620 78,62,46,121,35,52,18,92,116,1,36,64,47,158,64,49,98,66,100,156,242,65,23,
11621 196,149,35,103,194,94,100,108,144,230,203,156,64,66,37,201,16,11,32,249,
11622 132,4,34,92,44,93,146,55,152,72,24,137,112,151,153,27,36,5,100,229,144,8,
11623 162,98,92,210,5,76,73,241,214,111,31,23,60,145,158,57,44,48,46,92,185,164,
11624 160,72,151,41,0,50,107,179,244,59,36,93,127,92,6,19,172,3,11,216,0,56,224,
11625 151,29,102,241,241,115,201,25,227,164,64,106,37,199,197,211,116,240,242,
11626 113,197,233,144,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,84,
11627 129,13,173,161,144,168,105,56,98,78,100,142,214,215,69,1,13,173,161,144,
11628 168,105,57,34,78,100,142,214,215,69,16,67,107,105,110,114,168,254,24,147,
11629 153,35,181,181,212,32,67,107,105,110,114,168,254,72,147,153,35,181,181,212,
11630 36,65,130,3,144,8,26,252,200,13,30,85,16,16,64,90,242,231,192,64,161,163,
11631 203,31,26,172,193,17,4,23,105,159,96,27,172,251,16,32,196,4,14,137,112,17,
11632 136,48,164,28,134,80,215,202,1,132,130,8,12,39,52,64,155,31,24,56,36,1,189,
11633 207,132,0,35,233,35,195,62,3,196,149,36,100,72,160,2,200,232,44,227,0,11,
11634 37,160,68,142,128,36,157,25,200,32,26,79,90,4,73,43,192,122,54,71,65,103,
11635 44,248,14,134,140,151,227,138,231,208,45,96,148,248,134,140,151,227,138,
11636 231,240,1,255,254,10,74,146,56,128,104,4,147,152,72,6,144,28,174,143,8,1,
11637 30,1,165,3,96,31,0,211,3,21,11,153,35,0,211,131,68,131,160,137,16,250,5,
11638 196,131,160,137,200,160,199,156,67,248,0,255,255,65,140,10,48,177,115,56,
11639 35,130,60,19,134,79,89,240,52,177,115,56,39,12,156,123,144,217,251,15,135,
11640 34,167,30,20,170,154,255,232,12,47,244,0,97,28,17,224,39,238,32,40,71,4,
11641 120,39,12,156,4,253,228,5,137,195,39,30,228,54,124,4,253,228,128,194,115,
11642 68,9,252,15,128,232,104,201,126,56,191,35,64,90,193,41,241,13,25,47,199,23,
11643 228,105,3,86,225,1,100,224,156,199,130,36,249,144,10,192,76,71,250,16,15,
11644 18,61,96,17,62,200,3,72,128,136,143,247,32,22,75,64,137,248,64,22,79,90,39,
11645 249,64,38,84,12,167,20,52,223,196,2,230,238,45,214,36,120,32,72,158,208,4,
11646 102,238,45,194,2,201,197,186,196,143,4,9,19,218,0,92,221,202,61,228,143,4,
11647 9,19,218,8,35,55,113,110,16,22,78,81,239,36,120,32,72,158,208,64,73,197,12,
11648 255,0,13,18,60,128,159,212,128,169,76,17,156,185,100,76,255,163,64,65,26,
11649 57,114,200,153,255,70,144,33,13,18,232,50,75,226,104,6,149,3,41,199,246,
11650 130,12,128,28,142,156,120,203,175,158,8,194,207,1,6,81,20,79,88,11,237,84,
11651 11,161,32,127,255,247,191,255,255,255,255,137,235,16,221,170,129,116,36,0,
11652 0,0,0,0,16,0,0,12,196,0,0,15,135,240,0,0,0,2,61,123,164,137,162,164,218,67,
11653 74,134,162,120,128,0,1,224,254,0,0,0,0,71,173,33,129,52,84,155,72,105,80,
11654 212,79,16,0,0,60,63,192,0,0,0,3,244,143,146,22,230,192,0,0,176,60,0,0,0,0,
11655 33,214,2,251,82,1,73,180,134,204,134,36,96,127,255,159,161,255,255,255,255,
11656 144,235,16,221,169,0,164,218,67,102,67,18,48,63,255,207,240,255,255,255,
11657 255,196,60,17,145,56,134,204,241,226,158,8,200,156,42,220,9,158,65,196,34,
11658 92,42,26,137,147,120,64,74,37,196,54,100,49,35,188,36,5,68,184,208,113,187,
11659 194,80,212,75,146,1,73,196,54,100,49,35,188,38,57,37,56,240,0,0,0,0,0,0,0,
11660 0,32,235,248,68,48,156,2,24,94,24,0,243,119,10,139,144,123,242,3,102,238,
11661 18,239,115,72,217,160,11,223,16,23,55,113,241,32,145,36,57,188,18,16,102,3,
11662 5,120,35,34,89,32,15,180,152,173,127,0,218,235,88,0,228,180,227,200,0,0,
11663 248,127,0,0,0,0,197,107,240,64,6,77,220,24,38,78,74,113,67,77,130,4,12,155,
11664 185,52,48,156,148,226,134,155,4,10,194,96,129,132,166,238,45,194,2,201,193,
11665 130,100,228,167,20,52,216,32,113,41,187,139,112,128,178,114,104,97,57,41,
11666 197,13,54,8,32,48,216,32,130,195,224,130,19,97,124,134,23,6,0,57,137,62,77,
11667 12,38,12,0,179,18,124,45,22,190,96,128,141,176,134,28,98,79,180,152,139,
11668 218,45,124,193,1,27,97,16,32,196,159,24,230,204,246,194,40,89,137,62,210,
11669 98,103,92,217,158,216,70,7,49,39,193,130,100,182,17,194,140,73,246,147,16,
11670 250,9,146,216,72,6,49,39,193,131,22,194,72,73,137,62,210,98,31,65,139,97,
11671 40,32,196,159,14,234,70,86,194,88,89,137,62,210,98,63,93,72,202,216,76,10,
11672 49,39,198,33,180,153,37,108,38,134,152,147,237,38,38,117,13,164,201,43,97,
11673 56,40,196,159,36,65,57,163,149,176,158,26,98,79,180,152,165,210,9,205,28,
11674 173,133,0,243,18,124,98,22,180,72,130,115,71,43,97,68,72,196,159,105,49,51,
11675 168,90,209,34,9,205,28,173,133,33,19,18,124,154,24,76,185,164,227,138,89,
11676 18,119,0,7,145,39,201,161,132,188,64,124,137,62,49,11,90,36,65,57,163,149,
11677 210,166,37,34,79,180,152,153,212,45,104,145,4,230,142,87,74,160,84,137,62,
11678 72,130,115,71,43,171,234,134,200,147,237,38,41,116,130,115,71,43,171,235,5,
11679 72,147,227,16,218,76,146,186,254,184,108,137,62,210,98,103,80,218,76,146,
11680 186,254,192,68,137,62,29,212,140,174,207,178,23,34,79,180,152,143,215,82,
11681 50,187,62,208,60,137,62,12,19,37,210,182,21,34,79,180,152,135,208,76,151,
11682 74,224,68,137,62,49,205,153,238,175,186,23,34,79,180,152,153,215,54,103,
11683 186,190,240,92,137,62,22,139,95,48,64,70,235,251,225,210,36,251,73,136,189,
11684 162,215,204,16,17,186,255,2,14,98,79,152,32,35,108,48,64,242,36,249,130,2,
11685 55,75,6,212,224,72,200,51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,
11686 48,98,115,249,201,117,243,249,195,21,159,206,38,47,63,156,86,8,75,144,94,
11687 82,1,38,73,79,208,67,95,233,1,6,128,14,79,129,186,40,249,18,149,182,207,
11688 144,200,155,188,248,204,105,184,207,142,199,137,175,201,0,159,72,10,5,21,
11689 221,10,120,74,129,124,36,98,232,228,74,81,62,160,20,10,107,186,21,114,32,
11690 105,137,194,70,46,142,68,165,19,235,1,64,170,187,161,119,34,66,146,36,104,
11691 137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35,
11692 23,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165,
11693 19,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,
11694 72,115,96,0,15,106,32,0,0,0,0,91,60,165,195,201,194,8,134,149,216,162,0,
11695 192,41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176,
11696 195,192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20,
11697 1,119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219,
11698 36,98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0,
11699 0,83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1,
11700 102,8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48,
11701 20,28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179,
11702 216,162,152,192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,
11703 81,76,104,73,137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,
11704 166,56,36,196,159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,
11705 20,188,20,98,79,133,91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,
11706 68,137,62,81,13,158,197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,
11707 159,40,134,207,71,90,155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,
11708 67,103,167,165,77,174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,
11709 173,192,158,182,165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,
11710 140,35,103,0,0,3,192,252,0,0,0,0,206,25,228,35,208,226,100,150,211,201,29,
11711 162,44,140,35,103,0,0,3,192,252,0,0,0,0,206,25,244,35,208,226,100,150,211,
11712 201,29,162,44,140,35,103,0,0,3,192,252,0,0,0,0,206,26,4,35,208,226,100,150,
11713 211,201,29,162,44,140,35,103,0,0,0,1,0,0,0,0,0,206,26,20,35,208,226,100,
11714 150,211,201,29,162,44,140,35,103,0,0,0,1,0,0,0,0,0,206,26,36,35,208,226,
11715 100,150,211,201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,52,35,208,
11716 226,100,150,211,201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,68,35,
11717 208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,84,
11718 35,208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,129,0,0,0,0,0,195,
11719 154,99,16,38,36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,
11720 25,18,0,125,162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,
11721 235,116,36,162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,
11722 196,54,122,58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,
11723 200,144,3,237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,
11724 213,146,138,77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,
11725 183,2,125,89,40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,
11726 221,64,172,157,89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,
11727 31,104,142,182,125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,
11728 18,0,124,67,103,213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,
11729 59,68,117,179,216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,
11730 39,104,142,182,122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,
11731 73,77,162,6,90,40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,
11732 61,29,110,132,148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,
11733 67,109,20,76,157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,
11734 167,165,213,146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,
11735 68,201,194,173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,
11736 193,182,138,38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,
11737 178,116,36,166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,
11738 157,162,58,217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,
11739 81,50,113,13,159,66,74,113,97,175,221,48,216,110,64,4,42,22,189,179,0,196,
11740 133,0,185,80,32,28,78,99,193,18,80,36,4,19,159,141,172,0,178,90,4,74,73,0,
11741 22,209,68,201,187,129,4,2,8,3,132,64,60,36,0,171,240,84,6,149,113,72,176,
11742 157,91,116,116,32,88,181,129,32,11,42,218,221,131,234,219,165,1,8,187,152,
11743 255,188,231,235,248,47,86,227,105,18,2,56,175,185,255,244,17,91,40,110,173,
11744 198,209,208,36,7,188,189,179,240,238,82,97,80,93,122,32,125,144,132,160,12,
11745 22,162,42,7,236,161,25,232,237,105,64,158,160,230,63,205,59,127,102,11,217,
11746 66,51,210,129,61,65,236,127,154,118,254,205,171,197,34,168,48,6,90,194,1,0,
11747 39,75,88,72,8,9,33,186,194,80,64,76,13,214,19,2,130,96,110,150,189,0,65,6,
11748 51,214,20,128,65,17,11,214,19,130,137,121,211,210,211,144,6,39,75,88,80,0,
11749 201,119,235,10,8,41,86,231,71,88,80,129,79,135,186,122,133,224,34,25,69,
11750 234,80,3,91,141,172,40,96,139,113,180,181,133,36,21,110,54,142,134,176,165,
11751 1,176,23,213,47,0,216,134,234,215,128,111,117,181,232,128,209,3,70,230,107,
11752 64,5,139,168,209,235,10,32,36,144,102,235,136,3,146,27,172,40,160,146,132,
11753 103,172,40,192,115,3,117,133,28,22,113,163,69,172,41,103,1,66,188,17,145,
11754 52,168,4,202,113,67,76,130,227,76,194,13,240,108,0,0,83,224,0,2,193,0,104,
11755 146,84,97,48,0,1,94,192,56,169,24,145,179,192,0,5,112,8,56,16,32,128,56,18,
11756 52,125,230,86,147,190,140,28,50,21,13,39,31,23,60,145,158,57,12,141,47,129,
11757 6,155,194,188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,
11758 163,201,68,14,49,39,199,197,211,116,240,242,113,197,232,18,180,254,36,3,17,
11759 46,18,243,35,100,128,172,156,178,70,163,154,76,34,248,146,164,108,248,75,
11760 204,141,146,28,217,115,137,27,95,27,241,173,236,162,160,224,200,2,206,9,
11761 113,13,148,192,209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,178,
11762 66,213,136,68,201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,38,
11763 232,255,252,92,221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,38,
11764 3,66,213,47,135,254,72,12,162,99,133,116,112,0,1,72,66,14,16,16,50,37,202,
11765 160,150,154,66,14,20,8,57,192,28,24,80,113,50,113,100,105,166,120,248,0,0,
11766 179,1,65,196,201,199,20,178,36,227,224,0,2,208,54,113,240,0,1,100,11,181,
11767 192,0,5,178,1,18,160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,121,
11768 35,180,69,145,132,108,224,0,0,120,31,128,0,0,0,25,188,56,132,122,28,76,146,
11769 218,121,35,180,69,145,132,108,224,0,0,120,31,128,0,0,0,40,160,45,110,23,30,
11770 176,33,184,0,0,183,32,29,235,2,27,199,23,0,0,23,4,51,120,129,8,244,56,153,
11771 37,180,242,71,104,139,35,8,217,192,0,0,240,63,0,0,0,0,51,120,145,8,244,56,
11772 153,37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,120,161,8,244,
11773 56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,120,177,8,
11774 244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,120,193,
11775 8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,120,
11776 209,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,
11777 120,225,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,32,64,0,0,0,0,
11778 32,227,194,0,97,57,162,4,246,104,5,34,92,35,68,225,161,166,220,16,16,137,
11779 112,52,41,73,29,185,1,65,196,201,197,145,166,153,246,72,3,137,204,120,34,
11780 74,8,199,1,67,17,162,112,201,84,128,97,144,78,25,42,16,131,169,1,205,66,8,
11781 35,68,225,161,166,239,128,0,10,192,64,196,104,156,50,96,0,2,172,73,240,117,
11782 96,57,170,97,4,104,156,52,52,221,240,0,1,82,1,74,9,129,125,240,0,1,82,32,
11783 148,25,174,137,58,23,51,190,0,0,42,69,64,195,32,156,50,96,0,2,160,81,238,2,
11784 3,107,173,218,3,192,
11785 };
11786 #else
11787 #error invalid endianness defines
11788 #endif
11789 #endif  /* DUK_USE_ROM_OBJECTS */
11790 
11791 /* automatic undefs */
11792 #undef DUK__REFCINIT
11793 #line 1 "duk_error_macros.c"
11794 /*
11795  *  Error and fatal handling.
11796  */
11797 
11798 /* #include duk_internal.h -> already included */
11799 
11800 #define DUK__ERRFMT_BUFSIZE  256  /* size for formatting buffers */
11801 
11802 #if defined(DUK_USE_VERBOSE_ERRORS)
11803 
duk_err_handle_error_fmt(duk_hthread * thr,const char * filename,duk_uint_t line_and_code,const char * fmt,...)11804 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, ...) {
11805 	va_list ap;
11806 	char msg[DUK__ERRFMT_BUFSIZE];
11807 	va_start(ap, fmt);
11808 	(void) DUK_VSNPRINTF(msg, sizeof(msg), fmt, ap);
11809 	msg[sizeof(msg) - 1] = (char) 0;
11810 	duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
11811 	va_end(ap);  /* dead code, but ensures portability (see Linux man page notes) */
11812 }
11813 
duk_err_handle_error(duk_hthread * thr,const char * filename,duk_uint_t line_and_code,const char * msg)11814 DUK_INTERNAL DUK_COLD void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg) {
11815 	duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
11816 }
11817 
11818 #else  /* DUK_USE_VERBOSE_ERRORS */
11819 
duk_err_handle_error(duk_hthread * thr,duk_errcode_t code)11820 DUK_INTERNAL DUK_COLD void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code) {
11821 	duk_err_create_and_throw(thr, code);
11822 }
11823 
11824 #endif  /* DUK_USE_VERBOSE_ERRORS */
11825 
11826 /*
11827  *  Error throwing helpers
11828  */
11829 
11830 #if defined(DUK_USE_VERBOSE_ERRORS)
11831 #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)11832 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) {
11833 	DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
11834 	                   expect_name, duk_get_type_name(thr, idx), (long) idx);
11835 }
11836 #else
duk_err_require_type_index(duk_hthread * thr,const char * filename,duk_int_t linenumber,duk_idx_t idx,const char * expect_name)11837 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) {
11838 	DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
11839 	                   expect_name, duk_push_string_readable(thr, idx), (long) idx);
11840 }
11841 #endif
duk_err_error_internal(duk_hthread * thr,const char * filename,duk_int_t linenumber)11842 DUK_INTERNAL DUK_COLD void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11843 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, DUK_STR_INTERNAL_ERROR);
11844 }
duk_err_error_alloc_failed(duk_hthread * thr,const char * filename,duk_int_t linenumber)11845 DUK_INTERNAL DUK_COLD void duk_err_error_alloc_failed(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11846 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, DUK_STR_ALLOC_FAILED);
11847 }
duk_err_error(duk_hthread * thr,const char * filename,duk_int_t linenumber,const char * message)11848 DUK_INTERNAL DUK_COLD void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
11849 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, message);
11850 }
duk_err_range(duk_hthread * thr,const char * filename,duk_int_t linenumber,const char * message)11851 DUK_INTERNAL DUK_COLD void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
11852 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, message);
11853 }
duk_err_range_index(duk_hthread * thr,const char * filename,duk_int_t linenumber,duk_idx_t idx)11854 DUK_INTERNAL DUK_COLD void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx) {
11855 	DUK_ERROR_RAW_FMT1(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, "invalid stack index %ld", (long) (idx));
11856 }
duk_err_range_push_beyond(duk_hthread * thr,const char * filename,duk_int_t linenumber)11857 DUK_INTERNAL DUK_COLD void duk_err_range_push_beyond(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11858 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
11859 }
duk_err_type_invalid_args(duk_hthread * thr,const char * filename,duk_int_t linenumber)11860 DUK_INTERNAL DUK_COLD void duk_err_type_invalid_args(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11861 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_ARGS);
11862 }
duk_err_type_invalid_state(duk_hthread * thr,const char * filename,duk_int_t linenumber)11863 DUK_INTERNAL DUK_COLD void duk_err_type_invalid_state(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11864 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_STATE);
11865 }
duk_err_type_invalid_trap_result(duk_hthread * thr,const char * filename,duk_int_t linenumber)11866 DUK_INTERNAL DUK_COLD void duk_err_type_invalid_trap_result(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11867 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_TRAP_RESULT);
11868 }
11869 #else
11870 /* The file/line arguments are NULL and 0, they're ignored by DUK_ERROR_RAW()
11871  * when non-verbose errors are used.
11872  */
11873 
11874 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)11875 DUK_LOCAL void duk__err_shared(duk_hthread *thr, duk_errcode_t code) {
11876 	DUK_ERROR_RAW(thr, NULL, 0, code, NULL);
11877 }
duk_err_error(duk_hthread * thr)11878 DUK_INTERNAL DUK_COLD void duk_err_error(duk_hthread *thr) {
11879 	duk__err_shared(thr, DUK_ERR_ERROR);
11880 }
duk_err_range(duk_hthread * thr)11881 DUK_INTERNAL DUK_COLD void duk_err_range(duk_hthread *thr) {
11882 	duk__err_shared(thr, DUK_ERR_RANGE_ERROR);
11883 }
duk_err_eval(duk_hthread * thr)11884 DUK_INTERNAL DUK_COLD void duk_err_eval(duk_hthread *thr) {
11885 	duk__err_shared(thr, DUK_ERR_EVAL_ERROR);
11886 }
duk_err_reference(duk_hthread * thr)11887 DUK_INTERNAL DUK_COLD void duk_err_reference(duk_hthread *thr) {
11888 	duk__err_shared(thr, DUK_ERR_REFERENCE_ERROR);
11889 }
duk_err_syntax(duk_hthread * thr)11890 DUK_INTERNAL DUK_COLD void duk_err_syntax(duk_hthread *thr) {
11891 	duk__err_shared(thr, DUK_ERR_SYNTAX_ERROR);
11892 }
duk_err_type(duk_hthread * thr)11893 DUK_INTERNAL DUK_COLD void duk_err_type(duk_hthread *thr) {
11894 	duk__err_shared(thr, DUK_ERR_TYPE_ERROR);
11895 }
duk_err_uri(duk_hthread * thr)11896 DUK_INTERNAL DUK_COLD void duk_err_uri(duk_hthread *thr) {
11897 	duk__err_shared(thr, DUK_ERR_URI_ERROR);
11898 }
11899 #endif
11900 
11901 /*
11902  *  Default fatal error handler
11903  */
11904 
duk_default_fatal_handler(void * udata,const char * msg)11905 DUK_INTERNAL DUK_COLD void duk_default_fatal_handler(void *udata, const char *msg) {
11906 	DUK_UNREF(udata);
11907 	DUK_UNREF(msg);
11908 
11909 	msg = msg ? msg : "NULL";
11910 
11911 #if defined(DUK_USE_FATAL_HANDLER)
11912 	/* duk_config.h provided a custom default fatal handler. */
11913 	DUK_D(DUK_DPRINT("custom default fatal error handler called: %s", msg));
11914 	DUK_USE_FATAL_HANDLER(udata, msg);
11915 #elif defined(DUK_USE_CPP_EXCEPTIONS)
11916 	/* With C++ use a duk_fatal_exception which user code can catch in
11917 	 * a natural way.
11918 	 */
11919 	DUK_D(DUK_DPRINT("built-in default C++ fatal error handler called: %s", msg));
11920 	throw duk_fatal_exception(msg);
11921 #else
11922 	/* Default behavior is to abort() on error.  There's no printout
11923 	 * which makes this awkward, so it's always recommended to use an
11924 	 * explicit fatal error handler.
11925 	 *
11926 	 * ====================================================================
11927 	 * NOTE: If you are seeing this, you are most likely dealing with an
11928 	 * uncaught error.  You should provide a fatal error handler in Duktape
11929 	 * heap creation, and should consider using a protected call as your
11930 	 * first call into an empty Duktape context to properly handle errors.
11931 	 * See:
11932 	 *   - http://duktape.org/guide.html#error-handling
11933 	 *   - http://wiki.duktape.org/HowtoFatalErrors.html
11934 	 *   - http://duktape.org/api.html#taglist-protected
11935 	 * ====================================================================
11936 	 */
11937 	DUK_D(DUK_DPRINT("built-in default fatal error handler called: %s", msg));
11938 	DUK_ABORT();
11939 #endif
11940 
11941 	DUK_D(DUK_DPRINT("fatal error handler returned, enter forever loop"));
11942 	for (;;) {
11943 		/* Loop forever to ensure we don't return. */
11944 	}
11945 }
11946 
11947 /* automatic undefs */
11948 #undef DUK__ERRFMT_BUFSIZE
11949 #line 1 "duk_unicode_support.c"
11950 /*
11951  *  Various Unicode help functions for character classification predicates,
11952  *  case conversion, decoding, etc.
11953  */
11954 
11955 /* #include duk_internal.h -> already included */
11956 
11957 /*
11958  *  Fast path tables
11959  */
11960 
11961 #if defined(DUK_USE_IDCHAR_FASTPATH)
11962 DUK_INTERNAL const duk_int8_t duk_is_idchar_tab[128] = {
11963 	/* 0: not IdentifierStart or IdentifierPart
11964 	 * 1: IdentifierStart and IdentifierPart
11965 	 * -1: IdentifierPart only
11966 	 */
11967 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x00...0x0f */
11968 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x10...0x1f */
11969 	0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x20...0x2f */
11970 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,  0,  0,  0,  0,  0,   /* 0x30...0x3f */
11971 	0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,   /* 0x40...0x4f */
11972 	1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  1,   /* 0x50...0x5f */
11973 	0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,   /* 0x60...0x6f */
11974 	1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0    /* 0x70...0x7f */
11975 };
11976 #endif
11977 
11978 /*
11979  *  XUTF-8 and CESU-8 encoding/decoding
11980  */
11981 
duk_unicode_get_xutf8_length(duk_ucodepoint_t cp)11982 DUK_INTERNAL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp) {
11983 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
11984 	if (x < 0x80UL) {
11985 		/* 7 bits */
11986 		return 1;
11987 	} else if (x < 0x800UL) {
11988 		/* 11 bits */
11989 		return 2;
11990 	} else if (x < 0x10000UL) {
11991 		/* 16 bits */
11992 		return 3;
11993 	} else if (x < 0x200000UL) {
11994 		/* 21 bits */
11995 		return 4;
11996 	} else if (x < 0x4000000UL) {
11997 		/* 26 bits */
11998 		return 5;
11999 	} else if (x < (duk_ucodepoint_t) 0x80000000UL) {
12000 		/* 31 bits */
12001 		return 6;
12002 	} else {
12003 		/* 36 bits */
12004 		return 7;
12005 	}
12006 }
12007 
12008 #if defined(DUK_USE_ASSERTIONS)
duk_unicode_get_cesu8_length(duk_ucodepoint_t cp)12009 DUK_INTERNAL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp) {
12010 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
12011 	if (x < 0x80UL) {
12012 		/* 7 bits */
12013 		return 1;
12014 	} else if (x < 0x800UL) {
12015 		/* 11 bits */
12016 		return 2;
12017 	} else if (x < 0x10000UL) {
12018 		/* 16 bits */
12019 		return 3;
12020 	} else {
12021 		/* Encoded as surrogate pair, each encoding to 3 bytes for
12022 		 * 6 bytes total.  Codepoints above U+10FFFF encode as 6 bytes
12023 		 * too, see duk_unicode_encode_cesu8().
12024 		  */
12025 		return 3 + 3;
12026 	}
12027 }
12028 #endif  /* DUK_USE_ASSERTIONS */
12029 
12030 DUK_INTERNAL const duk_uint8_t duk_unicode_xutf8_markers[7] = {
12031 	0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe
12032 };
12033 
12034 /* Encode to extended UTF-8; 'out' must have space for at least
12035  * DUK_UNICODE_MAX_XUTF8_LENGTH bytes.  Allows encoding of any
12036  * 32-bit (unsigned) codepoint.
12037  */
duk_unicode_encode_xutf8(duk_ucodepoint_t cp,duk_uint8_t * out)12038 DUK_INTERNAL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out) {
12039 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
12040 	duk_small_int_t len;
12041 	duk_uint8_t marker;
12042 	duk_small_int_t i;
12043 
12044 	len = duk_unicode_get_xutf8_length(cp);
12045 	DUK_ASSERT(len > 0);
12046 
12047 	marker = duk_unicode_xutf8_markers[len - 1];  /* 64-bit OK because always >= 0 */
12048 
12049 	i = len;
12050 	DUK_ASSERT(i > 0);
12051 	do {
12052 		i--;
12053 		if (i > 0) {
12054 			out[i] = (duk_uint8_t) (0x80 + (x & 0x3f));
12055 			x >>= 6;
12056 		} else {
12057 			/* Note: masking of 'x' is not necessary because of
12058 			 * range check and shifting -> no bits overlapping
12059 			 * the marker should be set.
12060 			 */
12061 			out[0] = (duk_uint8_t) (marker + x);
12062 		}
12063 	} while (i > 0);
12064 
12065 	return len;
12066 }
12067 
12068 /* Encode to CESU-8; 'out' must have space for at least
12069  * DUK_UNICODE_MAX_CESU8_LENGTH bytes; codepoints above U+10FFFF
12070  * will encode to garbage but won't overwrite the output buffer.
12071  */
duk_unicode_encode_cesu8(duk_ucodepoint_t cp,duk_uint8_t * out)12072 DUK_INTERNAL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out) {
12073 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
12074 	duk_small_int_t len;
12075 
12076 	if (x < 0x80UL) {
12077 		out[0] = (duk_uint8_t) x;
12078 		len = 1;
12079 	} else if (x < 0x800UL) {
12080 		out[0] = (duk_uint8_t) (0xc0 + ((x >> 6) & 0x1f));
12081 		out[1] = (duk_uint8_t) (0x80 + (x & 0x3f));
12082 		len = 2;
12083 	} else if (x < 0x10000UL) {
12084 		/* surrogate pairs get encoded here */
12085 		out[0] = (duk_uint8_t) (0xe0 + ((x >> 12) & 0x0f));
12086 		out[1] = (duk_uint8_t) (0x80 + ((x >> 6) & 0x3f));
12087 		out[2] = (duk_uint8_t) (0x80 + (x & 0x3f));
12088 		len = 3;
12089 	} else {
12090 		/*
12091 		 *  Unicode codepoints above U+FFFF are encoded as surrogate
12092 		 *  pairs here.  This ensures that all CESU-8 codepoints are
12093 		 *  16-bit values as expected in ECMAScript.  The surrogate
12094 		 *  pairs always get a 3-byte encoding (each) in CESU-8.
12095 		 *  See: http://en.wikipedia.org/wiki/Surrogate_pair
12096 		 *
12097 		 *  20-bit codepoint, 10 bits (A and B) per surrogate pair:
12098 		 *
12099 		 *    x = 0b00000000 0000AAAA AAAAAABB BBBBBBBB
12100 		 *  sp1 = 0b110110AA AAAAAAAA  (0xd800 + ((x >> 10) & 0x3ff))
12101 		 *  sp2 = 0b110111BB BBBBBBBB  (0xdc00 + (x & 0x3ff))
12102 		 *
12103 		 *  Encoded into CESU-8:
12104 		 *
12105 		 *  sp1 -> 0b11101101  (0xe0 + ((sp1 >> 12) & 0x0f))
12106 		 *      -> 0b1010AAAA  (0x80 + ((sp1 >> 6) & 0x3f))
12107 		 *      -> 0b10AAAAAA  (0x80 + (sp1 & 0x3f))
12108 		 *  sp2 -> 0b11101101  (0xe0 + ((sp2 >> 12) & 0x0f))
12109 		 *      -> 0b1011BBBB  (0x80 + ((sp2 >> 6) & 0x3f))
12110 		 *      -> 0b10BBBBBB  (0x80 + (sp2 & 0x3f))
12111 		 *
12112 		 *  Note that 0x10000 must be subtracted first.  The code below
12113 		 *  avoids the sp1, sp2 temporaries which saves around 20 bytes
12114 		 *  of code.
12115 		 */
12116 
12117 		x -= 0x10000UL;
12118 
12119 		out[0] = (duk_uint8_t) (0xed);
12120 		out[1] = (duk_uint8_t) (0xa0 + ((x >> 16) & 0x0f));
12121 		out[2] = (duk_uint8_t) (0x80 + ((x >> 10) & 0x3f));
12122 		out[3] = (duk_uint8_t) (0xed);
12123 		out[4] = (duk_uint8_t) (0xb0 + ((x >> 6) & 0x0f));
12124 		out[5] = (duk_uint8_t) (0x80 + (x & 0x3f));
12125 		len = 6;
12126 	}
12127 
12128 	return len;
12129 }
12130 
12131 /* 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)12132 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) {
12133 	const duk_uint8_t *p;
12134 	duk_uint32_t res;
12135 	duk_uint_fast8_t ch;
12136 	duk_small_int_t n;
12137 
12138 	DUK_UNREF(thr);
12139 
12140 	p = *ptr;
12141 	if (p < ptr_start || p >= ptr_end) {
12142 		goto fail;
12143 	}
12144 
12145 	/*
12146 	 *  UTF-8 decoder which accepts longer than standard byte sequences.
12147 	 *  This allows full 32-bit code points to be used.
12148 	 */
12149 
12150 	ch = (duk_uint_fast8_t) (*p++);
12151 	if (ch < 0x80) {
12152 		/* 0xxx xxxx   [7 bits] */
12153 		res = (duk_uint32_t) (ch & 0x7f);
12154 		n = 0;
12155 	} else if (ch < 0xc0) {
12156 		/* 10xx xxxx -> invalid */
12157 		goto fail;
12158 	} else if (ch < 0xe0) {
12159 		/* 110x xxxx   10xx xxxx   [11 bits] */
12160 		res = (duk_uint32_t) (ch & 0x1f);
12161 		n = 1;
12162 	} else if (ch < 0xf0) {
12163 		/* 1110 xxxx   10xx xxxx   10xx xxxx   [16 bits] */
12164 		res = (duk_uint32_t) (ch & 0x0f);
12165 		n = 2;
12166 	} else if (ch < 0xf8) {
12167 		/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx   [21 bits] */
12168 		res = (duk_uint32_t) (ch & 0x07);
12169 		n = 3;
12170 	} else if (ch < 0xfc) {
12171 		/* 1111 10xx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [26 bits] */
12172 		res = (duk_uint32_t) (ch & 0x03);
12173 		n = 4;
12174 	} else if (ch < 0xfe) {
12175 		/* 1111 110x   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [31 bits] */
12176 		res = (duk_uint32_t) (ch & 0x01);
12177 		n = 5;
12178 	} else if (ch < 0xff) {
12179 		/* 1111 1110   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [36 bits] */
12180 		res = (duk_uint32_t) (0);
12181 		n = 6;
12182 	} else {
12183 		/* 8-byte format could be:
12184 		 * 1111 1111   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [41 bits]
12185 		 *
12186 		 * However, this format would not have a zero bit following the
12187 		 * leading one bits and would not allow 0xFF to be used as an
12188 		 * "invalid xutf-8" marker for internal keys.  Further, 8-byte
12189 		 * encodings (up to 41 bit code points) are not currently needed.
12190 		 */
12191 		goto fail;
12192 	}
12193 
12194 	DUK_ASSERT(p >= ptr_start);  /* verified at beginning */
12195 	if (p + n > ptr_end) {
12196 		/* check pointer at end */
12197 		goto fail;
12198 	}
12199 
12200 	while (n > 0) {
12201 		DUK_ASSERT(p >= ptr_start && p < ptr_end);
12202 		ch = (duk_uint_fast8_t) (*p++);
12203 #if 0
12204 		if (ch & 0xc0 != 0x80) {
12205 			/* not a continuation byte */
12206 			p--;
12207 			*ptr = p;
12208 			*out_cp = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
12209 			return 1;
12210 		}
12211 #endif
12212 		res = (res << 6) + (duk_uint32_t) (ch & 0x3f);
12213 		n--;
12214 	}
12215 
12216 	*ptr = p;
12217 	*out_cp = res;
12218 	return 1;
12219 
12220  fail:
12221 	return 0;
12222 }
12223 
12224 /* 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)12225 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) {
12226 	duk_ucodepoint_t cp;
12227 
12228 	if (duk_unicode_decode_xutf8(thr, ptr, ptr_start, ptr_end, &cp)) {
12229 		return cp;
12230 	}
12231 	DUK_ERROR_INTERNAL(thr);
12232 	DUK_WO_NORETURN(return 0;);
12233 }
12234 
12235 /* Compute (extended) utf-8 length without codepoint encoding validation,
12236  * used for string interning.
12237  *
12238  * NOTE: This algorithm is performance critical, more so than string hashing
12239  * in some cases.  It is needed when interning a string and needs to scan
12240  * every byte of the string with no skipping.  Having an ASCII fast path
12241  * is useful if possible in the algorithm.  The current algorithms were
12242  * chosen from several variants, based on x64 gcc -O2 testing.  See:
12243  * https://github.com/svaarala/duktape/pull/422
12244  *
12245  * NOTE: must match tools/dukutil.py:duk_unicode_unvalidated_utf8_length().
12246  */
12247 
12248 #if defined(DUK_USE_PREFER_SIZE)
12249 /* Small variant; roughly 150 bytes smaller than the fast variant. */
duk_unicode_unvalidated_utf8_length(const duk_uint8_t * data,duk_size_t blen)12250 DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {
12251 	const duk_uint8_t *p;
12252 	const duk_uint8_t *p_end;
12253 	duk_size_t ncont;
12254 	duk_size_t clen;
12255 
12256 	p = data;
12257 	p_end = data + blen;
12258 	ncont = 0;
12259 	while (p != p_end) {
12260 		duk_uint8_t x;
12261 		x = *p++;
12262 		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
12263 			ncont++;
12264 		}
12265 	}
12266 
12267 	DUK_ASSERT(ncont <= blen);
12268 	clen = blen - ncont;
12269 	DUK_ASSERT(clen <= blen);
12270 	return clen;
12271 }
12272 #else  /* DUK_USE_PREFER_SIZE */
12273 /* This seems like a good overall approach.  Fast path for ASCII in 4 byte
12274  * blocks.
12275  */
duk_unicode_unvalidated_utf8_length(const duk_uint8_t * data,duk_size_t blen)12276 DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {
12277 	const duk_uint8_t *p;
12278 	const duk_uint8_t *p_end;
12279 	const duk_uint32_t *p32_end;
12280 	const duk_uint32_t *p32;
12281 	duk_size_t ncont;
12282 	duk_size_t clen;
12283 
12284 	ncont = 0;  /* number of continuation (non-initial) bytes in [0x80,0xbf] */
12285 	p = data;
12286 	p_end = data + blen;
12287 	if (blen < 16) {
12288 		goto skip_fastpath;
12289 	}
12290 
12291 	/* Align 'p' to 4; the input data may have arbitrary alignment.
12292 	 * End of string check not needed because blen >= 16.
12293 	 */
12294 	while (((duk_size_t) (const void *) p) & 0x03U) {
12295 		duk_uint8_t x;
12296 		x = *p++;
12297 		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
12298 			ncont++;
12299 		}
12300 	}
12301 
12302 	/* Full, aligned 4-byte reads. */
12303 	p32_end = (const duk_uint32_t *) (const void *) (p + ((duk_size_t) (p_end - p) & (duk_size_t) (~0x03)));
12304 	p32 = (const duk_uint32_t *) (const void *) p;
12305 	while (p32 != (const duk_uint32_t *) p32_end) {
12306 		duk_uint32_t x;
12307 		x = *p32++;
12308 		if (DUK_LIKELY((x & 0x80808080UL) == 0)) {
12309 			;  /* ASCII fast path */
12310 		} else {
12311 			/* Flip highest bit of each byte which changes
12312 			 * the bit pattern 10xxxxxx into 00xxxxxx which
12313 			 * allows an easy bit mask test.
12314 			 */
12315 			x ^= 0x80808080UL;
12316 			if (DUK_UNLIKELY(!(x & 0xc0000000UL))) {
12317 				ncont++;
12318 			}
12319 			if (DUK_UNLIKELY(!(x & 0x00c00000UL))) {
12320 				ncont++;
12321 			}
12322 			if (DUK_UNLIKELY(!(x & 0x0000c000UL))) {
12323 				ncont++;
12324 			}
12325 			if (DUK_UNLIKELY(!(x & 0x000000c0UL))) {
12326 				ncont++;
12327 			}
12328 		}
12329 	}
12330 	p = (const duk_uint8_t *) p32;
12331 	/* Fall through to handle the rest. */
12332 
12333  skip_fastpath:
12334 	while (p != p_end) {
12335 		duk_uint8_t x;
12336 		x = *p++;
12337 		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
12338 			ncont++;
12339 		}
12340 	}
12341 
12342 	DUK_ASSERT(ncont <= blen);
12343 	clen = blen - ncont;
12344 	DUK_ASSERT(clen <= blen);
12345 	return clen;
12346 }
12347 #endif  /* DUK_USE_PREFER_SIZE */
12348 
12349 /* Check whether a string is UTF-8 compatible or not. */
duk_unicode_is_utf8_compatible(const duk_uint8_t * buf,duk_size_t len)12350 DUK_INTERNAL duk_bool_t duk_unicode_is_utf8_compatible(const duk_uint8_t *buf, duk_size_t len) {
12351 	duk_size_t i = 0;
12352 #if !defined(DUK_USE_PREFER_SIZE)
12353 	duk_size_t len_safe;
12354 #endif
12355 
12356 	/* Many practical strings are ASCII only, so use a fast path check
12357 	 * to check chunks of bytes at once with minimal branch cost.
12358 	 */
12359 #if !defined(DUK_USE_PREFER_SIZE)
12360 	len_safe = len & ~0x03UL;
12361 	for (; i < len_safe; i += 4) {
12362 		duk_uint8_t t = buf[i] | buf[i + 1] | buf[i + 2] | buf[i + 3];
12363 		if (DUK_UNLIKELY((t & 0x80U) != 0U)) {
12364 			/* At least one byte was outside 0x00-0x7f, break
12365 			 * out to slow path (and remain there).
12366 			 *
12367 			 * XXX: We could also deal with the problem character
12368 			 * and resume fast path later.
12369 			 */
12370 			break;
12371 		}
12372 	}
12373 #endif
12374 
12375 	for (; i < len;) {
12376 		duk_uint8_t t;
12377 		duk_size_t left;
12378 		duk_size_t ncont;
12379 		duk_uint32_t cp;
12380 		duk_uint32_t mincp;
12381 
12382 		t = buf[i++];
12383 		if (DUK_LIKELY((t & 0x80U) == 0U)) {
12384 			/* Fast path, ASCII. */
12385 			continue;
12386 		}
12387 
12388 		/* Non-ASCII start byte, slow path.
12389 		 *
12390 		 * 10xx xxxx          -> continuation byte
12391 		 * 110x xxxx + 1*CONT -> [0x80, 0x7ff]
12392 		 * 1110 xxxx + 2*CONT -> [0x800, 0xffff], must reject [0xd800,0xdfff]
12393 		 * 1111 0xxx + 3*CONT -> [0x10000, 0x10ffff]
12394 		 */
12395 		left = len - i;
12396 		if (t <= 0xdfU) {  /* 1101 1111 = 0xdf */
12397 			if (t <= 0xbfU) {  /* 1011 1111 = 0xbf */
12398 				return 0;
12399 			}
12400 			ncont = 1;
12401 			mincp = 0x80UL;
12402 			cp = t & 0x1fU;
12403 		} else if (t <= 0xefU) {  /* 1110 1111 = 0xef */
12404 			ncont = 2;
12405 			mincp = 0x800UL;
12406 			cp = t & 0x0fU;
12407 		} else if (t <= 0xf7U) {  /* 1111 0111 = 0xf7 */
12408 			ncont = 3;
12409 			mincp = 0x10000UL;
12410 			cp = t & 0x07U;
12411 		} else {
12412 			return 0;
12413 		}
12414 		if (left < ncont) {
12415 			return 0;
12416 		}
12417 		while (ncont > 0U) {
12418 			t = buf[i++];
12419 			if ((t & 0xc0U) != 0x80U) {  /* 10xx xxxx */
12420 				return 0;
12421 			}
12422 			cp = (cp << 6) + (t & 0x3fU);
12423 			ncont--;
12424 		}
12425 		if (cp < mincp || cp > 0x10ffffUL || (cp >= 0xd800UL && cp <= 0xdfffUL)) {
12426 			return 0;
12427 		}
12428 	}
12429 
12430 	return 1;
12431 }
12432 
12433 /*
12434  *  Unicode range matcher
12435  *
12436  *  Matches a codepoint against a packed bitstream of character ranges.
12437  *  Used for slow path Unicode matching.
12438  */
12439 
12440 /* Must match tools/extract_chars.py, generate_match_table3(). */
duk__uni_decode_value(duk_bitdecoder_ctx * bd_ctx)12441 DUK_LOCAL duk_uint32_t duk__uni_decode_value(duk_bitdecoder_ctx *bd_ctx) {
12442 	duk_uint32_t t;
12443 
12444 	t = (duk_uint32_t) duk_bd_decode(bd_ctx, 4);
12445 	if (t <= 0x0eU) {
12446 		return t;
12447 	}
12448 	t = (duk_uint32_t) duk_bd_decode(bd_ctx, 8);
12449 	if (t <= 0xfdU) {
12450 		return t + 0x0f;
12451 	}
12452 	if (t == 0xfeU) {
12453 		t = (duk_uint32_t) duk_bd_decode(bd_ctx, 12);
12454 		return t + 0x0fU + 0xfeU;
12455 	} else {
12456 		t = (duk_uint32_t) duk_bd_decode(bd_ctx, 24);
12457 		return t + 0x0fU + 0xfeU + 0x1000UL;
12458 	}
12459 }
12460 
duk__uni_range_match(const duk_uint8_t * unitab,duk_size_t unilen,duk_codepoint_t cp)12461 DUK_LOCAL duk_small_int_t duk__uni_range_match(const duk_uint8_t *unitab, duk_size_t unilen, duk_codepoint_t cp) {
12462 	duk_bitdecoder_ctx bd_ctx;
12463 	duk_codepoint_t prev_re;
12464 
12465 	duk_memzero(&bd_ctx, sizeof(bd_ctx));
12466 	bd_ctx.data = (const duk_uint8_t *) unitab;
12467 	bd_ctx.length = (duk_size_t) unilen;
12468 
12469 	prev_re = 0;
12470 	for (;;) {
12471 		duk_codepoint_t r1, r2;
12472 		r1 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
12473 		if (r1 == 0) {
12474 			break;
12475 		}
12476 		r2 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
12477 
12478 		r1 = prev_re + r1;
12479 		r2 = r1 + r2;
12480 		prev_re = r2;
12481 
12482 		/* [r1,r2] is the range */
12483 
12484 		DUK_DDD(DUK_DDDPRINT("duk__uni_range_match: cp=%06lx range=[0x%06lx,0x%06lx]",
12485 		                     (unsigned long) cp, (unsigned long) r1, (unsigned long) r2));
12486 		if (cp >= r1 && cp <= r2) {
12487 			return 1;
12488 		}
12489 	}
12490 
12491 	return 0;
12492 }
12493 
12494 /*
12495  *  "WhiteSpace" production check.
12496  */
12497 
duk_unicode_is_whitespace(duk_codepoint_t cp)12498 DUK_INTERNAL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp) {
12499 	/*
12500 	 *  E5 Section 7.2 specifies six characters specifically as
12501 	 *  white space:
12502 	 *
12503 	 *    0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULATION;;;;
12504 	 *    000B;<control>;Cc;0;S;;;;;N;LINE TABULATION;;;;
12505 	 *    000C;<control>;Cc;0;WS;;;;;N;FORM FEED (FF);;;;
12506 	 *    0020;SPACE;Zs;0;WS;;;;;N;;;;;
12507 	 *    00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
12508 	 *    FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;;
12509 	 *
12510 	 *  It also specifies any Unicode category 'Zs' characters as white
12511 	 *  space.  These can be extracted with the "tools/extract_chars.py" script.
12512 	 *  Current result:
12513 	 *
12514 	 *    RAW OUTPUT:
12515 	 *    ===========
12516 	 *    0020;SPACE;Zs;0;WS;;;;;N;;;;;
12517 	 *    00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
12518 	 *    1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;;
12519 	 *    180E;MONGOLIAN VOWEL SEPARATOR;Zs;0;WS;;;;;N;;;;;
12520 	 *    2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;;
12521 	 *    2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;;
12522 	 *    2002;EN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12523 	 *    2003;EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12524 	 *    2004;THREE-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12525 	 *    2005;FOUR-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12526 	 *    2006;SIX-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12527 	 *    2007;FIGURE SPACE;Zs;0;WS;<noBreak> 0020;;;;N;;;;;
12528 	 *    2008;PUNCTUATION SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12529 	 *    2009;THIN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12530 	 *    200A;HAIR SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12531 	 *    202F;NARROW NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;;;;;
12532 	 *    205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12533 	 *    3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;;
12534 	 *
12535 	 *    RANGES:
12536 	 *    =======
12537 	 *    0x0020
12538 	 *    0x00a0
12539 	 *    0x1680
12540 	 *    0x180e
12541 	 *    0x2000 ... 0x200a
12542 	 *    0x202f
12543 	 *    0x205f
12544 	 *    0x3000
12545 	 *
12546 	 *  A manual decoder (below) is probably most compact for this.
12547 	 */
12548 
12549 	duk_uint_fast8_t lo;
12550 	duk_uint_fast32_t hi;
12551 
12552 	/* cp == -1 (EOF) never matches and causes return value 0 */
12553 
12554 	lo = (duk_uint_fast8_t) (cp & 0xff);
12555 	hi = (duk_uint_fast32_t) (cp >> 8);  /* does not fit into an uchar */
12556 
12557 	if (hi == 0x0000UL) {
12558 		if (lo == 0x09U || lo == 0x0bU || lo == 0x0cU ||
12559 		    lo == 0x20U || lo == 0xa0U) {
12560 			return 1;
12561 		}
12562 	} else if (hi == 0x0020UL) {
12563 		if (lo <= 0x0aU || lo == 0x2fU || lo == 0x5fU) {
12564 			return 1;
12565 		}
12566 	} else if (cp == 0x1680L || cp == 0x180eL || cp == 0x3000L ||
12567 	           cp == 0xfeffL) {
12568 		return 1;
12569 	}
12570 
12571 	return 0;
12572 }
12573 
12574 /*
12575  *  "LineTerminator" production check.
12576  */
12577 
duk_unicode_is_line_terminator(duk_codepoint_t cp)12578 DUK_INTERNAL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp) {
12579 	/*
12580 	 *  E5 Section 7.3
12581 	 *
12582 	 *  A LineTerminatorSequence essentially merges <CR> <LF> sequences
12583 	 *  into a single line terminator.  This must be handled by the caller.
12584 	 */
12585 
12586 	if (cp == 0x000aL || cp == 0x000dL || cp == 0x2028L ||
12587 	    cp == 0x2029L) {
12588 		return 1;
12589 	}
12590 
12591 	return 0;
12592 }
12593 
12594 /*
12595  *  "IdentifierStart" production check.
12596  */
12597 
duk_unicode_is_identifier_start(duk_codepoint_t cp)12598 DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp) {
12599 	/*
12600 	 *  E5 Section 7.6:
12601 	 *
12602 	 *    IdentifierStart:
12603 	 *      UnicodeLetter
12604 	 *      $
12605 	 *      _
12606 	 *      \ UnicodeEscapeSequence
12607 	 *
12608 	 *  IdentifierStart production has one multi-character production:
12609 	 *
12610 	 *    \ UnicodeEscapeSequence
12611 	 *
12612 	 *  The '\' character is -not- matched by this function.  Rather, the caller
12613 	 *  should decode the escape and then call this function to check whether the
12614 	 *  decoded character is acceptable (see discussion in E5 Section 7.6).
12615 	 *
12616 	 *  The "UnicodeLetter" alternative of the production allows letters
12617 	 *  from various Unicode categories.  These can be extracted with the
12618 	 *  "tools/extract_chars.py" script.
12619 	 *
12620 	 *  Because the result has hundreds of Unicode codepoint ranges, matching
12621 	 *  for any values >= 0x80 are done using a very slow range-by-range scan
12622 	 *  and a packed range format.
12623 	 *
12624 	 *  The ASCII portion (codepoints 0x00 ... 0x7f) is fast-pathed below because
12625 	 *  it matters the most.  The ASCII related ranges of IdentifierStart are:
12626 	 *
12627 	 *    0x0041 ... 0x005a     ['A' ... 'Z']
12628 	 *    0x0061 ... 0x007a     ['a' ... 'z']
12629 	 *    0x0024                ['$']
12630 	 *    0x005f                ['_']
12631 	 */
12632 
12633 	/* ASCII (and EOF) fast path -- quick accept and reject */
12634 	if (cp <= 0x7fL) {
12635 #if defined(DUK_USE_IDCHAR_FASTPATH)
12636 		return (cp >= 0) && (duk_is_idchar_tab[cp] > 0);
12637 #else
12638 		if ((cp >= 'a' && cp <= 'z') ||
12639 		    (cp >= 'A' && cp <= 'Z') ||
12640 		    cp == '_' || cp == '$') {
12641 			return 1;
12642 		}
12643 		return 0;
12644 #endif
12645 	}
12646 
12647 	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
12648 
12649 #if defined(DUK_USE_SOURCE_NONBMP)
12650 	if (duk__uni_range_match(duk_unicode_ids_noa,
12651 	                         (duk_size_t) sizeof(duk_unicode_ids_noa),
12652 	                         (duk_codepoint_t) cp)) {
12653 		return 1;
12654 	}
12655 	return 0;
12656 #else
12657 	if (cp < 0x10000L) {
12658 		if (duk__uni_range_match(duk_unicode_ids_noabmp,
12659 		                         sizeof(duk_unicode_ids_noabmp),
12660 		                         (duk_codepoint_t) cp)) {
12661 			return 1;
12662 		}
12663 		return 0;
12664 	} else {
12665 		/* without explicit non-BMP support, assume non-BMP characters
12666 		 * are always accepted as identifier characters.
12667 		 */
12668 		return 1;
12669 	}
12670 #endif
12671 }
12672 
12673 /*
12674  *  "IdentifierPart" production check.
12675  */
12676 
duk_unicode_is_identifier_part(duk_codepoint_t cp)12677 DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp) {
12678 	/*
12679 	 *  E5 Section 7.6:
12680 	 *
12681 	 *    IdentifierPart:
12682 	 *      IdentifierStart
12683 	 *      UnicodeCombiningMark
12684 	 *      UnicodeDigit
12685 	 *      UnicodeConnectorPunctuation
12686 	 *      <ZWNJ>  [U+200C]
12687 	 *      <ZWJ>   [U+200D]
12688 	 *
12689 	 *  IdentifierPart production has one multi-character production
12690 	 *  as part of its IdentifierStart alternative.  The '\' character
12691 	 *  of an escape sequence is not matched here, see discussion in
12692 	 *  duk_unicode_is_identifier_start().
12693 	 *
12694 	 *  To match non-ASCII characters (codepoints >= 0x80), a very slow
12695 	 *  linear range-by-range scan is used.  The codepoint is first compared
12696 	 *  to the IdentifierStart ranges, and if it doesn't match, then to a
12697 	 *  set consisting of code points in IdentifierPart but not in
12698 	 *  IdentifierStart.  This is done to keep the unicode range data small,
12699 	 *  at the expense of speed.
12700 	 *
12701 	 *  The ASCII fast path consists of:
12702 	 *
12703 	 *    0x0030 ... 0x0039     ['0' ... '9', UnicodeDigit]
12704 	 *    0x0041 ... 0x005a     ['A' ... 'Z', IdentifierStart]
12705 	 *    0x0061 ... 0x007a     ['a' ... 'z', IdentifierStart]
12706 	 *    0x0024                ['$', IdentifierStart]
12707 	 *    0x005f                ['_', IdentifierStart and
12708 	 *                                UnicodeConnectorPunctuation]
12709 	 *
12710 	 *  UnicodeCombiningMark has no code points <= 0x7f.
12711 	 *
12712 	 *  The matching code reuses the "identifier start" tables, and then
12713 	 *  consults a separate range set for characters in "identifier part"
12714 	 *  but not in "identifier start".  These can be extracted with the
12715 	 *  "tools/extract_chars.py" script.
12716 	 *
12717 	 *  UnicodeCombiningMark -> categories Mn, Mc
12718 	 *  UnicodeDigit -> categories Nd
12719 	 *  UnicodeConnectorPunctuation -> categories Pc
12720 	 */
12721 
12722 	/* ASCII (and EOF) fast path -- quick accept and reject */
12723 	if (cp <= 0x7fL) {
12724 #if defined(DUK_USE_IDCHAR_FASTPATH)
12725 		return (cp >= 0) && (duk_is_idchar_tab[cp] != 0);
12726 #else
12727 		if ((cp >= 'a' && cp <= 'z') ||
12728 		    (cp >= 'A' && cp <= 'Z') ||
12729 		    (cp >= '0' && cp <= '9') ||
12730 		    cp == '_' || cp == '$') {
12731 			return 1;
12732 		}
12733 		return 0;
12734 #endif
12735 	}
12736 
12737 	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
12738 
12739 #if defined(DUK_USE_SOURCE_NONBMP)
12740 	if (duk__uni_range_match(duk_unicode_ids_noa,
12741 	                         sizeof(duk_unicode_ids_noa),
12742 	                         (duk_codepoint_t) cp) ||
12743 	    duk__uni_range_match(duk_unicode_idp_m_ids_noa,
12744 	                         sizeof(duk_unicode_idp_m_ids_noa),
12745 	                         (duk_codepoint_t) cp)) {
12746 		return 1;
12747 	}
12748 	return 0;
12749 #else
12750 	if (cp < 0x10000L) {
12751 		if (duk__uni_range_match(duk_unicode_ids_noabmp,
12752 		                         sizeof(duk_unicode_ids_noabmp),
12753 		                         (duk_codepoint_t) cp) ||
12754 		    duk__uni_range_match(duk_unicode_idp_m_ids_noabmp,
12755 		                         sizeof(duk_unicode_idp_m_ids_noabmp),
12756 		                         (duk_codepoint_t) cp)) {
12757 			return 1;
12758 		}
12759 		return 0;
12760 	} else {
12761 		/* without explicit non-BMP support, assume non-BMP characters
12762 		 * are always accepted as identifier characters.
12763 		 */
12764 		return 1;
12765 	}
12766 #endif
12767 }
12768 
12769 /*
12770  *  Unicode letter check.
12771  */
12772 
duk_unicode_is_letter(duk_codepoint_t cp)12773 DUK_INTERNAL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp) {
12774 	/*
12775 	 *  Unicode letter is now taken to be the categories:
12776 	 *
12777 	 *    Lu, Ll, Lt, Lm, Lo
12778 	 *
12779 	 *  (Not sure if this is exactly correct.)
12780 	 *
12781 	 *  The ASCII fast path consists of:
12782 	 *
12783 	 *    0x0041 ... 0x005a     ['A' ... 'Z']
12784 	 *    0x0061 ... 0x007a     ['a' ... 'z']
12785 	 */
12786 
12787 	/* ASCII (and EOF) fast path -- quick accept and reject */
12788 	if (cp <= 0x7fL) {
12789 		if ((cp >= 'a' && cp <= 'z') ||
12790 		    (cp >= 'A' && cp <= 'Z')) {
12791 			return 1;
12792 		}
12793 		return 0;
12794 	}
12795 
12796 	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
12797 
12798 #if defined(DUK_USE_SOURCE_NONBMP)
12799 	if (duk__uni_range_match(duk_unicode_ids_noa,
12800 	                         sizeof(duk_unicode_ids_noa),
12801 	                         (duk_codepoint_t) cp) &&
12802 	    !duk__uni_range_match(duk_unicode_ids_m_let_noa,
12803 	                          sizeof(duk_unicode_ids_m_let_noa),
12804 	                          (duk_codepoint_t) cp)) {
12805 		return 1;
12806 	}
12807 	return 0;
12808 #else
12809 	if (cp < 0x10000L) {
12810 		if (duk__uni_range_match(duk_unicode_ids_noabmp,
12811 		                         sizeof(duk_unicode_ids_noabmp),
12812 		                         (duk_codepoint_t) cp) &&
12813 		    !duk__uni_range_match(duk_unicode_ids_m_let_noabmp,
12814 		                          sizeof(duk_unicode_ids_m_let_noabmp),
12815 		                          (duk_codepoint_t) cp)) {
12816 			return 1;
12817 		}
12818 		return 0;
12819 	} else {
12820 		/* without explicit non-BMP support, assume non-BMP characters
12821 		 * are always accepted as letters.
12822 		 */
12823 		return 1;
12824 	}
12825 #endif
12826 }
12827 
12828 /*
12829  *  Complex case conversion helper which decodes a bit-packed conversion
12830  *  control stream generated by tools/extract_caseconv.py.  The conversion
12831  *  is very slow because it runs through the conversion data in a linear
12832  *  fashion to save space (which is why ASCII characters have a special
12833  *  fast path before arriving here).
12834  *
12835  *  The particular bit counts etc have been determined experimentally to
12836  *  be small but still sufficient, and must match the Python script
12837  *  (tools/extract_caseconv.py).
12838  *
12839  *  The return value is the case converted codepoint or -1 if the conversion
12840  *  results in multiple characters (this is useful for regexp Canonicalization
12841  *  operation).  If 'buf' is not NULL, the result codepoint(s) are also
12842  *  appended to the hbuffer.
12843  *
12844  *  Context and locale specific rules must be checked before consulting
12845  *  this function.
12846  */
12847 
12848 DUK_LOCAL
duk__slow_case_conversion(duk_hthread * thr,duk_bufwriter_ctx * bw,duk_codepoint_t cp,duk_bitdecoder_ctx * bd_ctx)12849 duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr,
12850                                           duk_bufwriter_ctx *bw,
12851                                           duk_codepoint_t cp,
12852                                           duk_bitdecoder_ctx *bd_ctx) {
12853 	duk_small_int_t skip = 0;
12854 	duk_small_int_t n;
12855 	duk_small_int_t t;
12856 	duk_small_int_t count;
12857 	duk_codepoint_t tmp_cp;
12858 	duk_codepoint_t start_i;
12859 	duk_codepoint_t start_o;
12860 
12861 	DUK_ASSERT(bd_ctx != NULL);
12862 	DUK_UNREF(thr);
12863 
12864 	DUK_DDD(DUK_DDDPRINT("slow case conversion for codepoint: %ld", (long) cp));
12865 
12866 	/* range conversion with a "skip" */
12867 	DUK_DDD(DUK_DDDPRINT("checking ranges"));
12868 	for (;;) {
12869 		skip++;
12870 		n = (duk_small_int_t) duk_bd_decode(bd_ctx, 6);
12871 		if (n == 0x3f) {
12872 			/* end marker */
12873 			break;
12874 		}
12875 		DUK_DDD(DUK_DDDPRINT("skip=%ld, n=%ld", (long) skip, (long) n));
12876 
12877 		while (n--) {
12878 			start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12879 			start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12880 			count = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
12881 			DUK_DDD(DUK_DDDPRINT("range: start_i=%ld, start_o=%ld, count=%ld, skip=%ld",
12882 			                     (long) start_i, (long) start_o, (long) count, (long) skip));
12883 
12884 			if (cp >= start_i) {
12885 				tmp_cp = cp - start_i;  /* always >= 0 */
12886 				if (tmp_cp < (duk_codepoint_t) count * (duk_codepoint_t) skip &&
12887 				    (tmp_cp % (duk_codepoint_t) skip) == 0) {
12888 					DUK_DDD(DUK_DDDPRINT("range matches input codepoint"));
12889 					cp = start_o + tmp_cp;
12890 					goto single;
12891 				}
12892 			}
12893 		}
12894 	}
12895 
12896 	/* 1:1 conversion */
12897 	n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
12898 	DUK_DDD(DUK_DDDPRINT("checking 1:1 conversions (count %ld)", (long) n));
12899 	while (n--) {
12900 		start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12901 		start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12902 		DUK_DDD(DUK_DDDPRINT("1:1 conversion %ld -> %ld", (long) start_i, (long) start_o));
12903 		if (cp == start_i) {
12904 			DUK_DDD(DUK_DDDPRINT("1:1 matches input codepoint"));
12905 			cp = start_o;
12906 			goto single;
12907 		}
12908 	}
12909 
12910 	/* complex, multicharacter conversion */
12911 	n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
12912 	DUK_DDD(DUK_DDDPRINT("checking 1:n conversions (count %ld)", (long) n));
12913 	while (n--) {
12914 		start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12915 		t = (duk_small_int_t) duk_bd_decode(bd_ctx, 2);
12916 		DUK_DDD(DUK_DDDPRINT("1:n conversion %ld -> %ld chars", (long) start_i, (long) t));
12917 		if (cp == start_i) {
12918 			DUK_DDD(DUK_DDDPRINT("1:n matches input codepoint"));
12919 			if (bw != NULL) {
12920 				while (t--) {
12921 					tmp_cp = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12922 					DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) tmp_cp);
12923 				}
12924 			}
12925 			return -1;
12926 		} else {
12927 			while (t--) {
12928 				(void) duk_bd_decode(bd_ctx, 16);
12929 			}
12930 		}
12931 	}
12932 
12933 	/* default: no change */
12934 	DUK_DDD(DUK_DDDPRINT("no rule matches, output is same as input"));
12935 	/* fall through */
12936 
12937  single:
12938 	if (bw != NULL) {
12939 		DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);
12940 	}
12941 	return cp;
12942 }
12943 
12944 /*
12945  *  Case conversion helper, with context/local sensitivity.
12946  *  For proper case conversion, one needs to know the character
12947  *  and the preceding and following characters, as well as
12948  *  locale/language.
12949  */
12950 
12951 /* XXX: add 'language' argument when locale/language sensitive rule
12952  * support added.
12953  */
12954 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)12955 duk_codepoint_t duk__case_transform_helper(duk_hthread *thr,
12956                                            duk_bufwriter_ctx *bw,
12957                                            duk_codepoint_t cp,
12958                                            duk_codepoint_t prev,
12959                                            duk_codepoint_t next,
12960                                            duk_bool_t uppercase) {
12961 	duk_bitdecoder_ctx bd_ctx;
12962 
12963 	/* fast path for ASCII */
12964 	if (cp < 0x80L) {
12965 		/* XXX: there are language sensitive rules for the ASCII range.
12966 		 * If/when language/locale support is implemented, they need to
12967 		 * be implemented here for the fast path.  There are no context
12968 		 * sensitive rules for ASCII range.
12969 		 */
12970 
12971 		if (uppercase) {
12972 			if (cp >= 'a' && cp <= 'z') {
12973 				cp = cp - 'a' + 'A';
12974 			}
12975 		} else {
12976 			if (cp >= 'A' && cp <= 'Z') {
12977 				cp = cp - 'A' + 'a';
12978 			}
12979 		}
12980 
12981 		if (bw != NULL) {
12982 			DUK_BW_WRITE_RAW_U8(thr, bw, (duk_uint8_t) cp);
12983 		}
12984 		return cp;
12985 	}
12986 
12987 	/* context and locale specific rules which cannot currently be represented
12988 	 * in the caseconv bitstream: hardcoded rules in C
12989 	 */
12990 	if (uppercase) {
12991 		/* XXX: turkish / azeri */
12992 	} else {
12993 		/*
12994 		 *  Final sigma context specific rule.  This is a rather tricky
12995 		 *  rule and this handling is probably not 100% correct now.
12996 		 *  The rule is not locale/language specific so it is supported.
12997 		 */
12998 
12999 		if (cp == 0x03a3L &&    /* U+03A3 = GREEK CAPITAL LETTER SIGMA */
13000 		    duk_unicode_is_letter(prev) &&        /* prev exists and is not a letter */
13001 		    !duk_unicode_is_letter(next)) {       /* next does not exist or next is not a letter */
13002 			/* Capital sigma occurred at "end of word", lowercase to
13003 			 * U+03C2 = GREEK SMALL LETTER FINAL SIGMA.  Otherwise
13004 			 * fall through and let the normal rules lowercase it to
13005 			 * U+03C3 = GREEK SMALL LETTER SIGMA.
13006 			 */
13007 			cp = 0x03c2L;
13008 			goto singlechar;
13009 		}
13010 
13011 		/* XXX: lithuanian not implemented */
13012 		/* XXX: lithuanian, explicit dot rules */
13013 		/* XXX: turkish / azeri, lowercase rules */
13014 	}
13015 
13016 	/* 1:1 or special conversions, but not locale/context specific: script generated rules */
13017 	duk_memzero(&bd_ctx, sizeof(bd_ctx));
13018 	if (uppercase) {
13019 		bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_uc;
13020 		bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_uc);
13021 	} else {
13022 		bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_lc;
13023 		bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_lc);
13024 	}
13025 	return duk__slow_case_conversion(thr, bw, cp, &bd_ctx);
13026 
13027  singlechar:
13028 	if (bw != NULL) {
13029 		DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);
13030 	}
13031 	return cp;
13032 
13033  /* unused now, not needed until Turkish/Azeri */
13034 #if 0
13035  nochar:
13036 	return -1;
13037 #endif
13038 }
13039 
13040 /*
13041  *  Replace valstack top with case converted version.
13042  */
13043 
duk_unicode_case_convert_string(duk_hthread * thr,duk_bool_t uppercase)13044 DUK_INTERNAL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase) {
13045 	duk_hstring *h_input;
13046 	duk_bufwriter_ctx bw_alloc;
13047 	duk_bufwriter_ctx *bw;
13048 	const duk_uint8_t *p, *p_start, *p_end;
13049 	duk_codepoint_t prev, curr, next;
13050 
13051 	h_input = duk_require_hstring(thr, -1);  /* Accept symbols. */
13052 	DUK_ASSERT(h_input != NULL);
13053 
13054 	bw = &bw_alloc;
13055 	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));
13056 
13057 	/* [ ... input buffer ] */
13058 
13059 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
13060 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
13061 	p = p_start;
13062 
13063 	prev = -1; DUK_UNREF(prev);
13064 	curr = -1;
13065 	next = -1;
13066 	for (;;) {
13067 		prev = curr;
13068 		curr = next;
13069 		next = -1;
13070 		if (p < p_end) {
13071 			next = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
13072 		} else {
13073 			/* end of input and last char has been processed */
13074 			if (curr < 0) {
13075 				break;
13076 			}
13077 		}
13078 
13079 		/* on first round, skip */
13080 		if (curr >= 0) {
13081 			/* XXX: could add a fast path to process chunks of input codepoints,
13082 			 * but relative benefit would be quite small.
13083 			 */
13084 
13085 			/* Ensure space for maximum multi-character result; estimate is overkill. */
13086 			DUK_BW_ENSURE(thr, bw, 8 * DUK_UNICODE_MAX_XUTF8_LENGTH);
13087 
13088 			duk__case_transform_helper(thr,
13089 			                           bw,
13090 			                           (duk_codepoint_t) curr,
13091 			                           prev,
13092 			                           next,
13093 			                           uppercase);
13094 		}
13095 	}
13096 
13097 	DUK_BW_COMPACT(thr, bw);
13098 	(void) duk_buffer_to_string(thr, -1);  /* Safe, output is encoded. */
13099 	/* invalidates h_buf pointer */
13100 	duk_remove_m2(thr);
13101 }
13102 
13103 #if defined(DUK_USE_REGEXP_SUPPORT)
13104 
13105 /*
13106  *  Canonicalize() abstract operation needed for canonicalization of individual
13107  *  codepoints during regexp compilation and execution, see E5 Section 15.10.2.8.
13108  *  Note that codepoints are canonicalized one character at a time, so no context
13109  *  specific rules can apply.  Locale specific rules can apply, though.
13110  */
13111 
duk_unicode_re_canonicalize_char(duk_hthread * thr,duk_codepoint_t cp)13112 DUK_INTERNAL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp) {
13113 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
13114 	/* Fast canonicalization lookup at the cost of 128kB footprint. */
13115 	DUK_ASSERT(cp >= 0);
13116 	DUK_UNREF(thr);
13117 	if (DUK_LIKELY(cp < 0x10000L)) {
13118 		return (duk_codepoint_t) duk_unicode_re_canon_lookup[cp];
13119 	}
13120 	return cp;
13121 #else  /* DUK_USE_REGEXP_CANON_WORKAROUND */
13122 	duk_codepoint_t y;
13123 
13124 	y = duk__case_transform_helper(thr,
13125 	                               NULL,    /* NULL is allowed, no output */
13126 	                               cp,      /* curr char */
13127 	                               -1,      /* prev char */
13128 	                               -1,      /* next char */
13129 	                               1);      /* uppercase */
13130 
13131 	if ((y < 0) || (cp >= 0x80 && y < 0x80)) {
13132 		/* multiple codepoint conversion or non-ASCII mapped to ASCII
13133 		 * --> leave as is.
13134 		 */
13135 		return cp;
13136 	}
13137 
13138 	return y;
13139 #endif  /* DUK_USE_REGEXP_CANON_WORKAROUND */
13140 }
13141 
13142 /*
13143  *  E5 Section 15.10.2.6 "IsWordChar" abstract operation.  Assume
13144  *  x < 0 for characters read outside the string.
13145  */
13146 
duk_unicode_re_is_wordchar(duk_codepoint_t x)13147 DUK_INTERNAL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t x) {
13148 	/*
13149 	 *  Note: the description in E5 Section 15.10.2.6 has a typo, it
13150 	 *  contains 'A' twice and lacks 'a'; the intent is [0-9a-zA-Z_].
13151 	 */
13152 	if ((x >= '0' && x <= '9') ||
13153 	    (x >= 'a' && x <= 'z') ||
13154 	    (x >= 'A' && x <= 'Z') ||
13155 	    (x == '_')) {
13156 		return 1;
13157 	}
13158 	return 0;
13159 }
13160 
13161 /*
13162  *  Regexp range tables
13163  */
13164 
13165 /* exposed because lexer needs these too */
13166 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_digit[2] = {
13167 	(duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
13168 };
13169 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_white[22] = {
13170 	(duk_uint16_t) 0x0009UL, (duk_uint16_t) 0x000DUL,
13171 	(duk_uint16_t) 0x0020UL, (duk_uint16_t) 0x0020UL,
13172 	(duk_uint16_t) 0x00A0UL, (duk_uint16_t) 0x00A0UL,
13173 	(duk_uint16_t) 0x1680UL, (duk_uint16_t) 0x1680UL,
13174 	(duk_uint16_t) 0x180EUL, (duk_uint16_t) 0x180EUL,
13175 	(duk_uint16_t) 0x2000UL, (duk_uint16_t) 0x200AUL,
13176 	(duk_uint16_t) 0x2028UL, (duk_uint16_t) 0x2029UL,
13177 	(duk_uint16_t) 0x202FUL, (duk_uint16_t) 0x202FUL,
13178 	(duk_uint16_t) 0x205FUL, (duk_uint16_t) 0x205FUL,
13179 	(duk_uint16_t) 0x3000UL, (duk_uint16_t) 0x3000UL,
13180 	(duk_uint16_t) 0xFEFFUL, (duk_uint16_t) 0xFEFFUL,
13181 };
13182 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_wordchar[8] = {
13183 	(duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
13184 	(duk_uint16_t) 0x0041UL, (duk_uint16_t) 0x005AUL,
13185 	(duk_uint16_t) 0x005FUL, (duk_uint16_t) 0x005FUL,
13186 	(duk_uint16_t) 0x0061UL, (duk_uint16_t) 0x007AUL,
13187 };
13188 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_digit[4] = {
13189 	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
13190 	(duk_uint16_t) 0x003AUL, (duk_uint16_t) 0xFFFFUL,
13191 };
13192 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_white[24] = {
13193 	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x0008UL,
13194 	(duk_uint16_t) 0x000EUL, (duk_uint16_t) 0x001FUL,
13195 	(duk_uint16_t) 0x0021UL, (duk_uint16_t) 0x009FUL,
13196 	(duk_uint16_t) 0x00A1UL, (duk_uint16_t) 0x167FUL,
13197 	(duk_uint16_t) 0x1681UL, (duk_uint16_t) 0x180DUL,
13198 	(duk_uint16_t) 0x180FUL, (duk_uint16_t) 0x1FFFUL,
13199 	(duk_uint16_t) 0x200BUL, (duk_uint16_t) 0x2027UL,
13200 	(duk_uint16_t) 0x202AUL, (duk_uint16_t) 0x202EUL,
13201 	(duk_uint16_t) 0x2030UL, (duk_uint16_t) 0x205EUL,
13202 	(duk_uint16_t) 0x2060UL, (duk_uint16_t) 0x2FFFUL,
13203 	(duk_uint16_t) 0x3001UL, (duk_uint16_t) 0xFEFEUL,
13204 	(duk_uint16_t) 0xFF00UL, (duk_uint16_t) 0xFFFFUL,
13205 };
13206 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10] = {
13207 	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
13208 	(duk_uint16_t) 0x003AUL, (duk_uint16_t) 0x0040UL,
13209 	(duk_uint16_t) 0x005BUL, (duk_uint16_t) 0x005EUL,
13210 	(duk_uint16_t) 0x0060UL, (duk_uint16_t) 0x0060UL,
13211 	(duk_uint16_t) 0x007BUL, (duk_uint16_t) 0xFFFFUL,
13212 };
13213 
13214 #endif  /* DUK_USE_REGEXP_SUPPORT */
13215 #line 1 "duk_util_memrw.c"
13216 /*
13217  *  Macro support functions for reading/writing raw data.
13218  *
13219  *  These are done using memcpy to ensure they're valid even for unaligned
13220  *  reads/writes on platforms where alignment counts.  On x86 at least gcc
13221  *  is able to compile these into a bswap+mov.  "Always inline" is used to
13222  *  ensure these macros compile to minimal code.
13223  */
13224 
13225 /* #include duk_internal.h -> already included */
13226 
13227 union duk__u16_union {
13228 	duk_uint8_t b[2];
13229 	duk_uint16_t x;
13230 };
13231 typedef union duk__u16_union duk__u16_union;
13232 
13233 union duk__u32_union {
13234 	duk_uint8_t b[4];
13235 	duk_uint32_t x;
13236 };
13237 typedef union duk__u32_union duk__u32_union;
13238 
13239 #if defined(DUK_USE_64BIT_OPS)
13240 union duk__u64_union {
13241 	duk_uint8_t b[8];
13242 	duk_uint64_t x;
13243 };
13244 typedef union duk__u64_union duk__u64_union;
13245 #endif
13246 
duk_raw_read_u16_be(const duk_uint8_t * p)13247 DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_read_u16_be(const duk_uint8_t *p) {
13248 	duk__u16_union u;
13249 	duk_memcpy((void *) u.b, (const void *) p, (size_t) 2);
13250 	u.x = DUK_NTOH16(u.x);
13251 	return u.x;
13252 }
13253 
duk_raw_read_u32_be(const duk_uint8_t * p)13254 DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_read_u32_be(const duk_uint8_t *p) {
13255 	duk__u32_union u;
13256 	duk_memcpy((void *) u.b, (const void *) p, (size_t) 4);
13257 	u.x = DUK_NTOH32(u.x);
13258 	return u.x;
13259 }
13260 
duk_raw_read_float_be(const duk_uint8_t * p)13261 DUK_INTERNAL DUK_ALWAYS_INLINE duk_float_t duk_raw_read_float_be(const duk_uint8_t *p) {
13262 	duk_float_union fu;
13263 	duk_memcpy((void *) fu.uc, (const void *) p, (size_t) 4);
13264 	duk_fltunion_big_to_host(&fu);
13265 	return fu.f;
13266 }
13267 
duk_raw_read_double_be(const duk_uint8_t * p)13268 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_read_double_be(const duk_uint8_t *p) {
13269 	duk_double_union du;
13270 	duk_memcpy((void *) du.uc, (const void *) p, (size_t) 8);
13271 	duk_dblunion_big_to_host(&du);
13272 	return du.d;
13273 }
13274 
duk_raw_readinc_u16_be(const duk_uint8_t ** p)13275 DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_readinc_u16_be(const duk_uint8_t **p) {
13276 	duk_uint16_t res = duk_raw_read_u16_be(*p);
13277 	*p += 2;
13278 	return res;
13279 }
13280 
duk_raw_readinc_u32_be(const duk_uint8_t ** p)13281 DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_readinc_u32_be(const duk_uint8_t **p) {
13282 	duk_uint32_t res = duk_raw_read_u32_be(*p);
13283 	*p += 4;
13284 	return res;
13285 }
13286 
duk_raw_readinc_float_be(const duk_uint8_t ** p)13287 DUK_INTERNAL DUK_ALWAYS_INLINE duk_float_t duk_raw_readinc_float_be(const duk_uint8_t **p) {
13288 	duk_float_t res = duk_raw_read_float_be(*p);
13289 	*p += 4;
13290 	return res;
13291 }
13292 
duk_raw_readinc_double_be(const duk_uint8_t ** p)13293 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_readinc_double_be(const duk_uint8_t **p) {
13294 	duk_double_t res = duk_raw_read_double_be(*p);
13295 	*p += 8;
13296 	return res;
13297 }
13298 
duk_raw_write_u16_be(duk_uint8_t * p,duk_uint16_t val)13299 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u16_be(duk_uint8_t *p, duk_uint16_t val) {
13300 	duk__u16_union u;
13301 	u.x = DUK_HTON16(val);
13302 	duk_memcpy((void *) p, (const void *) u.b, (size_t) 2);
13303 }
13304 
duk_raw_write_u32_be(duk_uint8_t * p,duk_uint32_t val)13305 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u32_be(duk_uint8_t *p, duk_uint32_t val) {
13306 	duk__u32_union u;
13307 	u.x = DUK_HTON32(val);
13308 	duk_memcpy((void *) p, (const void *) u.b, (size_t) 4);
13309 }
13310 
duk_raw_write_float_be(duk_uint8_t * p,duk_float_t val)13311 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_float_be(duk_uint8_t *p, duk_float_t val) {
13312 	duk_float_union fu;
13313 	fu.f = val;
13314 	duk_fltunion_host_to_big(&fu);
13315 	duk_memcpy((void *) p, (const void *) fu.uc, (size_t) 4);
13316 }
13317 
duk_raw_write_double_be(duk_uint8_t * p,duk_double_t val)13318 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_double_be(duk_uint8_t *p, duk_double_t val) {
13319 	duk_double_union du;
13320 	du.d = val;
13321 	duk_dblunion_host_to_big(&du);
13322 	duk_memcpy((void *) p, (const void *) du.uc, (size_t) 8);
13323 }
13324 
duk_raw_write_xutf8(duk_uint8_t * p,duk_ucodepoint_t val)13325 DUK_INTERNAL duk_small_int_t duk_raw_write_xutf8(duk_uint8_t *p, duk_ucodepoint_t val) {
13326 	duk_small_int_t len = duk_unicode_encode_xutf8(val, p);
13327 	return len;
13328 }
13329 
duk_raw_write_cesu8(duk_uint8_t * p,duk_ucodepoint_t val)13330 DUK_INTERNAL duk_small_int_t duk_raw_write_cesu8(duk_uint8_t *p, duk_ucodepoint_t val) {
13331 	duk_small_int_t len = duk_unicode_encode_cesu8(val, p);
13332 	return len;
13333 }
13334 
duk_raw_writeinc_u16_be(duk_uint8_t ** p,duk_uint16_t val)13335 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_u16_be(duk_uint8_t **p, duk_uint16_t val) {
13336 	duk_raw_write_u16_be(*p, val);
13337 	*p += 2;
13338 }
13339 
duk_raw_writeinc_u32_be(duk_uint8_t ** p,duk_uint32_t val)13340 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_u32_be(duk_uint8_t **p, duk_uint32_t val) {
13341 	duk_raw_write_u32_be(*p, val);
13342 	*p += 4;
13343 }
13344 
duk_raw_writeinc_float_be(duk_uint8_t ** p,duk_float_t val)13345 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_float_be(duk_uint8_t **p, duk_float_t val) {
13346 	duk_raw_write_float_be(*p, val);
13347 	*p += 4;
13348 }
13349 
duk_raw_writeinc_double_be(duk_uint8_t ** p,duk_double_t val)13350 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_double_be(duk_uint8_t **p, duk_double_t val) {
13351 	duk_raw_write_double_be(*p, val);
13352 	*p += 8;
13353 }
13354 
duk_raw_writeinc_xutf8(duk_uint8_t ** p,duk_ucodepoint_t val)13355 DUK_INTERNAL void duk_raw_writeinc_xutf8(duk_uint8_t **p, duk_ucodepoint_t val) {
13356 	duk_small_int_t len = duk_unicode_encode_xutf8(val, *p);
13357 	*p += len;
13358 }
13359 
duk_raw_writeinc_cesu8(duk_uint8_t ** p,duk_ucodepoint_t val)13360 DUK_INTERNAL void duk_raw_writeinc_cesu8(duk_uint8_t **p, duk_ucodepoint_t val) {
13361 	duk_small_int_t len = duk_unicode_encode_cesu8(val, *p);
13362 	*p += len;
13363 }
13364 #line 1 "duk_util_misc.c"
13365 /*
13366  *  Misc util stuff.
13367  */
13368 
13369 /* #include duk_internal.h -> already included */
13370 
13371 /*
13372  *  Lowercase digits for radix values 2 to 36.  Also doubles as lowercase
13373  *  hex nybble table.
13374  */
13375 
13376 DUK_INTERNAL const duk_uint8_t duk_lc_digits[36] = {
13377 	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
13378 	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
13379 	DUK_ASC_8, DUK_ASC_9, DUK_ASC_LC_A, DUK_ASC_LC_B,
13380 	DUK_ASC_LC_C, DUK_ASC_LC_D, DUK_ASC_LC_E, DUK_ASC_LC_F,
13381 	DUK_ASC_LC_G, DUK_ASC_LC_H, DUK_ASC_LC_I, DUK_ASC_LC_J,
13382 	DUK_ASC_LC_K, DUK_ASC_LC_L, DUK_ASC_LC_M, DUK_ASC_LC_N,
13383 	DUK_ASC_LC_O, DUK_ASC_LC_P, DUK_ASC_LC_Q, DUK_ASC_LC_R,
13384 	DUK_ASC_LC_S, DUK_ASC_LC_T, DUK_ASC_LC_U, DUK_ASC_LC_V,
13385 	DUK_ASC_LC_W, DUK_ASC_LC_X, DUK_ASC_LC_Y, DUK_ASC_LC_Z
13386 };
13387 
13388 DUK_INTERNAL const duk_uint8_t duk_uc_nybbles[16] = {
13389 	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
13390 	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
13391 	DUK_ASC_8, DUK_ASC_9, DUK_ASC_UC_A, DUK_ASC_UC_B,
13392 	DUK_ASC_UC_C, DUK_ASC_UC_D, DUK_ASC_UC_E, DUK_ASC_UC_F
13393 };
13394 
13395 /*
13396  *  Table for hex decoding ASCII hex digits
13397  */
13398 
13399 DUK_INTERNAL const duk_int8_t duk_hex_dectab[256] = {
13400 	/* -1 if invalid */
13401 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x00-0x0f */
13402 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x10-0x1f */
13403 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x20-0x2f */
13404 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,  /* 0x30-0x3f */
13405 	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x40-0x4f */
13406 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x50-0x5f */
13407 	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x60-0x6f */
13408 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x70-0x7f */
13409 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x80-0x8f */
13410 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x90-0x9f */
13411 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xa0-0xaf */
13412 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xb0-0xbf */
13413 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xc0-0xcf */
13414 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xd0-0xdf */
13415 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xe0-0xef */
13416 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1   /* 0xf0-0xff */
13417 };
13418 
13419 #if defined(DUK_USE_HEX_FASTPATH)
13420 /* Preshifted << 4.  Must use 16-bit entry to allow negative value signaling. */
13421 DUK_INTERNAL const duk_int16_t duk_hex_dectab_shift4[256] = {
13422 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x00-0x0f */
13423 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x10-0x1f */
13424 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x20-0x2f */
13425 	0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x30-0x3f */
13426 	  -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x40-0x4f */
13427 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x50-0x5f */
13428 	  -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x60-0x6f */
13429 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x70-0x7f */
13430 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x80-0x8f */
13431 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x90-0x9f */
13432 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xa0-0xaf */
13433 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xb0-0xbf */
13434 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xc0-0xcf */
13435 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xd0-0xdf */
13436 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xe0-0xef */
13437 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1   /* 0xf0-0xff */
13438 };
13439 #endif
13440 
13441 /*
13442  *  Table for hex encoding bytes
13443  */
13444 
13445 #if defined(DUK_USE_HEX_FASTPATH)
13446 /* Lookup to encode one byte directly into 2 characters:
13447  *
13448  *   def genhextab(bswap):
13449  *       for i in xrange(256):
13450  *           t = chr(i).encode('hex')
13451  *           if bswap:
13452  *               t = t[1] + t[0]
13453  *           print('0x' + t.encode('hex') + 'U')
13454  *   print('big endian'); genhextab(False)
13455  *   print('little endian'); genhextab(True)
13456 */
13457 DUK_INTERNAL const duk_uint16_t duk_hex_enctab[256] = {
13458 #if defined(DUK_USE_INTEGER_BE)
13459 	0x3030U, 0x3031U, 0x3032U, 0x3033U, 0x3034U, 0x3035U, 0x3036U, 0x3037U,
13460 	0x3038U, 0x3039U, 0x3061U, 0x3062U, 0x3063U, 0x3064U, 0x3065U, 0x3066U,
13461 	0x3130U, 0x3131U, 0x3132U, 0x3133U, 0x3134U, 0x3135U, 0x3136U, 0x3137U,
13462 	0x3138U, 0x3139U, 0x3161U, 0x3162U, 0x3163U, 0x3164U, 0x3165U, 0x3166U,
13463 	0x3230U, 0x3231U, 0x3232U, 0x3233U, 0x3234U, 0x3235U, 0x3236U, 0x3237U,
13464 	0x3238U, 0x3239U, 0x3261U, 0x3262U, 0x3263U, 0x3264U, 0x3265U, 0x3266U,
13465 	0x3330U, 0x3331U, 0x3332U, 0x3333U, 0x3334U, 0x3335U, 0x3336U, 0x3337U,
13466 	0x3338U, 0x3339U, 0x3361U, 0x3362U, 0x3363U, 0x3364U, 0x3365U, 0x3366U,
13467 	0x3430U, 0x3431U, 0x3432U, 0x3433U, 0x3434U, 0x3435U, 0x3436U, 0x3437U,
13468 	0x3438U, 0x3439U, 0x3461U, 0x3462U, 0x3463U, 0x3464U, 0x3465U, 0x3466U,
13469 	0x3530U, 0x3531U, 0x3532U, 0x3533U, 0x3534U, 0x3535U, 0x3536U, 0x3537U,
13470 	0x3538U, 0x3539U, 0x3561U, 0x3562U, 0x3563U, 0x3564U, 0x3565U, 0x3566U,
13471 	0x3630U, 0x3631U, 0x3632U, 0x3633U, 0x3634U, 0x3635U, 0x3636U, 0x3637U,
13472 	0x3638U, 0x3639U, 0x3661U, 0x3662U, 0x3663U, 0x3664U, 0x3665U, 0x3666U,
13473 	0x3730U, 0x3731U, 0x3732U, 0x3733U, 0x3734U, 0x3735U, 0x3736U, 0x3737U,
13474 	0x3738U, 0x3739U, 0x3761U, 0x3762U, 0x3763U, 0x3764U, 0x3765U, 0x3766U,
13475 	0x3830U, 0x3831U, 0x3832U, 0x3833U, 0x3834U, 0x3835U, 0x3836U, 0x3837U,
13476 	0x3838U, 0x3839U, 0x3861U, 0x3862U, 0x3863U, 0x3864U, 0x3865U, 0x3866U,
13477 	0x3930U, 0x3931U, 0x3932U, 0x3933U, 0x3934U, 0x3935U, 0x3936U, 0x3937U,
13478 	0x3938U, 0x3939U, 0x3961U, 0x3962U, 0x3963U, 0x3964U, 0x3965U, 0x3966U,
13479 	0x6130U, 0x6131U, 0x6132U, 0x6133U, 0x6134U, 0x6135U, 0x6136U, 0x6137U,
13480 	0x6138U, 0x6139U, 0x6161U, 0x6162U, 0x6163U, 0x6164U, 0x6165U, 0x6166U,
13481 	0x6230U, 0x6231U, 0x6232U, 0x6233U, 0x6234U, 0x6235U, 0x6236U, 0x6237U,
13482 	0x6238U, 0x6239U, 0x6261U, 0x6262U, 0x6263U, 0x6264U, 0x6265U, 0x6266U,
13483 	0x6330U, 0x6331U, 0x6332U, 0x6333U, 0x6334U, 0x6335U, 0x6336U, 0x6337U,
13484 	0x6338U, 0x6339U, 0x6361U, 0x6362U, 0x6363U, 0x6364U, 0x6365U, 0x6366U,
13485 	0x6430U, 0x6431U, 0x6432U, 0x6433U, 0x6434U, 0x6435U, 0x6436U, 0x6437U,
13486 	0x6438U, 0x6439U, 0x6461U, 0x6462U, 0x6463U, 0x6464U, 0x6465U, 0x6466U,
13487 	0x6530U, 0x6531U, 0x6532U, 0x6533U, 0x6534U, 0x6535U, 0x6536U, 0x6537U,
13488 	0x6538U, 0x6539U, 0x6561U, 0x6562U, 0x6563U, 0x6564U, 0x6565U, 0x6566U,
13489 	0x6630U, 0x6631U, 0x6632U, 0x6633U, 0x6634U, 0x6635U, 0x6636U, 0x6637U,
13490 	0x6638U, 0x6639U, 0x6661U, 0x6662U, 0x6663U, 0x6664U, 0x6665U, 0x6666U
13491 #else  /* DUK_USE_INTEGER_BE */
13492 	0x3030U, 0x3130U, 0x3230U, 0x3330U, 0x3430U, 0x3530U, 0x3630U, 0x3730U,
13493 	0x3830U, 0x3930U, 0x6130U, 0x6230U, 0x6330U, 0x6430U, 0x6530U, 0x6630U,
13494 	0x3031U, 0x3131U, 0x3231U, 0x3331U, 0x3431U, 0x3531U, 0x3631U, 0x3731U,
13495 	0x3831U, 0x3931U, 0x6131U, 0x6231U, 0x6331U, 0x6431U, 0x6531U, 0x6631U,
13496 	0x3032U, 0x3132U, 0x3232U, 0x3332U, 0x3432U, 0x3532U, 0x3632U, 0x3732U,
13497 	0x3832U, 0x3932U, 0x6132U, 0x6232U, 0x6332U, 0x6432U, 0x6532U, 0x6632U,
13498 	0x3033U, 0x3133U, 0x3233U, 0x3333U, 0x3433U, 0x3533U, 0x3633U, 0x3733U,
13499 	0x3833U, 0x3933U, 0x6133U, 0x6233U, 0x6333U, 0x6433U, 0x6533U, 0x6633U,
13500 	0x3034U, 0x3134U, 0x3234U, 0x3334U, 0x3434U, 0x3534U, 0x3634U, 0x3734U,
13501 	0x3834U, 0x3934U, 0x6134U, 0x6234U, 0x6334U, 0x6434U, 0x6534U, 0x6634U,
13502 	0x3035U, 0x3135U, 0x3235U, 0x3335U, 0x3435U, 0x3535U, 0x3635U, 0x3735U,
13503 	0x3835U, 0x3935U, 0x6135U, 0x6235U, 0x6335U, 0x6435U, 0x6535U, 0x6635U,
13504 	0x3036U, 0x3136U, 0x3236U, 0x3336U, 0x3436U, 0x3536U, 0x3636U, 0x3736U,
13505 	0x3836U, 0x3936U, 0x6136U, 0x6236U, 0x6336U, 0x6436U, 0x6536U, 0x6636U,
13506 	0x3037U, 0x3137U, 0x3237U, 0x3337U, 0x3437U, 0x3537U, 0x3637U, 0x3737U,
13507 	0x3837U, 0x3937U, 0x6137U, 0x6237U, 0x6337U, 0x6437U, 0x6537U, 0x6637U,
13508 	0x3038U, 0x3138U, 0x3238U, 0x3338U, 0x3438U, 0x3538U, 0x3638U, 0x3738U,
13509 	0x3838U, 0x3938U, 0x6138U, 0x6238U, 0x6338U, 0x6438U, 0x6538U, 0x6638U,
13510 	0x3039U, 0x3139U, 0x3239U, 0x3339U, 0x3439U, 0x3539U, 0x3639U, 0x3739U,
13511 	0x3839U, 0x3939U, 0x6139U, 0x6239U, 0x6339U, 0x6439U, 0x6539U, 0x6639U,
13512 	0x3061U, 0x3161U, 0x3261U, 0x3361U, 0x3461U, 0x3561U, 0x3661U, 0x3761U,
13513 	0x3861U, 0x3961U, 0x6161U, 0x6261U, 0x6361U, 0x6461U, 0x6561U, 0x6661U,
13514 	0x3062U, 0x3162U, 0x3262U, 0x3362U, 0x3462U, 0x3562U, 0x3662U, 0x3762U,
13515 	0x3862U, 0x3962U, 0x6162U, 0x6262U, 0x6362U, 0x6462U, 0x6562U, 0x6662U,
13516 	0x3063U, 0x3163U, 0x3263U, 0x3363U, 0x3463U, 0x3563U, 0x3663U, 0x3763U,
13517 	0x3863U, 0x3963U, 0x6163U, 0x6263U, 0x6363U, 0x6463U, 0x6563U, 0x6663U,
13518 	0x3064U, 0x3164U, 0x3264U, 0x3364U, 0x3464U, 0x3564U, 0x3664U, 0x3764U,
13519 	0x3864U, 0x3964U, 0x6164U, 0x6264U, 0x6364U, 0x6464U, 0x6564U, 0x6664U,
13520 	0x3065U, 0x3165U, 0x3265U, 0x3365U, 0x3465U, 0x3565U, 0x3665U, 0x3765U,
13521 	0x3865U, 0x3965U, 0x6165U, 0x6265U, 0x6365U, 0x6465U, 0x6565U, 0x6665U,
13522 	0x3066U, 0x3166U, 0x3266U, 0x3366U, 0x3466U, 0x3566U, 0x3666U, 0x3766U,
13523 	0x3866U, 0x3966U, 0x6166U, 0x6266U, 0x6366U, 0x6466U, 0x6566U, 0x6666U
13524 #endif  /* DUK_USE_INTEGER_BE */
13525 };
13526 #endif  /* DUK_USE_HEX_FASTPATH */
13527 
13528 /*
13529  *  Arbitrary byteswap for potentially unaligned values
13530  *
13531  *  Used to byteswap pointers e.g. in debugger code.
13532  */
13533 
13534 #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)13535 DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) {
13536 	duk_uint8_t tmp;
13537 	duk_uint8_t *q = p + len - 1;
13538 
13539 	while (p - q < 0) {
13540 		tmp = *p;
13541 		*p = *q;
13542 		*q = tmp;
13543 		p++;
13544 		q--;
13545 	}
13546 }
13547 #endif
13548 #line 1 "duk_hobject_class.c"
13549 /*
13550  *  Hobject ECMAScript [[Class]].
13551  */
13552 
13553 /* #include duk_internal.h -> already included */
13554 
13555 #if (DUK_STRIDX_UC_ARGUMENTS > 255)
13556 #error constant too large
13557 #endif
13558 #if (DUK_STRIDX_UC_ARRAY > 255)
13559 #error constant too large
13560 #endif
13561 #if (DUK_STRIDX_UC_BOOLEAN > 255)
13562 #error constant too large
13563 #endif
13564 #if (DUK_STRIDX_UC_DATE > 255)
13565 #error constant too large
13566 #endif
13567 #if (DUK_STRIDX_UC_ERROR > 255)
13568 #error constant too large
13569 #endif
13570 #if (DUK_STRIDX_UC_FUNCTION > 255)
13571 #error constant too large
13572 #endif
13573 #if (DUK_STRIDX_JSON > 255)
13574 #error constant too large
13575 #endif
13576 #if (DUK_STRIDX_MATH > 255)
13577 #error constant too large
13578 #endif
13579 #if (DUK_STRIDX_UC_NUMBER > 255)
13580 #error constant too large
13581 #endif
13582 #if (DUK_STRIDX_UC_OBJECT > 255)
13583 #error constant too large
13584 #endif
13585 #if (DUK_STRIDX_REG_EXP > 255)
13586 #error constant too large
13587 #endif
13588 #if (DUK_STRIDX_UC_STRING > 255)
13589 #error constant too large
13590 #endif
13591 #if (DUK_STRIDX_GLOBAL > 255)
13592 #error constant too large
13593 #endif
13594 #if (DUK_STRIDX_OBJ_ENV > 255)
13595 #error constant too large
13596 #endif
13597 #if (DUK_STRIDX_DEC_ENV > 255)
13598 #error constant too large
13599 #endif
13600 #if (DUK_STRIDX_UC_POINTER > 255)
13601 #error constant too large
13602 #endif
13603 #if (DUK_STRIDX_UC_THREAD > 255)
13604 #error constant too large
13605 #endif
13606 #if (DUK_STRIDX_ARRAY_BUFFER > 255)
13607 #error constant too large
13608 #endif
13609 #if (DUK_STRIDX_DATA_VIEW > 255)
13610 #error constant too large
13611 #endif
13612 #if (DUK_STRIDX_INT8_ARRAY > 255)
13613 #error constant too large
13614 #endif
13615 #if (DUK_STRIDX_UINT8_ARRAY > 255)
13616 #error constant too large
13617 #endif
13618 #if (DUK_STRIDX_UINT8_CLAMPED_ARRAY > 255)
13619 #error constant too large
13620 #endif
13621 #if (DUK_STRIDX_INT16_ARRAY > 255)
13622 #error constant too large
13623 #endif
13624 #if (DUK_STRIDX_UINT16_ARRAY > 255)
13625 #error constant too large
13626 #endif
13627 #if (DUK_STRIDX_INT32_ARRAY > 255)
13628 #error constant too large
13629 #endif
13630 #if (DUK_STRIDX_UINT32_ARRAY > 255)
13631 #error constant too large
13632 #endif
13633 #if (DUK_STRIDX_FLOAT32_ARRAY > 255)
13634 #error constant too large
13635 #endif
13636 #if (DUK_STRIDX_FLOAT64_ARRAY > 255)
13637 #error constant too large
13638 #endif
13639 #if (DUK_STRIDX_EMPTY_STRING > 255)
13640 #error constant too large
13641 #endif
13642 
13643 /* Note: assumes that these string indexes are 8-bit, genstrings.py must ensure that */
13644 DUK_INTERNAL duk_uint8_t duk_class_number_to_stridx[32] = {
13645 	DUK_STRIDX_EMPTY_STRING,  /* NONE, intentionally empty */
13646 	DUK_STRIDX_UC_OBJECT,
13647 	DUK_STRIDX_UC_ARRAY,
13648 	DUK_STRIDX_UC_FUNCTION,
13649 	DUK_STRIDX_UC_ARGUMENTS,
13650 	DUK_STRIDX_UC_BOOLEAN,
13651 	DUK_STRIDX_UC_DATE,
13652 	DUK_STRIDX_UC_ERROR,
13653 	DUK_STRIDX_JSON,
13654 	DUK_STRIDX_MATH,
13655 	DUK_STRIDX_UC_NUMBER,
13656 	DUK_STRIDX_REG_EXP,
13657 	DUK_STRIDX_UC_STRING,
13658 	DUK_STRIDX_GLOBAL,
13659 	DUK_STRIDX_UC_SYMBOL,
13660 	DUK_STRIDX_OBJ_ENV,
13661 	DUK_STRIDX_DEC_ENV,
13662 	DUK_STRIDX_UC_POINTER,
13663 	DUK_STRIDX_UC_THREAD,
13664 	DUK_STRIDX_ARRAY_BUFFER,
13665 	DUK_STRIDX_DATA_VIEW,
13666 	DUK_STRIDX_INT8_ARRAY,
13667 	DUK_STRIDX_UINT8_ARRAY,
13668 	DUK_STRIDX_UINT8_CLAMPED_ARRAY,
13669 	DUK_STRIDX_INT16_ARRAY,
13670 	DUK_STRIDX_UINT16_ARRAY,
13671 	DUK_STRIDX_INT32_ARRAY,
13672 	DUK_STRIDX_UINT32_ARRAY,
13673 	DUK_STRIDX_FLOAT32_ARRAY,
13674 	DUK_STRIDX_FLOAT64_ARRAY,
13675 	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
13676 	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
13677 };
13678 #line 1 "duk_alloc_default.c"
13679 /*
13680  *  Default allocation functions.
13681  *
13682  *  Assumes behavior such as malloc allowing zero size, yielding
13683  *  a NULL or a unique pointer which is a no-op for free.
13684  */
13685 
13686 /* #include duk_internal.h -> already included */
13687 
13688 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
duk_default_alloc_function(void * udata,duk_size_t size)13689 DUK_INTERNAL void *duk_default_alloc_function(void *udata, duk_size_t size) {
13690 	void *res;
13691 	DUK_UNREF(udata);
13692 	res = DUK_ANSI_MALLOC(size);
13693 	DUK_DDD(DUK_DDDPRINT("default alloc function: %lu -> %p",
13694 	                     (unsigned long) size, (void *) res));
13695 	return res;
13696 }
13697 
duk_default_realloc_function(void * udata,void * ptr,duk_size_t newsize)13698 DUK_INTERNAL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize) {
13699 	void *res;
13700 	DUK_UNREF(udata);
13701 	res = DUK_ANSI_REALLOC(ptr, newsize);
13702 	DUK_DDD(DUK_DDDPRINT("default realloc function: %p %lu -> %p",
13703 	                     (void *) ptr, (unsigned long) newsize, (void *) res));
13704 	return res;
13705 }
13706 
duk_default_free_function(void * udata,void * ptr)13707 DUK_INTERNAL void duk_default_free_function(void *udata, void *ptr) {
13708 	DUK_DDD(DUK_DDDPRINT("default free function: %p", (void *) ptr));
13709 	DUK_UNREF(udata);
13710 	DUK_ANSI_FREE(ptr);
13711 }
13712 #endif  /* DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS */
13713 #line 1 "duk_api_buffer.c"
13714 /*
13715  *  Buffer
13716  */
13717 
13718 /* #include duk_internal.h -> already included */
13719 
duk_resize_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t new_size)13720 DUK_EXTERNAL void *duk_resize_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t new_size) {
13721 	duk_hbuffer_dynamic *h;
13722 
13723 	DUK_ASSERT_API_ENTRY(thr);
13724 
13725 	h = (duk_hbuffer_dynamic *) duk_require_hbuffer(thr, idx);
13726 	DUK_ASSERT(h != NULL);
13727 
13728 	if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
13729 		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
13730 		DUK_WO_NORETURN(return NULL;);
13731 	}
13732 
13733 	/* Maximum size check is handled by callee. */
13734 	duk_hbuffer_resize(thr, h, new_size);
13735 
13736 	return DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
13737 }
13738 
duk_steal_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)13739 DUK_EXTERNAL void *duk_steal_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
13740 	duk_hbuffer_dynamic *h;
13741 	void *ptr;
13742 	duk_size_t sz;
13743 
13744 	DUK_ASSERT_API_ENTRY(thr);
13745 
13746 	h = (duk_hbuffer_dynamic *) duk_require_hbuffer(thr, idx);
13747 	DUK_ASSERT(h != NULL);
13748 
13749 	if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
13750 		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
13751 		DUK_WO_NORETURN(return NULL;);
13752 	}
13753 
13754 	/* Forget the previous allocation, setting size to 0 and alloc to
13755 	 * NULL.  Caller is responsible for freeing the previous allocation.
13756 	 * Getting the allocation and clearing it is done in the same API
13757 	 * call to avoid any chance of a realloc.
13758 	 */
13759 	ptr = DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
13760 	sz = DUK_HBUFFER_DYNAMIC_GET_SIZE(h);
13761 	if (out_size) {
13762 		*out_size = sz;
13763 	}
13764 	DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(thr->heap, h);
13765 	DUK_HBUFFER_DYNAMIC_SET_SIZE(h, 0);
13766 
13767 	return ptr;
13768 }
13769 
duk_config_buffer(duk_hthread * thr,duk_idx_t idx,void * ptr,duk_size_t len)13770 DUK_EXTERNAL void duk_config_buffer(duk_hthread *thr, duk_idx_t idx, void *ptr, duk_size_t len) {
13771 	duk_hbuffer_external *h;
13772 
13773 	DUK_ASSERT_API_ENTRY(thr);
13774 
13775 	h = (duk_hbuffer_external *) duk_require_hbuffer(thr, idx);
13776 	DUK_ASSERT(h != NULL);
13777 
13778 	if (!DUK_HBUFFER_HAS_EXTERNAL(h)) {
13779 		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
13780 		DUK_WO_NORETURN(return;);
13781 	}
13782 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h));
13783 
13784 	DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(thr->heap, h, ptr);
13785 	DUK_HBUFFER_EXTERNAL_SET_SIZE(h, len);
13786 }
13787 #line 1 "duk_api_bytecode.c"
13788 /*
13789  *  Bytecode dump/load
13790  *
13791  *  The bytecode load primitive is more important performance-wise than the
13792  *  dump primitive.
13793  *
13794  *  Unlike most Duktape API calls, bytecode dump/load is not guaranteed to be
13795  *  memory safe for invalid arguments - caller beware!  There's little point
13796  *  in trying to achieve memory safety unless bytecode instructions are also
13797  *  validated which is not easy to do with indirect register references etc.
13798  */
13799 
13800 /* #include duk_internal.h -> already included */
13801 
13802 #if defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
13803 
13804 #define DUK__SER_MARKER  0xbf
13805 #define DUK__SER_STRING  0x00
13806 #define DUK__SER_NUMBER  0x01
13807 #define DUK__BYTECODE_INITIAL_ALLOC 256
13808 #define DUK__NO_FORMALS  0xffffffffUL
13809 
13810 /*
13811  *  Dump/load helpers, xxx_raw() helpers do no buffer checks
13812  */
13813 
duk__load_string_raw(duk_hthread * thr,const duk_uint8_t * p)13814 DUK_LOCAL const duk_uint8_t *duk__load_string_raw(duk_hthread *thr, const duk_uint8_t *p) {
13815 	duk_uint32_t len;
13816 
13817 	len = DUK_RAW_READINC_U32_BE(p);
13818 	duk_push_lstring(thr, (const char *) p, len);
13819 	p += len;
13820 	return p;
13821 }
13822 
duk__load_buffer_raw(duk_hthread * thr,const duk_uint8_t * p)13823 DUK_LOCAL const duk_uint8_t *duk__load_buffer_raw(duk_hthread *thr, const duk_uint8_t *p) {
13824 	duk_uint32_t len;
13825 	duk_uint8_t *buf;
13826 
13827 	len = DUK_RAW_READINC_U32_BE(p);
13828 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len);
13829 	DUK_ASSERT(buf != NULL);
13830 	duk_memcpy((void *) buf, (const void *) p, (size_t) len);
13831 	p += len;
13832 	return p;
13833 }
13834 
duk__dump_hstring_raw(duk_uint8_t * p,duk_hstring * h)13835 DUK_LOCAL duk_uint8_t *duk__dump_hstring_raw(duk_uint8_t *p, duk_hstring *h) {
13836 	duk_size_t len;
13837 	duk_uint32_t tmp32;
13838 
13839 	DUK_ASSERT(h != NULL);
13840 
13841 	len = DUK_HSTRING_GET_BYTELEN(h);
13842 	DUK_ASSERT(len <= 0xffffffffUL);  /* string limits */
13843 	tmp32 = (duk_uint32_t) len;
13844 	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
13845 	duk_memcpy((void *) p,
13846 	           (const void *) DUK_HSTRING_GET_DATA(h),
13847 	           len);
13848 	p += len;
13849 	return p;
13850 }
13851 
duk__dump_hbuffer_raw(duk_hthread * thr,duk_uint8_t * p,duk_hbuffer * h)13852 DUK_LOCAL duk_uint8_t *duk__dump_hbuffer_raw(duk_hthread *thr, duk_uint8_t *p, duk_hbuffer *h) {
13853 	duk_size_t len;
13854 	duk_uint32_t tmp32;
13855 
13856 	DUK_ASSERT(thr != NULL);
13857 	DUK_ASSERT(h != NULL);
13858 	DUK_UNREF(thr);
13859 
13860 	len = DUK_HBUFFER_GET_SIZE(h);
13861 	DUK_ASSERT(len <= 0xffffffffUL);  /* buffer limits */
13862 	tmp32 = (duk_uint32_t) len;
13863 	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
13864 	/* When len == 0, buffer data pointer may be NULL. */
13865 	duk_memcpy_unsafe((void *) p,
13866 	                  (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h),
13867 	                  len);
13868 	p += len;
13869 	return p;
13870 }
13871 
duk__dump_string_prop(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func,duk_small_uint_t stridx)13872 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) {
13873 	duk_hstring *h_str;
13874 	duk_tval *tv;
13875 
13876 	tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
13877 	if (tv != NULL && DUK_TVAL_IS_STRING(tv)) {
13878 		h_str = DUK_TVAL_GET_STRING(tv);
13879 		DUK_ASSERT(h_str != NULL);
13880 	} else {
13881 		h_str = DUK_HTHREAD_STRING_EMPTY_STRING(thr);
13882 		DUK_ASSERT(h_str != NULL);
13883 	}
13884 	DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13885 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(h_str), p);
13886 	p = duk__dump_hstring_raw(p, h_str);
13887 	return p;
13888 }
13889 
duk__dump_buffer_prop(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func,duk_small_uint_t stridx)13890 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) {
13891 	duk_tval *tv;
13892 
13893 	tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
13894 	if (tv != NULL && DUK_TVAL_IS_BUFFER(tv)) {
13895 		duk_hbuffer *h_buf;
13896 		h_buf = DUK_TVAL_GET_BUFFER(tv);
13897 		DUK_ASSERT(h_buf != NULL);
13898 		DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13899 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HBUFFER_GET_SIZE(h_buf), p);
13900 		p = duk__dump_hbuffer_raw(thr, p, h_buf);
13901 	} else {
13902 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13903 		DUK_RAW_WRITEINC_U32_BE(p, 0);
13904 	}
13905 	return p;
13906 }
13907 
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)13908 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) {
13909 	duk_tval *tv;
13910 	duk_uint32_t val;
13911 
13912 	tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
13913 	if (tv != NULL && DUK_TVAL_IS_NUMBER(tv)) {
13914 		val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv);
13915 	} else {
13916 		val = def_value;
13917 	}
13918 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13919 	DUK_RAW_WRITEINC_U32_BE(p, val);
13920 	return p;
13921 }
13922 
duk__dump_varmap(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func)13923 DUK_LOCAL duk_uint8_t *duk__dump_varmap(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
13924 	duk_hobject *h;
13925 
13926 	h = duk_hobject_get_varmap(thr, (duk_hobject *) func);
13927 	if (h != NULL) {
13928 		duk_uint_fast32_t i;
13929 
13930 		/* We know _Varmap only has own properties so walk property
13931 		 * table directly.  We also know _Varmap is dense and all
13932 		 * values are numbers; assert for these.  GC and finalizers
13933 		 * shouldn't affect _Varmap so side effects should be fine.
13934 		 */
13935 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
13936 			duk_hstring *key;
13937 			duk_tval *tv_val;
13938 			duk_uint32_t val;
13939 
13940 			key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i);
13941 			DUK_ASSERT(key != NULL);  /* _Varmap is dense */
13942 			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h, i));
13943 			tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, i);
13944 			DUK_ASSERT(tv_val != NULL);
13945 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_val));  /* known to be number; in fact an integer */
13946 #if defined(DUK_USE_FASTINT)
13947 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_val));
13948 			DUK_ASSERT(DUK_TVAL_GET_FASTINT(tv_val) == (duk_int64_t) DUK_TVAL_GET_FASTINT_U32(tv_val));  /* known to be 32-bit */
13949 			val = DUK_TVAL_GET_FASTINT_U32(tv_val);
13950 #else
13951 			val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv_val);
13952 #endif
13953 
13954 			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13955 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(key) + 4U, p);
13956 			p = duk__dump_hstring_raw(p, key);
13957 			DUK_RAW_WRITEINC_U32_BE(p, val);
13958 		}
13959 	}
13960 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13961 	DUK_RAW_WRITEINC_U32_BE(p, 0);  /* end of _Varmap */
13962 	return p;
13963 }
13964 
duk__dump_formals(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func)13965 DUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
13966 	duk_harray *h;
13967 
13968 	h = duk_hobject_get_formals(thr, (duk_hobject *) func);
13969 	if (h != NULL) {
13970 		duk_uint32_t i;
13971 
13972 		/* Here we rely on _Formals being a dense array containing
13973 		 * strings.  This should be the case unless _Formals has been
13974 		 * tweaked by the application (which we don't support right
13975 		 * now).
13976 		 */
13977 
13978 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13979 		DUK_ASSERT(h->length != DUK__NO_FORMALS);  /* limits */
13980 		DUK_RAW_WRITEINC_U32_BE(p, h->length);
13981 
13982 		for (i = 0; i < h->length; i++) {
13983 			duk_tval *tv_val;
13984 			duk_hstring *varname;
13985 
13986 			tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, (duk_hobject *) h, i);
13987 			DUK_ASSERT(tv_val != NULL);
13988 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv_val));
13989 
13990 			varname = DUK_TVAL_GET_STRING(tv_val);
13991 			DUK_ASSERT(varname != NULL);
13992 			DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(varname) >= 1);
13993 
13994 			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13995 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(varname), p);
13996 			p = duk__dump_hstring_raw(p, varname);
13997 		}
13998 	} else {
13999 		DUK_DD(DUK_DDPRINT("dumping function without _Formals, emit marker to indicate missing _Formals"));
14000 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
14001 		DUK_RAW_WRITEINC_U32_BE(p, DUK__NO_FORMALS);  /* marker: no formals */
14002 	}
14003 	return p;
14004 }
14005 
duk__dump_func(duk_hthread * thr,duk_hcompfunc * func,duk_bufwriter_ctx * bw_ctx,duk_uint8_t * p)14006 static duk_uint8_t *duk__dump_func(duk_hthread *thr, duk_hcompfunc *func, duk_bufwriter_ctx *bw_ctx, duk_uint8_t *p) {
14007 	duk_tval *tv, *tv_end;
14008 	duk_instr_t *ins, *ins_end;
14009 	duk_hobject **fn, **fn_end;
14010 	duk_hstring *h_str;
14011 	duk_uint32_t count_instr;
14012 	duk_uint32_t tmp32;
14013 	duk_uint16_t tmp16;
14014 	duk_double_t d;
14015 
14016 	DUK_DD(DUK_DDPRINT("dumping function %p to %p: "
14017 	                   "consts=[%p,%p[ (%ld bytes, %ld items), "
14018 	                   "funcs=[%p,%p[ (%ld bytes, %ld items), "
14019 	                   "code=[%p,%p[ (%ld bytes, %ld items)",
14020 	                   (void *) func,
14021 	                   (void *) p,
14022 	                   (void *) DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, func),
14023 	                   (void *) DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, func),
14024 	                   (long) DUK_HCOMPFUNC_GET_CONSTS_SIZE(thr->heap, func),
14025 	                   (long) DUK_HCOMPFUNC_GET_CONSTS_COUNT(thr->heap, func),
14026 	                   (void *) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, func),
14027 	                   (void *) DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, func),
14028 	                   (long) DUK_HCOMPFUNC_GET_FUNCS_SIZE(thr->heap, func),
14029 	                   (long) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, func),
14030 	                   (void *) DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, func),
14031 	                   (void *) DUK_HCOMPFUNC_GET_CODE_END(thr->heap, func),
14032 	                   (long) DUK_HCOMPFUNC_GET_CODE_SIZE(thr->heap, func),
14033 	                   (long) DUK_HCOMPFUNC_GET_CODE_COUNT(thr->heap, func)));
14034 
14035 	DUK_ASSERT(DUK_USE_ESBC_MAX_BYTES <= 0x7fffffffUL);  /* ensures no overflow */
14036 	count_instr = (duk_uint32_t) DUK_HCOMPFUNC_GET_CODE_COUNT(thr->heap, func);
14037 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 3U * 4U + 2U * 2U + 3U * 4U + count_instr * 4U, p);
14038 
14039 	/* Fixed header info. */
14040 	tmp32 = count_instr;
14041 	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
14042 	tmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_CONSTS_COUNT(thr->heap, func);
14043 	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
14044 	tmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, func);
14045 	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
14046 	tmp16 = func->nregs;
14047 	DUK_RAW_WRITEINC_U16_BE(p, tmp16);
14048 	tmp16 = func->nargs;
14049 	DUK_RAW_WRITEINC_U16_BE(p, tmp16);
14050 #if defined(DUK_USE_DEBUGGER_SUPPORT)
14051 	tmp32 = func->start_line;
14052 	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
14053 	tmp32 = func->end_line;
14054 	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
14055 #else
14056 	DUK_RAW_WRITEINC_U32_BE(p, 0);
14057 	DUK_RAW_WRITEINC_U32_BE(p, 0);
14058 #endif
14059 	tmp32 = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) func);  /* masks flags, only duk_hobject flags */
14060 	tmp32 &= ~(DUK_HOBJECT_FLAG_HAVE_FINALIZER);  /* finalizer flag is lost */
14061 	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
14062 
14063 	/* Bytecode instructions: endian conversion needed unless
14064 	 * platform is big endian.
14065 	 */
14066 	ins = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, func);
14067 	ins_end = DUK_HCOMPFUNC_GET_CODE_END(thr->heap, func);
14068 	DUK_ASSERT((duk_size_t) (ins_end - ins) == (duk_size_t) count_instr);
14069 #if defined(DUK_USE_INTEGER_BE)
14070 	duk_memcpy_unsafe((void *) p, (const void *) ins, (size_t) (ins_end - ins));
14071 	p += (size_t) (ins_end - ins);
14072 #else
14073 	while (ins != ins_end) {
14074 		tmp32 = (duk_uint32_t) (*ins);
14075 		DUK_RAW_WRITEINC_U32_BE(p, tmp32);
14076 		ins++;
14077 	}
14078 #endif
14079 
14080 	/* Constants: variable size encoding. */
14081 	tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, func);
14082 	tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, func);
14083 	while (tv != tv_end) {
14084 		/* constants are strings or numbers now */
14085 		DUK_ASSERT(DUK_TVAL_IS_STRING(tv) ||
14086 		           DUK_TVAL_IS_NUMBER(tv));
14087 
14088 		if (DUK_TVAL_IS_STRING(tv)) {
14089 			h_str = DUK_TVAL_GET_STRING(tv);
14090 			DUK_ASSERT(h_str != NULL);
14091 			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
14092 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 4U + DUK_HSTRING_GET_BYTELEN(h_str), p);
14093 			*p++ = DUK__SER_STRING;
14094 			p = duk__dump_hstring_raw(p, h_str);
14095 		} else {
14096 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
14097 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 8U, p);
14098 			*p++ = DUK__SER_NUMBER;
14099 			d = DUK_TVAL_GET_NUMBER(tv);
14100 			DUK_RAW_WRITEINC_DOUBLE_BE(p, d);
14101 		}
14102 		tv++;
14103 	}
14104 
14105 	/* Inner functions recursively. */
14106 	fn = (duk_hobject **) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, func);
14107 	fn_end = (duk_hobject **) DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, func);
14108 	while (fn != fn_end) {
14109 		/* XXX: This causes recursion up to inner function depth
14110 		 * which is normally not an issue, e.g. mark-and-sweep uses
14111 		 * a recursion limiter to avoid C stack issues.  Avoiding
14112 		 * this would mean some sort of a work list or just refusing
14113 		 * to serialize deep functions.
14114 		 */
14115 		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(*fn));
14116 		p = duk__dump_func(thr, (duk_hcompfunc *) *fn, bw_ctx, p);
14117 		fn++;
14118 	}
14119 
14120 	/* Lexenv and varenv are not dumped. */
14121 
14122 	/* Object extra properties.
14123 	 *
14124 	 * There are some difference between function templates and functions.
14125 	 * For example, function templates don't have .length and nargs is
14126 	 * normally used to instantiate the functions.
14127 	 */
14128 
14129 	p = duk__dump_uint32_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_LENGTH, (duk_uint32_t) func->nargs);
14130 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
14131 	p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_NAME);
14132 #endif
14133 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
14134 	p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_FILE_NAME);
14135 #endif
14136 #if defined(DUK_USE_PC2LINE)
14137 	p = duk__dump_buffer_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_INT_PC2LINE);
14138 #endif
14139 	p = duk__dump_varmap(thr, p, bw_ctx, (duk_hobject *) func);
14140 	p = duk__dump_formals(thr, p, bw_ctx, (duk_hobject *) func);
14141 
14142 	DUK_DD(DUK_DDPRINT("serialized function %p -> final pointer %p", (void *) func, (void *) p));
14143 
14144 	return p;
14145 }
14146 
14147 /* Load a function from bytecode.  The function object returned here must
14148  * match what is created by duk_js_push_closure() with respect to its flags,
14149  * properties, etc.
14150  *
14151  * NOTE: there are intentionally no input buffer length / bound checks.
14152  * Adding them would be easy but wouldn't ensure memory safety as untrusted
14153  * or broken bytecode is unsafe during execution unless the opcodes themselves
14154  * are validated (which is quite complex, especially for indirect opcodes).
14155  */
14156 
14157 #define DUK__ASSERT_LEFT(n) do { \
14158 		DUK_ASSERT((duk_size_t) (p_end - p) >= (duk_size_t) (n)); \
14159 	} while (0)
14160 
duk__load_func(duk_hthread * thr,const duk_uint8_t * p,const duk_uint8_t * p_end)14161 static const duk_uint8_t *duk__load_func(duk_hthread *thr, const duk_uint8_t *p, const duk_uint8_t *p_end) {
14162 	duk_hcompfunc *h_fun;
14163 	duk_hbuffer *h_data;
14164 	duk_size_t data_size;
14165 	duk_uint32_t count_instr, count_const, count_funcs;
14166 	duk_uint32_t n;
14167 	duk_uint32_t tmp32;
14168 	duk_small_uint_t const_type;
14169 	duk_uint8_t *fun_data;
14170 	duk_uint8_t *q;
14171 	duk_idx_t idx_base;
14172 	duk_tval *tv1;
14173 	duk_uarridx_t arr_idx;
14174 	duk_uarridx_t arr_limit;
14175 	duk_hobject *func_env;
14176 	duk_bool_t need_pop;
14177 
14178 	/* XXX: There's some overlap with duk_js_closure() here, but
14179 	 * seems difficult to share code.  Ensure that the final function
14180 	 * looks the same as created by duk_js_closure().
14181 	 */
14182 
14183 	DUK_ASSERT(thr != NULL);
14184 
14185 	DUK_DD(DUK_DDPRINT("loading function, p=%p, p_end=%p", (const void *) p, (const void *) p_end));
14186 
14187 	DUK__ASSERT_LEFT(3 * 4);
14188 	count_instr = DUK_RAW_READINC_U32_BE(p);
14189 	count_const = DUK_RAW_READINC_U32_BE(p);
14190 	count_funcs = DUK_RAW_READINC_U32_BE(p);
14191 
14192 	data_size = sizeof(duk_tval) * count_const +
14193 	            sizeof(duk_hobject *) * count_funcs +
14194 	            sizeof(duk_instr_t) * count_instr;
14195 
14196 	DUK_DD(DUK_DDPRINT("instr=%ld, const=%ld, funcs=%ld, data_size=%ld",
14197 	                   (long) count_instr, (long) count_const,
14198 	                   (long) count_const, (long) data_size));
14199 
14200 	/* Value stack is used to ensure reachability of constants and
14201 	 * inner functions being loaded.  Require enough space to handle
14202 	 * large functions correctly.
14203 	 */
14204 	duk_require_stack(thr, (duk_idx_t) (2 + count_const + count_funcs));
14205 	idx_base = duk_get_top(thr);
14206 
14207 	/* Push function object, init flags etc.  This must match
14208 	 * duk_js_push_closure() quite carefully.
14209 	 */
14210 	h_fun = duk_push_hcompfunc(thr);
14211 	DUK_ASSERT(h_fun != NULL);
14212 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) h_fun));
14213 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, h_fun) == NULL);
14214 	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, h_fun) == NULL);
14215 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, h_fun) == NULL);
14216 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_fun) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
14217 
14218 	h_fun->nregs = DUK_RAW_READINC_U16_BE(p);
14219 	h_fun->nargs = DUK_RAW_READINC_U16_BE(p);
14220 #if defined(DUK_USE_DEBUGGER_SUPPORT)
14221 	h_fun->start_line = DUK_RAW_READINC_U32_BE(p);
14222 	h_fun->end_line = DUK_RAW_READINC_U32_BE(p);
14223 #else
14224 	p += 8;  /* skip line info */
14225 #endif
14226 
14227 	/* duk_hcompfunc flags; quite version specific */
14228 	tmp32 = DUK_RAW_READINC_U32_BE(p);
14229 	DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) h_fun, tmp32);  /* masks flags to only change duk_hobject flags */
14230 
14231 	/* standard prototype (no need to set here, already set) */
14232 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_fun) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
14233 #if 0
14234 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &h_fun->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
14235 #endif
14236 
14237 	/* assert just a few critical flags */
14238 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h_fun) == DUK_HTYPE_OBJECT);
14239 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&h_fun->obj));
14240 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(&h_fun->obj));
14241 	DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(&h_fun->obj));
14242 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(&h_fun->obj));
14243 	DUK_ASSERT(!DUK_HOBJECT_IS_PROXY(&h_fun->obj));
14244 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&h_fun->obj));
14245 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&h_fun->obj));
14246 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&h_fun->obj));
14247 
14248 	/* Create function 'data' buffer but don't attach it yet. */
14249 	fun_data = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, data_size);
14250 	DUK_ASSERT(fun_data != NULL);
14251 
14252 	/* Load bytecode instructions. */
14253 	DUK_ASSERT(sizeof(duk_instr_t) == 4);
14254 	DUK__ASSERT_LEFT(count_instr * sizeof(duk_instr_t));
14255 #if defined(DUK_USE_INTEGER_BE)
14256 	q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
14257 	duk_memcpy((void *) q,
14258 	           (const void *) p,
14259 	           sizeof(duk_instr_t) * count_instr);
14260 	p += sizeof(duk_instr_t) * count_instr;
14261 #else
14262 	q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
14263 	for (n = count_instr; n > 0; n--) {
14264 		*((duk_instr_t *) (void *) q) = DUK_RAW_READINC_U32_BE(p);
14265 		q += sizeof(duk_instr_t);
14266 	}
14267 #endif
14268 
14269 	/* Load constants onto value stack but don't yet copy to buffer. */
14270 	for (n = count_const; n > 0; n--) {
14271 		DUK__ASSERT_LEFT(1);
14272 		const_type = DUK_RAW_READINC_U8(p);
14273 		switch (const_type) {
14274 		case DUK__SER_STRING: {
14275 			p = duk__load_string_raw(thr, p);
14276 			break;
14277 		}
14278 		case DUK__SER_NUMBER: {
14279 			/* Important to do a fastint check so that constants are
14280 			 * properly read back as fastints.
14281 			 */
14282 			duk_tval tv_tmp;
14283 			duk_double_t val;
14284 			DUK__ASSERT_LEFT(8);
14285 			val = DUK_RAW_READINC_DOUBLE_BE(p);
14286 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(&tv_tmp, val);
14287 			duk_push_tval(thr, &tv_tmp);
14288 			break;
14289 		}
14290 		default: {
14291 			goto format_error;
14292 		}
14293 		}
14294 	}
14295 
14296 	/* Load inner functions to value stack, but don't yet copy to buffer. */
14297 	for (n = count_funcs; n > 0; n--) {
14298 		p = duk__load_func(thr, p, p_end);
14299 		if (p == NULL) {
14300 			goto format_error;
14301 		}
14302 	}
14303 
14304 	/* With constants and inner functions on value stack, we can now
14305 	 * atomically finish the function 'data' buffer, bump refcounts,
14306 	 * etc.
14307 	 *
14308 	 * Here we take advantage of the value stack being just a duk_tval
14309 	 * array: we can just memcpy() the constants as long as we incref
14310 	 * them afterwards.
14311 	 */
14312 
14313 	h_data = (duk_hbuffer *) duk_known_hbuffer(thr, idx_base + 1);
14314 	DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC(h_data));
14315 	DUK_HCOMPFUNC_SET_DATA(thr->heap, h_fun, h_data);
14316 	DUK_HBUFFER_INCREF(thr, h_data);
14317 
14318 	tv1 = duk_get_tval(thr, idx_base + 2);  /* may be NULL if no constants or inner funcs */
14319 	DUK_ASSERT((count_const == 0 && count_funcs == 0) || tv1 != NULL);
14320 
14321 	q = fun_data;
14322 	duk_memcpy_unsafe((void *) q, (const void *) tv1, sizeof(duk_tval) * count_const);
14323 	for (n = count_const; n > 0; n--) {
14324 		DUK_TVAL_INCREF_FAST(thr, (duk_tval *) (void *) q);  /* no side effects */
14325 		q += sizeof(duk_tval);
14326 	}
14327 	tv1 += count_const;
14328 
14329 	DUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_fun, (duk_hobject **) (void *) q);
14330 	for (n = count_funcs; n > 0; n--) {
14331 		duk_hobject *h_obj;
14332 
14333 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
14334 		h_obj = DUK_TVAL_GET_OBJECT(tv1);
14335 		DUK_ASSERT(h_obj != NULL);
14336 		tv1++;
14337 		DUK_HOBJECT_INCREF(thr, h_obj);
14338 
14339 		*((duk_hobject **) (void *) q) = h_obj;
14340 		q += sizeof(duk_hobject *);
14341 	}
14342 
14343 	DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, h_fun, (duk_instr_t *) (void *) q);
14344 
14345 	/* The function object is now reachable and refcounts are fine,
14346 	 * so we can pop off all the temporaries.
14347 	 */
14348 	DUK_DDD(DUK_DDDPRINT("function is reachable, reset top; func: %!iT", duk_get_tval(thr, idx_base)));
14349 	duk_set_top(thr, idx_base + 1);
14350 
14351 	/* Setup function properties. */
14352 	tmp32 = DUK_RAW_READINC_U32_BE(p);
14353 	duk_push_u32(thr, tmp32);
14354 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
14355 
14356 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
14357 	p = duk__load_string_raw(thr, p);  /* -> [ func funcname ] */
14358 	func_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
14359 	DUK_ASSERT(func_env != NULL);
14360 	need_pop = 0;
14361 	if (DUK_HOBJECT_HAS_NAMEBINDING((duk_hobject *) h_fun)) {
14362 		/* Original function instance/template had NAMEBINDING.
14363 		 * Must create a lexical environment on loading to allow
14364 		 * recursive functions like 'function foo() { foo(); }'.
14365 		 */
14366 		duk_hdecenv *new_env;
14367 
14368 		new_env = duk_hdecenv_alloc(thr,
14369 		                            DUK_HOBJECT_FLAG_EXTENSIBLE |
14370 		                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
14371 		DUK_ASSERT(new_env != NULL);
14372 		DUK_ASSERT(new_env->thread == NULL);  /* Closed. */
14373 		DUK_ASSERT(new_env->varmap == NULL);
14374 		DUK_ASSERT(new_env->regbase_byteoff == 0);
14375 		DUK_HDECENV_ASSERT_VALID(new_env);
14376 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
14377 		DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, func_env);
14378 		DUK_HOBJECT_INCREF(thr, func_env);
14379 
14380 		func_env = (duk_hobject *) new_env;
14381 
14382 		duk_push_hobject(thr, (duk_hobject *) new_env);
14383 
14384 		duk_dup_m2(thr);                                  /* -> [ func funcname env funcname ] */
14385 		duk_dup(thr, idx_base);                           /* -> [ func funcname env funcname func ] */
14386 		duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_NONE);  /* -> [ func funcname env ] */
14387 
14388 		need_pop = 1;  /* Need to pop env, but -after- updating h_fun and increfs. */
14389 	}
14390 	DUK_ASSERT(func_env != NULL);
14391 	DUK_HCOMPFUNC_SET_LEXENV(thr->heap, h_fun, func_env);
14392 	DUK_HCOMPFUNC_SET_VARENV(thr->heap, h_fun, func_env);
14393 	DUK_HOBJECT_INCREF(thr, func_env);
14394 	DUK_HOBJECT_INCREF(thr, func_env);
14395 	if (need_pop) {
14396 		duk_pop(thr);
14397 	}
14398 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
14399 #endif  /* DUK_USE_FUNC_NAME_PROPERTY */
14400 
14401 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
14402 	p = duk__load_string_raw(thr, p);
14403 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C);
14404 #endif  /* DUK_USE_FUNC_FILENAME_PROPERTY */
14405 
14406 	if (DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_fun)) {
14407 		/* Restore empty external .prototype only for constructable
14408 		 * functions.  The prototype object should inherit from
14409 		 * Object.prototype.
14410 		 */
14411 		duk_push_object(thr);
14412 		DUK_ASSERT(!duk_is_bare_object(thr, -1));
14413 		duk_dup_m2(thr);
14414 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);  /* func.prototype.constructor = func */
14415 		duk_compact_m1(thr);
14416 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);
14417 	}
14418 
14419 #if defined(DUK_USE_PC2LINE)
14420 	p = duk__load_buffer_raw(thr, p);
14421 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_WC);
14422 #endif  /* DUK_USE_PC2LINE */
14423 
14424 	duk_push_bare_object(thr);  /* _Varmap */
14425 	for (;;) {
14426 		/* XXX: awkward */
14427 		p = duk__load_string_raw(thr, p);
14428 		if (duk_get_length(thr, -1) == 0) {
14429 			duk_pop(thr);
14430 			break;
14431 		}
14432 		tmp32 = DUK_RAW_READINC_U32_BE(p);
14433 		duk_push_u32(thr, tmp32);
14434 		duk_put_prop(thr, -3);
14435 	}
14436 	duk_compact_m1(thr);
14437 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);
14438 
14439 	/* _Formals may have been missing in the original function, which is
14440 	 * handled using a marker length.
14441 	 */
14442 	arr_limit = DUK_RAW_READINC_U32_BE(p);
14443 	if (arr_limit != DUK__NO_FORMALS) {
14444 		duk_push_bare_array(thr);  /* _Formals */
14445 		for (arr_idx = 0; arr_idx < arr_limit; arr_idx++) {
14446 			p = duk__load_string_raw(thr, p);
14447 			duk_put_prop_index(thr, -2, arr_idx);
14448 		}
14449 		duk_compact_m1(thr);
14450 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);
14451 	} else {
14452 		DUK_DD(DUK_DDPRINT("no _Formals in dumped function"));
14453 	}
14454 
14455 	/* Return with final function pushed on stack top. */
14456 	DUK_DD(DUK_DDPRINT("final loaded function: %!iT", duk_get_tval(thr, -1)));
14457 	DUK_ASSERT_TOP(thr, idx_base + 1);
14458 	return p;
14459 
14460  format_error:
14461 	return NULL;
14462 }
14463 
duk_dump_function(duk_hthread * thr)14464 DUK_EXTERNAL void duk_dump_function(duk_hthread *thr) {
14465 	duk_hcompfunc *func;
14466 	duk_bufwriter_ctx bw_ctx_alloc;
14467 	duk_bufwriter_ctx *bw_ctx = &bw_ctx_alloc;
14468 	duk_uint8_t *p;
14469 
14470 	DUK_ASSERT_API_ENTRY(thr);
14471 
14472 	/* Bound functions don't have all properties so we'd either need to
14473 	 * lookup the non-bound target function or reject bound functions.
14474 	 * For now, bound functions are rejected with TypeError.
14475 	 */
14476 	func = duk_require_hcompfunc(thr, -1);
14477 	DUK_ASSERT(func != NULL);
14478 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&func->obj));
14479 
14480 	/* Estimating the result size beforehand would be costly, so
14481 	 * start with a reasonable size and extend as needed.
14482 	 */
14483 	DUK_BW_INIT_PUSHBUF(thr, bw_ctx, DUK__BYTECODE_INITIAL_ALLOC);
14484 	p = DUK_BW_GET_PTR(thr, bw_ctx);
14485 	*p++ = DUK__SER_MARKER;
14486 	p = duk__dump_func(thr, func, bw_ctx, p);
14487 	DUK_BW_SET_PTR(thr, bw_ctx, p);
14488 	DUK_BW_COMPACT(thr, bw_ctx);
14489 
14490 	DUK_DD(DUK_DDPRINT("serialized result: %!T", duk_get_tval(thr, -1)));
14491 
14492 	duk_remove_m2(thr);  /* [ ... func buf ] -> [ ... buf ] */
14493 }
14494 
duk_load_function(duk_hthread * thr)14495 DUK_EXTERNAL void duk_load_function(duk_hthread *thr) {
14496 	const duk_uint8_t *p_buf, *p, *p_end;
14497 	duk_size_t sz;
14498 
14499 	DUK_ASSERT_API_ENTRY(thr);
14500 
14501 	p_buf = (duk_uint8_t *) duk_require_buffer(thr, -1, &sz);
14502 	DUK_ASSERT(p_buf != NULL);
14503 
14504 	/* The caller is responsible for being sure that bytecode being loaded
14505 	 * is valid and trusted.  Invalid bytecode can cause memory unsafe
14506 	 * behavior directly during loading or later during bytecode execution
14507 	 * (instruction validation would be quite complex to implement).
14508 	 *
14509 	 * This signature check is the only sanity check for detecting
14510 	 * accidental invalid inputs.  The initial byte ensures no ordinary
14511 	 * string or Symbol will be accepted by accident.
14512 	 */
14513 	p = p_buf;
14514 	p_end = p_buf + sz;
14515 	if (sz < 1 || p[0] != DUK__SER_MARKER) {
14516 		goto format_error;
14517 	}
14518 	p++;
14519 
14520 	p = duk__load_func(thr, p, p_end);
14521 	if (p == NULL) {
14522 		goto format_error;
14523 	}
14524 
14525 	duk_remove_m2(thr);  /* [ ... buf func ] -> [ ... func ] */
14526 	return;
14527 
14528  format_error:
14529 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BYTECODE);
14530 	DUK_WO_NORETURN(return;);
14531 }
14532 
14533 #else  /* DUK_USE_BYTECODE_DUMP_SUPPORT */
14534 
duk_dump_function(duk_hthread * thr)14535 DUK_EXTERNAL void duk_dump_function(duk_hthread *thr) {
14536 	DUK_ASSERT_API_ENTRY(thr);
14537 	DUK_ERROR_UNSUPPORTED(thr);
14538 	DUK_WO_NORETURN(return;);
14539 }
14540 
duk_load_function(duk_hthread * thr)14541 DUK_EXTERNAL void duk_load_function(duk_hthread *thr) {
14542 	DUK_ASSERT_API_ENTRY(thr);
14543 	DUK_ERROR_UNSUPPORTED(thr);
14544 	DUK_WO_NORETURN(return;);
14545 }
14546 
14547 #endif  /* DUK_USE_BYTECODE_DUMP_SUPPORT */
14548 
14549 /* automatic undefs */
14550 #undef DUK__ASSERT_LEFT
14551 #undef DUK__BYTECODE_INITIAL_ALLOC
14552 #undef DUK__NO_FORMALS
14553 #undef DUK__SER_MARKER
14554 #undef DUK__SER_NUMBER
14555 #undef DUK__SER_STRING
14556 #line 1 "duk_api_call.c"
14557 /*
14558  *  Calls.
14559  *
14560  *  Protected variants should avoid ever throwing an error.  Must be careful
14561  *  to catch errors related to value stack manipulation and property lookup,
14562  *  not just the call itself.
14563  *
14564  *  The only exception is when arguments are insane, e.g. nargs/nrets are out
14565  *  of bounds; in such cases an error is thrown for two reasons.  First, we
14566  *  can't always respect the value stack input/output guarantees in such cases
14567  *  so the caller would end up with the value stack in an unexpected state.
14568  *  Second, an attempt to create an error might itself fail (although this
14569  *  could be avoided by pushing a preallocated object/string or a primitive
14570  *  value).
14571  */
14572 
14573 /* #include duk_internal.h -> already included */
14574 
14575 /*
14576  *  Helpers
14577  */
14578 
14579 struct duk__pcall_prop_args {
14580 	duk_idx_t obj_idx;
14581 	duk_idx_t nargs;
14582 	duk_small_uint_t call_flags;
14583 };
14584 typedef struct duk__pcall_prop_args duk__pcall_prop_args;
14585 
14586 struct duk__pcall_method_args {
14587 	duk_idx_t nargs;
14588 	duk_small_uint_t call_flags;
14589 };
14590 typedef struct duk__pcall_method_args duk__pcall_method_args;
14591 
14592 struct duk__pcall_args {
14593 	duk_idx_t nargs;
14594 	duk_small_uint_t call_flags;
14595 };
14596 typedef struct duk__pcall_args duk__pcall_args;
14597 
14598 /* Compute and validate idx_func for a certain 'nargs' and 'other'
14599  * parameter count (1 or 2, depending on whether 'this' binding is
14600  * present).
14601  */
duk__call_get_idx_func(duk_hthread * thr,duk_idx_t nargs,duk_idx_t other)14602 DUK_LOCAL duk_idx_t duk__call_get_idx_func(duk_hthread *thr, duk_idx_t nargs, duk_idx_t other) {
14603 	duk_idx_t idx_func;
14604 
14605 	/* XXX: byte arithmetic? */
14606 
14607 	DUK_ASSERT(other >= 0);
14608 
14609 	idx_func = duk_get_top(thr) - nargs - other;
14610 	if (DUK_UNLIKELY((idx_func | nargs) < 0)) {  /* idx_func < 0 || nargs < 0; OR sign bits */
14611 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14612 		DUK_WO_NORETURN(return 0;);
14613 	}
14614 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14615 	return idx_func;
14616 }
14617 
14618 /* Compute idx_func, assume index will be valid.  This is a valid assumption
14619  * for protected calls: nargs < 0 is checked explicitly and duk_safe_call()
14620  * validates the argument count.
14621  */
duk__call_get_idx_func_unvalidated(duk_hthread * thr,duk_idx_t nargs,duk_idx_t other)14622 DUK_LOCAL duk_idx_t duk__call_get_idx_func_unvalidated(duk_hthread *thr, duk_idx_t nargs, duk_idx_t other) {
14623 	duk_idx_t idx_func;
14624 
14625 	/* XXX: byte arithmetic? */
14626 
14627 	DUK_ASSERT(nargs >= 0);
14628 	DUK_ASSERT(other >= 0);
14629 
14630 	idx_func = duk_get_top(thr) - nargs - other;
14631 	DUK_ASSERT(idx_func >= 0);
14632 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14633 	return idx_func;
14634 }
14635 
14636 /* Prepare value stack for a method call through an object property.
14637  * May currently throw an error e.g. when getting the property.
14638  */
duk__call_prop_prep_stack(duk_hthread * thr,duk_idx_t normalized_obj_idx,duk_idx_t nargs)14639 DUK_LOCAL void duk__call_prop_prep_stack(duk_hthread *thr, duk_idx_t normalized_obj_idx, duk_idx_t nargs) {
14640 	DUK_CTX_ASSERT_VALID(thr);
14641 	DUK_ASSERT(nargs >= 0);
14642 
14643 	DUK_DDD(DUK_DDDPRINT("duk__call_prop_prep_stack, normalized_obj_idx=%ld, nargs=%ld, stacktop=%ld",
14644 	                     (long) normalized_obj_idx, (long) nargs, (long) duk_get_top(thr)));
14645 
14646 	/* [... key arg1 ... argN] */
14647 
14648 	/* duplicate key */
14649 	duk_dup(thr, -nargs - 1);  /* Note: -nargs alone would fail for nargs == 0, this is OK */
14650 	(void) duk_get_prop(thr, normalized_obj_idx);
14651 
14652 	DUK_DDD(DUK_DDDPRINT("func: %!T", (duk_tval *) duk_get_tval(thr, -1)));
14653 
14654 #if defined(DUK_USE_VERBOSE_ERRORS)
14655 	if (DUK_UNLIKELY(!duk_is_callable(thr, -1))) {
14656 		duk_tval *tv_base;
14657 		duk_tval *tv_key;
14658 
14659 		/* tv_targ is passed on stack top (at index -1). */
14660 		tv_base = DUK_GET_TVAL_POSIDX(thr, normalized_obj_idx);
14661 		tv_key = DUK_GET_TVAL_NEGIDX(thr, -nargs - 2);
14662 		DUK_ASSERT(tv_base >= thr->valstack_bottom && tv_base < thr->valstack_top);
14663 		DUK_ASSERT(tv_key >= thr->valstack_bottom && tv_key < thr->valstack_top);
14664 
14665 		duk_call_setup_propcall_error(thr, tv_base, tv_key);
14666 	}
14667 #endif
14668 
14669 	/* [... key arg1 ... argN func] */
14670 
14671 	duk_replace(thr, -nargs - 2);
14672 
14673 	/* [... func arg1 ... argN] */
14674 
14675 	duk_dup(thr, normalized_obj_idx);
14676 	duk_insert(thr, -nargs - 1);
14677 
14678 	/* [... func this arg1 ... argN] */
14679 }
14680 
duk_call(duk_hthread * thr,duk_idx_t nargs)14681 DUK_EXTERNAL void duk_call(duk_hthread *thr, duk_idx_t nargs) {
14682 	duk_small_uint_t call_flags;
14683 	duk_idx_t idx_func;
14684 
14685 	DUK_ASSERT_API_ENTRY(thr);
14686 
14687 	idx_func = duk__call_get_idx_func(thr, nargs, 1);
14688 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14689 
14690 	duk_insert_undefined(thr, idx_func + 1);
14691 
14692 	call_flags = 0;  /* not protected, respect reclimit, not constructor */
14693 	duk_handle_call_unprotected(thr, idx_func, call_flags);
14694 }
14695 
duk_call_method(duk_hthread * thr,duk_idx_t nargs)14696 DUK_EXTERNAL void duk_call_method(duk_hthread *thr, duk_idx_t nargs) {
14697 	duk_small_uint_t call_flags;
14698 	duk_idx_t idx_func;
14699 
14700 	DUK_ASSERT_API_ENTRY(thr);
14701 
14702 	idx_func = duk__call_get_idx_func(thr, nargs, 2);
14703 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14704 
14705 	call_flags = 0;  /* not protected, respect reclimit, not constructor */
14706 	duk_handle_call_unprotected(thr, idx_func, call_flags);
14707 }
14708 
duk_call_prop(duk_hthread * thr,duk_idx_t obj_idx,duk_idx_t nargs)14709 DUK_EXTERNAL void duk_call_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t nargs) {
14710 	/*
14711 	 *  XXX: if duk_handle_call() took values through indices, this could be
14712 	 *  made much more sensible.  However, duk_handle_call() needs to fudge
14713 	 *  the 'this' and 'func' values to handle bound functions, which is now
14714 	 *  done "in-place", so this is not a trivial change.
14715 	 */
14716 
14717 	DUK_ASSERT_API_ENTRY(thr);
14718 
14719 	obj_idx = duk_require_normalize_index(thr, obj_idx);  /* make absolute */
14720 	if (DUK_UNLIKELY(nargs < 0)) {
14721 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14722 		DUK_WO_NORETURN(return;);
14723 	}
14724 
14725 	duk__call_prop_prep_stack(thr, obj_idx, nargs);
14726 
14727 	duk_call_method(thr, nargs);
14728 }
14729 
duk__pcall_raw(duk_hthread * thr,void * udata)14730 DUK_LOCAL duk_ret_t duk__pcall_raw(duk_hthread *thr, void *udata) {
14731 	duk__pcall_args *args;
14732 	duk_idx_t idx_func;
14733 	duk_int_t ret;
14734 
14735 	DUK_CTX_ASSERT_VALID(thr);
14736 	DUK_ASSERT(udata != NULL);
14737 
14738 	args = (duk__pcall_args *) udata;
14739 	idx_func = duk__call_get_idx_func_unvalidated(thr, args->nargs, 1);
14740 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14741 
14742 	duk_insert_undefined(thr, idx_func + 1);
14743 
14744 	ret = duk_handle_call_unprotected(thr, idx_func, args->call_flags);
14745 	DUK_ASSERT(ret == 0);
14746 	DUK_UNREF(ret);
14747 
14748 	return 1;
14749 }
14750 
duk_pcall(duk_hthread * thr,duk_idx_t nargs)14751 DUK_EXTERNAL duk_int_t duk_pcall(duk_hthread *thr, duk_idx_t nargs) {
14752 	duk__pcall_args args;
14753 
14754 	DUK_ASSERT_API_ENTRY(thr);
14755 
14756 	args.nargs = nargs;
14757 	if (DUK_UNLIKELY(nargs < 0)) {
14758 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14759 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14760 	}
14761 	args.call_flags = 0;
14762 
14763 	return duk_safe_call(thr, duk__pcall_raw, (void *) &args /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
14764 }
14765 
duk__pcall_method_raw(duk_hthread * thr,void * udata)14766 DUK_LOCAL duk_ret_t duk__pcall_method_raw(duk_hthread *thr, void *udata) {
14767 	duk__pcall_method_args *args;
14768 	duk_idx_t idx_func;
14769 	duk_int_t ret;
14770 
14771 	DUK_CTX_ASSERT_VALID(thr);
14772 	DUK_ASSERT(udata != NULL);
14773 
14774 	args = (duk__pcall_method_args *) udata;
14775 
14776 	idx_func = duk__call_get_idx_func_unvalidated(thr, args->nargs, 2);
14777 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14778 
14779 	ret = duk_handle_call_unprotected(thr, idx_func, args->call_flags);
14780 	DUK_ASSERT(ret == 0);
14781 	DUK_UNREF(ret);
14782 
14783 	return 1;
14784 }
14785 
duk_pcall_method_flags(duk_hthread * thr,duk_idx_t nargs,duk_small_uint_t call_flags)14786 DUK_INTERNAL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags) {
14787 	duk__pcall_method_args args;
14788 
14789 	DUK_ASSERT_API_ENTRY(thr);
14790 
14791 	args.nargs = nargs;
14792 	if (DUK_UNLIKELY(nargs < 0)) {
14793 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14794 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14795 	}
14796 	args.call_flags = call_flags;
14797 
14798 	return duk_safe_call(thr, duk__pcall_method_raw, (void *) &args /*udata*/, nargs + 2 /*nargs*/, 1 /*nrets*/);
14799 }
14800 
duk_pcall_method(duk_hthread * thr,duk_idx_t nargs)14801 DUK_EXTERNAL duk_int_t duk_pcall_method(duk_hthread *thr, duk_idx_t nargs) {
14802 	DUK_ASSERT_API_ENTRY(thr);
14803 
14804 	return duk_pcall_method_flags(thr, nargs, 0);
14805 }
14806 
duk__pcall_prop_raw(duk_hthread * thr,void * udata)14807 DUK_LOCAL duk_ret_t duk__pcall_prop_raw(duk_hthread *thr, void *udata) {
14808 	duk__pcall_prop_args *args;
14809 	duk_idx_t obj_idx;
14810 	duk_int_t ret;
14811 
14812 	DUK_CTX_ASSERT_VALID(thr);
14813 	DUK_ASSERT(udata != NULL);
14814 
14815 	args = (duk__pcall_prop_args *) udata;
14816 
14817 	obj_idx = duk_require_normalize_index(thr, args->obj_idx);  /* make absolute */
14818 	duk__call_prop_prep_stack(thr, obj_idx, args->nargs);
14819 
14820 	ret = duk_handle_call_unprotected_nargs(thr, args->nargs, args->call_flags);
14821 	DUK_ASSERT(ret == 0);
14822 	DUK_UNREF(ret);
14823 	return 1;
14824 }
14825 
duk_pcall_prop(duk_hthread * thr,duk_idx_t obj_idx,duk_idx_t nargs)14826 DUK_EXTERNAL duk_int_t duk_pcall_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t nargs) {
14827 	duk__pcall_prop_args args;
14828 
14829 	DUK_ASSERT_API_ENTRY(thr);
14830 
14831 	args.obj_idx = obj_idx;
14832 	args.nargs = nargs;
14833 	if (DUK_UNLIKELY(nargs < 0)) {
14834 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14835 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14836 	}
14837 	args.call_flags = 0;
14838 
14839 	return duk_safe_call(thr, duk__pcall_prop_raw, (void *) &args /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
14840 }
14841 
duk_safe_call(duk_hthread * thr,duk_safe_call_function func,void * udata,duk_idx_t nargs,duk_idx_t nrets)14842 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) {
14843 	duk_int_t rc;
14844 
14845 	DUK_ASSERT_API_ENTRY(thr);
14846 
14847 	/* nargs condition; fail if: top - bottom < nargs
14848 	 *                      <=>  top < bottom + nargs
14849 	 * nrets condition; fail if: end - (top - nargs) < nrets
14850 	 *                      <=>  end - top + nargs < nrets
14851 	 *                      <=>  end + nargs < top + nrets
14852 	 */
14853 	/* XXX: check for any reserve? */
14854 
14855 	if (DUK_UNLIKELY((nargs | nrets) < 0 ||  /* nargs < 0 || nrets < 0; OR sign bits */
14856 	                 thr->valstack_top < thr->valstack_bottom + nargs ||        /* nargs too large compared to top */
14857 	                 thr->valstack_end + nargs < thr->valstack_top + nrets)) {  /* nrets too large compared to reserve */
14858 		DUK_D(DUK_DPRINT("not enough stack reserve for safe call or invalid arguments: "
14859 		                 "nargs=%ld < 0 (?), nrets=%ld < 0 (?), top=%ld < bottom=%ld + nargs=%ld (?), "
14860 		                 "end=%ld + nargs=%ld < top=%ld + nrets=%ld (?)",
14861 		                  (long) nargs,
14862 		                  (long) nrets,
14863 		                  (long) (thr->valstack_top - thr->valstack),
14864 		                  (long) (thr->valstack_bottom - thr->valstack),
14865 		                  (long) nargs,
14866 		                  (long) (thr->valstack_end - thr->valstack),
14867 		                  (long) nargs,
14868 		                  (long) (thr->valstack_top - thr->valstack),
14869 		                  (long) nrets));
14870 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14871 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14872 	}
14873 
14874 	rc = duk_handle_safe_call(thr,           /* thread */
14875 	                          func,          /* func */
14876 	                          udata,         /* udata */
14877 	                          nargs,         /* num_stack_args */
14878 	                          nrets);        /* num_stack_res */
14879 
14880 	return rc;
14881 }
14882 
duk_new(duk_hthread * thr,duk_idx_t nargs)14883 DUK_EXTERNAL void duk_new(duk_hthread *thr, duk_idx_t nargs) {
14884 	duk_idx_t idx_func;
14885 
14886 	DUK_ASSERT_API_ENTRY(thr);
14887 
14888 	idx_func = duk__call_get_idx_func(thr, nargs, 1);
14889 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14890 
14891 	duk_push_object(thr);  /* default instance; internal proto updated by call handling */
14892 	duk_insert(thr, idx_func + 1);
14893 
14894 	duk_handle_call_unprotected(thr, idx_func, DUK_CALL_FLAG_CONSTRUCT);
14895 }
14896 
duk__pnew_helper(duk_hthread * thr,void * udata)14897 DUK_LOCAL duk_ret_t duk__pnew_helper(duk_hthread *thr, void *udata) {
14898 	duk_idx_t nargs;
14899 
14900 	DUK_ASSERT(udata != NULL);
14901 	nargs = *((duk_idx_t *) udata);
14902 
14903 	duk_new(thr, nargs);
14904 	return 1;
14905 }
14906 
duk_pnew(duk_hthread * thr,duk_idx_t nargs)14907 DUK_EXTERNAL duk_int_t duk_pnew(duk_hthread *thr, duk_idx_t nargs) {
14908 	duk_int_t rc;
14909 
14910 	DUK_ASSERT_API_ENTRY(thr);
14911 
14912 	/* For now, just use duk_safe_call() to wrap duk_new().  We can't
14913 	 * simply use a protected duk_handle_call() because pushing the
14914 	 * default instance might throw.
14915 	 */
14916 
14917 	if (DUK_UNLIKELY(nargs < 0)) {
14918 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14919 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14920 	}
14921 
14922 	rc = duk_safe_call(thr, duk__pnew_helper, (void *) &nargs /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
14923 	return rc;
14924 }
14925 
duk_is_constructor_call(duk_hthread * thr)14926 DUK_EXTERNAL duk_bool_t duk_is_constructor_call(duk_hthread *thr) {
14927 	duk_activation *act;
14928 
14929 	DUK_ASSERT_API_ENTRY(thr);
14930 
14931 	act = thr->callstack_curr;
14932 	if (act != NULL) {
14933 		return ((act->flags & DUK_ACT_FLAG_CONSTRUCT) != 0 ? 1 : 0);
14934 	}
14935 	return 0;
14936 }
14937 
duk_require_constructor_call(duk_hthread * thr)14938 DUK_EXTERNAL void duk_require_constructor_call(duk_hthread *thr) {
14939 	DUK_ASSERT_API_ENTRY(thr);
14940 
14941 	if (!duk_is_constructor_call(thr)) {
14942 		DUK_ERROR_TYPE(thr, DUK_STR_CONSTRUCT_ONLY);
14943 		DUK_WO_NORETURN(return;);
14944 	}
14945 }
14946 
duk_is_strict_call(duk_hthread * thr)14947 DUK_EXTERNAL duk_bool_t duk_is_strict_call(duk_hthread *thr) {
14948 	duk_activation *act;
14949 
14950 	/* For user code this could just return 1 (strict) always
14951 	 * because all Duktape/C functions are considered strict,
14952 	 * and strict is also the default when nothing is running.
14953 	 * However, Duktape may call this function internally when
14954 	 * the current activation is an ECMAScript function, so
14955 	 * this cannot be replaced by a 'return 1' without fixing
14956 	 * the internal call sites.
14957 	 */
14958 
14959 	DUK_ASSERT_API_ENTRY(thr);
14960 
14961 	act = thr->callstack_curr;
14962 	if (act != NULL) {
14963 		return ((act->flags & DUK_ACT_FLAG_STRICT) != 0 ? 1 : 0);
14964 	} else {
14965 		/* Strict by default. */
14966 		return 1;
14967 	}
14968 }
14969 
14970 /*
14971  *  Duktape/C function magic
14972  */
14973 
duk_get_current_magic(duk_hthread * thr)14974 DUK_EXTERNAL duk_int_t duk_get_current_magic(duk_hthread *thr) {
14975 	duk_activation *act;
14976 	duk_hobject *func;
14977 
14978 	DUK_ASSERT_API_ENTRY(thr);
14979 
14980 	act = thr->callstack_curr;
14981 	if (act) {
14982 		func = DUK_ACT_GET_FUNC(act);
14983 		if (!func) {
14984 			duk_tval *tv = &act->tv_func;
14985 			duk_small_uint_t lf_flags;
14986 			lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
14987 			return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
14988 		}
14989 		DUK_ASSERT(func != NULL);
14990 
14991 		if (DUK_HOBJECT_IS_NATFUNC(func)) {
14992 			duk_hnatfunc *nf = (duk_hnatfunc *) func;
14993 			return (duk_int_t) nf->magic;
14994 		}
14995 	}
14996 	return 0;
14997 }
14998 
duk_get_magic(duk_hthread * thr,duk_idx_t idx)14999 DUK_EXTERNAL duk_int_t duk_get_magic(duk_hthread *thr, duk_idx_t idx) {
15000 	duk_tval *tv;
15001 	duk_hobject *h;
15002 
15003 	DUK_ASSERT_API_ENTRY(thr);
15004 
15005 	tv = duk_require_tval(thr, idx);
15006 	if (DUK_TVAL_IS_OBJECT(tv)) {
15007 		h = DUK_TVAL_GET_OBJECT(tv);
15008 		DUK_ASSERT(h != NULL);
15009 		if (!DUK_HOBJECT_HAS_NATFUNC(h)) {
15010 			goto type_error;
15011 		}
15012 		return (duk_int_t) ((duk_hnatfunc *) h)->magic;
15013 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
15014 		duk_small_uint_t lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
15015 		return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
15016 	}
15017 
15018 	/* fall through */
15019  type_error:
15020 	DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);
15021 	DUK_WO_NORETURN(return 0;);
15022 }
15023 
duk_set_magic(duk_hthread * thr,duk_idx_t idx,duk_int_t magic)15024 DUK_EXTERNAL void duk_set_magic(duk_hthread *thr, duk_idx_t idx, duk_int_t magic) {
15025 	duk_hnatfunc *nf;
15026 
15027 	DUK_ASSERT_API_ENTRY(thr);
15028 
15029 	nf = duk_require_hnatfunc(thr, idx);
15030 	DUK_ASSERT(nf != NULL);
15031 	nf->magic = (duk_int16_t) magic;
15032 }
15033 
15034 /*
15035  *  Misc helpers
15036  */
15037 
15038 /* Resolve a bound function on value stack top to a non-bound target
15039  * (leave other values as is).
15040  */
duk_resolve_nonbound_function(duk_hthread * thr)15041 DUK_INTERNAL void duk_resolve_nonbound_function(duk_hthread *thr) {
15042 	duk_tval *tv;
15043 
15044 	DUK_HTHREAD_ASSERT_VALID(thr);
15045 
15046 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
15047 	if (DUK_TVAL_IS_OBJECT(tv)) {
15048 		duk_hobject *h;
15049 
15050 		h = DUK_TVAL_GET_OBJECT(tv);
15051 		DUK_ASSERT(h != NULL);
15052 		if (DUK_HOBJECT_HAS_BOUNDFUNC(h)) {
15053 			duk_push_tval(thr, &((duk_hboundfunc *) (void *) h)->target);
15054 			duk_replace(thr, -2);
15055 #if 0
15056 			DUK_TVAL_SET_TVAL(tv, &((duk_hboundfunc *) h)->target);
15057 			DUK_TVAL_INCREF(thr, tv);
15058 			DUK_HOBJECT_DECREF_NORZ(thr, h);
15059 #endif
15060 			/* Rely on Function.prototype.bind() on never creating a bound
15061 			 * function whose target is not proper.  This is now safe
15062 			 * because the target is not even an internal property but a
15063 			 * struct member.
15064 			 */
15065 			DUK_ASSERT(duk_is_lightfunc(thr, -1) || duk_is_callable(thr, -1));
15066 		}
15067 	}
15068 
15069 	/* Lightfuncs cannot be bound but are always callable and
15070 	 * constructable.
15071 	 */
15072 }
15073 #line 1 "duk_api_codec.c"
15074 /*
15075  *  Encoding and decoding basic formats: hex, base64.
15076  *
15077  *  These are in-place operations which may allow an optimized implementation.
15078  *
15079  *  Base-64: https://tools.ietf.org/html/rfc4648#section-4
15080  */
15081 
15082 /* #include duk_internal.h -> already included */
15083 
15084 /*
15085  *  Misc helpers
15086  */
15087 
15088 /* Shared handling for encode/decode argument.  Fast path handling for
15089  * buffer and string values because they're the most common.  In particular,
15090  * avoid creating a temporary string or buffer when possible.  Return value
15091  * is guaranteed to be non-NULL, even for zero length input.
15092  */
duk__prep_codec_arg(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)15093 DUK_LOCAL const duk_uint8_t *duk__prep_codec_arg(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
15094 	const void *def_ptr = (const void *) out_len;  /* Any non-NULL pointer will do. */
15095 	const void *ptr;
15096 	duk_bool_t isbuffer;
15097 
15098 	DUK_ASSERT(out_len != NULL);
15099 	DUK_ASSERT(def_ptr != NULL);
15100 	DUK_ASSERT(duk_is_valid_index(thr, idx));  /* checked by caller */
15101 
15102 	ptr = (const void *) duk_get_buffer_data_raw(thr, idx, out_len, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, &isbuffer);
15103 	if (isbuffer) {
15104 		DUK_ASSERT(ptr != NULL || *out_len == 0U);
15105 		if (DUK_UNLIKELY(ptr == NULL)) {
15106 			ptr = def_ptr;
15107 		}
15108 		DUK_ASSERT(ptr != NULL);
15109 	} else {
15110 		/* For strings a non-NULL pointer is always guaranteed because
15111 		 * at least a NUL will be present.
15112 		 */
15113 		ptr = (const void *) duk_to_lstring(thr, idx, out_len);
15114 		DUK_ASSERT(ptr != NULL);
15115 	}
15116 	DUK_ASSERT(ptr != NULL);
15117 	return (const duk_uint8_t *) ptr;
15118 }
15119 
15120 /*
15121  *  Base64
15122  */
15123 
15124 #if defined(DUK_USE_BASE64_SUPPORT)
15125 /* Bytes emitted for number of padding characters in range [0,4]. */
15126 DUK_LOCAL const duk_int8_t duk__base64_decode_nequal_step[5] = {
15127 	3,   /* #### -> 24 bits, emit 3 bytes */
15128 	2,   /* ###= -> 18 bits, emit 2 bytes */
15129 	1,   /* ##== -> 12 bits, emit 1 byte */
15130 	-1,  /* #=== -> 6 bits, error */
15131 	0,   /* ==== -> 0 bits, emit 0 bytes */
15132 };
15133 
15134 #if defined(DUK_USE_BASE64_FASTPATH)
15135 DUK_LOCAL const duk_uint8_t duk__base64_enctab_fast[64] = {
15136 	0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, 0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU, 0x50U,  /* A...P */
15137 	0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U, 0x58U, 0x59U, 0x5aU, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U,  /* Q...f */
15138 	0x67U, 0x68U, 0x69U, 0x6aU, 0x6bU, 0x6cU, 0x6dU, 0x6eU, 0x6fU, 0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U,  /* g...v */
15139 	0x77U, 0x78U, 0x79U, 0x7aU, 0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U, 0x38U, 0x39U, 0x2bU, 0x2fU   /* w.../ */
15140 };
15141 #endif  /* DUK_USE_BASE64_FASTPATH */
15142 
15143 #if defined(DUK_USE_BASE64_FASTPATH)
15144 /* Decode table for one byte of input:
15145  *   -1 = allowed whitespace
15146  *   -2 = padding
15147  *   -3 = error
15148  *    0...63 decoded bytes
15149  */
15150 DUK_LOCAL const duk_int8_t duk__base64_dectab_fast[256] = {
15151 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -1, -1, -3, -3, -1, -3, -3,  /* 0x00...0x0f */
15152 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0x10...0x1f */
15153 	-1, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, 62, -3, -3, -3, 63,  /* 0x20...0x2f */
15154 	52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -3, -3, -3, -2, -3, -3,  /* 0x30...0x3f */
15155 	-3,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,  /* 0x40...0x4f */
15156 	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -3, -3, -3, -3, -3,  /* 0x50...0x5f */
15157 	-3, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,  /* 0x60...0x6f */
15158 	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -3, -3, -3, -3, -3,  /* 0x70...0x7f */
15159 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0x80...0x8f */
15160 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0x90...0x9f */
15161 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xa0...0xaf */
15162 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xb0...0xbf */
15163 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xc0...0xcf */
15164 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xd0...0xdf */
15165 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xe0...0xef */
15166 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3   /* 0xf0...0xff */
15167 };
15168 #endif  /* DUK_USE_BASE64_FASTPATH */
15169 
15170 #if defined(DUK_USE_BASE64_FASTPATH)
duk__base64_encode_fast_3(const duk_uint8_t * src,duk_uint8_t * dst)15171 DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_3(const duk_uint8_t *src, duk_uint8_t *dst) {
15172 	duk_uint_t t;
15173 
15174 	t = (duk_uint_t) src[0];
15175 	t = (t << 8) + (duk_uint_t) src[1];
15176 	t = (t << 8) + (duk_uint_t) src[2];
15177 
15178 	dst[0] = duk__base64_enctab_fast[t >> 18];
15179 	dst[1] = duk__base64_enctab_fast[(t >> 12) & 0x3fU];
15180 	dst[2] = duk__base64_enctab_fast[(t >> 6) & 0x3fU];
15181 	dst[3] = duk__base64_enctab_fast[t & 0x3fU];
15182 
15183 #if 0
15184 	/* Tested: not faster on x64, most likely due to aliasing between
15185 	 * output and input index computation.
15186 	 */
15187 	/* aaaaaabb bbbbcccc ccdddddd */
15188 	dst[0] = duk__base64_enctab_fast[(src[0] >> 2) & 0x3fU];
15189 	dst[1] = duk__base64_enctab_fast[((src[0] << 4) & 0x30U) | ((src[1] >> 4) & 0x0fU)];
15190 	dst[2] = duk__base64_enctab_fast[((src[1] << 2) & 0x3fU) | ((src[2] >> 6) & 0x03U)];
15191 	dst[3] = duk__base64_enctab_fast[src[2] & 0x3fU];
15192 #endif
15193 }
15194 
duk__base64_encode_fast_2(const duk_uint8_t * src,duk_uint8_t * dst)15195 DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_2(const duk_uint8_t *src, duk_uint8_t *dst) {
15196 	duk_uint_t t;
15197 
15198 	t = (duk_uint_t) src[0];
15199 	t = (t << 8) + (duk_uint_t) src[1];
15200 	dst[0] = duk__base64_enctab_fast[t >> 10];           /* XXXXXX-- -------- */
15201 	dst[1] = duk__base64_enctab_fast[(t >> 4) & 0x3fU];  /* ------XX XXXX---- */
15202 	dst[2] = duk__base64_enctab_fast[(t << 2) & 0x3fU];  /* -------- ----XXXX */
15203 	dst[3] = DUK_ASC_EQUALS;
15204 }
15205 
duk__base64_encode_fast_1(const duk_uint8_t * src,duk_uint8_t * dst)15206 DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_1(const duk_uint8_t *src, duk_uint8_t *dst) {
15207 	duk_uint_t t;
15208 
15209 	t = (duk_uint_t) src[0];
15210 	dst[0] = duk__base64_enctab_fast[t >> 2];            /* XXXXXX-- */
15211 	dst[1] = duk__base64_enctab_fast[(t << 4) & 0x3fU];  /* ------XX */
15212 	dst[2] = DUK_ASC_EQUALS;
15213 	dst[3] = DUK_ASC_EQUALS;
15214 }
15215 
duk__base64_encode_helper(const duk_uint8_t * src,duk_size_t srclen,duk_uint8_t * dst)15216 DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
15217 	duk_size_t n;
15218 	const duk_uint8_t *p;
15219 	duk_uint8_t *q;
15220 
15221 	n = srclen;
15222 	p = src;
15223 	q = dst;
15224 
15225 	if (n >= 16U) {
15226 		/* Fast path, unrolled by 4, allows interleaving.  Process
15227 		 * 12-byte input chunks which encode to 16-char output chunks.
15228 		 * Only enter when at least one block is emitted (avoids div+mul
15229 		 * for short inputs too).
15230 		 */
15231 		const duk_uint8_t *p_end_fast;
15232 
15233 		p_end_fast = p + ((n / 12U) * 12U);
15234 		DUK_ASSERT(p_end_fast >= p + 12);
15235 		do {
15236 			duk__base64_encode_fast_3(p, q);
15237 			duk__base64_encode_fast_3(p + 3, q + 4);
15238 			duk__base64_encode_fast_3(p + 6, q + 8);
15239 			duk__base64_encode_fast_3(p + 9, q + 12);
15240 			p += 12;
15241 			q += 16;
15242 		} while (DUK_LIKELY(p != p_end_fast));
15243 
15244 		DUK_ASSERT(src + srclen >= p);
15245 		n = (duk_size_t) (src + srclen - p);
15246 		DUK_ASSERT(n < 12U);
15247 	}
15248 
15249 	/* Remainder. */
15250 	while (n >= 3U) {
15251 		duk__base64_encode_fast_3(p, q);
15252 		p += 3;
15253 		q += 4;
15254 		n -= 3U;
15255 	}
15256 	DUK_ASSERT(n == 0U || n == 1U || n == 2U);
15257 	if (n == 1U) {
15258 		duk__base64_encode_fast_1(p, q);
15259 #if 0  /* Unnecessary. */
15260 		p += 1;
15261 		q += 4;
15262 		n -= 1U;
15263 #endif
15264 	} else if (n == 2U) {
15265 		duk__base64_encode_fast_2(p, q);
15266 #if 0  /* Unnecessary. */
15267 		p += 2;
15268 		q += 4;
15269 		n -= 2U;
15270 #endif
15271 	} else {
15272 		DUK_ASSERT(n == 0U);  /* nothing to do */
15273 		;
15274 	}
15275 }
15276 #else  /* DUK_USE_BASE64_FASTPATH */
duk__base64_encode_helper(const duk_uint8_t * src,duk_size_t srclen,duk_uint8_t * dst)15277 DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
15278 	duk_small_uint_t i, npad;
15279 	duk_uint_t t, x, y;
15280 	const duk_uint8_t *p;
15281 	const duk_uint8_t *p_end;
15282 	duk_uint8_t *q;
15283 
15284 	p = src;
15285 	p_end = src + srclen;
15286 	q = dst;
15287 	npad = 0U;
15288 
15289 	while (p < p_end) {
15290 		/* Read 3 bytes into 't', padded by zero. */
15291 		t = 0;
15292 		for (i = 0; i < 3; i++) {
15293 			t = t << 8;
15294 			if (p < p_end) {
15295 				t += (duk_uint_t) (*p++);
15296 			} else {
15297 				/* This only happens on the last loop and we're
15298 				 * guaranteed to exit on the next loop.
15299 				 */
15300 				npad++;
15301 			}
15302 		}
15303 		DUK_ASSERT(npad <= 2U);
15304 
15305 		/* Emit 4 encoded characters.  If npad > 0, some of the
15306 		 * chars will be incorrect (zero bits) but we fix up the
15307 		 * padding after the loop.  A straightforward 64-byte
15308 		 * lookup would be faster and cleaner, but this is shorter.
15309 		 */
15310 		for (i = 0; i < 4; i++) {
15311 			x = ((t >> 18) & 0x3fU);
15312 			t = t << 6;
15313 
15314 			if (x <= 51U) {
15315 				if (x <= 25) {
15316 					y = x + DUK_ASC_UC_A;
15317 				} else {
15318 					y = x - 26 + DUK_ASC_LC_A;
15319 				}
15320 			} else {
15321 				if (x <= 61U) {
15322 					y = x - 52 + DUK_ASC_0;
15323 				} else if (x == 62) {
15324 					y = DUK_ASC_PLUS;
15325 				} else {
15326 					DUK_ASSERT(x == 63);
15327 					y = DUK_ASC_SLASH;
15328 				}
15329 			}
15330 
15331 			*q++ = (duk_uint8_t) y;
15332 		}
15333 	}
15334 
15335 	/* Handle padding by rewriting 0-2 bogus characters at the end.
15336 	 *
15337 	 *  Missing bytes    npad     base64 example
15338 	 *    0               0         ####
15339 	 *    1               1         ###=
15340 	 *    2               2         ##==
15341 	 */
15342 	DUK_ASSERT(npad <= 2U);
15343 	while (npad > 0U) {
15344 		*(q - npad) = DUK_ASC_EQUALS;
15345 		npad--;
15346 	}
15347 }
15348 #endif  /* DUK_USE_BASE64_FASTPATH */
15349 
15350 #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)15351 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) {
15352 	duk_int_t x;
15353 	duk_uint_t t;
15354 	duk_small_uint_t n_equal;
15355 	duk_int8_t step;
15356 	const duk_uint8_t *p;
15357 	const duk_uint8_t *p_end;
15358 	const duk_uint8_t *p_end_safe;
15359 	duk_uint8_t *q;
15360 
15361 	DUK_ASSERT(src != NULL);  /* Required by pointer arithmetic below, which fails for NULL. */
15362 
15363 	p = src;
15364 	p_end = src + srclen;
15365 	p_end_safe = p_end - 8;  /* If 'src <= src_end_safe', safe to read 8 bytes. */
15366 	q = dst;
15367 
15368 	/* Alternate between a fast path which processes clean groups with no
15369 	 * padding or whitespace, and a slow path which processes one arbitrary
15370 	 * group and then re-enters the fast path.  This handles e.g. base64
15371 	 * with newlines reasonably well because the majority of a line is in
15372 	 * the fast path.
15373 	 */
15374 	for (;;) {
15375 		/* Fast path, on each loop handle two 4-char input groups.
15376 		 * If both are clean, emit 6 bytes and continue.  If first
15377 		 * is clean, emit 3 bytes and drop out; otherwise emit
15378 		 * nothing and drop out.  This approach could be extended to
15379 		 * more groups per loop, but for inputs with e.g. periodic
15380 		 * newlines (which are common) it might not be an improvement.
15381 		 */
15382 		while (DUK_LIKELY(p <= p_end_safe)) {
15383 			duk_int_t t1, t2;
15384 
15385 			/* The lookup byte is intentionally sign extended to
15386 			 * (at least) 32 bits and then ORed.  This ensures
15387 			 * that is at least 1 byte is negative, the highest
15388 			 * bit of the accumulator will be set at the end and
15389 			 * we don't need to check every byte.
15390 			 *
15391 			 * Read all input bytes first before writing output
15392 			 * bytes to minimize aliasing.
15393 			 */
15394 			DUK_DDD(DUK_DDDPRINT("fast loop: p=%p, p_end_safe=%p, p_end=%p",
15395 			                     (const void *) p, (const void *) p_end_safe, (const void *) p_end));
15396 
15397 			t1 = (duk_int_t) duk__base64_dectab_fast[p[0]];
15398 			t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[1]];
15399 			t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[2]];
15400 			t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[3]];
15401 
15402 			t2 = (duk_int_t) duk__base64_dectab_fast[p[4]];
15403 			t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[5]];
15404 			t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[6]];
15405 			t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[7]];
15406 
15407 			q[0] = (duk_uint8_t) (((duk_uint_t) t1 >> 16) & 0xffU);
15408 			q[1] = (duk_uint8_t) (((duk_uint_t) t1 >> 8) & 0xffU);
15409 			q[2] = (duk_uint8_t) ((duk_uint_t) t1 & 0xffU);
15410 
15411 			q[3] = (duk_uint8_t) (((duk_uint_t) t2 >> 16) & 0xffU);
15412 			q[4] = (duk_uint8_t) (((duk_uint_t) t2 >> 8) & 0xffU);
15413 			q[5] = (duk_uint8_t) ((duk_uint_t) t2 & 0xffU);
15414 
15415 			/* Optimistic check using one branch. */
15416 			if (DUK_LIKELY((t1 | t2) >= 0)) {
15417 				p += 8;
15418 				q += 6;
15419 			} else if (t1 >= 0) {
15420 				DUK_DDD(DUK_DDDPRINT("fast loop first group was clean, second was not, process one slow path group"));
15421 				DUK_ASSERT(t2 < 0);
15422 				p += 4;
15423 				q += 3;
15424 				break;
15425 			} else {
15426 				DUK_DDD(DUK_DDDPRINT("fast loop first group was not clean, second does not matter, process one slow path group"));
15427 				DUK_ASSERT(t1 < 0);
15428 				break;
15429 			}
15430 		}  /* fast path */
15431 
15432 		/* Slow path step 1: try to scan a 4-character encoded group,
15433 		 * end-of-input, or start-of-padding.  We exit with:
15434 		 *   1. n_chars == 4: full group, no padding, no end-of-input.
15435 		 *   2. n_chars < 4: partial group (may also be 0), encountered
15436 		 *      padding or end of input.
15437 		 *
15438 		 * The accumulator is initialized to 1; this allows us to detect
15439 		 * a full group by comparing >= 0x1000000 without an extra
15440 		 * counter variable.
15441 		 */
15442 		t = 1UL;
15443 		for (;;) {
15444 			DUK_DDD(DUK_DDDPRINT("slow loop: p=%p, p_end=%p, t=%lu",
15445 			                     (const void *) p, (const void *) p_end, (unsigned long) t));
15446 
15447 			if (DUK_LIKELY(p < p_end)) {
15448 				x = duk__base64_dectab_fast[*p++];
15449 				if (DUK_LIKELY(x >= 0)) {
15450 					DUK_ASSERT(x >= 0 && x <= 63);
15451 					t = (t << 6) + (duk_uint_t) x;
15452 					if (t >= 0x1000000UL) {
15453 						break;
15454 					}
15455 				} else if (x == -1) {
15456 					continue;  /* allowed ascii whitespace */
15457 				} else if (x == -2) {
15458 					p--;
15459 					break;  /* start of padding */
15460 				} else {
15461 					DUK_ASSERT(x == -3);
15462 					goto decode_error;
15463 				}
15464 			} else {
15465 				break;  /* end of input */
15466 			}
15467 		}  /* slow path step 1 */
15468 
15469 		/* Complete the padding by simulating pad characters,
15470 		 * regardless of actual input padding chars.
15471 		 */
15472 		n_equal = 0;
15473 		while (t < 0x1000000UL) {
15474 			t = (t << 6) + 0U;
15475 			n_equal++;
15476 		}
15477 
15478 		/* Slow path step 2: deal with full/partial group, padding,
15479 		 * etc.  Note that for num chars in [0,3] we intentionally emit
15480 		 * 3 bytes but don't step forward that much, buffer space is
15481 		 * guaranteed in setup.
15482 		 *
15483 		 *  num chars:
15484 		 *   0      ####   no output (= step 0)
15485 		 *   1      #===   reject, 6 bits of data
15486 		 *   2      ##==   12 bits of data, output 1 byte (= step 1)
15487 		 *   3      ###=   18 bits of data, output 2 bytes (= step 2)
15488 		 *   4      ####   24 bits of data, output 3 bytes (= step 3)
15489 		 */
15490 		q[0] = (duk_uint8_t) ((t >> 16) & 0xffU);
15491 		q[1] = (duk_uint8_t) ((t >> 8) & 0xffU);
15492 		q[2] = (duk_uint8_t) (t & 0xffU);
15493 
15494 		DUK_ASSERT(n_equal <= 4);
15495 		step = duk__base64_decode_nequal_step[n_equal];
15496 		if (DUK_UNLIKELY(step < 0)) {
15497 			goto decode_error;
15498 		}
15499 		q += step;
15500 
15501 		/* Slow path step 3: read and ignore padding and whitespace
15502 		 * until (a) next non-padding and non-whitespace character
15503 		 * after which we resume the fast path, or (b) end of input.
15504 		 * This allows us to accept missing, partial, full, and extra
15505 		 * padding cases uniformly.  We also support concatenated
15506 		 * base-64 documents because we resume scanning afterwards.
15507 		 *
15508 		 * Note that to support concatenated documents well, the '='
15509 		 * padding found inside the input must also allow for 'extra'
15510 		 * padding.  For example, 'Zm===' decodes to 'f' and has one
15511 		 * extra padding char.  So, 'Zm===Zm' should decode 'ff', even
15512 		 * though the standard break-up would be 'Zm==' + '=Zm' which
15513 		 * doesn't make sense.
15514 		 *
15515 		 * We also accept prepended padding like '==Zm9', because it
15516 		 * is equivalent to an empty document with extra padding ('==')
15517 		 * followed by a valid document.
15518 		 */
15519 
15520 		for (;;) {
15521 			if (DUK_UNLIKELY(p >= p_end)) {
15522 				goto done;
15523 			}
15524 			x = duk__base64_dectab_fast[*p++];
15525 			if (x == -1 || x == -2) {
15526 				;  /* padding or whitespace, keep eating */
15527 			} else {
15528 				p--;
15529 				break;  /* backtrack and go back to fast path, even for -1 */
15530 			}
15531 		}  /* slow path step 3 */
15532 	}  /* outer fast+slow path loop */
15533 
15534  done:
15535 	DUK_DDD(DUK_DDDPRINT("done; p=%p, p_end=%p",
15536 	                     (const void *) p, (const void *) p_end));
15537 
15538 	DUK_ASSERT(p == p_end);
15539 
15540 	*out_dst_final = q;
15541 	return 1;
15542 
15543  decode_error:
15544 	return 0;
15545 }
15546 #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)15547 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) {
15548 	duk_uint_t t, x;
15549 	duk_int_t y;
15550 	duk_int8_t step;
15551 	const duk_uint8_t *p;
15552 	const duk_uint8_t *p_end;
15553 	duk_uint8_t *q;
15554 	/* 0x09, 0x0a, or 0x0d */
15555 	duk_uint32_t mask_white = (1U << 9) | (1U << 10) | (1U << 13);
15556 
15557 	/* 't' tracks progress of the decoded group:
15558 	 *
15559 	 *  t == 1             no valid chars yet
15560 	 *  t >= 0x40          1x6 = 6 bits shifted in
15561 	 *  t >= 0x1000        2x6 = 12 bits shifted in
15562 	 *  t >= 0x40000       3x6 = 18 bits shifted in
15563 	 *  t >= 0x1000000     4x6 = 24 bits shifted in
15564 	 *
15565 	 * By initializing t=1 there's no need for a separate counter for
15566 	 * the number of characters found so far.
15567 	 */
15568 	p = src;
15569 	p_end = src + srclen;
15570 	q = dst;
15571 	t = 1UL;
15572 
15573 	for (;;) {
15574 		duk_small_uint_t n_equal;
15575 
15576 		DUK_ASSERT(t >= 1U);
15577 		if (p >= p_end) {
15578 			/* End of input: if input exists, treat like
15579 			 * start of padding, finish the block, then
15580 			 * re-enter here to see we're done.
15581 			 */
15582 			if (t == 1U) {
15583 				break;
15584 			} else {
15585 				goto simulate_padding;
15586 			}
15587 		}
15588 
15589 		x = *p++;
15590 
15591 		if (x >= 0x41U) {
15592 			/* Valid: a-z and A-Z. */
15593 			DUK_ASSERT(x >= 0x41U && x <= 0xffU);
15594 			if (x >= 0x61U && x <= 0x7aU) {
15595 				y = (duk_int_t) x - 0x61 + 26;
15596 			} else if (x <= 0x5aU) {
15597 				y = (duk_int_t) x - 0x41;
15598 			} else {
15599 				goto decode_error;
15600 			}
15601 		} else if (x >= 0x30U) {
15602 			/* Valid: 0-9 and =. */
15603 			DUK_ASSERT(x >= 0x30U && x <= 0x40U);
15604 			if (x <= 0x39U) {
15605 				y = (duk_int_t) x - 0x30 + 52;
15606 			} else if (x == 0x3dU) {
15607 				/* Skip padding and whitespace unless we're in the
15608 				 * middle of a block.  Otherwise complete group by
15609 				 * simulating shifting in the correct padding.
15610 				 */
15611 				if (t == 1U) {
15612 					continue;
15613 				}
15614 				goto simulate_padding;
15615 			} else {
15616 				goto decode_error;
15617 			}
15618 		} else if (x >= 0x20U) {
15619 			/* Valid: +, /, and 0x20 whitespace. */
15620 			DUK_ASSERT(x >= 0x20U && x <= 0x2fU);
15621 			if (x == 0x2bU) {
15622 				y = 62;
15623 			} else if (x == 0x2fU) {
15624 				y = 63;
15625 			} else if (x == 0x20U) {
15626 				continue;
15627 			} else {
15628 				goto decode_error;
15629 			}
15630 		} else {
15631 			/* Valid: whitespace. */
15632 			duk_uint32_t m;
15633 			DUK_ASSERT(x < 0x20U);  /* 0x00 to 0x1f */
15634 			m = (1U << x);
15635 			if (mask_white & m) {
15636 				/* Allow basic ASCII whitespace. */
15637 				continue;
15638 			} else {
15639 				goto decode_error;
15640 			}
15641 		}
15642 
15643 		DUK_ASSERT(y >= 0 && y <= 63);
15644 		t = (t << 6) + (duk_uint_t) y;
15645 		if (t < 0x1000000UL) {
15646 			continue;
15647 		}
15648 		/* fall through; no padding will be added */
15649 
15650 	 simulate_padding:
15651 		n_equal = 0;
15652 		while (t < 0x1000000UL) {
15653 			t = (t << 6) + 0U;
15654 			n_equal++;
15655 		}
15656 
15657 		/* Output 3 bytes from 't' and advance as needed. */
15658 		q[0] = (duk_uint8_t) ((t >> 16) & 0xffU);
15659 		q[1] = (duk_uint8_t) ((t >> 8) & 0xffU);
15660 		q[2] = (duk_uint8_t) (t & 0xffU);
15661 
15662 		DUK_ASSERT(n_equal <= 4U);
15663 		step = duk__base64_decode_nequal_step[n_equal];
15664 		if (step < 0) {
15665 			goto decode_error;
15666 		}
15667 		q += step;
15668 
15669 		/* Re-enter loop.  The actual padding characters are skipped
15670 		 * by the main loop.  This handles cases like missing, partial,
15671 		 * full, and extra padding, and allows parsing of concatenated
15672 		 * documents (with extra padding) like: Zm===Zm.  Also extra
15673 		 * prepended padding is accepted: ===Zm9v.
15674 		 */
15675 		t = 1U;
15676 	}
15677 	DUK_ASSERT(t == 1UL);
15678 
15679 	*out_dst_final = q;
15680 	return 1;
15681 
15682  decode_error:
15683 	return 0;
15684 }
15685 #endif  /* DUK_USE_BASE64_FASTPATH */
15686 
duk_base64_encode(duk_hthread * thr,duk_idx_t idx)15687 DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) {
15688 	const duk_uint8_t *src;
15689 	duk_size_t srclen;
15690 	duk_size_t dstlen;
15691 	duk_uint8_t *dst;
15692 	const char *ret;
15693 
15694 	DUK_ASSERT_API_ENTRY(thr);
15695 
15696 	idx = duk_require_normalize_index(thr, idx);
15697 	src = duk__prep_codec_arg(thr, idx, &srclen);
15698 	DUK_ASSERT(src != NULL);
15699 
15700 	/* Compute exact output length.  Computation must not wrap; this
15701 	 * limit works for 32-bit size_t:
15702 	 * >>> srclen = 3221225469
15703 	 * >>> '%x' % ((srclen + 2) / 3 * 4)
15704 	 * 'fffffffc'
15705 	 */
15706 	if (srclen > 3221225469UL) {
15707 		goto type_error;
15708 	}
15709 	dstlen = (srclen + 2U) / 3U * 4U;
15710 	dst = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, dstlen);
15711 
15712 	duk__base64_encode_helper((const duk_uint8_t *) src, srclen, dst);
15713 
15714 	ret = duk_buffer_to_string(thr, -1);  /* Safe, result is ASCII. */
15715 	duk_replace(thr, idx);
15716 	return ret;
15717 
15718  type_error:
15719 	DUK_ERROR_TYPE(thr, DUK_STR_BASE64_ENCODE_FAILED);
15720 	DUK_WO_NORETURN(return NULL;);
15721 }
15722 
duk_base64_decode(duk_hthread * thr,duk_idx_t idx)15723 DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) {
15724 	const duk_uint8_t *src;
15725 	duk_size_t srclen;
15726 	duk_size_t dstlen;
15727 	duk_uint8_t *dst;
15728 	duk_uint8_t *dst_final;
15729 
15730 	DUK_ASSERT_API_ENTRY(thr);
15731 
15732 	idx = duk_require_normalize_index(thr, idx);
15733 	src = duk__prep_codec_arg(thr, idx, &srclen);
15734 	DUK_ASSERT(src != NULL);
15735 
15736 	/* Round up and add safety margin.  Avoid addition before division to
15737 	 * avoid possibility of wrapping.  Margin includes +3 for rounding up,
15738 	 * and +3 for one extra group: the decoder may emit and then backtrack
15739 	 * a full group (3 bytes) from zero-sized input for technical reasons.
15740 	 * Similarly, 'xx' may ecause 1+3 = bytes to be emitted and then
15741 	 * backtracked.
15742 	 */
15743 	dstlen = (srclen / 4) * 3 + 6;  /* upper limit, assuming no whitespace etc */
15744 	dst = (duk_uint8_t *) duk_push_dynamic_buffer(thr, dstlen);
15745 	/* Note: for dstlen=0, dst may be NULL */
15746 
15747 	if (!duk__base64_decode_helper((const duk_uint8_t *) src, srclen, dst, &dst_final)) {
15748 		goto type_error;
15749 	}
15750 
15751 	/* XXX: convert to fixed buffer? */
15752 	(void) duk_resize_buffer(thr, -1, (duk_size_t) (dst_final - dst));
15753 	duk_replace(thr, idx);
15754 	return;
15755 
15756  type_error:
15757 	DUK_ERROR_TYPE(thr, DUK_STR_BASE64_DECODE_FAILED);
15758 	DUK_WO_NORETURN(return;);
15759 }
15760 #else  /* DUK_USE_BASE64_SUPPORT */
duk_base64_encode(duk_hthread * thr,duk_idx_t idx)15761 DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) {
15762 	DUK_UNREF(idx);
15763 	DUK_ERROR_UNSUPPORTED(thr);
15764 	DUK_WO_NORETURN(return NULL;);
15765 }
15766 
duk_base64_decode(duk_hthread * thr,duk_idx_t idx)15767 DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) {
15768 	DUK_UNREF(idx);
15769 	DUK_ERROR_UNSUPPORTED(thr);
15770 	DUK_WO_NORETURN(return;);
15771 }
15772 #endif  /* DUK_USE_BASE64_SUPPORT */
15773 
15774 /*
15775  *  Hex
15776  */
15777 
15778 #if defined(DUK_USE_HEX_SUPPORT)
duk_hex_encode(duk_hthread * thr,duk_idx_t idx)15779 DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {
15780 	const duk_uint8_t *inp;
15781 	duk_size_t len;
15782 	duk_size_t i;
15783 	duk_uint8_t *buf;
15784 	const char *ret;
15785 #if defined(DUK_USE_HEX_FASTPATH)
15786 	duk_size_t len_safe;
15787 	duk_uint16_t *p16;
15788 #endif
15789 
15790 	DUK_ASSERT_API_ENTRY(thr);
15791 
15792 	idx = duk_require_normalize_index(thr, idx);
15793 	inp = duk__prep_codec_arg(thr, idx, &len);
15794 	DUK_ASSERT(inp != NULL);
15795 
15796 	/* Fixed buffer, no zeroing because we'll fill all the data. */
15797 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len * 2);
15798 	DUK_ASSERT(buf != NULL);
15799 
15800 #if defined(DUK_USE_HEX_FASTPATH)
15801 	DUK_ASSERT((((duk_size_t) buf) & 0x01U) == 0);   /* pointer is aligned, guaranteed for fixed buffer */
15802 	p16 = (duk_uint16_t *) (void *) buf;
15803 	len_safe = len & ~0x03U;
15804 	for (i = 0; i < len_safe; i += 4) {
15805 		p16[0] = duk_hex_enctab[inp[i]];
15806 		p16[1] = duk_hex_enctab[inp[i + 1]];
15807 		p16[2] = duk_hex_enctab[inp[i + 2]];
15808 		p16[3] = duk_hex_enctab[inp[i + 3]];
15809 		p16 += 4;
15810 	}
15811 	for (; i < len; i++) {
15812 		*p16++ = duk_hex_enctab[inp[i]];
15813 	}
15814 #else  /* DUK_USE_HEX_FASTPATH */
15815 	for (i = 0; i < len; i++) {
15816 		duk_small_uint_t t;
15817 		t = (duk_small_uint_t) inp[i];
15818 		buf[i*2 + 0] = duk_lc_digits[t >> 4];
15819 		buf[i*2 + 1] = duk_lc_digits[t & 0x0f];
15820 	}
15821 #endif  /* DUK_USE_HEX_FASTPATH */
15822 
15823 	/* XXX: Using a string return value forces a string intern which is
15824 	 * not always necessary.  As a rough performance measure, hex encode
15825 	 * time for tests/perf/test-hex-encode.js dropped from ~35s to ~15s
15826 	 * without string coercion.  Change to returning a buffer and let the
15827 	 * caller coerce to string if necessary?
15828 	 */
15829 
15830 	ret = duk_buffer_to_string(thr, -1);  /* Safe, result is ASCII. */
15831 	duk_replace(thr, idx);
15832 	return ret;
15833 }
15834 
duk_hex_decode(duk_hthread * thr,duk_idx_t idx)15835 DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) {
15836 	const duk_uint8_t *inp;
15837 	duk_size_t len;
15838 	duk_size_t i;
15839 	duk_int_t t;
15840 	duk_uint8_t *buf;
15841 #if defined(DUK_USE_HEX_FASTPATH)
15842 	duk_int_t chk;
15843 	duk_uint8_t *p;
15844 	duk_size_t len_safe;
15845 #endif
15846 
15847 	DUK_ASSERT_API_ENTRY(thr);
15848 
15849 	idx = duk_require_normalize_index(thr, idx);
15850 	inp = duk__prep_codec_arg(thr, idx, &len);
15851 	DUK_ASSERT(inp != NULL);
15852 
15853 	if (len & 0x01) {
15854 		goto type_error;
15855 	}
15856 
15857 	/* Fixed buffer, no zeroing because we'll fill all the data. */
15858 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len / 2);
15859 	DUK_ASSERT(buf != NULL);
15860 
15861 #if defined(DUK_USE_HEX_FASTPATH)
15862 	p = buf;
15863 	len_safe = len & ~0x07U;
15864 	for (i = 0; i < len_safe; i += 8) {
15865 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i]]) |
15866 		    ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
15867 		chk = t;
15868 		p[0] = (duk_uint8_t) t;
15869 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 2]]) |
15870 		    ((duk_int_t) duk_hex_dectab[inp[i + 3]]);
15871 		chk |= t;
15872 		p[1] = (duk_uint8_t) t;
15873 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 4]]) |
15874 		    ((duk_int_t) duk_hex_dectab[inp[i + 5]]);
15875 		chk |= t;
15876 		p[2] = (duk_uint8_t) t;
15877 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 6]]) |
15878 		    ((duk_int_t) duk_hex_dectab[inp[i + 7]]);
15879 		chk |= t;
15880 		p[3] = (duk_uint8_t) t;
15881 		p += 4;
15882 
15883 		/* Check if any lookup above had a negative result. */
15884 		if (DUK_UNLIKELY(chk < 0)) {
15885 			goto type_error;
15886 		}
15887 	}
15888 	for (; i < len; i += 2) {
15889 		/* First cast to duk_int_t to sign extend, second cast to
15890 		 * duk_uint_t to avoid signed left shift, and final cast to
15891 		 * duk_int_t result type.
15892 		 */
15893 		t = (duk_int_t) ((((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i]]) << 4U) |
15894 		                 ((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i + 1]]));
15895 		if (DUK_UNLIKELY(t < 0)) {
15896 			goto type_error;
15897 		}
15898 		*p++ = (duk_uint8_t) t;
15899 	}
15900 #else  /* DUK_USE_HEX_FASTPATH */
15901 	for (i = 0; i < len; i += 2) {
15902 		/* For invalid characters the value -1 gets extended to
15903 		 * at least 16 bits.  If either nybble is invalid, the
15904 		 * resulting 't' will be < 0.
15905 		 */
15906 		t = (duk_int_t) ((((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i]]) << 4U) |
15907 		                 ((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i + 1]]));
15908 		if (DUK_UNLIKELY(t < 0)) {
15909 			goto type_error;
15910 		}
15911 		buf[i >> 1] = (duk_uint8_t) t;
15912 	}
15913 #endif  /* DUK_USE_HEX_FASTPATH */
15914 
15915 	duk_replace(thr, idx);
15916 	return;
15917 
15918  type_error:
15919 	DUK_ERROR_TYPE(thr, DUK_STR_HEX_DECODE_FAILED);
15920 	DUK_WO_NORETURN(return;);
15921 }
15922 #else  /* DUK_USE_HEX_SUPPORT */
duk_hex_encode(duk_hthread * thr,duk_idx_t idx)15923 DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {
15924 	DUK_UNREF(idx);
15925 	DUK_ERROR_UNSUPPORTED(thr);
15926 	DUK_WO_NORETURN(return NULL;);
15927 }
duk_hex_decode(duk_hthread * thr,duk_idx_t idx)15928 DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) {
15929 	DUK_UNREF(idx);
15930 	DUK_ERROR_UNSUPPORTED(thr);
15931 	DUK_WO_NORETURN(return;);
15932 }
15933 #endif  /* DUK_USE_HEX_SUPPORT */
15934 
15935 /*
15936  *  JSON
15937  */
15938 
15939 #if defined(DUK_USE_JSON_SUPPORT)
duk_json_encode(duk_hthread * thr,duk_idx_t idx)15940 DUK_EXTERNAL const char *duk_json_encode(duk_hthread *thr, duk_idx_t idx) {
15941 #if defined(DUK_USE_ASSERTIONS)
15942 	duk_idx_t top_at_entry;
15943 #endif
15944 	const char *ret;
15945 
15946 	DUK_ASSERT_API_ENTRY(thr);
15947 #if defined(DUK_USE_ASSERTIONS)
15948 	top_at_entry = duk_get_top(thr);
15949 #endif
15950 
15951 	idx = duk_require_normalize_index(thr, idx);
15952 	duk_bi_json_stringify_helper(thr,
15953 	                             idx /*idx_value*/,
15954 	                             DUK_INVALID_INDEX /*idx_replacer*/,
15955 	                             DUK_INVALID_INDEX /*idx_space*/,
15956 	                             0 /*flags*/);
15957 	DUK_ASSERT(duk_is_string(thr, -1));
15958 	duk_replace(thr, idx);
15959 	ret = duk_get_string(thr, idx);
15960 
15961 	DUK_ASSERT(duk_get_top(thr) == top_at_entry);
15962 
15963 	return ret;
15964 }
15965 
duk_json_decode(duk_hthread * thr,duk_idx_t idx)15966 DUK_EXTERNAL void duk_json_decode(duk_hthread *thr, duk_idx_t idx) {
15967 #if defined(DUK_USE_ASSERTIONS)
15968 	duk_idx_t top_at_entry;
15969 #endif
15970 
15971 	DUK_ASSERT_API_ENTRY(thr);
15972 #if defined(DUK_USE_ASSERTIONS)
15973 	top_at_entry = duk_get_top(thr);
15974 #endif
15975 
15976 	idx = duk_require_normalize_index(thr, idx);
15977 	duk_bi_json_parse_helper(thr,
15978 	                         idx /*idx_value*/,
15979 	                         DUK_INVALID_INDEX /*idx_reviver*/,
15980 	                         0 /*flags*/);
15981 	duk_replace(thr, idx);
15982 
15983 	DUK_ASSERT(duk_get_top(thr) == top_at_entry);
15984 }
15985 #else  /* DUK_USE_JSON_SUPPORT */
duk_json_encode(duk_hthread * thr,duk_idx_t idx)15986 DUK_EXTERNAL const char *duk_json_encode(duk_hthread *thr, duk_idx_t idx) {
15987 	DUK_ASSERT_API_ENTRY(thr);
15988 	DUK_UNREF(idx);
15989 	DUK_ERROR_UNSUPPORTED(thr);
15990 	DUK_WO_NORETURN(return NULL;);
15991 }
15992 
duk_json_decode(duk_hthread * thr,duk_idx_t idx)15993 DUK_EXTERNAL void duk_json_decode(duk_hthread *thr, duk_idx_t idx) {
15994 	DUK_ASSERT_API_ENTRY(thr);
15995 	DUK_UNREF(idx);
15996 	DUK_ERROR_UNSUPPORTED(thr);
15997 	DUK_WO_NORETURN(return;);
15998 }
15999 #endif  /* DUK_USE_JSON_SUPPORT */
16000 #line 1 "duk_api_compile.c"
16001 /*
16002  *  Compilation and evaluation
16003  */
16004 
16005 /* #include duk_internal.h -> already included */
16006 
16007 typedef struct duk__compile_raw_args duk__compile_raw_args;
16008 struct duk__compile_raw_args {
16009 	duk_size_t src_length;  /* should be first on 64-bit platforms */
16010 	const duk_uint8_t *src_buffer;
16011 	duk_uint_t flags;
16012 };
16013 
16014 /* 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)16015 DUK_EXTERNAL duk_int_t duk_eval_raw(duk_hthread *thr, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
16016 	duk_int_t rc;
16017 
16018 	DUK_ASSERT_API_ENTRY(thr);
16019 
16020 	/* Note: strictness is *not* inherited from the current Duktape/C.
16021 	 * This would be confusing because the current strictness state
16022 	 * depends on whether we're running inside a Duktape/C activation
16023 	 * (= strict mode) or outside of any activation (= non-strict mode).
16024 	 * See tests/api/test-eval-strictness.c for more discussion.
16025 	 */
16026 
16027 	/* [ ... source? filename? ] (depends on flags) */
16028 
16029 	rc = duk_compile_raw(thr, src_buffer, src_length, flags | DUK_COMPILE_EVAL);  /* may be safe, or non-safe depending on flags */
16030 
16031 	/* [ ... closure/error ] */
16032 
16033 	if (rc != DUK_EXEC_SUCCESS) {
16034 		rc = DUK_EXEC_ERROR;
16035 		goto got_rc;
16036 	}
16037 
16038 	duk_push_global_object(thr);  /* explicit 'this' binding, see GH-164 */
16039 
16040 	if (flags & DUK_COMPILE_SAFE) {
16041 		rc = duk_pcall_method(thr, 0);
16042 	} else {
16043 		duk_call_method(thr, 0);
16044 		rc = DUK_EXEC_SUCCESS;
16045 	}
16046 
16047 	/* [ ... result/error ] */
16048 
16049  got_rc:
16050 	if (flags & DUK_COMPILE_NORESULT) {
16051 		duk_pop(thr);
16052 	}
16053 
16054 	return rc;
16055 }
16056 
16057 /* Helper which can be called both directly and with duk_safe_call(). */
duk__do_compile(duk_hthread * thr,void * udata)16058 DUK_LOCAL duk_ret_t duk__do_compile(duk_hthread *thr, void *udata) {
16059 	duk__compile_raw_args *comp_args;
16060 	duk_uint_t flags;
16061 	duk_hcompfunc *h_templ;
16062 
16063 	DUK_CTX_ASSERT_VALID(thr);
16064 	DUK_ASSERT(udata != NULL);
16065 
16066 	/* Note: strictness is not inherited from the current Duktape/C
16067 	 * context.  Otherwise it would not be possible to compile
16068 	 * non-strict code inside a Duktape/C activation (which is
16069 	 * always strict now).  See tests/api/test-eval-strictness.c
16070 	 * for discussion.
16071 	 */
16072 
16073 	/* [ ... source? filename? ] (depends on flags) */
16074 
16075 	comp_args = (duk__compile_raw_args *) udata;
16076 	flags = comp_args->flags;
16077 
16078 	if (flags & DUK_COMPILE_NOFILENAME) {
16079 		/* Automatic filename: 'eval' or 'input'. */
16080 		duk_push_hstring_stridx(thr, (flags & DUK_COMPILE_EVAL) ? DUK_STRIDX_EVAL : DUK_STRIDX_INPUT);
16081 	}
16082 
16083 	/* [ ... source? filename ] */
16084 
16085 	if (!comp_args->src_buffer) {
16086 		duk_hstring *h_sourcecode;
16087 
16088 		h_sourcecode = duk_get_hstring(thr, -2);
16089 		if ((flags & DUK_COMPILE_NOSOURCE) ||  /* args incorrect */
16090 		    (h_sourcecode == NULL)) {          /* e.g. duk_push_string_file_raw() pushed undefined */
16091 			DUK_ERROR_TYPE(thr, DUK_STR_NO_SOURCECODE);
16092 			DUK_WO_NORETURN(return 0;);
16093 		}
16094 		DUK_ASSERT(h_sourcecode != NULL);
16095 		comp_args->src_buffer = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode);
16096 		comp_args->src_length = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode);
16097 	}
16098 	DUK_ASSERT(comp_args->src_buffer != NULL);
16099 
16100 	if (flags & DUK_COMPILE_FUNCTION) {
16101 		flags |= DUK_COMPILE_EVAL | DUK_COMPILE_FUNCEXPR;
16102 	}
16103 
16104 	/* [ ... source? filename ] */
16105 
16106 	duk_js_compile(thr, comp_args->src_buffer, comp_args->src_length, flags);
16107 
16108 	/* [ ... source? func_template ] */
16109 
16110 	if (flags & DUK_COMPILE_NOSOURCE) {
16111 		;
16112 	} else {
16113 		duk_remove_m2(thr);
16114 	}
16115 
16116 	/* [ ... func_template ] */
16117 
16118 	h_templ = (duk_hcompfunc *) duk_known_hobject(thr, -1);
16119 	duk_js_push_closure(thr,
16120 	                   h_templ,
16121 	                   thr->builtins[DUK_BIDX_GLOBAL_ENV],
16122 	                   thr->builtins[DUK_BIDX_GLOBAL_ENV],
16123 	                   1 /*add_auto_proto*/);
16124 	duk_remove_m2(thr);   /* -> [ ... closure ] */
16125 
16126 	/* [ ... closure ] */
16127 
16128 	return 1;
16129 }
16130 
duk_compile_raw(duk_hthread * thr,const char * src_buffer,duk_size_t src_length,duk_uint_t flags)16131 DUK_EXTERNAL duk_int_t duk_compile_raw(duk_hthread *thr, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
16132 	duk__compile_raw_args comp_args_alloc;
16133 	duk__compile_raw_args *comp_args = &comp_args_alloc;
16134 
16135 	DUK_ASSERT_API_ENTRY(thr);
16136 
16137 	if ((flags & DUK_COMPILE_STRLEN) && (src_buffer != NULL)) {
16138 		/* String length is computed here to avoid multiple evaluation
16139 		 * of a macro argument in the calling side.
16140 		 */
16141 		src_length = DUK_STRLEN(src_buffer);
16142 	}
16143 
16144 	comp_args->src_buffer = (const duk_uint8_t *) src_buffer;
16145 	comp_args->src_length = src_length;
16146 	comp_args->flags = flags;
16147 
16148 	/* [ ... source? filename? ] (depends on flags) */
16149 
16150 	if (flags & DUK_COMPILE_SAFE) {
16151 		duk_int_t rc;
16152 		duk_int_t nargs;
16153 		duk_int_t nrets = 1;
16154 
16155 		/* Arguments can be: [ source? filename? &comp_args] so that
16156 		 * nargs is 1 to 3.  Call site encodes the correct nargs count
16157 		 * directly into flags.
16158 		 */
16159 		nargs = flags & 0x07;
16160 		DUK_ASSERT(nargs == ((flags & DUK_COMPILE_NOSOURCE) ? 0 : 1) +
16161 		                    ((flags & DUK_COMPILE_NOFILENAME) ? 0 : 1));
16162 		rc = duk_safe_call(thr, duk__do_compile, (void *) comp_args, nargs, nrets);
16163 
16164 		/* [ ... closure ] */
16165 		return rc;
16166 	}
16167 
16168 	(void) duk__do_compile(thr, (void *) comp_args);
16169 
16170 	/* [ ... closure ] */
16171 	return DUK_EXEC_SUCCESS;
16172 }
16173 #line 1 "duk_api_debug.c"
16174 /*
16175  *  Debugging related API calls
16176  */
16177 
16178 /* #include duk_internal.h -> already included */
16179 
16180 #if defined(DUK_USE_JSON_SUPPORT)
duk_push_context_dump(duk_hthread * thr)16181 DUK_EXTERNAL void duk_push_context_dump(duk_hthread *thr) {
16182 	duk_idx_t idx;
16183 	duk_idx_t top;
16184 
16185 	DUK_ASSERT_API_ENTRY(thr);
16186 
16187 	/* We don't duk_require_stack() here now, but rely on the caller having
16188 	 * enough space.
16189 	 */
16190 
16191 	top = duk_get_top(thr);
16192 	duk_push_bare_array(thr);
16193 	for (idx = 0; idx < top; idx++) {
16194 		duk_dup(thr, idx);
16195 		duk_put_prop_index(thr, -2, (duk_uarridx_t) idx);
16196 	}
16197 
16198 	/* XXX: conversion errors should not propagate outwards.
16199 	 * Perhaps values need to be coerced individually?
16200 	 */
16201 	duk_bi_json_stringify_helper(thr,
16202 	                             duk_get_top_index(thr),  /*idx_value*/
16203 	                             DUK_INVALID_INDEX,  /*idx_replacer*/
16204 	                             DUK_INVALID_INDEX,  /*idx_space*/
16205 	                             DUK_JSON_FLAG_EXT_CUSTOM |
16206 	                             DUK_JSON_FLAG_ASCII_ONLY |
16207 	                             DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
16208 
16209 	duk_push_sprintf(thr, "ctx: top=%ld, stack=%s", (long) top, (const char *) duk_safe_to_string(thr, -1));
16210 	duk_replace(thr, -3);  /* [ ... arr jsonx(arr) res ] -> [ ... res jsonx(arr) ] */
16211 	duk_pop(thr);
16212 	DUK_ASSERT(duk_is_string(thr, -1));
16213 }
16214 #else  /* DUK_USE_JSON_SUPPORT */
duk_push_context_dump(duk_hthread * thr)16215 DUK_EXTERNAL void duk_push_context_dump(duk_hthread *thr) {
16216 	DUK_ASSERT_API_ENTRY(thr);
16217 	DUK_ERROR_UNSUPPORTED(thr);
16218 	DUK_WO_NORETURN(return;);
16219 }
16220 #endif  /* DUK_USE_JSON_SUPPORT */
16221 
16222 #if defined(DUK_USE_DEBUGGER_SUPPORT)
16223 
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)16224 DUK_EXTERNAL void duk_debugger_attach(duk_hthread *thr,
16225                                       duk_debug_read_function read_cb,
16226                                       duk_debug_write_function write_cb,
16227                                       duk_debug_peek_function peek_cb,
16228                                       duk_debug_read_flush_function read_flush_cb,
16229                                       duk_debug_write_flush_function write_flush_cb,
16230                                       duk_debug_request_function request_cb,
16231                                       duk_debug_detached_function detached_cb,
16232                                       void *udata) {
16233 	duk_heap *heap;
16234 	const char *str;
16235 	duk_size_t len;
16236 
16237 	/* XXX: should there be an error or an automatic detach if
16238 	 * already attached?
16239 	 */
16240 
16241 	DUK_D(DUK_DPRINT("application called duk_debugger_attach()"));
16242 
16243 	DUK_ASSERT_API_ENTRY(thr);
16244 	DUK_ASSERT(read_cb != NULL);
16245 	DUK_ASSERT(write_cb != NULL);
16246 	/* Other callbacks are optional. */
16247 
16248 	heap = thr->heap;
16249 	heap->dbg_read_cb = read_cb;
16250 	heap->dbg_write_cb = write_cb;
16251 	heap->dbg_peek_cb = peek_cb;
16252 	heap->dbg_read_flush_cb = read_flush_cb;
16253 	heap->dbg_write_flush_cb = write_flush_cb;
16254 	heap->dbg_request_cb = request_cb;
16255 	heap->dbg_detached_cb = detached_cb;
16256 	heap->dbg_udata = udata;
16257 	heap->dbg_have_next_byte = 0;
16258 
16259 	/* Start in paused state. */
16260 	heap->dbg_processing = 0;
16261 	heap->dbg_state_dirty = 0;
16262 	heap->dbg_force_restart = 0;
16263 	heap->dbg_pause_flags = 0;
16264 	heap->dbg_pause_act = NULL;
16265 	heap->dbg_pause_startline = 0;
16266 	heap->dbg_exec_counter = 0;
16267 	heap->dbg_last_counter = 0;
16268 	heap->dbg_last_time = 0.0;
16269 	duk_debug_set_paused(heap);  /* XXX: overlap with fields above */
16270 
16271 	/* Send version identification and flush right afterwards.  Note that
16272 	 * we must write raw, unframed bytes here.
16273 	 */
16274 	duk_push_sprintf(thr, "%ld %ld %s %s\n",
16275 	                 (long) DUK_DEBUG_PROTOCOL_VERSION,
16276 	                 (long) DUK_VERSION,
16277 	                 (const char *) DUK_GIT_DESCRIBE,
16278 	                 (const char *) DUK_USE_TARGET_INFO);
16279 	str = duk_get_lstring(thr, -1, &len);
16280 	DUK_ASSERT(str != NULL);
16281 	duk_debug_write_bytes(thr, (const duk_uint8_t *) str, len);
16282 	duk_debug_write_flush(thr);
16283 	duk_pop(thr);
16284 }
16285 
duk_debugger_detach(duk_hthread * thr)16286 DUK_EXTERNAL void duk_debugger_detach(duk_hthread *thr) {
16287 	DUK_D(DUK_DPRINT("application called duk_debugger_detach()"));
16288 
16289 	DUK_ASSERT_API_ENTRY(thr);
16290 	DUK_ASSERT(thr->heap != NULL);
16291 
16292 	/* Can be called multiple times with no harm. */
16293 	duk_debug_do_detach(thr->heap);
16294 }
16295 
duk_debugger_cooperate(duk_hthread * thr)16296 DUK_EXTERNAL void duk_debugger_cooperate(duk_hthread *thr) {
16297 	duk_bool_t processed_messages;
16298 
16299 	DUK_ASSERT_API_ENTRY(thr);
16300 	DUK_ASSERT(thr->heap != NULL);
16301 
16302 	if (!duk_debug_is_attached(thr->heap)) {
16303 		return;
16304 	}
16305 	if (thr->callstack_curr != NULL || thr->heap->dbg_processing) {
16306 		/* Calling duk_debugger_cooperate() while Duktape is being
16307 		 * called into is not supported.  This is not a 100% check
16308 		 * but prevents any damage in most cases.
16309 		 */
16310 		return;
16311 	}
16312 
16313 	processed_messages = duk_debug_process_messages(thr, 1 /*no_block*/);
16314 	DUK_UNREF(processed_messages);
16315 }
16316 
duk_debugger_notify(duk_hthread * thr,duk_idx_t nvalues)16317 DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_hthread *thr, duk_idx_t nvalues) {
16318 	duk_idx_t top;
16319 	duk_idx_t idx;
16320 	duk_bool_t ret = 0;
16321 
16322 	DUK_ASSERT_API_ENTRY(thr);
16323 	DUK_ASSERT(thr->heap != NULL);
16324 
16325 	DUK_D(DUK_DPRINT("application called duk_debugger_notify() with nvalues=%ld", (long) nvalues));
16326 
16327 	top = duk_get_top(thr);
16328 	if (top < nvalues) {
16329 		DUK_ERROR_RANGE(thr, "not enough stack values for notify");
16330 		DUK_WO_NORETURN(return 0;);
16331 	}
16332 	if (duk_debug_is_attached(thr->heap)) {
16333 		duk_debug_write_notify(thr, DUK_DBG_CMD_APPNOTIFY);
16334 		for (idx = top - nvalues; idx < top; idx++) {
16335 			duk_tval *tv = DUK_GET_TVAL_POSIDX(thr, idx);
16336 			duk_debug_write_tval(thr, tv);
16337 		}
16338 		duk_debug_write_eom(thr);
16339 
16340 		/* Return non-zero (true) if we have a good reason to believe
16341 		 * the notify was delivered; if we're still attached at least
16342 		 * a transport error was not indicated by the transport write
16343 		 * callback.  This is not a 100% guarantee of course.
16344 		 */
16345 		if (duk_debug_is_attached(thr->heap)) {
16346 			ret = 1;
16347 		}
16348 	}
16349 	duk_pop_n(thr, nvalues);
16350 	return ret;
16351 }
16352 
duk_debugger_pause(duk_hthread * thr)16353 DUK_EXTERNAL void duk_debugger_pause(duk_hthread *thr) {
16354 	DUK_ASSERT_API_ENTRY(thr);
16355 	DUK_ASSERT(thr->heap != NULL);
16356 
16357 	DUK_D(DUK_DPRINT("application called duk_debugger_pause()"));
16358 
16359 	/* Treat like a debugger statement: ignore when not attached. */
16360 	if (duk_debug_is_attached(thr->heap)) {
16361 		if (duk_debug_is_paused(thr->heap)) {
16362 			DUK_D(DUK_DPRINT("duk_debugger_pause() called when already paused; ignoring"));
16363 		} else {
16364 			duk_debug_set_paused(thr->heap);
16365 
16366 			/* Pause on the next opcode executed.  This is always safe to do even
16367 			 * inside the debugger message loop: the interrupt counter will be reset
16368 			 * to its proper value when the message loop exits.
16369 			 */
16370 			thr->interrupt_init = 1;
16371 			thr->interrupt_counter = 0;
16372 		}
16373 	}
16374 }
16375 
16376 #else  /* DUK_USE_DEBUGGER_SUPPORT */
16377 
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)16378 DUK_EXTERNAL void duk_debugger_attach(duk_hthread *thr,
16379                                       duk_debug_read_function read_cb,
16380                                       duk_debug_write_function write_cb,
16381                                       duk_debug_peek_function peek_cb,
16382                                       duk_debug_read_flush_function read_flush_cb,
16383                                       duk_debug_write_flush_function write_flush_cb,
16384                                       duk_debug_request_function request_cb,
16385                                       duk_debug_detached_function detached_cb,
16386                                       void *udata) {
16387 	DUK_ASSERT_API_ENTRY(thr);
16388 	DUK_UNREF(read_cb);
16389 	DUK_UNREF(write_cb);
16390 	DUK_UNREF(peek_cb);
16391 	DUK_UNREF(read_flush_cb);
16392 	DUK_UNREF(write_flush_cb);
16393 	DUK_UNREF(request_cb);
16394 	DUK_UNREF(detached_cb);
16395 	DUK_UNREF(udata);
16396 	DUK_ERROR_TYPE(thr, "no debugger support");
16397 	DUK_WO_NORETURN(return;);
16398 }
16399 
duk_debugger_detach(duk_hthread * thr)16400 DUK_EXTERNAL void duk_debugger_detach(duk_hthread *thr) {
16401 	DUK_ASSERT_API_ENTRY(thr);
16402 	DUK_ERROR_TYPE(thr, "no debugger support");
16403 	DUK_WO_NORETURN(return;);
16404 }
16405 
duk_debugger_cooperate(duk_hthread * thr)16406 DUK_EXTERNAL void duk_debugger_cooperate(duk_hthread *thr) {
16407 	/* nop */
16408 	DUK_ASSERT_API_ENTRY(thr);
16409 	DUK_UNREF(thr);
16410 }
16411 
duk_debugger_notify(duk_hthread * thr,duk_idx_t nvalues)16412 DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_hthread *thr, duk_idx_t nvalues) {
16413 	duk_idx_t top;
16414 
16415 	DUK_ASSERT_API_ENTRY(thr);
16416 
16417 	top = duk_get_top(thr);
16418 	if (top < nvalues) {
16419 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
16420 		DUK_WO_NORETURN(return 0;);
16421 	}
16422 
16423 	/* No debugger support, just pop values. */
16424 	duk_pop_n(thr, nvalues);
16425 	return 0;
16426 }
16427 
duk_debugger_pause(duk_hthread * thr)16428 DUK_EXTERNAL void duk_debugger_pause(duk_hthread *thr) {
16429 	/* Treat like debugger statement: nop */
16430 	DUK_ASSERT_API_ENTRY(thr);
16431 	DUK_UNREF(thr);
16432 }
16433 
16434 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
16435 #line 1 "duk_api_heap.c"
16436 /*
16437  *  Heap creation and destruction
16438  */
16439 
16440 /* #include duk_internal.h -> already included */
16441 
16442 typedef struct duk_internal_thread_state duk_internal_thread_state;
16443 
16444 struct duk_internal_thread_state {
16445 	duk_ljstate lj;
16446 	duk_bool_t creating_error;
16447 	duk_hthread *curr_thread;
16448 	duk_uint8_t thread_state;
16449 	duk_int_t call_recursion_depth;
16450 };
16451 
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)16452 DUK_EXTERNAL duk_hthread *duk_create_heap(duk_alloc_function alloc_func,
16453                                           duk_realloc_function realloc_func,
16454                                           duk_free_function free_func,
16455                                           void *heap_udata,
16456                                           duk_fatal_function fatal_handler) {
16457 	duk_heap *heap = NULL;
16458 	duk_hthread *thr;
16459 
16460 	/* Assume that either all memory funcs are NULL or non-NULL, mixed
16461 	 * cases will now be unsafe.
16462 	 */
16463 
16464 	/* XXX: just assert non-NULL values here and make caller arguments
16465 	 * do the defaulting to the default implementations (smaller code)?
16466 	 */
16467 
16468 	if (!alloc_func) {
16469 		DUK_ASSERT(realloc_func == NULL);
16470 		DUK_ASSERT(free_func == NULL);
16471 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
16472 		alloc_func = duk_default_alloc_function;
16473 		realloc_func = duk_default_realloc_function;
16474 		free_func = duk_default_free_function;
16475 #else
16476 		DUK_D(DUK_DPRINT("no allocation functions given and no default providers"));
16477 		return NULL;
16478 #endif
16479 	} else {
16480 		DUK_ASSERT(realloc_func != NULL);
16481 		DUK_ASSERT(free_func != NULL);
16482 	}
16483 
16484 	if (!fatal_handler) {
16485 		fatal_handler = duk_default_fatal_handler;
16486 	}
16487 
16488 	DUK_ASSERT(alloc_func != NULL);
16489 	DUK_ASSERT(realloc_func != NULL);
16490 	DUK_ASSERT(free_func != NULL);
16491 	DUK_ASSERT(fatal_handler != NULL);
16492 
16493 	heap = duk_heap_alloc(alloc_func, realloc_func, free_func, heap_udata, fatal_handler);
16494 	if (!heap) {
16495 		return NULL;
16496 	}
16497 	thr = heap->heap_thread;
16498 	DUK_ASSERT(thr != NULL);
16499 	DUK_ASSERT(thr->heap != NULL);
16500 	return thr;
16501 }
16502 
duk_destroy_heap(duk_hthread * thr)16503 DUK_EXTERNAL void duk_destroy_heap(duk_hthread *thr) {
16504 	duk_heap *heap;
16505 
16506 	if (!thr) {
16507 		return;
16508 	}
16509 	DUK_ASSERT_API_ENTRY(thr);
16510 	heap = thr->heap;
16511 	DUK_ASSERT(heap != NULL);
16512 
16513 	duk_heap_free(heap);
16514 }
16515 
duk_suspend(duk_hthread * thr,duk_thread_state * state)16516 DUK_EXTERNAL void duk_suspend(duk_hthread *thr, duk_thread_state *state) {
16517 	duk_internal_thread_state *snapshot = (duk_internal_thread_state *) (void *) state;
16518 	duk_heap *heap;
16519 	duk_ljstate *lj;
16520 
16521 	DUK_ASSERT_API_ENTRY(thr);
16522 	DUK_ASSERT(thr->heap != NULL);
16523 	DUK_ASSERT(state != NULL);  /* unvalidated */
16524 
16525 	/* Currently not supported when called from within a finalizer.
16526 	 * If that is done, the finalizer will remain running indefinitely,
16527 	 * preventing other finalizers from executing.  The assert is a bit
16528 	 * wider, checking that it would be OK to run pending finalizers.
16529 	 */
16530 	DUK_ASSERT(thr->heap->pf_prevent_count == 0);
16531 
16532 	/* Currently not supported to duk_suspend() from an errCreate()
16533 	 * call.
16534 	 */
16535 	DUK_ASSERT(thr->heap->creating_error == 0);
16536 
16537 	heap = thr->heap;
16538 	lj = &heap->lj;
16539 
16540 	duk_push_tval(thr, &lj->value1);
16541 	duk_push_tval(thr, &lj->value2);
16542 
16543 	/* XXX: creating_error == 0 is asserted above, so no need to store. */
16544 	duk_memcpy((void *) &snapshot->lj, (const void *) lj, sizeof(duk_ljstate));
16545 	snapshot->creating_error = heap->creating_error;
16546 	snapshot->curr_thread = heap->curr_thread;
16547 	snapshot->thread_state = thr->state;
16548 	snapshot->call_recursion_depth = heap->call_recursion_depth;
16549 
16550 	lj->jmpbuf_ptr = NULL;
16551 	lj->type = DUK_LJ_TYPE_UNKNOWN;
16552 	DUK_TVAL_SET_UNDEFINED(&lj->value1);
16553 	DUK_TVAL_SET_UNDEFINED(&lj->value2);
16554 	heap->creating_error = 0;
16555 	heap->curr_thread = NULL;
16556 	heap->call_recursion_depth = 0;
16557 
16558 	thr->state = DUK_HTHREAD_STATE_INACTIVE;
16559 }
16560 
duk_resume(duk_hthread * thr,const duk_thread_state * state)16561 DUK_EXTERNAL void duk_resume(duk_hthread *thr, const duk_thread_state *state) {
16562 	const duk_internal_thread_state *snapshot = (const duk_internal_thread_state *) (const void *) state;
16563 	duk_heap *heap;
16564 
16565 	DUK_ASSERT_API_ENTRY(thr);
16566 	DUK_ASSERT(thr->heap != NULL);
16567 	DUK_ASSERT(state != NULL);  /* unvalidated */
16568 
16569 	/* Shouldn't be necessary if duk_suspend() is called before
16570 	 * duk_resume(), but assert in case API sequence is incorrect.
16571 	 */
16572 	DUK_ASSERT(thr->heap->pf_prevent_count == 0);
16573 	DUK_ASSERT(thr->heap->creating_error == 0);
16574 
16575 	thr->state = snapshot->thread_state;
16576 
16577 	heap = thr->heap;
16578 
16579 	duk_memcpy((void *) &heap->lj, (const void *) &snapshot->lj, sizeof(duk_ljstate));
16580 	heap->creating_error = snapshot->creating_error;
16581 	heap->curr_thread = snapshot->curr_thread;
16582 	heap->call_recursion_depth = snapshot->call_recursion_depth;
16583 
16584 	duk_pop_2(thr);
16585 }
16586 
16587 /* XXX: better place for this */
duk_set_global_object(duk_hthread * thr)16588 DUK_EXTERNAL void duk_set_global_object(duk_hthread *thr) {
16589 	duk_hobject *h_glob;
16590 	duk_hobject *h_prev_glob;
16591 	duk_hobjenv *h_env;
16592 	duk_hobject *h_prev_env;
16593 
16594 	DUK_ASSERT_API_ENTRY(thr);
16595 
16596 	DUK_D(DUK_DPRINT("replace global object with: %!T", duk_get_tval(thr, -1)));
16597 
16598 	h_glob = duk_require_hobject(thr, -1);
16599 	DUK_ASSERT(h_glob != NULL);
16600 
16601 	/*
16602 	 *  Replace global object.
16603 	 */
16604 
16605 	h_prev_glob = thr->builtins[DUK_BIDX_GLOBAL];
16606 	DUK_UNREF(h_prev_glob);
16607 	thr->builtins[DUK_BIDX_GLOBAL] = h_glob;
16608 	DUK_HOBJECT_INCREF(thr, h_glob);
16609 	DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_glob);  /* side effects, in theory (referenced by global env) */
16610 
16611 	/*
16612 	 *  Replace lexical environment for global scope
16613 	 *
16614 	 *  Create a new object environment for the global lexical scope.
16615 	 *  We can't just reset the _Target property of the current one,
16616 	 *  because the lexical scope is shared by other threads with the
16617 	 *  same (initial) built-ins.
16618 	 */
16619 
16620 	h_env = duk_hobjenv_alloc(thr,
16621 	                          DUK_HOBJECT_FLAG_EXTENSIBLE |
16622 	                          DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
16623 	DUK_ASSERT(h_env != NULL);
16624 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_env) == NULL);
16625 
16626 	DUK_ASSERT(h_env->target == NULL);
16627 	DUK_ASSERT(h_glob != NULL);
16628 	h_env->target = h_glob;
16629 	DUK_HOBJECT_INCREF(thr, h_glob);
16630 	DUK_ASSERT(h_env->has_this == 0);
16631 
16632 	/* [ ... new_glob ] */
16633 
16634 	h_prev_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
16635 	thr->builtins[DUK_BIDX_GLOBAL_ENV] = (duk_hobject *) h_env;
16636 	DUK_HOBJECT_INCREF(thr, (duk_hobject *) h_env);
16637 	DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_env);  /* side effects */
16638 	DUK_UNREF(h_env);  /* without refcounts */
16639 	DUK_UNREF(h_prev_env);
16640 
16641 	/* [ ... new_glob ] */
16642 
16643 	duk_pop(thr);
16644 
16645 	/* [ ... ] */
16646 }
16647 #line 1 "duk_api_inspect.c"
16648 /*
16649  *  Inspection
16650  */
16651 
16652 /* #include duk_internal.h -> already included */
16653 
16654 /* For footprint efficient multiple value setting: arrays are much better than
16655  * varargs, format string with parsing is often better than string pointer arrays.
16656  */
duk__inspect_multiple_uint(duk_hthread * thr,const char * fmt,duk_int_t * vals)16657 DUK_LOCAL void duk__inspect_multiple_uint(duk_hthread *thr, const char *fmt, duk_int_t *vals) {
16658 	duk_int_t val;
16659 	const char *p;
16660 	const char *p_curr;
16661 	duk_size_t len;
16662 
16663 	for (p = fmt;;) {
16664 		len = DUK_STRLEN(p);
16665 		p_curr = p;
16666 		p += len + 1;
16667 		if (len == 0) {
16668 			/* Double NUL (= empty key) terminates. */
16669 			break;
16670 		}
16671 		val = *vals++;
16672 		if (val >= 0) {
16673 			/* Negative values are markers to skip key. */
16674 			duk_push_string(thr, p_curr);
16675 			duk_push_int(thr, val);
16676 			duk_put_prop(thr, -3);
16677 		}
16678 	}
16679 }
16680 
16681 /* Raw helper to extract internal information / statistics about a value.
16682  * The return value is an object with properties that are version specific.
16683  * The properties must not expose anything that would lead to security
16684  * issues (e.g. exposing compiled function 'data' buffer might be an issue).
16685  * Currently only counts and sizes and such are given so there shouldn't
16686  * be security implications.
16687  */
16688 
16689 #define DUK__IDX_TYPE     0
16690 #define DUK__IDX_ITAG     1
16691 #define DUK__IDX_REFC     2
16692 #define DUK__IDX_HBYTES   3
16693 #define DUK__IDX_CLASS    4
16694 #define DUK__IDX_PBYTES   5
16695 #define DUK__IDX_ESIZE    6
16696 #define DUK__IDX_ENEXT    7
16697 #define DUK__IDX_ASIZE    8
16698 #define DUK__IDX_HSIZE    9
16699 #define DUK__IDX_BCBYTES  10
16700 #define DUK__IDX_DBYTES   11
16701 #define DUK__IDX_TSTATE   12
16702 #define DUK__IDX_VARIANT  13
16703 
duk_inspect_value(duk_hthread * thr,duk_idx_t idx)16704 DUK_EXTERNAL void duk_inspect_value(duk_hthread *thr, duk_idx_t idx) {
16705 	duk_tval *tv;
16706 	duk_heaphdr *h;
16707 	/* The temporary values should be in an array rather than individual
16708 	 * variables which (in practice) ensures that the compiler won't map
16709 	 * them to registers and emit a lot of unnecessary shuffling code.
16710 	 */
16711 	duk_int_t vals[14];
16712 
16713 	DUK_ASSERT_API_ENTRY(thr);
16714 
16715 	/* Assume two's complement and set everything to -1. */
16716 	duk_memset((void *) &vals, (int) 0xff, sizeof(vals));
16717 	DUK_ASSERT(vals[DUK__IDX_TYPE] == -1);  /* spot check one */
16718 
16719 	tv = duk_get_tval_or_unused(thr, idx);
16720 	h = (DUK_TVAL_IS_HEAP_ALLOCATED(tv) ? DUK_TVAL_GET_HEAPHDR(tv) : NULL);
16721 
16722 	vals[DUK__IDX_TYPE] = duk_get_type_tval(tv);
16723 	vals[DUK__IDX_ITAG] = (duk_int_t) DUK_TVAL_GET_TAG(tv);
16724 
16725 	duk_push_bare_object(thr);  /* Invalidates 'tv'. */
16726 	tv = NULL;
16727 
16728 	if (h == NULL) {
16729 		goto finish;
16730 	}
16731 	duk_push_pointer(thr, (void *) h);
16732 	duk_put_prop_literal(thr, -2, "hptr");
16733 
16734 #if 0
16735 	/* Covers a lot of information, e.g. buffer and string variants. */
16736 	duk_push_uint(thr, (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));
16737 	duk_put_prop_literal(thr, -2, "hflags");
16738 #endif
16739 
16740 #if defined(DUK_USE_REFERENCE_COUNTING)
16741 	vals[DUK__IDX_REFC] = (duk_int_t) DUK_HEAPHDR_GET_REFCOUNT(h);
16742 #endif
16743 	vals[DUK__IDX_VARIANT] = 0;
16744 
16745 	/* Heaphdr size and additional allocation size, followed by
16746 	 * type specific stuff (with varying value count).
16747 	 */
16748 	switch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(h)) {
16749 	case DUK_HTYPE_STRING: {
16750 		duk_hstring *h_str = (duk_hstring *) h;
16751 		vals[DUK__IDX_HBYTES] = (duk_int_t) (sizeof(duk_hstring) + DUK_HSTRING_GET_BYTELEN(h_str) + 1);
16752 #if defined(DUK_USE_HSTRING_EXTDATA)
16753 		if (DUK_HSTRING_HAS_EXTDATA(h_str)) {
16754 			vals[DUK__IDX_VARIANT] = 1;
16755 		}
16756 #endif
16757 		break;
16758 	}
16759 	case DUK_HTYPE_OBJECT: {
16760 		duk_hobject *h_obj = (duk_hobject *) h;
16761 
16762 		/* XXX: variants here are maybe pointless; class is enough? */
16763 		if (DUK_HOBJECT_IS_ARRAY(h_obj)) {
16764 			vals[DUK__IDX_HBYTES] = sizeof(duk_harray);
16765 		} else if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
16766 			vals[DUK__IDX_HBYTES] = sizeof(duk_hcompfunc);
16767 		} else if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
16768 			vals[DUK__IDX_HBYTES] = sizeof(duk_hnatfunc);
16769 		} else if (DUK_HOBJECT_IS_THREAD(h_obj)) {
16770 			vals[DUK__IDX_HBYTES] = sizeof(duk_hthread);
16771 			vals[DUK__IDX_TSTATE] = ((duk_hthread *) h_obj)->state;
16772 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
16773 		} else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
16774 			vals[DUK__IDX_HBYTES] = sizeof(duk_hbufobj);
16775 			/* XXX: some size information */
16776 #endif
16777 		} else {
16778 			vals[DUK__IDX_HBYTES] = (duk_small_uint_t) sizeof(duk_hobject);
16779 		}
16780 
16781 		vals[DUK__IDX_CLASS] = (duk_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
16782 		vals[DUK__IDX_PBYTES] = (duk_int_t) DUK_HOBJECT_P_ALLOC_SIZE(h_obj);
16783 		vals[DUK__IDX_ESIZE] = (duk_int_t) DUK_HOBJECT_GET_ESIZE(h_obj);
16784 		vals[DUK__IDX_ENEXT] = (duk_int_t) DUK_HOBJECT_GET_ENEXT(h_obj);
16785 		vals[DUK__IDX_ASIZE] = (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj);
16786 		vals[DUK__IDX_HSIZE] = (duk_int_t) DUK_HOBJECT_GET_HSIZE(h_obj);
16787 
16788 		/* Note: e_next indicates the number of gc-reachable entries
16789 		 * in the entry part, and also indicates the index where the
16790 		 * next new property would be inserted.  It does *not* indicate
16791 		 * the number of non-NULL keys present in the object.  That
16792 		 * value could be counted separately but requires a pass through
16793 		 * the key list.
16794 		 */
16795 
16796 		if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
16797 			duk_hbuffer *h_data = (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(thr->heap, (duk_hcompfunc *) h_obj);
16798 			vals[DUK__IDX_BCBYTES] = (duk_int_t) (h_data ? DUK_HBUFFER_GET_SIZE(h_data) : 0);
16799 		}
16800 		break;
16801 	}
16802 	case DUK_HTYPE_BUFFER: {
16803 		duk_hbuffer *h_buf = (duk_hbuffer *) h;
16804 
16805 		if (DUK_HBUFFER_HAS_DYNAMIC(h_buf)) {
16806 			if (DUK_HBUFFER_HAS_EXTERNAL(h_buf)) {
16807 				vals[DUK__IDX_VARIANT] = 2;  /* buffer variant 2: external */
16808 				vals[DUK__IDX_HBYTES] = (duk_uint_t) (sizeof(duk_hbuffer_external));
16809 			} else {
16810 				/* When alloc_size == 0 the second allocation may not
16811 				 * actually exist.
16812 				 */
16813 				vals[DUK__IDX_VARIANT] = 1;  /* buffer variant 1: dynamic */
16814 				vals[DUK__IDX_HBYTES] = (duk_uint_t) (sizeof(duk_hbuffer_dynamic));
16815 			}
16816 			vals[DUK__IDX_DBYTES] = (duk_int_t) (DUK_HBUFFER_GET_SIZE(h_buf));
16817 		} else {
16818 			DUK_ASSERT(vals[DUK__IDX_VARIANT] == 0);  /* buffer variant 0: fixed */
16819 			vals[DUK__IDX_HBYTES] = (duk_int_t) (sizeof(duk_hbuffer_fixed) + DUK_HBUFFER_GET_SIZE(h_buf));
16820 		}
16821 		break;
16822 	}
16823 	}
16824 
16825  finish:
16826 	duk__inspect_multiple_uint(thr,
16827 	    "type" "\x00" "itag" "\x00" "refc" "\x00" "hbytes" "\x00" "class" "\x00"
16828 	    "pbytes" "\x00" "esize" "\x00" "enext" "\x00" "asize" "\x00" "hsize" "\x00"
16829 	    "bcbytes" "\x00" "dbytes" "\x00" "tstate" "\x00" "variant" "\x00" "\x00",
16830 	    (duk_int_t *) &vals);
16831 }
16832 
duk_inspect_callstack_entry(duk_hthread * thr,duk_int_t level)16833 DUK_EXTERNAL void duk_inspect_callstack_entry(duk_hthread *thr, duk_int_t level) {
16834 	duk_activation *act;
16835 	duk_uint_fast32_t pc;
16836 	duk_uint_fast32_t line;
16837 
16838 	DUK_ASSERT_API_ENTRY(thr);
16839 
16840 	/* -1   = top callstack entry
16841 	 * -2   = caller of level -1
16842 	 * etc
16843 	 */
16844 	act = duk_hthread_get_activation_for_level(thr, level);
16845 	if (act == NULL) {
16846 		duk_push_undefined(thr);
16847 		return;
16848 	}
16849 	duk_push_bare_object(thr);
16850 
16851 	/* Relevant PC is just before current one because PC is
16852 	 * post-incremented.  This should match what error augment
16853 	 * code does.
16854 	 */
16855 	pc = duk_hthread_get_act_prev_pc(thr, act);
16856 
16857 	duk_push_tval(thr, &act->tv_func);
16858 
16859 	duk_push_uint(thr, (duk_uint_t) pc);
16860 	duk_put_prop_stridx_short(thr, -3, DUK_STRIDX_PC);
16861 
16862 #if defined(DUK_USE_PC2LINE)
16863 	line = duk_hobject_pc2line_query(thr, -1, pc);
16864 #else
16865 	line = 0;
16866 #endif
16867 	duk_push_uint(thr, (duk_uint_t) line);
16868 	duk_put_prop_stridx_short(thr, -3, DUK_STRIDX_LINE_NUMBER);
16869 
16870 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_LC_FUNCTION);
16871 	/* Providing access to e.g. act->lex_env would be dangerous: these
16872 	 * internal structures must never be accessible to the application.
16873 	 * Duktape relies on them having consistent data, and this consistency
16874 	 * is only asserted for, not checked for.
16875 	 */
16876 }
16877 
16878 /* automatic undefs */
16879 #undef DUK__IDX_ASIZE
16880 #undef DUK__IDX_BCBYTES
16881 #undef DUK__IDX_CLASS
16882 #undef DUK__IDX_DBYTES
16883 #undef DUK__IDX_ENEXT
16884 #undef DUK__IDX_ESIZE
16885 #undef DUK__IDX_HBYTES
16886 #undef DUK__IDX_HSIZE
16887 #undef DUK__IDX_ITAG
16888 #undef DUK__IDX_PBYTES
16889 #undef DUK__IDX_REFC
16890 #undef DUK__IDX_TSTATE
16891 #undef DUK__IDX_TYPE
16892 #undef DUK__IDX_VARIANT
16893 #line 1 "duk_api_memory.c"
16894 /*
16895  *  Memory calls.
16896  */
16897 
16898 /* #include duk_internal.h -> already included */
16899 
duk_alloc_raw(duk_hthread * thr,duk_size_t size)16900 DUK_EXTERNAL void *duk_alloc_raw(duk_hthread *thr, duk_size_t size) {
16901 	DUK_ASSERT_API_ENTRY(thr);
16902 
16903 	return DUK_ALLOC_RAW(thr->heap, size);
16904 }
16905 
duk_free_raw(duk_hthread * thr,void * ptr)16906 DUK_EXTERNAL void duk_free_raw(duk_hthread *thr, void *ptr) {
16907 	DUK_ASSERT_API_ENTRY(thr);
16908 
16909 	DUK_FREE_RAW(thr->heap, ptr);
16910 }
16911 
duk_realloc_raw(duk_hthread * thr,void * ptr,duk_size_t size)16912 DUK_EXTERNAL void *duk_realloc_raw(duk_hthread *thr, void *ptr, duk_size_t size) {
16913 	DUK_ASSERT_API_ENTRY(thr);
16914 
16915 	return DUK_REALLOC_RAW(thr->heap, ptr, size);
16916 }
16917 
duk_alloc(duk_hthread * thr,duk_size_t size)16918 DUK_EXTERNAL void *duk_alloc(duk_hthread *thr, duk_size_t size) {
16919 	DUK_ASSERT_API_ENTRY(thr);
16920 
16921 	return DUK_ALLOC(thr->heap, size);
16922 }
16923 
duk_free(duk_hthread * thr,void * ptr)16924 DUK_EXTERNAL void duk_free(duk_hthread *thr, void *ptr) {
16925 	DUK_ASSERT_API_ENTRY(thr);
16926 
16927 	DUK_FREE_CHECKED(thr, ptr);
16928 }
16929 
duk_realloc(duk_hthread * thr,void * ptr,duk_size_t size)16930 DUK_EXTERNAL void *duk_realloc(duk_hthread *thr, void *ptr, duk_size_t size) {
16931 	DUK_ASSERT_API_ENTRY(thr);
16932 
16933 	/*
16934 	 *  Note: since this is an exposed API call, there should be
16935 	 *  no way a mark-and-sweep could have a side effect on the
16936 	 *  memory allocation behind 'ptr'; the pointer should never
16937 	 *  be something that Duktape wants to change.
16938 	 *
16939 	 *  Thus, no need to use DUK_REALLOC_INDIRECT (and we don't
16940 	 *  have the storage location here anyway).
16941 	 */
16942 
16943 	return DUK_REALLOC(thr->heap, ptr, size);
16944 }
16945 
duk_get_memory_functions(duk_hthread * thr,duk_memory_functions * out_funcs)16946 DUK_EXTERNAL void duk_get_memory_functions(duk_hthread *thr, duk_memory_functions *out_funcs) {
16947 	duk_heap *heap;
16948 
16949 	DUK_ASSERT_API_ENTRY(thr);
16950 	DUK_ASSERT(out_funcs != NULL);
16951 	DUK_ASSERT(thr != NULL);
16952 	DUK_ASSERT(thr->heap != NULL);
16953 
16954 	heap = thr->heap;
16955 	out_funcs->alloc_func = heap->alloc_func;
16956 	out_funcs->realloc_func = heap->realloc_func;
16957 	out_funcs->free_func = heap->free_func;
16958 	out_funcs->udata = heap->heap_udata;
16959 }
16960 
duk_gc(duk_hthread * thr,duk_uint_t flags)16961 DUK_EXTERNAL void duk_gc(duk_hthread *thr, duk_uint_t flags) {
16962 	duk_heap *heap;
16963 	duk_small_uint_t ms_flags;
16964 
16965 	DUK_ASSERT_API_ENTRY(thr);
16966 	heap = thr->heap;
16967 	DUK_ASSERT(heap != NULL);
16968 
16969 	DUK_D(DUK_DPRINT("mark-and-sweep requested by application"));
16970 	DUK_ASSERT(DUK_GC_COMPACT == DUK_MS_FLAG_EMERGENCY);  /* Compact flag is 1:1 with emergency flag which forces compaction. */
16971 	ms_flags = (duk_small_uint_t) flags;
16972 	duk_heap_mark_and_sweep(heap, ms_flags);
16973 }
16974 #line 1 "duk_api_object.c"
16975 /*
16976  *  Object handling: property access and other support functions.
16977  */
16978 
16979 /* #include duk_internal.h -> already included */
16980 
16981 /*
16982  *  Property handling
16983  *
16984  *  The API exposes only the most common property handling functions.
16985  *  The caller can invoke ECMAScript built-ins for full control (e.g.
16986  *  defineProperty, getOwnPropertyDescriptor).
16987  */
16988 
duk_get_prop(duk_hthread * thr,duk_idx_t obj_idx)16989 DUK_EXTERNAL duk_bool_t duk_get_prop(duk_hthread *thr, duk_idx_t obj_idx) {
16990 	duk_tval *tv_obj;
16991 	duk_tval *tv_key;
16992 	duk_bool_t rc;
16993 
16994 	DUK_ASSERT_API_ENTRY(thr);
16995 
16996 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
16997 	 * resize is not necessary for a property get right now.
16998 	 */
16999 
17000 	tv_obj = duk_require_tval(thr, obj_idx);
17001 	tv_key = duk_require_tval(thr, -1);
17002 
17003 	rc = duk_hobject_getprop(thr, tv_obj, tv_key);
17004 	DUK_ASSERT(rc == 0 || rc == 1);
17005 	/* a value is left on stack regardless of rc */
17006 
17007 	duk_remove_m2(thr);  /* remove key */
17008 	DUK_ASSERT(duk_is_undefined(thr, -1) || rc == 1);
17009 	return rc;  /* 1 if property found, 0 otherwise */
17010 }
17011 
duk_get_prop_string(duk_hthread * thr,duk_idx_t obj_idx,const char * key)17012 DUK_EXTERNAL duk_bool_t duk_get_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
17013 	DUK_ASSERT_API_ENTRY(thr);
17014 	DUK_ASSERT(key != NULL);
17015 
17016 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17017 	(void) duk_push_string(thr, key);
17018 	return duk_get_prop(thr, obj_idx);
17019 }
17020 
duk_get_prop_lstring(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)17021 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) {
17022 	DUK_ASSERT_API_ENTRY(thr);
17023 	DUK_ASSERT(key != NULL);
17024 
17025 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17026 	(void) duk_push_lstring(thr, key, key_len);
17027 	return duk_get_prop(thr, obj_idx);
17028 }
17029 
17030 #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)17031 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) {
17032 	DUK_ASSERT_API_ENTRY(thr);
17033 	DUK_ASSERT(key != NULL);
17034 	DUK_ASSERT(key[key_len] == (char) 0);
17035 
17036 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17037 	(void) duk_push_literal_raw(thr, key, key_len);
17038 	return duk_get_prop(thr, obj_idx);
17039 }
17040 #endif
17041 
duk_get_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx)17042 DUK_EXTERNAL duk_bool_t duk_get_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
17043 	DUK_ASSERT_API_ENTRY(thr);
17044 
17045 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17046 	duk_push_uarridx(thr, arr_idx);
17047 	return duk_get_prop(thr, obj_idx);
17048 }
17049 
duk_get_prop_heapptr(duk_hthread * thr,duk_idx_t obj_idx,void * ptr)17050 DUK_EXTERNAL duk_bool_t duk_get_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
17051 	DUK_ASSERT_API_ENTRY(thr);
17052 
17053 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17054 	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
17055 	return duk_get_prop(thr, obj_idx);
17056 }
17057 
duk_get_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)17058 DUK_INTERNAL duk_bool_t duk_get_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
17059 	DUK_ASSERT_API_ENTRY(thr);
17060 	DUK_ASSERT_STRIDX_VALID(stridx);
17061 
17062 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17063 	(void) duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
17064 	return duk_get_prop(thr, obj_idx);
17065 }
17066 
duk_get_prop_stridx_short_raw(duk_hthread * thr,duk_uint_t packed_args)17067 DUK_INTERNAL duk_bool_t duk_get_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
17068 	return duk_get_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
17069 	                                (duk_small_uint_t) (packed_args & 0xffffUL));
17070 }
17071 
duk_get_prop_stridx_boolean(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx,duk_bool_t * out_has_prop)17072 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) {
17073 	duk_bool_t rc;
17074 
17075 	DUK_ASSERT_API_ENTRY(thr);
17076 	DUK_ASSERT_STRIDX_VALID(stridx);
17077 
17078 	rc = duk_get_prop_stridx(thr, obj_idx, stridx);
17079 	if (out_has_prop) {
17080 		*out_has_prop = rc;
17081 	}
17082 	return duk_to_boolean_top_pop(thr);
17083 }
17084 
17085 /* This get variant is for internal use, it differs from standard
17086  * duk_get_prop() in that:
17087  *   - Object argument must be an object (primitive values not supported).
17088  *   - Key argument must be a string (no coercion).
17089  *   - Only own properties are checked (no inheritance).  Only "entry part"
17090  *     properties are checked (not array index properties).
17091  *   - Property must be a plain data property, not a getter.
17092  *   - Proxy traps are not triggered.
17093  */
duk_xget_owndataprop(duk_hthread * thr,duk_idx_t obj_idx)17094 DUK_INTERNAL duk_bool_t duk_xget_owndataprop(duk_hthread *thr, duk_idx_t obj_idx) {
17095 	duk_hobject *h_obj;
17096 	duk_hstring *h_key;
17097 	duk_tval *tv_val;
17098 
17099 	DUK_ASSERT_API_ENTRY(thr);
17100 
17101 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
17102 	 * resize is not necessary for a property get right now.
17103 	 */
17104 
17105 	h_obj = duk_get_hobject(thr, obj_idx);
17106 	if (h_obj == NULL) {
17107 		return 0;
17108 	}
17109 	h_key = duk_require_hstring(thr, -1);
17110 
17111 	tv_val = duk_hobject_find_entry_tval_ptr(thr->heap, h_obj, h_key);
17112 	if (tv_val == NULL) {
17113 		return 0;
17114 	}
17115 
17116 	duk_push_tval(thr, tv_val);
17117 	duk_remove_m2(thr);  /* remove key */
17118 
17119 	return 1;
17120 }
17121 
duk_xget_owndataprop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)17122 DUK_INTERNAL duk_bool_t duk_xget_owndataprop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
17123 	DUK_ASSERT_API_ENTRY(thr);
17124 	DUK_ASSERT_STRIDX_VALID(stridx);
17125 
17126 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17127 	(void) duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
17128 	return duk_xget_owndataprop(thr, obj_idx);
17129 }
17130 
duk_xget_owndataprop_stridx_short_raw(duk_hthread * thr,duk_uint_t packed_args)17131 DUK_INTERNAL duk_bool_t duk_xget_owndataprop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
17132 	return duk_xget_owndataprop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
17133 	                                   (duk_small_uint_t) (packed_args & 0xffffUL));
17134 }
17135 
duk__put_prop_shared(duk_hthread * thr,duk_idx_t obj_idx,duk_idx_t idx_key)17136 DUK_LOCAL duk_bool_t duk__put_prop_shared(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t idx_key) {
17137 	duk_tval *tv_obj;
17138 	duk_tval *tv_key;
17139 	duk_tval *tv_val;
17140 	duk_bool_t throw_flag;
17141 	duk_bool_t rc;
17142 
17143 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
17144 	 * resize is not necessary for a property put right now (putprop protects
17145 	 * against it internally).
17146 	 */
17147 
17148 	/* Key and value indices are either (-2, -1) or (-1, -2).  Given idx_key,
17149 	 * idx_val is always (idx_key ^ 0x01).
17150 	 */
17151 	DUK_ASSERT((idx_key == -2 && (idx_key ^ 1) == -1) ||
17152 	           (idx_key == -1 && (idx_key ^ 1) == -2));
17153 	/* XXX: Direct access; faster validation. */
17154 	tv_obj = duk_require_tval(thr, obj_idx);
17155 	tv_key = duk_require_tval(thr, idx_key);
17156 	tv_val = duk_require_tval(thr, idx_key ^ 1);
17157 	throw_flag = duk_is_strict_call(thr);
17158 
17159 	rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, throw_flag);
17160 	DUK_ASSERT(rc == 0 || rc == 1);
17161 
17162 	duk_pop_2(thr);  /* remove key and value */
17163 	return rc;  /* 1 if property found, 0 otherwise */
17164 }
17165 
duk_put_prop(duk_hthread * thr,duk_idx_t obj_idx)17166 DUK_EXTERNAL duk_bool_t duk_put_prop(duk_hthread *thr, duk_idx_t obj_idx) {
17167 	DUK_ASSERT_API_ENTRY(thr);
17168 	return duk__put_prop_shared(thr, obj_idx, -2);
17169 }
17170 
duk_put_prop_string(duk_hthread * thr,duk_idx_t obj_idx,const char * key)17171 DUK_EXTERNAL duk_bool_t duk_put_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
17172 	DUK_ASSERT_API_ENTRY(thr);
17173 	DUK_ASSERT(key != NULL);
17174 
17175 	/* Careful here and with other duk_put_prop_xxx() helpers: the
17176 	 * target object and the property value may be in the same value
17177 	 * stack slot (unusual, but still conceptually clear).
17178 	 */
17179 	obj_idx = duk_normalize_index(thr, obj_idx);
17180 	(void) duk_push_string(thr, key);
17181 	return duk__put_prop_shared(thr, obj_idx, -1);
17182 }
17183 
duk_put_prop_lstring(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)17184 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) {
17185 	DUK_ASSERT_API_ENTRY(thr);
17186 	DUK_ASSERT(key != NULL);
17187 
17188 	obj_idx = duk_normalize_index(thr, obj_idx);
17189 	(void) duk_push_lstring(thr, key, key_len);
17190 	return duk__put_prop_shared(thr, obj_idx, -1);
17191 }
17192 
17193 #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)17194 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) {
17195 	DUK_ASSERT_API_ENTRY(thr);
17196 	DUK_ASSERT(key != NULL);
17197 	DUK_ASSERT(key[key_len] == (char) 0);
17198 
17199 	obj_idx = duk_normalize_index(thr, obj_idx);
17200 	(void) duk_push_literal_raw(thr, key, key_len);
17201 	return duk__put_prop_shared(thr, obj_idx, -1);
17202 }
17203 #endif
17204 
duk_put_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx)17205 DUK_EXTERNAL duk_bool_t duk_put_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
17206 	DUK_ASSERT_API_ENTRY(thr);
17207 
17208 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17209 	duk_push_uarridx(thr, arr_idx);
17210 	return duk__put_prop_shared(thr, obj_idx, -1);
17211 }
17212 
duk_put_prop_heapptr(duk_hthread * thr,duk_idx_t obj_idx,void * ptr)17213 DUK_EXTERNAL duk_bool_t duk_put_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
17214 	DUK_ASSERT_API_ENTRY(thr);
17215 
17216 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17217 	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
17218 	return duk__put_prop_shared(thr, obj_idx, -1);
17219 }
17220 
17221 
duk_put_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)17222 DUK_INTERNAL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
17223 	DUK_ASSERT_API_ENTRY(thr);
17224 	DUK_ASSERT_STRIDX_VALID(stridx);
17225 
17226 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17227 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
17228 	return duk__put_prop_shared(thr, obj_idx, -1);
17229 }
17230 
duk_put_prop_stridx_short_raw(duk_hthread * thr,duk_uint_t packed_args)17231 DUK_INTERNAL duk_bool_t duk_put_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
17232 	return duk_put_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
17233 	                                (duk_small_uint_t) (packed_args & 0xffffUL));
17234 }
17235 
duk_del_prop(duk_hthread * thr,duk_idx_t obj_idx)17236 DUK_EXTERNAL duk_bool_t duk_del_prop(duk_hthread *thr, duk_idx_t obj_idx) {
17237 	duk_tval *tv_obj;
17238 	duk_tval *tv_key;
17239 	duk_bool_t throw_flag;
17240 	duk_bool_t rc;
17241 
17242 	DUK_ASSERT_API_ENTRY(thr);
17243 
17244 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
17245 	 * resize is not necessary for a property delete right now.
17246 	 */
17247 
17248 	tv_obj = duk_require_tval(thr, obj_idx);
17249 	tv_key = duk_require_tval(thr, -1);
17250 	throw_flag = duk_is_strict_call(thr);
17251 
17252 	rc = duk_hobject_delprop(thr, tv_obj, tv_key, throw_flag);
17253 	DUK_ASSERT(rc == 0 || rc == 1);
17254 
17255 	duk_pop(thr);  /* remove key */
17256 	return rc;
17257 }
17258 
duk_del_prop_string(duk_hthread * thr,duk_idx_t obj_idx,const char * key)17259 DUK_EXTERNAL duk_bool_t duk_del_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
17260 	DUK_ASSERT_API_ENTRY(thr);
17261 	DUK_ASSERT(key != NULL);
17262 
17263 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17264 	(void) duk_push_string(thr, key);
17265 	return duk_del_prop(thr, obj_idx);
17266 }
17267 
duk_del_prop_lstring(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)17268 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) {
17269 	DUK_ASSERT_API_ENTRY(thr);
17270 	DUK_ASSERT(key != NULL);
17271 
17272 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17273 	(void) duk_push_lstring(thr, key, key_len);
17274 	return duk_del_prop(thr, obj_idx);
17275 }
17276 
17277 #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)17278 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) {
17279 	DUK_ASSERT_API_ENTRY(thr);
17280 	DUK_ASSERT(key != NULL);
17281 	DUK_ASSERT(key[key_len] == (char) 0);
17282 
17283 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17284 	(void) duk_push_literal_raw(thr, key, key_len);
17285 	return duk_del_prop(thr, obj_idx);
17286 }
17287 #endif
17288 
duk_del_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx)17289 DUK_EXTERNAL duk_bool_t duk_del_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
17290 	DUK_ASSERT_API_ENTRY(thr);
17291 
17292 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17293 	duk_push_uarridx(thr, arr_idx);
17294 	return duk_del_prop(thr, obj_idx);
17295 }
17296 
duk_del_prop_heapptr(duk_hthread * thr,duk_idx_t obj_idx,void * ptr)17297 DUK_EXTERNAL duk_bool_t duk_del_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
17298 	DUK_ASSERT_API_ENTRY(thr);
17299 
17300 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17301 	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
17302 	return duk_del_prop(thr, obj_idx);
17303 }
17304 
duk_del_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)17305 DUK_INTERNAL duk_bool_t duk_del_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
17306 	DUK_ASSERT_API_ENTRY(thr);
17307 	DUK_ASSERT_STRIDX_VALID(stridx);
17308 
17309 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17310 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
17311 	return duk_del_prop(thr, obj_idx);
17312 }
17313 
17314 #if 0
17315 DUK_INTERNAL duk_bool_t duk_del_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
17316 	return duk_del_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
17317 	                                (duk_small_uint_t) (packed_args & 0xffffUL));
17318 }
17319 #endif
17320 
duk_has_prop(duk_hthread * thr,duk_idx_t obj_idx)17321 DUK_EXTERNAL duk_bool_t duk_has_prop(duk_hthread *thr, duk_idx_t obj_idx) {
17322 	duk_tval *tv_obj;
17323 	duk_tval *tv_key;
17324 	duk_bool_t rc;
17325 
17326 	DUK_ASSERT_API_ENTRY(thr);
17327 
17328 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
17329 	 * resize is not necessary for a property existence check right now.
17330 	 */
17331 
17332 	tv_obj = duk_require_tval(thr, obj_idx);
17333 	tv_key = duk_require_tval(thr, -1);
17334 
17335 	rc = duk_hobject_hasprop(thr, tv_obj, tv_key);
17336 	DUK_ASSERT(rc == 0 || rc == 1);
17337 
17338 	duk_pop(thr);  /* remove key */
17339 	return rc;  /* 1 if property found, 0 otherwise */
17340 }
17341 
duk_has_prop_string(duk_hthread * thr,duk_idx_t obj_idx,const char * key)17342 DUK_EXTERNAL duk_bool_t duk_has_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
17343 	DUK_ASSERT_API_ENTRY(thr);
17344 	DUK_ASSERT(key != NULL);
17345 
17346 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17347 	(void) duk_push_string(thr, key);
17348 	return duk_has_prop(thr, obj_idx);
17349 }
17350 
duk_has_prop_lstring(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)17351 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) {
17352 	DUK_ASSERT_API_ENTRY(thr);
17353 	DUK_ASSERT(key != NULL);
17354 
17355 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17356 	(void) duk_push_lstring(thr, key, key_len);
17357 	return duk_has_prop(thr, obj_idx);
17358 }
17359 
17360 #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)17361 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) {
17362 	DUK_ASSERT_API_ENTRY(thr);
17363 	DUK_ASSERT(key != NULL);
17364 	DUK_ASSERT(key[key_len] == (char) 0);
17365 
17366 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17367 	(void) duk_push_literal_raw(thr, key, key_len);
17368 	return duk_has_prop(thr, obj_idx);
17369 }
17370 #endif
17371 
duk_has_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx)17372 DUK_EXTERNAL duk_bool_t duk_has_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
17373 	DUK_ASSERT_API_ENTRY(thr);
17374 
17375 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17376 	duk_push_uarridx(thr, arr_idx);
17377 	return duk_has_prop(thr, obj_idx);
17378 }
17379 
duk_has_prop_heapptr(duk_hthread * thr,duk_idx_t obj_idx,void * ptr)17380 DUK_EXTERNAL duk_bool_t duk_has_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
17381 	DUK_ASSERT_API_ENTRY(thr);
17382 
17383 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17384 	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
17385 	return duk_has_prop(thr, obj_idx);
17386 }
17387 
duk_has_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)17388 DUK_INTERNAL duk_bool_t duk_has_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
17389 	DUK_ASSERT_API_ENTRY(thr);
17390 	DUK_ASSERT_STRIDX_VALID(stridx);
17391 
17392 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17393 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
17394 	return duk_has_prop(thr, obj_idx);
17395 }
17396 
17397 #if 0
17398 DUK_INTERNAL duk_bool_t duk_has_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
17399 	return duk_has_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
17400 	                                (duk_small_uint_t) (packed_args & 0xffffUL));
17401 }
17402 #endif
17403 
17404 /* Define own property without inheritance lookups and such.  This differs from
17405  * [[DefineOwnProperty]] because special behaviors (like Array 'length') are
17406  * not invoked by this method.  The caller must be careful to invoke any such
17407  * behaviors if necessary.
17408  */
duk_xdef_prop(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t desc_flags)17409 DUK_INTERNAL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t desc_flags) {
17410 	duk_hobject *obj;
17411 	duk_hstring *key;
17412 
17413 	DUK_ASSERT_API_ENTRY(thr);
17414 
17415 	obj = duk_require_hobject(thr, obj_idx);
17416 	DUK_ASSERT(obj != NULL);
17417 	key = duk_to_property_key_hstring(thr, -2);
17418 	DUK_ASSERT(key != NULL);
17419 	DUK_ASSERT(duk_require_tval(thr, -1) != NULL);
17420 
17421 	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
17422 
17423 	duk_pop(thr);  /* pop key */
17424 }
17425 
duk_xdef_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx,duk_small_uint_t desc_flags)17426 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) {
17427 	duk_hobject *obj;
17428 
17429 	DUK_ASSERT_API_ENTRY(thr);
17430 
17431 	obj = duk_require_hobject(thr, obj_idx);
17432 	DUK_ASSERT(obj != NULL);
17433 
17434 	duk_hobject_define_property_internal_arridx(thr, obj, arr_idx, desc_flags);
17435 	/* value popped by call */
17436 }
17437 
duk_xdef_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx,duk_small_uint_t desc_flags)17438 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) {
17439 	duk_hobject *obj;
17440 	duk_hstring *key;
17441 
17442 	DUK_ASSERT_API_ENTRY(thr);
17443 	DUK_ASSERT_STRIDX_VALID(stridx);
17444 
17445 	obj = duk_require_hobject(thr, obj_idx);
17446 	DUK_ASSERT(obj != NULL);
17447 	key = DUK_HTHREAD_GET_STRING(thr, stridx);
17448 	DUK_ASSERT(key != NULL);
17449 	DUK_ASSERT(duk_require_tval(thr, -1) != NULL);
17450 
17451 	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
17452 	/* value popped by call */
17453 }
17454 
duk_xdef_prop_stridx_short_raw(duk_hthread * thr,duk_uint_t packed_args)17455 DUK_INTERNAL void duk_xdef_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
17456 	duk_xdef_prop_stridx(thr, (duk_idx_t) (duk_int8_t) (packed_args >> 24),
17457 	                          (duk_small_uint_t) (packed_args >> 8) & 0xffffUL,
17458 	                          (duk_small_uint_t) (packed_args & 0xffL));
17459 }
17460 
17461 #if 0  /*unused*/
17462 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) {
17463 	duk_hobject *obj;
17464 	duk_hstring *key;
17465 
17466 	DUK_ASSERT_API_ENTRY(thr);
17467 	DUK_ASSERT_STRIDX_VALID(stridx);
17468 	DUK_ASSERT_BIDX_VALID(builtin_idx);
17469 
17470 	obj = duk_require_hobject(thr, obj_idx);
17471 	DUK_ASSERT(obj != NULL);
17472 	key = DUK_HTHREAD_GET_STRING(thr, stridx);
17473 	DUK_ASSERT(key != NULL);
17474 
17475 	duk_push_hobject(thr, thr->builtins[builtin_idx]);
17476 	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
17477 	/* value popped by call */
17478 }
17479 #endif
17480 
17481 /* This is a rare property helper; it sets the global thrower (E5 Section 13.2.3)
17482  * setter/getter into an object property.  This is needed by the 'arguments'
17483  * object creation code, function instance creation code, and Function.prototype.bind().
17484  */
17485 
duk_xdef_prop_stridx_thrower(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)17486 DUK_INTERNAL void duk_xdef_prop_stridx_thrower(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
17487 	DUK_ASSERT_API_ENTRY(thr);
17488 
17489 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17490 	duk_push_hstring_stridx(thr, stridx);
17491 	duk_push_hobject_bidx(thr, DUK_BIDX_TYPE_ERROR_THROWER);
17492 	duk_dup_top(thr);
17493 	duk_def_prop(thr, obj_idx, DUK_DEFPROP_HAVE_SETTER | DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_FORCE);  /* attributes always 0 */
17494 }
17495 
17496 /* Object.getOwnPropertyDescriptor() equivalent C binding. */
duk_get_prop_desc(duk_hthread * thr,duk_idx_t obj_idx,duk_uint_t flags)17497 DUK_EXTERNAL void duk_get_prop_desc(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t flags) {
17498 	DUK_ASSERT_API_ENTRY(thr);
17499 	DUK_UNREF(flags);  /* no flags defined yet */
17500 
17501 	duk_hobject_object_get_own_property_descriptor(thr, obj_idx);  /* [ ... key ] -> [ ... desc ] */
17502 }
17503 
17504 /* Object.defineProperty() equivalent C binding. */
duk_def_prop(duk_hthread * thr,duk_idx_t obj_idx,duk_uint_t flags)17505 DUK_EXTERNAL void duk_def_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t flags) {
17506 	duk_idx_t idx_base;
17507 	duk_hobject *obj;
17508 	duk_hstring *key;
17509 	duk_idx_t idx_value;
17510 	duk_hobject *get;
17511 	duk_hobject *set;
17512 	duk_uint_t is_data_desc;
17513 	duk_uint_t is_acc_desc;
17514 
17515 	DUK_ASSERT_API_ENTRY(thr);
17516 
17517 	obj = duk_require_hobject(thr, obj_idx);
17518 
17519 	is_data_desc = flags & (DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);
17520 	is_acc_desc = flags & (DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
17521 	if (is_data_desc && is_acc_desc) {
17522 		/* "Have" flags must not be conflicting so that they would
17523 		 * apply to both a plain property and an accessor at the same
17524 		 * time.
17525 		 */
17526 		goto fail_invalid_desc;
17527 	}
17528 
17529 	idx_base = duk_get_top_index(thr);
17530 	if (flags & DUK_DEFPROP_HAVE_SETTER) {
17531 		duk_require_type_mask(thr, idx_base, DUK_TYPE_MASK_UNDEFINED |
17532 		                                     DUK_TYPE_MASK_OBJECT |
17533 		                                     DUK_TYPE_MASK_LIGHTFUNC);
17534 		set = duk_get_hobject_promote_lfunc(thr, idx_base);
17535 		if (set != NULL && !DUK_HOBJECT_IS_CALLABLE(set)) {
17536 			goto fail_not_callable;
17537 		}
17538 		idx_base--;
17539 	} else {
17540 		set = NULL;
17541 	}
17542 	if (flags & DUK_DEFPROP_HAVE_GETTER) {
17543 		duk_require_type_mask(thr, idx_base, DUK_TYPE_MASK_UNDEFINED |
17544 		                                     DUK_TYPE_MASK_OBJECT |
17545 		                                     DUK_TYPE_MASK_LIGHTFUNC);
17546 		get = duk_get_hobject_promote_lfunc(thr, idx_base);
17547 		if (get != NULL && !DUK_HOBJECT_IS_CALLABLE(get)) {
17548 			goto fail_not_callable;
17549 		}
17550 		idx_base--;
17551 	} else {
17552 		get = NULL;
17553 	}
17554 	if (flags & DUK_DEFPROP_HAVE_VALUE) {
17555 		idx_value = idx_base;
17556 		idx_base--;
17557 	} else {
17558 		idx_value = (duk_idx_t) -1;
17559 	}
17560 	key = duk_to_property_key_hstring(thr, idx_base);
17561 	DUK_ASSERT(key != NULL);
17562 
17563 	duk_require_valid_index(thr, idx_base);
17564 
17565 	duk_hobject_define_property_helper(thr,
17566 	                                   flags /*defprop_flags*/,
17567 	                                   obj,
17568 	                                   key,
17569 	                                   idx_value,
17570 	                                   get,
17571 	                                   set,
17572 	                                   1 /*throw_flag*/);
17573 
17574 	/* Clean up stack */
17575 
17576 	duk_set_top(thr, idx_base);
17577 
17578 	/* [ ... obj ... ] */
17579 
17580 	return;
17581 
17582  fail_invalid_desc:
17583 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);
17584 	DUK_WO_NORETURN(return;);
17585 
17586  fail_not_callable:
17587 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
17588 	DUK_WO_NORETURN(return;);
17589 }
17590 
17591 /*
17592  *  Object related
17593  */
17594 
duk_compact(duk_hthread * thr,duk_idx_t obj_idx)17595 DUK_EXTERNAL void duk_compact(duk_hthread *thr, duk_idx_t obj_idx) {
17596 	duk_hobject *obj;
17597 
17598 	DUK_ASSERT_API_ENTRY(thr);
17599 
17600 	obj = duk_get_hobject(thr, obj_idx);
17601 	if (obj) {
17602 		/* Note: this may fail, caller should protect the call if necessary */
17603 		duk_hobject_compact_props(thr, obj);
17604 	}
17605 }
17606 
duk_compact_m1(duk_hthread * thr)17607 DUK_INTERNAL void duk_compact_m1(duk_hthread *thr) {
17608 	DUK_ASSERT_API_ENTRY(thr);
17609 
17610 	duk_compact(thr, -1);
17611 }
17612 
17613 /* XXX: the duk_hobject_enum.c stack APIs should be reworked */
17614 
duk_enum(duk_hthread * thr,duk_idx_t obj_idx,duk_uint_t enum_flags)17615 DUK_EXTERNAL void duk_enum(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t enum_flags) {
17616 	DUK_ASSERT_API_ENTRY(thr);
17617 
17618 	duk_dup(thr, obj_idx);
17619 	duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
17620 	duk_hobject_enumerator_create(thr, enum_flags);   /* [target] -> [enum] */
17621 }
17622 
duk_next(duk_hthread * thr,duk_idx_t enum_index,duk_bool_t get_value)17623 DUK_EXTERNAL duk_bool_t duk_next(duk_hthread *thr, duk_idx_t enum_index, duk_bool_t get_value) {
17624 	DUK_ASSERT_API_ENTRY(thr);
17625 
17626 	duk_require_hobject(thr, enum_index);
17627 	duk_dup(thr, enum_index);
17628 	return duk_hobject_enumerator_next(thr, get_value);
17629 }
17630 
duk_seal_freeze_raw(duk_hthread * thr,duk_idx_t obj_idx,duk_bool_t is_freeze)17631 DUK_INTERNAL void duk_seal_freeze_raw(duk_hthread *thr, duk_idx_t obj_idx, duk_bool_t is_freeze) {
17632 	duk_tval *tv;
17633 	duk_hobject *h;
17634 
17635 	DUK_ASSERT_API_ENTRY(thr);
17636 
17637 	tv = duk_require_tval(thr, obj_idx);
17638 	DUK_ASSERT(tv != NULL);
17639 
17640 	/* Seal/freeze are quite rare in practice so it'd be nice to get the
17641 	 * correct behavior simply via automatic promotion (at the cost of some
17642 	 * memory churn).  However, the promoted objects don't behave the same,
17643 	 * e.g. promoted lightfuncs are extensible.
17644 	 */
17645 
17646 	switch (DUK_TVAL_GET_TAG(tv)) {
17647 	case DUK_TAG_BUFFER:
17648 		/* Plain buffer: already sealed, but not frozen (and can't be frozen
17649 		 * because index properties can't be made non-writable.
17650 		 */
17651 		if (is_freeze) {
17652 			goto fail_cannot_freeze;
17653 		}
17654 		break;
17655 	case DUK_TAG_LIGHTFUNC:
17656 		/* Lightfunc: already sealed and frozen, success. */
17657 		break;
17658 	case DUK_TAG_OBJECT:
17659 		h = DUK_TVAL_GET_OBJECT(tv);
17660 		DUK_ASSERT(h != NULL);
17661 		if (is_freeze && DUK_HOBJECT_IS_BUFOBJ(h)) {
17662 			/* Buffer objects cannot be frozen because there's no internal
17663 			 * support for making virtual array indices non-writable.
17664 			 */
17665 			DUK_DD(DUK_DDPRINT("cannot freeze a buffer object"));
17666 			goto fail_cannot_freeze;
17667 		}
17668 		duk_hobject_object_seal_freeze_helper(thr, h, is_freeze);
17669 
17670 		/* Sealed and frozen objects cannot gain any more properties,
17671 		 * so this is a good time to compact them.
17672 		 */
17673 		duk_hobject_compact_props(thr, h);
17674 		break;
17675 	default:
17676 		/* ES2015 Sections 19.1.2.5, 19.1.2.17 */
17677 		break;
17678 	}
17679 	return;
17680 
17681  fail_cannot_freeze:
17682 	DUK_ERROR_TYPE_INVALID_ARGS(thr);  /* XXX: proper error message */
17683 	DUK_WO_NORETURN(return;);
17684 }
17685 
duk_seal(duk_hthread * thr,duk_idx_t obj_idx)17686 DUK_EXTERNAL void duk_seal(duk_hthread *thr, duk_idx_t obj_idx) {
17687 	DUK_ASSERT_API_ENTRY(thr);
17688 
17689 	duk_seal_freeze_raw(thr, obj_idx, 0 /*is_freeze*/);
17690 }
17691 
duk_freeze(duk_hthread * thr,duk_idx_t obj_idx)17692 DUK_EXTERNAL void duk_freeze(duk_hthread *thr, duk_idx_t obj_idx) {
17693 	DUK_ASSERT_API_ENTRY(thr);
17694 
17695 	duk_seal_freeze_raw(thr, obj_idx, 1 /*is_freeze*/);
17696 }
17697 
17698 /*
17699  *  Helpers for writing multiple properties
17700  */
17701 
duk_put_function_list(duk_hthread * thr,duk_idx_t obj_idx,const duk_function_list_entry * funcs)17702 DUK_EXTERNAL void duk_put_function_list(duk_hthread *thr, duk_idx_t obj_idx, const duk_function_list_entry *funcs) {
17703 	const duk_function_list_entry *ent = funcs;
17704 
17705 	DUK_ASSERT_API_ENTRY(thr);
17706 
17707 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17708 	if (ent != NULL) {
17709 		while (ent->key != NULL) {
17710 			duk_push_c_function(thr, ent->value, ent->nargs);
17711 			duk_put_prop_string(thr, obj_idx, ent->key);
17712 			ent++;
17713 		}
17714 	}
17715 }
17716 
duk_put_number_list(duk_hthread * thr,duk_idx_t obj_idx,const duk_number_list_entry * numbers)17717 DUK_EXTERNAL void duk_put_number_list(duk_hthread *thr, duk_idx_t obj_idx, const duk_number_list_entry *numbers) {
17718 	const duk_number_list_entry *ent = numbers;
17719 	duk_tval *tv;
17720 
17721 	DUK_ASSERT_API_ENTRY(thr);
17722 
17723 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17724 	if (ent != NULL) {
17725 		while (ent->key != NULL) {
17726 			tv = thr->valstack_top++;
17727 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));  /* value stack init policy */
17728 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, ent->value);  /* no need for decref/incref */
17729 			duk_put_prop_string(thr, obj_idx, ent->key);
17730 			ent++;
17731 		}
17732 	}
17733 }
17734 
17735 /*
17736  *  Shortcut for accessing global object properties
17737  */
17738 
duk_get_global_string(duk_hthread * thr,const char * key)17739 DUK_EXTERNAL duk_bool_t duk_get_global_string(duk_hthread *thr, const char *key) {
17740 	duk_bool_t ret;
17741 
17742 	DUK_ASSERT_API_ENTRY(thr);
17743 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17744 
17745 	/* XXX: direct implementation */
17746 
17747 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17748 	ret = duk_get_prop_string(thr, -1, key);
17749 	duk_remove_m2(thr);
17750 	return ret;
17751 }
17752 
duk_get_global_lstring(duk_hthread * thr,const char * key,duk_size_t key_len)17753 DUK_EXTERNAL duk_bool_t duk_get_global_lstring(duk_hthread *thr, const char *key, duk_size_t key_len) {
17754 	duk_bool_t ret;
17755 
17756 	DUK_ASSERT_API_ENTRY(thr);
17757 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17758 
17759 	/* XXX: direct implementation */
17760 
17761 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17762 	ret = duk_get_prop_lstring(thr, -1, key, key_len);
17763 	duk_remove_m2(thr);
17764 	return ret;
17765 }
17766 
17767 #if !defined(DUK_USE_PREFER_SIZE)
duk_get_global_literal_raw(duk_hthread * thr,const char * key,duk_size_t key_len)17768 DUK_EXTERNAL duk_bool_t duk_get_global_literal_raw(duk_hthread *thr, const char *key, duk_size_t key_len) {
17769 	duk_bool_t ret;
17770 
17771 	DUK_ASSERT_API_ENTRY(thr);
17772 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17773 	DUK_ASSERT(key[key_len] == (char) 0);
17774 
17775 	/* XXX: direct implementation */
17776 
17777 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17778 	ret = duk_get_prop_literal_raw(thr, -1, key, key_len);
17779 	duk_remove_m2(thr);
17780 	return ret;
17781 }
17782 #endif
17783 
duk_get_global_heapptr(duk_hthread * thr,void * ptr)17784 DUK_EXTERNAL duk_bool_t duk_get_global_heapptr(duk_hthread *thr, void *ptr) {
17785 	duk_bool_t ret;
17786 
17787 	DUK_ASSERT_API_ENTRY(thr);
17788 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17789 
17790 	/* XXX: direct implementation */
17791 
17792 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17793 	ret = duk_get_prop_heapptr(thr, -1, ptr);
17794 	duk_remove_m2(thr);
17795 	return ret;
17796 }
17797 
17798 
duk_put_global_string(duk_hthread * thr,const char * key)17799 DUK_EXTERNAL duk_bool_t duk_put_global_string(duk_hthread *thr, const char *key) {
17800 	duk_bool_t ret;
17801 
17802 	DUK_ASSERT_API_ENTRY(thr);
17803 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17804 
17805 	/* XXX: direct implementation */
17806 
17807 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17808 	duk_insert(thr, -2);
17809 	ret = duk_put_prop_string(thr, -2, key);  /* [ ... global val ] -> [ ... global ] */
17810 	duk_pop(thr);
17811 	return ret;
17812 }
17813 
duk_put_global_lstring(duk_hthread * thr,const char * key,duk_size_t key_len)17814 DUK_EXTERNAL duk_bool_t duk_put_global_lstring(duk_hthread *thr, const char *key, duk_size_t key_len) {
17815 	duk_bool_t ret;
17816 
17817 	DUK_ASSERT_API_ENTRY(thr);
17818 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17819 
17820 	/* XXX: direct implementation */
17821 
17822 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17823 	duk_insert(thr, -2);
17824 	ret = duk_put_prop_lstring(thr, -2, key, key_len);  /* [ ... global val ] -> [ ... global ] */
17825 	duk_pop(thr);
17826 	return ret;
17827 }
17828 
17829 #if !defined(DUK_USE_PREFER_SIZE)
duk_put_global_literal_raw(duk_hthread * thr,const char * key,duk_size_t key_len)17830 DUK_EXTERNAL duk_bool_t duk_put_global_literal_raw(duk_hthread *thr, const char *key, duk_size_t key_len) {
17831 	duk_bool_t ret;
17832 
17833 	DUK_ASSERT_API_ENTRY(thr);
17834 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17835 	DUK_ASSERT(key[key_len] == (char) 0);
17836 
17837 	/* XXX: direct implementation */
17838 
17839 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17840 	duk_insert(thr, -2);
17841 	ret = duk_put_prop_literal_raw(thr, -2, key, key_len);  /* [ ... global val ] -> [ ... global ] */
17842 	duk_pop(thr);
17843 	return ret;
17844 }
17845 #endif
17846 
duk_put_global_heapptr(duk_hthread * thr,void * ptr)17847 DUK_EXTERNAL duk_bool_t duk_put_global_heapptr(duk_hthread *thr, void *ptr) {
17848 	duk_bool_t ret;
17849 
17850 	DUK_ASSERT_API_ENTRY(thr);
17851 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17852 
17853 	/* XXX: direct implementation */
17854 
17855 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17856 	duk_insert(thr, -2);
17857 	ret = duk_put_prop_heapptr(thr, -2, ptr);  /* [ ... global val ] -> [ ... global ] */
17858 	duk_pop(thr);
17859 	return ret;
17860 }
17861 
17862 /*
17863  *  ES2015 GetMethod()
17864  */
17865 
duk_get_method_stridx(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t stridx)17866 DUK_INTERNAL duk_bool_t duk_get_method_stridx(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t stridx) {
17867 	(void) duk_get_prop_stridx(thr, idx, stridx);
17868 	if (duk_is_null_or_undefined(thr, -1)) {
17869 		duk_pop_nodecref_unsafe(thr);
17870 		return 0;
17871 	}
17872 	if (!duk_is_callable(thr, -1)) {
17873 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
17874 		DUK_WO_NORETURN(return 0;);
17875 	}
17876 	return 1;
17877 }
17878 
17879 /*
17880  *  Object prototype
17881  */
17882 
duk_get_prototype(duk_hthread * thr,duk_idx_t idx)17883 DUK_EXTERNAL void duk_get_prototype(duk_hthread *thr, duk_idx_t idx) {
17884 	duk_hobject *obj;
17885 	duk_hobject *proto;
17886 
17887 	DUK_ASSERT_API_ENTRY(thr);
17888 
17889 	obj = duk_require_hobject(thr, idx);
17890 	DUK_ASSERT(obj != NULL);
17891 
17892 	/* XXX: shared helper for duk_push_hobject_or_undefined()? */
17893 	proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, obj);
17894 	if (proto) {
17895 		duk_push_hobject(thr, proto);
17896 	} else {
17897 		duk_push_undefined(thr);
17898 	}
17899 }
17900 
duk_set_prototype(duk_hthread * thr,duk_idx_t idx)17901 DUK_EXTERNAL void duk_set_prototype(duk_hthread *thr, duk_idx_t idx) {
17902 	duk_hobject *obj;
17903 	duk_hobject *proto;
17904 
17905 	DUK_ASSERT_API_ENTRY(thr);
17906 
17907 	obj = duk_require_hobject(thr, idx);
17908 	DUK_ASSERT(obj != NULL);
17909 	duk_require_type_mask(thr, -1, DUK_TYPE_MASK_UNDEFINED |
17910 	                               DUK_TYPE_MASK_OBJECT);
17911 	proto = duk_get_hobject(thr, -1);
17912 	/* proto can also be NULL here (allowed explicitly) */
17913 
17914 #if defined(DUK_USE_ROM_OBJECTS)
17915 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
17916 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);  /* XXX: "read only object"? */
17917 		DUK_WO_NORETURN(return;);
17918 	}
17919 #endif
17920 
17921 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, obj, proto);
17922 
17923 	duk_pop(thr);
17924 }
17925 
duk_clear_prototype(duk_hthread * thr,duk_idx_t idx)17926 DUK_INTERNAL void duk_clear_prototype(duk_hthread *thr, duk_idx_t idx) {
17927 	duk_hobject *obj;
17928 
17929 	DUK_ASSERT_API_ENTRY(thr);
17930 
17931 	obj = duk_require_hobject(thr, idx);
17932 	DUK_ASSERT(obj != NULL);
17933 
17934 #if defined(DUK_USE_ROM_OBJECTS)
17935 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
17936 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);  /* XXX: "read only object"? */
17937 		DUK_WO_NORETURN(return;);
17938 	}
17939 #endif
17940 
17941 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, obj, NULL);
17942 }
17943 
duk_is_bare_object(duk_hthread * thr,duk_idx_t idx)17944 DUK_INTERNAL duk_bool_t duk_is_bare_object(duk_hthread *thr, duk_idx_t idx) {
17945 	duk_hobject *obj;
17946 	duk_hobject *proto;
17947 
17948 	DUK_ASSERT_API_ENTRY(thr);
17949 
17950 	obj = duk_require_hobject(thr, idx);
17951 	DUK_ASSERT(obj != NULL);
17952 
17953 	proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, obj);
17954 	return (proto == NULL);
17955 }
17956 
17957 /*
17958  *  Object finalizer
17959  */
17960 
17961 #if defined(DUK_USE_FINALIZER_SUPPORT)
17962 /* XXX: these could be implemented as macros calling an internal function
17963  * directly.
17964  * XXX: same issue as with Duktape.fin: there's no way to delete the property
17965  * now (just set it to undefined).
17966  */
duk_get_finalizer(duk_hthread * thr,duk_idx_t idx)17967 DUK_EXTERNAL void duk_get_finalizer(duk_hthread *thr, duk_idx_t idx) {
17968 	DUK_ASSERT_API_ENTRY(thr);
17969 
17970 	/* This get intentionally walks the inheritance chain at present,
17971 	 * which matches how the effective finalizer property is also
17972 	 * looked up in GC.
17973 	 */
17974 	duk_get_prop_stridx(thr, idx, DUK_STRIDX_INT_FINALIZER);
17975 }
17976 
duk_set_finalizer(duk_hthread * thr,duk_idx_t idx)17977 DUK_EXTERNAL void duk_set_finalizer(duk_hthread *thr, duk_idx_t idx) {
17978 	duk_hobject *h;
17979 	duk_bool_t callable;
17980 
17981 	DUK_ASSERT_API_ENTRY(thr);
17982 
17983 	h = duk_require_hobject(thr, idx);  /* Get before 'put' so that 'idx' is correct. */
17984 	callable = duk_is_callable(thr, -1);
17985 
17986 	/* At present finalizer is stored as a hidden Symbol, with normal
17987 	 * inheritance and access control.  As a result, finalizer cannot
17988 	 * currently be set on a non-extensible (sealed or frozen) object.
17989 	 * It might be useful to allow it.
17990 	 */
17991 	duk_put_prop_stridx(thr, idx, DUK_STRIDX_INT_FINALIZER);
17992 
17993 	/* In addition to setting the finalizer property, keep a "have
17994 	 * finalizer" flag in duk_hobject in sync so that refzero can do
17995 	 * a very quick finalizer check by walking the prototype chain
17996 	 * and checking the flag alone.  (Note that this means that just
17997 	 * setting _Finalizer on an object won't affect finalizer checks.)
17998 	 *
17999 	 * NOTE: if the argument is a Proxy object, this flag will be set
18000 	 * on the Proxy, not the target.  As a result, the target won't get
18001 	 * a finalizer flag and the Proxy also won't be finalized as there's
18002 	 * an explicit Proxy check in finalization now.
18003 	 */
18004 	if (callable) {
18005 		DUK_HOBJECT_SET_HAVE_FINALIZER(h);
18006 	} else {
18007 		DUK_HOBJECT_CLEAR_HAVE_FINALIZER(h);
18008 	}
18009 }
18010 #else  /* DUK_USE_FINALIZER_SUPPORT */
duk_get_finalizer(duk_hthread * thr,duk_idx_t idx)18011 DUK_EXTERNAL void duk_get_finalizer(duk_hthread *thr, duk_idx_t idx) {
18012 	DUK_ASSERT_API_ENTRY(thr);
18013 	DUK_UNREF(idx);
18014 	DUK_ERROR_UNSUPPORTED(thr);
18015 	DUK_WO_NORETURN(return;);
18016 }
18017 
duk_set_finalizer(duk_hthread * thr,duk_idx_t idx)18018 DUK_EXTERNAL void duk_set_finalizer(duk_hthread *thr, duk_idx_t idx) {
18019 	DUK_ASSERT_API_ENTRY(thr);
18020 	DUK_UNREF(idx);
18021 	DUK_ERROR_UNSUPPORTED(thr);
18022 	DUK_WO_NORETURN(return;);
18023 }
18024 #endif  /* DUK_USE_FINALIZER_SUPPORT */
18025 #line 1 "duk_api_random.c"
18026 /*
18027  *  Random numbers
18028  */
18029 
18030 /* #include duk_internal.h -> already included */
18031 
duk_random(duk_hthread * thr)18032 DUK_EXTERNAL duk_double_t duk_random(duk_hthread *thr) {
18033 	return (duk_double_t) DUK_UTIL_GET_RANDOM_DOUBLE(thr);
18034 }
18035 #line 1 "duk_api_stack.c"
18036 /*
18037  *  API calls related to general value stack manipulation: resizing the value
18038  *  stack, pushing and popping values, type checking and reading values,
18039  *  coercing values, etc.
18040  *
18041  *  Also contains internal functions (such as duk_get_tval()), defined
18042  *  in duk_api_internal.h, with semantics similar to the public API.
18043  */
18044 
18045 /* XXX: repetition of stack pre-checks -> helper or macro or inline */
18046 /* XXX: shared api error strings, and perhaps even throw code for rare cases? */
18047 
18048 /* #include duk_internal.h -> already included */
18049 
18050 /*
18051  *  Forward declarations
18052  */
18053 
18054 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);
18055 
18056 /*
18057  *  Global state for working around missing variadic macros
18058  */
18059 
18060 #if !defined(DUK_USE_VARIADIC_MACROS)
18061 DUK_EXTERNAL const char *duk_api_global_filename = NULL;
18062 DUK_EXTERNAL duk_int_t duk_api_global_line = 0;
18063 #endif
18064 
18065 /*
18066  *  Misc helpers
18067  */
18068 
18069 DUK_LOCAL const char * const duk__symbol_type_strings[4] = {
18070 	"hidden", "global", "local", "wellknown"
18071 };
18072 
18073 #if !defined(DUK_USE_PACKED_TVAL)
18074 DUK_LOCAL const duk_uint_t duk__type_from_tag[] = {
18075 	DUK_TYPE_NUMBER,
18076 	DUK_TYPE_NUMBER,  /* fastint */
18077 	DUK_TYPE_UNDEFINED,
18078 	DUK_TYPE_NULL,
18079 	DUK_TYPE_BOOLEAN,
18080 	DUK_TYPE_POINTER,
18081 	DUK_TYPE_LIGHTFUNC,
18082 	DUK_TYPE_NONE,
18083 	DUK_TYPE_STRING,
18084 	DUK_TYPE_OBJECT,
18085 	DUK_TYPE_BUFFER,
18086 };
18087 DUK_LOCAL const duk_uint_t duk__type_mask_from_tag[] = {
18088 	DUK_TYPE_MASK_NUMBER,
18089 	DUK_TYPE_MASK_NUMBER,  /* fastint */
18090 	DUK_TYPE_MASK_UNDEFINED,
18091 	DUK_TYPE_MASK_NULL,
18092 	DUK_TYPE_MASK_BOOLEAN,
18093 	DUK_TYPE_MASK_POINTER,
18094 	DUK_TYPE_MASK_LIGHTFUNC,
18095 	DUK_TYPE_MASK_NONE,
18096 	DUK_TYPE_MASK_STRING,
18097 	DUK_TYPE_MASK_OBJECT,
18098 	DUK_TYPE_MASK_BUFFER,
18099 };
18100 #endif  /* !DUK_USE_PACKED_TVAL */
18101 
18102 /* Assert that there's room for one value. */
18103 #define DUK__ASSERT_SPACE() do { \
18104 		DUK_ASSERT(!(thr->valstack_top >= thr->valstack_end)); \
18105 	} while (0)
18106 
18107 /* Check that there's room to push one value. */
18108 #if defined(DUK_USE_VALSTACK_UNSAFE)
18109 /* Faster but value stack overruns are memory unsafe. */
18110 #define DUK__CHECK_SPACE() DUK__ASSERT_SPACE()
18111 #else
18112 #define DUK__CHECK_SPACE() do { \
18113 		if (DUK_UNLIKELY(thr->valstack_top >= thr->valstack_end)) { \
18114 			DUK_ERROR_RANGE_PUSH_BEYOND(thr); \
18115 		} \
18116 	} while (0)
18117 #endif
18118 
duk__get_symbol_type(duk_hstring * h)18119 DUK_LOCAL duk_small_uint_t duk__get_symbol_type(duk_hstring *h) {
18120 	const duk_uint8_t *data;
18121 	duk_size_t len;
18122 
18123 	DUK_ASSERT(h != NULL);
18124 	DUK_ASSERT(DUK_HSTRING_HAS_SYMBOL(h));
18125 	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(h) >= 1);  /* always true, symbol prefix */
18126 
18127 	data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
18128 	len = DUK_HSTRING_GET_BYTELEN(h);
18129 	DUK_ASSERT(len >= 1);
18130 
18131 	/* XXX: differentiate between 0x82 and 0xff (hidden vs. internal?)? */
18132 
18133 	if (data[0] == 0xffU) {
18134 		return DUK_SYMBOL_TYPE_HIDDEN;
18135 	} else if (data[0] == 0x82U) {
18136 		return DUK_SYMBOL_TYPE_HIDDEN;
18137 	} else if (data[0] == 0x80U) {
18138 		return DUK_SYMBOL_TYPE_GLOBAL;
18139 	} else if (data[len - 1] != 0xffU) {
18140 		return DUK_SYMBOL_TYPE_LOCAL;
18141 	} else {
18142 		return DUK_SYMBOL_TYPE_WELLKNOWN;
18143 	}
18144 }
18145 
duk__get_symbol_type_string(duk_hstring * h)18146 DUK_LOCAL const char *duk__get_symbol_type_string(duk_hstring *h) {
18147 	duk_small_uint_t idx;
18148 	idx = duk__get_symbol_type(h);
18149 	DUK_ASSERT(idx < sizeof(duk__symbol_type_strings));
18150 	return duk__symbol_type_strings[idx];
18151 }
18152 
18153 DUK_LOCAL_DECL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t tag);
18154 
duk__api_coerce_d2i(duk_hthread * thr,duk_idx_t idx,duk_int_t def_value,duk_bool_t require)18155 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) {
18156 	duk_tval *tv;
18157 	duk_small_int_t c;
18158 	duk_double_t d;
18159 
18160 	tv = duk_get_tval_or_unused(thr, idx);
18161 	DUK_ASSERT(tv != NULL);
18162 
18163 	/*
18164 	 *  Special cases like NaN and +/- Infinity are handled explicitly
18165 	 *  because a plain C coercion from double to int handles these cases
18166 	 *  in undesirable ways.  For instance, NaN may coerce to INT_MIN
18167 	 *  (not zero), and INT_MAX + 1 may coerce to INT_MIN (not INT_MAX).
18168 	 *
18169 	 *  This double-to-int coercion differs from ToInteger() because it
18170 	 *  has a finite range (ToInteger() allows e.g. +/- Infinity).  It
18171 	 *  also differs from ToInt32() because the INT_MIN/INT_MAX clamping
18172 	 *  depends on the size of the int type on the platform.  In particular,
18173 	 *  on platforms with a 64-bit int type, the full range is allowed.
18174 	 */
18175 
18176 #if defined(DUK_USE_FASTINT)
18177 	if (DUK_TVAL_IS_FASTINT(tv)) {
18178 		duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
18179 #if (DUK_INT_MAX <= 0x7fffffffL)
18180 		/* Clamping only necessary for 32-bit ints. */
18181 		if (t < DUK_INT_MIN) {
18182 			t = DUK_INT_MIN;
18183 		} else if (t > DUK_INT_MAX) {
18184 			t = DUK_INT_MAX;
18185 		}
18186 #endif
18187 		return (duk_int_t) t;
18188 	}
18189 #endif
18190 
18191 	if (DUK_TVAL_IS_NUMBER(tv)) {
18192 		d = DUK_TVAL_GET_NUMBER(tv);
18193 		c = (duk_small_int_t) DUK_FPCLASSIFY(d);
18194 		if (c == DUK_FP_NAN) {
18195 			return 0;
18196 		} else if (d < (duk_double_t) DUK_INT_MIN) {
18197 			/* covers -Infinity */
18198 			return DUK_INT_MIN;
18199 		} else if (d > (duk_double_t) DUK_INT_MAX) {
18200 			/* covers +Infinity */
18201 			return DUK_INT_MAX;
18202 		} else {
18203 			/* coerce towards zero */
18204 			return (duk_int_t) d;
18205 		}
18206 	}
18207 
18208 	if (require) {
18209 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
18210 		DUK_WO_NORETURN(return 0;);
18211 	}
18212 
18213 	return def_value;
18214 }
18215 
duk__api_coerce_d2ui(duk_hthread * thr,duk_idx_t idx,duk_uint_t def_value,duk_bool_t require)18216 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) {
18217 	duk_tval *tv;
18218 	duk_small_int_t c;
18219 	duk_double_t d;
18220 
18221 	/* Same as above but for unsigned int range. */
18222 
18223 	tv = duk_get_tval_or_unused(thr, idx);
18224 	DUK_ASSERT(tv != NULL);
18225 
18226 #if defined(DUK_USE_FASTINT)
18227 	if (DUK_TVAL_IS_FASTINT(tv)) {
18228 		duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
18229 		if (t < 0) {
18230 			t = 0;
18231 		}
18232 #if (DUK_UINT_MAX <= 0xffffffffUL)
18233 		/* Clamping only necessary for 32-bit ints. */
18234 		else if (t > DUK_UINT_MAX) {
18235 			t = DUK_UINT_MAX;
18236 		}
18237 #endif
18238 		return (duk_uint_t) t;
18239 	}
18240 #endif
18241 
18242 	if (DUK_TVAL_IS_NUMBER(tv)) {
18243 		d = DUK_TVAL_GET_NUMBER(tv);
18244 		c = (duk_small_int_t) DUK_FPCLASSIFY(d);
18245 		if (c == DUK_FP_NAN) {
18246 			return 0;
18247 		} else if (d < 0.0) {
18248 			/* covers -Infinity */
18249 			return (duk_uint_t) 0;
18250 		} else if (d > (duk_double_t) DUK_UINT_MAX) {
18251 			/* covers +Infinity */
18252 			return (duk_uint_t) DUK_UINT_MAX;
18253 		} else {
18254 			/* coerce towards zero */
18255 			return (duk_uint_t) d;
18256 		}
18257 	}
18258 
18259 	if (require) {
18260 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
18261 		DUK_WO_NORETURN(return 0;);
18262 	}
18263 
18264 	return def_value;
18265 }
18266 
18267 /*
18268  *  Stack index validation/normalization and getting a stack duk_tval ptr.
18269  *
18270  *  These are called by many API entrypoints so the implementations must be
18271  *  fast and "inlined".
18272  *
18273  *  There's some repetition because of this; keep the functions in sync.
18274  */
18275 
duk_normalize_index(duk_hthread * thr,duk_idx_t idx)18276 DUK_EXTERNAL duk_idx_t duk_normalize_index(duk_hthread *thr, duk_idx_t idx) {
18277 	duk_uidx_t vs_size;
18278 	duk_uidx_t uidx;
18279 
18280 	DUK_ASSERT_API_ENTRY(thr);
18281 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
18282 
18283 	/* Care must be taken to avoid pointer wrapping in the index
18284 	 * validation.  For instance, on a 32-bit platform with 8-byte
18285 	 * duk_tval the index 0x20000000UL would wrap the memory space
18286 	 * once.
18287 	 */
18288 
18289 	/* Assume value stack sizes (in elements) fits into duk_idx_t. */
18290 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18291 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
18292 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
18293 
18294 	if (idx < 0) {
18295 		uidx = vs_size + (duk_uidx_t) idx;
18296 	} else {
18297 		/* since index non-negative */
18298 		DUK_ASSERT(idx != DUK_INVALID_INDEX);
18299 		uidx = (duk_uidx_t) idx;
18300 	}
18301 
18302 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
18303 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
18304 
18305 	if (DUK_LIKELY(uidx < vs_size)) {
18306 		return (duk_idx_t) uidx;
18307 	}
18308 	return DUK_INVALID_INDEX;
18309 }
18310 
duk_require_normalize_index(duk_hthread * thr,duk_idx_t idx)18311 DUK_EXTERNAL duk_idx_t duk_require_normalize_index(duk_hthread *thr, duk_idx_t idx) {
18312 	duk_uidx_t vs_size;
18313 	duk_uidx_t uidx;
18314 
18315 	DUK_ASSERT_API_ENTRY(thr);
18316 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
18317 
18318 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18319 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
18320 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
18321 
18322 	if (idx < 0) {
18323 		uidx = vs_size + (duk_uidx_t) idx;
18324 	} else {
18325 		DUK_ASSERT(idx != DUK_INVALID_INDEX);
18326 		uidx = (duk_uidx_t) idx;
18327 	}
18328 
18329 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
18330 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
18331 
18332 	if (DUK_LIKELY(uidx < vs_size)) {
18333 		return (duk_idx_t) uidx;
18334 	}
18335 	DUK_ERROR_RANGE_INDEX(thr, idx);
18336 	DUK_WO_NORETURN(return 0;);
18337 }
18338 
duk_get_tval(duk_hthread * thr,duk_idx_t idx)18339 DUK_INTERNAL duk_tval *duk_get_tval(duk_hthread *thr, duk_idx_t idx) {
18340 	duk_uidx_t vs_size;
18341 	duk_uidx_t uidx;
18342 
18343 	DUK_ASSERT_API_ENTRY(thr);
18344 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
18345 
18346 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18347 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
18348 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
18349 
18350 	if (idx < 0) {
18351 		uidx = vs_size + (duk_uidx_t) idx;
18352 	} else {
18353 		DUK_ASSERT(idx != DUK_INVALID_INDEX);
18354 		uidx = (duk_uidx_t) idx;
18355 	}
18356 
18357 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
18358 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
18359 
18360 	if (DUK_LIKELY(uidx < vs_size)) {
18361 		return thr->valstack_bottom + uidx;
18362 	}
18363 	return NULL;
18364 }
18365 
18366 /* Variant of duk_get_tval() which is guaranteed to return a valid duk_tval
18367  * pointer.  When duk_get_tval() would return NULL, this variant returns a
18368  * pointer to a duk_tval with tag DUK_TAG_UNUSED.  This allows the call site
18369  * to avoid an unnecessary NULL check which sometimes leads to better code.
18370  * The return duk_tval is read only (at least for the UNUSED value).
18371  */
18372 DUK_LOCAL const duk_tval_unused duk__const_tval_unused = DUK_TVAL_UNUSED_INITIALIZER();
18373 
duk_get_tval_or_unused(duk_hthread * thr,duk_idx_t idx)18374 DUK_INTERNAL duk_tval *duk_get_tval_or_unused(duk_hthread *thr, duk_idx_t idx) {
18375 	duk_tval *tv;
18376 
18377 	DUK_ASSERT_API_ENTRY(thr);
18378 
18379 	tv = duk_get_tval(thr, idx);
18380 	if (tv != NULL) {
18381 		return tv;
18382 	}
18383 	return (duk_tval *) DUK_LOSE_CONST(&duk__const_tval_unused);
18384 }
18385 
duk_require_tval(duk_hthread * thr,duk_idx_t idx)18386 DUK_INTERNAL duk_tval *duk_require_tval(duk_hthread *thr, duk_idx_t idx) {
18387 	duk_uidx_t vs_size;
18388 	duk_uidx_t uidx;
18389 
18390 	DUK_ASSERT_API_ENTRY(thr);
18391 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
18392 
18393 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18394 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
18395 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
18396 
18397 	/* Use unsigned arithmetic to optimize comparison. */
18398 	if (idx < 0) {
18399 		uidx = vs_size + (duk_uidx_t) idx;
18400 	} else {
18401 		DUK_ASSERT(idx != DUK_INVALID_INDEX);
18402 		uidx = (duk_uidx_t) idx;
18403 	}
18404 
18405 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
18406 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
18407 
18408 	if (DUK_LIKELY(uidx < vs_size)) {
18409 		return thr->valstack_bottom + uidx;
18410 	}
18411 	DUK_ERROR_RANGE_INDEX(thr, idx);
18412 	DUK_WO_NORETURN(return NULL;);
18413 }
18414 
18415 /* Non-critical. */
duk_is_valid_index(duk_hthread * thr,duk_idx_t idx)18416 DUK_EXTERNAL duk_bool_t duk_is_valid_index(duk_hthread *thr, duk_idx_t idx) {
18417 	DUK_ASSERT_API_ENTRY(thr);
18418 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
18419 
18420 	return (duk_normalize_index(thr, idx) >= 0);
18421 }
18422 
18423 /* Non-critical. */
duk_require_valid_index(duk_hthread * thr,duk_idx_t idx)18424 DUK_EXTERNAL void duk_require_valid_index(duk_hthread *thr, duk_idx_t idx) {
18425 	DUK_ASSERT_API_ENTRY(thr);
18426 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
18427 
18428 	if (DUK_UNLIKELY(duk_normalize_index(thr, idx) < 0)) {
18429 		DUK_ERROR_RANGE_INDEX(thr, idx);
18430 		DUK_WO_NORETURN(return;);
18431 	}
18432 }
18433 
18434 /*
18435  *  Value stack top handling
18436  */
18437 
duk_get_top(duk_hthread * thr)18438 DUK_EXTERNAL duk_idx_t duk_get_top(duk_hthread *thr) {
18439 	DUK_ASSERT_API_ENTRY(thr);
18440 
18441 	return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
18442 }
18443 
18444 /* Internal helper to get current top but to require a minimum top value
18445  * (TypeError if not met).
18446  */
duk_get_top_require_min(duk_hthread * thr,duk_idx_t min_top)18447 DUK_INTERNAL duk_idx_t duk_get_top_require_min(duk_hthread *thr, duk_idx_t min_top) {
18448 	duk_idx_t ret;
18449 
18450 	DUK_ASSERT_API_ENTRY(thr);
18451 
18452 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
18453 	if (DUK_UNLIKELY(ret < min_top)) {
18454 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
18455 		DUK_WO_NORETURN(return 0;);
18456 	}
18457 	return ret;
18458 }
18459 
18460 /* Set stack top within currently allocated range, but don't reallocate.
18461  * This is performance critical especially for call handling, so whenever
18462  * changing, profile and look at generated code.
18463  */
duk_set_top(duk_hthread * thr,duk_idx_t idx)18464 DUK_EXTERNAL void duk_set_top(duk_hthread *thr, duk_idx_t idx) {
18465 	duk_uidx_t vs_size;
18466 	duk_uidx_t vs_limit;
18467 	duk_uidx_t uidx;
18468 	duk_tval *tv;
18469 
18470 	DUK_ASSERT_API_ENTRY(thr);
18471 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
18472 
18473 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18474 	DUK_ASSERT(thr->valstack_end >= thr->valstack_bottom);
18475 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
18476 	vs_limit = (duk_uidx_t) (thr->valstack_end - thr->valstack_bottom);
18477 
18478 	if (idx < 0) {
18479 		/* Negative indices are always within allocated stack but
18480 		 * must not go below zero index.
18481 		 */
18482 		uidx = vs_size + (duk_uidx_t) idx;
18483 	} else {
18484 		/* Positive index can be higher than valstack top but must
18485 		 * not go above allocated stack (equality is OK).
18486 		 */
18487 		uidx = (duk_uidx_t) idx;
18488 	}
18489 
18490 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
18491 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
18492 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_limit);
18493 
18494 #if defined(DUK_USE_VALSTACK_UNSAFE)
18495 	DUK_ASSERT(uidx <= vs_limit);
18496 	DUK_UNREF(vs_limit);
18497 #else
18498 	if (DUK_UNLIKELY(uidx > vs_limit)) {
18499 		DUK_ERROR_RANGE_INDEX(thr, idx);
18500 		DUK_WO_NORETURN(return;);
18501 	}
18502 #endif
18503 	DUK_ASSERT(uidx <= vs_limit);
18504 
18505 	/* Handle change in value stack top.  Respect value stack
18506 	 * initialization policy: 'undefined' above top.  Note that
18507 	 * DECREF may cause a side effect that reallocates valstack,
18508 	 * so must relookup after DECREF.
18509 	 */
18510 
18511 	if (uidx >= vs_size) {
18512 		/* Stack size increases or stays the same. */
18513 #if defined(DUK_USE_ASSERTIONS)
18514 		duk_uidx_t count;
18515 
18516 		count = uidx - vs_size;
18517 		while (count != 0) {
18518 			count--;
18519 			tv = thr->valstack_top + count;
18520 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
18521 		}
18522 #endif
18523 		thr->valstack_top = thr->valstack_bottom + uidx;
18524 	} else {
18525 		/* Stack size decreases. */
18526 #if defined(DUK_USE_REFERENCE_COUNTING)
18527 		duk_uidx_t count;
18528 		duk_tval *tv_end;
18529 
18530 		count = vs_size - uidx;
18531 		DUK_ASSERT(count > 0);
18532 		tv = thr->valstack_top;
18533 		tv_end = tv - count;
18534 		DUK_ASSERT(tv > tv_end);  /* Because count > 0. */
18535 		do {
18536 			tv--;
18537 			DUK_ASSERT(tv >= thr->valstack_bottom);
18538 			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
18539 		} while (tv != tv_end);
18540 		thr->valstack_top = tv_end;
18541 		DUK_REFZERO_CHECK_FAST(thr);
18542 #else  /* DUK_USE_REFERENCE_COUNTING */
18543 		duk_uidx_t count;
18544 		duk_tval *tv_end;
18545 
18546 		count = vs_size - uidx;
18547 		tv = thr->valstack_top;
18548 		tv_end = tv - count;
18549 		DUK_ASSERT(tv > tv_end);
18550 		do {
18551 			tv--;
18552 			DUK_TVAL_SET_UNDEFINED(tv);
18553 		} while (tv != tv_end);
18554 		thr->valstack_top = tv_end;
18555 #endif  /* DUK_USE_REFERENCE_COUNTING */
18556 	}
18557 }
18558 
18559 /* Internal variant with a non-negative index and no runtime size checks. */
18560 #if defined(DUK_USE_PREFER_SIZE)
duk_set_top_unsafe(duk_hthread * thr,duk_idx_t idx)18561 DUK_INTERNAL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx) {
18562 	DUK_ASSERT_API_ENTRY(thr);
18563 
18564 	duk_set_top(thr, idx);
18565 }
18566 #else  /* DUK_USE_PREFER_SIZE */
duk_set_top_unsafe(duk_hthread * thr,duk_idx_t idx)18567 DUK_INTERNAL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx) {
18568 	duk_uidx_t uidx;
18569 	duk_uidx_t vs_size;
18570 	duk_tval *tv;
18571 
18572 	DUK_ASSERT_API_ENTRY(thr);
18573 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18574 	DUK_ASSERT(thr->valstack_end >= thr->valstack_bottom);
18575 	DUK_ASSERT(idx >= 0);
18576 	DUK_ASSERT(idx <= (duk_idx_t) (thr->valstack_end - thr->valstack_bottom));
18577 
18578 	/* XXX: byte arithmetic */
18579 	uidx = (duk_uidx_t) idx;
18580 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
18581 
18582 	if (uidx >= vs_size) {
18583 		/* Stack size increases or stays the same. */
18584 #if defined(DUK_USE_ASSERTIONS)
18585 		duk_uidx_t count;
18586 
18587 		count = uidx - vs_size;
18588 		while (count != 0) {
18589 			count--;
18590 			tv = thr->valstack_top + count;
18591 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
18592 		}
18593 #endif
18594 		thr->valstack_top = thr->valstack_bottom + uidx;
18595 	} else {
18596 		/* Stack size decreases. */
18597 #if defined(DUK_USE_REFERENCE_COUNTING)
18598 		duk_uidx_t count;
18599 		duk_tval *tv_end;
18600 
18601 		count = vs_size - uidx;
18602 		DUK_ASSERT(count > 0);
18603 		tv = thr->valstack_top;
18604 		tv_end = tv - count;
18605 		DUK_ASSERT(tv > tv_end);  /* Because count > 0. */
18606 		do {
18607 			tv--;
18608 			DUK_ASSERT(tv >= thr->valstack_bottom);
18609 			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
18610 		} while (tv != tv_end);
18611 		thr->valstack_top = tv_end;
18612 		DUK_REFZERO_CHECK_FAST(thr);
18613 #else  /* DUK_USE_REFERENCE_COUNTING */
18614 		duk_uidx_t count;
18615 		duk_tval *tv_end;
18616 
18617 		count = vs_size - uidx;
18618 		tv = thr->valstack_top;
18619 		tv_end = tv - count;
18620 		DUK_ASSERT(tv > tv_end);
18621 		do {
18622 			tv--;
18623 			DUK_TVAL_SET_UNDEFINED(tv);
18624 		} while (tv != tv_end);
18625 		thr->valstack_top = tv_end;
18626 #endif  /* DUK_USE_REFERENCE_COUNTING */
18627 	}
18628 }
18629 #endif  /* DUK_USE_PREFER_SIZE */
18630 
18631 /* Internal helper: set top to 'top', and set [idx_wipe_start,top[ to
18632  * 'undefined' (doing nothing if idx_wipe_start == top).  Indices are
18633  * positive and within value stack reserve.  This is used by call handling.
18634  */
duk_set_top_and_wipe(duk_hthread * thr,duk_idx_t top,duk_idx_t idx_wipe_start)18635 DUK_INTERNAL void duk_set_top_and_wipe(duk_hthread *thr, duk_idx_t top, duk_idx_t idx_wipe_start) {
18636 	DUK_ASSERT_API_ENTRY(thr);
18637 	DUK_ASSERT(top >= 0);
18638 	DUK_ASSERT(idx_wipe_start >= 0);
18639 	DUK_ASSERT(idx_wipe_start <= top);
18640 	DUK_ASSERT(thr->valstack_bottom + top <= thr->valstack_end);
18641 	DUK_ASSERT(thr->valstack_bottom + idx_wipe_start <= thr->valstack_end);
18642 
18643 	duk_set_top_unsafe(thr, idx_wipe_start);
18644 	duk_set_top_unsafe(thr, top);
18645 }
18646 
duk_get_top_index(duk_hthread * thr)18647 DUK_EXTERNAL duk_idx_t duk_get_top_index(duk_hthread *thr) {
18648 	duk_idx_t ret;
18649 
18650 	DUK_ASSERT_API_ENTRY(thr);
18651 
18652 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
18653 	if (DUK_UNLIKELY(ret < 0)) {
18654 		/* Return invalid index; if caller uses this without checking
18655 		 * in another API call, the index won't map to a valid stack
18656 		 * entry.
18657 		 */
18658 		return DUK_INVALID_INDEX;
18659 	}
18660 	return ret;
18661 }
18662 
18663 /* Internal variant: call assumes there is at least one element on the value
18664  * stack frame; this is only asserted for.
18665  */
duk_get_top_index_unsafe(duk_hthread * thr)18666 DUK_INTERNAL duk_idx_t duk_get_top_index_unsafe(duk_hthread *thr) {
18667 	duk_idx_t ret;
18668 
18669 	DUK_ASSERT_API_ENTRY(thr);
18670 
18671 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
18672 	return ret;
18673 }
18674 
duk_require_top_index(duk_hthread * thr)18675 DUK_EXTERNAL duk_idx_t duk_require_top_index(duk_hthread *thr) {
18676 	duk_idx_t ret;
18677 
18678 	DUK_ASSERT_API_ENTRY(thr);
18679 
18680 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
18681 	if (DUK_UNLIKELY(ret < 0)) {
18682 		DUK_ERROR_RANGE_INDEX(thr, -1);
18683 		DUK_WO_NORETURN(return 0;);
18684 	}
18685 	return ret;
18686 }
18687 
18688 /*
18689  *  Value stack resizing.
18690  *
18691  *  This resizing happens above the current "top": the value stack can be
18692  *  grown or shrunk, but the "top" is not affected.  The value stack cannot
18693  *  be resized to a size below the current reserve.
18694  *
18695  *  The low level reallocation primitive must carefully recompute all value
18696  *  stack pointers, and must also work if ALL pointers are NULL.  The resize
18697  *  is quite tricky because the valstack realloc may cause a mark-and-sweep,
18698  *  which may run finalizers.  Running finalizers may resize the valstack
18699  *  recursively (the same value stack we're working on).  So, after realloc
18700  *  returns, we know that the valstack bottom, top, and reserve should still
18701  *  be the same (there should not be live values above the "top"), but its
18702  *  underlying size, alloc_end, and base pointer may have changed.
18703  *
18704  *  'new_size' is known to be <= DUK_USE_VALSTACK_LIMIT, which ensures that
18705  *  size_t and pointer arithmetic won't wrap in duk__resize_valstack().
18706  */
18707 
18708 /* Low level valstack resize primitive, used for both grow and shrink.  All
18709  * adjustments for slack etc have already been done.  Doesn't throw but does
18710  * have allocation side effects.
18711  */
duk__resize_valstack(duk_hthread * thr,duk_size_t new_size)18712 DUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__resize_valstack(duk_hthread *thr, duk_size_t new_size) {
18713 	duk_tval *pre_valstack;
18714 	duk_tval *pre_bottom;
18715 	duk_tval *pre_top;
18716 	duk_tval *pre_end;
18717 	duk_tval *pre_alloc_end;
18718 	duk_ptrdiff_t ptr_diff;
18719 	duk_tval *new_valstack;
18720 	duk_size_t new_alloc_size;
18721 	duk_tval *tv_prev_alloc_end;
18722 	duk_tval *p;
18723 
18724 	DUK_HTHREAD_ASSERT_VALID(thr);
18725 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
18726 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18727 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
18728 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
18729 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) <= new_size);  /* can't resize below 'top' */
18730 	DUK_ASSERT(new_size <= DUK_USE_VALSTACK_LIMIT);  /* valstack limit caller has check, prevents wrapping */
18731 	DUK_ASSERT(new_size <= DUK_SIZE_MAX / sizeof(duk_tval));  /* specific assert for wrapping */
18732 
18733 	/* Pre-realloc pointer copies for asserts and debug logs. */
18734 	pre_valstack = thr->valstack;
18735 	pre_bottom = thr->valstack_bottom;
18736 	pre_top = thr->valstack_top;
18737 	pre_end = thr->valstack_end;
18738 	pre_alloc_end = thr->valstack_alloc_end;
18739 
18740 	DUK_UNREF(pre_valstack);
18741 	DUK_UNREF(pre_bottom);
18742 	DUK_UNREF(pre_top);
18743 	DUK_UNREF(pre_end);
18744 	DUK_UNREF(pre_alloc_end);
18745 
18746 	/* If finalizer torture enabled, force base pointer change every time
18747 	 * when it would be allowed.
18748 	 */
18749 #if defined(DUK_USE_FINALIZER_TORTURE)
18750 	if (thr->heap->pf_prevent_count == 0) {
18751 		duk_hthread_valstack_torture_realloc(thr);
18752 	}
18753 #endif
18754 
18755 	/* Allocate a new valstack using DUK_REALLOC_DIRECT() to deal with
18756 	 * a side effect changing the base pointer.
18757 	 */
18758 	new_alloc_size = sizeof(duk_tval) * new_size;
18759 	new_valstack = (duk_tval *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_valstack_ptr, (void *) thr, new_alloc_size);
18760 	if (DUK_UNLIKELY(new_valstack == NULL)) {
18761 		/* Because new_size != 0, if condition doesn't need to be
18762 		 * (new_valstack != NULL || new_size == 0).
18763 		 */
18764 		DUK_ASSERT(new_size != 0);
18765 		DUK_D(DUK_DPRINT("failed to resize valstack to %lu entries (%lu bytes)",
18766 		                 (unsigned long) new_size, (unsigned long) new_alloc_size));
18767 		return 0;
18768 	}
18769 
18770 	/* Debug log any changes in pointer(s) by side effects.  These don't
18771 	 * necessarily imply any incorrect behavior, but should be rare in
18772 	 * practice.
18773 	 */
18774 #if defined(DUK_USE_DEBUG)
18775 	if (thr->valstack != pre_valstack) {
18776 		DUK_D(DUK_DPRINT("valstack base pointer changed during valstack resize: %p -> %p",
18777 		                 (void *) pre_valstack, (void *) thr->valstack));
18778 	}
18779 	if (thr->valstack_bottom != pre_bottom) {
18780 		DUK_D(DUK_DPRINT("valstack bottom pointer changed during valstack resize: %p -> %p",
18781 		                 (void *) pre_bottom, (void *) thr->valstack_bottom));
18782 	}
18783 	if (thr->valstack_top != pre_top) {
18784 		DUK_D(DUK_DPRINT("valstack top pointer changed during valstack resize: %p -> %p",
18785 		                 (void *) pre_top, (void *) thr->valstack_top));
18786 	}
18787 	if (thr->valstack_end != pre_end) {
18788 		DUK_D(DUK_DPRINT("valstack end pointer changed during valstack resize: %p -> %p",
18789 		                 (void *) pre_end, (void *) thr->valstack_end));
18790 	}
18791 	if (thr->valstack_alloc_end != pre_alloc_end) {
18792 		DUK_D(DUK_DPRINT("valstack alloc_end pointer changed during valstack resize: %p -> %p",
18793 		                 (void *) pre_alloc_end, (void *) thr->valstack_alloc_end));
18794 	}
18795 #endif
18796 
18797 	/* Assertions: offsets for bottom, top, and end (reserve) must not
18798 	 * have changed even with side effects because they are always
18799 	 * restored in unwind.  For alloc_end there's no guarantee: it may
18800 	 * have grown or shrunk (but remain above 'end').
18801 	 */
18802 	DUK_ASSERT(thr->valstack_bottom - thr->valstack == pre_bottom - pre_valstack);
18803 	DUK_ASSERT(thr->valstack_top - thr->valstack == pre_top - pre_valstack);
18804 	DUK_ASSERT(thr->valstack_end - thr->valstack == pre_end - pre_valstack);
18805 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
18806 
18807 	/* Write new pointers.  Most pointers can be handled as a pointer
18808 	 * difference.
18809 	 */
18810 	ptr_diff = (duk_ptrdiff_t) ((duk_uint8_t *) new_valstack - (duk_uint8_t *) thr->valstack);
18811 	tv_prev_alloc_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_alloc_end + ptr_diff);
18812 	thr->valstack = new_valstack;
18813 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + ptr_diff);
18814 	thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_top + ptr_diff);
18815 	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_end + ptr_diff);
18816 	thr->valstack_alloc_end = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + new_alloc_size);
18817 
18818 	/* Assertions: pointer sanity after pointer updates. */
18819 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
18820 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18821 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
18822 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
18823 
18824 	DUK_D(DUK_DPRINT("resized valstack %lu -> %lu elements (%lu -> %lu bytes): "
18825 	                 "base=%p -> %p, bottom=%p -> %p (%ld), top=%p -> %p (%ld), "
18826 	                 "end=%p -> %p (%ld), alloc_end=%p -> %p (%ld);"
18827 	                 " tv_prev_alloc_end=%p (-> %ld inits; <0 means shrink)",
18828 	                 (unsigned long) (pre_alloc_end - pre_valstack),
18829 	                 (unsigned long) new_size,
18830 	                 (unsigned long) ((duk_uint8_t *) pre_alloc_end - (duk_uint8_t *) pre_valstack),
18831 	                 (unsigned long) new_alloc_size,
18832 	                 (void *) pre_valstack, (void *) thr->valstack,
18833 	                 (void *) pre_bottom, (void *) thr->valstack_bottom, (long) (thr->valstack_bottom - thr->valstack),
18834 	                 (void *) pre_top, (void *) thr->valstack_top, (long) (thr->valstack_top - thr->valstack),
18835 	                 (void *) pre_end, (void *) thr->valstack_end, (long) (thr->valstack_end - thr->valstack),
18836 	                 (void *) pre_alloc_end, (void *) thr->valstack_alloc_end, (long) (thr->valstack_alloc_end - thr->valstack),
18837 	                 (void *) tv_prev_alloc_end, (long) (thr->valstack_alloc_end - tv_prev_alloc_end)));
18838 
18839 	/* If allocation grew, init any new slots to 'undefined'. */
18840 	p = tv_prev_alloc_end;
18841 	while (p < thr->valstack_alloc_end) {
18842 		/* Never executed if new size is smaller. */
18843 		DUK_TVAL_SET_UNDEFINED(p);
18844 		p++;
18845 	}
18846 
18847 	/* Assert for value stack initialization policy. */
18848 #if defined(DUK_USE_ASSERTIONS)
18849 	p = thr->valstack_top;
18850 	while (p < thr->valstack_alloc_end) {
18851 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(p));
18852 		p++;
18853 	}
18854 #endif
18855 
18856 	return 1;
18857 }
18858 
duk__valstack_grow(duk_hthread * thr,duk_size_t min_bytes,duk_bool_t throw_on_error)18859 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) {
18860 	duk_size_t min_size;
18861 	duk_size_t new_size;
18862 
18863 	DUK_ASSERT(min_bytes / sizeof(duk_tval) * sizeof(duk_tval) == min_bytes);
18864 	min_size = min_bytes / sizeof(duk_tval);  /* from bytes to slots */
18865 
18866 #if defined(DUK_USE_VALSTACK_GROW_SHIFT)
18867 	/* New size is minimum size plus a proportional slack, e.g. shift of
18868 	 * 2 means a 25% slack.
18869 	 */
18870 	new_size = min_size + (min_size >> DUK_USE_VALSTACK_GROW_SHIFT);
18871 #else
18872 	/* New size is tight with no slack.  This is sometimes preferred in
18873 	 * low memory environments.
18874 	 */
18875 	new_size = min_size;
18876 #endif
18877 
18878 	if (DUK_UNLIKELY(new_size > DUK_USE_VALSTACK_LIMIT || new_size < min_size /*wrap*/)) {
18879 		/* Note: may be triggered even if minimal new_size would not reach the limit,
18880 		 * plan limit accordingly.
18881 		 */
18882 		if (throw_on_error) {
18883 			DUK_ERROR_RANGE(thr, DUK_STR_VALSTACK_LIMIT);
18884 			DUK_WO_NORETURN(return 0;);
18885 		}
18886 		return 0;
18887 	}
18888 
18889 	if (duk__resize_valstack(thr, new_size) == 0) {
18890 		if (throw_on_error) {
18891 			DUK_ERROR_ALLOC_FAILED(thr);
18892 			DUK_WO_NORETURN(return 0;);
18893 		}
18894 		return 0;
18895 	}
18896 
18897 	thr->valstack_end = thr->valstack + min_size;
18898 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
18899 
18900 	return 1;
18901 }
18902 
18903 /* Hot, inlined value stack grow check.  Because value stack almost never
18904  * grows, the actual resize call is in a NOINLINE helper.
18905  */
duk_valstack_grow_check_throw(duk_hthread * thr,duk_size_t min_bytes)18906 DUK_INTERNAL DUK_INLINE void duk_valstack_grow_check_throw(duk_hthread *thr, duk_size_t min_bytes) {
18907 	duk_tval *tv;
18908 
18909 	tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + min_bytes);
18910 	if (DUK_LIKELY(thr->valstack_end >= tv)) {
18911 		return;
18912 	}
18913 	if (DUK_LIKELY(thr->valstack_alloc_end >= tv)) {
18914 		/* Values in [valstack_top,valstack_alloc_end[ are initialized
18915 		 * to 'undefined' so we can just move the end pointer.
18916 		 */
18917 		thr->valstack_end = tv;
18918 		return;
18919 	}
18920 	(void) duk__valstack_grow(thr, min_bytes, 1 /*throw_on_error*/);
18921 }
18922 
18923 /* Hot, inlined value stack grow check which doesn't throw. */
duk_valstack_grow_check_nothrow(duk_hthread * thr,duk_size_t min_bytes)18924 DUK_INTERNAL DUK_INLINE duk_bool_t duk_valstack_grow_check_nothrow(duk_hthread *thr, duk_size_t min_bytes) {
18925 	duk_tval *tv;
18926 
18927 	tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + min_bytes);
18928 	if (DUK_LIKELY(thr->valstack_end >= tv)) {
18929 		return 1;
18930 	}
18931 	if (DUK_LIKELY(thr->valstack_alloc_end >= tv)) {
18932 		thr->valstack_end = tv;
18933 		return 1;
18934 	}
18935 	return duk__valstack_grow(thr, min_bytes, 0 /*throw_on_error*/);
18936 }
18937 
18938 /* Value stack shrink check, called from mark-and-sweep. */
duk_valstack_shrink_check_nothrow(duk_hthread * thr,duk_bool_t snug)18939 DUK_INTERNAL void duk_valstack_shrink_check_nothrow(duk_hthread *thr, duk_bool_t snug) {
18940 	duk_size_t alloc_bytes;
18941 	duk_size_t reserve_bytes;
18942 	duk_size_t shrink_bytes;
18943 
18944 	alloc_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_alloc_end - (duk_uint8_t *) thr->valstack);
18945 	reserve_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
18946 	DUK_ASSERT(alloc_bytes >= reserve_bytes);
18947 
18948 	/* We're free to shrink the value stack allocation down to
18949 	 * reserve_bytes but not more.  If 'snug' (emergency GC)
18950 	 * shrink whatever we can.  Otherwise only shrink if the new
18951 	 * size would be considerably smaller.
18952 	 */
18953 
18954 #if defined(DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT)
18955 	if (snug) {
18956 		shrink_bytes = reserve_bytes;
18957 	} else {
18958 		duk_size_t proportion, slack;
18959 
18960 		/* Require that value stack shrinks by at least X% of its
18961 		 * current size.  For example, shift of 2 means at least
18962 		 * 25%.  The proportion is computed as bytes and may not
18963 		 * be a multiple of sizeof(duk_tval); that's OK here.
18964 		 */
18965 		proportion = alloc_bytes >> DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT;
18966 		if (alloc_bytes - reserve_bytes < proportion) {
18967 			/* Too little would be freed, do nothing. */
18968 			return;
18969 		}
18970 
18971 		/* Keep a slack after shrinking.  The slack is again a
18972 		 * proportion of the current size (the proportion should
18973 		 * of course be smaller than the check proportion above).
18974 		 */
18975 #if defined(DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT)
18976 		DUK_ASSERT(DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT > DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT);
18977 		slack = alloc_bytes >> DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT;
18978 #else
18979 		slack = 0;
18980 #endif
18981 		shrink_bytes = reserve_bytes +
18982 		               slack / sizeof(duk_tval) * sizeof(duk_tval);  /* multiple of duk_tval */
18983 	}
18984 #else  /* DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT */
18985 	/* Always snug, useful in some low memory environments. */
18986 	DUK_UNREF(snug);
18987 	shrink_bytes = reserve_bytes;
18988 #endif  /* DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT */
18989 
18990 	DUK_D(DUK_DPRINT("valstack shrink check: alloc_bytes=%ld, reserve_bytes=%ld, shrink_bytes=%ld (unvalidated)",
18991 	                 (long) alloc_bytes, (long) reserve_bytes, (long) shrink_bytes));
18992 	DUK_ASSERT(shrink_bytes >= reserve_bytes);
18993 	if (shrink_bytes >= alloc_bytes) {
18994 		/* Skip if shrink target is same as current one (or higher,
18995 		 * though that shouldn't happen in practice).
18996 		 */
18997 		return;
18998 	}
18999 	DUK_ASSERT(shrink_bytes / sizeof(duk_tval) * sizeof(duk_tval) == shrink_bytes);
19000 
19001 	DUK_D(DUK_DPRINT("valstack shrink check: decided to shrink, snug: %ld", (long) snug));
19002 
19003 	duk__resize_valstack(thr, shrink_bytes / sizeof(duk_tval));
19004 }
19005 
duk_check_stack(duk_hthread * thr,duk_idx_t extra)19006 DUK_EXTERNAL duk_bool_t duk_check_stack(duk_hthread *thr, duk_idx_t extra) {
19007 	duk_size_t min_new_bytes;
19008 
19009 	DUK_ASSERT_API_ENTRY(thr);
19010 	DUK_ASSERT(thr != NULL);
19011 
19012 	if (DUK_UNLIKELY(extra < 0 || extra > DUK_USE_VALSTACK_LIMIT)) {
19013 		if (extra < 0) {
19014 			/* Clamping to zero makes the API more robust to calling code
19015 			 * calculation errors.
19016 			 */
19017 			extra = 0;
19018 		} else {
19019 			/* Cause grow check to fail without wrapping arithmetic. */
19020 			extra = DUK_USE_VALSTACK_LIMIT;
19021 		}
19022 	}
19023 
19024 	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack) +
19025 	                sizeof(duk_tval) * ((duk_size_t) extra + DUK_VALSTACK_INTERNAL_EXTRA);
19026 	return duk_valstack_grow_check_nothrow(thr, min_new_bytes);
19027 }
19028 
duk_require_stack(duk_hthread * thr,duk_idx_t extra)19029 DUK_EXTERNAL void duk_require_stack(duk_hthread *thr, duk_idx_t extra) {
19030 	duk_size_t min_new_bytes;
19031 
19032 	DUK_ASSERT_API_ENTRY(thr);
19033 	DUK_ASSERT(thr != NULL);
19034 
19035 	if (DUK_UNLIKELY(extra < 0 || extra > DUK_USE_VALSTACK_LIMIT)) {
19036 		if (extra < 0) {
19037 			/* Clamping to zero makes the API more robust to calling code
19038 			 * calculation errors.
19039 			 */
19040 			extra = 0;
19041 		} else {
19042 			/* Cause grow check to fail without wrapping arithmetic. */
19043 			extra = DUK_USE_VALSTACK_LIMIT;
19044 		}
19045 	}
19046 
19047 	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack) +
19048 	                sizeof(duk_tval) * ((duk_size_t) extra + DUK_VALSTACK_INTERNAL_EXTRA);
19049 	duk_valstack_grow_check_throw(thr, min_new_bytes);
19050 }
19051 
duk_check_stack_top(duk_hthread * thr,duk_idx_t top)19052 DUK_EXTERNAL duk_bool_t duk_check_stack_top(duk_hthread *thr, duk_idx_t top) {
19053 	duk_size_t min_new_bytes;
19054 
19055 	DUK_ASSERT_API_ENTRY(thr);
19056 
19057 	if (DUK_UNLIKELY(top < 0 || top > DUK_USE_VALSTACK_LIMIT)) {
19058 		if (top < 0) {
19059 			/* Clamping to zero makes the API more robust to calling code
19060 			 * calculation errors.
19061 			 */
19062 			top = 0;
19063 		} else {
19064 			/* Cause grow check to fail without wrapping arithmetic. */
19065 			top = DUK_USE_VALSTACK_LIMIT;
19066 		}
19067 	}
19068 
19069 	DUK_ASSERT(top >= 0);
19070 	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) +
19071 	                sizeof(duk_tval) * ((duk_size_t) top + DUK_VALSTACK_INTERNAL_EXTRA);
19072 	return duk_valstack_grow_check_nothrow(thr, min_new_bytes);
19073 }
19074 
duk_require_stack_top(duk_hthread * thr,duk_idx_t top)19075 DUK_EXTERNAL void duk_require_stack_top(duk_hthread *thr, duk_idx_t top) {
19076 	duk_size_t min_new_bytes;
19077 
19078 	DUK_ASSERT_API_ENTRY(thr);
19079 
19080 	if (DUK_UNLIKELY(top < 0 || top > DUK_USE_VALSTACK_LIMIT)) {
19081 		if (top < 0) {
19082 			/* Clamping to zero makes the API more robust to calling code
19083 			 * calculation errors.
19084 			 */
19085 			top = 0;
19086 		} else {
19087 			/* Cause grow check to fail without wrapping arithmetic. */
19088 			top = DUK_USE_VALSTACK_LIMIT;
19089 		}
19090 	}
19091 
19092 	DUK_ASSERT(top >= 0);
19093 	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) +
19094 	                sizeof(duk_tval) * ((duk_size_t) top + DUK_VALSTACK_INTERNAL_EXTRA);
19095 	duk_valstack_grow_check_throw(thr, min_new_bytes);
19096 }
19097 
19098 /*
19099  *  Basic stack manipulation: swap, dup, insert, replace, etc
19100  */
19101 
duk_swap(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)19102 DUK_EXTERNAL void duk_swap(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
19103 	duk_tval *tv1;
19104 	duk_tval *tv2;
19105 	duk_tval tv_tmp;
19106 
19107 	DUK_ASSERT_API_ENTRY(thr);
19108 
19109 	tv1 = duk_require_tval(thr, idx1);
19110 	DUK_ASSERT(tv1 != NULL);
19111 	tv2 = duk_require_tval(thr, idx2);
19112 	DUK_ASSERT(tv2 != NULL);
19113 
19114 	/* If tv1==tv2 this is a NOP, no check is needed */
19115 	DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
19116 	DUK_TVAL_SET_TVAL(tv1, tv2);
19117 	DUK_TVAL_SET_TVAL(tv2, &tv_tmp);
19118 }
19119 
duk_swap_top(duk_hthread * thr,duk_idx_t idx)19120 DUK_EXTERNAL void duk_swap_top(duk_hthread *thr, duk_idx_t idx) {
19121 	DUK_ASSERT_API_ENTRY(thr);
19122 
19123 	duk_swap(thr, idx, -1);
19124 }
19125 
duk_dup(duk_hthread * thr,duk_idx_t from_idx)19126 DUK_EXTERNAL void duk_dup(duk_hthread *thr, duk_idx_t from_idx) {
19127 	duk_tval *tv_from;
19128 	duk_tval *tv_to;
19129 
19130 	DUK_ASSERT_API_ENTRY(thr);
19131 	DUK__CHECK_SPACE();
19132 
19133 	tv_from = duk_require_tval(thr, from_idx);
19134 	tv_to = thr->valstack_top++;
19135 	DUK_ASSERT(tv_from != NULL);
19136 	DUK_ASSERT(tv_to != NULL);
19137 	DUK_TVAL_SET_TVAL(tv_to, tv_from);
19138 	DUK_TVAL_INCREF(thr, tv_to);  /* no side effects */
19139 }
19140 
duk_dup_top(duk_hthread * thr)19141 DUK_EXTERNAL void duk_dup_top(duk_hthread *thr) {
19142 #if defined(DUK_USE_PREFER_SIZE)
19143 	duk_dup(thr, -1);
19144 #else
19145 	duk_tval *tv_from;
19146 	duk_tval *tv_to;
19147 
19148 	DUK_ASSERT_API_ENTRY(thr);
19149 	DUK__CHECK_SPACE();
19150 
19151 	if (DUK_UNLIKELY(thr->valstack_top - thr->valstack_bottom <= 0)) {
19152 		DUK_ERROR_RANGE_INDEX(thr, -1);
19153 		DUK_WO_NORETURN(return;);
19154 	}
19155 	tv_from = thr->valstack_top - 1;
19156 	tv_to = thr->valstack_top++;
19157 	DUK_ASSERT(tv_from != NULL);
19158 	DUK_ASSERT(tv_to != NULL);
19159 	DUK_TVAL_SET_TVAL(tv_to, tv_from);
19160 	DUK_TVAL_INCREF(thr, tv_to);  /* no side effects */
19161 #endif
19162 }
19163 
duk_dup_0(duk_hthread * thr)19164 DUK_INTERNAL void duk_dup_0(duk_hthread *thr) {
19165 	DUK_ASSERT_API_ENTRY(thr);
19166 	duk_dup(thr, 0);
19167 }
duk_dup_1(duk_hthread * thr)19168 DUK_INTERNAL void duk_dup_1(duk_hthread *thr) {
19169 	DUK_ASSERT_API_ENTRY(thr);
19170 	duk_dup(thr, 1);
19171 }
duk_dup_2(duk_hthread * thr)19172 DUK_INTERNAL void duk_dup_2(duk_hthread *thr) {
19173 	DUK_ASSERT_API_ENTRY(thr);
19174 	duk_dup(thr, 2);
19175 }
duk_dup_m2(duk_hthread * thr)19176 DUK_INTERNAL void duk_dup_m2(duk_hthread *thr) {
19177 	DUK_ASSERT_API_ENTRY(thr);
19178 	duk_dup(thr, -2);
19179 }
duk_dup_m3(duk_hthread * thr)19180 DUK_INTERNAL void duk_dup_m3(duk_hthread *thr) {
19181 	DUK_ASSERT_API_ENTRY(thr);
19182 	duk_dup(thr, -3);
19183 }
duk_dup_m4(duk_hthread * thr)19184 DUK_INTERNAL void duk_dup_m4(duk_hthread *thr) {
19185 	DUK_ASSERT_API_ENTRY(thr);
19186 	duk_dup(thr, -4);
19187 }
19188 
duk_insert(duk_hthread * thr,duk_idx_t to_idx)19189 DUK_EXTERNAL void duk_insert(duk_hthread *thr, duk_idx_t to_idx) {
19190 	duk_tval *p;
19191 	duk_tval *q;
19192 	duk_tval tv_tmp;
19193 	duk_size_t nbytes;
19194 
19195 	DUK_ASSERT_API_ENTRY(thr);
19196 
19197 	p = duk_require_tval(thr, to_idx);
19198 	DUK_ASSERT(p != NULL);
19199 	q = duk_require_tval(thr, -1);
19200 	DUK_ASSERT(q != NULL);
19201 
19202 	DUK_ASSERT(q >= p);
19203 
19204 	/*              nbytes
19205 	 *           <--------->
19206 	 *    [ ... | p | x | x | q ]
19207 	 * => [ ... | q | p | x | x ]
19208 	 */
19209 
19210 	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));
19211 
19212 	DUK_DDD(DUK_DDDPRINT("duk_insert: to_idx=%ld, p=%p, q=%p, nbytes=%lu",
19213 	                     (long) to_idx, (void *) p, (void *) q, (unsigned long) nbytes));
19214 
19215 	/* No net refcount changes.  No need to special case nbytes == 0
19216 	 * (p == q).
19217 	 */
19218 	DUK_TVAL_SET_TVAL(&tv_tmp, q);
19219 	duk_memmove((void *) (p + 1), (const void *) p, (size_t) nbytes);
19220 	DUK_TVAL_SET_TVAL(p, &tv_tmp);
19221 }
19222 
duk_insert_undefined(duk_hthread * thr,duk_idx_t idx)19223 DUK_INTERNAL void duk_insert_undefined(duk_hthread *thr, duk_idx_t idx) {
19224 	DUK_ASSERT_API_ENTRY(thr);
19225 	DUK_ASSERT(idx >= 0);  /* Doesn't support negative indices. */
19226 
19227 	duk_push_undefined(thr);
19228 	duk_insert(thr, idx);
19229 }
19230 
duk_insert_undefined_n(duk_hthread * thr,duk_idx_t idx,duk_idx_t count)19231 DUK_INTERNAL void duk_insert_undefined_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {
19232 	duk_tval *tv, *tv_end;
19233 
19234 	DUK_ASSERT_API_ENTRY(thr);
19235 	DUK_ASSERT(idx >= 0);  /* Doesn't support negative indices or count. */
19236 	DUK_ASSERT(count >= 0);
19237 
19238 	tv = duk_reserve_gap(thr, idx, count);
19239 	tv_end = tv + count;
19240 	while (tv != tv_end) {
19241 		DUK_TVAL_SET_UNDEFINED(tv);
19242 		tv++;
19243 	}
19244 }
19245 
duk_pull(duk_hthread * thr,duk_idx_t from_idx)19246 DUK_EXTERNAL void duk_pull(duk_hthread *thr, duk_idx_t from_idx) {
19247 	duk_tval *p;
19248 	duk_tval *q;
19249 	duk_tval tv_tmp;
19250 	duk_size_t nbytes;
19251 
19252 	DUK_ASSERT_API_ENTRY(thr);
19253 
19254 	/*                         nbytes
19255 	 *                       <--------->
19256 	 *    [ ... | x | x | p | y | y | q ]
19257 	 * => [ ... | x | x | y | y | q | p ]
19258 	 */
19259 
19260 	p = duk_require_tval(thr, from_idx);
19261 	DUK_ASSERT(p != NULL);
19262 	q = duk_require_tval(thr, -1);
19263 	DUK_ASSERT(q != NULL);
19264 
19265 	DUK_ASSERT(q >= p);
19266 
19267 	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));
19268 
19269 	DUK_DDD(DUK_DDDPRINT("duk_pull: from_idx=%ld, p=%p, q=%p, nbytes=%lu",
19270 	                     (long) from_idx, (void *) p, (void *) q, (unsigned long) nbytes));
19271 
19272 	/* No net refcount changes.  No need to special case nbytes == 0
19273 	 * (p == q).
19274 	 */
19275 	DUK_TVAL_SET_TVAL(&tv_tmp, p);
19276 	duk_memmove((void *) p, (const void *) (p + 1), (size_t) nbytes);
19277 	DUK_TVAL_SET_TVAL(q, &tv_tmp);
19278 }
19279 
duk_replace(duk_hthread * thr,duk_idx_t to_idx)19280 DUK_EXTERNAL void duk_replace(duk_hthread *thr, duk_idx_t to_idx) {
19281 	duk_tval *tv1;
19282 	duk_tval *tv2;
19283 	duk_tval tv_tmp;
19284 
19285 	DUK_ASSERT_API_ENTRY(thr);
19286 
19287 	tv1 = duk_require_tval(thr, -1);
19288 	DUK_ASSERT(tv1 != NULL);
19289 	tv2 = duk_require_tval(thr, to_idx);
19290 	DUK_ASSERT(tv2 != NULL);
19291 
19292 	/* For tv1 == tv2, both pointing to stack top, the end result
19293 	 * is same as duk_pop(thr).
19294 	 */
19295 	DUK_TVAL_SET_TVAL(&tv_tmp, tv2);
19296 	DUK_TVAL_SET_TVAL(tv2, tv1);
19297 	DUK_TVAL_SET_UNDEFINED(tv1);
19298 	thr->valstack_top--;
19299 	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
19300 }
19301 
duk_copy(duk_hthread * thr,duk_idx_t from_idx,duk_idx_t to_idx)19302 DUK_EXTERNAL void duk_copy(duk_hthread *thr, duk_idx_t from_idx, duk_idx_t to_idx) {
19303 	duk_tval *tv1;
19304 	duk_tval *tv2;
19305 
19306 	DUK_ASSERT_API_ENTRY(thr);
19307 
19308 	tv1 = duk_require_tval(thr, from_idx);
19309 	DUK_ASSERT(tv1 != NULL);
19310 	tv2 = duk_require_tval(thr, to_idx);
19311 	DUK_ASSERT(tv2 != NULL);
19312 
19313 	/* For tv1 == tv2, this is a no-op (no explicit check needed). */
19314 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv2, tv1);  /* side effects */
19315 }
19316 
duk_remove(duk_hthread * thr,duk_idx_t idx)19317 DUK_EXTERNAL void duk_remove(duk_hthread *thr, duk_idx_t idx) {
19318 	duk_tval *p;
19319 	duk_tval *q;
19320 #if defined(DUK_USE_REFERENCE_COUNTING)
19321 	duk_tval tv_tmp;
19322 #endif
19323 	duk_size_t nbytes;
19324 
19325 	DUK_ASSERT_API_ENTRY(thr);
19326 
19327 	p = duk_require_tval(thr, idx);
19328 	DUK_ASSERT(p != NULL);
19329 	q = duk_require_tval(thr, -1);
19330 	DUK_ASSERT(q != NULL);
19331 
19332 	DUK_ASSERT(q >= p);
19333 
19334 	/*              nbytes            zero size case
19335 	 *           <--------->
19336 	 *    [ ... | p | x | x | q ]     [ ... | p==q ]
19337 	 * => [ ... | x | x | q ]         [ ... ]
19338 	 */
19339 
19340 #if defined(DUK_USE_REFERENCE_COUNTING)
19341 	/* use a temp: decref only when valstack reachable values are correct */
19342 	DUK_TVAL_SET_TVAL(&tv_tmp, p);
19343 #endif
19344 
19345 	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));  /* Note: 'q' is top-1 */
19346 	duk_memmove((void *) p, (const void *) (p + 1), (size_t) nbytes);
19347 
19348 	DUK_TVAL_SET_UNDEFINED(q);
19349 	thr->valstack_top--;
19350 
19351 #if defined(DUK_USE_REFERENCE_COUNTING)
19352 	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
19353 #endif
19354 }
19355 
duk_remove_unsafe(duk_hthread * thr,duk_idx_t idx)19356 DUK_INTERNAL void duk_remove_unsafe(duk_hthread *thr, duk_idx_t idx) {
19357 	DUK_ASSERT_API_ENTRY(thr);
19358 
19359 	duk_remove(thr, idx);  /* XXX: no optimization for now */
19360 }
19361 
duk_remove_m2(duk_hthread * thr)19362 DUK_INTERNAL void duk_remove_m2(duk_hthread *thr) {
19363 	DUK_ASSERT_API_ENTRY(thr);
19364 
19365 	duk_remove(thr, -2);
19366 }
19367 
duk_remove_n(duk_hthread * thr,duk_idx_t idx,duk_idx_t count)19368 DUK_INTERNAL void duk_remove_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {
19369 #if defined(DUK_USE_PREFER_SIZE)
19370 	/* XXX: maybe too slow even when preferring size? */
19371 	DUK_ASSERT_API_ENTRY(thr);
19372 	DUK_ASSERT(count >= 0);
19373 	DUK_ASSERT(idx >= 0);
19374 
19375 	while (count-- > 0) {
19376 		duk_remove(thr, idx);
19377 	}
19378 #else  /* DUK_USE_PREFER_SIZE */
19379 	duk_tval *tv_src;
19380 	duk_tval *tv_dst;
19381 	duk_tval *tv_newtop;
19382 	duk_tval *tv;
19383 	duk_size_t bytes;
19384 
19385 	DUK_ASSERT_API_ENTRY(thr);
19386 	DUK_ASSERT(count >= 0);
19387 	DUK_ASSERT(idx >= 0);
19388 
19389 	tv_dst = thr->valstack_bottom + idx;
19390 	DUK_ASSERT(tv_dst <= thr->valstack_top);
19391 	tv_src = tv_dst + count;
19392 	DUK_ASSERT(tv_src <= thr->valstack_top);
19393 	bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) tv_src);
19394 
19395 	for (tv = tv_dst; tv < tv_src; tv++) {
19396 		DUK_TVAL_DECREF_NORZ(thr, tv);
19397 	}
19398 
19399 	duk_memmove((void *) tv_dst, (const void *) tv_src, bytes);
19400 
19401 	tv_newtop = thr->valstack_top - count;
19402 	for (tv = tv_newtop; tv < thr->valstack_top; tv++) {
19403 		DUK_TVAL_SET_UNDEFINED(tv);
19404 	}
19405 	thr->valstack_top = tv_newtop;
19406 
19407 	/* When not preferring size, only NORZ macros are used; caller
19408 	 * is expected to DUK_REFZERO_CHECK().
19409 	 */
19410 #endif  /* DUK_USE_PREFER_SIZE */
19411 }
19412 
duk_remove_n_unsafe(duk_hthread * thr,duk_idx_t idx,duk_idx_t count)19413 DUK_INTERNAL void duk_remove_n_unsafe(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {
19414 	DUK_ASSERT_API_ENTRY(thr);
19415 
19416 	duk_remove_n(thr, idx, count);  /* XXX: no optimization for now */
19417 }
19418 
19419 /*
19420  *  Stack slice primitives
19421  */
19422 
duk_xcopymove_raw(duk_hthread * to_thr,duk_hthread * from_thr,duk_idx_t count,duk_bool_t is_copy)19423 DUK_EXTERNAL void duk_xcopymove_raw(duk_hthread *to_thr, duk_hthread *from_thr, duk_idx_t count, duk_bool_t is_copy) {
19424 	void *src;
19425 	duk_size_t nbytes;
19426 	duk_tval *p;
19427 	duk_tval *q;
19428 
19429 	/* XXX: several pointer comparison issues here */
19430 
19431 	DUK_ASSERT_API_ENTRY(to_thr);
19432 	DUK_CTX_ASSERT_VALID(to_thr);
19433 	DUK_CTX_ASSERT_VALID(from_thr);
19434 	DUK_ASSERT(to_thr->heap == from_thr->heap);
19435 
19436 	if (DUK_UNLIKELY(to_thr == from_thr)) {
19437 		DUK_ERROR_TYPE(to_thr, DUK_STR_INVALID_CONTEXT);
19438 		DUK_WO_NORETURN(return;);
19439 	}
19440 	if (DUK_UNLIKELY((duk_uidx_t) count > (duk_uidx_t) DUK_USE_VALSTACK_LIMIT)) {
19441 		/* Maximum value check ensures 'nbytes' won't wrap below.
19442 		 * Also handles negative count.
19443 		 */
19444 		DUK_ERROR_RANGE_INVALID_COUNT(to_thr);
19445 		DUK_WO_NORETURN(return;);
19446 	}
19447 	DUK_ASSERT(count >= 0);
19448 
19449 	nbytes = sizeof(duk_tval) * (duk_size_t) count;
19450 	if (DUK_UNLIKELY(nbytes == 0)) {
19451 		return;
19452 	}
19453 	DUK_ASSERT(to_thr->valstack_top <= to_thr->valstack_end);
19454 	if (DUK_UNLIKELY((duk_size_t) ((duk_uint8_t *) to_thr->valstack_end - (duk_uint8_t *) to_thr->valstack_top) < nbytes)) {
19455 		DUK_ERROR_RANGE_PUSH_BEYOND(to_thr);
19456 		DUK_WO_NORETURN(return;);
19457 	}
19458 	src = (void *) ((duk_uint8_t *) from_thr->valstack_top - nbytes);
19459 	if (DUK_UNLIKELY(src < (void *) from_thr->valstack_bottom)) {
19460 		DUK_ERROR_RANGE_INVALID_COUNT(to_thr);
19461 		DUK_WO_NORETURN(return;);
19462 	}
19463 
19464 	/* Copy values (no overlap even if to_thr == from_thr; that's not
19465 	 * allowed now anyway).
19466 	 */
19467 	DUK_ASSERT(nbytes > 0);
19468 	duk_memcpy((void *) to_thr->valstack_top, (const void *) src, (size_t) nbytes);
19469 
19470 	p = to_thr->valstack_top;
19471 	to_thr->valstack_top = (duk_tval *) (void *) (((duk_uint8_t *) p) + nbytes);
19472 
19473 	if (is_copy) {
19474 		/* Incref copies, keep originals. */
19475 		q = to_thr->valstack_top;
19476 		while (p < q) {
19477 			DUK_TVAL_INCREF(to_thr, p);  /* no side effects */
19478 			p++;
19479 		}
19480 	} else {
19481 		/* No net refcount change. */
19482 		p = from_thr->valstack_top;
19483 		q = (duk_tval *) (void *) (((duk_uint8_t *) p) - nbytes);
19484 		from_thr->valstack_top = q;
19485 
19486 		while (p > q) {
19487 			p--;
19488 			DUK_TVAL_SET_UNDEFINED(p);
19489 			/* XXX: fast primitive to set a bunch of values to UNDEFINED */
19490 		}
19491 	}
19492 }
19493 
19494 /* Internal helper: reserve a gap of 'count' elements at 'idx_base' and return a
19495  * pointer to the gap.  Values in the gap are garbage and MUST be initialized by
19496  * the caller before any side effects may occur.  The caller must ensure there's
19497  * enough stack reserve for 'count' values.
19498  */
duk_reserve_gap(duk_hthread * thr,duk_idx_t idx_base,duk_idx_t count)19499 DUK_INTERNAL duk_tval *duk_reserve_gap(duk_hthread *thr, duk_idx_t idx_base, duk_idx_t count) {
19500 	duk_tval *tv_src;
19501 	duk_tval *tv_dst;
19502 	duk_size_t gap_bytes;
19503 	duk_size_t copy_bytes;
19504 
19505 	/* Caller is responsible for ensuring there's enough preallocated
19506 	 * value stack.
19507 	 */
19508 	DUK_ASSERT_API_ENTRY(thr);
19509 	DUK_ASSERT(count >= 0);
19510 	DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack_top) >= (duk_size_t) count);
19511 
19512 	tv_src = thr->valstack_bottom + idx_base;
19513 	gap_bytes = (duk_size_t) count * sizeof(duk_tval);
19514 	tv_dst = (duk_tval *) (void *) ((duk_uint8_t *) tv_src + gap_bytes);
19515 	copy_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) tv_src);
19516 	thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_top + gap_bytes);
19517 	duk_memmove((void *) tv_dst, (const void *) tv_src, copy_bytes);
19518 
19519 	/* Values in the gap are left as garbage: caller must fill them in
19520 	 * and INCREF them before any side effects.
19521 	 */
19522 	return tv_src;
19523 }
19524 
19525 /*
19526  *  Get/opt/require
19527  */
19528 
duk_require_undefined(duk_hthread * thr,duk_idx_t idx)19529 DUK_EXTERNAL void duk_require_undefined(duk_hthread *thr, duk_idx_t idx) {
19530 	duk_tval *tv;
19531 
19532 	DUK_ASSERT_API_ENTRY(thr);
19533 
19534 	tv = duk_get_tval_or_unused(thr, idx);
19535 	DUK_ASSERT(tv != NULL);
19536 	if (DUK_UNLIKELY(!DUK_TVAL_IS_UNDEFINED(tv))) {
19537 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "undefined", DUK_STR_NOT_UNDEFINED);
19538 		DUK_WO_NORETURN(return;);
19539 	}
19540 }
19541 
duk_require_null(duk_hthread * thr,duk_idx_t idx)19542 DUK_EXTERNAL void duk_require_null(duk_hthread *thr, duk_idx_t idx) {
19543 	duk_tval *tv;
19544 
19545 	DUK_ASSERT_API_ENTRY(thr);
19546 
19547 	tv = duk_get_tval_or_unused(thr, idx);
19548 	DUK_ASSERT(tv != NULL);
19549 	if (DUK_UNLIKELY(!DUK_TVAL_IS_NULL(tv))) {
19550 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "null", DUK_STR_NOT_NULL);
19551 		DUK_WO_NORETURN(return;);
19552 	}
19553 }
19554 
duk__get_boolean_raw(duk_hthread * thr,duk_idx_t idx,duk_bool_t def_value)19555 DUK_LOCAL DUK_ALWAYS_INLINE duk_bool_t duk__get_boolean_raw(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {
19556 	duk_bool_t ret;
19557 	duk_tval *tv;
19558 
19559 	DUK_CTX_ASSERT_VALID(thr);
19560 
19561 	tv = duk_get_tval_or_unused(thr, idx);
19562 	DUK_ASSERT(tv != NULL);
19563 	if (DUK_TVAL_IS_BOOLEAN(tv)) {
19564 		ret = DUK_TVAL_GET_BOOLEAN(tv);
19565 		DUK_ASSERT(ret == 0 || ret == 1);
19566 	} else {
19567 		ret = def_value;
19568 		/* Not guaranteed to be 0 or 1. */
19569 	}
19570 
19571 	return ret;
19572 }
19573 
duk_get_boolean(duk_hthread * thr,duk_idx_t idx)19574 DUK_EXTERNAL duk_bool_t duk_get_boolean(duk_hthread *thr, duk_idx_t idx) {
19575 	DUK_ASSERT_API_ENTRY(thr);
19576 
19577 	return duk__get_boolean_raw(thr, idx, 0);  /* default: false */
19578 }
19579 
duk_get_boolean_default(duk_hthread * thr,duk_idx_t idx,duk_bool_t def_value)19580 DUK_EXTERNAL duk_bool_t duk_get_boolean_default(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {
19581 	DUK_ASSERT_API_ENTRY(thr);
19582 
19583 	return duk__get_boolean_raw(thr, idx, def_value);
19584 }
19585 
duk_require_boolean(duk_hthread * thr,duk_idx_t idx)19586 DUK_EXTERNAL duk_bool_t duk_require_boolean(duk_hthread *thr, duk_idx_t idx) {
19587 	duk_tval *tv;
19588 	duk_bool_t ret;
19589 
19590 	DUK_ASSERT_API_ENTRY(thr);
19591 
19592 	tv = duk_get_tval_or_unused(thr, idx);
19593 	DUK_ASSERT(tv != NULL);
19594 	if (DUK_LIKELY(DUK_TVAL_IS_BOOLEAN(tv))) {
19595 		ret = DUK_TVAL_GET_BOOLEAN(tv);
19596 		DUK_ASSERT(ret == 0 || ret == 1);
19597 		return ret;
19598 	} else {
19599 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "boolean", DUK_STR_NOT_BOOLEAN);
19600 		DUK_WO_NORETURN(return 0;);
19601 	}
19602 }
19603 
duk_opt_boolean(duk_hthread * thr,duk_idx_t idx,duk_bool_t def_value)19604 DUK_EXTERNAL duk_bool_t duk_opt_boolean(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {
19605 	DUK_ASSERT_API_ENTRY(thr);
19606 
19607 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19608 		return def_value;
19609 	}
19610 	return duk_require_boolean(thr, idx);
19611 }
19612 
duk__get_number_raw(duk_hthread * thr,duk_idx_t idx,duk_double_t def_value)19613 DUK_LOCAL DUK_ALWAYS_INLINE duk_double_t duk__get_number_raw(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {
19614 	duk_double_union ret;
19615 	duk_tval *tv;
19616 
19617 	DUK_CTX_ASSERT_VALID(thr);
19618 
19619 	tv = duk_get_tval_or_unused(thr, idx);
19620 	DUK_ASSERT(tv != NULL);
19621 #if defined(DUK_USE_FASTINT)
19622 	if (DUK_TVAL_IS_FASTINT(tv)) {
19623 		ret.d = (duk_double_t) DUK_TVAL_GET_FASTINT(tv);  /* XXX: cast trick */
19624 	}
19625 	else
19626 #endif
19627 	if (DUK_TVAL_IS_DOUBLE(tv)) {
19628 		/* When using packed duk_tval, number must be in NaN-normalized form
19629 		 * for it to be a duk_tval, so no need to normalize.  NOP for unpacked
19630 		 * duk_tval.
19631 		 */
19632 		ret.d = DUK_TVAL_GET_DOUBLE(tv);
19633 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&ret));
19634 	} else {
19635 		ret.d = def_value;
19636 		/* Default value (including NaN) may not be normalized. */
19637 	}
19638 
19639 	return ret.d;
19640 }
19641 
duk_get_number(duk_hthread * thr,duk_idx_t idx)19642 DUK_EXTERNAL duk_double_t duk_get_number(duk_hthread *thr, duk_idx_t idx) {
19643 	DUK_ASSERT_API_ENTRY(thr);
19644 	return duk__get_number_raw(thr, idx, DUK_DOUBLE_NAN);  /* default: NaN */
19645 }
19646 
duk_get_number_default(duk_hthread * thr,duk_idx_t idx,duk_double_t def_value)19647 DUK_EXTERNAL duk_double_t duk_get_number_default(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {
19648 	DUK_ASSERT_API_ENTRY(thr);
19649 	return duk__get_number_raw(thr, idx, def_value);
19650 }
19651 
duk_require_number(duk_hthread * thr,duk_idx_t idx)19652 DUK_EXTERNAL duk_double_t duk_require_number(duk_hthread *thr, duk_idx_t idx) {
19653 	duk_tval *tv;
19654 	duk_double_union ret;
19655 
19656 	DUK_ASSERT_API_ENTRY(thr);
19657 
19658 	tv = duk_get_tval_or_unused(thr, idx);
19659 	DUK_ASSERT(tv != NULL);
19660 	if (DUK_UNLIKELY(!DUK_TVAL_IS_NUMBER(tv))) {
19661 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
19662 		DUK_WO_NORETURN(return 0.0;);
19663 	}
19664 
19665 	ret.d = DUK_TVAL_GET_NUMBER(tv);
19666 
19667 	/* When using packed duk_tval, number must be in NaN-normalized form
19668 	 * for it to be a duk_tval, so no need to normalize.  NOP for unpacked
19669 	 * duk_tval.
19670 	 */
19671 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&ret));
19672 	return ret.d;
19673 }
19674 
duk_opt_number(duk_hthread * thr,duk_idx_t idx,duk_double_t def_value)19675 DUK_EXTERNAL duk_double_t duk_opt_number(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {
19676 	DUK_ASSERT_API_ENTRY(thr);
19677 
19678 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19679 		/* User provided default is not NaN normalized. */
19680 		return def_value;
19681 	}
19682 	return duk_require_number(thr, idx);
19683 }
19684 
duk_get_int(duk_hthread * thr,duk_idx_t idx)19685 DUK_EXTERNAL duk_int_t duk_get_int(duk_hthread *thr, duk_idx_t idx) {
19686 	DUK_ASSERT_API_ENTRY(thr);
19687 
19688 	return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 0 /*require*/);
19689 }
19690 
duk_get_uint(duk_hthread * thr,duk_idx_t idx)19691 DUK_EXTERNAL duk_uint_t duk_get_uint(duk_hthread *thr, duk_idx_t idx) {
19692 	DUK_ASSERT_API_ENTRY(thr);
19693 
19694 	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 0 /*require*/);
19695 }
19696 
duk_get_int_default(duk_hthread * thr,duk_idx_t idx,duk_int_t def_value)19697 DUK_EXTERNAL duk_int_t duk_get_int_default(duk_hthread *thr, duk_idx_t idx, duk_int_t def_value) {
19698 	DUK_ASSERT_API_ENTRY(thr);
19699 
19700 	return (duk_int_t) duk__api_coerce_d2i(thr, idx, def_value, 0 /*require*/);
19701 }
19702 
duk_get_uint_default(duk_hthread * thr,duk_idx_t idx,duk_uint_t def_value)19703 DUK_EXTERNAL duk_uint_t duk_get_uint_default(duk_hthread *thr, duk_idx_t idx, duk_uint_t def_value) {
19704 	DUK_ASSERT_API_ENTRY(thr);
19705 
19706 	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, def_value, 0 /*require*/);
19707 }
19708 
duk_require_int(duk_hthread * thr,duk_idx_t idx)19709 DUK_EXTERNAL duk_int_t duk_require_int(duk_hthread *thr, duk_idx_t idx) {
19710 	DUK_ASSERT_API_ENTRY(thr);
19711 
19712 	return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 1 /*require*/);
19713 }
19714 
duk_require_uint(duk_hthread * thr,duk_idx_t idx)19715 DUK_EXTERNAL duk_uint_t duk_require_uint(duk_hthread *thr, duk_idx_t idx) {
19716 	DUK_ASSERT_API_ENTRY(thr);
19717 
19718 	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 1 /*require*/);
19719 }
19720 
duk_opt_int(duk_hthread * thr,duk_idx_t idx,duk_int_t def_value)19721 DUK_EXTERNAL duk_int_t duk_opt_int(duk_hthread *thr, duk_idx_t idx, duk_int_t def_value) {
19722 	DUK_ASSERT_API_ENTRY(thr);
19723 
19724 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19725 		return def_value;
19726 	}
19727 	return duk_require_int(thr, idx);
19728 }
19729 
duk_opt_uint(duk_hthread * thr,duk_idx_t idx,duk_uint_t def_value)19730 DUK_EXTERNAL duk_uint_t duk_opt_uint(duk_hthread *thr, duk_idx_t idx, duk_uint_t def_value) {
19731 	DUK_ASSERT_API_ENTRY(thr);
19732 
19733 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19734 		return def_value;
19735 	}
19736 	return duk_require_uint(thr, idx);
19737 }
19738 
duk_get_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)19739 DUK_EXTERNAL const char *duk_get_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
19740 	duk_hstring *h;
19741 	const char *ret;
19742 	duk_size_t len;
19743 
19744 	DUK_ASSERT_API_ENTRY(thr);
19745 
19746 	h = duk_get_hstring(thr, idx);
19747 	if (h != NULL) {
19748 		len = DUK_HSTRING_GET_BYTELEN(h);
19749 		ret = (const char *) DUK_HSTRING_GET_DATA(h);
19750 	} else {
19751 		len = 0;
19752 		ret = NULL;
19753 	}
19754 
19755 	if (out_len != NULL) {
19756 		*out_len = len;
19757 	}
19758 	return ret;
19759 }
19760 
duk_require_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)19761 DUK_EXTERNAL const char *duk_require_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
19762 	duk_hstring *h;
19763 
19764 	DUK_ASSERT_API_ENTRY(thr);
19765 
19766 	h = duk_require_hstring(thr, idx);
19767 	DUK_ASSERT(h != NULL);
19768 	if (out_len) {
19769 		*out_len = DUK_HSTRING_GET_BYTELEN(h);
19770 	}
19771 	return (const char *) DUK_HSTRING_GET_DATA(h);
19772 }
19773 
duk_require_lstring_notsymbol(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)19774 DUK_INTERNAL const char *duk_require_lstring_notsymbol(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
19775 	duk_hstring *h;
19776 
19777 	DUK_ASSERT_API_ENTRY(thr);
19778 
19779 	h = duk_require_hstring_notsymbol(thr, idx);
19780 	DUK_ASSERT(h != NULL);
19781 	if (out_len) {
19782 		*out_len = DUK_HSTRING_GET_BYTELEN(h);
19783 	}
19784 	return (const char *) DUK_HSTRING_GET_DATA(h);
19785 }
19786 
duk_get_string(duk_hthread * thr,duk_idx_t idx)19787 DUK_EXTERNAL const char *duk_get_string(duk_hthread *thr, duk_idx_t idx) {
19788 	duk_hstring *h;
19789 
19790 	DUK_ASSERT_API_ENTRY(thr);
19791 
19792 	h = duk_get_hstring(thr, idx);
19793 	if (h != NULL) {
19794 		return (const char *) DUK_HSTRING_GET_DATA(h);
19795 	} else {
19796 		return NULL;
19797 	}
19798 }
19799 
duk_opt_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len,const char * def_ptr,duk_size_t def_len)19800 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) {
19801 	DUK_ASSERT_API_ENTRY(thr);
19802 
19803 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19804 		if (out_len != NULL) {
19805 			*out_len = def_len;
19806 		}
19807 		return def_ptr;
19808 	}
19809 	return duk_require_lstring(thr, idx, out_len);
19810 }
19811 
duk_opt_string(duk_hthread * thr,duk_idx_t idx,const char * def_ptr)19812 DUK_EXTERNAL const char *duk_opt_string(duk_hthread *thr, duk_idx_t idx, const char *def_ptr) {
19813 	DUK_ASSERT_API_ENTRY(thr);
19814 
19815 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19816 		return def_ptr;
19817 	}
19818 	return duk_require_string(thr, idx);
19819 }
19820 
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)19821 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) {
19822 	duk_hstring *h;
19823 	const char *ret;
19824 	duk_size_t len;
19825 
19826 	DUK_ASSERT_API_ENTRY(thr);
19827 
19828 	h = duk_get_hstring(thr, idx);
19829 	if (h != NULL) {
19830 		len = DUK_HSTRING_GET_BYTELEN(h);
19831 		ret = (const char *) DUK_HSTRING_GET_DATA(h);
19832 	} else {
19833 		len = def_len;
19834 		ret = def_ptr;
19835 	}
19836 
19837 	if (out_len != NULL) {
19838 		*out_len = len;
19839 	}
19840 	return ret;
19841 }
19842 
duk_get_string_default(duk_hthread * thr,duk_idx_t idx,const char * def_value)19843 DUK_EXTERNAL const char *duk_get_string_default(duk_hthread *thr, duk_idx_t idx, const char *def_value) {
19844 	duk_hstring *h;
19845 
19846 	DUK_ASSERT_API_ENTRY(thr);
19847 
19848 	h = duk_get_hstring(thr, idx);
19849 	if (h != NULL) {
19850 		return (const char *) DUK_HSTRING_GET_DATA(h);
19851 	} else {
19852 		return def_value;
19853 	}
19854 }
19855 
duk_get_string_notsymbol(duk_hthread * thr,duk_idx_t idx)19856 DUK_INTERNAL const char *duk_get_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {
19857 	duk_hstring *h;
19858 
19859 	DUK_ASSERT_API_ENTRY(thr);
19860 
19861 	h = duk_get_hstring_notsymbol(thr, idx);
19862 	if (h) {
19863 		return (const char *) DUK_HSTRING_GET_DATA(h);
19864 	} else {
19865 		return NULL;
19866 	}
19867 }
19868 
duk_require_string(duk_hthread * thr,duk_idx_t idx)19869 DUK_EXTERNAL const char *duk_require_string(duk_hthread *thr, duk_idx_t idx) {
19870 	DUK_ASSERT_API_ENTRY(thr);
19871 
19872 	return duk_require_lstring(thr, idx, NULL);
19873 }
19874 
duk_require_string_notsymbol(duk_hthread * thr,duk_idx_t idx)19875 DUK_INTERNAL const char *duk_require_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {
19876 	duk_hstring *h;
19877 
19878 	DUK_ASSERT_API_ENTRY(thr);
19879 
19880 	h = duk_require_hstring_notsymbol(thr, idx);
19881 	DUK_ASSERT(h != NULL);
19882 	return (const char *) DUK_HSTRING_GET_DATA(h);
19883 }
19884 
duk_require_object(duk_hthread * thr,duk_idx_t idx)19885 DUK_EXTERNAL void duk_require_object(duk_hthread *thr, duk_idx_t idx) {
19886 	duk_tval *tv;
19887 
19888 	DUK_ASSERT_API_ENTRY(thr);
19889 
19890 	tv = duk_get_tval_or_unused(thr, idx);
19891 	DUK_ASSERT(tv != NULL);
19892 	if (DUK_UNLIKELY(!DUK_TVAL_IS_OBJECT(tv))) {
19893 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
19894 		DUK_WO_NORETURN(return;);
19895 	}
19896 }
19897 
duk__get_pointer_raw(duk_hthread * thr,duk_idx_t idx,void * def_value)19898 DUK_LOCAL void *duk__get_pointer_raw(duk_hthread *thr, duk_idx_t idx, void *def_value) {
19899 	duk_tval *tv;
19900 	void *p;
19901 
19902 	DUK_CTX_ASSERT_VALID(thr);
19903 
19904 	tv = duk_get_tval_or_unused(thr, idx);
19905 	DUK_ASSERT(tv != NULL);
19906 	if (!DUK_TVAL_IS_POINTER(tv)) {
19907 		return def_value;
19908 	}
19909 
19910 	p = DUK_TVAL_GET_POINTER(tv);  /* may be NULL */
19911 	return p;
19912 }
19913 
duk_get_pointer(duk_hthread * thr,duk_idx_t idx)19914 DUK_EXTERNAL void *duk_get_pointer(duk_hthread *thr, duk_idx_t idx) {
19915 	DUK_ASSERT_API_ENTRY(thr);
19916 	return duk__get_pointer_raw(thr, idx, NULL /*def_value*/);
19917 }
19918 
duk_opt_pointer(duk_hthread * thr,duk_idx_t idx,void * def_value)19919 DUK_EXTERNAL void *duk_opt_pointer(duk_hthread *thr, duk_idx_t idx, void *def_value) {
19920 	DUK_ASSERT_API_ENTRY(thr);
19921 
19922 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19923 		return def_value;
19924 	}
19925 	return duk_require_pointer(thr, idx);
19926 }
19927 
duk_get_pointer_default(duk_hthread * thr,duk_idx_t idx,void * def_value)19928 DUK_EXTERNAL void *duk_get_pointer_default(duk_hthread *thr, duk_idx_t idx, void *def_value) {
19929 	DUK_ASSERT_API_ENTRY(thr);
19930 	return duk__get_pointer_raw(thr, idx, def_value);
19931 }
19932 
duk_require_pointer(duk_hthread * thr,duk_idx_t idx)19933 DUK_EXTERNAL void *duk_require_pointer(duk_hthread *thr, duk_idx_t idx) {
19934 	duk_tval *tv;
19935 	void *p;
19936 
19937 	DUK_ASSERT_API_ENTRY(thr);
19938 
19939 	/* Note: here we must be wary of the fact that a pointer may be
19940 	 * valid and be a NULL.
19941 	 */
19942 	tv = duk_get_tval_or_unused(thr, idx);
19943 	DUK_ASSERT(tv != NULL);
19944 	if (DUK_UNLIKELY(!DUK_TVAL_IS_POINTER(tv))) {
19945 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "pointer", DUK_STR_NOT_POINTER);
19946 		DUK_WO_NORETURN(return NULL;);
19947 	}
19948 	p = DUK_TVAL_GET_POINTER(tv);  /* may be NULL */
19949 	return p;
19950 }
19951 
19952 #if 0  /*unused*/
19953 DUK_INTERNAL void *duk_get_voidptr(duk_hthread *thr, duk_idx_t idx) {
19954 	duk_tval *tv;
19955 	duk_heaphdr *h;
19956 
19957 	DUK_ASSERT_API_ENTRY(thr);
19958 
19959 	tv = duk_get_tval_or_unused(thr, idx);
19960 	DUK_ASSERT(tv != NULL);
19961 	if (!DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
19962 		return NULL;
19963 	}
19964 
19965 	h = DUK_TVAL_GET_HEAPHDR(tv);
19966 	DUK_ASSERT(h != NULL);
19967 	return (void *) h;
19968 }
19969 #endif
19970 
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)19971 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) {
19972 	duk_hbuffer *h;
19973 	void *ret;
19974 	duk_size_t len;
19975 	duk_tval *tv;
19976 
19977 	DUK_CTX_ASSERT_VALID(thr);
19978 
19979 	if (out_size != NULL) {
19980 		*out_size = 0;
19981 	}
19982 
19983 	tv = duk_get_tval_or_unused(thr, idx);
19984 	DUK_ASSERT(tv != NULL);
19985 	if (DUK_LIKELY(DUK_TVAL_IS_BUFFER(tv))) {
19986 		h = DUK_TVAL_GET_BUFFER(tv);
19987 		DUK_ASSERT(h != NULL);
19988 
19989 		len = DUK_HBUFFER_GET_SIZE(h);
19990 		ret = DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);
19991 	} else {
19992 		if (throw_flag) {
19993 			DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
19994 			DUK_WO_NORETURN(return NULL;);
19995 		}
19996 		len = def_size;
19997 		ret = def_ptr;
19998 	}
19999 
20000 	if (out_size != NULL) {
20001 		*out_size = len;
20002 	}
20003 	return ret;
20004 }
20005 
duk_get_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)20006 DUK_EXTERNAL void *duk_get_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
20007 	DUK_ASSERT_API_ENTRY(thr);
20008 
20009 	return duk__get_buffer_helper(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/);
20010 }
20011 
duk_opt_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,void * def_ptr,duk_size_t def_size)20012 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) {
20013 	DUK_ASSERT_API_ENTRY(thr);
20014 
20015 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
20016 		if (out_size != NULL) {
20017 			*out_size = def_size;
20018 		}
20019 		return def_ptr;
20020 	}
20021 	return duk_require_buffer(thr, idx, out_size);
20022 }
20023 
duk_get_buffer_default(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,void * def_ptr,duk_size_t def_len)20024 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) {
20025 	DUK_ASSERT_API_ENTRY(thr);
20026 
20027 	return duk__get_buffer_helper(thr, idx, out_size, def_ptr, def_len, 0 /*throw_flag*/);
20028 }
20029 
duk_require_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)20030 DUK_EXTERNAL void *duk_require_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
20031 	DUK_ASSERT_API_ENTRY(thr);
20032 
20033 	return duk__get_buffer_helper(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 1 /*throw_flag*/);
20034 }
20035 
20036 /* Get the active buffer data area for a plain buffer or a buffer object.
20037  * Return NULL if the the value is not a buffer.  Note that a buffer may
20038  * have a NULL data pointer when its size is zero, the optional 'out_isbuffer'
20039  * argument allows caller to detect this reliably.
20040  */
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)20041 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) {
20042 	duk_tval *tv;
20043 
20044 	DUK_ASSERT_API_ENTRY(thr);
20045 
20046 	if (out_isbuffer != NULL) {
20047 		*out_isbuffer = 0;
20048 	}
20049 	if (out_size != NULL) {
20050 		*out_size = def_size;
20051 	}
20052 
20053 	tv = duk_get_tval_or_unused(thr, idx);
20054 	DUK_ASSERT(tv != NULL);
20055 
20056 	if (DUK_TVAL_IS_BUFFER(tv)) {
20057 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
20058 		DUK_ASSERT(h != NULL);
20059 		if (out_size != NULL) {
20060 			*out_size = DUK_HBUFFER_GET_SIZE(h);
20061 		}
20062 		if (out_isbuffer != NULL) {
20063 			*out_isbuffer = 1;
20064 		}
20065 		return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);  /* may be NULL (but only if size is 0) */
20066 	}
20067 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
20068 	else if (DUK_TVAL_IS_OBJECT(tv)) {
20069 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
20070 		DUK_ASSERT(h != NULL);
20071 		if (DUK_HOBJECT_IS_BUFOBJ(h)) {
20072 			/* XXX: this is probably a useful shared helper: for a
20073 			 * duk_hbufobj, get a validated buffer pointer/length.
20074 			 */
20075 			duk_hbufobj *h_bufobj = (duk_hbufobj *) h;
20076 			DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
20077 
20078 			if (h_bufobj->buf != NULL &&
20079 			    DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
20080 				duk_uint8_t *p;
20081 
20082 				p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf);
20083 				if (out_size != NULL) {
20084 					*out_size = (duk_size_t) h_bufobj->length;
20085 				}
20086 				if (out_isbuffer != NULL) {
20087 					*out_isbuffer = 1;
20088 				}
20089 				return (void *) (p + h_bufobj->offset);
20090 			}
20091 			/* if slice not fully valid, treat as error */
20092 		}
20093 	}
20094 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
20095 
20096 	if (throw_flag) {
20097 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
20098 		DUK_WO_NORETURN(return NULL;);
20099 	}
20100 	return def_ptr;
20101 }
20102 
duk_get_buffer_data(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)20103 DUK_EXTERNAL void *duk_get_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
20104 	DUK_ASSERT_API_ENTRY(thr);
20105 	return duk_get_buffer_data_raw(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, NULL);
20106 }
20107 
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)20108 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) {
20109 	DUK_ASSERT_API_ENTRY(thr);
20110 	return duk_get_buffer_data_raw(thr, idx, out_size, def_ptr, def_size, 0 /*throw_flag*/, NULL);
20111 }
20112 
duk_opt_buffer_data(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,void * def_ptr,duk_size_t def_size)20113 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) {
20114 	DUK_ASSERT_API_ENTRY(thr);
20115 
20116 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
20117 		if (out_size != NULL) {
20118 			*out_size = def_size;
20119 		}
20120 		return def_ptr;
20121 	}
20122 	return duk_require_buffer_data(thr, idx, out_size);
20123 }
20124 
duk_require_buffer_data(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)20125 DUK_EXTERNAL void *duk_require_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
20126 	DUK_ASSERT_API_ENTRY(thr);
20127 	return duk_get_buffer_data_raw(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 1 /*throw_flag*/, NULL);
20128 }
20129 
20130 /* Raw helper for getting a value from the stack, checking its tag.
20131  * The tag cannot be a number because numbers don't have an internal
20132  * tag in the packed representation.
20133  */
20134 
duk__get_tagged_heaphdr_raw(duk_hthread * thr,duk_idx_t idx,duk_uint_t tag)20135 DUK_LOCAL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t tag) {
20136 	duk_tval *tv;
20137 	duk_heaphdr *ret;
20138 
20139 	DUK_CTX_ASSERT_VALID(thr);
20140 
20141 	tv = duk_get_tval_or_unused(thr, idx);
20142 	DUK_ASSERT(tv != NULL);
20143 	if (DUK_TVAL_GET_TAG(tv) != tag) {
20144 		return (duk_heaphdr *) NULL;
20145 	}
20146 
20147 	ret = DUK_TVAL_GET_HEAPHDR(tv);
20148 	DUK_ASSERT(ret != NULL);  /* tagged null pointers should never occur */
20149 	return ret;
20150 
20151 }
20152 
duk_get_hstring(duk_hthread * thr,duk_idx_t idx)20153 DUK_INTERNAL duk_hstring *duk_get_hstring(duk_hthread *thr, duk_idx_t idx) {
20154 	DUK_ASSERT_API_ENTRY(thr);
20155 	return (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
20156 }
20157 
duk_get_hstring_notsymbol(duk_hthread * thr,duk_idx_t idx)20158 DUK_INTERNAL duk_hstring *duk_get_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx) {
20159 	duk_hstring *h;
20160 
20161 	DUK_ASSERT_API_ENTRY(thr);
20162 
20163 	h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
20164 	if (DUK_UNLIKELY(h && DUK_HSTRING_HAS_SYMBOL(h))) {
20165 		return NULL;
20166 	}
20167 	return h;
20168 }
20169 
duk_require_hstring(duk_hthread * thr,duk_idx_t idx)20170 DUK_INTERNAL duk_hstring *duk_require_hstring(duk_hthread *thr, duk_idx_t idx) {
20171 	duk_hstring *h;
20172 
20173 	DUK_ASSERT_API_ENTRY(thr);
20174 
20175 	h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
20176 	if (DUK_UNLIKELY(h == NULL)) {
20177 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "string", DUK_STR_NOT_STRING);
20178 		DUK_WO_NORETURN(return NULL;);
20179 	}
20180 	return h;
20181 }
20182 
duk_require_hstring_notsymbol(duk_hthread * thr,duk_idx_t idx)20183 DUK_INTERNAL duk_hstring *duk_require_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx) {
20184 	duk_hstring *h;
20185 
20186 	DUK_ASSERT_API_ENTRY(thr);
20187 
20188 	h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
20189 	if (DUK_UNLIKELY(h == NULL || DUK_HSTRING_HAS_SYMBOL(h))) {
20190 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "string", DUK_STR_NOT_STRING);
20191 		DUK_WO_NORETURN(return NULL;);
20192 	}
20193 	return h;
20194 }
20195 
duk_get_hobject(duk_hthread * thr,duk_idx_t idx)20196 DUK_INTERNAL duk_hobject *duk_get_hobject(duk_hthread *thr, duk_idx_t idx) {
20197 	DUK_ASSERT_API_ENTRY(thr);
20198 	return (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20199 }
20200 
duk_require_hobject(duk_hthread * thr,duk_idx_t idx)20201 DUK_INTERNAL duk_hobject *duk_require_hobject(duk_hthread *thr, duk_idx_t idx) {
20202 	duk_hobject *h;
20203 
20204 	DUK_ASSERT_API_ENTRY(thr);
20205 
20206 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20207 	if (DUK_UNLIKELY(h == NULL)) {
20208 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
20209 		DUK_WO_NORETURN(return NULL;);
20210 	}
20211 	return h;
20212 }
20213 
duk_get_hbuffer(duk_hthread * thr,duk_idx_t idx)20214 DUK_INTERNAL duk_hbuffer *duk_get_hbuffer(duk_hthread *thr, duk_idx_t idx) {
20215 	DUK_ASSERT_API_ENTRY(thr);
20216 	return (duk_hbuffer *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_BUFFER);
20217 }
20218 
duk_require_hbuffer(duk_hthread * thr,duk_idx_t idx)20219 DUK_INTERNAL duk_hbuffer *duk_require_hbuffer(duk_hthread *thr, duk_idx_t idx) {
20220 	duk_hbuffer *h;
20221 
20222 	DUK_ASSERT_API_ENTRY(thr);
20223 
20224 	h = (duk_hbuffer *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_BUFFER);
20225 	if (DUK_UNLIKELY(h == NULL)) {
20226 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
20227 		DUK_WO_NORETURN(return NULL;);
20228 	}
20229 	return h;
20230 }
20231 
duk_get_hthread(duk_hthread * thr,duk_idx_t idx)20232 DUK_INTERNAL duk_hthread *duk_get_hthread(duk_hthread *thr, duk_idx_t idx) {
20233 	duk_hobject *h;
20234 
20235 	DUK_ASSERT_API_ENTRY(thr);
20236 
20237 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20238 	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_THREAD(h))) {
20239 		h = NULL;
20240 	}
20241 	return (duk_hthread *) h;
20242 }
20243 
duk_require_hthread(duk_hthread * thr,duk_idx_t idx)20244 DUK_INTERNAL duk_hthread *duk_require_hthread(duk_hthread *thr, duk_idx_t idx) {
20245 	duk_hobject *h;
20246 
20247 	DUK_ASSERT_API_ENTRY(thr);
20248 
20249 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20250 	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_THREAD(h)))) {
20251 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "thread", DUK_STR_NOT_THREAD);
20252 		DUK_WO_NORETURN(return NULL;);
20253 	}
20254 	return (duk_hthread *) h;
20255 }
20256 
duk_get_hcompfunc(duk_hthread * thr,duk_idx_t idx)20257 DUK_INTERNAL duk_hcompfunc *duk_get_hcompfunc(duk_hthread *thr, duk_idx_t idx) {
20258 	duk_hobject *h;
20259 
20260 	DUK_ASSERT_API_ENTRY(thr);
20261 
20262 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20263 	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_COMPFUNC(h))) {
20264 		h = NULL;
20265 	}
20266 	return (duk_hcompfunc *) h;
20267 }
20268 
duk_require_hcompfunc(duk_hthread * thr,duk_idx_t idx)20269 DUK_INTERNAL duk_hcompfunc *duk_require_hcompfunc(duk_hthread *thr, duk_idx_t idx) {
20270 	duk_hobject *h;
20271 
20272 	DUK_ASSERT_API_ENTRY(thr);
20273 
20274 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20275 	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_COMPFUNC(h)))) {
20276 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "compiledfunction", DUK_STR_NOT_COMPFUNC);
20277 		DUK_WO_NORETURN(return NULL;);
20278 	}
20279 	return (duk_hcompfunc *) h;
20280 }
20281 
duk_get_hnatfunc(duk_hthread * thr,duk_idx_t idx)20282 DUK_INTERNAL duk_hnatfunc *duk_get_hnatfunc(duk_hthread *thr, duk_idx_t idx) {
20283 	duk_hobject *h;
20284 
20285 	DUK_ASSERT_API_ENTRY(thr);
20286 
20287 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20288 	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_NATFUNC(h))) {
20289 		h = NULL;
20290 	}
20291 	return (duk_hnatfunc *) h;
20292 }
20293 
duk_require_hnatfunc(duk_hthread * thr,duk_idx_t idx)20294 DUK_INTERNAL duk_hnatfunc *duk_require_hnatfunc(duk_hthread *thr, duk_idx_t idx) {
20295 	duk_hobject *h;
20296 
20297 	DUK_ASSERT_API_ENTRY(thr);
20298 
20299 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20300 	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_NATFUNC(h)))) {
20301 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "nativefunction", DUK_STR_NOT_NATFUNC);
20302 		DUK_WO_NORETURN(return NULL;);
20303 	}
20304 	return (duk_hnatfunc *) h;
20305 }
20306 
duk_get_c_function(duk_hthread * thr,duk_idx_t idx)20307 DUK_EXTERNAL duk_c_function duk_get_c_function(duk_hthread *thr, duk_idx_t idx) {
20308 	duk_tval *tv;
20309 	duk_hobject *h;
20310 	duk_hnatfunc *f;
20311 
20312 	DUK_ASSERT_API_ENTRY(thr);
20313 
20314 	tv = duk_get_tval_or_unused(thr, idx);
20315 	DUK_ASSERT(tv != NULL);
20316 	if (DUK_UNLIKELY(!DUK_TVAL_IS_OBJECT(tv))) {
20317 		return NULL;
20318 	}
20319 	h = DUK_TVAL_GET_OBJECT(tv);
20320 	DUK_ASSERT(h != NULL);
20321 
20322 	if (DUK_UNLIKELY(!DUK_HOBJECT_IS_NATFUNC(h))) {
20323 		return NULL;
20324 	}
20325 	DUK_ASSERT(DUK_HOBJECT_HAS_NATFUNC(h));
20326 	f = (duk_hnatfunc *) h;
20327 
20328 	return f->func;
20329 }
20330 
duk_opt_c_function(duk_hthread * thr,duk_idx_t idx,duk_c_function def_value)20331 DUK_EXTERNAL duk_c_function duk_opt_c_function(duk_hthread *thr, duk_idx_t idx, duk_c_function def_value) {
20332 	DUK_ASSERT_API_ENTRY(thr);
20333 
20334 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
20335 		return def_value;
20336 	}
20337 	return duk_require_c_function(thr, idx);
20338 }
20339 
duk_get_c_function_default(duk_hthread * thr,duk_idx_t idx,duk_c_function def_value)20340 DUK_EXTERNAL duk_c_function duk_get_c_function_default(duk_hthread *thr, duk_idx_t idx, duk_c_function def_value) {
20341 	duk_c_function ret;
20342 
20343 	DUK_ASSERT_API_ENTRY(thr);
20344 
20345 	ret = duk_get_c_function(thr, idx);
20346 	if (ret != NULL) {
20347 		return ret;
20348 	}
20349 
20350 	return def_value;
20351 }
20352 
duk_require_c_function(duk_hthread * thr,duk_idx_t idx)20353 DUK_EXTERNAL duk_c_function duk_require_c_function(duk_hthread *thr, duk_idx_t idx) {
20354 	duk_c_function ret;
20355 
20356 	DUK_ASSERT_API_ENTRY(thr);
20357 
20358 	ret = duk_get_c_function(thr, idx);
20359 	if (DUK_UNLIKELY(!ret)) {
20360 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "nativefunction", DUK_STR_NOT_NATFUNC);
20361 		DUK_WO_NORETURN(return ret;);
20362 	}
20363 	return ret;
20364 }
20365 
duk_require_function(duk_hthread * thr,duk_idx_t idx)20366 DUK_EXTERNAL void duk_require_function(duk_hthread *thr, duk_idx_t idx) {
20367 	DUK_ASSERT_API_ENTRY(thr);
20368 	if (DUK_UNLIKELY(!duk_is_function(thr, idx))) {
20369 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "function", DUK_STR_NOT_FUNCTION);
20370 		DUK_WO_NORETURN(return;);
20371 	}
20372 }
20373 
duk_require_constructable(duk_hthread * thr,duk_idx_t idx)20374 DUK_EXTERNAL void duk_require_constructable(duk_hthread *thr, duk_idx_t idx) {
20375 	duk_hobject *h;
20376 
20377 	DUK_ASSERT_API_ENTRY(thr);
20378 
20379 	h = duk_require_hobject_accept_mask(thr, idx, DUK_TYPE_MASK_LIGHTFUNC);
20380 	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_HAS_CONSTRUCTABLE(h))) {
20381 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "constructable", DUK_STR_NOT_CONSTRUCTABLE);
20382 		DUK_WO_NORETURN(return;);
20383 	}
20384 	/* Lightfuncs (h == NULL) are constructable. */
20385 }
20386 
duk_get_context(duk_hthread * thr,duk_idx_t idx)20387 DUK_EXTERNAL duk_hthread *duk_get_context(duk_hthread *thr, duk_idx_t idx) {
20388 	DUK_ASSERT_API_ENTRY(thr);
20389 
20390 	return duk_get_hthread(thr, idx);
20391 }
20392 
duk_require_context(duk_hthread * thr,duk_idx_t idx)20393 DUK_EXTERNAL duk_hthread *duk_require_context(duk_hthread *thr, duk_idx_t idx) {
20394 	DUK_ASSERT_API_ENTRY(thr);
20395 
20396 	return duk_require_hthread(thr, idx);
20397 }
20398 
duk_opt_context(duk_hthread * thr,duk_idx_t idx,duk_hthread * def_value)20399 DUK_EXTERNAL duk_hthread *duk_opt_context(duk_hthread *thr, duk_idx_t idx, duk_hthread *def_value) {
20400 	DUK_ASSERT_API_ENTRY(thr);
20401 
20402 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
20403 		return def_value;
20404 	}
20405 	return duk_require_context(thr, idx);
20406 }
20407 
duk_get_context_default(duk_hthread * thr,duk_idx_t idx,duk_hthread * def_value)20408 DUK_EXTERNAL duk_hthread *duk_get_context_default(duk_hthread *thr, duk_idx_t idx, duk_hthread *def_value) {
20409 	duk_hthread *ret;
20410 
20411 	DUK_ASSERT_API_ENTRY(thr);
20412 
20413 	ret = duk_get_context(thr, idx);
20414 	if (ret != NULL) {
20415 		return ret;
20416 	}
20417 
20418 	return def_value;
20419 }
20420 
duk_get_heapptr(duk_hthread * thr,duk_idx_t idx)20421 DUK_EXTERNAL void *duk_get_heapptr(duk_hthread *thr, duk_idx_t idx) {
20422 	duk_tval *tv;
20423 	void *ret;
20424 
20425 	DUK_ASSERT_API_ENTRY(thr);
20426 
20427 	tv = duk_get_tval_or_unused(thr, idx);
20428 	DUK_ASSERT(tv != NULL);
20429 	if (DUK_UNLIKELY(!DUK_TVAL_IS_HEAP_ALLOCATED(tv))) {
20430 		return (void *) NULL;
20431 	}
20432 
20433 	ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
20434 	DUK_ASSERT(ret != NULL);
20435 	return ret;
20436 }
20437 
duk_opt_heapptr(duk_hthread * thr,duk_idx_t idx,void * def_value)20438 DUK_EXTERNAL void *duk_opt_heapptr(duk_hthread *thr, duk_idx_t idx, void *def_value) {
20439 	DUK_ASSERT_API_ENTRY(thr);
20440 
20441 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
20442 		return def_value;
20443 	}
20444 	return duk_require_heapptr(thr, idx);
20445 }
20446 
duk_get_heapptr_default(duk_hthread * thr,duk_idx_t idx,void * def_value)20447 DUK_EXTERNAL void *duk_get_heapptr_default(duk_hthread *thr, duk_idx_t idx, void *def_value) {
20448 	void *ret;
20449 
20450 	DUK_ASSERT_API_ENTRY(thr);
20451 
20452 	ret = duk_get_heapptr(thr, idx);
20453 	if (ret != NULL) {
20454 		return ret;
20455 	}
20456 
20457 	return def_value;
20458 }
20459 
duk_require_heapptr(duk_hthread * thr,duk_idx_t idx)20460 DUK_EXTERNAL void *duk_require_heapptr(duk_hthread *thr, duk_idx_t idx) {
20461 	duk_tval *tv;
20462 	void *ret;
20463 
20464 	DUK_ASSERT_API_ENTRY(thr);
20465 
20466 	tv = duk_get_tval_or_unused(thr, idx);
20467 	DUK_ASSERT(tv != NULL);
20468 	if (DUK_UNLIKELY(!DUK_TVAL_IS_HEAP_ALLOCATED(tv))) {
20469 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "heapobject", DUK_STR_UNEXPECTED_TYPE);
20470 		DUK_WO_NORETURN(return NULL;);
20471 	}
20472 
20473 	ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
20474 	DUK_ASSERT(ret != NULL);
20475 	return ret;
20476 }
20477 
20478 /* 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)20479 DUK_LOCAL duk_hobject *duk__get_hobject_promote_mask_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
20480 	duk_uint_t val_mask;
20481 	duk_hobject *res;
20482 
20483 	DUK_CTX_ASSERT_VALID(thr);
20484 
20485 	res = duk_get_hobject(thr, idx);  /* common case, not promoted */
20486 	if (DUK_LIKELY(res != NULL)) {
20487 		DUK_ASSERT(res != NULL);
20488 		return res;
20489 	}
20490 
20491 	val_mask = duk_get_type_mask(thr, idx);
20492 	if (val_mask & type_mask) {
20493 		if (type_mask & DUK_TYPE_MASK_PROMOTE) {
20494 			res = duk_to_hobject(thr, idx);
20495 			DUK_ASSERT(res != NULL);
20496 			return res;
20497 		} else {
20498 			return NULL;  /* accept without promoting */
20499 		}
20500 	}
20501 
20502 	if (type_mask & DUK_TYPE_MASK_THROW) {
20503 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
20504 		DUK_WO_NORETURN(return NULL;);
20505 	}
20506 	return NULL;
20507 }
20508 
20509 /* Get a duk_hobject * at 'idx'; if the value is not an object but matches the
20510  * supplied 'type_mask', promote it to an object and return the duk_hobject *.
20511  * This is useful for call sites which want an object but also accept a plain
20512  * buffer and/or a lightfunc which gets automatically promoted to an object.
20513  * Return value is NULL if value is neither an object nor a plain type allowed
20514  * by the mask.
20515  */
duk_get_hobject_promote_mask(duk_hthread * thr,duk_idx_t idx,duk_uint_t type_mask)20516 DUK_INTERNAL duk_hobject *duk_get_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
20517 	DUK_ASSERT_API_ENTRY(thr);
20518 	return duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_PROMOTE);
20519 }
20520 
20521 /* Like duk_get_hobject_promote_mask() but throw a TypeError instead of
20522  * returning a NULL.
20523  */
duk_require_hobject_promote_mask(duk_hthread * thr,duk_idx_t idx,duk_uint_t type_mask)20524 DUK_INTERNAL duk_hobject *duk_require_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
20525 	DUK_ASSERT_API_ENTRY(thr);
20526 	return duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_THROW | DUK_TYPE_MASK_PROMOTE);
20527 }
20528 
20529 /* Require a duk_hobject * at 'idx'; if the value is not an object but matches the
20530  * supplied 'type_mask', return a NULL instead.  Otherwise throw a TypeError.
20531  */
duk_require_hobject_accept_mask(duk_hthread * thr,duk_idx_t idx,duk_uint_t type_mask)20532 DUK_INTERNAL duk_hobject *duk_require_hobject_accept_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
20533 	DUK_ASSERT_API_ENTRY(thr);
20534 	return duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_THROW);
20535 }
20536 
duk_get_hobject_with_class(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t classnum)20537 DUK_INTERNAL duk_hobject *duk_get_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum) {
20538 	duk_hobject *h;
20539 
20540 	DUK_ASSERT_API_ENTRY(thr);
20541 	DUK_ASSERT_DISABLE(classnum >= 0);  /* unsigned */
20542 	DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
20543 
20544 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20545 	if (DUK_UNLIKELY(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) != classnum)) {
20546 		h = NULL;
20547 	}
20548 	return h;
20549 }
20550 
duk_require_hobject_with_class(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t classnum)20551 DUK_INTERNAL duk_hobject *duk_require_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum) {
20552 	duk_hobject *h;
20553 
20554 	DUK_ASSERT_API_ENTRY(thr);
20555 	DUK_ASSERT_DISABLE(classnum >= 0);  /* unsigned */
20556 	DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
20557 
20558 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20559 	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) == classnum))) {
20560 		duk_hstring *h_class;
20561 		h_class = DUK_HTHREAD_GET_STRING(thr, DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum));
20562 		DUK_UNREF(h_class);
20563 
20564 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, (const char *) DUK_HSTRING_GET_DATA(h_class), DUK_STR_UNEXPECTED_TYPE);
20565 		DUK_WO_NORETURN(return NULL;);
20566 	}
20567 	return h;
20568 }
20569 
duk_get_length(duk_hthread * thr,duk_idx_t idx)20570 DUK_EXTERNAL duk_size_t duk_get_length(duk_hthread *thr, duk_idx_t idx) {
20571 	duk_tval *tv;
20572 
20573 	DUK_ASSERT_API_ENTRY(thr);
20574 
20575 	tv = duk_get_tval_or_unused(thr, idx);
20576 	DUK_ASSERT(tv != NULL);
20577 
20578 	switch (DUK_TVAL_GET_TAG(tv)) {
20579 	case DUK_TAG_UNDEFINED:
20580 	case DUK_TAG_NULL:
20581 	case DUK_TAG_BOOLEAN:
20582 	case DUK_TAG_POINTER:
20583 		return 0;
20584 #if defined(DUK_USE_PREFER_SIZE)
20585 	/* String and buffer have a virtual non-configurable .length property
20586 	 * which is within size_t range so it can be looked up without specific
20587 	 * type checks.  Lightfuncs inherit from %NativeFunctionPrototype%
20588 	 * which provides an inherited .length accessor; it could be overwritten
20589 	 * to produce unexpected types or values, but just number convert and
20590 	 * duk_size_t cast for now.
20591 	 */
20592 	case DUK_TAG_STRING:
20593 	case DUK_TAG_BUFFER:
20594 	case DUK_TAG_LIGHTFUNC: {
20595 		duk_size_t ret;
20596 		duk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
20597 		ret = (duk_size_t) duk_to_number_m1(thr);
20598 		duk_pop_unsafe(thr);
20599 		return ret;
20600 	}
20601 #else  /* DUK_USE_PREFER_SIZE */
20602 	case DUK_TAG_STRING: {
20603 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
20604 		DUK_ASSERT(h != NULL);
20605 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
20606 			return 0;
20607 		}
20608 		return (duk_size_t) DUK_HSTRING_GET_CHARLEN(h);
20609 	}
20610 	case DUK_TAG_BUFFER: {
20611 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
20612 		DUK_ASSERT(h != NULL);
20613 		return (duk_size_t) DUK_HBUFFER_GET_SIZE(h);
20614 	}
20615 	case DUK_TAG_LIGHTFUNC: {
20616 		/* We could look up the length from the lightfunc duk_tval,
20617 		 * but since Duktape 2.2 lightfunc .length comes from
20618 		 * %NativeFunctionPrototype% which can be overridden, so
20619 		 * look up the property explicitly.
20620 		 */
20621 		duk_size_t ret;
20622 		duk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
20623 		ret = (duk_size_t) duk_to_number_m1(thr);
20624 		duk_pop_unsafe(thr);
20625 		return ret;
20626 	}
20627 #endif  /* DUK_USE_PREFER_SIZE */
20628 	case DUK_TAG_OBJECT: {
20629 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
20630 		DUK_ASSERT(h != NULL);
20631 		return (duk_size_t) duk_hobject_get_length(thr, h);
20632 	}
20633 #if defined(DUK_USE_FASTINT)
20634 	case DUK_TAG_FASTINT:
20635 #endif
20636 	default:
20637 		/* number or 'unused' */
20638 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv) || DUK_TVAL_IS_UNUSED(tv));
20639 		return 0;
20640 	}
20641 
20642 	DUK_UNREACHABLE();
20643 }
20644 
20645 /*
20646  *  duk_known_xxx() helpers
20647  *
20648  *  Used internally when we're 100% sure that a certain index is valid and
20649  *  contains an object of a certain type.  For example, if we duk_push_object()
20650  *  we can then safely duk_known_hobject(thr, -1).  These helpers just assert
20651  *  for the index and type, and if the assumptions are not valid, memory unsafe
20652  *  behavior happens.
20653  */
20654 
duk__known_heaphdr(duk_hthread * thr,duk_idx_t idx)20655 DUK_LOCAL duk_heaphdr *duk__known_heaphdr(duk_hthread *thr, duk_idx_t idx) {
20656 	duk_tval *tv;
20657 	duk_heaphdr *h;
20658 
20659 	DUK_CTX_ASSERT_VALID(thr);
20660 	if (idx < 0) {
20661 		tv = thr->valstack_top + idx;
20662 	} else {
20663 		tv = thr->valstack_bottom + idx;
20664 	}
20665 	DUK_ASSERT(tv >= thr->valstack_bottom);
20666 	DUK_ASSERT(tv < thr->valstack_top);
20667 	h = DUK_TVAL_GET_HEAPHDR(tv);
20668 	DUK_ASSERT(h != NULL);
20669 	return h;
20670 }
20671 
duk_known_hstring(duk_hthread * thr,duk_idx_t idx)20672 DUK_INTERNAL duk_hstring *duk_known_hstring(duk_hthread *thr, duk_idx_t idx) {
20673 	DUK_ASSERT_API_ENTRY(thr);
20674 	DUK_ASSERT(duk_get_hstring(thr, idx) != NULL);
20675 	return (duk_hstring *) duk__known_heaphdr(thr, idx);
20676 }
20677 
duk_known_hobject(duk_hthread * thr,duk_idx_t idx)20678 DUK_INTERNAL duk_hobject *duk_known_hobject(duk_hthread *thr, duk_idx_t idx) {
20679 	DUK_ASSERT_API_ENTRY(thr);
20680 	DUK_ASSERT(duk_get_hobject(thr, idx) != NULL);
20681 	return (duk_hobject *) duk__known_heaphdr(thr, idx);
20682 }
20683 
duk_known_hbuffer(duk_hthread * thr,duk_idx_t idx)20684 DUK_INTERNAL duk_hbuffer *duk_known_hbuffer(duk_hthread *thr, duk_idx_t idx) {
20685 	DUK_ASSERT_API_ENTRY(thr);
20686 	DUK_ASSERT(duk_get_hbuffer(thr, idx) != NULL);
20687 	return (duk_hbuffer *) duk__known_heaphdr(thr, idx);
20688 }
20689 
duk_known_hcompfunc(duk_hthread * thr,duk_idx_t idx)20690 DUK_INTERNAL duk_hcompfunc *duk_known_hcompfunc(duk_hthread *thr, duk_idx_t idx) {
20691 	DUK_ASSERT_API_ENTRY(thr);
20692 	DUK_ASSERT(duk_get_hcompfunc(thr, idx) != NULL);
20693 	return (duk_hcompfunc *) duk__known_heaphdr(thr, idx);
20694 }
20695 
duk_known_hnatfunc(duk_hthread * thr,duk_idx_t idx)20696 DUK_INTERNAL duk_hnatfunc *duk_known_hnatfunc(duk_hthread *thr, duk_idx_t idx) {
20697 	DUK_ASSERT_API_ENTRY(thr);
20698 	DUK_ASSERT(duk_get_hnatfunc(thr, idx) != NULL);
20699 	return (duk_hnatfunc *) duk__known_heaphdr(thr, idx);
20700 }
20701 
duk_set_length(duk_hthread * thr,duk_idx_t idx,duk_size_t len)20702 DUK_EXTERNAL void duk_set_length(duk_hthread *thr, duk_idx_t idx, duk_size_t len) {
20703 	DUK_ASSERT_API_ENTRY(thr);
20704 
20705 	idx = duk_normalize_index(thr, idx);
20706 	duk_push_uint(thr, (duk_uint_t) len);
20707 	duk_put_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
20708 }
20709 
20710 /*
20711  *  Conversions and coercions
20712  *
20713  *  The conversion/coercions are in-place operations on the value stack.
20714  *  Some operations are implemented here directly, while others call a
20715  *  helper in duk_js_ops.c after validating arguments.
20716  */
20717 
20718 /* E5 Section 8.12.8 */
20719 
duk__defaultvalue_coerce_attempt(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t func_stridx)20720 DUK_LOCAL duk_bool_t duk__defaultvalue_coerce_attempt(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t func_stridx) {
20721 	if (duk_get_prop_stridx(thr, idx, func_stridx)) {
20722 		/* [ ... func ] */
20723 		if (duk_is_callable(thr, -1)) {
20724 			duk_dup(thr, idx);         /* -> [ ... func this ] */
20725 			duk_call_method(thr, 0);     /* -> [ ... retval ] */
20726 			if (duk_is_primitive(thr, -1)) {
20727 				duk_replace(thr, idx);
20728 				return 1;
20729 			}
20730 			/* [ ... retval ]; popped below */
20731 		}
20732 	}
20733 	duk_pop_unsafe(thr);  /* [ ... func/retval ] -> [ ... ] */
20734 	return 0;
20735 }
20736 
duk_to_undefined(duk_hthread * thr,duk_idx_t idx)20737 DUK_EXTERNAL void duk_to_undefined(duk_hthread *thr, duk_idx_t idx) {
20738 	duk_tval *tv;
20739 
20740 	DUK_ASSERT_API_ENTRY(thr);
20741 
20742 	tv = duk_require_tval(thr, idx);
20743 	DUK_ASSERT(tv != NULL);
20744 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
20745 }
20746 
duk_to_null(duk_hthread * thr,duk_idx_t idx)20747 DUK_EXTERNAL void duk_to_null(duk_hthread *thr, duk_idx_t idx) {
20748 	duk_tval *tv;
20749 
20750 	DUK_ASSERT_API_ENTRY(thr);
20751 
20752 	tv = duk_require_tval(thr, idx);
20753 	DUK_ASSERT(tv != NULL);
20754 	DUK_TVAL_SET_NULL_UPDREF(thr, tv);  /* side effects */
20755 }
20756 
20757 /* E5 Section 9.1 */
20758 DUK_LOCAL const char * const duk__toprim_hint_strings[3] = {
20759 	"default", "string", "number"
20760 };
duk__to_primitive_helper(duk_hthread * thr,duk_idx_t idx,duk_int_t hint,duk_bool_t check_symbol)20761 DUK_LOCAL void duk__to_primitive_helper(duk_hthread *thr, duk_idx_t idx, duk_int_t hint, duk_bool_t check_symbol) {
20762 	/* Inline initializer for coercers[] is not allowed by old compilers like BCC. */
20763 	duk_small_uint_t coercers[2];
20764 
20765 	DUK_ASSERT_API_ENTRY(thr);
20766 	DUK_ASSERT(hint == DUK_HINT_NONE || hint == DUK_HINT_NUMBER || hint == DUK_HINT_STRING);
20767 
20768 	idx = duk_require_normalize_index(thr, idx);
20769 
20770 	/* If already primitive, return as is. */
20771 	if (!duk_check_type_mask(thr, idx, DUK_TYPE_MASK_OBJECT |
20772 	                                   DUK_TYPE_MASK_LIGHTFUNC |
20773 	                                   DUK_TYPE_MASK_BUFFER)) {
20774 		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */
20775 		return;
20776 	}
20777 
20778 	/* @@toPrimitive lookup.  Also do for plain buffers and lightfuncs
20779 	 * which mimic objects.
20780 	 */
20781 	if (check_symbol && duk_get_method_stridx(thr, idx, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)) {
20782 		DUK_ASSERT(hint >= 0 && (duk_size_t) hint < sizeof(duk__toprim_hint_strings) / sizeof(const char *));
20783 		duk_dup(thr, idx);
20784 		duk_push_string(thr, duk__toprim_hint_strings[hint]);
20785 		duk_call_method(thr, 1);  /* [ ... method value hint ] -> [ ... res] */
20786 		if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |
20787 	                                         DUK_TYPE_MASK_LIGHTFUNC |
20788 		                                 DUK_TYPE_MASK_BUFFER)) {
20789 			goto fail;
20790 		}
20791 		duk_replace(thr, idx);
20792 		return;
20793 	}
20794 
20795 	/* Objects are coerced based on E5 specification.
20796 	 * Lightfuncs are coerced because they behave like
20797 	 * objects even if they're internally a primitive
20798 	 * type.  Same applies to plain buffers, which behave
20799 	 * like ArrayBuffer objects since Duktape 2.x.
20800 	 */
20801 
20802 	/* Hint magic for Date is unnecessary in ES2015 because of
20803 	 * Date.prototype[@@toPrimitive].  However, it is needed if
20804 	 * symbol support is not enabled.
20805 	 */
20806 #if defined(DUK_USE_SYMBOL_BUILTIN)
20807 	if (hint == DUK_HINT_NONE) {
20808 		hint = DUK_HINT_NUMBER;
20809 	}
20810 #else  /* DUK_USE_SYMBOL_BUILTIN */
20811 	if (hint == DUK_HINT_NONE) {
20812 		duk_small_uint_t class_number;
20813 
20814 		class_number = duk_get_class_number(thr, idx);
20815 		if (class_number == DUK_HOBJECT_CLASS_DATE) {
20816 			hint = DUK_HINT_STRING;
20817 		} else {
20818 			hint = DUK_HINT_NUMBER;
20819 		}
20820 	}
20821 #endif  /* DUK_USE_SYMBOL_BUILTIN */
20822 
20823 	coercers[0] = DUK_STRIDX_VALUE_OF;
20824 	coercers[1] = DUK_STRIDX_TO_STRING;
20825 	if (hint == DUK_HINT_STRING) {
20826 		coercers[0] = DUK_STRIDX_TO_STRING;
20827 		coercers[1] = DUK_STRIDX_VALUE_OF;
20828 	}
20829 
20830 	if (duk__defaultvalue_coerce_attempt(thr, idx, coercers[0])) {
20831 		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */
20832 		return;
20833 	}
20834 
20835 	if (duk__defaultvalue_coerce_attempt(thr, idx, coercers[1])) {
20836 		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */
20837 		return;
20838 	}
20839 
20840  fail:
20841 	DUK_ERROR_TYPE(thr, DUK_STR_TOPRIMITIVE_FAILED);
20842 	DUK_WO_NORETURN(return;);
20843 }
20844 
duk_to_primitive(duk_hthread * thr,duk_idx_t idx,duk_int_t hint)20845 DUK_EXTERNAL void duk_to_primitive(duk_hthread *thr, duk_idx_t idx, duk_int_t hint) {
20846 	duk__to_primitive_helper(thr, idx, hint, 1 /*check_symbol*/);
20847 }
20848 
20849 #if defined(DUK_USE_SYMBOL_BUILTIN)
duk_to_primitive_ordinary(duk_hthread * thr,duk_idx_t idx,duk_int_t hint)20850 DUK_INTERNAL void duk_to_primitive_ordinary(duk_hthread *thr, duk_idx_t idx, duk_int_t hint) {
20851 	duk__to_primitive_helper(thr, idx, hint, 0 /*check_symbol*/);
20852 }
20853 #endif
20854 
20855 /* E5 Section 9.2 */
duk_to_boolean(duk_hthread * thr,duk_idx_t idx)20856 DUK_EXTERNAL duk_bool_t duk_to_boolean(duk_hthread *thr, duk_idx_t idx) {
20857 	duk_tval *tv;
20858 	duk_bool_t val;
20859 
20860 	DUK_ASSERT_API_ENTRY(thr);
20861 
20862 	idx = duk_require_normalize_index(thr, idx);
20863 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
20864 	DUK_ASSERT(tv != NULL);
20865 
20866 	val = duk_js_toboolean(tv);
20867 	DUK_ASSERT(val == 0 || val == 1);
20868 
20869 	/* Note: no need to re-lookup tv, conversion is side effect free. */
20870 	DUK_ASSERT(tv != NULL);
20871 	DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, val);  /* side effects */
20872 	return val;
20873 }
20874 
duk_to_boolean_top_pop(duk_hthread * thr)20875 DUK_INTERNAL duk_bool_t duk_to_boolean_top_pop(duk_hthread *thr) {
20876 	duk_tval *tv;
20877 	duk_bool_t val;
20878 
20879 	DUK_ASSERT_API_ENTRY(thr);
20880 
20881 	tv = duk_require_tval(thr, -1);
20882 	DUK_ASSERT(tv != NULL);
20883 
20884 	val = duk_js_toboolean(tv);
20885 	DUK_ASSERT(val == 0 || val == 1);
20886 
20887 	duk_pop_unsafe(thr);
20888 	return val;
20889 }
20890 
duk_to_number(duk_hthread * thr,duk_idx_t idx)20891 DUK_EXTERNAL duk_double_t duk_to_number(duk_hthread *thr, duk_idx_t idx) {
20892 	duk_tval *tv;
20893 	duk_double_t d;
20894 
20895 	DUK_ASSERT_API_ENTRY(thr);
20896 
20897 	/* XXX: No need to normalize; the whole operation could be inlined here to
20898 	 * avoid 'tv' re-lookup.
20899 	 */
20900 	idx = duk_require_normalize_index(thr, idx);
20901 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
20902 	DUK_ASSERT(tv != NULL);
20903 	d = duk_js_tonumber(thr, tv);  /* XXX: fastint coercion? now result will always be a non-fastint */
20904 
20905 	/* ToNumber() may have side effects so must relookup 'tv'. */
20906 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
20907 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d);  /* side effects */
20908 	return d;
20909 }
20910 
duk_to_number_m1(duk_hthread * thr)20911 DUK_INTERNAL duk_double_t duk_to_number_m1(duk_hthread *thr) {
20912 	DUK_ASSERT_API_ENTRY(thr);
20913 	return duk_to_number(thr, -1);
20914 }
duk_to_number_m2(duk_hthread * thr)20915 DUK_INTERNAL duk_double_t duk_to_number_m2(duk_hthread *thr) {
20916 	DUK_ASSERT_API_ENTRY(thr);
20917 	return duk_to_number(thr, -2);
20918 }
20919 
duk_to_number_tval(duk_hthread * thr,duk_tval * tv)20920 DUK_INTERNAL duk_double_t duk_to_number_tval(duk_hthread *thr, duk_tval *tv) {
20921 #if defined(DUK_USE_PREFER_SIZE)
20922 	duk_double_t res;
20923 
20924 	DUK_ASSERT_API_ENTRY(thr);
20925 
20926 	duk_push_tval(thr, tv);
20927 	res = duk_to_number_m1(thr);
20928 	duk_pop_unsafe(thr);
20929 	return res;
20930 #else
20931 	duk_double_t res;
20932 	duk_tval *tv_dst;
20933 
20934 	DUK_ASSERT_API_ENTRY(thr);
20935 	DUK__ASSERT_SPACE();
20936 
20937 	tv_dst = thr->valstack_top++;
20938 	DUK_TVAL_SET_TVAL(tv_dst, tv);
20939 	DUK_TVAL_INCREF(thr, tv_dst);  /* decref not necessary */
20940 	res = duk_to_number_m1(thr);  /* invalidates tv_dst */
20941 
20942 	tv_dst = --thr->valstack_top;
20943 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_dst));
20944 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv_dst));  /* plain number */
20945 	DUK_TVAL_SET_UNDEFINED(tv_dst);  /* valstack init policy */
20946 
20947 	return res;
20948 #endif
20949 }
20950 
20951 /* XXX: combine all the integer conversions: they share everything
20952  * but the helper function for coercion.
20953  */
20954 
20955 typedef duk_double_t (*duk__toint_coercer)(duk_hthread *thr, duk_tval *tv);
20956 
duk__to_int_uint_helper(duk_hthread * thr,duk_idx_t idx,duk__toint_coercer coerce_func)20957 DUK_LOCAL duk_double_t duk__to_int_uint_helper(duk_hthread *thr, duk_idx_t idx, duk__toint_coercer coerce_func) {
20958 	duk_tval *tv;
20959 	duk_double_t d;
20960 
20961 	DUK_CTX_ASSERT_VALID(thr);
20962 
20963 	tv = duk_require_tval(thr, idx);
20964 	DUK_ASSERT(tv != NULL);
20965 
20966 #if defined(DUK_USE_FASTINT)
20967 	/* If argument is a fastint, guarantee that it remains one.
20968 	 * There's no downgrade check for other cases.
20969 	 */
20970 	if (DUK_TVAL_IS_FASTINT(tv)) {
20971 		/* XXX: Unnecessary conversion back and forth. */
20972 		return (duk_double_t) DUK_TVAL_GET_FASTINT(tv);
20973 	}
20974 #endif
20975 	d = coerce_func(thr, tv);
20976 
20977 	/* XXX: fastint? */
20978 
20979 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
20980 	tv = duk_require_tval(thr, idx);
20981 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d);  /* side effects */
20982 	return d;
20983 }
20984 
duk_to_int(duk_hthread * thr,duk_idx_t idx)20985 DUK_EXTERNAL duk_int_t duk_to_int(duk_hthread *thr, duk_idx_t idx) {
20986 	/* Value coercion (in stack): ToInteger(), E5 Section 9.4,
20987 	 * API return value coercion: custom.
20988 	 */
20989 	DUK_ASSERT_API_ENTRY(thr);
20990 	(void) duk__to_int_uint_helper(thr, idx, duk_js_tointeger);
20991 	return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 0 /*require*/);
20992 }
20993 
duk_to_uint(duk_hthread * thr,duk_idx_t idx)20994 DUK_EXTERNAL duk_uint_t duk_to_uint(duk_hthread *thr, duk_idx_t idx) {
20995 	/* Value coercion (in stack): ToInteger(), E5 Section 9.4,
20996 	 * API return value coercion: custom.
20997 	 */
20998 	DUK_ASSERT_API_ENTRY(thr);
20999 	(void) duk__to_int_uint_helper(thr, idx, duk_js_tointeger);
21000 	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 0 /*require*/);
21001 }
21002 
duk_to_int32(duk_hthread * thr,duk_idx_t idx)21003 DUK_EXTERNAL duk_int32_t duk_to_int32(duk_hthread *thr, duk_idx_t idx) {
21004 	duk_tval *tv;
21005 	duk_int32_t ret;
21006 
21007 	DUK_ASSERT_API_ENTRY(thr);
21008 
21009 	tv = duk_require_tval(thr, idx);
21010 	DUK_ASSERT(tv != NULL);
21011 	ret = duk_js_toint32(thr, tv);
21012 
21013 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
21014 	tv = duk_require_tval(thr, idx);
21015 	DUK_TVAL_SET_I32_UPDREF(thr, tv, ret);  /* side effects */
21016 	return ret;
21017 }
21018 
duk_to_uint32(duk_hthread * thr,duk_idx_t idx)21019 DUK_EXTERNAL duk_uint32_t duk_to_uint32(duk_hthread *thr, duk_idx_t idx) {
21020 	duk_tval *tv;
21021 	duk_uint32_t ret;
21022 
21023 	DUK_ASSERT_API_ENTRY(thr);
21024 
21025 	tv = duk_require_tval(thr, idx);
21026 	DUK_ASSERT(tv != NULL);
21027 	ret = duk_js_touint32(thr, tv);
21028 
21029 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
21030 	tv = duk_require_tval(thr, idx);
21031 	DUK_TVAL_SET_U32_UPDREF(thr, tv, ret);  /* side effects */
21032 	return ret;
21033 }
21034 
duk_to_uint16(duk_hthread * thr,duk_idx_t idx)21035 DUK_EXTERNAL duk_uint16_t duk_to_uint16(duk_hthread *thr, duk_idx_t idx) {
21036 	duk_tval *tv;
21037 	duk_uint16_t ret;
21038 
21039 	DUK_ASSERT_API_ENTRY(thr);
21040 
21041 	tv = duk_require_tval(thr, idx);
21042 	DUK_ASSERT(tv != NULL);
21043 	ret = duk_js_touint16(thr, tv);
21044 
21045 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
21046 	tv = duk_require_tval(thr, idx);
21047 	DUK_TVAL_SET_U32_UPDREF(thr, tv, ret);  /* side effects */
21048 	return ret;
21049 }
21050 
21051 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21052 /* Special coercion for Uint8ClampedArray. */
duk_to_uint8clamped(duk_hthread * thr,duk_idx_t idx)21053 DUK_INTERNAL duk_uint8_t duk_to_uint8clamped(duk_hthread *thr, duk_idx_t idx) {
21054 	duk_double_t d;
21055 	duk_double_t t;
21056 	duk_uint8_t ret;
21057 
21058 	DUK_ASSERT_API_ENTRY(thr);
21059 
21060 	/* XXX: Simplify this algorithm, should be possible to come up with
21061 	 * a shorter and faster algorithm by inspecting IEEE representation
21062 	 * directly.
21063 	 */
21064 
21065 	d = duk_to_number(thr, idx);
21066 	if (d <= 0.0) {
21067 		return 0;
21068 	} else if (d >= 255) {
21069 		return 255;
21070 	} else if (DUK_ISNAN(d)) {
21071 		/* Avoid NaN-to-integer coercion as it is compiler specific. */
21072 		return 0;
21073 	}
21074 
21075 	t = d - DUK_FLOOR(d);
21076 	if (duk_double_equals(t, 0.5)) {
21077 		/* Exact halfway, round to even. */
21078 		ret = (duk_uint8_t) d;
21079 		ret = (ret + 1) & 0xfe;  /* Example: d=3.5, t=0.5 -> ret = (3 + 1) & 0xfe = 4 & 0xfe = 4
21080 		                          * Example: d=4.5, t=0.5 -> ret = (4 + 1) & 0xfe = 5 & 0xfe = 4
21081 		                          */
21082 	} else {
21083 		/* Not halfway, round to nearest. */
21084 		ret = (duk_uint8_t) (d + 0.5);
21085 	}
21086 	return ret;
21087 }
21088 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
21089 
duk_to_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)21090 DUK_EXTERNAL const char *duk_to_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
21091 	DUK_ASSERT_API_ENTRY(thr);
21092 
21093 	(void) duk_to_string(thr, idx);
21094 	DUK_ASSERT(duk_is_string(thr, idx));
21095 	return duk_require_lstring(thr, idx, out_len);
21096 }
21097 
duk__safe_to_string_raw(duk_hthread * thr,void * udata)21098 DUK_LOCAL duk_ret_t duk__safe_to_string_raw(duk_hthread *thr, void *udata) {
21099 	DUK_CTX_ASSERT_VALID(thr);
21100 	DUK_UNREF(udata);
21101 
21102 	(void) duk_to_string(thr, -1);
21103 	return 1;
21104 }
21105 
duk_safe_to_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)21106 DUK_EXTERNAL const char *duk_safe_to_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
21107 	DUK_ASSERT_API_ENTRY(thr);
21108 
21109 	idx = duk_require_normalize_index(thr, idx);
21110 
21111 	/* We intentionally ignore the duk_safe_call() return value and only
21112 	 * check the output type.  This way we don't also need to check that
21113 	 * the returned value is indeed a string in the success case.
21114 	 */
21115 
21116 	duk_dup(thr, idx);
21117 	(void) duk_safe_call(thr, duk__safe_to_string_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
21118 	if (!duk_is_string(thr, -1)) {
21119 		/* Error: try coercing error to string once. */
21120 		(void) duk_safe_call(thr, duk__safe_to_string_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
21121 		if (!duk_is_string(thr, -1)) {
21122 			/* Double error */
21123 			duk_pop_unsafe(thr);
21124 			duk_push_hstring_stridx(thr, DUK_STRIDX_UC_ERROR);
21125 		} else {
21126 			;
21127 		}
21128 	} else {
21129 		/* String; may be a symbol, accepted. */
21130 		;
21131 	}
21132 	DUK_ASSERT(duk_is_string(thr, -1));
21133 
21134 	duk_replace(thr, idx);
21135 	DUK_ASSERT(duk_get_string(thr, idx) != NULL);
21136 	return duk_get_lstring(thr, idx, out_len);
21137 }
21138 
duk_to_stacktrace(duk_hthread * thr,duk_idx_t idx)21139 DUK_EXTERNAL const char *duk_to_stacktrace(duk_hthread *thr, duk_idx_t idx) {
21140 	DUK_ASSERT_API_ENTRY(thr);
21141 	idx = duk_require_normalize_index(thr, idx);
21142 
21143 	/* The expected argument to the call is an Error object.  The stack
21144 	 * trace is extracted without an inheritance-based instanceof check
21145 	 * so that one can also extract the stack trace of a foreign error
21146 	 * created in another Realm.  Accept only a string .stack property.
21147 	 */
21148 	if (duk_is_object(thr, idx)) {
21149 		(void) duk_get_prop_string(thr, idx, "stack");
21150 		if (duk_is_string(thr, -1)) {
21151 			duk_replace(thr, idx);
21152 		} else {
21153 			duk_pop(thr);
21154 		}
21155 	}
21156 
21157 	return duk_to_string(thr, idx);
21158 }
21159 
duk__safe_to_stacktrace_raw(duk_hthread * thr,void * udata)21160 DUK_LOCAL duk_ret_t duk__safe_to_stacktrace_raw(duk_hthread *thr, void *udata) {
21161 	DUK_CTX_ASSERT_VALID(thr);
21162 	DUK_UNREF(udata);
21163 
21164 	(void) duk_to_stacktrace(thr, -1);
21165 
21166 	return 1;
21167 }
21168 
duk_safe_to_stacktrace(duk_hthread * thr,duk_idx_t idx)21169 DUK_EXTERNAL const char *duk_safe_to_stacktrace(duk_hthread *thr, duk_idx_t idx) {
21170 	duk_int_t rc;
21171 
21172 	DUK_ASSERT_API_ENTRY(thr);
21173 	idx = duk_require_normalize_index(thr, idx);
21174 
21175 	duk_dup(thr, idx);
21176 	rc = duk_safe_call(thr, duk__safe_to_stacktrace_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
21177 	if (rc != 0) {
21178 		/* Coercion failed.  Try to coerce the coercion itself error
21179 		 * to a stack trace once.  If that also fails, return a fixed,
21180 		 * preallocated 'Error' string to avoid potential infinite loop.
21181 		 */
21182 		rc = duk_safe_call(thr, duk__safe_to_stacktrace_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
21183 		if (rc != 0) {
21184 			duk_pop_unsafe(thr);
21185 			duk_push_hstring_stridx(thr, DUK_STRIDX_UC_ERROR);
21186 		}
21187 	}
21188 	duk_replace(thr, idx);
21189 
21190 	return duk_get_string(thr, idx);
21191 }
21192 
duk_to_property_key_hstring(duk_hthread * thr,duk_idx_t idx)21193 DUK_INTERNAL duk_hstring *duk_to_property_key_hstring(duk_hthread *thr, duk_idx_t idx) {
21194 	duk_hstring *h;
21195 
21196 	DUK_ASSERT_API_ENTRY(thr);
21197 
21198 	duk_to_primitive(thr, idx, DUK_HINT_STRING);  /* needed for e.g. Symbol objects */
21199 	h = duk_get_hstring(thr, idx);
21200 	if (h == NULL) {
21201 		/* The "is string?" check may seem unnecessary, but as things
21202 		 * are duk_to_hstring() invokes ToString() which fails for
21203 		 * symbols.  But since symbols are already strings for Duktape
21204 		 * C API, we check for that before doing the coercion.
21205 		 */
21206 		h = duk_to_hstring(thr, idx);
21207 	}
21208 	DUK_ASSERT(h != NULL);
21209 	return h;
21210 }
21211 
21212 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* only needed by debugger for now */
duk_safe_to_hstring(duk_hthread * thr,duk_idx_t idx)21213 DUK_INTERNAL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx) {
21214 	DUK_ASSERT_API_ENTRY(thr);
21215 
21216 	(void) duk_safe_to_string(thr, idx);
21217 	DUK_ASSERT(duk_is_string(thr, idx));
21218 	DUK_ASSERT(duk_get_hstring(thr, idx) != NULL);
21219 	return duk_known_hstring(thr, idx);
21220 }
21221 #endif
21222 
21223 /* Push Object.prototype.toString() output for 'tv'. */
duk_push_class_string_tval(duk_hthread * thr,duk_tval * tv,duk_bool_t avoid_side_effects)21224 DUK_INTERNAL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects) {
21225 	duk_hobject *h_obj;
21226 	duk_small_uint_t classnum;
21227 	duk_small_uint_t stridx;
21228 	duk_tval tv_tmp;
21229 
21230 	DUK_ASSERT_API_ENTRY(thr);
21231 	DUK_ASSERT(tv != NULL);
21232 
21233 	/* Stabilize 'tv', duk_push_literal() may trigger side effects. */
21234 	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
21235 	tv = &tv_tmp;
21236 
21237 	/* Conceptually for any non-undefined/null value we should do a
21238 	 * ToObject() coercion and look up @@toStringTag (from the object
21239 	 * prototype) to see if a custom result should be used, with the
21240 	 * exception of Arrays which are handled specially first.
21241 	 *
21242 	 * We'd like to avoid the actual conversion, but even for primitive
21243 	 * types the prototype may have @@toStringTag.  What's worse, the
21244 	 * @@toStringTag property may be a getter that must get the object
21245 	 * coerced value (not the prototype) as its 'this' binding.
21246 	 *
21247 	 * For now, do an actual object coercion.  This could be avoided by
21248 	 * doing a side effect free lookup to see if a getter would be invoked.
21249 	 * If not, the value can be read directly and the object coercion could
21250 	 * be avoided.  This may not be worth it in practice, because
21251 	 * Object.prototype.toString() is usually not performance critical.
21252 	 */
21253 
21254 	duk_push_literal(thr, "[object ");  /* -> [ ... "[object" ] */
21255 
21256 	switch (DUK_TVAL_GET_TAG(tv)) {
21257 	case DUK_TAG_UNUSED:  /* Treat like 'undefined', shouldn't happen. */
21258 	case DUK_TAG_UNDEFINED: {
21259 		duk_push_hstring_stridx(thr, DUK_STRIDX_UC_UNDEFINED);
21260 		goto finish;
21261 	}
21262 	case DUK_TAG_NULL: {
21263 		duk_push_hstring_stridx(thr, DUK_STRIDX_UC_NULL);
21264 		goto finish;
21265 	}
21266 	}
21267 
21268 	duk_push_tval(thr, tv);
21269 	tv = NULL;  /* Invalidated by ToObject(). */
21270 	h_obj = duk_to_hobject(thr, -1);
21271 	DUK_ASSERT(h_obj != NULL);
21272 	if (duk_js_isarray_hobject(h_obj)) {
21273 		stridx = DUK_STRIDX_UC_ARRAY;
21274 	} else {
21275 		/* [ ... "[object" obj ] */
21276 
21277 #if defined(DUK_USE_SYMBOL_BUILTIN)
21278 		/* XXX: better handling with avoid_side_effects == 1; lookup tval
21279 		 * without Proxy or getter side effects, and use it in sanitized
21280 		 * form if it's a string.
21281 		 */
21282 		if (!avoid_side_effects) {
21283 			(void) duk_get_prop_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG);
21284 			if (duk_is_string_notsymbol(thr, -1)) {
21285 				duk_remove_m2(thr);
21286 				goto finish;
21287 			}
21288 			duk_pop_unsafe(thr);
21289 		}
21290 #else
21291 		DUK_UNREF(avoid_side_effects);
21292 #endif
21293 
21294 		classnum = DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
21295 		stridx = DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum);
21296 	}
21297 	duk_pop_unsafe(thr);
21298 	duk_push_hstring_stridx(thr, stridx);
21299 
21300  finish:
21301 	/* [ ... "[object" tag ] */
21302 	duk_push_literal(thr, "]");
21303 	duk_concat(thr, 3);  /* [ ... "[object" tag "]" ] -> [ ... res ] */
21304 }
21305 
21306 /* 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)21307 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) {
21308 	duk_tval *tv;
21309 	duk_tval tv_tmp;
21310 	duk_double_t d, dmin, dmax;
21311 	duk_int_t res;
21312 	duk_bool_t clamped = 0;
21313 
21314 	DUK_ASSERT_API_ENTRY(thr);
21315 
21316 	tv = duk_require_tval(thr, idx);
21317 	DUK_ASSERT(tv != NULL);
21318 	d = duk_js_tointeger(thr, tv);  /* E5 Section 9.4, ToInteger() */
21319 
21320 	dmin = (duk_double_t) minval;
21321 	dmax = (duk_double_t) maxval;
21322 
21323 	if (d < dmin) {
21324 		clamped = 1;
21325 		res = minval;
21326 		d = dmin;
21327 	} else if (d > dmax) {
21328 		clamped = 1;
21329 		res = maxval;
21330 		d = dmax;
21331 	} else {
21332 		res = (duk_int_t) d;
21333 	}
21334 	DUK_UNREF(d);  /* SCANBUILD: with suitable dmin/dmax limits 'd' is unused */
21335 	/* 'd' and 'res' agree here */
21336 
21337 	/* Relookup in case duk_js_tointeger() ends up e.g. coercing an object. */
21338 	tv = duk_get_tval(thr, idx);
21339 	DUK_ASSERT(tv != NULL);  /* not popped by side effect */
21340 	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
21341 #if defined(DUK_USE_FASTINT)
21342 #if (DUK_INT_MAX <= 0x7fffffffL)
21343 	DUK_TVAL_SET_I32(tv, res);
21344 #else
21345 	/* Clamping needed if duk_int_t is 64 bits. */
21346 	if (res >= DUK_FASTINT_MIN && res <= DUK_FASTINT_MAX) {
21347 		DUK_TVAL_SET_FASTINT(tv, res);
21348 	} else {
21349 		DUK_TVAL_SET_NUMBER(tv, d);
21350 	}
21351 #endif
21352 #else
21353 	DUK_TVAL_SET_NUMBER(tv, d);  /* no need to incref */
21354 #endif
21355 	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
21356 
21357 	if (out_clamped) {
21358 		*out_clamped = clamped;
21359 	} else {
21360 		/* coerced value is updated to value stack even when RangeError thrown */
21361 		if (clamped) {
21362 			DUK_ERROR_RANGE(thr, DUK_STR_NUMBER_OUTSIDE_RANGE);
21363 			DUK_WO_NORETURN(return 0;);
21364 		}
21365 	}
21366 
21367 	return res;
21368 }
21369 
duk_to_int_clamped(duk_hthread * thr,duk_idx_t idx,duk_idx_t minval,duk_idx_t maxval)21370 DUK_INTERNAL duk_int_t duk_to_int_clamped(duk_hthread *thr, duk_idx_t idx, duk_idx_t minval, duk_idx_t maxval) {
21371 	duk_bool_t dummy;
21372 
21373 	DUK_ASSERT_API_ENTRY(thr);
21374 
21375 	return duk_to_int_clamped_raw(thr, idx, minval, maxval, &dummy);
21376 }
21377 
duk_to_int_check_range(duk_hthread * thr,duk_idx_t idx,duk_int_t minval,duk_int_t maxval)21378 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) {
21379 	DUK_ASSERT_API_ENTRY(thr);
21380 	return duk_to_int_clamped_raw(thr, idx, minval, maxval, NULL);  /* out_clamped==NULL -> RangeError if outside range */
21381 }
21382 
duk_to_string(duk_hthread * thr,duk_idx_t idx)21383 DUK_EXTERNAL const char *duk_to_string(duk_hthread *thr, duk_idx_t idx) {
21384 	duk_tval *tv;
21385 
21386 	DUK_ASSERT_API_ENTRY(thr);
21387 
21388 	idx = duk_require_normalize_index(thr, idx);
21389 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
21390 	DUK_ASSERT(tv != NULL);
21391 
21392 	switch (DUK_TVAL_GET_TAG(tv)) {
21393 	case DUK_TAG_UNDEFINED: {
21394 		duk_push_hstring_stridx(thr, DUK_STRIDX_LC_UNDEFINED);
21395 		break;
21396 	}
21397 	case DUK_TAG_NULL: {
21398 		duk_push_hstring_stridx(thr, DUK_STRIDX_LC_NULL);
21399 		break;
21400 	}
21401 	case DUK_TAG_BOOLEAN: {
21402 		if (DUK_TVAL_GET_BOOLEAN(tv)) {
21403 			duk_push_hstring_stridx(thr, DUK_STRIDX_TRUE);
21404 		} else {
21405 			duk_push_hstring_stridx(thr, DUK_STRIDX_FALSE);
21406 		}
21407 		break;
21408 	}
21409 	case DUK_TAG_STRING: {
21410 		/* Nop for actual strings, TypeError for Symbols.
21411 		 * Because various internals rely on ToString() coercion of
21412 		 * internal strings, -allow- (NOP) string coercion for hidden
21413 		 * symbols.
21414 		 */
21415 #if 1
21416 		duk_hstring *h;
21417 		h = DUK_TVAL_GET_STRING(tv);
21418 		DUK_ASSERT(h != NULL);
21419 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
21420 			DUK_ERROR_TYPE(thr, DUK_STR_CANNOT_STRING_COERCE_SYMBOL);
21421 			DUK_WO_NORETURN(goto skip_replace;);
21422 		} else {
21423 			goto skip_replace;
21424 		}
21425 #else
21426 		goto skip_replace;
21427 #endif
21428 		break;
21429 	}
21430 	case DUK_TAG_BUFFER: /* Go through Uint8Array.prototype.toString() for coercion. */
21431 	case DUK_TAG_OBJECT: {
21432 		/* Plain buffers: go through ArrayBuffer.prototype.toString()
21433 		 * for coercion.
21434 		 *
21435 		 * Symbol objects: duk_to_primitive() results in a plain symbol
21436 		 * value, and duk_to_string() then causes a TypeError.
21437 		 */
21438 		duk_to_primitive(thr, idx, DUK_HINT_STRING);
21439 		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* ToPrimitive() must guarantee */
21440 		DUK_ASSERT(!duk_is_object(thr, idx));
21441 		return duk_to_string(thr, idx);  /* Note: recursive call */
21442 	}
21443 	case DUK_TAG_POINTER: {
21444 		void *ptr = DUK_TVAL_GET_POINTER(tv);
21445 		if (ptr != NULL) {
21446 			duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) ptr);
21447 		} else {
21448 			/* Represent a null pointer as 'null' to be consistent with
21449 			 * the JX format variant.  Native '%p' format for a NULL
21450 			 * pointer may be e.g. '(nil)'.
21451 			 */
21452 			duk_push_hstring_stridx(thr, DUK_STRIDX_LC_NULL);
21453 		}
21454 		break;
21455 	}
21456 	case DUK_TAG_LIGHTFUNC: {
21457 		/* Should match Function.prototype.toString() */
21458 		duk_push_lightfunc_tostring(thr, tv);
21459 		break;
21460 	}
21461 #if defined(DUK_USE_FASTINT)
21462 	case DUK_TAG_FASTINT:
21463 #endif
21464 	default: {
21465 		/* number */
21466 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21467 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21468 		duk_push_tval(thr, tv);
21469 		duk_numconv_stringify(thr,
21470 		                      10 /*radix*/,
21471 		                      0 /*precision:shortest*/,
21472 		                      0 /*force_exponential*/);
21473 		break;
21474 	}
21475 	}
21476 
21477 	duk_replace(thr, idx);
21478 
21479  skip_replace:
21480 	DUK_ASSERT(duk_is_string(thr, idx));
21481 	return duk_require_string(thr, idx);
21482 }
21483 
duk_to_hstring(duk_hthread * thr,duk_idx_t idx)21484 DUK_INTERNAL duk_hstring *duk_to_hstring(duk_hthread *thr, duk_idx_t idx) {
21485 	duk_hstring *ret;
21486 
21487 	DUK_ASSERT_API_ENTRY(thr);
21488 
21489 	duk_to_string(thr, idx);
21490 	ret = duk_get_hstring(thr, idx);
21491 	DUK_ASSERT(ret != NULL);
21492 	return ret;
21493 }
21494 
duk_to_hstring_m1(duk_hthread * thr)21495 DUK_INTERNAL duk_hstring *duk_to_hstring_m1(duk_hthread *thr) {
21496 	DUK_ASSERT_API_ENTRY(thr);
21497 	return duk_to_hstring(thr, -1);
21498 }
21499 
duk_to_hstring_acceptsymbol(duk_hthread * thr,duk_idx_t idx)21500 DUK_INTERNAL duk_hstring *duk_to_hstring_acceptsymbol(duk_hthread *thr, duk_idx_t idx) {
21501 	duk_hstring *ret;
21502 
21503 	DUK_ASSERT_API_ENTRY(thr);
21504 
21505 	ret = duk_get_hstring(thr, idx);
21506 	if (DUK_UNLIKELY(ret && DUK_HSTRING_HAS_SYMBOL(ret))) {
21507 		return ret;
21508 	}
21509 	return duk_to_hstring(thr, idx);
21510 }
21511 
21512 /* Convert a plain buffer or any buffer object into a string, using the buffer
21513  * bytes 1:1 in the internal string representation.  For views the active byte
21514  * slice (not element slice interpreted as an initializer) is used.  This is
21515  * necessary in Duktape 2.x because ToString(plainBuffer) no longer creates a
21516  * string with the same bytes as in the buffer but rather (usually)
21517  * '[object ArrayBuffer]'.
21518  */
duk_buffer_to_string(duk_hthread * thr,duk_idx_t idx)21519 DUK_EXTERNAL const char *duk_buffer_to_string(duk_hthread *thr, duk_idx_t idx) {
21520 	void *ptr_src;
21521 	duk_size_t len;
21522 	const char *res;
21523 
21524 	DUK_ASSERT_API_ENTRY(thr);
21525 
21526 	idx = duk_require_normalize_index(thr, idx);
21527 
21528 	ptr_src = duk_require_buffer_data(thr, idx, &len);
21529 	DUK_ASSERT(ptr_src != NULL || len == 0);
21530 
21531 	res = duk_push_lstring(thr, (const char *) ptr_src, len);
21532 	duk_replace(thr, idx);
21533 	return res;
21534 }
21535 
duk_to_buffer_raw(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,duk_uint_t mode)21536 DUK_EXTERNAL void *duk_to_buffer_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, duk_uint_t mode) {
21537 	duk_hbuffer *h_buf;
21538 	const duk_uint8_t *src_data;
21539 	duk_size_t src_size;
21540 	duk_uint8_t *dst_data;
21541 
21542 	DUK_ASSERT_API_ENTRY(thr);
21543 
21544 	idx = duk_require_normalize_index(thr, idx);
21545 
21546 	h_buf = duk_get_hbuffer(thr, idx);
21547 	if (h_buf != NULL) {
21548 		/* Buffer is kept as is, with the fixed/dynamic nature of the
21549 		 * buffer only changed if requested.  An external buffer
21550 		 * is converted into a non-external dynamic buffer in a
21551 		 * duk_to_dynamic_buffer() call.
21552 		 */
21553 		duk_uint_t tmp;
21554 		duk_uint8_t *tmp_ptr;
21555 
21556 		tmp_ptr = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf);
21557 		src_data = (const duk_uint8_t *) tmp_ptr;
21558 		src_size = DUK_HBUFFER_GET_SIZE(h_buf);
21559 
21560 		tmp = (DUK_HBUFFER_HAS_DYNAMIC(h_buf) ? DUK_BUF_MODE_DYNAMIC : DUK_BUF_MODE_FIXED);
21561 		if ((tmp == mode && !DUK_HBUFFER_HAS_EXTERNAL(h_buf)) ||
21562 		    mode == DUK_BUF_MODE_DONTCARE) {
21563 			/* Note: src_data may be NULL if input is a zero-size
21564 			 * dynamic buffer.
21565 			 */
21566 			dst_data = tmp_ptr;
21567 			goto skip_copy;
21568 		}
21569 	} else {
21570 		/* Non-buffer value is first ToString() coerced, then converted
21571 		 * to a buffer (fixed buffer is used unless a dynamic buffer is
21572 		 * explicitly requested).  Symbols are rejected with a TypeError.
21573 		 * XXX: C API could maybe allow symbol-to-buffer coercion?
21574 		 */
21575 		src_data = (const duk_uint8_t *) duk_to_lstring(thr, idx, &src_size);
21576 	}
21577 
21578 	dst_data = (duk_uint8_t *) duk_push_buffer(thr, src_size, (mode == DUK_BUF_MODE_DYNAMIC) /*dynamic*/);
21579 	/* dst_data may be NULL if size is zero. */
21580 	duk_memcpy_unsafe((void *) dst_data, (const void *) src_data, (size_t) src_size);
21581 
21582 	duk_replace(thr, idx);
21583  skip_copy:
21584 
21585 	if (out_size) {
21586 		*out_size = src_size;
21587 	}
21588 	return dst_data;
21589 }
21590 
duk_to_pointer(duk_hthread * thr,duk_idx_t idx)21591 DUK_EXTERNAL void *duk_to_pointer(duk_hthread *thr, duk_idx_t idx) {
21592 	duk_tval *tv;
21593 	void *res;
21594 
21595 	DUK_ASSERT_API_ENTRY(thr);
21596 
21597 	idx = duk_require_normalize_index(thr, idx);
21598 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
21599 	DUK_ASSERT(tv != NULL);
21600 
21601 	switch (DUK_TVAL_GET_TAG(tv)) {
21602 	case DUK_TAG_UNDEFINED:
21603 	case DUK_TAG_NULL:
21604 	case DUK_TAG_BOOLEAN:
21605 		res = NULL;
21606 		break;
21607 	case DUK_TAG_POINTER:
21608 		res = DUK_TVAL_GET_POINTER(tv);
21609 		break;
21610 	case DUK_TAG_STRING:
21611 	case DUK_TAG_OBJECT:
21612 	case DUK_TAG_BUFFER:
21613 		/* Heap allocated: return heap pointer which is NOT useful
21614 		 * for the caller, except for debugging.
21615 		 */
21616 		res = (void *) DUK_TVAL_GET_HEAPHDR(tv);
21617 		break;
21618 	case DUK_TAG_LIGHTFUNC:
21619 		/* Function pointers do not always cast correctly to void *
21620 		 * (depends on memory and segmentation model for instance),
21621 		 * so they coerce to NULL.
21622 		 */
21623 		res = NULL;
21624 		break;
21625 #if defined(DUK_USE_FASTINT)
21626 	case DUK_TAG_FASTINT:
21627 #endif
21628 	default:
21629 		/* number */
21630 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21631 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21632 		res = NULL;
21633 		break;
21634 	}
21635 
21636 	duk_push_pointer(thr, res);
21637 	duk_replace(thr, idx);
21638 	return res;
21639 }
21640 
duk__push_func_from_lightfunc(duk_hthread * thr,duk_c_function func,duk_small_uint_t lf_flags)21641 DUK_LOCAL void duk__push_func_from_lightfunc(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags) {
21642 	duk_idx_t nargs;
21643 	duk_uint_t flags = 0;   /* shared flags for a subset of types */
21644 	duk_small_uint_t lf_len;
21645 	duk_hnatfunc *nf;
21646 
21647 	nargs = (duk_idx_t) DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
21648 	if (nargs == DUK_LFUNC_NARGS_VARARGS) {
21649 		nargs = (duk_idx_t) DUK_VARARGS;
21650 	}
21651 
21652 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21653 	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
21654 	        DUK_HOBJECT_FLAG_CALLABLE |
21655 	        DUK_HOBJECT_FLAG_FASTREFS |
21656 	        DUK_HOBJECT_FLAG_NATFUNC |
21657 	        DUK_HOBJECT_FLAG_NEWENV |
21658 	        DUK_HOBJECT_FLAG_STRICT |
21659 	        DUK_HOBJECT_FLAG_NOTAIL |
21660 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
21661 	(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE);
21662 
21663 	lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
21664 	if ((duk_idx_t) lf_len != nargs) {
21665 		/* Explicit length is only needed if it differs from 'nargs'. */
21666 		duk_push_int(thr, (duk_int_t) lf_len);
21667 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);
21668 	}
21669 
21670 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
21671 	duk_push_lightfunc_name_raw(thr, func, lf_flags);
21672 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
21673 #endif
21674 
21675 	nf = duk_known_hnatfunc(thr, -1);
21676 	nf->magic = (duk_int16_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
21677 }
21678 
duk_to_object(duk_hthread * thr,duk_idx_t idx)21679 DUK_EXTERNAL void duk_to_object(duk_hthread *thr, duk_idx_t idx) {
21680 	duk_tval *tv;
21681 	duk_uint_t flags = 0;   /* shared flags for a subset of types */
21682 	duk_small_int_t proto = 0;
21683 
21684 	DUK_ASSERT_API_ENTRY(thr);
21685 
21686 	idx = duk_require_normalize_index(thr, idx);
21687 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
21688 	DUK_ASSERT(tv != NULL);
21689 
21690 	switch (DUK_TVAL_GET_TAG(tv)) {
21691 #if !defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21692 	case DUK_TAG_BUFFER:  /* With no bufferobject support, don't object coerce. */
21693 #endif
21694 	case DUK_TAG_UNDEFINED:
21695 	case DUK_TAG_NULL: {
21696 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE);
21697 		DUK_WO_NORETURN(return;);
21698 		break;
21699 	}
21700 	case DUK_TAG_BOOLEAN: {
21701 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21702 		        DUK_HOBJECT_FLAG_FASTREFS |
21703 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BOOLEAN);
21704 		proto = DUK_BIDX_BOOLEAN_PROTOTYPE;
21705 		goto create_object;
21706 	}
21707 	case DUK_TAG_STRING: {
21708 		duk_hstring *h;
21709 		h = DUK_TVAL_GET_STRING(tv);
21710 		DUK_ASSERT(h != NULL);
21711 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
21712 			flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21713 			        DUK_HOBJECT_FLAG_FASTREFS |
21714 			        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_SYMBOL);
21715 			proto = DUK_BIDX_SYMBOL_PROTOTYPE;
21716 		} else {
21717 			flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21718 			        DUK_HOBJECT_FLAG_FASTREFS |
21719 			        DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
21720 			        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);
21721 			proto = DUK_BIDX_STRING_PROTOTYPE;
21722 		}
21723 		goto create_object;
21724 	}
21725 	case DUK_TAG_OBJECT: {
21726 		/* nop */
21727 		break;
21728 	}
21729 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21730 	case DUK_TAG_BUFFER: {
21731 		/* A plain buffer object coerces to a full ArrayBuffer which
21732 		 * is not fully transparent behavior (ToObject() should be a
21733 		 * nop for an object).  This behavior matches lightfuncs which
21734 		 * also coerce to an equivalent Function object.  There are
21735 		 * also downsides to defining ToObject(plainBuffer) as a no-op;
21736 		 * for example duk_to_hobject() could result in a NULL pointer.
21737 		 */
21738 		duk_hbuffer *h_buf;
21739 
21740 		h_buf = DUK_TVAL_GET_BUFFER(tv);
21741 		DUK_ASSERT(h_buf != NULL);
21742 		duk_hbufobj_push_uint8array_from_plain(thr, h_buf);
21743 		goto replace_value;
21744 	}
21745 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
21746 	case DUK_TAG_POINTER: {
21747 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21748 		        DUK_HOBJECT_FLAG_FASTREFS |
21749 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER);
21750 		proto = DUK_BIDX_POINTER_PROTOTYPE;
21751 		goto create_object;
21752 	}
21753 	case DUK_TAG_LIGHTFUNC: {
21754 		/* Lightfunc coerces to a Function instance with concrete
21755 		 * properties.  Since 'length' is virtual for Duktape/C
21756 		 * functions, don't need to define that.  The result is made
21757 		 * extensible to mimic what happens to strings in object
21758 		 * coercion:
21759 		 *
21760 		 *   > Object.isExtensible(Object('foo'))
21761 		 *   true
21762 		 */
21763 		duk_small_uint_t lf_flags;
21764 		duk_c_function func;
21765 
21766 		DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
21767 		duk__push_func_from_lightfunc(thr, func, lf_flags);
21768 		goto replace_value;
21769 	}
21770 #if defined(DUK_USE_FASTINT)
21771 	case DUK_TAG_FASTINT:
21772 #endif
21773 	default: {
21774 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21775 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21776 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21777 		        DUK_HOBJECT_FLAG_FASTREFS |
21778 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_NUMBER);
21779 		proto = DUK_BIDX_NUMBER_PROTOTYPE;
21780 		goto create_object;
21781 	}
21782 	}
21783 	DUK_ASSERT(duk_is_object(thr, idx));
21784 	return;
21785 
21786  create_object:
21787 	(void) duk_push_object_helper(thr, flags, proto);
21788 
21789 	/* Note: Boolean prototype's internal value property is not writable,
21790 	 * but duk_xdef_prop_stridx() disregards the write protection.  Boolean
21791 	 * instances are immutable.
21792 	 *
21793 	 * String and buffer special behaviors are already enabled which is not
21794 	 * ideal, but a write to the internal value is not affected by them.
21795 	 */
21796 	duk_dup(thr, idx);
21797 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
21798 
21799  replace_value:
21800 	duk_replace(thr, idx);
21801 	DUK_ASSERT(duk_is_object(thr, idx));
21802 }
21803 
duk_to_hobject(duk_hthread * thr,duk_idx_t idx)21804 DUK_INTERNAL duk_hobject *duk_to_hobject(duk_hthread *thr, duk_idx_t idx) {
21805 	duk_hobject *ret;
21806 
21807 	DUK_ASSERT_API_ENTRY(thr);
21808 
21809 	duk_to_object(thr, idx);
21810 	ret = duk_known_hobject(thr, idx);
21811 	return ret;
21812 }
21813 
21814 /*
21815  *  Type checking
21816  */
21817 
duk__tag_check(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t tag)21818 DUK_LOCAL duk_bool_t duk__tag_check(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t tag) {
21819 	duk_tval *tv;
21820 
21821 	tv = duk_get_tval_or_unused(thr, idx);
21822 	DUK_ASSERT(tv != NULL);
21823 	return (DUK_TVAL_GET_TAG(tv) == tag);
21824 }
21825 
duk__obj_flag_any_default_false(duk_hthread * thr,duk_idx_t idx,duk_uint_t flag_mask)21826 DUK_LOCAL duk_bool_t duk__obj_flag_any_default_false(duk_hthread *thr, duk_idx_t idx, duk_uint_t flag_mask) {
21827 	duk_hobject *obj;
21828 
21829 	DUK_ASSERT_API_ENTRY(thr);
21830 
21831 	obj = duk_get_hobject(thr, idx);
21832 	if (obj) {
21833 		return (DUK_HEAPHDR_CHECK_FLAG_BITS((duk_heaphdr *) obj, flag_mask) ? 1 : 0);
21834 	}
21835 	return 0;
21836 }
21837 
duk_get_type_tval(duk_tval * tv)21838 DUK_INTERNAL duk_int_t duk_get_type_tval(duk_tval *tv) {
21839 	DUK_ASSERT(tv != NULL);
21840 
21841 #if defined(DUK_USE_PACKED_TVAL)
21842 	switch (DUK_TVAL_GET_TAG(tv)) {
21843 	case DUK_TAG_UNUSED:
21844 		return DUK_TYPE_NONE;
21845 	case DUK_TAG_UNDEFINED:
21846 		return DUK_TYPE_UNDEFINED;
21847 	case DUK_TAG_NULL:
21848 		return DUK_TYPE_NULL;
21849 	case DUK_TAG_BOOLEAN:
21850 		return DUK_TYPE_BOOLEAN;
21851 	case DUK_TAG_STRING:
21852 		return DUK_TYPE_STRING;
21853 	case DUK_TAG_OBJECT:
21854 		return DUK_TYPE_OBJECT;
21855 	case DUK_TAG_BUFFER:
21856 		return DUK_TYPE_BUFFER;
21857 	case DUK_TAG_POINTER:
21858 		return DUK_TYPE_POINTER;
21859 	case DUK_TAG_LIGHTFUNC:
21860 		return DUK_TYPE_LIGHTFUNC;
21861 #if defined(DUK_USE_FASTINT)
21862 	case DUK_TAG_FASTINT:
21863 #endif
21864 	default:
21865 		/* Note: number has no explicit tag (in 8-byte representation) */
21866 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21867 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21868 		return DUK_TYPE_NUMBER;
21869 	}
21870 #else  /* DUK_USE_PACKED_TVAL */
21871 	DUK_ASSERT(DUK_TVAL_IS_VALID_TAG(tv));
21872 	DUK_ASSERT(sizeof(duk__type_from_tag) / sizeof(duk_uint_t) == DUK_TAG_MAX - DUK_TAG_MIN + 1);
21873 	return (duk_int_t) duk__type_from_tag[DUK_TVAL_GET_TAG(tv) - DUK_TAG_MIN];
21874 #endif  /* DUK_USE_PACKED_TVAL */
21875 }
21876 
duk_get_type(duk_hthread * thr,duk_idx_t idx)21877 DUK_EXTERNAL duk_int_t duk_get_type(duk_hthread *thr, duk_idx_t idx) {
21878 	duk_tval *tv;
21879 
21880 	DUK_ASSERT_API_ENTRY(thr);
21881 
21882 	tv = duk_get_tval_or_unused(thr, idx);
21883 	DUK_ASSERT(tv != NULL);
21884 
21885 	return duk_get_type_tval(tv);
21886 }
21887 
21888 #if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
21889 DUK_LOCAL const char * const duk__type_names[] = {
21890 	"none",
21891 	"undefined",
21892 	"null",
21893 	"boolean",
21894 	"number",
21895 	"string",
21896 	"object",
21897 	"buffer",
21898 	"pointer",
21899 	"lightfunc"
21900 };
21901 
duk_get_type_name(duk_hthread * thr,duk_idx_t idx)21902 DUK_INTERNAL const char *duk_get_type_name(duk_hthread *thr, duk_idx_t idx) {
21903 	duk_int_t type_tag;
21904 
21905 	DUK_ASSERT_API_ENTRY(thr);
21906 
21907 	type_tag = duk_get_type(thr, idx);
21908 	DUK_ASSERT(type_tag >= DUK_TYPE_MIN && type_tag <= DUK_TYPE_MAX);
21909 	DUK_ASSERT(DUK_TYPE_MIN == 0 && sizeof(duk__type_names) / sizeof(const char *) == DUK_TYPE_MAX + 1);
21910 
21911 	return duk__type_names[type_tag];
21912 }
21913 #endif  /* DUK_USE_VERBOSE_ERRORS && DUK_USE_PARANOID_ERRORS */
21914 
duk_get_class_number(duk_hthread * thr,duk_idx_t idx)21915 DUK_INTERNAL duk_small_uint_t duk_get_class_number(duk_hthread *thr, duk_idx_t idx) {
21916 	duk_tval *tv;
21917 	duk_hobject *obj;
21918 
21919 	DUK_ASSERT_API_ENTRY(thr);
21920 
21921 	tv = duk_get_tval_or_unused(thr, idx);
21922 	DUK_ASSERT(tv != NULL);
21923 
21924 	switch (DUK_TVAL_GET_TAG(tv)) {
21925 	case DUK_TAG_OBJECT:
21926 		obj = DUK_TVAL_GET_OBJECT(tv);
21927 		DUK_ASSERT(obj != NULL);
21928 		return DUK_HOBJECT_GET_CLASS_NUMBER(obj);
21929 	case DUK_TAG_BUFFER:
21930 		/* Buffers behave like Uint8Array objects. */
21931 		return DUK_HOBJECT_CLASS_UINT8ARRAY;
21932 	case DUK_TAG_LIGHTFUNC:
21933 		/* Lightfuncs behave like Function objects. */
21934 		return DUK_HOBJECT_CLASS_FUNCTION;
21935 	default:
21936 		/* Primitive or UNUSED, no class number. */
21937 		return DUK_HOBJECT_CLASS_NONE;
21938 	}
21939 }
21940 
duk_check_type(duk_hthread * thr,duk_idx_t idx,duk_int_t type)21941 DUK_EXTERNAL duk_bool_t duk_check_type(duk_hthread *thr, duk_idx_t idx, duk_int_t type) {
21942 	DUK_ASSERT_API_ENTRY(thr);
21943 
21944 	return (duk_get_type(thr, idx) == type) ? 1 : 0;
21945 }
21946 
duk_get_type_mask_tval(duk_tval * tv)21947 DUK_INTERNAL duk_uint_t duk_get_type_mask_tval(duk_tval *tv) {
21948 	DUK_ASSERT(tv != NULL);
21949 
21950 #if defined(DUK_USE_PACKED_TVAL)
21951 	switch (DUK_TVAL_GET_TAG(tv)) {
21952 	case DUK_TAG_UNUSED:
21953 		return DUK_TYPE_MASK_NONE;
21954 	case DUK_TAG_UNDEFINED:
21955 		return DUK_TYPE_MASK_UNDEFINED;
21956 	case DUK_TAG_NULL:
21957 		return DUK_TYPE_MASK_NULL;
21958 	case DUK_TAG_BOOLEAN:
21959 		return DUK_TYPE_MASK_BOOLEAN;
21960 	case DUK_TAG_STRING:
21961 		return DUK_TYPE_MASK_STRING;
21962 	case DUK_TAG_OBJECT:
21963 		return DUK_TYPE_MASK_OBJECT;
21964 	case DUK_TAG_BUFFER:
21965 		return DUK_TYPE_MASK_BUFFER;
21966 	case DUK_TAG_POINTER:
21967 		return DUK_TYPE_MASK_POINTER;
21968 	case DUK_TAG_LIGHTFUNC:
21969 		return DUK_TYPE_MASK_LIGHTFUNC;
21970 #if defined(DUK_USE_FASTINT)
21971 	case DUK_TAG_FASTINT:
21972 #endif
21973 	default:
21974 		/* Note: number has no explicit tag (in 8-byte representation) */
21975 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21976 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21977 		return DUK_TYPE_MASK_NUMBER;
21978 	}
21979 #else  /* DUK_USE_PACKED_TVAL */
21980 	DUK_ASSERT(DUK_TVAL_IS_VALID_TAG(tv));
21981 	DUK_ASSERT(sizeof(duk__type_mask_from_tag) / sizeof(duk_uint_t) == DUK_TAG_MAX - DUK_TAG_MIN + 1);
21982 	return duk__type_mask_from_tag[DUK_TVAL_GET_TAG(tv) - DUK_TAG_MIN];
21983 #endif  /* DUK_USE_PACKED_TVAL */
21984 }
21985 
duk_get_type_mask(duk_hthread * thr,duk_idx_t idx)21986 DUK_EXTERNAL duk_uint_t duk_get_type_mask(duk_hthread *thr, duk_idx_t idx) {
21987 	duk_tval *tv;
21988 
21989 	DUK_ASSERT_API_ENTRY(thr);
21990 
21991 	tv = duk_get_tval_or_unused(thr, idx);
21992 	DUK_ASSERT(tv != NULL);
21993 
21994 	return duk_get_type_mask_tval(tv);
21995 }
21996 
duk_check_type_mask(duk_hthread * thr,duk_idx_t idx,duk_uint_t mask)21997 DUK_EXTERNAL duk_bool_t duk_check_type_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t mask) {
21998 	DUK_ASSERT_API_ENTRY(thr);
21999 
22000 	if (DUK_LIKELY((duk_get_type_mask(thr, idx) & mask) != 0U)) {
22001 		return 1;
22002 	}
22003 	if (mask & DUK_TYPE_MASK_THROW) {
22004 		DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);
22005 		DUK_WO_NORETURN(return 0;);
22006 	}
22007 	return 0;
22008 }
22009 
duk_is_undefined(duk_hthread * thr,duk_idx_t idx)22010 DUK_EXTERNAL duk_bool_t duk_is_undefined(duk_hthread *thr, duk_idx_t idx) {
22011 	DUK_ASSERT_API_ENTRY(thr);
22012 	return duk__tag_check(thr, idx, DUK_TAG_UNDEFINED);
22013 }
22014 
duk_is_null(duk_hthread * thr,duk_idx_t idx)22015 DUK_EXTERNAL duk_bool_t duk_is_null(duk_hthread *thr, duk_idx_t idx) {
22016 	DUK_ASSERT_API_ENTRY(thr);
22017 	return duk__tag_check(thr, idx, DUK_TAG_NULL);
22018 }
22019 
duk_is_boolean(duk_hthread * thr,duk_idx_t idx)22020 DUK_EXTERNAL duk_bool_t duk_is_boolean(duk_hthread *thr, duk_idx_t idx) {
22021 	DUK_ASSERT_API_ENTRY(thr);
22022 	return duk__tag_check(thr, idx, DUK_TAG_BOOLEAN);
22023 }
22024 
duk_is_number(duk_hthread * thr,duk_idx_t idx)22025 DUK_EXTERNAL duk_bool_t duk_is_number(duk_hthread *thr, duk_idx_t idx) {
22026 	duk_tval *tv;
22027 
22028 	DUK_ASSERT_API_ENTRY(thr);
22029 
22030 	/*
22031 	 *  Number is special because it doesn't have a specific
22032 	 *  tag in the 8-byte representation.
22033 	 */
22034 
22035 	/* XXX: shorter version for unpacked representation? */
22036 
22037 	tv = duk_get_tval_or_unused(thr, idx);
22038 	DUK_ASSERT(tv != NULL);
22039 	return DUK_TVAL_IS_NUMBER(tv);
22040 }
22041 
duk_is_nan(duk_hthread * thr,duk_idx_t idx)22042 DUK_EXTERNAL duk_bool_t duk_is_nan(duk_hthread *thr, duk_idx_t idx) {
22043 	/* XXX: This will now return false for non-numbers, even though they would
22044 	 * coerce to NaN (as a general rule).  In particular, duk_get_number()
22045 	 * returns a NaN for non-numbers, so should this function also return
22046 	 * true for non-numbers?
22047 	 */
22048 
22049 	duk_tval *tv;
22050 
22051 	DUK_ASSERT_API_ENTRY(thr);
22052 
22053 	tv = duk_get_tval_or_unused(thr, idx);
22054 	DUK_ASSERT(tv != NULL);
22055 
22056 	/* XXX: for packed duk_tval an explicit "is number" check is unnecessary */
22057 	if (!DUK_TVAL_IS_NUMBER(tv)) {
22058 		return 0;
22059 	}
22060 	return (duk_bool_t) DUK_ISNAN(DUK_TVAL_GET_NUMBER(tv));
22061 }
22062 
duk_is_string(duk_hthread * thr,duk_idx_t idx)22063 DUK_EXTERNAL duk_bool_t duk_is_string(duk_hthread *thr, duk_idx_t idx) {
22064 	DUK_ASSERT_API_ENTRY(thr);
22065 	return duk__tag_check(thr, idx, DUK_TAG_STRING);
22066 }
22067 
duk_is_string_notsymbol(duk_hthread * thr,duk_idx_t idx)22068 DUK_INTERNAL duk_bool_t duk_is_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {
22069 	DUK_ASSERT_API_ENTRY(thr);
22070 	return duk_get_hstring_notsymbol(thr, idx) != NULL;
22071 }
22072 
duk_is_object(duk_hthread * thr,duk_idx_t idx)22073 DUK_EXTERNAL duk_bool_t duk_is_object(duk_hthread *thr, duk_idx_t idx) {
22074 	DUK_ASSERT_API_ENTRY(thr);
22075 	return duk__tag_check(thr, idx, DUK_TAG_OBJECT);
22076 }
22077 
duk_is_buffer(duk_hthread * thr,duk_idx_t idx)22078 DUK_EXTERNAL duk_bool_t duk_is_buffer(duk_hthread *thr, duk_idx_t idx) {
22079 	DUK_ASSERT_API_ENTRY(thr);
22080 	return duk__tag_check(thr, idx, DUK_TAG_BUFFER);
22081 }
22082 
22083 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_is_buffer_data(duk_hthread * thr,duk_idx_t idx)22084 DUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_hthread *thr, duk_idx_t idx) {
22085 	duk_tval *tv;
22086 
22087 	DUK_ASSERT_API_ENTRY(thr);
22088 
22089 	tv = duk_get_tval_or_unused(thr, idx);
22090 	DUK_ASSERT(tv != NULL);
22091 	if (DUK_TVAL_IS_BUFFER(tv)) {
22092 		return 1;
22093 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
22094 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
22095 		DUK_ASSERT(h != NULL);
22096 		if (DUK_HOBJECT_IS_BUFOBJ(h)) {
22097 			return 1;
22098 		}
22099 	}
22100 	return 0;
22101 }
22102 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_is_buffer_data(duk_hthread * thr,duk_idx_t idx)22103 DUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_hthread *thr, duk_idx_t idx) {
22104 	DUK_ASSERT_API_ENTRY(thr);
22105 
22106 	return duk_is_buffer(thr, idx);
22107 }
22108 
22109 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
22110 
duk_is_pointer(duk_hthread * thr,duk_idx_t idx)22111 DUK_EXTERNAL duk_bool_t duk_is_pointer(duk_hthread *thr, duk_idx_t idx) {
22112 	DUK_ASSERT_API_ENTRY(thr);
22113 	return duk__tag_check(thr, idx, DUK_TAG_POINTER);
22114 }
22115 
duk_is_lightfunc(duk_hthread * thr,duk_idx_t idx)22116 DUK_EXTERNAL duk_bool_t duk_is_lightfunc(duk_hthread *thr, duk_idx_t idx) {
22117 	DUK_ASSERT_API_ENTRY(thr);
22118 	return duk__tag_check(thr, idx, DUK_TAG_LIGHTFUNC);
22119 }
22120 
duk_is_symbol(duk_hthread * thr,duk_idx_t idx)22121 DUK_EXTERNAL duk_bool_t duk_is_symbol(duk_hthread *thr, duk_idx_t idx) {
22122 	duk_hstring *h;
22123 
22124 	DUK_ASSERT_API_ENTRY(thr);
22125 	h = duk_get_hstring(thr, idx);
22126 	/* Use DUK_LIKELY() here because caller may be more likely to type
22127 	 * check an expected symbol than not.
22128 	 */
22129 	if (DUK_LIKELY(h != NULL && DUK_HSTRING_HAS_SYMBOL(h))) {
22130 		return 1;
22131 	}
22132 	return 0;
22133 }
22134 
22135 /* IsArray(), returns true for Array instance or Proxy of Array instance. */
duk_is_array(duk_hthread * thr,duk_idx_t idx)22136 DUK_EXTERNAL duk_bool_t duk_is_array(duk_hthread *thr, duk_idx_t idx) {
22137 	duk_tval *tv;
22138 
22139 	DUK_ASSERT_API_ENTRY(thr);
22140 
22141 	tv = duk_get_tval(thr, idx);
22142 	if (tv) {
22143 		return duk_js_isarray(tv);
22144 	}
22145 	return 0;
22146 }
22147 
duk_is_function(duk_hthread * thr,duk_idx_t idx)22148 DUK_EXTERNAL duk_bool_t duk_is_function(duk_hthread *thr, duk_idx_t idx) {
22149 	duk_tval *tv;
22150 
22151 	DUK_ASSERT_API_ENTRY(thr);
22152 
22153 	tv = duk_get_tval_or_unused(thr, idx);
22154 	if (DUK_TVAL_IS_OBJECT(tv)) {
22155 		duk_hobject *h;
22156 		h = DUK_TVAL_GET_OBJECT(tv);
22157 		DUK_ASSERT(h != NULL);
22158 		return DUK_HOBJECT_HAS_CALLABLE(h) ? 1 : 0;
22159 	}
22160 	if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
22161 		return 1;
22162 	}
22163 	return 0;
22164 }
22165 
duk_is_callable_tval(duk_hthread * thr,duk_tval * tv)22166 DUK_INTERNAL duk_bool_t duk_is_callable_tval(duk_hthread *thr, duk_tval *tv) {
22167 	DUK_ASSERT_API_ENTRY(thr);
22168 
22169 	DUK_UNREF(thr);
22170 
22171 	if (DUK_TVAL_IS_OBJECT(tv)) {
22172 		duk_hobject *h;
22173 		h = DUK_TVAL_GET_OBJECT(tv);
22174 		DUK_ASSERT(h != NULL);
22175 		return DUK_HOBJECT_HAS_CALLABLE(h) ? 1 : 0;
22176 	}
22177 	if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
22178 		return 1;
22179 	}
22180 	return 0;
22181 }
22182 
duk_is_constructable(duk_hthread * thr,duk_idx_t idx)22183 DUK_EXTERNAL duk_bool_t duk_is_constructable(duk_hthread *thr, duk_idx_t idx) {
22184 	duk_tval *tv;
22185 
22186 	DUK_ASSERT_API_ENTRY(thr);
22187 
22188 	tv = duk_get_tval_or_unused(thr, idx);
22189 	if (DUK_TVAL_IS_OBJECT(tv)) {
22190 		duk_hobject *h;
22191 		h = DUK_TVAL_GET_OBJECT(tv);
22192 		DUK_ASSERT(h != NULL);
22193 		return DUK_HOBJECT_HAS_CONSTRUCTABLE(h) ? 1 : 0;
22194 	}
22195 	if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
22196 		return 1;
22197 	}
22198 	return 0;
22199 }
22200 
duk_is_c_function(duk_hthread * thr,duk_idx_t idx)22201 DUK_EXTERNAL duk_bool_t duk_is_c_function(duk_hthread *thr, duk_idx_t idx) {
22202 	DUK_ASSERT_API_ENTRY(thr);
22203 	return duk__obj_flag_any_default_false(thr,
22204 	                                       idx,
22205 	                                       DUK_HOBJECT_FLAG_NATFUNC);
22206 }
22207 
duk_is_ecmascript_function(duk_hthread * thr,duk_idx_t idx)22208 DUK_EXTERNAL duk_bool_t duk_is_ecmascript_function(duk_hthread *thr, duk_idx_t idx) {
22209 	DUK_ASSERT_API_ENTRY(thr);
22210 	return duk__obj_flag_any_default_false(thr,
22211 	                                       idx,
22212 	                                       DUK_HOBJECT_FLAG_COMPFUNC);
22213 }
22214 
duk_is_bound_function(duk_hthread * thr,duk_idx_t idx)22215 DUK_EXTERNAL duk_bool_t duk_is_bound_function(duk_hthread *thr, duk_idx_t idx) {
22216 	DUK_ASSERT_API_ENTRY(thr);
22217 	return duk__obj_flag_any_default_false(thr,
22218 	                                       idx,
22219 	                                       DUK_HOBJECT_FLAG_BOUNDFUNC);
22220 }
22221 
duk_is_thread(duk_hthread * thr,duk_idx_t idx)22222 DUK_EXTERNAL duk_bool_t duk_is_thread(duk_hthread *thr, duk_idx_t idx) {
22223 	duk_hobject *obj;
22224 
22225 	DUK_ASSERT_API_ENTRY(thr);
22226 
22227 	obj = duk_get_hobject(thr, idx);
22228 	if (obj) {
22229 		return (DUK_HOBJECT_GET_CLASS_NUMBER(obj) == DUK_HOBJECT_CLASS_THREAD ? 1 : 0);
22230 	}
22231 	return 0;
22232 }
22233 
duk_is_fixed_buffer(duk_hthread * thr,duk_idx_t idx)22234 DUK_EXTERNAL duk_bool_t duk_is_fixed_buffer(duk_hthread *thr, duk_idx_t idx) {
22235 	duk_tval *tv;
22236 
22237 	DUK_ASSERT_API_ENTRY(thr);
22238 
22239 	tv = duk_get_tval_or_unused(thr, idx);
22240 	DUK_ASSERT(tv != NULL);
22241 	if (DUK_TVAL_IS_BUFFER(tv)) {
22242 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
22243 		DUK_ASSERT(h != NULL);
22244 		return (DUK_HBUFFER_HAS_DYNAMIC(h) ? 0 : 1);
22245 	}
22246 	return 0;
22247 }
22248 
duk_is_dynamic_buffer(duk_hthread * thr,duk_idx_t idx)22249 DUK_EXTERNAL duk_bool_t duk_is_dynamic_buffer(duk_hthread *thr, duk_idx_t idx) {
22250 	duk_tval *tv;
22251 
22252 	DUK_ASSERT_API_ENTRY(thr);
22253 
22254 	tv = duk_get_tval_or_unused(thr, idx);
22255 	DUK_ASSERT(tv != NULL);
22256 	if (DUK_TVAL_IS_BUFFER(tv)) {
22257 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
22258 		DUK_ASSERT(h != NULL);
22259 		return (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
22260 	}
22261 	return 0;
22262 }
22263 
duk_is_external_buffer(duk_hthread * thr,duk_idx_t idx)22264 DUK_EXTERNAL duk_bool_t duk_is_external_buffer(duk_hthread *thr, duk_idx_t idx) {
22265 	duk_tval *tv;
22266 
22267 	DUK_ASSERT_API_ENTRY(thr);
22268 
22269 	tv = duk_get_tval_or_unused(thr, idx);
22270 	DUK_ASSERT(tv != NULL);
22271 	if (DUK_TVAL_IS_BUFFER(tv)) {
22272 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
22273 		DUK_ASSERT(h != NULL);
22274 		return (DUK_HBUFFER_HAS_DYNAMIC(h) && DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
22275 	}
22276 	return 0;
22277 }
22278 
duk_get_error_code(duk_hthread * thr,duk_idx_t idx)22279 DUK_EXTERNAL duk_errcode_t duk_get_error_code(duk_hthread *thr, duk_idx_t idx) {
22280 	duk_hobject *h;
22281 	duk_uint_t sanity;
22282 
22283 	DUK_ASSERT_API_ENTRY(thr);
22284 
22285 	h = duk_get_hobject(thr, idx);
22286 
22287 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
22288 	do {
22289 		if (!h) {
22290 			return DUK_ERR_NONE;
22291 		}
22292 
22293 		/* XXX: something more convenient? */
22294 
22295 		if (h == thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE]) {
22296 			return DUK_ERR_EVAL_ERROR;
22297 		}
22298 		if (h == thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE]) {
22299 			return DUK_ERR_RANGE_ERROR;
22300 		}
22301 		if (h == thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE]) {
22302 			return DUK_ERR_REFERENCE_ERROR;
22303 		}
22304 		if (h == thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE]) {
22305 			return DUK_ERR_SYNTAX_ERROR;
22306 		}
22307 		if (h == thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE]) {
22308 			return DUK_ERR_TYPE_ERROR;
22309 		}
22310 		if (h == thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE]) {
22311 			return DUK_ERR_URI_ERROR;
22312 		}
22313 		if (h == thr->builtins[DUK_BIDX_ERROR_PROTOTYPE]) {
22314 			return DUK_ERR_ERROR;
22315 		}
22316 
22317 		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
22318 	} while (--sanity > 0);
22319 
22320 	return DUK_ERR_NONE;
22321 }
22322 
22323 /*
22324  *  Pushers
22325  */
22326 
duk_push_tval(duk_hthread * thr,duk_tval * tv)22327 DUK_INTERNAL void duk_push_tval(duk_hthread *thr, duk_tval *tv) {
22328 	duk_tval *tv_slot;
22329 
22330 	DUK_ASSERT_API_ENTRY(thr);
22331 	DUK_ASSERT(tv != NULL);
22332 
22333 	DUK__CHECK_SPACE();
22334 	tv_slot = thr->valstack_top++;
22335 	DUK_TVAL_SET_TVAL(tv_slot, tv);
22336 	DUK_TVAL_INCREF(thr, tv);  /* no side effects */
22337 }
22338 
duk_push_undefined(duk_hthread * thr)22339 DUK_EXTERNAL void duk_push_undefined(duk_hthread *thr) {
22340 	DUK_ASSERT_API_ENTRY(thr);
22341 
22342 	DUK__CHECK_SPACE();
22343 
22344 	/* Because value stack init policy is 'undefined above top',
22345 	 * we don't need to write, just assert.
22346 	 */
22347 	thr->valstack_top++;
22348 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
22349 }
22350 
duk_push_null(duk_hthread * thr)22351 DUK_EXTERNAL void duk_push_null(duk_hthread *thr) {
22352 	duk_tval *tv_slot;
22353 
22354 	DUK_ASSERT_API_ENTRY(thr);
22355 	DUK__CHECK_SPACE();
22356 	tv_slot = thr->valstack_top++;
22357 	DUK_TVAL_SET_NULL(tv_slot);
22358 }
22359 
duk_push_boolean(duk_hthread * thr,duk_bool_t val)22360 DUK_EXTERNAL void duk_push_boolean(duk_hthread *thr, duk_bool_t val) {
22361 	duk_tval *tv_slot;
22362 	duk_small_int_t b;
22363 
22364 	DUK_ASSERT_API_ENTRY(thr);
22365 	DUK__CHECK_SPACE();
22366 	b = (val ? 1 : 0);  /* ensure value is 1 or 0 (not other non-zero) */
22367 	tv_slot = thr->valstack_top++;
22368 	DUK_TVAL_SET_BOOLEAN(tv_slot, b);
22369 }
22370 
duk_push_true(duk_hthread * thr)22371 DUK_EXTERNAL void duk_push_true(duk_hthread *thr) {
22372 	duk_tval *tv_slot;
22373 
22374 	DUK_ASSERT_API_ENTRY(thr);
22375 	DUK__CHECK_SPACE();
22376 	tv_slot = thr->valstack_top++;
22377 	DUK_TVAL_SET_BOOLEAN_TRUE(tv_slot);
22378 }
22379 
duk_push_false(duk_hthread * thr)22380 DUK_EXTERNAL void duk_push_false(duk_hthread *thr) {
22381 	duk_tval *tv_slot;
22382 
22383 	DUK_ASSERT_API_ENTRY(thr);
22384 	DUK__CHECK_SPACE();
22385 	tv_slot = thr->valstack_top++;
22386 	DUK_TVAL_SET_BOOLEAN_FALSE(tv_slot);
22387 }
22388 
22389 /* normalize NaN which may not match our canonical internal NaN */
duk_push_number(duk_hthread * thr,duk_double_t val)22390 DUK_EXTERNAL void duk_push_number(duk_hthread *thr, duk_double_t val) {
22391 	duk_tval *tv_slot;
22392 	duk_double_union du;
22393 
22394 	DUK_ASSERT_API_ENTRY(thr);
22395 	DUK__CHECK_SPACE();
22396 	du.d = val;
22397 	DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
22398 	tv_slot = thr->valstack_top++;
22399 	DUK_TVAL_SET_NUMBER(tv_slot, du.d);
22400 }
22401 
duk_push_int(duk_hthread * thr,duk_int_t val)22402 DUK_EXTERNAL void duk_push_int(duk_hthread *thr, duk_int_t val) {
22403 #if defined(DUK_USE_FASTINT)
22404 	duk_tval *tv_slot;
22405 
22406 	DUK_ASSERT_API_ENTRY(thr);
22407 	DUK__CHECK_SPACE();
22408 	tv_slot = thr->valstack_top++;
22409 #if DUK_INT_MAX <= 0x7fffffffL
22410 	DUK_TVAL_SET_I32(tv_slot, (duk_int32_t) val);
22411 #else
22412 	if (val >= DUK_FASTINT_MIN && val <= DUK_FASTINT_MAX) {
22413 		DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
22414 	} else {
22415 		duk_double_t = (duk_double_t) val;
22416 		DUK_TVAL_SET_NUMBER(tv_slot, d);
22417 	}
22418 #endif
22419 #else  /* DUK_USE_FASTINT */
22420 	duk_tval *tv_slot;
22421 	duk_double_t d;
22422 
22423 	DUK_ASSERT_API_ENTRY(thr);
22424 	DUK__CHECK_SPACE();
22425 	d = (duk_double_t) val;
22426 	tv_slot = thr->valstack_top++;
22427 	DUK_TVAL_SET_NUMBER(tv_slot, d);
22428 #endif  /* DUK_USE_FASTINT */
22429 }
22430 
duk_push_uint(duk_hthread * thr,duk_uint_t val)22431 DUK_EXTERNAL void duk_push_uint(duk_hthread *thr, duk_uint_t val) {
22432 #if defined(DUK_USE_FASTINT)
22433 	duk_tval *tv_slot;
22434 
22435 	DUK_ASSERT_API_ENTRY(thr);
22436 	DUK__CHECK_SPACE();
22437 	tv_slot = thr->valstack_top++;
22438 #if DUK_UINT_MAX <= 0xffffffffUL
22439 	DUK_TVAL_SET_U32(tv_slot, (duk_uint32_t) val);
22440 #else
22441 	if (val <= DUK_FASTINT_MAX) {  /* val is unsigned so >= 0 */
22442 		/* XXX: take advantage of val being unsigned, no need to mask */
22443 		DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
22444 	} else {
22445 		duk_double_t = (duk_double_t) val;
22446 		DUK_TVAL_SET_NUMBER(tv_slot, d);
22447 	}
22448 #endif
22449 #else  /* DUK_USE_FASTINT */
22450 	duk_tval *tv_slot;
22451 	duk_double_t d;
22452 
22453 	DUK_ASSERT_API_ENTRY(thr);
22454 	DUK__CHECK_SPACE();
22455 	d = (duk_double_t) val;
22456 	tv_slot = thr->valstack_top++;
22457 	DUK_TVAL_SET_NUMBER(tv_slot, d);
22458 #endif  /* DUK_USE_FASTINT */
22459 }
22460 
duk_push_nan(duk_hthread * thr)22461 DUK_EXTERNAL void duk_push_nan(duk_hthread *thr) {
22462 	duk_tval *tv_slot;
22463 	duk_double_union du;
22464 
22465 	DUK_ASSERT_API_ENTRY(thr);
22466 	DUK__CHECK_SPACE();
22467 	DUK_DBLUNION_SET_NAN(&du);
22468 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
22469 	tv_slot = thr->valstack_top++;
22470 	DUK_TVAL_SET_NUMBER(tv_slot, du.d);
22471 }
22472 
duk_push_lstring(duk_hthread * thr,const char * str,duk_size_t len)22473 DUK_EXTERNAL const char *duk_push_lstring(duk_hthread *thr, const char *str, duk_size_t len) {
22474 	duk_hstring *h;
22475 	duk_tval *tv_slot;
22476 
22477 	DUK_ASSERT_API_ENTRY(thr);
22478 
22479 	/* Check stack before interning (avoid hanging temp). */
22480 	DUK__CHECK_SPACE();
22481 
22482 	/* NULL with zero length represents an empty string; NULL with higher
22483 	 * length is also now treated like an empty string although it is
22484 	 * a bit dubious.  This is unlike duk_push_string() which pushes a
22485 	 * 'null' if the input string is a NULL.
22486 	 */
22487 	if (DUK_UNLIKELY(str == NULL)) {
22488 		len = 0U;
22489 	}
22490 
22491 	/* Check for maximum string length. */
22492 	if (DUK_UNLIKELY(len > DUK_HSTRING_MAX_BYTELEN)) {
22493 		DUK_ERROR_RANGE(thr, DUK_STR_STRING_TOO_LONG);
22494 		DUK_WO_NORETURN(return NULL;);
22495 	}
22496 
22497 	h = duk_heap_strtable_intern_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
22498 	DUK_ASSERT(h != NULL);
22499 
22500 	tv_slot = thr->valstack_top++;
22501 	DUK_TVAL_SET_STRING(tv_slot, h);
22502 	DUK_HSTRING_INCREF(thr, h);  /* no side effects */
22503 
22504 	return (const char *) DUK_HSTRING_GET_DATA(h);
22505 }
22506 
duk_push_string(duk_hthread * thr,const char * str)22507 DUK_EXTERNAL const char *duk_push_string(duk_hthread *thr, const char *str) {
22508 	DUK_ASSERT_API_ENTRY(thr);
22509 
22510 	if (str) {
22511 		return duk_push_lstring(thr, str, DUK_STRLEN(str));
22512 	} else {
22513 		duk_push_null(thr);
22514 		return NULL;
22515 	}
22516 }
22517 
22518 #if !defined(DUK_USE_PREFER_SIZE)
22519 #if defined(DUK_USE_LITCACHE_SIZE)
duk_push_literal_raw(duk_hthread * thr,const char * str,duk_size_t len)22520 DUK_EXTERNAL const char *duk_push_literal_raw(duk_hthread *thr, const char *str, duk_size_t len) {
22521 	duk_hstring *h;
22522 	duk_tval *tv_slot;
22523 
22524 	DUK_ASSERT_API_ENTRY(thr);
22525 	DUK_ASSERT(str != NULL);
22526 	DUK_ASSERT(str[len] == (char) 0);
22527 
22528 	/* Check for maximum string length. */
22529 	if (DUK_UNLIKELY(len > DUK_HSTRING_MAX_BYTELEN)) {
22530 		DUK_ERROR_RANGE(thr, DUK_STR_STRING_TOO_LONG);
22531 		DUK_WO_NORETURN(return NULL;);
22532 	}
22533 
22534 	h = duk_heap_strtable_intern_literal_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
22535 	DUK_ASSERT(h != NULL);
22536 
22537 	tv_slot = thr->valstack_top++;
22538 	DUK_TVAL_SET_STRING(tv_slot, h);
22539 	DUK_HSTRING_INCREF(thr, h);  /* no side effects */
22540 
22541 	return (const char *) DUK_HSTRING_GET_DATA(h);
22542 }
22543 #else  /* DUK_USE_LITCACHE_SIZE */
duk_push_literal_raw(duk_hthread * thr,const char * str,duk_size_t len)22544 DUK_EXTERNAL const char *duk_push_literal_raw(duk_hthread *thr, const char *str, duk_size_t len) {
22545 	DUK_ASSERT_API_ENTRY(thr);
22546 	DUK_ASSERT(str != NULL);
22547 	DUK_ASSERT(str[len] == (char) 0);
22548 
22549 	return duk_push_lstring(thr, str, len);
22550 }
22551 #endif  /* DUK_USE_LITCACHE_SIZE */
22552 #endif  /* !DUK_USE_PREFER_SIZE */
22553 
duk_push_pointer(duk_hthread * thr,void * val)22554 DUK_EXTERNAL void duk_push_pointer(duk_hthread *thr, void *val) {
22555 	duk_tval *tv_slot;
22556 
22557 	DUK_ASSERT_API_ENTRY(thr);
22558 	DUK__CHECK_SPACE();
22559 	tv_slot = thr->valstack_top++;
22560 	DUK_TVAL_SET_POINTER(tv_slot, val);
22561 }
22562 
duk_push_uint_to_hstring(duk_hthread * thr,duk_uint_t i)22563 DUK_INTERNAL duk_hstring *duk_push_uint_to_hstring(duk_hthread *thr, duk_uint_t i) {
22564 	duk_hstring *h_tmp;
22565 
22566 	DUK_ASSERT_API_ENTRY(thr);
22567 
22568 	/* XXX: this could be a direct DUK_SPRINTF to a buffer followed by duk_push_string() */
22569 	duk_push_uint(thr, (duk_uint_t) i);
22570 	h_tmp = duk_to_hstring_m1(thr);
22571 	DUK_ASSERT(h_tmp != NULL);
22572 	return h_tmp;
22573 }
22574 
duk__push_this_helper(duk_hthread * thr,duk_small_uint_t check_object_coercible)22575 DUK_LOCAL void duk__push_this_helper(duk_hthread *thr, duk_small_uint_t check_object_coercible) {
22576 	duk_tval *tv_slot;
22577 
22578 	DUK__CHECK_SPACE();
22579 
22580 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* because of valstack init policy */
22581 	tv_slot = thr->valstack_top++;
22582 
22583 	if (DUK_UNLIKELY(thr->callstack_curr == NULL)) {
22584 		if (check_object_coercible) {
22585 			goto type_error;
22586 		}
22587 		/* 'undefined' already on stack top */
22588 	} else {
22589 		duk_tval *tv;
22590 
22591 		/* 'this' binding is just before current activation's bottom */
22592 		DUK_ASSERT(thr->valstack_bottom > thr->valstack);
22593 		tv = thr->valstack_bottom - 1;
22594 		if (check_object_coercible &&
22595 		    (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv))) {
22596 			/* XXX: better macro for DUK_TVAL_IS_UNDEFINED_OR_NULL(tv) */
22597 			goto type_error;
22598 		}
22599 
22600 		DUK_TVAL_SET_TVAL(tv_slot, tv);
22601 		DUK_TVAL_INCREF(thr, tv);
22602 	}
22603 	return;
22604 
22605  type_error:
22606 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE);
22607 	DUK_WO_NORETURN(return;);
22608 }
22609 
duk_push_this(duk_hthread * thr)22610 DUK_EXTERNAL void duk_push_this(duk_hthread *thr) {
22611 	DUK_ASSERT_API_ENTRY(thr);
22612 
22613 	duk__push_this_helper(thr, 0 /*check_object_coercible*/);
22614 }
22615 
duk_push_this_check_object_coercible(duk_hthread * thr)22616 DUK_INTERNAL void duk_push_this_check_object_coercible(duk_hthread *thr) {
22617 	DUK_ASSERT_API_ENTRY(thr);
22618 
22619 	duk__push_this_helper(thr, 1 /*check_object_coercible*/);
22620 }
22621 
duk_push_this_coercible_to_object(duk_hthread * thr)22622 DUK_INTERNAL duk_hobject *duk_push_this_coercible_to_object(duk_hthread *thr) {
22623 	duk_hobject *h;
22624 
22625 	DUK_ASSERT_API_ENTRY(thr);
22626 
22627 	duk__push_this_helper(thr, 1 /*check_object_coercible*/);
22628 	h = duk_to_hobject(thr, -1);
22629 	DUK_ASSERT(h != NULL);
22630 	return h;
22631 }
22632 
duk_push_this_coercible_to_string(duk_hthread * thr)22633 DUK_INTERNAL duk_hstring *duk_push_this_coercible_to_string(duk_hthread *thr) {
22634 	DUK_ASSERT_API_ENTRY(thr);
22635 
22636 	duk__push_this_helper(thr, 1 /*check_object_coercible*/);
22637 	return duk_to_hstring_m1(thr);  /* This will reject all Symbol values; accepts Symbol objects. */
22638 }
22639 
duk_get_borrowed_this_tval(duk_hthread * thr)22640 DUK_INTERNAL duk_tval *duk_get_borrowed_this_tval(duk_hthread *thr) {
22641 	DUK_ASSERT_API_ENTRY(thr);
22642 
22643 	DUK_ASSERT(thr->callstack_top > 0);  /* caller required to know */
22644 	DUK_ASSERT(thr->callstack_curr != NULL);  /* caller required to know */
22645 	DUK_ASSERT(thr->valstack_bottom > thr->valstack);  /* consequence of above */
22646 	DUK_ASSERT(thr->valstack_bottom - 1 >= thr->valstack);  /* 'this' binding exists */
22647 
22648 	return thr->valstack_bottom - 1;
22649 }
22650 
duk_push_new_target(duk_hthread * thr)22651 DUK_EXTERNAL void duk_push_new_target(duk_hthread *thr) {
22652 	duk_activation *act;
22653 
22654 	DUK_ASSERT_API_ENTRY(thr);
22655 
22656 	/* https://www.ecma-international.org/ecma-262/6.0/#sec-meta-properties-runtime-semantics-evaluation
22657 	 * https://www.ecma-international.org/ecma-262/6.0/#sec-getnewtarget
22658 	 *
22659 	 * No newTarget support now, so as a first approximation
22660 	 * use the resolved (non-bound) target function.
22661 	 *
22662 	 * Check CONSTRUCT flag from current function, or if running
22663 	 * direct eval, from a non-direct-eval parent (with possibly
22664 	 * more than one nested direct eval).  An alternative to this
22665 	 * would be to store [[NewTarget]] as a hidden symbol of the
22666 	 * lexical scope, and then just look up that variable.
22667 	 *
22668 	 * Calls from the application will either be for an empty
22669 	 * call stack, or a Duktape/C function as the top activation.
22670 	 */
22671 
22672 	act = thr->callstack_curr;
22673 	for (;;) {
22674 		if (act == NULL) {
22675 			break;
22676 		}
22677 
22678 		if (act->flags & DUK_ACT_FLAG_CONSTRUCT) {
22679 			duk_push_tval(thr, &act->tv_func);
22680 			return;
22681 		} else if (act->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
22682 			act = act->parent;
22683 		} else {
22684 			break;
22685 		}
22686 	}
22687 
22688 	duk_push_undefined(thr);
22689 }
22690 
duk_push_current_function(duk_hthread * thr)22691 DUK_EXTERNAL void duk_push_current_function(duk_hthread *thr) {
22692 	duk_activation *act;
22693 
22694 	DUK_ASSERT_API_ENTRY(thr);
22695 
22696 	act = thr->callstack_curr;
22697 	if (act != NULL) {
22698 		duk_push_tval(thr, &act->tv_func);
22699 	} else {
22700 		duk_push_undefined(thr);
22701 	}
22702 }
22703 
duk_push_current_thread(duk_hthread * thr)22704 DUK_EXTERNAL void duk_push_current_thread(duk_hthread *thr) {
22705 	DUK_ASSERT_API_ENTRY(thr);
22706 
22707 	if (thr->heap->curr_thread) {
22708 		duk_push_hobject(thr, (duk_hobject *) thr->heap->curr_thread);
22709 	} else {
22710 		duk_push_undefined(thr);
22711 	}
22712 }
22713 
duk_push_global_object(duk_hthread * thr)22714 DUK_EXTERNAL void duk_push_global_object(duk_hthread *thr) {
22715 	DUK_ASSERT_API_ENTRY(thr);
22716 
22717 	duk_push_hobject_bidx(thr, DUK_BIDX_GLOBAL);
22718 }
22719 
22720 /* XXX: size optimize */
duk__push_stash(duk_hthread * thr)22721 DUK_LOCAL void duk__push_stash(duk_hthread *thr) {
22722 	if (!duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE)) {
22723 		DUK_DDD(DUK_DDDPRINT("creating heap/global/thread stash on first use"));
22724 		duk_pop_unsafe(thr);
22725 		duk_push_bare_object(thr);
22726 		duk_dup_top(thr);
22727 		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_C);  /* [ ... parent stash stash ] -> [ ... parent stash ] */
22728 	}
22729 	duk_remove_m2(thr);
22730 }
22731 
duk_push_heap_stash(duk_hthread * thr)22732 DUK_EXTERNAL void duk_push_heap_stash(duk_hthread *thr) {
22733 	duk_heap *heap;
22734 	DUK_ASSERT_API_ENTRY(thr);
22735 	heap = thr->heap;
22736 	DUK_ASSERT(heap->heap_object != NULL);
22737 	duk_push_hobject(thr, heap->heap_object);
22738 	duk__push_stash(thr);
22739 }
22740 
duk_push_global_stash(duk_hthread * thr)22741 DUK_EXTERNAL void duk_push_global_stash(duk_hthread *thr) {
22742 	DUK_ASSERT_API_ENTRY(thr);
22743 	duk_push_global_object(thr);
22744 	duk__push_stash(thr);
22745 }
22746 
duk_push_thread_stash(duk_hthread * thr,duk_hthread * target_thr)22747 DUK_EXTERNAL void duk_push_thread_stash(duk_hthread *thr, duk_hthread *target_thr) {
22748 	DUK_ASSERT_API_ENTRY(thr);
22749 	if (DUK_UNLIKELY(target_thr == NULL)) {
22750 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
22751 		DUK_WO_NORETURN(return;);
22752 	}
22753 	duk_push_hobject(thr, (duk_hobject *) target_thr);
22754 	duk__push_stash(thr);
22755 }
22756 
22757 /* 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)22758 DUK_LOCAL duk_int_t duk__try_push_vsprintf(duk_hthread *thr, void *buf, duk_size_t sz, const char *fmt, va_list ap) {
22759 	duk_int_t len;
22760 
22761 	DUK_CTX_ASSERT_VALID(thr);
22762 	DUK_UNREF(thr);
22763 
22764 	/* NUL terminator handling doesn't matter here */
22765 	len = DUK_VSNPRINTF((char *) buf, sz, fmt, ap);
22766 	if (len < (duk_int_t) sz) {
22767 		/* Return value of 'sz' or more indicates output was (potentially)
22768 		 * truncated.
22769 		 */
22770 		return (duk_int_t) len;
22771 	}
22772 	return -1;
22773 }
22774 
duk_push_vsprintf(duk_hthread * thr,const char * fmt,va_list ap)22775 DUK_EXTERNAL const char *duk_push_vsprintf(duk_hthread *thr, const char *fmt, va_list ap) {
22776 	duk_uint8_t stack_buf[DUK_PUSH_SPRINTF_INITIAL_SIZE];
22777 	duk_size_t sz = DUK_PUSH_SPRINTF_INITIAL_SIZE;
22778 	duk_bool_t pushed_buf = 0;
22779 	void *buf;
22780 	duk_int_t len;  /* XXX: duk_ssize_t */
22781 	const char *res;
22782 
22783 	DUK_ASSERT_API_ENTRY(thr);
22784 
22785 	/* special handling of fmt==NULL */
22786 	if (!fmt) {
22787 		duk_hstring *h_str;
22788 		duk_push_hstring_empty(thr);
22789 		h_str = duk_known_hstring(thr, -1);
22790 		return (const char *) DUK_HSTRING_GET_DATA(h_str);
22791 	}
22792 
22793 	/* initial estimate based on format string */
22794 	sz = DUK_STRLEN(fmt) + 16;  /* format plus something to avoid just missing */
22795 	if (sz < DUK_PUSH_SPRINTF_INITIAL_SIZE) {
22796 		sz = DUK_PUSH_SPRINTF_INITIAL_SIZE;
22797 	}
22798 	DUK_ASSERT(sz > 0);
22799 
22800 	/* Try to make do with a stack buffer to avoid allocating a temporary buffer.
22801 	 * This works 99% of the time which is quite nice.
22802 	 */
22803 	for (;;) {
22804 		va_list ap_copy;  /* copied so that 'ap' can be reused */
22805 
22806 		if (sz <= sizeof(stack_buf)) {
22807 			buf = stack_buf;
22808 		} else if (!pushed_buf) {
22809 			pushed_buf = 1;
22810 			buf = duk_push_dynamic_buffer(thr, sz);
22811 		} else {
22812 			buf = duk_resize_buffer(thr, -1, sz);
22813 		}
22814 		DUK_ASSERT(buf != NULL);
22815 
22816 		DUK_VA_COPY(ap_copy, ap);
22817 		len = duk__try_push_vsprintf(thr, buf, sz, fmt, ap_copy);
22818 		va_end(ap_copy);
22819 		if (len >= 0) {
22820 			break;
22821 		}
22822 
22823 		/* failed, resize and try again */
22824 		sz = sz * 2;
22825 		if (DUK_UNLIKELY(sz >= DUK_PUSH_SPRINTF_SANITY_LIMIT)) {
22826 			DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
22827 			DUK_WO_NORETURN(return NULL;);
22828 		}
22829 	}
22830 
22831 	/* Cannot use duk_buffer_to_string() on the buffer because it is
22832 	 * usually larger than 'len'; 'buf' is also usually a stack buffer.
22833 	 */
22834 	res = duk_push_lstring(thr, (const char *) buf, (duk_size_t) len);  /* [ buf? res ] */
22835 	if (pushed_buf) {
22836 		duk_remove_m2(thr);
22837 	}
22838 	return res;
22839 }
22840 
duk_push_sprintf(duk_hthread * thr,const char * fmt,...)22841 DUK_EXTERNAL const char *duk_push_sprintf(duk_hthread *thr, const char *fmt, ...) {
22842 	va_list ap;
22843 	const char *ret;
22844 
22845 	DUK_ASSERT_API_ENTRY(thr);
22846 
22847 	/* allow fmt==NULL */
22848 	va_start(ap, fmt);
22849 	ret = duk_push_vsprintf(thr, fmt, ap);
22850 	va_end(ap);
22851 
22852 	return ret;
22853 }
22854 
duk_push_object_helper(duk_hthread * thr,duk_uint_t hobject_flags_and_class,duk_small_int_t prototype_bidx)22855 DUK_INTERNAL duk_hobject *duk_push_object_helper(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
22856 	duk_tval *tv_slot;
22857 	duk_hobject *h;
22858 
22859 	DUK_ASSERT_API_ENTRY(thr);
22860 	DUK_ASSERT(prototype_bidx == -1 ||
22861 	           (prototype_bidx >= 0 && prototype_bidx < DUK_NUM_BUILTINS));
22862 
22863 	DUK__CHECK_SPACE();
22864 
22865 	h = duk_hobject_alloc(thr, hobject_flags_and_class);
22866 	DUK_ASSERT(h != NULL);
22867 
22868 	DUK_DDD(DUK_DDDPRINT("created object with flags: 0x%08lx", (unsigned long) h->hdr.h_flags));
22869 
22870 	tv_slot = thr->valstack_top;
22871 	DUK_TVAL_SET_OBJECT(tv_slot, h);
22872 	DUK_HOBJECT_INCREF(thr, h);  /* no side effects */
22873 	thr->valstack_top++;
22874 
22875 	/* object is now reachable */
22876 
22877 	if (prototype_bidx >= 0) {
22878 		DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, h, thr->builtins[prototype_bidx]);
22879 	} else {
22880 		DUK_ASSERT(prototype_bidx == -1);
22881 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h) == NULL);
22882 	}
22883 
22884 	return h;
22885 }
22886 
duk_push_object_helper_proto(duk_hthread * thr,duk_uint_t hobject_flags_and_class,duk_hobject * proto)22887 DUK_INTERNAL duk_hobject *duk_push_object_helper_proto(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_hobject *proto) {
22888 	duk_hobject *h;
22889 
22890 	DUK_ASSERT_API_ENTRY(thr);
22891 
22892 	h = duk_push_object_helper(thr, hobject_flags_and_class, -1);
22893 	DUK_ASSERT(h != NULL);
22894 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, h, proto);
22895 	return h;
22896 }
22897 
duk_push_object(duk_hthread * thr)22898 DUK_EXTERNAL duk_idx_t duk_push_object(duk_hthread *thr) {
22899 	DUK_ASSERT_API_ENTRY(thr);
22900 
22901 	(void) duk_push_object_helper(thr,
22902 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
22903 	                              DUK_HOBJECT_FLAG_FASTREFS |
22904 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
22905 	                              DUK_BIDX_OBJECT_PROTOTYPE);
22906 	return duk_get_top_index_unsafe(thr);
22907 }
22908 
duk_push_array(duk_hthread * thr)22909 DUK_EXTERNAL duk_idx_t duk_push_array(duk_hthread *thr) {
22910 	duk_uint_t flags;
22911 	duk_harray *obj;
22912 	duk_idx_t ret;
22913 	duk_tval *tv_slot;
22914 
22915 	DUK_ASSERT_API_ENTRY(thr);
22916 
22917 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
22918 	        DUK_HOBJECT_FLAG_FASTREFS |
22919 	        DUK_HOBJECT_FLAG_ARRAY_PART |
22920 	        DUK_HOBJECT_FLAG_EXOTIC_ARRAY |
22921 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAY);
22922 
22923 	obj = duk_harray_alloc(thr, flags);
22924 	DUK_ASSERT(obj != NULL);
22925 
22926 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_ARRAY_PROTOTYPE]);
22927 
22928 	tv_slot = thr->valstack_top;
22929 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22930 	DUK_HOBJECT_INCREF(thr, obj);  /* XXX: could preallocate with refcount = 1 */
22931 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
22932 	thr->valstack_top++;
22933 
22934 	DUK_ASSERT(obj->length == 0);  /* Array .length starts at zero. */
22935 	return ret;
22936 }
22937 
duk_push_bare_array(duk_hthread * thr)22938 DUK_EXTERNAL duk_idx_t duk_push_bare_array(duk_hthread *thr) {
22939 	duk_uint_t flags;
22940 	duk_harray *obj;
22941 	duk_idx_t ret;
22942 	duk_tval *tv_slot;
22943 
22944 	DUK_ASSERT_API_ENTRY(thr);
22945 
22946 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
22947 	        DUK_HOBJECT_FLAG_FASTREFS |
22948 	        DUK_HOBJECT_FLAG_ARRAY_PART |
22949 	        DUK_HOBJECT_FLAG_EXOTIC_ARRAY |
22950 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAY);
22951 
22952 	obj = duk_harray_alloc(thr, flags);
22953 	DUK_ASSERT(obj != NULL);
22954 
22955 	tv_slot = thr->valstack_top;
22956 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22957 	DUK_HOBJECT_INCREF(thr, obj);  /* XXX: could preallocate with refcount = 1 */
22958 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
22959 	thr->valstack_top++;
22960 
22961 	DUK_ASSERT(obj->length == 0);  /* Array .length starts at zero. */
22962 	return ret;
22963 }
22964 
duk_push_harray(duk_hthread * thr)22965 DUK_INTERNAL duk_harray *duk_push_harray(duk_hthread *thr) {
22966 	/* XXX: API call could do this directly, cast to void in API macro. */
22967 	duk_harray *a;
22968 
22969 	DUK_ASSERT_API_ENTRY(thr);
22970 
22971 	(void) duk_push_array(thr);
22972 	DUK_ASSERT(DUK_TVAL_IS_OBJECT(thr->valstack_top - 1));
22973 	a = (duk_harray *) DUK_TVAL_GET_OBJECT(thr->valstack_top - 1);
22974 	DUK_ASSERT(a != NULL);
22975 	return a;
22976 }
22977 
22978 /* Push a duk_harray with preallocated size (.length also set to match size).
22979  * Caller may then populate array part of the duk_harray directly.
22980  */
duk_push_harray_with_size(duk_hthread * thr,duk_uint32_t size)22981 DUK_INTERNAL duk_harray *duk_push_harray_with_size(duk_hthread *thr, duk_uint32_t size) {
22982 	duk_harray *a;
22983 
22984 	DUK_ASSERT_API_ENTRY(thr);
22985 
22986 	a = duk_push_harray(thr);
22987 
22988 	duk_hobject_realloc_props(thr,
22989 	                          (duk_hobject *) a,
22990 	                          0,
22991 	                          size,
22992 	                          0,
22993 	                          0);
22994 	a->length = size;
22995 	return a;
22996 }
22997 
duk_push_harray_with_size_outptr(duk_hthread * thr,duk_uint32_t size)22998 DUK_INTERNAL duk_tval *duk_push_harray_with_size_outptr(duk_hthread *thr, duk_uint32_t size) {
22999 	duk_harray *a;
23000 
23001 	DUK_ASSERT_API_ENTRY(thr);
23002 
23003 	a = duk_push_harray_with_size(thr, size);
23004 	DUK_ASSERT(a != NULL);
23005 	return DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a);
23006 }
23007 
duk_push_thread_raw(duk_hthread * thr,duk_uint_t flags)23008 DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_hthread *thr, duk_uint_t flags) {
23009 	duk_hthread *obj;
23010 	duk_idx_t ret;
23011 	duk_tval *tv_slot;
23012 
23013 	DUK_ASSERT_API_ENTRY(thr);
23014 
23015 	DUK__CHECK_SPACE();
23016 
23017 	obj = duk_hthread_alloc(thr,
23018 	                        DUK_HOBJECT_FLAG_EXTENSIBLE |
23019 	                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
23020 	DUK_ASSERT(obj != NULL);
23021 	obj->state = DUK_HTHREAD_STATE_INACTIVE;
23022 #if defined(DUK_USE_ROM_STRINGS)
23023 	/* Nothing to initialize, strs[] is in ROM. */
23024 #else
23025 #if defined(DUK_USE_HEAPPTR16)
23026 	obj->strs16 = thr->strs16;
23027 #else
23028 	obj->strs = thr->strs;
23029 #endif
23030 #endif
23031 	DUK_DDD(DUK_DDDPRINT("created thread object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
23032 
23033 	/* make the new thread reachable */
23034 	tv_slot = thr->valstack_top;
23035 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
23036 	DUK_HTHREAD_INCREF(thr, obj);
23037 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
23038 	thr->valstack_top++;
23039 
23040 	/* important to do this *after* pushing, to make the thread reachable for gc */
23041 	if (DUK_UNLIKELY(!duk_hthread_init_stacks(thr->heap, obj))) {
23042 		DUK_ERROR_ALLOC_FAILED(thr);
23043 		DUK_WO_NORETURN(return 0;);
23044 	}
23045 
23046 	/* initialize built-ins - either by copying or creating new ones */
23047 	if (flags & DUK_THREAD_NEW_GLOBAL_ENV) {
23048 		duk_hthread_create_builtin_objects(obj);
23049 	} else {
23050 		duk_hthread_copy_builtin_objects(thr, obj);
23051 	}
23052 
23053 	/* default prototype */
23054 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, obj->builtins[DUK_BIDX_THREAD_PROTOTYPE]);
23055 
23056 	/* Initial stack size satisfies the stack slack constraints so there
23057 	 * is no need to require stack here.
23058 	 */
23059 	DUK_ASSERT(DUK_VALSTACK_INITIAL_SIZE >=
23060 	           DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
23061 
23062 	return ret;
23063 }
23064 
duk_push_hcompfunc(duk_hthread * thr)23065 DUK_INTERNAL duk_hcompfunc *duk_push_hcompfunc(duk_hthread *thr) {
23066 	duk_hcompfunc *obj;
23067 	duk_tval *tv_slot;
23068 
23069 	DUK_ASSERT_API_ENTRY(thr);
23070 
23071 	DUK__CHECK_SPACE();
23072 
23073 	/* Template functions are not strictly constructable (they don't
23074 	 * have a "prototype" property for instance), so leave the
23075 	 * DUK_HOBJECT_FLAG_CONSRUCTABLE flag cleared here.
23076 	 */
23077 
23078 	obj = duk_hcompfunc_alloc(thr,
23079 	                          DUK_HOBJECT_FLAG_EXTENSIBLE |
23080 	                          DUK_HOBJECT_FLAG_CALLABLE |
23081 	                          DUK_HOBJECT_FLAG_COMPFUNC |
23082 	                          DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));
23083 	if (DUK_UNLIKELY(obj == NULL)) {
23084 		DUK_ERROR_ALLOC_FAILED(thr);
23085 		DUK_WO_NORETURN(return NULL;);
23086 	}
23087 
23088 	DUK_DDD(DUK_DDDPRINT("created compiled function object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
23089 
23090 	tv_slot = thr->valstack_top;
23091 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
23092 	DUK_HOBJECT_INCREF(thr, obj);
23093 	thr->valstack_top++;
23094 
23095 	/* default prototype */
23096 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) obj) == NULL);
23097 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
23098 
23099 	return obj;
23100 }
23101 
duk_push_hboundfunc(duk_hthread * thr)23102 DUK_INTERNAL duk_hboundfunc *duk_push_hboundfunc(duk_hthread *thr) {
23103 	duk_hboundfunc *obj;
23104 	duk_tval *tv_slot;
23105 
23106 	DUK_ASSERT_API_ENTRY(thr);
23107 
23108 	DUK__CHECK_SPACE();
23109 	obj = duk_hboundfunc_alloc(thr->heap,
23110 	                           DUK_HOBJECT_FLAG_EXTENSIBLE |
23111 	                           DUK_HOBJECT_FLAG_BOUNDFUNC |
23112 	                           DUK_HOBJECT_FLAG_CONSTRUCTABLE |
23113 	                           DUK_HOBJECT_FLAG_CALLABLE |
23114 	                           DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));
23115 	if (!obj) {
23116 		DUK_ERROR_ALLOC_FAILED(thr);
23117 		DUK_WO_NORETURN(return NULL;);
23118 	}
23119 
23120 	tv_slot = thr->valstack_top++;
23121 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
23122 	DUK_HOBJECT_INCREF(thr, obj);
23123 
23124 	/* Prototype is left as NULL because the caller always sets it (and
23125 	 * it depends on the target function).
23126 	 */
23127 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) obj) == NULL);
23128 
23129 	return obj;
23130 }
23131 
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)23132 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) {
23133 	duk_hnatfunc *obj;
23134 	duk_idx_t ret;
23135 	duk_tval *tv_slot;
23136 	duk_int16_t func_nargs;
23137 
23138 	DUK_CTX_ASSERT_VALID(thr);
23139 
23140 	DUK__CHECK_SPACE();
23141 
23142 	if (DUK_UNLIKELY(func == NULL)) {
23143 		goto api_error;
23144 	}
23145 	if (nargs >= 0 && nargs < DUK_HNATFUNC_NARGS_MAX) {
23146 		func_nargs = (duk_int16_t) nargs;
23147 	} else if (nargs == DUK_VARARGS) {
23148 		func_nargs = DUK_HNATFUNC_NARGS_VARARGS;
23149 	} else {
23150 		goto api_error;
23151 	}
23152 
23153 	obj = duk_hnatfunc_alloc(thr, flags);
23154 	DUK_ASSERT(obj != NULL);
23155 
23156 	obj->func = func;
23157 	obj->nargs = func_nargs;
23158 
23159 	DUK_DDD(DUK_DDDPRINT("created native function object with flags: 0x%08lx, nargs=%ld",
23160 	                     (unsigned long) obj->obj.hdr.h_flags, (long) obj->nargs));
23161 
23162 	tv_slot = thr->valstack_top;
23163 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
23164 	DUK_HOBJECT_INCREF(thr, obj);
23165 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
23166 	thr->valstack_top++;
23167 
23168 	DUK_ASSERT_BIDX_VALID(proto_bidx);
23169 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[proto_bidx]);
23170 	return ret;
23171 
23172  api_error:
23173 	DUK_ERROR_TYPE_INVALID_ARGS(thr);
23174 	DUK_WO_NORETURN(return 0;);
23175 }
23176 
duk_push_c_function(duk_hthread * thr,duk_c_function func,duk_int_t nargs)23177 DUK_EXTERNAL duk_idx_t duk_push_c_function(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {
23178 	duk_uint_t flags;
23179 
23180 	DUK_ASSERT_API_ENTRY(thr);
23181 
23182 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
23183 	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
23184 	        DUK_HOBJECT_FLAG_CALLABLE |
23185 	        DUK_HOBJECT_FLAG_FASTREFS |
23186 	        DUK_HOBJECT_FLAG_NATFUNC |
23187 	        DUK_HOBJECT_FLAG_NEWENV |
23188 	        DUK_HOBJECT_FLAG_STRICT |
23189 	        DUK_HOBJECT_FLAG_NOTAIL |
23190 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
23191 
23192 	/* Default prototype is a Duktape specific %NativeFunctionPrototype%
23193 	 * which provides .length and .name getters.
23194 	 */
23195 	return duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE);
23196 }
23197 
duk_push_c_function_builtin(duk_hthread * thr,duk_c_function func,duk_int_t nargs)23198 DUK_INTERNAL void duk_push_c_function_builtin(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {
23199 	duk_uint_t flags;
23200 
23201 	DUK_ASSERT_API_ENTRY(thr);
23202 
23203 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
23204 	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
23205 	        DUK_HOBJECT_FLAG_CALLABLE |
23206 	        DUK_HOBJECT_FLAG_FASTREFS |
23207 	        DUK_HOBJECT_FLAG_NATFUNC |
23208 	        DUK_HOBJECT_FLAG_NEWENV |
23209 	        DUK_HOBJECT_FLAG_STRICT |
23210 	        DUK_HOBJECT_FLAG_NOTAIL |
23211 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
23212 
23213 	/* Must use Function.prototype for standard built-in functions. */
23214 	(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_FUNCTION_PROTOTYPE);
23215 }
23216 
duk_push_c_function_builtin_noconstruct(duk_hthread * thr,duk_c_function func,duk_int_t nargs)23217 DUK_INTERNAL void duk_push_c_function_builtin_noconstruct(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {
23218 	duk_uint_t flags;
23219 
23220 	DUK_ASSERT_API_ENTRY(thr);
23221 
23222 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
23223 	        DUK_HOBJECT_FLAG_CALLABLE |
23224 	        DUK_HOBJECT_FLAG_FASTREFS |
23225 	        DUK_HOBJECT_FLAG_NATFUNC |
23226 	        DUK_HOBJECT_FLAG_NEWENV |
23227 	        DUK_HOBJECT_FLAG_STRICT |
23228 	        DUK_HOBJECT_FLAG_NOTAIL |
23229 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
23230 
23231 	/* Must use Function.prototype for standard built-in functions. */
23232 	(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_FUNCTION_PROTOTYPE);
23233 }
23234 
duk_push_c_lightfunc(duk_hthread * thr,duk_c_function func,duk_idx_t nargs,duk_idx_t length,duk_int_t magic)23235 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) {
23236 	duk_small_uint_t lf_flags;
23237 	duk_tval *tv_slot;
23238 
23239 	DUK_ASSERT_API_ENTRY(thr);
23240 
23241 	DUK__CHECK_SPACE();
23242 
23243 	if (nargs >= DUK_LFUNC_NARGS_MIN && nargs <= DUK_LFUNC_NARGS_MAX) {
23244 		/* as is */
23245 	} else if (nargs == DUK_VARARGS) {
23246 		nargs = DUK_LFUNC_NARGS_VARARGS;
23247 	} else {
23248 		goto api_error;
23249 	}
23250 	if (DUK_UNLIKELY(!(length >= DUK_LFUNC_LENGTH_MIN && length <= DUK_LFUNC_LENGTH_MAX))) {
23251 		goto api_error;
23252 	}
23253 	if (DUK_UNLIKELY(!(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX))) {
23254 		goto api_error;
23255 	}
23256 
23257 	lf_flags = DUK_LFUNC_FLAGS_PACK((duk_small_int_t) magic, (duk_small_uint_t) length, (duk_small_uint_t) nargs);
23258 	tv_slot = thr->valstack_top++;
23259 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_slot));
23260 	DUK_TVAL_SET_LIGHTFUNC(tv_slot, func, lf_flags);
23261 	DUK_ASSERT(tv_slot >= thr->valstack_bottom);
23262 	return (duk_idx_t) (tv_slot - thr->valstack_bottom);
23263 
23264  api_error:
23265 	DUK_ERROR_TYPE_INVALID_ARGS(thr);
23266 	DUK_WO_NORETURN(return 0;);
23267 }
23268 
23269 #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)23270 DUK_INTERNAL duk_hbufobj *duk_push_bufobj_raw(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
23271 	duk_hbufobj *obj;
23272 	duk_tval *tv_slot;
23273 
23274 	DUK_ASSERT_API_ENTRY(thr);
23275 	DUK_ASSERT(prototype_bidx >= 0);
23276 
23277 	DUK__CHECK_SPACE();
23278 
23279 	obj = duk_hbufobj_alloc(thr, hobject_flags_and_class);
23280 	DUK_ASSERT(obj != NULL);
23281 
23282 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[prototype_bidx]);
23283 	DUK_HBUFOBJ_ASSERT_VALID(obj);
23284 
23285 	tv_slot = thr->valstack_top;
23286 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
23287 	DUK_HOBJECT_INCREF(thr, obj);
23288 	thr->valstack_top++;
23289 
23290 	return obj;
23291 }
23292 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
23293 
23294 /* XXX: There's quite a bit of overlap with buffer creation handling in
23295  * duk_bi_buffer.c.  Look for overlap and refactor.
23296  */
23297 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23298 #define DUK__PACK_ARGS(classnum,protobidx,elemtype,elemshift,istypedarray) \
23299 	(((classnum) << 24) | ((protobidx) << 16) | ((elemtype) << 8) | ((elemshift) << 4) | (istypedarray))
23300 
23301 static const duk_uint32_t duk__bufobj_flags_lookup[] = {
23302 	/* Node.js Buffers are Uint8Array instances which inherit from Buffer.prototype. */
23303 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_ARRAYBUFFER,       DUK_BIDX_ARRAYBUFFER_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT8,        0, 0),  /* DUK_BUFOBJ_ARRAYBUFFER */
23304 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY,        DUK_BIDX_NODEJS_BUFFER_PROTOTYPE,     DUK_HBUFOBJ_ELEM_UINT8,        0, 1),  /* DUK_BUFOBJ_NODEJS_BUFFER */
23305 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_DATAVIEW,          DUK_BIDX_DATAVIEW_PROTOTYPE,          DUK_HBUFOBJ_ELEM_UINT8,        0, 0),  /* DUK_BUFOBJ_DATAVIEW */
23306 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT8ARRAY,         DUK_BIDX_INT8ARRAY_PROTOTYPE,         DUK_HBUFOBJ_ELEM_INT8,         0, 1),  /* DUK_BUFOBJ_INT8ARRAY */
23307 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY,        DUK_BIDX_UINT8ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_UINT8,        0, 1),  /* DUK_BUFOBJ_UINT8ARRAY */
23308 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY, DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT8CLAMPED, 0, 1),  /* DUK_BUFOBJ_UINT8CLAMPEDARRAY */
23309 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT16ARRAY,        DUK_BIDX_INT16ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_INT16,        1, 1),  /* DUK_BUFOBJ_INT16ARRAY */
23310 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT16ARRAY,       DUK_BIDX_UINT16ARRAY_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT16,       1, 1),  /* DUK_BUFOBJ_UINT16ARRAY */
23311 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT32ARRAY,        DUK_BIDX_INT32ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_INT32,        2, 1),  /* DUK_BUFOBJ_INT32ARRAY */
23312 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT32ARRAY,       DUK_BIDX_UINT32ARRAY_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT32,       2, 1),  /* DUK_BUFOBJ_UINT32ARRAY */
23313 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT32ARRAY,      DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,      DUK_HBUFOBJ_ELEM_FLOAT32,      2, 1),  /* DUK_BUFOBJ_FLOAT32ARRAY */
23314 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT64ARRAY,      DUK_BIDX_FLOAT64ARRAY_PROTOTYPE,      DUK_HBUFOBJ_ELEM_FLOAT64,      3, 1)   /* DUK_BUFOBJ_FLOAT64ARRAY */
23315 };
23316 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
23317 
23318 #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)23319 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) {
23320 	duk_hbufobj *h_bufobj;
23321 	duk_hbuffer *h_val;
23322 	duk_hobject *h_arraybuf;
23323 	duk_uint32_t tmp;
23324 	duk_uint_t classnum;
23325 	duk_uint_t protobidx;
23326 	duk_uint_t lookupidx;
23327 	duk_uint_t uint_offset, uint_length, uint_added;
23328 
23329 	DUK_ASSERT_API_ENTRY(thr);
23330 
23331 	/* The underlying types for offset/length in duk_hbufobj is
23332 	 * duk_uint_t; make sure argument values fit.
23333 	 */
23334 	uint_offset = (duk_uint_t) byte_offset;
23335 	uint_length = (duk_uint_t) byte_length;
23336 	if (sizeof(duk_size_t) != sizeof(duk_uint_t)) {
23337 		if (DUK_UNLIKELY((duk_size_t) uint_offset != byte_offset || (duk_size_t) uint_length != byte_length)) {
23338 			goto range_error;
23339 		}
23340 	}
23341 
23342 	DUK_ASSERT_DISABLE(flags >= 0);  /* flags is unsigned */
23343 	lookupidx = flags;
23344 	if (DUK_UNLIKELY(lookupidx >= sizeof(duk__bufobj_flags_lookup) / sizeof(duk_uint32_t))) {
23345 		goto arg_error;
23346 	}
23347 	tmp = duk__bufobj_flags_lookup[lookupidx];
23348 	classnum = tmp >> 24;
23349 	protobidx = (tmp >> 16) & 0xff;
23350 
23351 	h_arraybuf = duk_get_hobject(thr, idx_buffer);
23352 	if (h_arraybuf != NULL &&  /* argument is an object */
23353 	    flags != DUK_BUFOBJ_ARRAYBUFFER &&  /* creating a view */
23354 	    DUK_HOBJECT_GET_CLASS_NUMBER(h_arraybuf) == DUK_HOBJECT_CLASS_ARRAYBUFFER  /* argument is ArrayBuffer */) {
23355 		duk_uint_t tmp_offset;
23356 
23357 		DUK_HBUFOBJ_ASSERT_VALID((duk_hbufobj *) h_arraybuf);
23358 		h_val = ((duk_hbufobj *) h_arraybuf)->buf;
23359 		if (DUK_UNLIKELY(h_val == NULL)) {
23360 			goto arg_error;
23361 		}
23362 
23363 		tmp_offset = uint_offset + ((duk_hbufobj *) h_arraybuf)->offset;
23364 		if (DUK_UNLIKELY(tmp_offset < uint_offset)) {
23365 			goto range_error;
23366 		}
23367 		uint_offset = tmp_offset;
23368 
23369 		/* Note intentional difference to new TypedArray(): we allow
23370 		 * caller to create an uncovered typed array (which is memory
23371 		 * safe); new TypedArray() rejects it.
23372 		 */
23373 	} else {
23374 		/* Handle unexpected object arguments here too, for nice error
23375 		 * messages.
23376 		 */
23377 		h_arraybuf = NULL;
23378 		h_val = duk_require_hbuffer(thr, idx_buffer);
23379 	}
23380 
23381 	/* Wrap check for offset+length. */
23382 	uint_added = uint_offset + uint_length;
23383 	if (DUK_UNLIKELY(uint_added < uint_offset)) {
23384 		goto range_error;
23385 	}
23386 	DUK_ASSERT(uint_added >= uint_offset && uint_added >= uint_length);
23387 
23388 	DUK_ASSERT(h_val != NULL);
23389 
23390 	h_bufobj = duk_push_bufobj_raw(thr,
23391 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
23392 	                               DUK_HOBJECT_FLAG_BUFOBJ |
23393 	                               DUK_HOBJECT_CLASS_AS_FLAGS(classnum),
23394 	                               (duk_small_int_t) protobidx);
23395 	DUK_ASSERT(h_bufobj != NULL);
23396 
23397 	h_bufobj->buf = h_val;
23398 	DUK_HBUFFER_INCREF(thr, h_val);
23399 	h_bufobj->buf_prop = h_arraybuf;
23400 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, h_arraybuf);
23401 	h_bufobj->offset = uint_offset;
23402 	h_bufobj->length = uint_length;
23403 	h_bufobj->shift = (tmp >> 4) & 0x0f;
23404 	h_bufobj->elem_type = (tmp >> 8) & 0xff;
23405 	h_bufobj->is_typedarray = tmp & 0x0f;
23406 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
23407 
23408 	/* TypedArray views need an automatic ArrayBuffer which must be
23409 	 * provided as .buffer property of the view.  The ArrayBuffer is
23410 	 * referenced via duk_hbufobj->buf_prop and an inherited .buffer
23411 	 * accessor returns it.  The ArrayBuffer is created lazily on first
23412 	 * access if necessary so we don't need to do anything more here.
23413 	 */
23414 	return;
23415 
23416  range_error:
23417 	DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARGS);
23418 	DUK_WO_NORETURN(return;);
23419 
23420  arg_error:
23421 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_ARGS);
23422 	DUK_WO_NORETURN(return;);
23423 }
23424 #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)23425 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) {
23426 	DUK_ASSERT_API_ENTRY(thr);
23427 	DUK_UNREF(idx_buffer);
23428 	DUK_UNREF(byte_offset);
23429 	DUK_UNREF(byte_length);
23430 	DUK_UNREF(flags);
23431 	DUK_ERROR_UNSUPPORTED(thr);
23432 	DUK_WO_NORETURN(return;);
23433 }
23434 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
23435 
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)23436 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) {
23437 	duk_hobject *proto;
23438 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
23439 	duk_small_uint_t augment_flags;
23440 #endif
23441 
23442 	DUK_ASSERT_API_ENTRY(thr);
23443 	DUK_ASSERT(thr != NULL);
23444 	DUK_UNREF(filename);
23445 	DUK_UNREF(line);
23446 
23447 	/* Error code also packs a tracedata related flag. */
23448 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
23449 	augment_flags = 0;
23450 	if (err_code & DUK_ERRCODE_FLAG_NOBLAME_FILELINE) {
23451 		augment_flags = DUK_AUGMENT_FLAG_NOBLAME_FILELINE;
23452 	}
23453 #endif
23454 	err_code = err_code & (~DUK_ERRCODE_FLAG_NOBLAME_FILELINE);
23455 
23456 	/* error gets its 'name' from the prototype */
23457 	proto = duk_error_prototype_from_code(thr, err_code);
23458 	(void) duk_push_object_helper_proto(thr,
23459 	                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
23460 	                                    DUK_HOBJECT_FLAG_FASTREFS |
23461 	                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR),
23462 	                                    proto);
23463 
23464 	/* ... and its 'message' from an instance property */
23465 	if (fmt) {
23466 		duk_push_vsprintf(thr, fmt, ap);
23467 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
23468 	} else {
23469 		/* If no explicit message given, put error code into message field
23470 		 * (as a number).  This is not fully in keeping with the ECMAScript
23471 		 * error model because messages are supposed to be strings (Error
23472 		 * constructors use ToString() on their argument).  However, it's
23473 		 * probably more useful than having a separate 'code' property.
23474 		 */
23475 		duk_push_int(thr, err_code);
23476 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
23477 	}
23478 
23479 	/* XXX: .code = err_code disabled, not sure if useful */
23480 
23481 	/* Creation time error augmentation */
23482 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
23483 	/* filename may be NULL in which case file/line is not recorded */
23484 	duk_err_augment_error_create(thr, thr, filename, line, augment_flags);  /* may throw an error */
23485 #endif
23486 
23487 	return duk_get_top_index_unsafe(thr);
23488 }
23489 
duk_push_error_object_raw(duk_hthread * thr,duk_errcode_t err_code,const char * filename,duk_int_t line,const char * fmt,...)23490 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, ...) {
23491 	va_list ap;
23492 	duk_idx_t ret;
23493 
23494 	DUK_ASSERT_API_ENTRY(thr);
23495 
23496 	va_start(ap, fmt);
23497 	ret = duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
23498 	va_end(ap);
23499 	return ret;
23500 }
23501 
23502 #if !defined(DUK_USE_VARIADIC_MACROS)
duk_push_error_object_stash(duk_hthread * thr,duk_errcode_t err_code,const char * fmt,...)23503 DUK_EXTERNAL duk_idx_t duk_push_error_object_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, ...) {
23504 	const char *filename = duk_api_global_filename;
23505 	duk_int_t line = duk_api_global_line;
23506 	va_list ap;
23507 	duk_idx_t ret;
23508 
23509 	DUK_ASSERT_API_ENTRY(thr);
23510 
23511 	duk_api_global_filename = NULL;
23512 	duk_api_global_line = 0;
23513 	va_start(ap, fmt);
23514 	ret = duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
23515 	va_end(ap);
23516 	return ret;
23517 }
23518 #endif  /* DUK_USE_VARIADIC_MACROS */
23519 
duk_push_buffer_raw(duk_hthread * thr,duk_size_t size,duk_small_uint_t flags)23520 DUK_EXTERNAL void *duk_push_buffer_raw(duk_hthread *thr, duk_size_t size, duk_small_uint_t flags) {
23521 	duk_tval *tv_slot;
23522 	duk_hbuffer *h;
23523 	void *buf_data;
23524 
23525 	DUK_ASSERT_API_ENTRY(thr);
23526 
23527 	DUK__CHECK_SPACE();
23528 
23529 	/* Check for maximum buffer length. */
23530 	if (DUK_UNLIKELY(size > DUK_HBUFFER_MAX_BYTELEN)) {
23531 		DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);
23532 		DUK_WO_NORETURN(return NULL;);
23533 	}
23534 
23535 	h = duk_hbuffer_alloc(thr->heap, size, flags, &buf_data);
23536 	if (DUK_UNLIKELY(h == NULL)) {
23537 		DUK_ERROR_ALLOC_FAILED(thr);
23538 		DUK_WO_NORETURN(return NULL;);
23539 	}
23540 
23541 	tv_slot = thr->valstack_top;
23542 	DUK_TVAL_SET_BUFFER(tv_slot, h);
23543 	DUK_HBUFFER_INCREF(thr, h);
23544 	thr->valstack_top++;
23545 
23546 	return (void *) buf_data;
23547 }
23548 
duk_push_fixed_buffer_nozero(duk_hthread * thr,duk_size_t len)23549 DUK_INTERNAL void *duk_push_fixed_buffer_nozero(duk_hthread *thr, duk_size_t len) {
23550 	DUK_ASSERT_API_ENTRY(thr);
23551 	return duk_push_buffer_raw(thr, len, DUK_BUF_FLAG_NOZERO);
23552 }
23553 
duk_push_fixed_buffer_zero(duk_hthread * thr,duk_size_t len)23554 DUK_INTERNAL void *duk_push_fixed_buffer_zero(duk_hthread *thr, duk_size_t len) {
23555 	void *ptr;
23556 
23557 	DUK_ASSERT_API_ENTRY(thr);
23558 
23559 	ptr = duk_push_buffer_raw(thr, len, 0);
23560 	DUK_ASSERT(ptr != NULL);
23561 #if !defined(DUK_USE_ZERO_BUFFER_DATA)
23562 	/* ES2015 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA
23563 	 * is not set.
23564 	 */
23565 	duk_memzero((void *) ptr, (size_t) len);
23566 #endif
23567 	return ptr;
23568 }
23569 
23570 #if defined(DUK_USE_ES6_PROXY)
duk_push_proxy(duk_hthread * thr,duk_uint_t proxy_flags)23571 DUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags) {
23572 	duk_hobject *h_target;
23573 	duk_hobject *h_handler;
23574 	duk_hproxy *h_proxy;
23575 	duk_tval *tv_slot;
23576 	duk_uint_t flags;
23577 
23578 	DUK_ASSERT_API_ENTRY(thr);
23579 	DUK_UNREF(proxy_flags);
23580 
23581 	/* DUK__CHECK_SPACE() unnecessary because the Proxy is written to
23582 	 * value stack in-place.
23583 	 */
23584 #if 0
23585 	DUK__CHECK_SPACE();
23586 #endif
23587 
23588 	/* Reject a proxy object as the target because it would need
23589 	 * special handling in property lookups.  (ES2015 has no such
23590 	 * restriction.)
23591 	 */
23592 	h_target = duk_require_hobject_promote_mask(thr, -2, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
23593 	DUK_ASSERT(h_target != NULL);
23594 	if (DUK_HOBJECT_IS_PROXY(h_target)) {
23595 		goto fail_args;
23596 	}
23597 
23598 	/* Reject a proxy object as the handler because it would cause
23599 	 * potentially unbounded recursion.  (ES2015 has no such
23600 	 * restriction.)
23601 	 *
23602 	 * There's little practical reason to use a lightfunc or a plain
23603 	 * buffer as the handler table: one could only provide traps via
23604 	 * their prototype objects (Function.prototype and ArrayBuffer.prototype).
23605 	 * Even so, as lightfuncs and plain buffers mimic their object
23606 	 * counterparts, they're promoted and accepted here.
23607 	 */
23608 	h_handler = duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
23609 	DUK_ASSERT(h_handler != NULL);
23610 	if (DUK_HOBJECT_IS_PROXY(h_handler)) {
23611 		goto fail_args;
23612 	}
23613 
23614 	/* XXX: Proxy object currently has no prototype, so ToPrimitive()
23615 	 * coercion fails which is a bit confusing.
23616 	 */
23617 
23618 	/* CALLABLE and CONSTRUCTABLE flags are copied from the (initial)
23619 	 * target, see ES2015 Sections 9.5.15 and 9.5.13.
23620 	 */
23621 	flags = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h_target) &
23622 	        (DUK_HOBJECT_FLAG_CALLABLE | DUK_HOBJECT_FLAG_CONSTRUCTABLE);
23623 	flags |= DUK_HOBJECT_FLAG_EXTENSIBLE |
23624 	         DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ;
23625 	if (flags & DUK_HOBJECT_FLAG_CALLABLE) {
23626 		flags |= DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION) |
23627 		         DUK_HOBJECT_FLAG_SPECIAL_CALL;
23628 	} else {
23629 		flags |= DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT);
23630 	}
23631 
23632 	h_proxy = duk_hproxy_alloc(thr, flags);
23633 	DUK_ASSERT(h_proxy != NULL);
23634 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_proxy) == NULL);
23635 
23636 	/* Initialize Proxy target and handler references; avoid INCREF
23637 	 * by stealing the value stack refcounts via direct value stack
23638 	 * manipulation.  INCREF is needed for the Proxy itself however.
23639 	 */
23640 	DUK_ASSERT(h_target != NULL);
23641 	h_proxy->target = h_target;
23642 	DUK_ASSERT(h_handler != NULL);
23643 	h_proxy->handler = h_handler;
23644 	DUK_HPROXY_ASSERT_VALID(h_proxy);
23645 
23646 	DUK_ASSERT(duk_get_hobject(thr, -2) == h_target);
23647 	DUK_ASSERT(duk_get_hobject(thr, -1) == h_handler);
23648 	tv_slot = thr->valstack_top - 2;
23649 	DUK_ASSERT(tv_slot >= thr->valstack_bottom);
23650 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) h_proxy);
23651 	DUK_HOBJECT_INCREF(thr, (duk_hobject *) h_proxy);
23652 	tv_slot++;
23653 	DUK_TVAL_SET_UNDEFINED(tv_slot);  /* [ ... target handler ] -> [ ... proxy undefined ] */
23654 	thr->valstack_top = tv_slot;      /* -> [ ... proxy ] */
23655 
23656 	DUK_DD(DUK_DDPRINT("created Proxy: %!iT", duk_get_tval(thr, -1)));
23657 
23658 	return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom - 1);
23659 
23660  fail_args:
23661 	DUK_ERROR_TYPE_INVALID_ARGS(thr);
23662 	DUK_WO_NORETURN(return 0;);
23663 }
23664 #else  /* DUK_USE_ES6_PROXY */
duk_push_proxy(duk_hthread * thr,duk_uint_t proxy_flags)23665 DUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags) {
23666 	DUK_ASSERT_API_ENTRY(thr);
23667 	DUK_UNREF(proxy_flags);
23668 	DUK_ERROR_UNSUPPORTED(thr);
23669 	DUK_WO_NORETURN(return 0;);
23670 }
23671 #endif  /* DUK_USE_ES6_PROXY */
23672 
23673 #if defined(DUK_USE_ASSERTIONS)
duk__validate_push_heapptr(duk_hthread * thr,void * ptr)23674 DUK_LOCAL void duk__validate_push_heapptr(duk_hthread *thr, void *ptr) {
23675 	duk_heaphdr *h;
23676 	duk_heaphdr *curr;
23677 	duk_bool_t found = 0;
23678 
23679 	h = (duk_heaphdr *) ptr;
23680 	if (h == NULL) {
23681 		/* Allowed. */
23682 		return;
23683 	}
23684 	DUK_ASSERT(h != NULL);
23685 	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
23686 
23687 	/* One particular problem case is where an object has been
23688 	 * queued for finalization but the finalizer hasn't yet been
23689 	 * executed.
23690 	 *
23691 	 * Corner case: we're running in a finalizer for object X, and
23692 	 * user code calls duk_push_heapptr() for X itself.  In this
23693 	 * case X will be in finalize_list, and we can detect the case
23694 	 * by seeing that X's FINALIZED flag is set (which is done before
23695 	 * the finalizer starts executing).
23696 	 */
23697 #if defined(DUK_USE_FINALIZER_SUPPORT)
23698 	for (curr = thr->heap->finalize_list;
23699 	     curr != NULL;
23700 	     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
23701 		/* FINALIZABLE is set for all objects on finalize_list
23702 		 * except for an object being finalized right now.  So
23703 		 * can't assert here.
23704 		 */
23705 #if 0
23706 		DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(curr));
23707 #endif
23708 
23709 		if (curr == h) {
23710 			if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h)) {
23711 				/* Object is currently being finalized. */
23712 				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
23713 				found = 1;
23714 			} else {
23715 				/* Not being finalized but on finalize_list,
23716 				 * allowed since Duktape 2.1.
23717 				 */
23718 				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
23719 				found = 1;
23720 			}
23721 		}
23722 	}
23723 #endif  /* DUK_USE_FINALIZER_SUPPORT */
23724 
23725 #if defined(DUK_USE_REFERENCE_COUNTING)
23726 	/* Because refzero_list is now processed to completion inline with
23727 	 * no side effects, it's always empty here.
23728 	 */
23729 	DUK_ASSERT(thr->heap->refzero_list == NULL);
23730 #endif
23731 
23732 	/* If not present in finalize_list (or refzero_list), it
23733 	 * must be either in heap_allocated or the string table.
23734 	 */
23735 	if (DUK_HEAPHDR_IS_STRING(h)) {
23736 		duk_uint32_t i;
23737 		duk_hstring *str;
23738 		duk_heap *heap = thr->heap;
23739 
23740 		DUK_ASSERT(found == 0);
23741 		for (i = 0; i < heap->st_size; i++) {
23742 #if defined(DUK_USE_STRTAB_PTRCOMP)
23743 			str = DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, heap->strtable16[i]);
23744 #else
23745 			str = heap->strtable[i];
23746 #endif
23747 			while (str != NULL) {
23748 				if (str == (duk_hstring *) h) {
23749 					DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
23750 					found = 1;
23751 					break;
23752 				}
23753 				str = str->hdr.h_next;
23754 			}
23755 		}
23756 		DUK_ASSERT(found != 0);
23757 	} else {
23758 		for (curr = thr->heap->heap_allocated;
23759 		     curr != NULL;
23760 		     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
23761 			if (curr == h) {
23762 				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
23763 				found = 1;
23764 			}
23765 		}
23766 		DUK_ASSERT(found != 0);
23767 	}
23768 }
23769 #endif  /* DUK_USE_ASSERTIONS */
23770 
duk_push_heapptr(duk_hthread * thr,void * ptr)23771 DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_hthread *thr, void *ptr) {
23772 	duk_idx_t ret;
23773 	duk_tval *tv;
23774 
23775 	DUK_ASSERT_API_ENTRY(thr);
23776 
23777 	/* Reviving an object using a heap pointer is a dangerous API
23778 	 * operation: if the application doesn't guarantee that the
23779 	 * pointer target is always reachable, difficult-to-diagnose
23780 	 * problems may ensue.  Try to validate the 'ptr' argument to
23781 	 * the extent possible.
23782 	 */
23783 
23784 #if defined(DUK_USE_ASSERTIONS)
23785 	duk__validate_push_heapptr(thr, ptr);
23786 #endif
23787 
23788 	DUK__CHECK_SPACE();
23789 
23790 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
23791 	tv = thr->valstack_top++;
23792 
23793 	if (ptr == NULL) {
23794 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
23795 		return ret;
23796 	}
23797 
23798 	DUK_HEAPHDR_ASSERT_VALID((duk_heaphdr *) ptr);
23799 
23800 	/* If the argument is on finalize_list it has technically been
23801 	 * unreachable before duk_push_heapptr() but it's still safe to
23802 	 * push it.  Starting from Duktape 2.1 allow application code to
23803 	 * do so.  There are two main cases:
23804 	 *
23805 	 *   (1) The object is on the finalize_list and we're called by
23806 	 *       the finalizer for the object being finalized.  In this
23807 	 *       case do nothing: finalize_list handling will deal with
23808 	 *       the object queueing.  This is detected by the object not
23809 	 *       having a FINALIZABLE flag despite being on the finalize_list;
23810 	 *       the flag is cleared for the object being finalized only.
23811 	 *
23812 	 *   (2) The object is on the finalize_list but is not currently
23813 	 *       being processed.  In this case the object can be queued
23814 	 *       back to heap_allocated with a few flags cleared, in effect
23815 	 *       cancelling the finalizer.
23816 	 */
23817 	if (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) ptr))) {
23818 		duk_heaphdr *curr;
23819 
23820 		DUK_D(DUK_DPRINT("duk_push_heapptr() with a pointer on finalize_list, autorescue"));
23821 
23822 		curr = (duk_heaphdr *) ptr;
23823 		DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
23824 
23825 		/* Because FINALIZED is set prior to finalizer call, it will
23826 		 * be set for the object being currently finalized, but not
23827 		 * for other objects on finalize_list.
23828 		 */
23829 		DUK_HEAPHDR_CLEAR_FINALIZED(curr);
23830 
23831 		/* Dequeue object from finalize_list and queue it back to
23832 		 * heap_allocated.
23833 		 */
23834 #if defined(DUK_USE_REFERENCE_COUNTING)
23835 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);  /* Preincremented on finalize_list insert. */
23836 		DUK_HEAPHDR_PREDEC_REFCOUNT(curr);
23837 #endif
23838 		DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(thr->heap, curr);
23839 		DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(thr->heap, curr);
23840 
23841 		/* Continue with the rest. */
23842 	}
23843 
23844 	switch (DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr)) {
23845 	case DUK_HTYPE_STRING:
23846 		DUK_TVAL_SET_STRING(tv, (duk_hstring *) ptr);
23847 		break;
23848 	case DUK_HTYPE_OBJECT:
23849 		DUK_TVAL_SET_OBJECT(tv, (duk_hobject *) ptr);
23850 		break;
23851 	default:
23852 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr) == DUK_HTYPE_BUFFER);
23853 		DUK_TVAL_SET_BUFFER(tv, (duk_hbuffer *) ptr);
23854 		break;
23855 	}
23856 
23857 	DUK_HEAPHDR_INCREF(thr, (duk_heaphdr *) ptr);
23858 
23859 	return ret;
23860 }
23861 
23862 /* Push object with no prototype, i.e. a "bare" object. */
duk_push_bare_object(duk_hthread * thr)23863 DUK_EXTERNAL duk_idx_t duk_push_bare_object(duk_hthread *thr) {
23864 	DUK_ASSERT_API_ENTRY(thr);
23865 
23866 	(void) duk_push_object_helper(thr,
23867 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
23868 	                              DUK_HOBJECT_FLAG_FASTREFS |
23869 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
23870 	                              -1);  /* no prototype */
23871 	return duk_get_top_index_unsafe(thr);
23872 }
23873 
duk_push_hstring(duk_hthread * thr,duk_hstring * h)23874 DUK_INTERNAL void duk_push_hstring(duk_hthread *thr, duk_hstring *h) {
23875 	duk_tval tv;
23876 
23877 	DUK_ASSERT_API_ENTRY(thr);
23878 	DUK_ASSERT(h != NULL);
23879 
23880 	DUK_TVAL_SET_STRING(&tv, h);
23881 	duk_push_tval(thr, &tv);
23882 }
23883 
duk_push_hstring_stridx(duk_hthread * thr,duk_small_uint_t stridx)23884 DUK_INTERNAL void duk_push_hstring_stridx(duk_hthread *thr, duk_small_uint_t stridx) {
23885 	DUK_ASSERT_API_ENTRY(thr);
23886 	DUK_ASSERT_STRIDX_VALID(stridx);
23887 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
23888 }
23889 
duk_push_hstring_empty(duk_hthread * thr)23890 DUK_INTERNAL void duk_push_hstring_empty(duk_hthread *thr) {
23891 	DUK_ASSERT_API_ENTRY(thr);
23892 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, DUK_STRIDX_EMPTY_STRING));
23893 }
23894 
duk_push_hobject(duk_hthread * thr,duk_hobject * h)23895 DUK_INTERNAL void duk_push_hobject(duk_hthread *thr, duk_hobject *h) {
23896 	duk_tval tv;
23897 
23898 	DUK_ASSERT_API_ENTRY(thr);
23899 	DUK_ASSERT(h != NULL);
23900 
23901 	DUK_TVAL_SET_OBJECT(&tv, h);
23902 	duk_push_tval(thr, &tv);
23903 }
23904 
duk_push_hbuffer(duk_hthread * thr,duk_hbuffer * h)23905 DUK_INTERNAL void duk_push_hbuffer(duk_hthread *thr, duk_hbuffer *h) {
23906 	duk_tval tv;
23907 
23908 	DUK_ASSERT_API_ENTRY(thr);
23909 	DUK_ASSERT(h != NULL);
23910 
23911 	DUK_TVAL_SET_BUFFER(&tv, h);
23912 	duk_push_tval(thr, &tv);
23913 }
23914 
duk_push_hobject_bidx(duk_hthread * thr,duk_small_int_t builtin_idx)23915 DUK_INTERNAL void duk_push_hobject_bidx(duk_hthread *thr, duk_small_int_t builtin_idx) {
23916 	DUK_ASSERT_API_ENTRY(thr);
23917 	DUK_ASSERT(builtin_idx >= 0 && builtin_idx < DUK_NUM_BUILTINS);
23918 	DUK_ASSERT(thr->builtins[builtin_idx] != NULL);
23919 
23920 	duk_push_hobject(thr, thr->builtins[builtin_idx]);
23921 }
23922 
23923 /*
23924  *  Poppers
23925  */
23926 
duk__pop_n_unsafe_raw(duk_hthread * thr,duk_idx_t count)23927 DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_n_unsafe_raw(duk_hthread *thr, duk_idx_t count) {
23928 	duk_tval *tv;
23929 #if defined(DUK_USE_REFERENCE_COUNTING)
23930 	duk_tval *tv_end;
23931 #endif
23932 
23933 	DUK_CTX_ASSERT_VALID(thr);
23934 	DUK_ASSERT(count >= 0);
23935 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) count);
23936 
23937 #if defined(DUK_USE_REFERENCE_COUNTING)
23938 	tv = thr->valstack_top;
23939 	tv_end = tv - count;
23940 	while (tv != tv_end) {
23941 		tv--;
23942 		DUK_ASSERT(tv >= thr->valstack_bottom);
23943 		DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
23944 	}
23945 	thr->valstack_top = tv;
23946 	DUK_REFZERO_CHECK_FAST(thr);
23947 #else
23948 	tv = thr->valstack_top;
23949 	while (count > 0) {
23950 		count--;
23951 		tv--;
23952 		DUK_ASSERT(tv >= thr->valstack_bottom);
23953 		DUK_TVAL_SET_UNDEFINED(tv);
23954 	}
23955 	thr->valstack_top = tv;
23956 #endif
23957 
23958 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23959 }
23960 
duk_pop_n(duk_hthread * thr,duk_idx_t count)23961 DUK_EXTERNAL void duk_pop_n(duk_hthread *thr, duk_idx_t count) {
23962 	DUK_ASSERT_API_ENTRY(thr);
23963 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23964 
23965 	if (DUK_UNLIKELY((duk_uidx_t) (thr->valstack_top - thr->valstack_bottom) < (duk_uidx_t) count)) {
23966 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
23967 		DUK_WO_NORETURN(return;);
23968 	}
23969 	DUK_ASSERT(count >= 0);
23970 
23971 	duk__pop_n_unsafe_raw(thr, count);
23972 }
23973 
23974 #if defined(DUK_USE_PREFER_SIZE)
duk_pop_n_unsafe(duk_hthread * thr,duk_idx_t count)23975 DUK_INTERNAL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count) {
23976 	DUK_ASSERT_API_ENTRY(thr);
23977 	duk_pop_n(thr, count);
23978 }
23979 #else  /* DUK_USE_PREFER_SIZE */
duk_pop_n_unsafe(duk_hthread * thr,duk_idx_t count)23980 DUK_INTERNAL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count) {
23981 	DUK_ASSERT_API_ENTRY(thr);
23982 	duk__pop_n_unsafe_raw(thr, count);
23983 }
23984 #endif  /* DUK_USE_PREFER_SIZE */
23985 
23986 /* Pop N elements without DECREF (in effect "stealing" any actual refcounts). */
23987 #if defined(DUK_USE_REFERENCE_COUNTING)
duk_pop_n_nodecref_unsafe(duk_hthread * thr,duk_idx_t count)23988 DUK_INTERNAL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count) {
23989 	duk_tval *tv;
23990 
23991 	DUK_ASSERT_API_ENTRY(thr);
23992 	DUK_ASSERT(count >= 0);
23993 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23994 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) count);
23995 
23996 	tv = thr->valstack_top;
23997 	while (count > 0) {
23998 		count--;
23999 		tv--;
24000 		DUK_ASSERT(tv >= thr->valstack_bottom);
24001 		DUK_TVAL_SET_UNDEFINED(tv);
24002 	}
24003 	thr->valstack_top = tv;
24004 
24005 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24006 }
24007 #else  /* DUK_USE_REFERENCE_COUNTING */
duk_pop_n_nodecref_unsafe(duk_hthread * thr,duk_idx_t count)24008 DUK_INTERNAL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count) {
24009 	DUK_ASSERT_API_ENTRY(thr);
24010 	duk_pop_n_unsafe(thr, count);
24011 }
24012 #endif  /* DUK_USE_REFERENCE_COUNTING */
24013 
24014 /* Popping one element is called so often that when footprint is not an issue,
24015  * compile a specialized function for it.
24016  */
24017 #if defined(DUK_USE_PREFER_SIZE)
duk_pop(duk_hthread * thr)24018 DUK_EXTERNAL void duk_pop(duk_hthread *thr) {
24019 	DUK_ASSERT_API_ENTRY(thr);
24020 	duk_pop_n(thr, 1);
24021 }
duk_pop_unsafe(duk_hthread * thr)24022 DUK_INTERNAL void duk_pop_unsafe(duk_hthread *thr) {
24023 	DUK_ASSERT_API_ENTRY(thr);
24024 	duk_pop_n_unsafe(thr, 1);
24025 }
duk_pop_nodecref_unsafe(duk_hthread * thr)24026 DUK_INTERNAL void duk_pop_nodecref_unsafe(duk_hthread *thr) {
24027 	DUK_ASSERT_API_ENTRY(thr);
24028 	duk_pop_n_nodecref_unsafe(thr, 1);
24029 }
24030 #else  /* DUK_USE_PREFER_SIZE */
duk__pop_unsafe_raw(duk_hthread * thr)24031 DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_unsafe_raw(duk_hthread *thr) {
24032 	duk_tval *tv;
24033 
24034 	DUK_CTX_ASSERT_VALID(thr);
24035 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
24036 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24037 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);
24038 
24039 	tv = --thr->valstack_top;
24040 	DUK_ASSERT(tv >= thr->valstack_bottom);
24041 #if defined(DUK_USE_REFERENCE_COUNTING)
24042 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
24043 #else
24044 	DUK_TVAL_SET_UNDEFINED(tv);
24045 #endif
24046 
24047 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24048 }
duk_pop(duk_hthread * thr)24049 DUK_EXTERNAL void duk_pop(duk_hthread *thr) {
24050 	DUK_ASSERT_API_ENTRY(thr);
24051 
24052 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24053 	if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {
24054 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
24055 		DUK_WO_NORETURN(return;);
24056 	}
24057 
24058 	duk__pop_unsafe_raw(thr);
24059 }
duk_pop_unsafe(duk_hthread * thr)24060 DUK_INTERNAL void duk_pop_unsafe(duk_hthread *thr) {
24061 	DUK_ASSERT_API_ENTRY(thr);
24062 	duk__pop_unsafe_raw(thr);
24063 }
duk_pop_nodecref_unsafe(duk_hthread * thr)24064 DUK_INTERNAL void duk_pop_nodecref_unsafe(duk_hthread *thr) {
24065 	duk_tval *tv;
24066 
24067 	DUK_ASSERT_API_ENTRY(thr);
24068 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
24069 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24070 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);
24071 
24072 	tv = --thr->valstack_top;
24073 	DUK_ASSERT(tv >= thr->valstack_bottom);
24074 	DUK_TVAL_SET_UNDEFINED(tv);
24075 
24076 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24077 }
24078 #endif  /* !DUK_USE_PREFER_SIZE */
24079 
24080 #if defined(DUK_USE_PREFER_SIZE)
duk_pop_undefined(duk_hthread * thr)24081 DUK_INTERNAL void duk_pop_undefined(duk_hthread *thr) {
24082 	DUK_ASSERT_API_ENTRY(thr);
24083 	duk_pop_nodecref_unsafe(thr);
24084 }
24085 #else  /* DUK_USE_PREFER_SIZE */
duk_pop_undefined(duk_hthread * thr)24086 DUK_INTERNAL void duk_pop_undefined(duk_hthread *thr) {
24087 	DUK_ASSERT_API_ENTRY(thr);
24088 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
24089 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24090 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);
24091 
24092 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
24093 	thr->valstack_top--;
24094 
24095 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24096 }
24097 #endif  /* !DUK_USE_PREFER_SIZE */
24098 
24099 #if defined(DUK_USE_PREFER_SIZE)
duk_pop_2(duk_hthread * thr)24100 DUK_EXTERNAL void duk_pop_2(duk_hthread *thr) {
24101 	DUK_ASSERT_API_ENTRY(thr);
24102 	duk_pop_n(thr, 2);
24103 }
duk_pop_2_unsafe(duk_hthread * thr)24104 DUK_INTERNAL void duk_pop_2_unsafe(duk_hthread *thr) {
24105 	DUK_ASSERT_API_ENTRY(thr);
24106 	duk_pop_n_unsafe(thr, 2);
24107 }
duk_pop_2_nodecref_unsafe(duk_hthread * thr)24108 DUK_INTERNAL void duk_pop_2_nodecref_unsafe(duk_hthread *thr) {
24109 	DUK_ASSERT_API_ENTRY(thr);
24110 	duk_pop_n_nodecref_unsafe(thr, 2);
24111 }
24112 #else
duk__pop_2_unsafe_raw(duk_hthread * thr)24113 DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_2_unsafe_raw(duk_hthread *thr) {
24114 	duk_tval *tv;
24115 
24116 	DUK_CTX_ASSERT_VALID(thr);
24117 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
24118 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24119 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 2);
24120 
24121 	tv = --thr->valstack_top;
24122 	DUK_ASSERT(tv >= thr->valstack_bottom);
24123 #if defined(DUK_USE_REFERENCE_COUNTING)
24124 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
24125 #else
24126 	DUK_TVAL_SET_UNDEFINED(tv);
24127 #endif
24128 	tv = --thr->valstack_top;
24129 	DUK_ASSERT(tv >= thr->valstack_bottom);
24130 #if defined(DUK_USE_REFERENCE_COUNTING)
24131 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
24132 #else
24133 	DUK_TVAL_SET_UNDEFINED(tv);
24134 #endif
24135 
24136 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24137 }
duk_pop_2(duk_hthread * thr)24138 DUK_EXTERNAL void duk_pop_2(duk_hthread *thr) {
24139 	DUK_ASSERT_API_ENTRY(thr);
24140 
24141 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24142 	if (DUK_UNLIKELY(thr->valstack_top - 2 < thr->valstack_bottom)) {
24143 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
24144 		DUK_WO_NORETURN(return;);
24145 	}
24146 
24147 	duk__pop_2_unsafe_raw(thr);
24148 }
duk_pop_2_unsafe(duk_hthread * thr)24149 DUK_INTERNAL void duk_pop_2_unsafe(duk_hthread *thr) {
24150 	DUK_ASSERT_API_ENTRY(thr);
24151 	duk__pop_2_unsafe_raw(thr);
24152 }
duk_pop_2_nodecref_unsafe(duk_hthread * thr)24153 DUK_INTERNAL void duk_pop_2_nodecref_unsafe(duk_hthread *thr) {
24154 	DUK_ASSERT_API_ENTRY(thr);
24155 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
24156 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24157 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 2);
24158 
24159 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
24160 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 2));
24161 	thr->valstack_top -= 2;
24162 
24163 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24164 }
24165 #endif  /* !DUK_USE_PREFER_SIZE */
24166 
duk_pop_3(duk_hthread * thr)24167 DUK_EXTERNAL void duk_pop_3(duk_hthread *thr) {
24168 	DUK_ASSERT_API_ENTRY(thr);
24169 	duk_pop_n(thr, 3);
24170 }
24171 
duk_pop_3_unsafe(duk_hthread * thr)24172 DUK_INTERNAL void duk_pop_3_unsafe(duk_hthread *thr) {
24173 	DUK_ASSERT_API_ENTRY(thr);
24174 	duk_pop_n_unsafe(thr, 3);
24175 }
24176 
duk_pop_3_nodecref_unsafe(duk_hthread * thr)24177 DUK_INTERNAL void duk_pop_3_nodecref_unsafe(duk_hthread *thr) {
24178 	DUK_ASSERT_API_ENTRY(thr);
24179 	duk_pop_n_nodecref_unsafe(thr, 3);
24180 }
24181 
24182 /*
24183  *  Pack and unpack (pack value stack entries into an array and vice versa)
24184  */
24185 
24186 /* XXX: pack index range? array index offset? */
24187 /* XXX: need ability to pack into a bare array? */
duk_pack(duk_hthread * thr,duk_idx_t count)24188 DUK_INTERNAL void duk_pack(duk_hthread *thr, duk_idx_t count) {
24189 	duk_tval *tv_src;
24190 	duk_tval *tv_dst;
24191 	duk_tval *tv_curr;
24192 	duk_tval *tv_limit;
24193 	duk_idx_t top;
24194 
24195 	DUK_ASSERT_API_ENTRY(thr);
24196 
24197 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24198 	top = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
24199 	DUK_ASSERT(top >= 0);
24200 	if (DUK_UNLIKELY((duk_uidx_t) count > (duk_uidx_t) top)) {
24201 		/* Also handles negative count. */
24202 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
24203 		DUK_WO_NORETURN(return;);
24204 	}
24205 	DUK_ASSERT(count >= 0);
24206 
24207 	/* Wrapping is controlled by the check above: value stack top can be
24208 	 * at most DUK_USE_VALSTACK_LIMIT which is low enough so that
24209 	 * multiplying with sizeof(duk_tval) won't wrap.
24210 	 */
24211 	DUK_ASSERT(count >= 0 && count <= (duk_idx_t) DUK_USE_VALSTACK_LIMIT);
24212 	DUK_ASSERT((duk_size_t) count <= DUK_SIZE_MAX / sizeof(duk_tval));  /* no wrapping */
24213 
24214 	tv_dst = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) count);  /* XXX: uninitialized would be OK */
24215 	DUK_ASSERT(count == 0 || tv_dst != NULL);
24216 	DUK_ASSERT(!duk_is_bare_object(thr, -1));
24217 
24218 	/* Copy value stack values directly to the array part without
24219 	 * any refcount updates: net refcount changes are zero.
24220 	 */
24221 	tv_src = thr->valstack_top - count - 1;
24222 	duk_memcpy_unsafe((void *) tv_dst, (const void *) tv_src, (size_t) count * sizeof(duk_tval));
24223 
24224 	/* Overwrite result array to final value stack location and wipe
24225 	 * the rest; no refcount operations needed.
24226 	 */
24227 
24228 	tv_dst = tv_src;  /* when count == 0, same as tv_src (OK) */
24229 	tv_src = thr->valstack_top - 1;
24230 	DUK_TVAL_SET_TVAL(tv_dst, tv_src);
24231 
24232 	/* XXX: internal helper to wipe a value stack segment? */
24233 	tv_curr = tv_dst + 1;
24234 	tv_limit = thr->valstack_top;
24235 	while (tv_curr != tv_limit) {
24236 		/* Wipe policy: keep as 'undefined'. */
24237 		DUK_TVAL_SET_UNDEFINED(tv_curr);
24238 		tv_curr++;
24239 	}
24240 	thr->valstack_top = tv_dst + 1;
24241 }
24242 
duk_unpack_array_like(duk_hthread * thr,duk_idx_t idx)24243 DUK_INTERNAL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx) {
24244 	duk_tval *tv;
24245 
24246 	DUK_ASSERT_API_ENTRY(thr);
24247 
24248 	tv = duk_require_tval(thr, idx);
24249 	if (DUK_LIKELY(DUK_TVAL_IS_OBJECT(tv))) {
24250 		duk_hobject *h;
24251 		duk_uint32_t len;
24252 		duk_uint32_t i;
24253 
24254 		h = DUK_TVAL_GET_OBJECT(tv);
24255 		DUK_ASSERT(h != NULL);
24256 		DUK_UNREF(h);
24257 
24258 #if defined(DUK_USE_ARRAY_FASTPATH)  /* close enough */
24259 		if (DUK_LIKELY(DUK_HOBJECT_IS_ARRAY(h) &&
24260 		               ((duk_harray *) h)->length <= DUK_HOBJECT_GET_ASIZE(h))) {
24261 			duk_harray *h_arr;
24262 			duk_tval *tv_src;
24263 			duk_tval *tv_dst;
24264 
24265 			h_arr = (duk_harray *) h;
24266 			len = h_arr->length;
24267 			if (DUK_UNLIKELY(len >= 0x80000000UL)) {
24268 				goto fail_over_2g;
24269 			}
24270 			duk_require_stack(thr, (duk_idx_t) len);
24271 
24272 			/* The potential allocation in duk_require_stack() may
24273 			 * run a finalizer which modifies the argArray so that
24274 			 * e.g. becomes sparse.  So, we need to recheck that the
24275 			 * array didn't change size and that there's still a
24276 			 * valid backing array part.
24277 			 *
24278 			 * XXX: alternatively, could prevent finalizers for the
24279 			 * duration.
24280 			 */
24281 			if (DUK_UNLIKELY(len != h_arr->length ||
24282 			                 h_arr->length > DUK_HOBJECT_GET_ASIZE((duk_hobject *) h_arr))) {
24283 				goto skip_fast;
24284 			}
24285 
24286 			/* Main fast path: arguments array is almost always
24287 			 * an actual array (though it might also be an arguments
24288 			 * object).
24289 			 */
24290 
24291 			DUK_DDD(DUK_DDDPRINT("fast path for %ld elements", (long) h_arr->length));
24292 			tv_src = DUK_HOBJECT_A_GET_BASE(thr->heap, h);
24293 			tv_dst = thr->valstack_top;
24294 			while (len-- > 0) {
24295 				DUK_ASSERT(tv_dst < thr->valstack_end);
24296 				if (DUK_UNLIKELY(DUK_TVAL_IS_UNUSED(tv_src))) {
24297 					/* Gaps are very unlikely.  Skip over them,
24298 					 * without an ancestor lookup (technically
24299 					 * not compliant).
24300 					 */
24301 					DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_dst));  /* valstack policy */
24302 				} else {
24303 					DUK_TVAL_SET_TVAL(tv_dst, tv_src);
24304 					DUK_TVAL_INCREF(thr, tv_dst);
24305 				}
24306 				tv_src++;
24307 				tv_dst++;
24308 			}
24309 			DUK_ASSERT(tv_dst <= thr->valstack_end);
24310 			thr->valstack_top = tv_dst;
24311 			return (duk_idx_t) h_arr->length;
24312 		}
24313 	 skip_fast:
24314 #endif  /* DUK_USE_ARRAY_FASTPATH */
24315 
24316 		/* Slow path: actual lookups.  The initial 'length' lookup
24317 		 * decides the output length, regardless of side effects that
24318 		 * may resize or change the argArray while we read the
24319 		 * indices.
24320 		 */
24321 		idx = duk_normalize_index(thr, idx);
24322 		duk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
24323 		len = duk_to_uint32(thr, -1);  /* ToUint32() coercion required */
24324 		if (DUK_UNLIKELY(len >= 0x80000000UL)) {
24325 			goto fail_over_2g;
24326 		}
24327 		duk_pop_unsafe(thr);
24328 		DUK_DDD(DUK_DDDPRINT("slow path for %ld elements", (long) len));
24329 
24330 		duk_require_stack(thr, (duk_idx_t) len);
24331 		for (i = 0; i < len; i++) {
24332 			duk_get_prop_index(thr, idx, (duk_uarridx_t) i);
24333 		}
24334 		return (duk_idx_t) len;
24335 	} else if (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv)) {
24336 		return 0;
24337 	}
24338 
24339 	DUK_ERROR_TYPE_INVALID_ARGS(thr);
24340 	DUK_WO_NORETURN(return 0;);
24341 
24342  fail_over_2g:
24343 	DUK_ERROR_RANGE_INVALID_LENGTH(thr);
24344 	DUK_WO_NORETURN(return 0;);
24345 }
24346 
24347 /*
24348  *  Error throwing
24349  */
24350 
24351 #if defined(DUK_USE_GCC_PRAGMAS)
24352 #pragma GCC diagnostic push
24353 #pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn"
24354 #elif defined(DUK_USE_CLANG_PRAGMAS)
24355 #pragma clang diagnostic push
24356 #endif
24357 
duk_throw_raw(duk_hthread * thr)24358 DUK_EXTERNAL void duk_throw_raw(duk_hthread *thr) {
24359 	duk_tval *tv_val;
24360 
24361 	DUK_ASSERT_API_ENTRY(thr);
24362 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
24363 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
24364 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
24365 
24366 	if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {
24367 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
24368 		DUK_WO_NORETURN(return;);
24369 	}
24370 
24371 	/* Errors are augmented when they are created, not when they are
24372 	 * thrown or re-thrown.  The current error handler, however, runs
24373 	 * just before an error is thrown.
24374 	 */
24375 
24376 	/* Sync so that augmentation sees up-to-date activations, NULL
24377 	 * thr->ptr_curr_pc so that it's not used if side effects occur
24378 	 * in augmentation or longjmp handling.
24379 	 */
24380 	duk_hthread_sync_and_null_currpc(thr);
24381 
24382 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
24383 	DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (before throw augment)", (duk_tval *) duk_get_tval(thr, -1)));
24384 	duk_err_augment_error_throw(thr);
24385 #endif
24386 	DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (after throw augment)", (duk_tval *) duk_get_tval(thr, -1)));
24387 
24388 	tv_val = DUK_GET_TVAL_NEGIDX(thr, -1);
24389 	duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, tv_val);
24390 #if defined(DUK_USE_DEBUGGER_SUPPORT)
24391 	duk_err_check_debugger_integration(thr);
24392 #endif
24393 
24394 	/* thr->heap->lj.jmpbuf_ptr is checked by duk_err_longjmp() so we don't
24395 	 * need to check that here.  If the value is NULL, a fatal error occurs
24396 	 * because we can't return.
24397 	 */
24398 
24399 	duk_err_longjmp(thr);
24400 	DUK_UNREACHABLE();
24401 }
24402 
duk_fatal_raw(duk_hthread * thr,const char * err_msg)24403 DUK_EXTERNAL void duk_fatal_raw(duk_hthread *thr, const char *err_msg) {
24404 	DUK_ASSERT_API_ENTRY(thr);
24405 	DUK_ASSERT(thr != NULL);
24406 	DUK_ASSERT(thr->heap != NULL);
24407 	DUK_ASSERT(thr->heap->fatal_func != NULL);
24408 
24409 	DUK_D(DUK_DPRINT("fatal error occurred: %s", err_msg ? err_msg : "NULL"));
24410 
24411 	/* fatal_func should be noreturn, but noreturn declarations on function
24412 	 * pointers has a very spotty support apparently so it's not currently
24413 	 * done.
24414 	 */
24415 	thr->heap->fatal_func(thr->heap->heap_udata, err_msg);
24416 
24417 	/* If the fatal handler returns, all bets are off.  It'd be nice to
24418 	 * print something here but since we don't want to depend on stdio,
24419 	 * there's no way to do so portably.
24420 	 */
24421 	DUK_D(DUK_DPRINT("fatal error handler returned, all bets are off!"));
24422 	for (;;) {
24423 		/* loop forever, don't return (function marked noreturn) */
24424 	}
24425 }
24426 
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)24427 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) {
24428 	DUK_ASSERT_API_ENTRY(thr);
24429 
24430 	duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
24431 	(void) duk_throw(thr);
24432 	DUK_WO_NORETURN(return;);
24433 }
24434 
duk_error_raw(duk_hthread * thr,duk_errcode_t err_code,const char * filename,duk_int_t line,const char * fmt,...)24435 DUK_EXTERNAL void duk_error_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
24436 	va_list ap;
24437 
24438 	DUK_ASSERT_API_ENTRY(thr);
24439 
24440 	va_start(ap, fmt);
24441 	duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
24442 	va_end(ap);
24443 	(void) duk_throw(thr);
24444 	DUK_WO_NORETURN(return;);
24445 }
24446 
24447 #if defined(DUK_USE_GCC_PRAGMAS)
24448 #pragma GCC diagnostic pop
24449 #elif defined(DUK_USE_CLANG_PRAGMAS)
24450 #pragma clang diagnostic pop
24451 #endif
24452 
24453 #if !defined(DUK_USE_VARIADIC_MACROS)
24454 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));
24455 
duk__throw_error_from_stash(duk_hthread * thr,duk_errcode_t err_code,const char * fmt,va_list ap)24456 DUK_LOCAL void duk__throw_error_from_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, va_list ap) {
24457 	const char *filename;
24458 	duk_int_t line;
24459 
24460 	DUK_CTX_ASSERT_VALID(thr);
24461 
24462 	filename = duk_api_global_filename;
24463 	line = duk_api_global_line;
24464 	duk_api_global_filename = NULL;
24465 	duk_api_global_line = 0;
24466 
24467 	duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
24468 	(void) duk_throw(thr);
24469 	DUK_WO_NORETURN(return;);
24470 }
24471 
24472 #define DUK__ERROR_STASH_SHARED(code) do { \
24473 		va_list ap; \
24474 		va_start(ap, fmt); \
24475 		duk__throw_error_from_stash(thr, (code), fmt, ap); \
24476 		va_end(ap); \
24477 		DUK_WO_NORETURN(return 0;); \
24478 	} while (0)
24479 
duk_error_stash(duk_hthread * thr,duk_errcode_t err_code,const char * fmt,...)24480 DUK_EXTERNAL duk_ret_t duk_error_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, ...) {
24481 	DUK_ASSERT_API_ENTRY(thr);
24482 	DUK__ERROR_STASH_SHARED(err_code);
24483 }
duk_generic_error_stash(duk_hthread * thr,const char * fmt,...)24484 DUK_EXTERNAL duk_ret_t duk_generic_error_stash(duk_hthread *thr, const char *fmt, ...) {
24485 	DUK_ASSERT_API_ENTRY(thr);
24486 	DUK__ERROR_STASH_SHARED(DUK_ERR_ERROR);
24487 }
duk_eval_error_stash(duk_hthread * thr,const char * fmt,...)24488 DUK_EXTERNAL duk_ret_t duk_eval_error_stash(duk_hthread *thr, const char *fmt, ...) {
24489 	DUK_ASSERT_API_ENTRY(thr);
24490 	DUK__ERROR_STASH_SHARED(DUK_ERR_EVAL_ERROR);
24491 }
duk_range_error_stash(duk_hthread * thr,const char * fmt,...)24492 DUK_EXTERNAL duk_ret_t duk_range_error_stash(duk_hthread *thr, const char *fmt, ...) {
24493 	DUK_ASSERT_API_ENTRY(thr);
24494 	DUK__ERROR_STASH_SHARED(DUK_ERR_RANGE_ERROR);
24495 }
duk_reference_error_stash(duk_hthread * thr,const char * fmt,...)24496 DUK_EXTERNAL duk_ret_t duk_reference_error_stash(duk_hthread *thr, const char *fmt, ...) {
24497 	DUK_ASSERT_API_ENTRY(thr);
24498 	DUK__ERROR_STASH_SHARED(DUK_ERR_REFERENCE_ERROR);
24499 }
duk_syntax_error_stash(duk_hthread * thr,const char * fmt,...)24500 DUK_EXTERNAL duk_ret_t duk_syntax_error_stash(duk_hthread *thr, const char *fmt, ...) {
24501 	DUK_ASSERT_API_ENTRY(thr);
24502 	DUK__ERROR_STASH_SHARED(DUK_ERR_SYNTAX_ERROR);
24503 }
duk_type_error_stash(duk_hthread * thr,const char * fmt,...)24504 DUK_EXTERNAL duk_ret_t duk_type_error_stash(duk_hthread *thr, const char *fmt, ...) {
24505 	DUK_ASSERT_API_ENTRY(thr);
24506 	DUK__ERROR_STASH_SHARED(DUK_ERR_TYPE_ERROR);
24507 }
duk_uri_error_stash(duk_hthread * thr,const char * fmt,...)24508 DUK_EXTERNAL duk_ret_t duk_uri_error_stash(duk_hthread *thr, const char *fmt, ...) {
24509 	DUK_ASSERT_API_ENTRY(thr);
24510 	DUK__ERROR_STASH_SHARED(DUK_ERR_URI_ERROR);
24511 }
24512 #endif  /* DUK_USE_VARIADIC_MACROS */
24513 
24514 /*
24515  *  Comparison
24516  */
24517 
duk_equals(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)24518 DUK_EXTERNAL duk_bool_t duk_equals(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
24519 	duk_tval *tv1, *tv2;
24520 
24521 	DUK_ASSERT_API_ENTRY(thr);
24522 
24523 	tv1 = duk_get_tval(thr, idx1);
24524 	tv2 = duk_get_tval(thr, idx2);
24525 	if ((tv1 == NULL) || (tv2 == NULL)) {
24526 		return 0;
24527 	}
24528 
24529 	/* Coercion may be needed, the helper handles that by pushing the
24530 	 * tagged values to the stack.
24531 	 */
24532 	return duk_js_equals(thr, tv1, tv2);
24533 }
24534 
duk_strict_equals(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)24535 DUK_EXTERNAL duk_bool_t duk_strict_equals(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
24536 	duk_tval *tv1, *tv2;
24537 
24538 	DUK_ASSERT_API_ENTRY(thr);
24539 
24540 	tv1 = duk_get_tval(thr, idx1);
24541 	tv2 = duk_get_tval(thr, idx2);
24542 	if ((tv1 == NULL) || (tv2 == NULL)) {
24543 		return 0;
24544 	}
24545 
24546 	/* No coercions or other side effects, so safe */
24547 	return duk_js_strict_equals(tv1, tv2);
24548 }
24549 
duk_samevalue(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)24550 DUK_EXTERNAL duk_bool_t duk_samevalue(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
24551 	duk_tval *tv1, *tv2;
24552 
24553 	DUK_ASSERT_API_ENTRY(thr);
24554 
24555 	tv1 = duk_get_tval(thr, idx1);
24556 	tv2 = duk_get_tval(thr, idx2);
24557 	if ((tv1 == NULL) || (tv2 == NULL)) {
24558 		return 0;
24559 	}
24560 
24561 	/* No coercions or other side effects, so safe */
24562 	return duk_js_samevalue(tv1, tv2);
24563 }
24564 
24565 /*
24566  *  instanceof
24567  */
24568 
duk_instanceof(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)24569 DUK_EXTERNAL duk_bool_t duk_instanceof(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
24570 	duk_tval *tv1, *tv2;
24571 
24572 	DUK_ASSERT_API_ENTRY(thr);
24573 
24574 	/* Index validation is strict, which differs from duk_equals().
24575 	 * The strict behavior mimics how instanceof itself works, e.g.
24576 	 * it is a TypeError if rval is not a -callable- object.  It would
24577 	 * be somewhat inconsistent if rval would be allowed to be
24578 	 * non-existent without a TypeError.
24579 	 */
24580 	tv1 = duk_require_tval(thr, idx1);
24581 	DUK_ASSERT(tv1 != NULL);
24582 	tv2 = duk_require_tval(thr, idx2);
24583 	DUK_ASSERT(tv2 != NULL);
24584 
24585 	return duk_js_instanceof(thr, tv1, tv2);
24586 }
24587 
24588 /*
24589  *  Lightfunc
24590  */
24591 
duk_push_lightfunc_name_raw(duk_hthread * thr,duk_c_function func,duk_small_uint_t lf_flags)24592 DUK_INTERNAL void duk_push_lightfunc_name_raw(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags) {
24593 	/* Lightfunc name, includes Duktape/C native function pointer, which
24594 	 * can often be used to locate the function from a symbol table.
24595 	 * The name also includes the 16-bit duk_tval flags field because it
24596 	 * includes the magic value.  Because a single native function often
24597 	 * provides different functionality depending on the magic value, it
24598 	 * seems reasonably to include it in the name.
24599 	 *
24600 	 * On the other hand, a complicated name increases string table
24601 	 * pressure in low memory environments (but only when function name
24602 	 * is accessed).
24603 	 */
24604 
24605 	DUK_ASSERT_API_ENTRY(thr);
24606 
24607 	duk_push_literal(thr, "light_");
24608 	duk_push_string_funcptr(thr, (duk_uint8_t *) &func, sizeof(func));
24609 	duk_push_sprintf(thr, "_%04x", (unsigned int) lf_flags);
24610 	duk_concat(thr, 3);
24611 }
24612 
duk_push_lightfunc_name(duk_hthread * thr,duk_tval * tv)24613 DUK_INTERNAL void duk_push_lightfunc_name(duk_hthread *thr, duk_tval *tv) {
24614 	duk_c_function func;
24615 	duk_small_uint_t lf_flags;
24616 
24617 	DUK_ASSERT_API_ENTRY(thr);
24618 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));
24619 
24620 	DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
24621 	duk_push_lightfunc_name_raw(thr, func, lf_flags);
24622 }
24623 
duk_push_lightfunc_tostring(duk_hthread * thr,duk_tval * tv)24624 DUK_INTERNAL void duk_push_lightfunc_tostring(duk_hthread *thr, duk_tval *tv) {
24625 	duk_c_function func;
24626 	duk_small_uint_t lf_flags;
24627 
24628 	DUK_ASSERT_API_ENTRY(thr);
24629 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));
24630 
24631 	DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);  /* read before 'tv' potentially invalidated */
24632 	duk_push_literal(thr, "function ");
24633 	duk_push_lightfunc_name_raw(thr, func, lf_flags);
24634 	duk_push_literal(thr, "() { [lightfunc code] }");
24635 	duk_concat(thr, 3);
24636 }
24637 
24638 /*
24639  *  Function pointers
24640  *
24641  *  Printing function pointers is non-portable, so we do that by hex printing
24642  *  bytes from memory.
24643  */
24644 
duk_push_string_funcptr(duk_hthread * thr,duk_uint8_t * ptr,duk_size_t sz)24645 DUK_INTERNAL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, duk_size_t sz) {
24646 	duk_uint8_t buf[32 * 2];
24647 	duk_uint8_t *p, *q;
24648 	duk_small_uint_t i;
24649 	duk_small_uint_t t;
24650 
24651 	DUK_ASSERT_API_ENTRY(thr);
24652 	DUK_ASSERT(sz <= 32);  /* sanity limit for function pointer size */
24653 
24654 	p = buf;
24655 #if defined(DUK_USE_INTEGER_LE)
24656 	q = ptr + sz;
24657 #else
24658 	q = ptr;
24659 #endif
24660 	for (i = 0; i < sz; i++) {
24661 #if defined(DUK_USE_INTEGER_LE)
24662 		t = *(--q);
24663 #else
24664 		t = *(q++);
24665 #endif
24666 		*p++ = duk_lc_digits[t >> 4];
24667 		*p++ = duk_lc_digits[t & 0x0f];
24668 	}
24669 
24670 	duk_push_lstring(thr, (const char *) buf, sz * 2);
24671 }
24672 
24673 /*
24674  *  Push readable string summarizing duk_tval.  The operation is side effect
24675  *  free and will only throw from internal errors (e.g. out of memory).
24676  *  This is used by e.g. property access code to summarize a key/base safely,
24677  *  and is not intended to be fast (but small and safe).
24678  */
24679 
24680 /* String limits for summary strings. */
24681 #define DUK__READABLE_SUMMARY_MAXCHARS 96  /* maximum supported by helper */
24682 #define DUK__READABLE_STRING_MAXCHARS  32  /* for strings/symbols */
24683 #define DUK__READABLE_ERRMSG_MAXCHARS  96  /* for error messages */
24684 
24685 /* String sanitizer which escapes ASCII control characters and a few other
24686  * ASCII characters, passes Unicode as is, and replaces invalid UTF-8 with
24687  * question marks.  No errors are thrown for any input string, except in out
24688  * of memory situations.
24689  */
duk__push_hstring_readable_unicode(duk_hthread * thr,duk_hstring * h_input,duk_small_uint_t maxchars)24690 DUK_LOCAL void duk__push_hstring_readable_unicode(duk_hthread *thr, duk_hstring *h_input, duk_small_uint_t maxchars) {
24691 	const duk_uint8_t *p, *p_start, *p_end;
24692 	duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH * DUK__READABLE_SUMMARY_MAXCHARS +
24693 	                2 /*quotes*/ + 3 /*periods*/];
24694 	duk_uint8_t *q;
24695 	duk_ucodepoint_t cp;
24696 	duk_small_uint_t nchars;
24697 
24698 	DUK_CTX_ASSERT_VALID(thr);
24699 	DUK_ASSERT(h_input != NULL);
24700 	DUK_ASSERT(maxchars <= DUK__READABLE_SUMMARY_MAXCHARS);
24701 
24702 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
24703 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
24704 	p = p_start;
24705 	q = buf;
24706 
24707 	nchars = 0;
24708 	*q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
24709 	for (;;) {
24710 		if (p >= p_end) {
24711 			break;
24712 		}
24713 		if (nchars == maxchars) {
24714 			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
24715 			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
24716 			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
24717 			break;
24718 		}
24719 		if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
24720 			if (cp < 0x20 || cp == 0x7f || cp == DUK_ASC_SINGLEQUOTE || cp == DUK_ASC_BACKSLASH) {
24721 				DUK_ASSERT(DUK_UNICODE_MAX_XUTF8_LENGTH >= 4);  /* estimate is valid */
24722 				DUK_ASSERT((cp >> 4) <= 0x0f);
24723 				*q++ = (duk_uint8_t) DUK_ASC_BACKSLASH;
24724 				*q++ = (duk_uint8_t) DUK_ASC_LC_X;
24725 				*q++ = (duk_uint8_t) duk_lc_digits[cp >> 4];
24726 				*q++ = (duk_uint8_t) duk_lc_digits[cp & 0x0f];
24727 			} else {
24728 				q += duk_unicode_encode_xutf8(cp, q);
24729 			}
24730 		} else {
24731 			p++;  /* advance manually */
24732 			*q++ = (duk_uint8_t) DUK_ASC_QUESTION;
24733 		}
24734 		nchars++;
24735 	}
24736 	*q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
24737 
24738 	duk_push_lstring(thr, (const char *) buf, (duk_size_t) (q - buf));
24739 }
24740 
duk__push_string_tval_readable(duk_hthread * thr,duk_tval * tv,duk_bool_t error_aware)24741 DUK_LOCAL const char *duk__push_string_tval_readable(duk_hthread *thr, duk_tval *tv, duk_bool_t error_aware) {
24742 	DUK_CTX_ASSERT_VALID(thr);
24743 	/* 'tv' may be NULL */
24744 
24745 	if (tv == NULL) {
24746 		duk_push_literal(thr, "none");
24747 	} else {
24748 		switch (DUK_TVAL_GET_TAG(tv)) {
24749 		case DUK_TAG_STRING: {
24750 			duk_hstring *h = DUK_TVAL_GET_STRING(tv);
24751 			if (DUK_HSTRING_HAS_SYMBOL(h)) {
24752 				/* XXX: string summary produces question marks
24753 				 * so this is not very ideal.
24754 				 */
24755 				duk_push_literal(thr, "[Symbol ");
24756 				duk_push_string(thr, duk__get_symbol_type_string(h));
24757 				duk_push_literal(thr, " ");
24758 				duk__push_hstring_readable_unicode(thr, h, DUK__READABLE_STRING_MAXCHARS);
24759 				duk_push_literal(thr, "]");
24760 				duk_concat(thr, 5);
24761 				break;
24762 			}
24763 			duk__push_hstring_readable_unicode(thr, h, DUK__READABLE_STRING_MAXCHARS);
24764 			break;
24765 		}
24766 		case DUK_TAG_OBJECT: {
24767 			duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
24768 			DUK_ASSERT(h != NULL);
24769 
24770 			if (error_aware &&
24771 			    duk_hobject_prototype_chain_contains(thr, h, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {
24772 				/* Get error message in a side effect free way if
24773 				 * possible; if not, summarize as a generic object.
24774 				 * Error message currently gets quoted.
24775 				 */
24776 				/* XXX: better internal getprop call; get without side effects
24777 				 * but traverse inheritance chain.
24778 				 */
24779 				duk_tval *tv_msg;
24780 				tv_msg = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, h, DUK_STRIDX_MESSAGE);
24781 				if (tv_msg != NULL && DUK_TVAL_IS_STRING(tv_msg)) {
24782 					/* It's critical to avoid recursion so
24783 					 * only summarize a string .message.
24784 					 */
24785 					duk__push_hstring_readable_unicode(thr, DUK_TVAL_GET_STRING(tv_msg), DUK__READABLE_ERRMSG_MAXCHARS);
24786 					break;
24787 				}
24788 			}
24789 			duk_push_class_string_tval(thr, tv, 1 /*avoid_side_effects*/);
24790 			break;
24791 		}
24792 		case DUK_TAG_BUFFER: {
24793 			/* While plain buffers mimic Uint8Arrays, they summarize differently.
24794 			 * This is useful so that the summarized string accurately reflects the
24795 			 * internal type which may matter for figuring out bugs etc.
24796 			 */
24797 			/* XXX: Hex encoded, length limited buffer summary here? */
24798 			duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
24799 			DUK_ASSERT(h != NULL);
24800 			duk_push_sprintf(thr, "[buffer:%ld]", (long) DUK_HBUFFER_GET_SIZE(h));
24801 			break;
24802 		}
24803 		case DUK_TAG_POINTER: {
24804 			/* Surround with parentheses like in JX, ensures NULL pointer
24805 			 * is distinguishable from null value ("(null)" vs "null").
24806 			 */
24807 			duk_push_tval(thr, tv);
24808 			duk_push_sprintf(thr, "(%s)", duk_to_string(thr, -1));
24809 			duk_remove_m2(thr);
24810 			break;
24811 		}
24812 		default: {
24813 			duk_push_tval(thr, tv);
24814 			break;
24815 		}
24816 		}
24817 	}
24818 
24819 	return duk_to_string(thr, -1);
24820 }
duk_push_string_tval_readable(duk_hthread * thr,duk_tval * tv)24821 DUK_INTERNAL const char *duk_push_string_tval_readable(duk_hthread *thr, duk_tval *tv) {
24822 	DUK_ASSERT_API_ENTRY(thr);
24823 	return duk__push_string_tval_readable(thr, tv, 0 /*error_aware*/);
24824 }
24825 
duk_push_string_readable(duk_hthread * thr,duk_idx_t idx)24826 DUK_INTERNAL const char *duk_push_string_readable(duk_hthread *thr, duk_idx_t idx) {
24827 	DUK_ASSERT_API_ENTRY(thr);
24828 	return duk_push_string_tval_readable(thr, duk_get_tval(thr, idx));
24829 }
24830 
duk_push_string_tval_readable_error(duk_hthread * thr,duk_tval * tv)24831 DUK_INTERNAL const char *duk_push_string_tval_readable_error(duk_hthread *thr, duk_tval *tv) {
24832 	DUK_ASSERT_API_ENTRY(thr);
24833 	return duk__push_string_tval_readable(thr, tv, 1 /*error_aware*/);
24834 }
24835 
duk_push_symbol_descriptive_string(duk_hthread * thr,duk_hstring * h)24836 DUK_INTERNAL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstring *h) {
24837 	const duk_uint8_t *p;
24838 	const duk_uint8_t *p_end;
24839 	const duk_uint8_t *q;
24840 
24841 	DUK_ASSERT_API_ENTRY(thr);
24842 
24843 	/* .toString() */
24844 	duk_push_literal(thr, "Symbol(");
24845 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
24846 	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
24847 	DUK_ASSERT(p[0] == 0xff || (p[0] & 0xc0) == 0x80);
24848 	p++;
24849 	for (q = p; q < p_end; q++) {
24850 		if (*q == 0xffU) {
24851 			/* Terminate either at end-of-string (but NUL MUST
24852 			 * be accepted without terminating description) or
24853 			 * 0xFF, which is used to mark start of unique trailer
24854 			 * (and cannot occur in CESU-8 / extended UTF-8).
24855 			 */
24856 			break;
24857 		}
24858 	}
24859 	duk_push_lstring(thr, (const char *) p, (duk_size_t) (q - p));
24860 	duk_push_literal(thr, ")");
24861 	duk_concat(thr, 3);
24862 }
24863 
24864 /*
24865  *  Functions
24866  */
24867 
24868 #if 0  /* not used yet */
24869 DUK_INTERNAL void duk_push_hnatfunc_name(duk_hthread *thr, duk_hnatfunc *h) {
24870 	duk_c_function func;
24871 
24872 	DUK_ASSERT_API_ENTRY(thr);
24873 	DUK_ASSERT(h != NULL);
24874 	DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h));
24875 
24876 	duk_push_sprintf(thr, "native_");
24877 	func = h->func;
24878 	duk_push_string_funcptr(thr, (duk_uint8_t *) &func, sizeof(func));
24879 	duk_push_sprintf(thr, "_%04x_%04x",
24880 	                 (unsigned int) (duk_uint16_t) h->nargs,
24881 	                 (unsigned int) (duk_uint16_t) h->magic);
24882 	duk_concat(thr, 3);
24883 }
24884 #endif
24885 
24886 /*
24887  *  duk_tval slice copy
24888  */
24889 
duk_copy_tvals_incref(duk_hthread * thr,duk_tval * tv_dst,duk_tval * tv_src,duk_size_t count)24890 DUK_INTERNAL void duk_copy_tvals_incref(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_size_t count) {
24891 	duk_tval *tv;
24892 
24893 	DUK_ASSERT_API_ENTRY(thr);
24894 	DUK_UNREF(thr);
24895 	DUK_ASSERT(count * sizeof(duk_tval) >= count);  /* no wrap */
24896 
24897 	duk_memcpy_unsafe((void *) tv_dst, (const void *) tv_src, count * sizeof(duk_tval));
24898 
24899 	tv = tv_dst;
24900 	while (count-- > 0) {
24901 		DUK_TVAL_INCREF(thr, tv);
24902 		tv++;
24903 	}
24904 }
24905 
24906 /* automatic undefs */
24907 #undef DUK__ASSERT_SPACE
24908 #undef DUK__CHECK_SPACE
24909 #undef DUK__ERROR_STASH_SHARED
24910 #undef DUK__PACK_ARGS
24911 #undef DUK__READABLE_ERRMSG_MAXCHARS
24912 #undef DUK__READABLE_STRING_MAXCHARS
24913 #undef DUK__READABLE_SUMMARY_MAXCHARS
24914 #line 1 "duk_api_string.c"
24915 /*
24916  *  String manipulation
24917  */
24918 
24919 /* #include duk_internal.h -> already included */
24920 
duk__concat_and_join_helper(duk_hthread * thr,duk_idx_t count_in,duk_bool_t is_join)24921 DUK_LOCAL void duk__concat_and_join_helper(duk_hthread *thr, duk_idx_t count_in, duk_bool_t is_join) {
24922 	duk_uint_t count;
24923 	duk_uint_t i;
24924 	duk_size_t idx;
24925 	duk_size_t len;
24926 	duk_hstring *h;
24927 	duk_uint8_t *buf;
24928 
24929 	DUK_CTX_ASSERT_VALID(thr);
24930 
24931 	if (DUK_UNLIKELY(count_in <= 0)) {
24932 		if (count_in < 0) {
24933 			DUK_ERROR_RANGE_INVALID_COUNT(thr);
24934 			DUK_WO_NORETURN(return;);
24935 		}
24936 		DUK_ASSERT(count_in == 0);
24937 		duk_push_hstring_empty(thr);
24938 		return;
24939 	}
24940 	count = (duk_uint_t) count_in;
24941 
24942 	if (is_join) {
24943 		duk_size_t t1, t2, limit;
24944 		h = duk_to_hstring(thr, -((duk_idx_t) count) - 1);
24945 		DUK_ASSERT(h != NULL);
24946 
24947 		/* A bit tricky overflow test, see doc/code-issues.rst. */
24948 		t1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
24949 		t2 = (duk_size_t) (count - 1);
24950 		limit = (duk_size_t) DUK_HSTRING_MAX_BYTELEN;
24951 		if (DUK_UNLIKELY(t2 != 0 && t1 > limit / t2)) {
24952 			/* Combined size of separators already overflows. */
24953 			goto error_overflow;
24954 		}
24955 		len = (duk_size_t) (t1 * t2);
24956 	} else {
24957 		len = (duk_size_t) 0;
24958 	}
24959 
24960 	for (i = count; i >= 1; i--) {
24961 		duk_size_t new_len;
24962 		h = duk_to_hstring(thr, -((duk_idx_t) i));
24963 		new_len = len + (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
24964 
24965 		/* Impose a string maximum length, need to handle overflow
24966 		 * correctly.
24967 		 */
24968 		if (new_len < len ||  /* wrapped */
24969 		    new_len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN) {
24970 			goto error_overflow;
24971 		}
24972 		len = new_len;
24973 	}
24974 
24975 	DUK_DDD(DUK_DDDPRINT("join/concat %lu strings, total length %lu bytes",
24976 	                     (unsigned long) count, (unsigned long) len));
24977 
24978 	/* Use stack allocated buffer to ensure reachability in errors
24979 	 * (e.g. intern error).
24980 	 */
24981 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len);
24982 	DUK_ASSERT(buf != NULL);
24983 
24984 	/* [ ... (sep) str1 str2 ... strN buf ] */
24985 
24986 	idx = 0;
24987 	for (i = count; i >= 1; i--) {
24988 		if (is_join && i != count) {
24989 			h = duk_require_hstring(thr, -((duk_idx_t) count) - 2);  /* extra -1 for buffer */
24990 			duk_memcpy(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
24991 			idx += DUK_HSTRING_GET_BYTELEN(h);
24992 		}
24993 		h = duk_require_hstring(thr, -((duk_idx_t) i) - 1);  /* extra -1 for buffer */
24994 		duk_memcpy(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
24995 		idx += DUK_HSTRING_GET_BYTELEN(h);
24996 	}
24997 
24998 	DUK_ASSERT(idx == len);
24999 
25000 	/* [ ... (sep) str1 str2 ... strN buf ] */
25001 
25002 	/* Get rid of the strings early to minimize memory use before intern. */
25003 
25004 	if (is_join) {
25005 		duk_replace(thr, -((duk_idx_t) count) - 2);  /* overwrite sep */
25006 		duk_pop_n(thr, (duk_idx_t) count);
25007 	} else {
25008 		duk_replace(thr, -((duk_idx_t) count) - 1);  /* overwrite str1 */
25009 		duk_pop_n(thr, (duk_idx_t) (count - 1));
25010 	}
25011 
25012 	/* [ ... buf ] */
25013 
25014 	(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */
25015 
25016 	/* [ ... res ] */
25017 	return;
25018 
25019  error_overflow:
25020 	DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
25021 	DUK_WO_NORETURN(return;);
25022 }
25023 
duk_concat(duk_hthread * thr,duk_idx_t count)25024 DUK_EXTERNAL void duk_concat(duk_hthread *thr, duk_idx_t count) {
25025 	DUK_ASSERT_API_ENTRY(thr);
25026 
25027 	duk__concat_and_join_helper(thr, count, 0 /*is_join*/);
25028 }
25029 
25030 #if defined(DUK_USE_PREFER_SIZE)
duk_concat_2(duk_hthread * thr)25031 DUK_INTERNAL void duk_concat_2(duk_hthread *thr) {
25032 	DUK_ASSERT_API_ENTRY(thr);
25033 	duk_concat(thr, 2);
25034 }
25035 #else  /* DUK_USE_PREFER_SIZE */
duk_concat_2(duk_hthread * thr)25036 DUK_INTERNAL void duk_concat_2(duk_hthread *thr) {
25037 	duk_hstring *h1;
25038 	duk_hstring *h2;
25039 	duk_uint8_t *buf;
25040 	duk_size_t len1;
25041 	duk_size_t len2;
25042 	duk_size_t len;
25043 
25044 	DUK_ASSERT_API_ENTRY(thr);
25045 	DUK_ASSERT(duk_get_top(thr) >= 2);  /* Trusted caller. */
25046 
25047 	h1 = duk_to_hstring(thr, -2);
25048 	h2 = duk_to_hstring(thr, -1);
25049 	len1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
25050 	len2 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
25051 	len = len1 + len2;
25052 	if (DUK_UNLIKELY(len < len1 ||  /* wrapped */
25053 	                 len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN)) {
25054 		goto error_overflow;
25055 	}
25056 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len);
25057 	DUK_ASSERT(buf != NULL);
25058 
25059 	duk_memcpy((void *) buf, (const void *) DUK_HSTRING_GET_DATA(h1), (size_t) len1);
25060 	duk_memcpy((void *) (buf + len1), (const void *) DUK_HSTRING_GET_DATA(h2), (size_t) len2);
25061 	(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */
25062 
25063 	/* [ ... str1 str2 buf ] */
25064 
25065 	duk_replace(thr, -3);
25066 	duk_pop_unsafe(thr);
25067 	return;
25068 
25069  error_overflow:
25070 	DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
25071 	DUK_WO_NORETURN(return;);
25072 }
25073 #endif  /* DUK_USE_PREFER_SIZE */
25074 
duk_join(duk_hthread * thr,duk_idx_t count)25075 DUK_EXTERNAL void duk_join(duk_hthread *thr, duk_idx_t count) {
25076 	DUK_ASSERT_API_ENTRY(thr);
25077 
25078 	duk__concat_and_join_helper(thr, count, 1 /*is_join*/);
25079 }
25080 
25081 /* XXX: could map/decode be unified with duk_unicode_support.c code?
25082  * Case conversion needs also the character surroundings though.
25083  */
25084 
duk_decode_string(duk_hthread * thr,duk_idx_t idx,duk_decode_char_function callback,void * udata)25085 DUK_EXTERNAL void duk_decode_string(duk_hthread *thr, duk_idx_t idx, duk_decode_char_function callback, void *udata) {
25086 	duk_hstring *h_input;
25087 	const duk_uint8_t *p, *p_start, *p_end;
25088 	duk_codepoint_t cp;
25089 
25090 	DUK_ASSERT_API_ENTRY(thr);
25091 
25092 	h_input = duk_require_hstring(thr, idx);  /* Accept symbols. */
25093 	DUK_ASSERT(h_input != NULL);
25094 
25095 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
25096 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
25097 	p = p_start;
25098 
25099 	for (;;) {
25100 		if (p >= p_end) {
25101 			break;
25102 		}
25103 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
25104 		callback(udata, cp);
25105 	}
25106 }
25107 
duk_map_string(duk_hthread * thr,duk_idx_t idx,duk_map_char_function callback,void * udata)25108 DUK_EXTERNAL void duk_map_string(duk_hthread *thr, duk_idx_t idx, duk_map_char_function callback, void *udata) {
25109 	duk_hstring *h_input;
25110 	duk_bufwriter_ctx bw_alloc;
25111 	duk_bufwriter_ctx *bw;
25112 	const duk_uint8_t *p, *p_start, *p_end;
25113 	duk_codepoint_t cp;
25114 
25115 	DUK_ASSERT_API_ENTRY(thr);
25116 
25117 	idx = duk_normalize_index(thr, idx);
25118 
25119 	h_input = duk_require_hstring(thr, idx);  /* Accept symbols. */
25120 	DUK_ASSERT(h_input != NULL);
25121 
25122 	bw = &bw_alloc;
25123 	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));  /* Reasonable output estimate. */
25124 
25125 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
25126 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
25127 	p = p_start;
25128 
25129 	for (;;) {
25130 		/* XXX: could write output in chunks with fewer ensure calls,
25131 		 * but relative benefit would be small here.
25132 		 */
25133 
25134 		if (p >= p_end) {
25135 			break;
25136 		}
25137 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
25138 		cp = callback(udata, cp);
25139 
25140 		DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
25141 	}
25142 
25143 	DUK_BW_COMPACT(thr, bw);
25144 	(void) duk_buffer_to_string(thr, -1);  /* Safe, extended UTF-8 encoded. */
25145 	duk_replace(thr, idx);
25146 }
25147 
duk_substring(duk_hthread * thr,duk_idx_t idx,duk_size_t start_offset,duk_size_t end_offset)25148 DUK_EXTERNAL void duk_substring(duk_hthread *thr, duk_idx_t idx, duk_size_t start_offset, duk_size_t end_offset) {
25149 	duk_hstring *h;
25150 	duk_hstring *res;
25151 	duk_size_t start_byte_offset;
25152 	duk_size_t end_byte_offset;
25153 	duk_size_t charlen;
25154 
25155 	DUK_ASSERT_API_ENTRY(thr);
25156 
25157 	idx = duk_require_normalize_index(thr, idx);  /* Accept symbols. */
25158 	h = duk_require_hstring(thr, idx);
25159 	DUK_ASSERT(h != NULL);
25160 
25161 	charlen = DUK_HSTRING_GET_CHARLEN(h);
25162 	if (end_offset >= charlen) {
25163 		end_offset = charlen;
25164 	}
25165 	if (start_offset > end_offset) {
25166 		start_offset = end_offset;
25167 	}
25168 
25169 	DUK_ASSERT_DISABLE(start_offset >= 0);
25170 	DUK_ASSERT(start_offset <= end_offset && start_offset <= DUK_HSTRING_GET_CHARLEN(h));
25171 	DUK_ASSERT_DISABLE(end_offset >= 0);
25172 	DUK_ASSERT(end_offset >= start_offset && end_offset <= DUK_HSTRING_GET_CHARLEN(h));
25173 
25174 	/* Guaranteed by string limits. */
25175 	DUK_ASSERT(start_offset <= DUK_UINT32_MAX);
25176 	DUK_ASSERT(end_offset <= DUK_UINT32_MAX);
25177 
25178 	start_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) start_offset);
25179 	end_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) end_offset);
25180 
25181 	DUK_ASSERT(end_byte_offset >= start_byte_offset);
25182 	DUK_ASSERT(end_byte_offset - start_byte_offset <= DUK_UINT32_MAX);  /* Guaranteed by string limits. */
25183 
25184 	/* No size check is necessary. */
25185 	res = duk_heap_strtable_intern_checked(thr,
25186 	                                       DUK_HSTRING_GET_DATA(h) + start_byte_offset,
25187 	                                       (duk_uint32_t) (end_byte_offset - start_byte_offset));
25188 
25189 	duk_push_hstring(thr, res);
25190 	duk_replace(thr, idx);
25191 }
25192 
25193 /* XXX: this is quite clunky.  Add Unicode helpers to scan backwards and
25194  * forwards with a callback to process codepoints?
25195  */
duk_trim(duk_hthread * thr,duk_idx_t idx)25196 DUK_EXTERNAL void duk_trim(duk_hthread *thr, duk_idx_t idx) {
25197 	duk_hstring *h;
25198 	const duk_uint8_t *p, *p_start, *p_end, *p_tmp1, *p_tmp2;  /* pointers for scanning */
25199 	const duk_uint8_t *q_start, *q_end;  /* start (incl) and end (excl) of trimmed part */
25200 	duk_codepoint_t cp;
25201 
25202 	DUK_ASSERT_API_ENTRY(thr);
25203 
25204 	idx = duk_require_normalize_index(thr, idx);  /* Accept symbols. */
25205 	h = duk_require_hstring(thr, idx);
25206 	DUK_ASSERT(h != NULL);
25207 
25208 	p_start = DUK_HSTRING_GET_DATA(h);
25209 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
25210 
25211 	p = p_start;
25212 	while (p < p_end) {
25213 		p_tmp1 = p;
25214 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp1, p_start, p_end);
25215 		if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {
25216 			break;
25217 		}
25218 		p = p_tmp1;
25219 	}
25220 	q_start = p;
25221 	if (p == p_end) {
25222 		/* Entire string is whitespace. */
25223 		q_end = p;
25224 		goto scan_done;
25225 	}
25226 
25227 	p = p_end;
25228 	while (p > p_start) {
25229 		p_tmp1 = p;
25230 		while (p > p_start) {
25231 			p--;
25232 			if (((*p) & 0xc0) != 0x80) {
25233 				break;
25234 			}
25235 		}
25236 		p_tmp2 = p;
25237 
25238 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp2, p_start, p_end);
25239 		if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {
25240 			p = p_tmp1;
25241 			break;
25242 		}
25243 	}
25244 	q_end = p;
25245 
25246  scan_done:
25247 	/* This may happen when forward and backward scanning disagree
25248 	 * (possible for non-extended-UTF-8 strings).
25249 	 */
25250 	if (q_end < q_start) {
25251 		q_end = q_start;
25252 	}
25253 
25254 	DUK_ASSERT(q_start >= p_start && q_start <= p_end);
25255 	DUK_ASSERT(q_end >= p_start && q_end <= p_end);
25256 	DUK_ASSERT(q_end >= q_start);
25257 
25258 	DUK_DDD(DUK_DDDPRINT("trim: p_start=%p, p_end=%p, q_start=%p, q_end=%p",
25259 	                     (const void *) p_start, (const void *) p_end,
25260 	                     (const void *) q_start, (const void *) q_end));
25261 
25262 	if (q_start == p_start && q_end == p_end) {
25263 		DUK_DDD(DUK_DDDPRINT("nothing was trimmed: avoid interning (hashing etc)"));
25264 		return;
25265 	}
25266 
25267 	duk_push_lstring(thr, (const char *) q_start, (duk_size_t) (q_end - q_start));
25268 	duk_replace(thr, idx);
25269 }
25270 
duk_char_code_at(duk_hthread * thr,duk_idx_t idx,duk_size_t char_offset)25271 DUK_EXTERNAL duk_codepoint_t duk_char_code_at(duk_hthread *thr, duk_idx_t idx, duk_size_t char_offset) {
25272 	duk_hstring *h;
25273 	duk_ucodepoint_t cp;
25274 
25275 	DUK_ASSERT_API_ENTRY(thr);
25276 
25277 	/* XXX: Share code with String.prototype.charCodeAt?  Main difference
25278 	 * is handling of clamped offsets.
25279 	 */
25280 
25281 	h = duk_require_hstring(thr, idx);  /* Accept symbols. */
25282 	DUK_ASSERT(h != NULL);
25283 
25284 	DUK_ASSERT_DISABLE(char_offset >= 0);  /* Always true, arg is unsigned. */
25285 	if (char_offset >= DUK_HSTRING_GET_CHARLEN(h)) {
25286 		return 0;
25287 	}
25288 
25289 	DUK_ASSERT(char_offset <= DUK_UINT_MAX);  /* Guaranteed by string limits. */
25290 	cp = duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) char_offset, 0 /*surrogate_aware*/);
25291 	return (duk_codepoint_t) cp;
25292 }
25293 #line 1 "duk_api_time.c"
25294 /*
25295  *  Date/time.
25296  */
25297 
25298 /* #include duk_internal.h -> already included */
25299 
duk_time_get_ecmascript_time(duk_hthread * thr)25300 DUK_INTERNAL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr) {
25301 	/* ECMAScript time, with millisecond fractions.  Exposed via
25302 	 * duk_get_now() for example.
25303 	 */
25304 	DUK_UNREF(thr);
25305 	return (duk_double_t) DUK_USE_DATE_GET_NOW(thr);
25306 }
25307 
duk_time_get_ecmascript_time_nofrac(duk_hthread * thr)25308 DUK_INTERNAL duk_double_t duk_time_get_ecmascript_time_nofrac(duk_hthread *thr) {
25309 	/* ECMAScript time without millisecond fractions.  Exposed via
25310 	 * the Date built-in which doesn't allow fractions.
25311 	 */
25312 	DUK_UNREF(thr);
25313 	return (duk_double_t) DUK_FLOOR(DUK_USE_DATE_GET_NOW(thr));
25314 }
25315 
duk_time_get_monotonic_time(duk_hthread * thr)25316 DUK_INTERNAL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr) {
25317 	DUK_UNREF(thr);
25318 #if defined(DUK_USE_GET_MONOTONIC_TIME)
25319 	return (duk_double_t) DUK_USE_GET_MONOTONIC_TIME(thr);
25320 #else
25321 	return (duk_double_t) DUK_USE_DATE_GET_NOW(thr);
25322 #endif
25323 }
25324 
duk_get_now(duk_hthread * thr)25325 DUK_EXTERNAL duk_double_t duk_get_now(duk_hthread *thr) {
25326 	DUK_ASSERT_API_ENTRY(thr);
25327 	DUK_UNREF(thr);
25328 
25329 	/* This API intentionally allows millisecond fractions. */
25330 	return duk_time_get_ecmascript_time(thr);
25331 }
25332 
25333 #if 0  /* XXX: worth exposing? */
25334 DUK_EXTERNAL duk_double_t duk_get_monotonic_time(duk_hthread *thr) {
25335 	DUK_ASSERT_API_ENTRY(thr);
25336 	DUK_UNREF(thr);
25337 
25338 	return duk_time_get_monotonic_time(thr);
25339 }
25340 #endif
25341 
duk_time_to_components(duk_hthread * thr,duk_double_t timeval,duk_time_components * comp)25342 DUK_EXTERNAL void duk_time_to_components(duk_hthread *thr, duk_double_t timeval, duk_time_components *comp) {
25343 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
25344 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
25345 	duk_uint_t flags;
25346 
25347 	DUK_ASSERT_API_ENTRY(thr);
25348 	DUK_ASSERT(comp != NULL);  /* XXX: or check? */
25349 	DUK_UNREF(thr);
25350 
25351 	/* Convert as one-based, but change month to zero-based to match the
25352 	 * ECMAScript Date built-in behavior 1:1.
25353 	 */
25354 	flags = DUK_DATE_FLAG_ONEBASED | DUK_DATE_FLAG_NAN_TO_ZERO;
25355 
25356 	duk_bi_date_timeval_to_parts(timeval, parts, dparts, flags);
25357 
25358 	/* XXX: sub-millisecond accuracy for the API */
25359 
25360 	DUK_ASSERT(dparts[DUK_DATE_IDX_MONTH] >= 1.0 && dparts[DUK_DATE_IDX_MONTH] <= 12.0);
25361 	comp->year = dparts[DUK_DATE_IDX_YEAR];
25362 	comp->month = dparts[DUK_DATE_IDX_MONTH] - 1.0;
25363 	comp->day = dparts[DUK_DATE_IDX_DAY];
25364 	comp->hours = dparts[DUK_DATE_IDX_HOUR];
25365 	comp->minutes = dparts[DUK_DATE_IDX_MINUTE];
25366 	comp->seconds = dparts[DUK_DATE_IDX_SECOND];
25367 	comp->milliseconds = dparts[DUK_DATE_IDX_MILLISECOND];
25368 	comp->weekday = dparts[DUK_DATE_IDX_WEEKDAY];
25369 }
25370 
duk_components_to_time(duk_hthread * thr,duk_time_components * comp)25371 DUK_EXTERNAL duk_double_t duk_components_to_time(duk_hthread *thr, duk_time_components *comp) {
25372 	duk_double_t d;
25373 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
25374 	duk_uint_t flags;
25375 
25376 	DUK_ASSERT_API_ENTRY(thr);
25377 	DUK_ASSERT(comp != NULL);  /* XXX: or check? */
25378 	DUK_UNREF(thr);
25379 
25380 	/* Match Date constructor behavior (with UTC time).  Month is given
25381 	 * as zero-based.  Day-of-month is given as one-based so normalize
25382 	 * it to zero-based as the internal conversion helpers expects all
25383 	 * components to be zero-based.
25384 	 */
25385 	flags = 0;
25386 
25387 	/* XXX: expensive conversion; use array format in API instead, or unify
25388 	 * time provider and time API to use same struct?
25389 	 */
25390 
25391 	dparts[DUK_DATE_IDX_YEAR] = comp->year;
25392 	dparts[DUK_DATE_IDX_MONTH] = comp->month;
25393 	dparts[DUK_DATE_IDX_DAY] = comp->day - 1.0;
25394 	dparts[DUK_DATE_IDX_HOUR] = comp->hours;
25395 	dparts[DUK_DATE_IDX_MINUTE] = comp->minutes;
25396 	dparts[DUK_DATE_IDX_SECOND] = comp->seconds;
25397 	dparts[DUK_DATE_IDX_MILLISECOND] = comp->milliseconds;
25398 	dparts[DUK_DATE_IDX_WEEKDAY] = 0;  /* ignored */
25399 
25400 	d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
25401 
25402 	return d;
25403 }
25404 #line 1 "duk_bi_array.c"
25405 /*
25406  *  Array built-ins
25407  *
25408  *  Most Array built-ins are intentionally generic in ECMAScript, and are
25409  *  intended to work even when the 'this' binding is not an Array instance.
25410  *  This ECMAScript feature is also used by much real world code.  For this
25411  *  reason the implementations here don't assume exotic Array behavior or
25412  *  e.g. presence of a .length property.  However, some algorithms have a
25413  *  fast path for duk_harray backed actual Array instances, enabled when
25414  *  footprint is not a concern.
25415  *
25416  *  XXX: the "Throw" flag should be set for (almost?) all [[Put]] and
25417  *  [[Delete]] operations, but it's currently false throughout.  Go through
25418  *  all put/delete cases and check throw flag use.  Need a new API primitive
25419  *  which allows throws flag to be specified.
25420  *
25421  *  XXX: array lengths above 2G won't work reliably.  There are many places
25422  *  where one needs a full signed 32-bit range ([-0xffffffff, 0xffffffff],
25423  *  i.e. -33- bits).  Although array 'length' cannot be written to be outside
25424  *  the unsigned 32-bit range (E5.1 Section 15.4.5.1 throws a RangeError if so)
25425  *  some intermediate values may be above 0xffffffff and this may not be always
25426  *  correctly handled now (duk_uint32_t is not enough for all algorithms).
25427  *  For instance, push() can legitimately write entries beyond length 0xffffffff
25428  *  and cause a RangeError only at the end.  To do this properly, the current
25429  *  push() implementation tracks the array index using a 'double' instead of a
25430  *  duk_uint32_t (which is somewhat awkward).  See test-bi-array-push-maxlen.js.
25431  *
25432  *  On using "put" vs. "def" prop
25433  *  =============================
25434  *
25435  *  Code below must be careful to use the appropriate primitive as it matters
25436  *  for compliance.  When using "put" there may be inherited properties in
25437  *  Array.prototype which cause side effects when values are written.  When
25438  *  using "define" there are no such side effects, and many test262 test cases
25439  *  check for this (for real world code, such side effects are very rare).
25440  *  Both "put" and "define" are used in the E5.1 specification; as a rule,
25441  *  "put" is used when modifying an existing array (or a non-array 'this'
25442  *  binding) and "define" for setting values into a fresh result array.
25443  */
25444 
25445 /* #include duk_internal.h -> already included */
25446 
25447 /* Perform an intermediate join when this many elements have been pushed
25448  * on the value stack.
25449  */
25450 #define  DUK__ARRAY_MID_JOIN_LIMIT  4096
25451 
25452 #if defined(DUK_USE_ARRAY_BUILTIN)
25453 
25454 /*
25455  *  Shared helpers.
25456  */
25457 
25458 /* Shared entry code for many Array built-ins: the 'this' binding is pushed
25459  * on the value stack and object coerced, and the current .length is returned.
25460  * Note that length is left on stack (it could be popped, but that's not
25461  * usually necessary because call handling will clean it up automatically).
25462  */
duk__push_this_obj_len_u32(duk_hthread * thr)25463 DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32(duk_hthread *thr) {
25464 	duk_uint32_t len;
25465 
25466 	/* XXX: push more directly? */
25467 	(void) duk_push_this_coercible_to_object(thr);
25468 	DUK_HOBJECT_ASSERT_VALID(duk_get_hobject(thr, -1));
25469 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_LENGTH);
25470 	len = duk_to_uint32(thr, -1);
25471 
25472 	/* -> [ ... ToObject(this) ToUint32(length) ] */
25473 	return len;
25474 }
25475 
duk__push_this_obj_len_u32_limited(duk_hthread * thr)25476 DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32_limited(duk_hthread *thr) {
25477 	/* Range limited to [0, 0x7fffffff] range, i.e. range that can be
25478 	 * represented with duk_int32_t.  Use this when the method doesn't
25479 	 * handle the full 32-bit unsigned range correctly.
25480 	 */
25481 	duk_uint32_t ret = duk__push_this_obj_len_u32(thr);
25482 	if (DUK_UNLIKELY(ret >= 0x80000000UL)) {
25483 		DUK_ERROR_RANGE_INVALID_LENGTH(thr);
25484 		DUK_WO_NORETURN(return 0U;);
25485 	}
25486 	return ret;
25487 }
25488 
25489 #if defined(DUK_USE_ARRAY_FASTPATH)
25490 /* Check if 'this' binding is an Array instance (duk_harray) which satisfies
25491  * a few other guarantees for fast path operation.  The fast path doesn't
25492  * need to handle all operations, even for duk_harrays, but must handle a
25493  * significant fraction to improve performance.  Return a non-NULL duk_harray
25494  * pointer when all fast path criteria are met, NULL otherwise.
25495  */
duk__arraypart_fastpath_this(duk_hthread * thr)25496 DUK_LOCAL duk_harray *duk__arraypart_fastpath_this(duk_hthread *thr) {
25497 	duk_tval *tv;
25498 	duk_hobject *h;
25499 	duk_uint_t flags_mask, flags_bits, flags_value;
25500 
25501 	DUK_ASSERT(thr->valstack_bottom > thr->valstack);  /* because call in progress */
25502 	tv = DUK_GET_THIS_TVAL_PTR(thr);
25503 
25504 	/* Fast path requires that 'this' is a duk_harray.  Read only arrays
25505 	 * (ROM backed) are also rejected for simplicity.
25506 	 */
25507 	if (!DUK_TVAL_IS_OBJECT(tv)) {
25508 		DUK_DD(DUK_DDPRINT("reject array fast path: not an object"));
25509 		return NULL;
25510 	}
25511 	h = DUK_TVAL_GET_OBJECT(tv);
25512 	DUK_ASSERT(h != NULL);
25513 	flags_mask = DUK_HOBJECT_FLAG_ARRAY_PART | \
25514 	             DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
25515 	             DUK_HEAPHDR_FLAG_READONLY;
25516 	flags_bits = DUK_HOBJECT_FLAG_ARRAY_PART | \
25517 	             DUK_HOBJECT_FLAG_EXOTIC_ARRAY;
25518 	flags_value = DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) h);
25519 	if ((flags_value & flags_mask) != flags_bits) {
25520 		DUK_DD(DUK_DDPRINT("reject array fast path: object flag check failed"));
25521 		return NULL;
25522 	}
25523 
25524 	/* In some cases a duk_harray's 'length' may be larger than the
25525 	 * current array part allocation.  Avoid the fast path in these
25526 	 * cases, so that all fast path code can safely assume that all
25527 	 * items in the range [0,length[ are backed by the current array
25528 	 * part allocation.
25529 	 */
25530 	if (((duk_harray *) h)->length > DUK_HOBJECT_GET_ASIZE(h)) {
25531 		DUK_DD(DUK_DDPRINT("reject array fast path: length > array part size"));
25532 		return NULL;
25533 	}
25534 
25535 	/* Guarantees for fast path. */
25536 	DUK_ASSERT(h != NULL);
25537 	DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0 || DUK_HOBJECT_A_GET_BASE(thr->heap, h) != NULL);
25538 	DUK_ASSERT(((duk_harray *) h)->length <= DUK_HOBJECT_GET_ASIZE(h));
25539 
25540 	DUK_DD(DUK_DDPRINT("array fast path allowed for: %!O", (duk_heaphdr *) h));
25541 	return (duk_harray *) h;
25542 }
25543 #endif  /* DUK_USE_ARRAY_FASTPATH */
25544 
25545 /*
25546  *  Constructor
25547  */
25548 
duk_bi_array_constructor(duk_hthread * thr)25549 DUK_INTERNAL duk_ret_t duk_bi_array_constructor(duk_hthread *thr) {
25550 	duk_idx_t nargs;
25551 	duk_harray *a;
25552 	duk_double_t d;
25553 	duk_uint32_t len;
25554 	duk_uint32_t len_prealloc;
25555 
25556 	nargs = duk_get_top(thr);
25557 
25558 	if (nargs == 1 && duk_is_number(thr, 0)) {
25559 		/* XXX: expensive check (also shared elsewhere - so add a shared internal API call?) */
25560 		d = duk_get_number(thr, 0);
25561 		len = duk_to_uint32(thr, 0);
25562 		if (!duk_double_equals((duk_double_t) len, d)) {
25563 			DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
25564 		}
25565 
25566 		/* For small lengths create a dense preallocated array.
25567 		 * For large arrays preallocate an initial part.
25568 		 */
25569 		len_prealloc = len < 64 ? len : 64;
25570 		a = duk_push_harray_with_size(thr, len_prealloc);
25571 		DUK_ASSERT(a != NULL);
25572 		DUK_ASSERT(!duk_is_bare_object(thr, -1));
25573 		a->length = len;
25574 		return 1;
25575 	}
25576 
25577 	duk_pack(thr, nargs);
25578 	return 1;
25579 }
25580 
25581 /*
25582  *  isArray()
25583  */
25584 
duk_bi_array_constructor_is_array(duk_hthread * thr)25585 DUK_INTERNAL duk_ret_t duk_bi_array_constructor_is_array(duk_hthread *thr) {
25586 	DUK_ASSERT_TOP(thr, 1);
25587 	duk_push_boolean(thr, duk_js_isarray(DUK_GET_TVAL_POSIDX(thr, 0)));
25588 	return 1;
25589 }
25590 
25591 /*
25592  *  toString()
25593  */
25594 
duk_bi_array_prototype_to_string(duk_hthread * thr)25595 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_to_string(duk_hthread *thr) {
25596 	(void) duk_push_this_coercible_to_object(thr);
25597 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_JOIN);
25598 
25599 	/* [ ... this func ] */
25600 	if (!duk_is_callable(thr, -1)) {
25601 		/* Fall back to the initial (original) Object.toString().  We don't
25602 		 * currently have pointers to the built-in functions, only the top
25603 		 * level global objects (like "Array") so this is now done in a bit
25604 		 * of a hacky manner.  It would be cleaner to push the (original)
25605 		 * function and use duk_call_method().
25606 		 */
25607 
25608 		/* XXX: 'this' will be ToObject() coerced twice, which is incorrect
25609 		 * but should have no visible side effects.
25610 		 */
25611 		DUK_DDD(DUK_DDDPRINT("this.join is not callable, fall back to (original) Object.toString"));
25612 		duk_set_top(thr, 0);
25613 		return duk_bi_object_prototype_to_string(thr);  /* has access to 'this' binding */
25614 	}
25615 
25616 	/* [ ... this func ] */
25617 
25618 	duk_insert(thr, -2);
25619 
25620 	/* [ ... func this ] */
25621 
25622 	DUK_DDD(DUK_DDDPRINT("calling: func=%!iT, this=%!iT",
25623 	                     (duk_tval *) duk_get_tval(thr, -2),
25624 	                     (duk_tval *) duk_get_tval(thr, -1)));
25625 	duk_call_method(thr, 0);
25626 
25627 	return 1;
25628 }
25629 
25630 /*
25631  *  concat()
25632  */
25633 
duk_bi_array_prototype_concat(duk_hthread * thr)25634 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_concat(duk_hthread *thr) {
25635 	duk_idx_t i, n;
25636 	duk_uint32_t j, idx, len;
25637 	duk_hobject *h;
25638 	duk_size_t tmp_len;
25639 
25640 	/* XXX: In ES2015 Array .length can be up to 2^53-1.  The current
25641 	 * implementation is limited to 2^32-1.
25642 	 */
25643 
25644 	/* XXX: Fast path for array 'this' and array element. */
25645 
25646 	/* XXX: The insert here is a bit expensive if there are a lot of items.
25647 	 * It could also be special cased in the outermost for loop quite easily
25648 	 * (as the element is dup()'d anyway).
25649 	 */
25650 
25651 	(void) duk_push_this_coercible_to_object(thr);
25652 	duk_insert(thr, 0);
25653 	n = duk_get_top(thr);
25654 	duk_push_array(thr);  /* -> [ ToObject(this) item1 ... itemN arr ] */
25655 
25656 	/* NOTE: The Array special behaviors are NOT invoked by duk_xdef_prop_index()
25657 	 * (which differs from the official algorithm).  If no error is thrown, this
25658 	 * doesn't matter as the length is updated at the end.  However, if an error
25659 	 * is thrown, the length will be unset.  That shouldn't matter because the
25660 	 * caller won't get a reference to the intermediate value.
25661 	 */
25662 
25663 	idx = 0;
25664 	for (i = 0; i < n; i++) {
25665 		duk_bool_t spreadable;
25666 		duk_bool_t need_has_check;
25667 
25668 		DUK_ASSERT_TOP(thr, n + 1);
25669 
25670 		/* [ ToObject(this) item1 ... itemN arr ] */
25671 
25672 		h = duk_get_hobject(thr, i);
25673 
25674 		if (h == NULL) {
25675 			spreadable = 0;
25676 		} else {
25677 #if defined(DUK_USE_SYMBOL_BUILTIN)
25678 			duk_get_prop_stridx(thr, i, DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE);
25679 			if (duk_is_undefined(thr, -1)) {
25680 				spreadable = duk_js_isarray_hobject(h);
25681 			} else {
25682 				spreadable = duk_to_boolean(thr, -1);
25683 			}
25684 			duk_pop_nodecref_unsafe(thr);
25685 #else
25686 			spreadable = duk_js_isarray_hobject(h);
25687 #endif
25688 		}
25689 
25690 		if (!spreadable) {
25691 			duk_dup(thr, i);
25692 			duk_xdef_prop_index_wec(thr, -2, idx);
25693 			idx++;
25694 			if (DUK_UNLIKELY(idx == 0U)) {
25695 				/* Index after update is 0, and index written
25696 				 * was 0xffffffffUL which is no longer a valid
25697 				 * array index.
25698 				 */
25699 				goto fail_wrap;
25700 			}
25701 			continue;
25702 		}
25703 
25704 		DUK_ASSERT(duk_is_object(thr, i));
25705 		need_has_check = (DUK_HOBJECT_IS_PROXY(h) != 0);  /* Always 0 w/o Proxy support. */
25706 
25707 		/* [ ToObject(this) item1 ... itemN arr ] */
25708 
25709 		tmp_len = duk_get_length(thr, i);
25710 		len = (duk_uint32_t) tmp_len;
25711 		if (DUK_UNLIKELY(tmp_len != (duk_size_t) len)) {
25712 			goto fail_wrap;
25713 		}
25714 		if (DUK_UNLIKELY(idx + len < idx)) {
25715 			/* Result length must be at most 0xffffffffUL to be
25716 			 * a valid 32-bit array index.
25717 			 */
25718 			goto fail_wrap;
25719 		}
25720 		for (j = 0; j < len; j++) {
25721 			/* For a Proxy element, an explicit 'has' check is
25722 			 * needed to allow the Proxy to present gaps.
25723 			 */
25724 			if (need_has_check) {
25725 				if (duk_has_prop_index(thr, i, j)) {
25726 					duk_get_prop_index(thr, i, j);
25727 					duk_xdef_prop_index_wec(thr, -2, idx);
25728 				}
25729 			} else {
25730 				if (duk_get_prop_index(thr, i, j)) {
25731 					duk_xdef_prop_index_wec(thr, -2, idx);
25732 				} else {
25733 					duk_pop_undefined(thr);
25734 				}
25735 			}
25736 			idx++;
25737 			DUK_ASSERT(idx != 0U);  /* Wrap check above. */
25738 		}
25739 	}
25740 
25741 	/* ES5.1 has a specification "bug" in that nonexistent trailing
25742 	 * elements don't affect the result .length.  Test262 and other
25743 	 * engines disagree, and the specification bug was fixed in ES2015
25744 	 * (see NOTE 1 in https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.concat).
25745 	 */
25746 	duk_push_uarridx(thr, idx);
25747 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
25748 
25749 	DUK_ASSERT_TOP(thr, n + 1);
25750 	return 1;
25751 
25752  fail_wrap:
25753 	DUK_ERROR_RANGE_INVALID_LENGTH(thr);
25754 	DUK_WO_NORETURN(return 0;);
25755 }
25756 
25757 /*
25758  *  join(), toLocaleString()
25759  *
25760  *  Note: checking valstack is necessary, but only in the per-element loop.
25761  *
25762  *  Note: the trivial approach of pushing all the elements on the value stack
25763  *  and then calling duk_join() fails when the array contains a large number
25764  *  of elements.  This problem can't be offloaded to duk_join() because the
25765  *  elements to join must be handled here and have special handling.  Current
25766  *  approach is to do intermediate joins with very large number of elements.
25767  *  There is no fancy handling; the prefix gets re-joined multiple times.
25768  */
25769 
duk_bi_array_prototype_join_shared(duk_hthread * thr)25770 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_join_shared(duk_hthread *thr) {
25771 	duk_uint32_t len, count;
25772 	duk_uint32_t idx;
25773 	duk_small_int_t to_locale_string = duk_get_current_magic(thr);
25774 	duk_idx_t valstack_required;
25775 
25776 	/* For join(), nargs is 1.  For toLocaleString(), nargs is 0 and
25777 	 * setting the top essentially pushes an undefined to the stack,
25778 	 * thus defaulting to a comma separator.
25779 	 */
25780 	duk_set_top(thr, 1);
25781 	if (duk_is_undefined(thr, 0)) {
25782 		duk_pop_undefined(thr);
25783 		duk_push_hstring_stridx(thr, DUK_STRIDX_COMMA);
25784 	} else {
25785 		duk_to_string(thr, 0);
25786 	}
25787 
25788 	len = duk__push_this_obj_len_u32(thr);
25789 
25790 	/* [ sep ToObject(this) len ] */
25791 
25792 	DUK_DDD(DUK_DDDPRINT("sep=%!T, this=%!T, len=%lu",
25793 	                     (duk_tval *) duk_get_tval(thr, 0),
25794 	                     (duk_tval *) duk_get_tval(thr, 1),
25795 	                     (unsigned long) len));
25796 
25797 	/* The extra (+4) is tight. */
25798 	valstack_required = (duk_idx_t) ((len >= DUK__ARRAY_MID_JOIN_LIMIT ?
25799 	                                  DUK__ARRAY_MID_JOIN_LIMIT : len) + 4);
25800 	duk_require_stack(thr, valstack_required);
25801 
25802 	duk_dup_0(thr);
25803 
25804 	/* [ sep ToObject(this) len sep ] */
25805 
25806 	count = 0;
25807 	idx = 0;
25808 	for (;;) {
25809 		DUK_DDD(DUK_DDDPRINT("join idx=%ld", (long) idx));
25810 		if (count >= DUK__ARRAY_MID_JOIN_LIMIT ||   /* intermediate join to avoid valstack overflow */
25811 		    idx >= len) { /* end of loop (careful with len==0) */
25812 			/* [ sep ToObject(this) len sep str0 ... str(count-1) ] */
25813 			DUK_DDD(DUK_DDDPRINT("mid/final join, count=%ld, idx=%ld, len=%ld",
25814 			                     (long) count, (long) idx, (long) len));
25815 			duk_join(thr, (duk_idx_t) count);  /* -> [ sep ToObject(this) len str ] */
25816 			duk_dup_0(thr);                    /* -> [ sep ToObject(this) len str sep ] */
25817 			duk_insert(thr, -2);               /* -> [ sep ToObject(this) len sep str ] */
25818 			count = 1;
25819 		}
25820 		if (idx >= len) {
25821 			/* if true, the stack already contains the final result */
25822 			break;
25823 		}
25824 
25825 		duk_get_prop_index(thr, 1, (duk_uarridx_t) idx);
25826 		if (duk_is_null_or_undefined(thr, -1)) {
25827 			duk_pop_nodecref_unsafe(thr);
25828 			duk_push_hstring_empty(thr);
25829 		} else {
25830 			if (to_locale_string) {
25831 				duk_to_object(thr, -1);
25832 				duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_LOCALE_STRING);
25833 				duk_insert(thr, -2);  /* -> [ ... toLocaleString ToObject(val) ] */
25834 				duk_call_method(thr, 0);
25835 			}
25836 			duk_to_string(thr, -1);
25837 		}
25838 
25839 		count++;
25840 		idx++;
25841 	}
25842 
25843 	/* [ sep ToObject(this) len sep result ] */
25844 
25845 	return 1;
25846 }
25847 
25848 /*
25849  *  pop(), push()
25850  */
25851 
25852 #if defined(DUK_USE_ARRAY_FASTPATH)
duk__array_pop_fastpath(duk_hthread * thr,duk_harray * h_arr)25853 DUK_LOCAL duk_ret_t duk__array_pop_fastpath(duk_hthread *thr, duk_harray *h_arr) {
25854 	duk_tval *tv_arraypart;
25855 	duk_tval *tv_val;
25856 	duk_uint32_t len;
25857 
25858 	tv_arraypart = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) h_arr);
25859 	len = h_arr->length;
25860 	if (len <= 0) {
25861 		/* nop, return undefined */
25862 		return 0;
25863 	}
25864 
25865 	len--;
25866 	h_arr->length = len;
25867 
25868 	/* Fast path doesn't check for an index property inherited from
25869 	 * Array.prototype.  This is quite often acceptable; if not,
25870 	 * disable fast path.
25871 	 */
25872 	DUK_ASSERT_VS_SPACE(thr);
25873 	tv_val = tv_arraypart + len;
25874 	if (DUK_TVAL_IS_UNUSED(tv_val)) {
25875 		/* No net refcount change.  Value stack already has
25876 		 * 'undefined' based on value stack init policy.
25877 		 */
25878 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
25879 		DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv_val));
25880 	} else {
25881 		/* No net refcount change. */
25882 		DUK_TVAL_SET_TVAL(thr->valstack_top, tv_val);
25883 		DUK_TVAL_SET_UNUSED(tv_val);
25884 	}
25885 	thr->valstack_top++;
25886 
25887 	/* XXX: there's no shrink check in the fast path now */
25888 
25889 	return 1;
25890 }
25891 #endif  /* DUK_USE_ARRAY_FASTPATH */
25892 
duk_bi_array_prototype_pop(duk_hthread * thr)25893 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_pop(duk_hthread *thr) {
25894 	duk_uint32_t len;
25895 	duk_uint32_t idx;
25896 #if defined(DUK_USE_ARRAY_FASTPATH)
25897 	duk_harray *h_arr;
25898 #endif
25899 
25900 	DUK_ASSERT_TOP(thr, 0);
25901 
25902 #if defined(DUK_USE_ARRAY_FASTPATH)
25903 	h_arr = duk__arraypart_fastpath_this(thr);
25904 	if (h_arr) {
25905 		return duk__array_pop_fastpath(thr, h_arr);
25906 	}
25907 #endif
25908 
25909 	/* XXX: Merge fastpath check into a related call (push this, coerce length, etc)? */
25910 
25911 	len = duk__push_this_obj_len_u32(thr);
25912 	if (len == 0) {
25913 		duk_push_int(thr, 0);
25914 		duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
25915 		return 0;
25916 	}
25917 	idx = len - 1;
25918 
25919 	duk_get_prop_index(thr, 0, (duk_uarridx_t) idx);
25920 	duk_del_prop_index(thr, 0, (duk_uarridx_t) idx);
25921 	duk_push_u32(thr, idx);
25922 	duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
25923 	return 1;
25924 }
25925 
25926 #if defined(DUK_USE_ARRAY_FASTPATH)
duk__array_push_fastpath(duk_hthread * thr,duk_harray * h_arr)25927 DUK_LOCAL duk_ret_t duk__array_push_fastpath(duk_hthread *thr, duk_harray *h_arr) {
25928 	duk_tval *tv_arraypart;
25929 	duk_tval *tv_src;
25930 	duk_tval *tv_dst;
25931 	duk_uint32_t len;
25932 	duk_idx_t i, n;
25933 
25934 	len = h_arr->length;
25935 	tv_arraypart = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) h_arr);
25936 
25937 	n = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
25938 	DUK_ASSERT(n >= 0);
25939 	DUK_ASSERT((duk_uint32_t) n <= DUK_UINT32_MAX);
25940 	if (DUK_UNLIKELY(len + (duk_uint32_t) n < len)) {
25941 		DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
25942 		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);  /* != 0 return value returned as is by caller */
25943 	}
25944 	if (len + (duk_uint32_t) n > DUK_HOBJECT_GET_ASIZE((duk_hobject *) h_arr)) {
25945 		/* Array part would need to be extended.  Rely on slow path
25946 		 * for now.
25947 		 *
25948 		 * XXX: Rework hobject code a bit and add extend support.
25949 		 */
25950 		return 0;
25951 	}
25952 
25953 	tv_src = thr->valstack_bottom;
25954 	tv_dst = tv_arraypart + len;
25955 	for (i = 0; i < n; i++) {
25956 		/* No net refcount change; reset value stack values to
25957 		 * undefined to satisfy value stack init policy.
25958 		 */
25959 		DUK_TVAL_SET_TVAL(tv_dst, tv_src);
25960 		DUK_TVAL_SET_UNDEFINED(tv_src);
25961 		tv_src++;
25962 		tv_dst++;
25963 	}
25964 	thr->valstack_top = thr->valstack_bottom;
25965 	len += (duk_uint32_t) n;
25966 	h_arr->length = len;
25967 
25968 	DUK_ASSERT((duk_uint_t) len == len);
25969 	duk_push_uint(thr, (duk_uint_t) len);
25970 	return 1;
25971 }
25972 #endif  /* DUK_USE_ARRAY_FASTPATH */
25973 
duk_bi_array_prototype_push(duk_hthread * thr)25974 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_push(duk_hthread *thr) {
25975 	/* Note: 'this' is not necessarily an Array object.  The push()
25976 	 * algorithm is supposed to work for other kinds of objects too,
25977 	 * so the algorithm has e.g. an explicit update for the 'length'
25978 	 * property which is normally "magical" in arrays.
25979 	 */
25980 
25981 	duk_uint32_t len;
25982 	duk_idx_t i, n;
25983 #if defined(DUK_USE_ARRAY_FASTPATH)
25984 	duk_harray *h_arr;
25985 #endif
25986 
25987 #if defined(DUK_USE_ARRAY_FASTPATH)
25988 	h_arr = duk__arraypart_fastpath_this(thr);
25989 	if (h_arr) {
25990 		duk_ret_t rc;
25991 		rc = duk__array_push_fastpath(thr, h_arr);
25992 		if (rc != 0) {
25993 			return rc;
25994 		}
25995 		DUK_DD(DUK_DDPRINT("array push() fast path exited, resize case"));
25996 	}
25997 #endif
25998 
25999 	n = duk_get_top(thr);
26000 	len = duk__push_this_obj_len_u32(thr);
26001 
26002 	/* [ arg1 ... argN obj length ] */
26003 
26004 	/* Technically Array.prototype.push() can create an Array with length
26005 	 * longer than 2^32-1, i.e. outside the 32-bit range.  The final length
26006 	 * is *not* wrapped to 32 bits in the specification.
26007 	 *
26008 	 * This implementation tracks length with a uint32 because it's much
26009 	 * more practical.
26010 	 *
26011 	 * See: test-bi-array-push-maxlen.js.
26012 	 */
26013 
26014 	if (len + (duk_uint32_t) n < len) {
26015 		DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
26016 		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
26017 	}
26018 
26019 	for (i = 0; i < n; i++) {
26020 		duk_dup(thr, i);
26021 		duk_put_prop_index(thr, -3, (duk_uarridx_t) (len + (duk_uint32_t) i));
26022 	}
26023 	len += (duk_uint32_t) n;
26024 
26025 	duk_push_u32(thr, len);
26026 	duk_dup_top(thr);
26027 	duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);
26028 
26029 	/* [ arg1 ... argN obj length new_length ] */
26030 	return 1;
26031 }
26032 
26033 /*
26034  *  sort()
26035  *
26036  *  Currently qsort with random pivot.  This is now really, really slow,
26037  *  because there is no fast path for array parts.
26038  *
26039  *  Signed indices are used because qsort() leaves and degenerate cases
26040  *  may use a negative offset.
26041  */
26042 
duk__array_sort_compare(duk_hthread * thr,duk_int_t idx1,duk_int_t idx2)26043 DUK_LOCAL duk_small_int_t duk__array_sort_compare(duk_hthread *thr, duk_int_t idx1, duk_int_t idx2) {
26044 	duk_bool_t have1, have2;
26045 	duk_bool_t undef1, undef2;
26046 	duk_small_int_t ret;
26047 	duk_idx_t idx_obj = 1;  /* fixed offsets in valstack */
26048 	duk_idx_t idx_fn = 0;
26049 	duk_hstring *h1, *h2;
26050 
26051 	/* Fast exit if indices are identical.  This is valid for a non-existent property,
26052 	 * for an undefined value, and almost always for ToString() coerced comparison of
26053 	 * arbitrary values (corner cases where this is not the case include e.g. a an
26054 	 * object with varying ToString() coercion).
26055 	 *
26056 	 * The specification does not prohibit "caching" of values read from the array, so
26057 	 * assuming equality for comparing an index with itself falls into the category of
26058 	 * "caching".
26059 	 *
26060 	 * Also, compareFn may be inconsistent, so skipping a call to compareFn here may
26061 	 * have an effect on the final result.  The specification does not require any
26062 	 * specific behavior for inconsistent compare functions, so again, this fast path
26063 	 * is OK.
26064 	 */
26065 
26066 	if (idx1 == idx2) {
26067 		DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld -> indices identical, quick exit",
26068 		                     (long) idx1, (long) idx2));
26069 		return 0;
26070 	}
26071 
26072 	have1 = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) idx1);
26073 	have2 = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) idx2);
26074 
26075 	DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld, have1=%ld, have2=%ld, val1=%!T, val2=%!T",
26076 	                     (long) idx1, (long) idx2, (long) have1, (long) have2,
26077 	                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
26078 
26079 	if (have1) {
26080 		if (have2) {
26081 			;
26082 		} else {
26083 			ret = -1;
26084 			goto pop_ret;
26085 		}
26086 	} else {
26087 		if (have2) {
26088 			ret = 1;
26089 			goto pop_ret;
26090 		} else {
26091 			ret = 0;
26092 			goto pop_ret;
26093 		}
26094 	}
26095 
26096 	undef1 = duk_is_undefined(thr, -2);
26097 	undef2 = duk_is_undefined(thr, -1);
26098 	if (undef1) {
26099 		if (undef2) {
26100 			ret = 0;
26101 			goto pop_ret;
26102 		} else {
26103 			ret = 1;
26104 			goto pop_ret;
26105 		}
26106 	} else {
26107 		if (undef2) {
26108 			ret = -1;
26109 			goto pop_ret;
26110 		} else {
26111 			;
26112 		}
26113 	}
26114 
26115 	if (!duk_is_undefined(thr, idx_fn)) {
26116 		duk_double_t d;
26117 
26118 		/* No need to check callable; duk_call() will do that. */
26119 		duk_dup(thr, idx_fn);    /* -> [ ... x y fn ] */
26120 		duk_insert(thr, -3);     /* -> [ ... fn x y ] */
26121 		duk_call(thr, 2);        /* -> [ ... res ] */
26122 
26123 		/* ES5 is a bit vague about what to do if the return value is
26124 		 * not a number.  ES2015 provides a concrete description:
26125 		 * http://www.ecma-international.org/ecma-262/6.0/#sec-sortcompare.
26126 		 */
26127 
26128 		d = duk_to_number_m1(thr);
26129 		if (d < 0.0) {
26130 			ret = -1;
26131 		} else if (d > 0.0) {
26132 			ret = 1;
26133 		} else {
26134 			/* Because NaN compares to false, NaN is handled here
26135 			 * without an explicit check above.
26136 			 */
26137 			ret = 0;
26138 		}
26139 
26140 		duk_pop_nodecref_unsafe(thr);
26141 		DUK_DDD(DUK_DDDPRINT("-> result %ld (from comparefn, after coercion)", (long) ret));
26142 		return ret;
26143 	}
26144 
26145 	/* string compare is the default (a bit oddly) */
26146 
26147 	/* XXX: any special handling for plain array; causes repeated coercion now? */
26148 	h1 = duk_to_hstring(thr, -2);
26149 	h2 = duk_to_hstring_m1(thr);
26150 	DUK_ASSERT(h1 != NULL);
26151 	DUK_ASSERT(h2 != NULL);
26152 
26153 	ret = duk_js_string_compare(h1, h2);  /* retval is directly usable */
26154 	goto pop_ret;
26155 
26156  pop_ret:
26157 	duk_pop_2_unsafe(thr);
26158 	DUK_DDD(DUK_DDDPRINT("-> result %ld", (long) ret));
26159 	return ret;
26160 }
26161 
duk__array_sort_swap(duk_hthread * thr,duk_int_t l,duk_int_t r)26162 DUK_LOCAL void duk__array_sort_swap(duk_hthread *thr, duk_int_t l, duk_int_t r) {
26163 	duk_bool_t have_l, have_r;
26164 	duk_idx_t idx_obj = 1;  /* fixed offset in valstack */
26165 
26166 	if (l == r) {
26167 		return;
26168 	}
26169 
26170 	/* swap elements; deal with non-existent elements correctly */
26171 	have_l = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) l);
26172 	have_r = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) r);
26173 
26174 	if (have_r) {
26175 		/* right exists, [[Put]] regardless whether or not left exists */
26176 		duk_put_prop_index(thr, idx_obj, (duk_uarridx_t) l);
26177 	} else {
26178 		duk_del_prop_index(thr, idx_obj, (duk_uarridx_t) l);
26179 		duk_pop_undefined(thr);
26180 	}
26181 
26182 	if (have_l) {
26183 		duk_put_prop_index(thr, idx_obj, (duk_uarridx_t) r);
26184 	} else {
26185 		duk_del_prop_index(thr, idx_obj, (duk_uarridx_t) r);
26186 		duk_pop_undefined(thr);
26187 	}
26188 }
26189 
26190 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
26191 /* 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)26192 DUK_LOCAL void duk__debuglog_qsort_state(duk_hthread *thr, duk_int_t lo, duk_int_t hi, duk_int_t pivot) {
26193 	char buf[4096];
26194 	char *ptr = buf;
26195 	duk_int_t i, n;
26196 	n = (duk_int_t) duk_get_length(thr, 1);
26197 	if (n > 4000) {
26198 		n = 4000;
26199 	}
26200 	*ptr++ = '[';
26201 	for (i = 0; i < n; i++) {
26202 		if (i == pivot) {
26203 			*ptr++ = '|';
26204 		} else if (i == lo) {
26205 			*ptr++ = '<';
26206 		} else if (i == hi) {
26207 			*ptr++ = '>';
26208 		} else if (i >= lo && i <= hi) {
26209 			*ptr++ = '-';
26210 		} else {
26211 			*ptr++ = ' ';
26212 		}
26213 	}
26214 	*ptr++ = ']';
26215 	*ptr++ = '\0';
26216 
26217 	DUK_DDD(DUK_DDDPRINT("%s   (lo=%ld, hi=%ld, pivot=%ld)",
26218 	                     (const char *) buf, (long) lo, (long) hi, (long) pivot));
26219 }
26220 #endif
26221 
duk__array_qsort(duk_hthread * thr,duk_int_t lo,duk_int_t hi)26222 DUK_LOCAL void duk__array_qsort(duk_hthread *thr, duk_int_t lo, duk_int_t hi) {
26223 	duk_int_t p, l, r;
26224 
26225 	/* The lo/hi indices may be crossed and hi < 0 is possible at entry. */
26226 
26227 	DUK_DDD(DUK_DDDPRINT("duk__array_qsort: lo=%ld, hi=%ld, obj=%!T",
26228 	                     (long) lo, (long) hi, (duk_tval *) duk_get_tval(thr, 1)));
26229 
26230 	DUK_ASSERT_TOP(thr, 3);
26231 
26232 	/* In some cases it may be that lo > hi, or hi < 0; these
26233 	 * degenerate cases happen e.g. for empty arrays, and in
26234 	 * recursion leaves.
26235 	 */
26236 
26237 	/* trivial cases */
26238 	if (hi - lo < 1) {
26239 		DUK_DDD(DUK_DDDPRINT("degenerate case, return immediately"));
26240 		return;
26241 	}
26242 	DUK_ASSERT(hi > lo);
26243 	DUK_ASSERT(hi - lo + 1 >= 2);
26244 
26245 	/* randomized pivot selection */
26246 	p = lo + (duk_int_t) (DUK_UTIL_GET_RANDOM_DOUBLE(thr) * (duk_double_t) (hi - lo + 1));
26247 	DUK_ASSERT(p >= lo && p <= hi);
26248 	DUK_DDD(DUK_DDDPRINT("lo=%ld, hi=%ld, chose pivot p=%ld", (long) lo, (long) hi, (long) p));
26249 
26250 	/* move pivot out of the way */
26251 	duk__array_sort_swap(thr, p, lo);
26252 	p = lo;
26253 	DUK_DDD(DUK_DDDPRINT("pivot moved out of the way: %!T", (duk_tval *) duk_get_tval(thr, 1)));
26254 
26255 	l = lo + 1;
26256 	r = hi;
26257 	for (;;) {
26258 		/* find elements to swap */
26259 		for (;;) {
26260 			DUK_DDD(DUK_DDDPRINT("left scan: l=%ld, r=%ld, p=%ld",
26261 			                     (long) l, (long) r, (long) p));
26262 			if (l >= hi) {
26263 				break;
26264 			}
26265 			if (duk__array_sort_compare(thr, l, p) >= 0) {  /* !(l < p) */
26266 				break;
26267 			}
26268 			l++;
26269 		}
26270 		for (;;) {
26271 			DUK_DDD(DUK_DDDPRINT("right scan: l=%ld, r=%ld, p=%ld",
26272 			                     (long) l, (long) r, (long) p));
26273 			if (r <= lo) {
26274 				break;
26275 			}
26276 			if (duk__array_sort_compare(thr, p, r) >= 0) {  /* !(p < r) */
26277 				break;
26278 			}
26279 			r--;
26280 		}
26281 		if (l >= r) {
26282 			goto done;
26283 		}
26284 		DUK_ASSERT(l < r);
26285 
26286 		DUK_DDD(DUK_DDDPRINT("swap %ld and %ld", (long) l, (long) r));
26287 
26288 		duk__array_sort_swap(thr, l, r);
26289 
26290 		DUK_DDD(DUK_DDDPRINT("after swap: %!T", (duk_tval *) duk_get_tval(thr, 1)));
26291 		l++;
26292 		r--;
26293 	}
26294  done:
26295 	/* Note that 'l' and 'r' may cross, i.e. r < l */
26296 	DUK_ASSERT(l >= lo && l <= hi);
26297 	DUK_ASSERT(r >= lo && r <= hi);
26298 
26299 	/* XXX: there's no explicit recursion bound here now.  For the average
26300 	 * qsort recursion depth O(log n) that's not really necessary: e.g. for
26301 	 * 2**32 recursion depth would be about 32 which is OK.  However, qsort
26302 	 * worst case recursion depth is O(n) which may be a problem.
26303 	 */
26304 
26305 	/* move pivot to its final place */
26306 	DUK_DDD(DUK_DDDPRINT("before final pivot swap: %!T", (duk_tval *) duk_get_tval(thr, 1)));
26307 	duk__array_sort_swap(thr, lo, r);
26308 
26309 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
26310 	duk__debuglog_qsort_state(thr, lo, hi, r);
26311 #endif
26312 
26313 	DUK_DDD(DUK_DDDPRINT("recurse: pivot=%ld, obj=%!T", (long) r, (duk_tval *) duk_get_tval(thr, 1)));
26314 	duk__array_qsort(thr, lo, r - 1);
26315 	duk__array_qsort(thr, r + 1, hi);
26316 }
26317 
duk_bi_array_prototype_sort(duk_hthread * thr)26318 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_sort(duk_hthread *thr) {
26319 	duk_uint32_t len;
26320 
26321 	/* XXX: len >= 0x80000000 won't work below because a signed type
26322 	 * is needed by qsort.
26323 	 */
26324 	len = duk__push_this_obj_len_u32_limited(thr);
26325 
26326 	/* stack[0] = compareFn
26327 	 * stack[1] = ToObject(this)
26328 	 * stack[2] = ToUint32(length)
26329 	 */
26330 
26331 	if (len > 0) {
26332 		/* avoid degenerate cases, so that (len - 1) won't underflow */
26333 		duk__array_qsort(thr, (duk_int_t) 0, (duk_int_t) (len - 1));
26334 	}
26335 
26336 	DUK_ASSERT_TOP(thr, 3);
26337 	duk_pop_nodecref_unsafe(thr);
26338 	return 1;  /* return ToObject(this) */
26339 }
26340 
26341 /*
26342  *  splice()
26343  */
26344 
26345 /* XXX: this compiles to over 500 bytes now, even without special handling
26346  * for an array part.  Uses signed ints so does not handle full array range correctly.
26347  */
26348 
26349 /* XXX: can shift() / unshift() use the same helper?
26350  *   shift() is (close to?) <--> splice(0, 1)
26351  *   unshift is (close to?) <--> splice(0, 0, [items])?
26352  */
26353 
duk_bi_array_prototype_splice(duk_hthread * thr)26354 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_splice(duk_hthread *thr) {
26355 	duk_idx_t nargs;
26356 	duk_uint32_t len_u32;
26357 	duk_int_t len;
26358 	duk_bool_t have_delcount;
26359 	duk_int_t item_count;
26360 	duk_int_t act_start;
26361 	duk_int_t del_count;
26362 	duk_int_t i, n;
26363 
26364 	DUK_UNREF(have_delcount);
26365 
26366 	nargs = duk_get_top(thr);
26367 	if (nargs < 2) {
26368 		duk_set_top(thr, 2);
26369 		nargs = 2;
26370 		have_delcount = 0;
26371 	} else {
26372 		have_delcount = 1;
26373 	}
26374 
26375 	/* XXX: len >= 0x80000000 won't work below because we need to be
26376 	 * able to represent -len.
26377 	 */
26378 	len_u32 = duk__push_this_obj_len_u32_limited(thr);
26379 	len = (duk_int_t) len_u32;
26380 	DUK_ASSERT(len >= 0);
26381 
26382 	act_start = duk_to_int_clamped(thr, 0, -len, len);
26383 	if (act_start < 0) {
26384 		act_start = len + act_start;
26385 	}
26386 	DUK_ASSERT(act_start >= 0 && act_start <= len);
26387 
26388 #if defined(DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT)
26389 	if (have_delcount) {
26390 #endif
26391 		del_count = duk_to_int_clamped(thr, 1, 0, len - act_start);
26392 #if defined(DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT)
26393 	} else {
26394 		/* E5.1 standard behavior when deleteCount is not given would be
26395 		 * to treat it just like if 'undefined' was given, which coerces
26396 		 * ultimately to 0.  Real world behavior is to splice to the end
26397 		 * of array, see test-bi-array-proto-splice-no-delcount.js.
26398 		 */
26399 		del_count = len - act_start;
26400 	}
26401 #endif
26402 
26403 	DUK_ASSERT(nargs >= 2);
26404 	item_count = (duk_int_t) (nargs - 2);
26405 
26406 	DUK_ASSERT(del_count >= 0 && del_count <= len - act_start);
26407 	DUK_ASSERT(del_count + act_start <= len);
26408 
26409 	/* For now, restrict result array into 32-bit length range. */
26410 	if (((duk_double_t) len) - ((duk_double_t) del_count) + ((duk_double_t) item_count) > (duk_double_t) DUK_UINT32_MAX) {
26411 		DUK_D(DUK_DPRINT("Array.prototype.splice() would go beyond 32-bit length, throw"));
26412 		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
26413 	}
26414 
26415 	duk_push_array(thr);
26416 
26417 	/* stack[0] = start
26418 	 * stack[1] = deleteCount
26419 	 * stack[2...nargs-1] = items
26420 	 * stack[nargs] = ToObject(this)               -3
26421 	 * stack[nargs+1] = ToUint32(length)           -2
26422 	 * stack[nargs+2] = result array               -1
26423 	 */
26424 
26425 	DUK_ASSERT_TOP(thr, nargs + 3);
26426 
26427 	/* Step 9: copy elements-to-be-deleted into the result array */
26428 
26429 	for (i = 0; i < del_count; i++) {
26430 		if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (act_start + i))) {
26431 			duk_xdef_prop_index_wec(thr, -2, (duk_uarridx_t) i);  /* throw flag irrelevant (false in std alg) */
26432 		} else {
26433 			duk_pop_undefined(thr);
26434 		}
26435 	}
26436 	duk_push_u32(thr, (duk_uint32_t) del_count);
26437 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
26438 
26439 	/* Steps 12 and 13: reorganize elements to make room for itemCount elements */
26440 
26441 	if (item_count < del_count) {
26442 		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 1
26443 		 * -> [ A B F G H ]          (conceptual intermediate step)
26444 		 * -> [ A B . F G H ]        (placeholder marked)
26445 		 *    [ A B C F G H ]        (actual result at this point, C will be replaced)
26446 		 */
26447 
26448 		DUK_ASSERT_TOP(thr, nargs + 3);
26449 
26450 		n = len - del_count;
26451 		for (i = act_start; i < n; i++) {
26452 			if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (i + del_count))) {
26453 				duk_put_prop_index(thr, -4, (duk_uarridx_t) (i + item_count));
26454 			} else {
26455 				duk_pop_undefined(thr);
26456 				duk_del_prop_index(thr, -3, (duk_uarridx_t) (i + item_count));
26457 			}
26458 		}
26459 
26460 		DUK_ASSERT_TOP(thr, nargs + 3);
26461 
26462 		/* loop iterator init and limit changed from standard algorithm */
26463 		n = len - del_count + item_count;
26464 		for (i = len - 1; i >= n; i--) {
26465 			duk_del_prop_index(thr, -3, (duk_uarridx_t) i);
26466 		}
26467 
26468 		DUK_ASSERT_TOP(thr, nargs + 3);
26469 	} else if (item_count > del_count) {
26470 		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 4
26471 		 * -> [ A B F G H ]          (conceptual intermediate step)
26472 		 * -> [ A B . . . . F G H ]  (placeholder marked)
26473 		 *    [ A B C D E F F G H ]  (actual result at this point)
26474 		 */
26475 
26476 		DUK_ASSERT_TOP(thr, nargs + 3);
26477 
26478 		/* loop iterator init and limit changed from standard algorithm */
26479 		for (i = len - del_count - 1; i >= act_start; i--) {
26480 			if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (i + del_count))) {
26481 				duk_put_prop_index(thr, -4, (duk_uarridx_t) (i + item_count));
26482 			} else {
26483 				duk_pop_undefined(thr);
26484 				duk_del_prop_index(thr, -3, (duk_uarridx_t) (i + item_count));
26485 			}
26486 		}
26487 
26488 		DUK_ASSERT_TOP(thr, nargs + 3);
26489 	} else {
26490 		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 3
26491 		 * -> [ A B F G H ]          (conceptual intermediate step)
26492 		 * -> [ A B . . . F G H ]    (placeholder marked)
26493 		 *    [ A B C D E F G H ]    (actual result at this point)
26494 		 */
26495 	}
26496 	DUK_ASSERT_TOP(thr, nargs + 3);
26497 
26498 	/* Step 15: insert itemCount elements into the hole made above */
26499 
26500 	for (i = 0; i < item_count; i++) {
26501 		duk_dup(thr, i + 2);  /* args start at index 2 */
26502 		duk_put_prop_index(thr, -4, (duk_uarridx_t) (act_start + i));
26503 	}
26504 
26505 	/* Step 16: update length; note that the final length may be above 32 bit range
26506 	 * (but we checked above that this isn't the case here)
26507 	 */
26508 
26509 	duk_push_u32(thr, (duk_uint32_t) (len - del_count + item_count));
26510 	duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);
26511 
26512 	/* result array is already at the top of stack */
26513 	DUK_ASSERT_TOP(thr, nargs + 3);
26514 	return 1;
26515 }
26516 
26517 /*
26518  *  reverse()
26519  */
26520 
duk_bi_array_prototype_reverse(duk_hthread * thr)26521 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reverse(duk_hthread *thr) {
26522 	duk_uint32_t len;
26523 	duk_uint32_t middle;
26524 	duk_uint32_t lower, upper;
26525 	duk_bool_t have_lower, have_upper;
26526 
26527 	len = duk__push_this_obj_len_u32(thr);
26528 	middle = len / 2;
26529 
26530 	/* If len <= 1, middle will be 0 and for-loop bails out
26531 	 * immediately (0 < 0 -> false).
26532 	 */
26533 
26534 	for (lower = 0; lower < middle; lower++) {
26535 		DUK_ASSERT(len >= 2);
26536 		DUK_ASSERT_TOP(thr, 2);
26537 
26538 		DUK_ASSERT(len >= lower + 1);
26539 		upper = len - lower - 1;
26540 
26541 		have_lower = duk_get_prop_index(thr, -2, (duk_uarridx_t) lower);
26542 		have_upper = duk_get_prop_index(thr, -3, (duk_uarridx_t) upper);
26543 
26544 		/* [ ToObject(this) ToUint32(length) lowerValue upperValue ] */
26545 
26546 		if (have_upper) {
26547 			duk_put_prop_index(thr, -4, (duk_uarridx_t) lower);
26548 		} else {
26549 			duk_del_prop_index(thr, -4, (duk_uarridx_t) lower);
26550 			duk_pop_undefined(thr);
26551 		}
26552 
26553 		if (have_lower) {
26554 			duk_put_prop_index(thr, -3, (duk_uarridx_t) upper);
26555 		} else {
26556 			duk_del_prop_index(thr, -3, (duk_uarridx_t) upper);
26557 			duk_pop_undefined(thr);
26558 		}
26559 
26560 		DUK_ASSERT_TOP(thr, 2);
26561 	}
26562 
26563 	DUK_ASSERT_TOP(thr, 2);
26564 	duk_pop_unsafe(thr);  /* -> [ ToObject(this) ] */
26565 	return 1;
26566 }
26567 
26568 /*
26569  *  slice()
26570  */
26571 
duk_bi_array_prototype_slice(duk_hthread * thr)26572 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_slice(duk_hthread *thr) {
26573 	duk_uint32_t len_u32;
26574 	duk_int_t len;
26575 	duk_int_t start, end;
26576 	duk_int_t i;
26577 	duk_uarridx_t idx;
26578 	duk_uint32_t res_length = 0;
26579 
26580 	/* XXX: len >= 0x80000000 won't work below because we need to be
26581 	 * able to represent -len.
26582 	 */
26583 	len_u32 = duk__push_this_obj_len_u32_limited(thr);
26584 	len = (duk_int_t) len_u32;
26585 	DUK_ASSERT(len >= 0);
26586 
26587 	duk_push_array(thr);
26588 
26589 	/* stack[0] = start
26590 	 * stack[1] = end
26591 	 * stack[2] = ToObject(this)
26592 	 * stack[3] = ToUint32(length)
26593 	 * stack[4] = result array
26594 	 */
26595 
26596 	start = duk_to_int_clamped(thr, 0, -len, len);
26597 	if (start < 0) {
26598 		start = len + start;
26599 	}
26600 	/* XXX: could duk_is_undefined() provide defaulting undefined to 'len'
26601 	 * (the upper limit)?
26602 	 */
26603 	if (duk_is_undefined(thr, 1)) {
26604 		end = len;
26605 	} else {
26606 		end = duk_to_int_clamped(thr, 1, -len, len);
26607 		if (end < 0) {
26608 			end = len + end;
26609 		}
26610 	}
26611 	DUK_ASSERT(start >= 0 && start <= len);
26612 	DUK_ASSERT(end >= 0 && end <= len);
26613 
26614 	idx = 0;
26615 	for (i = start; i < end; i++) {
26616 		DUK_ASSERT_TOP(thr, 5);
26617 		if (duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
26618 			duk_xdef_prop_index_wec(thr, 4, idx);
26619 			res_length = idx + 1;
26620 		} else {
26621 			duk_pop_undefined(thr);
26622 		}
26623 		idx++;
26624 		DUK_ASSERT_TOP(thr, 5);
26625 	}
26626 
26627 	duk_push_u32(thr, res_length);
26628 	duk_xdef_prop_stridx_short(thr, 4, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
26629 
26630 	DUK_ASSERT_TOP(thr, 5);
26631 	return 1;
26632 }
26633 
26634 /*
26635  *  shift()
26636  */
26637 
duk_bi_array_prototype_shift(duk_hthread * thr)26638 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_shift(duk_hthread *thr) {
26639 	duk_uint32_t len;
26640 	duk_uint32_t i;
26641 
26642 	len = duk__push_this_obj_len_u32(thr);
26643 	if (len == 0) {
26644 		duk_push_int(thr, 0);
26645 		duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
26646 		return 0;
26647 	}
26648 
26649 	duk_get_prop_index(thr, 0, 0);
26650 
26651 	/* stack[0] = object (this)
26652 	 * stack[1] = ToUint32(length)
26653 	 * stack[2] = elem at index 0 (retval)
26654 	 */
26655 
26656 	for (i = 1; i < len; i++) {
26657 		DUK_ASSERT_TOP(thr, 3);
26658 		if (duk_get_prop_index(thr, 0, (duk_uarridx_t) i)) {
26659 			/* fromPresent = true */
26660 			duk_put_prop_index(thr, 0, (duk_uarridx_t) (i - 1));
26661 		} else {
26662 			/* fromPresent = false */
26663 			duk_del_prop_index(thr, 0, (duk_uarridx_t) (i - 1));
26664 			duk_pop_undefined(thr);
26665 		}
26666 	}
26667 	duk_del_prop_index(thr, 0, (duk_uarridx_t) (len - 1));
26668 
26669 	duk_push_u32(thr, (duk_uint32_t) (len - 1));
26670 	duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
26671 
26672 	DUK_ASSERT_TOP(thr, 3);
26673 	return 1;
26674 }
26675 
26676 /*
26677  *  unshift()
26678  */
26679 
duk_bi_array_prototype_unshift(duk_hthread * thr)26680 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_unshift(duk_hthread *thr) {
26681 	duk_idx_t nargs;
26682 	duk_uint32_t len;
26683 	duk_uint32_t i;
26684 
26685 	nargs = duk_get_top(thr);
26686 	len = duk__push_this_obj_len_u32(thr);
26687 
26688 	/* stack[0...nargs-1] = unshift args (vararg)
26689 	 * stack[nargs] = ToObject(this)
26690 	 * stack[nargs+1] = ToUint32(length)
26691 	 */
26692 
26693 	DUK_ASSERT_TOP(thr, nargs + 2);
26694 
26695 	/* Note: unshift() may operate on indices above unsigned 32-bit range
26696 	 * and the final length may be >= 2**32.  However, we restrict the
26697 	 * final result to 32-bit range for practicality.
26698 	 */
26699 
26700 	if (len + (duk_uint32_t) nargs < len) {
26701 		DUK_D(DUK_DPRINT("Array.prototype.unshift() would go beyond 32-bit length, throw"));
26702 		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
26703 	}
26704 
26705 	i = len;
26706 	while (i > 0) {
26707 		DUK_ASSERT_TOP(thr, nargs + 2);
26708 		i--;
26709 		/* k+argCount-1; note that may be above 32-bit range */
26710 
26711 		if (duk_get_prop_index(thr, -2, (duk_uarridx_t) i)) {
26712 			/* fromPresent = true */
26713 			/* [ ... ToObject(this) ToUint32(length) val ] */
26714 			duk_put_prop_index(thr, -3, (duk_uarridx_t) (i + (duk_uint32_t) nargs));  /* -> [ ... ToObject(this) ToUint32(length) ] */
26715 		} else {
26716 			/* fromPresent = false */
26717 			/* [ ... ToObject(this) ToUint32(length) val ] */
26718 			duk_pop_undefined(thr);
26719 			duk_del_prop_index(thr, -2, (duk_uarridx_t) (i + (duk_uint32_t) nargs));  /* -> [ ... ToObject(this) ToUint32(length) ] */
26720 		}
26721 		DUK_ASSERT_TOP(thr, nargs + 2);
26722 	}
26723 
26724 	for (i = 0; i < (duk_uint32_t) nargs; i++) {
26725 		DUK_ASSERT_TOP(thr, nargs + 2);
26726 		duk_dup(thr, (duk_idx_t) i);  /* -> [ ... ToObject(this) ToUint32(length) arg[i] ] */
26727 		duk_put_prop_index(thr, -3, (duk_uarridx_t) i);
26728 		DUK_ASSERT_TOP(thr, nargs + 2);
26729 	}
26730 
26731 	DUK_ASSERT_TOP(thr, nargs + 2);
26732 	duk_push_u32(thr, len + (duk_uint32_t) nargs);
26733 	duk_dup_top(thr);  /* -> [ ... ToObject(this) ToUint32(length) final_len final_len ] */
26734 	duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);
26735 	return 1;
26736 }
26737 
26738 /*
26739  *  indexOf(), lastIndexOf()
26740  */
26741 
duk_bi_array_prototype_indexof_shared(duk_hthread * thr)26742 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_hthread *thr) {
26743 	duk_idx_t nargs;
26744 	duk_int_t i, len;
26745 	duk_int_t from_idx;
26746 	duk_small_int_t idx_step = duk_get_current_magic(thr);  /* idx_step is +1 for indexOf, -1 for lastIndexOf */
26747 
26748 	/* lastIndexOf() needs to be a vararg function because we must distinguish
26749 	 * between an undefined fromIndex and a "not given" fromIndex; indexOf() is
26750 	 * made vararg for symmetry although it doesn't strictly need to be.
26751 	 */
26752 
26753 	nargs = duk_get_top(thr);
26754 	duk_set_top(thr, 2);
26755 
26756 	/* XXX: must be able to represent -len */
26757 	len = (duk_int_t) duk__push_this_obj_len_u32_limited(thr);
26758 	if (len == 0) {
26759 		goto not_found;
26760 	}
26761 
26762 	/* Index clamping is a bit tricky, we must ensure that we'll only iterate
26763 	 * through elements that exist and that the specific requirements from E5.1
26764 	 * Sections 15.4.4.14 and 15.4.4.15 are fulfilled; especially:
26765 	 *
26766 	 *   - indexOf: clamp to [-len,len], negative handling -> [0,len],
26767 	 *     if clamped result is len, for-loop bails out immediately
26768 	 *
26769 	 *   - lastIndexOf: clamp to [-len-1, len-1], negative handling -> [-1, len-1],
26770 	 *     if clamped result is -1, for-loop bails out immediately
26771 	 *
26772 	 * If fromIndex is not given, ToInteger(undefined) = 0, which is correct
26773 	 * for indexOf() but incorrect for lastIndexOf().  Hence special handling,
26774 	 * and why lastIndexOf() needs to be a vararg function.
26775 	 */
26776 
26777 	if (nargs >= 2) {
26778 		/* indexOf: clamp fromIndex to [-len, len]
26779 		 * (if fromIndex == len, for-loop terminates directly)
26780 		 *
26781 		 * lastIndexOf: clamp fromIndex to [-len - 1, len - 1]
26782 		 * (if clamped to -len-1 -> fromIndex becomes -1, terminates for-loop directly)
26783 		 */
26784 		from_idx = duk_to_int_clamped(thr,
26785 		                              1,
26786 		                              (idx_step > 0 ? -len : -len - 1),
26787 		                              (idx_step > 0 ? len : len - 1));
26788 		if (from_idx < 0) {
26789 			/* for lastIndexOf, result may be -1 (mark immediate termination) */
26790 			from_idx = len + from_idx;
26791 		}
26792 	} else {
26793 		/* for indexOf, ToInteger(undefined) would be 0, i.e. correct, but
26794 		 * handle both indexOf and lastIndexOf specially here.
26795 		 */
26796 		if (idx_step > 0) {
26797 			from_idx = 0;
26798 		} else {
26799 			from_idx = len - 1;
26800 		}
26801 	}
26802 
26803 	/* stack[0] = searchElement
26804 	 * stack[1] = fromIndex
26805 	 * stack[2] = object
26806 	 * stack[3] = length (not needed, but not popped above)
26807 	 */
26808 
26809 	for (i = from_idx; i >= 0 && i < len; i += idx_step) {
26810 		DUK_ASSERT_TOP(thr, 4);
26811 
26812 		if (duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
26813 			DUK_ASSERT_TOP(thr, 5);
26814 			if (duk_strict_equals(thr, 0, 4)) {
26815 				duk_push_int(thr, i);
26816 				return 1;
26817 			}
26818 		}
26819 
26820 		duk_pop_unsafe(thr);
26821 	}
26822 
26823  not_found:
26824 	duk_push_int(thr, -1);
26825 	return 1;
26826 }
26827 
26828 /*
26829  *  every(), some(), forEach(), map(), filter()
26830  */
26831 
26832 #define DUK__ITER_EVERY    0
26833 #define DUK__ITER_SOME     1
26834 #define DUK__ITER_FOREACH  2
26835 #define DUK__ITER_MAP      3
26836 #define DUK__ITER_FILTER   4
26837 
26838 /* XXX: This helper is a bit awkward because the handling for the different iteration
26839  * callers is quite different.  This now compiles to a bit less than 500 bytes, so with
26840  * 5 callers the net result is about 100 bytes / caller.
26841  */
26842 
duk_bi_array_prototype_iter_shared(duk_hthread * thr)26843 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_iter_shared(duk_hthread *thr) {
26844 	duk_uint32_t len;
26845 	duk_uint32_t i;
26846 	duk_uarridx_t k;
26847 	duk_bool_t bval;
26848 	duk_small_int_t iter_type = duk_get_current_magic(thr);
26849 	duk_uint32_t res_length = 0;
26850 
26851 	/* each call this helper serves has nargs==2 */
26852 	DUK_ASSERT_TOP(thr, 2);
26853 
26854 	len = duk__push_this_obj_len_u32(thr);
26855 	duk_require_callable(thr, 0);
26856 	/* if thisArg not supplied, behave as if undefined was supplied */
26857 
26858 	if (iter_type == DUK__ITER_MAP || iter_type == DUK__ITER_FILTER) {
26859 		duk_push_array(thr);
26860 	} else {
26861 		duk_push_undefined(thr);
26862 	}
26863 
26864 	/* stack[0] = callback
26865 	 * stack[1] = thisArg
26866 	 * stack[2] = object
26867 	 * stack[3] = ToUint32(length)  (unused, but avoid unnecessary pop)
26868 	 * stack[4] = result array (or undefined)
26869 	 */
26870 
26871 	k = 0;  /* result index for filter() */
26872 	for (i = 0; i < len; i++) {
26873 		DUK_ASSERT_TOP(thr, 5);
26874 
26875 		if (!duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
26876 			/* For 'map' trailing missing elements don't invoke the
26877 			 * callback but count towards the result length.
26878 			 */
26879 			if (iter_type == DUK__ITER_MAP) {
26880 				res_length = i + 1;
26881 			}
26882 			duk_pop_undefined(thr);
26883 			continue;
26884 		}
26885 
26886 		/* The original value needs to be preserved for filter(), hence
26887 		 * this funny order.  We can't re-get the value because of side
26888 		 * effects.
26889 		 */
26890 
26891 		duk_dup_0(thr);
26892 		duk_dup_1(thr);
26893 		duk_dup_m3(thr);
26894 		duk_push_u32(thr, i);
26895 		duk_dup_2(thr);  /* [ ... val callback thisArg val i obj ] */
26896 		duk_call_method(thr, 3); /* -> [ ... val retval ] */
26897 
26898 		switch (iter_type) {
26899 		case DUK__ITER_EVERY:
26900 			bval = duk_to_boolean(thr, -1);
26901 			if (!bval) {
26902 				/* stack top contains 'false' */
26903 				return 1;
26904 			}
26905 			break;
26906 		case DUK__ITER_SOME:
26907 			bval = duk_to_boolean(thr, -1);
26908 			if (bval) {
26909 				/* stack top contains 'true' */
26910 				return 1;
26911 			}
26912 			break;
26913 		case DUK__ITER_FOREACH:
26914 			/* nop */
26915 			break;
26916 		case DUK__ITER_MAP:
26917 			duk_dup_top(thr);
26918 			duk_xdef_prop_index_wec(thr, 4, (duk_uarridx_t) i);  /* retval to result[i] */
26919 			res_length = i + 1;
26920 			break;
26921 		case DUK__ITER_FILTER:
26922 			bval = duk_to_boolean(thr, -1);
26923 			if (bval) {
26924 				duk_dup_m2(thr);  /* orig value */
26925 				duk_xdef_prop_index_wec(thr, 4, (duk_uarridx_t) k);
26926 				k++;
26927 				res_length = k;
26928 			}
26929 			break;
26930 		default:
26931 			DUK_UNREACHABLE();
26932 			break;
26933 		}
26934 		duk_pop_2_unsafe(thr);
26935 
26936 		DUK_ASSERT_TOP(thr, 5);
26937 	}
26938 
26939 	switch (iter_type) {
26940 	case DUK__ITER_EVERY:
26941 		duk_push_true(thr);
26942 		break;
26943 	case DUK__ITER_SOME:
26944 		duk_push_false(thr);
26945 		break;
26946 	case DUK__ITER_FOREACH:
26947 		duk_push_undefined(thr);
26948 		break;
26949 	case DUK__ITER_MAP:
26950 	case DUK__ITER_FILTER:
26951 		DUK_ASSERT_TOP(thr, 5);
26952 		DUK_ASSERT(duk_is_array(thr, -1));  /* topmost element is the result array already */
26953 		duk_push_u32(thr, res_length);
26954 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
26955 		break;
26956 	default:
26957 		DUK_UNREACHABLE();
26958 		break;
26959 	}
26960 
26961 	return 1;
26962 }
26963 
26964 /*
26965  *  reduce(), reduceRight()
26966  */
26967 
duk_bi_array_prototype_reduce_shared(duk_hthread * thr)26968 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_hthread *thr) {
26969 	duk_idx_t nargs;
26970 	duk_bool_t have_acc;
26971 	duk_uint32_t i, len;
26972 	duk_small_int_t idx_step = duk_get_current_magic(thr);  /* idx_step is +1 for reduce, -1 for reduceRight */
26973 
26974 	/* We're a varargs function because we need to detect whether
26975 	 * initialValue was given or not.
26976 	 */
26977 	nargs = duk_get_top(thr);
26978 	DUK_DDD(DUK_DDDPRINT("nargs=%ld", (long) nargs));
26979 
26980 	duk_set_top(thr, 2);
26981 	len = duk__push_this_obj_len_u32(thr);
26982 	duk_require_callable(thr, 0);
26983 
26984 	/* stack[0] = callback fn
26985 	 * stack[1] = initialValue
26986 	 * stack[2] = object (coerced this)
26987 	 * stack[3] = length (not needed, but not popped above)
26988 	 * stack[4] = accumulator
26989 	 */
26990 
26991 	have_acc = 0;
26992 	if (nargs >= 2) {
26993 		duk_dup_1(thr);
26994 		have_acc = 1;
26995 	}
26996 	DUK_DDD(DUK_DDDPRINT("have_acc=%ld, acc=%!T",
26997 	                     (long) have_acc, (duk_tval *) duk_get_tval(thr, 3)));
26998 
26999 	/* For len == 0, i is initialized to len - 1 which underflows.
27000 	 * The condition (i < len) will then exit the for-loop on the
27001 	 * first round which is correct.  Similarly, loop termination
27002 	 * happens by i underflowing.
27003 	 */
27004 
27005 	for (i = (idx_step >= 0 ? 0 : len - 1);
27006 	     i < len;  /* i >= 0 would always be true */
27007 	     i += (duk_uint32_t) idx_step) {
27008 		DUK_DDD(DUK_DDDPRINT("i=%ld, len=%ld, have_acc=%ld, top=%ld, acc=%!T",
27009 		                     (long) i, (long) len, (long) have_acc,
27010 		                     (long) duk_get_top(thr),
27011 		                     (duk_tval *) duk_get_tval(thr, 4)));
27012 
27013 		DUK_ASSERT((have_acc && duk_get_top(thr) == 5) ||
27014 		           (!have_acc && duk_get_top(thr) == 4));
27015 
27016 		if (!duk_has_prop_index(thr, 2, (duk_uarridx_t) i)) {
27017 			continue;
27018 		}
27019 
27020 		if (!have_acc) {
27021 			DUK_ASSERT_TOP(thr, 4);
27022 			duk_get_prop_index(thr, 2, (duk_uarridx_t) i);
27023 			have_acc = 1;
27024 			DUK_ASSERT_TOP(thr, 5);
27025 		} else {
27026 			DUK_ASSERT_TOP(thr, 5);
27027 			duk_dup_0(thr);
27028 			duk_dup(thr, 4);
27029 			duk_get_prop_index(thr, 2, (duk_uarridx_t) i);
27030 			duk_push_u32(thr, i);
27031 			duk_dup_2(thr);
27032 			DUK_DDD(DUK_DDDPRINT("calling reduce function: func=%!T, prev=%!T, curr=%!T, idx=%!T, obj=%!T",
27033 			                     (duk_tval *) duk_get_tval(thr, -5), (duk_tval *) duk_get_tval(thr, -4),
27034 			                     (duk_tval *) duk_get_tval(thr, -3), (duk_tval *) duk_get_tval(thr, -2),
27035 			                     (duk_tval *) duk_get_tval(thr, -1)));
27036 			duk_call(thr, 4);
27037 			DUK_DDD(DUK_DDDPRINT("-> result: %!T", (duk_tval *) duk_get_tval(thr, -1)));
27038 			duk_replace(thr, 4);
27039 			DUK_ASSERT_TOP(thr, 5);
27040 		}
27041 	}
27042 
27043 	if (!have_acc) {
27044 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27045 	}
27046 
27047 	DUK_ASSERT_TOP(thr, 5);
27048 	return 1;
27049 }
27050 
27051 #endif  /* DUK_USE_ARRAY_BUILTIN */
27052 
27053 /* automatic undefs */
27054 #undef DUK__ARRAY_MID_JOIN_LIMIT
27055 #undef DUK__ITER_EVERY
27056 #undef DUK__ITER_FILTER
27057 #undef DUK__ITER_FOREACH
27058 #undef DUK__ITER_MAP
27059 #undef DUK__ITER_SOME
27060 #line 1 "duk_bi_boolean.c"
27061 /*
27062  *  Boolean built-ins
27063  */
27064 
27065 /* #include duk_internal.h -> already included */
27066 
27067 #if defined(DUK_USE_BOOLEAN_BUILTIN)
27068 
27069 /* Shared helper to provide toString() and valueOf().  Checks 'this', gets
27070  * the primitive value to stack top, and optionally coerces with ToString().
27071  */
duk_bi_boolean_prototype_tostring_shared(duk_hthread * thr)27072 DUK_INTERNAL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_hthread *thr) {
27073 	duk_tval *tv;
27074 	duk_hobject *h;
27075 	duk_small_int_t coerce_tostring = duk_get_current_magic(thr);
27076 
27077 	/* XXX: there is room to use a shared helper here, many built-ins
27078 	 * check the 'this' type, and if it's an object, check its class,
27079 	 * then get its internal value, etc.
27080 	 */
27081 
27082 	duk_push_this(thr);
27083 	tv = duk_get_tval(thr, -1);
27084 	DUK_ASSERT(tv != NULL);
27085 
27086 	if (DUK_TVAL_IS_BOOLEAN(tv)) {
27087 		goto type_ok;
27088 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
27089 		h = DUK_TVAL_GET_OBJECT(tv);
27090 		DUK_ASSERT(h != NULL);
27091 
27092 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_BOOLEAN) {
27093 			duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
27094 			DUK_ASSERT(duk_is_boolean(thr, -1));
27095 			goto type_ok;
27096 		}
27097 	}
27098 
27099 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27100 	/* never here */
27101 
27102  type_ok:
27103 	if (coerce_tostring) {
27104 		duk_to_string(thr, -1);
27105 	}
27106 	return 1;
27107 }
27108 
duk_bi_boolean_constructor(duk_hthread * thr)27109 DUK_INTERNAL duk_ret_t duk_bi_boolean_constructor(duk_hthread *thr) {
27110 	duk_hobject *h_this;
27111 
27112 	duk_to_boolean(thr, 0);
27113 
27114 	if (duk_is_constructor_call(thr)) {
27115 		/* XXX: helper; rely on Boolean.prototype as being non-writable, non-configurable */
27116 		duk_push_this(thr);
27117 		h_this = duk_known_hobject(thr, -1);
27118 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE]);
27119 
27120 		DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_BOOLEAN);
27121 
27122 		duk_dup_0(thr);  /* -> [ val obj val ] */
27123 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);  /* XXX: proper flags? */
27124 	}  /* unbalanced stack */
27125 
27126 	return 1;
27127 }
27128 
27129 #endif  /* DUK_USE_BOOLEAN_BUILTIN */
27130 #line 1 "duk_bi_buffer.c"
27131 /*
27132  *  ES2015 TypedArray and Node.js Buffer built-ins
27133  */
27134 
27135 /* #include duk_internal.h -> already included */
27136 
27137 /*
27138  *  Helpers for buffer handling, enabled with DUK_USE_BUFFEROBJECT_SUPPORT.
27139  */
27140 
27141 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
27142 /* Map class number (minus DUK_HOBJECT_CLASS_BUFOBJ_MIN) to a bidx for the
27143  * default internal prototype.
27144  */
27145 static const duk_uint8_t duk__buffer_proto_from_classnum[] = {
27146 	DUK_BIDX_ARRAYBUFFER_PROTOTYPE,
27147 	DUK_BIDX_DATAVIEW_PROTOTYPE,
27148 	DUK_BIDX_INT8ARRAY_PROTOTYPE,
27149 	DUK_BIDX_UINT8ARRAY_PROTOTYPE,
27150 	DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,
27151 	DUK_BIDX_INT16ARRAY_PROTOTYPE,
27152 	DUK_BIDX_UINT16ARRAY_PROTOTYPE,
27153 	DUK_BIDX_INT32ARRAY_PROTOTYPE,
27154 	DUK_BIDX_UINT32ARRAY_PROTOTYPE,
27155 	DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,
27156 	DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
27157 };
27158 
27159 /* Map DUK_HBUFOBJ_ELEM_xxx to duk_hobject class number.
27160  * Sync with duk_hbufobj.h and duk_hobject.h.
27161  */
27162 static const duk_uint8_t duk__buffer_class_from_elemtype[9] = {
27163 	DUK_HOBJECT_CLASS_UINT8ARRAY,
27164 	DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY,
27165 	DUK_HOBJECT_CLASS_INT8ARRAY,
27166 	DUK_HOBJECT_CLASS_UINT16ARRAY,
27167 	DUK_HOBJECT_CLASS_INT16ARRAY,
27168 	DUK_HOBJECT_CLASS_UINT32ARRAY,
27169 	DUK_HOBJECT_CLASS_INT32ARRAY,
27170 	DUK_HOBJECT_CLASS_FLOAT32ARRAY,
27171 	DUK_HOBJECT_CLASS_FLOAT64ARRAY
27172 };
27173 
27174 /* Map DUK_HBUFOBJ_ELEM_xxx to prototype object built-in index.
27175  * Sync with duk_hbufobj.h.
27176  */
27177 static const duk_uint8_t duk__buffer_proto_from_elemtype[9] = {
27178 	DUK_BIDX_UINT8ARRAY_PROTOTYPE,
27179 	DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,
27180 	DUK_BIDX_INT8ARRAY_PROTOTYPE,
27181 	DUK_BIDX_UINT16ARRAY_PROTOTYPE,
27182 	DUK_BIDX_INT16ARRAY_PROTOTYPE,
27183 	DUK_BIDX_UINT32ARRAY_PROTOTYPE,
27184 	DUK_BIDX_INT32ARRAY_PROTOTYPE,
27185 	DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,
27186 	DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
27187 };
27188 
27189 /* Map DUK__FLD_xxx to byte size. */
27190 static const duk_uint8_t duk__buffer_nbytes_from_fldtype[6] = {
27191 	1,  /* DUK__FLD_8BIT */
27192 	2,  /* DUK__FLD_16BIT */
27193 	4,  /* DUK__FLD_32BIT */
27194 	4,  /* DUK__FLD_FLOAT */
27195 	8,  /* DUK__FLD_DOUBLE */
27196 	0   /* DUK__FLD_VARINT; not relevant here */
27197 };
27198 
27199 /* Bitfield for each DUK_HBUFOBJ_ELEM_xxx indicating which element types
27200  * are compatible with a blind byte copy for the TypedArray set() method (also
27201  * used for TypedArray constructor).  Array index is target buffer elem type,
27202  * bitfield indicates compatible source types.  The types must have same byte
27203  * size and they must be coercion compatible.
27204  */
27205 #if !defined(DUK_USE_PREFER_SIZE)
27206 static duk_uint16_t duk__buffer_elemtype_copy_compatible[9] = {
27207 	/* xxx -> DUK_HBUFOBJ_ELEM_UINT8 */
27208 	(1U << DUK_HBUFOBJ_ELEM_UINT8) |
27209 		(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED) |
27210 		(1U << DUK_HBUFOBJ_ELEM_INT8),
27211 
27212 	/* xxx -> DUK_HBUFOBJ_ELEM_UINT8CLAMPED
27213 	 * Note: INT8 is -not- copy compatible, e.g. -1 would coerce to 0x00.
27214 	 */
27215 	(1U << DUK_HBUFOBJ_ELEM_UINT8) |
27216 		(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED),
27217 
27218 	/* xxx -> DUK_HBUFOBJ_ELEM_INT8 */
27219 	(1U << DUK_HBUFOBJ_ELEM_UINT8) |
27220 		(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED) |
27221 		(1U << DUK_HBUFOBJ_ELEM_INT8),
27222 
27223 	/* xxx -> DUK_HBUFOBJ_ELEM_UINT16 */
27224 	(1U << DUK_HBUFOBJ_ELEM_UINT16) |
27225 		(1U << DUK_HBUFOBJ_ELEM_INT16),
27226 
27227 	/* xxx -> DUK_HBUFOBJ_ELEM_INT16 */
27228 	(1U << DUK_HBUFOBJ_ELEM_UINT16) |
27229 		(1U << DUK_HBUFOBJ_ELEM_INT16),
27230 
27231 	/* xxx -> DUK_HBUFOBJ_ELEM_UINT32 */
27232 	(1U << DUK_HBUFOBJ_ELEM_UINT32) |
27233 		(1U << DUK_HBUFOBJ_ELEM_INT32),
27234 
27235 	/* xxx -> DUK_HBUFOBJ_ELEM_INT32 */
27236 	(1U << DUK_HBUFOBJ_ELEM_UINT32) |
27237 		(1U << DUK_HBUFOBJ_ELEM_INT32),
27238 
27239 	/* xxx -> DUK_HBUFOBJ_ELEM_FLOAT32 */
27240 	(1U << DUK_HBUFOBJ_ELEM_FLOAT32),
27241 
27242 	/* xxx -> DUK_HBUFOBJ_ELEM_FLOAT64 */
27243 	(1U << DUK_HBUFOBJ_ELEM_FLOAT64)
27244 };
27245 #endif  /* !DUK_USE_PREFER_SIZE */
27246 
duk__hbufobj_promote_this(duk_hthread * thr)27247 DUK_LOCAL duk_hbufobj *duk__hbufobj_promote_this(duk_hthread *thr) {
27248 	duk_tval *tv_dst;
27249 	duk_hbufobj *res;
27250 
27251 	duk_push_this(thr);
27252 	DUK_ASSERT(duk_is_buffer(thr, -1));
27253 	res = (duk_hbufobj *) duk_to_hobject(thr, -1);
27254 	DUK_HBUFOBJ_ASSERT_VALID(res);
27255 	DUK_DD(DUK_DDPRINT("promoted 'this' automatically to an ArrayBuffer: %!iT", duk_get_tval(thr, -1)));
27256 
27257 	tv_dst = duk_get_borrowed_this_tval(thr);
27258 	DUK_TVAL_SET_OBJECT_UPDREF(thr, tv_dst, (duk_hobject *) res);
27259 	duk_pop(thr);
27260 
27261 	return res;
27262 }
27263 
27264 #define DUK__BUFOBJ_FLAG_THROW    (1 << 0)
27265 #define DUK__BUFOBJ_FLAG_PROMOTE  (1 << 1)
27266 
27267 /* Shared helper.  When DUK__BUFOBJ_FLAG_PROMOTE is given, the return value is
27268  * always a duk_hbufobj *.  Without the flag the return value can also be a
27269  * plain buffer, and the caller must check for it using DUK_HEAPHDR_IS_BUFFER().
27270  */
duk__getrequire_bufobj_this(duk_hthread * thr,duk_small_uint_t flags)27271 DUK_LOCAL duk_heaphdr *duk__getrequire_bufobj_this(duk_hthread *thr, duk_small_uint_t flags) {
27272 	duk_tval *tv;
27273 	duk_hbufobj *h_this;
27274 
27275 	DUK_ASSERT(thr != NULL);
27276 
27277 	tv = duk_get_borrowed_this_tval(thr);
27278 	DUK_ASSERT(tv != NULL);
27279 
27280 	if (DUK_TVAL_IS_OBJECT(tv)) {
27281 		h_this = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);
27282 		DUK_ASSERT(h_this != NULL);
27283 		if (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_this)) {
27284 			DUK_HBUFOBJ_ASSERT_VALID(h_this);
27285 			return (duk_heaphdr *) h_this;
27286 		}
27287 	} else if (DUK_TVAL_IS_BUFFER(tv)) {
27288 		if (flags & DUK__BUFOBJ_FLAG_PROMOTE) {
27289 			/* Promote a plain buffer to a Uint8Array.  This is very
27290 			 * inefficient but allows plain buffer to be used wherever an
27291 			 * Uint8Array is used with very small cost; hot path functions
27292 			 * like index read/write calls should provide direct buffer
27293 			 * support to avoid promotion.
27294 			 */
27295 			/* XXX: make this conditional to a flag if call sites need it? */
27296 			h_this = duk__hbufobj_promote_this(thr);
27297 			DUK_ASSERT(h_this != NULL);
27298 			DUK_HBUFOBJ_ASSERT_VALID(h_this);
27299 			return (duk_heaphdr *) h_this;
27300 		} else {
27301 			/* XXX: ugly, share return pointer for duk_hbuffer. */
27302 			return (duk_heaphdr *) DUK_TVAL_GET_BUFFER(tv);
27303 		}
27304 	}
27305 
27306 	if (flags & DUK__BUFOBJ_FLAG_THROW) {
27307 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER);
27308 		DUK_WO_NORETURN(return NULL;);
27309 	}
27310 	return NULL;
27311 }
27312 
27313 /* Check that 'this' is a duk_hbufobj and return a pointer to it. */
duk__get_bufobj_this(duk_hthread * thr)27314 DUK_LOCAL duk_hbufobj *duk__get_bufobj_this(duk_hthread *thr) {
27315 	return (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_PROMOTE);
27316 }
27317 
27318 /* Check that 'this' is a duk_hbufobj and return a pointer to it
27319  * (NULL if not).
27320  */
duk__require_bufobj_this(duk_hthread * thr)27321 DUK_LOCAL duk_hbufobj *duk__require_bufobj_this(duk_hthread *thr) {
27322 	return (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW | DUK__BUFOBJ_FLAG_PROMOTE);
27323 }
27324 
27325 /* Check that value is a duk_hbufobj and return a pointer to it. */
duk__require_bufobj_value(duk_hthread * thr,duk_idx_t idx)27326 DUK_LOCAL duk_hbufobj *duk__require_bufobj_value(duk_hthread *thr, duk_idx_t idx) {
27327 	duk_tval *tv;
27328 	duk_hbufobj *h_obj;
27329 
27330 	/* Don't accept relative indices now. */
27331 	DUK_ASSERT(idx >= 0);
27332 
27333 	tv = duk_require_tval(thr, idx);
27334 	DUK_ASSERT(tv != NULL);
27335 	if (DUK_TVAL_IS_OBJECT(tv)) {
27336 		h_obj = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);
27337 		DUK_ASSERT(h_obj != NULL);
27338 		if (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_obj)) {
27339 			DUK_HBUFOBJ_ASSERT_VALID(h_obj);
27340 			return h_obj;
27341 		}
27342 	} else if (DUK_TVAL_IS_BUFFER(tv)) {
27343 		h_obj = (duk_hbufobj *) duk_to_hobject(thr, idx);
27344 		DUK_ASSERT(h_obj != NULL);
27345 		DUK_HBUFOBJ_ASSERT_VALID(h_obj);
27346 		return h_obj;
27347 	}
27348 
27349 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER);
27350 	DUK_WO_NORETURN(return NULL;);
27351 }
27352 
duk__set_bufobj_buffer(duk_hthread * thr,duk_hbufobj * h_bufobj,duk_hbuffer * h_val)27353 DUK_LOCAL void duk__set_bufobj_buffer(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_hbuffer *h_val) {
27354 	DUK_ASSERT(thr != NULL);
27355 	DUK_ASSERT(h_bufobj != NULL);
27356 	DUK_ASSERT(h_bufobj->buf == NULL);  /* no need to decref */
27357 	DUK_ASSERT(h_val != NULL);
27358 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
27359 	DUK_UNREF(thr);
27360 
27361 	h_bufobj->buf = h_val;
27362 	DUK_HBUFFER_INCREF(thr, h_val);
27363 	h_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val);
27364 	DUK_ASSERT(h_bufobj->shift == 0);
27365 	DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFOBJ_ELEM_UINT8);
27366 	DUK_ASSERT(h_bufobj->is_typedarray == 0);
27367 
27368 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
27369 }
27370 
27371 /* 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)27372 DUK_LOCAL void duk__resolve_offset_opt_length(duk_hthread *thr,
27373                                               duk_hbufobj *h_bufarg,
27374                                               duk_idx_t idx_offset,
27375                                               duk_idx_t idx_length,
27376                                               duk_uint_t *out_offset,
27377                                               duk_uint_t *out_length,
27378                                               duk_bool_t throw_flag) {
27379 	duk_int_t offset_signed;
27380 	duk_int_t length_signed;
27381 	duk_uint_t offset;
27382 	duk_uint_t length;
27383 
27384 	offset_signed = duk_to_int(thr, idx_offset);
27385 	if (offset_signed < 0) {
27386 		goto fail_range;
27387 	}
27388 	offset = (duk_uint_t) offset_signed;
27389 	if (offset > h_bufarg->length) {
27390 		goto fail_range;
27391 	}
27392 	DUK_ASSERT_DISABLE(offset >= 0);  /* unsigned */
27393 	DUK_ASSERT(offset <= h_bufarg->length);
27394 
27395 	if (duk_is_undefined(thr, idx_length)) {
27396 		DUK_ASSERT(h_bufarg->length >= offset);
27397 		length = h_bufarg->length - offset;  /* >= 0 */
27398 	} else {
27399 		length_signed = duk_to_int(thr, idx_length);
27400 		if (length_signed < 0) {
27401 			goto fail_range;
27402 		}
27403 		length = (duk_uint_t) length_signed;
27404 		DUK_ASSERT(h_bufarg->length >= offset);
27405 		if (length > h_bufarg->length - offset) {
27406 			/* Unlike for negative arguments, some call sites
27407 			 * want length to be clamped if it's positive.
27408 			 */
27409 			if (throw_flag) {
27410 				goto fail_range;
27411 			} else {
27412 				length = h_bufarg->length - offset;
27413 			}
27414 		}
27415 	}
27416 	DUK_ASSERT_DISABLE(length >= 0);  /* unsigned */
27417 	DUK_ASSERT(offset + length <= h_bufarg->length);
27418 
27419 	*out_offset = offset;
27420 	*out_length = length;
27421 	return;
27422 
27423  fail_range:
27424 	DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARGS);
27425 	DUK_WO_NORETURN(return;);
27426 }
27427 
27428 /* Shared lenient buffer length clamping helper.  No negative indices, no
27429  * element/byte shifting.
27430  */
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)27431 DUK_LOCAL void duk__clamp_startend_nonegidx_noshift(duk_hthread *thr,
27432                                                     duk_int_t buffer_length,
27433                                                     duk_idx_t idx_start,
27434                                                     duk_idx_t idx_end,
27435                                                     duk_int_t *out_start_offset,
27436                                                     duk_int_t *out_end_offset) {
27437 	duk_int_t start_offset;
27438 	duk_int_t end_offset;
27439 
27440 	DUK_ASSERT(out_start_offset != NULL);
27441 	DUK_ASSERT(out_end_offset != NULL);
27442 
27443 	/* undefined coerces to zero which is correct */
27444 	start_offset = duk_to_int_clamped(thr, idx_start, 0, buffer_length);
27445 	if (duk_is_undefined(thr, idx_end)) {
27446 		end_offset = buffer_length;
27447 	} else {
27448 		end_offset = duk_to_int_clamped(thr, idx_end, start_offset, buffer_length);
27449 	}
27450 
27451 	DUK_ASSERT(start_offset >= 0);
27452 	DUK_ASSERT(start_offset <= buffer_length);
27453 	DUK_ASSERT(end_offset >= 0);
27454 	DUK_ASSERT(end_offset <= buffer_length);
27455 	DUK_ASSERT(start_offset <= end_offset);
27456 
27457 	*out_start_offset = start_offset;
27458 	*out_end_offset = end_offset;
27459 }
27460 
27461 /* Shared lenient buffer length clamping helper.  Indices are treated as
27462  * element indices (though output values are byte offsets) which only
27463  * really matters for TypedArray views as other buffer object have a zero
27464  * shift.  Negative indices are counted from end of input slice; crossed
27465  * indices are clamped to zero length; and final indices are clamped
27466  * against input slice.  Used for e.g. ArrayBuffer slice().
27467  */
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)27468 DUK_LOCAL void duk__clamp_startend_negidx_shifted(duk_hthread *thr,
27469                                                   duk_int_t buffer_length,
27470                                                   duk_uint8_t buffer_shift,
27471                                                   duk_idx_t idx_start,
27472                                                   duk_idx_t idx_end,
27473                                                   duk_int_t *out_start_offset,
27474                                                   duk_int_t *out_end_offset) {
27475 	duk_int_t start_offset;
27476 	duk_int_t end_offset;
27477 
27478 	DUK_ASSERT(out_start_offset != NULL);
27479 	DUK_ASSERT(out_end_offset != NULL);
27480 
27481 	buffer_length >>= buffer_shift;  /* as (full) elements */
27482 
27483 	/* Resolve start/end offset as element indices first; arguments
27484 	 * at idx_start/idx_end are element offsets.  Working with element
27485 	 * indices first also avoids potential for wrapping.
27486 	 */
27487 
27488 	start_offset = duk_to_int(thr, idx_start);
27489 	if (start_offset < 0) {
27490 		start_offset = buffer_length + start_offset;
27491 	}
27492 	if (duk_is_undefined(thr, idx_end)) {
27493 		end_offset = buffer_length;
27494 	} else {
27495 		end_offset = duk_to_int(thr, idx_end);
27496 		if (end_offset < 0) {
27497 			end_offset = buffer_length + end_offset;
27498 		}
27499 	}
27500 	/* Note: start_offset/end_offset can still be < 0 here. */
27501 
27502 	if (start_offset < 0) {
27503 		start_offset = 0;
27504 	} else if (start_offset > buffer_length) {
27505 		start_offset = buffer_length;
27506 	}
27507 	if (end_offset < start_offset) {
27508 		end_offset = start_offset;
27509 	} else if (end_offset > buffer_length) {
27510 		end_offset = buffer_length;
27511 	}
27512 	DUK_ASSERT(start_offset >= 0);
27513 	DUK_ASSERT(start_offset <= buffer_length);
27514 	DUK_ASSERT(end_offset >= 0);
27515 	DUK_ASSERT(end_offset <= buffer_length);
27516 	DUK_ASSERT(start_offset <= end_offset);
27517 
27518 	/* Convert indices to byte offsets. */
27519 	start_offset <<= buffer_shift;
27520 	end_offset <<= buffer_shift;
27521 
27522 	*out_start_offset = start_offset;
27523 	*out_end_offset = end_offset;
27524 }
27525 
duk_hbufobj_promote_plain(duk_hthread * thr,duk_idx_t idx)27526 DUK_INTERNAL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx) {
27527 	if (duk_is_buffer(thr, idx)) {
27528 		duk_to_object(thr, idx);
27529 	}
27530 }
27531 
duk_hbufobj_push_uint8array_from_plain(duk_hthread * thr,duk_hbuffer * h_buf)27532 DUK_INTERNAL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_hbuffer *h_buf) {
27533 	/* Push Uint8Array which will share the same underlying buffer as
27534 	 * the plain buffer argument.  Also create an ArrayBuffer with the
27535 	 * same backing for the result .buffer property.
27536 	 */
27537 
27538 	duk_push_hbuffer(thr, h_buf);
27539 	duk_push_buffer_object(thr, -1, 0, (duk_size_t) DUK_HBUFFER_GET_SIZE(h_buf), DUK_BUFOBJ_UINT8ARRAY);
27540 	duk_remove_m2(thr);
27541 
27542 #if 0
27543 	/* More verbose equivalent; maybe useful if e.g. .buffer is omitted. */
27544 	h_bufobj = duk_push_bufobj_raw(thr,
27545 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27546 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27547 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_UINT8ARRAY),
27548 	                               DUK_BIDX_UINT8ARRAY_PROTOTYPE);
27549 	DUK_ASSERT(h_bufobj != NULL);
27550 	duk__set_bufobj_buffer(thr, h_bufobj, h_buf);
27551 	h_bufobj->is_typedarray = 1;
27552 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
27553 
27554 	h_arrbuf = duk_push_bufobj_raw(thr,
27555 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27556 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27557 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
27558 	                               DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
27559 	DUK_ASSERT(h_arrbuf != NULL);
27560 	duk__set_bufobj_buffer(thr, h_arrbuf, h_buf);
27561 	DUK_ASSERT(h_arrbuf->is_typedarray == 0);
27562 	DUK_HBUFOBJ_ASSERT_VALID(h_arrbuf);
27563 
27564 	DUK_ASSERT(h_bufobj->buf_prop == NULL);
27565 	h_bufobj->buf_prop = (duk_hobject *) h_arrbuf;
27566 	DUK_ASSERT(h_arrbuf != NULL);
27567 	DUK_HBUFOBJ_INCREF(thr, h_arrbuf);
27568 	duk_pop(thr);
27569 #endif
27570 }
27571 
27572 /* 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)27573 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) {
27574 	duk_double_union du;
27575 
27576 	DUK_ASSERT(elem_size > 0);
27577 	duk_memcpy((void *) du.uc, (const void *) p, (size_t) elem_size);
27578 
27579 	switch (h_bufobj->elem_type) {
27580 	case DUK_HBUFOBJ_ELEM_UINT8:
27581 	case DUK_HBUFOBJ_ELEM_UINT8CLAMPED:
27582 		duk_push_uint(thr, (duk_uint_t) du.uc[0]);
27583 		break;
27584 	case DUK_HBUFOBJ_ELEM_INT8:
27585 		duk_push_int(thr, (duk_int_t) (duk_int8_t) du.uc[0]);
27586 		break;
27587 	case DUK_HBUFOBJ_ELEM_UINT16:
27588 		duk_push_uint(thr, (duk_uint_t) du.us[0]);
27589 		break;
27590 	case DUK_HBUFOBJ_ELEM_INT16:
27591 		duk_push_int(thr, (duk_int_t) (duk_int16_t) du.us[0]);
27592 		break;
27593 	case DUK_HBUFOBJ_ELEM_UINT32:
27594 		duk_push_uint(thr, (duk_uint_t) du.ui[0]);
27595 		break;
27596 	case DUK_HBUFOBJ_ELEM_INT32:
27597 		duk_push_int(thr, (duk_int_t) (duk_int32_t) du.ui[0]);
27598 		break;
27599 	case DUK_HBUFOBJ_ELEM_FLOAT32:
27600 		duk_push_number(thr, (duk_double_t) du.f[0]);
27601 		break;
27602 	case DUK_HBUFOBJ_ELEM_FLOAT64:
27603 		duk_push_number(thr, (duk_double_t) du.d);
27604 		break;
27605 	default:
27606 		DUK_UNREACHABLE();
27607 	}
27608 }
27609 
27610 /* 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)27611 DUK_INTERNAL void duk_hbufobj_validated_write(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {
27612 	duk_double_union du;
27613 
27614 	/* NOTE! Caller must ensure that any side effects from the
27615 	 * coercions below are safe.  If that cannot be guaranteed
27616 	 * (which is normally the case), caller must coerce the
27617 	 * argument using duk_to_number() before any pointer
27618 	 * validations; the result of duk_to_number() always coerces
27619 	 * without side effects here.
27620 	 */
27621 
27622 	switch (h_bufobj->elem_type) {
27623 	case DUK_HBUFOBJ_ELEM_UINT8:
27624 		du.uc[0] = (duk_uint8_t) duk_to_uint32(thr, -1);
27625 		break;
27626 	case DUK_HBUFOBJ_ELEM_UINT8CLAMPED:
27627 		du.uc[0] = (duk_uint8_t) duk_to_uint8clamped(thr, -1);
27628 		break;
27629 	case DUK_HBUFOBJ_ELEM_INT8:
27630 		du.uc[0] = (duk_uint8_t) duk_to_int32(thr, -1);
27631 		break;
27632 	case DUK_HBUFOBJ_ELEM_UINT16:
27633 		du.us[0] = (duk_uint16_t) duk_to_uint32(thr, -1);
27634 		break;
27635 	case DUK_HBUFOBJ_ELEM_INT16:
27636 		du.us[0] = (duk_uint16_t) duk_to_int32(thr, -1);
27637 		break;
27638 	case DUK_HBUFOBJ_ELEM_UINT32:
27639 		du.ui[0] = (duk_uint32_t) duk_to_uint32(thr, -1);
27640 		break;
27641 	case DUK_HBUFOBJ_ELEM_INT32:
27642 		du.ui[0] = (duk_uint32_t) duk_to_int32(thr, -1);
27643 		break;
27644 	case DUK_HBUFOBJ_ELEM_FLOAT32:
27645 		/* A double-to-float cast is undefined behavior in C99 if
27646 		 * the cast is out-of-range, so use a helper.  Example:
27647 		 * runtime error: value -1e+100 is outside the range of representable values of type 'float'
27648 		 */
27649 		du.f[0] = duk_double_to_float_t(duk_to_number_m1(thr));
27650 		break;
27651 	case DUK_HBUFOBJ_ELEM_FLOAT64:
27652 		du.d = (duk_double_t) duk_to_number_m1(thr);
27653 		break;
27654 	default:
27655 		DUK_UNREACHABLE();
27656 	}
27657 
27658 	DUK_ASSERT(elem_size > 0);
27659 	duk_memcpy((void *) p, (const void *) du.uc, (size_t) elem_size);
27660 }
27661 
27662 /* Helper to create a fixed buffer from argument value at index 0.
27663  * Node.js and allocPlain() compatible.
27664  */
duk__hbufobj_fixed_from_argvalue(duk_hthread * thr)27665 DUK_LOCAL duk_hbuffer *duk__hbufobj_fixed_from_argvalue(duk_hthread *thr) {
27666 	duk_int_t len;
27667 	duk_int_t i;
27668 	duk_size_t buf_size;
27669 	duk_uint8_t *buf;
27670 
27671 	switch (duk_get_type(thr, 0)) {
27672 	case DUK_TYPE_NUMBER: {
27673 		len = duk_to_int_clamped(thr, 0, 0, DUK_INT_MAX);
27674 		(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) len);
27675 		break;
27676 	}
27677 	case DUK_TYPE_BUFFER: { /* Treat like Uint8Array. */
27678 		goto slow_copy;
27679 	}
27680 	case DUK_TYPE_OBJECT: {
27681 		duk_hobject *h;
27682 		duk_hbufobj *h_bufobj;
27683 
27684 		/* For Node.js Buffers "Passing an ArrayBuffer returns a Buffer
27685 		 * that shares allocated memory with the given ArrayBuffer."
27686 		 * https://nodejs.org/api/buffer.html#buffer_buffer_from_buffer_alloc_and_buffer_allocunsafe
27687 		 */
27688 
27689 		h = duk_known_hobject(thr, 0);
27690 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAYBUFFER) {
27691 			DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ(h));
27692 			h_bufobj = (duk_hbufobj *) h;
27693 			if (DUK_UNLIKELY(h_bufobj->buf == NULL)) {
27694 				DUK_ERROR_TYPE_INVALID_ARGS(thr);
27695 				DUK_WO_NORETURN(return NULL;);
27696 			}
27697 			if (DUK_UNLIKELY(h_bufobj->offset != 0 || h_bufobj->length != DUK_HBUFFER_GET_SIZE(h_bufobj->buf))) {
27698 				/* No support for ArrayBuffers with slice
27699 				 * offset/length.
27700 				 */
27701 				DUK_ERROR_TYPE_INVALID_ARGS(thr);
27702 				DUK_WO_NORETURN(return NULL;);
27703 			}
27704 			duk_push_hbuffer(thr, h_bufobj->buf);
27705 			return h_bufobj->buf;
27706 		}
27707 		goto slow_copy;
27708 	}
27709 	case DUK_TYPE_STRING: {
27710 		/* ignore encoding for now */
27711 		duk_require_hstring_notsymbol(thr, 0);
27712 		duk_dup_0(thr);
27713 		(void) duk_to_buffer(thr, -1, &buf_size);
27714 		break;
27715 	}
27716 	default:
27717 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
27718 		DUK_WO_NORETURN(return NULL;);
27719 	}
27720 
27721  done:
27722 	DUK_ASSERT(duk_is_buffer(thr, -1));
27723 	return duk_known_hbuffer(thr, -1);
27724 
27725  slow_copy:
27726 	/* XXX: fast path for typed arrays and other buffer objects? */
27727 
27728 	(void) duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
27729 	len = duk_to_int_clamped(thr, -1, 0, DUK_INT_MAX);
27730 	duk_pop(thr);
27731 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len);  /* no zeroing, all indices get initialized */
27732 	for (i = 0; i < len; i++) {
27733 		/* XXX: fast path for array or buffer arguments? */
27734 		duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
27735 		buf[i] = (duk_uint8_t) (duk_to_uint32(thr, -1) & 0xffU);
27736 		duk_pop(thr);
27737 	}
27738 	goto done;
27739 }
27740 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27741 
27742 /*
27743  *  Node.js Buffer constructor
27744  *
27745  *  Node.js Buffers are just Uint8Arrays with internal prototype set to
27746  *  Buffer.prototype so they're handled otherwise the same as Uint8Array.
27747  *  However, the constructor arguments are very different so a separate
27748  *  constructor entry point is used.
27749  */
27750 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_constructor(duk_hthread * thr)27751 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_hthread *thr) {
27752 	duk_hbuffer *h_buf;
27753 
27754 	h_buf = duk__hbufobj_fixed_from_argvalue(thr);
27755 	DUK_ASSERT(h_buf != NULL);
27756 
27757 	duk_push_buffer_object(thr,
27758 	                       -1,
27759 	                       0,
27760 	                       DUK_HBUFFER_FIXED_GET_SIZE((duk_hbuffer_fixed *) (void *) h_buf),
27761 	                       DUK_BUFOBJ_UINT8ARRAY);
27762 	duk_push_hobject_bidx(thr, DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);
27763 	duk_set_prototype(thr, -2);
27764 
27765 	/* XXX: a more direct implementation */
27766 
27767 	return 1;
27768 }
27769 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27770 
27771 /*
27772  *  ArrayBuffer, DataView, and TypedArray constructors
27773  */
27774 
27775 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_arraybuffer_constructor(duk_hthread * thr)27776 DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_constructor(duk_hthread *thr) {
27777 	duk_hbufobj *h_bufobj;
27778 	duk_hbuffer *h_val;
27779 	duk_int_t len;
27780 
27781 	DUK_CTX_ASSERT_VALID(thr);
27782 
27783 	duk_require_constructor_call(thr);
27784 
27785 	len = duk_to_int(thr, 0);
27786 	if (len < 0) {
27787 		goto fail_length;
27788 	}
27789 	(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) len);
27790 	h_val = (duk_hbuffer *) duk_known_hbuffer(thr, -1);
27791 
27792 	h_bufobj = duk_push_bufobj_raw(thr,
27793 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27794 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27795 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
27796 	                               DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
27797 	DUK_ASSERT(h_bufobj != NULL);
27798 
27799 	duk__set_bufobj_buffer(thr, h_bufobj, h_val);
27800 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
27801 
27802 	return 1;
27803 
27804  fail_length:
27805 	DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
27806 }
27807 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27808 
27809 
27810 /* Format of magic, bits:
27811  *   0...1: elem size shift (0-3)
27812  *   2...5: elem type (DUK_HBUFOBJ_ELEM_xxx)
27813  *
27814  * XXX: add prototype bidx explicitly to magic instead of using a mapping?
27815  */
27816 
27817 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_typedarray_constructor(duk_hthread * thr)27818 DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
27819 	duk_tval *tv;
27820 	duk_hobject *h_obj;
27821 	duk_hbufobj *h_bufobj = NULL;
27822 	duk_hbufobj *h_bufarg = NULL;
27823 	duk_hbuffer *h_val;
27824 	duk_small_uint_t magic;
27825 	duk_small_uint_t shift;
27826 	duk_small_uint_t elem_type;
27827 	duk_small_uint_t elem_size;
27828 	duk_small_uint_t class_num;
27829 	duk_small_uint_t proto_bidx;
27830 	duk_uint_t align_mask;
27831 	duk_uint_t elem_length;
27832 	duk_int_t elem_length_signed;
27833 	duk_uint_t byte_length;
27834 	duk_small_uint_t copy_mode;
27835 
27836 	/* XXX: The same copy helpers could be shared with at least some
27837 	 * buffer functions.
27838 	 */
27839 
27840 	duk_require_constructor_call(thr);
27841 
27842 	/* We could fit built-in index into magic but that'd make the magic
27843 	 * number dependent on built-in numbering (genbuiltins.py doesn't
27844 	 * handle that yet).  So map both class and prototype from the
27845 	 * element type.
27846 	 */
27847 	magic = (duk_small_uint_t) duk_get_current_magic(thr);
27848 	shift = magic & 0x03U;               /* bits 0...1: shift */
27849 	elem_type = (magic >> 2) & 0x0fU;    /* bits 2...5: type */
27850 	elem_size = 1U << shift;
27851 	align_mask = elem_size - 1;
27852 	DUK_ASSERT(elem_type < sizeof(duk__buffer_proto_from_elemtype) / sizeof(duk_uint8_t));
27853 	proto_bidx = duk__buffer_proto_from_elemtype[elem_type];
27854 	DUK_ASSERT(proto_bidx < DUK_NUM_BUILTINS);
27855 	DUK_ASSERT(elem_type < sizeof(duk__buffer_class_from_elemtype) / sizeof(duk_uint8_t));
27856 	class_num = duk__buffer_class_from_elemtype[elem_type];
27857 
27858 	DUK_DD(DUK_DDPRINT("typedarray constructor, magic=%d, shift=%d, elem_type=%d, "
27859 	                   "elem_size=%d, proto_bidx=%d, class_num=%d",
27860 	                   (int) magic, (int) shift, (int) elem_type, (int) elem_size,
27861 	                   (int) proto_bidx, (int) class_num));
27862 
27863 	/* Argument variants.  When the argument is an ArrayBuffer a view to
27864 	 * the same buffer is created; otherwise a new ArrayBuffer is always
27865 	 * created.
27866 	 */
27867 
27868 	/* XXX: initial iteration to treat a plain buffer like an ArrayBuffer:
27869 	 * coerce to an ArrayBuffer object and use that as .buffer.  The underlying
27870 	 * buffer will be the same but result .buffer !== inputPlainBuffer.
27871 	 */
27872 	duk_hbufobj_promote_plain(thr, 0);
27873 
27874 	tv = duk_get_tval(thr, 0);
27875 	DUK_ASSERT(tv != NULL);  /* arg count */
27876 	if (DUK_TVAL_IS_OBJECT(tv)) {
27877 		h_obj = DUK_TVAL_GET_OBJECT(tv);
27878 		DUK_ASSERT(h_obj != NULL);
27879 
27880 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_ARRAYBUFFER) {
27881 			/* ArrayBuffer: unlike any other argument variant, create
27882 			 * a view into the existing buffer.
27883 			 */
27884 
27885 			duk_int_t byte_offset_signed;
27886 			duk_uint_t byte_offset;
27887 
27888 			h_bufarg = (duk_hbufobj *) h_obj;
27889 
27890 			byte_offset_signed = duk_to_int(thr, 1);
27891 			if (byte_offset_signed < 0) {
27892 				goto fail_arguments;
27893 			}
27894 			byte_offset = (duk_uint_t) byte_offset_signed;
27895 			if (byte_offset > h_bufarg->length ||
27896 			    (byte_offset & align_mask) != 0) {
27897 				/* Must be >= 0 and multiple of element size. */
27898 				goto fail_arguments;
27899 			}
27900 			if (duk_is_undefined(thr, 2)) {
27901 				DUK_ASSERT(h_bufarg->length >= byte_offset);
27902 				byte_length = h_bufarg->length - byte_offset;
27903 				if ((byte_length & align_mask) != 0) {
27904 					/* Must be element size multiple from
27905 					 * start offset to end of buffer.
27906 					 */
27907 					goto fail_arguments;
27908 				}
27909 				elem_length = (byte_length >> shift);
27910 			} else {
27911 				elem_length_signed = duk_to_int(thr, 2);
27912 				if (elem_length_signed < 0) {
27913 					goto fail_arguments;
27914 				}
27915 				elem_length = (duk_uint_t) elem_length_signed;
27916 				byte_length = elem_length << shift;
27917 				if ((byte_length >> shift) != elem_length) {
27918 					/* Byte length would overflow. */
27919 					/* XXX: easier check with less code? */
27920 					goto fail_arguments;
27921 				}
27922 				DUK_ASSERT(h_bufarg->length >= byte_offset);
27923 				if (byte_length > h_bufarg->length - byte_offset) {
27924 					/* Not enough data. */
27925 					goto fail_arguments;
27926 				}
27927 			}
27928 			DUK_UNREF(elem_length);
27929 			DUK_ASSERT_DISABLE(byte_offset >= 0);
27930 			DUK_ASSERT(byte_offset <= h_bufarg->length);
27931 			DUK_ASSERT_DISABLE(byte_length >= 0);
27932 			DUK_ASSERT(byte_offset + byte_length <= h_bufarg->length);
27933 			DUK_ASSERT((elem_length << shift) == byte_length);
27934 
27935 			h_bufobj = duk_push_bufobj_raw(thr,
27936 			                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27937 			                               DUK_HOBJECT_FLAG_BUFOBJ |
27938 			                               DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
27939 			                               (duk_small_int_t) proto_bidx);
27940 			h_val = h_bufarg->buf;
27941 			if (h_val == NULL) {
27942 				DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27943 			}
27944 			h_bufobj->buf = h_val;
27945 			DUK_HBUFFER_INCREF(thr, h_val);
27946 			h_bufobj->offset = h_bufarg->offset + byte_offset;
27947 			h_bufobj->length = byte_length;
27948 			h_bufobj->shift = (duk_uint8_t) shift;
27949 			h_bufobj->elem_type = (duk_uint8_t) elem_type;
27950 			h_bufobj->is_typedarray = 1;
27951 			DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
27952 
27953 			/* Set .buffer to the argument ArrayBuffer. */
27954 			DUK_ASSERT(h_bufobj->buf_prop == NULL);
27955 			h_bufobj->buf_prop = (duk_hobject *) h_bufarg;
27956 			DUK_ASSERT(h_bufarg != NULL);
27957 			DUK_HBUFOBJ_INCREF(thr, h_bufarg);
27958 			return 1;
27959 		} else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
27960 			/* TypedArray (or other non-ArrayBuffer duk_hbufobj).
27961 			 * Conceptually same behavior as for an Array-like argument,
27962 			 * with a few fast paths.
27963 			 */
27964 
27965 			h_bufarg = (duk_hbufobj *) h_obj;
27966 			DUK_HBUFOBJ_ASSERT_VALID(h_bufarg);
27967 			elem_length_signed = (duk_int_t) (h_bufarg->length >> h_bufarg->shift);
27968 			if (h_bufarg->buf == NULL) {
27969 				DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27970 			}
27971 
27972 			/* Select copy mode.  Must take into account element
27973 			 * compatibility and validity of the underlying source
27974 			 * buffer.
27975 			 */
27976 
27977 			DUK_DDD(DUK_DDDPRINT("selecting copy mode for bufobj arg, "
27978 			                     "src byte_length=%ld, src shift=%d, "
27979 			                     "src/dst elem_length=%ld; "
27980 			                     "dst shift=%d -> dst byte_length=%ld",
27981 			                     (long) h_bufarg->length, (int) h_bufarg->shift,
27982 			                     (long) elem_length_signed, (int) shift,
27983 			                     (long) (elem_length_signed << shift)));
27984 
27985 			copy_mode = 2;  /* default is explicit index read/write copy */
27986 #if !defined(DUK_USE_PREFER_SIZE)
27987 			/* With a size optimized build copy_mode 2 is enough.
27988 			 * Modes 0 and 1 are faster but conceptually the same.
27989 			 */
27990 			DUK_ASSERT(elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
27991 			if (DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {
27992 				if ((duk__buffer_elemtype_copy_compatible[elem_type] & (1 << h_bufarg->elem_type)) != 0) {
27993 					DUK_DDD(DUK_DDDPRINT("source/target are copy compatible, memcpy"));
27994 					DUK_ASSERT(shift == h_bufarg->shift);  /* byte sizes will match */
27995 					copy_mode = 0;
27996 				} else {
27997 					DUK_DDD(DUK_DDDPRINT("source/target not copy compatible but valid, fast copy"));
27998 					copy_mode = 1;
27999 				}
28000 			}
28001 #endif  /* !DUK_USE_PREFER_SIZE */
28002 		} else {
28003 			/* Array or Array-like */
28004 			elem_length_signed = (duk_int_t) duk_get_length(thr, 0);
28005 			copy_mode = 2;
28006 		}
28007 	} else {
28008 		/* Non-object argument is simply int coerced, matches
28009 		 * V8 behavior (except for "null", which we coerce to
28010 		 * 0 but V8 TypeErrors).
28011 		 */
28012 		elem_length_signed = duk_to_int(thr, 0);
28013 		copy_mode = 3;
28014 	}
28015 	if (elem_length_signed < 0) {
28016 		goto fail_arguments;
28017 	}
28018 	elem_length = (duk_uint_t) elem_length_signed;
28019 	byte_length = (duk_uint_t) (elem_length << shift);
28020 	if ((byte_length >> shift) != elem_length) {
28021 		/* Byte length would overflow. */
28022 		/* XXX: easier check with less code? */
28023 		goto fail_arguments;
28024 	}
28025 
28026 	DUK_DDD(DUK_DDDPRINT("elem_length=%ld, byte_length=%ld",
28027 	                     (long) elem_length, (long) byte_length));
28028 
28029 	/* ArrayBuffer argument is handled specially above; the rest of the
28030 	 * argument variants are handled by shared code below.
28031 	 *
28032 	 * ArrayBuffer in h_bufobj->buf_prop is intentionally left unset.
28033 	 * It will be automatically created by the .buffer accessor on
28034 	 * first access.
28035 	 */
28036 
28037 	/* Push the resulting view object on top of a plain fixed buffer. */
28038 	(void) duk_push_fixed_buffer(thr, byte_length);
28039 	h_val = duk_known_hbuffer(thr, -1);
28040 	DUK_ASSERT(h_val != NULL);
28041 
28042 	h_bufobj = duk_push_bufobj_raw(thr,
28043 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
28044 	                               DUK_HOBJECT_FLAG_BUFOBJ |
28045 	                               DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
28046 	                               (duk_small_int_t) proto_bidx);
28047 
28048 	h_bufobj->buf = h_val;
28049 	DUK_HBUFFER_INCREF(thr, h_val);
28050 	DUK_ASSERT(h_bufobj->offset == 0);
28051 	h_bufobj->length = byte_length;
28052 	h_bufobj->shift = (duk_uint8_t) shift;
28053 	h_bufobj->elem_type = (duk_uint8_t) elem_type;
28054 	h_bufobj->is_typedarray = 1;
28055 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
28056 
28057 	/* Copy values, the copy method depends on the arguments.
28058 	 *
28059 	 * Copy mode decision may depend on the validity of the underlying
28060 	 * buffer of the source argument; there must be no harmful side effects
28061 	 * from there to here for copy_mode to still be valid.
28062 	 */
28063 	DUK_DDD(DUK_DDDPRINT("copy mode: %d", (int) copy_mode));
28064 	switch (copy_mode) {
28065 		/* Copy modes 0 and 1 can be omitted in size optimized build,
28066 		 * copy mode 2 handles them (but more slowly).
28067 		 */
28068 #if !defined(DUK_USE_PREFER_SIZE)
28069 	case 0: {
28070 		/* Use byte copy. */
28071 
28072 		duk_uint8_t *p_src;
28073 		duk_uint8_t *p_dst;
28074 
28075 		DUK_ASSERT(h_bufobj != NULL);
28076 		DUK_ASSERT(h_bufobj->buf != NULL);
28077 		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufobj));
28078 		DUK_ASSERT(h_bufarg != NULL);
28079 		DUK_ASSERT(h_bufarg->buf != NULL);
28080 		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufarg));
28081 
28082 		p_dst = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj);
28083 		p_src = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
28084 
28085 		DUK_DDD(DUK_DDDPRINT("using memcpy: p_src=%p, p_dst=%p, byte_length=%ld",
28086 		                     (void *) p_src, (void *) p_dst, (long) byte_length));
28087 
28088 		duk_memcpy_unsafe((void *) p_dst, (const void *) p_src, (size_t) byte_length);
28089 		break;
28090 	}
28091 	case 1: {
28092 		/* Copy values through direct validated reads and writes. */
28093 
28094 		duk_small_uint_t src_elem_size;
28095 		duk_small_uint_t dst_elem_size;
28096 		duk_uint8_t *p_src;
28097 		duk_uint8_t *p_src_end;
28098 		duk_uint8_t *p_dst;
28099 
28100 		DUK_ASSERT(h_bufobj != NULL);
28101 		DUK_ASSERT(h_bufobj->buf != NULL);
28102 		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufobj));
28103 		DUK_ASSERT(h_bufarg != NULL);
28104 		DUK_ASSERT(h_bufarg->buf != NULL);
28105 		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufarg));
28106 
28107 		src_elem_size = (duk_small_uint_t) (1U << h_bufarg->shift);
28108 		dst_elem_size = elem_size;
28109 
28110 		p_src = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
28111 		p_dst = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj);
28112 		p_src_end = p_src + h_bufarg->length;
28113 
28114 		DUK_DDD(DUK_DDDPRINT("using fast copy: p_src=%p, p_src_end=%p, p_dst=%p, "
28115 		                     "src_elem_size=%d, dst_elem_size=%d",
28116 		                     (void *) p_src, (void *) p_src_end, (void *) p_dst,
28117 		                     (int) src_elem_size, (int) dst_elem_size));
28118 
28119 		while (p_src != p_src_end) {
28120 			DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
28121 			                     "p_src=%p, p_src_end=%p, p_dst=%p",
28122 			                     (void *) p_src, (void *) p_src_end, (void *) p_dst));
28123 			/* A validated read() is always a number, so it's write coercion
28124 			 * is always side effect free an won't invalidate pointers etc.
28125 			 */
28126 			duk_hbufobj_push_validated_read(thr, h_bufarg, p_src, src_elem_size);
28127 			duk_hbufobj_validated_write(thr, h_bufobj, p_dst, dst_elem_size);
28128 			duk_pop(thr);
28129 			p_src += src_elem_size;
28130 			p_dst += dst_elem_size;
28131 		}
28132 		break;
28133 	}
28134 #endif  /* !DUK_USE_PREFER_SIZE */
28135 	case 2: {
28136 		/* Copy values by index reads and writes.  Let virtual
28137 		 * property handling take care of coercion.
28138 		 */
28139 		duk_uint_t i;
28140 
28141 		DUK_DDD(DUK_DDDPRINT("using slow copy"));
28142 
28143 		for (i = 0; i < elem_length; i++) {
28144 			duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
28145 			duk_put_prop_index(thr, -2, (duk_uarridx_t) i);
28146 		}
28147 		break;
28148 	}
28149 	default:
28150 	case 3: {
28151 		/* No copy, leave zero bytes in the buffer.  There's no
28152 		 * ambiguity with Float32/Float64 because zero bytes also
28153 		 * represent 0.0.
28154 		 */
28155 
28156 		DUK_DDD(DUK_DDDPRINT("using no copy"));
28157 		break;
28158 	}
28159 	}
28160 
28161 	return 1;
28162 
28163  fail_arguments:
28164 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
28165 }
28166 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28167 /* When bufferobject support is disabled, new Uint8Array() could still be
28168  * supported to create a plain fixed buffer.  Disabled for now.
28169  */
28170 #if 0
28171 DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
28172 	duk_int_t elem_length_signed;
28173 	duk_uint_t byte_length;
28174 
28175 	/* XXX: The same copy helpers could be shared with at least some
28176 	 * buffer functions.
28177 	 */
28178 
28179 	duk_require_constructor_call(thr);
28180 
28181 	elem_length_signed = duk_require_int(thr, 0);
28182 	if (elem_length_signed < 0) {
28183 		goto fail_arguments;
28184 	}
28185 	byte_length = (duk_uint_t) elem_length_signed;
28186 
28187 	(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) byte_length);
28188 	return 1;
28189 
28190  fail_arguments:
28191 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
28192 }
28193 #endif  /* 0 */
28194 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28195 
28196 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_dataview_constructor(duk_hthread * thr)28197 DUK_INTERNAL duk_ret_t duk_bi_dataview_constructor(duk_hthread *thr) {
28198 	duk_hbufobj *h_bufarg;
28199 	duk_hbufobj *h_bufobj;
28200 	duk_hbuffer *h_val;
28201 	duk_uint_t offset;
28202 	duk_uint_t length;
28203 
28204 	duk_require_constructor_call(thr);
28205 
28206 	h_bufarg = duk__require_bufobj_value(thr, 0);
28207 	DUK_ASSERT(h_bufarg != NULL);
28208 	if (DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_bufarg) != DUK_HOBJECT_CLASS_ARRAYBUFFER) {
28209 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28210 	}
28211 
28212 	duk__resolve_offset_opt_length(thr, h_bufarg, 1, 2, &offset, &length, 1 /*throw_flag*/);
28213 	DUK_ASSERT(offset <= h_bufarg->length);
28214 	DUK_ASSERT(offset + length <= h_bufarg->length);
28215 
28216 	h_bufobj = duk_push_bufobj_raw(thr,
28217 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
28218 	                               DUK_HOBJECT_FLAG_BUFOBJ |
28219 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATAVIEW),
28220 	                               DUK_BIDX_DATAVIEW_PROTOTYPE);
28221 
28222 	h_val = h_bufarg->buf;
28223 	if (h_val == NULL) {
28224 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28225 	}
28226 	h_bufobj->buf = h_val;
28227 	DUK_HBUFFER_INCREF(thr, h_val);
28228 	h_bufobj->offset = h_bufarg->offset + offset;
28229 	h_bufobj->length = length;
28230 	DUK_ASSERT(h_bufobj->shift == 0);
28231 	DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFOBJ_ELEM_UINT8);
28232 	DUK_ASSERT(h_bufobj->is_typedarray == 0);
28233 
28234 	DUK_ASSERT(h_bufobj->buf_prop == NULL);
28235 	h_bufobj->buf_prop = (duk_hobject *) h_bufarg;
28236 	DUK_ASSERT(h_bufarg != NULL);
28237 	DUK_HBUFOBJ_INCREF(thr, h_bufarg);
28238 
28239 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
28240 	return 1;
28241 }
28242 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28243 
28244 /*
28245  *  ArrayBuffer.isView()
28246  */
28247 
28248 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_arraybuffer_isview(duk_hthread * thr)28249 DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_isview(duk_hthread *thr) {
28250 	duk_hobject *h_obj;
28251 	duk_bool_t ret = 0;
28252 
28253 	if (duk_is_buffer(thr, 0)) {
28254 		ret = 1;
28255 	} else {
28256 		h_obj = duk_get_hobject(thr, 0);
28257 		if (h_obj != NULL && DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
28258 			/* DataView needs special casing: ArrayBuffer.isView() is
28259 			 * true, but ->is_typedarray is 0.
28260 			 */
28261 			ret = ((duk_hbufobj *) h_obj)->is_typedarray ||
28262 			      (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_DATAVIEW);
28263 		}
28264 	}
28265 	duk_push_boolean(thr, ret);
28266 	return 1;
28267 }
28268 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28269 
28270 /*
28271  *  Uint8Array.allocPlain()
28272  */
28273 
28274 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_uint8array_allocplain(duk_hthread * thr)28275 DUK_INTERNAL duk_ret_t duk_bi_uint8array_allocplain(duk_hthread *thr) {
28276 	duk__hbufobj_fixed_from_argvalue(thr);
28277 	return 1;
28278 }
28279 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28280 
28281 /*
28282  *  Uint8Array.plainOf()
28283  */
28284 
28285 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_uint8array_plainof(duk_hthread * thr)28286 DUK_INTERNAL duk_ret_t duk_bi_uint8array_plainof(duk_hthread *thr) {
28287 	duk_hbufobj *h_bufobj;
28288 
28289 #if !defined(DUK_USE_PREFER_SIZE)
28290 	/* Avoid churn if argument is already a plain buffer. */
28291 	if (duk_is_buffer(thr, 0)) {
28292 		return 1;
28293 	}
28294 #endif
28295 
28296 	/* Promotes plain buffers to ArrayBuffers, so for a plain buffer
28297 	 * argument we'll create a pointless temporary (but still work
28298 	 * correctly).
28299 	 */
28300 	h_bufobj = duk__require_bufobj_value(thr, 0);
28301 	if (h_bufobj->buf == NULL) {
28302 		duk_push_undefined(thr);
28303 	} else {
28304 		duk_push_hbuffer(thr, h_bufobj->buf);
28305 	}
28306 	return 1;
28307 }
28308 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28309 
28310 /*
28311  *  Node.js Buffer: toString([encoding], [start], [end])
28312  */
28313 
28314 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_tostring(duk_hthread * thr)28315 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_hthread *thr) {
28316 	duk_hbufobj *h_this;
28317 	duk_int_t start_offset, end_offset;
28318 	duk_uint8_t *buf_slice;
28319 	duk_size_t slice_length;
28320 
28321 	h_this = duk__get_bufobj_this(thr);
28322 	if (h_this == NULL) {
28323 		/* XXX: happens e.g. when evaluating: String(Buffer.prototype). */
28324 		duk_push_literal(thr, "[object Object]");
28325 		return 1;
28326 	}
28327 	DUK_HBUFOBJ_ASSERT_VALID(h_this);
28328 
28329 	/* Ignore encoding for now. */
28330 
28331 	duk__clamp_startend_nonegidx_noshift(thr,
28332 	                                     (duk_int_t) h_this->length,
28333 	                                     1 /*idx_start*/,
28334 	                                     2 /*idx_end*/,
28335 	                                     &start_offset,
28336 	                                     &end_offset);
28337 
28338 	slice_length = (duk_size_t) (end_offset - start_offset);
28339 	buf_slice = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, slice_length);  /* all bytes initialized below */
28340 	DUK_ASSERT(buf_slice != NULL);
28341 
28342 	/* Neutered or uncovered, TypeError. */
28343 	if (h_this->buf == NULL ||
28344 	    !DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, (duk_size_t) start_offset + slice_length)) {
28345 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28346 	}
28347 
28348 	/* XXX: ideally we wouldn't make a copy but a view into the buffer for the
28349 	 * decoding process.  Or the decoding helper could be changed to accept
28350 	 * the slice info (a buffer pointer is NOT a good approach because guaranteeing
28351 	 * its stability is difficult).
28352 	 */
28353 
28354 	DUK_ASSERT(DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, (duk_size_t) start_offset + slice_length));
28355 	duk_memcpy_unsafe((void *) buf_slice,
28356 	                  (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
28357 	                  (size_t) slice_length);
28358 
28359 	/* Use the equivalent of: new TextEncoder().encode(this) to convert the
28360 	 * string.  Result will be valid UTF-8; non-CESU-8 inputs are currently
28361 	 * interpreted loosely.  Value stack convention is a bit odd for now.
28362 	 */
28363 	duk_replace(thr, 0);
28364 	duk_set_top(thr, 1);
28365 	return duk_textdecoder_decode_utf8_nodejs(thr);
28366 }
28367 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28368 
28369 /*
28370  *  Node.js Buffer.prototype: toJSON()
28371  */
28372 
28373 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_tojson(duk_hthread * thr)28374 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_hthread *thr) {
28375 	duk_hbufobj *h_this;
28376 	duk_uint8_t *buf;
28377 	duk_uint_t i, n;
28378 	duk_tval *tv;
28379 
28380 	h_this = duk__require_bufobj_this(thr);
28381 	DUK_ASSERT(h_this != NULL);
28382 
28383 	if (h_this->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_this)) {
28384 		/* Serialize uncovered backing buffer as a null; doesn't
28385 		 * really matter as long we're memory safe.
28386 		 */
28387 		duk_push_null(thr);
28388 		return 1;
28389 	}
28390 
28391 	duk_push_object(thr);
28392 	duk_push_hstring_stridx(thr, DUK_STRIDX_UC_BUFFER);
28393 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_TYPE);
28394 
28395 	/* XXX: uninitialized would be OK */
28396 	DUK_ASSERT_DISABLE((duk_size_t) h_this->length <= (duk_size_t) DUK_UINT32_MAX);
28397 	tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) h_this->length);  /* XXX: needs revision with >4G buffers */
28398 	DUK_ASSERT(!duk_is_bare_object(thr, -1));
28399 
28400 	DUK_ASSERT(h_this->buf != NULL);
28401 	buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
28402 	for (i = 0, n = h_this->length; i < n; i++) {
28403 		DUK_TVAL_SET_U32(tv + i, (duk_uint32_t) buf[i]);  /* no need for decref or incref */
28404 	}
28405 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_DATA);
28406 
28407 	return 1;
28408 }
28409 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28410 
28411 /*
28412  *  Node.js Buffer.prototype.equals()
28413  *  Node.js Buffer.prototype.compare()
28414  *  Node.js Buffer.compare()
28415  */
28416 
28417 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_buffer_compare_shared(duk_hthread * thr)28418 DUK_INTERNAL duk_ret_t duk_bi_buffer_compare_shared(duk_hthread *thr) {
28419 	duk_small_uint_t magic;
28420 	duk_hbufobj *h_bufarg1;
28421 	duk_hbufobj *h_bufarg2;
28422 	duk_small_int_t comp_res;
28423 
28424 	/* XXX: keep support for plain buffers and non-Node.js buffers? */
28425 
28426 	magic = (duk_small_uint_t) duk_get_current_magic(thr);
28427 	if (magic & 0x02U) {
28428 		/* Static call style. */
28429 		h_bufarg1 = duk__require_bufobj_value(thr, 0);
28430 		h_bufarg2 = duk__require_bufobj_value(thr, 1);
28431 	} else {
28432 		h_bufarg1 = duk__require_bufobj_this(thr);
28433 		h_bufarg2 = duk__require_bufobj_value(thr, 0);
28434 	}
28435 	DUK_ASSERT(h_bufarg1 != NULL);
28436 	DUK_ASSERT(h_bufarg2 != NULL);
28437 
28438 	/* We want to compare the slice/view areas of the arguments.
28439 	 * If either slice/view is invalid (underlying buffer is shorter)
28440 	 * ensure equals() is false, but otherwise the only thing that
28441 	 * matters is to be memory safe.
28442 	 */
28443 
28444 	if (DUK_HBUFOBJ_VALID_SLICE(h_bufarg1) &&
28445 	    DUK_HBUFOBJ_VALID_SLICE(h_bufarg2)) {
28446 		comp_res = duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg1->buf) + h_bufarg1->offset,
28447 		                               (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg2->buf) + h_bufarg2->offset,
28448 		                               (duk_size_t) h_bufarg1->length,
28449 		                               (duk_size_t) h_bufarg2->length);
28450 	} else {
28451 		comp_res = -1;  /* either nonzero value is ok */
28452 	}
28453 
28454 	if (magic & 0x01U) {
28455 		/* compare: similar to string comparison but for buffer data. */
28456 		duk_push_int(thr, comp_res);
28457 	} else {
28458 		/* equals */
28459 		duk_push_boolean(thr, (comp_res == 0));
28460 	}
28461 
28462 	return 1;
28463 }
28464 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28465 
28466 /*
28467  *  Node.js Buffer.prototype.fill()
28468  */
28469 
28470 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_fill(duk_hthread * thr)28471 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_fill(duk_hthread *thr) {
28472 	duk_hbufobj *h_this;
28473 	const duk_uint8_t *fill_str_ptr;
28474 	duk_size_t fill_str_len;
28475 	duk_uint8_t fill_value;
28476 	duk_int_t fill_offset;
28477 	duk_int_t fill_end;
28478 	duk_size_t fill_length;
28479 	duk_uint8_t *p;
28480 
28481 	h_this = duk__require_bufobj_this(thr);
28482 	DUK_ASSERT(h_this != NULL);
28483 	if (h_this->buf == NULL) {
28484 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28485 	}
28486 
28487 	/* [ value offset end ] */
28488 
28489 	if (duk_is_string_notsymbol(thr, 0)) {
28490 		fill_str_ptr = (const duk_uint8_t *) duk_get_lstring(thr, 0, &fill_str_len);
28491 		DUK_ASSERT(fill_str_ptr != NULL);
28492 	} else {
28493 		/* Symbols get ToNumber() coerced and cause TypeError. */
28494 		fill_value = (duk_uint8_t) duk_to_uint32(thr, 0);
28495 		fill_str_ptr = (const duk_uint8_t *) &fill_value;
28496 		fill_str_len = 1;
28497 	}
28498 
28499 	/* Fill offset handling is more lenient than in Node.js. */
28500 
28501 	duk__clamp_startend_nonegidx_noshift(thr,
28502 	                                     (duk_int_t) h_this->length,
28503 	                                     1 /*idx_start*/,
28504 	                                     2 /*idx_end*/,
28505 	                                     &fill_offset,
28506 	                                     &fill_end);
28507 
28508 	DUK_DDD(DUK_DDDPRINT("fill: fill_value=%02x, fill_offset=%ld, fill_end=%ld, view length=%ld",
28509 	                     (unsigned int) fill_value, (long) fill_offset, (long) fill_end, (long) h_this->length));
28510 
28511 	DUK_ASSERT(fill_end - fill_offset >= 0);
28512 	DUK_ASSERT(h_this->buf != NULL);
28513 
28514 	p = (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + fill_offset);
28515 	fill_length = (duk_size_t) (fill_end - fill_offset);
28516 	if (fill_str_len == 1) {
28517 		/* Handle single character fills as memset() even when
28518 		 * the fill data comes from a one-char argument.
28519 		 */
28520 		duk_memset_unsafe((void *) p, (int) fill_str_ptr[0], (size_t) fill_length);
28521 	} else if (fill_str_len > 1) {
28522 		duk_size_t i, n, t;
28523 
28524 		for (i = 0, n = (duk_size_t) (fill_end - fill_offset), t = 0; i < n; i++) {
28525 			p[i] = fill_str_ptr[t++];
28526 			if (t >= fill_str_len) {
28527 				t = 0;
28528 			}
28529 		}
28530 	} else {
28531 		DUK_DDD(DUK_DDDPRINT("zero size fill pattern, ignore silently"));
28532 	}
28533 
28534 	/* Return the Buffer to allow chaining: b.fill(0x11).fill(0x22, 3, 5).toString() */
28535 	duk_push_this(thr);
28536 	return 1;
28537 }
28538 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28539 
28540 /*
28541  *  Node.js Buffer.prototype.write(string, [offset], [length], [encoding])
28542  */
28543 
28544 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_write(duk_hthread * thr)28545 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_write(duk_hthread *thr) {
28546 	duk_hbufobj *h_this;
28547 	duk_uint_t offset;
28548 	duk_uint_t length;
28549 	const duk_uint8_t *str_data;
28550 	duk_size_t str_len;
28551 
28552 	/* XXX: very inefficient support for plain buffers */
28553 	h_this = duk__require_bufobj_this(thr);
28554 	DUK_ASSERT(h_this != NULL);
28555 
28556 	/* Argument must be a string, e.g. a buffer is not allowed. */
28557 	str_data = (const duk_uint8_t *) duk_require_lstring_notsymbol(thr, 0, &str_len);
28558 
28559 	duk__resolve_offset_opt_length(thr, h_this, 1, 2, &offset, &length, 0 /*throw_flag*/);
28560 	DUK_ASSERT(offset <= h_this->length);
28561 	DUK_ASSERT(offset + length <= h_this->length);
28562 
28563 	/* XXX: encoding is ignored now. */
28564 
28565 	if (length > str_len) {
28566 		length = (duk_uint_t) str_len;
28567 	}
28568 
28569 	if (DUK_HBUFOBJ_VALID_SLICE(h_this)) {
28570 		/* Cannot overlap. */
28571 		duk_memcpy_unsafe((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset),
28572 		                  (const void *) str_data,
28573 		                  (size_t) length);
28574 	} else {
28575 		DUK_DDD(DUK_DDDPRINT("write() target buffer is not covered, silent ignore"));
28576 	}
28577 
28578 	duk_push_uint(thr, length);
28579 	return 1;
28580 }
28581 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28582 
28583 /*
28584  *  Node.js Buffer.prototype.copy()
28585  */
28586 
28587 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_copy(duk_hthread * thr)28588 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_copy(duk_hthread *thr) {
28589 	duk_hbufobj *h_this;
28590 	duk_hbufobj *h_bufarg;
28591 	duk_int_t source_length;
28592 	duk_int_t target_length;
28593 	duk_int_t target_start, source_start, source_end;
28594 	duk_uint_t target_ustart, source_ustart, source_uend;
28595 	duk_uint_t copy_size = 0;
28596 
28597 	/* [ targetBuffer targetStart sourceStart sourceEnd ] */
28598 
28599 	h_this = duk__require_bufobj_this(thr);
28600 	h_bufarg = duk__require_bufobj_value(thr, 0);
28601 	DUK_ASSERT(h_this != NULL);
28602 	DUK_ASSERT(h_bufarg != NULL);
28603 	source_length = (duk_int_t) h_this->length;
28604 	target_length = (duk_int_t) h_bufarg->length;
28605 
28606 	target_start = duk_to_int(thr, 1);
28607 	source_start = duk_to_int(thr, 2);
28608 	if (duk_is_undefined(thr, 3)) {
28609 		source_end = source_length;
28610 	} else {
28611 		source_end = duk_to_int(thr, 3);
28612 	}
28613 
28614 	DUK_DDD(DUK_DDDPRINT("checking copy args: target_start=%ld, target_length=%ld, "
28615 	                     "source_start=%ld, source_end=%ld, source_length=%ld",
28616 	                     (long) target_start, (long) h_bufarg->length,
28617 	                     (long) source_start, (long) source_end, (long) source_length));
28618 
28619 	/* This behavior mostly mimics Node.js now. */
28620 
28621 	if (source_start < 0 || source_end < 0 || target_start < 0) {
28622 		/* Negative offsets cause a RangeError. */
28623 		goto fail_bounds;
28624 	}
28625 	source_ustart = (duk_uint_t) source_start;
28626 	source_uend = (duk_uint_t) source_end;
28627 	target_ustart = (duk_uint_t) target_start;
28628 	if (source_ustart >= source_uend ||  /* crossed offsets or zero size */
28629 	    source_ustart >= (duk_uint_t) source_length ||  /* source out-of-bounds (but positive) */
28630 	    target_ustart >= (duk_uint_t) target_length) {  /* target out-of-bounds (but positive) */
28631 		goto silent_ignore;
28632 	}
28633 	if (source_uend >= (duk_uint_t) source_length) {
28634 		/* Source end clamped silently to available length. */
28635 		source_uend = (duk_uint_t) source_length;
28636 	}
28637 	copy_size = source_uend - source_ustart;
28638 	if (target_ustart + copy_size > (duk_uint_t) target_length) {
28639 		/* Clamp to target's end if too long.
28640 		 *
28641 		 * NOTE: there's no overflow possibility in the comparison;
28642 		 * both target_ustart and copy_size are >= 0 and based on
28643 		 * values in duk_int_t range.  Adding them as duk_uint_t
28644 		 * values is then guaranteed not to overflow.
28645 		 */
28646 		DUK_ASSERT(target_ustart + copy_size >= target_ustart);  /* no overflow */
28647 		DUK_ASSERT(target_ustart + copy_size >= copy_size);  /* no overflow */
28648 		copy_size = (duk_uint_t) target_length - target_ustart;
28649 	}
28650 
28651 	DUK_DDD(DUK_DDDPRINT("making copy: target_ustart=%lu source_ustart=%lu copy_size=%lu",
28652 	                     (unsigned long) target_ustart, (unsigned long) source_ustart,
28653 	                     (unsigned long) copy_size));
28654 
28655 	DUK_ASSERT(copy_size >= 1);
28656 	DUK_ASSERT(source_ustart <= (duk_uint_t) source_length);
28657 	DUK_ASSERT(source_ustart + copy_size <= (duk_uint_t) source_length);
28658 	DUK_ASSERT(target_ustart <= (duk_uint_t) target_length);
28659 	DUK_ASSERT(target_ustart + copy_size <= (duk_uint_t) target_length);
28660 
28661 	/* Ensure copy is covered by underlying buffers. */
28662 	DUK_ASSERT(h_bufarg->buf != NULL);  /* length check */
28663 	DUK_ASSERT(h_this->buf != NULL);    /* length check */
28664 	if (DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufarg, target_ustart + copy_size) &&
28665 	    DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, source_ustart + copy_size)) {
28666 		/* Must use memmove() because copy area may overlap (source and target
28667 		 * buffer may be the same, or from different slices.
28668 		 */
28669 		duk_memmove_unsafe((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg) + target_ustart),
28670 		                   (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + source_ustart),
28671 		                   (size_t) copy_size);
28672 	} else {
28673 		DUK_DDD(DUK_DDDPRINT("buffer copy not covered by underlying buffer(s), ignoring"));
28674 	}
28675 
28676  silent_ignore:
28677 	/* Return value is like write(), number of bytes written.
28678 	 * The return value matters because of code like:
28679 	 * "off += buf.copy(...)".
28680          */
28681 	duk_push_uint(thr, copy_size);
28682 	return 1;
28683 
28684  fail_bounds:
28685 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
28686 }
28687 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28688 
28689 /*
28690  *  TypedArray.prototype.set()
28691  *
28692  *  TypedArray set() is pretty interesting to implement because:
28693  *
28694  *    - The source argument may be a plain array or a typedarray.  If the
28695  *      source is a TypedArray, values are decoded and re-encoded into the
28696  *      target (not as a plain byte copy).  This may happen even when the
28697  *      element byte size is the same, e.g. integer values may be re-encoded
28698  *      into floats.
28699  *
28700  *    - Source and target may refer to the same underlying buffer, so that
28701  *      the set() operation may overlap.  The specification requires that this
28702  *      must work as if a copy was made before the operation.  Note that this
28703  *      is NOT a simple memmove() situation because the source and target
28704  *      byte sizes may be different -- e.g. a 4-byte source (Int8Array) may
28705  *      expand to a 16-byte target (Uint32Array) so that the target overlaps
28706  *      the source both from beginning and the end (unlike in typical memmove).
28707  *
28708  *    - Even if 'buf' pointers of the source and target differ, there's no
28709  *      guarantee that their memory areas don't overlap.  This may be the
28710  *      case with external buffers.
28711  *
28712  *  Even so, it is nice to optimize for the common case:
28713  *
28714  *    - Source and target separate buffers or non-overlapping.
28715  *
28716  *    - Source and target have a compatible type so that a plain byte copy
28717  *      is possible.  Note that while e.g. uint8 and int8 are compatible
28718  *      (coercion one way or another doesn't change the byte representation),
28719  *      e.g. int8 and uint8clamped are NOT compatible when writing int8
28720  *      values into uint8clamped typedarray (-1 would clamp to 0 for instance).
28721  *
28722  *  See test-bi-typedarray-proto-set.js.
28723  */
28724 
28725 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_typedarray_set(duk_hthread * thr)28726 DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_hthread *thr) {
28727 	duk_hbufobj *h_this;
28728 	duk_hobject *h_obj;
28729 	duk_uarridx_t i, n;
28730 	duk_int_t offset_signed;
28731 	duk_uint_t offset_elems;
28732 	duk_uint_t offset_bytes;
28733 
28734 	h_this = duk__require_bufobj_this(thr);
28735 	DUK_ASSERT(h_this != NULL);
28736 	DUK_HBUFOBJ_ASSERT_VALID(h_this);
28737 
28738 	if (h_this->buf == NULL) {
28739 		DUK_DDD(DUK_DDDPRINT("source neutered, skip copy"));
28740 		return 0;
28741 	}
28742 
28743 	duk_hbufobj_promote_plain(thr, 0);
28744 	h_obj = duk_require_hobject(thr, 0);
28745 
28746 	/* XXX: V8 throws a TypeError for negative values.  Would it
28747 	 * be more useful to interpret negative offsets here from the
28748 	 * end of the buffer too?
28749 	 */
28750 	offset_signed = duk_to_int(thr, 1);
28751 	if (offset_signed < 0) {
28752 		/* For some reason this is a TypeError (at least in V8). */
28753 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28754 	}
28755 	offset_elems = (duk_uint_t) offset_signed;
28756 	offset_bytes = offset_elems << h_this->shift;
28757 	if ((offset_bytes >> h_this->shift) != offset_elems) {
28758 		/* Byte length would overflow. */
28759 		/* XXX: easier check with less code? */
28760 		goto fail_args;
28761 	}
28762 	if (offset_bytes > h_this->length) {
28763 		/* Equality may be OK but >length not.  Checking
28764 		 * this explicitly avoids some overflow cases
28765 		 * below.
28766 		 */
28767 		goto fail_args;
28768 	}
28769 	DUK_ASSERT(offset_bytes <= h_this->length);
28770 
28771 	/* Fast path: source is a TypedArray (or any bufobj). */
28772 
28773 	if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
28774 		duk_hbufobj *h_bufarg;
28775 #if !defined(DUK_USE_PREFER_SIZE)
28776 		duk_uint16_t comp_mask;
28777 #endif
28778 		duk_small_int_t no_overlap = 0;
28779 		duk_uint_t src_length;
28780 		duk_uint_t dst_length;
28781 		duk_uint_t dst_length_elems;
28782 		duk_uint8_t *p_src_base;
28783 		duk_uint8_t *p_src_end;
28784 		duk_uint8_t *p_src;
28785 		duk_uint8_t *p_dst_base;
28786 		duk_uint8_t *p_dst;
28787 		duk_small_uint_t src_elem_size;
28788 		duk_small_uint_t dst_elem_size;
28789 
28790 		h_bufarg = (duk_hbufobj *) h_obj;
28791 		DUK_HBUFOBJ_ASSERT_VALID(h_bufarg);
28792 
28793 		if (h_bufarg->buf == NULL) {
28794 			DUK_DDD(DUK_DDDPRINT("target neutered, skip copy"));
28795 			return 0;
28796 		}
28797 
28798 		/* Nominal size check. */
28799 		src_length = h_bufarg->length;  /* bytes in source */
28800 		dst_length_elems = (src_length >> h_bufarg->shift);  /* elems in source and dest */
28801 		dst_length = dst_length_elems << h_this->shift;  /* bytes in dest */
28802 		if ((dst_length >> h_this->shift) != dst_length_elems) {
28803 			/* Byte length would overflow. */
28804 			/* XXX: easier check with less code? */
28805 			goto fail_args;
28806 		}
28807 		DUK_DDD(DUK_DDDPRINT("nominal size check: src_length=%ld, dst_length=%ld",
28808 		                     (long) src_length, (long) dst_length));
28809 		DUK_ASSERT(offset_bytes <= h_this->length);
28810 		if (dst_length > h_this->length - offset_bytes) {
28811 			/* Overflow not an issue because subtraction is used on the right
28812 			 * side and guaranteed to be >= 0.
28813 			 */
28814 			DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
28815 			goto fail_args;
28816 		}
28817 		if (!DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, offset_bytes + dst_length)) {
28818 			DUK_DDD(DUK_DDDPRINT("copy not covered by underlying target buffer, ignore"));
28819 			return 0;
28820 		}
28821 
28822 		p_src_base = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
28823 		p_dst_base = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset_bytes;
28824 
28825 		/* Check actual underlying buffers for validity and that they
28826 		 * cover the copy.  No side effects are allowed after the check
28827 		 * so that the validity status doesn't change.
28828 		 */
28829 		if (!DUK_HBUFOBJ_VALID_SLICE(h_this) ||
28830 		    !DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {
28831 			/* The condition could be more narrow and check for the
28832 			 * copy area only, but there's no need for fine grained
28833 			 * behavior when the underlying buffer is misconfigured.
28834 			 */
28835 			DUK_DDD(DUK_DDDPRINT("source and/or target not covered by underlying buffer, skip copy"));
28836 			return 0;
28837 		}
28838 
28839 		/* We want to do a straight memory copy if possible: this is
28840 		 * an important operation because .set() is the TypedArray
28841 		 * way to copy chunks of memory.  However, because set()
28842 		 * conceptually works in terms of elements, not all views are
28843 		 * compatible with direct byte copying.
28844 		 *
28845 		 * If we do manage a direct copy, the "overlap issue" handled
28846 		 * below can just be solved using memmove() because the source
28847 		 * and destination element sizes are necessarily equal.
28848 		 */
28849 
28850 #if !defined(DUK_USE_PREFER_SIZE)
28851 		DUK_ASSERT(h_this->elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
28852 		comp_mask = duk__buffer_elemtype_copy_compatible[h_this->elem_type];
28853 		if (comp_mask & (1 << h_bufarg->elem_type)) {
28854 			DUK_ASSERT(src_length == dst_length);
28855 
28856 			DUK_DDD(DUK_DDDPRINT("fast path: able to use memmove() because views are compatible"));
28857 			duk_memmove_unsafe((void *) p_dst_base, (const void *) p_src_base, (size_t) dst_length);
28858 			return 0;
28859 		}
28860 		DUK_DDD(DUK_DDDPRINT("fast path: views are not compatible with a byte copy, copy by item"));
28861 #endif  /* !DUK_USE_PREFER_SIZE */
28862 
28863 		/* We want to avoid making a copy to process set() but that's
28864 		 * not always possible: the source and the target may overlap
28865 		 * and because element sizes are different, the overlap cannot
28866 		 * always be handled with a memmove() or choosing the copy
28867 		 * direction in a certain way.  For example, if source type is
28868 		 * uint8 and target type is uint32, the target area may exceed
28869 		 * the source area from both ends!
28870 		 *
28871 		 * Note that because external buffers may point to the same
28872 		 * memory areas, we must ultimately make this check using
28873 		 * pointers.
28874 		 *
28875 		 * NOTE: careful with side effects: any side effect may cause
28876 		 * a buffer resize (or external buffer pointer/length update)!
28877 		 */
28878 
28879 		DUK_DDD(DUK_DDDPRINT("overlap check: p_src_base=%p, src_length=%ld, "
28880 		                     "p_dst_base=%p, dst_length=%ld",
28881 		                     (void *) p_src_base, (long) src_length,
28882 		                     (void *) p_dst_base, (long) dst_length));
28883 
28884 		if (p_src_base >= p_dst_base + dst_length ||  /* source starts after dest ends */
28885 		    p_src_base + src_length <= p_dst_base) {   /* source ends before dest starts */
28886 			no_overlap = 1;
28887 		}
28888 
28889 		if (!no_overlap) {
28890 			/* There's overlap: the desired end result is that
28891 			 * conceptually a copy is made to avoid "trampling"
28892 			 * of source data by destination writes.  We make
28893 			 * an actual temporary copy to handle this case.
28894 			 */
28895 			duk_uint8_t *p_src_copy;
28896 
28897 			DUK_DDD(DUK_DDDPRINT("there is overlap, make a copy of the source"));
28898 			p_src_copy = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, src_length);
28899 			DUK_ASSERT(p_src_copy != NULL);
28900 			duk_memcpy_unsafe((void *) p_src_copy, (const void *) p_src_base, (size_t) src_length);
28901 
28902 			p_src_base = p_src_copy;  /* use p_src_base from now on */
28903 		}
28904 		/* Value stack intentionally mixed size here. */
28905 
28906 		DUK_DDD(DUK_DDDPRINT("after overlap check: p_src_base=%p, src_length=%ld, "
28907 		                     "p_dst_base=%p, dst_length=%ld, valstack top=%ld",
28908 		                     (void *) p_src_base, (long) src_length,
28909 		                     (void *) p_dst_base, (long) dst_length,
28910 		                     (long) duk_get_top(thr)));
28911 
28912 		/* Ready to make the copy.  We must proceed element by element
28913 		 * and must avoid any side effects that might cause the buffer
28914 		 * validity check above to become invalid.
28915 		 *
28916 		 * Although we work through the value stack here, only plain
28917 		 * numbers are handled which should be side effect safe.
28918 		 */
28919 
28920 		src_elem_size = (duk_small_uint_t) (1U << h_bufarg->shift);
28921 		dst_elem_size = (duk_small_uint_t) (1U << h_this->shift);
28922 		p_src = p_src_base;
28923 		p_dst = p_dst_base;
28924 		p_src_end = p_src_base + src_length;
28925 
28926 		while (p_src != p_src_end) {
28927 			DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
28928 			                     "p_src=%p, p_src_end=%p, p_dst=%p",
28929 			                     (void *) p_src, (void *) p_src_end, (void *) p_dst));
28930 			/* A validated read() is always a number, so it's write coercion
28931 			 * is always side effect free an won't invalidate pointers etc.
28932 			 */
28933 			duk_hbufobj_push_validated_read(thr, h_bufarg, p_src, src_elem_size);
28934 			duk_hbufobj_validated_write(thr, h_this, p_dst, dst_elem_size);
28935 			duk_pop(thr);
28936 			p_src += src_elem_size;
28937 			p_dst += dst_elem_size;
28938 		}
28939 
28940 		return 0;
28941 	} else {
28942 		/* Slow path: quite slow, but we save space by using the property code
28943 		 * to write coerce target values.  We don't need to worry about overlap
28944 		 * here because the source is not a TypedArray.
28945 		 *
28946 		 * We could use the bufobj write coercion helper but since the
28947 		 * property read may have arbitrary side effects, full validity checks
28948 		 * would be needed for every element anyway.
28949 		 */
28950 
28951 		n = (duk_uarridx_t) duk_get_length(thr, 0);
28952 		DUK_ASSERT(offset_bytes <= h_this->length);
28953 		if ((n << h_this->shift) > h_this->length - offset_bytes) {
28954 			/* Overflow not an issue because subtraction is used on the right
28955 			 * side and guaranteed to be >= 0.
28956 			 */
28957 			DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
28958 			goto fail_args;
28959 		}
28960 
28961 		/* There's no need to check for buffer validity status for the
28962 		 * target here: the property access code will do that for each
28963 		 * element.  Moreover, if we did check the validity here, side
28964 		 * effects from reading the source argument might invalidate
28965 		 * the results anyway.
28966 		 */
28967 
28968 		DUK_ASSERT_TOP(thr, 2);
28969 		duk_push_this(thr);
28970 
28971 		for (i = 0; i < n; i++) {
28972 			duk_get_prop_index(thr, 0, i);
28973 			duk_put_prop_index(thr, 2, offset_elems + i);
28974 		}
28975 	}
28976 
28977 	return 0;
28978 
28979  fail_args:
28980 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
28981 }
28982 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28983 
28984 /*
28985  *  Node.js Buffer.prototype.slice([start], [end])
28986  *  ArrayBuffer.prototype.slice(begin, [end])
28987  *  TypedArray.prototype.subarray(begin, [end])
28988  *
28989  *  The API calls are almost identical; negative indices are counted from end
28990  *  of buffer, and final indices are clamped (allowing crossed indices).  Main
28991  *  differences:
28992  *
28993  *    - Copy/view behavior; Node.js .slice() and TypedArray .subarray() create
28994  *      views, ArrayBuffer .slice() creates a copy
28995  *
28996  *    - Resulting object has a different class and prototype depending on the
28997  *      call (or 'this' argument)
28998  *
28999  *    - TypedArray .subarray() arguments are element indices, not byte offsets
29000  *
29001  *    - Plain buffer argument creates a plain buffer slice
29002  */
29003 
29004 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk__arraybuffer_plain_slice(duk_hthread * thr,duk_hbuffer * h_val)29005 DUK_LOCAL void duk__arraybuffer_plain_slice(duk_hthread *thr, duk_hbuffer *h_val) {
29006 	duk_int_t start_offset, end_offset;
29007 	duk_uint_t slice_length;
29008 	duk_uint8_t *p_copy;
29009 	duk_size_t copy_length;
29010 
29011 	duk__clamp_startend_negidx_shifted(thr,
29012 	                                   (duk_int_t) DUK_HBUFFER_GET_SIZE(h_val),
29013 	                                   0 /*buffer_shift*/,
29014 	                                   0 /*idx_start*/,
29015 	                                   1 /*idx_end*/,
29016 	                                   &start_offset,
29017 	                                   &end_offset);
29018 	DUK_ASSERT(end_offset <= (duk_int_t) DUK_HBUFFER_GET_SIZE(h_val));
29019 	DUK_ASSERT(start_offset >= 0);
29020 	DUK_ASSERT(end_offset >= start_offset);
29021 	slice_length = (duk_uint_t) (end_offset - start_offset);
29022 
29023 	p_copy = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) slice_length);
29024 	DUK_ASSERT(p_copy != NULL);
29025 	copy_length = slice_length;
29026 
29027 	duk_memcpy_unsafe((void *) p_copy,
29028 	                  (const void *) ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_val) + start_offset),
29029 	                  copy_length);
29030 }
29031 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
29032 
29033 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29034 /* Shared helper for slice/subarray operation.
29035  * Magic: 0x01=isView, 0x02=copy, 0x04=Node.js Buffer special handling.
29036  */
duk_bi_buffer_slice_shared(duk_hthread * thr)29037 DUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_hthread *thr) {
29038 	duk_small_int_t magic;
29039 	duk_small_uint_t res_class_num;
29040 	duk_small_int_t res_proto_bidx;
29041 	duk_hbufobj *h_this;
29042 	duk_hbufobj *h_bufobj;
29043 	duk_hbuffer *h_val;
29044 	duk_int_t start_offset, end_offset;
29045 	duk_uint_t slice_length;
29046 	duk_tval *tv;
29047 
29048 	/* [ start end ] */
29049 
29050 	magic = duk_get_current_magic(thr);
29051 
29052 	tv = duk_get_borrowed_this_tval(thr);
29053 	DUK_ASSERT(tv != NULL);
29054 
29055 	if (DUK_TVAL_IS_BUFFER(tv)) {
29056 		/* For plain buffers return a plain buffer slice. */
29057 		h_val = DUK_TVAL_GET_BUFFER(tv);
29058 		DUK_ASSERT(h_val != NULL);
29059 
29060 		if (magic & 0x02) {
29061 			/* Make copy: ArrayBuffer.prototype.slice() uses this. */
29062 			duk__arraybuffer_plain_slice(thr, h_val);
29063 			return 1;
29064 		} else {
29065 			/* View into existing buffer: cannot be done if the
29066 			 * result is a plain buffer because there's no slice
29067 			 * info.  So return an ArrayBuffer instance; coerce
29068 			 * the 'this' binding into an object and behave as if
29069 			 * the original call was for an Object-coerced plain
29070 			 * buffer (handled automatically by duk__require_bufobj_this()).
29071 			 */
29072 
29073 			DUK_DDD(DUK_DDDPRINT("slice() doesn't handle view into plain buffer, coerce 'this' to ArrayBuffer object"));
29074 			/* fall through */
29075 		}
29076 	}
29077 	tv = NULL;  /* No longer valid nor needed. */
29078 
29079 	h_this = duk__require_bufobj_this(thr);
29080 
29081 	/* Slice offsets are element (not byte) offsets, which only matters
29082 	 * for TypedArray views, Node.js Buffer and ArrayBuffer have shift
29083 	 * zero so byte and element offsets are the same.  Negative indices
29084 	 * are counted from end of slice, crossed indices are allowed (and
29085 	 * result in zero length result), and final values are clamped
29086 	 * against the current slice.  There's intentionally no check
29087 	 * against the underlying buffer here.
29088 	 */
29089 
29090 	duk__clamp_startend_negidx_shifted(thr,
29091 	                                   (duk_int_t) h_this->length,
29092 	                                   (duk_uint8_t) h_this->shift,
29093 	                                   0 /*idx_start*/,
29094 	                                   1 /*idx_end*/,
29095 	                                   &start_offset,
29096 	                                   &end_offset);
29097 	DUK_ASSERT(end_offset >= start_offset);
29098 	DUK_ASSERT(start_offset >= 0);
29099 	DUK_ASSERT(end_offset >= 0);
29100 	slice_length = (duk_uint_t) (end_offset - start_offset);
29101 
29102 	/* The resulting buffer object gets the same class and prototype as
29103 	 * the buffer in 'this', e.g. if the input is a Uint8Array the
29104 	 * result is a Uint8Array; if the input is a Float32Array, the
29105 	 * result is a Float32Array.  The result internal prototype should
29106 	 * be the default prototype for the class (e.g. initial value of
29107 	 * Uint8Array.prototype), not copied from the argument (Duktape 1.x
29108 	 * did that).
29109 	 *
29110 	 * Node.js Buffers have special handling: they're Uint8Arrays as far
29111 	 * as the internal class is concerned, so the new Buffer should also
29112 	 * be an Uint8Array but inherit from Buffer.prototype.
29113 	 */
29114 	res_class_num = DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_this);
29115 	DUK_ASSERT(res_class_num >= DUK_HOBJECT_CLASS_BUFOBJ_MIN);  /* type check guarantees */
29116 	DUK_ASSERT(res_class_num <= DUK_HOBJECT_CLASS_BUFOBJ_MAX);
29117 	res_proto_bidx = duk__buffer_proto_from_classnum[res_class_num - DUK_HOBJECT_CLASS_BUFOBJ_MIN];
29118 	if (magic & 0x04) {
29119 		res_proto_bidx = DUK_BIDX_NODEJS_BUFFER_PROTOTYPE;
29120 	}
29121 	h_bufobj = duk_push_bufobj_raw(thr,
29122 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
29123 	                               DUK_HOBJECT_FLAG_BUFOBJ |
29124 	                               DUK_HOBJECT_CLASS_AS_FLAGS(res_class_num),
29125 	                               res_proto_bidx);
29126 	DUK_ASSERT(h_bufobj != NULL);
29127 
29128 	DUK_ASSERT(h_bufobj->length == 0);
29129 	h_bufobj->shift = h_this->shift;  /* inherit */
29130 	h_bufobj->elem_type = h_this->elem_type;  /* inherit */
29131 	h_bufobj->is_typedarray = magic & 0x01;
29132 	DUK_ASSERT(h_bufobj->is_typedarray == 0 || h_bufobj->is_typedarray == 1);
29133 
29134 	h_val = h_this->buf;
29135 	if (h_val == NULL) {
29136 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
29137 	}
29138 
29139 	if (magic & 0x02) {
29140 		/* non-zero: make copy */
29141 		duk_uint8_t *p_copy;
29142 		duk_size_t copy_length;
29143 
29144 		p_copy = (duk_uint8_t *) duk_push_fixed_buffer_zero(thr, (duk_size_t) slice_length);  /* must be zeroed, not all bytes always copied */
29145 		DUK_ASSERT(p_copy != NULL);
29146 
29147 		/* Copy slice, respecting underlying buffer limits; remainder
29148 		 * is left as zero.
29149 		 */
29150 		copy_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, slice_length);
29151 		duk_memcpy_unsafe((void *) p_copy,
29152 		                  (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
29153 		                  copy_length);
29154 
29155 		h_val = duk_known_hbuffer(thr, -1);
29156 
29157 		h_bufobj->buf = h_val;
29158 		DUK_HBUFFER_INCREF(thr, h_val);
29159 		h_bufobj->length = slice_length;
29160 		DUK_ASSERT(h_bufobj->offset == 0);
29161 
29162 		duk_pop(thr);  /* reachable so pop OK */
29163 	} else {
29164 		h_bufobj->buf = h_val;
29165 		DUK_HBUFFER_INCREF(thr, h_val);
29166 		h_bufobj->length = slice_length;
29167 		h_bufobj->offset = h_this->offset + (duk_uint_t) start_offset;
29168 
29169 		/* Copy the .buffer property, needed for TypedArray.prototype.subarray().
29170 		 *
29171 		 * XXX: limit copy only for TypedArray classes specifically?
29172 		 */
29173 
29174 		DUK_ASSERT(h_bufobj->buf_prop == NULL);
29175 		h_bufobj->buf_prop = h_this->buf_prop;  /* may be NULL */
29176 		DUK_HOBJECT_INCREF_ALLOWNULL(thr, (duk_hobject *) h_bufobj->buf_prop);
29177 	}
29178 	/* unbalanced stack on purpose */
29179 
29180 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
29181 	return 1;
29182 }
29183 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29184 
29185 /*
29186  *  Node.js Buffer.isEncoding()
29187  */
29188 
29189 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_is_encoding(duk_hthread * thr)29190 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_hthread *thr) {
29191 	const char *encoding;
29192 
29193 	/* only accept lowercase 'utf8' now. */
29194 
29195 	encoding = duk_to_string(thr, 0);
29196 	DUK_ASSERT(duk_is_string(thr, 0));  /* guaranteed by duk_to_string() */
29197 	duk_push_boolean(thr, DUK_STRCMP(encoding, "utf8") == 0);
29198 	return 1;
29199 }
29200 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29201 
29202 /*
29203  *  Node.js Buffer.isBuffer()
29204  */
29205 
29206 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_is_buffer(duk_hthread * thr)29207 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_hthread *thr) {
29208 	duk_hobject *h;
29209 	duk_hobject *h_proto;
29210 	duk_bool_t ret = 0;
29211 
29212 	DUK_ASSERT(duk_get_top(thr) >= 1);  /* nargs */
29213 	h = duk_get_hobject(thr, 0);
29214 	if (h != NULL) {
29215 		h_proto = thr->builtins[DUK_BIDX_NODEJS_BUFFER_PROTOTYPE];
29216 		DUK_ASSERT(h_proto != NULL);
29217 
29218 		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
29219 		if (h != NULL) {
29220 			ret = duk_hobject_prototype_chain_contains(thr, h, h_proto, 0 /*ignore_loop*/);
29221 		}
29222 	}
29223 
29224 	duk_push_boolean(thr, ret);
29225 	return 1;
29226 }
29227 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29228 
29229 /*
29230  *  Node.js Buffer.byteLength()
29231  */
29232 
29233 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_byte_length(duk_hthread * thr)29234 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_hthread *thr) {
29235 	const char *str;
29236 	duk_size_t len;
29237 
29238 	/* At the moment Buffer(<str>) will just use the string bytes as
29239 	 * is (ignoring encoding), so we return the string length here
29240 	 * unconditionally.
29241 	 */
29242 
29243 	/* XXX: to be revised; Old Node.js behavior just coerces any buffer
29244 	 * values to string:
29245 	 * $ node
29246 	 * > Buffer.byteLength(new Uint32Array(10))
29247 	 * 20
29248 	 * > Buffer.byteLength(new Uint32Array(100))
29249 	 * 20
29250 	 * (The 20 comes from '[object Uint32Array]'.length
29251 	 */
29252 
29253 	str = duk_to_lstring(thr, 0, &len);
29254 	DUK_UNREF(str);
29255 	duk_push_size_t(thr, len);
29256 	return 1;
29257 }
29258 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29259 
29260 /*
29261  *  Node.js Buffer.concat()
29262  */
29263 
29264 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_concat(duk_hthread * thr)29265 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_hthread *thr) {
29266 	duk_hobject *h_arg;
29267 	duk_uint_t total_length;
29268 	duk_hbufobj *h_bufobj;
29269 	duk_hbufobj *h_bufres;
29270 	duk_hbuffer *h_val;
29271 	duk_uint_t i, n;
29272 	duk_uint8_t *p;
29273 	duk_size_t space_left;
29274 	duk_size_t copy_size;
29275 
29276 	/* Node.js accepts only actual Arrays. */
29277 	h_arg = duk_require_hobject(thr, 0);
29278 	if (DUK_HOBJECT_GET_CLASS_NUMBER(h_arg) != DUK_HOBJECT_CLASS_ARRAY) {
29279 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
29280 	}
29281 
29282 	/* Compute result length and validate argument buffers. */
29283 	n = (duk_uint_t) duk_get_length(thr, 0);
29284 	total_length = 0;
29285 	for (i = 0; i < n; i++) {
29286 		/* Neutered checks not necessary here: neutered buffers have
29287 		 * zero 'length' so we'll effectively skip them.
29288 		 */
29289 		DUK_ASSERT_TOP(thr, 2);  /* [ array totalLength ] */
29290 		duk_get_prop_index(thr, 0, (duk_uarridx_t) i);  /* -> [ array totalLength buf ] */
29291 		h_bufobj = duk__require_bufobj_value(thr, 2);
29292 		DUK_ASSERT(h_bufobj != NULL);
29293 		total_length += h_bufobj->length;
29294 		if (DUK_UNLIKELY(total_length < h_bufobj->length)) {
29295 			DUK_DCERROR_RANGE_INVALID_ARGS(thr);  /* Wrapped. */
29296 		}
29297 		duk_pop(thr);
29298 	}
29299 	/* In Node.js v0.12.1 a 1-element array is special and won't create a
29300 	 * copy, this was fixed later so an explicit check no longer needed.
29301 	 */
29302 
29303 	/* User totalLength overrides a computed length, but we'll check
29304 	 * every copy in the copy loop.  Note that duk_to_int() can
29305 	 * technically have arbitrary side effects so we need to recheck
29306 	 * the buffers in the copy loop.
29307 	 */
29308 	if (!duk_is_undefined(thr, 1) && n > 0) {
29309 		/* For n == 0, Node.js ignores totalLength argument and
29310 		 * returns a zero length buffer.
29311 		 */
29312 		duk_int_t total_length_signed;
29313 		total_length_signed = duk_to_int(thr, 1);
29314 		if (total_length_signed < 0) {
29315 			DUK_DCERROR_RANGE_INVALID_ARGS(thr);
29316 		}
29317 		total_length = (duk_uint_t) total_length_signed;
29318 	}
29319 
29320 	h_bufres = duk_push_bufobj_raw(thr,
29321 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
29322 	                               DUK_HOBJECT_FLAG_BUFOBJ |
29323 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_UINT8ARRAY),
29324 	                               DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);
29325 	DUK_ASSERT(h_bufres != NULL);
29326 
29327 	p = (duk_uint8_t *) duk_push_fixed_buffer_zero(thr, total_length);  /* must be zeroed, all bytes not necessarily written over */
29328 	DUK_ASSERT(p != NULL);
29329 	space_left = (duk_size_t) total_length;
29330 
29331 	for (i = 0; i < n; i++) {
29332 		DUK_ASSERT_TOP(thr, 4);  /* [ array totalLength bufres buf ] */
29333 
29334 		duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
29335 		h_bufobj = duk__require_bufobj_value(thr, 4);
29336 		DUK_ASSERT(h_bufobj != NULL);
29337 
29338 		copy_size = h_bufobj->length;
29339 		if (copy_size > space_left) {
29340 			copy_size = space_left;
29341 		}
29342 
29343 		if (h_bufobj->buf != NULL &&
29344 		    DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
29345 			duk_memcpy_unsafe((void *) p,
29346 			                  (const void *) DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj),
29347 			                  copy_size);
29348 		} else {
29349 			/* Just skip, leaving zeroes in the result. */
29350 			;
29351 		}
29352 		p += copy_size;
29353 		space_left -= copy_size;
29354 
29355 		duk_pop(thr);
29356 	}
29357 
29358 	h_val = duk_known_hbuffer(thr, -1);
29359 
29360 	duk__set_bufobj_buffer(thr, h_bufres, h_val);
29361 	h_bufres->is_typedarray = 1;
29362 	DUK_HBUFOBJ_ASSERT_VALID(h_bufres);
29363 
29364 	duk_pop(thr);  /* pop plain buffer, now reachable through h_bufres */
29365 
29366 	return 1;  /* return h_bufres */
29367 }
29368 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29369 
29370 /*
29371  *  Shared readfield and writefield methods
29372  *
29373  *  The readfield/writefield methods need support for endianness and field
29374  *  types.  All offsets are byte based so no offset shifting is needed.
29375  */
29376 
29377 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29378 /* Format of magic, bits:
29379  *   0...1: field type; 0=uint8, 1=uint16, 2=uint32, 3=float, 4=double, 5=unused, 6=unused, 7=unused
29380  *       3: endianness: 0=little, 1=big
29381  *       4: signed: 1=yes, 0=no
29382  *       5: typedarray: 1=yes, 0=no
29383  */
29384 #define  DUK__FLD_8BIT         0
29385 #define  DUK__FLD_16BIT        1
29386 #define  DUK__FLD_32BIT        2
29387 #define  DUK__FLD_FLOAT        3
29388 #define  DUK__FLD_DOUBLE       4
29389 #define  DUK__FLD_VARINT       5
29390 #define  DUK__FLD_BIGENDIAN    (1 << 3)
29391 #define  DUK__FLD_SIGNED       (1 << 4)
29392 #define  DUK__FLD_TYPEDARRAY   (1 << 5)
29393 
29394 /* XXX: split into separate functions for each field type? */
duk_bi_buffer_readfield(duk_hthread * thr)29395 DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {
29396 	duk_small_uint_t magic = (duk_small_uint_t) duk_get_current_magic(thr);
29397 	duk_small_uint_t magic_ftype;
29398 	duk_small_uint_t magic_bigendian;
29399 	duk_small_uint_t magic_signed;
29400 	duk_small_uint_t magic_typedarray;
29401 	duk_small_uint_t endswap;
29402 	duk_hbufobj *h_this;
29403 	duk_bool_t no_assert;
29404 	duk_int_t offset_signed;
29405 	duk_uint_t offset;
29406 	duk_uint_t buffer_length;
29407 	duk_uint_t check_length;
29408 	duk_uint8_t *buf;
29409 	duk_double_union du;
29410 
29411 	magic_ftype = magic & 0x0007U;
29412 	magic_bigendian = magic & 0x0008U;
29413 	magic_signed = magic & 0x0010U;
29414 	magic_typedarray = magic & 0x0020U;
29415 
29416 	h_this = duk__require_bufobj_this(thr);  /* XXX: very inefficient for plain buffers */
29417 	DUK_ASSERT(h_this != NULL);
29418 	buffer_length = h_this->length;
29419 
29420 	/* [ offset noAssert                 ], when ftype != DUK__FLD_VARINT */
29421 	/* [ offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
29422 	/* [ offset littleEndian             ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
29423 
29424 	/* Handle TypedArray vs. Node.js Buffer arg differences */
29425 	if (magic_typedarray) {
29426 		no_assert = 0;
29427 #if defined(DUK_USE_INTEGER_LE)
29428 		endswap = !duk_to_boolean(thr, 1);  /* 1=little endian */
29429 #else
29430 		endswap = duk_to_boolean(thr, 1);  /* 1=little endian */
29431 #endif
29432 	} else {
29433 		no_assert = duk_to_boolean(thr, (magic_ftype == DUK__FLD_VARINT) ? 2 : 1);
29434 #if defined(DUK_USE_INTEGER_LE)
29435 		endswap = magic_bigendian;
29436 #else
29437 		endswap = !magic_bigendian;
29438 #endif
29439 	}
29440 
29441 	/* Offset is coerced first to signed integer range and then to unsigned.
29442 	 * This ensures we can add a small byte length (1-8) to the offset in
29443 	 * bound checks and not wrap.
29444 	 */
29445 	offset_signed = duk_to_int(thr, 0);
29446 	offset = (duk_uint_t) offset_signed;
29447 	if (offset_signed < 0) {
29448 		goto fail_bounds;
29449 	}
29450 
29451 	DUK_DDD(DUK_DDDPRINT("readfield, buffer_length=%ld, offset=%ld, no_assert=%d, "
29452 	                     "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
29453 	                     "endswap=%u",
29454 	                     (long) buffer_length, (long) offset, (int) no_assert,
29455 	                     (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
29456 	                     (int) (magic_signed >> 4), (int) endswap));
29457 
29458 	/* Update 'buffer_length' to be the effective, safe limit which
29459 	 * takes into account the underlying buffer.  This value will be
29460 	 * potentially invalidated by any side effect.
29461 	 */
29462 	check_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, buffer_length);
29463 	DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
29464 	                     (long) buffer_length, (long) check_length));
29465 
29466 	if (h_this->buf) {
29467 		buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
29468 	} else {
29469 		/* Neutered.  We could go into the switch-case safely with
29470 		 * buf == NULL because check_length == 0.  To avoid scanbuild
29471 		 * warnings, fail directly instead.
29472 		 */
29473 		DUK_ASSERT(check_length == 0);
29474 		goto fail_neutered;
29475 	}
29476 	DUK_ASSERT(buf != NULL);
29477 
29478 	switch (magic_ftype) {
29479 	case DUK__FLD_8BIT: {
29480 		duk_uint8_t tmp;
29481 		if (offset + 1U > check_length) {
29482 			goto fail_bounds;
29483 		}
29484 		tmp = buf[offset];
29485 		if (magic_signed) {
29486 			duk_push_int(thr, (duk_int_t) ((duk_int8_t) tmp));
29487 		} else {
29488 			duk_push_uint(thr, (duk_uint_t) tmp);
29489 		}
29490 		break;
29491 	}
29492 	case DUK__FLD_16BIT: {
29493 		duk_uint16_t tmp;
29494 		if (offset + 2U > check_length) {
29495 			goto fail_bounds;
29496 		}
29497 		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 2);
29498 		tmp = du.us[0];
29499 		if (endswap) {
29500 			tmp = DUK_BSWAP16(tmp);
29501 		}
29502 		if (magic_signed) {
29503 			duk_push_int(thr, (duk_int_t) ((duk_int16_t) tmp));
29504 		} else {
29505 			duk_push_uint(thr, (duk_uint_t) tmp);
29506 		}
29507 		break;
29508 	}
29509 	case DUK__FLD_32BIT: {
29510 		duk_uint32_t tmp;
29511 		if (offset + 4U > check_length) {
29512 			goto fail_bounds;
29513 		}
29514 		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 4);
29515 		tmp = du.ui[0];
29516 		if (endswap) {
29517 			tmp = DUK_BSWAP32(tmp);
29518 		}
29519 		if (magic_signed) {
29520 			duk_push_int(thr, (duk_int_t) ((duk_int32_t) tmp));
29521 		} else {
29522 			duk_push_uint(thr, (duk_uint_t) tmp);
29523 		}
29524 		break;
29525 	}
29526 	case DUK__FLD_FLOAT: {
29527 		duk_uint32_t tmp;
29528 		if (offset + 4U > check_length) {
29529 			goto fail_bounds;
29530 		}
29531 		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 4);
29532 		if (endswap) {
29533 			tmp = du.ui[0];
29534 			tmp = DUK_BSWAP32(tmp);
29535 			du.ui[0] = tmp;
29536 		}
29537 		duk_push_number(thr, (duk_double_t) du.f[0]);
29538 		break;
29539 	}
29540 	case DUK__FLD_DOUBLE: {
29541 		if (offset + 8U > check_length) {
29542 			goto fail_bounds;
29543 		}
29544 		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 8);
29545 		if (endswap) {
29546 			DUK_DBLUNION_BSWAP64(&du);
29547 		}
29548 		duk_push_number(thr, (duk_double_t) du.d);
29549 		break;
29550 	}
29551 	case DUK__FLD_VARINT: {
29552 		/* Node.js Buffer variable width integer field.  We don't really
29553 		 * care about speed here, so aim for shortest algorithm.
29554 		 */
29555 		duk_int_t field_bytelen;
29556 		duk_int_t i, i_step, i_end;
29557 #if defined(DUK_USE_64BIT_OPS)
29558 		duk_int64_t tmp;
29559 		duk_small_uint_t shift_tmp;
29560 #else
29561 		duk_double_t tmp;
29562 		duk_small_int_t highbyte;
29563 #endif
29564 		const duk_uint8_t *p;
29565 
29566 		field_bytelen = duk_get_int(thr, 1);  /* avoid side effects! */
29567 		if (field_bytelen < 1 || field_bytelen > 6) {
29568 			goto fail_field_length;
29569 		}
29570 		if (offset + (duk_uint_t) field_bytelen > check_length) {
29571 			goto fail_bounds;
29572 		}
29573 		p = (const duk_uint8_t *) (buf + offset);
29574 
29575 		/* Slow gathering of value using either 64-bit arithmetic
29576 		 * or IEEE doubles if 64-bit types not available.  Handling
29577 		 * of negative numbers is a bit non-obvious in both cases.
29578 		 */
29579 
29580 		if (magic_bigendian) {
29581 			/* Gather in big endian */
29582 			i = 0;
29583 			i_step = 1;
29584 			i_end = field_bytelen;  /* one i_step over */
29585 		} else {
29586 			/* Gather in little endian */
29587 			i = field_bytelen - 1;
29588 			i_step = -1;
29589 			i_end = -1;  /* one i_step over */
29590 		}
29591 
29592 #if defined(DUK_USE_64BIT_OPS)
29593 		tmp = 0;
29594 		do {
29595 			DUK_ASSERT(i >= 0 && i < field_bytelen);
29596 			tmp = (tmp << 8) + (duk_int64_t) p[i];
29597 			i += i_step;
29598 		} while (i != i_end);
29599 
29600 		if (magic_signed) {
29601 			/* Shift to sign extend.  Left shift must be unsigned
29602 			 * to avoid undefined behavior; right shift must be
29603 			 * signed to sign extend properly.
29604 			 */
29605 			shift_tmp = (duk_small_uint_t) (64U - (duk_small_uint_t) field_bytelen * 8U);
29606 			tmp = (duk_int64_t) ((duk_uint64_t) tmp << shift_tmp) >> shift_tmp;
29607 		}
29608 
29609 		duk_push_i64(thr, tmp);
29610 #else
29611 		highbyte = p[i];
29612 		if (magic_signed && (highbyte & 0x80) != 0) {
29613 			/* 0xff => 255 - 256 = -1; 0x80 => 128 - 256 = -128 */
29614 			tmp = (duk_double_t) (highbyte - 256);
29615 		} else {
29616 			tmp = (duk_double_t) highbyte;
29617 		}
29618 		for (;;) {
29619 			i += i_step;
29620 			if (i == i_end) {
29621 				break;
29622 			}
29623 			DUK_ASSERT(i >= 0 && i < field_bytelen);
29624 			tmp = (tmp * 256.0) + (duk_double_t) p[i];
29625 		}
29626 
29627 		duk_push_number(thr, tmp);
29628 #endif
29629 		break;
29630 	}
29631 	default: {  /* should never happen but default here */
29632 		goto fail_bounds;
29633 	}
29634 	}
29635 
29636 	return 1;
29637 
29638  fail_neutered:
29639  fail_field_length:
29640  fail_bounds:
29641 	if (no_assert) {
29642 		/* Node.js return value for noAssert out-of-bounds reads is
29643 		 * usually (but not always) NaN.  Return NaN consistently.
29644 		 */
29645 		duk_push_nan(thr);
29646 		return 1;
29647 	}
29648 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
29649 }
29650 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29651 
29652 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29653 /* XXX: split into separate functions for each field type? */
duk_bi_buffer_writefield(duk_hthread * thr)29654 DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
29655 	duk_small_uint_t magic = (duk_small_uint_t) duk_get_current_magic(thr);
29656 	duk_small_uint_t magic_ftype;
29657 	duk_small_uint_t magic_bigendian;
29658 	duk_small_uint_t magic_signed;
29659 	duk_small_uint_t magic_typedarray;
29660 	duk_small_uint_t endswap;
29661 	duk_hbufobj *h_this;
29662 	duk_bool_t no_assert;
29663 	duk_int_t offset_signed;
29664 	duk_uint_t offset;
29665 	duk_uint_t buffer_length;
29666 	duk_uint_t check_length;
29667 	duk_uint8_t *buf;
29668 	duk_double_union du;
29669 	duk_int_t nbytes = 0;
29670 
29671 	magic_ftype = magic & 0x0007U;
29672 	magic_bigendian = magic & 0x0008U;
29673 	magic_signed = magic & 0x0010U;
29674 	magic_typedarray = magic & 0x0020U;
29675 	DUK_UNREF(magic_signed);
29676 
29677 	h_this = duk__require_bufobj_this(thr);  /* XXX: very inefficient for plain buffers */
29678 	DUK_ASSERT(h_this != NULL);
29679 	buffer_length = h_this->length;
29680 
29681 	/* [ value  offset noAssert                 ], when ftype != DUK__FLD_VARINT */
29682 	/* [ value  offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
29683 	/* [ offset value  littleEndian             ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
29684 
29685 	/* Handle TypedArray vs. Node.js Buffer arg differences */
29686 	if (magic_typedarray) {
29687 		no_assert = 0;
29688 #if defined(DUK_USE_INTEGER_LE)
29689 		endswap = !duk_to_boolean(thr, 2);  /* 1=little endian */
29690 #else
29691 		endswap = duk_to_boolean(thr, 2);  /* 1=little endian */
29692 #endif
29693 		duk_swap(thr, 0, 1);  /* offset/value order different from Node.js */
29694 	} else {
29695 		no_assert = duk_to_boolean(thr, (magic_ftype == DUK__FLD_VARINT) ? 3 : 2);
29696 #if defined(DUK_USE_INTEGER_LE)
29697 		endswap = magic_bigendian;
29698 #else
29699 		endswap = !magic_bigendian;
29700 #endif
29701 	}
29702 
29703 	/* Offset is coerced first to signed integer range and then to unsigned.
29704 	 * This ensures we can add a small byte length (1-8) to the offset in
29705 	 * bound checks and not wrap.
29706 	 */
29707 	offset_signed = duk_to_int(thr, 1);
29708 	offset = (duk_uint_t) offset_signed;
29709 
29710 	/* We need 'nbytes' even for a failed offset; return value must be
29711 	 * (offset + nbytes) even when write fails due to invalid offset.
29712 	 */
29713 	if (magic_ftype != DUK__FLD_VARINT) {
29714 		DUK_ASSERT(magic_ftype < (duk_small_uint_t) (sizeof(duk__buffer_nbytes_from_fldtype) / sizeof(duk_uint8_t)));
29715 		nbytes = duk__buffer_nbytes_from_fldtype[magic_ftype];
29716 	} else {
29717 		nbytes = duk_get_int(thr, 2);
29718 		if (nbytes < 1 || nbytes > 6) {
29719 			goto fail_field_length;
29720 		}
29721 	}
29722 	DUK_ASSERT(nbytes >= 1 && nbytes <= 8);
29723 
29724 	/* Now we can check offset validity. */
29725 	if (offset_signed < 0) {
29726 		goto fail_bounds;
29727 	}
29728 
29729 	DUK_DDD(DUK_DDDPRINT("writefield, value=%!T, buffer_length=%ld, offset=%ld, no_assert=%d, "
29730 	                     "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
29731 	                     "endswap=%u",
29732 	                     duk_get_tval(thr, 0), (long) buffer_length, (long) offset, (int) no_assert,
29733 	                     (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
29734 	                     (int) (magic_signed >> 4), (int) endswap));
29735 
29736 	/* Coerce value to a number before computing check_length, so that
29737 	 * the field type specific coercion below can't have side effects
29738 	 * that would invalidate check_length.
29739 	 */
29740 	duk_to_number(thr, 0);
29741 
29742 	/* Update 'buffer_length' to be the effective, safe limit which
29743 	 * takes into account the underlying buffer.  This value will be
29744 	 * potentially invalidated by any side effect.
29745 	 */
29746 	check_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, buffer_length);
29747 	DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
29748 	                     (long) buffer_length, (long) check_length));
29749 
29750 	if (h_this->buf) {
29751 		buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
29752 	} else {
29753 		/* Neutered.  We could go into the switch-case safely with
29754 		 * buf == NULL because check_length == 0.  To avoid scanbuild
29755 		 * warnings, fail directly instead.
29756 		 */
29757 		DUK_ASSERT(check_length == 0);
29758 		goto fail_neutered;
29759 	}
29760 	DUK_ASSERT(buf != NULL);
29761 
29762 	switch (magic_ftype) {
29763 	case DUK__FLD_8BIT: {
29764 		if (offset + 1U > check_length) {
29765 			goto fail_bounds;
29766 		}
29767 		/* sign doesn't matter when writing */
29768 		buf[offset] = (duk_uint8_t) duk_to_uint32(thr, 0);
29769 		break;
29770 	}
29771 	case DUK__FLD_16BIT: {
29772 		duk_uint16_t tmp;
29773 		if (offset + 2U > check_length) {
29774 			goto fail_bounds;
29775 		}
29776 		tmp = (duk_uint16_t) duk_to_uint32(thr, 0);
29777 		if (endswap) {
29778 			tmp = DUK_BSWAP16(tmp);
29779 		}
29780 		du.us[0] = tmp;
29781 		/* sign doesn't matter when writing */
29782 		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 2);
29783 		break;
29784 	}
29785 	case DUK__FLD_32BIT: {
29786 		duk_uint32_t tmp;
29787 		if (offset + 4U > check_length) {
29788 			goto fail_bounds;
29789 		}
29790 		tmp = (duk_uint32_t) duk_to_uint32(thr, 0);
29791 		if (endswap) {
29792 			tmp = DUK_BSWAP32(tmp);
29793 		}
29794 		du.ui[0] = tmp;
29795 		/* sign doesn't matter when writing */
29796 		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 4);
29797 		break;
29798 	}
29799 	case DUK__FLD_FLOAT: {
29800 		duk_uint32_t tmp;
29801 		if (offset + 4U > check_length) {
29802 			goto fail_bounds;
29803 		}
29804 		du.f[0] = (duk_float_t) duk_to_number(thr, 0);
29805 		if (endswap) {
29806 			tmp = du.ui[0];
29807 			tmp = DUK_BSWAP32(tmp);
29808 			du.ui[0] = tmp;
29809 		}
29810 		/* sign doesn't matter when writing */
29811 		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 4);
29812 		break;
29813 	}
29814 	case DUK__FLD_DOUBLE: {
29815 		if (offset + 8U > check_length) {
29816 			goto fail_bounds;
29817 		}
29818 		du.d = (duk_double_t) duk_to_number(thr, 0);
29819 		if (endswap) {
29820 			DUK_DBLUNION_BSWAP64(&du);
29821 		}
29822 		/* sign doesn't matter when writing */
29823 		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 8);
29824 		break;
29825 	}
29826 	case DUK__FLD_VARINT: {
29827 		/* Node.js Buffer variable width integer field.  We don't really
29828 		 * care about speed here, so aim for shortest algorithm.
29829 		 */
29830 		duk_int_t field_bytelen;
29831 		duk_int_t i, i_step, i_end;
29832 #if defined(DUK_USE_64BIT_OPS)
29833 		duk_int64_t tmp;
29834 #else
29835 		duk_double_t tmp;
29836 #endif
29837 		duk_uint8_t *p;
29838 
29839 		field_bytelen = (duk_int_t) nbytes;
29840 		if (offset + (duk_uint_t) field_bytelen > check_length) {
29841 			goto fail_bounds;
29842 		}
29843 
29844 		/* Slow writing of value using either 64-bit arithmetic
29845 		 * or IEEE doubles if 64-bit types not available.  There's
29846 		 * no special sign handling when writing varints.
29847 		 */
29848 
29849 		if (magic_bigendian) {
29850 			/* Write in big endian */
29851 			i = field_bytelen;  /* one i_step added at top of loop */
29852 			i_step = -1;
29853 			i_end = 0;
29854 		} else {
29855 			/* Write in little endian */
29856 			i = -1;  /* one i_step added at top of loop */
29857 			i_step = 1;
29858 			i_end = field_bytelen - 1;
29859 		}
29860 
29861 		/* XXX: The duk_to_number() cast followed by integer coercion
29862 		 * is platform specific so NaN, +/- Infinity, and out-of-bounds
29863 		 * values result in platform specific output now.
29864 		 * See: test-bi-nodejs-buffer-proto-varint-special.js
29865 		 */
29866 
29867 #if defined(DUK_USE_64BIT_OPS)
29868 		tmp = (duk_int64_t) duk_to_number(thr, 0);
29869 		p = (duk_uint8_t *) (buf + offset);
29870 		do {
29871 			i += i_step;
29872 			DUK_ASSERT(i >= 0 && i < field_bytelen);
29873 			p[i] = (duk_uint8_t) (tmp & 0xff);
29874 			tmp = tmp >> 8;  /* unnecessary shift for last byte */
29875 		} while (i != i_end);
29876 #else
29877 		tmp = duk_to_number(thr, 0);
29878 		p = (duk_uint8_t *) (buf + offset);
29879 		do {
29880 			i += i_step;
29881 			tmp = DUK_FLOOR(tmp);
29882 			DUK_ASSERT(i >= 0 && i < field_bytelen);
29883 			p[i] = (duk_uint8_t) (DUK_FMOD(tmp, 256.0));
29884 			tmp = tmp / 256.0;  /* unnecessary div for last byte */
29885 		} while (i != i_end);
29886 #endif
29887 		break;
29888 	}
29889 	default: {  /* should never happen but default here */
29890 		goto fail_bounds;
29891 	}
29892 	}
29893 
29894 	/* Node.js Buffer: return offset + #bytes written (i.e. next
29895 	 * write offset).
29896 	 */
29897 	if (magic_typedarray) {
29898 		/* For TypedArrays 'undefined' return value is specified
29899 		 * by ES2015 (matches V8).
29900 		 */
29901 		return 0;
29902 	}
29903 	duk_push_uint(thr, offset + (duk_uint_t) nbytes);
29904 	return 1;
29905 
29906  fail_neutered:
29907  fail_field_length:
29908  fail_bounds:
29909 	if (no_assert) {
29910 		/* Node.js return value for failed writes is offset + #bytes
29911 		 * that would have been written.
29912 		 */
29913 		/* XXX: for negative input offsets, 'offset' will be a large
29914 		 * positive value so the result here is confusing.
29915 		 */
29916 		if (magic_typedarray) {
29917 			return 0;
29918 		}
29919 		duk_push_uint(thr, offset + (duk_uint_t) nbytes);
29920 		return 1;
29921 	}
29922 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
29923 }
29924 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29925 
29926 /*
29927  *  Accessors for .buffer, .byteLength, .byteOffset
29928  */
29929 
29930 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk__autospawn_arraybuffer(duk_hthread * thr,duk_hbuffer * h_buf)29931 DUK_LOCAL duk_hbufobj *duk__autospawn_arraybuffer(duk_hthread *thr, duk_hbuffer *h_buf) {
29932 	duk_hbufobj *h_res;
29933 
29934 	h_res = duk_push_bufobj_raw(thr,
29935 	                            DUK_HOBJECT_FLAG_EXTENSIBLE |
29936 	                            DUK_HOBJECT_FLAG_BUFOBJ |
29937 	                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
29938 	                            DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
29939 	DUK_ASSERT(h_res != NULL);
29940 	DUK_UNREF(h_res);
29941 
29942 	duk__set_bufobj_buffer(thr, h_res, h_buf);
29943 	DUK_HBUFOBJ_ASSERT_VALID(h_res);
29944 	DUK_ASSERT(h_res->buf_prop == NULL);
29945 	return h_res;
29946 }
29947 
duk_bi_typedarray_buffer_getter(duk_hthread * thr)29948 DUK_INTERNAL duk_ret_t duk_bi_typedarray_buffer_getter(duk_hthread *thr) {
29949 	duk_hbufobj *h_bufobj;
29950 
29951 	h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
29952 	DUK_ASSERT(h_bufobj != NULL);
29953 	if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
29954 		DUK_DD(DUK_DDPRINT("autospawn ArrayBuffer for plain buffer"));
29955 		(void) duk__autospawn_arraybuffer(thr, (duk_hbuffer *) h_bufobj);
29956 		return 1;
29957 	} else {
29958 		if (h_bufobj->buf_prop == NULL &&
29959 		    DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_bufobj) != DUK_HOBJECT_CLASS_ARRAYBUFFER &&
29960 		    h_bufobj->buf != NULL) {
29961 			duk_hbufobj *h_arrbuf;
29962 
29963 			DUK_DD(DUK_DDPRINT("autospawn ArrayBuffer for typed array or DataView"));
29964 			h_arrbuf = duk__autospawn_arraybuffer(thr, h_bufobj->buf);
29965 
29966 			if (h_bufobj->buf_prop == NULL) {
29967 				/* Must recheck buf_prop, in case ArrayBuffer
29968 				 * alloc had a side effect which already filled
29969 				 * it!
29970 				 */
29971 
29972 				/* Set ArrayBuffer's .byteOffset and .byteLength based
29973 				 * on the view so that Arraybuffer[view.byteOffset]
29974 				 * matches view[0].
29975 				 */
29976 				h_arrbuf->offset = 0;
29977 				DUK_ASSERT(h_bufobj->offset + h_bufobj->length >= h_bufobj->offset);  /* Wrap check on creation. */
29978 				h_arrbuf->length = h_bufobj->offset + h_bufobj->length;
29979 				DUK_ASSERT(h_arrbuf->buf_prop == NULL);
29980 
29981 				DUK_ASSERT(h_bufobj->buf_prop == NULL);
29982 				h_bufobj->buf_prop = (duk_hobject *) h_arrbuf;
29983 				DUK_HBUFOBJ_INCREF(thr, h_arrbuf);  /* Now reachable and accounted for. */
29984 			}
29985 
29986 			/* Left on stack; pushed for the second time below (OK). */
29987 		}
29988 		if (h_bufobj->buf_prop) {
29989 			duk_push_hobject(thr, h_bufobj->buf_prop);
29990 			return 1;
29991 		}
29992 	}
29993 	return 0;
29994 }
29995 
duk_bi_typedarray_byteoffset_getter(duk_hthread * thr)29996 DUK_INTERNAL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_hthread *thr) {
29997 	duk_hbufobj *h_bufobj;
29998 
29999 	h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
30000 	DUK_ASSERT(h_bufobj != NULL);
30001 	if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
30002 		duk_push_uint(thr, 0);
30003 	} else {
30004 		/* If neutered must return 0; offset is zeroed during
30005 		 * neutering.
30006 		 */
30007 		duk_push_uint(thr, h_bufobj->offset);
30008 	}
30009 	return 1;
30010 }
30011 
duk_bi_typedarray_bytelength_getter(duk_hthread * thr)30012 DUK_INTERNAL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_hthread *thr) {
30013 	duk_hbufobj *h_bufobj;
30014 
30015 	h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
30016 	DUK_ASSERT(h_bufobj != NULL);
30017 	if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
30018 		duk_hbuffer *h_buf;
30019 
30020 		h_buf = (duk_hbuffer *) h_bufobj;
30021 		DUK_ASSERT(DUK_HBUFFER_GET_SIZE(h_buf) <= DUK_UINT_MAX);  /* Buffer limits. */
30022 		duk_push_uint(thr, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));
30023 	} else {
30024 		/* If neutered must return 0; length is zeroed during
30025 		 * neutering.
30026 		 */
30027 		duk_push_uint(thr, h_bufobj->length);
30028 	}
30029 	return 1;
30030 }
30031 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
30032 /* No .buffer getter without ArrayBuffer support. */
30033 #if 0
30034 DUK_INTERNAL duk_ret_t duk_bi_typedarray_buffer_getter(duk_hthread *thr) {
30035 	return 0;
30036 }
30037 #endif
30038 
duk_bi_typedarray_byteoffset_getter(duk_hthread * thr)30039 DUK_INTERNAL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_hthread *thr) {
30040 	duk_push_uint(thr, 0);
30041 	return 1;
30042 }
30043 
duk_bi_typedarray_bytelength_getter(duk_hthread * thr)30044 DUK_INTERNAL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_hthread *thr) {
30045 	duk_hbuffer *h_buf;
30046 
30047 	/* XXX: helper? */
30048 	duk_push_this(thr);
30049 	h_buf = duk_require_hbuffer(thr, -1);
30050 	duk_push_uint(thr, DUK_HBUFFER_GET_SIZE(h_buf));
30051 	return 1;
30052 }
30053 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
30054 
30055 /* automatic undefs */
30056 #undef DUK__BUFOBJ_FLAG_PROMOTE
30057 #undef DUK__BUFOBJ_FLAG_THROW
30058 #undef DUK__FLD_16BIT
30059 #undef DUK__FLD_32BIT
30060 #undef DUK__FLD_8BIT
30061 #undef DUK__FLD_BIGENDIAN
30062 #undef DUK__FLD_DOUBLE
30063 #undef DUK__FLD_FLOAT
30064 #undef DUK__FLD_SIGNED
30065 #undef DUK__FLD_TYPEDARRAY
30066 #undef DUK__FLD_VARINT
30067 #line 1 "duk_bi_cbor.c"
30068 /*
30069  *  CBOR bindings.
30070  *
30071  *  http://cbor.io/
30072  *  https://tools.ietf.org/html/rfc7049
30073  */
30074 
30075 /* #include duk_internal.h -> already included */
30076 
30077 #if defined(DUK_USE_CBOR_SUPPORT)
30078 
30079 /* #define DUK_CBOR_STRESS */
30080 
30081 /* Default behavior for encoding strings: use CBOR text string if string
30082  * is UTF-8 compatible, otherwise use CBOR byte string.  These defines
30083  * can be used to force either type for all strings.  Using text strings
30084  * for non-UTF-8 data is technically invalid CBOR.
30085  */
30086 /* #define DUK_CBOR_TEXT_STRINGS */
30087 /* #define DUK_CBOR_BYTE_STRINGS */
30088 
30089 /* Misc. defines. */
30090 /* #define DUK_CBOR_PREFER_SIZE */
30091 /* #define DUK_CBOR_DOUBLE_AS_IS */
30092 /* #define DUK_CBOR_DECODE_FASTPATH */
30093 
30094 typedef struct {
30095 	duk_hthread *thr;
30096 	duk_uint8_t *ptr;
30097 	duk_uint8_t *buf;
30098 	duk_uint8_t *buf_end;
30099 	duk_size_t len;
30100 	duk_idx_t idx_buf;
30101 	duk_uint_t recursion_depth;
30102 	duk_uint_t recursion_limit;
30103 } duk_cbor_encode_context;
30104 
30105 typedef struct {
30106 	duk_hthread *thr;
30107 	const duk_uint8_t *buf;
30108 	duk_size_t off;
30109 	duk_size_t len;
30110 	duk_uint_t recursion_depth;
30111 	duk_uint_t recursion_limit;
30112 } duk_cbor_decode_context;
30113 
30114 DUK_LOCAL void duk__cbor_encode_value(duk_cbor_encode_context *enc_ctx);
30115 DUK_LOCAL void duk__cbor_decode_value(duk_cbor_decode_context *dec_ctx);
30116 
30117 /*
30118  *  Misc
30119  */
30120 
duk__cbor_double_to_uint32(double d)30121 DUK_LOCAL duk_uint32_t duk__cbor_double_to_uint32(double d) {
30122 	/* Out of range casts are undefined behavior, so caller must avoid. */
30123 	DUK_ASSERT(d >= 0.0 && d <= 4294967295.0);
30124 	return (duk_uint32_t) d;
30125 }
30126 
30127 /*
30128  *  Encoding
30129  */
30130 
duk__cbor_encode_error(duk_cbor_encode_context * enc_ctx)30131 DUK_LOCAL void duk__cbor_encode_error(duk_cbor_encode_context *enc_ctx) {
30132 	(void) duk_type_error(enc_ctx->thr, "cbor encode error");
30133 }
30134 
duk__cbor_encode_req_stack(duk_cbor_encode_context * enc_ctx)30135 DUK_LOCAL void duk__cbor_encode_req_stack(duk_cbor_encode_context *enc_ctx) {
30136 	duk_require_stack(enc_ctx->thr, 4);
30137 }
30138 
duk__cbor_encode_objarr_entry(duk_cbor_encode_context * enc_ctx)30139 DUK_LOCAL void duk__cbor_encode_objarr_entry(duk_cbor_encode_context *enc_ctx) {
30140 	duk_hthread *thr = enc_ctx->thr;
30141 
30142 	/* Native stack check in object/array recursion. */
30143 	duk_native_stack_check(thr);
30144 
30145 	/* When working with deeply recursive structures, this is important
30146 	 * to ensure there's no effective depth limit.
30147 	 */
30148 	duk__cbor_encode_req_stack(enc_ctx);
30149 
30150 	DUK_ASSERT(enc_ctx->recursion_depth <= enc_ctx->recursion_limit);
30151 	if (enc_ctx->recursion_depth >= enc_ctx->recursion_limit) {
30152 		DUK_ERROR_RANGE(thr, DUK_STR_ENC_RECLIMIT);
30153 		DUK_WO_NORETURN(return;);
30154 	}
30155 	enc_ctx->recursion_depth++;
30156 }
30157 
duk__cbor_encode_objarr_exit(duk_cbor_encode_context * enc_ctx)30158 DUK_LOCAL void duk__cbor_encode_objarr_exit(duk_cbor_encode_context *enc_ctx) {
30159 	DUK_ASSERT(enc_ctx->recursion_depth > 0);
30160 	enc_ctx->recursion_depth--;
30161 }
30162 
30163 /* Check that a size_t is in uint32 range to avoid out-of-range casts. */
duk__cbor_encode_sizet_uint32_check(duk_cbor_encode_context * enc_ctx,duk_size_t len)30164 DUK_LOCAL void duk__cbor_encode_sizet_uint32_check(duk_cbor_encode_context *enc_ctx, duk_size_t len) {
30165 	if (DUK_UNLIKELY(sizeof(duk_size_t) > sizeof(duk_uint32_t) && len > (duk_size_t) DUK_UINT32_MAX)) {
30166 		duk__cbor_encode_error(enc_ctx);
30167 	}
30168 }
30169 
duk__cbor_encode_ensure_slowpath(duk_cbor_encode_context * enc_ctx,duk_size_t len)30170 DUK_LOCAL DUK_NOINLINE void duk__cbor_encode_ensure_slowpath(duk_cbor_encode_context *enc_ctx, duk_size_t len) {
30171 	duk_size_t oldlen;
30172 	duk_size_t minlen;
30173 	duk_size_t newlen;
30174 	duk_uint8_t *p_new;
30175 	duk_size_t old_data_len;
30176 
30177 	DUK_ASSERT(enc_ctx->ptr >= enc_ctx->buf);
30178 	DUK_ASSERT(enc_ctx->buf_end >= enc_ctx->ptr);
30179 	DUK_ASSERT(enc_ctx->buf_end >= enc_ctx->buf);
30180 
30181 	/* Overflow check.
30182 	 *
30183 	 * Limit example: 0xffffffffUL / 2U = 0x7fffffffUL, we reject >= 0x80000000UL.
30184 	 */
30185 	oldlen = enc_ctx->len;
30186 	minlen = oldlen + len;
30187 	if (DUK_UNLIKELY(oldlen > DUK_SIZE_MAX / 2U || minlen < oldlen)) {
30188 		duk__cbor_encode_error(enc_ctx);
30189 	}
30190 
30191 #if defined(DUK_CBOR_STRESS)
30192 	newlen = oldlen + 1U;
30193 #else
30194 	newlen = oldlen * 2U;
30195 #endif
30196 	DUK_ASSERT(newlen >= oldlen);
30197 
30198 	if (minlen > newlen) {
30199 		newlen = minlen;
30200 	}
30201 	DUK_ASSERT(newlen >= oldlen);
30202 	DUK_ASSERT(newlen >= minlen);
30203 	DUK_ASSERT(newlen > 0U);
30204 
30205 	DUK_DD(DUK_DDPRINT("cbor encode buffer resized to %ld", (long) newlen));
30206 
30207 	p_new = (duk_uint8_t *) duk_resize_buffer(enc_ctx->thr, enc_ctx->idx_buf, newlen);
30208 	DUK_ASSERT(p_new != NULL);
30209 	old_data_len = (duk_size_t) (enc_ctx->ptr - enc_ctx->buf);
30210 	enc_ctx->buf = p_new;
30211 	enc_ctx->buf_end = p_new + newlen;
30212 	enc_ctx->ptr = p_new + old_data_len;
30213 	enc_ctx->len = newlen;
30214 }
30215 
duk__cbor_encode_ensure(duk_cbor_encode_context * enc_ctx,duk_size_t len)30216 DUK_LOCAL DUK_INLINE void duk__cbor_encode_ensure(duk_cbor_encode_context *enc_ctx, duk_size_t len) {
30217 	if (DUK_LIKELY((duk_size_t) (enc_ctx->buf_end - enc_ctx->ptr) >= len)) {
30218 		return;
30219 	}
30220 	duk__cbor_encode_ensure_slowpath(enc_ctx, len);
30221 }
30222 
duk__cbor_get_reserve(duk_cbor_encode_context * enc_ctx)30223 DUK_LOCAL duk_size_t duk__cbor_get_reserve(duk_cbor_encode_context *enc_ctx) {
30224 	DUK_ASSERT(enc_ctx->ptr >= enc_ctx->buf);
30225 	DUK_ASSERT(enc_ctx->ptr <= enc_ctx->buf_end);
30226 	return (duk_size_t) (enc_ctx->buf_end - enc_ctx->ptr);
30227 }
30228 
duk__cbor_encode_uint32(duk_cbor_encode_context * enc_ctx,duk_uint32_t u,duk_uint8_t base)30229 DUK_LOCAL void duk__cbor_encode_uint32(duk_cbor_encode_context *enc_ctx, duk_uint32_t u, duk_uint8_t base) {
30230 	duk_uint8_t *p;
30231 
30232 	/* Caller must ensure space. */
30233 	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 4);
30234 
30235 	p = enc_ctx->ptr;
30236 	if (DUK_LIKELY(u <= 23U)) {
30237 		*p++ = (duk_uint8_t) (base + (duk_uint8_t) u);
30238 	} else if (u <= 0xffUL) {
30239 		*p++ = base + 0x18U;
30240 		*p++ = (duk_uint8_t) u;
30241 	} else if (u <= 0xffffUL) {
30242 		*p++ = base + 0x19U;
30243 		DUK_RAW_WRITEINC_U16_BE(p, (duk_uint16_t) u);
30244 	} else {
30245 		*p++ = base + 0x1aU;
30246 		DUK_RAW_WRITEINC_U32_BE(p, u);
30247 	}
30248 	enc_ctx->ptr = p;
30249 }
30250 
30251 #if defined(DUK_CBOR_DOUBLE_AS_IS)
duk__cbor_encode_double(duk_cbor_encode_context * enc_ctx,double d)30252 DUK_LOCAL void duk__cbor_encode_double(duk_cbor_encode_context *enc_ctx, double d) {
30253 	duk_uint8_t *p;
30254 
30255 	/* Caller must ensure space. */
30256 	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
30257 
30258 	p = enc_ctx->ptr;
30259 	*p++ = 0xfbU;
30260 	DUK_RAW_WRITEINC_DOUBLE_BE(p, d);
30261 	p += 8;
30262 	enc_ctx->ptr = p;
30263 }
30264 #else  /* DUK_CBOR_DOUBLE_AS_IS */
duk__cbor_encode_double_fp(duk_cbor_encode_context * enc_ctx,double d)30265 DUK_LOCAL void duk__cbor_encode_double_fp(duk_cbor_encode_context *enc_ctx, double d) {
30266 	duk_double_union u;
30267 	duk_uint16_t u16;
30268 	duk_int16_t expt;
30269 	duk_uint8_t *p;
30270 
30271 	DUK_ASSERT(DUK_FPCLASSIFY(d) != DUK_FP_ZERO);
30272 
30273 	/* Caller must ensure space. */
30274 	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
30275 
30276 	/* Organize into little endian (no-op if platform is little endian). */
30277 	u.d = d;
30278 	duk_dblunion_host_to_little(&u);
30279 
30280 	/* Check if 'd' can represented as a normal half-float.
30281 	 * Denormal half-floats could also be used, but that check
30282 	 * isn't done now (denormal half-floats are decoded of course).
30283 	 * So just check exponent range and that at most 10 significant
30284 	 * bits (excluding implicit leading 1) are used in 'd'.
30285 	 */
30286 	u16 = (((duk_uint16_t) u.uc[7]) << 8) | ((duk_uint16_t) u.uc[6]);
30287 	expt = (duk_int16_t) ((u16 & 0x7ff0U) >> 4) - 1023;
30288 
30289 	if (expt >= -14 && expt <= 15) {
30290 		/* Half-float normal exponents (excl. denormals).
30291 		 *
30292 		 *          7        6        5        4        3        2        1        0  (LE index)
30293 		 * double: seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
30294 		 * half:         seeeee mmmm mmmmmm00 00000000 00000000 00000000 00000000 00000000
30295 		 */
30296 		duk_bool_t use_half_float;
30297 
30298 		use_half_float =
30299 		    (u.uc[0] == 0 && u.uc[1] == 0 && u.uc[2] == 0 && u.uc[3] == 0 &&
30300 		     u.uc[4] == 0 && (u.uc[5] & 0x03U) == 0);
30301 
30302 		if (use_half_float) {
30303 			duk_uint32_t t;
30304 
30305 			expt += 15;
30306 			t = (duk_uint32_t) (u.uc[7] & 0x80U) << 8;
30307 			t += (duk_uint32_t) expt << 10;
30308 			t += ((duk_uint32_t) u.uc[6] & 0x0fU) << 6;
30309 			t += ((duk_uint32_t) u.uc[5]) >> 2;
30310 
30311 			/* seeeeemm mmmmmmmm */
30312 			p = enc_ctx->ptr;
30313 			*p++ = 0xf9U;
30314 			DUK_RAW_WRITEINC_U16_BE(p, (duk_uint16_t) t);
30315 			enc_ctx->ptr = p;
30316 			return;
30317 		}
30318 	}
30319 
30320 	/* Same check for plain float.  Also no denormal support here. */
30321 	if (expt >= -126 && expt <= 127) {
30322 		/* Float normal exponents (excl. denormals).
30323 		 *
30324 		 * double: seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
30325 		 * float:     seeee eeeemmmm mmmmmmmm mmmmmmmm mmm00000 00000000 00000000 00000000
30326 		 */
30327 		duk_bool_t use_float;
30328 		duk_float_t d_float;
30329 
30330 		/* We could do this explicit mantissa check, but doing
30331 		 * a double-float-double cast is fine because we've
30332 		 * already verified that the exponent is in range so
30333 		 * that the narrower cast is not undefined behavior.
30334 		 */
30335 #if 0
30336 		use_float =
30337 		    (u.uc[0] == 0 && u.uc[1] == 0 && u.uc[2] == 0 && (u.uc[3] & 0xe0U) == 0);
30338 #endif
30339 		d_float = (duk_float_t) d;
30340 		use_float = duk_double_equals((duk_double_t) d_float, d);
30341 		if (use_float) {
30342 			p = enc_ctx->ptr;
30343 			*p++ = 0xfaU;
30344 			DUK_RAW_WRITEINC_FLOAT_BE(p, d_float);
30345 			enc_ctx->ptr = p;
30346 			return;
30347 		}
30348 	}
30349 
30350 	/* Special handling for NaN and Inf which we want to encode as
30351 	 * half-floats.  They share the same (maximum) exponent.
30352 	 */
30353 	if (expt == 1024) {
30354 		DUK_ASSERT(DUK_ISNAN(d) || DUK_ISINF(d));
30355 		p = enc_ctx->ptr;
30356 		*p++ = 0xf9U;
30357 		if (DUK_ISNAN(d)) {
30358 			/* Shortest NaN encoding is using a half-float.  Lose the
30359 			 * exact NaN bits in the process.  IEEE double would be
30360 			 * 7ff8 0000 0000 0000, i.e. a quiet NaN in most architectures
30361 			 * (https://en.wikipedia.org/wiki/NaN#Encoding).  The
30362 			 * equivalent half float is 7e00.
30363 			 */
30364 			*p++ = 0x7eU;
30365 		} else {
30366 			/* Shortest +/- Infinity encoding is using a half-float. */
30367 			if (DUK_SIGNBIT(d)) {
30368 				*p++ = 0xfcU;
30369 			} else {
30370 				*p++ = 0x7cU;
30371 			}
30372 		}
30373 		*p++ = 0x00U;
30374 		enc_ctx->ptr = p;
30375 		return;
30376 	}
30377 
30378 	/* Cannot use half-float or float, encode as full IEEE double. */
30379 	p = enc_ctx->ptr;
30380 	*p++ = 0xfbU;
30381 	DUK_RAW_WRITEINC_DOUBLE_BE(p, d);
30382 	enc_ctx->ptr = p;
30383 }
30384 
duk__cbor_encode_double(duk_cbor_encode_context * enc_ctx,double d)30385 DUK_LOCAL void duk__cbor_encode_double(duk_cbor_encode_context *enc_ctx, double d) {
30386 	duk_uint8_t *p;
30387 	double d_floor;
30388 
30389 	/* Integers and floating point values of all types are conceptually
30390 	 * equivalent in CBOR.  Try to always choose the shortest encoding
30391 	 * which is not always immediately obvious.  For example, NaN and Inf
30392 	 * can be most compactly represented as a half-float (assuming NaN
30393 	 * bits are not preserved), and 0x1'0000'0000 as a single precision
30394 	 * float.  Shortest forms in preference order (prefer integer over
30395 	 * float when equal length):
30396 	 *
30397 	 *   uint        1 byte    [0,23] (not -0)
30398 	 *   sint        1 byte    [-24,-1]
30399 	 *   uint+1      2 bytes   [24,255]
30400 	 *   sint+1      2 bytes   [-256,-25]
30401 	 *   uint+2      3 bytes   [256,65535]
30402 	 *   sint+2      3 bytes   [-65536,-257]
30403 	 *   half-float  3 bytes   -0, NaN, +/- Infinity, range [-65504,65504]
30404 	 *   uint+4      5 bytes   [65536,4294967295]
30405 	 *   sint+4      5 bytes   [-4294967296,-258]
30406 	 *   float       5 bytes   range [-(1 - 2^(-24)) * 2^128, (1 - 2^(-24)) * 2^128]
30407 	 *   uint+8      9 bytes   [4294967296,18446744073709551615]
30408 	 *   sint+8      9 bytes   [-18446744073709551616,-4294967297]
30409 	 *   double      9 bytes
30410 	 *
30411 	 * For whole numbers (compatible with integers):
30412 	 *   - 1-byte or 2-byte uint/sint representation is preferred for
30413 	 *     [-256,255].
30414 	 *   - 3-byte uint/sint is preferred for [-65536,65535].  Half floats
30415 	 *     are never preferred because they have the same length.
30416 	 *   - 5-byte uint/sint is preferred for [-4294967296,4294967295].
30417 	 *     Single precision floats are never preferred, and half-floats
30418 	 *     don't reach above the 3-byte uint/sint range so they're never
30419 	 *     preferred.
30420 	 *   - So, for all integers up to signed/unsigned 32-bit range the
30421 	 *     preferred encoding is always an integer uint/sint.
30422 	 *   - For integers above 32 bits the situation is more complicated.
30423 	 *     Half-floats are never useful for them because of their limited
30424 	 *     range, but IEEE single precision floats (5 bytes encoded) can
30425 	 *     represent some integers between the 32-bit and 64-bit ranges
30426 	 *     which require 9 bytes as a uint/sint.
30427 	 *
30428 	 * For floating point values not compatible with integers, the
30429 	 * preferred encoding is quite clear:
30430 	 *   - For +Inf/-Inf use half-float.
30431 	 *   - For NaN use a half-float, assuming NaN bits ("payload") is
30432 	 *     not worth preserving.  Duktape doesn't in general guarantee
30433 	 *     preservation of the NaN payload so using a half-float seems
30434 	 *     consistent with that.
30435 	 *   - For remaining values, prefer the shortest form which doesn't
30436 	 *     lose any precision.  For normal half-floats and single precision
30437 	 *     floats this is simple: just check exponent and mantissa bits
30438 	 *     using a fixed mask.  For denormal half-floats and single
30439 	 *     precision floats the check is a bit more complicated: a normal
30440 	 *     IEEE double can sometimes be represented as a denormal
30441 	 *     half-float or single precision float.
30442 	 *
30443 	 * https://en.wikipedia.org/wiki/Half-precision_floating-point_format#IEEE_754_half-precision_binary_floating-point_format:_binary16
30444 	 */
30445 
30446 	/* Caller must ensure space. */
30447 	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
30448 
30449 	/* Most important path is integers.  The floor() test will be true
30450 	 * for Inf too (but not NaN).
30451 	 */
30452 	d_floor = DUK_FLOOR(d);  /* identity if d is +/- 0.0, NaN, or +/- Infinity */
30453 	if (DUK_LIKELY(duk_double_equals(d_floor, d) != 0)) {
30454 		DUK_ASSERT(!DUK_ISNAN(d));  /* NaN == NaN compares false. */
30455 		if (DUK_SIGNBIT(d)) {
30456 			if (d >= -4294967296.0) {
30457 				d = -1.0 - d;
30458 				if (d >= 0.0) {
30459 					DUK_ASSERT(d >= 0.0);
30460 					duk__cbor_encode_uint32(enc_ctx, duk__cbor_double_to_uint32(d), 0x20U);
30461 					return;
30462 				}
30463 
30464 				/* Input was negative zero, d == -1.0 < 0.0.
30465 				 * Shortest -0 is using half-float.
30466 				 */
30467 				p = enc_ctx->ptr;
30468 				*p++ = 0xf9U;
30469 				*p++ = 0x80U;
30470 				*p++ = 0x00U;
30471 				enc_ctx->ptr = p;
30472 				return;
30473 			}
30474 		} else {
30475 			if (d <= 4294967295.0) {
30476 				/* Positive zero needs no special handling. */
30477 				DUK_ASSERT(d >= 0.0);
30478 				duk__cbor_encode_uint32(enc_ctx, duk__cbor_double_to_uint32(d), 0x00U);
30479 				return;
30480 			}
30481 		}
30482 	}
30483 
30484 	/* 64-bit integers are not supported at present.  So
30485 	 * we also don't need to deal with choosing between a
30486 	 * 64-bit uint/sint representation vs. IEEE double or
30487 	 * float.
30488 	 */
30489 
30490 	DUK_ASSERT(DUK_FPCLASSIFY(d) != DUK_FP_ZERO);
30491 	duk__cbor_encode_double_fp(enc_ctx, d);
30492 }
30493 #endif  /* DUK_CBOR_DOUBLE_AS_IS */
30494 
duk__cbor_encode_string_top(duk_cbor_encode_context * enc_ctx)30495 DUK_LOCAL void duk__cbor_encode_string_top(duk_cbor_encode_context *enc_ctx) {
30496 	const duk_uint8_t *str;
30497 	duk_size_t len;
30498 	duk_uint8_t *p;
30499 
30500 	/* CBOR differentiates between UTF-8 text strings and byte strings.
30501 	 * Text strings MUST be valid UTF-8, so not all Duktape strings can
30502 	 * be encoded as valid CBOR text strings.  Possible behaviors:
30503 	 *
30504 	 *   1. Use text string when input is valid UTF-8, otherwise use
30505 	 *      byte string (maybe tagged to indicate it was an extended
30506 	 *      UTF-8 string).
30507 	 *   2. Always use text strings, but sanitize input string so that
30508 	 *      invalid UTF-8 is replaced with U+FFFD for example.  Combine
30509 	 *      surrogates whenever possible.
30510 	 *   3. Always use byte strings.  This is simple and produces valid
30511 	 *      CBOR, but isn't ideal for interoperability.
30512 	 *   4. Always use text strings, even for invalid UTF-8 such as
30513 	 *      codepoints in the surrogate pair range.  This is simple but
30514 	 *      produces technically invalid CBOR for non-UTF-8 strings which
30515 	 *      may affect interoperability.
30516 	 *
30517 	 * Current default is 1; can be changed with defines.
30518 	 */
30519 
30520 	/* Caller must ensure space. */
30521 	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
30522 
30523 	str = (const duk_uint8_t *) duk_require_lstring(enc_ctx->thr, -1, &len);
30524 	if (duk_is_symbol(enc_ctx->thr, -1)) {
30525 		/* Symbols, encode as an empty table for now.  This matches
30526 		 * the behavior of cbor-js.
30527 		 *
30528 		 * XXX: Maybe encode String() coercion with a tag?
30529 		 * XXX: Option to keep enough information to recover
30530 		 * Symbols when decoding (this is not always desirable).
30531 		 */
30532 		p = enc_ctx->ptr;
30533 		*p++ = 0xa0U;
30534 		enc_ctx->ptr = p;
30535 		return;
30536 	}
30537 
30538 	duk__cbor_encode_sizet_uint32_check(enc_ctx, len);
30539 #if defined(DUK_CBOR_TEXT_STRINGS)
30540 	duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x60U);
30541 #elif defined(DUK_CBOR_BYTE_STRINGS)
30542 	duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x40U);
30543 #else
30544 	duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len,
30545 	                        (DUK_LIKELY(duk_unicode_is_utf8_compatible(str, len) != 0) ? 0x60U : 0x40U));
30546 #endif
30547 	duk__cbor_encode_ensure(enc_ctx, len);
30548 	p = enc_ctx->ptr;
30549 	duk_memcpy((void *) p, (const void *) str, len);
30550 	p += len;
30551 	enc_ctx->ptr = p;
30552 }
30553 
duk__cbor_encode_object(duk_cbor_encode_context * enc_ctx)30554 DUK_LOCAL void duk__cbor_encode_object(duk_cbor_encode_context *enc_ctx) {
30555 	duk_uint8_t *buf;
30556 	duk_size_t len;
30557 	duk_uint8_t *p;
30558 	duk_size_t i;
30559 	duk_size_t off_ib;
30560 	duk_uint32_t count;
30561 
30562 	/* Caller must ensure space. */
30563 	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
30564 
30565 	duk__cbor_encode_objarr_entry(enc_ctx);
30566 
30567 	/* XXX: Support for specific built-ins like Date and RegExp. */
30568 	if (duk_is_array(enc_ctx->thr, -1)) {
30569 		/* Shortest encoding for arrays >= 256 in length is actually
30570 		 * the indefinite length one (3 or more bytes vs. 2 bytes).
30571 		 * We still use the definite length version because it is
30572 		 * more decoding friendly.
30573 		 */
30574 		len = duk_get_length(enc_ctx->thr, -1);
30575 		duk__cbor_encode_sizet_uint32_check(enc_ctx, len);
30576 		duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x80U);
30577 		for (i = 0; i < len; i++) {
30578 			duk_get_prop_index(enc_ctx->thr, -1, (duk_uarridx_t) i);
30579 			duk__cbor_encode_value(enc_ctx);
30580 		}
30581 	} else if (duk_is_buffer_data(enc_ctx->thr, -1)) {
30582 		/* XXX: Tag buffer data?
30583 		 * XXX: Encode typed arrays as integer arrays rather
30584 		 * than buffer data as is?
30585 		 */
30586 		buf = (duk_uint8_t *) duk_require_buffer_data(enc_ctx->thr, -1, &len);
30587 		duk__cbor_encode_sizet_uint32_check(enc_ctx, len);
30588 		duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x40U);
30589 		duk__cbor_encode_ensure(enc_ctx, len);
30590 		p = enc_ctx->ptr;
30591 		duk_memcpy_unsafe((void *) p, (const void *) buf, len);
30592 		p += len;
30593 		enc_ctx->ptr = p;
30594 	} else {
30595 		/* We don't know the number of properties in advance
30596 		 * but would still like to encode at least small
30597 		 * objects without indefinite length.  Emit an
30598 		 * indefinite length byte initially, and if the final
30599 		 * property count is small enough to also fit in one
30600 		 * byte, backpatch it later.  Otherwise keep the
30601 		 * indefinite length.  This works well up to 23
30602 		 * properties which is practical and good enough.
30603 		 */
30604 		off_ib = (duk_size_t) (enc_ctx->ptr - enc_ctx->buf);  /* XXX: get_offset? */
30605 		count = 0U;
30606 		p = enc_ctx->ptr;
30607 		*p++ = 0xa0U + 0x1fU;  /* indefinite length */
30608 		enc_ctx->ptr = p;
30609 		duk_enum(enc_ctx->thr, -1, DUK_ENUM_OWN_PROPERTIES_ONLY);
30610 		while (duk_next(enc_ctx->thr, -1, 1 /*get_value*/)) {
30611 			duk_insert(enc_ctx->thr, -2);  /* [ ... key value ] -> [ ... value key ] */
30612 			duk__cbor_encode_value(enc_ctx);
30613 			duk__cbor_encode_value(enc_ctx);
30614 			count++;
30615 			if (count == 0U) {
30616 				duk__cbor_encode_error(enc_ctx);
30617 			}
30618 		}
30619 		duk_pop(enc_ctx->thr);
30620 		if (count <= 0x17U) {
30621 			DUK_ASSERT(off_ib < enc_ctx->len);
30622 			enc_ctx->buf[off_ib] = 0xa0U + (duk_uint8_t) count;
30623 		} else {
30624 			duk__cbor_encode_ensure(enc_ctx, 1);
30625 			p = enc_ctx->ptr;
30626 			*p++ = 0xffU;  /* break */
30627 			enc_ctx->ptr = p;
30628 		}
30629 	}
30630 
30631 	duk__cbor_encode_objarr_exit(enc_ctx);
30632 }
30633 
duk__cbor_encode_buffer(duk_cbor_encode_context * enc_ctx)30634 DUK_LOCAL void duk__cbor_encode_buffer(duk_cbor_encode_context *enc_ctx) {
30635 	duk_uint8_t *buf;
30636 	duk_size_t len;
30637 	duk_uint8_t *p;
30638 
30639 	/* Caller must ensure space. */
30640 	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
30641 
30642 	/* Tag buffer data? */
30643 	buf = (duk_uint8_t *) duk_require_buffer(enc_ctx->thr, -1, &len);
30644 	duk__cbor_encode_sizet_uint32_check(enc_ctx, len);
30645 	duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x40U);
30646 	duk__cbor_encode_ensure(enc_ctx, len);
30647 	p = enc_ctx->ptr;
30648 	duk_memcpy_unsafe((void *) p, (const void *) buf, len);
30649 	p += len;
30650 	enc_ctx->ptr = p;
30651 }
30652 
duk__cbor_encode_pointer(duk_cbor_encode_context * enc_ctx)30653 DUK_LOCAL void duk__cbor_encode_pointer(duk_cbor_encode_context *enc_ctx) {
30654 	/* Pointers (void *) are challenging to encode.  They can't
30655 	 * be relied to be even 64-bit integer compatible (there are
30656 	 * pointer models larger than that), nor can floats encode
30657 	 * them.  They could be encoded as strings (%p format) but
30658 	 * that's not portable.  They could be encoded as direct memory
30659 	 * representations.  Recovering pointers is non-portable in any
30660 	 * case but it would be nice to be able to detect and recover
30661 	 * compatible pointers.
30662 	 *
30663 	 * For now, encode as "(%p)" string, matching JX.  There doesn't
30664 	 * seem to be an appropriate tag, so pointers don't currently
30665 	 * survive a CBOR encode/decode roundtrip intact.
30666 	 */
30667 	const char *ptr;
30668 
30669 	ptr = duk_to_string(enc_ctx->thr, -1);
30670 	DUK_ASSERT(ptr != NULL);
30671 	duk_push_sprintf(enc_ctx->thr, "(%s)", ptr);
30672 	duk_remove(enc_ctx->thr, -2);
30673 	duk__cbor_encode_string_top(enc_ctx);
30674 }
30675 
duk__cbor_encode_lightfunc(duk_cbor_encode_context * enc_ctx)30676 DUK_LOCAL void duk__cbor_encode_lightfunc(duk_cbor_encode_context *enc_ctx) {
30677 	duk_uint8_t *p;
30678 
30679 	/* Caller must ensure space. */
30680 	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);
30681 
30682 	/* For now encode as an empty object. */
30683 	p = enc_ctx->ptr;
30684 	*p++ = 0xa0U;
30685 	enc_ctx->ptr = p;
30686 }
30687 
duk__cbor_encode_value(duk_cbor_encode_context * enc_ctx)30688 DUK_LOCAL void duk__cbor_encode_value(duk_cbor_encode_context *enc_ctx) {
30689 	duk_uint8_t *p;
30690 
30691 	/* Encode/decode cycle currently loses some type information.
30692 	 * This can be improved by registering custom tags with IANA.
30693 	 */
30694 
30695 	/* Reserve space for up to 64-bit types (1 initial byte + 8
30696 	 * followup bytes).  This allows encoding of integers, floats,
30697 	 * string/buffer length fields, etc without separate checks
30698 	 * in each code path.
30699 	 */
30700 	duk__cbor_encode_ensure(enc_ctx, 1 + 8);
30701 
30702 	switch (duk_get_type(enc_ctx->thr, -1)) {
30703 	case DUK_TYPE_UNDEFINED: {
30704 		p = enc_ctx->ptr;
30705 		*p++ = 0xf7;
30706 		enc_ctx->ptr = p;
30707 		break;
30708 	}
30709 	case DUK_TYPE_NULL: {
30710 		p = enc_ctx->ptr;
30711 		*p++ = 0xf6;
30712 		enc_ctx->ptr = p;
30713 		break;
30714 	}
30715 	case DUK_TYPE_BOOLEAN: {
30716 		duk_uint8_t u8 = duk_get_boolean(enc_ctx->thr, -1) ? 0xf5U : 0xf4U;
30717 		p = enc_ctx->ptr;
30718 		*p++ = u8;
30719 		enc_ctx->ptr = p;
30720 		break;
30721 	}
30722 	case DUK_TYPE_NUMBER: {
30723 		duk__cbor_encode_double(enc_ctx, duk_get_number(enc_ctx->thr, -1));
30724 		break;
30725 	}
30726 	case DUK_TYPE_STRING: {
30727 		duk__cbor_encode_string_top(enc_ctx);
30728 		break;
30729 	}
30730 	case DUK_TYPE_OBJECT: {
30731 		duk__cbor_encode_object(enc_ctx);
30732 		break;
30733 	}
30734 	case DUK_TYPE_BUFFER: {
30735 		duk__cbor_encode_buffer(enc_ctx);
30736 		break;
30737 	}
30738 	case DUK_TYPE_POINTER: {
30739 		duk__cbor_encode_pointer(enc_ctx);
30740 		break;
30741 	}
30742 	case DUK_TYPE_LIGHTFUNC: {
30743 		duk__cbor_encode_lightfunc(enc_ctx);
30744 		break;
30745 	}
30746 	case DUK_TYPE_NONE:
30747 	default:
30748 		goto fail;
30749 	}
30750 
30751 	duk_pop(enc_ctx->thr);
30752 	return;
30753 
30754  fail:
30755 	duk__cbor_encode_error(enc_ctx);
30756 }
30757 
30758 /*
30759  *  Decoding
30760  */
30761 
duk__cbor_decode_error(duk_cbor_decode_context * dec_ctx)30762 DUK_LOCAL void duk__cbor_decode_error(duk_cbor_decode_context *dec_ctx) {
30763 	(void) duk_type_error(dec_ctx->thr, "cbor decode error");
30764 }
30765 
duk__cbor_decode_req_stack(duk_cbor_decode_context * dec_ctx)30766 DUK_LOCAL void duk__cbor_decode_req_stack(duk_cbor_decode_context *dec_ctx) {
30767 	duk_require_stack(dec_ctx->thr, 4);
30768 }
30769 
duk__cbor_decode_objarr_entry(duk_cbor_decode_context * dec_ctx)30770 DUK_LOCAL void duk__cbor_decode_objarr_entry(duk_cbor_decode_context *dec_ctx) {
30771 	duk_hthread *thr = dec_ctx->thr;
30772 
30773 	/* Native stack check in object/array recursion. */
30774 	duk_native_stack_check(thr);
30775 
30776 	duk__cbor_decode_req_stack(dec_ctx);
30777 
30778 	DUK_ASSERT(dec_ctx->recursion_depth <= dec_ctx->recursion_limit);
30779 	if (dec_ctx->recursion_depth >= dec_ctx->recursion_limit) {
30780 		DUK_ERROR_RANGE(thr, DUK_STR_DEC_RECLIMIT);
30781 		DUK_WO_NORETURN(return;);
30782 	}
30783 	dec_ctx->recursion_depth++;
30784 }
30785 
duk__cbor_decode_objarr_exit(duk_cbor_decode_context * dec_ctx)30786 DUK_LOCAL void duk__cbor_decode_objarr_exit(duk_cbor_decode_context *dec_ctx) {
30787 	DUK_ASSERT(dec_ctx->recursion_depth > 0);
30788 	dec_ctx->recursion_depth--;
30789 }
30790 
duk__cbor_decode_readbyte(duk_cbor_decode_context * dec_ctx)30791 DUK_LOCAL duk_uint8_t duk__cbor_decode_readbyte(duk_cbor_decode_context *dec_ctx) {
30792 	DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
30793 	if (DUK_UNLIKELY(dec_ctx->len - dec_ctx->off < 1U)) {
30794 		duk__cbor_decode_error(dec_ctx);
30795 	}
30796 	return dec_ctx->buf[dec_ctx->off++];
30797 }
30798 
duk__cbor_decode_read_u16(duk_cbor_decode_context * dec_ctx)30799 DUK_LOCAL duk_uint16_t duk__cbor_decode_read_u16(duk_cbor_decode_context *dec_ctx) {
30800 	duk_uint16_t res;
30801 
30802 	DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
30803 	if (DUK_UNLIKELY(dec_ctx->len - dec_ctx->off < 2U)) {
30804 		duk__cbor_decode_error(dec_ctx);
30805 	}
30806 	res = DUK_RAW_READ_U16_BE(dec_ctx->buf + dec_ctx->off);
30807 	dec_ctx->off += 2;
30808 	return res;
30809 }
30810 
duk__cbor_decode_read_u32(duk_cbor_decode_context * dec_ctx)30811 DUK_LOCAL duk_uint32_t duk__cbor_decode_read_u32(duk_cbor_decode_context *dec_ctx) {
30812 	duk_uint32_t res;
30813 
30814 	DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
30815 	if (DUK_UNLIKELY(dec_ctx->len - dec_ctx->off < 4U)) {
30816 		duk__cbor_decode_error(dec_ctx);
30817 	}
30818 	res = DUK_RAW_READ_U32_BE(dec_ctx->buf + dec_ctx->off);
30819 	dec_ctx->off += 4;
30820 	return res;
30821 }
30822 
duk__cbor_decode_peekbyte(duk_cbor_decode_context * dec_ctx)30823 DUK_LOCAL duk_uint8_t duk__cbor_decode_peekbyte(duk_cbor_decode_context *dec_ctx) {
30824 	if (DUK_UNLIKELY(dec_ctx->off >= dec_ctx->len)) {
30825 		duk__cbor_decode_error(dec_ctx);
30826 	}
30827 	return dec_ctx->buf[dec_ctx->off];
30828 }
30829 
duk__cbor_decode_rewind(duk_cbor_decode_context * dec_ctx,duk_size_t len)30830 DUK_LOCAL void duk__cbor_decode_rewind(duk_cbor_decode_context *dec_ctx, duk_size_t len) {
30831 	DUK_ASSERT(len <= dec_ctx->off);  /* Caller must ensure. */
30832 	dec_ctx->off -= len;
30833 }
30834 
30835 #if 0
30836 DUK_LOCAL void duk__cbor_decode_ensure(duk_cbor_decode_context *dec_ctx, duk_size_t len) {
30837 	if (dec_ctx->off + len > dec_ctx->len) {
30838 		duk__cbor_decode_error(dec_ctx);
30839 	}
30840 }
30841 #endif
30842 
duk__cbor_decode_consume(duk_cbor_decode_context * dec_ctx,duk_size_t len)30843 DUK_LOCAL const duk_uint8_t *duk__cbor_decode_consume(duk_cbor_decode_context *dec_ctx, duk_size_t len) {
30844 	DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
30845 	if (DUK_LIKELY(dec_ctx->len - dec_ctx->off >= len)) {
30846 		const duk_uint8_t *res = dec_ctx->buf + dec_ctx->off;
30847 		dec_ctx->off += len;
30848 		return res;
30849 	}
30850 
30851 	duk__cbor_decode_error(dec_ctx);  /* Not enough input. */
30852 	return NULL;
30853 }
30854 
duk__cbor_decode_checkbreak(duk_cbor_decode_context * dec_ctx)30855 DUK_LOCAL int duk__cbor_decode_checkbreak(duk_cbor_decode_context *dec_ctx) {
30856 	if (duk__cbor_decode_peekbyte(dec_ctx) == 0xffU) {
30857 		DUK_ASSERT(dec_ctx->off < dec_ctx->len);
30858 		dec_ctx->off++;
30859 #if 0
30860 		(void) duk__cbor_decode_readbyte(dec_ctx);
30861 #endif
30862 		return 1;
30863 	}
30864 	return 0;
30865 }
30866 
duk__cbor_decode_push_aival_int(duk_cbor_decode_context * dec_ctx,duk_uint8_t ib,duk_bool_t negative)30867 DUK_LOCAL void duk__cbor_decode_push_aival_int(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_bool_t negative) {
30868 	duk_uint8_t ai;
30869 	duk_uint32_t t, t1, t2;
30870 #if 0
30871 	duk_uint64_t t3;
30872 #endif
30873 	duk_double_t d1, d2;
30874 	duk_double_t d;
30875 
30876 	ai = ib & 0x1fU;
30877 	if (ai <= 0x17U) {
30878 		t = ai;
30879 		goto shared_exit;
30880 	}
30881 
30882 	switch (ai) {
30883 	case 0x18U:  /* 1 byte */
30884 		t = (duk_uint32_t) duk__cbor_decode_readbyte(dec_ctx);
30885 		goto shared_exit;
30886 	case 0x19U:  /* 2 byte */
30887 		t = (duk_uint32_t) duk__cbor_decode_read_u16(dec_ctx);
30888 		goto shared_exit;
30889 	case 0x1aU:  /* 4 byte */
30890 		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
30891 		goto shared_exit;
30892 	case 0x1bU:  /* 8 byte */
30893 		/* For uint64 it's important to handle the -1.0 part before
30894 		 * casting to double: otherwise the adjustment might be lost
30895 		 * in the cast.  Uses: -1.0 - d <=> -(d + 1.0).
30896 		 */
30897 		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
30898 		t2 = t;
30899 		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
30900 		t1 = t;
30901 #if 0
30902 		t3 = (duk_uint64_t) t2 * DUK_U64_CONSTANT(0x100000000) + (duk_uint64_t) t1;
30903 		if (negative) {
30904 			if (t3 == DUK_UINT64_MAX) {
30905 				/* -(0xffff'ffff'ffff'ffffULL + 1) =
30906 				 * -0x1'0000'0000'0000'0000
30907 				 *
30908 				 * >>> -0x10000000000000000
30909 				 * -18446744073709551616L
30910 				 */
30911 				return -18446744073709551616.0;
30912 			} else {
30913 				return -((duk_double_t) (t3 + DUK_U64_CONSTANT(1)));
30914 			}
30915 		} else {
30916 			return (duk_double_t) t3;  /* XXX: cast helper */
30917 		}
30918 #endif
30919 #if 0
30920 		t3 = (duk_uint64_t) t2 * DUK_U64_CONSTANT(0x100000000) + (duk_uint64_t) t1;
30921 		if (negative) {
30922 			/* Simpler version: take advantage of the fact that
30923 			 * 0xffff'ffff'ffff'ffff and 0x1'0000'0000'0000'0000
30924 			 * both round to 0x1'0000'0000'0000'0000:
30925 			 * > (0xffffffffffffffff).toString(16)
30926 			 * '10000000000000000'
30927 			 * > (0x10000000000000000).toString(16)
30928 			 * '10000000000000000'
30929 			 *
30930 			 * For the DUK_UINT64_MAX case we just skip the +1
30931 			 * increment to avoid wrapping; the result still
30932 			 * comes out right for an IEEE double cast.
30933 			 */
30934 			if (t3 != DUK_UINT64_MAX) {
30935 				t3++;
30936 			}
30937 			return -((duk_double_t) t3);
30938 		} else {
30939 			return (duk_double_t) t3;  /* XXX: cast helper */
30940 		}
30941 #endif
30942 #if 1
30943 		/* Use two double parts, avoids dependency on 64-bit type.
30944 		 * Avoid precision loss carefully, especially when dealing
30945 		 * with the required +1 for negative values.
30946 		 *
30947 		 * No fastint check for this path at present.
30948 		 */
30949 		d1 = (duk_double_t) t1;  /* XXX: cast helpers */
30950 		d2 = (duk_double_t) t2 * 4294967296.0;
30951 		if (negative) {
30952 			d1 += 1.0;
30953 		}
30954 		d = d2 + d1;
30955 		if (negative) {
30956 			d = -d;
30957 		}
30958 #endif
30959 		/* XXX: a push and check for fastint API would be nice */
30960 		duk_push_number(dec_ctx->thr, d);
30961 		return;
30962 	}
30963 
30964 	duk__cbor_decode_error(dec_ctx);
30965 	return;
30966 
30967  shared_exit:
30968 	if (negative) {
30969 		/* XXX: a push and check for fastint API would be nice */
30970 		if ((duk_uint_t) t <= (duk_uint_t) -(DUK_INT_MIN + 1)) {
30971 			duk_push_int(dec_ctx->thr, -1 - ((duk_int_t) t));
30972 		} else {
30973 			duk_push_number(dec_ctx->thr, -1.0 - (duk_double_t) t);
30974 		}
30975 	} else {
30976 		duk_push_uint(dec_ctx->thr, (duk_uint_t) t);
30977 	}
30978 }
30979 
duk__cbor_decode_skip_aival_int(duk_cbor_decode_context * dec_ctx,duk_uint8_t ib)30980 DUK_LOCAL void duk__cbor_decode_skip_aival_int(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib) {
30981 	const duk_int8_t skips[32] = {
30982 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
30983 		0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 8, -1, -1, -1, -1
30984 	};
30985 	duk_uint8_t ai;
30986 	duk_int8_t skip;
30987 
30988 	ai = ib & 0x1fU;
30989 	skip = skips[ai];
30990 	if (DUK_UNLIKELY(skip < 0)) {
30991 		duk__cbor_decode_error(dec_ctx);
30992 	}
30993 	duk__cbor_decode_consume(dec_ctx, (duk_size_t) skip);
30994 	return;
30995 }
30996 
duk__cbor_decode_aival_uint32(duk_cbor_decode_context * dec_ctx,duk_uint8_t ib)30997 DUK_LOCAL duk_uint32_t duk__cbor_decode_aival_uint32(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib) {
30998 	duk_uint8_t ai;
30999 	duk_uint32_t t;
31000 
31001 	ai = ib & 0x1fU;
31002 	if (ai <= 0x17U) {
31003 		return (duk_uint32_t) ai;
31004 	}
31005 
31006 	switch (ai) {
31007 	case 0x18U:  /* 1 byte */
31008 		t = (duk_uint32_t) duk__cbor_decode_readbyte(dec_ctx);
31009 		return t;
31010 	case 0x19U:  /* 2 byte */
31011 		t = (duk_uint32_t) duk__cbor_decode_read_u16(dec_ctx);
31012 		return t;
31013 	case 0x1aU:  /* 4 byte */
31014 		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
31015 		return t;
31016 	case 0x1bU:  /* 8 byte */
31017 		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
31018 		if (t != 0U) {
31019 			break;
31020 		}
31021 		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
31022 		return t;
31023 	}
31024 
31025 	duk__cbor_decode_error(dec_ctx);
31026 	return 0U;
31027 }
31028 
duk__cbor_decode_buffer(duk_cbor_decode_context * dec_ctx,duk_uint8_t expected_base)31029 DUK_LOCAL void duk__cbor_decode_buffer(duk_cbor_decode_context *dec_ctx, duk_uint8_t expected_base) {
31030 	duk_uint32_t len;
31031 	duk_uint8_t *buf;
31032 	const duk_uint8_t *inp;
31033 	duk_uint8_t ib;
31034 
31035 	ib = duk__cbor_decode_readbyte(dec_ctx);
31036 	if ((ib & 0xe0U) != expected_base) {
31037 		duk__cbor_decode_error(dec_ctx);
31038 	}
31039 	/* Indefinite format is rejected by the following on purpose. */
31040 	len = duk__cbor_decode_aival_uint32(dec_ctx, ib);
31041 	inp = duk__cbor_decode_consume(dec_ctx, len);
31042 	/* XXX: duk_push_fixed_buffer_with_data() would be a nice API addition. */
31043 	buf = (duk_uint8_t *) duk_push_fixed_buffer(dec_ctx->thr, (duk_size_t) len);
31044 	duk_memcpy((void *) buf, (const void *) inp, (size_t) len);
31045 }
31046 
duk__cbor_decode_join_buffers(duk_cbor_decode_context * dec_ctx,duk_idx_t count)31047 DUK_LOCAL void duk__cbor_decode_join_buffers(duk_cbor_decode_context *dec_ctx, duk_idx_t count) {
31048 	duk_size_t total_size = 0;
31049 	duk_idx_t top = duk_get_top(dec_ctx->thr);
31050 	duk_idx_t base = top - count;  /* count is >= 1 */
31051 	duk_idx_t idx;
31052 	duk_uint8_t *p = NULL;
31053 
31054 	DUK_ASSERT(count >= 1);
31055 	DUK_ASSERT(top >= count);
31056 
31057 	for (;;) {
31058 		/* First round: compute total size.
31059 		 * Second round: copy into place.
31060 		 */
31061 		for (idx = base; idx < top; idx++) {
31062 			duk_uint8_t *buf_data;
31063 			duk_size_t buf_size;
31064 
31065 			buf_data = (duk_uint8_t *) duk_require_buffer(dec_ctx->thr, idx, &buf_size);
31066 			if (p != NULL) {
31067 				duk_memcpy_unsafe((void *) p, (const void *) buf_data, buf_size);
31068 				p += buf_size;
31069 			} else {
31070 				total_size += buf_size;
31071 				if (DUK_UNLIKELY(total_size < buf_size)) {  /* Wrap check. */
31072 					duk__cbor_decode_error(dec_ctx);
31073 				}
31074 			}
31075 		}
31076 
31077 		if (p != NULL) {
31078 			break;
31079 		} else {
31080 			p = (duk_uint8_t *) duk_push_fixed_buffer(dec_ctx->thr, total_size);
31081 			DUK_ASSERT(p != NULL);
31082 		}
31083 	}
31084 
31085 	duk_replace(dec_ctx->thr, base);
31086 	duk_pop_n(dec_ctx->thr, count - 1);
31087 }
31088 
duk__cbor_decode_and_join_strbuf(duk_cbor_decode_context * dec_ctx,duk_uint8_t expected_base)31089 DUK_LOCAL void duk__cbor_decode_and_join_strbuf(duk_cbor_decode_context *dec_ctx, duk_uint8_t expected_base) {
31090 	duk_idx_t count = 0;
31091 	for (;;) {
31092 		if (duk__cbor_decode_checkbreak(dec_ctx)) {
31093 			break;
31094 		}
31095 		duk_require_stack(dec_ctx->thr, 1);
31096 		duk__cbor_decode_buffer(dec_ctx, expected_base);
31097 		count++;
31098 		if (DUK_UNLIKELY(count <= 0)) {  /* Wrap check. */
31099 			duk__cbor_decode_error(dec_ctx);
31100 		}
31101 	}
31102 	if (count == 0) {
31103 		(void) duk_push_fixed_buffer(dec_ctx->thr, 0);
31104 	} else if (count > 1) {
31105 		duk__cbor_decode_join_buffers(dec_ctx, count);
31106 	}
31107 }
31108 
duk__cbor_decode_half_float(duk_cbor_decode_context * dec_ctx)31109 DUK_LOCAL duk_double_t duk__cbor_decode_half_float(duk_cbor_decode_context *dec_ctx) {
31110 	duk_double_union u;
31111 	const duk_uint8_t *inp;
31112 	duk_int_t expt;
31113 	duk_uint_t u16;
31114 	duk_uint_t tmp;
31115 	duk_double_t res;
31116 
31117 	inp = duk__cbor_decode_consume(dec_ctx, 2);
31118 	u16 = ((duk_uint_t) inp[0] << 8) + (duk_uint_t) inp[1];
31119 	expt = (duk_int_t) ((u16 >> 10) & 0x1fU) - 15;
31120 
31121 	/* Reconstruct IEEE double into little endian order first, then convert
31122 	 * to host order.
31123 	 */
31124 
31125 	duk_memzero((void *) &u, sizeof(u));
31126 
31127 	if (expt == -15) {
31128 		/* Zero or denormal; but note that half float
31129 		 * denormals become double normals.
31130 		 */
31131 		if ((u16 & 0x03ffU) == 0) {
31132 			u.uc[7] = inp[0] & 0x80U;
31133 		} else {
31134 			/* Create denormal by first creating a double that
31135 			 * contains the denormal bits and a leading implicit
31136 			 * 1-bit.  Then subtract away the implicit 1-bit.
31137 			 *
31138 			 *    0.mmmmmmmmmm * 2^-14
31139 			 *    1.mmmmmmmmmm 0.... * 2^-14
31140 			 *   -1.0000000000 0.... * 2^-14
31141 			 *
31142 			 * Double exponent: -14 + 1023 = 0x3f1
31143 			 */
31144 			u.uc[7] = 0x3fU;
31145 			u.uc[6] = 0x10U + (duk_uint8_t) ((u16 >> 6) & 0x0fU);
31146 			u.uc[5] = (duk_uint8_t) ((u16 << 2) & 0xffU);  /* Mask is really 0xfcU */
31147 
31148 			duk_dblunion_little_to_host(&u);
31149 			res = u.d - 0.00006103515625;  /* 2^(-14) */
31150 			if (u16 & 0x8000U) {
31151 				res = -res;
31152 			}
31153 			return res;
31154 		}
31155 	} else if (expt == 16) {
31156 		/* +/- Inf or NaN. */
31157 		if ((u16 & 0x03ffU) == 0) {
31158 			u.uc[7] = (inp[0] & 0x80U) + 0x7fU;
31159 			u.uc[6] = 0xf0U;
31160 		} else {
31161 			/* Create a 'quiet NaN' with highest
31162 			 * bit set (there are some platforms
31163 			 * where the NaN payload convention is
31164 			 * the opposite).  Keep sign.
31165 			 */
31166 			u.uc[7] = (inp[0] & 0x80U) + 0x7fU;
31167 			u.uc[6] = 0xf8U;
31168 		}
31169 	} else {
31170 		/* Normal. */
31171 		tmp = (inp[0] & 0x80U) ? 0x80000000UL : 0UL;
31172 		tmp += (duk_uint_t) (expt + 1023) << 20;
31173 		tmp += (duk_uint_t) (inp[0] & 0x03U) << 18;
31174 		tmp += (duk_uint_t) (inp[1] & 0xffU) << 10;
31175 		u.uc[7] = (tmp >> 24) & 0xffU;
31176 		u.uc[6] = (tmp >> 16) & 0xffU;
31177 		u.uc[5] = (tmp >> 8) & 0xffU;
31178 		u.uc[4] = (tmp >> 0) & 0xffU;
31179 	}
31180 
31181 	duk_dblunion_little_to_host(&u);
31182 	return u.d;
31183 }
31184 
duk__cbor_decode_string(duk_cbor_decode_context * dec_ctx,duk_uint8_t ib,duk_uint8_t ai)31185 DUK_LOCAL void duk__cbor_decode_string(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai) {
31186 	/* If the CBOR string data is not valid UTF-8 it is technically
31187 	 * invalid CBOR.  Possible behaviors at least:
31188 	 *
31189 	 *   1. Reject the input, i.e. throw TypeError.
31190 	 *
31191 	 *   2. Accept the input, but sanitize non-UTF-8 data into UTF-8
31192 	 *      using U+FFFD replacements.  Also it might make sense to
31193 	 *      decode non-BMP codepoints into surrogates for better
31194 	 *      ECMAScript compatibility.
31195 	 *
31196 	 *   3. Accept the input as a Duktape string (which are not always
31197 	 *      valid UTF-8), but reject any input that would create a
31198 	 *      Symbol representation.
31199 	 *
31200 	 * Current behavior is 3.
31201 	 */
31202 
31203 	if (ai == 0x1fU) {
31204 		duk_uint8_t *buf_data;
31205 		duk_size_t buf_size;
31206 
31207 		duk__cbor_decode_and_join_strbuf(dec_ctx, 0x60U);
31208 		buf_data = (duk_uint8_t *) duk_require_buffer(dec_ctx->thr, -1, &buf_size);
31209 		(void) duk_push_lstring(dec_ctx->thr, (const char *) buf_data, buf_size);
31210 		duk_remove(dec_ctx->thr, -2);
31211 	} else {
31212 		duk_uint32_t len;
31213 		const duk_uint8_t *inp;
31214 
31215 		len = duk__cbor_decode_aival_uint32(dec_ctx, ib);
31216 		inp = duk__cbor_decode_consume(dec_ctx, len);
31217 		(void) duk_push_lstring(dec_ctx->thr, (const char *) inp, (duk_size_t) len);
31218 	}
31219 	if (duk_is_symbol(dec_ctx->thr, -1)) {
31220 		/* Refuse to create Symbols when decoding. */
31221 		duk__cbor_decode_error(dec_ctx);
31222 	}
31223 
31224 	/* XXX: Here a Duktape API call to convert input -> utf-8 with
31225 	 * replacements would be nice.
31226 	 */
31227 }
31228 
duk__cbor_decode_array(duk_cbor_decode_context * dec_ctx,duk_uint8_t ib,duk_uint8_t ai)31229 DUK_LOCAL duk_bool_t duk__cbor_decode_array(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai) {
31230 	duk_uint32_t idx, len;
31231 
31232 	duk__cbor_decode_objarr_entry(dec_ctx);
31233 
31234 	/* Support arrays up to 0xfffffffeU in length.  0xffffffff is
31235 	 * used as an indefinite length marker.
31236 	 */
31237 	if (ai == 0x1fU) {
31238 		len = 0xffffffffUL;
31239 	} else {
31240 		len = duk__cbor_decode_aival_uint32(dec_ctx, ib);
31241 		if (len == 0xffffffffUL) {
31242 			goto failure;
31243 		}
31244 	}
31245 
31246 	/* XXX: use bare array? */
31247 	duk_push_array(dec_ctx->thr);
31248 	for (idx = 0U; ;) {
31249 		if (len == 0xffffffffUL && duk__cbor_decode_checkbreak(dec_ctx)) {
31250 			break;
31251 		}
31252 		if (idx == len) {
31253 			if (ai == 0x1fU) {
31254 				goto failure;
31255 			}
31256 			break;
31257 		}
31258 		duk__cbor_decode_value(dec_ctx);
31259 		duk_put_prop_index(dec_ctx->thr, -2, (duk_uarridx_t) idx);
31260 		idx++;
31261 		if (idx == 0U) {
31262 			goto failure;  /* wrapped */
31263 		}
31264 	}
31265 
31266 #if 0
31267  success:
31268 #endif
31269 	duk__cbor_decode_objarr_exit(dec_ctx);
31270 	return 1;
31271 
31272  failure:
31273 	/* No need to unwind recursion checks, caller will throw. */
31274 	return 0;
31275 }
31276 
duk__cbor_decode_map(duk_cbor_decode_context * dec_ctx,duk_uint8_t ib,duk_uint8_t ai)31277 DUK_LOCAL duk_bool_t duk__cbor_decode_map(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai) {
31278 	duk_uint32_t count;
31279 
31280 	duk__cbor_decode_objarr_entry(dec_ctx);
31281 
31282 	if (ai == 0x1fU) {
31283 		count = 0xffffffffUL;
31284 	} else {
31285 		count = duk__cbor_decode_aival_uint32(dec_ctx, ib);
31286 		if (count == 0xffffffffUL) {
31287 			goto failure;
31288 		}
31289 	}
31290 
31291 	/* XXX: use bare object? */
31292 	duk_push_object(dec_ctx->thr);
31293 	for (;;) {
31294 		if (count == 0xffffffffUL) {
31295 			if (duk__cbor_decode_checkbreak(dec_ctx)) {
31296 				break;
31297 			}
31298 		} else {
31299 			if (count == 0UL) {
31300 				break;
31301 			}
31302 			count--;
31303 		}
31304 
31305 		/* Non-string keys are coerced to strings,
31306 		 * possibly leading to overwriting previous
31307 		 * keys.  Last key of a certain coerced name
31308 		 * wins.  If key is an object, it will coerce
31309 		 * to '[object Object]' which is consistent
31310 		 * but potentially misleading.  One alternative
31311 		 * would be to skip non-string keys.
31312 		 */
31313 		duk__cbor_decode_value(dec_ctx);
31314 		duk__cbor_decode_value(dec_ctx);
31315 		duk_put_prop(dec_ctx->thr, -3);
31316 	}
31317 
31318 #if 0
31319  success:
31320 #endif
31321 	duk__cbor_decode_objarr_exit(dec_ctx);
31322 	return 1;
31323 
31324  failure:
31325 	/* No need to unwind recursion checks, caller will throw. */
31326 	return 0;
31327 }
31328 
duk__cbor_decode_float(duk_cbor_decode_context * dec_ctx)31329 DUK_LOCAL duk_double_t duk__cbor_decode_float(duk_cbor_decode_context *dec_ctx) {
31330 	duk_float_union u;
31331 	const duk_uint8_t *inp;
31332 	inp = duk__cbor_decode_consume(dec_ctx, 4);
31333 	duk_memcpy((void *) u.uc, (const void *) inp, 4);
31334 	duk_fltunion_big_to_host(&u);
31335 	return (duk_double_t) u.f;
31336 }
31337 
duk__cbor_decode_double(duk_cbor_decode_context * dec_ctx)31338 DUK_LOCAL duk_double_t duk__cbor_decode_double(duk_cbor_decode_context *dec_ctx) {
31339 	duk_double_union u;
31340 	const duk_uint8_t *inp;
31341 	inp = duk__cbor_decode_consume(dec_ctx, 8);
31342 	duk_memcpy((void *) u.uc, (const void *) inp, 8);
31343 	duk_dblunion_big_to_host(&u);
31344 	return u.d;
31345 }
31346 
31347 #if defined(DUK_CBOR_DECODE_FASTPATH)
31348 #define DUK__CBOR_AI  (ib & 0x1fU)
31349 
duk__cbor_decode_value(duk_cbor_decode_context * dec_ctx)31350 DUK_LOCAL void duk__cbor_decode_value(duk_cbor_decode_context *dec_ctx) {
31351 	duk_uint8_t ib;
31352 
31353 	/* Any paths potentially recursing back to duk__cbor_decode_value()
31354 	 * must perform a Duktape value stack growth check.  Avoid the check
31355 	 * here for simple paths like primitive values.
31356 	 */
31357 
31358  reread_initial_byte:
31359 	DUK_DDD(DUK_DDDPRINT("cbor decode off=%ld len=%ld", (long) dec_ctx->off, (long) dec_ctx->len));
31360 
31361 	ib = duk__cbor_decode_readbyte(dec_ctx);
31362 
31363 	/* Full initial byte switch, footprint cost over baseline is ~+1kB. */
31364 	/* XXX: Force full switch with no range check. */
31365 
31366 	switch (ib) {
31367 	case 0x00U: case 0x01U: case 0x02U: case 0x03U: case 0x04U: case 0x05U: case 0x06U: case 0x07U:
31368 	case 0x08U: case 0x09U: case 0x0aU: case 0x0bU: case 0x0cU: case 0x0dU: case 0x0eU: case 0x0fU:
31369 	case 0x10U: case 0x11U: case 0x12U: case 0x13U: case 0x14U: case 0x15U: case 0x16U: case 0x17U:
31370 		duk_push_uint(dec_ctx->thr, ib);
31371 		break;
31372 	case 0x18U: case 0x19U: case 0x1aU: case 0x1bU:
31373 		duk__cbor_decode_push_aival_int(dec_ctx, ib, 0 /*negative*/);
31374 		break;
31375 	case 0x1cU: case 0x1dU: case 0x1eU: case 0x1fU:
31376 		goto format_error;
31377 	case 0x20U: case 0x21U: case 0x22U: case 0x23U: case 0x24U: case 0x25U: case 0x26U: case 0x27U:
31378 	case 0x28U: case 0x29U: case 0x2aU: case 0x2bU: case 0x2cU: case 0x2dU: case 0x2eU: case 0x2fU:
31379 	case 0x30U: case 0x31U: case 0x32U: case 0x33U: case 0x34U: case 0x35U: case 0x36U: case 0x37U:
31380 		duk_push_int(dec_ctx->thr, -((duk_int_t) ((ib - 0x20U) + 1U)));
31381 		break;
31382 	case 0x38U: case 0x39U: case 0x3aU: case 0x3bU:
31383 		duk__cbor_decode_push_aival_int(dec_ctx, ib, 1 /*negative*/);
31384 		break;
31385 	case 0x3cU: case 0x3dU: case 0x3eU: case 0x3fU:
31386 		goto format_error;
31387 	case 0x40U: case 0x41U: case 0x42U: case 0x43U: case 0x44U: case 0x45U: case 0x46U: case 0x47U:
31388 	case 0x48U: case 0x49U: case 0x4aU: case 0x4bU: case 0x4cU: case 0x4dU: case 0x4eU: case 0x4fU:
31389 	case 0x50U: case 0x51U: case 0x52U: case 0x53U: case 0x54U: case 0x55U: case 0x56U: case 0x57U:
31390 		/* XXX: Avoid rewind, we know the length already. */
31391 		DUK_ASSERT(dec_ctx->off > 0U);
31392 		dec_ctx->off--;
31393 		duk__cbor_decode_buffer(dec_ctx, 0x40U);
31394 		break;
31395 	case 0x58U: case 0x59U: case 0x5aU: case 0x5bU:
31396 		/* XXX: Avoid rewind, decode length inline. */
31397 		DUK_ASSERT(dec_ctx->off > 0U);
31398 		dec_ctx->off--;
31399 		duk__cbor_decode_buffer(dec_ctx, 0x40U);
31400 		break;
31401 	case 0x5cU: case 0x5dU: case 0x5eU:
31402 		goto format_error;
31403 	case 0x5fU:
31404 		duk__cbor_decode_and_join_strbuf(dec_ctx, 0x40U);
31405 		break;
31406 	case 0x60U: case 0x61U: case 0x62U: case 0x63U: case 0x64U: case 0x65U: case 0x66U: case 0x67U:
31407 	case 0x68U: case 0x69U: case 0x6aU: case 0x6bU: case 0x6cU: case 0x6dU: case 0x6eU: case 0x6fU:
31408 	case 0x70U: case 0x71U: case 0x72U: case 0x73U: case 0x74U: case 0x75U: case 0x76U: case 0x77U:
31409 		/* XXX: Avoid double decode of length. */
31410 		duk__cbor_decode_string(dec_ctx, ib, DUK__CBOR_AI);
31411 		break;
31412 	case 0x78U: case 0x79U: case 0x7aU: case 0x7bU:
31413 		/* XXX: Avoid double decode of length. */
31414 		duk__cbor_decode_string(dec_ctx, ib, DUK__CBOR_AI);
31415 		break;
31416 	case 0x7cU: case 0x7dU: case 0x7eU:
31417 		goto format_error;
31418 	case 0x7fU:
31419 		duk__cbor_decode_string(dec_ctx, ib, DUK__CBOR_AI);
31420 		break;
31421 	case 0x80U: case 0x81U: case 0x82U: case 0x83U: case 0x84U: case 0x85U: case 0x86U: case 0x87U:
31422 	case 0x88U: case 0x89U: case 0x8aU: case 0x8bU: case 0x8cU: case 0x8dU: case 0x8eU: case 0x8fU:
31423 	case 0x90U: case 0x91U: case 0x92U: case 0x93U: case 0x94U: case 0x95U: case 0x96U: case 0x97U:
31424 		if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
31425 			goto format_error;
31426 		}
31427 		break;
31428 	case 0x98U: case 0x99U: case 0x9aU: case 0x9bU:
31429 		if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
31430 			goto format_error;
31431 		}
31432 		break;
31433 	case 0x9cU: case 0x9dU: case 0x9eU:
31434 		goto format_error;
31435 	case 0x9fU:
31436 		if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
31437 			goto format_error;
31438 		}
31439 		break;
31440 	case 0xa0U: case 0xa1U: case 0xa2U: case 0xa3U: case 0xa4U: case 0xa5U: case 0xa6U: case 0xa7U:
31441 	case 0xa8U: case 0xa9U: case 0xaaU: case 0xabU: case 0xacU: case 0xadU: case 0xaeU: case 0xafU:
31442 	case 0xb0U: case 0xb1U: case 0xb2U: case 0xb3U: case 0xb4U: case 0xb5U: case 0xb6U: case 0xb7U:
31443 		if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
31444 			goto format_error;
31445 		}
31446 		break;
31447 	case 0xb8U: case 0xb9U: case 0xbaU: case 0xbbU:
31448 		if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
31449 			goto format_error;
31450 		}
31451 		break;
31452 	case 0xbcU: case 0xbdU: case 0xbeU:
31453 		goto format_error;
31454 	case 0xbfU:
31455 		if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
31456 			goto format_error;
31457 		}
31458 		break;
31459 	case 0xc0U: case 0xc1U: case 0xc2U: case 0xc3U: case 0xc4U: case 0xc5U: case 0xc6U: case 0xc7U:
31460 	case 0xc8U: case 0xc9U: case 0xcaU: case 0xcbU: case 0xccU: case 0xcdU: case 0xceU: case 0xcfU:
31461 	case 0xd0U: case 0xd1U: case 0xd2U: case 0xd3U: case 0xd4U: case 0xd5U: case 0xd6U: case 0xd7U:
31462 		/* Tag 0-23: drop. */
31463 		goto reread_initial_byte;
31464 	case 0xd8U: case 0xd9U: case 0xdaU: case 0xdbU:
31465 		duk__cbor_decode_skip_aival_int(dec_ctx, ib);
31466 		goto reread_initial_byte;
31467 	case 0xdcU: case 0xddU: case 0xdeU: case 0xdfU:
31468 		goto format_error;
31469 	case 0xe0U:
31470 		goto format_error;
31471 	case 0xe1U:
31472 		goto format_error;
31473 	case 0xe2U:
31474 		goto format_error;
31475 	case 0xe3U:
31476 		goto format_error;
31477 	case 0xe4U:
31478 		goto format_error;
31479 	case 0xe5U:
31480 		goto format_error;
31481 	case 0xe6U:
31482 		goto format_error;
31483 	case 0xe7U:
31484 		goto format_error;
31485 	case 0xe8U:
31486 		goto format_error;
31487 	case 0xe9U:
31488 		goto format_error;
31489 	case 0xeaU:
31490 		goto format_error;
31491 	case 0xebU:
31492 		goto format_error;
31493 	case 0xecU:
31494 		goto format_error;
31495 	case 0xedU:
31496 		goto format_error;
31497 	case 0xeeU:
31498 		goto format_error;
31499 	case 0xefU:
31500 		goto format_error;
31501 	case 0xf0U:
31502 		goto format_error;
31503 	case 0xf1U:
31504 		goto format_error;
31505 	case 0xf2U:
31506 		goto format_error;
31507 	case 0xf3U:
31508 		goto format_error;
31509 	case 0xf4U:
31510 		duk_push_false(dec_ctx->thr);
31511 		break;
31512 	case 0xf5U:
31513 		duk_push_true(dec_ctx->thr);
31514 		break;
31515 	case 0xf6U:
31516 		duk_push_null(dec_ctx->thr);
31517 		break;
31518 	case 0xf7U:
31519 		duk_push_undefined(dec_ctx->thr);
31520 		break;
31521 	case 0xf8U:
31522 		/* Simple value 32-255, nothing defined yet, so reject. */
31523 		goto format_error;
31524 	case 0xf9U: {
31525 		duk_double_t d;
31526 		d = duk__cbor_decode_half_float(dec_ctx);
31527 		duk_push_number(dec_ctx->thr, d);
31528 		break;
31529 	}
31530 	case 0xfaU: {
31531 		duk_double_t d;
31532 		d = duk__cbor_decode_float(dec_ctx);
31533 		duk_push_number(dec_ctx->thr, d);
31534 		break;
31535 	}
31536 	case 0xfbU: {
31537 		duk_double_t d;
31538 		d = duk__cbor_decode_double(dec_ctx);
31539 		duk_push_number(dec_ctx->thr, d);
31540 		break;
31541 	}
31542 	case 0xfcU:
31543 	case 0xfdU:
31544 	case 0xfeU:
31545 	case 0xffU:
31546 		goto format_error;
31547 	}  /* end switch */
31548 
31549 	return;
31550 
31551  format_error:
31552 	duk__cbor_decode_error(dec_ctx);
31553 }
31554 #else  /* DUK_CBOR_DECODE_FASTPATH */
duk__cbor_decode_value(duk_cbor_decode_context * dec_ctx)31555 DUK_LOCAL void duk__cbor_decode_value(duk_cbor_decode_context *dec_ctx) {
31556 	duk_uint8_t ib, mt, ai;
31557 
31558 	/* Any paths potentially recursing back to duk__cbor_decode_value()
31559 	 * must perform a Duktape value stack growth check.  Avoid the check
31560 	 * here for simple paths like primitive values.
31561 	 */
31562 
31563  reread_initial_byte:
31564 	DUK_DDD(DUK_DDDPRINT("cbor decode off=%ld len=%ld", (long) dec_ctx->off, (long) dec_ctx->len));
31565 
31566 	ib = duk__cbor_decode_readbyte(dec_ctx);
31567 	mt = ib >> 5U;
31568 	ai = ib & 0x1fU;
31569 
31570 	/* Additional information in [24,27] = [0x18,0x1b] has relatively
31571 	 * uniform handling for all major types: read 1/2/4/8 additional
31572 	 * bytes.  For major type 7 the 1-byte value is a 'simple type', and
31573 	 * 2/4/8-byte values are floats.  For other major types the 1/2/4/8
31574 	 * byte values are integers.  The lengths are uniform, but the typing
31575 	 * is not.
31576 	 */
31577 
31578 	switch (mt) {
31579 	case 0U: {  /* unsigned integer */
31580 		duk__cbor_decode_push_aival_int(dec_ctx, ib, 0 /*negative*/);
31581 		break;
31582 	}
31583 	case 1U: {  /* negative integer */
31584 		duk__cbor_decode_push_aival_int(dec_ctx, ib, 1 /*negative*/);
31585 		break;
31586 	}
31587 	case 2U: {  /* byte string */
31588 		if (ai == 0x1fU) {
31589 			duk__cbor_decode_and_join_strbuf(dec_ctx, 0x40U);
31590 		} else {
31591 			duk__cbor_decode_rewind(dec_ctx, 1U);
31592 			duk__cbor_decode_buffer(dec_ctx, 0x40U);
31593 		}
31594 		break;
31595 	}
31596 	case 3U: {  /* text string */
31597 		duk__cbor_decode_string(dec_ctx, ib, ai);
31598 		break;
31599 	}
31600 	case 4U: {  /* array of data items */
31601 		if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, ai) == 0)) {
31602 			goto format_error;
31603 		}
31604 		break;
31605 	}
31606 	case 5U: {  /* map of pairs of data items */
31607 		if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, ai) == 0)) {
31608 			goto format_error;
31609 		}
31610 		break;
31611 	}
31612 	case 6U: {  /* semantic tagging */
31613 		/* Tags are ignored now, re-read initial byte.  A tagged
31614 		 * value may itself be tagged (an unlimited number of times)
31615 		 * so keep on peeling away tags.
31616 		 */
31617 		duk__cbor_decode_skip_aival_int(dec_ctx, ib);
31618 		goto reread_initial_byte;
31619 	}
31620 	case 7U: {  /* floating point numbers, simple data types, break; other */
31621 		switch (ai) {
31622 		case 0x14U: {
31623 			duk_push_false(dec_ctx->thr);
31624 			break;
31625 		}
31626 		case 0x15U: {
31627 			duk_push_true(dec_ctx->thr);
31628 			break;
31629 		}
31630 		case 0x16U: {
31631 			duk_push_null(dec_ctx->thr);
31632 			break;
31633 		}
31634 		case 0x17U: {
31635 			duk_push_undefined(dec_ctx->thr);
31636 			break;
31637 		}
31638 		case 0x18U: {  /* more simple values (1 byte) */
31639 			/* Simple value encoded in additional byte (none
31640 			 * are defined so far).  RFC 7049 states that the
31641 			 * follow-up byte must be 32-255 to minimize
31642 			 * confusion.  So, a non-shortest encoding like
31643 			 * f815 (= true, shortest encoding f5) must be
31644 			 * rejected.  cbor.me tester rejects f815, but
31645 			 * e.g. Python CBOR binding decodes it as true.
31646 			 */
31647 			goto format_error;
31648 		}
31649 		case 0x19U: {  /* half-float (2 bytes) */
31650 			duk_double_t d;
31651 			d = duk__cbor_decode_half_float(dec_ctx);
31652 			duk_push_number(dec_ctx->thr, d);
31653 			break;
31654 		}
31655 		case 0x1aU: {  /* float (4 bytes) */
31656 			duk_double_t d;
31657 			d = duk__cbor_decode_float(dec_ctx);
31658 			duk_push_number(dec_ctx->thr, d);
31659 			break;
31660 		}
31661 		case 0x1bU: {  /* double (8 bytes) */
31662 			duk_double_t d;
31663 			d = duk__cbor_decode_double(dec_ctx);
31664 			duk_push_number(dec_ctx->thr, d);
31665 			break;
31666 		}
31667 		case 0xffU:  /* unexpected break */
31668 		default: {
31669 			goto format_error;
31670 		}
31671 		}  /* end switch */
31672 		break;
31673 	}
31674 	default: {
31675 		goto format_error;  /* will never actually occur */
31676 	}
31677 	}  /* end switch */
31678 
31679 	return;
31680 
31681  format_error:
31682 	duk__cbor_decode_error(dec_ctx);
31683 }
31684 #endif  /* DUK_CBOR_DECODE_FASTPATH */
31685 
duk__cbor_encode(duk_hthread * thr,duk_idx_t idx,duk_uint_t encode_flags)31686 DUK_LOCAL void duk__cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t encode_flags) {
31687 	duk_cbor_encode_context enc_ctx;
31688 	duk_uint8_t *buf;
31689 
31690 	DUK_UNREF(encode_flags);
31691 
31692 	idx = duk_require_normalize_index(thr, idx);
31693 
31694 	enc_ctx.thr = thr;
31695 	enc_ctx.idx_buf = duk_get_top(thr);
31696 
31697 	enc_ctx.len = 64;
31698 	buf = (duk_uint8_t *) duk_push_dynamic_buffer(thr, enc_ctx.len);
31699 	enc_ctx.ptr = buf;
31700 	enc_ctx.buf = buf;
31701 	enc_ctx.buf_end = buf + enc_ctx.len;
31702 
31703 	enc_ctx.recursion_depth = 0;
31704 	enc_ctx.recursion_limit = DUK_USE_CBOR_ENC_RECLIMIT;
31705 
31706 	duk_dup(thr, idx);
31707 	duk__cbor_encode_req_stack(&enc_ctx);
31708 	duk__cbor_encode_value(&enc_ctx);
31709 	DUK_ASSERT(enc_ctx.recursion_depth == 0);
31710 	duk_resize_buffer(enc_ctx.thr, enc_ctx.idx_buf, (duk_size_t) (enc_ctx.ptr - enc_ctx.buf));
31711 	duk_replace(thr, idx);
31712 }
31713 
duk__cbor_decode(duk_hthread * thr,duk_idx_t idx,duk_uint_t decode_flags)31714 DUK_LOCAL void duk__cbor_decode(duk_hthread *thr, duk_idx_t idx, duk_uint_t decode_flags) {
31715 	duk_cbor_decode_context dec_ctx;
31716 
31717 	DUK_UNREF(decode_flags);
31718 
31719 	/* Suppress compile warnings for functions only needed with e.g.
31720 	 * asserts enabled.
31721 	 */
31722 	DUK_UNREF(duk__cbor_get_reserve);
31723 
31724 	idx = duk_require_normalize_index(thr, idx);
31725 
31726 	dec_ctx.thr = thr;
31727 	dec_ctx.buf = (const duk_uint8_t *) duk_require_buffer_data(thr, idx, &dec_ctx.len);
31728 	dec_ctx.off = 0;
31729 	/* dec_ctx.len: set above */
31730 
31731 	dec_ctx.recursion_depth = 0;
31732 	dec_ctx.recursion_limit = DUK_USE_CBOR_DEC_RECLIMIT;
31733 
31734 	duk__cbor_decode_req_stack(&dec_ctx);
31735 	duk__cbor_decode_value(&dec_ctx);
31736 	DUK_ASSERT(dec_ctx.recursion_depth == 0);
31737 	if (dec_ctx.off != dec_ctx.len) {
31738 		(void) duk_type_error(thr, "trailing garbage");
31739 	}
31740 
31741 	duk_replace(thr, idx);
31742 }
31743 
31744 #else  /* DUK_USE_CBOR_SUPPORT */
31745 
duk__cbor_encode(duk_hthread * thr,duk_idx_t idx,duk_uint_t encode_flags)31746 DUK_LOCAL void duk__cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t encode_flags) {
31747 	DUK_UNREF(idx);
31748 	DUK_UNREF(encode_flags);
31749 	DUK_ERROR_UNSUPPORTED(thr);
31750 }
31751 
duk__cbor_decode(duk_hthread * thr,duk_idx_t idx,duk_uint_t decode_flags)31752 DUK_LOCAL void duk__cbor_decode(duk_hthread *thr, duk_idx_t idx, duk_uint_t decode_flags) {
31753 	DUK_UNREF(idx);
31754 	DUK_UNREF(decode_flags);
31755 	DUK_ERROR_UNSUPPORTED(thr);
31756 }
31757 
31758 #endif  /* DUK_USE_CBOR_SUPPORT */
31759 
31760 /*
31761  *  Public APIs
31762  */
31763 
duk_cbor_encode(duk_hthread * thr,duk_idx_t idx,duk_uint_t encode_flags)31764 DUK_EXTERNAL void duk_cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t encode_flags) {
31765 	DUK_ASSERT_API_ENTRY(thr);
31766 	duk__cbor_encode(thr, idx, encode_flags);
31767 }
duk_cbor_decode(duk_hthread * thr,duk_idx_t idx,duk_uint_t decode_flags)31768 DUK_EXTERNAL void duk_cbor_decode(duk_hthread *thr, duk_idx_t idx, duk_uint_t decode_flags) {
31769 	DUK_ASSERT_API_ENTRY(thr);
31770 	duk__cbor_decode(thr, idx, decode_flags);
31771 }
31772 
31773 #if defined(DUK_USE_CBOR_BUILTIN)
31774 #if defined(DUK_USE_CBOR_SUPPORT)
duk_bi_cbor_encode(duk_hthread * thr)31775 DUK_INTERNAL duk_ret_t duk_bi_cbor_encode(duk_hthread *thr) {
31776 	DUK_ASSERT_TOP(thr, 1);
31777 
31778 	duk__cbor_encode(thr, -1, 0 /*flags*/);
31779 
31780 	/* Produce an ArrayBuffer by first decoding into a plain buffer which
31781 	 * mimics a Uint8Array and gettings its .buffer property.
31782 	 */
31783 	/* XXX: shortcut */
31784 	(void) duk_get_prop_stridx(thr, -1, DUK_STRIDX_LC_BUFFER);
31785 	return 1;
31786 }
31787 
duk_bi_cbor_decode(duk_hthread * thr)31788 DUK_INTERNAL duk_ret_t duk_bi_cbor_decode(duk_hthread *thr) {
31789 	DUK_ASSERT_TOP(thr, 1);
31790 
31791 	duk__cbor_decode(thr, -1, 0 /*flags*/);
31792 	return 1;
31793 }
31794 #else  /* DUK_USE_CBOR_SUPPORT */
duk_bi_cbor_encode(duk_hthread * thr)31795 DUK_INTERNAL duk_ret_t duk_bi_cbor_encode(duk_hthread *thr) {
31796 	DUK_ERROR_UNSUPPORTED(thr);
31797 	DUK_WO_NORETURN(return 0;);
31798 }
duk_bi_cbor_decode(duk_hthread * thr)31799 DUK_INTERNAL duk_ret_t duk_bi_cbor_decode(duk_hthread *thr) {
31800 	DUK_ERROR_UNSUPPORTED(thr);
31801 	DUK_WO_NORETURN(return 0;);
31802 }
31803 #endif  /* DUK_USE_CBOR_SUPPORT */
31804 #endif  /* DUK_USE_CBOR_BUILTIN */
31805 
31806 /* automatic undefs */
31807 #undef DUK__CBOR_AI
31808 #line 1 "duk_bi_date.c"
31809 /*
31810  *  Date built-ins
31811  *
31812  *  Unlike most built-ins, Date has some platform dependencies for getting
31813  *  UTC time, converting between UTC and local time, and parsing and
31814  *  formatting time values.  These are all abstracted behind DUK_USE_xxx
31815  *  config options.  There are built-in platform specific providers for
31816  *  POSIX and Windows, but external providers can also be used.
31817  *
31818  *  See doc/datetime.rst.
31819  *
31820  */
31821 
31822 /* #include duk_internal.h -> already included */
31823 
31824 /* XXX: currently defines unnecessary symbols when DUK_USE_DATE_BUILTIN is disabled. */
31825 
31826 /*
31827  *  Forward declarations
31828  */
31829 
31830 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);
31831 DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval(duk_hthread *thr, duk_small_uint_t flags);
31832 DUK_LOCAL_DECL void duk__twodigit_year_fixup(duk_hthread *thr, duk_idx_t idx_val);
31833 DUK_LOCAL_DECL duk_ret_t duk__set_this_timeval_from_dparts(duk_hthread *thr, duk_double_t *dparts, duk_small_uint_t flags);
31834 
31835 /*
31836  *  Other file level defines
31837  */
31838 
31839 /* Debug macro to print all parts and dparts (used manually because of debug level). */
31840 #define  DUK__DPRINT_PARTS_AND_DPARTS(parts,dparts)  do { \
31841 		DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld, dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
31842 		                 (long) (parts)[0], (long) (parts)[1], \
31843 		                 (long) (parts)[2], (long) (parts)[3], \
31844 		                 (long) (parts)[4], (long) (parts)[5], \
31845 		                 (long) (parts)[6], (long) (parts)[7], \
31846 		                 (double) (dparts)[0], (double) (dparts)[1], \
31847 		                 (double) (dparts)[2], (double) (dparts)[3], \
31848 		                 (double) (dparts)[4], (double) (dparts)[5], \
31849 		                 (double) (dparts)[6], (double) (dparts)[7])); \
31850 	} while (0)
31851 #define  DUK__DPRINT_PARTS(parts)  do { \
31852 		DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld", \
31853 		                 (long) (parts)[0], (long) (parts)[1], \
31854 		                 (long) (parts)[2], (long) (parts)[3], \
31855 		                 (long) (parts)[4], (long) (parts)[5], \
31856 		                 (long) (parts)[6], (long) (parts)[7])); \
31857 	} while (0)
31858 #define  DUK__DPRINT_DPARTS(dparts)  do { \
31859 		DUK_D(DUK_DPRINT("dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
31860 		                 (double) (dparts)[0], (double) (dparts)[1], \
31861 		                 (double) (dparts)[2], (double) (dparts)[3], \
31862 		                 (double) (dparts)[4], (double) (dparts)[5], \
31863 		                 (double) (dparts)[6], (double) (dparts)[7])); \
31864 	} while (0)
31865 
31866 /* Equivalent year for DST calculations outside [1970,2038[ range, see
31867  * E5 Section 15.9.1.8.  Equivalent year has the same leap-year-ness and
31868  * starts with the same weekday on Jan 1.
31869  * https://bugzilla.mozilla.org/show_bug.cgi?id=351066
31870  */
31871 #define DUK__YEAR(x) ((duk_uint8_t) ((x) - 1970))
31872 DUK_LOCAL duk_uint8_t duk__date_equivyear[14] = {
31873 #if 1
31874 	/* This is based on V8 EquivalentYear() algorithm (see util/genequivyear.py):
31875 	 * http://code.google.com/p/v8/source/browse/trunk/src/date.h#146
31876 	 */
31877 
31878 	/* non-leap year: sunday, monday, ... */
31879 	DUK__YEAR(2023), DUK__YEAR(2035), DUK__YEAR(2019), DUK__YEAR(2031),
31880 	DUK__YEAR(2015), DUK__YEAR(2027), DUK__YEAR(2011),
31881 
31882 	/* leap year: sunday, monday, ... */
31883 	DUK__YEAR(2012), DUK__YEAR(2024), DUK__YEAR(2008), DUK__YEAR(2020),
31884 	DUK__YEAR(2032), DUK__YEAR(2016), DUK__YEAR(2028)
31885 #endif
31886 
31887 #if 0
31888 	/* This is based on Rhino EquivalentYear() algorithm:
31889 	 * https://github.com/mozilla/rhino/blob/f99cc11d616f0cdda2c42bde72b3484df6182947/src/org/mozilla/javascript/NativeDate.java
31890 	 */
31891 
31892 	/* non-leap year: sunday, monday, ... */
31893 	DUK__YEAR(1978), DUK__YEAR(1973), DUK__YEAR(1985), DUK__YEAR(1986),
31894 	DUK__YEAR(1981), DUK__YEAR(1971), DUK__YEAR(1977),
31895 
31896 	/* leap year: sunday, monday, ... */
31897 	DUK__YEAR(1984), DUK__YEAR(1996), DUK__YEAR(1980), DUK__YEAR(1992),
31898 	DUK__YEAR(1976), DUK__YEAR(1988), DUK__YEAR(1972)
31899 #endif
31900 };
31901 
31902 /*
31903  *  ISO 8601 subset parser.
31904  */
31905 
31906 /* Parser part count. */
31907 #define DUK__NUM_ISO8601_PARSER_PARTS  9
31908 
31909 /* Parser part indices. */
31910 #define DUK__PI_YEAR         0
31911 #define DUK__PI_MONTH        1
31912 #define DUK__PI_DAY          2
31913 #define DUK__PI_HOUR         3
31914 #define DUK__PI_MINUTE       4
31915 #define DUK__PI_SECOND       5
31916 #define DUK__PI_MILLISECOND  6
31917 #define DUK__PI_TZHOUR       7
31918 #define DUK__PI_TZMINUTE     8
31919 
31920 /* Parser part masks. */
31921 #define DUK__PM_YEAR         (1 << DUK__PI_YEAR)
31922 #define DUK__PM_MONTH        (1 << DUK__PI_MONTH)
31923 #define DUK__PM_DAY          (1 << DUK__PI_DAY)
31924 #define DUK__PM_HOUR         (1 << DUK__PI_HOUR)
31925 #define DUK__PM_MINUTE       (1 << DUK__PI_MINUTE)
31926 #define DUK__PM_SECOND       (1 << DUK__PI_SECOND)
31927 #define DUK__PM_MILLISECOND  (1 << DUK__PI_MILLISECOND)
31928 #define DUK__PM_TZHOUR       (1 << DUK__PI_TZHOUR)
31929 #define DUK__PM_TZMINUTE     (1 << DUK__PI_TZMINUTE)
31930 
31931 /* Parser separator indices. */
31932 #define DUK__SI_PLUS         0
31933 #define DUK__SI_MINUS        1
31934 #define DUK__SI_T            2
31935 #define DUK__SI_SPACE        3
31936 #define DUK__SI_COLON        4
31937 #define DUK__SI_PERIOD       5
31938 #define DUK__SI_Z            6
31939 #define DUK__SI_NUL          7
31940 
31941 /* Parser separator masks. */
31942 #define DUK__SM_PLUS         (1 << DUK__SI_PLUS)
31943 #define DUK__SM_MINUS        (1 << DUK__SI_MINUS)
31944 #define DUK__SM_T            (1 << DUK__SI_T)
31945 #define DUK__SM_SPACE        (1 << DUK__SI_SPACE)
31946 #define DUK__SM_COLON        (1 << DUK__SI_COLON)
31947 #define DUK__SM_PERIOD       (1 << DUK__SI_PERIOD)
31948 #define DUK__SM_Z            (1 << DUK__SI_Z)
31949 #define DUK__SM_NUL          (1 << DUK__SI_NUL)
31950 
31951 /* Rule control flags. */
31952 #define DUK__CF_NEG          (1 << 0)  /* continue matching, set neg_tzoffset flag */
31953 #define DUK__CF_ACCEPT       (1 << 1)  /* accept string */
31954 #define DUK__CF_ACCEPT_NUL   (1 << 2)  /* accept string if next char is NUL (otherwise reject) */
31955 
31956 #define DUK__PACK_RULE(partmask,sepmask,nextpart,flags)  \
31957 	((duk_uint32_t) (partmask) + \
31958 	 (((duk_uint32_t) (sepmask)) << 9) + \
31959 	 (((duk_uint32_t) (nextpart)) << 17) + \
31960 	 (((duk_uint32_t) (flags)) << 21))
31961 
31962 #define DUK__UNPACK_RULE(rule,var_nextidx,var_flags)  do { \
31963 		(var_nextidx) = (duk_small_uint_t) (((rule) >> 17) & 0x0f); \
31964 		(var_flags) = (duk_small_uint_t) ((rule) >> 21); \
31965 	} while (0)
31966 
31967 #define DUK__RULE_MASK_PART_SEP  0x1ffffUL
31968 
31969 /* Matching separator index is used in the control table */
31970 DUK_LOCAL const duk_uint8_t duk__parse_iso8601_seps[] = {
31971 	DUK_ASC_PLUS /*0*/, DUK_ASC_MINUS /*1*/, DUK_ASC_UC_T /*2*/, DUK_ASC_SPACE /*3*/,
31972 	DUK_ASC_COLON /*4*/, DUK_ASC_PERIOD /*5*/, DUK_ASC_UC_Z /*6*/, DUK_ASC_NUL /*7*/
31973 };
31974 
31975 /* Rule table: first matching rule is used to determine what to do next. */
31976 DUK_LOCAL const duk_uint32_t duk__parse_iso8601_control[] = {
31977 	DUK__PACK_RULE(DUK__PM_YEAR, DUK__SM_MINUS, DUK__PI_MONTH, 0),
31978 	DUK__PACK_RULE(DUK__PM_MONTH, DUK__SM_MINUS, DUK__PI_DAY, 0),
31979 	DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY, DUK__SM_T | DUK__SM_SPACE, DUK__PI_HOUR, 0),
31980 	DUK__PACK_RULE(DUK__PM_HOUR, DUK__SM_COLON, DUK__PI_MINUTE, 0),
31981 	DUK__PACK_RULE(DUK__PM_MINUTE, DUK__SM_COLON, DUK__PI_SECOND, 0),
31982 	DUK__PACK_RULE(DUK__PM_SECOND, DUK__SM_PERIOD, DUK__PI_MILLISECOND, 0),
31983 	DUK__PACK_RULE(DUK__PM_TZHOUR, DUK__SM_COLON, DUK__PI_TZMINUTE, 0),
31984 	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),
31985 	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),
31986 	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),
31987 	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)
31988 
31989 	/* Note1: the specification doesn't require matching a time form with
31990 	 *        just hours ("HH"), but we accept it here, e.g. "2012-01-02T12Z".
31991 	 *
31992 	 * Note2: the specification doesn't require matching a timezone offset
31993 	 *        with just hours ("HH"), but accept it here, e.g. "2012-01-02T03:04:05+02"
31994 	 */
31995 };
31996 
duk__parse_string_iso8601_subset(duk_hthread * thr,const char * str)31997 DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_hthread *thr, const char *str) {
31998 	duk_int_t parts[DUK__NUM_ISO8601_PARSER_PARTS];
31999 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
32000 	duk_double_t d;
32001 	const duk_uint8_t *p;
32002 	duk_small_uint_t part_idx = 0;
32003 	duk_int_t accum = 0;
32004 	duk_small_uint_t ndigits = 0;
32005 	duk_bool_t neg_year = 0;
32006 	duk_bool_t neg_tzoffset = 0;
32007 	duk_uint_fast8_t ch;
32008 	duk_small_uint_t i;
32009 
32010 	/* During parsing, month and day are one-based; set defaults here. */
32011 	duk_memzero(parts, sizeof(parts));
32012 	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] == 0);  /* don't care value, year is mandatory */
32013 	parts[DUK_DATE_IDX_MONTH] = 1;
32014 	parts[DUK_DATE_IDX_DAY] = 1;
32015 
32016 	/* Special handling for year sign. */
32017 	p = (const duk_uint8_t *) str;
32018 	ch = p[0];
32019 	if (ch == DUK_ASC_PLUS) {
32020 		p++;
32021 	} else if (ch == DUK_ASC_MINUS) {
32022 		neg_year = 1;
32023 		p++;
32024 	}
32025 
32026 	for (;;) {
32027 		ch = *p++;
32028 		DUK_DDD(DUK_DDDPRINT("parsing, part_idx=%ld, char=%ld ('%c')",
32029 		                     (long) part_idx, (long) ch,
32030 		                     (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : DUK_ASC_QUESTION)));
32031 
32032 		if (ch >= DUK_ASC_0 && ch <= DUK_ASC_9) {
32033 			if (ndigits >= 9) {
32034 				DUK_DDD(DUK_DDDPRINT("too many digits -> reject"));
32035 				goto reject;
32036 			}
32037 			if (part_idx == DUK__PI_MILLISECOND && ndigits >= 3) {
32038 				/* ignore millisecond fractions after 3 */
32039 			} else {
32040 				accum = accum * 10 + ((duk_int_t) ch) - ((duk_int_t) DUK_ASC_0) + 0x00;
32041 				ndigits++;
32042 			}
32043 		} else {
32044 			duk_uint_fast32_t match_val;
32045 			duk_small_uint_t sep_idx;
32046 
32047 			if (ndigits <= 0) {
32048 				goto reject;
32049 			}
32050 			if (part_idx == DUK__PI_MILLISECOND) {
32051 				/* complete the millisecond field */
32052 				while (ndigits < 3) {
32053 					accum *= 10;
32054 					ndigits++;
32055 				}
32056 			}
32057 			parts[part_idx] = accum;
32058 			DUK_DDD(DUK_DDDPRINT("wrote part %ld -> value %ld", (long) part_idx, (long) accum));
32059 
32060 			accum = 0;
32061 			ndigits = 0;
32062 
32063 			for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t)); i++) {
32064 				if (duk__parse_iso8601_seps[i] == ch) {
32065 					break;
32066 				}
32067 			}
32068 			if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t))) {
32069 				DUK_DDD(DUK_DDDPRINT("separator character doesn't match -> reject"));
32070 				goto reject;
32071 			}
32072 
32073 			sep_idx = i;
32074 			match_val = (1UL << part_idx) + (1UL << (sep_idx + 9));  /* match against rule part/sep bits */
32075 
32076 			for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t)); i++) {
32077 				duk_uint_fast32_t rule = duk__parse_iso8601_control[i];
32078 				duk_small_uint_t nextpart;
32079 				duk_small_uint_t cflags;
32080 
32081 				DUK_DDD(DUK_DDDPRINT("part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, considering rule=0x%08lx",
32082 				                     (long) part_idx, (long) sep_idx,
32083 				                     (unsigned long) match_val, (unsigned long) rule));
32084 
32085 				if ((rule & match_val) != match_val) {
32086 					continue;
32087 				}
32088 
32089 				DUK__UNPACK_RULE(rule, nextpart, cflags);
32090 
32091 				DUK_DDD(DUK_DDDPRINT("rule match -> part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, "
32092 				                     "rule=0x%08lx -> nextpart=%ld, cflags=0x%02lx",
32093 				                     (long) part_idx, (long) sep_idx,
32094 				                     (unsigned long) match_val, (unsigned long) rule,
32095 				                     (long) nextpart, (unsigned long) cflags));
32096 
32097 				if (cflags & DUK__CF_NEG) {
32098 					neg_tzoffset = 1;
32099 				}
32100 
32101 				if (cflags & DUK__CF_ACCEPT) {
32102 					goto accept;
32103 				}
32104 
32105 				if (cflags & DUK__CF_ACCEPT_NUL) {
32106 					DUK_ASSERT(*(p - 1) != (char) 0);
32107 					if (*p == DUK_ASC_NUL) {
32108 						goto accept;
32109 					}
32110 					goto reject;
32111 				}
32112 
32113 				part_idx = nextpart;
32114 				break;
32115 			}  /* rule match */
32116 
32117 			if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t))) {
32118 				DUK_DDD(DUK_DDDPRINT("no rule matches -> reject"));
32119 				goto reject;
32120 			}
32121 
32122 			if (ch == 0) {
32123 				/* This shouldn't be necessary, but check just in case
32124 				 * to avoid any chance of overruns.
32125 				 */
32126 				DUK_DDD(DUK_DDDPRINT("NUL after rule matching (should not happen) -> reject"));
32127 				goto reject;
32128 			}
32129 		}  /* if-digit-else-ctrl */
32130 	}  /* char loop */
32131 
32132 	/* We should never exit the loop above. */
32133 	DUK_UNREACHABLE();
32134 
32135  reject:
32136 	DUK_DDD(DUK_DDDPRINT("reject"));
32137 	return 0;
32138 
32139  accept:
32140 	DUK_DDD(DUK_DDDPRINT("accept"));
32141 
32142 	/* Apply timezone offset to get the main parts in UTC */
32143 	if (neg_year) {
32144 		parts[DUK__PI_YEAR] = -parts[DUK__PI_YEAR];
32145 	}
32146 	if (neg_tzoffset) {
32147 		parts[DUK__PI_HOUR] += parts[DUK__PI_TZHOUR];
32148 		parts[DUK__PI_MINUTE] += parts[DUK__PI_TZMINUTE];
32149 	} else {
32150 		parts[DUK__PI_HOUR] -= parts[DUK__PI_TZHOUR];
32151 		parts[DUK__PI_MINUTE] -= parts[DUK__PI_TZMINUTE];
32152 	}
32153 	parts[DUK__PI_MONTH] -= 1;  /* zero-based month */
32154 	parts[DUK__PI_DAY] -= 1;  /* zero-based day */
32155 
32156 	/* Use double parts, they tolerate unnormalized time.
32157 	 *
32158 	 * Note: DUK_DATE_IDX_WEEKDAY is initialized with a bogus value (DUK__PI_TZHOUR)
32159 	 * on purpose.  It won't be actually used by duk_bi_date_get_timeval_from_dparts(),
32160 	 * but will make the value initialized just in case, and avoid any
32161 	 * potential for Valgrind issues.
32162 	 */
32163 	for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
32164 		DUK_DDD(DUK_DDDPRINT("part[%ld] = %ld", (long) i, (long) parts[i]));
32165 		dparts[i] = parts[i];
32166 	}
32167 
32168 	d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
32169 	duk_push_number(thr, d);
32170 	return 1;
32171 }
32172 
32173 /*
32174  *  Date/time parsing helper.
32175  *
32176  *  Parse a datetime string into a time value.  We must first try to parse
32177  *  the input according to the standard format in E5.1 Section 15.9.1.15.
32178  *  If that fails, we can try to parse using custom parsing, which can
32179  *  either be platform neutral (custom code) or platform specific (using
32180  *  existing platform API calls).
32181  *
32182  *  Note in particular that we must parse whatever toString(), toUTCString(),
32183  *  and toISOString() can produce; see E5.1 Section 15.9.4.2.
32184  *
32185  *  Returns 1 to allow tail calling.
32186  *
32187  *  There is much room for improvement here with respect to supporting
32188  *  alternative datetime formats.  For instance, V8 parses '2012-01-01' as
32189  *  UTC and '2012/01/01' as local time.
32190  */
32191 
duk__parse_string(duk_hthread * thr,const char * str)32192 DUK_LOCAL duk_ret_t duk__parse_string(duk_hthread *thr, const char *str) {
32193 	/* XXX: there is a small risk here: because the ISO 8601 parser is
32194 	 * very loose, it may end up parsing some datetime values which
32195 	 * would be better parsed with a platform specific parser.
32196 	 */
32197 
32198 	DUK_ASSERT(str != NULL);
32199 	DUK_DDD(DUK_DDDPRINT("parse datetime from string '%s'", (const char *) str));
32200 
32201 	if (duk__parse_string_iso8601_subset(thr, str) != 0) {
32202 		return 1;
32203 	}
32204 
32205 #if defined(DUK_USE_DATE_PARSE_STRING)
32206 	/* Contract, either:
32207 	 * - Push value on stack and return 1
32208 	 * - Don't push anything on stack and return 0
32209 	 */
32210 
32211 	if (DUK_USE_DATE_PARSE_STRING(thr, str) != 0) {
32212 		return 1;
32213 	}
32214 #else
32215 	/* No platform-specific parsing, this is not an error. */
32216 #endif
32217 
32218 	duk_push_nan(thr);
32219 	return 1;
32220 }
32221 
32222 /*
32223  *  Calendar helpers
32224  *
32225  *  Some helpers are used for getters and can operate on normalized values
32226  *  which can be represented with 32-bit signed integers.  Other helpers are
32227  *  needed by setters and operate on un-normalized double values, must watch
32228  *  out for non-finite numbers etc.
32229  */
32230 
32231 DUK_LOCAL duk_uint8_t duk__days_in_month[12] = {
32232 	(duk_uint8_t) 31, (duk_uint8_t) 28, (duk_uint8_t) 31, (duk_uint8_t) 30,
32233 	(duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 31,
32234 	(duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31
32235 };
32236 
32237 /* Maximum iteration count for computing UTC-to-local time offset when
32238  * creating an ECMAScript time value from local parts.
32239  */
32240 #define DUK__LOCAL_TZOFFSET_MAXITER   4
32241 
32242 /* Because 'day since epoch' can be negative and is used to compute weekday
32243  * using a modulo operation, add this multiple of 7 to avoid negative values
32244  * when year is below 1970 epoch.  ECMAScript time values are restricted to
32245  * +/- 100 million days from epoch, so this adder fits nicely into 32 bits.
32246  * Round to a multiple of 7 (= floor(100000000 / 7) * 7) and add margin.
32247  */
32248 #define DUK__WEEKDAY_MOD_ADDER  (20000000 * 7)  /* 0x08583b00 */
32249 
duk_bi_date_is_leap_year(duk_int_t year)32250 DUK_INTERNAL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year) {
32251 	if ((year % 4) != 0) {
32252 		return 0;
32253 	}
32254 	if ((year % 100) != 0) {
32255 		return 1;
32256 	}
32257 	if ((year % 400) != 0) {
32258 		return 0;
32259 	}
32260 	return 1;
32261 }
32262 
duk_bi_date_timeval_in_valid_range(duk_double_t x)32263 DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x) {
32264 	return (x >= -DUK_DATE_MSEC_100M_DAYS && x <= DUK_DATE_MSEC_100M_DAYS);
32265 }
32266 
duk_bi_date_timeval_in_leeway_range(duk_double_t x)32267 DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x) {
32268 	return (x >= -DUK_DATE_MSEC_100M_DAYS_LEEWAY && x <= DUK_DATE_MSEC_100M_DAYS_LEEWAY);
32269 }
32270 
duk_bi_date_year_in_valid_range(duk_double_t x)32271 DUK_INTERNAL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t x) {
32272 	return (x >= DUK_DATE_MIN_ECMA_YEAR && x <= DUK_DATE_MAX_ECMA_YEAR);
32273 }
32274 
duk__timeclip(duk_double_t x)32275 DUK_LOCAL duk_double_t duk__timeclip(duk_double_t x) {
32276 	if (!DUK_ISFINITE(x)) {
32277 		return DUK_DOUBLE_NAN;
32278 	}
32279 
32280 	if (!duk_bi_date_timeval_in_valid_range(x)) {
32281 		return DUK_DOUBLE_NAN;
32282 	}
32283 
32284 	x = duk_js_tointeger_number(x);
32285 
32286 	/* Here we'd have the option to normalize -0 to +0. */
32287 	return x;
32288 }
32289 
32290 /* Integer division which floors also negative values correctly. */
duk__div_floor(duk_int_t a,duk_int_t b)32291 DUK_LOCAL duk_int_t duk__div_floor(duk_int_t a, duk_int_t b) {
32292 	DUK_ASSERT(b > 0);
32293 	if (a >= 0) {
32294 		return a / b;
32295 	} else {
32296 		/* e.g. a = -4, b = 5  -->  -4 - 5 + 1 / 5  -->  -8 / 5  -->  -1
32297 		 *      a = -5, b = 5  -->  -5 - 5 + 1 / 5  -->  -9 / 5  -->  -1
32298 		 *      a = -6, b = 5  -->  -6 - 5 + 1 / 5  -->  -10 / 5  -->  -2
32299 		 */
32300 		return (a - b + 1) / b;
32301 	}
32302 }
32303 
32304 /* Compute day number of the first day of a given year. */
duk__day_from_year(duk_int_t year)32305 DUK_LOCAL duk_int_t duk__day_from_year(duk_int_t year) {
32306 	/* Note: in integer arithmetic, (x / 4) is same as floor(x / 4) for non-negative
32307 	 * values, but is incorrect for negative ones.
32308 	 */
32309 	return 365 * (year - 1970)
32310 	       + duk__div_floor(year - 1969, 4)
32311 	       - duk__div_floor(year - 1901, 100)
32312 	       + duk__div_floor(year - 1601, 400);
32313 }
32314 
32315 /* 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)32316 DUK_LOCAL duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_within_year) {
32317 	duk_int_t year;
32318 	duk_int_t diff_days;
32319 
32320 	/* estimate year upwards (towards positive infinity), then back down;
32321 	 * two iterations should be enough
32322 	 */
32323 
32324 	if (day >= 0) {
32325 		year = 1970 + day / 365;
32326 	} else {
32327 		year = 1970 + day / 366;
32328 	}
32329 
32330 	for (;;) {
32331 		diff_days = duk__day_from_year(year) - day;
32332 		DUK_DDD(DUK_DDDPRINT("year=%ld day=%ld, diff_days=%ld", (long) year, (long) day, (long) diff_days));
32333 		if (diff_days <= 0) {
32334 			DUK_ASSERT(-diff_days < 366);  /* fits into duk_small_int_t */
32335 			*out_day_within_year = -diff_days;
32336 			DUK_DDD(DUK_DDDPRINT("--> year=%ld, day-within-year=%ld",
32337 			                     (long) year, (long) *out_day_within_year));
32338 			DUK_ASSERT(*out_day_within_year >= 0);
32339 			DUK_ASSERT(*out_day_within_year < (duk_bi_date_is_leap_year(year) ? 366 : 365));
32340 			return year;
32341 		}
32342 
32343 		/* Note: this is very tricky; we must never 'overshoot' the
32344 		 * correction downwards.
32345 		 */
32346 		year -= 1 + (diff_days - 1) / 366;  /* conservative */
32347 	}
32348 }
32349 
32350 /* Given a (year, month, day-within-month) triple, compute day number.
32351  * The input triple is un-normalized and may contain non-finite values.
32352  */
duk__make_day(duk_double_t year,duk_double_t month,duk_double_t day)32353 DUK_LOCAL duk_double_t duk__make_day(duk_double_t year, duk_double_t month, duk_double_t day) {
32354 	duk_int_t day_num;
32355 	duk_bool_t is_leap;
32356 	duk_small_int_t i, n;
32357 
32358 	/* Assume that year, month, day are all coerced to whole numbers.
32359 	 * They may also be NaN or infinity, in which case this function
32360 	 * must return NaN or infinity to ensure time value becomes NaN.
32361 	 * If 'day' is NaN, the final return will end up returning a NaN,
32362 	 * so it doesn't need to be checked here.
32363 	 */
32364 
32365 	if (!DUK_ISFINITE(year) || !DUK_ISFINITE(month)) {
32366 		return DUK_DOUBLE_NAN;
32367 	}
32368 
32369 	year += DUK_FLOOR(month / 12.0);
32370 
32371 	month = DUK_FMOD(month, 12.0);
32372 	if (month < 0.0) {
32373 		/* handle negative values */
32374 		month += 12.0;
32375 	}
32376 
32377 	/* The algorithm in E5.1 Section 15.9.1.12 normalizes month, but
32378 	 * does not normalize the day-of-month (nor check whether or not
32379 	 * it is finite) because it's not necessary for finding the day
32380 	 * number which matches the (year,month) pair.
32381 	 *
32382 	 * We assume that duk__day_from_year() is exact here.
32383 	 *
32384 	 * Without an explicit infinity / NaN check in the beginning,
32385 	 * day_num would be a bogus integer here.
32386 	 *
32387 	 * It's possible for 'year' to be out of integer range here.
32388 	 * If so, we need to return NaN without integer overflow.
32389 	 * This fixes test-bug-setyear-overflow.js.
32390 	 */
32391 
32392 	if (!duk_bi_date_year_in_valid_range(year)) {
32393 		DUK_DD(DUK_DDPRINT("year not in ecmascript valid range, avoid integer overflow: %lf", (double) year));
32394 		return DUK_DOUBLE_NAN;
32395 	}
32396 	day_num = duk__day_from_year((duk_int_t) year);
32397 	is_leap = duk_bi_date_is_leap_year((duk_int_t) year);
32398 
32399 	n = (duk_small_int_t) month;
32400 	for (i = 0; i < n; i++) {
32401 		day_num += duk__days_in_month[i];
32402 		if (i == 1 && is_leap) {
32403 			day_num++;
32404 		}
32405 	}
32406 
32407 	/* If 'day' is NaN, returns NaN. */
32408 	return (duk_double_t) day_num + day;
32409 }
32410 
32411 /* Split time value into parts.  The time value may contain fractions (it may
32412  * come from duk_time_to_components() API call) which are truncated.  Possible
32413  * local time adjustment has already been applied when reading the time value.
32414  */
duk_bi_date_timeval_to_parts(duk_double_t d,duk_int_t * parts,duk_double_t * dparts,duk_small_uint_t flags)32415 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) {
32416 	duk_double_t d1, d2;
32417 	duk_int_t t1, t2;
32418 	duk_int_t day_since_epoch;
32419 	duk_int_t year;  /* does not fit into 16 bits */
32420 	duk_small_int_t day_in_year;
32421 	duk_small_int_t month;
32422 	duk_small_int_t day;
32423 	duk_small_int_t dim;
32424 	duk_int_t jan1_since_epoch;
32425 	duk_small_int_t jan1_weekday;
32426 	duk_int_t equiv_year;
32427 	duk_small_uint_t i;
32428 	duk_bool_t is_leap;
32429 	duk_small_int_t arridx;
32430 
32431 	DUK_ASSERT(DUK_ISFINITE(d));    /* caller checks */
32432 	d = DUK_FLOOR(d);  /* remove fractions if present */
32433 	DUK_ASSERT(duk_double_equals(DUK_FLOOR(d), d));
32434 
32435 	/* The timevalue must be in valid ECMAScript range, but since a local
32436 	 * time offset can be applied, we need to allow a +/- 24h leeway to
32437 	 * the value.  In other words, although the UTC time is within the
32438 	 * ECMAScript range, the local part values can be just outside of it.
32439 	 */
32440 	DUK_UNREF(duk_bi_date_timeval_in_leeway_range);
32441 	DUK_ASSERT(duk_bi_date_timeval_in_leeway_range(d));
32442 
32443 	/* These computations are guaranteed to be exact for the valid
32444 	 * E5 time value range, assuming milliseconds without fractions.
32445 	 */
32446 	d1 = (duk_double_t) DUK_FMOD(d, (double) DUK_DATE_MSEC_DAY);
32447 	if (d1 < 0.0) {
32448 		/* deal with negative values */
32449 		d1 += (duk_double_t) DUK_DATE_MSEC_DAY;
32450 	}
32451 	d2 = DUK_FLOOR((double) (d / (duk_double_t) DUK_DATE_MSEC_DAY));
32452 	DUK_ASSERT(duk_double_equals(d2 * ((duk_double_t) DUK_DATE_MSEC_DAY) + d1, d));
32453 	/* now expected to fit into a 32-bit integer */
32454 	t1 = (duk_int_t) d1;
32455 	t2 = (duk_int_t) d2;
32456 	day_since_epoch = t2;
32457 	DUK_ASSERT(duk_double_equals((duk_double_t) t1, d1));
32458 	DUK_ASSERT(duk_double_equals((duk_double_t) t2, d2));
32459 
32460 	/* t1 = milliseconds within day (fits 32 bit)
32461 	 * t2 = day number from epoch (fits 32 bit, may be negative)
32462 	 */
32463 
32464 	parts[DUK_DATE_IDX_MILLISECOND] = t1 % 1000; t1 /= 1000;
32465 	parts[DUK_DATE_IDX_SECOND] = t1 % 60; t1 /= 60;
32466 	parts[DUK_DATE_IDX_MINUTE] = t1 % 60; t1 /= 60;
32467 	parts[DUK_DATE_IDX_HOUR] = t1;
32468 	DUK_ASSERT(parts[DUK_DATE_IDX_MILLISECOND] >= 0 && parts[DUK_DATE_IDX_MILLISECOND] <= 999);
32469 	DUK_ASSERT(parts[DUK_DATE_IDX_SECOND] >= 0 && parts[DUK_DATE_IDX_SECOND] <= 59);
32470 	DUK_ASSERT(parts[DUK_DATE_IDX_MINUTE] >= 0 && parts[DUK_DATE_IDX_MINUTE] <= 59);
32471 	DUK_ASSERT(parts[DUK_DATE_IDX_HOUR] >= 0 && parts[DUK_DATE_IDX_HOUR] <= 23);
32472 
32473 	DUK_DDD(DUK_DDDPRINT("d=%lf, d1=%lf, d2=%lf, t1=%ld, t2=%ld, parts: hour=%ld min=%ld sec=%ld msec=%ld",
32474 	                     (double) d, (double) d1, (double) d2, (long) t1, (long) t2,
32475 	                     (long) parts[DUK_DATE_IDX_HOUR],
32476 	                     (long) parts[DUK_DATE_IDX_MINUTE],
32477 	                     (long) parts[DUK_DATE_IDX_SECOND],
32478 	                     (long) parts[DUK_DATE_IDX_MILLISECOND]));
32479 
32480 	/* This assert depends on the input parts representing time inside
32481 	 * the ECMAScript range.
32482 	 */
32483 	DUK_ASSERT(t2 + DUK__WEEKDAY_MOD_ADDER >= 0);
32484 	parts[DUK_DATE_IDX_WEEKDAY] = (t2 + 4 + DUK__WEEKDAY_MOD_ADDER) % 7;  /* E5.1 Section 15.9.1.6 */
32485 	DUK_ASSERT(parts[DUK_DATE_IDX_WEEKDAY] >= 0 && parts[DUK_DATE_IDX_WEEKDAY] <= 6);
32486 
32487 	year = duk__year_from_day(t2, &day_in_year);
32488 	day = day_in_year;
32489 	is_leap = duk_bi_date_is_leap_year(year);
32490 	for (month = 0; month < 12; month++) {
32491 		dim = duk__days_in_month[month];
32492 		if (month == 1 && is_leap) {
32493 			dim++;
32494 		}
32495 		DUK_DDD(DUK_DDDPRINT("month=%ld, dim=%ld, day=%ld",
32496 		                     (long) month, (long) dim, (long) day));
32497 		if (day < dim) {
32498 			break;
32499 		}
32500 		day -= dim;
32501 	}
32502 	DUK_DDD(DUK_DDDPRINT("final month=%ld", (long) month));
32503 	DUK_ASSERT(month >= 0 && month <= 11);
32504 	DUK_ASSERT(day >= 0 && day <= 31);
32505 
32506 	/* Equivalent year mapping, used to avoid DST trouble when platform
32507 	 * may fail to provide reasonable DST answers for dates outside the
32508 	 * ordinary range (e.g. 1970-2038).  An equivalent year has the same
32509 	 * leap-year-ness as the original year and begins on the same weekday
32510 	 * (Jan 1).
32511 	 *
32512 	 * The year 2038 is avoided because there seem to be problems with it
32513 	 * on some platforms.  The year 1970 is also avoided as there were
32514 	 * practical problems with it; an equivalent year is used for it too,
32515 	 * which breaks some DST computations for 1970 right now, see e.g.
32516 	 * test-bi-date-tzoffset-brute-fi.js.
32517 	 */
32518 	if ((flags & DUK_DATE_FLAG_EQUIVYEAR) && (year < 1971 || year > 2037)) {
32519 		DUK_ASSERT(is_leap == 0 || is_leap == 1);
32520 
32521 		jan1_since_epoch = day_since_epoch - day_in_year;  /* day number for Jan 1 since epoch */
32522 		DUK_ASSERT(jan1_since_epoch + DUK__WEEKDAY_MOD_ADDER >= 0);
32523 		jan1_weekday = (jan1_since_epoch + 4 + DUK__WEEKDAY_MOD_ADDER) % 7;  /* E5.1 Section 15.9.1.6 */
32524 		DUK_ASSERT(jan1_weekday >= 0 && jan1_weekday <= 6);
32525 		arridx = jan1_weekday;
32526 		if (is_leap) {
32527 			arridx += 7;
32528 		}
32529 		DUK_ASSERT(arridx >= 0 && arridx < (duk_small_int_t) (sizeof(duk__date_equivyear) / sizeof(duk_uint8_t)));
32530 
32531 		equiv_year = (duk_int_t) duk__date_equivyear[arridx] + 1970;
32532 		year = equiv_year;
32533 		DUK_DDD(DUK_DDDPRINT("equiv year mapping, year=%ld, day_in_year=%ld, day_since_epoch=%ld, "
32534 		                     "jan1_since_epoch=%ld, jan1_weekday=%ld -> equiv year %ld",
32535 		                     (long) year, (long) day_in_year, (long) day_since_epoch,
32536 		                     (long) jan1_since_epoch, (long) jan1_weekday, (long) equiv_year));
32537 	}
32538 
32539 	parts[DUK_DATE_IDX_YEAR] = year;
32540 	parts[DUK_DATE_IDX_MONTH] = month;
32541 	parts[DUK_DATE_IDX_DAY] = day;
32542 
32543 	if (flags & DUK_DATE_FLAG_ONEBASED) {
32544 		parts[DUK_DATE_IDX_MONTH]++;  /* zero-based -> one-based */
32545 		parts[DUK_DATE_IDX_DAY]++;    /* -""- */
32546 	}
32547 
32548 	if (dparts != NULL) {
32549 		for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
32550 			dparts[i] = (duk_double_t) parts[i];
32551 		}
32552 	}
32553 }
32554 
32555 /* Compute time value from (double) parts.  The parts can be either UTC
32556  * or local time; if local, they need to be (conceptually) converted into
32557  * UTC time.  The parts may represent valid or invalid time, and may be
32558  * wildly out of range (but may cancel each other and still come out in
32559  * the valid Date range).
32560  */
duk_bi_date_get_timeval_from_dparts(duk_double_t * dparts,duk_small_uint_t flags)32561 DUK_INTERNAL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags) {
32562 #if defined(DUK_USE_PARANOID_DATE_COMPUTATION)
32563 	/* See comments below on MakeTime why these are volatile. */
32564 	volatile duk_double_t tmp_time;
32565 	volatile duk_double_t tmp_day;
32566 	volatile duk_double_t d;
32567 #else
32568 	duk_double_t tmp_time;
32569 	duk_double_t tmp_day;
32570 	duk_double_t d;
32571 #endif
32572 	duk_small_uint_t i;
32573 	duk_int_t tzoff, tzoffprev1, tzoffprev2;
32574 
32575 	/* Expects 'this' at top of stack on entry. */
32576 
32577 	/* Coerce all finite parts with ToInteger().  ToInteger() must not
32578 	 * be called for NaN/Infinity because it will convert e.g. NaN to
32579 	 * zero.  If ToInteger() has already been called, this has no side
32580 	 * effects and is idempotent.
32581 	 *
32582 	 * Don't read dparts[DUK_DATE_IDX_WEEKDAY]; it will cause Valgrind
32583 	 * issues if the value is uninitialized.
32584 	 */
32585 	for (i = 0; i <= DUK_DATE_IDX_MILLISECOND; i++) {
32586 		/* SCANBUILD: scan-build complains here about assigned value
32587 		 * being garbage or undefined.  This is correct but operating
32588 		 * on undefined values has no ill effect and is ignored by the
32589 		 * caller in the case where this happens.
32590 		 */
32591 		d = dparts[i];
32592 		if (DUK_ISFINITE(d)) {
32593 			dparts[i] = duk_js_tointeger_number(d);
32594 		}
32595 	}
32596 
32597 	/* Use explicit steps in computation to try to ensure that
32598 	 * computation happens with intermediate results coerced to
32599 	 * double values (instead of using something more accurate).
32600 	 * E.g. E5.1 Section 15.9.1.11 requires use of IEEE 754
32601 	 * rules (= ECMAScript '+' and '*' operators).
32602 	 *
32603 	 * Without 'volatile' even this approach fails on some platform
32604 	 * and compiler combinations.  For instance, gcc 4.8.1 on Ubuntu
32605 	 * 64-bit, with -m32 and without -std=c99, test-bi-date-canceling.js
32606 	 * would fail because of some optimizations when computing tmp_time
32607 	 * (MakeTime below).  Adding 'volatile' to tmp_time solved this
32608 	 * particular problem (annoyingly, also adding debug prints or
32609 	 * running the executable under valgrind hides it).
32610 	 */
32611 
32612 	/* MakeTime */
32613 	tmp_time = 0.0;
32614 	tmp_time += dparts[DUK_DATE_IDX_HOUR] * ((duk_double_t) DUK_DATE_MSEC_HOUR);
32615 	tmp_time += dparts[DUK_DATE_IDX_MINUTE] * ((duk_double_t) DUK_DATE_MSEC_MINUTE);
32616 	tmp_time += dparts[DUK_DATE_IDX_SECOND] * ((duk_double_t) DUK_DATE_MSEC_SECOND);
32617 	tmp_time += dparts[DUK_DATE_IDX_MILLISECOND];
32618 
32619 	/* MakeDay */
32620 	tmp_day = duk__make_day(dparts[DUK_DATE_IDX_YEAR], dparts[DUK_DATE_IDX_MONTH], dparts[DUK_DATE_IDX_DAY]);
32621 
32622 	/* MakeDate */
32623 	d = tmp_day * ((duk_double_t) DUK_DATE_MSEC_DAY) + tmp_time;
32624 
32625 	DUK_DDD(DUK_DDDPRINT("time=%lf day=%lf --> timeval=%lf",
32626 	                     (double) tmp_time, (double) tmp_day, (double) d));
32627 
32628 	/* Optional UTC conversion. */
32629 	if (flags & DUK_DATE_FLAG_LOCALTIME) {
32630 		/* DUK_USE_DATE_GET_LOCAL_TZOFFSET() needs to be called with a
32631 		 * time value computed from UTC parts.  At this point we only
32632 		 * have 'd' which is a time value computed from local parts, so
32633 		 * it is off by the UTC-to-local time offset which we don't know
32634 		 * yet.  The current solution for computing the UTC-to-local
32635 		 * time offset is to iterate a few times and detect a fixed
32636 		 * point or a two-cycle loop (or a sanity iteration limit),
32637 		 * see test-bi-date-local-parts.js and test-bi-date-tzoffset-basic-fi.js.
32638 		 *
32639 		 * E5.1 Section 15.9.1.9:
32640 		 * UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA)
32641 		 *
32642 		 * For NaN/inf, DUK_USE_DATE_GET_LOCAL_TZOFFSET() returns 0.
32643 		 */
32644 
32645 #if 0
32646 		/* Old solution: don't iterate, incorrect */
32647 		tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
32648 		DUK_DDD(DUK_DDDPRINT("tzoffset w/o iteration, tzoff=%ld", (long) tzoff));
32649 		d -= tzoff * 1000L;
32650 		DUK_UNREF(tzoffprev1);
32651 		DUK_UNREF(tzoffprev2);
32652 #endif
32653 
32654 		/* Iteration solution */
32655 		tzoff = 0;
32656 		tzoffprev1 = 999999999L;  /* invalid value which never matches */
32657 		for (i = 0; i < DUK__LOCAL_TZOFFSET_MAXITER; i++) {
32658 			tzoffprev2 = tzoffprev1;
32659 			tzoffprev1 = tzoff;
32660 			tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d - tzoff * 1000L);
32661 			DUK_DDD(DUK_DDDPRINT("tzoffset iteration, i=%d, tzoff=%ld, tzoffprev1=%ld tzoffprev2=%ld",
32662 			                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
32663 			if (tzoff == tzoffprev1) {
32664 				DUK_DDD(DUK_DDDPRINT("tzoffset iteration finished, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
32665 				                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
32666 				break;
32667 			} else if (tzoff == tzoffprev2) {
32668 				/* Two value cycle, see e.g. test-bi-date-tzoffset-basic-fi.js.
32669 				 * In these cases, favor a higher tzoffset to get a consistent
32670 				 * result which is independent of iteration count.  Not sure if
32671 				 * this is a generically correct solution.
32672 				 */
32673 				DUK_DDD(DUK_DDDPRINT("tzoffset iteration two-value cycle, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
32674 				                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
32675 				if (tzoffprev1 > tzoff) {
32676 					tzoff = tzoffprev1;
32677 				}
32678 				break;
32679 			}
32680 		}
32681 		DUK_DDD(DUK_DDDPRINT("tzoffset iteration, tzoff=%ld", (long) tzoff));
32682 		d -= tzoff * 1000L;
32683 	}
32684 
32685 	/* TimeClip(), which also handles Infinity -> NaN conversion */
32686 	d = duk__timeclip(d);
32687 
32688 	return d;
32689 }
32690 
32691 /*
32692  *  API oriented helpers
32693  */
32694 
32695 /* Push 'this' binding, check that it is a Date object; then push the
32696  * internal time value.  At the end, stack is: [ ... this timeval ].
32697  * Returns the time value.  Local time adjustment is done if requested.
32698  */
duk__push_this_get_timeval_tzoffset(duk_hthread * thr,duk_small_uint_t flags,duk_int_t * out_tzoffset)32699 DUK_LOCAL duk_double_t duk__push_this_get_timeval_tzoffset(duk_hthread *thr, duk_small_uint_t flags, duk_int_t *out_tzoffset) {
32700 	duk_hobject *h;
32701 	duk_double_t d;
32702 	duk_int_t tzoffset = 0;
32703 
32704 	duk_push_this(thr);
32705 	h = duk_get_hobject(thr, -1);  /* XXX: getter with class check, useful in built-ins */
32706 	if (h == NULL || DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_DATE) {
32707 		DUK_ERROR_TYPE(thr, "expected Date");
32708 		DUK_WO_NORETURN(return 0.0;);
32709 	}
32710 
32711 	duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
32712 	d = duk_to_number_m1(thr);
32713 	duk_pop(thr);
32714 
32715 	if (DUK_ISNAN(d)) {
32716 		if (flags & DUK_DATE_FLAG_NAN_TO_ZERO) {
32717 			d = 0.0;
32718 		}
32719 		if (flags & DUK_DATE_FLAG_NAN_TO_RANGE_ERROR) {
32720 			DUK_ERROR_RANGE(thr, "Invalid Date");
32721 			DUK_WO_NORETURN(return 0.0;);
32722 		}
32723 	}
32724 	/* if no NaN handling flag, may still be NaN here, but not Inf */
32725 	DUK_ASSERT(!DUK_ISINF(d));
32726 
32727 	if (flags & DUK_DATE_FLAG_LOCALTIME) {
32728 		/* Note: DST adjustment is determined using UTC time.
32729 		 * If 'd' is NaN, tzoffset will be 0.
32730 		 */
32731 		tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);  /* seconds */
32732 		d += tzoffset * 1000L;
32733 	}
32734 	if (out_tzoffset) {
32735 		*out_tzoffset = tzoffset;
32736 	}
32737 
32738 	/* [ ... this ] */
32739 	return d;
32740 }
32741 
duk__push_this_get_timeval(duk_hthread * thr,duk_small_uint_t flags)32742 DUK_LOCAL duk_double_t duk__push_this_get_timeval(duk_hthread *thr, duk_small_uint_t flags) {
32743 	return duk__push_this_get_timeval_tzoffset(thr, flags, NULL);
32744 }
32745 
32746 /* Set timeval to 'this' from dparts, push the new time value onto the
32747  * value stack and return 1 (caller can then tail call us).  Expects
32748  * the value stack to contain 'this' on the stack top.
32749  */
duk__set_this_timeval_from_dparts(duk_hthread * thr,duk_double_t * dparts,duk_small_uint_t flags)32750 DUK_LOCAL duk_ret_t duk__set_this_timeval_from_dparts(duk_hthread *thr, duk_double_t *dparts, duk_small_uint_t flags) {
32751 	duk_double_t d;
32752 
32753 	/* [ ... this ] */
32754 
32755 	d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
32756 	duk_push_number(thr, d);  /* -> [ ... this timeval_new ] */
32757 	duk_dup_top(thr);         /* -> [ ... this timeval_new timeval_new ] */
32758 
32759 	/* Must force write because e.g. .setYear() must work even when
32760 	 * the Date instance is frozen.
32761 	 */
32762 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
32763 
32764 	/* Stack top: new time value, return 1 to allow tail calls. */
32765 	return 1;
32766 }
32767 
32768 /* '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)32769 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) {
32770 	char yearstr[8];   /* "-123456\0" */
32771 	char tzstr[8];     /* "+11:22\0" */
32772 	char sep = (flags & DUK_DATE_FLAG_SEP_T) ? DUK_ASC_UC_T : DUK_ASC_SPACE;
32773 
32774 	DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
32775 	DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
32776 	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= -999999 && parts[DUK_DATE_IDX_YEAR] <= 999999);
32777 
32778 	/* Note: %06d for positive value, %07d for negative value to include
32779 	 * sign and 6 digits.
32780 	 */
32781 	DUK_SNPRINTF(yearstr,
32782 	             sizeof(yearstr),
32783 	             (parts[DUK_DATE_IDX_YEAR] >= 0 && parts[DUK_DATE_IDX_YEAR] <= 9999) ? "%04ld" :
32784 	                    ((parts[DUK_DATE_IDX_YEAR] >= 0) ? "+%06ld" : "%07ld"),
32785 	             (long) parts[DUK_DATE_IDX_YEAR]);
32786 	yearstr[sizeof(yearstr) - 1] = (char) 0;
32787 
32788 	if (flags & DUK_DATE_FLAG_LOCALTIME) {
32789 		/* tzoffset seconds are dropped; 16 bits suffice for
32790 		 * time offset in minutes
32791 		 */
32792 		const char *fmt;
32793 		duk_small_int_t tmp, arg_hours, arg_minutes;
32794 
32795 		if (tzoffset >= 0) {
32796 			tmp = tzoffset;
32797 			fmt = "+%02d:%02d";
32798 		} else {
32799 			tmp = -tzoffset;
32800 			fmt = "-%02d:%02d";
32801 		}
32802 		tmp = tmp / 60;
32803 		arg_hours = tmp / 60;
32804 		arg_minutes = tmp % 60;
32805 		DUK_ASSERT(arg_hours <= 24);  /* Even less is actually guaranteed for a valid tzoffset. */
32806 		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. */
32807 
32808 		DUK_SNPRINTF(tzstr, sizeof(tzstr), fmt, (int) arg_hours, (int) arg_minutes);
32809 		tzstr[sizeof(tzstr) - 1] = (char) 0;
32810 	} else {
32811 		tzstr[0] = DUK_ASC_UC_Z;
32812 		tzstr[1] = (char) 0;
32813 	}
32814 
32815 	/* Unlike year, the other parts fit into 16 bits so %d format
32816 	 * is portable.
32817 	 */
32818 	if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
32819 		DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d%c%02d:%02d:%02d.%03d%s",
32820 		            (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY], (int) sep,
32821 		            (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
32822 		            (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND], (const char *) tzstr);
32823 	} else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
32824 		DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d",
32825 		            (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY]);
32826 	} else {
32827 		DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);
32828 		DUK_SPRINTF((char *) out_buf, "%02d:%02d:%02d.%03d%s",
32829 		            (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
32830 		            (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND],
32831 		            (const char *) tzstr);
32832 	}
32833 }
32834 
32835 /* Helper for string conversion calls: check 'this' binding, get the
32836  * internal time value, and format date and/or time in a few formats.
32837  * Return value allows tail calls.
32838  */
duk__to_string_helper(duk_hthread * thr,duk_small_uint_t flags)32839 DUK_LOCAL duk_ret_t duk__to_string_helper(duk_hthread *thr, duk_small_uint_t flags) {
32840 	duk_double_t d;
32841 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
32842 	duk_int_t tzoffset;  /* seconds, doesn't fit into 16 bits */
32843 	duk_bool_t rc;
32844 	duk_uint8_t buf[DUK_BI_DATE_ISO8601_BUFSIZE];
32845 
32846 	DUK_UNREF(rc);  /* unreferenced with some options */
32847 
32848 	d = duk__push_this_get_timeval_tzoffset(thr, flags, &tzoffset);
32849 	if (DUK_ISNAN(d)) {
32850 		duk_push_hstring_stridx(thr, DUK_STRIDX_INVALID_DATE);
32851 		return 1;
32852 	}
32853 	DUK_ASSERT(DUK_ISFINITE(d));
32854 
32855 	/* formatters always get one-based month/day-of-month */
32856 	duk_bi_date_timeval_to_parts(d, parts, NULL, DUK_DATE_FLAG_ONEBASED);
32857 	DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
32858 	DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
32859 
32860 	if (flags & DUK_DATE_FLAG_TOSTRING_LOCALE) {
32861 		/* try locale specific formatter; if it refuses to format the
32862 		 * string, fall back to an ISO 8601 formatted value in local
32863 		 * time.
32864 		 */
32865 #if defined(DUK_USE_DATE_FORMAT_STRING)
32866 		/* Contract, either:
32867 		 * - Push string to value stack and return 1
32868 		 * - Don't push anything and return 0
32869 		 */
32870 
32871 		rc = DUK_USE_DATE_FORMAT_STRING(thr, parts, tzoffset, flags);
32872 		if (rc != 0) {
32873 			return 1;
32874 		}
32875 #else
32876 		/* No locale specific formatter; this is OK, we fall back
32877 		 * to ISO 8601.
32878 		 */
32879 #endif
32880 	}
32881 
32882 	/* Different calling convention than above used because the helper
32883 	 * is shared.
32884 	 */
32885 	duk__format_parts_iso8601(parts, tzoffset, flags, buf);
32886 	duk_push_string(thr, (const char *) buf);
32887 	return 1;
32888 }
32889 
32890 /* Helper for component getter calls: check 'this' binding, get the
32891  * internal time value, split it into parts (either as UTC time or
32892  * local time), push a specified component as a return value to the
32893  * value stack and return 1 (caller can then tail call us).
32894  */
duk__get_part_helper(duk_hthread * thr,duk_small_uint_t flags_and_idx)32895 DUK_LOCAL duk_ret_t duk__get_part_helper(duk_hthread *thr, duk_small_uint_t flags_and_idx) {
32896 	duk_double_t d;
32897 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
32898 	duk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> DUK_DATE_FLAG_VALUE_SHIFT);  /* unpack args */
32899 
32900 	DUK_ASSERT_DISABLE(idx_part >= 0);  /* unsigned */
32901 	DUK_ASSERT(idx_part < DUK_DATE_IDX_NUM_PARTS);
32902 
32903 	d = duk__push_this_get_timeval(thr, flags_and_idx);
32904 	if (DUK_ISNAN(d)) {
32905 		duk_push_nan(thr);
32906 		return 1;
32907 	}
32908 	DUK_ASSERT(DUK_ISFINITE(d));
32909 
32910 	duk_bi_date_timeval_to_parts(d, parts, NULL, flags_and_idx);  /* no need to mask idx portion */
32911 
32912 	/* Setter APIs detect special year numbers (0...99) and apply a +1900
32913 	 * only in certain cases.  The legacy getYear() getter applies -1900
32914 	 * unconditionally.
32915 	 */
32916 	duk_push_int(thr, (flags_and_idx & DUK_DATE_FLAG_SUB1900) ? parts[idx_part] - 1900 : parts[idx_part]);
32917 	return 1;
32918 }
32919 
32920 /* Helper for component setter calls: check 'this' binding, get the
32921  * internal time value, split it into parts (either as UTC time or
32922  * local time), modify one or more components as specified, recompute
32923  * the time value, set it as the internal value.  Finally, push the
32924  * new time value as a return value to the value stack and return 1
32925  * (caller can then tail call us).
32926  */
duk__set_part_helper(duk_hthread * thr,duk_small_uint_t flags_and_maxnargs)32927 DUK_LOCAL duk_ret_t duk__set_part_helper(duk_hthread *thr, duk_small_uint_t flags_and_maxnargs) {
32928 	duk_double_t d;
32929 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
32930 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
32931 	duk_idx_t nargs;
32932 	duk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> DUK_DATE_FLAG_VALUE_SHIFT);  /* unpack args */
32933 	duk_small_uint_t idx_first, idx;
32934 	duk_small_uint_t i;
32935 
32936 	nargs = duk_get_top(thr);
32937 	d = duk__push_this_get_timeval(thr, flags_and_maxnargs);
32938 	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
32939 
32940 	if (DUK_ISFINITE(d)) {
32941 		duk_bi_date_timeval_to_parts(d, parts, dparts, flags_and_maxnargs);
32942 	} else {
32943 		/* NaN timevalue: we need to coerce the arguments, but
32944 		 * the resulting internal timestamp needs to remain NaN.
32945 		 * This works but is not pretty: parts and dparts will
32946 		 * be partially uninitialized, but we only write to them.
32947 		 */
32948 	}
32949 
32950 	/*
32951 	 *  Determining which datetime components to overwrite based on
32952 	 *  stack arguments is a bit complicated, but important to factor
32953 	 *  out from setters themselves for compactness.
32954 	 *
32955 	 *  If DUK_DATE_FLAG_TIMESETTER, maxnargs indicates setter type:
32956 	 *
32957 	 *   1 -> millisecond
32958 	 *   2 -> second, [millisecond]
32959 	 *   3 -> minute, [second], [millisecond]
32960 	 *   4 -> hour, [minute], [second], [millisecond]
32961 	 *
32962 	 *  Else:
32963 	 *
32964 	 *   1 -> date
32965 	 *   2 -> month, [date]
32966 	 *   3 -> year, [month], [date]
32967 	 *
32968 	 *  By comparing nargs and maxnargs (and flags) we know which
32969 	 *  components to override.  We rely on part index ordering.
32970 	 */
32971 
32972 	if (flags_and_maxnargs & DUK_DATE_FLAG_TIMESETTER) {
32973 		DUK_ASSERT(maxnargs >= 1 && maxnargs <= 4);
32974 		idx_first = DUK_DATE_IDX_MILLISECOND - (maxnargs - 1);
32975 	} else {
32976 		DUK_ASSERT(maxnargs >= 1 && maxnargs <= 3);
32977 		idx_first = DUK_DATE_IDX_DAY - (maxnargs - 1);
32978 	}
32979 	DUK_ASSERT_DISABLE(idx_first >= 0);  /* unsigned */
32980 	DUK_ASSERT(idx_first < DUK_DATE_IDX_NUM_PARTS);
32981 
32982 	for (i = 0; i < maxnargs; i++) {
32983 		if ((duk_idx_t) i >= nargs) {
32984 			/* no argument given -> leave components untouched */
32985 			break;
32986 		}
32987 		idx = idx_first + i;
32988 		DUK_ASSERT_DISABLE(idx >= 0);  /* unsigned */
32989 		DUK_ASSERT(idx < DUK_DATE_IDX_NUM_PARTS);
32990 
32991 		if (idx == DUK_DATE_IDX_YEAR && (flags_and_maxnargs & DUK_DATE_FLAG_YEAR_FIXUP)) {
32992 			duk__twodigit_year_fixup(thr, (duk_idx_t) i);
32993 		}
32994 
32995 		dparts[idx] = duk_to_number(thr, (duk_idx_t) i);
32996 
32997 		if (idx == DUK_DATE_IDX_DAY) {
32998 			/* Day-of-month is one-based in the API, but zero-based
32999 			 * internally, so fix here.  Note that month is zero-based
33000 			 * both in the API and internally.
33001 			 */
33002 			/* SCANBUILD: complains about use of uninitialized values.
33003 			 * The complaint is correct, but operating in undefined
33004 			 * values here is intentional in some cases and the caller
33005 			 * ignores the results.
33006 			 */
33007 			dparts[idx] -= 1.0;
33008 		}
33009 	}
33010 
33011 	/* Leaves new timevalue on stack top and returns 1, which is correct
33012 	 * for part setters.
33013 	 */
33014 	if (DUK_ISFINITE(d)) {
33015 		return duk__set_this_timeval_from_dparts(thr, dparts, flags_and_maxnargs);
33016 	} else {
33017 		/* Internal timevalue is already NaN, so don't touch it. */
33018 		duk_push_nan(thr);
33019 		return 1;
33020 	}
33021 }
33022 
33023 /* Apply ToNumber() to specified index; if ToInteger(val) in [0,99], add
33024  * 1900 and replace value at idx_val.
33025  */
duk__twodigit_year_fixup(duk_hthread * thr,duk_idx_t idx_val)33026 DUK_LOCAL void duk__twodigit_year_fixup(duk_hthread *thr, duk_idx_t idx_val) {
33027 	duk_double_t d;
33028 
33029 	/* XXX: idx_val would fit into 16 bits, but using duk_small_uint_t
33030 	 * might not generate better code due to casting.
33031 	 */
33032 
33033 	/* E5 Sections 15.9.3.1, B.2.4, B.2.5 */
33034 	duk_to_number(thr, idx_val);
33035 	if (duk_is_nan(thr, idx_val)) {
33036 		return;
33037 	}
33038 	duk_dup(thr, idx_val);
33039 	duk_to_int(thr, -1);
33040 	d = duk_get_number(thr, -1);  /* get as double to handle huge numbers correctly */
33041 	if (d >= 0.0 && d <= 99.0) {
33042 		d += 1900.0;
33043 		duk_push_number(thr, d);
33044 		duk_replace(thr, idx_val);
33045 	}
33046 	duk_pop(thr);
33047 }
33048 
33049 /* Set datetime parts from stack arguments, defaulting any missing values.
33050  * Day-of-week is not set; it is not required when setting the time value.
33051  */
duk__set_parts_from_args(duk_hthread * thr,duk_double_t * dparts,duk_idx_t nargs)33052 DUK_LOCAL void duk__set_parts_from_args(duk_hthread *thr, duk_double_t *dparts, duk_idx_t nargs) {
33053 	duk_double_t d;
33054 	duk_small_uint_t i;
33055 	duk_small_uint_t idx;
33056 
33057 	/* Causes a ToNumber() coercion, but doesn't break coercion order since
33058 	 * year is coerced first anyway.
33059 	 */
33060 	duk__twodigit_year_fixup(thr, 0);
33061 
33062 	/* There are at most 7 args, but we use 8 here so that also
33063 	 * DUK_DATE_IDX_WEEKDAY gets initialized (to zero) to avoid the potential
33064 	 * for any Valgrind gripes later.
33065 	 */
33066 	for (i = 0; i < 8; i++) {
33067 		/* Note: rely on index ordering */
33068 		idx = DUK_DATE_IDX_YEAR + i;
33069 		if ((duk_idx_t) i < nargs) {
33070 			d = duk_to_number(thr, (duk_idx_t) i);
33071 			if (idx == DUK_DATE_IDX_DAY) {
33072 				/* Convert day from one-based to zero-based (internal).  This may
33073 				 * cause the day part to be negative, which is OK.
33074 				 */
33075 				d -= 1.0;
33076 			}
33077 		} else {
33078 			/* All components default to 0 except day-of-month which defaults
33079 			 * to 1.  However, because our internal day-of-month is zero-based,
33080 			 * it also defaults to zero here.
33081 			 */
33082 			d = 0.0;
33083 		}
33084 		dparts[idx] = d;
33085 	}
33086 
33087 	DUK_DDD(DUK_DDDPRINT("parts from args -> %lf %lf %lf %lf %lf %lf %lf %lf",
33088 	                     (double) dparts[0], (double) dparts[1],
33089 	                     (double) dparts[2], (double) dparts[3],
33090 	                     (double) dparts[4], (double) dparts[5],
33091 	                     (double) dparts[6], (double) dparts[7]));
33092 }
33093 
33094 /*
33095  *  Indirect magic value lookup for Date methods.
33096  *
33097  *  Date methods don't put their control flags into the function magic value
33098  *  because they wouldn't fit into a LIGHTFUNC's magic field.  Instead, the
33099  *  magic value is set to an index pointing to the array of control flags
33100  *  below.
33101  *
33102  *  This must be kept in strict sync with genbuiltins.py!
33103  */
33104 
33105 static duk_uint16_t duk__date_magics[] = {
33106 	/* 0: toString */
33107 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME,
33108 
33109 	/* 1: toDateString */
33110 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_LOCALTIME,
33111 
33112 	/* 2: toTimeString */
33113 	DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME,
33114 
33115 	/* 3: toLocaleString */
33116 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
33117 
33118 	/* 4: toLocaleDateString */
33119 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
33120 
33121 	/* 5: toLocaleTimeString */
33122 	DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
33123 
33124 	/* 6: toUTCString */
33125 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME,
33126 
33127 	/* 7: toISOString */
33128 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_NAN_TO_RANGE_ERROR + DUK_DATE_FLAG_SEP_T,
33129 
33130 	/* 8: getFullYear */
33131 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
33132 
33133 	/* 9: getUTCFullYear */
33134 	0 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
33135 
33136 	/* 10: getMonth */
33137 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT),
33138 
33139 	/* 11: getUTCMonth */
33140 	0 + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT),
33141 
33142 	/* 12: getDate */
33143 	DUK_DATE_FLAG_ONEBASED + DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT),
33144 
33145 	/* 13: getUTCDate */
33146 	DUK_DATE_FLAG_ONEBASED + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT),
33147 
33148 	/* 14: getDay */
33149 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT),
33150 
33151 	/* 15: getUTCDay */
33152 	0 + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT),
33153 
33154 	/* 16: getHours */
33155 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT),
33156 
33157 	/* 17: getUTCHours */
33158 	0 + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT),
33159 
33160 	/* 18: getMinutes */
33161 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT),
33162 
33163 	/* 19: getUTCMinutes */
33164 	0 + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT),
33165 
33166 	/* 20: getSeconds */
33167 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT),
33168 
33169 	/* 21: getUTCSeconds */
33170 	0 + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT),
33171 
33172 	/* 22: getMilliseconds */
33173 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT),
33174 
33175 	/* 23: getUTCMilliseconds */
33176 	0 + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT),
33177 
33178 	/* 24: setMilliseconds */
33179 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
33180 
33181 	/* 25: setUTCMilliseconds */
33182 	DUK_DATE_FLAG_TIMESETTER + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
33183 
33184 	/* 26: setSeconds */
33185 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
33186 
33187 	/* 27: setUTCSeconds */
33188 	DUK_DATE_FLAG_TIMESETTER + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
33189 
33190 	/* 28: setMinutes */
33191 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
33192 
33193 	/* 29: setUTCMinutes */
33194 	DUK_DATE_FLAG_TIMESETTER + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
33195 
33196 	/* 30: setHours */
33197 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (4 << DUK_DATE_FLAG_VALUE_SHIFT),
33198 
33199 	/* 31: setUTCHours */
33200 	DUK_DATE_FLAG_TIMESETTER + (4 << DUK_DATE_FLAG_VALUE_SHIFT),
33201 
33202 	/* 32: setDate */
33203 	DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
33204 
33205 	/* 33: setUTCDate */
33206 	0 + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
33207 
33208 	/* 34: setMonth */
33209 	DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
33210 
33211 	/* 35: setUTCMonth */
33212 	0 + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
33213 
33214 	/* 36: setFullYear */
33215 	DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
33216 
33217 	/* 37: setUTCFullYear */
33218 	DUK_DATE_FLAG_NAN_TO_ZERO + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
33219 
33220 	/* 38: getYear */
33221 	DUK_DATE_FLAG_LOCALTIME + DUK_DATE_FLAG_SUB1900 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
33222 
33223 	/* 39: setYear */
33224 	DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_YEAR_FIXUP + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
33225 };
33226 
duk__date_get_indirect_magic(duk_hthread * thr)33227 DUK_LOCAL duk_small_uint_t duk__date_get_indirect_magic(duk_hthread *thr) {
33228 	duk_small_uint_t magicidx = (duk_small_uint_t) duk_get_current_magic(thr);
33229 	DUK_ASSERT(magicidx < (duk_small_int_t) (sizeof(duk__date_magics) / sizeof(duk_uint16_t)));
33230 	return (duk_small_uint_t) duk__date_magics[magicidx];
33231 }
33232 
33233 #if defined(DUK_USE_DATE_BUILTIN)
33234 /*
33235  *  Constructor calls
33236  */
33237 
duk_bi_date_constructor(duk_hthread * thr)33238 DUK_INTERNAL duk_ret_t duk_bi_date_constructor(duk_hthread *thr) {
33239 	duk_idx_t nargs = duk_get_top(thr);
33240 	duk_bool_t is_cons = duk_is_constructor_call(thr);
33241 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
33242 	duk_double_t d;
33243 
33244 	DUK_DDD(DUK_DDDPRINT("Date constructor, nargs=%ld, is_cons=%ld", (long) nargs, (long) is_cons));
33245 
33246 	(void) duk_push_object_helper(thr,
33247 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
33248 	                              DUK_HOBJECT_FLAG_FASTREFS |
33249 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATE),
33250 	                              DUK_BIDX_DATE_PROTOTYPE);
33251 
33252 	/* Unlike most built-ins, the internal [[PrimitiveValue]] of a Date
33253 	 * is mutable.
33254 	 */
33255 
33256 	if (nargs == 0 || !is_cons) {
33257 		d = duk__timeclip(duk_time_get_ecmascript_time_nofrac(thr));
33258 		duk_push_number(thr, d);
33259 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
33260 		if (!is_cons) {
33261 			/* called as a normal function: return new Date().toString() */
33262 			duk_to_string(thr, -1);
33263 		}
33264 		return 1;
33265 	} else if (nargs == 1) {
33266 		const char *str;
33267 		duk_to_primitive(thr, 0, DUK_HINT_NONE);
33268 		str = duk_get_string_notsymbol(thr, 0);
33269 		if (str) {
33270 			duk__parse_string(thr, str);
33271 			duk_replace(thr, 0);  /* may be NaN */
33272 		}
33273 		d = duk__timeclip(duk_to_number(thr, 0));  /* symbols fail here */
33274 		duk_push_number(thr, d);
33275 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
33276 		return 1;
33277 	}
33278 
33279 	duk__set_parts_from_args(thr, dparts, nargs);
33280 
33281 	/* Parts are in local time, convert when setting. */
33282 
33283 	(void) duk__set_this_timeval_from_dparts(thr, dparts, DUK_DATE_FLAG_LOCALTIME /*flags*/);  /* -> [ ... this timeval ] */
33284 	duk_pop(thr);  /* -> [ ... this ] */
33285 	return 1;
33286 }
33287 
duk_bi_date_constructor_parse(duk_hthread * thr)33288 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_parse(duk_hthread *thr) {
33289 	return duk__parse_string(thr, duk_to_string(thr, 0));
33290 }
33291 
duk_bi_date_constructor_utc(duk_hthread * thr)33292 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_utc(duk_hthread *thr) {
33293 	duk_idx_t nargs = duk_get_top(thr);
33294 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
33295 	duk_double_t d;
33296 
33297 	/* Behavior for nargs < 2 is implementation dependent: currently we'll
33298 	 * set a NaN time value (matching V8 behavior) in this case.
33299 	 */
33300 
33301 	if (nargs < 2) {
33302 		duk_push_nan(thr);
33303 	} else {
33304 		duk__set_parts_from_args(thr, dparts, nargs);
33305 		d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
33306 		duk_push_number(thr, d);
33307 	}
33308 	return 1;
33309 }
33310 
duk_bi_date_constructor_now(duk_hthread * thr)33311 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_now(duk_hthread *thr) {
33312 	duk_double_t d;
33313 
33314 	d = duk_time_get_ecmascript_time_nofrac(thr);
33315 	DUK_ASSERT(duk_double_equals(duk__timeclip(d), d));  /* TimeClip() should never be necessary */
33316 	duk_push_number(thr, d);
33317 	return 1;
33318 }
33319 
33320 /*
33321  *  String/JSON conversions
33322  *
33323  *  Human readable conversions are now basically ISO 8601 with a space
33324  *  (instead of 'T') as the date/time separator.  This is a good baseline
33325  *  and is platform independent.
33326  *
33327  *  A shared native helper to provide many conversions.  Magic value contains
33328  *  a set of flags.  The helper provides:
33329  *
33330  *    toString()
33331  *    toDateString()
33332  *    toTimeString()
33333  *    toLocaleString()
33334  *    toLocaleDateString()
33335  *    toLocaleTimeString()
33336  *    toUTCString()
33337  *    toISOString()
33338  *
33339  *  Notes:
33340  *
33341  *    - Date.prototype.toGMTString() and Date.prototype.toUTCString() are
33342  *      required to be the same ECMAScript function object (!), so it is
33343  *      omitted from here.
33344  *
33345  *    - Date.prototype.toUTCString(): E5.1 specification does not require a
33346  *      specific format, but result should be human readable.  The
33347  *      specification suggests using ISO 8601 format with a space (instead
33348  *      of 'T') separator if a more human readable format is not available.
33349  *
33350  *    - Date.prototype.toISOString(): unlike other conversion functions,
33351  *      toISOString() requires a RangeError for invalid date values.
33352  */
33353 
duk_bi_date_prototype_tostring_shared(duk_hthread * thr)33354 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_hthread *thr) {
33355 	duk_small_uint_t flags = duk__date_get_indirect_magic(thr);
33356 	return duk__to_string_helper(thr, flags);
33357 }
33358 
duk_bi_date_prototype_value_of(duk_hthread * thr)33359 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_value_of(duk_hthread *thr) {
33360 	/* This native function is also used for Date.prototype.getTime()
33361 	 * as their behavior is identical.
33362 	 */
33363 
33364 	duk_double_t d = duk__push_this_get_timeval(thr, 0 /*flags*/);  /* -> [ this ] */
33365 	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
33366 	duk_push_number(thr, d);
33367 	return 1;
33368 }
33369 
duk_bi_date_prototype_to_json(duk_hthread * thr)33370 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_to_json(duk_hthread *thr) {
33371 	/* Note: toJSON() is a generic function which works even if 'this'
33372 	 * is not a Date.  The sole argument is ignored.
33373 	 */
33374 
33375 	duk_push_this(thr);
33376 	duk_to_object(thr, -1);
33377 
33378 	duk_dup_top(thr);
33379 	duk_to_primitive(thr, -1, DUK_HINT_NUMBER);
33380 	if (duk_is_number(thr, -1)) {
33381 		duk_double_t d = duk_get_number(thr, -1);
33382 		if (!DUK_ISFINITE(d)) {
33383 			duk_push_null(thr);
33384 			return 1;
33385 		}
33386 	}
33387 	duk_pop(thr);
33388 
33389 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_ISO_STRING);
33390 	duk_dup_m2(thr);  /* -> [ O toIsoString O ] */
33391 	duk_call_method(thr, 0);
33392 	return 1;
33393 }
33394 
33395 /*
33396  *  Getters.
33397  *
33398  *  Implementing getters is quite easy.  The internal time value is either
33399  *  NaN, or represents milliseconds (without fractions) from Jan 1, 1970.
33400  *  The internal time value can be converted to integer parts, and each
33401  *  part will be normalized and will fit into a 32-bit signed integer.
33402  *
33403  *  A shared native helper to provide all getters.  Magic value contains
33404  *  a set of flags and also packs the date component index argument.  The
33405  *  helper provides:
33406  *
33407  *    getFullYear()
33408  *    getUTCFullYear()
33409  *    getMonth()
33410  *    getUTCMonth()
33411  *    getDate()
33412  *    getUTCDate()
33413  *    getDay()
33414  *    getUTCDay()
33415  *    getHours()
33416  *    getUTCHours()
33417  *    getMinutes()
33418  *    getUTCMinutes()
33419  *    getSeconds()
33420  *    getUTCSeconds()
33421  *    getMilliseconds()
33422  *    getUTCMilliseconds()
33423  *    getYear()
33424  *
33425  *  Notes:
33426  *
33427  *    - Date.prototype.getDate(): 'date' means day-of-month, and is
33428  *      zero-based in internal calculations but public API expects it to
33429  *      be one-based.
33430  *
33431  *    - Date.prototype.getTime() and Date.prototype.valueOf() have identical
33432  *      behavior.  They have separate function objects, but share the same C
33433  *      function (duk_bi_date_prototype_value_of).
33434  */
33435 
duk_bi_date_prototype_get_shared(duk_hthread * thr)33436 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_shared(duk_hthread *thr) {
33437 	duk_small_uint_t flags_and_idx = duk__date_get_indirect_magic(thr);
33438 	return duk__get_part_helper(thr, flags_and_idx);
33439 }
33440 
duk_bi_date_prototype_get_timezone_offset(duk_hthread * thr)33441 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_hthread *thr) {
33442 	/*
33443 	 *  Return (t - LocalTime(t)) in minutes:
33444 	 *
33445 	 *    t - LocalTime(t) = t - (t + LocalTZA + DaylightSavingTA(t))
33446 	 *                     = -(LocalTZA + DaylightSavingTA(t))
33447 	 *
33448 	 *  where DaylightSavingTA() is checked for time 't'.
33449 	 *
33450 	 *  Note that the sign of the result is opposite to common usage,
33451 	 *  e.g. for EE(S)T which normally is +2h or +3h from UTC, this
33452 	 *  function returns -120 or -180.
33453 	 *
33454 	 */
33455 
33456 	duk_double_t d;
33457 	duk_int_t tzoffset;
33458 
33459 	/* Note: DST adjustment is determined using UTC time. */
33460 	d = duk__push_this_get_timeval(thr, 0 /*flags*/);
33461 	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
33462 	if (DUK_ISNAN(d)) {
33463 		duk_push_nan(thr);
33464 	} else {
33465 		DUK_ASSERT(DUK_ISFINITE(d));
33466 		tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
33467 		duk_push_int(thr, -tzoffset / 60);
33468 	}
33469 	return 1;
33470 }
33471 
33472 /*
33473  *  Setters.
33474  *
33475  *  Setters are a bit more complicated than getters.  Component setters
33476  *  break down the current time value into its (normalized) component
33477  *  parts, replace one or more components with -unnormalized- new values,
33478  *  and the components are then converted back into a time value.  As an
33479  *  example of using unnormalized values:
33480  *
33481  *    var d = new Date(1234567890);
33482  *
33483  *  is equivalent to:
33484  *
33485  *    var d = new Date(0);
33486  *    d.setUTCMilliseconds(1234567890);
33487  *
33488  *  A shared native helper to provide almost all setters.  Magic value
33489  *  contains a set of flags and also packs the "maxnargs" argument.  The
33490  *  helper provides:
33491  *
33492  *    setMilliseconds()
33493  *    setUTCMilliseconds()
33494  *    setSeconds()
33495  *    setUTCSeconds()
33496  *    setMinutes()
33497  *    setUTCMinutes()
33498  *    setHours()
33499  *    setUTCHours()
33500  *    setDate()
33501  *    setUTCDate()
33502  *    setMonth()
33503  *    setUTCMonth()
33504  *    setFullYear()
33505  *    setUTCFullYear()
33506  *    setYear()
33507  *
33508  *  Notes:
33509  *
33510  *    - Date.prototype.setYear() (Section B addition): special year check
33511  *      is omitted.  NaN / Infinity will just flow through and ultimately
33512  *      result in a NaN internal time value.
33513  *
33514  *    - Date.prototype.setYear() does not have optional arguments for
33515  *      setting month and day-in-month (like setFullYear()), but we indicate
33516  *      'maxnargs' to be 3 to get the year written to the correct component
33517  *      index in duk__set_part_helper().  The function has nargs == 1, so only
33518  *      the year will be set regardless of actual argument count.
33519  */
33520 
duk_bi_date_prototype_set_shared(duk_hthread * thr)33521 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_shared(duk_hthread *thr) {
33522 	duk_small_uint_t flags_and_maxnargs = duk__date_get_indirect_magic(thr);
33523 	return duk__set_part_helper(thr, flags_and_maxnargs);
33524 }
33525 
duk_bi_date_prototype_set_time(duk_hthread * thr)33526 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_time(duk_hthread *thr) {
33527 	duk_double_t d;
33528 
33529 	(void) duk__push_this_get_timeval(thr, 0 /*flags*/); /* -> [ timeval this ] */
33530 	d = duk__timeclip(duk_to_number(thr, 0));
33531 	duk_push_number(thr, d);
33532 	duk_dup_top(thr);
33533 	/* Must force write because .setTime() must work even when
33534 	 * the Date instance is frozen.
33535 	 */
33536 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
33537 	/* -> [ timeval this timeval ] */
33538 
33539 	return 1;
33540 }
33541 
33542 /*
33543  *  Misc.
33544  */
33545 
33546 #if defined(DUK_USE_SYMBOL_BUILTIN)
duk_bi_date_prototype_toprimitive(duk_hthread * thr)33547 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_toprimitive(duk_hthread *thr) {
33548 	duk_size_t hintlen;
33549 	const char *hintstr;
33550 	duk_int_t hint;
33551 
33552 	/* Invokes OrdinaryToPrimitive() with suitable hint.  Note that the
33553 	 * method is generic, and works on non-Date arguments too.
33554 	 *
33555 	 * https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype-@@toprimitive
33556 	 */
33557 
33558 	duk_push_this(thr);
33559 	duk_require_object(thr, -1);
33560 	DUK_ASSERT_TOP(thr, 2);
33561 
33562 	hintstr = duk_require_lstring(thr, 0, &hintlen);
33563 	if ((hintlen == 6 && DUK_STRCMP(hintstr, "string") == 0) ||
33564 	    (hintlen == 7 && DUK_STRCMP(hintstr, "default") == 0)) {
33565 		hint = DUK_HINT_STRING;
33566 	} else if (hintlen == 6 && DUK_STRCMP(hintstr, "number") == 0) {
33567 		hint = DUK_HINT_NUMBER;
33568 	} else {
33569 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
33570 	}
33571 
33572 	duk_to_primitive_ordinary(thr, -1, hint);
33573 	return 1;
33574 }
33575 #endif  /* DUK_USE_SYMBOL_BUILTIN */
33576 
33577 #endif  /* DUK_USE_DATE_BUILTIN */
33578 
33579 /* automatic undefs */
33580 #undef DUK__CF_ACCEPT
33581 #undef DUK__CF_ACCEPT_NUL
33582 #undef DUK__CF_NEG
33583 #undef DUK__DPRINT_DPARTS
33584 #undef DUK__DPRINT_PARTS
33585 #undef DUK__DPRINT_PARTS_AND_DPARTS
33586 #undef DUK__LOCAL_TZOFFSET_MAXITER
33587 #undef DUK__NUM_ISO8601_PARSER_PARTS
33588 #undef DUK__PACK_RULE
33589 #undef DUK__PI_DAY
33590 #undef DUK__PI_HOUR
33591 #undef DUK__PI_MILLISECOND
33592 #undef DUK__PI_MINUTE
33593 #undef DUK__PI_MONTH
33594 #undef DUK__PI_SECOND
33595 #undef DUK__PI_TZHOUR
33596 #undef DUK__PI_TZMINUTE
33597 #undef DUK__PI_YEAR
33598 #undef DUK__PM_DAY
33599 #undef DUK__PM_HOUR
33600 #undef DUK__PM_MILLISECOND
33601 #undef DUK__PM_MINUTE
33602 #undef DUK__PM_MONTH
33603 #undef DUK__PM_SECOND
33604 #undef DUK__PM_TZHOUR
33605 #undef DUK__PM_TZMINUTE
33606 #undef DUK__PM_YEAR
33607 #undef DUK__RULE_MASK_PART_SEP
33608 #undef DUK__SI_COLON
33609 #undef DUK__SI_MINUS
33610 #undef DUK__SI_NUL
33611 #undef DUK__SI_PERIOD
33612 #undef DUK__SI_PLUS
33613 #undef DUK__SI_SPACE
33614 #undef DUK__SI_T
33615 #undef DUK__SI_Z
33616 #undef DUK__SM_COLON
33617 #undef DUK__SM_MINUS
33618 #undef DUK__SM_NUL
33619 #undef DUK__SM_PERIOD
33620 #undef DUK__SM_PLUS
33621 #undef DUK__SM_SPACE
33622 #undef DUK__SM_T
33623 #undef DUK__SM_Z
33624 #undef DUK__UNPACK_RULE
33625 #undef DUK__WEEKDAY_MOD_ADDER
33626 #undef DUK__YEAR
33627 #line 1 "duk_bi_date_unix.c"
33628 /*
33629  *  Unix-like Date providers
33630  *
33631  *  Generally useful Unix / POSIX / ANSI Date providers.
33632  */
33633 
33634 /* #include duk_internal.h -> already included */
33635 
33636 /* The necessary #includes are in place in duk_config.h. */
33637 
33638 /* Buffer sizes for some UNIX calls.  Larger than strictly necessary
33639  * to avoid Valgrind errors.
33640  */
33641 #define DUK__STRPTIME_BUF_SIZE  64
33642 #define DUK__STRFTIME_BUF_SIZE  64
33643 
33644 #if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
33645 /* Get current ECMAScript time (= UNIX/Posix time, but in milliseconds). */
duk_bi_date_get_now_gettimeofday(void)33646 DUK_INTERNAL duk_double_t duk_bi_date_get_now_gettimeofday(void) {
33647 	struct timeval tv;
33648 	duk_double_t d;
33649 
33650 	if (gettimeofday(&tv, NULL) != 0) {
33651 		DUK_D(DUK_DPRINT("gettimeofday() failed"));
33652 		return 0.0;
33653 	}
33654 
33655 	/* As of Duktape 2.2.0 allow fractions. */
33656 	d = ((duk_double_t) tv.tv_sec) * 1000.0 +
33657 	    ((duk_double_t) tv.tv_usec) / 1000.0;
33658 
33659 	return d;
33660 }
33661 #endif  /* DUK_USE_DATE_NOW_GETTIMEOFDAY */
33662 
33663 #if defined(DUK_USE_DATE_NOW_TIME)
33664 /* Not a very good provider: only full seconds are available. */
duk_bi_date_get_now_time(void)33665 DUK_INTERNAL duk_double_t duk_bi_date_get_now_time(void) {
33666 	time_t t;
33667 
33668 	t = time(NULL);
33669 	if (t == (time_t) -1) {
33670 		DUK_D(DUK_DPRINT("time() failed"));
33671 		return 0.0;
33672 	}
33673 	return ((duk_double_t) t) * 1000.0;
33674 }
33675 #endif  /* DUK_USE_DATE_NOW_TIME */
33676 
33677 #if defined(DUK_USE_DATE_TZO_GMTIME) || defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S)
33678 /* Get local time offset (in seconds) for a certain (UTC) instant 'd'. */
duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d)33679 DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) {
33680 	time_t t, t1, t2;
33681 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
33682 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
33683 	struct tm tms[2];
33684 #if defined(DUK_USE_DATE_TZO_GMTIME)
33685 	struct tm *tm_ptr;
33686 #endif
33687 
33688 	/* For NaN/inf, the return value doesn't matter. */
33689 	if (!DUK_ISFINITE(d)) {
33690 		return 0;
33691 	}
33692 
33693 	/* If not within ECMAScript range, some integer time calculations
33694 	 * won't work correctly (and some asserts will fail), so bail out
33695 	 * if so.  This fixes test-bug-date-insane-setyear.js.  There is
33696 	 * a +/- 24h leeway in this range check to avoid a test262 corner
33697 	 * case documented in test-bug-date-timeval-edges.js.
33698 	 */
33699 	if (!duk_bi_date_timeval_in_leeway_range(d)) {
33700 		DUK_DD(DUK_DDPRINT("timeval not within valid range, skip tzoffset computation to avoid integer overflows"));
33701 		return 0;
33702 	}
33703 
33704 	/*
33705 	 *  This is a bit tricky to implement portably.  The result depends
33706 	 *  on the timestamp (specifically, DST depends on the timestamp).
33707 	 *  If e.g. UNIX APIs are used, they'll have portability issues with
33708 	 *  very small and very large years.
33709 	 *
33710 	 *  Current approach:
33711 	 *
33712 	 *  - Stay within portable UNIX limits by using equivalent year mapping.
33713 	 *    Avoid year 1970 and 2038 as some conversions start to fail, at
33714 	 *    least on some platforms.  Avoiding 1970 means that there are
33715 	 *    currently DST discrepancies for 1970.
33716 	 *
33717 	 *  - Create a UTC and local time breakdowns from 't'.  Then create
33718 	 *    a time_t using gmtime() and localtime() and compute the time
33719 	 *    difference between the two.
33720 	 *
33721 	 *  Equivalent year mapping (E5 Section 15.9.1.8):
33722 	 *
33723 	 *    If the host environment provides functionality for determining
33724 	 *    daylight saving time, the implementation of ECMAScript is free
33725 	 *    to map the year in question to an equivalent year (same
33726 	 *    leap-year-ness and same starting week day for the year) for which
33727 	 *    the host environment provides daylight saving time information.
33728 	 *    The only restriction is that all equivalent years should produce
33729 	 *    the same result.
33730 	 *
33731 	 *  This approach is quite reasonable but not entirely correct, e.g.
33732 	 *  the specification also states (E5 Section 15.9.1.8):
33733 	 *
33734 	 *    The implementation of ECMAScript should not try to determine
33735 	 *    whether the exact time was subject to daylight saving time, but
33736 	 *    just whether daylight saving time would have been in effect if
33737 	 *    the _current daylight saving time algorithm_ had been used at the
33738 	 *    time.  This avoids complications such as taking into account the
33739 	 *    years that the locale observed daylight saving time year round.
33740 	 *
33741 	 *  Since we rely on the platform APIs for conversions between local
33742 	 *  time and UTC, we can't guarantee the above.  Rather, if the platform
33743 	 *  has historical DST rules they will be applied.  This seems to be the
33744 	 *  general preferred direction in ECMAScript standardization (or at least
33745 	 *  implementations) anyway, and even the equivalent year mapping should
33746 	 *  be disabled if the platform is known to handle DST properly for the
33747 	 *  full ECMAScript range.
33748 	 *
33749 	 *  The following has useful discussion and links:
33750 	 *
33751 	 *    https://bugzilla.mozilla.org/show_bug.cgi?id=351066
33752 	 */
33753 
33754 	duk_bi_date_timeval_to_parts(d, parts, dparts, DUK_DATE_FLAG_EQUIVYEAR /*flags*/);
33755 	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= 1970 && parts[DUK_DATE_IDX_YEAR] <= 2038);
33756 
33757 	d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
33758 	DUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0);  /* unsigned 31-bit range */
33759 	t = (time_t) (d / 1000.0);
33760 	DUK_DDD(DUK_DDDPRINT("timeval: %lf -> time_t %ld", (double) d, (long) t));
33761 
33762 	duk_memzero((void *) tms, sizeof(struct tm) * 2);
33763 
33764 #if defined(DUK_USE_DATE_TZO_GMTIME_R)
33765 	(void) gmtime_r(&t, &tms[0]);
33766 	(void) localtime_r(&t, &tms[1]);
33767 #elif defined(DUK_USE_DATE_TZO_GMTIME_S)
33768 	(void) gmtime_s(&t, &tms[0]);
33769 	(void) localtime_s(&t, &tms[1]);
33770 #elif defined(DUK_USE_DATE_TZO_GMTIME)
33771 	tm_ptr = gmtime(&t);
33772 	duk_memcpy((void *) &tms[0], tm_ptr, sizeof(struct tm));
33773 	tm_ptr = localtime(&t);
33774 	duk_memcpy((void *) &tms[1], tm_ptr, sizeof(struct tm));
33775 #else
33776 #error internal error
33777 #endif
33778 	DUK_DDD(DUK_DDDPRINT("gmtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
33779 	                     "wday:%ld,yday:%ld,isdst:%ld}",
33780 	                     (long) tms[0].tm_sec, (long) tms[0].tm_min, (long) tms[0].tm_hour,
33781 	                     (long) tms[0].tm_mday, (long) tms[0].tm_mon, (long) tms[0].tm_year,
33782 	                     (long) tms[0].tm_wday, (long) tms[0].tm_yday, (long) tms[0].tm_isdst));
33783 	DUK_DDD(DUK_DDDPRINT("localtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
33784 	                     "wday:%ld,yday:%ld,isdst:%ld}",
33785 	                     (long) tms[1].tm_sec, (long) tms[1].tm_min, (long) tms[1].tm_hour,
33786 	                     (long) tms[1].tm_mday, (long) tms[1].tm_mon, (long) tms[1].tm_year,
33787 	                     (long) tms[1].tm_wday, (long) tms[1].tm_yday, (long) tms[1].tm_isdst));
33788 
33789 	/* tm_isdst is both an input and an output to mktime(), use 0 to
33790 	 * avoid DST handling in mktime():
33791 	 * - https://github.com/svaarala/duktape/issues/406
33792 	 * - http://stackoverflow.com/questions/8558919/mktime-and-tm-isdst
33793 	 */
33794 	tms[0].tm_isdst = 0;
33795 	tms[1].tm_isdst = 0;
33796 	t1 = mktime(&tms[0]);  /* UTC */
33797 	t2 = mktime(&tms[1]);  /* local */
33798 	if (t1 == (time_t) -1 || t2 == (time_t) -1) {
33799 		/* This check used to be for (t < 0) but on some platforms
33800 		 * time_t is unsigned and apparently the proper way to detect
33801 		 * an mktime() error return is the cast above.  See e.g.:
33802 		 * http://pubs.opengroup.org/onlinepubs/009695299/functions/mktime.html
33803 		 */
33804 		goto mktime_error;
33805 	}
33806 	DUK_DDD(DUK_DDDPRINT("t1=%ld (utc), t2=%ld (local)", (long) t1, (long) t2));
33807 
33808 	/* Compute final offset in seconds, positive if local time ahead of
33809 	 * UTC (returned value is UTC-to-local offset).
33810 	 *
33811 	 * difftime() returns a double, so coercion to int generates quite
33812 	 * a lot of code.  Direct subtraction is not portable, however.
33813 	 * XXX: allow direct subtraction on known platforms.
33814 	 */
33815 #if 0
33816 	return (duk_int_t) (t2 - t1);
33817 #endif
33818 	return (duk_int_t) difftime(t2, t1);
33819 
33820  mktime_error:
33821 	/* XXX: return something more useful, so that caller can throw? */
33822 	DUK_D(DUK_DPRINT("mktime() failed, d=%lf", (double) d));
33823 	return 0;
33824 }
33825 #endif  /* DUK_USE_DATE_TZO_GMTIME */
33826 
33827 #if defined(DUK_USE_DATE_PRS_STRPTIME)
duk_bi_date_parse_string_strptime(duk_hthread * thr,const char * str)33828 DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr, const char *str) {
33829 	struct tm tm;
33830 	time_t t;
33831 	char buf[DUK__STRPTIME_BUF_SIZE];
33832 
33833 	/* Copy to buffer with slack to avoid Valgrind gripes from strptime. */
33834 	DUK_ASSERT(str != NULL);
33835 	duk_memzero(buf, sizeof(buf));  /* valgrind whine without this */
33836 	DUK_SNPRINTF(buf, sizeof(buf), "%s", (const char *) str);
33837 	buf[sizeof(buf) - 1] = (char) 0;
33838 
33839 	DUK_DDD(DUK_DDDPRINT("parsing: '%s'", (const char *) buf));
33840 
33841 	duk_memzero(&tm, sizeof(tm));
33842 	if (strptime((const char *) buf, "%c", &tm) != NULL) {
33843 		DUK_DDD(DUK_DDDPRINT("before mktime: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
33844 		                     "wday:%ld,yday:%ld,isdst:%ld}",
33845 		                     (long) tm.tm_sec, (long) tm.tm_min, (long) tm.tm_hour,
33846 		                     (long) tm.tm_mday, (long) tm.tm_mon, (long) tm.tm_year,
33847 		                     (long) tm.tm_wday, (long) tm.tm_yday, (long) tm.tm_isdst));
33848 		tm.tm_isdst = -1;  /* negative: dst info not available */
33849 
33850 		t = mktime(&tm);
33851 		DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
33852 		if (t >= 0) {
33853 			duk_push_number(thr, ((duk_double_t) t) * 1000.0);
33854 			return 1;
33855 		}
33856 	}
33857 
33858 	return 0;
33859 }
33860 #endif  /* DUK_USE_DATE_PRS_STRPTIME */
33861 
33862 #if defined(DUK_USE_DATE_PRS_GETDATE)
duk_bi_date_parse_string_getdate(duk_hthread * thr,const char * str)33863 DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const char *str) {
33864 	struct tm tm;
33865 	duk_small_int_t rc;
33866 	time_t t;
33867 
33868 	/* For this to work, DATEMSK must be set, so this is not very
33869 	 * convenient for an embeddable interpreter.
33870 	 */
33871 
33872 	duk_memzero(&tm, sizeof(struct tm));
33873 	rc = (duk_small_int_t) getdate_r(str, &tm);
33874 	DUK_DDD(DUK_DDDPRINT("getdate_r() -> %ld", (long) rc));
33875 
33876 	if (rc == 0) {
33877 		t = mktime(&tm);
33878 		DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
33879 		if (t >= 0) {
33880 			duk_push_number(thr, (duk_double_t) t);
33881 			return 1;
33882 		}
33883 	}
33884 
33885 	return 0;
33886 }
33887 #endif  /* DUK_USE_DATE_PRS_GETDATE */
33888 
33889 #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)33890 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) {
33891 	char buf[DUK__STRFTIME_BUF_SIZE];
33892 	struct tm tm;
33893 	const char *fmt;
33894 
33895 	DUK_UNREF(tzoffset);
33896 
33897 	/* If the platform doesn't support the entire ECMAScript range, we need
33898 	 * to return 0 so that the caller can fall back to the default formatter.
33899 	 *
33900 	 * For now, assume that if time_t is 8 bytes or more, the whole ECMAScript
33901 	 * range is supported.  For smaller time_t values (4 bytes in practice),
33902 	 * assumes that the signed 32-bit range is supported.
33903 	 *
33904 	 * XXX: detect this more correctly per platform.  The size of time_t is
33905 	 * probably not an accurate guarantee of strftime() supporting or not
33906 	 * supporting a large time range (the full ECMAScript range).
33907 	 */
33908 	if (sizeof(time_t) < 8 &&
33909 	    (parts[DUK_DATE_IDX_YEAR] < 1970 || parts[DUK_DATE_IDX_YEAR] > 2037)) {
33910 		/* be paranoid for 32-bit time values (even avoiding negative ones) */
33911 		return 0;
33912 	}
33913 
33914 	duk_memzero(&tm, sizeof(tm));
33915 	tm.tm_sec = parts[DUK_DATE_IDX_SECOND];
33916 	tm.tm_min = parts[DUK_DATE_IDX_MINUTE];
33917 	tm.tm_hour = parts[DUK_DATE_IDX_HOUR];
33918 	tm.tm_mday = parts[DUK_DATE_IDX_DAY];       /* already one-based */
33919 	tm.tm_mon = parts[DUK_DATE_IDX_MONTH] - 1;  /* one-based -> zero-based */
33920 	tm.tm_year = parts[DUK_DATE_IDX_YEAR] - 1900;
33921 	tm.tm_wday = parts[DUK_DATE_IDX_WEEKDAY];
33922 	tm.tm_isdst = 0;
33923 
33924 	duk_memzero(buf, sizeof(buf));
33925 	if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
33926 		fmt = "%c";
33927 	} else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
33928 		fmt = "%x";
33929 	} else {
33930 		DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);
33931 		fmt = "%X";
33932 	}
33933 	(void) strftime(buf, sizeof(buf) - 1, fmt, &tm);
33934 	DUK_ASSERT(buf[sizeof(buf) - 1] == 0);
33935 
33936 	duk_push_string(thr, buf);
33937 	return 1;
33938 }
33939 #endif  /* DUK_USE_DATE_FMT_STRFTIME */
33940 
33941 #if defined(DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME)
duk_bi_date_get_monotonic_time_clock_gettime(void)33942 DUK_INTERNAL duk_double_t duk_bi_date_get_monotonic_time_clock_gettime(void) {
33943 	struct timespec ts;
33944 
33945 	if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
33946 		return (duk_double_t) ts.tv_sec * 1000.0 + (duk_double_t) ts.tv_nsec / 1000000.0;
33947 	} else {
33948 		DUK_D(DUK_DPRINT("clock_gettime(CLOCK_MONOTONIC) failed"));
33949 		return 0.0;
33950 	}
33951 }
33952 #endif
33953 
33954 /* automatic undefs */
33955 #undef DUK__STRFTIME_BUF_SIZE
33956 #undef DUK__STRPTIME_BUF_SIZE
33957 #line 1 "duk_bi_date_windows.c"
33958 /*
33959  *  Windows Date providers
33960  *
33961  *  Platform specific links:
33962  *
33963  *    - http://msdn.microsoft.com/en-us/library/windows/desktop/ms725473(v=vs.85).aspx
33964  */
33965 
33966 /* #include duk_internal.h -> already included */
33967 
33968 /* The necessary #includes are in place in duk_config.h. */
33969 
33970 #if defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS)
33971 /* Shared Windows helpers. */
duk__convert_systime_to_ularge(const SYSTEMTIME * st,ULARGE_INTEGER * res)33972 DUK_LOCAL void duk__convert_systime_to_ularge(const SYSTEMTIME *st, ULARGE_INTEGER *res) {
33973 	FILETIME ft;
33974 	if (SystemTimeToFileTime(st, &ft) == 0) {
33975 		DUK_D(DUK_DPRINT("SystemTimeToFileTime() failed, returning 0"));
33976 		res->QuadPart = 0;
33977 	} else {
33978 		res->LowPart = ft.dwLowDateTime;
33979 		res->HighPart = ft.dwHighDateTime;
33980 	}
33981 }
33982 
33983 #if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
duk__convert_filetime_to_ularge(const FILETIME * ft,ULARGE_INTEGER * res)33984 DUK_LOCAL void duk__convert_filetime_to_ularge(const FILETIME *ft, ULARGE_INTEGER *res) {
33985 	res->LowPart = ft->dwLowDateTime;
33986 	res->HighPart = ft->dwHighDateTime;
33987 }
33988 #endif  /* DUK_USE_DATE_NOW_WINDOWS_SUBMS */
33989 
duk__set_systime_jan1970(SYSTEMTIME * st)33990 DUK_LOCAL void duk__set_systime_jan1970(SYSTEMTIME *st) {
33991 	duk_memzero((void *) st, sizeof(*st));
33992 	st->wYear = 1970;
33993 	st->wMonth = 1;
33994 	st->wDayOfWeek = 4;  /* not sure whether or not needed; Thursday */
33995 	st->wDay = 1;
33996 	DUK_ASSERT(st->wHour == 0);
33997 	DUK_ASSERT(st->wMinute == 0);
33998 	DUK_ASSERT(st->wSecond == 0);
33999 	DUK_ASSERT(st->wMilliseconds == 0);
34000 }
34001 #endif  /* defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) */
34002 
34003 #if defined(DUK_USE_DATE_NOW_WINDOWS)
duk_bi_date_get_now_windows(void)34004 DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows(void) {
34005 	/* Suggested step-by-step method from documentation of RtlTimeToSecondsSince1970:
34006 	 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724928(v=vs.85).aspx
34007 	 */
34008 	SYSTEMTIME st1, st2;
34009 	ULARGE_INTEGER tmp1, tmp2;
34010 
34011 	GetSystemTime(&st1);
34012 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
34013 
34014 	duk__set_systime_jan1970(&st2);
34015 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
34016 
34017 	/* Difference is in 100ns units, convert to milliseconds, keeping
34018 	 * fractions since Duktape 2.2.0.  This is only theoretical because
34019 	 * SYSTEMTIME is limited to milliseconds.
34020 	 */
34021 	return (duk_double_t) ((LONGLONG) tmp1.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000.0;
34022 }
34023 #endif  /* DUK_USE_DATE_NOW_WINDOWS */
34024 
34025 #if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
duk_bi_date_get_now_windows_subms(void)34026 DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows_subms(void) {
34027 	/* Variant of the basic algorithm using GetSystemTimePreciseAsFileTime()
34028 	 * for more accuracy.
34029 	 */
34030 	FILETIME ft1;
34031 	SYSTEMTIME st2;
34032 	ULARGE_INTEGER tmp1, tmp2;
34033 
34034 	GetSystemTimePreciseAsFileTime(&ft1);
34035 	duk__convert_filetime_to_ularge((const FILETIME *) &ft1, &tmp1);
34036 
34037 	duk__set_systime_jan1970(&st2);
34038 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
34039 
34040 	/* Difference is in 100ns units, convert to milliseconds, keeping
34041 	 * fractions since Duktape 2.2.0.
34042 	 */
34043 	return (duk_double_t) ((LONGLONG) tmp1.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000.0;
34044 }
34045 #endif  /* DUK_USE_DATE_NOW_WINDOWS */
34046 
34047 #if defined(DUK_USE_DATE_TZO_WINDOWS)
duk_bi_date_get_local_tzoffset_windows(duk_double_t d)34048 DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) {
34049 	SYSTEMTIME st1;
34050 	SYSTEMTIME st2;
34051 	SYSTEMTIME st3;
34052 	ULARGE_INTEGER tmp1;
34053 	ULARGE_INTEGER tmp2;
34054 	ULARGE_INTEGER tmp3;
34055 	FILETIME ft1;
34056 
34057 	/* XXX: handling of timestamps outside Windows supported range.
34058 	 * How does Windows deal with dates before 1600?  Does windows
34059 	 * support all ECMAScript years (like -200000 and +200000)?
34060 	 * Should equivalent year mapping be used here too?  If so, use
34061 	 * a shared helper (currently integrated into timeval-to-parts).
34062 	 */
34063 
34064 	/* Use the approach described in "Remarks" of FileTimeToLocalFileTime:
34065 	 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277(v=vs.85).aspx
34066 	 */
34067 
34068 	duk__set_systime_jan1970(&st1);
34069 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
34070 	tmp2.QuadPart = (ULONGLONG) (d * 10000.0);  /* millisec -> 100ns units since jan 1, 1970 */
34071 	tmp2.QuadPart += tmp1.QuadPart;             /* input 'd' in Windows UTC, 100ns units */
34072 
34073 	ft1.dwLowDateTime = tmp2.LowPart;
34074 	ft1.dwHighDateTime = tmp2.HighPart;
34075 	if (FileTimeToSystemTime((const FILETIME *) &ft1, &st2) == 0) {
34076 		DUK_D(DUK_DPRINT("FileTimeToSystemTime() failed, return tzoffset 0"));
34077 		return 0;
34078 	}
34079 	if (SystemTimeToTzSpecificLocalTime((LPTIME_ZONE_INFORMATION) NULL, &st2, &st3) == 0) {
34080 		DUK_D(DUK_DPRINT("SystemTimeToTzSpecificLocalTime() failed, return tzoffset 0"));
34081 		return 0;
34082 	}
34083 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st3, &tmp3);
34084 
34085 	/* Positive if local time ahead of UTC. */
34086 	return (duk_int_t) (((LONGLONG) tmp3.QuadPart - (LONGLONG) tmp2.QuadPart) / DUK_I64_CONSTANT(10000000));  /* seconds */
34087 }
34088 #endif  /* DUK_USE_DATE_TZO_WINDOWS */
34089 
34090 #if defined(DUK_USE_DATE_TZO_WINDOWS_NO_DST)
duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d)34091 DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d) {
34092 	SYSTEMTIME st1;
34093 	SYSTEMTIME st2;
34094 	FILETIME ft1;
34095 	FILETIME ft2;
34096 	ULARGE_INTEGER tmp1;
34097 	ULARGE_INTEGER tmp2;
34098 
34099 	/* Do a similar computation to duk_bi_date_get_local_tzoffset_windows
34100 	 * but without accounting for daylight savings time.  Use this on
34101 	 * Windows platforms (like Durango) that don't support the
34102 	 * SystemTimeToTzSpecificLocalTime() call.
34103 	 */
34104 
34105 	/* current time not needed for this computation */
34106 	DUK_UNREF(d);
34107 
34108 	duk__set_systime_jan1970(&st1);
34109 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
34110 
34111 	ft1.dwLowDateTime = tmp1.LowPart;
34112 	ft1.dwHighDateTime = tmp1.HighPart;
34113 	if (FileTimeToLocalFileTime((const FILETIME *) &ft1, &ft2) == 0) {
34114 		DUK_D(DUK_DPRINT("FileTimeToLocalFileTime() failed, return tzoffset 0"));
34115 		return 0;
34116 	}
34117 	if (FileTimeToSystemTime((const FILETIME *) &ft2, &st2) == 0) {
34118 		DUK_D(DUK_DPRINT("FileTimeToSystemTime() failed, return tzoffset 0"));
34119 		return 0;
34120 	}
34121 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
34122 
34123 	return (duk_int_t) (((LONGLONG) tmp2.QuadPart - (LONGLONG) tmp1.QuadPart) / DUK_I64_CONSTANT(10000000));  /* seconds */
34124 }
34125 #endif  /* DUK_USE_DATE_TZO_WINDOWS_NO_DST */
34126 
34127 #if defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC)
duk_bi_date_get_monotonic_time_windows_qpc(void)34128 DUK_INTERNAL duk_double_t duk_bi_date_get_monotonic_time_windows_qpc(void) {
34129 	LARGE_INTEGER count, freq;
34130 
34131 	/* There are legacy issues with QueryPerformanceCounter():
34132 	 * - Potential jumps: https://support.microsoft.com/en-us/help/274323/performance-counter-value-may-unexpectedly-leap-forward
34133 	 * - Differences between cores (XP): https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx#qpc_support_in_windows_versions
34134 	 *
34135 	 * We avoid these by enabling QPC by default only for Vista or later.
34136 	 */
34137 
34138 	if (QueryPerformanceCounter(&count) && QueryPerformanceFrequency(&freq)) {
34139 		/* XXX: QueryPerformanceFrequency() can be cached */
34140 		return (duk_double_t) count.QuadPart / (duk_double_t) freq.QuadPart * 1000.0;
34141 	} else {
34142 		/* MSDN: "On systems that run Windows XP or later, the function
34143 		 * will always succeed and will thus never return zero."
34144 		 * Provide minimal error path just in case user enables this
34145 		 * feature in pre-XP Windows.
34146 		 */
34147 		return 0.0;
34148 	}
34149 }
34150 #endif  /* DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC */
34151 #line 1 "duk_bi_duktape.c"
34152 /*
34153  *  Duktape built-ins
34154  *
34155  *  Size optimization note: it might seem that vararg multipurpose functions
34156  *  like fin(), enc(), and dec() are not very size optimal, but using a single
34157  *  user-visible ECMAScript function saves a lot of run-time footprint; each
34158  *  Function instance takes >100 bytes.  Using a shared native helper and a
34159  *  'magic' value won't save much if there are multiple Function instances
34160  *  anyway.
34161  */
34162 
34163 /* #include duk_internal.h -> already included */
34164 
34165 #if defined(DUK_USE_DUKTAPE_BUILTIN)
34166 
duk_bi_duktape_object_info(duk_hthread * thr)34167 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_info(duk_hthread *thr) {
34168 	duk_inspect_value(thr, -1);
34169 	return 1;
34170 }
34171 
duk_bi_duktape_object_act(duk_hthread * thr)34172 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_act(duk_hthread *thr) {
34173 	duk_int_t level;
34174 
34175 	level = duk_to_int(thr, 0);
34176 	duk_inspect_callstack_entry(thr, level);
34177 	return 1;
34178 }
34179 
duk_bi_duktape_object_gc(duk_hthread * thr)34180 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_gc(duk_hthread *thr) {
34181 	duk_small_uint_t flags;
34182 
34183 	flags = (duk_small_uint_t) duk_get_uint(thr, 0);
34184 	duk_heap_mark_and_sweep(thr->heap, flags);
34185 
34186 	/* XXX: Not sure what the best return value would be in the API.
34187 	 * Return true for now.
34188 	 */
34189 	duk_push_true(thr);
34190 	return 1;
34191 }
34192 
34193 #if defined(DUK_USE_FINALIZER_SUPPORT)
duk_bi_duktape_object_fin(duk_hthread * thr)34194 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_fin(duk_hthread *thr) {
34195 	(void) duk_require_hobject(thr, 0);
34196 	if (duk_get_top(thr) >= 2) {
34197 		/* Set: currently a finalizer is disabled by setting it to
34198 		 * undefined; this does not remove the property at the moment.
34199 		 * The value could be type checked to be either a function
34200 		 * or something else; if something else, the property could
34201 		 * be deleted.  Must use duk_set_finalizer() to keep
34202 		 * DUK_HOBJECT_FLAG_HAVE_FINALIZER in sync.
34203 		 */
34204 		duk_set_top(thr, 2);
34205 		duk_set_finalizer(thr, 0);
34206 		return 0;
34207 	} else {
34208 		/* Get. */
34209 		DUK_ASSERT(duk_get_top(thr) == 1);
34210 		duk_get_finalizer(thr, 0);
34211 		return 1;
34212 	}
34213 }
34214 #endif  /* DUK_USE_FINALIZER_SUPPORT */
34215 
duk_bi_duktape_object_enc(duk_hthread * thr)34216 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_enc(duk_hthread *thr) {
34217 	duk_hstring *h_str;
34218 
34219 	/* Vararg function: must be careful to check/require arguments.
34220 	 * The JSON helpers accept invalid indices and treat them like
34221 	 * non-existent optional parameters.
34222 	 */
34223 
34224 	h_str = duk_require_hstring(thr, 0);  /* Could reject symbols, but no point: won't match comparisons. */
34225 	duk_require_valid_index(thr, 1);
34226 
34227 	if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
34228 		duk_set_top(thr, 2);
34229 		duk_hex_encode(thr, 1);
34230 		DUK_ASSERT_TOP(thr, 2);
34231 	} else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
34232 		duk_set_top(thr, 2);
34233 		duk_base64_encode(thr, 1);
34234 		DUK_ASSERT_TOP(thr, 2);
34235 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)
34236 	} else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
34237 		duk_bi_json_stringify_helper(thr,
34238 		                             1 /*idx_value*/,
34239 		                             2 /*idx_replacer*/,
34240 		                             3 /*idx_space*/,
34241 		                             DUK_JSON_FLAG_EXT_CUSTOM |
34242 		                             DUK_JSON_FLAG_ASCII_ONLY |
34243 		                             DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
34244 #endif
34245 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
34246 	} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
34247 		duk_bi_json_stringify_helper(thr,
34248 		                             1 /*idx_value*/,
34249 		                             2 /*idx_replacer*/,
34250 		                             3 /*idx_space*/,
34251 		                             DUK_JSON_FLAG_EXT_COMPATIBLE |
34252 		                             DUK_JSON_FLAG_ASCII_ONLY /*flags*/);
34253 #endif
34254 	} else {
34255 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
34256 	}
34257 	return 1;
34258 }
34259 
duk_bi_duktape_object_dec(duk_hthread * thr)34260 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_dec(duk_hthread *thr) {
34261 	duk_hstring *h_str;
34262 
34263 	/* Vararg function: must be careful to check/require arguments.
34264 	 * The JSON helpers accept invalid indices and treat them like
34265 	 * non-existent optional parameters.
34266 	 */
34267 
34268 	h_str = duk_require_hstring(thr, 0);  /* Could reject symbols, but no point: won't match comparisons */
34269 	duk_require_valid_index(thr, 1);
34270 
34271 	if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
34272 		duk_set_top(thr, 2);
34273 		duk_hex_decode(thr, 1);
34274 		DUK_ASSERT_TOP(thr, 2);
34275 	} else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
34276 		duk_set_top(thr, 2);
34277 		duk_base64_decode(thr, 1);
34278 		DUK_ASSERT_TOP(thr, 2);
34279 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)
34280 	} else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
34281 		duk_bi_json_parse_helper(thr,
34282 		                         1 /*idx_value*/,
34283 		                         2 /*idx_replacer*/,
34284 		                         DUK_JSON_FLAG_EXT_CUSTOM /*flags*/);
34285 #endif
34286 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
34287 	} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
34288 		duk_bi_json_parse_helper(thr,
34289 		                         1 /*idx_value*/,
34290 		                         2 /*idx_replacer*/,
34291 		                         DUK_JSON_FLAG_EXT_COMPATIBLE /*flags*/);
34292 #endif
34293 	} else {
34294 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
34295 	}
34296 	return 1;
34297 }
34298 
34299 /*
34300  *  Compact an object
34301  */
34302 
duk_bi_duktape_object_compact(duk_hthread * thr)34303 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_compact(duk_hthread *thr) {
34304 	DUK_ASSERT_TOP(thr, 1);
34305 	duk_compact(thr, 0);
34306 	return 1;  /* return the argument object */
34307 }
34308 
34309 #endif  /* DUK_USE_DUKTAPE_BUILTIN */
34310 #line 1 "duk_bi_encoding.c"
34311 /*
34312  *  WHATWG Encoding API built-ins
34313  *
34314  *  API specification: https://encoding.spec.whatwg.org/#api
34315  *  Web IDL: https://www.w3.org/TR/WebIDL/
34316  */
34317 
34318 /* #include duk_internal.h -> already included */
34319 
34320 /*
34321  *  Data structures for encoding/decoding
34322  */
34323 
34324 typedef struct {
34325 	duk_uint8_t *out;      /* where to write next byte(s) */
34326 	duk_codepoint_t lead;  /* lead surrogate */
34327 } duk__encode_context;
34328 
34329 typedef struct {
34330 	/* UTF-8 decoding state */
34331 	duk_codepoint_t codepoint;  /* built up incrementally */
34332 	duk_uint8_t upper;          /* max value of next byte (decode error otherwise) */
34333 	duk_uint8_t lower;          /* min value of next byte (ditto) */
34334 	duk_uint8_t needed;         /* how many more bytes we need */
34335 	duk_uint8_t bom_handled;    /* BOM seen or no longer expected */
34336 
34337 	/* Decoder configuration */
34338 	duk_uint8_t fatal;
34339 	duk_uint8_t ignore_bom;
34340 } duk__decode_context;
34341 
34342 /* The signed duk_codepoint_t type is used to signal a decoded codepoint
34343  * (>= 0) or various other states using negative values.
34344  */
34345 #define DUK__CP_CONTINUE   (-1)  /* continue to next byte, no completed codepoint */
34346 #define DUK__CP_ERROR      (-2)  /* decoding error */
34347 #define DUK__CP_RETRY      (-3)  /* decoding error; retry last byte */
34348 
34349 /*
34350  *  Raw helpers for encoding/decoding
34351  */
34352 
34353 /* Emit UTF-8 (= CESU-8) encoded U+FFFD (replacement char), i.e. ef bf bd. */
duk__utf8_emit_repl(duk_uint8_t * ptr)34354 DUK_LOCAL duk_uint8_t *duk__utf8_emit_repl(duk_uint8_t *ptr) {
34355 	*ptr++ = 0xef;
34356 	*ptr++ = 0xbf;
34357 	*ptr++ = 0xbd;
34358 	return ptr;
34359 }
34360 
duk__utf8_decode_init(duk__decode_context * dec_ctx)34361 DUK_LOCAL void duk__utf8_decode_init(duk__decode_context *dec_ctx) {
34362 	/* (Re)init the decoding state of 'dec_ctx' but leave decoder
34363 	 * configuration fields untouched.
34364 	 */
34365 	dec_ctx->codepoint = 0x0000L;
34366 	dec_ctx->upper = 0xbf;
34367 	dec_ctx->lower = 0x80;
34368 	dec_ctx->needed = 0;
34369 	dec_ctx->bom_handled = 0;
34370 }
34371 
duk__utf8_decode_next(duk__decode_context * dec_ctx,duk_uint8_t x)34372 DUK_LOCAL duk_codepoint_t duk__utf8_decode_next(duk__decode_context *dec_ctx, duk_uint8_t x) {
34373 	/*
34374 	 *  UTF-8 algorithm based on the Encoding specification:
34375 	 *  https://encoding.spec.whatwg.org/#utf-8-decoder
34376 	 *
34377 	 *  Two main states: decoding initial byte vs. decoding continuation
34378 	 *  bytes.  Shortest length encoding is validated by restricting the
34379 	 *  allowed range of first continuation byte using 'lower' and 'upper'.
34380 	 */
34381 
34382 	if (dec_ctx->needed == 0) {
34383 		/* process initial byte */
34384 		if (x <= 0x7f) {
34385 			/* U+0000-U+007F, 1 byte (ASCII) */
34386 			return (duk_codepoint_t) x;
34387 		} else if (x >= 0xc2 && x <= 0xdf) {
34388 			/* U+0080-U+07FF, 2 bytes */
34389 			dec_ctx->needed = 1;
34390 			dec_ctx->codepoint = x & 0x1f;
34391 			DUK_ASSERT(dec_ctx->lower == 0x80);
34392 			DUK_ASSERT(dec_ctx->upper == 0xbf);
34393 			return DUK__CP_CONTINUE;
34394 		} else if (x >= 0xe0 && x <= 0xef) {
34395 			/* U+0800-U+FFFF, 3 bytes */
34396 			if (x == 0xe0) {
34397 				dec_ctx->lower = 0xa0;
34398 				DUK_ASSERT(dec_ctx->upper == 0xbf);
34399 			} else if (x == 0xed) {
34400 				DUK_ASSERT(dec_ctx->lower == 0x80);
34401 				dec_ctx->upper = 0x9f;
34402 			}
34403 			dec_ctx->needed = 2;
34404 			dec_ctx->codepoint = x & 0x0f;
34405 			return DUK__CP_CONTINUE;
34406 		} else if (x >= 0xf0 && x <= 0xf4) {
34407 			/* U+010000-U+10FFFF, 4 bytes */
34408 			if (x == 0xf0) {
34409 				dec_ctx->lower = 0x90;
34410 				DUK_ASSERT(dec_ctx->upper == 0xbf);
34411 			} else if (x == 0xf4) {
34412 				DUK_ASSERT(dec_ctx->lower == 0x80);
34413 				dec_ctx->upper = 0x8f;
34414 			}
34415 			dec_ctx->needed = 3;
34416 			dec_ctx->codepoint = x & 0x07;
34417 			return DUK__CP_CONTINUE;
34418 		} else {
34419 			/* not a legal initial byte */
34420 			return DUK__CP_ERROR;
34421 		}
34422 	} else {
34423 		/* process continuation byte */
34424 		if (x >= dec_ctx->lower && x <= dec_ctx->upper) {
34425 			dec_ctx->lower = 0x80;
34426 			dec_ctx->upper = 0xbf;
34427 			dec_ctx->codepoint = (dec_ctx->codepoint << 6) | (x & 0x3f);
34428 			if (--dec_ctx->needed > 0) {
34429 				/* need more bytes */
34430 				return DUK__CP_CONTINUE;
34431 			} else {
34432 				/* got a codepoint */
34433 				duk_codepoint_t ret;
34434 				DUK_ASSERT(dec_ctx->codepoint <= 0x10ffffL);  /* Decoding rules guarantee. */
34435 				ret = dec_ctx->codepoint;
34436 				dec_ctx->codepoint = 0x0000L;
34437 				dec_ctx->needed = 0;
34438 				return ret;
34439 			}
34440 		} else {
34441 			/* We just encountered an illegal UTF-8 continuation byte.  This might
34442 			 * be the initial byte of the next character; if we return a plain
34443 			 * error status and the decoder is in replacement mode, the character
34444 			 * will be masked.  We still need to alert the caller to the error
34445 			 * though.
34446 			 */
34447 			dec_ctx->codepoint = 0x0000L;
34448 			dec_ctx->needed = 0;
34449 			dec_ctx->lower = 0x80;
34450 			dec_ctx->upper = 0xbf;
34451 			return DUK__CP_RETRY;
34452 		}
34453 	}
34454 }
34455 
34456 #if defined(DUK_USE_ENCODING_BUILTINS)
duk__utf8_encode_char(void * udata,duk_codepoint_t codepoint)34457 DUK_LOCAL void duk__utf8_encode_char(void *udata, duk_codepoint_t codepoint) {
34458 	duk__encode_context *enc_ctx;
34459 
34460 	DUK_ASSERT(codepoint >= 0);
34461 	enc_ctx = (duk__encode_context *) udata;
34462 	DUK_ASSERT(enc_ctx != NULL);
34463 
34464 #if !defined(DUK_USE_PREFER_SIZE)
34465 	if (codepoint <= 0x7f && enc_ctx->lead == 0x0000L) {
34466 		/* Fast path for ASCII. */
34467 		*enc_ctx->out++ = (duk_uint8_t) codepoint;
34468 		return;
34469 	}
34470 #endif
34471 
34472 	if (DUK_UNLIKELY(codepoint > 0x10ffffL)) {
34473 		/* cannot legally encode in UTF-8 */
34474 		codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
34475 	} else if (codepoint >= 0xd800L && codepoint <= 0xdfffL) {
34476 		if (codepoint <= 0xdbffL) {
34477 			/* high surrogate */
34478 			duk_codepoint_t prev_lead = enc_ctx->lead;
34479 			enc_ctx->lead = codepoint;
34480 			if (prev_lead == 0x0000L) {
34481 				/* high surrogate, no output */
34482 				return;
34483 			} else {
34484 				/* consecutive high surrogates, consider first one unpaired */
34485 				codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
34486 			}
34487 		} else {
34488 			/* low surrogate */
34489 			if (enc_ctx->lead != 0x0000L) {
34490 				codepoint = (duk_codepoint_t) (0x010000L + ((enc_ctx->lead - 0xd800L) << 10) + (codepoint - 0xdc00L));
34491 				enc_ctx->lead = 0x0000L;
34492 			} else {
34493 				/* unpaired low surrogate */
34494 				DUK_ASSERT(enc_ctx->lead == 0x0000L);
34495 				codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
34496 			}
34497 		}
34498 	} else {
34499 		if (enc_ctx->lead != 0x0000L) {
34500 			/* unpaired high surrogate: emit replacement character and the input codepoint */
34501 			enc_ctx->lead = 0x0000L;
34502 			enc_ctx->out = duk__utf8_emit_repl(enc_ctx->out);
34503 		}
34504 	}
34505 
34506 	/* Codepoint may be original input, a decoded surrogate pair, or may
34507 	 * have been replaced with U+FFFD.
34508 	 */
34509 	enc_ctx->out += duk_unicode_encode_xutf8((duk_ucodepoint_t) codepoint, enc_ctx->out);
34510 }
34511 #endif  /* DUK_USE_ENCODING_BUILTINS */
34512 
34513 /* Shared helper for buffer-to-string using a TextDecoder() compatible UTF-8
34514  * decoder.
34515  */
duk__decode_helper(duk_hthread * thr,duk__decode_context * dec_ctx)34516 DUK_LOCAL duk_ret_t duk__decode_helper(duk_hthread *thr, duk__decode_context *dec_ctx) {
34517 	const duk_uint8_t *input;
34518 	duk_size_t len = 0;
34519 	duk_size_t len_tmp;
34520 	duk_bool_t stream = 0;
34521 	duk_codepoint_t codepoint;
34522 	duk_uint8_t *output;
34523 	const duk_uint8_t *in;
34524 	duk_uint8_t *out;
34525 
34526 	DUK_ASSERT(dec_ctx != NULL);
34527 
34528 	/* Careful with input buffer pointer: any side effects involving
34529 	 * code execution (e.g. getters, coercion calls, and finalizers)
34530 	 * may cause a resize and invalidate a pointer we've read.  This
34531 	 * is why the pointer is actually looked up at the last minute.
34532 	 * Argument validation must still happen first to match WHATWG
34533 	 * required side effect order.
34534 	 */
34535 
34536 	if (duk_is_undefined(thr, 0)) {
34537 		duk_push_fixed_buffer_nozero(thr, 0);
34538 		duk_replace(thr, 0);
34539 	}
34540 	(void) duk_require_buffer_data(thr, 0, &len);  /* Need 'len', avoid pointer. */
34541 
34542 	if (duk_check_type_mask(thr, 1, DUK_TYPE_MASK_UNDEFINED |
34543 	                                DUK_TYPE_MASK_NULL |
34544 	                                DUK_TYPE_MASK_NONE)) {
34545 		/* Use defaults, treat missing value like undefined. */
34546 	} else {
34547 		duk_require_type_mask(thr, 1, DUK_TYPE_MASK_UNDEFINED |
34548 	                                      DUK_TYPE_MASK_NULL |
34549 	                                      DUK_TYPE_MASK_LIGHTFUNC |
34550 	                                      DUK_TYPE_MASK_BUFFER |
34551 		                              DUK_TYPE_MASK_OBJECT);
34552 		if (duk_get_prop_literal(thr, 1, "stream")) {
34553 			stream = duk_to_boolean(thr, -1);
34554 		}
34555 	}
34556 
34557 	/* Allowance is 3*len in the general case because all bytes may potentially
34558 	 * become U+FFFD.  If the first byte completes a non-BMP codepoint it will
34559 	 * decode to a CESU-8 surrogate pair (6 bytes) so we allow 3 extra bytes to
34560 	 * compensate: (1*3)+3 = 6.  Non-BMP codepoints are safe otherwise because
34561 	 * the 4->6 expansion is well under the 3x allowance.
34562 	 *
34563 	 * XXX: As with TextEncoder, need a better buffer allocation strategy here.
34564 	 */
34565 	if (len >= (DUK_HBUFFER_MAX_BYTELEN / 3) - 3) {
34566 		DUK_ERROR_TYPE(thr, DUK_STR_RESULT_TOO_LONG);
34567 		DUK_WO_NORETURN(return 0;);
34568 	}
34569 	output = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, 3 + (3 * len));  /* used parts will be always manually written over */
34570 
34571 	input = (const duk_uint8_t *) duk_get_buffer_data(thr, 0, &len_tmp);
34572 	DUK_ASSERT(input != NULL || len == 0);
34573 	if (DUK_UNLIKELY(len != len_tmp)) {
34574 		/* Very unlikely but possible: source buffer was resized by
34575 		 * a side effect when fixed buffer was pushed.  Output buffer
34576 		 * may not be large enough to hold output, so just fail if
34577 		 * length has changed.
34578 		 */
34579 		DUK_D(DUK_DPRINT("input buffer resized by side effect, fail"));
34580 		goto fail_type;
34581 	}
34582 
34583 	/* From this point onwards it's critical that no side effect occur
34584 	 * which may disturb 'input': finalizer execution, property accesses,
34585 	 * active coercions, etc.  Even an allocation related mark-and-sweep
34586 	 * may affect the pointer because it may trigger a pending finalizer.
34587 	 */
34588 
34589 	in = input;
34590 	out = output;
34591 	while (in < input + len) {
34592 		codepoint = duk__utf8_decode_next(dec_ctx, *in++);
34593 		if (codepoint < 0) {
34594 			if (codepoint == DUK__CP_CONTINUE) {
34595 				continue;
34596 			}
34597 
34598 			/* Decoding error with or without retry. */
34599 			DUK_ASSERT(codepoint == DUK__CP_ERROR || codepoint == DUK__CP_RETRY);
34600 			if (codepoint == DUK__CP_RETRY) {
34601 				--in;  /* retry last byte */
34602 			}
34603 			/* replacement mode: replace with U+FFFD */
34604 			codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
34605 			if (dec_ctx->fatal) {
34606 				/* fatal mode: throw a TypeError */
34607 				goto fail_type;
34608 			}
34609 			/* Continue with 'codepoint', Unicode replacement. */
34610 		}
34611 		DUK_ASSERT(codepoint >= 0x0000L && codepoint <= 0x10ffffL);
34612 
34613 		if (!dec_ctx->bom_handled) {
34614 			dec_ctx->bom_handled = 1;
34615 			if (codepoint == 0xfeffL && !dec_ctx->ignore_bom) {
34616 				continue;
34617 			}
34618 		}
34619 
34620 		out += duk_unicode_encode_cesu8((duk_ucodepoint_t) codepoint, out);
34621 		DUK_ASSERT(out <= output + (3 + (3 * len)));
34622 	}
34623 
34624 	if (!stream) {
34625 		if (dec_ctx->needed != 0) {
34626 			/* truncated sequence at end of buffer */
34627 			if (dec_ctx->fatal) {
34628 				goto fail_type;
34629 			} else {
34630 				out += duk_unicode_encode_cesu8(DUK_UNICODE_CP_REPLACEMENT_CHARACTER, out);
34631 				DUK_ASSERT(out <= output + (3 + (3 * len)));
34632 			}
34633 		}
34634 		duk__utf8_decode_init(dec_ctx);  /* Initialize decoding state for potential reuse. */
34635 	}
34636 
34637 	/* Output buffer is fixed and thus stable even if there had been
34638 	 * side effects (which there shouldn't be).
34639 	 */
34640 	duk_push_lstring(thr, (const char *) output, (duk_size_t) (out - output));
34641 	return 1;
34642 
34643  fail_type:
34644 	DUK_ERROR_TYPE(thr, DUK_STR_UTF8_DECODE_FAILED);
34645 	DUK_WO_NORETURN(return 0;);
34646 }
34647 
34648 /*
34649  *  Built-in bindings
34650  */
34651 
34652 #if defined(DUK_USE_ENCODING_BUILTINS)
duk_bi_textencoder_constructor(duk_hthread * thr)34653 DUK_INTERNAL duk_ret_t duk_bi_textencoder_constructor(duk_hthread *thr) {
34654 	/* TextEncoder currently requires no persistent state, so the constructor
34655 	 * does nothing on purpose.
34656 	 */
34657 
34658 	duk_require_constructor_call(thr);
34659 	return 0;
34660 }
34661 
duk_bi_textencoder_prototype_encoding_getter(duk_hthread * thr)34662 DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_hthread *thr) {
34663 	duk_push_literal(thr, "utf-8");
34664 	return 1;
34665 }
34666 
duk_bi_textencoder_prototype_encode(duk_hthread * thr)34667 DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encode(duk_hthread *thr) {
34668 	duk__encode_context enc_ctx;
34669 	duk_size_t len;
34670 	duk_size_t final_len;
34671 	duk_uint8_t *output;
34672 
34673 	DUK_ASSERT_TOP(thr, 1);
34674 	if (duk_is_undefined(thr, 0)) {
34675 		len = 0;
34676 	} else {
34677 		duk_hstring *h_input;
34678 
34679 		h_input = duk_to_hstring(thr, 0);
34680 		DUK_ASSERT(h_input != NULL);
34681 
34682 		len = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_input);
34683 		if (len >= DUK_HBUFFER_MAX_BYTELEN / 3) {
34684 			DUK_ERROR_TYPE(thr, DUK_STR_RESULT_TOO_LONG);
34685 			DUK_WO_NORETURN(return 0;);
34686 		}
34687 	}
34688 
34689 	/* Allowance is 3*len because all bytes can potentially be replaced with
34690 	 * U+FFFD -- which rather inconveniently encodes to 3 bytes in UTF-8.
34691 	 * Rely on dynamic buffer data pointer stability: no other code has
34692 	 * access to the data pointer.
34693 	 *
34694 	 * XXX: The buffer allocation strategy used here is rather inefficient.
34695 	 * Maybe switch to a chunk-based strategy, or preprocess the string to
34696 	 * figure out the space needed ahead of time?
34697 	 */
34698 	DUK_ASSERT(3 * len >= len);
34699 	output = (duk_uint8_t *) duk_push_dynamic_buffer(thr, 3 * len);
34700 
34701 	if (len > 0) {
34702 		DUK_ASSERT(duk_is_string(thr, 0));  /* True if len > 0. */
34703 
34704 		/* XXX: duk_decode_string() is used to process the input
34705 		 * string.  For standard ECMAScript strings, represented
34706 		 * internally as CESU-8, this is fine.  However, behavior
34707 		 * beyond CESU-8 is not very strict: codepoints using an
34708 		 * extended form of UTF-8 are also accepted, and invalid
34709 		 * codepoint sequences (which are allowed in Duktape strings)
34710 		 * are not handled as well as they could (e.g. invalid
34711 		 * continuation bytes may mask following codepoints).
34712 		 * This is how ECMAScript code would also see such strings.
34713 		 * Maybe replace duk_decode_string() with an explicit strict
34714 		 * CESU-8 decoder here?
34715 		 */
34716 		enc_ctx.lead = 0x0000L;
34717 		enc_ctx.out = output;
34718 		duk_decode_string(thr, 0, duk__utf8_encode_char, (void *) &enc_ctx);
34719 		if (enc_ctx.lead != 0x0000L) {
34720 			/* unpaired high surrogate at end of string */
34721 			enc_ctx.out = duk__utf8_emit_repl(enc_ctx.out);
34722 			DUK_ASSERT(enc_ctx.out <= output + (3 * len));
34723 		}
34724 
34725 		/* The output buffer is usually very much oversized, so shrink it to
34726 		 * actually needed size.  Pointer stability assumed up to this point.
34727 		 */
34728 		DUK_ASSERT_TOP(thr, 2);
34729 		DUK_ASSERT(output == (duk_uint8_t *) duk_get_buffer_data(thr, -1, NULL));
34730 
34731 		final_len = (duk_size_t) (enc_ctx.out - output);
34732 		duk_resize_buffer(thr, -1, final_len);
34733 		/* 'output' and 'enc_ctx.out' are potentially invalidated by the resize. */
34734 	} else {
34735 		final_len = 0;
34736 	}
34737 
34738 	/* Standard WHATWG output is a Uint8Array.  Here the Uint8Array will
34739 	 * be backed by a dynamic buffer which differs from e.g. Uint8Arrays
34740 	 * created as 'new Uint8Array(N)'.  ECMAScript code won't see the
34741 	 * difference but C code will.  When bufferobjects are not supported,
34742 	 * returns a plain dynamic buffer.
34743 	 */
34744 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
34745 	duk_push_buffer_object(thr, -1, 0, final_len, DUK_BUFOBJ_UINT8ARRAY);
34746 #endif
34747 	return 1;
34748 }
34749 
duk_bi_textdecoder_constructor(duk_hthread * thr)34750 DUK_INTERNAL duk_ret_t duk_bi_textdecoder_constructor(duk_hthread *thr) {
34751 	duk__decode_context *dec_ctx;
34752 	duk_bool_t fatal = 0;
34753 	duk_bool_t ignore_bom = 0;
34754 
34755 	DUK_ASSERT_TOP(thr, 2);
34756 	duk_require_constructor_call(thr);
34757 	if (!duk_is_undefined(thr, 0)) {
34758 		/* XXX: For now ignore 'label' (encoding identifier). */
34759 		duk_to_string(thr, 0);
34760 	}
34761 	if (!duk_is_null_or_undefined(thr, 1)) {
34762 		if (duk_get_prop_literal(thr, 1, "fatal")) {
34763 			fatal = duk_to_boolean(thr, -1);
34764 		}
34765 		if (duk_get_prop_literal(thr, 1, "ignoreBOM")) {
34766 			ignore_bom = duk_to_boolean(thr, -1);
34767 		}
34768 	}
34769 
34770 	duk_push_this(thr);
34771 
34772 	/* The decode context is not assumed to be zeroed; all fields are
34773 	 * initialized explicitly.
34774 	 */
34775 	dec_ctx = (duk__decode_context *) duk_push_fixed_buffer(thr, sizeof(duk__decode_context));
34776 	dec_ctx->fatal = (duk_uint8_t) fatal;
34777 	dec_ctx->ignore_bom = (duk_uint8_t) ignore_bom;
34778 	duk__utf8_decode_init(dec_ctx);  /* Initializes remaining fields. */
34779 
34780 	duk_put_prop_literal(thr, -2, DUK_INTERNAL_SYMBOL("Context"));
34781 	return 0;
34782 }
34783 
34784 /* Get TextDecoder context from 'this'; leaves garbage on stack. */
duk__get_textdecoder_context(duk_hthread * thr)34785 DUK_LOCAL duk__decode_context *duk__get_textdecoder_context(duk_hthread *thr) {
34786 	duk__decode_context *dec_ctx;
34787 	duk_push_this(thr);
34788 	duk_get_prop_literal(thr, -1, DUK_INTERNAL_SYMBOL("Context"));
34789 	dec_ctx = (duk__decode_context *) duk_require_buffer(thr, -1, NULL);
34790 	DUK_ASSERT(dec_ctx != NULL);
34791 	return dec_ctx;
34792 }
34793 
duk_bi_textdecoder_prototype_shared_getter(duk_hthread * thr)34794 DUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_hthread *thr) {
34795 	duk__decode_context *dec_ctx;
34796 	duk_int_t magic;
34797 
34798 	dec_ctx = duk__get_textdecoder_context(thr);
34799 	magic = duk_get_current_magic(thr);
34800 	switch (magic) {
34801 	case 0:
34802 		/* Encoding is now fixed, so _Context lookup is only needed to
34803 		 * validate the 'this' binding (TypeError if not TextDecoder-like).
34804 		 */
34805 		duk_push_literal(thr, "utf-8");
34806 		break;
34807 	case 1:
34808 		duk_push_boolean(thr, dec_ctx->fatal);
34809 		break;
34810 	default:
34811 		duk_push_boolean(thr, dec_ctx->ignore_bom);
34812 		break;
34813 	}
34814 
34815 	return 1;
34816 }
34817 
duk_bi_textdecoder_prototype_decode(duk_hthread * thr)34818 DUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_hthread *thr) {
34819 	duk__decode_context *dec_ctx;
34820 
34821 	dec_ctx = duk__get_textdecoder_context(thr);
34822 	return duk__decode_helper(thr, dec_ctx);
34823 }
34824 #endif  /* DUK_USE_ENCODING_BUILTINS */
34825 
34826 /*
34827  *  Internal helper for Node.js Buffer
34828  */
34829 
34830 /* Internal helper used for Node.js Buffer .toString().  Value stack convention
34831  * is currently odd: it mimics TextDecoder .decode() so that argument must be at
34832  * index 0, and decode options (not present for Buffer) at index 1.  Return value
34833  * is a Duktape/C function return value.
34834  */
duk_textdecoder_decode_utf8_nodejs(duk_hthread * thr)34835 DUK_INTERNAL duk_ret_t duk_textdecoder_decode_utf8_nodejs(duk_hthread *thr) {
34836 	duk__decode_context dec_ctx;
34837 
34838 	dec_ctx.fatal = 0;  /* use replacement chars */
34839 	dec_ctx.ignore_bom = 1;  /* ignore BOMs (matches Node.js Buffer .toString()) */
34840 	duk__utf8_decode_init(&dec_ctx);
34841 
34842 	return duk__decode_helper(thr, &dec_ctx);
34843 }
34844 
34845 /* automatic undefs */
34846 #undef DUK__CP_CONTINUE
34847 #undef DUK__CP_ERROR
34848 #undef DUK__CP_RETRY
34849 #line 1 "duk_bi_error.c"
34850 /*
34851  *  Error built-ins
34852  */
34853 
34854 /* #include duk_internal.h -> already included */
34855 
duk_bi_error_constructor_shared(duk_hthread * thr)34856 DUK_INTERNAL duk_ret_t duk_bi_error_constructor_shared(duk_hthread *thr) {
34857 	/* Behavior for constructor and non-constructor call is
34858 	 * the same except for augmenting the created error.  When
34859 	 * called as a constructor, the caller (duk_new()) will handle
34860 	 * augmentation; when called as normal function, we need to do
34861 	 * it here.
34862 	 */
34863 
34864 	duk_small_int_t bidx_prototype = duk_get_current_magic(thr);
34865 
34866 	/* same for both error and each subclass like TypeError */
34867 	duk_uint_t flags_and_class = DUK_HOBJECT_FLAG_EXTENSIBLE |
34868 	                             DUK_HOBJECT_FLAG_FASTREFS |
34869 	                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR);
34870 
34871 	(void) duk_push_object_helper(thr, flags_and_class, bidx_prototype);
34872 
34873 	/* If message is undefined, the own property 'message' is not set at
34874 	 * all to save property space.  An empty message is inherited anyway.
34875 	 */
34876 	if (!duk_is_undefined(thr, 0)) {
34877 		duk_to_string(thr, 0);
34878 		duk_dup_0(thr);  /* [ message error message ] */
34879 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
34880 	}
34881 
34882 	/* Augment the error if called as a normal function.  __FILE__ and __LINE__
34883 	 * are not desirable in this case.
34884 	 */
34885 
34886 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
34887 	if (!duk_is_constructor_call(thr)) {
34888 		duk_err_augment_error_create(thr, thr, NULL, 0, DUK_AUGMENT_FLAG_NOBLAME_FILELINE);
34889 	}
34890 #endif
34891 
34892 	return 1;
34893 }
34894 
duk_bi_error_prototype_to_string(duk_hthread * thr)34895 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_hthread *thr) {
34896 	/* XXX: optimize with more direct internal access */
34897 
34898 	duk_push_this(thr);
34899 	(void) duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
34900 
34901 	/* [ ... this ] */
34902 
34903 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME);
34904 	if (duk_is_undefined(thr, -1)) {
34905 		duk_pop(thr);
34906 		duk_push_literal(thr, "Error");
34907 	} else {
34908 		duk_to_string(thr, -1);
34909 	}
34910 
34911 	/* [ ... this name ] */
34912 
34913 	/* XXX: Are steps 6 and 7 in E5 Section 15.11.4.4 duplicated by
34914 	 * accident or are they actually needed?  The first ToString()
34915 	 * could conceivably return 'undefined'.
34916 	 */
34917 	duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE);
34918 	if (duk_is_undefined(thr, -1)) {
34919 		duk_pop(thr);
34920 		duk_push_hstring_empty(thr);
34921 	} else {
34922 		duk_to_string(thr, -1);
34923 	}
34924 
34925 	/* [ ... this name message ] */
34926 
34927 	if (duk_get_length(thr, -2) == 0) {
34928 		/* name is empty -> return message */
34929 		return 1;
34930 	}
34931 	if (duk_get_length(thr, -1) == 0) {
34932 		/* message is empty -> return name */
34933 		duk_pop(thr);
34934 		return 1;
34935 	}
34936 	duk_push_literal(thr, ": ");
34937 	duk_insert(thr, -2);  /* ... name ': ' message */
34938 	duk_concat(thr, 3);
34939 
34940 	return 1;
34941 }
34942 
34943 #if defined(DUK_USE_TRACEBACKS)
34944 
34945 /*
34946  *  Traceback handling
34947  *
34948  *  The unified helper decodes the traceback and produces various requested
34949  *  outputs.  It should be optimized for size, and may leave garbage on stack,
34950  *  only the topmost return value matters.  For instance, traceback separator
34951  *  and decoded strings are pushed even when looking for filename only.
34952  *
34953  *  NOTE: although _Tracedata is an internal property, user code can currently
34954  *  write to the array (or replace it with something other than an array).
34955  *  The code below must tolerate arbitrary _Tracedata.  It can throw errors
34956  *  etc, but cannot cause a segfault or memory unsafe behavior.
34957  */
34958 
34959 /* constants arbitrary, chosen for small loads */
34960 #define DUK__OUTPUT_TYPE_TRACEBACK   (-1)
34961 #define DUK__OUTPUT_TYPE_FILENAME    0
34962 #define DUK__OUTPUT_TYPE_LINENUMBER  1
34963 
duk__error_getter_helper(duk_hthread * thr,duk_small_int_t output_type)34964 DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_hthread *thr, duk_small_int_t output_type) {
34965 	duk_idx_t idx_td;
34966 	duk_small_int_t i;  /* traceback depth fits into 16 bits */
34967 	duk_small_int_t t;  /* stack type fits into 16 bits */
34968 	duk_small_int_t count_func = 0;  /* traceback depth ensures fits into 16 bits */
34969 	const char *str_tailcall = " tailcall";
34970 	const char *str_strict = " strict";
34971 	const char *str_construct = " construct";
34972 	const char *str_prevyield = " preventsyield";
34973 	const char *str_directeval = " directeval";
34974 	const char *str_empty = "";
34975 
34976 	DUK_ASSERT_TOP(thr, 0);  /* fixed arg count */
34977 
34978 	duk_push_this(thr);
34979 	duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_TRACEDATA);
34980 	idx_td = duk_get_top_index(thr);
34981 
34982 	duk_push_hstring_stridx(thr, DUK_STRIDX_NEWLINE_4SPACE);
34983 	duk_push_this(thr);
34984 
34985 	/* [ ... this tracedata sep this ] */
34986 
34987 	/* XXX: skip null filename? */
34988 
34989 	if (duk_check_type(thr, idx_td, DUK_TYPE_OBJECT)) {
34990 		/* Current tracedata contains 2 entries per callstack entry. */
34991 		for (i = 0; ; i += 2) {
34992 			duk_int_t pc;
34993 			duk_uint_t line;
34994 			duk_uint_t flags;
34995 			duk_double_t d;
34996 			const char *funcname;
34997 			const char *filename;
34998 			duk_hobject *h_func;
34999 			duk_hstring *h_name;
35000 
35001 			duk_require_stack(thr, 5);
35002 			duk_get_prop_index(thr, idx_td, (duk_uarridx_t) i);
35003 			duk_get_prop_index(thr, idx_td, (duk_uarridx_t) (i + 1));
35004 			d = duk_to_number_m1(thr);
35005 			pc = duk_double_to_int_t(DUK_FMOD(d, DUK_DOUBLE_2TO32));
35006 			flags = duk_double_to_uint_t(DUK_FLOOR(d / DUK_DOUBLE_2TO32));
35007 			t = (duk_small_int_t) duk_get_type(thr, -2);
35008 
35009 			if (t == DUK_TYPE_OBJECT || t == DUK_TYPE_LIGHTFUNC) {
35010 				/*
35011 				 *  ECMAScript/native function call or lightfunc call
35012 				 */
35013 
35014 				count_func++;
35015 
35016 				/* [ ... v1(func) v2(pc+flags) ] */
35017 
35018 				/* These may be systematically omitted by Duktape
35019 				 * with certain config options, but allow user to
35020 				 * set them on a case-by-case basis.
35021 				 */
35022 				duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);
35023 				duk_get_prop_stridx_short(thr, -3, DUK_STRIDX_FILE_NAME);
35024 
35025 #if defined(DUK_USE_PC2LINE)
35026 				line = (duk_uint_t) duk_hobject_pc2line_query(thr, -4, (duk_uint_fast32_t) pc);
35027 #else
35028 				line = 0;
35029 #endif
35030 
35031 				/* [ ... v1 v2 name filename ] */
35032 
35033 				/* When looking for .fileName/.lineNumber, blame first
35034 				 * function which has a .fileName.
35035 				 */
35036 				if (duk_is_string_notsymbol(thr, -1)) {
35037 					if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
35038 						return 1;
35039 					} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
35040 						duk_push_uint(thr, line);
35041 						return 1;
35042 					}
35043 				}
35044 
35045 				/* XXX: Change 'anon' handling here too, to use empty string for anonymous functions? */
35046 				/* XXX: Could be improved by coercing to a readable duk_tval (especially string escaping) */
35047 				h_name = duk_get_hstring_notsymbol(thr, -2);  /* may be NULL */
35048 				funcname = (h_name == NULL || h_name == DUK_HTHREAD_STRING_EMPTY_STRING(thr)) ?
35049 				           "[anon]" : (const char *) DUK_HSTRING_GET_DATA(h_name);
35050 				filename = duk_get_string_notsymbol(thr, -1);
35051 				filename = filename ? filename : "";
35052 				DUK_ASSERT(funcname != NULL);
35053 				DUK_ASSERT(filename != NULL);
35054 
35055 				h_func = duk_get_hobject(thr, -4);  /* NULL for lightfunc */
35056 
35057 				if (h_func == NULL) {
35058 					duk_push_sprintf(thr, "at %s light%s%s%s%s%s",
35059 					                 (const char *) funcname,
35060 					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
35061 					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
35062 					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
35063 					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
35064 					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
35065 				} else if (DUK_HOBJECT_HAS_NATFUNC(h_func)) {
35066 					duk_push_sprintf(thr, "at %s (%s) native%s%s%s%s%s",
35067 					                 (const char *) funcname,
35068 					                 (const char *) filename,
35069 					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
35070 					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
35071 					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
35072 					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
35073 					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
35074 				} else {
35075 					duk_push_sprintf(thr, "at %s (%s:%lu)%s%s%s%s%s",
35076 					                 (const char *) funcname,
35077 					                 (const char *) filename,
35078 					                 (unsigned long) line,
35079 					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
35080 					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
35081 					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
35082 					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
35083 					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
35084 				}
35085 				duk_replace(thr, -5);   /* [ ... v1 v2 name filename str ] -> [ ... str v2 name filename ] */
35086 				duk_pop_3(thr);         /* -> [ ... str ] */
35087 			} else if (t == DUK_TYPE_STRING) {
35088 				const char *str_file;
35089 
35090 				/*
35091 				 *  __FILE__ / __LINE__ entry, here 'pc' is line number directly.
35092 				 *  Sometimes __FILE__ / __LINE__ is reported as the source for
35093 				 *  the error (fileName, lineNumber), sometimes not.
35094 				 */
35095 
35096 				/* [ ... v1(filename) v2(line+flags) ] */
35097 
35098 				/* When looking for .fileName/.lineNumber, blame compilation
35099 				 * or C call site unless flagged not to do so.
35100 				 */
35101 				if (!(flags & DUK_TB_FLAG_NOBLAME_FILELINE)) {
35102 					if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
35103 						duk_pop(thr);
35104 						return 1;
35105 					} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
35106 						duk_push_int(thr, pc);
35107 						return 1;
35108 					}
35109 				}
35110 
35111 				/* Tracedata is trusted but avoid any risk of using a NULL
35112 				 * for %s format because it has undefined behavior.  Symbols
35113 				 * don't need to be explicitly rejected as they pose no memory
35114 				 * safety issues.
35115 				 */
35116 				str_file = (const char *) duk_get_string(thr, -2);
35117 				duk_push_sprintf(thr, "at [anon] (%s:%ld) internal",
35118 				                 (const char *) (str_file ? str_file : "null"), (long) pc);
35119 				duk_replace(thr, -3);  /* [ ... v1 v2 str ] -> [ ... str v2 ] */
35120 				duk_pop(thr);          /* -> [ ... str ] */
35121 			} else {
35122 				/* unknown, ignore */
35123 				duk_pop_2(thr);
35124 				break;
35125 			}
35126 		}
35127 
35128 		if (count_func >= DUK_USE_TRACEBACK_DEPTH) {
35129 			/* Possibly truncated; there is no explicit truncation
35130 			 * marker so this is the best we can do.
35131 			 */
35132 
35133 			duk_push_hstring_stridx(thr, DUK_STRIDX_BRACKETED_ELLIPSIS);
35134 		}
35135 	}
35136 
35137 	/* [ ... this tracedata sep this str1 ... strN ] */
35138 
35139 	if (output_type != DUK__OUTPUT_TYPE_TRACEBACK) {
35140 		return 0;
35141 	} else {
35142 		/* The 'this' after 'sep' will get ToString() coerced by
35143 		 * duk_join() automatically.  We don't want to do that
35144 		 * coercion when providing .fileName or .lineNumber (GH-254).
35145 		 */
35146 		duk_join(thr, duk_get_top(thr) - (idx_td + 2) /*count, not including sep*/);
35147 		return 1;
35148 	}
35149 }
35150 
35151 /* XXX: Output type could be encoded into native function 'magic' value to
35152  * save space.  For setters the stridx could be encoded into 'magic'.
35153  */
35154 
duk_bi_error_prototype_stack_getter(duk_hthread * thr)35155 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_hthread *thr) {
35156 	return duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_TRACEBACK);
35157 }
35158 
duk_bi_error_prototype_filename_getter(duk_hthread * thr)35159 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_hthread *thr) {
35160 	return duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_FILENAME);
35161 }
35162 
duk_bi_error_prototype_linenumber_getter(duk_hthread * thr)35163 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_hthread *thr) {
35164 	return duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_LINENUMBER);
35165 }
35166 
35167 #else  /* DUK_USE_TRACEBACKS */
35168 
35169 /*
35170  *  Traceback handling when tracebacks disabled.
35171  *
35172  *  The fileName / lineNumber stubs are now necessary because built-in
35173  *  data will include the accessor properties in Error.prototype.  If those
35174  *  are removed for builds without tracebacks, these can also be removed.
35175  *  'stack' should still be present and produce a ToString() equivalent:
35176  *  this is useful for user code which prints a stacktrace and expects to
35177  *  see something useful.  A normal stacktrace also begins with a ToString()
35178  *  of the error so this makes sense.
35179  */
35180 
duk_bi_error_prototype_stack_getter(duk_hthread * thr)35181 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_hthread *thr) {
35182 	/* XXX: remove this native function and map 'stack' accessor
35183 	 * to the toString() implementation directly.
35184 	 */
35185 	return duk_bi_error_prototype_to_string(thr);
35186 }
35187 
duk_bi_error_prototype_filename_getter(duk_hthread * thr)35188 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_hthread *thr) {
35189 	DUK_UNREF(thr);
35190 	return 0;
35191 }
35192 
duk_bi_error_prototype_linenumber_getter(duk_hthread * thr)35193 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_hthread *thr) {
35194 	DUK_UNREF(thr);
35195 	return 0;
35196 }
35197 
35198 #endif  /* DUK_USE_TRACEBACKS */
35199 
duk__error_setter_helper(duk_hthread * thr,duk_small_uint_t stridx_key)35200 DUK_LOCAL duk_ret_t duk__error_setter_helper(duk_hthread *thr, duk_small_uint_t stridx_key) {
35201 	/* Attempt to write 'stack', 'fileName', 'lineNumber' works as if
35202 	 * user code called Object.defineProperty() to create an overriding
35203 	 * own property.  This allows user code to overwrite .fileName etc
35204 	 * intuitively as e.g. "err.fileName = 'dummy'" as one might expect.
35205 	 * See https://github.com/svaarala/duktape/issues/387.
35206 	 */
35207 
35208 	DUK_ASSERT_TOP(thr, 1);  /* fixed arg count: value */
35209 
35210 	duk_push_this(thr);
35211 	duk_push_hstring_stridx(thr, stridx_key);
35212 	duk_dup_0(thr);
35213 
35214 	/* [ ... obj key value ] */
35215 
35216 	DUK_DD(DUK_DDPRINT("error setter: %!T %!T %!T",
35217 	                   duk_get_tval(thr, -3), duk_get_tval(thr, -2), duk_get_tval(thr, -1)));
35218 
35219 	duk_def_prop(thr, -3, DUK_DEFPROP_HAVE_VALUE |
35220 	                      DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE |
35221 	                      DUK_DEFPROP_HAVE_ENUMERABLE | /*not enumerable*/
35222 	                      DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE);
35223 	return 0;
35224 }
35225 
duk_bi_error_prototype_stack_setter(duk_hthread * thr)35226 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_setter(duk_hthread *thr) {
35227 	return duk__error_setter_helper(thr, DUK_STRIDX_STACK);
35228 }
35229 
duk_bi_error_prototype_filename_setter(duk_hthread * thr)35230 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_setter(duk_hthread *thr) {
35231 	return duk__error_setter_helper(thr, DUK_STRIDX_FILE_NAME);
35232 }
35233 
duk_bi_error_prototype_linenumber_setter(duk_hthread * thr)35234 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_hthread *thr) {
35235 	return duk__error_setter_helper(thr, DUK_STRIDX_LINE_NUMBER);
35236 }
35237 
35238 /* automatic undefs */
35239 #undef DUK__OUTPUT_TYPE_FILENAME
35240 #undef DUK__OUTPUT_TYPE_LINENUMBER
35241 #undef DUK__OUTPUT_TYPE_TRACEBACK
35242 #line 1 "duk_bi_function.c"
35243 /*
35244  *  Function built-ins
35245  */
35246 
35247 /* #include duk_internal.h -> already included */
35248 
35249 /* Needed even when Function built-in is disabled. */
duk_bi_function_prototype(duk_hthread * thr)35250 DUK_INTERNAL duk_ret_t duk_bi_function_prototype(duk_hthread *thr) {
35251 	/* ignore arguments, return undefined (E5 Section 15.3.4) */
35252 	DUK_UNREF(thr);
35253 	return 0;
35254 }
35255 
35256 #if defined(DUK_USE_FUNCTION_BUILTIN)
duk_bi_function_constructor(duk_hthread * thr)35257 DUK_INTERNAL duk_ret_t duk_bi_function_constructor(duk_hthread *thr) {
35258 	duk_hstring *h_sourcecode;
35259 	duk_idx_t nargs;
35260 	duk_idx_t i;
35261 	duk_small_uint_t comp_flags;
35262 	duk_hcompfunc *func;
35263 	duk_hobject *outer_lex_env;
35264 	duk_hobject *outer_var_env;
35265 
35266 	/* normal and constructor calls have identical semantics */
35267 
35268 	nargs = duk_get_top(thr);
35269 	for (i = 0; i < nargs; i++) {
35270 		duk_to_string(thr, i);  /* Rejects Symbols during coercion. */
35271 	}
35272 
35273 	if (nargs == 0) {
35274 		duk_push_hstring_empty(thr);
35275 		duk_push_hstring_empty(thr);
35276 	} else if (nargs == 1) {
35277 		/* XXX: cover this with the generic >1 case? */
35278 		duk_push_hstring_empty(thr);
35279 	} else {
35280 		duk_insert(thr, 0);   /* [ arg1 ... argN-1 body] -> [body arg1 ... argN-1] */
35281 		duk_push_literal(thr, ",");
35282 		duk_insert(thr, 1);
35283 		duk_join(thr, nargs - 1);
35284 	}
35285 
35286 	/* [ body formals ], formals is comma separated list that needs to be parsed */
35287 
35288 	DUK_ASSERT_TOP(thr, 2);
35289 
35290 	/* XXX: this placeholder is not always correct, but use for now.
35291 	 * It will fail in corner cases; see test-dev-func-cons-args.js.
35292 	 */
35293 	duk_push_literal(thr, "function(");
35294 	duk_dup_1(thr);
35295 	duk_push_literal(thr, "){");
35296 	duk_dup_0(thr);
35297 	duk_push_literal(thr, "\n}");  /* Newline is important to handle trailing // comment. */
35298 	duk_concat(thr, 5);
35299 
35300 	/* [ body formals source ] */
35301 
35302 	DUK_ASSERT_TOP(thr, 3);
35303 
35304 	/* strictness is not inherited, intentional */
35305 	comp_flags = DUK_COMPILE_FUNCEXPR;
35306 
35307 	duk_push_hstring_stridx(thr, DUK_STRIDX_COMPILE);  /* XXX: copy from caller? */  /* XXX: ignored now */
35308 	h_sourcecode = duk_require_hstring(thr, -2);  /* no symbol check needed; -2 is concat'd code */
35309 	duk_js_compile(thr,
35310 	               (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode),
35311 	               (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode),
35312 	               comp_flags);
35313 
35314 	/* Force .name to 'anonymous' (ES2015). */
35315 	duk_push_literal(thr, "anonymous");
35316 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
35317 
35318 	func = (duk_hcompfunc *) duk_known_hobject(thr, -1);
35319 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) func));
35320 	DUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) func));
35321 
35322 	/* [ body formals source template ] */
35323 
35324 	/* only outer_lex_env matters, as functions always get a new
35325 	 * variable declaration environment.
35326 	 */
35327 
35328 	outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
35329 	outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
35330 
35331 	duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 1 /*add_auto_proto*/);
35332 
35333 	/* [ body formals source template closure ] */
35334 
35335 	return 1;
35336 }
35337 #endif  /* DUK_USE_FUNCTION_BUILTIN */
35338 
35339 #if defined(DUK_USE_FUNCTION_BUILTIN)
duk_bi_function_prototype_to_string(duk_hthread * thr)35340 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_to_string(duk_hthread *thr) {
35341 	duk_tval *tv;
35342 
35343 	/*
35344 	 *  E5 Section 15.3.4.2 places few requirements on the output of
35345 	 *  this function: the result is implementation dependent, must
35346 	 *  follow FunctionDeclaration syntax (in particular, must have a
35347 	 *  name even for anonymous functions or functions with empty name).
35348 	 *  The output does NOT need to compile into anything useful.
35349 	 *
35350 	 *  E6 Section 19.2.3.5 changes the requirements completely: the
35351 	 *  result must either eval() to a functionally equivalent object
35352 	 *  OR eval() to a SyntaxError.
35353 	 *
35354 	 *  We opt for the SyntaxError approach for now, with a syntax that
35355 	 *  mimics V8's native function syntax:
35356 	 *
35357 	 *      'function cos() { [native code] }'
35358 	 *
35359 	 *  but extended with [ecmascript code], [bound code], and
35360 	 *  [lightfunc code].
35361 	 */
35362 
35363 	duk_push_this(thr);
35364 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
35365 	DUK_ASSERT(tv != NULL);
35366 
35367 	if (DUK_TVAL_IS_OBJECT(tv)) {
35368 		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv);
35369 		const char *func_name;
35370 
35371 		/* Function name: missing/undefined is mapped to empty string,
35372 		 * otherwise coerce to string.  No handling for invalid identifier
35373 		 * characters or e.g. '{' in the function name.  This doesn't
35374 		 * really matter as long as a SyntaxError results.  Technically
35375 		 * if the name contained a suitable prefix followed by '//' it
35376 		 * might cause the result to parse without error.
35377 		 */
35378 		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME);
35379 		if (duk_is_undefined(thr, -1)) {
35380 			func_name = "";
35381 		} else {
35382 			func_name = duk_to_string(thr, -1);
35383 			DUK_ASSERT(func_name != NULL);
35384 		}
35385 
35386 		if (DUK_HOBJECT_IS_COMPFUNC(obj)) {
35387 			duk_push_sprintf(thr, "function %s() { [ecmascript code] }", (const char *) func_name);
35388 		} else if (DUK_HOBJECT_IS_NATFUNC(obj)) {
35389 			duk_push_sprintf(thr, "function %s() { [native code] }", (const char *) func_name);
35390 		} else if (DUK_HOBJECT_IS_BOUNDFUNC(obj)) {
35391 			duk_push_sprintf(thr, "function %s() { [bound code] }", (const char *) func_name);
35392 		} else {
35393 			goto type_error;
35394 		}
35395 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
35396 		duk_push_lightfunc_tostring(thr, tv);
35397 	} else {
35398 		goto type_error;
35399 	}
35400 
35401 	return 1;
35402 
35403  type_error:
35404 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
35405 }
35406 #endif
35407 
35408 /* Always present because the native function pointer is needed in call
35409  * handling.
35410  */
duk_bi_function_prototype_call(duk_hthread * thr)35411 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_call(duk_hthread *thr) {
35412 	/* .call() is dealt with in call handling by simulating its
35413 	 * effects so this function is actually never called.
35414 	 */
35415 	DUK_UNREF(thr);
35416 	return DUK_RET_TYPE_ERROR;
35417 }
35418 
duk_bi_function_prototype_apply(duk_hthread * thr)35419 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_apply(duk_hthread *thr) {
35420 	/* Like .call(), never actually called. */
35421 	DUK_UNREF(thr);
35422 	return DUK_RET_TYPE_ERROR;
35423 }
35424 
duk_bi_reflect_apply(duk_hthread * thr)35425 DUK_INTERNAL duk_ret_t duk_bi_reflect_apply(duk_hthread *thr) {
35426 	/* Like .call(), never actually called. */
35427 	DUK_UNREF(thr);
35428 	return DUK_RET_TYPE_ERROR;
35429 }
35430 
duk_bi_reflect_construct(duk_hthread * thr)35431 DUK_INTERNAL duk_ret_t duk_bi_reflect_construct(duk_hthread *thr) {
35432 	/* Like .call(), never actually called. */
35433 	DUK_UNREF(thr);
35434 	return DUK_RET_TYPE_ERROR;
35435 }
35436 
35437 #if defined(DUK_USE_FUNCTION_BUILTIN)
35438 /* Create a bound function which points to a target function which may
35439  * be bound or non-bound.  If the target is bound, the argument lists
35440  * and 'this' binding of the functions are merged and the resulting
35441  * function points directly to the non-bound target.
35442  */
duk_bi_function_prototype_bind(duk_hthread * thr)35443 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_hthread *thr) {
35444 	duk_hboundfunc *h_bound;
35445 	duk_idx_t nargs;  /* bound args, not counting 'this' binding */
35446 	duk_idx_t bound_nargs;
35447 	duk_int_t bound_len;
35448 	duk_tval *tv_prevbound;
35449 	duk_idx_t n_prevbound;
35450 	duk_tval *tv_res;
35451 	duk_tval *tv_tmp;
35452 
35453 	/* XXX: C API call, e.g. duk_push_bound_function(thr, target_idx, nargs); */
35454 
35455 	/* Vararg function, careful arg handling, e.g. thisArg may not
35456 	 * be present.
35457 	 */
35458 	nargs = duk_get_top(thr) - 1;  /* actual args, not counting 'this' binding */
35459 	if (nargs < 0) {
35460 		nargs++;
35461 		duk_push_undefined(thr);
35462 	}
35463 	DUK_ASSERT(nargs >= 0);
35464 
35465 	/* Limit 'nargs' for bound functions to guarantee arithmetic
35466 	 * below will never wrap.
35467 	 */
35468 	if (nargs > (duk_idx_t) DUK_HBOUNDFUNC_MAX_ARGS) {
35469 		DUK_DCERROR_RANGE_INVALID_COUNT(thr);
35470 	}
35471 
35472 	duk_push_this(thr);
35473 	duk_require_callable(thr, -1);
35474 
35475 	/* [ thisArg arg1 ... argN func ]  (thisArg+args == nargs+1 total) */
35476 	DUK_ASSERT_TOP(thr, nargs + 2);
35477 
35478 	/* Create bound function object. */
35479 	h_bound = duk_push_hboundfunc(thr);
35480 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&h_bound->target));
35481 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&h_bound->this_binding));
35482 	DUK_ASSERT(h_bound->args == NULL);
35483 	DUK_ASSERT(h_bound->nargs == 0);
35484 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_bound) == NULL);
35485 
35486 	/* [ thisArg arg1 ... argN func boundFunc ] */
35487 
35488 	/* If the target is a bound function, argument lists must be
35489 	 * merged.  The 'this' binding closest to the target function
35490 	 * wins because in call handling the 'this' gets replaced over
35491 	 * and over again until we call the non-bound function.
35492 	 */
35493 	tv_prevbound = NULL;
35494 	n_prevbound = 0;
35495 	tv_tmp = DUK_GET_TVAL_POSIDX(thr, 0);
35496 	DUK_TVAL_SET_TVAL(&h_bound->this_binding, tv_tmp);
35497 	tv_tmp = DUK_GET_TVAL_NEGIDX(thr, -2);
35498 	DUK_TVAL_SET_TVAL(&h_bound->target, tv_tmp);
35499 
35500 	if (DUK_TVAL_IS_OBJECT(tv_tmp)) {
35501 		duk_hobject *h_target;
35502 		duk_hobject *bound_proto;
35503 
35504 		h_target = DUK_TVAL_GET_OBJECT(tv_tmp);
35505 		DUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(h_target));
35506 
35507 		/* Internal prototype must be copied from the target.
35508 		 * For lightfuncs Function.prototype is used and is already
35509 		 * in place.
35510 		 */
35511 		bound_proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_target);
35512 		DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) h_bound, bound_proto);
35513 
35514 		/* The 'strict' flag is copied to get the special [[Get]] of E5.1
35515 		 * Section 15.3.5.4 to apply when a 'caller' value is a strict bound
35516 		 * function.  Not sure if this is correct, because the specification
35517 		 * is a bit ambiguous on this point but it would make sense.
35518 		 */
35519 		/* Strictness is inherited from target. */
35520 		if (DUK_HOBJECT_HAS_STRICT(h_target)) {
35521 			DUK_HOBJECT_SET_STRICT((duk_hobject *) h_bound);
35522 		}
35523 
35524 		if (DUK_HOBJECT_HAS_BOUNDFUNC(h_target)) {
35525 			duk_hboundfunc *h_boundtarget;
35526 
35527 			h_boundtarget = (duk_hboundfunc *) (void *) h_target;
35528 
35529 			/* The final function should always be non-bound, unless
35530 			 * there's a bug in the internals.  Assert for it.
35531 			 */
35532 			DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(&h_boundtarget->target) ||
35533 			           (DUK_TVAL_IS_OBJECT(&h_boundtarget->target) &&
35534 			            DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(&h_boundtarget->target)) &&
35535 			            !DUK_HOBJECT_IS_BOUNDFUNC(DUK_TVAL_GET_OBJECT(&h_boundtarget->target))));
35536 
35537 			DUK_TVAL_SET_TVAL(&h_bound->target, &h_boundtarget->target);
35538 			DUK_TVAL_SET_TVAL(&h_bound->this_binding, &h_boundtarget->this_binding);
35539 
35540 			tv_prevbound = h_boundtarget->args;
35541 			n_prevbound = h_boundtarget->nargs;
35542 		}
35543 	} else {
35544 		/* Lightfuncs are always strict. */
35545 		duk_hobject *bound_proto;
35546 
35547 		DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_tmp));
35548 		DUK_HOBJECT_SET_STRICT((duk_hobject *) h_bound);
35549 		bound_proto = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
35550 		DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) h_bound, bound_proto);
35551 	}
35552 
35553 	DUK_TVAL_INCREF(thr, &h_bound->target);  /* old values undefined, no decref needed */
35554 	DUK_TVAL_INCREF(thr, &h_bound->this_binding);
35555 
35556 	bound_nargs = n_prevbound + nargs;
35557 	if (bound_nargs > (duk_idx_t) DUK_HBOUNDFUNC_MAX_ARGS) {
35558 		DUK_DCERROR_RANGE_INVALID_COUNT(thr);
35559 	}
35560 	tv_res = (duk_tval *) DUK_ALLOC_CHECKED(thr, ((duk_size_t) bound_nargs) * sizeof(duk_tval));
35561 	DUK_ASSERT(tv_res != NULL || bound_nargs == 0);
35562 	DUK_ASSERT(h_bound->args == NULL);
35563 	DUK_ASSERT(h_bound->nargs == 0);
35564 	h_bound->args = tv_res;
35565 	h_bound->nargs = bound_nargs;
35566 
35567 	DUK_ASSERT(n_prevbound >= 0);
35568 	duk_copy_tvals_incref(thr, tv_res, tv_prevbound, (duk_size_t) n_prevbound);
35569 	DUK_ASSERT(nargs >= 0);
35570 	duk_copy_tvals_incref(thr, tv_res + n_prevbound, DUK_GET_TVAL_POSIDX(thr, 1), (duk_size_t) nargs);
35571 
35572 	/* [ thisArg arg1 ... argN func boundFunc ] */
35573 
35574 	/* Bound function 'length' property is interesting.
35575 	 * For lightfuncs, simply read the virtual property.
35576 	 */
35577 	duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH);
35578 	bound_len = duk_get_int(thr, -1);  /* ES2015: no coercion */
35579 	if (bound_len < nargs) {
35580 		bound_len = 0;
35581 	} else {
35582 		bound_len -= nargs;
35583 	}
35584 	if (sizeof(duk_int_t) > 4 && bound_len > (duk_int_t) DUK_UINT32_MAX) {
35585 		bound_len = (duk_int_t) DUK_UINT32_MAX;
35586 	}
35587 	duk_pop(thr);
35588 	DUK_ASSERT(bound_len >= 0);
35589 	tv_tmp = thr->valstack_top++;
35590 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_tmp));
35591 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv_tmp));
35592 	DUK_TVAL_SET_U32(tv_tmp, (duk_uint32_t) bound_len);  /* in-place update, fastint */
35593 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);  /* attrs in E6 Section 9.2.4 */
35594 
35595 	/* XXX: could these be virtual? */
35596 	/* Caller and arguments must use the same thrower, [[ThrowTypeError]]. */
35597 	duk_xdef_prop_stridx_thrower(thr, -1, DUK_STRIDX_CALLER);
35598 	duk_xdef_prop_stridx_thrower(thr, -1, DUK_STRIDX_LC_ARGUMENTS);
35599 
35600 	/* Function name and fileName (non-standard). */
35601 	duk_push_literal(thr, "bound ");  /* ES2015 19.2.3.2. */
35602 	duk_get_prop_stridx(thr, -3, DUK_STRIDX_NAME);
35603 	if (!duk_is_string_notsymbol(thr, -1)) {
35604 		/* ES2015 has requirement to check that .name of target is a string
35605 		 * (also must check for Symbol); if not, targetName should be the
35606 		 * empty string.  ES2015 19.2.3.2.
35607 		 */
35608 		duk_pop(thr);
35609 		duk_push_hstring_empty(thr);
35610 	}
35611 	duk_concat(thr, 2);
35612 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
35613 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
35614 	duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME);
35615 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C);
35616 #endif
35617 
35618 	DUK_DDD(DUK_DDDPRINT("created bound function: %!iT", (duk_tval *) duk_get_tval(thr, -1)));
35619 
35620 	return 1;
35621 }
35622 #endif  /* DUK_USE_FUNCTION_BUILTIN */
35623 
35624 /* %NativeFunctionPrototype% .length getter. */
duk_bi_native_function_length(duk_hthread * thr)35625 DUK_INTERNAL duk_ret_t duk_bi_native_function_length(duk_hthread *thr) {
35626 	duk_tval *tv;
35627 	duk_hnatfunc *h;
35628 	duk_int16_t func_nargs;
35629 
35630 	tv = duk_get_borrowed_this_tval(thr);
35631 	DUK_ASSERT(tv != NULL);
35632 
35633 	if (DUK_TVAL_IS_OBJECT(tv)) {
35634 		h = (duk_hnatfunc *) DUK_TVAL_GET_OBJECT(tv);
35635 		DUK_ASSERT(h != NULL);
35636 		if (!DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h)) {
35637 			goto fail_type;
35638 		}
35639 		func_nargs = h->nargs;
35640 		duk_push_int(thr, func_nargs == DUK_HNATFUNC_NARGS_VARARGS ? 0 : func_nargs);
35641 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
35642 		duk_small_uint_t lf_flags;
35643 		duk_small_uint_t lf_len;
35644 
35645 		lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
35646 		lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
35647 		duk_push_uint(thr, lf_len);
35648 	} else {
35649 		goto fail_type;
35650 	}
35651 	return 1;
35652 
35653  fail_type:
35654 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
35655 }
35656 
35657 /* %NativeFunctionPrototype% .name getter. */
duk_bi_native_function_name(duk_hthread * thr)35658 DUK_INTERNAL duk_ret_t duk_bi_native_function_name(duk_hthread *thr) {
35659 	duk_tval *tv;
35660 	duk_hnatfunc *h;
35661 
35662 	tv = duk_get_borrowed_this_tval(thr);
35663 	DUK_ASSERT(tv != NULL);
35664 
35665 	if (DUK_TVAL_IS_OBJECT(tv)) {
35666 		h = (duk_hnatfunc *) DUK_TVAL_GET_OBJECT(tv);
35667 		DUK_ASSERT(h != NULL);
35668 		if (!DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h)) {
35669 			goto fail_type;
35670 		}
35671 #if 0
35672 		duk_push_hnatfunc_name(thr, h);
35673 #endif
35674 		duk_push_hstring_empty(thr);
35675 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
35676 		duk_push_lightfunc_name(thr, tv);
35677 	} else {
35678 		goto fail_type;
35679 	}
35680 	return 1;
35681 
35682  fail_type:
35683 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
35684 }
35685 
35686 #if defined(DUK_USE_SYMBOL_BUILTIN)
duk_bi_function_prototype_hasinstance(duk_hthread * thr)35687 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_hasinstance(duk_hthread *thr) {
35688 	/* This binding: RHS, stack index 0: LHS. */
35689 	duk_bool_t ret;
35690 
35691 	ret = duk_js_instanceof_ordinary(thr, DUK_GET_TVAL_POSIDX(thr, 0), DUK_GET_THIS_TVAL_PTR(thr));
35692 	duk_push_boolean(thr, ret);
35693 	return 1;
35694 }
35695 #endif  /* DUK_USE_SYMBOL_BUILTIN */
35696 #line 1 "duk_bi_global.c"
35697 /*
35698  *  Global object built-ins
35699  */
35700 
35701 /* #include duk_internal.h -> already included */
35702 
35703 /*
35704  *  Encoding/decoding helpers
35705  */
35706 
35707 /* XXX: Could add fast path (for each transform callback) with direct byte
35708  * lookups (no shifting) and no explicit check for x < 0x80 before table
35709  * lookup.
35710  */
35711 
35712 /* Macros for creating and checking bitmasks for character encoding.
35713  * Bit number is a bit counterintuitive, but minimizes code size.
35714  */
35715 #define DUK__MKBITS(a,b,c,d,e,f,g,h)  ((duk_uint8_t) ( \
35716 	((a) << 0) | ((b) << 1) | ((c) << 2) | ((d) << 3) | \
35717 	((e) << 4) | ((f) << 5) | ((g) << 6) | ((h) << 7) \
35718 	))
35719 #define DUK__CHECK_BITMASK(table,cp)  ((table)[(cp) >> 3] & (1 << ((cp) & 0x07)))
35720 
35721 /* E5.1 Section 15.1.3.3: uriReserved + uriUnescaped + '#' */
35722 DUK_LOCAL const duk_uint8_t duk__encode_uriunescaped_table[16] = {
35723 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
35724 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
35725 	DUK__MKBITS(0, 1, 0, 1, 1, 0, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x20-0x2f */
35726 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 0, 1, 0, 1),  /* 0x30-0x3f */
35727 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
35728 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
35729 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
35730 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0),  /* 0x70-0x7f */
35731 };
35732 
35733 /* E5.1 Section 15.1.3.4: uriUnescaped */
35734 DUK_LOCAL const duk_uint8_t duk__encode_uricomponent_unescaped_table[16] = {
35735 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
35736 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
35737 	DUK__MKBITS(0, 1, 0, 0, 0, 0, 0, 1), DUK__MKBITS(1, 1, 1, 0, 0, 1, 1, 0),  /* 0x20-0x2f */
35738 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
35739 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
35740 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
35741 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
35742 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0),  /* 0x70-0x7f */
35743 };
35744 
35745 /* E5.1 Section 15.1.3.1: uriReserved + '#' */
35746 DUK_LOCAL const duk_uint8_t duk__decode_uri_reserved_table[16] = {
35747 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
35748 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
35749 	DUK__MKBITS(0, 0, 0, 1, 1, 0, 1, 0), DUK__MKBITS(0, 0, 0, 1, 1, 0, 0, 1),  /* 0x20-0x2f */
35750 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 0, 1),  /* 0x30-0x3f */
35751 	DUK__MKBITS(1, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x40-0x4f */
35752 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x50-0x5f */
35753 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x60-0x6f */
35754 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x70-0x7f */
35755 };
35756 
35757 /* E5.1 Section 15.1.3.2: empty */
35758 DUK_LOCAL const duk_uint8_t duk__decode_uri_component_reserved_table[16] = {
35759 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
35760 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
35761 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x20-0x2f */
35762 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
35763 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x40-0x4f */
35764 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x50-0x5f */
35765 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x60-0x6f */
35766 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x70-0x7f */
35767 };
35768 
35769 #if defined(DUK_USE_SECTION_B)
35770 /* E5.1 Section B.2.2, step 7. */
35771 DUK_LOCAL const duk_uint8_t duk__escape_unescaped_table[16] = {
35772 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
35773 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
35774 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 1, 1),  /* 0x20-0x2f */
35775 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
35776 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
35777 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
35778 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
35779 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 0)   /* 0x70-0x7f */
35780 };
35781 #endif  /* DUK_USE_SECTION_B */
35782 
35783 typedef struct {
35784 	duk_hthread *thr;
35785 	duk_hstring *h_str;
35786 	duk_bufwriter_ctx bw;
35787 	const duk_uint8_t *p;
35788 	const duk_uint8_t *p_start;
35789 	const duk_uint8_t *p_end;
35790 } duk__transform_context;
35791 
35792 typedef void (*duk__transform_callback)(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp);
35793 
35794 /* XXX: refactor and share with other code */
duk__decode_hex_escape(const duk_uint8_t * p,duk_small_int_t n)35795 DUK_LOCAL duk_small_int_t duk__decode_hex_escape(const duk_uint8_t *p, duk_small_int_t n) {
35796 	duk_small_int_t ch;
35797 	duk_small_int_t t = 0;
35798 
35799 	while (n > 0) {
35800 		t = t * 16;
35801 		ch = (duk_small_int_t) duk_hex_dectab[*p++];
35802 		if (DUK_LIKELY(ch >= 0)) {
35803 			t += ch;
35804 		} else {
35805 			return -1;
35806 		}
35807 		n--;
35808 	}
35809 	return t;
35810 }
35811 
duk__transform_helper(duk_hthread * thr,duk__transform_callback callback,const void * udata)35812 DUK_LOCAL int duk__transform_helper(duk_hthread *thr, duk__transform_callback callback, const void *udata) {
35813 	duk__transform_context tfm_ctx_alloc;
35814 	duk__transform_context *tfm_ctx = &tfm_ctx_alloc;
35815 	duk_codepoint_t cp;
35816 
35817 	tfm_ctx->thr = thr;
35818 
35819 	tfm_ctx->h_str = duk_to_hstring(thr, 0);
35820 	DUK_ASSERT(tfm_ctx->h_str != NULL);
35821 
35822 	DUK_BW_INIT_PUSHBUF(thr, &tfm_ctx->bw, DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str));  /* initial size guess */
35823 
35824 	tfm_ctx->p_start = DUK_HSTRING_GET_DATA(tfm_ctx->h_str);
35825 	tfm_ctx->p_end = tfm_ctx->p_start + DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str);
35826 	tfm_ctx->p = tfm_ctx->p_start;
35827 
35828 	while (tfm_ctx->p < tfm_ctx->p_end) {
35829 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end);
35830 		callback(tfm_ctx, udata, cp);
35831 	}
35832 
35833 	DUK_BW_COMPACT(thr, &tfm_ctx->bw);
35834 
35835 	(void) duk_buffer_to_string(thr, -1);  /* Safe if transform is safe. */
35836 	return 1;
35837 }
35838 
duk__transform_callback_encode_uri(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)35839 DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
35840 	duk_uint8_t xutf8_buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
35841 	duk_small_int_t len;
35842 	duk_codepoint_t cp1, cp2;
35843 	duk_small_int_t i, t;
35844 	const duk_uint8_t *unescaped_table = (const duk_uint8_t *) udata;
35845 
35846 	/* UTF-8 encoded bytes escaped as %xx%xx%xx... -> 3 * nbytes.
35847 	 * Codepoint range is restricted so this is a slightly too large
35848 	 * but doesn't matter.
35849 	 */
35850 	DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 3 * DUK_UNICODE_MAX_XUTF8_LENGTH);
35851 
35852 	if (cp < 0) {
35853 		goto uri_error;
35854 	} else if ((cp < 0x80L) && DUK__CHECK_BITMASK(unescaped_table, cp)) {
35855 		DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
35856 		return;
35857 	} else if (cp >= 0xdc00L && cp <= 0xdfffL) {
35858 		goto uri_error;
35859 	} else if (cp >= 0xd800L && cp <= 0xdbffL) {
35860 		/* Needs lookahead */
35861 		if (duk_unicode_decode_xutf8(tfm_ctx->thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end, (duk_ucodepoint_t *) &cp2) == 0) {
35862 			goto uri_error;
35863 		}
35864 		if (!(cp2 >= 0xdc00L && cp2 <= 0xdfffL)) {
35865 			goto uri_error;
35866 		}
35867 		cp1 = cp;
35868 		cp = (duk_codepoint_t) (((cp1 - 0xd800L) << 10) + (cp2 - 0xdc00L) + 0x10000L);
35869 	} else if (cp > 0x10ffffL) {
35870 		/* Although we can allow non-BMP characters (they'll decode
35871 		 * back into surrogate pairs), we don't allow extended UTF-8
35872 		 * characters; they would encode to URIs which won't decode
35873 		 * back because of strict UTF-8 checks in URI decoding.
35874 		 * (However, we could just as well allow them here.)
35875 		 */
35876 		goto uri_error;
35877 	} else {
35878 		/* Non-BMP characters within valid UTF-8 range: encode as is.
35879 		 * They'll decode back into surrogate pairs if the escaped
35880 		 * output is decoded.
35881 		 */
35882 		;
35883 	}
35884 
35885 	len = duk_unicode_encode_xutf8((duk_ucodepoint_t) cp, xutf8_buf);
35886 	for (i = 0; i < len; i++) {
35887 		t = (duk_small_int_t) xutf8_buf[i];
35888 		DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
35889 		                      &tfm_ctx->bw,
35890 		                      DUK_ASC_PERCENT,
35891 		                      (duk_uint8_t) duk_uc_nybbles[t >> 4],
35892                                       (duk_uint8_t) duk_uc_nybbles[t & 0x0f]);
35893 	}
35894 
35895 	return;
35896 
35897  uri_error:
35898 	DUK_ERROR_URI(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
35899 	DUK_WO_NORETURN(return;);
35900 }
35901 
duk__transform_callback_decode_uri(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)35902 DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
35903 	const duk_uint8_t *reserved_table = (const duk_uint8_t *) udata;
35904 	duk_small_uint_t utf8_blen;
35905 	duk_codepoint_t min_cp;
35906 	duk_small_int_t t;  /* must be signed */
35907 	duk_small_uint_t i;
35908 
35909 	/* Maximum write size: XUTF8 path writes max DUK_UNICODE_MAX_XUTF8_LENGTH,
35910 	 * percent escape path writes max two times CESU-8 encoded BMP length.
35911 	 */
35912 	DUK_BW_ENSURE(tfm_ctx->thr,
35913 	              &tfm_ctx->bw,
35914 	              (DUK_UNICODE_MAX_XUTF8_LENGTH >= 2 * DUK_UNICODE_MAX_CESU8_BMP_LENGTH ?
35915 	              DUK_UNICODE_MAX_XUTF8_LENGTH : DUK_UNICODE_MAX_CESU8_BMP_LENGTH));
35916 
35917 	if (cp == (duk_codepoint_t) '%') {
35918 		const duk_uint8_t *p = tfm_ctx->p;
35919 		duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p);  /* bytes left */
35920 
35921 		DUK_DDD(DUK_DDDPRINT("percent encoding, left=%ld", (long) left));
35922 
35923 		if (left < 2) {
35924 			goto uri_error;
35925 		}
35926 
35927 		t = duk__decode_hex_escape(p, 2);
35928 		DUK_DDD(DUK_DDDPRINT("first byte: %ld", (long) t));
35929 		if (t < 0) {
35930 			goto uri_error;
35931 		}
35932 
35933 		if (t < 0x80) {
35934 			if (DUK__CHECK_BITMASK(reserved_table, t)) {
35935 				/* decode '%xx' to '%xx' if decoded char in reserved set */
35936 				DUK_ASSERT(tfm_ctx->p - 1 >= tfm_ctx->p_start);
35937 				DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
35938 				                      &tfm_ctx->bw,
35939 				                      DUK_ASC_PERCENT,
35940 				                      p[0],
35941 				                      p[1]);
35942 			} else {
35943 				DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) t);
35944 			}
35945 			tfm_ctx->p += 2;
35946 			return;
35947 		}
35948 
35949 		/* Decode UTF-8 codepoint from a sequence of hex escapes.  The
35950 		 * first byte of the sequence has been decoded to 't'.
35951 		 *
35952 		 * Note that UTF-8 validation must be strict according to the
35953 		 * specification: E5.1 Section 15.1.3, decode algorithm step
35954 		 * 4.d.vii.8.  URIError from non-shortest encodings is also
35955 		 * specifically noted in the spec.
35956 		 */
35957 
35958 		DUK_ASSERT(t >= 0x80);
35959 		if (t < 0xc0) {
35960 			/* continuation byte */
35961 			goto uri_error;
35962 		} else if (t < 0xe0) {
35963 			/* 110x xxxx; 2 bytes */
35964 			utf8_blen = 2;
35965 			min_cp = 0x80L;
35966 			cp = t & 0x1f;
35967 		} else if (t < 0xf0) {
35968 			/* 1110 xxxx; 3 bytes */
35969 			utf8_blen = 3;
35970 			min_cp = 0x800L;
35971 			cp = t & 0x0f;
35972 		} else if (t < 0xf8) {
35973 			/* 1111 0xxx; 4 bytes */
35974 			utf8_blen = 4;
35975 			min_cp = 0x10000L;
35976 			cp = t & 0x07;
35977 		} else {
35978 			/* extended utf-8 not allowed for URIs */
35979 			goto uri_error;
35980 		}
35981 
35982 		if (left < utf8_blen * 3 - 1) {
35983 			/* '%xx%xx...%xx', p points to char after first '%' */
35984 			goto uri_error;
35985 		}
35986 
35987 		p += 3;
35988 		for (i = 1; i < utf8_blen; i++) {
35989 			/* p points to digit part ('%xy', p points to 'x') */
35990 			t = duk__decode_hex_escape(p, 2);
35991 			DUK_DDD(DUK_DDDPRINT("i=%ld utf8_blen=%ld cp=%ld t=0x%02lx",
35992 			                     (long) i, (long) utf8_blen, (long) cp, (unsigned long) t));
35993 			if (t < 0) {
35994 				goto uri_error;
35995 			}
35996 			if ((t & 0xc0) != 0x80) {
35997 				goto uri_error;
35998 			}
35999 			cp = (cp << 6) + (t & 0x3f);
36000 			p += 3;
36001 		}
36002 		p--;  /* p overshoots */
36003 		tfm_ctx->p = p;
36004 
36005 		DUK_DDD(DUK_DDDPRINT("final cp=%ld, min_cp=%ld", (long) cp, (long) min_cp));
36006 
36007 		if (cp < min_cp || cp > 0x10ffffL || (cp >= 0xd800L && cp <= 0xdfffL)) {
36008 			goto uri_error;
36009 		}
36010 
36011 		/* The E5.1 algorithm checks whether or not a decoded codepoint
36012 		 * is below 0x80 and perhaps may be in the "reserved" set.
36013 		 * This seems pointless because the single byte UTF-8 case is
36014 		 * handled separately, and non-shortest encodings are rejected.
36015 		 * So, 'cp' cannot be below 0x80 here, and thus cannot be in
36016 		 * the reserved set.
36017 		 */
36018 
36019 		/* utf-8 validation ensures these */
36020 		DUK_ASSERT(cp >= 0x80L && cp <= 0x10ffffL);
36021 
36022 		if (cp >= 0x10000L) {
36023 			cp -= 0x10000L;
36024 			DUK_ASSERT(cp < 0x100000L);
36025 
36026 			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp >> 10) + 0xd800L));
36027 			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp & 0x03ffL) + 0xdc00L));
36028 		} else {
36029 			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
36030 		}
36031 	} else {
36032 		DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
36033 	}
36034 	return;
36035 
36036  uri_error:
36037 	DUK_ERROR_URI(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
36038 	DUK_WO_NORETURN(return;);
36039 }
36040 
36041 #if defined(DUK_USE_SECTION_B)
duk__transform_callback_escape(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)36042 DUK_LOCAL void duk__transform_callback_escape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
36043 	DUK_UNREF(udata);
36044 
36045 	DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 6);
36046 
36047 	if (cp < 0) {
36048 		goto esc_error;
36049 	} else if ((cp < 0x80L) && DUK__CHECK_BITMASK(duk__escape_unescaped_table, cp)) {
36050 		DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
36051 	} else if (cp < 0x100L) {
36052 		DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
36053 		                      &tfm_ctx->bw,
36054 		                      (duk_uint8_t) DUK_ASC_PERCENT,
36055 		                      (duk_uint8_t) duk_uc_nybbles[cp >> 4],
36056 		                      (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
36057 	} else if (cp < 0x10000L) {
36058 		DUK_BW_WRITE_RAW_U8_6(tfm_ctx->thr,
36059 		                      &tfm_ctx->bw,
36060 		                      (duk_uint8_t) DUK_ASC_PERCENT,
36061 		                      (duk_uint8_t) DUK_ASC_LC_U,
36062 		                      (duk_uint8_t) duk_uc_nybbles[cp >> 12],
36063 		                      (duk_uint8_t) duk_uc_nybbles[(cp >> 8) & 0x0f],
36064 		                      (duk_uint8_t) duk_uc_nybbles[(cp >> 4) & 0x0f],
36065 		                      (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
36066 	} else {
36067 		/* Characters outside BMP cannot be escape()'d.  We could
36068 		 * encode them as surrogate pairs (for codepoints inside
36069 		 * valid UTF-8 range, but not extended UTF-8).  Because
36070 		 * escape() and unescape() are legacy functions, we don't.
36071 		 */
36072 		goto esc_error;
36073 	}
36074 
36075 	return;
36076 
36077  esc_error:
36078 	DUK_ERROR_TYPE(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
36079 	DUK_WO_NORETURN(return;);
36080 }
36081 
duk__transform_callback_unescape(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)36082 DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
36083 	duk_small_int_t t;
36084 
36085 	DUK_UNREF(udata);
36086 
36087 	if (cp == (duk_codepoint_t) '%') {
36088 		const duk_uint8_t *p = tfm_ctx->p;
36089 		duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p);  /* bytes left */
36090 
36091 		if (left >= 5 && p[0] == 'u' &&
36092 		    ((t = duk__decode_hex_escape(p + 1, 4)) >= 0)) {
36093 			cp = (duk_codepoint_t) t;
36094 			tfm_ctx->p += 5;
36095 		} else if (left >= 2 &&
36096 		           ((t = duk__decode_hex_escape(p, 2)) >= 0)) {
36097 			cp = (duk_codepoint_t) t;
36098 			tfm_ctx->p += 2;
36099 		}
36100 	}
36101 
36102 	DUK_BW_WRITE_ENSURE_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
36103 }
36104 #endif  /* DUK_USE_SECTION_B */
36105 
36106 /*
36107  *  Eval
36108  *
36109  *  Eval needs to handle both a "direct eval" and an "indirect eval".
36110  *  Direct eval handling needs access to the caller's activation so that its
36111  *  lexical environment can be accessed.  A direct eval is only possible from
36112  *  ECMAScript code; an indirect eval call is possible also from C code.
36113  *  When an indirect eval call is made from C code, there may not be a
36114  *  calling activation at all which needs careful handling.
36115  */
36116 
duk_bi_global_object_eval(duk_hthread * thr)36117 DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_hthread *thr) {
36118 	duk_hstring *h;
36119 	duk_activation *act_caller;
36120 	duk_activation *act_eval;
36121 	duk_hcompfunc *func;
36122 	duk_hobject *outer_lex_env;
36123 	duk_hobject *outer_var_env;
36124 	duk_bool_t this_to_global = 1;
36125 	duk_small_uint_t comp_flags;
36126 	duk_int_t level = -2;
36127 	duk_small_uint_t call_flags;
36128 
36129 	DUK_ASSERT(duk_get_top(thr) == 1 || duk_get_top(thr) == 2);  /* 2 when called by debugger */
36130 	DUK_ASSERT(thr->callstack_top >= 1);  /* at least this function exists */
36131 	DUK_ASSERT(thr->callstack_curr != NULL);
36132 	DUK_ASSERT((thr->callstack_curr->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0 || /* indirect eval */
36133 	           (thr->callstack_top >= 2));  /* if direct eval, calling activation must exist */
36134 
36135 	/*
36136 	 *  callstack_top - 1 --> this function
36137 	 *  callstack_top - 2 --> caller (may not exist)
36138 	 *
36139 	 *  If called directly from C, callstack_top might be 1.  If calling
36140 	 *  activation doesn't exist, call must be indirect.
36141 	 */
36142 
36143 	h = duk_get_hstring_notsymbol(thr, 0);
36144 	if (!h) {
36145 		/* Symbol must be returned as is, like any non-string values. */
36146 		return 1;  /* return arg as-is */
36147 	}
36148 
36149 #if defined(DUK_USE_DEBUGGER_SUPPORT)
36150 	/* NOTE: level is used only by the debugger and should never be present
36151 	 * for an ECMAScript eval().
36152 	 */
36153 	DUK_ASSERT(level == -2);  /* by default, use caller's environment */
36154 	if (duk_get_top(thr) >= 2 && duk_is_number(thr, 1)) {
36155 		level = duk_get_int(thr, 1);
36156 	}
36157 	DUK_ASSERT(level <= -2);  /* This is guaranteed by debugger code. */
36158 #endif
36159 
36160 	/* [ source ] */
36161 
36162 	comp_flags = DUK_COMPILE_EVAL;
36163 	act_eval = thr->callstack_curr;  /* this function */
36164 	DUK_ASSERT(act_eval != NULL);
36165 	act_caller = duk_hthread_get_activation_for_level(thr, level);
36166 	if (act_caller != NULL) {
36167 		/* Have a calling activation, check for direct eval (otherwise
36168 		 * assume indirect eval.
36169 		 */
36170 		if ((act_caller->flags & DUK_ACT_FLAG_STRICT) &&
36171 		    (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL)) {
36172 			/* Only direct eval inherits strictness from calling code
36173 			 * (E5.1 Section 10.1.1).
36174 			 */
36175 			comp_flags |= DUK_COMPILE_STRICT;
36176 		}
36177 	} else {
36178 		DUK_ASSERT((act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0);
36179 	}
36180 
36181 	duk_push_hstring_stridx(thr, DUK_STRIDX_INPUT);  /* XXX: copy from caller? */
36182 	duk_js_compile(thr,
36183 	               (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h),
36184 	               (duk_size_t) DUK_HSTRING_GET_BYTELEN(h),
36185 	               comp_flags);
36186 	func = (duk_hcompfunc *) duk_known_hobject(thr, -1);
36187 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) func));
36188 
36189 	/* [ source template ] */
36190 
36191 	/* E5 Section 10.4.2 */
36192 
36193 	if (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
36194 		DUK_ASSERT(thr->callstack_top >= 2);
36195 		DUK_ASSERT(act_caller != NULL);
36196 		if (act_caller->lex_env == NULL) {
36197 			DUK_ASSERT(act_caller->var_env == NULL);
36198 			DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
36199 
36200 			/* this may have side effects, so re-lookup act */
36201 			duk_js_init_activation_environment_records_delayed(thr, act_caller);
36202 		}
36203 		DUK_ASSERT(act_caller->lex_env != NULL);
36204 		DUK_ASSERT(act_caller->var_env != NULL);
36205 
36206 		this_to_global = 0;
36207 
36208 		if (DUK_HOBJECT_HAS_STRICT((duk_hobject *) func)) {
36209 			duk_hdecenv *new_env;
36210 			duk_hobject *act_lex_env;
36211 
36212 			DUK_DDD(DUK_DDDPRINT("direct eval call to a strict function -> "
36213 			                     "var_env and lex_env to a fresh env, "
36214 			                     "this_binding to caller's this_binding"));
36215 
36216 			act_lex_env = act_caller->lex_env;
36217 
36218 			new_env = duk_hdecenv_alloc(thr,
36219 			                            DUK_HOBJECT_FLAG_EXTENSIBLE |
36220 			                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
36221 			DUK_ASSERT(new_env != NULL);
36222 			duk_push_hobject(thr, (duk_hobject *) new_env);
36223 
36224 			DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
36225 			DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, act_lex_env);
36226 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, act_lex_env);
36227 			DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));
36228 
36229 			outer_lex_env = (duk_hobject *) new_env;
36230 			outer_var_env = (duk_hobject *) new_env;
36231 
36232 			duk_insert(thr, 0);  /* stash to bottom of value stack to keep new_env reachable for duration of eval */
36233 
36234 			/* compiler's responsibility */
36235 			DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func));
36236 		} else {
36237 			DUK_DDD(DUK_DDDPRINT("direct eval call to a non-strict function -> "
36238 			                     "var_env and lex_env to caller's envs, "
36239 			                     "this_binding to caller's this_binding"));
36240 
36241 			outer_lex_env = act_caller->lex_env;
36242 			outer_var_env = act_caller->var_env;
36243 
36244 			/* compiler's responsibility */
36245 			DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func));
36246 		}
36247 	} else {
36248 		DUK_DDD(DUK_DDDPRINT("indirect eval call -> var_env and lex_env to "
36249 		                     "global object, this_binding to global object"));
36250 
36251 		this_to_global = 1;
36252 		outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
36253 		outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
36254 	}
36255 
36256 	/* Eval code doesn't need an automatic .prototype object. */
36257 	duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 0 /*add_auto_proto*/);
36258 
36259 	/* [ env? source template closure ] */
36260 
36261 	if (this_to_global) {
36262 		DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
36263 		duk_push_hobject_bidx(thr, DUK_BIDX_GLOBAL);
36264 	} else {
36265 		duk_tval *tv;
36266 		DUK_ASSERT(thr->callstack_top >= 2);
36267 		DUK_ASSERT(act_caller != NULL);
36268 		tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act_caller->bottom_byteoff - sizeof(duk_tval));  /* this is just beneath bottom */
36269 		DUK_ASSERT(tv >= thr->valstack);
36270 		duk_push_tval(thr, tv);
36271 	}
36272 
36273 	DUK_DDD(DUK_DDDPRINT("eval -> lex_env=%!iO, var_env=%!iO, this_binding=%!T",
36274 	                     (duk_heaphdr *) outer_lex_env,
36275 	                     (duk_heaphdr *) outer_var_env,
36276 	                     duk_get_tval(thr, -1)));
36277 
36278 	/* [ env? source template closure this ] */
36279 
36280 	call_flags = 0;
36281 	if (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
36282 		/* Set DIRECT_EVAL flag for the call; it's not strictly
36283 		 * needed for the 'inner' eval call (the eval body) but
36284 		 * current new.target implementation expects to find it
36285 		 * so it can traverse direct eval chains up to the real
36286 		 * calling function.
36287 		 */
36288 		call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
36289 	}
36290 	duk_handle_call_unprotected_nargs(thr, 0, call_flags);
36291 
36292 	/* [ env? source template result ] */
36293 
36294 	return 1;
36295 }
36296 
36297 /*
36298  *  Parsing of ints and floats
36299  */
36300 
36301 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_parse_int(duk_hthread * thr)36302 DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_int(duk_hthread *thr) {
36303 	duk_int32_t radix;
36304 	duk_small_uint_t s2n_flags;
36305 
36306 	DUK_ASSERT_TOP(thr, 2);
36307 	duk_to_string(thr, 0);  /* Reject symbols. */
36308 
36309 	radix = duk_to_int32(thr, 1);
36310 
36311 	/* While parseInt() recognizes 0xdeadbeef, it doesn't recognize
36312 	 * ES2015 0o123 or 0b10001.
36313 	 */
36314 	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
36315 	            DUK_S2N_FLAG_ALLOW_GARBAGE |
36316 	            DUK_S2N_FLAG_ALLOW_PLUS |
36317 	            DUK_S2N_FLAG_ALLOW_MINUS |
36318 	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
36319 	            DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
36320 
36321 	/* Specification stripPrefix maps to DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT.
36322 	 *
36323 	 * Don't autodetect octals (from leading zeroes), require user code to
36324 	 * provide an explicit radix 8 for parsing octal.  See write-up from Mozilla:
36325 	 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt#ECMAScript_5_Removes_Octal_Interpretation
36326 	 */
36327 
36328 	if (radix != 0) {
36329 		if (radix < 2 || radix > 36) {
36330 			goto ret_nan;
36331 		}
36332 		if (radix != 16) {
36333 			s2n_flags &= ~DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
36334 		}
36335 	} else {
36336 		radix = 10;
36337 	}
36338 
36339 	duk_dup_0(thr);
36340 	duk_numconv_parse(thr, (duk_small_int_t) radix, s2n_flags);
36341 	return 1;
36342 
36343  ret_nan:
36344 	duk_push_nan(thr);
36345 	return 1;
36346 }
36347 #endif  /* DUK_USE_GLOBAL_BUILTIN */
36348 
36349 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_parse_float(duk_hthread * thr)36350 DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_float(duk_hthread *thr) {
36351 	duk_small_uint_t s2n_flags;
36352 
36353 	DUK_ASSERT_TOP(thr, 1);
36354 	duk_to_string(thr, 0);  /* Reject symbols. */
36355 
36356 	/* XXX: check flags */
36357 	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
36358 	            DUK_S2N_FLAG_ALLOW_EXP |
36359 	            DUK_S2N_FLAG_ALLOW_GARBAGE |
36360 	            DUK_S2N_FLAG_ALLOW_PLUS |
36361 	            DUK_S2N_FLAG_ALLOW_MINUS |
36362 	            DUK_S2N_FLAG_ALLOW_INF |
36363 	            DUK_S2N_FLAG_ALLOW_FRAC |
36364 	            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
36365 	            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
36366 	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
36367 
36368 	duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
36369 	return 1;
36370 }
36371 #endif  /* DUK_USE_GLOBAL_BUILTIN */
36372 
36373 /*
36374  *  Number checkers
36375  */
36376 
36377 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_is_nan(duk_hthread * thr)36378 DUK_INTERNAL duk_ret_t duk_bi_global_object_is_nan(duk_hthread *thr) {
36379 	duk_double_t d = duk_to_number(thr, 0);
36380 	duk_push_boolean(thr, (duk_bool_t) DUK_ISNAN(d));
36381 	return 1;
36382 }
36383 #endif  /* DUK_USE_GLOBAL_BUILTIN */
36384 
36385 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_is_finite(duk_hthread * thr)36386 DUK_INTERNAL duk_ret_t duk_bi_global_object_is_finite(duk_hthread *thr) {
36387 	duk_double_t d = duk_to_number(thr, 0);
36388 	duk_push_boolean(thr, (duk_bool_t) DUK_ISFINITE(d));
36389 	return 1;
36390 }
36391 #endif  /* DUK_USE_GLOBAL_BUILTIN */
36392 
36393 /*
36394  *  URI handling
36395  */
36396 
36397 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_decode_uri(duk_hthread * thr)36398 DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri(duk_hthread *thr) {
36399 	return duk__transform_helper(thr, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_reserved_table);
36400 }
36401 
duk_bi_global_object_decode_uri_component(duk_hthread * thr)36402 DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri_component(duk_hthread *thr) {
36403 	return duk__transform_helper(thr, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_component_reserved_table);
36404 }
36405 
duk_bi_global_object_encode_uri(duk_hthread * thr)36406 DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri(duk_hthread *thr) {
36407 	return duk__transform_helper(thr, duk__transform_callback_encode_uri, (const void *) duk__encode_uriunescaped_table);
36408 }
36409 
duk_bi_global_object_encode_uri_component(duk_hthread * thr)36410 DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri_component(duk_hthread *thr) {
36411 	return duk__transform_helper(thr, duk__transform_callback_encode_uri, (const void *) duk__encode_uricomponent_unescaped_table);
36412 }
36413 
36414 #if defined(DUK_USE_SECTION_B)
duk_bi_global_object_escape(duk_hthread * thr)36415 DUK_INTERNAL duk_ret_t duk_bi_global_object_escape(duk_hthread *thr) {
36416 	return duk__transform_helper(thr, duk__transform_callback_escape, (const void *) NULL);
36417 }
36418 
duk_bi_global_object_unescape(duk_hthread * thr)36419 DUK_INTERNAL duk_ret_t duk_bi_global_object_unescape(duk_hthread *thr) {
36420 	return duk__transform_helper(thr, duk__transform_callback_unescape, (const void *) NULL);
36421 }
36422 #endif  /* DUK_USE_SECTION_B */
36423 #endif  /* DUK_USE_GLOBAL_BUILTIN */
36424 
36425 /* automatic undefs */
36426 #undef DUK__CHECK_BITMASK
36427 #undef DUK__MKBITS
36428 #line 1 "duk_bi_json.c"
36429 /*
36430  *  JSON built-ins.
36431  *
36432  *  See doc/json.rst.
36433  *
36434  *  Codepoints are handled as duk_uint_fast32_t to ensure that the full
36435  *  unsigned 32-bit range is supported.  This matters to e.g. JX.
36436  *
36437  *  Input parsing doesn't do an explicit end-of-input check at all.  This is
36438  *  safe: input string data is always NUL-terminated (0x00) and valid JSON
36439  *  inputs never contain plain NUL characters, so that as long as syntax checks
36440  *  are correct, we'll never read past the NUL.  This approach reduces code size
36441  *  and improves parsing performance, but it's critical that syntax checks are
36442  *  indeed correct!
36443  */
36444 
36445 /* #include duk_internal.h -> already included */
36446 
36447 #if defined(DUK_USE_JSON_SUPPORT)
36448 
36449 /*
36450  *  Local defines and forward declarations.
36451  */
36452 
36453 #define DUK__JSON_DECSTR_BUFSIZE 128
36454 #define DUK__JSON_DECSTR_CHUNKSIZE 64
36455 #define DUK__JSON_ENCSTR_CHUNKSIZE 64
36456 #define DUK__JSON_STRINGIFY_BUFSIZE 128
36457 #define DUK__JSON_MAX_ESC_LEN 10  /* '\Udeadbeef' */
36458 
36459 DUK_LOCAL_DECL void duk__json_dec_syntax_error(duk_json_dec_ctx *js_ctx);
36460 DUK_LOCAL_DECL void duk__json_dec_eat_white(duk_json_dec_ctx *js_ctx);
36461 #if defined(DUK_USE_JX)
36462 DUK_LOCAL_DECL duk_uint8_t duk__json_dec_peek(duk_json_dec_ctx *js_ctx);
36463 #endif
36464 DUK_LOCAL_DECL duk_uint8_t duk__json_dec_get(duk_json_dec_ctx *js_ctx);
36465 DUK_LOCAL_DECL duk_uint8_t duk__json_dec_get_nonwhite(duk_json_dec_ctx *js_ctx);
36466 DUK_LOCAL_DECL duk_uint_fast32_t duk__json_dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n);
36467 DUK_LOCAL_DECL void duk__json_dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx);
36468 DUK_LOCAL_DECL void duk__json_dec_string(duk_json_dec_ctx *js_ctx);
36469 #if defined(DUK_USE_JX)
36470 DUK_LOCAL_DECL void duk__json_dec_plain_string(duk_json_dec_ctx *js_ctx);
36471 DUK_LOCAL_DECL void duk__json_dec_pointer(duk_json_dec_ctx *js_ctx);
36472 DUK_LOCAL_DECL void duk__json_dec_buffer(duk_json_dec_ctx *js_ctx);
36473 #endif
36474 DUK_LOCAL_DECL void duk__json_dec_number(duk_json_dec_ctx *js_ctx);
36475 DUK_LOCAL_DECL void duk__json_dec_objarr_entry(duk_json_dec_ctx *js_ctx);
36476 DUK_LOCAL_DECL void duk__json_dec_objarr_exit(duk_json_dec_ctx *js_ctx);
36477 DUK_LOCAL_DECL void duk__json_dec_object(duk_json_dec_ctx *js_ctx);
36478 DUK_LOCAL_DECL void duk__json_dec_array(duk_json_dec_ctx *js_ctx);
36479 DUK_LOCAL_DECL void duk__json_dec_value(duk_json_dec_ctx *js_ctx);
36480 DUK_LOCAL_DECL void duk__json_dec_reviver_walk(duk_json_dec_ctx *js_ctx);
36481 
36482 DUK_LOCAL_DECL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch);
36483 DUK_LOCAL_DECL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2);
36484 DUK_LOCAL_DECL void duk__unemit_1(duk_json_enc_ctx *js_ctx);
36485 DUK_LOCAL_DECL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h);
36486 #if defined(DUK_USE_FASTINT)
36487 DUK_LOCAL_DECL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p);
36488 #endif
36489 DUK_LOCAL_DECL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx);
36490 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);
36491 DUK_LOCAL_DECL void duk__json_enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k);
36492 DUK_LOCAL_DECL void duk__json_enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str);
36493 DUK_LOCAL_DECL void duk__json_enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
36494 DUK_LOCAL_DECL void duk__json_enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
36495 DUK_LOCAL_DECL void duk__json_enc_object(duk_json_enc_ctx *js_ctx);
36496 DUK_LOCAL_DECL void duk__json_enc_array(duk_json_enc_ctx *js_ctx);
36497 DUK_LOCAL_DECL duk_bool_t duk__json_enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder);
36498 DUK_LOCAL_DECL duk_bool_t duk__json_enc_allow_into_proplist(duk_tval *tv);
36499 DUK_LOCAL_DECL void duk__json_enc_double(duk_json_enc_ctx *js_ctx);
36500 #if defined(DUK_USE_FASTINT)
36501 DUK_LOCAL_DECL void duk__json_enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv);
36502 #endif
36503 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36504 DUK_LOCAL_DECL void duk__json_enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
36505 DUK_LOCAL_DECL void duk__json_enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr);
36506 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
36507 DUK_LOCAL_DECL void duk__json_enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj);
36508 #endif
36509 #endif
36510 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
36511 DUK_LOCAL_DECL void duk__json_enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
36512 #endif
36513 DUK_LOCAL_DECL void duk__json_enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth);
36514 
36515 /*
36516  *  Helper tables
36517  */
36518 
36519 #if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
36520 DUK_LOCAL const duk_uint8_t duk__json_quotestr_lookup[256] = {
36521 	/* 0x00 ... 0x7f: as is
36522 	 * 0x80: escape generically
36523 	 * 0x81: slow path
36524 	 * 0xa0 ... 0xff: backslash + one char
36525 	 */
36526 
36527 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xe2, 0xf4, 0xee, 0x80, 0xe6, 0xf2, 0x80, 0x80,
36528 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
36529 	0x20, 0x21, 0xa2, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
36530 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
36531 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
36532 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0xdc, 0x5d, 0x5e, 0x5f,
36533 	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
36534 	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x81,
36535 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
36536 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
36537 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
36538 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
36539 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
36540 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
36541 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
36542 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81
36543 };
36544 #else  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
36545 DUK_LOCAL const duk_uint8_t duk__json_quotestr_esc[14] = {
36546 	DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
36547 	DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
36548 	DUK_ASC_LC_B, DUK_ASC_LC_T, DUK_ASC_LC_N, DUK_ASC_NUL,
36549 	DUK_ASC_LC_F, DUK_ASC_LC_R
36550 };
36551 #endif  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
36552 
36553 #if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
36554 DUK_LOCAL const duk_uint8_t duk__json_decstr_lookup[256] = {
36555 	/* 0x00: slow path
36556 	 * other: as is
36557 	 */
36558 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36559 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36560 	0x20, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
36561 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
36562 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
36563 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x5d, 0x5e, 0x5f,
36564 	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
36565 	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
36566 	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
36567 	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
36568 	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
36569 	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
36570 	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
36571 	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
36572 	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
36573 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
36574 };
36575 #endif  /* DUK_USE_JSON_DECSTRING_FASTPATH */
36576 
36577 #if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
36578 DUK_LOCAL const duk_uint8_t duk__json_eatwhite_lookup[256] = {
36579 	/* 0x00: finish (non-white)
36580 	 * 0x01: continue
36581 	 */
36582 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
36583 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36584 	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36585 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36586 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36587 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36588 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36589 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36590 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36591 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36592 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36593 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36594 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36595 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36596 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36597 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
36598 };
36599 #endif  /* DUK_USE_JSON_EATWHITE_FASTPATH */
36600 
36601 #if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
36602 DUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256] = {
36603 	/* 0x00: finish (not part of number)
36604 	 * 0x01: continue
36605 	 */
36606 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36607 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36608 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00,
36609 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36610 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36611 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36612 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36613 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36614 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36615 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36616 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36617 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36618 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36619 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36620 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36621 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
36622 };
36623 #endif  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
36624 
36625 /*
36626  *  Parsing implementation.
36627  *
36628  *  JSON lexer is now separate from duk_lexer.c because there are numerous
36629  *  small differences making it difficult to share the lexer.
36630  *
36631  *  The parser here works with raw bytes directly; this works because all
36632  *  JSON delimiters are ASCII characters.  Invalid xUTF-8 encoded values
36633  *  inside strings will be passed on without normalization; this is not a
36634  *  compliance concern because compliant inputs will always be valid
36635  *  CESU-8 encodings.
36636  */
36637 
duk__json_dec_syntax_error(duk_json_dec_ctx * js_ctx)36638 DUK_LOCAL void duk__json_dec_syntax_error(duk_json_dec_ctx *js_ctx) {
36639 	/* Shared handler to minimize parser size.  Cause will be
36640 	 * hidden, unfortunately, but we'll have an offset which
36641 	 * is often quite enough.
36642 	 */
36643 	DUK_ERROR_FMT1(js_ctx->thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_FMT_INVALID_JSON,
36644 	               (long) (js_ctx->p - js_ctx->p_start));
36645 	DUK_WO_NORETURN(return;);
36646 }
36647 
duk__json_dec_eat_white(duk_json_dec_ctx * js_ctx)36648 DUK_LOCAL void duk__json_dec_eat_white(duk_json_dec_ctx *js_ctx) {
36649 	const duk_uint8_t *p;
36650 	duk_uint8_t t;
36651 
36652 	p = js_ctx->p;
36653 	for (;;) {
36654 		DUK_ASSERT(p <= js_ctx->p_end);
36655 		t = *p;
36656 
36657 #if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
36658 		/* This fast path is pretty marginal in practice.
36659 		 * XXX: candidate for removal.
36660 		 */
36661 		DUK_ASSERT(duk__json_eatwhite_lookup[0x00] == 0x00);  /* end-of-input breaks */
36662 		if (duk__json_eatwhite_lookup[t] == 0) {
36663 			break;
36664 		}
36665 #else  /* DUK_USE_JSON_EATWHITE_FASTPATH */
36666 		if (!(t == 0x20 || t == 0x0a || t == 0x0d || t == 0x09)) {
36667 			/* NUL also comes here.  Comparison order matters, 0x20
36668 			 * is most common whitespace.
36669 			 */
36670 			break;
36671 		}
36672 #endif  /* DUK_USE_JSON_EATWHITE_FASTPATH */
36673 		p++;
36674 	}
36675 	js_ctx->p = p;
36676 }
36677 
36678 #if defined(DUK_USE_JX)
duk__json_dec_peek(duk_json_dec_ctx * js_ctx)36679 DUK_LOCAL duk_uint8_t duk__json_dec_peek(duk_json_dec_ctx *js_ctx) {
36680 	DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
36681 	return *js_ctx->p;
36682 }
36683 #endif
36684 
duk__json_dec_get(duk_json_dec_ctx * js_ctx)36685 DUK_LOCAL duk_uint8_t duk__json_dec_get(duk_json_dec_ctx *js_ctx) {
36686 	DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
36687 	return *js_ctx->p++;
36688 }
36689 
duk__json_dec_get_nonwhite(duk_json_dec_ctx * js_ctx)36690 DUK_LOCAL duk_uint8_t duk__json_dec_get_nonwhite(duk_json_dec_ctx *js_ctx) {
36691 	duk__json_dec_eat_white(js_ctx);
36692 	return duk__json_dec_get(js_ctx);
36693 }
36694 
36695 /* For JX, expressing the whole unsigned 32-bit range matters. */
duk__json_dec_decode_hex_escape(duk_json_dec_ctx * js_ctx,duk_small_uint_t n)36696 DUK_LOCAL duk_uint_fast32_t duk__json_dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n) {
36697 	duk_small_uint_t i;
36698 	duk_uint_fast32_t res = 0;
36699 	duk_uint8_t x;
36700 	duk_small_int_t t;
36701 
36702 	for (i = 0; i < n; i++) {
36703 		/* XXX: share helper from lexer; duk_lexer.c / hexval(). */
36704 
36705 		x = duk__json_dec_get(js_ctx);
36706 		DUK_DDD(DUK_DDDPRINT("decode_hex_escape: i=%ld, n=%ld, res=%ld, x=%ld",
36707 		                     (long) i, (long) n, (long) res, (long) x));
36708 
36709 		/* x == 0x00 (EOF) causes syntax_error */
36710 		DUK_ASSERT(duk_hex_dectab[0] == -1);
36711 		t = duk_hex_dectab[x & 0xff];
36712 		if (DUK_LIKELY(t >= 0)) {
36713 			res = (res * 16) + (duk_uint_fast32_t) t;
36714 		} else {
36715 			/* catches EOF and invalid digits */
36716 			goto syntax_error;
36717 		}
36718 	}
36719 
36720 	DUK_DDD(DUK_DDDPRINT("final hex decoded value: %ld", (long) res));
36721 	return res;
36722 
36723  syntax_error:
36724 	duk__json_dec_syntax_error(js_ctx);
36725 	DUK_UNREACHABLE();
36726 	return 0;
36727 }
36728 
duk__json_dec_req_stridx(duk_json_dec_ctx * js_ctx,duk_small_uint_t stridx)36729 DUK_LOCAL void duk__json_dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx) {
36730 	duk_hstring *h;
36731 	const duk_uint8_t *p;
36732 	duk_uint8_t x, y;
36733 
36734 	/* First character has already been eaten and checked by the caller.
36735 	 * We can scan until a NUL in stridx string because no built-in strings
36736 	 * have internal NULs.
36737 	 */
36738 
36739 	DUK_ASSERT_STRIDX_VALID(stridx);
36740 	h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
36741 	DUK_ASSERT(h != NULL);
36742 
36743 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h) + 1;
36744 	DUK_ASSERT(*(js_ctx->p - 1) == *(p - 1));  /* first character has been matched */
36745 
36746 	for (;;) {
36747 		x = *p;
36748 		if (x == 0) {
36749 			break;
36750 		}
36751 		y = duk__json_dec_get(js_ctx);
36752 		if (x != y) {
36753 			/* Catches EOF of JSON input. */
36754 			goto syntax_error;
36755 		}
36756 		p++;
36757 	}
36758 
36759 	return;
36760 
36761  syntax_error:
36762 	duk__json_dec_syntax_error(js_ctx);
36763 	DUK_UNREACHABLE();
36764 }
36765 
duk__json_dec_string_escape(duk_json_dec_ctx * js_ctx,duk_uint8_t ** ext_p)36766 DUK_LOCAL duk_small_int_t duk__json_dec_string_escape(duk_json_dec_ctx *js_ctx, duk_uint8_t **ext_p) {
36767 	duk_uint_fast32_t cp;
36768 
36769 	/* EOF (-1) will be cast to an unsigned value first
36770 	 * and then re-cast for the switch.  In any case, it
36771 	 * will match the default case (syntax error).
36772 	 */
36773 	cp = (duk_uint_fast32_t) duk__json_dec_get(js_ctx);
36774 	switch (cp) {
36775 	case DUK_ASC_BACKSLASH: break;
36776 	case DUK_ASC_DOUBLEQUOTE: break;
36777 	case DUK_ASC_SLASH: break;
36778 	case DUK_ASC_LC_T: cp = 0x09; break;
36779 	case DUK_ASC_LC_N: cp = 0x0a; break;
36780 	case DUK_ASC_LC_R: cp = 0x0d; break;
36781 	case DUK_ASC_LC_F: cp = 0x0c; break;
36782 	case DUK_ASC_LC_B: cp = 0x08; break;
36783 	case DUK_ASC_LC_U: {
36784 		cp = duk__json_dec_decode_hex_escape(js_ctx, 4);
36785 		break;
36786 	}
36787 #if defined(DUK_USE_JX)
36788 	case DUK_ASC_UC_U: {
36789 		if (js_ctx->flag_ext_custom) {
36790 			cp = duk__json_dec_decode_hex_escape(js_ctx, 8);
36791 		} else {
36792 			return 1;  /* syntax error */
36793 		}
36794 		break;
36795 	}
36796 	case DUK_ASC_LC_X: {
36797 		if (js_ctx->flag_ext_custom) {
36798 			cp = duk__json_dec_decode_hex_escape(js_ctx, 2);
36799 		} else {
36800 			return 1;  /* syntax error */
36801 		}
36802 		break;
36803 	}
36804 #endif  /* DUK_USE_JX */
36805 	default:
36806 		/* catches EOF (0x00) */
36807 		return 1;  /* syntax error */
36808 	}
36809 
36810 	DUK_RAW_WRITEINC_XUTF8(*ext_p, cp);
36811 
36812 	return 0;
36813 }
36814 
duk__json_dec_string(duk_json_dec_ctx * js_ctx)36815 DUK_LOCAL void duk__json_dec_string(duk_json_dec_ctx *js_ctx) {
36816 	duk_hthread *thr = js_ctx->thr;
36817 	duk_bufwriter_ctx bw_alloc;
36818 	duk_bufwriter_ctx *bw;
36819 	duk_uint8_t *q;
36820 
36821 	/* '"' was eaten by caller */
36822 
36823 	/* Note that we currently parse -bytes-, not codepoints.
36824 	 * All non-ASCII extended UTF-8 will encode to bytes >= 0x80,
36825 	 * so they'll simply pass through (valid UTF-8 or not).
36826 	 */
36827 
36828 	bw = &bw_alloc;
36829 	DUK_BW_INIT_PUSHBUF(js_ctx->thr, bw, DUK__JSON_DECSTR_BUFSIZE);
36830 	q = DUK_BW_GET_PTR(js_ctx->thr, bw);
36831 
36832 #if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
36833 	for (;;) {
36834 		duk_small_uint_t safe;
36835 		duk_uint8_t b, x;
36836 		const duk_uint8_t *p;
36837 
36838 		/* Select a safe loop count where no output checks are
36839 		 * needed assuming we won't encounter escapes.  Input
36840 		 * bound checks are not necessary as a NUL (guaranteed)
36841 		 * will cause a SyntaxError before we read out of bounds.
36842 		 */
36843 
36844 		safe = DUK__JSON_DECSTR_CHUNKSIZE;
36845 
36846 		/* Ensure space for 1:1 output plus one escape. */
36847 		q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, safe + DUK_UNICODE_MAX_XUTF8_LENGTH, q);
36848 
36849 		p = js_ctx->p;  /* temp copy, write back for next loop */
36850 		for (;;) {
36851 			if (safe == 0) {
36852 				js_ctx->p = p;
36853 				break;
36854 			}
36855 			safe--;
36856 
36857 			/* End of input (NUL) goes through slow path and causes SyntaxError. */
36858 			DUK_ASSERT(duk__json_decstr_lookup[0] == 0x00);
36859 
36860 			b = *p++;
36861 			x = (duk_small_int_t) duk__json_decstr_lookup[b];
36862 			if (DUK_LIKELY(x != 0)) {
36863 				/* Fast path, decode as is. */
36864 				*q++ = b;
36865 			} else if (b == DUK_ASC_DOUBLEQUOTE) {
36866 				js_ctx->p = p;
36867 				goto found_quote;
36868 			} else if (b == DUK_ASC_BACKSLASH) {
36869 				/* We've ensured space for one escaped input; then
36870 				 * bail out and recheck (this makes escape handling
36871 				 * quite slow but it's uncommon).
36872 				 */
36873 				js_ctx->p = p;
36874 				if (duk__json_dec_string_escape(js_ctx, &q) != 0) {
36875 					goto syntax_error;
36876 				}
36877 				break;
36878 			} else {
36879 				js_ctx->p = p;
36880 				goto syntax_error;
36881 			}
36882 		}
36883 	}
36884  found_quote:
36885 #else  /* DUK_USE_JSON_DECSTRING_FASTPATH */
36886 	for (;;) {
36887 		duk_uint8_t x;
36888 
36889 		q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, DUK_UNICODE_MAX_XUTF8_LENGTH, q);
36890 
36891 		x = duk__json_dec_get(js_ctx);
36892 
36893 		if (x == DUK_ASC_DOUBLEQUOTE) {
36894 			break;
36895 		} else if (x == DUK_ASC_BACKSLASH) {
36896 			if (duk__json_dec_string_escape(js_ctx, &q) != 0) {
36897 				goto syntax_error;
36898 			}
36899 		} else if (x < 0x20) {
36900 			/* catches EOF (NUL) */
36901 			goto syntax_error;
36902 		} else {
36903 			*q++ = (duk_uint8_t) x;
36904 		}
36905 	}
36906 #endif  /* DUK_USE_JSON_DECSTRING_FASTPATH */
36907 
36908 	DUK_BW_SETPTR_AND_COMPACT(js_ctx->thr, bw, q);
36909 	(void) duk_buffer_to_string(thr, -1);  /* Safe if input string is safe. */
36910 
36911 	/* [ ... str ] */
36912 
36913 	return;
36914 
36915  syntax_error:
36916 	duk__json_dec_syntax_error(js_ctx);
36917 	DUK_UNREACHABLE();
36918 }
36919 
36920 #if defined(DUK_USE_JX)
36921 /* Decode a plain string consisting entirely of identifier characters.
36922  * Used to parse plain keys (e.g. "foo: 123").
36923  */
duk__json_dec_plain_string(duk_json_dec_ctx * js_ctx)36924 DUK_LOCAL void duk__json_dec_plain_string(duk_json_dec_ctx *js_ctx) {
36925 	duk_hthread *thr = js_ctx->thr;
36926 	const duk_uint8_t *p;
36927 	duk_small_int_t x;
36928 
36929 	/* Caller has already eaten the first char so backtrack one byte. */
36930 
36931 	js_ctx->p--;  /* safe */
36932 	p = js_ctx->p;
36933 
36934 	/* Here again we parse bytes, and non-ASCII UTF-8 will cause end of
36935 	 * parsing (which is correct except if there are non-shortest encodings).
36936 	 * There is also no need to check explicitly for end of input buffer as
36937 	 * the input is NUL padded and NUL will exit the parsing loop.
36938 	 *
36939 	 * Because no unescaping takes place, we can just scan to the end of the
36940 	 * plain string and intern from the input buffer.
36941 	 */
36942 
36943 	for (;;) {
36944 		x = *p;
36945 
36946 		/* There is no need to check the first character specially here
36947 		 * (i.e. reject digits): the caller only accepts valid initial
36948 		 * characters and won't call us if the first character is a digit.
36949 		 * This also ensures that the plain string won't be empty.
36950 		 */
36951 
36952 		if (!duk_unicode_is_identifier_part((duk_codepoint_t) x)) {
36953 			break;
36954 		}
36955 		p++;
36956 	}
36957 
36958 	duk_push_lstring(thr, (const char *) js_ctx->p, (duk_size_t) (p - js_ctx->p));
36959 	js_ctx->p = p;
36960 
36961 	/* [ ... str ] */
36962 }
36963 #endif  /* DUK_USE_JX */
36964 
36965 #if defined(DUK_USE_JX)
duk__json_dec_pointer(duk_json_dec_ctx * js_ctx)36966 DUK_LOCAL void duk__json_dec_pointer(duk_json_dec_ctx *js_ctx) {
36967 	duk_hthread *thr = js_ctx->thr;
36968 	const duk_uint8_t *p;
36969 	duk_small_int_t x;
36970 	void *voidptr;
36971 
36972 	/* Caller has already eaten the first character ('(') which we don't need. */
36973 
36974 	p = js_ctx->p;
36975 
36976 	for (;;) {
36977 		x = *p;
36978 
36979 		/* Assume that the native representation never contains a closing
36980 		 * parenthesis.
36981 		 */
36982 
36983 		if (x == DUK_ASC_RPAREN) {
36984 			break;
36985 		} else if (x <= 0) {
36986 			/* NUL term or -1 (EOF), NUL check would suffice */
36987 			goto syntax_error;
36988 		}
36989 		p++;
36990 	}
36991 
36992 	/* There is no need to NUL delimit the sscanf() call: trailing garbage is
36993 	 * ignored and there is always a NUL terminator which will force an error
36994 	 * if no error is encountered before it.  It's possible that the scan
36995 	 * would scan further than between [js_ctx->p,p[ though and we'd advance
36996 	 * by less than the scanned value.
36997 	 *
36998 	 * Because pointers are platform specific, a failure to scan a pointer
36999 	 * results in a null pointer which is a better placeholder than a missing
37000 	 * value or an error.
37001 	 */
37002 
37003 	voidptr = NULL;
37004 	(void) DUK_SSCANF((const char *) js_ctx->p, DUK_STR_FMT_PTR, &voidptr);
37005 	duk_push_pointer(thr, voidptr);
37006 	js_ctx->p = p + 1;  /* skip ')' */
37007 
37008 	/* [ ... ptr ] */
37009 
37010 	return;
37011 
37012  syntax_error:
37013 	duk__json_dec_syntax_error(js_ctx);
37014 	DUK_UNREACHABLE();
37015 }
37016 #endif  /* DUK_USE_JX */
37017 
37018 #if defined(DUK_USE_JX)
duk__json_dec_buffer(duk_json_dec_ctx * js_ctx)37019 DUK_LOCAL void duk__json_dec_buffer(duk_json_dec_ctx *js_ctx) {
37020 	duk_hthread *thr = js_ctx->thr;
37021 	const duk_uint8_t *p;
37022 	duk_uint8_t *buf;
37023 	duk_size_t src_len;
37024 	duk_small_int_t x;
37025 
37026 	/* Caller has already eaten the first character ('|') which we don't need. */
37027 
37028 	p = js_ctx->p;
37029 
37030 	/* XXX: Would be nice to share the fast path loop from duk_hex_decode()
37031 	 * and avoid creating a temporary buffer.  However, there are some
37032 	 * differences which prevent trivial sharing:
37033 	 *
37034 	 *   - Pipe char detection
37035 	 *   - EOF detection
37036 	 *   - Unknown length of input and output
37037 	 *
37038 	 * The best approach here would be a bufwriter and a reasonaly sized
37039 	 * safe inner loop (e.g. 64 output bytes at a time).
37040 	 */
37041 
37042 	for (;;) {
37043 		x = *p;
37044 
37045 		/* This loop intentionally does not ensure characters are valid
37046 		 * ([0-9a-fA-F]) because the hex decode call below will do that.
37047 		 */
37048 		if (x == DUK_ASC_PIPE) {
37049 			break;
37050 		} else if (x <= 0) {
37051 			/* NUL term or -1 (EOF), NUL check would suffice */
37052 			goto syntax_error;
37053 		}
37054 		p++;
37055 	}
37056 
37057 	/* XXX: this is not very nice; unnecessary copy is made. */
37058 	src_len = (duk_size_t) (p - js_ctx->p);
37059 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, src_len);
37060 	DUK_ASSERT(buf != NULL);
37061 	duk_memcpy((void *) buf, (const void *) js_ctx->p, src_len);
37062 	duk_hex_decode(thr, -1);
37063 
37064 	js_ctx->p = p + 1;  /* skip '|' */
37065 
37066 	/* [ ... buf ] */
37067 
37068 	return;
37069 
37070  syntax_error:
37071 	duk__json_dec_syntax_error(js_ctx);
37072 	DUK_UNREACHABLE();
37073 }
37074 #endif  /* DUK_USE_JX */
37075 
37076 /* Parse a number, other than NaN or +/- Infinity */
duk__json_dec_number(duk_json_dec_ctx * js_ctx)37077 DUK_LOCAL void duk__json_dec_number(duk_json_dec_ctx *js_ctx) {
37078 	duk_hthread *thr = js_ctx->thr;
37079 	const duk_uint8_t *p_start;
37080 	const duk_uint8_t *p;
37081 	duk_uint8_t x;
37082 	duk_small_uint_t s2n_flags;
37083 
37084 	DUK_DDD(DUK_DDDPRINT("parse_number"));
37085 
37086 	p_start = js_ctx->p;
37087 
37088 	/* First pass parse is very lenient (e.g. allows '1.2.3') and extracts a
37089 	 * string for strict number parsing.
37090 	 */
37091 
37092 	p = js_ctx->p;
37093 	for (;;) {
37094 		x = *p;
37095 
37096 		DUK_DDD(DUK_DDDPRINT("parse_number: p_start=%p, p=%p, p_end=%p, x=%ld",
37097 		                     (const void *) p_start, (const void *) p,
37098 		                     (const void *) js_ctx->p_end, (long) x));
37099 
37100 #if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
37101 		/* This fast path is pretty marginal in practice.
37102 		 * XXX: candidate for removal.
37103 		 */
37104 		DUK_ASSERT(duk__json_decnumber_lookup[0x00] == 0x00);  /* end-of-input breaks */
37105 		if (duk__json_decnumber_lookup[x] == 0) {
37106 			break;
37107 		}
37108 #else  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
37109 		if (!((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
37110 		      (x == DUK_ASC_PERIOD || x == DUK_ASC_LC_E ||
37111 		       x == DUK_ASC_UC_E || x == DUK_ASC_MINUS || x == DUK_ASC_PLUS))) {
37112 			/* Plus sign must be accepted for positive exponents
37113 			 * (e.g. '1.5e+2').  This clause catches NULs.
37114 			 */
37115 			break;
37116 		}
37117 #endif  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
37118 		p++;  /* safe, because matched (NUL causes a break) */
37119 	}
37120 	js_ctx->p = p;
37121 
37122 	DUK_ASSERT(js_ctx->p > p_start);
37123 	duk_push_lstring(thr, (const char *) p_start, (duk_size_t) (p - p_start));
37124 
37125 	s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
37126 	            DUK_S2N_FLAG_ALLOW_MINUS |  /* but don't allow leading plus */
37127 	            DUK_S2N_FLAG_ALLOW_FRAC;
37128 
37129 	DUK_DDD(DUK_DDDPRINT("parse_number: string before parsing: %!T",
37130 	                     (duk_tval *) duk_get_tval(thr, -1)));
37131 	duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
37132 	if (duk_is_nan(thr, -1)) {
37133 		duk__json_dec_syntax_error(js_ctx);
37134 	}
37135 	DUK_ASSERT(duk_is_number(thr, -1));
37136 	DUK_DDD(DUK_DDDPRINT("parse_number: final number: %!T",
37137 	                     (duk_tval *) duk_get_tval(thr, -1)));
37138 
37139 	/* [ ... num ] */
37140 }
37141 
duk__json_dec_objarr_entry(duk_json_dec_ctx * js_ctx)37142 DUK_LOCAL void duk__json_dec_objarr_entry(duk_json_dec_ctx *js_ctx) {
37143 	duk_hthread *thr = js_ctx->thr;
37144 	duk_require_stack(thr, DUK_JSON_DEC_REQSTACK);
37145 
37146 	/* c recursion check */
37147 
37148 	duk_native_stack_check(thr);
37149 
37150 	DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */
37151 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
37152 	if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
37153 		DUK_ERROR_RANGE(thr, DUK_STR_DEC_RECLIMIT);
37154 		DUK_WO_NORETURN(return;);
37155 	}
37156 	js_ctx->recursion_depth++;
37157 }
37158 
duk__json_dec_objarr_exit(duk_json_dec_ctx * js_ctx)37159 DUK_LOCAL void duk__json_dec_objarr_exit(duk_json_dec_ctx *js_ctx) {
37160 	/* c recursion check */
37161 
37162 	DUK_ASSERT(js_ctx->recursion_depth > 0);
37163 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
37164 	js_ctx->recursion_depth--;
37165 }
37166 
duk__json_dec_object(duk_json_dec_ctx * js_ctx)37167 DUK_LOCAL void duk__json_dec_object(duk_json_dec_ctx *js_ctx) {
37168 	duk_hthread *thr = js_ctx->thr;
37169 	duk_int_t key_count;  /* XXX: a "first" flag would suffice */
37170 	duk_uint8_t x;
37171 
37172 	DUK_DDD(DUK_DDDPRINT("parse_object"));
37173 
37174 	duk__json_dec_objarr_entry(js_ctx);
37175 
37176 	duk_push_object(thr);
37177 
37178 	/* Initial '{' has been checked and eaten by caller. */
37179 
37180 	key_count = 0;
37181 	for (;;) {
37182 		x = duk__json_dec_get_nonwhite(js_ctx);
37183 
37184 		DUK_DDD(DUK_DDDPRINT("parse_object: obj=%!T, x=%ld, key_count=%ld",
37185 		                     (duk_tval *) duk_get_tval(thr, -1),
37186 		                     (long) x, (long) key_count));
37187 
37188 		/* handle comma and closing brace */
37189 
37190 		if (x == DUK_ASC_COMMA && key_count > 0) {
37191 			/* accept comma, expect new value */
37192 			x = duk__json_dec_get_nonwhite(js_ctx);
37193 		} else if (x == DUK_ASC_RCURLY) {
37194 			/* eat closing brace */
37195 			break;
37196 		} else if (key_count == 0) {
37197 			/* accept anything, expect first value (EOF will be
37198 			 * caught by key parsing below.
37199 			 */
37200 			;
37201 		} else {
37202 			/* catches EOF (NUL) and initial comma */
37203 			goto syntax_error;
37204 		}
37205 
37206 		/* parse key and value */
37207 
37208 		if (x == DUK_ASC_DOUBLEQUOTE) {
37209 			duk__json_dec_string(js_ctx);
37210 #if defined(DUK_USE_JX)
37211 		} else if (js_ctx->flag_ext_custom &&
37212 		           duk_unicode_is_identifier_start((duk_codepoint_t) x)) {
37213 			duk__json_dec_plain_string(js_ctx);
37214 #endif
37215 		} else {
37216 			goto syntax_error;
37217 		}
37218 
37219 		/* [ ... obj key ] */
37220 
37221 		x = duk__json_dec_get_nonwhite(js_ctx);
37222 		if (x != DUK_ASC_COLON) {
37223 			goto syntax_error;
37224 		}
37225 
37226 		duk__json_dec_value(js_ctx);
37227 
37228 		/* [ ... obj key val ] */
37229 
37230 		duk_xdef_prop_wec(thr, -3);
37231 
37232 		/* [ ... obj ] */
37233 
37234 		key_count++;
37235 	}
37236 
37237 	/* [ ... obj ] */
37238 
37239 	DUK_DDD(DUK_DDDPRINT("parse_object: final object is %!T",
37240 	                     (duk_tval *) duk_get_tval(thr, -1)));
37241 
37242 	duk__json_dec_objarr_exit(js_ctx);
37243 	return;
37244 
37245  syntax_error:
37246 	duk__json_dec_syntax_error(js_ctx);
37247 	DUK_UNREACHABLE();
37248 }
37249 
duk__json_dec_array(duk_json_dec_ctx * js_ctx)37250 DUK_LOCAL void duk__json_dec_array(duk_json_dec_ctx *js_ctx) {
37251 	duk_hthread *thr = js_ctx->thr;
37252 	duk_uarridx_t arr_idx;
37253 	duk_uint8_t x;
37254 
37255 	DUK_DDD(DUK_DDDPRINT("parse_array"));
37256 
37257 	duk__json_dec_objarr_entry(js_ctx);
37258 
37259 	duk_push_array(thr);
37260 
37261 	/* Initial '[' has been checked and eaten by caller. */
37262 
37263 	arr_idx = 0;
37264 	for (;;) {
37265 		x = duk__json_dec_get_nonwhite(js_ctx);
37266 
37267 		DUK_DDD(DUK_DDDPRINT("parse_array: arr=%!T, x=%ld, arr_idx=%ld",
37268 		                     (duk_tval *) duk_get_tval(thr, -1),
37269 		                     (long) x, (long) arr_idx));
37270 
37271 		/* handle comma and closing bracket */
37272 
37273 		if ((x == DUK_ASC_COMMA) && (arr_idx != 0)) {
37274 			/* accept comma, expect new value */
37275 			;
37276 		} else if (x == DUK_ASC_RBRACKET) {
37277 			/* eat closing bracket */
37278 			break;
37279 		} else if (arr_idx == 0) {
37280 			/* accept anything, expect first value (EOF will be
37281 			 * caught by duk__json_dec_value() below.
37282 			 */
37283 			js_ctx->p--;  /* backtrack (safe) */
37284 		} else {
37285 			/* catches EOF (NUL) and initial comma */
37286 			goto syntax_error;
37287 		}
37288 
37289 		/* parse value */
37290 
37291 		duk__json_dec_value(js_ctx);
37292 
37293 		/* [ ... arr val ] */
37294 
37295 		duk_xdef_prop_index_wec(thr, -2, arr_idx);
37296 		arr_idx++;
37297 	}
37298 
37299 	/* Must set 'length' explicitly when using duk_xdef_prop_xxx() to
37300 	 * set the values.
37301 	 */
37302 
37303 	duk_set_length(thr, -1, arr_idx);
37304 
37305 	/* [ ... arr ] */
37306 
37307 	DUK_DDD(DUK_DDDPRINT("parse_array: final array is %!T",
37308 	                     (duk_tval *) duk_get_tval(thr, -1)));
37309 
37310 	duk__json_dec_objarr_exit(js_ctx);
37311 	return;
37312 
37313  syntax_error:
37314 	duk__json_dec_syntax_error(js_ctx);
37315 	DUK_UNREACHABLE();
37316 }
37317 
duk__json_dec_value(duk_json_dec_ctx * js_ctx)37318 DUK_LOCAL void duk__json_dec_value(duk_json_dec_ctx *js_ctx) {
37319 	duk_hthread *thr = js_ctx->thr;
37320 	duk_uint8_t x;
37321 
37322 	x = duk__json_dec_get_nonwhite(js_ctx);
37323 
37324 	DUK_DDD(DUK_DDDPRINT("parse_value: initial x=%ld", (long) x));
37325 
37326 	/* Note: duk__json_dec_req_stridx() backtracks one char */
37327 
37328 	if (x == DUK_ASC_DOUBLEQUOTE) {
37329 		duk__json_dec_string(js_ctx);
37330 	} else if ((x >= DUK_ASC_0 && x <= DUK_ASC_9) || (x == DUK_ASC_MINUS)) {
37331 #if defined(DUK_USE_JX)
37332 		if (js_ctx->flag_ext_custom && x == DUK_ASC_MINUS && duk__json_dec_peek(js_ctx) == DUK_ASC_UC_I) {
37333 			duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY);  /* "-Infinity", '-' has been eaten */
37334 			duk_push_number(thr, -DUK_DOUBLE_INFINITY);
37335 		} else {
37336 #else
37337 		{  /* unconditional block */
37338 #endif
37339 			/* We already ate 'x', so backup one byte. */
37340 			js_ctx->p--;  /* safe */
37341 			duk__json_dec_number(js_ctx);
37342 		}
37343 	} else if (x == DUK_ASC_LC_T) {
37344 		duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_TRUE);
37345 		duk_push_true(thr);
37346 	} else if (x == DUK_ASC_LC_F) {
37347 		duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_FALSE);
37348 		duk_push_false(thr);
37349 	} else if (x == DUK_ASC_LC_N) {
37350 		duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_LC_NULL);
37351 		duk_push_null(thr);
37352 #if defined(DUK_USE_JX)
37353 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_LC_U) {
37354 		duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_LC_UNDEFINED);
37355 		duk_push_undefined(thr);
37356 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_N) {
37357 		duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_NAN);
37358 		duk_push_nan(thr);
37359 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_I) {
37360 		duk__json_dec_req_stridx(js_ctx, DUK_STRIDX_INFINITY);
37361 		duk_push_number(thr, DUK_DOUBLE_INFINITY);
37362 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_LPAREN) {
37363 		duk__json_dec_pointer(js_ctx);
37364 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_PIPE) {
37365 		duk__json_dec_buffer(js_ctx);
37366 #endif
37367 	} else if (x == DUK_ASC_LCURLY) {
37368 		duk__json_dec_object(js_ctx);
37369 	} else if (x == DUK_ASC_LBRACKET) {
37370 		duk__json_dec_array(js_ctx);
37371 	} else {
37372 		/* catches EOF (NUL) */
37373 		goto syntax_error;
37374 	}
37375 
37376 	duk__json_dec_eat_white(js_ctx);
37377 
37378 	/* [ ... val ] */
37379 	return;
37380 
37381  syntax_error:
37382 	duk__json_dec_syntax_error(js_ctx);
37383 	DUK_UNREACHABLE();
37384 }
37385 
37386 /* Recursive value reviver, implements the Walk() algorithm.  The parsing
37387  * step ensures there is a reasonable depth limit to the input.  However,
37388  * the reviver may create more depth by editing object or array entries, so
37389  * we have both C recursion limit and native stack checks here.
37390  */
37391 DUK_LOCAL void duk__json_dec_reviver_walk(duk_json_dec_ctx *js_ctx) {
37392 	duk_hthread *thr = js_ctx->thr;
37393 	duk_hobject *h;
37394 	duk_uarridx_t i, arr_len;
37395 
37396 	duk__json_dec_objarr_entry(js_ctx);
37397 
37398 	DUK_DDD(DUK_DDDPRINT("walk: top=%ld, holder=%!T, name=%!T",
37399 	                     (long) duk_get_top(thr),
37400 	                     (duk_tval *) duk_get_tval(thr, -2),
37401 	                     (duk_tval *) duk_get_tval(thr, -1)));
37402 
37403 	duk_dup_top(thr);
37404 	duk_get_prop(thr, -3);  /* -> [ ... holder name val ] */
37405 
37406 	h = duk_get_hobject(thr, -1);
37407 	if (h != NULL) {
37408 		if (duk_js_isarray_hobject(h)) {
37409 			arr_len = (duk_uarridx_t) duk_get_length(thr, -1);
37410 			for (i = 0; i < arr_len; i++) {
37411 				/* [ ... holder name val ] */
37412 
37413 				DUK_DDD(DUK_DDDPRINT("walk: array, top=%ld, i=%ld, arr_len=%ld, holder=%!T, name=%!T, val=%!T",
37414 				                     (long) duk_get_top(thr), (long) i, (long) arr_len,
37415 				                     (duk_tval *) duk_get_tval(thr, -3), (duk_tval *) duk_get_tval(thr, -2),
37416 				                     (duk_tval *) duk_get_tval(thr, -1)));
37417 
37418 				duk_dup_top(thr);
37419 				(void) duk_push_uint_to_hstring(thr, (duk_uint_t) i);  /* -> [ ... holder name val val ToString(i) ] */
37420 				duk__json_dec_reviver_walk(js_ctx);  /* -> [ ... holder name val new_elem ] */
37421 
37422 				if (duk_is_undefined(thr, -1)) {
37423 					duk_pop(thr);
37424 					duk_del_prop_index(thr, -1, i);
37425 				} else {
37426 					/* XXX: duk_xdef_prop_index_wec() would be more appropriate
37427 					 * here but it currently makes some assumptions that might
37428 					 * not hold (e.g. that previous property is not an accessor).
37429 					 */
37430 					duk_put_prop_index(thr, -2, i);
37431 				}
37432 			}
37433 		} else {
37434 			/* [ ... holder name val ] */
37435 			duk_enum(thr, -1, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);
37436 			while (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {
37437 				DUK_DDD(DUK_DDDPRINT("walk: object, top=%ld, holder=%!T, name=%!T, val=%!T, enum=%!iT, obj_key=%!T",
37438 				                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -5),
37439 				                     (duk_tval *) duk_get_tval(thr, -4), (duk_tval *) duk_get_tval(thr, -3),
37440 				                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
37441 
37442 				/* [ ... holder name val enum obj_key ] */
37443 				duk_dup_m3(thr);
37444 				duk_dup_m2(thr);
37445 
37446 				/* [ ... holder name val enum obj_key val obj_key ] */
37447 				duk__json_dec_reviver_walk(js_ctx);
37448 
37449 				/* [ ... holder name val enum obj_key new_elem ] */
37450 				if (duk_is_undefined(thr, -1)) {
37451 					duk_pop(thr);
37452 					duk_del_prop(thr, -3);
37453 				} else {
37454 					/* XXX: duk_xdef_prop_index_wec() would be more appropriate
37455 					 * here but it currently makes some assumptions that might
37456 					 * not hold (e.g. that previous property is not an accessor).
37457 					 *
37458 					 * Using duk_put_prop() works incorrectly with '__proto__'
37459 					 * if the own property with that name has been deleted.  This
37460 					 * does not happen normally, but a clever reviver can trigger
37461 					 * that, see complex reviver case in: test-bug-json-parse-__proto__.js.
37462 					 */
37463 					duk_put_prop(thr, -4);
37464 				}
37465 			}
37466 			duk_pop(thr);  /* pop enum */
37467 		}
37468 	}
37469 
37470 	/* [ ... holder name val ] */
37471 
37472 	duk_dup(thr, js_ctx->idx_reviver);
37473 	duk_insert(thr, -4);  /* -> [ ... reviver holder name val ] */
37474 	duk_call_method(thr, 2);  /* -> [ ... res ] */
37475 
37476 	duk__json_dec_objarr_exit(js_ctx);
37477 
37478 	DUK_DDD(DUK_DDDPRINT("walk: top=%ld, result=%!T",
37479 	                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -1)));
37480 }
37481 
37482 /*
37483  *  Stringify implementation.
37484  */
37485 
37486 #define DUK__EMIT_1(js_ctx,ch)          duk__emit_1((js_ctx), (duk_uint_fast8_t) (ch))
37487 #define DUK__EMIT_2(js_ctx,ch1,ch2)     duk__emit_2((js_ctx), (duk_uint_fast8_t) (ch1), (duk_uint_fast8_t) (ch2))
37488 #define DUK__EMIT_HSTR(js_ctx,h)        duk__emit_hstring((js_ctx), (h))
37489 #if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
37490 #define DUK__EMIT_CSTR(js_ctx,p)        duk__emit_cstring((js_ctx), (p))
37491 #endif
37492 #define DUK__EMIT_STRIDX(js_ctx,i)      duk__emit_stridx((js_ctx), (i))
37493 #define DUK__UNEMIT_1(js_ctx)           duk__unemit_1((js_ctx))
37494 
37495 DUK_LOCAL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch) {
37496 	DUK_BW_WRITE_ENSURE_U8(js_ctx->thr, &js_ctx->bw, ch);
37497 }
37498 
37499 DUK_LOCAL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2) {
37500 	DUK_BW_WRITE_ENSURE_U8_2(js_ctx->thr, &js_ctx->bw, ch1, ch2);
37501 }
37502 
37503 DUK_LOCAL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h) {
37504 	DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
37505 }
37506 
37507 #if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
37508 DUK_LOCAL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *str) {
37509 	DUK_BW_WRITE_ENSURE_CSTRING(js_ctx->thr, &js_ctx->bw, str);
37510 }
37511 #endif
37512 
37513 DUK_LOCAL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx) {
37514 	duk_hstring *h;
37515 
37516 	DUK_ASSERT_STRIDX_VALID(stridx);
37517 	h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
37518 	DUK_ASSERT(h != NULL);
37519 
37520 	DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
37521 }
37522 
37523 DUK_LOCAL void duk__unemit_1(duk_json_enc_ctx *js_ctx) {
37524 	DUK_ASSERT(DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw) >= 1);
37525 	DUK_BW_ADD_PTR(js_ctx->thr, &js_ctx->bw, -1);
37526 }
37527 
37528 #define DUK__MKESC(nybbles,esc1,esc2)  \
37529 	(((duk_uint_fast32_t) (nybbles)) << 16) | \
37530 	(((duk_uint_fast32_t) (esc1)) << 8) | \
37531 	((duk_uint_fast32_t) (esc2))
37532 
37533 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) {
37534 	duk_uint_fast32_t tmp;
37535 	duk_small_uint_t dig;
37536 
37537 	DUK_UNREF(js_ctx);
37538 
37539 	/* Caller ensures space for at least DUK__JSON_MAX_ESC_LEN. */
37540 
37541 	/* Select appropriate escape format automatically, and set 'tmp' to a
37542 	 * value encoding both the escape format character and the nybble count:
37543 	 *
37544 	 *   (nybble_count << 16) | (escape_char1) | (escape_char2)
37545 	 */
37546 
37547 #if defined(DUK_USE_JX)
37548 	if (DUK_LIKELY(cp < 0x100UL)) {
37549 		if (DUK_UNLIKELY(js_ctx->flag_ext_custom != 0U)) {
37550 			tmp = DUK__MKESC(2, DUK_ASC_BACKSLASH, DUK_ASC_LC_X);
37551 		} else {
37552 			tmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U);
37553 		}
37554 	} else
37555 #endif
37556 	if (DUK_LIKELY(cp < 0x10000UL)) {
37557 		tmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U);
37558 	} else {
37559 #if defined(DUK_USE_JX)
37560 		if (DUK_LIKELY(js_ctx->flag_ext_custom != 0U)) {
37561 			tmp = DUK__MKESC(8, DUK_ASC_BACKSLASH, DUK_ASC_UC_U);
37562 		} else
37563 #endif
37564 		{
37565 			/* In compatible mode and standard JSON mode, output
37566 			 * something useful for non-BMP characters.  This won't
37567 			 * roundtrip but will still be more or less readable and
37568 			 * more useful than an error.
37569 			 */
37570 			tmp = DUK__MKESC(8, DUK_ASC_UC_U, DUK_ASC_PLUS);
37571 		}
37572 	}
37573 
37574 	*q++ = (duk_uint8_t) ((tmp >> 8) & 0xff);
37575 	*q++ = (duk_uint8_t) (tmp & 0xff);
37576 
37577 	tmp = tmp >> 16;
37578 	while (tmp > 0) {
37579 		tmp--;
37580 		dig = (duk_small_uint_t) ((cp >> (4 * tmp)) & 0x0f);
37581 		*q++ = duk_lc_digits[dig];
37582 	}
37583 
37584 	return q;
37585 }
37586 
37587 DUK_LOCAL void duk__json_enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k) {
37588 	const duk_int8_t *p, *p_start, *p_end;  /* Note: intentionally signed. */
37589 	duk_size_t k_len;
37590 	duk_codepoint_t cp;
37591 
37592 	DUK_ASSERT(k != NULL);
37593 
37594 	/* Accept ASCII strings which conform to identifier requirements
37595 	 * as being emitted without key quotes.  Since we only accept ASCII
37596 	 * there's no need for actual decoding: 'p' is intentionally signed
37597 	 * so that bytes >= 0x80 extend to negative values and are rejected
37598 	 * as invalid identifier codepoints.
37599 	 */
37600 
37601 	if (js_ctx->flag_avoid_key_quotes) {
37602 		k_len = DUK_HSTRING_GET_BYTELEN(k);
37603 		p_start = (const duk_int8_t *) DUK_HSTRING_GET_DATA(k);
37604 		p_end = p_start + k_len;
37605 		p = p_start;
37606 
37607 		if (p == p_end) {
37608 			/* Zero length string is not accepted without quotes */
37609 			goto quote_normally;
37610 		}
37611 		cp = (duk_codepoint_t) (*p++);
37612 		if (DUK_UNLIKELY(!duk_unicode_is_identifier_start(cp))) {
37613 			goto quote_normally;
37614 		}
37615 		while (p < p_end) {
37616 			cp = (duk_codepoint_t) (*p++);
37617 			if (DUK_UNLIKELY(!duk_unicode_is_identifier_part(cp))) {
37618 				goto quote_normally;
37619 			}
37620 		}
37621 
37622 		/* This seems faster than emitting bytes one at a time and
37623 		 * then potentially rewinding.
37624 		 */
37625 		DUK__EMIT_HSTR(js_ctx, k);
37626 		return;
37627 	}
37628 
37629  quote_normally:
37630 	duk__json_enc_quote_string(js_ctx, k);
37631 }
37632 
37633 /* The Quote(value) operation: quote a string.
37634  *
37635  * Stack policy: [ ] -> [ ].
37636  */
37637 
37638 DUK_LOCAL void duk__json_enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str) {
37639 	duk_hthread *thr = js_ctx->thr;
37640 	const duk_uint8_t *p, *p_start, *p_end, *p_now, *p_tmp;
37641 	duk_uint8_t *q;
37642 	duk_ucodepoint_t cp;  /* typed for duk_unicode_decode_xutf8() */
37643 
37644 	DUK_DDD(DUK_DDDPRINT("duk__json_enc_quote_string: h_str=%!O", (duk_heaphdr *) h_str));
37645 
37646 	DUK_ASSERT(h_str != NULL);
37647 	p_start = DUK_HSTRING_GET_DATA(h_str);
37648 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_str);
37649 	p = p_start;
37650 
37651 	DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE);
37652 
37653 	/* Encode string in small chunks, estimating the maximum expansion so that
37654 	 * there's no need to ensure space while processing the chunk.
37655 	 */
37656 
37657 	while (p < p_end) {
37658 		duk_size_t left, now, space;
37659 
37660 		left = (duk_size_t) (p_end - p);
37661 		now = (left > DUK__JSON_ENCSTR_CHUNKSIZE ?
37662 		       DUK__JSON_ENCSTR_CHUNKSIZE : left);
37663 
37664 		/* Maximum expansion per input byte is 6:
37665 		 *   - invalid UTF-8 byte causes "\uXXXX" to be emitted (6/1 = 6).
37666 		 *   - 2-byte UTF-8 encodes as "\uXXXX" (6/2 = 3).
37667 		 *   - 4-byte UTF-8 encodes as "\Uxxxxxxxx" (10/4 = 2.5).
37668 		 */
37669 		space = now * 6;
37670 		q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
37671 
37672 		p_now = p + now;
37673 
37674 		while (p < p_now) {
37675 #if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
37676 			duk_uint8_t b;
37677 
37678 			b = duk__json_quotestr_lookup[*p++];
37679 			if (DUK_LIKELY(b < 0x80)) {
37680 				/* Most input bytes go through here. */
37681 				*q++ = b;
37682 			} else if (b >= 0xa0) {
37683 				*q++ = DUK_ASC_BACKSLASH;
37684 				*q++ = (duk_uint8_t) (b - 0x80);
37685 			} else if (b == 0x80) {
37686 				cp = (duk_ucodepoint_t) (*(p - 1));
37687 				q = duk__emit_esc_auto_fast(js_ctx, cp, q);
37688 			} else if (b == 0x7f && js_ctx->flag_ascii_only) {
37689 				/* 0x7F is special */
37690 				DUK_ASSERT(b == 0x81);
37691 				cp = (duk_ucodepoint_t) 0x7f;
37692 				q = duk__emit_esc_auto_fast(js_ctx, cp, q);
37693 			} else {
37694 				DUK_ASSERT(b == 0x81);
37695 				p--;
37696 
37697 				/* slow path is shared */
37698 #else  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
37699 			cp = *p;
37700 
37701 			if (DUK_LIKELY(cp <= 0x7f)) {
37702 				/* ascii fast path: avoid decoding utf-8 */
37703 				p++;
37704 				if (cp == 0x22 || cp == 0x5c) {
37705 					/* double quote or backslash */
37706 					*q++ = DUK_ASC_BACKSLASH;
37707 					*q++ = (duk_uint8_t) cp;
37708 				} else if (cp < 0x20) {
37709 					duk_uint_fast8_t esc_char;
37710 
37711 					/* This approach is a bit shorter than a straight
37712 					 * if-else-ladder and also a bit faster.
37713 					 */
37714 					if (cp < (sizeof(duk__json_quotestr_esc) / sizeof(duk_uint8_t)) &&
37715 					    (esc_char = duk__json_quotestr_esc[cp]) != 0) {
37716 						*q++ = DUK_ASC_BACKSLASH;
37717 						*q++ = (duk_uint8_t) esc_char;
37718 					} else {
37719 						q = duk__emit_esc_auto_fast(js_ctx, cp, q);
37720 					}
37721 				} else if (cp == 0x7f && js_ctx->flag_ascii_only) {
37722 					q = duk__emit_esc_auto_fast(js_ctx, cp, q);
37723 				} else {
37724 					/* any other printable -> as is */
37725 					*q++ = (duk_uint8_t) cp;
37726 				}
37727 			} else {
37728 				/* slow path is shared */
37729 #endif  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
37730 
37731 				/* slow path decode */
37732 
37733 				/* If XUTF-8 decoding fails, treat the offending byte as a codepoint directly
37734 				 * and go forward one byte.  This is of course very lossy, but allows some kind
37735 				 * of output to be produced even for internal strings which don't conform to
37736 				 * XUTF-8.  All standard ECMAScript strings are always CESU-8, so this behavior
37737 				 * does not violate the ECMAScript specification.  The behavior is applied to
37738 				 * all modes, including ECMAScript standard JSON.  Because the current XUTF-8
37739 				 * decoding is not very strict, this behavior only really affects initial bytes
37740 				 * and truncated codepoints.
37741 				 *
37742 				 * Another alternative would be to scan forwards to start of next codepoint
37743 				 * (or end of input) and emit just one replacement codepoint.
37744 				 */
37745 
37746 				p_tmp = p;
37747 				if (!duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
37748 					/* Decode failed. */
37749 					cp = *p_tmp;
37750 					p = p_tmp + 1;
37751 				}
37752 
37753 #if defined(DUK_USE_NONSTD_JSON_ESC_U2028_U2029)
37754 				if (js_ctx->flag_ascii_only || cp == 0x2028 || cp == 0x2029) {
37755 #else
37756 				if (js_ctx->flag_ascii_only) {
37757 #endif
37758 					q = duk__emit_esc_auto_fast(js_ctx, cp, q);
37759 				} else {
37760 					/* as is */
37761 					DUK_RAW_WRITEINC_XUTF8(q, cp);
37762 				}
37763 			}
37764 		}
37765 
37766 		DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
37767 	}
37768 
37769 	DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE);
37770 }
37771 
37772 /* Encode a double (checked by caller) from stack top.  Stack top may be
37773  * replaced by serialized string but is not popped (caller does that).
37774  */
37775 DUK_LOCAL void duk__json_enc_double(duk_json_enc_ctx *js_ctx) {
37776 	duk_hthread *thr;
37777 	duk_tval *tv;
37778 	duk_double_t d;
37779 	duk_small_int_t c;
37780 	duk_small_int_t s;
37781 	duk_small_uint_t stridx;
37782 	duk_small_uint_t n2s_flags;
37783 	duk_hstring *h_str;
37784 
37785 	DUK_ASSERT(js_ctx != NULL);
37786 	thr = js_ctx->thr;
37787 	DUK_ASSERT(thr != NULL);
37788 
37789 	/* Caller must ensure 'tv' is indeed a double and not a fastint! */
37790 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
37791 	DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
37792 	d = DUK_TVAL_GET_DOUBLE(tv);
37793 
37794 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
37795 	s = (duk_small_int_t) DUK_SIGNBIT(d);
37796 	DUK_UNREF(s);
37797 
37798 	if (DUK_LIKELY(!(c == DUK_FP_INFINITE || c == DUK_FP_NAN))) {
37799 		DUK_ASSERT(DUK_ISFINITE(d));
37800 
37801 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37802 		/* Negative zero needs special handling in JX/JC because
37803 		 * it would otherwise serialize to '0', not '-0'.
37804 		 */
37805 		if (DUK_UNLIKELY(c == DUK_FP_ZERO && s != 0 &&
37806 		                 (js_ctx->flag_ext_custom_or_compatible))) {
37807 			duk_push_hstring_stridx(thr, DUK_STRIDX_MINUS_ZERO);  /* '-0' */
37808 		} else
37809 #endif  /* DUK_USE_JX || DUK_USE_JC */
37810 		{
37811 			n2s_flags = 0;
37812 			/* [ ... number ] -> [ ... string ] */
37813 			duk_numconv_stringify(thr, 10 /*radix*/, 0 /*digits*/, n2s_flags);
37814 		}
37815 		h_str = duk_known_hstring(thr, -1);
37816 		DUK__EMIT_HSTR(js_ctx, h_str);
37817 		return;
37818 	}
37819 
37820 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37821 	if (!(js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
37822 	                       DUK_JSON_FLAG_EXT_COMPATIBLE))) {
37823 		stridx = DUK_STRIDX_LC_NULL;
37824 	} else if (c == DUK_FP_NAN) {
37825 		stridx = js_ctx->stridx_custom_nan;
37826 	} else if (s == 0) {
37827 		stridx = js_ctx->stridx_custom_posinf;
37828 	} else {
37829 		stridx = js_ctx->stridx_custom_neginf;
37830 	}
37831 #else
37832 	stridx = DUK_STRIDX_LC_NULL;
37833 #endif
37834 	DUK__EMIT_STRIDX(js_ctx, stridx);
37835 }
37836 
37837 #if defined(DUK_USE_FASTINT)
37838 /* Encode a fastint from duk_tval ptr, no value stack effects. */
37839 DUK_LOCAL void duk__json_enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
37840 	duk_int64_t v;
37841 
37842 	/* Fastint range is signed 48-bit so longest value is -2^47 = -140737488355328
37843 	 * (16 chars long), longest signed 64-bit value is -2^63 = -9223372036854775808
37844 	 * (20 chars long).  Alloc space for 64-bit range to be safe.
37845 	 */
37846 	duk_uint8_t buf[20 + 1];
37847 
37848 	/* Caller must ensure 'tv' is indeed a fastint! */
37849 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
37850 	v = DUK_TVAL_GET_FASTINT(tv);
37851 
37852 	/* XXX: There are no format strings in duk_config.h yet, could add
37853 	 * one for formatting duk_int64_t.  For now, assumes "%lld" and that
37854 	 * "long long" type exists.  Could also rely on C99 directly but that
37855 	 * won't work for older MSVC.
37856 	 */
37857 	DUK_SPRINTF((char *) buf, "%lld", (long long) v);
37858 	DUK__EMIT_CSTR(js_ctx, (const char *) buf);
37859 }
37860 #endif
37861 
37862 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37863 #if defined(DUK_USE_HEX_FASTPATH)
37864 DUK_LOCAL duk_uint8_t *duk__json_enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
37865 	duk_uint8_t *q;
37866 	duk_uint16_t *q16;
37867 	duk_small_uint_t x;
37868 	duk_size_t i, len_safe;
37869 #if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
37870 	duk_bool_t shift_dst;
37871 #endif
37872 
37873 	/* Unlike in duk_hex_encode() 'dst' is not necessarily aligned by 2.
37874 	 * For platforms where unaligned accesses are not allowed, shift 'dst'
37875 	 * ahead by 1 byte to get alignment and then duk_memmove() the result
37876 	 * in place.  The faster encoding loop makes up the difference.
37877 	 * There's always space for one extra byte because a terminator always
37878 	 * follows the hex data and that's been accounted for by the caller.
37879 	 */
37880 
37881 #if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
37882 	q16 = (duk_uint16_t *) (void *) dst;
37883 #else
37884 	shift_dst = (duk_bool_t) (((duk_size_t) dst) & 0x01U);
37885 	if (shift_dst) {
37886 		DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst not aligned -> step to dst + 1"));
37887 		q16 = (duk_uint16_t *) (void *) (dst + 1);
37888 	} else {
37889 		DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst is aligned"));
37890 		q16 = (duk_uint16_t *) (void *) dst;
37891 	}
37892 	DUK_ASSERT((((duk_size_t) q16) & 0x01U) == 0);
37893 #endif
37894 
37895 	len_safe = src_len & ~0x03U;
37896 	for (i = 0; i < len_safe; i += 4) {
37897 		q16[0] = duk_hex_enctab[src[i]];
37898 		q16[1] = duk_hex_enctab[src[i + 1]];
37899 		q16[2] = duk_hex_enctab[src[i + 2]];
37900 		q16[3] = duk_hex_enctab[src[i + 3]];
37901 		q16 += 4;
37902 	}
37903 	q = (duk_uint8_t *) q16;
37904 
37905 #if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
37906 	if (shift_dst) {
37907 		q--;
37908 		duk_memmove((void *) dst, (const void *) (dst + 1), 2 * len_safe);
37909 		DUK_ASSERT(dst + 2 * len_safe == q);
37910 	}
37911 #endif
37912 
37913 	for (; i < src_len; i++) {
37914 		x = src[i];
37915 		*q++ = duk_lc_digits[x >> 4];
37916 		*q++ = duk_lc_digits[x & 0x0f];
37917 	}
37918 
37919 	return q;
37920 }
37921 #else  /* DUK_USE_HEX_FASTPATH */
37922 DUK_LOCAL duk_uint8_t *duk__json_enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
37923 	const duk_uint8_t *p;
37924 	const duk_uint8_t *p_end;
37925 	duk_uint8_t *q;
37926 	duk_small_uint_t x;
37927 
37928 	p = src;
37929 	p_end = src + src_len;
37930 	q = dst;
37931 	while (p != p_end) {
37932 		x = *p++;
37933 		*q++ = duk_lc_digits[x >> 4];
37934 		*q++ = duk_lc_digits[x & 0x0f];
37935 	}
37936 
37937 	return q;
37938 }
37939 #endif  /* DUK_USE_HEX_FASTPATH */
37940 
37941 DUK_LOCAL void duk__json_enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len) {
37942 	duk_hthread *thr;
37943 	duk_uint8_t *q;
37944 	duk_size_t space;
37945 
37946 	thr = js_ctx->thr;
37947 
37948 	DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);  /* caller checks */
37949 	DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);
37950 
37951 	/* Buffer values are encoded in (lowercase) hex to make the
37952 	 * binary data readable.  Base64 or similar would be more
37953 	 * compact but less readable, and the point of JX/JC
37954 	 * variants is to be as useful to a programmer as possible.
37955 	 */
37956 
37957 	/* The #if defined() clutter here needs to handle the three
37958 	 * cases: (1) JX+JC, (2) JX only, (3) JC only.
37959 	 */
37960 
37961 	/* Note: space must cater for both JX and JC. */
37962 	space = 9 + buf_len * 2 + 2;
37963 	DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7ffffffeUL);
37964 	DUK_ASSERT((space - 2) / 2 >= buf_len);  /* overflow not possible, buffer limits */
37965 	q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
37966 
37967 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
37968 	if (js_ctx->flag_ext_custom)
37969 #endif
37970 #if defined(DUK_USE_JX)
37971 	{
37972 		*q++ = DUK_ASC_PIPE;
37973 		q = duk__json_enc_buffer_data_hex(buf_data, buf_len, q);
37974 		*q++ = DUK_ASC_PIPE;
37975 
37976 	}
37977 #endif
37978 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
37979 	else
37980 #endif
37981 #if defined(DUK_USE_JC)
37982 	{
37983 		DUK_ASSERT(js_ctx->flag_ext_compatible);
37984 		duk_memcpy((void *) q, (const void *) "{\"_buf\":\"", 9);  /* len: 9 */
37985 		q += 9;
37986 		q = duk__json_enc_buffer_data_hex(buf_data, buf_len, q);
37987 		*q++ = DUK_ASC_DOUBLEQUOTE;
37988 		*q++ = DUK_ASC_RCURLY;
37989 	}
37990 #endif
37991 
37992 	DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
37993 }
37994 
37995 DUK_LOCAL void duk__json_enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
37996 	duk__json_enc_buffer_data(js_ctx,
37997 	                     (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h),
37998 	                     (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
37999 }
38000 #endif  /* DUK_USE_JX || DUK_USE_JC */
38001 
38002 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
38003 DUK_LOCAL void duk__json_enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
38004 	duk_size_t i, n;
38005 	const duk_uint8_t *buf;
38006 	duk_uint8_t *q;
38007 
38008 	n = DUK_HBUFFER_GET_SIZE(h);
38009 	if (n == 0) {
38010 		DUK__EMIT_2(js_ctx, DUK_ASC_LCURLY, DUK_ASC_RCURLY);
38011 		return;
38012 	}
38013 
38014 	DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
38015 
38016 	/* Maximum encoded length with 32-bit index: 1 + 10 + 2 + 3 + 1 + 1 = 18,
38017 	 * with 64-bit index: 1 + 20 + 2 + 3 + 1 + 1 = 28.  32 has some slack.
38018 	 *
38019 	 * Note that because the output buffer is reallocated from time to time,
38020 	 * side effects (such as finalizers) affecting the buffer 'h' must be
38021 	 * disabled.  This is the case in the JSON.stringify() fast path.
38022 	 */
38023 
38024 	buf = (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h);
38025 	if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
38026 		for (i = 0; i < n; i++) {
38027 			duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth + 1);
38028 			q = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, 32);
38029 			q += DUK_SPRINTF((char *) q, "\"%lu\": %u,", (unsigned long) i, (unsigned int) buf[i]);
38030 			DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q);
38031 		}
38032 	} else {
38033 		q = DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw);
38034 		for (i = 0; i < n; i++) {
38035 			q = DUK_BW_ENSURE_RAW(js_ctx->thr, &js_ctx->bw, 32, q);
38036 			q += DUK_SPRINTF((char *) q, "\"%lu\":%u,", (unsigned long) i, (unsigned int) buf[i]);
38037 		}
38038 		DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q);
38039 	}
38040 	DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
38041 
38042 	if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
38043 		duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth);
38044 	}
38045 	DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
38046 }
38047 #endif  /* DUK_USE_JSON_STRINGIFY_FASTPATH */
38048 
38049 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38050 DUK_LOCAL void duk__json_enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) {
38051 	char buf[64];  /* XXX: how to figure correct size? */
38052 	const char *fmt;
38053 
38054 	DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);  /* caller checks */
38055 	DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);
38056 
38057 	duk_memzero(buf, sizeof(buf));
38058 
38059 	/* The #if defined() clutter here needs to handle the three
38060 	 * cases: (1) JX+JC, (2) JX only, (3) JC only.
38061 	 */
38062 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
38063 	if (js_ctx->flag_ext_custom)
38064 #endif
38065 #if defined(DUK_USE_JX)
38066 	{
38067 		fmt = ptr ? "(%p)" : "(null)";
38068 	}
38069 #endif
38070 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
38071 	else
38072 #endif
38073 #if defined(DUK_USE_JC)
38074 	{
38075 		DUK_ASSERT(js_ctx->flag_ext_compatible);
38076 		fmt = ptr ? "{\"_ptr\":\"%p\"}" : "{\"_ptr\":\"null\"}";
38077 	}
38078 #endif
38079 
38080 	/* When ptr == NULL, the format argument is unused. */
38081 	DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr);  /* must not truncate */
38082 	DUK__EMIT_CSTR(js_ctx, buf);
38083 }
38084 #endif  /* DUK_USE_JX || DUK_USE_JC */
38085 
38086 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
38087 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38088 DUK_LOCAL void duk__json_enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj) {
38089 	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
38090 
38091 	if (h_bufobj->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
38092 		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
38093 	} else {
38094 		/* Handle both full and partial slice (as long as covered). */
38095 		duk__json_enc_buffer_data(js_ctx,
38096 		                     (duk_uint8_t *) DUK_HBUFOBJ_GET_SLICE_BASE(js_ctx->thr->heap, h_bufobj),
38097 		                     (duk_size_t) h_bufobj->length);
38098 	}
38099 }
38100 #endif  /* DUK_USE_JX || DUK_USE_JC */
38101 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
38102 
38103 /* Indent helper.  Calling code relies on js_ctx->recursion_depth also being
38104  * directly related to indent depth.
38105  */
38106 #if defined(DUK_USE_PREFER_SIZE)
38107 DUK_LOCAL void duk__json_enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {
38108 	DUK_ASSERT(js_ctx->h_gap != NULL);
38109 	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0);  /* caller guarantees */
38110 
38111 	DUK__EMIT_1(js_ctx, 0x0a);
38112 	while (depth-- > 0) {
38113 		DUK__EMIT_HSTR(js_ctx, js_ctx->h_gap);
38114 	}
38115 }
38116 #else  /* DUK_USE_PREFER_SIZE */
38117 DUK_LOCAL void duk__json_enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {
38118 	const duk_uint8_t *gap_data;
38119 	duk_size_t gap_len;
38120 	duk_size_t avail_bytes;   /* bytes of indent available for copying */
38121 	duk_size_t need_bytes;    /* bytes of indent still needed */
38122 	duk_uint8_t *p_start;
38123 	duk_uint8_t *p;
38124 
38125 	DUK_ASSERT(js_ctx->h_gap != NULL);
38126 	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0);  /* caller guarantees */
38127 
38128 	DUK__EMIT_1(js_ctx, 0x0a);
38129 	if (DUK_UNLIKELY(depth == 0)) {
38130 		return;
38131 	}
38132 
38133 	/* To handle deeper indents efficiently, make use of copies we've
38134 	 * already emitted.  In effect we can emit a sequence of 1, 2, 4,
38135 	 * 8, etc copies, and then finish the last run.  Byte counters
38136 	 * avoid multiply with gap_len on every loop.
38137 	 */
38138 
38139 	gap_data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(js_ctx->h_gap);
38140 	gap_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap);
38141 	DUK_ASSERT(gap_len > 0);
38142 
38143 	need_bytes = gap_len * depth;
38144 	p = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, need_bytes);
38145 	p_start = p;
38146 
38147 	duk_memcpy((void *) p, (const void *) gap_data, (size_t) gap_len);
38148 	p += gap_len;
38149 	avail_bytes = gap_len;
38150 	DUK_ASSERT(need_bytes >= gap_len);
38151 	need_bytes -= gap_len;
38152 
38153 	while (need_bytes >= avail_bytes) {
38154 		duk_memcpy((void *) p, (const void *) p_start, (size_t) avail_bytes);
38155 		p += avail_bytes;
38156 		need_bytes -= avail_bytes;
38157 		avail_bytes <<= 1;
38158 	}
38159 
38160 	DUK_ASSERT(need_bytes < avail_bytes);  /* need_bytes may be zero */
38161 	duk_memcpy((void *) p, (const void *) p_start, (size_t) need_bytes);
38162 	p += need_bytes;
38163 	/*avail_bytes += need_bytes*/
38164 
38165 	DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, p);
38166 }
38167 #endif  /* DUK_USE_PREFER_SIZE */
38168 
38169 /* Shared entry handling for object/array serialization. */
38170 DUK_LOCAL void duk__json_enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
38171 	duk_hthread *thr = js_ctx->thr;
38172 	duk_hobject *h_target;
38173 	duk_uint_fast32_t i, n;
38174 
38175 	*entry_top = duk_get_top(thr);
38176 
38177 	duk_native_stack_check(thr);
38178 	duk_require_stack(thr, DUK_JSON_ENC_REQSTACK);
38179 
38180 	/* Loop check using a hybrid approach: a fixed-size visited[] array
38181 	 * with overflow in a loop check object.
38182 	 */
38183 
38184 	h_target = duk_known_hobject(thr, -1);  /* object or array */
38185 
38186 	n = js_ctx->recursion_depth;
38187 	if (DUK_UNLIKELY(n > DUK_JSON_ENC_LOOPARRAY)) {
38188 		n = DUK_JSON_ENC_LOOPARRAY;
38189 	}
38190 	for (i = 0; i < n; i++) {
38191 		if (DUK_UNLIKELY(js_ctx->visiting[i] == h_target)) {
38192 			DUK_DD(DUK_DDPRINT("slow path loop detect"));
38193 			DUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT);
38194 			DUK_WO_NORETURN(return;);
38195 		}
38196 	}
38197 	if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
38198 		js_ctx->visiting[js_ctx->recursion_depth] = h_target;
38199 	} else {
38200 		duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) h_target);
38201 		duk_dup_top(thr);  /* -> [ ... voidp voidp ] */
38202 		if (duk_has_prop(thr, js_ctx->idx_loop)) {
38203 			DUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT);
38204 			DUK_WO_NORETURN(return;);
38205 		}
38206 		duk_push_true(thr);  /* -> [ ... voidp true ] */
38207 		duk_put_prop(thr, js_ctx->idx_loop);  /* -> [ ... ] */
38208 	}
38209 
38210 	/* C recursion check. */
38211 
38212 	DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */
38213 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
38214 	if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
38215 		DUK_ERROR_RANGE(thr, DUK_STR_ENC_RECLIMIT);
38216 		DUK_WO_NORETURN(return;);
38217 	}
38218 	js_ctx->recursion_depth++;
38219 
38220 	DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
38221 	                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop)));
38222 }
38223 
38224 /* Shared exit handling for object/array serialization. */
38225 DUK_LOCAL void duk__json_enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
38226 	duk_hthread *thr = js_ctx->thr;
38227 	duk_hobject *h_target;
38228 
38229 	/* C recursion check. */
38230 
38231 	DUK_ASSERT(js_ctx->recursion_depth > 0);
38232 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
38233 	js_ctx->recursion_depth--;
38234 
38235 	/* Loop check. */
38236 
38237 	h_target = duk_known_hobject(thr, *entry_top - 1);  /* original target at entry_top - 1 */
38238 
38239 	if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
38240 		/* Previous entry was inside visited[], nothing to do. */
38241 	} else {
38242 		duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) h_target);
38243 		duk_del_prop(thr, js_ctx->idx_loop);  /* -> [ ... ] */
38244 	}
38245 
38246 	/* Restore stack top after unbalanced code paths. */
38247 	duk_set_top(thr, *entry_top);
38248 
38249 	DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
38250 	                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop)));
38251 }
38252 
38253 /* The JO(value) operation: encode object.
38254  *
38255  * Stack policy: [ object ] -> [ object ].
38256  */
38257 DUK_LOCAL void duk__json_enc_object(duk_json_enc_ctx *js_ctx) {
38258 	duk_hthread *thr = js_ctx->thr;
38259 	duk_hstring *h_key;
38260 	duk_idx_t entry_top;
38261 	duk_idx_t idx_obj;
38262 	duk_idx_t idx_keys;
38263 	duk_bool_t emitted;
38264 	duk_uarridx_t arr_len, i;
38265 	duk_size_t prev_size;
38266 
38267 	DUK_DDD(DUK_DDDPRINT("duk__json_enc_object: obj=%!T", (duk_tval *) duk_get_tval(thr, -1)));
38268 
38269 	duk__json_enc_objarr_entry(js_ctx, &entry_top);
38270 
38271 	idx_obj = entry_top - 1;
38272 
38273 	if (js_ctx->idx_proplist >= 0) {
38274 		idx_keys = js_ctx->idx_proplist;
38275 	} else {
38276 		/* XXX: would be nice to enumerate an object at specified index */
38277 		duk_dup(thr, idx_obj);
38278 		(void) duk_hobject_get_enumerated_keys(thr, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);  /* [ ... target ] -> [ ... target keys ] */
38279 		idx_keys = duk_require_normalize_index(thr, -1);
38280 		/* leave stack unbalanced on purpose */
38281 	}
38282 
38283 	DUK_DDD(DUK_DDDPRINT("idx_keys=%ld, h_keys=%!T",
38284 	                     (long) idx_keys, (duk_tval *) duk_get_tval(thr, idx_keys)));
38285 
38286 	/* Steps 8-10 have been merged to avoid a "partial" variable. */
38287 
38288 	DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
38289 
38290 	/* XXX: keys is an internal object with all keys to be processed
38291 	 * in its (gapless) array part.  Because nobody can touch the keys
38292 	 * object, we could iterate its array part directly (keeping in mind
38293 	 * that it can be reallocated).
38294 	 */
38295 
38296 	arr_len = (duk_uarridx_t) duk_get_length(thr, idx_keys);
38297 	emitted = 0;
38298 	for (i = 0; i < arr_len; i++) {
38299 		duk_get_prop_index(thr, idx_keys, i);  /* -> [ ... key ] */
38300 
38301 		DUK_DDD(DUK_DDDPRINT("object property loop: holder=%!T, key=%!T",
38302 		                     (duk_tval *) duk_get_tval(thr, idx_obj),
38303 		                     (duk_tval *) duk_get_tval(thr, -1)));
38304 
38305 		h_key = duk_known_hstring(thr, -1);
38306 		DUK_ASSERT(h_key != NULL);
38307 		DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(h_key));  /* proplist filtering; enum options */
38308 
38309 		prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
38310 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
38311 			duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth);
38312 			duk__json_enc_key_autoquote(js_ctx, h_key);
38313 			DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
38314 		} else {
38315 			duk__json_enc_key_autoquote(js_ctx, h_key);
38316 			DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
38317 		}
38318 
38319 		/* [ ... key ] */
38320 
38321 		if (DUK_UNLIKELY(duk__json_enc_value(js_ctx, idx_obj) == 0)) {
38322 			/* Value would yield 'undefined', so skip key altogether.
38323 			 * Side effects have already happened.
38324 			 */
38325 			DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
38326 		} else {
38327 			DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
38328 			emitted = 1;
38329 		}
38330 
38331 		/* [ ... ] */
38332 	}
38333 
38334 	if (emitted) {
38335 		DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
38336 		DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
38337 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
38338 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
38339 			duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
38340 		}
38341 	}
38342 	DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
38343 
38344 	duk__json_enc_objarr_exit(js_ctx, &entry_top);
38345 
38346 	DUK_ASSERT_TOP(thr, entry_top);
38347 }
38348 
38349 /* The JA(value) operation: encode array.
38350  *
38351  * Stack policy: [ array ] -> [ array ].
38352  */
38353 DUK_LOCAL void duk__json_enc_array(duk_json_enc_ctx *js_ctx) {
38354 	duk_hthread *thr = js_ctx->thr;
38355 	duk_idx_t entry_top;
38356 	duk_idx_t idx_arr;
38357 	duk_bool_t emitted;
38358 	duk_uarridx_t i, arr_len;
38359 
38360 	DUK_DDD(DUK_DDDPRINT("duk__json_enc_array: array=%!T",
38361 	                     (duk_tval *) duk_get_tval(thr, -1)));
38362 
38363 	duk__json_enc_objarr_entry(js_ctx, &entry_top);
38364 
38365 	idx_arr = entry_top - 1;
38366 
38367 	/* Steps 8-10 have been merged to avoid a "partial" variable. */
38368 
38369 	DUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET);
38370 
38371 	arr_len = (duk_uarridx_t) duk_get_length(thr, idx_arr);
38372 	emitted = 0;
38373 	for (i = 0; i < arr_len; i++) {
38374 		DUK_DDD(DUK_DDDPRINT("array entry loop: array=%!T, index=%ld, arr_len=%ld",
38375 		                     (duk_tval *) duk_get_tval(thr, idx_arr),
38376 		                     (long) i, (long) arr_len));
38377 
38378 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
38379 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
38380 			duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth);
38381 		}
38382 
38383 		(void) duk_push_uint_to_hstring(thr, (duk_uint_t) i);  /* -> [ ... key ] */
38384 
38385 		/* [ ... key ] */
38386 
38387 		if (DUK_UNLIKELY(duk__json_enc_value(js_ctx, idx_arr) == 0)) {
38388 			/* Value would normally be omitted, replace with 'null'. */
38389 			DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
38390 		} else {
38391 			;
38392 		}
38393 
38394 		/* [ ... ] */
38395 
38396 		DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
38397 		emitted = 1;
38398 	}
38399 
38400 	if (emitted) {
38401 		DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
38402 		DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
38403 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
38404 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
38405 			duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
38406 		}
38407 	}
38408 	DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
38409 
38410 	duk__json_enc_objarr_exit(js_ctx, &entry_top);
38411 
38412 	DUK_ASSERT_TOP(thr, entry_top);
38413 }
38414 
38415 /* The Str(key, holder) operation.
38416  *
38417  * Stack policy: [ ... key ] -> [ ... ]
38418  */
38419 DUK_LOCAL duk_bool_t duk__json_enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder) {
38420 	duk_hthread *thr = js_ctx->thr;
38421 	duk_tval *tv;
38422 	duk_tval *tv_holder;
38423 	duk_tval *tv_key;
38424 	duk_small_int_t c;
38425 
38426 	DUK_DDD(DUK_DDDPRINT("duk__json_enc_value: idx_holder=%ld, holder=%!T, key=%!T",
38427 	                     (long) idx_holder, (duk_tval *) duk_get_tval(thr, idx_holder),
38428 	                     (duk_tval *) duk_get_tval(thr, -1)));
38429 
38430 	tv_holder = DUK_GET_TVAL_POSIDX(thr, idx_holder);
38431 	DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_holder));
38432 	tv_key = DUK_GET_TVAL_NEGIDX(thr, -1);
38433 	DUK_ASSERT(DUK_TVAL_IS_STRING(tv_key));
38434 	DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING(tv_key)));  /* Caller responsible. */
38435 	(void) duk_hobject_getprop(thr, tv_holder, tv_key);
38436 
38437 	/* -> [ ... key val ] */
38438 
38439 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
38440 
38441 	/* Standard JSON checks for .toJSON() only for actual objects; for
38442 	 * example, setting Number.prototype.toJSON and then serializing a
38443 	 * number won't invoke the .toJSON() method.  However, lightfuncs and
38444 	 * plain buffers mimic objects so we check for their .toJSON() method.
38445 	 */
38446 	if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |
38447 	                                 DUK_TYPE_MASK_LIGHTFUNC |
38448 	                                 DUK_TYPE_MASK_BUFFER)) {
38449 		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_JSON);
38450 		if (duk_is_callable(thr, -1)) {  /* toJSON() can also be a lightfunc */
38451 			DUK_DDD(DUK_DDDPRINT("value is object, has callable toJSON() -> call it"));
38452 			/* XXX: duk_dup_unvalidated(thr, -2) etc. */
38453 			duk_dup_m2(thr);          /* -> [ ... key val toJSON val ] */
38454 			duk_dup_m4(thr);          /* -> [ ... key val toJSON val key ] */
38455 			duk_call_method(thr, 1);  /* -> [ ... key val val' ] */
38456 			duk_remove_m2(thr);       /* -> [ ... key val' ] */
38457 		} else {
38458 			duk_pop(thr);             /* -> [ ... key val ] */
38459 		}
38460 	}
38461 
38462 	/* [ ... key val ] */
38463 
38464 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
38465 
38466 	if (js_ctx->h_replacer) {
38467 		/* XXX: Here a "slice copy" would be useful. */
38468 		DUK_DDD(DUK_DDDPRINT("replacer is set, call replacer"));
38469 		duk_push_hobject(thr, js_ctx->h_replacer);  /* -> [ ... key val replacer ] */
38470 		duk_dup(thr, idx_holder);                   /* -> [ ... key val replacer holder ] */
38471 		duk_dup_m4(thr);                            /* -> [ ... key val replacer holder key ] */
38472 		duk_dup_m4(thr);                            /* -> [ ... key val replacer holder key val ] */
38473 		duk_call_method(thr, 2);                    /* -> [ ... key val val' ] */
38474 		duk_remove_m2(thr);                         /* -> [ ... key val' ] */
38475 	}
38476 
38477 	/* [ ... key val ] */
38478 
38479 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
38480 
38481 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
38482 	if (DUK_TVAL_IS_OBJECT(tv)) {
38483 		duk_hobject *h;
38484 
38485 		h = DUK_TVAL_GET_OBJECT(tv);
38486 		DUK_ASSERT(h != NULL);
38487 
38488 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
38489 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38490 		if (DUK_HOBJECT_IS_BUFOBJ(h) &&
38491 		    js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE)) {
38492 			/* With JX/JC a bufferobject gets serialized specially. */
38493 			duk_hbufobj *h_bufobj;
38494 			h_bufobj = (duk_hbufobj *) h;
38495 			DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
38496 			duk__json_enc_bufobj(js_ctx, h_bufobj);
38497 			goto pop2_emitted;
38498 		}
38499 		/* Otherwise bufferobjects get serialized as normal objects. */
38500 #endif  /* JX || JC */
38501 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
38502 		c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
38503 		switch (c) {
38504 		case DUK_HOBJECT_CLASS_NUMBER: {
38505 			DUK_DDD(DUK_DDDPRINT("value is a Number object -> coerce with ToNumber()"));
38506 			duk_to_number_m1(thr);
38507 			/* The coercion potentially invokes user .valueOf() and .toString()
38508 			 * but can't result in a function value because ToPrimitive() would
38509 			 * reject such a result: test-dev-json-stringify-coercion-1.js.
38510 			 */
38511 			DUK_ASSERT(!duk_is_callable(thr, -1));
38512 			break;
38513 		}
38514 		case DUK_HOBJECT_CLASS_STRING: {
38515 			DUK_DDD(DUK_DDDPRINT("value is a String object -> coerce with ToString()"));
38516 			duk_to_string(thr, -1);
38517 			/* Same coercion behavior as for Number. */
38518 			DUK_ASSERT(!duk_is_callable(thr, -1));
38519 			break;
38520 		}
38521 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38522 		case DUK_HOBJECT_CLASS_POINTER:
38523 #endif
38524 		case DUK_HOBJECT_CLASS_BOOLEAN: {
38525 			DUK_DDD(DUK_DDDPRINT("value is a Boolean/Buffer/Pointer object -> get internal value"));
38526 			duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
38527 			duk_remove_m2(thr);
38528 			break;
38529 		}
38530 		default: {
38531 			/* Normal object which doesn't get automatically coerced to a
38532 			 * primitive value.  Functions are checked for specially.  The
38533 			 * primitive value coercions for Number, String, Pointer, and
38534 			 * Boolean can't result in functions so suffices to check here.
38535 			 * Symbol objects are handled like plain objects (their primitive
38536 			 * value is NOT looked up like for e.g. String objects).
38537 			 */
38538 			DUK_ASSERT(h != NULL);
38539 			if (DUK_HOBJECT_IS_CALLABLE(h)) {
38540 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38541 				if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
38542 				                     DUK_JSON_FLAG_EXT_COMPATIBLE)) {
38543 					/* We only get here when doing non-standard JSON encoding */
38544 					DUK_DDD(DUK_DDDPRINT("-> function allowed, serialize to custom format"));
38545 					DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);
38546 					DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
38547 					goto pop2_emitted;
38548 				} else {
38549 					DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
38550 					goto pop2_undef;
38551 				}
38552 #else  /* DUK_USE_JX || DUK_USE_JC */
38553 				DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
38554 				goto pop2_undef;
38555 #endif  /* DUK_USE_JX || DUK_USE_JC */
38556 			}
38557 		}
38558 		}  /* end switch */
38559 	}
38560 
38561 	/* [ ... key val ] */
38562 
38563 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
38564 
38565 	if (duk_check_type_mask(thr, -1, js_ctx->mask_for_undefined)) {
38566 		/* will result in undefined */
38567 		DUK_DDD(DUK_DDDPRINT("-> will result in undefined (type mask check)"));
38568 		goto pop2_undef;
38569 	}
38570 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
38571 
38572 	switch (DUK_TVAL_GET_TAG(tv)) {
38573 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38574 	/* When JX/JC not in use, the type mask above will avoid this case if needed. */
38575 	case DUK_TAG_UNDEFINED: {
38576 		DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
38577 		break;
38578 	}
38579 #endif
38580 	case DUK_TAG_NULL: {
38581 		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
38582 		break;
38583 	}
38584 	case DUK_TAG_BOOLEAN: {
38585 		DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?
38586 		                 DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
38587 		break;
38588 	}
38589 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38590 	/* When JX/JC not in use, the type mask above will avoid this case if needed. */
38591 	case DUK_TAG_POINTER: {
38592 		duk__json_enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
38593 		break;
38594 	}
38595 #endif  /* DUK_USE_JX || DUK_USE_JC */
38596 	case DUK_TAG_STRING: {
38597 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
38598 		DUK_ASSERT(h != NULL);
38599 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
38600 			goto pop2_undef;
38601 		}
38602 		duk__json_enc_quote_string(js_ctx, h);
38603 		break;
38604 	}
38605 	case DUK_TAG_OBJECT: {
38606 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
38607 		DUK_ASSERT(h != NULL);
38608 
38609 		/* Function values are handled completely above (including
38610 		 * coercion results):
38611 		 */
38612 		DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE(h));
38613 
38614 		if (duk_js_isarray_hobject(h)) {
38615 			duk__json_enc_array(js_ctx);
38616 		} else {
38617 			duk__json_enc_object(js_ctx);
38618 		}
38619 		break;
38620 	}
38621 	/* Because plain buffers mimics Uint8Array, they have enumerable
38622 	 * index properties [0,byteLength[.  Because JSON only serializes
38623 	 * enumerable own properties, no properties can be serialized for
38624 	 * plain buffers (all virtual properties are non-enumerable).  However,
38625 	 * there may be a .toJSON() method which was already handled above.
38626 	 */
38627 	case DUK_TAG_BUFFER: {
38628 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38629 		if (js_ctx->flag_ext_custom_or_compatible) {
38630 			duk__json_enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));
38631 			break;
38632 		}
38633 #endif
38634 
38635 		/* Could implement a fastpath, but the fast path would need
38636 		 * to handle realloc side effects correctly.
38637 		 */
38638 		duk_to_object(thr, -1);
38639 		duk__json_enc_object(js_ctx);
38640 		break;
38641 	}
38642 	case DUK_TAG_LIGHTFUNC: {
38643 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38644 		/* We only get here when doing non-standard JSON encoding */
38645 		DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);
38646 		DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
38647 #else
38648 		/* Standard JSON omits functions */
38649 		DUK_UNREACHABLE();
38650 #endif
38651 		break;
38652 	}
38653 #if defined(DUK_USE_FASTINT)
38654 	case DUK_TAG_FASTINT:
38655 		/* Number serialization has a significant impact relative to
38656 		 * other fast path code, so careful fast path for fastints.
38657 		 */
38658 		duk__json_enc_fastint_tval(js_ctx, tv);
38659 		break;
38660 #endif
38661 	default: {
38662 		/* number */
38663 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
38664 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
38665 		/* XXX: A fast path for usual integers would be useful when
38666 		 * fastint support is not enabled.
38667 		 */
38668 		duk__json_enc_double(js_ctx);
38669 		break;
38670 	}
38671 	}
38672 
38673 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38674  pop2_emitted:
38675 #endif
38676 	duk_pop_2(thr); /* [ ... key val ] -> [ ... ] */
38677 	return 1;  /* emitted */
38678 
38679  pop2_undef:
38680 	duk_pop_2(thr);  /* [ ... key val ] -> [ ... ] */
38681 	return 0;  /* not emitted */
38682 }
38683 
38684 /* E5 Section 15.12.3, main algorithm, step 4.b.ii steps 1-4. */
38685 DUK_LOCAL duk_bool_t duk__json_enc_allow_into_proplist(duk_tval *tv) {
38686 	duk_small_int_t c;
38687 
38688 	/* XXX: some kind of external internal type checker?
38689 	 * - type mask; symbol flag; class mask
38690 	 */
38691 	DUK_ASSERT(tv != NULL);
38692 	if (DUK_TVAL_IS_STRING(tv)) {
38693 		duk_hstring *h;
38694 		h = DUK_TVAL_GET_STRING(tv);
38695 		DUK_ASSERT(h != NULL);
38696 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
38697 			return 0;
38698 		}
38699 		return 1;
38700 	} else if (DUK_TVAL_IS_NUMBER(tv)) {
38701 		return 1;
38702 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
38703 		duk_hobject *h;
38704 		h = DUK_TVAL_GET_OBJECT(tv);
38705 		DUK_ASSERT(h != NULL);
38706 		c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
38707 		if (c == DUK_HOBJECT_CLASS_STRING || c == DUK_HOBJECT_CLASS_NUMBER) {
38708 			return 1;
38709 		}
38710 	}
38711 
38712 	return 0;
38713 }
38714 
38715 /*
38716  *  JSON.stringify() fast path
38717  *
38718  *  Otherwise supports full JSON, JX, and JC features, but bails out on any
38719  *  possible side effect which might change the value being serialized.  The
38720  *  fast path can take advantage of the fact that the value being serialized
38721  *  is unchanged so that we can walk directly through property tables etc.
38722  */
38723 
38724 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
38725 DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
38726 	duk_uint_fast32_t i, n;
38727 
38728 	DUK_DDD(DUK_DDDPRINT("stringify fast: %!T", tv));
38729 
38730 	DUK_ASSERT(js_ctx != NULL);
38731 	DUK_ASSERT(js_ctx->thr != NULL);
38732 
38733 #if 0 /* disabled for now */
38734  restart_match:
38735 #endif
38736 
38737 	DUK_ASSERT(tv != NULL);
38738 
38739 	switch (DUK_TVAL_GET_TAG(tv)) {
38740 	case DUK_TAG_UNDEFINED: {
38741 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38742 		if (js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible) {
38743 			DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
38744 			break;
38745 		} else {
38746 			goto emit_undefined;
38747 		}
38748 #else
38749 		goto emit_undefined;
38750 #endif
38751 	}
38752 	case DUK_TAG_NULL: {
38753 		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
38754 		break;
38755 	}
38756 	case DUK_TAG_BOOLEAN: {
38757 		DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?
38758 		                 DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
38759 		break;
38760 	}
38761 	case DUK_TAG_STRING: {
38762 		duk_hstring *h;
38763 		h = DUK_TVAL_GET_STRING(tv);
38764 		DUK_ASSERT(h != NULL);
38765 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
38766 			goto emit_undefined;
38767 		}
38768 		duk__json_enc_quote_string(js_ctx, h);
38769 		break;
38770 	}
38771 	case DUK_TAG_OBJECT: {
38772 		duk_hobject *obj;
38773 		duk_tval *tv_val;
38774 		duk_bool_t emitted = 0;
38775 		duk_uint32_t c_bit, c_all, c_array, c_unbox, c_undef,
38776 		             c_func, c_bufobj, c_object, c_abort;
38777 
38778 		/* For objects JSON.stringify() only looks for own, enumerable
38779 		 * properties which is nice for the fast path here.
38780 		 *
38781 		 * For arrays JSON.stringify() uses [[Get]] so it will actually
38782 		 * inherit properties during serialization!  This fast path
38783 		 * supports gappy arrays as long as there's no actual inherited
38784 		 * property (which might be a getter etc).
38785 		 *
38786 		 * Since recursion only happens for objects, we can have both
38787 		 * recursion and loop checks here.  We use a simple, depth-limited
38788 		 * loop check in the fast path because the object-based tracking
38789 		 * is very slow (when tested, it accounted for 50% of fast path
38790 		 * execution time for input data with a lot of small objects!).
38791 		 */
38792 
38793 		/* XXX: for real world code, could just ignore array inheritance
38794 		 * and only look at array own properties.
38795 		 */
38796 
38797 		/* We rely on a few object flag / class number relationships here,
38798 		 * assert for them.
38799 		 */
38800 
38801 		obj = DUK_TVAL_GET_OBJECT(tv);
38802 		DUK_ASSERT(obj != NULL);
38803 		DUK_HOBJECT_ASSERT_VALID(obj);
38804 
38805 		/* Once recursion depth is increased, exit path must decrease
38806 		 * it (though it's OK to abort the fast path).
38807 		 */
38808 
38809 		DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */
38810 		DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
38811 		if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
38812 			DUK_DD(DUK_DDPRINT("fast path recursion limit"));
38813 			DUK_ERROR_RANGE(js_ctx->thr, DUK_STR_DEC_RECLIMIT);
38814 			DUK_WO_NORETURN(return 0;);
38815 		}
38816 
38817 		for (i = 0, n = (duk_uint_fast32_t) js_ctx->recursion_depth; i < n; i++) {
38818 			if (DUK_UNLIKELY(js_ctx->visiting[i] == obj)) {
38819 				DUK_DD(DUK_DDPRINT("fast path loop detect"));
38820 				DUK_ERROR_TYPE(js_ctx->thr, DUK_STR_CYCLIC_INPUT);
38821 				DUK_WO_NORETURN(return 0;);
38822 			}
38823 		}
38824 
38825 		/* Guaranteed by recursion_limit setup so we don't have to
38826 		 * check twice.
38827 		 */
38828 		DUK_ASSERT(js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY);
38829 		js_ctx->visiting[js_ctx->recursion_depth] = obj;
38830 		js_ctx->recursion_depth++;
38831 
38832 		/* If object has a .toJSON() property, we can't be certain
38833 		 * that it wouldn't mutate any value arbitrarily, so bail
38834 		 * out of the fast path.
38835 		 *
38836 		 * If an object is a Proxy we also can't avoid side effects
38837 		 * so abandon.
38838 		 */
38839 		/* XXX: non-callable .toJSON() doesn't need to cause an abort
38840 		 * but does at the moment, probably not worth fixing.
38841 		 */
38842 		if (duk_hobject_hasprop_raw(js_ctx->thr, obj, DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr)) ||
38843 		    DUK_HOBJECT_IS_PROXY(obj)) {
38844 			DUK_DD(DUK_DDPRINT("object has a .toJSON property or object is a Proxy, abort fast path"));
38845 			goto abort_fastpath;
38846 		}
38847 
38848 		/* We could use a switch-case for the class number but it turns out
38849 		 * a small if-else ladder on class masks is better.  The if-ladder
38850 		 * should be in order of relevancy.
38851 		 */
38852 
38853 		/* XXX: move masks to js_ctx? they don't change during one
38854 		 * fast path invocation.
38855 		 */
38856 		DUK_ASSERT(DUK_HOBJECT_CLASS_MAX <= 31);
38857 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
38858 		if (js_ctx->flag_ext_custom_or_compatible) {
38859 			c_all = DUK_HOBJECT_CMASK_ALL;
38860 			c_array = DUK_HOBJECT_CMASK_ARRAY;
38861 			c_unbox = DUK_HOBJECT_CMASK_NUMBER |
38862 			          DUK_HOBJECT_CMASK_STRING |
38863 			          DUK_HOBJECT_CMASK_BOOLEAN |
38864 			          DUK_HOBJECT_CMASK_POINTER;  /* Symbols are not unboxed. */
38865 			c_func = DUK_HOBJECT_CMASK_FUNCTION;
38866 			c_bufobj = DUK_HOBJECT_CMASK_ALL_BUFOBJS;
38867 			c_undef = 0;
38868 			c_abort = 0;
38869 			c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef | c_abort);
38870 		}
38871 		else
38872 #endif
38873 		{
38874 			c_all = DUK_HOBJECT_CMASK_ALL;
38875 			c_array = DUK_HOBJECT_CMASK_ARRAY;
38876 			c_unbox = DUK_HOBJECT_CMASK_NUMBER |
38877 			          DUK_HOBJECT_CMASK_STRING |
38878 			          DUK_HOBJECT_CMASK_BOOLEAN;  /* Symbols are not unboxed. */
38879 			c_func = 0;
38880 			c_bufobj = 0;
38881 			c_undef = DUK_HOBJECT_CMASK_FUNCTION |
38882 			          DUK_HOBJECT_CMASK_POINTER;
38883 			/* As the fast path doesn't currently properly support
38884 			 * duk_hbufobj virtual properties, abort fast path if
38885 			 * we encounter them in plain JSON mode.
38886 			 */
38887 			c_abort = DUK_HOBJECT_CMASK_ALL_BUFOBJS;
38888 			c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef | c_abort);
38889 		}
38890 
38891 		c_bit = (duk_uint32_t) DUK_HOBJECT_GET_CLASS_MASK(obj);
38892 		if (c_bit & c_object) {
38893 			/* All other object types. */
38894 			DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
38895 
38896 			/* A non-Array object should not have an array part in practice.
38897 			 * But since it is supported internally (and perhaps used at some
38898 			 * point), check and abandon if that's the case.
38899 			 */
38900 			if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
38901 				DUK_DD(DUK_DDPRINT("non-Array object has array part, abort fast path"));
38902 				goto abort_fastpath;
38903 			}
38904 
38905 			for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(obj); i++) {
38906 				duk_hstring *k;
38907 				duk_size_t prev_size;
38908 
38909 				k = DUK_HOBJECT_E_GET_KEY(js_ctx->thr->heap, obj, i);
38910 				if (!k) {
38911 					continue;
38912 				}
38913 				if (DUK_HSTRING_HAS_ARRIDX(k)) {
38914 					/* If an object has array index keys we would need
38915 					 * to sort them into the ES2015 enumeration order to
38916 					 * be consistent with the slow path.  Abort the fast
38917 					 * path and handle in the slow path for now.
38918 					 */
38919 					DUK_DD(DUK_DDPRINT("property key is an array index, abort fast path"));
38920 					goto abort_fastpath;
38921 				}
38922 				if (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(js_ctx->thr->heap, obj, i)) {
38923 					continue;
38924 				}
38925 				if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(js_ctx->thr->heap, obj, i)) {
38926 					/* Getter might have arbitrary side effects,
38927 					 * so bail out.
38928 					 */
38929 					DUK_DD(DUK_DDPRINT("property is an accessor, abort fast path"));
38930 					goto abort_fastpath;
38931 				}
38932 				if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(k))) {
38933 					continue;
38934 				}
38935 
38936 				tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(js_ctx->thr->heap, obj, i);
38937 
38938 				prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
38939 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
38940 					duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth);
38941 					duk__json_enc_key_autoquote(js_ctx, k);
38942 					DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
38943 				} else {
38944 					duk__json_enc_key_autoquote(js_ctx, k);
38945 					DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
38946 				}
38947 
38948 				if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) {
38949 					DUK_DD(DUK_DDPRINT("prop value not supported, rewind key and colon"));
38950 					DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
38951 				} else {
38952 					DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
38953 					emitted = 1;
38954 				}
38955 			}
38956 
38957 			/* If any non-Array value had enumerable virtual own
38958 			 * properties, they should be serialized here (actually,
38959 			 * before the explicit properties).  Standard types don't.
38960 			 */
38961 
38962 			if (emitted) {
38963 				DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
38964 				DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
38965 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
38966 					DUK_ASSERT(js_ctx->recursion_depth >= 1);
38967 					duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
38968 				}
38969 			}
38970 			DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
38971 		} else if (c_bit & c_array) {
38972 			duk_uint_fast32_t arr_len;
38973 			duk_uint_fast32_t asize;
38974 
38975 			DUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET);
38976 
38977 			/* Assume arrays are dense in the fast path. */
38978 			if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
38979 				DUK_DD(DUK_DDPRINT("Array object is sparse, abort fast path"));
38980 				goto abort_fastpath;
38981 			}
38982 
38983 			arr_len = (duk_uint_fast32_t) ((duk_harray *) obj)->length;
38984 			asize = (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(obj);
38985 			/* Array part may be larger than 'length'; if so, iterate
38986 			 * only up to array 'length'.  Array part may also be smaller
38987 			 * than 'length' in some cases.
38988 			 */
38989 			for (i = 0; i < arr_len; i++) {
38990 				duk_tval *tv_arrval;
38991 				duk_hstring *h_tmp;
38992 				duk_bool_t has_inherited;
38993 
38994 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
38995 					duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth);
38996 				}
38997 
38998 				if (DUK_LIKELY(i < asize)) {
38999 					tv_arrval = DUK_HOBJECT_A_GET_VALUE_PTR(js_ctx->thr->heap, obj, i);
39000 					if (DUK_LIKELY(!DUK_TVAL_IS_UNUSED(tv_arrval))) {
39001 						/* Expected case: element is present. */
39002 						if (duk__json_stringify_fast_value(js_ctx, tv_arrval) == 0) {
39003 							DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
39004 						}
39005 						goto elem_done;
39006 					}
39007 				}
39008 
39009 				/* Gap in array; check for inherited property,
39010 				 * bail out if one exists.  This should be enough
39011 				 * to support gappy arrays for all practical code.
39012 				 */
39013 
39014 				h_tmp = duk_push_uint_to_hstring(js_ctx->thr, (duk_uint_t) i);
39015 				has_inherited = duk_hobject_hasprop_raw(js_ctx->thr, obj, h_tmp);
39016 				duk_pop(js_ctx->thr);
39017 				if (has_inherited) {
39018 					DUK_D(DUK_DPRINT("gap in array, conflicting inherited property, abort fast path"));
39019 					goto abort_fastpath;
39020 				}
39021 
39022 				/* Ordinary gap, undefined encodes to 'null' in
39023 				 * standard JSON, but JX/JC use their form for
39024 				 * undefined to better preserve the typing.
39025 				 */
39026 				DUK_D(DUK_DPRINT("gap in array, no conflicting inherited property, remain on fast path"));
39027 #if defined(DUK_USE_JX)
39028 				DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
39029 #else
39030 				DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
39031 #endif
39032 				/* fall through */
39033 
39034 			 elem_done:
39035 				DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
39036 				emitted = 1;
39037 			}
39038 
39039 			if (emitted) {
39040 				DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
39041 				DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
39042 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
39043 					DUK_ASSERT(js_ctx->recursion_depth >= 1);
39044 					duk__json_enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
39045 				}
39046 			}
39047 			DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
39048 		} else if (c_bit & c_unbox) {
39049 			/* Certain boxed types are required to go through
39050 			 * automatic unboxing.  Rely on internal value being
39051 			 * sane (to avoid infinite recursion).
39052 			 */
39053 			DUK_ASSERT((c_bit & DUK_HOBJECT_CMASK_SYMBOL) == 0);  /* Symbols are not unboxed. */
39054 
39055 #if 1
39056 			/* The code below is incorrect if .toString() or .valueOf() have
39057 			 * have been overridden.  The correct approach would be to look up
39058 			 * the method(s) and if they resolve to the built-in function we
39059 			 * can safely bypass it and look up the internal value directly.
39060 			 * Unimplemented for now, abort fast path for boxed values.
39061 			 */
39062 			goto abort_fastpath;
39063 #else  /* disabled */
39064 			/* Disabled until fixed, see above. */
39065 			duk_tval *tv_internal;
39066 
39067 			DUK_DD(DUK_DDPRINT("auto unboxing in fast path"));
39068 
39069 			tv_internal = duk_hobject_get_internal_value_tval_ptr(js_ctx->thr->heap, obj);
39070 			DUK_ASSERT(tv_internal != NULL);
39071 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv_internal) ||
39072 			           DUK_TVAL_IS_NUMBER(tv_internal) ||
39073 			           DUK_TVAL_IS_BOOLEAN(tv_internal) ||
39074 			           DUK_TVAL_IS_POINTER(tv_internal));
39075 
39076 			tv = tv_internal;
39077 			DUK_ASSERT(js_ctx->recursion_depth > 0);
39078 			js_ctx->recursion_depth--;  /* required to keep recursion depth correct */
39079 			goto restart_match;
39080 #endif  /* disabled */
39081 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39082 		} else if (c_bit & c_func) {
39083 			DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
39084 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
39085 		} else if (c_bit & c_bufobj) {
39086 			duk__json_enc_bufobj(js_ctx, (duk_hbufobj *) obj);
39087 #endif
39088 #endif
39089 		} else if (c_bit & c_abort) {
39090 			DUK_DD(DUK_DDPRINT("abort fast path for unsupported type"));
39091 			goto abort_fastpath;
39092 		} else {
39093 			DUK_ASSERT((c_bit & c_undef) != 0);
39094 
39095 			/* Must decrease recursion depth before returning. */
39096 			DUK_ASSERT(js_ctx->recursion_depth > 0);
39097 			DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
39098 			js_ctx->recursion_depth--;
39099 			goto emit_undefined;
39100 		}
39101 
39102 		DUK_ASSERT(js_ctx->recursion_depth > 0);
39103 		DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
39104 		js_ctx->recursion_depth--;
39105 		break;
39106 	}
39107 	case DUK_TAG_BUFFER: {
39108 		/* Plain buffers are treated like Uint8Arrays: they have
39109 		 * enumerable indices.  Other virtual properties are not
39110 		 * enumerable, and inherited properties are not serialized.
39111 		 * However, there can be a replacer (not relevant here) or
39112 		 * a .toJSON() method (which we need to check for explicitly).
39113 		 */
39114 
39115 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
39116 		if (duk_hobject_hasprop_raw(js_ctx->thr,
39117 		                            js_ctx->thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE],
39118 		                            DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr))) {
39119 			DUK_DD(DUK_DDPRINT("value is a plain buffer and there's an inherited .toJSON, abort fast path"));
39120 			goto abort_fastpath;
39121 		}
39122 #endif
39123 
39124 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39125 		if (js_ctx->flag_ext_custom_or_compatible) {
39126 			duk__json_enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));
39127 			break;
39128 		}
39129 #endif
39130 
39131 		/* Plain buffers mimic Uint8Arrays, and have enumerable index
39132 		 * properties.
39133 		 */
39134 		duk__json_enc_buffer_json_fastpath(js_ctx, DUK_TVAL_GET_BUFFER(tv));
39135 		break;
39136 	}
39137 	case DUK_TAG_POINTER: {
39138 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39139 		if (js_ctx->flag_ext_custom_or_compatible) {
39140 			duk__json_enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
39141 			break;
39142 		} else {
39143 			goto emit_undefined;
39144 		}
39145 #else
39146 		goto emit_undefined;
39147 #endif
39148 	}
39149 	case DUK_TAG_LIGHTFUNC: {
39150 		/* A lightfunc might also inherit a .toJSON() so just bail out. */
39151 		/* XXX: Could just lookup .toJSON() and continue in fast path,
39152 		 * as it would almost never be defined.
39153 		 */
39154 		DUK_DD(DUK_DDPRINT("value is a lightfunc, abort fast path"));
39155 		goto abort_fastpath;
39156 	}
39157 #if defined(DUK_USE_FASTINT)
39158 	case DUK_TAG_FASTINT: {
39159 		/* Number serialization has a significant impact relative to
39160 		 * other fast path code, so careful fast path for fastints.
39161 		 */
39162 		duk__json_enc_fastint_tval(js_ctx, tv);
39163 		break;
39164 	}
39165 #endif
39166 	default: {
39167 		/* XXX: A fast path for usual integers would be useful when
39168 		 * fastint support is not enabled.
39169 		 */
39170 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
39171 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
39172 
39173 		/* XXX: Stack discipline is annoying, could be changed in numconv. */
39174 		duk_push_tval(js_ctx->thr, tv);
39175 		duk__json_enc_double(js_ctx);
39176 		duk_pop(js_ctx->thr);
39177 
39178 #if 0
39179 		/* Could also rely on native sprintf(), but it will handle
39180 		 * values like NaN, Infinity, -0, exponent notation etc in
39181 		 * a JSON-incompatible way.
39182 		 */
39183 		duk_double_t d;
39184 		char buf[64];
39185 
39186 		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
39187 		d = DUK_TVAL_GET_DOUBLE(tv);
39188 		DUK_SPRINTF(buf, "%lg", d);
39189 		DUK__EMIT_CSTR(js_ctx, buf);
39190 #endif
39191 	}
39192 	}
39193 	return 1;  /* not undefined */
39194 
39195  emit_undefined:
39196 	return 0;  /* value was undefined/unsupported */
39197 
39198  abort_fastpath:
39199 	/* Error message doesn't matter: the error is ignored anyway. */
39200 	DUK_DD(DUK_DDPRINT("aborting fast path"));
39201 	DUK_ERROR_INTERNAL(js_ctx->thr);
39202 	DUK_WO_NORETURN(return 0;);
39203 }
39204 
39205 DUK_LOCAL duk_ret_t duk__json_stringify_fast(duk_hthread *thr, void *udata) {
39206 	duk_json_enc_ctx *js_ctx;
39207 	duk_tval *tv;
39208 
39209 	DUK_ASSERT(thr != NULL);
39210 	DUK_ASSERT(udata != NULL);
39211 
39212 	js_ctx = (duk_json_enc_ctx *) udata;
39213 	DUK_ASSERT(js_ctx != NULL);
39214 
39215 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
39216 	if (duk__json_stringify_fast_value(js_ctx, tv) == 0) {
39217 		DUK_DD(DUK_DDPRINT("top level value not supported, fail fast path"));
39218 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);  /* Error message is ignored, so doesn't matter. */
39219 	}
39220 
39221 	return 0;
39222 }
39223 #endif  /* DUK_USE_JSON_STRINGIFY_FASTPATH */
39224 
39225 /*
39226  *  Top level wrappers
39227  */
39228 
39229 DUK_INTERNAL
39230 void duk_bi_json_parse_helper(duk_hthread *thr,
39231                               duk_idx_t idx_value,
39232                               duk_idx_t idx_reviver,
39233                               duk_small_uint_t flags) {
39234 	duk_json_dec_ctx js_ctx_alloc;
39235 	duk_json_dec_ctx *js_ctx = &js_ctx_alloc;
39236 	duk_hstring *h_text;
39237 #if defined(DUK_USE_ASSERTIONS)
39238 	duk_idx_t entry_top = duk_get_top(thr);
39239 #endif
39240 
39241 	/* negative top-relative indices not allowed now */
39242 	DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
39243 	DUK_ASSERT(idx_reviver == DUK_INVALID_INDEX || idx_reviver >= 0);
39244 
39245 	DUK_DDD(DUK_DDDPRINT("JSON parse start: text=%!T, reviver=%!T, flags=0x%08lx, stack_top=%ld",
39246 	                     (duk_tval *) duk_get_tval(thr, idx_value),
39247 	                     (duk_tval *) duk_get_tval(thr, idx_reviver),
39248 	                     (unsigned long) flags,
39249 	                     (long) duk_get_top(thr)));
39250 
39251 	duk_memzero(&js_ctx_alloc, sizeof(js_ctx_alloc));
39252 	js_ctx->thr = thr;
39253 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
39254 	/* nothing now */
39255 #endif
39256 	js_ctx->recursion_limit = DUK_USE_JSON_DEC_RECLIMIT;
39257 	DUK_ASSERT(js_ctx->recursion_depth == 0);
39258 
39259 	/* Flag handling currently assumes that flags are consistent.  This is OK
39260 	 * because the call sites are now strictly controlled.
39261 	 */
39262 
39263 	js_ctx->flags = flags;
39264 #if defined(DUK_USE_JX)
39265 	js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
39266 #endif
39267 #if defined(DUK_USE_JC)
39268 	js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;
39269 #endif
39270 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39271 	js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
39272 #endif
39273 
39274 	h_text = duk_to_hstring(thr, idx_value);  /* coerce in-place; rejects Symbols */
39275 	DUK_ASSERT(h_text != NULL);
39276 
39277 	/* JSON parsing code is allowed to read [p_start,p_end]: p_end is
39278 	 * valid and points to the string NUL terminator (which is always
39279 	 * guaranteed for duk_hstrings.
39280 	 */
39281 	js_ctx->p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text);
39282 	js_ctx->p = js_ctx->p_start;
39283 	js_ctx->p_end = ((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text)) +
39284 	                DUK_HSTRING_GET_BYTELEN(h_text);
39285 	DUK_ASSERT(*(js_ctx->p_end) == 0x00);
39286 
39287 	duk__json_dec_value(js_ctx);  /* -> [ ... value ] */
39288 	DUK_ASSERT(js_ctx->recursion_depth == 0);
39289 
39290 	/* Trailing whitespace has been eaten by duk__json_dec_value(), so if
39291 	 * we're not at end of input here, it's a SyntaxError.
39292 	 */
39293 
39294 	if (js_ctx->p != js_ctx->p_end) {
39295 		duk__json_dec_syntax_error(js_ctx);
39296 	}
39297 
39298 	if (duk_is_callable(thr, idx_reviver)) {
39299 		DUK_DDD(DUK_DDDPRINT("applying reviver: %!T",
39300 		                     (duk_tval *) duk_get_tval(thr, idx_reviver)));
39301 
39302 		js_ctx->idx_reviver = idx_reviver;
39303 
39304 		duk_push_object(thr);
39305 		duk_dup_m2(thr);  /* -> [ ... val root val ] */
39306 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_EMPTY_STRING);  /* default attrs ok */
39307 		duk_push_hstring_stridx(thr, DUK_STRIDX_EMPTY_STRING);  /* -> [ ... val root "" ] */
39308 
39309 		DUK_DDD(DUK_DDDPRINT("start reviver walk, root=%!T, name=%!T",
39310 		                     (duk_tval *) duk_get_tval(thr, -2),
39311 		                     (duk_tval *) duk_get_tval(thr, -1)));
39312 
39313 		DUK_ASSERT(js_ctx->recursion_depth == 0);
39314 		duk__json_dec_reviver_walk(js_ctx);  /* [ ... val root "" ] -> [ ... val val' ] */
39315 		DUK_ASSERT(js_ctx->recursion_depth == 0);
39316 		duk_remove_m2(thr);             /* -> [ ... val' ] */
39317 	} else {
39318 		DUK_DDD(DUK_DDDPRINT("reviver does not exist or is not callable: %!T",
39319 		                     (duk_tval *) duk_get_tval(thr, idx_reviver)));
39320 	}
39321 
39322 	/* Final result is at stack top. */
39323 
39324 	DUK_DDD(DUK_DDDPRINT("JSON parse end: text=%!T, reviver=%!T, flags=0x%08lx, result=%!T, stack_top=%ld",
39325 	                     (duk_tval *) duk_get_tval(thr, idx_value),
39326 	                     (duk_tval *) duk_get_tval(thr, idx_reviver),
39327 	                     (unsigned long) flags,
39328 	                     (duk_tval *) duk_get_tval(thr, -1),
39329 	                     (long) duk_get_top(thr)));
39330 
39331 	DUK_ASSERT(duk_get_top(thr) == entry_top + 1);
39332 }
39333 
39334 DUK_INTERNAL
39335 void duk_bi_json_stringify_helper(duk_hthread *thr,
39336                                   duk_idx_t idx_value,
39337                                   duk_idx_t idx_replacer,
39338                                   duk_idx_t idx_space,
39339                                   duk_small_uint_t flags) {
39340 	duk_json_enc_ctx js_ctx_alloc;
39341 	duk_json_enc_ctx *js_ctx = &js_ctx_alloc;
39342 	duk_hobject *h;
39343 	duk_idx_t idx_holder;
39344 	duk_idx_t entry_top;
39345 
39346 	/* negative top-relative indices not allowed now */
39347 	DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
39348 	DUK_ASSERT(idx_replacer == DUK_INVALID_INDEX || idx_replacer >= 0);
39349 	DUK_ASSERT(idx_space == DUK_INVALID_INDEX || idx_space >= 0);
39350 
39351 	DUK_DDD(DUK_DDDPRINT("JSON stringify start: value=%!T, replacer=%!T, space=%!T, flags=0x%08lx, stack_top=%ld",
39352 	                     (duk_tval *) duk_get_tval(thr, idx_value),
39353 	                     (duk_tval *) duk_get_tval(thr, idx_replacer),
39354 	                     (duk_tval *) duk_get_tval(thr, idx_space),
39355 	                     (unsigned long) flags,
39356 	                     (long) duk_get_top(thr)));
39357 
39358 	entry_top = duk_get_top(thr);
39359 
39360 	/*
39361 	 *  Context init
39362 	 */
39363 
39364 	duk_memzero(&js_ctx_alloc, sizeof(js_ctx_alloc));
39365 	js_ctx->thr = thr;
39366 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
39367 	js_ctx->h_replacer = NULL;
39368 	js_ctx->h_gap = NULL;
39369 #endif
39370 	js_ctx->idx_proplist = -1;
39371 
39372 	/* Flag handling currently assumes that flags are consistent.  This is OK
39373 	 * because the call sites are now strictly controlled.
39374 	 */
39375 
39376 	js_ctx->flags = flags;
39377 	js_ctx->flag_ascii_only = flags & DUK_JSON_FLAG_ASCII_ONLY;
39378 	js_ctx->flag_avoid_key_quotes = flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES;
39379 #if defined(DUK_USE_JX)
39380 	js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
39381 #endif
39382 #if defined(DUK_USE_JC)
39383 	js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;
39384 #endif
39385 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39386 	js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
39387 #endif
39388 
39389 	/* The #if defined() clutter here handles the JX/JC enable/disable
39390 	 * combinations properly.
39391 	 */
39392 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39393 	js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_NULL;  /* standard JSON; array gaps */
39394 #if defined(DUK_USE_JX)
39395 	if (flags & DUK_JSON_FLAG_EXT_CUSTOM) {
39396 		js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_UNDEFINED;
39397 		js_ctx->stridx_custom_nan = DUK_STRIDX_NAN;
39398 		js_ctx->stridx_custom_neginf = DUK_STRIDX_MINUS_INFINITY;
39399 		js_ctx->stridx_custom_posinf = DUK_STRIDX_INFINITY;
39400 		js_ctx->stridx_custom_function =
39401 		        (flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES) ?
39402 		                DUK_STRIDX_JSON_EXT_FUNCTION2 :
39403 		                DUK_STRIDX_JSON_EXT_FUNCTION1;
39404 	}
39405 #endif  /* DUK_USE_JX */
39406 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
39407 	else
39408 #endif  /* DUK_USE_JX && DUK_USE_JC */
39409 #if defined(DUK_USE_JC)
39410 	if (js_ctx->flags & DUK_JSON_FLAG_EXT_COMPATIBLE) {
39411 		js_ctx->stridx_custom_undefined = DUK_STRIDX_JSON_EXT_UNDEFINED;
39412 		js_ctx->stridx_custom_nan = DUK_STRIDX_JSON_EXT_NAN;
39413 		js_ctx->stridx_custom_neginf = DUK_STRIDX_JSON_EXT_NEGINF;
39414 		js_ctx->stridx_custom_posinf = DUK_STRIDX_JSON_EXT_POSINF;
39415 		js_ctx->stridx_custom_function = DUK_STRIDX_JSON_EXT_FUNCTION1;
39416 	}
39417 #endif  /* DUK_USE_JC */
39418 #endif  /* DUK_USE_JX || DUK_USE_JC */
39419 
39420 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
39421 	if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
39422 	                     DUK_JSON_FLAG_EXT_COMPATIBLE)) {
39423 		DUK_ASSERT(js_ctx->mask_for_undefined == 0);  /* already zero */
39424 	}
39425 	else
39426 #endif  /* DUK_USE_JX || DUK_USE_JC */
39427 	{
39428 		/* Plain buffer is treated like ArrayBuffer and serialized.
39429 		 * Lightfuncs are treated like objects, but JSON explicitly
39430 		 * skips serializing Function objects so we can just reject
39431 		 * lightfuncs here.
39432 		 */
39433 		js_ctx->mask_for_undefined = DUK_TYPE_MASK_UNDEFINED |
39434 		                             DUK_TYPE_MASK_POINTER |
39435 		                             DUK_TYPE_MASK_LIGHTFUNC;
39436 	}
39437 
39438 	DUK_BW_INIT_PUSHBUF(thr, &js_ctx->bw, DUK__JSON_STRINGIFY_BUFSIZE);
39439 
39440 	js_ctx->idx_loop = duk_push_bare_object(thr);
39441 	DUK_ASSERT(js_ctx->idx_loop >= 0);
39442 
39443 	/* [ ... buf loop ] */
39444 
39445 	/*
39446 	 *  Process replacer/proplist (2nd argument to JSON.stringify)
39447 	 */
39448 
39449 	h = duk_get_hobject(thr, idx_replacer);
39450 	if (h != NULL) {
39451 		if (DUK_HOBJECT_IS_CALLABLE(h)) {
39452 			js_ctx->h_replacer = h;
39453 		} else if (duk_js_isarray_hobject(h)) {
39454 			/* Here the specification requires correct array index enumeration
39455 			 * which is a bit tricky for sparse arrays (it is handled by the
39456 			 * enum setup code).  We now enumerate ancestors too, although the
39457 			 * specification is not very clear on whether that is required.
39458 			 */
39459 
39460 			duk_uarridx_t plist_idx = 0;
39461 			duk_small_uint_t enum_flags;
39462 
39463 			js_ctx->idx_proplist = duk_push_bare_array(thr);
39464 
39465 			enum_flags = DUK_ENUM_ARRAY_INDICES_ONLY |
39466 			             DUK_ENUM_SORT_ARRAY_INDICES;  /* expensive flag */
39467 			duk_enum(thr, idx_replacer, enum_flags);
39468 			while (duk_next(thr, -1 /*enum_index*/, 1 /*get_value*/)) {
39469 				/* [ ... proplist enum_obj key val ] */
39470 				if (duk__json_enc_allow_into_proplist(duk_get_tval(thr, -1))) {
39471 					/* XXX: duplicates should be eliminated here */
39472 					DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> accept",
39473 					                     (duk_tval *) duk_get_tval(thr, -2),
39474 					                     (duk_tval *) duk_get_tval(thr, -1)));
39475 					duk_to_string(thr, -1);  /* extra coercion of strings is OK */
39476 					duk_put_prop_index(thr, -4, plist_idx);  /* -> [ ... proplist enum_obj key ] */
39477 					plist_idx++;
39478 					duk_pop(thr);
39479 				} else {
39480 					DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> reject",
39481 					                     (duk_tval *) duk_get_tval(thr, -2),
39482 					                     (duk_tval *) duk_get_tval(thr, -1)));
39483 					duk_pop_2(thr);
39484 				}
39485                         }
39486                         duk_pop(thr);  /* pop enum */
39487 
39488 			/* [ ... proplist ] */
39489 		}
39490 	}
39491 
39492 	/* [ ... buf loop (proplist) ] */
39493 
39494 	/*
39495 	 *  Process space (3rd argument to JSON.stringify)
39496 	 */
39497 
39498 	h = duk_get_hobject(thr, idx_space);
39499 	if (h != NULL) {
39500 		duk_small_uint_t c = DUK_HOBJECT_GET_CLASS_NUMBER(h);
39501 		if (c == DUK_HOBJECT_CLASS_NUMBER) {
39502 			duk_to_number(thr, idx_space);
39503 		} else if (c == DUK_HOBJECT_CLASS_STRING) {
39504 			duk_to_string(thr, idx_space);
39505 		}
39506 	}
39507 
39508 	if (duk_is_number(thr, idx_space)) {
39509 		duk_small_int_t nspace;
39510 		/* spaces[] must be static to allow initializer with old compilers like BCC */
39511 		static const char spaces[10] = {
39512 			DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
39513 			DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
39514 			DUK_ASC_SPACE, DUK_ASC_SPACE
39515 		};  /* XXX: helper */
39516 
39517 		/* ToInteger() coercion; NaN -> 0, infinities are clamped to 0 and 10 */
39518 		nspace = (duk_small_int_t) duk_to_int_clamped(thr, idx_space, 0 /*minval*/, 10 /*maxval*/);
39519 		DUK_ASSERT(nspace >= 0 && nspace <= 10);
39520 
39521 		duk_push_lstring(thr, spaces, (duk_size_t) nspace);
39522 		js_ctx->h_gap = duk_known_hstring(thr, -1);
39523 		DUK_ASSERT(js_ctx->h_gap != NULL);
39524 	} else if (duk_is_string_notsymbol(thr, idx_space)) {
39525 		duk_dup(thr, idx_space);
39526 		duk_substring(thr, -1, 0, 10);  /* clamp to 10 chars */
39527 		js_ctx->h_gap = duk_known_hstring(thr, -1);
39528 	} else {
39529 		/* nop */
39530 	}
39531 
39532 	if (js_ctx->h_gap != NULL) {
39533 		/* If gap is empty, behave as if not given at all.  Check
39534 		 * against byte length because character length is more
39535 		 * expensive.
39536 		 */
39537 		if (DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) == 0) {
39538 			js_ctx->h_gap = NULL;
39539 		}
39540 	}
39541 
39542 	/* [ ... buf loop (proplist) (gap) ] */
39543 
39544 	/*
39545 	 *  Fast path: assume no mutation, iterate object property tables
39546 	 *  directly; bail out if that assumption doesn't hold.
39547 	 */
39548 
39549 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
39550 	if (js_ctx->h_replacer == NULL &&  /* replacer is a mutation risk */
39551 	    js_ctx->idx_proplist == -1) {  /* proplist is very rare */
39552 		duk_int_t pcall_rc;
39553 		duk_small_uint_t prev_ms_base_flags;
39554 
39555 		DUK_DD(DUK_DDPRINT("try JSON.stringify() fast path"));
39556 
39557 		/* Use recursion_limit to ensure we don't overwrite js_ctx->visiting[]
39558 		 * array so we don't need two counter checks in the fast path.  The
39559 		 * slow path has a much larger recursion limit which we'll use if
39560 		 * necessary.
39561 		 */
39562 		DUK_ASSERT(DUK_USE_JSON_ENC_RECLIMIT >= DUK_JSON_ENC_LOOPARRAY);
39563 		js_ctx->recursion_limit = DUK_JSON_ENC_LOOPARRAY;
39564 		DUK_ASSERT(js_ctx->recursion_depth == 0);
39565 
39566 		/* Execute the fast path in a protected call.  If any error is thrown,
39567 		 * fall back to the slow path.  This includes e.g. recursion limit
39568 		 * because the fast path has a smaller recursion limit (and simpler,
39569 		 * limited loop detection).
39570 		 */
39571 
39572 		duk_dup(thr, idx_value);
39573 
39574 		/* Must prevent finalizers which may have arbitrary side effects. */
39575 		prev_ms_base_flags = thr->heap->ms_base_flags;
39576 		thr->heap->ms_base_flags |=
39577 		        DUK_MS_FLAG_NO_OBJECT_COMPACTION;      /* Avoid attempt to compact any objects. */
39578 		thr->heap->pf_prevent_count++;                 /* Prevent finalizers. */
39579 		DUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */
39580 
39581 		pcall_rc = duk_safe_call(thr, duk__json_stringify_fast, (void *) js_ctx /*udata*/, 1 /*nargs*/, 0 /*nret*/);
39582 
39583 		DUK_ASSERT(thr->heap->pf_prevent_count > 0);
39584 		thr->heap->pf_prevent_count--;
39585 		thr->heap->ms_base_flags = prev_ms_base_flags;
39586 
39587 		if (pcall_rc == DUK_EXEC_SUCCESS) {
39588 			DUK_DD(DUK_DDPRINT("fast path successful"));
39589 			DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
39590 			goto replace_finished;
39591 		}
39592 
39593 		/* We come here for actual aborts (like encountering .toJSON())
39594 		 * but also for recursion/loop errors.  Bufwriter size can be
39595 		 * kept because we'll probably need at least as much as we've
39596 		 * allocated so far.
39597 		 */
39598 		DUK_D(DUK_DPRINT("fast path failed, serialize using slow path instead"));
39599 		DUK_BW_RESET_SIZE(thr, &js_ctx->bw);
39600 		js_ctx->recursion_depth = 0;
39601 	}
39602 #endif
39603 
39604 	/*
39605 	 *  Create wrapper object and serialize
39606 	 */
39607 
39608 	idx_holder = duk_push_object(thr);
39609 	duk_dup(thr, idx_value);
39610 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_EMPTY_STRING);
39611 
39612 	DUK_DDD(DUK_DDDPRINT("before: flags=0x%08lx, loop=%!T, replacer=%!O, "
39613 	                     "proplist=%!T, gap=%!O, holder=%!T",
39614 	                     (unsigned long) js_ctx->flags,
39615 	                     (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop),
39616 	                     (duk_heaphdr *) js_ctx->h_replacer,
39617 	                     (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(thr, js_ctx->idx_proplist) : NULL),
39618 	                     (duk_heaphdr *) js_ctx->h_gap,
39619 	                     (duk_tval *) duk_get_tval(thr, -1)));
39620 
39621 	/* serialize the wrapper with empty string key */
39622 
39623 	duk_push_hstring_empty(thr);
39624 
39625 	/* [ ... buf loop (proplist) (gap) holder "" ] */
39626 
39627 	js_ctx->recursion_limit = DUK_USE_JSON_ENC_RECLIMIT;
39628 	DUK_ASSERT(js_ctx->recursion_depth == 0);
39629 
39630 	if (DUK_UNLIKELY(duk__json_enc_value(js_ctx, idx_holder) == 0)) {  /* [ ... holder key ] -> [ ... holder ] */
39631 		/* Result is undefined. */
39632 		duk_push_undefined(thr);
39633 	} else {
39634 		/* Convert buffer to result string. */
39635 		DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
39636 	}
39637 
39638 	DUK_DDD(DUK_DDDPRINT("after: flags=0x%08lx, loop=%!T, replacer=%!O, "
39639 	                     "proplist=%!T, gap=%!O, holder=%!T",
39640 	                     (unsigned long) js_ctx->flags,
39641 	                     (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop),
39642 	                     (duk_heaphdr *) js_ctx->h_replacer,
39643 	                     (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(thr, js_ctx->idx_proplist) : NULL),
39644 	                     (duk_heaphdr *) js_ctx->h_gap,
39645 	                     (duk_tval *) duk_get_tval(thr, idx_holder)));
39646 
39647 	/* The stack has a variable shape here, so force it to the
39648 	 * desired one explicitly.
39649 	 */
39650 
39651 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
39652  replace_finished:
39653 #endif
39654 	duk_replace(thr, entry_top);
39655 	duk_set_top(thr, entry_top + 1);
39656 
39657 	DUK_DDD(DUK_DDDPRINT("JSON stringify end: value=%!T, replacer=%!T, space=%!T, "
39658 	                     "flags=0x%08lx, result=%!T, stack_top=%ld",
39659 	                     (duk_tval *) duk_get_tval(thr, idx_value),
39660 	                     (duk_tval *) duk_get_tval(thr, idx_replacer),
39661 	                     (duk_tval *) duk_get_tval(thr, idx_space),
39662 	                     (unsigned long) flags,
39663 	                     (duk_tval *) duk_get_tval(thr, -1),
39664 	                     (long) duk_get_top(thr)));
39665 
39666 	DUK_ASSERT(duk_get_top(thr) == entry_top + 1);
39667 }
39668 
39669 #if defined(DUK_USE_JSON_BUILTIN)
39670 
39671 /*
39672  *  Entry points
39673  */
39674 
39675 DUK_INTERNAL duk_ret_t duk_bi_json_object_parse(duk_hthread *thr) {
39676 	duk_bi_json_parse_helper(thr,
39677 	                         0 /*idx_value*/,
39678 	                         1 /*idx_replacer*/,
39679 	                         0 /*flags*/);
39680 	return 1;
39681 }
39682 
39683 DUK_INTERNAL duk_ret_t duk_bi_json_object_stringify(duk_hthread *thr) {
39684 	duk_bi_json_stringify_helper(thr,
39685 	                             0 /*idx_value*/,
39686 	                             1 /*idx_replacer*/,
39687 	                             2 /*idx_space*/,
39688 	                             0 /*flags*/);
39689 	return 1;
39690 }
39691 
39692 #endif  /* DUK_USE_JSON_BUILTIN */
39693 
39694 #endif  /* DUK_USE_JSON_SUPPORT */
39695 
39696 /* automatic undefs */
39697 #undef DUK__EMIT_1
39698 #undef DUK__EMIT_2
39699 #undef DUK__EMIT_CSTR
39700 #undef DUK__EMIT_HSTR
39701 #undef DUK__EMIT_STRIDX
39702 #undef DUK__JSON_DECSTR_BUFSIZE
39703 #undef DUK__JSON_DECSTR_CHUNKSIZE
39704 #undef DUK__JSON_ENCSTR_CHUNKSIZE
39705 #undef DUK__JSON_MAX_ESC_LEN
39706 #undef DUK__JSON_STRINGIFY_BUFSIZE
39707 #undef DUK__MKESC
39708 #undef DUK__UNEMIT_1
39709 #line 1 "duk_bi_math.c"
39710 /*
39711  *  Math built-ins
39712  */
39713 
39714 /* #include duk_internal.h -> already included */
39715 
39716 #if defined(DUK_USE_MATH_BUILTIN)
39717 
39718 /*
39719  *  Use static helpers which can work with math.h functions matching
39720  *  the following signatures. This is not portable if any of these math
39721  *  functions is actually a macro.
39722  *
39723  *  Typing here is intentionally 'double' wherever values interact with
39724  *  the standard library APIs.
39725  */
39726 
39727 typedef double (*duk__one_arg_func)(double);
39728 typedef double (*duk__two_arg_func)(double, double);
39729 
39730 DUK_LOCAL duk_ret_t duk__math_minmax(duk_hthread *thr, duk_double_t initial, duk__two_arg_func min_max) {
39731 	duk_idx_t n = duk_get_top(thr);
39732 	duk_idx_t i;
39733 	duk_double_t res = initial;
39734 	duk_double_t t;
39735 
39736 	/*
39737 	 *  Note: fmax() does not match the E5 semantics.  E5 requires
39738 	 *  that if -any- input to Math.max() is a NaN, the result is a
39739 	 *  NaN.  fmax() will return a NaN only if -both- inputs are NaN.
39740 	 *  Same applies to fmin().
39741 	 *
39742 	 *  Note: every input value must be coerced with ToNumber(), even
39743 	 *  if we know the result will be a NaN anyway: ToNumber() may have
39744 	 *  side effects for which even order of evaluation matters.
39745 	 */
39746 
39747 	for (i = 0; i < n; i++) {
39748 		t = duk_to_number(thr, i);
39749 		if (DUK_FPCLASSIFY(t) == DUK_FP_NAN || DUK_FPCLASSIFY(res) == DUK_FP_NAN) {
39750 			/* Note: not normalized, but duk_push_number() will normalize */
39751 			res = (duk_double_t) DUK_DOUBLE_NAN;
39752 		} else {
39753 			res = (duk_double_t) min_max(res, (double) t);
39754 		}
39755 	}
39756 
39757 	duk_push_number(thr, res);
39758 	return 1;
39759 }
39760 
39761 DUK_LOCAL double duk__fmin_fixed(double x, double y) {
39762 	/* fmin() with args -0 and +0 is not guaranteed to return
39763 	 * -0 as ECMAScript requires.
39764 	 */
39765 	if (duk_double_equals(x, 0.0) && duk_double_equals(y, 0.0)) {
39766 		duk_double_union du1, du2;
39767 		du1.d = x;
39768 		du2.d = y;
39769 
39770 		/* Already checked to be zero so these must hold, and allow us
39771 		 * to check for "x is -0 or y is -0" by ORing the high parts
39772 		 * for comparison.
39773 		 */
39774 		DUK_ASSERT(du1.ui[DUK_DBL_IDX_UI0] == 0 || du1.ui[DUK_DBL_IDX_UI0] == 0x80000000UL);
39775 		DUK_ASSERT(du2.ui[DUK_DBL_IDX_UI0] == 0 || du2.ui[DUK_DBL_IDX_UI0] == 0x80000000UL);
39776 
39777 		/* XXX: what's the safest way of creating a negative zero? */
39778 		if ((du1.ui[DUK_DBL_IDX_UI0] | du2.ui[DUK_DBL_IDX_UI0]) != 0) {
39779 			/* Enter here if either x or y (or both) is -0. */
39780 			return -0.0;
39781 		} else {
39782 			return +0.0;
39783 		}
39784 	}
39785 	return duk_double_fmin(x, y);
39786 }
39787 
39788 DUK_LOCAL double duk__fmax_fixed(double x, double y) {
39789 	/* fmax() with args -0 and +0 is not guaranteed to return
39790 	 * +0 as ECMAScript requires.
39791 	 */
39792 	if (duk_double_equals(x, 0.0) && duk_double_equals(y, 0.0)) {
39793 		if (DUK_SIGNBIT(x) == 0 || DUK_SIGNBIT(y) == 0) {
39794 			return +0.0;
39795 		} else {
39796 			return -0.0;
39797 		}
39798 	}
39799 	return duk_double_fmax(x, y);
39800 }
39801 
39802 #if defined(DUK_USE_ES6)
39803 DUK_LOCAL double duk__cbrt(double x) {
39804 	/* cbrt() is C99.  To avoid hassling embedders with the need to provide a
39805 	 * cube root function, we can get by with pow().  The result is not
39806 	 * identical, but that's OK: ES2015 says it's implementation-dependent.
39807 	 */
39808 
39809 #if defined(DUK_CBRT)
39810 	/* cbrt() matches ES2015 requirements. */
39811 	return DUK_CBRT(x);
39812 #else
39813 	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
39814 
39815 	/* pow() does not, however. */
39816 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {
39817 		return x;
39818 	}
39819 	if (DUK_SIGNBIT(x)) {
39820 		return -DUK_POW(-x, 1.0 / 3.0);
39821 	} else {
39822 		return DUK_POW(x, 1.0 / 3.0);
39823 	}
39824 #endif
39825 }
39826 
39827 DUK_LOCAL double duk__log2(double x) {
39828 #if defined(DUK_LOG2)
39829 	return DUK_LOG2(x);
39830 #else
39831 	return DUK_LOG(x) * DUK_DOUBLE_LOG2E;
39832 #endif
39833 }
39834 
39835 DUK_LOCAL double duk__log10(double x) {
39836 #if defined(DUK_LOG10)
39837 	return DUK_LOG10(x);
39838 #else
39839 	return DUK_LOG(x) * DUK_DOUBLE_LOG10E;
39840 #endif
39841 }
39842 
39843 DUK_LOCAL double duk__trunc(double x) {
39844 #if defined(DUK_TRUNC)
39845 	return DUK_TRUNC(x);
39846 #else
39847 	/* Handles -0 correctly: -0.0 matches 'x >= 0.0' but floor()
39848 	 * is required to return -0 when the argument is -0.
39849 	 */
39850 	return x >= 0.0 ? DUK_FLOOR(x) : DUK_CEIL(x);
39851 #endif
39852 }
39853 #endif  /* DUK_USE_ES6 */
39854 
39855 DUK_LOCAL double duk__round_fixed(double x) {
39856 	/* Numbers half-way between integers must be rounded towards +Infinity,
39857 	 * e.g. -3.5 must be rounded to -3 (not -4).  When rounded to zero, zero
39858 	 * sign must be set appropriately.  E5.1 Section 15.8.2.15.
39859 	 *
39860 	 * Note that ANSI C round() is "round to nearest integer, away from zero",
39861 	 * which is incorrect for negative values.  Here we make do with floor().
39862 	 */
39863 
39864 	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
39865 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {
39866 		return x;
39867 	}
39868 
39869 	/*
39870 	 *  x is finite and non-zero
39871 	 *
39872 	 *  -1.6 -> floor(-1.1) -> -2
39873 	 *  -1.5 -> floor(-1.0) -> -1  (towards +Inf)
39874 	 *  -1.4 -> floor(-0.9) -> -1
39875 	 *  -0.5 -> -0.0               (special case)
39876 	 *  -0.1 -> -0.0               (special case)
39877 	 *  +0.1 -> +0.0               (special case)
39878 	 *  +0.5 -> floor(+1.0) -> 1   (towards +Inf)
39879 	 *  +1.4 -> floor(+1.9) -> 1
39880 	 *  +1.5 -> floor(+2.0) -> 2   (towards +Inf)
39881 	 *  +1.6 -> floor(+2.1) -> 2
39882 	 */
39883 
39884 	if (x >= -0.5 && x < 0.5) {
39885 		/* +0.5 is handled by floor, this is on purpose */
39886 		if (x < 0.0) {
39887 			return -0.0;
39888 		} else {
39889 			return +0.0;
39890 		}
39891 	}
39892 
39893 	return DUK_FLOOR(x + 0.5);
39894 }
39895 
39896 /* Wrappers for calling standard math library methods.  These may be required
39897  * on platforms where one or more of the math built-ins are defined as macros
39898  * or inline functions and are thus not suitable to be used as function pointers.
39899  */
39900 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
39901 DUK_LOCAL double duk__fabs(double x) {
39902 	return DUK_FABS(x);
39903 }
39904 DUK_LOCAL double duk__acos(double x) {
39905 	return DUK_ACOS(x);
39906 }
39907 DUK_LOCAL double duk__asin(double x) {
39908 	return DUK_ASIN(x);
39909 }
39910 DUK_LOCAL double duk__atan(double x) {
39911 	return DUK_ATAN(x);
39912 }
39913 DUK_LOCAL double duk__ceil(double x) {
39914 	return DUK_CEIL(x);
39915 }
39916 DUK_LOCAL double duk__cos(double x) {
39917 	return DUK_COS(x);
39918 }
39919 DUK_LOCAL double duk__exp(double x) {
39920 	return DUK_EXP(x);
39921 }
39922 DUK_LOCAL double duk__floor(double x) {
39923 	return DUK_FLOOR(x);
39924 }
39925 DUK_LOCAL double duk__log(double x) {
39926 	return DUK_LOG(x);
39927 }
39928 DUK_LOCAL double duk__sin(double x) {
39929 	return DUK_SIN(x);
39930 }
39931 DUK_LOCAL double duk__sqrt(double x) {
39932 	return DUK_SQRT(x);
39933 }
39934 DUK_LOCAL double duk__tan(double x) {
39935 	return DUK_TAN(x);
39936 }
39937 DUK_LOCAL double duk__atan2_fixed(double x, double y) {
39938 #if defined(DUK_USE_ATAN2_WORKAROUNDS)
39939 	/* Specific fixes to common atan2() implementation issues:
39940 	 * - test-bug-mingw-math-issues.js
39941 	 */
39942 	if (DUK_ISINF(x) && DUK_ISINF(y)) {
39943 		if (DUK_SIGNBIT(x)) {
39944 			if (DUK_SIGNBIT(y)) {
39945 				return -2.356194490192345;
39946 			} else {
39947 				return -0.7853981633974483;
39948 			}
39949 		} else {
39950 			if (DUK_SIGNBIT(y)) {
39951 				return 2.356194490192345;
39952 			} else {
39953 				return 0.7853981633974483;
39954 			}
39955 		}
39956 	}
39957 #else
39958 	/* Some ISO C assumptions. */
39959 
39960 	DUK_ASSERT(duk_double_equals(DUK_ATAN2(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY), 0.7853981633974483));
39961 	DUK_ASSERT(duk_double_equals(DUK_ATAN2(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY), -0.7853981633974483));
39962 	DUK_ASSERT(duk_double_equals(DUK_ATAN2(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY), 2.356194490192345));
39963 	DUK_ASSERT(duk_double_equals(DUK_ATAN2(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY), -2.356194490192345));
39964 #endif
39965 
39966 	return DUK_ATAN2(x, y);
39967 }
39968 #endif  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
39969 
39970 /* order must match constants in genbuiltins.py */
39971 DUK_LOCAL const duk__one_arg_func duk__one_arg_funcs[] = {
39972 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
39973 	duk__fabs,
39974 	duk__acos,
39975 	duk__asin,
39976 	duk__atan,
39977 	duk__ceil,
39978 	duk__cos,
39979 	duk__exp,
39980 	duk__floor,
39981 	duk__log,
39982 	duk__round_fixed,
39983 	duk__sin,
39984 	duk__sqrt,
39985 	duk__tan,
39986 #if defined(DUK_USE_ES6)
39987 	duk__cbrt,
39988 	duk__log2,
39989 	duk__log10,
39990 	duk__trunc
39991 #endif
39992 #else  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
39993 	DUK_FABS,
39994 	DUK_ACOS,
39995 	DUK_ASIN,
39996 	DUK_ATAN,
39997 	DUK_CEIL,
39998 	DUK_COS,
39999 	DUK_EXP,
40000 	DUK_FLOOR,
40001 	DUK_LOG,
40002 	duk__round_fixed,
40003 	DUK_SIN,
40004 	DUK_SQRT,
40005 	DUK_TAN,
40006 #if defined(DUK_USE_ES6)
40007 	duk__cbrt,
40008 	duk__log2,
40009 	duk__log10,
40010 	duk__trunc
40011 #endif
40012 #endif  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
40013 };
40014 
40015 /* order must match constants in genbuiltins.py */
40016 DUK_LOCAL const duk__two_arg_func duk__two_arg_funcs[] = {
40017 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
40018 	duk__atan2_fixed,
40019 	duk_js_arith_pow
40020 #else
40021 	duk__atan2_fixed,
40022 	duk_js_arith_pow
40023 #endif
40024 };
40025 
40026 DUK_INTERNAL duk_ret_t duk_bi_math_object_onearg_shared(duk_hthread *thr) {
40027 	duk_small_int_t fun_idx = duk_get_current_magic(thr);
40028 	duk__one_arg_func fun;
40029 	duk_double_t arg1;
40030 
40031 	DUK_ASSERT(fun_idx >= 0);
40032 	DUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__one_arg_funcs) / sizeof(duk__one_arg_func)));
40033 	arg1 = duk_to_number(thr, 0);
40034 	fun = duk__one_arg_funcs[fun_idx];
40035 	duk_push_number(thr, (duk_double_t) fun((double) arg1));
40036 	return 1;
40037 }
40038 
40039 DUK_INTERNAL duk_ret_t duk_bi_math_object_twoarg_shared(duk_hthread *thr) {
40040 	duk_small_int_t fun_idx = duk_get_current_magic(thr);
40041 	duk__two_arg_func fun;
40042 	duk_double_t arg1;
40043 	duk_double_t arg2;
40044 
40045 	DUK_ASSERT(fun_idx >= 0);
40046 	DUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__two_arg_funcs) / sizeof(duk__two_arg_func)));
40047 	arg1 = duk_to_number(thr, 0);  /* explicit ordered evaluation to match coercion semantics */
40048 	arg2 = duk_to_number(thr, 1);
40049 	fun = duk__two_arg_funcs[fun_idx];
40050 	duk_push_number(thr, (duk_double_t) fun((double) arg1, (double) arg2));
40051 	return 1;
40052 }
40053 
40054 DUK_INTERNAL duk_ret_t duk_bi_math_object_max(duk_hthread *thr) {
40055 	return duk__math_minmax(thr, -DUK_DOUBLE_INFINITY, duk__fmax_fixed);
40056 }
40057 
40058 DUK_INTERNAL duk_ret_t duk_bi_math_object_min(duk_hthread *thr) {
40059 	return duk__math_minmax(thr, DUK_DOUBLE_INFINITY, duk__fmin_fixed);
40060 }
40061 
40062 DUK_INTERNAL duk_ret_t duk_bi_math_object_random(duk_hthread *thr) {
40063 	duk_push_number(thr, (duk_double_t) DUK_UTIL_GET_RANDOM_DOUBLE(thr));
40064 	return 1;
40065 }
40066 
40067 #if defined(DUK_USE_ES6)
40068 DUK_INTERNAL duk_ret_t duk_bi_math_object_hypot(duk_hthread *thr) {
40069 	/*
40070 	 *  E6 Section 20.2.2.18: Math.hypot
40071 	 *
40072 	 *  - If no arguments are passed, the result is +0.
40073 	 *  - If any argument is +inf, the result is +inf.
40074 	 *  - If any argument is -inf, the result is +inf.
40075 	 *  - If no argument is +inf or -inf, and any argument is NaN, the result is
40076 	 *    NaN.
40077 	 *  - If all arguments are either +0 or -0, the result is +0.
40078 	 */
40079 
40080 	duk_idx_t nargs;
40081 	duk_idx_t i;
40082 	duk_bool_t found_nan;
40083 	duk_double_t max;
40084 	duk_double_t sum, summand;
40085 	duk_double_t comp, prelim;
40086 	duk_double_t t;
40087 
40088 	nargs = duk_get_top(thr);
40089 
40090 	/* Find the highest value.  Also ToNumber() coerces. */
40091 	max = 0.0;
40092 	found_nan = 0;
40093 	for (i = 0; i < nargs; i++) {
40094 		t = DUK_FABS(duk_to_number(thr, i));
40095 		if (DUK_FPCLASSIFY(t) == DUK_FP_NAN) {
40096 			found_nan = 1;
40097 		} else {
40098 			max = duk_double_fmax(max, t);
40099 		}
40100 	}
40101 
40102 	/* Early return cases. */
40103 	if (duk_double_equals(max, DUK_DOUBLE_INFINITY)) {
40104 		duk_push_number(thr, DUK_DOUBLE_INFINITY);
40105 		return 1;
40106 	} else if (found_nan) {
40107 		duk_push_number(thr, DUK_DOUBLE_NAN);
40108 		return 1;
40109 	} else if (duk_double_equals(max, 0.0)) {
40110 		duk_push_number(thr, 0.0);
40111 		/* Otherwise we'd divide by zero. */
40112 		return 1;
40113 	}
40114 
40115 	/* Use Kahan summation and normalize to the highest value to minimize
40116 	 * floating point rounding error and avoid overflow.
40117 	 *
40118 	 * https://en.wikipedia.org/wiki/Kahan_summation_algorithm
40119 	 */
40120 	sum = 0.0;
40121 	comp = 0.0;
40122 	for (i = 0; i < nargs; i++) {
40123 		t = DUK_FABS(duk_get_number(thr, i)) / max;
40124 		summand = (t * t) - comp;
40125 		prelim = sum + summand;
40126 		comp = (prelim - sum) - summand;
40127 		sum = prelim;
40128 	}
40129 
40130 	duk_push_number(thr, (duk_double_t) DUK_SQRT(sum) * max);
40131 	return 1;
40132 }
40133 #endif  /* DUK_USE_ES6 */
40134 
40135 #if defined(DUK_USE_ES6)
40136 DUK_INTERNAL duk_ret_t duk_bi_math_object_sign(duk_hthread *thr) {
40137 	duk_double_t d;
40138 
40139 	d = duk_to_number(thr, 0);
40140 	if (duk_double_is_nan(d)) {
40141 		DUK_ASSERT(duk_is_nan(thr, -1));
40142 		return 1;  /* NaN input -> return NaN */
40143 	}
40144 	if (duk_double_equals(d, 0.0)) {
40145 		/* Zero sign kept, i.e. -0 -> -0, +0 -> +0. */
40146 		return 1;
40147 	}
40148 	duk_push_int(thr, (d > 0.0 ? 1 : -1));
40149 	return 1;
40150 }
40151 #endif  /* DUK_USE_ES6 */
40152 
40153 #if defined(DUK_USE_ES6)
40154 DUK_INTERNAL duk_ret_t duk_bi_math_object_clz32(duk_hthread *thr) {
40155 	duk_uint32_t x;
40156 	duk_small_uint_t i;
40157 
40158 #if defined(DUK_USE_PREFER_SIZE)
40159 	duk_uint32_t mask;
40160 
40161 	x = duk_to_uint32(thr, 0);
40162 	for (i = 0, mask = 0x80000000UL; mask != 0; mask >>= 1) {
40163 		if (x & mask) {
40164 			break;
40165 		}
40166 		i++;
40167 	}
40168 	DUK_ASSERT(i <= 32);
40169 	duk_push_uint(thr, i);
40170 	return 1;
40171 #else  /* DUK_USE_PREFER_SIZE */
40172 	i = 0;
40173 	x = duk_to_uint32(thr, 0);
40174 	if (x & 0xffff0000UL) {
40175 		x >>= 16;
40176 	} else {
40177 		i += 16;
40178 	}
40179 	if (x & 0x0000ff00UL) {
40180 		x >>= 8;
40181 	} else {
40182 		i += 8;
40183 	}
40184 	if (x & 0x000000f0UL) {
40185 		x >>= 4;
40186 	} else {
40187 		i += 4;
40188 	}
40189 	if (x & 0x0000000cUL) {
40190 		x >>= 2;
40191 	} else {
40192 		i += 2;
40193 	}
40194 	if (x & 0x00000002UL) {
40195 		x >>= 1;
40196 	} else {
40197 		i += 1;
40198 	}
40199 	if (x & 0x00000001UL) {
40200 		;
40201 	} else {
40202 		i += 1;
40203 	}
40204 	DUK_ASSERT(i <= 32);
40205 	duk_push_uint(thr, i);
40206 	return 1;
40207 #endif  /* DUK_USE_PREFER_SIZE */
40208 }
40209 #endif  /* DUK_USE_ES6 */
40210 
40211 #if defined(DUK_USE_ES6)
40212 DUK_INTERNAL duk_ret_t duk_bi_math_object_imul(duk_hthread *thr) {
40213 	duk_uint32_t x, y, z;
40214 
40215 	x = duk_to_uint32(thr, 0);
40216 	y = duk_to_uint32(thr, 1);
40217 	z = x * y;
40218 
40219 	/* While arguments are ToUint32() coerced and the multiplication
40220 	 * is unsigned as such, the final result is curiously interpreted
40221 	 * as a signed 32-bit value.
40222 	 */
40223 	duk_push_i32(thr, (duk_int32_t) z);
40224 	return 1;
40225 }
40226 #endif  /* DUK_USE_ES6 */
40227 
40228 #endif  /* DUK_USE_MATH_BUILTIN */
40229 #line 1 "duk_bi_number.c"
40230 /*
40231  *  Number built-ins
40232  */
40233 
40234 /* #include duk_internal.h -> already included */
40235 
40236 #if defined(DUK_USE_NUMBER_BUILTIN)
40237 
40238 DUK_LOCAL duk_double_t duk__push_this_number_plain(duk_hthread *thr) {
40239 	duk_hobject *h;
40240 
40241 	/* Number built-in accepts a plain number or a Number object (whose
40242 	 * internal value is operated on).  Other types cause TypeError.
40243 	 */
40244 
40245 	duk_push_this(thr);
40246 	if (duk_is_number(thr, -1)) {
40247 		DUK_DDD(DUK_DDDPRINT("plain number value: %!T", (duk_tval *) duk_get_tval(thr, -1)));
40248 		goto done;
40249 	}
40250 	h = duk_get_hobject(thr, -1);
40251 	if (!h ||
40252 	    (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_NUMBER)) {
40253 		DUK_DDD(DUK_DDDPRINT("unacceptable this value: %!T", (duk_tval *) duk_get_tval(thr, -1)));
40254 		DUK_ERROR_TYPE(thr, "number expected");
40255 		DUK_WO_NORETURN(return 0.0;);
40256 	}
40257 	duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
40258 	DUK_ASSERT(duk_is_number(thr, -1));
40259 	DUK_DDD(DUK_DDDPRINT("number object: %!T, internal value: %!T",
40260 	                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
40261 	duk_remove_m2(thr);
40262 
40263  done:
40264 	return duk_get_number(thr, -1);
40265 }
40266 
40267 DUK_INTERNAL duk_ret_t duk_bi_number_constructor(duk_hthread *thr) {
40268 	duk_idx_t nargs;
40269 	duk_hobject *h_this;
40270 
40271 	/*
40272 	 *  The Number constructor uses ToNumber(arg) for number coercion
40273 	 *  (coercing an undefined argument to NaN).  However, if the
40274 	 *  argument is not given at all, +0 must be used instead.  To do
40275 	 *  this, a vararg function is used.
40276 	 */
40277 
40278 	nargs = duk_get_top(thr);
40279 	if (nargs == 0) {
40280 		duk_push_int(thr, 0);
40281 	}
40282 	duk_to_number(thr, 0);
40283 	duk_set_top(thr, 1);
40284 	DUK_ASSERT_TOP(thr, 1);
40285 
40286 	if (!duk_is_constructor_call(thr)) {
40287 		return 1;
40288 	}
40289 
40290 	/*
40291 	 *  E5 Section 15.7.2.1 requires that the constructed object
40292 	 *  must have the original Number.prototype as its internal
40293 	 *  prototype.  However, since Number.prototype is non-writable
40294 	 *  and non-configurable, this doesn't have to be enforced here:
40295 	 *  The default object (bound to 'this') is OK, though we have
40296 	 *  to change its class.
40297 	 *
40298 	 *  Internal value set to ToNumber(arg) or +0; if no arg given,
40299 	 *  ToNumber(undefined) = NaN, so special treatment is needed
40300 	 *  (above).  String internal value is immutable.
40301 	 */
40302 
40303 	/* XXX: helper */
40304 	duk_push_this(thr);
40305 	h_this = duk_known_hobject(thr, -1);
40306 	DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_NUMBER);
40307 
40308 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE]);
40309 	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_this) == DUK_HOBJECT_CLASS_NUMBER);
40310 	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_this));
40311 
40312 	duk_dup_0(thr);  /* -> [ val obj val ] */
40313 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
40314 	return 0;  /* no return value -> don't replace created value */
40315 }
40316 
40317 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_value_of(duk_hthread *thr) {
40318 	(void) duk__push_this_number_plain(thr);
40319 	return 1;
40320 }
40321 
40322 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_string(duk_hthread *thr) {
40323 	duk_small_int_t radix;
40324 	duk_small_uint_t n2s_flags;
40325 
40326 	(void) duk__push_this_number_plain(thr);
40327 	if (duk_is_undefined(thr, 0)) {
40328 		radix = 10;
40329 	} else {
40330 		radix = (duk_small_int_t) duk_to_int_check_range(thr, 0, 2, 36);
40331 	}
40332 	DUK_DDD(DUK_DDDPRINT("radix=%ld", (long) radix));
40333 
40334 	n2s_flags = 0;
40335 
40336 	duk_numconv_stringify(thr,
40337 	                      radix /*radix*/,
40338 	                      0 /*digits*/,
40339 	                      n2s_flags /*flags*/);
40340 	return 1;
40341 }
40342 
40343 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_hthread *thr) {
40344 	/* XXX: just use toString() for now; permitted although not recommended.
40345 	 * nargs==1, so radix is passed to toString().
40346 	 */
40347 	return duk_bi_number_prototype_to_string(thr);
40348 }
40349 
40350 /*
40351  *  toFixed(), toExponential(), toPrecision()
40352  */
40353 
40354 /* XXX: shared helper for toFixed(), toExponential(), toPrecision()? */
40355 
40356 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_fixed(duk_hthread *thr) {
40357 	duk_small_int_t frac_digits;
40358 	duk_double_t d;
40359 	duk_small_int_t c;
40360 	duk_small_uint_t n2s_flags;
40361 
40362 	/* In ES5.1 frac_digits is coerced first; in ES2015 the 'this number
40363 	 * value' check is done first.
40364 	 */
40365 	d = duk__push_this_number_plain(thr);
40366 	frac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20);
40367 
40368 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
40369 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
40370 		goto use_to_string;
40371 	}
40372 
40373 	if (d >= 1.0e21 || d <= -1.0e21) {
40374 		goto use_to_string;
40375 	}
40376 
40377 	n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
40378 	            DUK_N2S_FLAG_FRACTION_DIGITS;
40379 
40380 	duk_numconv_stringify(thr,
40381 	                      10 /*radix*/,
40382 	                      frac_digits /*digits*/,
40383 	                      n2s_flags /*flags*/);
40384 	return 1;
40385 
40386  use_to_string:
40387 	DUK_ASSERT_TOP(thr, 2);
40388 	duk_to_string(thr, -1);
40389 	return 1;
40390 }
40391 
40392 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_exponential(duk_hthread *thr) {
40393 	duk_bool_t frac_undefined;
40394 	duk_small_int_t frac_digits;
40395 	duk_double_t d;
40396 	duk_small_int_t c;
40397 	duk_small_uint_t n2s_flags;
40398 
40399 	d = duk__push_this_number_plain(thr);
40400 
40401 	frac_undefined = duk_is_undefined(thr, 0);
40402 	duk_to_int(thr, 0);  /* for side effects */
40403 
40404 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
40405 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
40406 		goto use_to_string;
40407 	}
40408 
40409 	frac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20);
40410 
40411 	n2s_flags = DUK_N2S_FLAG_FORCE_EXP |
40412 	           (frac_undefined ? 0 : DUK_N2S_FLAG_FIXED_FORMAT);
40413 
40414 	duk_numconv_stringify(thr,
40415 	                      10 /*radix*/,
40416 	                      frac_digits + 1 /*leading digit + fractions*/,
40417 	                      n2s_flags /*flags*/);
40418 	return 1;
40419 
40420  use_to_string:
40421 	DUK_ASSERT_TOP(thr, 2);
40422 	duk_to_string(thr, -1);
40423 	return 1;
40424 }
40425 
40426 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_precision(duk_hthread *thr) {
40427 	/* The specification has quite awkward order of coercion and
40428 	 * checks for toPrecision().  The operations below are a bit
40429 	 * reordered, within constraints of observable side effects.
40430 	 */
40431 
40432 	duk_double_t d;
40433 	duk_small_int_t prec;
40434 	duk_small_int_t c;
40435 	duk_small_uint_t n2s_flags;
40436 
40437 	DUK_ASSERT_TOP(thr, 1);
40438 
40439 	d = duk__push_this_number_plain(thr);
40440 	if (duk_is_undefined(thr, 0)) {
40441 		goto use_to_string;
40442 	}
40443 	DUK_ASSERT_TOP(thr, 2);
40444 
40445 	duk_to_int(thr, 0);  /* for side effects */
40446 
40447 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
40448 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
40449 		goto use_to_string;
40450 	}
40451 
40452 	prec = (duk_small_int_t) duk_to_int_check_range(thr, 0, 1, 21);
40453 
40454 	n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
40455 	            DUK_N2S_FLAG_NO_ZERO_PAD;
40456 
40457 	duk_numconv_stringify(thr,
40458 	                      10 /*radix*/,
40459 	                      prec /*digits*/,
40460 	                      n2s_flags /*flags*/);
40461 	return 1;
40462 
40463  use_to_string:
40464 	/* Used when precision is undefined; also used for NaN (-> "NaN"),
40465 	 * and +/- infinity (-> "Infinity", "-Infinity").
40466 	 */
40467 
40468 	DUK_ASSERT_TOP(thr, 2);
40469 	duk_to_string(thr, -1);
40470 	return 1;
40471 }
40472 
40473 /*
40474  *  ES2015 isFinite() etc
40475  */
40476 
40477 #if defined(DUK_USE_ES6)
40478 DUK_INTERNAL duk_ret_t duk_bi_number_check_shared(duk_hthread *thr) {
40479 	duk_int_t magic;
40480 	duk_bool_t ret = 0;
40481 
40482 	if (duk_is_number(thr, 0)) {
40483 		duk_double_t d;
40484 
40485 		magic = duk_get_current_magic(thr);
40486 		d = duk_get_number(thr, 0);
40487 
40488 		switch (magic) {
40489 		case 0:  /* isFinite() */
40490 			ret = duk_double_is_finite(d);
40491 			break;
40492 		case 1:  /* isInteger() */
40493 			ret = duk_double_is_integer(d);
40494 			break;
40495 		case 2:  /* isNaN() */
40496 			ret = duk_double_is_nan(d);
40497 			break;
40498 		default:  /* isSafeInteger() */
40499 			DUK_ASSERT(magic == 3);
40500 			ret = duk_double_is_safe_integer(d);
40501 		}
40502 	}
40503 
40504 	duk_push_boolean(thr, ret);
40505 	return 1;
40506 }
40507 #endif  /* DUK_USE_ES6 */
40508 
40509 #endif  /* DUK_USE_NUMBER_BUILTIN */
40510 #line 1 "duk_bi_object.c"
40511 /*
40512  *  Object built-ins
40513  */
40514 
40515 /* #include duk_internal.h -> already included */
40516 
40517 /* Needed even when Object built-in disabled. */
40518 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_string(duk_hthread *thr) {
40519 	duk_tval *tv;
40520 
40521 	tv = DUK_HTHREAD_THIS_PTR(thr);
40522 	duk_push_class_string_tval(thr, tv, 0 /*avoid_side_effects*/);
40523 	return 1;
40524 }
40525 
40526 #if defined(DUK_USE_OBJECT_BUILTIN)
40527 DUK_INTERNAL duk_ret_t duk_bi_object_constructor(duk_hthread *thr) {
40528 	duk_uint_t arg_mask;
40529 
40530 	arg_mask = duk_get_type_mask(thr, 0);
40531 
40532 	if (!duk_is_constructor_call(thr) &&  /* not a constructor call */
40533 	    ((arg_mask & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED)) == 0)) {  /* and argument not null or undefined */
40534 		duk_to_object(thr, 0);
40535 		return 1;
40536 	}
40537 
40538 	/* Pointer and buffer primitive values are treated like other
40539 	 * primitives values which have a fully fledged object counterpart:
40540 	 * promote to an object value.  Lightfuncs and plain buffers are
40541 	 * coerced with ToObject() even they could also be returned as is.
40542 	 */
40543 	if (arg_mask & (DUK_TYPE_MASK_OBJECT |
40544 	                DUK_TYPE_MASK_STRING |
40545 	                DUK_TYPE_MASK_BOOLEAN |
40546 	                DUK_TYPE_MASK_NUMBER |
40547 	                DUK_TYPE_MASK_POINTER |
40548 	                DUK_TYPE_MASK_BUFFER |
40549 	                DUK_TYPE_MASK_LIGHTFUNC)) {
40550 		/* For DUK_TYPE_OBJECT the coercion is a no-op and could
40551 		 * be checked for explicitly, but Object(obj) calls are
40552 		 * not very common so opt for minimal footprint.
40553 		 */
40554 		duk_to_object(thr, 0);
40555 		return 1;
40556 	}
40557 
40558 	(void) duk_push_object_helper(thr,
40559 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
40560 	                              DUK_HOBJECT_FLAG_FASTREFS |
40561 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
40562 	                              DUK_BIDX_OBJECT_PROTOTYPE);
40563 	return 1;
40564 }
40565 #endif  /* DUK_USE_OBJECT_BUILTIN */
40566 
40567 #if defined(DUK_USE_OBJECT_BUILTIN) && defined(DUK_USE_ES6)
40568 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_assign(duk_hthread *thr) {
40569 	duk_idx_t nargs;
40570 	duk_int_t idx;
40571 
40572 	nargs = duk_get_top_require_min(thr, 1 /*min_top*/);
40573 
40574 	duk_to_object(thr, 0);
40575 	for (idx = 1; idx < nargs; idx++) {
40576 		/* E7 19.1.2.1 (step 4a) */
40577 		if (duk_is_null_or_undefined(thr, idx)) {
40578 			continue;
40579 		}
40580 
40581 		/* duk_enum() respects ES2015+ [[OwnPropertyKeys]] ordering, which is
40582 		 * convenient here.
40583 		 */
40584 		duk_to_object(thr, idx);
40585 		duk_enum(thr, idx, DUK_ENUM_OWN_PROPERTIES_ONLY);
40586 		while (duk_next(thr, -1, 1 /*get_value*/)) {
40587 			/* [ target ... enum key value ] */
40588 			duk_put_prop(thr, 0);
40589 			/* [ target ... enum ] */
40590 		}
40591 		/* Could pop enumerator, but unnecessary because of duk_set_top()
40592 		 * below.
40593 		 */
40594 	}
40595 
40596 	duk_set_top(thr, 1);
40597 	return 1;
40598 }
40599 #endif
40600 
40601 #if defined(DUK_USE_OBJECT_BUILTIN) && defined(DUK_USE_ES6)
40602 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is(duk_hthread *thr) {
40603 	DUK_ASSERT_TOP(thr, 2);
40604 	duk_push_boolean(thr, duk_samevalue(thr, 0, 1));
40605 	return 1;
40606 }
40607 #endif
40608 
40609 #if defined(DUK_USE_OBJECT_BUILTIN)
40610 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_create(duk_hthread *thr) {
40611 	duk_hobject *proto;
40612 
40613 	DUK_ASSERT_TOP(thr, 2);
40614 
40615 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
40616 	duk_hbufobj_promote_plain(thr, 0);
40617 #endif
40618 	proto = duk_require_hobject_accept_mask(thr, 0, DUK_TYPE_MASK_NULL);
40619 	DUK_ASSERT(proto != NULL || duk_is_null(thr, 0));
40620 
40621 	(void) duk_push_object_helper_proto(thr,
40622 	                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
40623 	                                    DUK_HOBJECT_FLAG_FASTREFS |
40624 	                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
40625 	                                    proto);
40626 
40627 	if (!duk_is_undefined(thr, 1)) {
40628 		/* [ O Properties obj ] */
40629 
40630 		duk_replace(thr, 0);
40631 
40632 		/* [ obj Properties ] */
40633 
40634 		/* Just call the "original" Object.defineProperties() to
40635 		 * finish up.
40636 		 */
40637 
40638 		return duk_bi_object_constructor_define_properties(thr);
40639 	}
40640 
40641 	/* [ O Properties obj ] */
40642 
40643 	return 1;
40644 }
40645 #endif  /* DUK_USE_OBJECT_BUILTIN */
40646 
40647 #if defined(DUK_USE_OBJECT_BUILTIN)
40648 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_properties(duk_hthread *thr) {
40649 	duk_small_uint_t pass;
40650 	duk_uint_t defprop_flags;
40651 	duk_hobject *obj;
40652 	duk_idx_t idx_value;
40653 	duk_hobject *get;
40654 	duk_hobject *set;
40655 
40656 	/* Lightfunc and plain buffer handling by ToObject() coercion. */
40657 	obj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
40658 	DUK_ASSERT(obj != NULL);
40659 
40660 	duk_to_object(thr, 1);        /* properties object */
40661 
40662 	DUK_DDD(DUK_DDDPRINT("target=%!iT, properties=%!iT",
40663 	                     (duk_tval *) duk_get_tval(thr, 0),
40664 	                     (duk_tval *) duk_get_tval(thr, 1)));
40665 
40666 	/*
40667 	 *  Two pass approach to processing the property descriptors.
40668 	 *  On first pass validate and normalize all descriptors before
40669 	 *  any changes are made to the target object.  On second pass
40670 	 *  make the actual modifications to the target object.
40671 	 *
40672 	 *  Right now we'll just use the same normalize/validate helper
40673 	 *  on both passes, ignoring its outputs on the first pass.
40674 	 */
40675 
40676 	for (pass = 0; pass < 2; pass++) {
40677 		duk_set_top(thr, 2);  /* -> [ hobject props ] */
40678 		duk_enum(thr, 1, DUK_ENUM_OWN_PROPERTIES_ONLY | DUK_ENUM_INCLUDE_SYMBOLS /*enum_flags*/);
40679 
40680 		for (;;) {
40681 			duk_hstring *key;
40682 
40683 			/* [ hobject props enum(props) ] */
40684 
40685 			duk_set_top(thr, 3);
40686 
40687 			if (!duk_next(thr, 2, 1 /*get_value*/)) {
40688 				break;
40689 			}
40690 
40691 			DUK_DDD(DUK_DDDPRINT("-> key=%!iT, desc=%!iT",
40692 			                     (duk_tval *) duk_get_tval(thr, -2),
40693 			                     (duk_tval *) duk_get_tval(thr, -1)));
40694 
40695 			/* [ hobject props enum(props) key desc ] */
40696 
40697 			duk_hobject_prepare_property_descriptor(thr,
40698 			                                        4 /*idx_desc*/,
40699 			                                        &defprop_flags,
40700 			                                        &idx_value,
40701 			                                        &get,
40702 			                                        &set);
40703 
40704 			/* [ hobject props enum(props) key desc [multiple values] ] */
40705 
40706 			if (pass == 0) {
40707 				continue;
40708 			}
40709 
40710 			/* This allows symbols on purpose. */
40711 			key = duk_known_hstring(thr, 3);
40712 			DUK_ASSERT(key != NULL);
40713 
40714 			duk_hobject_define_property_helper(thr,
40715 			                                   defprop_flags,
40716 			                                   obj,
40717 			                                   key,
40718 			                                   idx_value,
40719 			                                   get,
40720 			                                   set,
40721 			                                   1 /*throw_flag*/);
40722 		}
40723 	}
40724 
40725 	/*
40726 	 *  Return target object
40727 	 */
40728 
40729 	duk_dup_0(thr);
40730 	return 1;
40731 }
40732 #endif  /* DUK_USE_OBJECT_BUILTIN */
40733 
40734 #if defined(DUK_USE_OBJECT_BUILTIN)
40735 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_hthread *thr) {
40736 	DUK_ASSERT_TOP(thr, 1);
40737 
40738 	duk_seal_freeze_raw(thr, 0, (duk_bool_t) duk_get_current_magic(thr) /*is_freeze*/);
40739 	return 1;
40740 }
40741 #endif  /* DUK_USE_OBJECT_BUILTIN */
40742 
40743 #if defined(DUK_USE_OBJECT_BUILTIN)
40744 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_hthread *thr) {
40745 	duk_hobject *h;
40746 	duk_bool_t is_frozen;
40747 	duk_uint_t mask;
40748 
40749 	is_frozen = (duk_bool_t) duk_get_current_magic(thr);
40750 	mask = duk_get_type_mask(thr, 0);
40751 	if (mask & (DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {
40752 		DUK_ASSERT(is_frozen == 0 || is_frozen == 1);
40753 		duk_push_boolean(thr, (mask & DUK_TYPE_MASK_LIGHTFUNC) ?
40754 		                          1 :               /* lightfunc always frozen and sealed */
40755 		                          (is_frozen ^ 1)); /* buffer sealed but not frozen (index props writable) */
40756 	} else {
40757 		/* ES2015 Sections 19.1.2.12, 19.1.2.13: anything other than an object
40758 		 * is considered to be already sealed and frozen.
40759 		 */
40760 		h = duk_get_hobject(thr, 0);
40761 		duk_push_boolean(thr, (h == NULL) ||
40762 		                      duk_hobject_object_is_sealed_frozen_helper(thr, h, is_frozen /*is_frozen*/));
40763 	}
40764 	return 1;
40765 }
40766 #endif  /* DUK_USE_OBJECT_BUILTIN */
40767 
40768 #if defined(DUK_USE_OBJECT_BUILTIN)
40769 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_hthread *thr) {
40770 	DUK_ASSERT_TOP(thr, 0);
40771 	(void) duk_push_this_coercible_to_object(thr);
40772 	duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_TO_STRING);
40773 #if 0  /* This is mentioned explicitly in the E5.1 spec, but duk_call_method() checks for it in practice. */
40774 	duk_require_callable(thr, 1);
40775 #endif
40776 	duk_dup_0(thr);  /* -> [ O toString O ] */
40777 	duk_call_method(thr, 0);  /* XXX: call method tail call? */
40778 	return 1;
40779 }
40780 #endif  /* DUK_USE_OBJECT_BUILTIN */
40781 
40782 #if defined(DUK_USE_OBJECT_BUILTIN)
40783 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_value_of(duk_hthread *thr) {
40784 	/* For lightfuncs and plain buffers, returns Object() coerced. */
40785 	(void) duk_push_this_coercible_to_object(thr);
40786 	return 1;
40787 }
40788 #endif  /* DUK_USE_OBJECT_BUILTIN */
40789 
40790 #if defined(DUK_USE_OBJECT_BUILTIN)
40791 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_hthread *thr) {
40792 	duk_hobject *h_v;
40793 	duk_hobject *h_obj;
40794 
40795 	DUK_ASSERT_TOP(thr, 1);
40796 
40797 	h_v = duk_get_hobject(thr, 0);
40798 	if (!h_v) {
40799 		duk_push_false(thr);  /* XXX: tail call: return duk_push_false(thr) */
40800 		return 1;
40801 	}
40802 
40803 	h_obj = duk_push_this_coercible_to_object(thr);
40804 	DUK_ASSERT(h_obj != NULL);
40805 
40806 	/* E5.1 Section 15.2.4.6, step 3.a, lookup proto once before compare.
40807 	 * Prototype loops should cause an error to be thrown.
40808 	 */
40809 	duk_push_boolean(thr, duk_hobject_prototype_chain_contains(thr, DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_v), h_obj, 0 /*ignore_loop*/));
40810 	return 1;
40811 }
40812 #endif  /* DUK_USE_OBJECT_BUILTIN */
40813 
40814 #if defined(DUK_USE_OBJECT_BUILTIN)
40815 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_has_own_property(duk_hthread *thr) {
40816 	return (duk_ret_t) duk_hobject_object_ownprop_helper(thr, 0 /*required_desc_flags*/);
40817 }
40818 #endif  /* DUK_USE_OBJECT_BUILTIN */
40819 
40820 #if defined(DUK_USE_OBJECT_BUILTIN)
40821 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_hthread *thr) {
40822 	return (duk_ret_t) duk_hobject_object_ownprop_helper(thr, DUK_PROPDESC_FLAG_ENUMERABLE /*required_desc_flags*/);
40823 }
40824 #endif  /* DUK_USE_OBJECT_BUILTIN */
40825 
40826 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
40827 /* Shared helper to implement Object.getPrototypeOf,
40828  * Object.prototype.__proto__ getter, and Reflect.getPrototypeOf.
40829  *
40830  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
40831  */
40832 DUK_INTERNAL duk_ret_t duk_bi_object_getprototype_shared(duk_hthread *thr) {
40833 	/*
40834 	 *  magic = 0: __proto__ getter
40835 	 *  magic = 1: Object.getPrototypeOf()
40836 	 *  magic = 2: Reflect.getPrototypeOf()
40837 	 */
40838 
40839 	duk_hobject *h;
40840 	duk_hobject *proto;
40841 	duk_tval *tv;
40842 	duk_int_t magic;
40843 
40844 	magic = duk_get_current_magic(thr);
40845 
40846 	if (magic == 0) {
40847 		DUK_ASSERT_TOP(thr, 0);
40848 		duk_push_this_coercible_to_object(thr);
40849 	}
40850 	DUK_ASSERT(duk_get_top(thr) >= 1);
40851 	if (magic < 2) {
40852 		/* ES2015 Section 19.1.2.9, step 1 */
40853 		duk_to_object(thr, 0);
40854 	}
40855 	tv = DUK_GET_TVAL_POSIDX(thr, 0);
40856 
40857 	switch (DUK_TVAL_GET_TAG(tv)) {
40858 	case DUK_TAG_BUFFER:
40859 		proto = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
40860 		break;
40861 	case DUK_TAG_LIGHTFUNC:
40862 		proto = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
40863 		break;
40864 	case DUK_TAG_OBJECT:
40865 		h = DUK_TVAL_GET_OBJECT(tv);
40866 		proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
40867 		break;
40868 	default:
40869 		/* This implicitly handles CheckObjectCoercible() caused
40870 		 * TypeError.
40871 		 */
40872 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
40873 	}
40874 	if (proto != NULL) {
40875 		duk_push_hobject(thr, proto);
40876 	} else {
40877 		duk_push_null(thr);
40878 	}
40879 	return 1;
40880 }
40881 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
40882 
40883 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
40884 /* Shared helper to implement ES2015 Object.setPrototypeOf,
40885  * Object.prototype.__proto__ setter, and Reflect.setPrototypeOf.
40886  *
40887  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
40888  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.setprototypeof
40889  */
40890 DUK_INTERNAL duk_ret_t duk_bi_object_setprototype_shared(duk_hthread *thr) {
40891 	/*
40892 	 *  magic = 0: __proto__ setter
40893 	 *  magic = 1: Object.setPrototypeOf()
40894 	 *  magic = 2: Reflect.setPrototypeOf()
40895 	 */
40896 
40897 	duk_hobject *h_obj;
40898 	duk_hobject *h_new_proto;
40899 	duk_hobject *h_curr;
40900 	duk_ret_t ret_success = 1;  /* retval for success path */
40901 	duk_uint_t mask;
40902 	duk_int_t magic;
40903 
40904 	/* Preliminaries for __proto__ and setPrototypeOf (E6 19.1.2.18 steps 1-4). */
40905 	magic = duk_get_current_magic(thr);
40906 	if (magic == 0) {
40907 		duk_push_this_check_object_coercible(thr);
40908 		duk_insert(thr, 0);
40909 		if (!duk_check_type_mask(thr, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT)) {
40910 			return 0;
40911 		}
40912 
40913 		/* __proto__ setter returns 'undefined' on success unlike the
40914 		 * setPrototypeOf() call which returns the target object.
40915 		 */
40916 		ret_success = 0;
40917 	} else {
40918 		if (magic == 1) {
40919 			duk_require_object_coercible(thr, 0);
40920 		} else {
40921 			duk_require_hobject_accept_mask(thr, 0,
40922 			                                DUK_TYPE_MASK_LIGHTFUNC |
40923 			                                DUK_TYPE_MASK_BUFFER);
40924 		}
40925 		duk_require_type_mask(thr, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT);
40926 	}
40927 
40928 	h_new_proto = duk_get_hobject(thr, 1);
40929 	/* h_new_proto may be NULL */
40930 
40931 	mask = duk_get_type_mask(thr, 0);
40932 	if (mask & (DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {
40933 		duk_hobject *curr_proto;
40934 		curr_proto = thr->builtins[(mask & DUK_TYPE_MASK_LIGHTFUNC) ?
40935 		                               DUK_BIDX_FUNCTION_PROTOTYPE :
40936 		                               DUK_BIDX_UINT8ARRAY_PROTOTYPE];
40937 		if (h_new_proto == curr_proto) {
40938 			goto skip;
40939 		}
40940 		goto fail_nonextensible;
40941 	}
40942 	h_obj = duk_get_hobject(thr, 0);
40943 	if (h_obj == NULL) {
40944 		goto skip;
40945 	}
40946 	DUK_ASSERT(h_obj != NULL);
40947 
40948 	/* [[SetPrototypeOf]] standard behavior, E6 9.1.2. */
40949 	/* TODO: implement Proxy object support here */
40950 
40951 	if (h_new_proto == DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_obj)) {
40952 		goto skip;
40953 	}
40954 	if (!DUK_HOBJECT_HAS_EXTENSIBLE(h_obj)) {
40955 		goto fail_nonextensible;
40956 	}
40957 	for (h_curr = h_new_proto; h_curr != NULL; h_curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_curr)) {
40958 		/* Loop prevention. */
40959 		if (h_curr == h_obj) {
40960 			goto fail_loop;
40961 		}
40962 	}
40963 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h_obj, h_new_proto);
40964 	/* fall thru */
40965 
40966  skip:
40967 	duk_set_top(thr, 1);
40968 	if (magic == 2) {
40969 		duk_push_true(thr);
40970 	}
40971 	return ret_success;
40972 
40973  fail_nonextensible:
40974  fail_loop:
40975 	if (magic != 2) {
40976 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
40977 	} else {
40978 		duk_push_false(thr);
40979 		return 1;
40980 	}
40981 }
40982 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
40983 
40984 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
40985 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_property(duk_hthread *thr) {
40986 	/*
40987 	 *  magic = 0: Object.defineProperty()
40988 	 *  magic = 1: Reflect.defineProperty()
40989 	 */
40990 
40991 	duk_hobject *obj;
40992 	duk_hstring *key;
40993 	duk_hobject *get;
40994 	duk_hobject *set;
40995 	duk_idx_t idx_value;
40996 	duk_uint_t defprop_flags;
40997 	duk_small_uint_t magic;
40998 	duk_bool_t throw_flag;
40999 	duk_bool_t ret;
41000 
41001 	DUK_ASSERT(thr != NULL);
41002 
41003 	DUK_DDD(DUK_DDDPRINT("Object.defineProperty(): ctx=%p obj=%!T key=%!T desc=%!T",
41004 	                     (void *) thr,
41005 	                     (duk_tval *) duk_get_tval(thr, 0),
41006 	                     (duk_tval *) duk_get_tval(thr, 1),
41007 	                     (duk_tval *) duk_get_tval(thr, 2)));
41008 
41009 	/* [ obj key desc ] */
41010 
41011 	magic = (duk_small_uint_t) duk_get_current_magic(thr);
41012 
41013 	/* Lightfuncs are currently supported by coercing to a temporary
41014 	 * Function object; changes will be allowed (the coerced value is
41015 	 * extensible) but will be lost.  Same for plain buffers.
41016 	 */
41017 	obj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
41018 	DUK_ASSERT(obj != NULL);
41019 	key = duk_to_property_key_hstring(thr, 1);
41020 	(void) duk_require_hobject(thr, 2);
41021 
41022 	DUK_ASSERT(obj != NULL);
41023 	DUK_ASSERT(key != NULL);
41024 	DUK_ASSERT(duk_get_hobject(thr, 2) != NULL);
41025 
41026 	/*
41027 	 *  Validate and convert argument property descriptor (an ECMAScript
41028 	 *  object) into a set of defprop_flags and possibly property value,
41029 	 *  getter, and/or setter values on the value stack.
41030 	 *
41031 	 *  Lightfunc set/get values are coerced to full Functions.
41032 	 */
41033 
41034 	duk_hobject_prepare_property_descriptor(thr,
41035 	                                        2 /*idx_desc*/,
41036 	                                        &defprop_flags,
41037 	                                        &idx_value,
41038 	                                        &get,
41039 	                                        &set);
41040 
41041 	/*
41042 	 *  Use Object.defineProperty() helper for the actual operation.
41043 	 */
41044 
41045 	DUK_ASSERT(magic == 0U || magic == 1U);
41046 	throw_flag = magic ^ 1U;
41047 	ret = duk_hobject_define_property_helper(thr,
41048 	                                         defprop_flags,
41049 	                                         obj,
41050 	                                         key,
41051 	                                         idx_value,
41052 	                                         get,
41053 	                                         set,
41054 	                                         throw_flag);
41055 
41056 	/* Ignore the normalize/validate helper outputs on the value stack,
41057 	 * they're popped automatically.
41058 	 */
41059 
41060 	if (magic == 0U) {
41061 		/* Object.defineProperty(): return target object. */
41062 		duk_push_hobject(thr, obj);
41063 	} else {
41064 		/* Reflect.defineProperty(): return success/fail. */
41065 		duk_push_boolean(thr, ret);
41066 	}
41067 	return 1;
41068 }
41069 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
41070 
41071 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
41072 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_hthread *thr) {
41073 	DUK_ASSERT_TOP(thr, 2);
41074 
41075 	/* ES2015 Section 19.1.2.6, step 1 */
41076 	if (duk_get_current_magic(thr) == 0) {
41077 		duk_to_object(thr, 0);
41078 	}
41079 
41080 	/* [ obj key ] */
41081 
41082 	duk_hobject_object_get_own_property_descriptor(thr, -2);
41083 	return 1;
41084 }
41085 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
41086 
41087 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
41088 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_extensible(duk_hthread *thr) {
41089 	/*
41090 	 *  magic = 0: Object.isExtensible()
41091 	 *  magic = 1: Reflect.isExtensible()
41092 	 */
41093 
41094 	duk_hobject *h;
41095 
41096 	if (duk_get_current_magic(thr) == 0) {
41097 		h = duk_get_hobject(thr, 0);
41098 	} else {
41099 		/* Reflect.isExtensible(): throw if non-object, but we accept lightfuncs
41100 		 * and plain buffers here because they pretend to be objects.
41101 		 */
41102 		h = duk_require_hobject_accept_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
41103 	}
41104 
41105 	duk_push_boolean(thr, (h != NULL) && DUK_HOBJECT_HAS_EXTENSIBLE(h));
41106 	return 1;
41107 }
41108 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
41109 
41110 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
41111 /* Shared helper for various key/symbol listings, magic:
41112  * 0=Object.keys()
41113  * 1=Object.getOwnPropertyNames(),
41114  * 2=Object.getOwnPropertySymbols(),
41115  * 3=Reflect.ownKeys()
41116  */
41117 DUK_LOCAL const duk_small_uint_t duk__object_keys_enum_flags[4] = {
41118 	/* Object.keys() */
41119 	DUK_ENUM_OWN_PROPERTIES_ONLY |
41120 	    DUK_ENUM_NO_PROXY_BEHAVIOR,
41121 
41122 	/* Object.getOwnPropertyNames() */
41123 	DUK_ENUM_INCLUDE_NONENUMERABLE |
41124 	    DUK_ENUM_OWN_PROPERTIES_ONLY |
41125 	    DUK_ENUM_NO_PROXY_BEHAVIOR,
41126 
41127 	/* Object.getOwnPropertySymbols() */
41128 	DUK_ENUM_INCLUDE_SYMBOLS |
41129 	    DUK_ENUM_OWN_PROPERTIES_ONLY |
41130 	    DUK_ENUM_EXCLUDE_STRINGS |
41131 	    DUK_ENUM_INCLUDE_NONENUMERABLE |
41132 	    DUK_ENUM_NO_PROXY_BEHAVIOR,
41133 
41134 	/* Reflect.ownKeys() */
41135 	DUK_ENUM_INCLUDE_SYMBOLS |
41136 	    DUK_ENUM_OWN_PROPERTIES_ONLY |
41137 	    DUK_ENUM_INCLUDE_NONENUMERABLE |
41138 	    DUK_ENUM_NO_PROXY_BEHAVIOR
41139 };
41140 
41141 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_keys_shared(duk_hthread *thr) {
41142 	duk_hobject *obj;
41143 #if defined(DUK_USE_ES6_PROXY)
41144 	duk_hobject *h_proxy_target;
41145 	duk_hobject *h_proxy_handler;
41146 	duk_hobject *h_trap_result;
41147 #endif
41148 	duk_small_uint_t enum_flags;
41149 	duk_int_t magic;
41150 
41151 	DUK_ASSERT_TOP(thr, 1);
41152 
41153 	magic = duk_get_current_magic(thr);
41154 	if (magic == 3) {
41155 		/* ES2015 Section 26.1.11 requires a TypeError for non-objects.  Lightfuncs
41156 		 * and plain buffers pretend to be objects, so accept those too.
41157 		 */
41158 		obj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
41159 	} else {
41160 		/* ES2015: ToObject coerce. */
41161 		obj = duk_to_hobject(thr, 0);
41162 	}
41163 	DUK_ASSERT(obj != NULL);
41164 	DUK_UNREF(obj);
41165 
41166 	/* XXX: proxy chains */
41167 
41168 #if defined(DUK_USE_ES6_PROXY)
41169 	/* XXX: better sharing of code between proxy target call sites */
41170 	if (DUK_LIKELY(!duk_hobject_proxy_check(obj,
41171 	                                        &h_proxy_target,
41172 	                                        &h_proxy_handler))) {
41173 		goto skip_proxy;
41174 	}
41175 
41176 	duk_push_hobject(thr, h_proxy_handler);
41177 	if (!duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_OWN_KEYS)) {
41178 		/* Careful with reachability here: don't pop 'obj' before pushing
41179 		 * proxy target.
41180 		 */
41181 		DUK_DDD(DUK_DDDPRINT("no ownKeys trap, get keys of target instead"));
41182 		duk_pop_2(thr);
41183 		duk_push_hobject(thr, h_proxy_target);
41184 		duk_replace(thr, 0);
41185 		DUK_ASSERT_TOP(thr, 1);
41186 		goto skip_proxy;
41187 	}
41188 
41189 	/* [ obj handler trap ] */
41190 	duk_insert(thr, -2);
41191 	duk_push_hobject(thr, h_proxy_target);  /* -> [ obj trap handler target ] */
41192 	duk_call_method(thr, 1 /*nargs*/);      /* -> [ obj trap_result ] */
41193 	h_trap_result = duk_require_hobject(thr, -1);
41194 	DUK_UNREF(h_trap_result);
41195 
41196 	magic = duk_get_current_magic(thr);
41197 	DUK_ASSERT(magic >= 0 && magic < (duk_int_t) (sizeof(duk__object_keys_enum_flags) / sizeof(duk_small_uint_t)));
41198 	enum_flags = duk__object_keys_enum_flags[magic];
41199 
41200 	duk_proxy_ownkeys_postprocess(thr, h_proxy_target, enum_flags);
41201 	return 1;
41202 
41203  skip_proxy:
41204 #endif  /* DUK_USE_ES6_PROXY */
41205 
41206 	DUK_ASSERT_TOP(thr, 1);
41207 	magic = duk_get_current_magic(thr);
41208 	DUK_ASSERT(magic >= 0 && magic < (duk_int_t) (sizeof(duk__object_keys_enum_flags) / sizeof(duk_small_uint_t)));
41209 	enum_flags = duk__object_keys_enum_flags[magic];
41210 	return duk_hobject_get_enumerated_keys(thr, enum_flags);
41211 }
41212 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
41213 
41214 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
41215 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_hthread *thr) {
41216 	/*
41217 	 *  magic = 0: Object.preventExtensions()
41218 	 *  magic = 1: Reflect.preventExtensions()
41219 	 */
41220 
41221 	duk_hobject *h;
41222 	duk_uint_t mask;
41223 	duk_int_t magic;
41224 
41225 	magic = duk_get_current_magic(thr);
41226 
41227 	/* Silent success for lightfuncs and plain buffers always. */
41228 	mask = DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER;
41229 
41230 	/* Object.preventExtensions() silent success for non-object. */
41231 	if (magic == 0) {
41232 		mask |= DUK_TYPE_MASK_UNDEFINED |
41233 		        DUK_TYPE_MASK_NULL |
41234 		        DUK_TYPE_MASK_BOOLEAN |
41235 		        DUK_TYPE_MASK_NUMBER |
41236 		        DUK_TYPE_MASK_STRING |
41237 		        DUK_TYPE_MASK_POINTER;
41238 	}
41239 
41240 	if (duk_check_type_mask(thr, 0, mask)) {
41241 		/* Not an object, already non-extensible so always success. */
41242 		goto done;
41243 	}
41244 	h = duk_require_hobject(thr, 0);
41245 	DUK_ASSERT(h != NULL);
41246 
41247 	DUK_HOBJECT_CLEAR_EXTENSIBLE(h);
41248 
41249 	/* A non-extensible object cannot gain any more properties,
41250 	 * so this is a good time to compact.
41251 	 */
41252 	duk_hobject_compact_props(thr, h);
41253 
41254  done:
41255 	if (magic == 1) {
41256 		duk_push_true(thr);
41257 	}
41258 	return 1;
41259 }
41260 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
41261 
41262 /*
41263  *  __defineGetter__, __defineSetter__, __lookupGetter__, __lookupSetter__
41264  */
41265 
41266 #if defined(DUK_USE_ES8)
41267 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_defineaccessor(duk_hthread *thr) {
41268 	duk_push_this(thr);
41269 	duk_insert(thr, 0);
41270 	duk_to_object(thr, 0);
41271 	duk_require_callable(thr, 2);
41272 
41273 	/* [ ToObject(this) key getter/setter ] */
41274 
41275 	/* ToPropertyKey() coercion is not needed, duk_def_prop() does it. */
41276 	duk_def_prop(thr, 0, DUK_DEFPROP_SET_ENUMERABLE |
41277 	                     DUK_DEFPROP_SET_CONFIGURABLE |
41278 	                     (duk_get_current_magic(thr) ? DUK_DEFPROP_HAVE_SETTER : DUK_DEFPROP_HAVE_GETTER));
41279 	return 0;
41280 }
41281 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_lookupaccessor(duk_hthread *thr) {
41282 	duk_uint_t sanity;
41283 
41284 	duk_push_this(thr);
41285 	duk_to_object(thr, -1);
41286 
41287 	/* XXX: Prototype walk (with sanity) should be a core property
41288 	 * operation, could add a flag to e.g. duk_get_prop_desc().
41289 	 */
41290 
41291 	/* ToPropertyKey() coercion is not needed, duk_get_prop_desc() does it. */
41292 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
41293 	while (!duk_is_undefined(thr, -1)) {
41294 		/* [ key obj ] */
41295 		duk_dup(thr, 0);
41296 		duk_get_prop_desc(thr, 1, 0 /*flags*/);
41297 		if (!duk_is_undefined(thr, -1)) {
41298 			duk_get_prop_stridx(thr, -1, (duk_get_current_magic(thr) != 0 ? DUK_STRIDX_SET : DUK_STRIDX_GET));
41299 			return 1;
41300 		}
41301 		duk_pop(thr);
41302 
41303 		if (DUK_UNLIKELY(sanity-- == 0)) {
41304 			DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
41305 			DUK_WO_NORETURN(return 0;);
41306 		}
41307 
41308 		duk_get_prototype(thr, -1);
41309 		duk_remove(thr, -2);
41310 	}
41311 	return 1;
41312 }
41313 #endif  /* DUK_USE_ES8 */
41314 #line 1 "duk_bi_performance.c"
41315 /*
41316  *  High resolution time API (performance.now() et al)
41317  *
41318  *  API specification: https://encoding.spec.whatwg.org/#ap://www.w3.org/TR/hr-time/
41319  */
41320 
41321 /* #include duk_internal.h -> already included */
41322 
41323 #if defined(DUK_USE_PERFORMANCE_BUILTIN)
41324 DUK_INTERNAL duk_ret_t duk_bi_performance_now(duk_hthread *thr) {
41325 	/* From API spec:
41326 	 * The DOMHighResTimeStamp type is used to store a time value in
41327 	 * milliseconds, measured relative from the time origin, global
41328 	 * monotonic clock, or a time value that represents a duration
41329 	 * between two DOMHighResTimeStamp's.
41330 	 */
41331 	duk_push_number(thr, duk_time_get_monotonic_time(thr));
41332 	return 1;
41333 }
41334 
41335 #if 0  /* Missing until semantics decided. */
41336 DUK_INTERNAL duk_ret_t duk_bi_performance_timeorigin_getter(duk_hthread *thr) {
41337 	/* No decision yet how to handle timeOrigins, e.g. should one be
41338 	 * initialized per heap, or per global object set.  See
41339 	 * https://www.w3.org/TR/hr-time/#time-origin.
41340 	 */
41341 	duk_push_uint(thr, 0);
41342 	return 1;
41343 }
41344 #endif  /* 0 */
41345 #endif  /* DUK_USE_PERFORMANCE_BUILTIN */
41346 #line 1 "duk_bi_pointer.c"
41347 /*
41348  *  Pointer built-ins
41349  */
41350 
41351 /* #include duk_internal.h -> already included */
41352 
41353 /*
41354  *  Constructor
41355  */
41356 
41357 DUK_INTERNAL duk_ret_t duk_bi_pointer_constructor(duk_hthread *thr) {
41358 	/* XXX: this behavior is quite useless now; it would be nice to be able
41359 	 * to create pointer values from e.g. numbers or strings.  Numbers are
41360 	 * problematic on 64-bit platforms though.  Hex encoded strings?
41361 	 */
41362 	if (duk_get_top(thr) == 0) {
41363 		duk_push_pointer(thr, NULL);
41364 	} else {
41365 		duk_to_pointer(thr, 0);
41366 	}
41367 	DUK_ASSERT(duk_is_pointer(thr, 0));
41368 	duk_set_top(thr, 1);
41369 
41370 	if (duk_is_constructor_call(thr)) {
41371 		(void) duk_push_object_helper(thr,
41372 		                              DUK_HOBJECT_FLAG_EXTENSIBLE |
41373 		                              DUK_HOBJECT_FLAG_FASTREFS |
41374 		                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER),
41375 		                              DUK_BIDX_POINTER_PROTOTYPE);
41376 
41377 		/* Pointer object internal value is immutable. */
41378 		duk_dup_0(thr);
41379 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
41380 	}
41381 	/* Note: unbalanced stack on purpose */
41382 
41383 	return 1;
41384 }
41385 
41386 /*
41387  *  toString(), valueOf()
41388  */
41389 
41390 DUK_INTERNAL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_hthread *thr) {
41391 	duk_tval *tv;
41392 	duk_small_int_t to_string = duk_get_current_magic(thr);
41393 
41394 	duk_push_this(thr);
41395 	tv = duk_require_tval(thr, -1);
41396 	DUK_ASSERT(tv != NULL);
41397 
41398 	if (DUK_TVAL_IS_POINTER(tv)) {
41399 		/* nop */
41400 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
41401 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
41402 		DUK_ASSERT(h != NULL);
41403 
41404 		/* Must be a "pointer object", i.e. class "Pointer" */
41405 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_POINTER) {
41406 			goto type_error;
41407 		}
41408 
41409 		duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
41410 	} else {
41411 		goto type_error;
41412 	}
41413 
41414 	if (to_string) {
41415 		duk_to_string(thr, -1);
41416 	}
41417 	return 1;
41418 
41419  type_error:
41420 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
41421 }
41422 #line 1 "duk_bi_promise.c"
41423 /*
41424  *  Promise built-in
41425  */
41426 
41427 /* #include duk_internal.h -> already included */
41428 
41429 #if defined(DUK_USE_PROMISE_BUILTIN)
41430 
41431 DUK_INTERNAL duk_ret_t duk_bi_promise_constructor(duk_hthread *thr) {
41432 	DUK_ERROR_TYPE(thr, "unimplemented");
41433 	DUK_WO_NORETURN(return 0;);
41434 }
41435 
41436 DUK_INTERNAL duk_ret_t duk_bi_promise_all(duk_hthread *thr) {
41437 	DUK_ERROR_TYPE(thr, "unimplemented");
41438 	DUK_WO_NORETURN(return 0;);
41439 }
41440 
41441 DUK_INTERNAL duk_ret_t duk_bi_promise_race(duk_hthread *thr) {
41442 	DUK_ERROR_TYPE(thr, "unimplemented");
41443 	DUK_WO_NORETURN(return 0;);
41444 }
41445 
41446 DUK_INTERNAL duk_ret_t duk_bi_promise_reject(duk_hthread *thr) {
41447 	DUK_ERROR_TYPE(thr, "unimplemented");
41448 	DUK_WO_NORETURN(return 0;);
41449 }
41450 
41451 DUK_INTERNAL duk_ret_t duk_bi_promise_resolve(duk_hthread *thr) {
41452 	DUK_ERROR_TYPE(thr, "unimplemented");
41453 	DUK_WO_NORETURN(return 0;);
41454 }
41455 
41456 DUK_INTERNAL duk_ret_t duk_bi_promise_catch(duk_hthread *thr) {
41457 	DUK_ERROR_TYPE(thr, "unimplemented");
41458 	DUK_WO_NORETURN(return 0;);
41459 }
41460 
41461 DUK_INTERNAL duk_ret_t duk_bi_promise_then(duk_hthread *thr) {
41462 	DUK_ERROR_TYPE(thr, "unimplemented");
41463 	DUK_WO_NORETURN(return 0;);
41464 }
41465 
41466 #endif  /* DUK_USE_PROMISE_BUILTIN */
41467 #line 1 "duk_bi_proxy.c"
41468 /*
41469  *  Proxy built-in (ES2015)
41470  */
41471 
41472 /* #include duk_internal.h -> already included */
41473 
41474 #if defined(DUK_USE_ES6_PROXY)
41475 /* Post-process a Proxy ownKeys() result at stack top.  Push a cleaned up
41476  * array of valid result keys (strings or symbols).  TypeError for invalid
41477  * values.  Flags are shared with duk_enum().
41478  */
41479 DUK_INTERNAL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h_proxy_target, duk_uint_t flags) {
41480 	duk_uarridx_t i, len, idx;
41481 	duk_propdesc desc;
41482 
41483 	DUK_CTX_ASSERT_VALID(thr);
41484 	DUK_ASSERT(h_proxy_target != NULL);
41485 
41486 	len = (duk_uarridx_t) duk_get_length(thr, -1);
41487 	idx = 0;
41488 	duk_push_array(thr);
41489 	/* XXX: preallocated dense array, fill in directly */
41490 	for (i = 0; i < len; i++) {
41491 		duk_hstring *h;
41492 
41493 		/* [ obj trap_result res_arr ] */
41494 		(void) duk_get_prop_index(thr, -2, i);
41495 		h = duk_get_hstring(thr, -1);
41496 		if (h == NULL) {
41497 			DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr);
41498 			DUK_WO_NORETURN(return;);
41499 		}
41500 
41501 		if (!(flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
41502 			/* No support for 'getOwnPropertyDescriptor' trap yet,
41503 			 * so check enumerability always from target object
41504 			 * descriptor.
41505 			 */
41506 			if (duk_hobject_get_own_propdesc(thr, h_proxy_target, duk_known_hstring(thr, -1), &desc, 0 /*flags*/)) {
41507 				if ((desc.flags & DUK_PROPDESC_FLAG_ENUMERABLE) == 0) {
41508 					DUK_DDD(DUK_DDDPRINT("ignore non-enumerable property: %!T", duk_get_tval(thr, -1)));
41509 					goto skip_key;
41510 				}
41511 			} else {
41512 				DUK_DDD(DUK_DDDPRINT("ignore non-existent property: %!T", duk_get_tval(thr, -1)));
41513 				goto skip_key;
41514 			}
41515 		}
41516 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
41517 			if (!(flags & DUK_ENUM_INCLUDE_SYMBOLS)) {
41518 				DUK_DDD(DUK_DDDPRINT("ignore symbol property: %!T", duk_get_tval(thr, -1)));
41519 				goto skip_key;
41520 			}
41521 			if (DUK_HSTRING_HAS_HIDDEN(h) && !(flags & DUK_ENUM_INCLUDE_HIDDEN)) {
41522 				DUK_DDD(DUK_DDDPRINT("ignore hidden symbol property: %!T", duk_get_tval(thr, -1)));
41523 				goto skip_key;
41524 			}
41525 		} else {
41526 			if (flags & DUK_ENUM_EXCLUDE_STRINGS) {
41527 				DUK_DDD(DUK_DDDPRINT("ignore string property: %!T", duk_get_tval(thr, -1)));
41528 				goto skip_key;
41529 			}
41530 		}
41531 
41532 		/* [ obj trap_result res_arr propname ] */
41533 		duk_push_uarridx(thr, idx++);
41534 		duk_insert(thr, -2);
41535 		duk_def_prop(thr, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_SET_WEC);
41536 		continue;
41537 
41538 	 skip_key:
41539 		duk_pop(thr);
41540 		continue;
41541 	}
41542 
41543 	/* XXX: Missing trap result validation for non-configurable target keys
41544 	 * (must be present), for non-extensible target all target keys must be
41545 	 * present and no extra keys can be present.
41546 	 * http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys
41547 	 */
41548 
41549 	/* XXX: The key enumerability check should trigger the "getOwnPropertyDescriptor"
41550 	 * trap which has not yet been implemented.  In the absence of such a trap,
41551 	 * the enumerability should be checked from the target object; this is
41552 	 * handled above.
41553 	 */
41554 }
41555 #endif  /* DUK_USE_ES6_PROXY */
41556 
41557 #if defined(DUK_USE_ES6_PROXY)
41558 DUK_INTERNAL duk_ret_t duk_bi_proxy_constructor(duk_hthread *thr) {
41559 	DUK_ASSERT_TOP(thr, 2);  /* [ target handler ] */
41560 
41561 	duk_require_constructor_call(thr);
41562 	duk_push_proxy(thr, 0 /*flags*/);  /* [ target handler ] -> [ proxy ] */
41563 	return 1;  /* replacement */
41564 }
41565 #endif  /* DUK_USE_ES6_PROXY */
41566 #line 1 "duk_bi_reflect.c"
41567 /*
41568  *  'Reflect' built-in (ES2016 Section 26.1)
41569  *  http://www.ecma-international.org/ecma-262/7.0/#sec-reflect-object
41570  *
41571  *  Many Reflect built-in functions are provided by shared helpers in
41572  *  duk_bi_object.c or duk_bi_function.c.
41573  */
41574 
41575 /* #include duk_internal.h -> already included */
41576 
41577 #if defined(DUK_USE_REFLECT_BUILTIN)
41578 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_delete_property(duk_hthread *thr) {
41579 	duk_tval *tv_obj;
41580 	duk_tval *tv_key;
41581 	duk_bool_t ret;
41582 
41583 	DUK_ASSERT_TOP(thr, 2);
41584 	(void) duk_require_hobject(thr, 0);
41585 	(void) duk_to_string(thr, 1);
41586 
41587 	/* [ target key ] */
41588 
41589 	DUK_ASSERT(thr != NULL);
41590 	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
41591 	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
41592 	ret = duk_hobject_delprop(thr, tv_obj, tv_key, 0 /*throw_flag*/);
41593 	duk_push_boolean(thr, ret);
41594 	return 1;
41595 }
41596 
41597 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_get(duk_hthread *thr) {
41598 	duk_tval *tv_obj;
41599 	duk_tval *tv_key;
41600 	duk_idx_t nargs;
41601 
41602 	DUK_ASSERT(thr != NULL);
41603 	nargs = duk_get_top_require_min(thr, 2 /*min_top*/);
41604 	(void) duk_require_hobject(thr, 0);
41605 	(void) duk_to_string(thr, 1);
41606 	if (nargs >= 3 && !duk_strict_equals(thr, 0, 2)) {
41607 		/* XXX: [[Get]] receiver currently unsupported */
41608 		DUK_ERROR_UNSUPPORTED(thr);
41609 		DUK_WO_NORETURN(return 0;);
41610 	}
41611 
41612 	/* [ target key receiver? ...? ] */
41613 
41614 	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
41615 	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
41616 	(void) duk_hobject_getprop(thr, tv_obj, tv_key);  /* This could also be a duk_get_prop(). */
41617 	return 1;
41618 }
41619 
41620 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_has(duk_hthread *thr) {
41621 	duk_tval *tv_obj;
41622 	duk_tval *tv_key;
41623 	duk_bool_t ret;
41624 
41625 	DUK_ASSERT(thr != NULL);
41626 	DUK_ASSERT_TOP(thr, 2);
41627 	(void) duk_require_hobject(thr, 0);
41628 	(void) duk_to_string(thr, 1);
41629 
41630 	/* [ target key ] */
41631 
41632 	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
41633 	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
41634 	ret = duk_hobject_hasprop(thr, tv_obj, tv_key);
41635 	duk_push_boolean(thr, ret);
41636 	return 1;
41637 }
41638 
41639 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_set(duk_hthread *thr) {
41640 	duk_tval *tv_obj;
41641 	duk_tval *tv_key;
41642 	duk_tval *tv_val;
41643 	duk_idx_t nargs;
41644 	duk_bool_t ret;
41645 
41646 	DUK_ASSERT(thr != NULL);
41647 	nargs = duk_get_top_require_min(thr, 3 /*min_top*/);
41648 	(void) duk_require_hobject(thr, 0);
41649 	(void) duk_to_string(thr, 1);
41650 	if (nargs >= 4 && !duk_strict_equals(thr, 0, 3)) {
41651 		/* XXX: [[Set]] receiver currently unsupported */
41652 		DUK_ERROR_UNSUPPORTED(thr);
41653 		DUK_WO_NORETURN(return 0;);
41654 	}
41655 
41656 	/* [ target key value receiver? ...? ] */
41657 
41658 	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
41659 	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
41660 	tv_val = DUK_GET_TVAL_POSIDX(thr, 2);
41661 	ret = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, 0 /*throw_flag*/);
41662 	duk_push_boolean(thr, ret);
41663 	return 1;
41664 }
41665 #endif  /* DUK_USE_REFLECT_BUILTIN */
41666 #line 1 "duk_bi_regexp.c"
41667 /*
41668  *  RegExp built-ins
41669  */
41670 
41671 /* #include duk_internal.h -> already included */
41672 
41673 #if defined(DUK_USE_REGEXP_SUPPORT)
41674 
41675 DUK_LOCAL void duk__get_this_regexp(duk_hthread *thr) {
41676 	duk_hobject *h;
41677 
41678 	duk_push_this(thr);
41679 	h = duk_require_hobject_with_class(thr, -1, DUK_HOBJECT_CLASS_REGEXP);
41680 	DUK_ASSERT(h != NULL);
41681 	DUK_UNREF(h);
41682 	duk_insert(thr, 0);  /* prepend regexp to valstack 0 index */
41683 }
41684 
41685 /* XXX: much to improve (code size) */
41686 DUK_INTERNAL duk_ret_t duk_bi_regexp_constructor(duk_hthread *thr) {
41687 	duk_hobject *h_pattern;
41688 
41689 	DUK_ASSERT_TOP(thr, 2);
41690 	h_pattern = duk_get_hobject(thr, 0);
41691 
41692 	if (!duk_is_constructor_call(thr) &&
41693 	    h_pattern != NULL &&
41694 	    DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP &&
41695 	    duk_is_undefined(thr, 1)) {
41696 		/* Called as a function, pattern has [[Class]] "RegExp" and
41697 		 * flags is undefined -> return object as is.
41698 		 */
41699 		/* XXX: ES2015 has a NewTarget SameValue() check which is not
41700 		 * yet implemented.
41701 		 */
41702 		duk_dup_0(thr);
41703 		return 1;
41704 	}
41705 
41706 	/* Else functionality is identical for function call and constructor
41707 	 * call.
41708 	 */
41709 
41710 	if (h_pattern != NULL &&
41711 	    DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP) {
41712 		duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_SOURCE);
41713 		if (duk_is_undefined(thr, 1)) {
41714 			/* In ES5 one would need to read the flags individually;
41715 			 * in ES2015 just read .flags.
41716 			 */
41717 			duk_get_prop_stridx(thr, 0, DUK_STRIDX_FLAGS);
41718 		} else {
41719 			/* In ES2015 allowed; overrides argument RegExp flags. */
41720 			duk_dup_1(thr);
41721 		}
41722 	} else {
41723 		if (duk_is_undefined(thr, 0)) {
41724 			duk_push_hstring_empty(thr);
41725 		} else {
41726 			duk_dup_0(thr);
41727 			duk_to_string(thr, -1);  /* Rejects Symbols. */
41728 		}
41729 		if (duk_is_undefined(thr, 1)) {
41730 			duk_push_hstring_empty(thr);
41731 		} else {
41732 			duk_dup_1(thr);
41733 			duk_to_string(thr, -1);  /* Rejects Symbols. */
41734 		}
41735 
41736 		/* [ ... pattern flags ] */
41737 	}
41738 
41739 	DUK_DDD(DUK_DDDPRINT("RegExp constructor/function call, pattern=%!T, flags=%!T",
41740 	                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
41741 
41742 	/* [ ... pattern flags ] (both uncoerced) */
41743 
41744 	duk_to_string(thr, -2);
41745 	duk_to_string(thr, -1);
41746 	duk_regexp_compile(thr);
41747 
41748 	/* [ ... bytecode escaped_source ] */
41749 
41750 	duk_regexp_create_instance(thr);
41751 
41752 	/* [ ... RegExp ] */
41753 
41754 	return 1;
41755 }
41756 
41757 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_exec(duk_hthread *thr) {
41758 	duk__get_this_regexp(thr);
41759 
41760 	/* [ regexp input ] */
41761 
41762 	duk_regexp_match(thr);
41763 
41764 	/* [ result ] */
41765 
41766 	return 1;
41767 }
41768 
41769 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_test(duk_hthread *thr) {
41770 	duk__get_this_regexp(thr);
41771 
41772 	/* [ regexp input ] */
41773 
41774 	/* result object is created and discarded; wasteful but saves code space */
41775 	duk_regexp_match(thr);
41776 
41777 	/* [ result ] */
41778 
41779 	duk_push_boolean(thr, (duk_is_null(thr, -1) ? 0 : 1));
41780 
41781 	return 1;
41782 }
41783 
41784 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_tostring(duk_hthread *thr) {
41785 	/* This must be generic in ES2015 and later. */
41786 	DUK_ASSERT_TOP(thr, 0);
41787 	duk_push_this(thr);
41788 	duk_push_literal(thr, "/");
41789 	duk_get_prop_stridx(thr, 0, DUK_STRIDX_SOURCE);
41790 	duk_dup_m2(thr);  /* another "/" */
41791 	duk_get_prop_stridx(thr, 0, DUK_STRIDX_FLAGS);
41792 	duk_concat(thr, 4);
41793 	return 1;
41794 }
41795 
41796 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_flags(duk_hthread *thr) {
41797 	/* .flags is ES2015 but present even when ES2015 bindings are
41798 	 * disabled because the constructor relies on it.
41799 	 */
41800 	duk_uint8_t buf[8];  /* enough for all flags + NUL */
41801 	duk_uint8_t *p = buf;
41802 
41803 	/* .flags is generic and works on any object. */
41804 	duk_push_this(thr);
41805 	(void) duk_require_hobject(thr, -1);
41806 	if (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL)) {
41807 		*p++ = DUK_ASC_LC_G;
41808 	}
41809 	if (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_IGNORE_CASE, NULL)) {
41810 		*p++ = DUK_ASC_LC_I;
41811 	}
41812 	if (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_MULTILINE, NULL)) {
41813 		*p++ = DUK_ASC_LC_M;
41814 	}
41815 	/* .unicode: to be added */
41816 	/* .sticky: to be added */
41817 	*p++ = DUK_ASC_NUL;
41818 	DUK_ASSERT((duk_size_t) (p - buf) <= sizeof(buf));
41819 
41820 	duk_push_string(thr, (const char *) buf);
41821 	return 1;
41822 }
41823 
41824 /* Shared helper for providing .source, .global, .multiline, etc getters. */
41825 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_hthread *thr) {
41826 	duk_hstring *h_bc;
41827 	duk_small_uint_t re_flags;
41828 	duk_hobject *h;
41829 	duk_int_t magic;
41830 
41831 	DUK_ASSERT_TOP(thr, 0);
41832 
41833 	duk_push_this(thr);
41834 	h = duk_require_hobject(thr, -1);
41835 	magic = duk_get_current_magic(thr);
41836 
41837 	if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_REGEXP) {
41838 		duk_xget_owndataprop_stridx_short(thr, 0, DUK_STRIDX_INT_SOURCE);
41839 		duk_xget_owndataprop_stridx_short(thr, 0, DUK_STRIDX_INT_BYTECODE);
41840 		h_bc = duk_require_hstring(thr, -1);
41841 		re_flags = (duk_small_uint_t) DUK_HSTRING_GET_DATA(h_bc)[0];  /* Safe even if h_bc length is 0 (= NUL) */
41842 		duk_pop(thr);
41843 	} else if (h == thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]) {
41844 		/* In ES2015 and ES2016 a TypeError would be thrown here.
41845 		 * However, this had real world issues so ES2017 draft
41846 		 * allows RegExp.prototype specifically, returning '(?:)'
41847 		 * for .source and undefined for all flags.
41848 		 */
41849 		if (magic != 16 /* .source */) {
41850 			return 0;
41851 		}
41852 		duk_push_literal(thr, "(?:)");  /* .source handled by switch-case */
41853 		re_flags = 0;
41854 	} else {
41855 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
41856 	}
41857 
41858 	/* [ regexp source ] */
41859 
41860 	switch (magic) {
41861 	case 0: {  /* global */
41862 		duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_GLOBAL));
41863 		break;
41864 	}
41865 	case 1: {  /* ignoreCase */
41866 		duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_IGNORE_CASE));
41867 		break;
41868 	}
41869 	case 2: {  /* multiline */
41870 		duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_MULTILINE));
41871 		break;
41872 	}
41873 #if 0
41874 	/* Don't provide until implemented to avoid interfering with feature
41875 	 * detection in user code.
41876 	 */
41877 	case 3:    /* sticky */
41878 	case 4: {  /* unicode */
41879 		duk_push_false(thr);
41880 		break;
41881 	}
41882 #endif
41883 	default: {  /* source */
41884 		/* leave 'source' on top */
41885 		break;
41886 	}
41887 	}
41888 
41889 	return 1;
41890 }
41891 
41892 #endif  /* DUK_USE_REGEXP_SUPPORT */
41893 #line 1 "duk_bi_string.c"
41894 /*
41895  *  String built-ins
41896  *
41897  *  Most String built-ins must only accept strings (or String objects).
41898  *  Symbols, represented internally as strings, must be generally rejected.
41899  *  The duk_push_this_coercible_to_string() helper does this automatically.
41900  */
41901 
41902 /* XXX: There are several limitations in the current implementation for
41903  * strings with >= 0x80000000UL characters.  In some cases one would need
41904  * to be able to represent the range [-0xffffffff,0xffffffff] and so on.
41905  * Generally character and byte length are assumed to fit into signed 32
41906  * bits (< 0x80000000UL).  Places with issues are not marked explicitly
41907  * below in all cases, look for signed type usage (duk_int_t etc) for
41908  * offsets/lengths.
41909  */
41910 
41911 /* #include duk_internal.h -> already included */
41912 
41913 #if defined(DUK_USE_STRING_BUILTIN)
41914 
41915 /*
41916  *  Helpers
41917  */
41918 
41919 DUK_LOCAL duk_hstring *duk__str_tostring_notregexp(duk_hthread *thr, duk_idx_t idx) {
41920 	duk_hstring *h;
41921 
41922 	if (duk_get_class_number(thr, idx) == DUK_HOBJECT_CLASS_REGEXP) {
41923 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
41924 		DUK_WO_NORETURN(return NULL;);
41925 	}
41926 	h = duk_to_hstring(thr, idx);
41927 	DUK_ASSERT(h != NULL);
41928 
41929 	return h;
41930 }
41931 
41932 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) {
41933 	duk_int_t cpos;
41934 	duk_int_t bpos;
41935 	const duk_uint8_t *p_start, *p_end, *p;
41936 	const duk_uint8_t *q_start;
41937 	duk_int_t q_blen;
41938 	duk_uint8_t firstbyte;
41939 	duk_uint8_t t;
41940 
41941 	cpos = start_cpos;
41942 
41943 	/* Empty searchstring always matches; cpos must be clamped here.
41944 	 * (If q_blen were < 0 due to clamped coercion, it would also be
41945 	 * caught here.)
41946 	 */
41947 	q_start = DUK_HSTRING_GET_DATA(h_search);
41948 	q_blen = (duk_int_t) DUK_HSTRING_GET_BYTELEN(h_search);
41949 	if (q_blen <= 0) {
41950 		return cpos;
41951 	}
41952 	DUK_ASSERT(q_blen > 0);
41953 
41954 	bpos = (duk_int_t) duk_heap_strcache_offset_char2byte(thr, h_this, (duk_uint32_t) cpos);
41955 
41956 	p_start = DUK_HSTRING_GET_DATA(h_this);
41957 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_this);
41958 	p = p_start + bpos;
41959 
41960 	/* This loop is optimized for size.  For speed, there should be
41961 	 * two separate loops, and we should ensure that memcmp() can be
41962 	 * used without an extra "will searchstring fit" check.  Doing
41963 	 * the preconditioning for 'p' and 'p_end' is easy but cpos
41964 	 * must be updated if 'p' is wound back (backward scanning).
41965 	 */
41966 
41967 	firstbyte = q_start[0];  /* leading byte of match string */
41968 	while (p <= p_end && p >= p_start) {
41969 		t = *p;
41970 
41971 		/* For ECMAScript strings, this check can only match for
41972 		 * initial UTF-8 bytes (not continuation bytes).  For other
41973 		 * strings all bets are off.
41974 		 */
41975 
41976 		if ((t == firstbyte) && ((duk_size_t) (p_end - p) >= (duk_size_t) q_blen)) {
41977 			DUK_ASSERT(q_blen > 0);
41978 			if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
41979 				return cpos;
41980 			}
41981 		}
41982 
41983 		/* track cpos while scanning */
41984 		if (backwards) {
41985 			/* when going backwards, we decrement cpos 'early';
41986 			 * 'p' may point to a continuation byte of the char
41987 			 * at offset 'cpos', but that's OK because we'll
41988 			 * backtrack all the way to the initial byte.
41989 			 */
41990 			if ((t & 0xc0) != 0x80) {
41991 				cpos--;
41992 			}
41993 			p--;
41994 		} else {
41995 			if ((t & 0xc0) != 0x80) {
41996 				cpos++;
41997 			}
41998 			p++;
41999 		}
42000 	}
42001 
42002 	/* Not found.  Empty string case is handled specially above. */
42003 	return -1;
42004 }
42005 
42006 /*
42007  *  Constructor
42008  */
42009 
42010 DUK_INTERNAL duk_ret_t duk_bi_string_constructor(duk_hthread *thr) {
42011 	duk_hstring *h;
42012 	duk_uint_t flags;
42013 
42014 	/* String constructor needs to distinguish between an argument not given at all
42015 	 * vs. given as 'undefined'.  We're a vararg function to handle this properly.
42016 	 */
42017 
42018 	/* XXX: copy current activation flags to thr, including current magic,
42019 	 * is_constructor_call etc.  This takes a few bytes in duk_hthread but
42020 	 * makes call sites smaller (there are >30 is_constructor_call and get
42021 	 * current magic call sites.
42022 	 */
42023 
42024 	if (duk_get_top(thr) == 0) {
42025 		duk_push_hstring_empty(thr);
42026 	} else {
42027 		h = duk_to_hstring_acceptsymbol(thr, 0);
42028 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h) && !duk_is_constructor_call(thr))) {
42029 			duk_push_symbol_descriptive_string(thr, h);
42030 			duk_replace(thr, 0);
42031 		}
42032 	}
42033 	duk_to_string(thr, 0);  /* catches symbol argument for constructor call */
42034 	DUK_ASSERT(duk_is_string(thr, 0));
42035 	duk_set_top(thr, 1);  /* Top may be 1 or larger. */
42036 
42037 	if (duk_is_constructor_call(thr)) {
42038 		/* String object internal value is immutable */
42039 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
42040 		        DUK_HOBJECT_FLAG_FASTREFS |
42041 		        DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
42042 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);
42043 		duk_push_object_helper(thr, flags, DUK_BIDX_STRING_PROTOTYPE);
42044 		duk_dup_0(thr);
42045 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
42046 	}
42047 	/* Note: unbalanced stack on purpose */
42048 
42049 	return 1;
42050 }
42051 
42052 DUK_LOCAL duk_ret_t duk__construct_from_codepoints(duk_hthread *thr, duk_bool_t nonbmp) {
42053 	duk_bufwriter_ctx bw_alloc;
42054 	duk_bufwriter_ctx *bw;
42055 	duk_idx_t i, n;
42056 	duk_ucodepoint_t cp;
42057 
42058 	/* XXX: It would be nice to build the string directly but ToUint16()
42059 	 * coercion is needed so a generic helper would not be very
42060 	 * helpful (perhaps coerce the value stack first here and then
42061 	 * build a string from a duk_tval number sequence in one go?).
42062 	 */
42063 
42064 	n = duk_get_top(thr);
42065 
42066 	bw = &bw_alloc;
42067 	DUK_BW_INIT_PUSHBUF(thr, bw, (duk_size_t) n);  /* initial estimate for ASCII only codepoints */
42068 
42069 	for (i = 0; i < n; i++) {
42070 		/* XXX: could improve bufwriter handling to write multiple codepoints
42071 		 * with one ensure call but the relative benefit would be quite small.
42072 		 */
42073 
42074 		if (nonbmp) {
42075 			/* ES2015 requires that (1) SameValue(cp, ToInteger(cp)) and
42076 			 * (2) cp >= 0 and cp <= 0x10ffff.  This check does not
42077 			 * implement the steps exactly but the outcome should be
42078 			 * the same.
42079 			 */
42080 			duk_int32_t i32 = 0;
42081 			if (!duk_is_whole_get_int32(duk_to_number(thr, i), &i32) ||
42082 			    i32 < 0 || i32 > 0x10ffffL) {
42083 				DUK_DCERROR_RANGE_INVALID_ARGS(thr);
42084 			}
42085 			DUK_ASSERT(i32 >= 0 && i32 <= 0x10ffffL);
42086 			cp = (duk_ucodepoint_t) i32;
42087 			DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);
42088 		} else {
42089 #if defined(DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT)
42090 			/* ToUint16() coercion is mandatory in the E5.1 specification, but
42091 			 * this non-compliant behavior makes more sense because we support
42092 			 * non-BMP codepoints.  Don't use CESU-8 because that'd create
42093 			 * surrogate pairs.
42094 			 */
42095 			cp = (duk_ucodepoint_t) duk_to_uint32(thr, i);
42096 			DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
42097 #else
42098 			cp = (duk_ucodepoint_t) duk_to_uint16(thr, i);
42099 			DUK_ASSERT(cp >= 0 && cp <= 0x10ffffL);
42100 			DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);
42101 #endif
42102 		}
42103 	}
42104 
42105 	DUK_BW_COMPACT(thr, bw);
42106 	(void) duk_buffer_to_string(thr, -1);  /* Safe, extended UTF-8 or CESU-8 encoded. */
42107 	return 1;
42108 }
42109 
42110 DUK_INTERNAL duk_ret_t duk_bi_string_constructor_from_char_code(duk_hthread *thr) {
42111 	return duk__construct_from_codepoints(thr, 0 /*nonbmp*/);
42112 }
42113 
42114 #if defined(DUK_USE_ES6)
42115 DUK_INTERNAL duk_ret_t duk_bi_string_constructor_from_code_point(duk_hthread *thr) {
42116 	return duk__construct_from_codepoints(thr, 1 /*nonbmp*/);
42117 }
42118 #endif
42119 
42120 /*
42121  *  toString(), valueOf()
42122  */
42123 
42124 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_to_string(duk_hthread *thr) {
42125 	duk_tval *tv;
42126 
42127 	duk_push_this(thr);
42128 	tv = duk_require_tval(thr, -1);
42129 	DUK_ASSERT(tv != NULL);
42130 
42131 	if (DUK_TVAL_IS_STRING(tv)) {
42132 		/* return as is */
42133 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
42134 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
42135 		DUK_ASSERT(h != NULL);
42136 
42137 		/* Must be a "string object", i.e. class "String" */
42138 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_STRING) {
42139 			goto type_error;
42140 		}
42141 
42142 		duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
42143 		DUK_ASSERT(duk_is_string(thr, -1));
42144 	} else {
42145 		goto type_error;
42146 	}
42147 
42148 	(void) duk_require_hstring_notsymbol(thr, -1);  /* Reject symbols (and wrapped symbols). */
42149 	return 1;
42150 
42151  type_error:
42152 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
42153 }
42154 
42155 /*
42156  *  Character and charcode access
42157  */
42158 
42159 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_at(duk_hthread *thr) {
42160 	duk_hstring *h;
42161 	duk_int_t pos;
42162 
42163 	/* XXX: faster implementation */
42164 
42165 	h = duk_push_this_coercible_to_string(thr);
42166 	DUK_ASSERT(h != NULL);
42167 
42168 	pos = duk_to_int(thr, 0);
42169 
42170 	if (sizeof(duk_size_t) >= sizeof(duk_uint_t)) {
42171 		/* Cast to duk_size_t works in this case:
42172 		 * - If pos < 0, (duk_size_t) pos will always be
42173 		 *   >= max_charlen, and result will be the empty string
42174 		 *   (see duk_substring()).
42175 		 * - If pos >= 0, pos + 1 cannot wrap.
42176 		 */
42177 		DUK_ASSERT((duk_size_t) DUK_INT_MIN >= DUK_HSTRING_MAX_BYTELEN);
42178 		DUK_ASSERT((duk_size_t) DUK_INT_MAX + 1U > (duk_size_t) DUK_INT_MAX);
42179 		duk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) pos + 1U);
42180 	} else {
42181 		/* If size_t is smaller than int, explicit bounds checks
42182 		 * are needed because an int may wrap multiple times.
42183 		 */
42184 		if (DUK_UNLIKELY(pos < 0 || (duk_uint_t) pos >= (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h))) {
42185 			duk_push_hstring_empty(thr);
42186 		} else {
42187 			duk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) pos + 1U);
42188 		}
42189 	}
42190 
42191 	return 1;
42192 }
42193 
42194 /* Magic: 0=charCodeAt, 1=codePointAt */
42195 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_code_at(duk_hthread *thr) {
42196 	duk_int_t pos;
42197 	duk_hstring *h;
42198 	duk_bool_t clamped;
42199 	duk_uint32_t cp;
42200 	duk_int_t magic;
42201 
42202 	/* XXX: faster implementation */
42203 
42204 	DUK_DDD(DUK_DDDPRINT("arg=%!T", (duk_tval *) duk_get_tval(thr, 0)));
42205 
42206 	h = duk_push_this_coercible_to_string(thr);
42207 	DUK_ASSERT(h != NULL);
42208 
42209 	pos = duk_to_int_clamped_raw(thr,
42210 	                             0 /*index*/,
42211 	                             0 /*min(incl)*/,
42212 	                             (duk_int_t) DUK_HSTRING_GET_CHARLEN(h) - 1 /*max(incl)*/,
42213 	                             &clamped /*out_clamped*/);
42214 #if defined(DUK_USE_ES6)
42215 	magic = duk_get_current_magic(thr);
42216 #else
42217 	DUK_ASSERT(duk_get_current_magic(thr) == 0);
42218 	magic = 0;
42219 #endif
42220 	if (clamped) {
42221 		/* For out-of-bounds indices .charCodeAt() returns NaN and
42222 		 * .codePointAt() returns undefined.
42223 		 */
42224 		if (magic != 0) {
42225 			return 0;
42226 		}
42227 		duk_push_nan(thr);
42228 	} else {
42229 		DUK_ASSERT(pos >= 0);
42230 		cp = (duk_uint32_t) duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) pos, (duk_bool_t) magic /*surrogate_aware*/);
42231 		duk_push_u32(thr, cp);
42232 	}
42233 	return 1;
42234 }
42235 
42236 /*
42237  *  substring(), substr(), slice()
42238  */
42239 
42240 /* XXX: any chance of merging these three similar but still slightly
42241  * different algorithms so that footprint would be reduced?
42242  */
42243 
42244 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substring(duk_hthread *thr) {
42245 	duk_hstring *h;
42246 	duk_int_t start_pos, end_pos;
42247 	duk_int_t len;
42248 
42249 	h = duk_push_this_coercible_to_string(thr);
42250 	DUK_ASSERT(h != NULL);
42251 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
42252 
42253 	/* [ start end str ] */
42254 
42255 	start_pos = duk_to_int_clamped(thr, 0, 0, len);
42256 	if (duk_is_undefined(thr, 1)) {
42257 		end_pos = len;
42258 	} else {
42259 		end_pos = duk_to_int_clamped(thr, 1, 0, len);
42260 	}
42261 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
42262 	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
42263 
42264 	if (start_pos > end_pos) {
42265 		duk_int_t tmp = start_pos;
42266 		start_pos = end_pos;
42267 		end_pos = tmp;
42268 	}
42269 
42270 	DUK_ASSERT(end_pos >= start_pos);
42271 
42272 	duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
42273 	return 1;
42274 }
42275 
42276 #if defined(DUK_USE_SECTION_B)
42277 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substr(duk_hthread *thr) {
42278 	duk_hstring *h;
42279 	duk_int_t start_pos, end_pos;
42280 	duk_int_t len;
42281 
42282 	/* Unlike non-obsolete String calls, substr() algorithm in E5.1
42283 	 * specification will happily coerce undefined and null to strings
42284 	 * ("undefined" and "null").
42285 	 */
42286 	duk_push_this(thr);
42287 	h = duk_to_hstring_m1(thr);  /* Reject Symbols. */
42288 	DUK_ASSERT(h != NULL);
42289 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
42290 
42291 	/* [ start length str ] */
42292 
42293 	/* The implementation for computing of start_pos and end_pos differs
42294 	 * from the standard algorithm, but is intended to result in the exactly
42295 	 * same behavior.  This is not always obvious.
42296 	 */
42297 
42298 	/* combines steps 2 and 5; -len ensures max() not needed for step 5 */
42299 	start_pos = duk_to_int_clamped(thr, 0, -len, len);
42300 	if (start_pos < 0) {
42301 		start_pos = len + start_pos;
42302 	}
42303 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
42304 
42305 	/* combines steps 3, 6; step 7 is not needed */
42306 	if (duk_is_undefined(thr, 1)) {
42307 		end_pos = len;
42308 	} else {
42309 		DUK_ASSERT(start_pos <= len);
42310 		end_pos = start_pos + duk_to_int_clamped(thr, 1, 0, len - start_pos);
42311 	}
42312 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
42313 	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
42314 	DUK_ASSERT(end_pos >= start_pos);
42315 
42316 	duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
42317 	return 1;
42318 }
42319 #endif  /* DUK_USE_SECTION_B */
42320 
42321 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_slice(duk_hthread *thr) {
42322 	duk_hstring *h;
42323 	duk_int_t start_pos, end_pos;
42324 	duk_int_t len;
42325 
42326 	h = duk_push_this_coercible_to_string(thr);
42327 	DUK_ASSERT(h != NULL);
42328 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
42329 
42330 	/* [ start end str ] */
42331 
42332 	start_pos = duk_to_int_clamped(thr, 0, -len, len);
42333 	if (start_pos < 0) {
42334 		start_pos = len + start_pos;
42335 	}
42336 	if (duk_is_undefined(thr, 1)) {
42337 		end_pos = len;
42338 	} else {
42339 		end_pos = duk_to_int_clamped(thr, 1, -len, len);
42340 		if (end_pos < 0) {
42341 			end_pos = len + end_pos;
42342 		}
42343 	}
42344 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
42345 	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
42346 
42347 	if (end_pos < start_pos) {
42348 		end_pos = start_pos;
42349 	}
42350 
42351 	DUK_ASSERT(end_pos >= start_pos);
42352 
42353 	duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
42354 	return 1;
42355 }
42356 
42357 /*
42358  *  Case conversion
42359  */
42360 
42361 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_hthread *thr) {
42362 	duk_small_int_t uppercase = duk_get_current_magic(thr);
42363 
42364 	(void) duk_push_this_coercible_to_string(thr);
42365 	duk_unicode_case_convert_string(thr, (duk_bool_t) uppercase);
42366 	return 1;
42367 }
42368 
42369 /*
42370  *  indexOf() and lastIndexOf()
42371  */
42372 
42373 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_hthread *thr) {
42374 	duk_hstring *h_this;
42375 	duk_hstring *h_search;
42376 	duk_int_t clen_this;
42377 	duk_int_t cpos;
42378 	duk_small_uint_t is_lastindexof = (duk_small_uint_t) duk_get_current_magic(thr);  /* 0=indexOf, 1=lastIndexOf */
42379 
42380 	h_this = duk_push_this_coercible_to_string(thr);
42381 	DUK_ASSERT(h_this != NULL);
42382 	clen_this = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h_this);
42383 
42384 	h_search = duk_to_hstring(thr, 0);
42385 	DUK_ASSERT(h_search != NULL);
42386 
42387 	duk_to_number(thr, 1);
42388 	if (duk_is_nan(thr, 1) && is_lastindexof) {
42389 		/* indexOf: NaN should cause pos to be zero.
42390 		 * lastIndexOf: NaN should cause pos to be +Infinity
42391 		 * (and later be clamped to len).
42392 		 */
42393 		cpos = clen_this;
42394 	} else {
42395 		cpos = duk_to_int_clamped(thr, 1, 0, clen_this);
42396 	}
42397 
42398 	cpos = duk__str_search_shared(thr, h_this, h_search, cpos, is_lastindexof /*backwards*/);
42399 	duk_push_int(thr, cpos);
42400 	return 1;
42401 }
42402 
42403 /*
42404  *  replace()
42405  */
42406 
42407 /* XXX: the current implementation works but is quite clunky; it compiles
42408  * to almost 1,4kB of x86 code so it needs to be simplified (better approach,
42409  * shared helpers, etc).  Some ideas for refactoring:
42410  *
42411  * - a primitive to convert a string into a regexp matcher (reduces matching
42412  *   code at the cost of making matching much slower)
42413  * - use replace() as a basic helper for match() and split(), which are both
42414  *   much simpler
42415  * - API call to get_prop and to_boolean
42416  */
42417 
42418 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {
42419 	duk_hstring *h_input;
42420 	duk_hstring *h_match;
42421 	duk_hstring *h_search;
42422 	duk_hobject *h_re;
42423 	duk_bufwriter_ctx bw_alloc;
42424 	duk_bufwriter_ctx *bw;
42425 #if defined(DUK_USE_REGEXP_SUPPORT)
42426 	duk_bool_t is_regexp;
42427 	duk_bool_t is_global;
42428 #endif
42429 	duk_bool_t is_repl_func;
42430 	duk_uint32_t match_start_coff, match_start_boff;
42431 #if defined(DUK_USE_REGEXP_SUPPORT)
42432 	duk_int_t match_caps;
42433 #endif
42434 	duk_uint32_t prev_match_end_boff;
42435 	const duk_uint8_t *r_start, *r_end, *r;   /* repl string scan */
42436 	duk_size_t tmp_sz;
42437 
42438 	DUK_ASSERT_TOP(thr, 2);
42439 	h_input = duk_push_this_coercible_to_string(thr);
42440 	DUK_ASSERT(h_input != NULL);
42441 
42442 	bw = &bw_alloc;
42443 	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));  /* input size is good output starting point */
42444 
42445 	DUK_ASSERT_TOP(thr, 4);
42446 
42447 	/* stack[0] = search value
42448 	 * stack[1] = replace value
42449 	 * stack[2] = input string
42450 	 * stack[3] = result buffer
42451 	 */
42452 
42453 	h_re = duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_REGEXP);
42454 	if (h_re) {
42455 #if defined(DUK_USE_REGEXP_SUPPORT)
42456 		is_regexp = 1;
42457 		is_global = duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL);
42458 
42459 		if (is_global) {
42460 			/* start match from beginning */
42461 			duk_push_int(thr, 0);
42462 			duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
42463 		}
42464 #else  /* DUK_USE_REGEXP_SUPPORT */
42465 		DUK_DCERROR_UNSUPPORTED(thr);
42466 #endif  /* DUK_USE_REGEXP_SUPPORT */
42467 	} else {
42468 		duk_to_string(thr, 0);  /* rejects symbols */
42469 #if defined(DUK_USE_REGEXP_SUPPORT)
42470 		is_regexp = 0;
42471 		is_global = 0;
42472 #endif
42473 	}
42474 
42475 	if (duk_is_function(thr, 1)) {
42476 		is_repl_func = 1;
42477 		r_start = NULL;
42478 		r_end = NULL;
42479 	} else {
42480 		duk_hstring *h_repl;
42481 
42482 		is_repl_func = 0;
42483 		h_repl = duk_to_hstring(thr, 1);  /* reject symbols */
42484 		DUK_ASSERT(h_repl != NULL);
42485 		r_start = DUK_HSTRING_GET_DATA(h_repl);
42486 		r_end = r_start + DUK_HSTRING_GET_BYTELEN(h_repl);
42487 	}
42488 
42489 	prev_match_end_boff = 0;
42490 
42491 	for (;;) {
42492 		/*
42493 		 *  If matching with a regexp:
42494 		 *    - non-global RegExp: lastIndex not touched on a match, zeroed
42495 		 *      on a non-match
42496 		 *    - global RegExp: on match, lastIndex will be updated by regexp
42497 		 *      executor to point to next char after the matching part (so that
42498 		 *      characters in the matching part are not matched again)
42499 		 *
42500 		 *  If matching with a string:
42501 		 *    - always non-global match, find first occurrence
42502 		 *
42503 		 *  We need:
42504 		 *    - The character offset of start-of-match for the replacer function
42505 		 *    - The byte offsets for start-of-match and end-of-match to implement
42506 		 *      the replacement values $&, $`, and $', and to copy non-matching
42507 		 *      input string portions (including header and trailer) verbatim.
42508 		 *
42509 		 *  NOTE: the E5.1 specification is a bit vague how the RegExp should
42510 		 *  behave in the replacement process; e.g. is matching done first for
42511 		 *  all matches (in the global RegExp case) before any replacer calls
42512 		 *  are made?  See: test-bi-string-proto-replace.js for discussion.
42513 		 */
42514 
42515 		DUK_ASSERT_TOP(thr, 4);
42516 
42517 #if defined(DUK_USE_REGEXP_SUPPORT)
42518 		if (is_regexp) {
42519 			duk_dup_0(thr);
42520 			duk_dup_2(thr);
42521 			duk_regexp_match(thr);  /* [ ... regexp input ] -> [ res_obj ] */
42522 			if (!duk_is_object(thr, -1)) {
42523 				duk_pop(thr);
42524 				break;
42525 			}
42526 
42527 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);
42528 			DUK_ASSERT(duk_is_number(thr, -1));
42529 			match_start_coff = duk_get_uint(thr, -1);
42530 			duk_pop(thr);
42531 
42532 			duk_get_prop_index(thr, -1, 0);
42533 			DUK_ASSERT(duk_is_string(thr, -1));
42534 			h_match = duk_known_hstring(thr, -1);
42535 			duk_pop(thr);  /* h_match is borrowed, remains reachable through match_obj */
42536 
42537 			if (DUK_HSTRING_GET_BYTELEN(h_match) == 0) {
42538 				/* This should be equivalent to match() algorithm step 8.f.iii.2:
42539 				 * detect an empty match and allow it, but don't allow it twice.
42540 				 */
42541 				duk_uint32_t last_index;
42542 
42543 				duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
42544 				last_index = (duk_uint32_t) duk_get_uint(thr, -1);
42545 				DUK_DDD(DUK_DDDPRINT("empty match, bump lastIndex: %ld -> %ld",
42546 				                     (long) last_index, (long) (last_index + 1)));
42547 				duk_pop(thr);
42548 				duk_push_uint(thr, (duk_uint_t) (last_index + 1));
42549 				duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
42550 			}
42551 
42552 			DUK_ASSERT(duk_get_length(thr, -1) <= DUK_INT_MAX);  /* string limits */
42553 			match_caps = (duk_int_t) duk_get_length(thr, -1);
42554 		} else {
42555 #else  /* DUK_USE_REGEXP_SUPPORT */
42556 		{  /* unconditionally */
42557 #endif  /* DUK_USE_REGEXP_SUPPORT */
42558 			const duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
42559 			const duk_uint8_t *q_start;               /* match string */
42560 			duk_size_t p_blen;
42561 			duk_size_t q_blen;
42562 
42563 #if defined(DUK_USE_REGEXP_SUPPORT)
42564 			DUK_ASSERT(!is_global);  /* single match always */
42565 #endif
42566 
42567 			p_start = DUK_HSTRING_GET_DATA(h_input);
42568 			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
42569 			p_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_input);
42570 			p = p_start;
42571 
42572 			h_search = duk_known_hstring(thr, 0);
42573 			q_start = DUK_HSTRING_GET_DATA(h_search);
42574 			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_search);
42575 
42576 			if (q_blen > p_blen) {
42577 				break;  /* no match */
42578 			}
42579 
42580 			p_end -= q_blen;  /* ensure full memcmp() fits in while */
42581 			DUK_ASSERT(p_end >= p);
42582 
42583 			match_start_coff = 0;
42584 
42585 			while (p <= p_end) {
42586 				DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
42587 				if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
42588 					duk_dup_0(thr);
42589 					h_match = duk_known_hstring(thr, -1);
42590 #if defined(DUK_USE_REGEXP_SUPPORT)
42591 					match_caps = 0;
42592 #endif
42593 					goto found;
42594 				}
42595 
42596 				/* track utf-8 non-continuation bytes */
42597 				if ((p[0] & 0xc0) != 0x80) {
42598 					match_start_coff++;
42599 				}
42600 				p++;
42601 			}
42602 
42603 			/* not found */
42604 			break;
42605 		}
42606 	 found:
42607 
42608 		/* stack[0] = search value
42609 		 * stack[1] = replace value
42610 		 * stack[2] = input string
42611 		 * stack[3] = result buffer
42612 		 * stack[4] = regexp match OR match string
42613 		 */
42614 
42615 		match_start_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
42616 
42617 		tmp_sz = (duk_size_t) (match_start_boff - prev_match_end_boff);
42618 		DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
42619 
42620 		prev_match_end_boff = match_start_boff + DUK_HSTRING_GET_BYTELEN(h_match);
42621 
42622 		if (is_repl_func) {
42623 			duk_idx_t idx_args;
42624 			duk_hstring *h_repl;
42625 
42626 			/* regexp res_obj is at index 4 */
42627 
42628 			duk_dup_1(thr);
42629 			idx_args = duk_get_top(thr);
42630 
42631 #if defined(DUK_USE_REGEXP_SUPPORT)
42632 			if (is_regexp) {
42633 				duk_int_t idx;
42634 				duk_require_stack(thr, match_caps + 2);
42635 				for (idx = 0; idx < match_caps; idx++) {
42636 					/* match followed by capture(s) */
42637 					duk_get_prop_index(thr, 4, (duk_uarridx_t) idx);
42638 				}
42639 			} else {
42640 #else  /* DUK_USE_REGEXP_SUPPORT */
42641 			{  /* unconditionally */
42642 #endif  /* DUK_USE_REGEXP_SUPPORT */
42643 				/* match == search string, by definition */
42644 				duk_dup_0(thr);
42645 			}
42646 			duk_push_uint(thr, (duk_uint_t) match_start_coff);
42647 			duk_dup_2(thr);
42648 
42649 			/* [ ... replacer match [captures] match_char_offset input ] */
42650 
42651 			duk_call(thr, duk_get_top(thr) - idx_args);
42652 			h_repl = duk_to_hstring_m1(thr);  /* -> [ ... repl_value ] */
42653 			DUK_ASSERT(h_repl != NULL);
42654 
42655 			DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_repl);
42656 
42657 			duk_pop(thr);  /* repl_value */
42658 		} else {
42659 			r = r_start;
42660 
42661 			while (r < r_end) {
42662 				duk_int_t ch1;
42663 				duk_int_t ch2;
42664 #if defined(DUK_USE_REGEXP_SUPPORT)
42665 				duk_int_t ch3;
42666 #endif
42667 				duk_size_t left;
42668 
42669 				ch1 = *r++;
42670 				if (ch1 != DUK_ASC_DOLLAR) {
42671 					goto repl_write;
42672 				}
42673 				DUK_ASSERT(r <= r_end);
42674 				left = (duk_size_t) (r_end - r);
42675 
42676 				if (left <= 0) {
42677 					goto repl_write;
42678 				}
42679 
42680 				ch2 = r[0];
42681 				switch (ch2) {
42682 				case DUK_ASC_DOLLAR: {
42683 					ch1 = (1 << 8) + DUK_ASC_DOLLAR;
42684 					goto repl_write;
42685 				}
42686 				case DUK_ASC_AMP: {
42687 					DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_match);
42688 					r++;
42689 					continue;
42690 				}
42691 				case DUK_ASC_GRAVE: {
42692 					tmp_sz = (duk_size_t) match_start_boff;
42693 					DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input), tmp_sz);
42694 					r++;
42695 					continue;
42696 				}
42697 				case DUK_ASC_SINGLEQUOTE: {
42698 					duk_uint32_t match_end_boff;
42699 
42700 					/* Use match charlen instead of bytelen, just in case the input and
42701 					 * match codepoint encodings would have different lengths.
42702 					 */
42703 					/* XXX: charlen computed here, and also in char2byte helper. */
42704 					match_end_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr,
42705 					                                                                   h_input,
42706 					                                                                   match_start_coff + (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_match));
42707 
42708 					tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - match_end_boff);
42709 					DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + match_end_boff, tmp_sz);
42710 					r++;
42711 					continue;
42712 				}
42713 				default: {
42714 #if defined(DUK_USE_REGEXP_SUPPORT)
42715 					duk_int_t capnum, captmp, capadv;
42716 					/* XXX: optional check, match_caps is zero if no regexp,
42717 					 * so dollar will be interpreted literally anyway.
42718 					 */
42719 
42720 					if (!is_regexp) {
42721 						goto repl_write;
42722 					}
42723 
42724 					if (!(ch2 >= DUK_ASC_0 && ch2 <= DUK_ASC_9)) {
42725 						goto repl_write;
42726 					}
42727 					capnum = ch2 - DUK_ASC_0;
42728 					capadv = 1;
42729 
42730 					if (left >= 2) {
42731 						ch3 = r[1];
42732 						if (ch3 >= DUK_ASC_0 && ch3 <= DUK_ASC_9) {
42733 							captmp = capnum * 10 + (ch3 - DUK_ASC_0);
42734 							if (captmp < match_caps) {
42735 								capnum = captmp;
42736 								capadv = 2;
42737 							}
42738 						}
42739 					}
42740 
42741 					if (capnum > 0 && capnum < match_caps) {
42742 						DUK_ASSERT(is_regexp != 0);  /* match_caps == 0 without regexps */
42743 
42744 						/* regexp res_obj is at offset 4 */
42745 						duk_get_prop_index(thr, 4, (duk_uarridx_t) capnum);
42746 						if (duk_is_string(thr, -1)) {
42747 							duk_hstring *h_tmp_str;
42748 
42749 							h_tmp_str = duk_known_hstring(thr, -1);
42750 
42751 							DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_tmp_str);
42752 						} else {
42753 							/* undefined -> skip (replaced with empty) */
42754 						}
42755 						duk_pop(thr);
42756 						r += capadv;
42757 						continue;
42758 					} else {
42759 						goto repl_write;
42760 					}
42761 #else  /* DUK_USE_REGEXP_SUPPORT */
42762 					goto repl_write;  /* unconditionally */
42763 #endif  /* DUK_USE_REGEXP_SUPPORT */
42764 				}  /* default case */
42765 				}  /* switch (ch2) */
42766 
42767 			 repl_write:
42768 				/* ch1 = (r_increment << 8) + byte */
42769 
42770 				DUK_BW_WRITE_ENSURE_U8(thr, bw, (duk_uint8_t) (ch1 & 0xff));
42771 				r += ch1 >> 8;
42772 			}  /* while repl */
42773 		}  /* if (is_repl_func) */
42774 
42775 		duk_pop(thr);  /* pop regexp res_obj or match string */
42776 
42777 #if defined(DUK_USE_REGEXP_SUPPORT)
42778 		if (!is_global) {
42779 #else
42780 		{  /* unconditionally; is_global==0 */
42781 #endif
42782 			break;
42783 		}
42784 	}
42785 
42786 	/* trailer */
42787 	tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff);
42788 	DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
42789 
42790 	DUK_ASSERT_TOP(thr, 4);
42791 	DUK_BW_COMPACT(thr, bw);
42792 	(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */
42793 	return 1;
42794 }
42795 
42796 /*
42797  *  split()
42798  */
42799 
42800 /* XXX: very messy now, but works; clean up, remove unused variables (nomimally
42801  * used so compiler doesn't complain).
42802  */
42803 
42804 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_hthread *thr) {
42805 	duk_hstring *h_input;
42806 	duk_hstring *h_sep;
42807 	duk_uint32_t limit;
42808 	duk_uint32_t arr_idx;
42809 #if defined(DUK_USE_REGEXP_SUPPORT)
42810 	duk_bool_t is_regexp;
42811 #endif
42812 	duk_bool_t matched;  /* set to 1 if any match exists (needed for empty input special case) */
42813 	duk_uint32_t prev_match_end_coff, prev_match_end_boff;
42814 	duk_uint32_t match_start_boff, match_start_coff;
42815 	duk_uint32_t match_end_boff, match_end_coff;
42816 
42817 	h_input = duk_push_this_coercible_to_string(thr);
42818 	DUK_ASSERT(h_input != NULL);
42819 
42820 	duk_push_array(thr);
42821 
42822 	if (duk_is_undefined(thr, 1)) {
42823 		limit = 0xffffffffUL;
42824 	} else {
42825 		limit = duk_to_uint32(thr, 1);
42826 	}
42827 
42828 	if (limit == 0) {
42829 		return 1;
42830 	}
42831 
42832 	/* If the separator is a RegExp, make a "clone" of it.  The specification
42833 	 * algorithm calls [[Match]] directly for specific indices; we emulate this
42834 	 * by tweaking lastIndex and using a "force global" variant of duk_regexp_match()
42835 	 * which will use global-style matching even when the RegExp itself is non-global.
42836 	 */
42837 
42838 	if (duk_is_undefined(thr, 0)) {
42839 		/* The spec algorithm first does "R = ToString(separator)" before checking
42840 		 * whether separator is undefined.  Since this is side effect free, we can
42841 		 * skip the ToString() here.
42842 		 */
42843 		duk_dup_2(thr);
42844 		duk_put_prop_index(thr, 3, 0);
42845 		return 1;
42846 	} else if (duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_REGEXP) != NULL) {
42847 #if defined(DUK_USE_REGEXP_SUPPORT)
42848 		duk_push_hobject_bidx(thr, DUK_BIDX_REGEXP_CONSTRUCTOR);
42849 		duk_dup_0(thr);
42850 		duk_new(thr, 1);  /* [ ... RegExp val ] -> [ ... res ] */
42851 		duk_replace(thr, 0);
42852 		/* lastIndex is initialized to zero by new RegExp() */
42853 		is_regexp = 1;
42854 #else
42855 		DUK_DCERROR_UNSUPPORTED(thr);
42856 #endif
42857 	} else {
42858 		duk_to_string(thr, 0);
42859 #if defined(DUK_USE_REGEXP_SUPPORT)
42860 		is_regexp = 0;
42861 #endif
42862 	}
42863 
42864 	/* stack[0] = separator (string or regexp)
42865 	 * stack[1] = limit
42866 	 * stack[2] = input string
42867 	 * stack[3] = result array
42868 	 */
42869 
42870 	prev_match_end_boff = 0;
42871 	prev_match_end_coff = 0;
42872 	arr_idx = 0;
42873 	matched = 0;
42874 
42875 	for (;;) {
42876 		/*
42877 		 *  The specification uses RegExp [[Match]] to attempt match at specific
42878 		 *  offsets.  We don't have such a primitive, so we use an actual RegExp
42879 		 *  and tweak lastIndex.  Since the RegExp may be non-global, we use a
42880 		 *  special variant which forces global-like behavior for matching.
42881 		 */
42882 
42883 		DUK_ASSERT_TOP(thr, 4);
42884 
42885 #if defined(DUK_USE_REGEXP_SUPPORT)
42886 		if (is_regexp) {
42887 			duk_dup_0(thr);
42888 			duk_dup_2(thr);
42889 			duk_regexp_match_force_global(thr);  /* [ ... regexp input ] -> [ res_obj ] */
42890 			if (!duk_is_object(thr, -1)) {
42891 				duk_pop(thr);
42892 				break;
42893 			}
42894 			matched = 1;
42895 
42896 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);
42897 			DUK_ASSERT(duk_is_number(thr, -1));
42898 			match_start_coff = duk_get_uint(thr, -1);
42899 			match_start_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
42900 			duk_pop(thr);
42901 
42902 			if (match_start_coff == DUK_HSTRING_GET_CHARLEN(h_input)) {
42903 				/* don't allow an empty match at the end of the string */
42904 				duk_pop(thr);
42905 				break;
42906 			}
42907 
42908 			duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
42909 			DUK_ASSERT(duk_is_number(thr, -1));
42910 			match_end_coff = duk_get_uint(thr, -1);
42911 			match_end_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_end_coff);
42912 			duk_pop(thr);
42913 
42914 			/* empty match -> bump and continue */
42915 			if (prev_match_end_boff == match_end_boff) {
42916 				duk_push_uint(thr, (duk_uint_t) (match_end_coff + 1));
42917 				duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
42918 				duk_pop(thr);
42919 				continue;
42920 			}
42921 		} else {
42922 #else  /* DUK_USE_REGEXP_SUPPORT */
42923 		{  /* unconditionally */
42924 #endif  /* DUK_USE_REGEXP_SUPPORT */
42925 			const duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
42926 			const duk_uint8_t *q_start;               /* match string */
42927 			duk_size_t q_blen, q_clen;
42928 
42929 			p_start = DUK_HSTRING_GET_DATA(h_input);
42930 			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
42931 			p = p_start + prev_match_end_boff;
42932 
42933 			h_sep = duk_known_hstring(thr, 0);  /* symbol already rejected above */
42934 			q_start = DUK_HSTRING_GET_DATA(h_sep);
42935 			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sep);
42936 			q_clen = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_sep);
42937 
42938 			p_end -= q_blen;  /* ensure full memcmp() fits in while */
42939 
42940 			match_start_coff = prev_match_end_coff;
42941 
42942 			if (q_blen == 0) {
42943 				/* Handle empty separator case: it will always match, and always
42944 				 * triggers the check in step 13.c.iii initially.  Note that we
42945 				 * must skip to either end of string or start of first codepoint,
42946 				 * skipping over any continuation bytes!
42947 				 *
42948 				 * Don't allow an empty string to match at the end of the input.
42949 				 */
42950 
42951 				matched = 1;  /* empty separator can always match */
42952 
42953 				match_start_coff++;
42954 				p++;
42955 				while (p < p_end) {
42956 					if ((p[0] & 0xc0) != 0x80) {
42957 						goto found;
42958 					}
42959 					p++;
42960 				}
42961 				goto not_found;
42962 			}
42963 
42964 			DUK_ASSERT(q_blen > 0 && q_clen > 0);
42965 			while (p <= p_end) {
42966 				DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
42967 				DUK_ASSERT(q_blen > 0);  /* no issues with empty memcmp() */
42968 				if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
42969 					/* never an empty match, so step 13.c.iii can't be triggered */
42970 					goto found;
42971 				}
42972 
42973 				/* track utf-8 non-continuation bytes */
42974 				if ((p[0] & 0xc0) != 0x80) {
42975 					match_start_coff++;
42976 				}
42977 				p++;
42978 			}
42979 
42980 		 not_found:
42981 			/* not found */
42982 			break;
42983 
42984 		 found:
42985 			matched = 1;
42986 			match_start_boff = (duk_uint32_t) (p - p_start);
42987 			match_end_coff = (duk_uint32_t) (match_start_coff + q_clen);  /* constrained by string length */
42988 			match_end_boff = (duk_uint32_t) (match_start_boff + q_blen);  /* ditto */
42989 
42990 			/* empty match (may happen with empty separator) -> bump and continue */
42991 			if (prev_match_end_boff == match_end_boff) {
42992 				prev_match_end_boff++;
42993 				prev_match_end_coff++;
42994 				continue;
42995 			}
42996 		}  /* if (is_regexp) */
42997 
42998 		/* stack[0] = separator (string or regexp)
42999 		 * stack[1] = limit
43000 		 * stack[2] = input string
43001 		 * stack[3] = result array
43002 		 * stack[4] = regexp res_obj (if is_regexp)
43003 		 */
43004 
43005 		DUK_DDD(DUK_DDDPRINT("split; match_start b=%ld,c=%ld, match_end b=%ld,c=%ld, prev_end b=%ld,c=%ld",
43006 		                     (long) match_start_boff, (long) match_start_coff,
43007 		                     (long) match_end_boff, (long) match_end_coff,
43008 		                     (long) prev_match_end_boff, (long) prev_match_end_coff));
43009 
43010 		duk_push_lstring(thr,
43011 		                 (const char *) (DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff),
43012 		                 (duk_size_t) (match_start_boff - prev_match_end_boff));
43013 		duk_put_prop_index(thr, 3, arr_idx);
43014 		arr_idx++;
43015 		if (arr_idx >= limit) {
43016 			goto hit_limit;
43017 		}
43018 
43019 #if defined(DUK_USE_REGEXP_SUPPORT)
43020 		if (is_regexp) {
43021 			duk_size_t i, len;
43022 
43023 			len = duk_get_length(thr, 4);
43024 			for (i = 1; i < len; i++) {
43025 				DUK_ASSERT(i <= DUK_UARRIDX_MAX);  /* cannot have >4G captures */
43026 				duk_get_prop_index(thr, 4, (duk_uarridx_t) i);
43027 				duk_put_prop_index(thr, 3, arr_idx);
43028 				arr_idx++;
43029 				if (arr_idx >= limit) {
43030 					goto hit_limit;
43031 				}
43032 			}
43033 
43034 			duk_pop(thr);
43035 			/* lastIndex already set up for next match */
43036 		} else {
43037 #else  /* DUK_USE_REGEXP_SUPPORT */
43038 		{  /* unconditionally */
43039 #endif  /* DUK_USE_REGEXP_SUPPORT */
43040 			/* no action */
43041 		}
43042 
43043 		prev_match_end_boff = match_end_boff;
43044 		prev_match_end_coff = match_end_coff;
43045 		continue;
43046 	}  /* for */
43047 
43048 	/* Combined step 11 (empty string special case) and 14-15. */
43049 
43050 	DUK_DDD(DUK_DDDPRINT("split trailer; prev_end b=%ld,c=%ld",
43051 	                     (long) prev_match_end_boff, (long) prev_match_end_coff));
43052 
43053 	if (DUK_HSTRING_GET_BYTELEN(h_input) > 0 || !matched) {
43054 		/* Add trailer if:
43055 		 *   a) non-empty input
43056 		 *   b) empty input and no (zero size) match found (step 11)
43057 		 */
43058 
43059 		duk_push_lstring(thr,
43060 		                 (const char *) DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff,
43061 		                 (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff));
43062 		duk_put_prop_index(thr, 3, arr_idx);
43063 		/* No arr_idx update or limit check */
43064 	}
43065 
43066 	return 1;
43067 
43068  hit_limit:
43069 #if defined(DUK_USE_REGEXP_SUPPORT)
43070 	if (is_regexp) {
43071 		duk_pop(thr);
43072 	}
43073 #endif
43074 
43075 	return 1;
43076 }
43077 
43078 /*
43079  *  Various
43080  */
43081 
43082 #if defined(DUK_USE_REGEXP_SUPPORT)
43083 DUK_LOCAL void duk__to_regexp_helper(duk_hthread *thr, duk_idx_t idx, duk_bool_t force_new) {
43084 	duk_hobject *h;
43085 
43086 	/* Shared helper for match() steps 3-4, search() steps 3-4. */
43087 
43088 	DUK_ASSERT(idx >= 0);
43089 
43090 	if (force_new) {
43091 		goto do_new;
43092 	}
43093 
43094 	h = duk_get_hobject_with_class(thr, idx, DUK_HOBJECT_CLASS_REGEXP);
43095 	if (!h) {
43096 		goto do_new;
43097 	}
43098 	return;
43099 
43100  do_new:
43101 	duk_push_hobject_bidx(thr, DUK_BIDX_REGEXP_CONSTRUCTOR);
43102 	duk_dup(thr, idx);
43103 	duk_new(thr, 1);  /* [ ... RegExp val ] -> [ ... res ] */
43104 	duk_replace(thr, idx);
43105 }
43106 #endif  /* DUK_USE_REGEXP_SUPPORT */
43107 
43108 #if defined(DUK_USE_REGEXP_SUPPORT)
43109 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_search(duk_hthread *thr) {
43110 	/* Easiest way to implement the search required by the specification
43111 	 * is to do a RegExp test() with lastIndex forced to zero.  To avoid
43112 	 * side effects on the argument, "clone" the RegExp if a RegExp was
43113 	 * given as input.
43114 	 *
43115 	 * The global flag of the RegExp should be ignored; setting lastIndex
43116 	 * to zero (which happens when "cloning" the RegExp) should have an
43117 	 * equivalent effect.
43118 	 */
43119 
43120 	DUK_ASSERT_TOP(thr, 1);
43121 	(void) duk_push_this_coercible_to_string(thr);  /* at index 1 */
43122 	duk__to_regexp_helper(thr, 0 /*index*/, 1 /*force_new*/);
43123 
43124 	/* stack[0] = regexp
43125 	 * stack[1] = string
43126 	 */
43127 
43128 	/* Avoid using RegExp.prototype methods, as they're writable and
43129 	 * configurable and may have been changed.
43130 	 */
43131 
43132 	duk_dup_0(thr);
43133 	duk_dup_1(thr);  /* [ ... re_obj input ] */
43134 	duk_regexp_match(thr);  /* -> [ ... res_obj ] */
43135 
43136 	if (!duk_is_object(thr, -1)) {
43137 		duk_push_int(thr, -1);
43138 		return 1;
43139 	}
43140 
43141 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);
43142 	DUK_ASSERT(duk_is_number(thr, -1));
43143 	return 1;
43144 }
43145 #endif  /* DUK_USE_REGEXP_SUPPORT */
43146 
43147 #if defined(DUK_USE_REGEXP_SUPPORT)
43148 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_match(duk_hthread *thr) {
43149 	duk_bool_t global;
43150 	duk_int_t prev_last_index;
43151 	duk_int_t this_index;
43152 	duk_int_t arr_idx;
43153 
43154 	DUK_ASSERT_TOP(thr, 1);
43155 	(void) duk_push_this_coercible_to_string(thr);
43156 	duk__to_regexp_helper(thr, 0 /*index*/, 0 /*force_new*/);
43157 	global = duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL);
43158 	DUK_ASSERT_TOP(thr, 2);
43159 
43160 	/* stack[0] = regexp
43161 	 * stack[1] = string
43162 	 */
43163 
43164 	if (!global) {
43165 		duk_regexp_match(thr);  /* -> [ res_obj ] */
43166 		return 1;  /* return 'res_obj' */
43167 	}
43168 
43169 	/* Global case is more complex. */
43170 
43171 	/* [ regexp string ] */
43172 
43173 	duk_push_int(thr, 0);
43174 	duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
43175 	duk_push_array(thr);
43176 
43177 	/* [ regexp string res_arr ] */
43178 
43179 	prev_last_index = 0;
43180 	arr_idx = 0;
43181 
43182 	for (;;) {
43183 		DUK_ASSERT_TOP(thr, 3);
43184 
43185 		duk_dup_0(thr);
43186 		duk_dup_1(thr);
43187 		duk_regexp_match(thr);  /* -> [ ... regexp string ] -> [ ... res_obj ] */
43188 
43189 		if (!duk_is_object(thr, -1)) {
43190 			duk_pop(thr);
43191 			break;
43192 		}
43193 
43194 		duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
43195 		DUK_ASSERT(duk_is_number(thr, -1));
43196 		this_index = duk_get_int(thr, -1);
43197 		duk_pop(thr);
43198 
43199 		if (this_index == prev_last_index) {
43200 			this_index++;
43201 			duk_push_int(thr, this_index);
43202 			duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
43203 		}
43204 		prev_last_index = this_index;
43205 
43206 		duk_get_prop_index(thr, -1, 0);  /* match string */
43207 		duk_put_prop_index(thr, 2, (duk_uarridx_t) arr_idx);
43208 		arr_idx++;
43209 		duk_pop(thr);  /* res_obj */
43210 	}
43211 
43212 	if (arr_idx == 0) {
43213 		duk_push_null(thr);
43214 	}
43215 
43216 	return 1;  /* return 'res_arr' or 'null' */
43217 }
43218 #endif  /* DUK_USE_REGEXP_SUPPORT */
43219 
43220 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_concat(duk_hthread *thr) {
43221 	/* duk_concat() coerces arguments with ToString() in correct order */
43222 	(void) duk_push_this_coercible_to_string(thr);
43223 	duk_insert(thr, 0);  /* this is relatively expensive */
43224 	duk_concat(thr, duk_get_top(thr));
43225 	return 1;
43226 }
43227 
43228 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_trim(duk_hthread *thr) {
43229 	DUK_ASSERT_TOP(thr, 0);
43230 	(void) duk_push_this_coercible_to_string(thr);
43231 	duk_trim(thr, 0);
43232 	DUK_ASSERT_TOP(thr, 1);
43233 	return 1;
43234 }
43235 
43236 #if defined(DUK_USE_ES6)
43237 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_repeat(duk_hthread *thr) {
43238 	duk_hstring *h_input;
43239 	duk_size_t input_blen;
43240 	duk_size_t result_len;
43241 	duk_int_t count_signed;
43242 	duk_uint_t count;
43243 	const duk_uint8_t *src;
43244 	duk_uint8_t *buf;
43245 	duk_uint8_t *p;
43246 	duk_double_t d;
43247 #if !defined(DUK_USE_PREFER_SIZE)
43248 	duk_size_t copy_size;
43249 	duk_uint8_t *p_end;
43250 #endif
43251 
43252 	DUK_ASSERT_TOP(thr, 1);
43253 	h_input = duk_push_this_coercible_to_string(thr);
43254 	DUK_ASSERT(h_input != NULL);
43255 	input_blen = DUK_HSTRING_GET_BYTELEN(h_input);
43256 
43257 	/* Count is ToNumber() coerced; +Infinity must be always rejected
43258 	 * (even if input string is zero length), as well as negative values
43259 	 * and -Infinity.  -Infinity doesn't require an explicit check
43260 	 * because duk_get_int() clamps it to DUK_INT_MIN which gets rejected
43261 	 * as a negative value (regardless of input string length).
43262 	 */
43263 	d = duk_to_number(thr, 0);
43264 	if (duk_double_is_posinf(d)) {
43265 		goto fail_range;
43266 	}
43267 	count_signed = duk_get_int(thr, 0);
43268 	if (count_signed < 0) {
43269 		goto fail_range;
43270 	}
43271 	count = (duk_uint_t) count_signed;
43272 
43273 	/* Overflow check for result length. */
43274 	result_len = count * input_blen;
43275 	if (count != 0 && result_len / count != input_blen) {
43276 		goto fail_range;
43277 	}
43278 
43279 	/* Temporary fixed buffer, later converted to string. */
43280 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, result_len);
43281 	DUK_ASSERT(buf != NULL);
43282 	src = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
43283 	DUK_ASSERT(src != NULL);
43284 
43285 #if defined(DUK_USE_PREFER_SIZE)
43286 	p = buf;
43287 	while (count-- > 0) {
43288 		duk_memcpy((void *) p, (const void *) src, input_blen);  /* copy size may be zero, but pointers are valid */
43289 		p += input_blen;
43290 	}
43291 #else  /* DUK_USE_PREFER_SIZE */
43292 	/* Take advantage of already copied pieces to speed up the process
43293 	 * especially for small repeated strings.
43294 	 */
43295 	p = buf;
43296 	p_end = p + result_len;
43297 	copy_size = input_blen;
43298 	for (;;) {
43299 		duk_size_t remain = (duk_size_t) (p_end - p);
43300 		DUK_DDD(DUK_DDDPRINT("remain=%ld, copy_size=%ld, input_blen=%ld, result_len=%ld",
43301 		                     (long) remain, (long) copy_size, (long) input_blen,
43302 		                     (long) result_len));
43303 		if (remain <= copy_size) {
43304 			/* If result_len is zero, this case is taken and does
43305 			 * a zero size copy (with valid pointers).
43306 			 */
43307 			duk_memcpy((void *) p, (const void *) src, remain);
43308 			break;
43309 		} else {
43310 			duk_memcpy((void *) p, (const void *) src, copy_size);
43311 			p += copy_size;
43312 		}
43313 
43314 		src = (const duk_uint8_t *) buf;  /* Use buf as source for larger copies. */
43315 		copy_size = (duk_size_t) (p - buf);
43316 	}
43317 #endif  /* DUK_USE_PREFER_SIZE */
43318 
43319 	/* XXX: It would be useful to be able to create a duk_hstring with
43320 	 * a certain byte size whose data area wasn't initialized and which
43321 	 * wasn't in the string table yet.  This would allow a string to be
43322 	 * constructed directly without a buffer temporary and when it was
43323 	 * finished, it could be injected into the string table.  Currently
43324 	 * this isn't possible because duk_hstrings are only tracked by the
43325 	 * intern table (they are not in heap_allocated).
43326 	 */
43327 
43328 	duk_buffer_to_string(thr, -1);  /* Safe if input is safe. */
43329 	return 1;
43330 
43331  fail_range:
43332 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
43333 }
43334 #endif  /* DUK_USE_ES6 */
43335 
43336 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_locale_compare(duk_hthread *thr) {
43337 	duk_hstring *h1;
43338 	duk_hstring *h2;
43339 	duk_size_t h1_len, h2_len, prefix_len;
43340 	duk_small_int_t ret = 0;
43341 	duk_small_int_t rc;
43342 
43343 	/* The current implementation of localeCompare() is simply a codepoint
43344 	 * by codepoint comparison, implemented with a simple string compare
43345 	 * because UTF-8 should preserve codepoint ordering (assuming valid
43346 	 * shortest UTF-8 encoding).
43347 	 *
43348 	 * The specification requires that the return value must be related
43349 	 * to the sort order: e.g. negative means that 'this' comes before
43350 	 * 'that' in sort order.  We assume an ascending sort order.
43351 	 */
43352 
43353 	/* XXX: could share code with duk_js_ops.c, duk_js_compare_helper */
43354 
43355 	h1 = duk_push_this_coercible_to_string(thr);
43356 	DUK_ASSERT(h1 != NULL);
43357 
43358 	h2 = duk_to_hstring(thr, 0);
43359 	DUK_ASSERT(h2 != NULL);
43360 
43361 	h1_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
43362 	h2_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
43363 	prefix_len = (h1_len <= h2_len ? h1_len : h2_len);
43364 
43365 	rc = (duk_small_int_t) duk_memcmp((const void *) DUK_HSTRING_GET_DATA(h1),
43366 	                                  (const void *) DUK_HSTRING_GET_DATA(h2),
43367 	                                  (size_t) prefix_len);
43368 
43369 	if (rc < 0) {
43370 		ret = -1;
43371 		goto done;
43372 	} else if (rc > 0) {
43373 		ret = 1;
43374 		goto done;
43375 	}
43376 
43377 	/* prefix matches, lengths matter now */
43378 	if (h1_len > h2_len) {
43379 		ret = 1;
43380 		goto done;
43381 	} else if (h1_len == h2_len) {
43382 		DUK_ASSERT(ret == 0);
43383 		goto done;
43384 	}
43385 	ret = -1;
43386 	goto done;
43387 
43388  done:
43389 	duk_push_int(thr, (duk_int_t) ret);
43390 	return 1;
43391 }
43392 
43393 #if defined(DUK_USE_ES6)
43394 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_hthread *thr) {
43395 	duk_int_t magic;
43396 	duk_hstring *h_target;
43397 	duk_size_t blen_target;
43398 	duk_hstring *h_search;
43399 	duk_size_t blen_search;
43400 	duk_int_t off;
43401 	duk_bool_t result = 0;
43402 	duk_size_t blen_left;
43403 
43404 	/* Because string byte lengths are in [0,DUK_INT_MAX] it's safe to
43405 	 * subtract two string lengths without overflow.
43406 	 */
43407 	DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= DUK_INT_MAX);
43408 
43409 	h_target = duk_push_this_coercible_to_string(thr);
43410 	DUK_ASSERT(h_target != NULL);
43411 
43412 	h_search = duk__str_tostring_notregexp(thr, 0);
43413 	DUK_ASSERT(h_search != NULL);
43414 
43415 	magic = duk_get_current_magic(thr);
43416 
43417 	/* Careful to avoid pointer overflows in the matching logic. */
43418 
43419 	blen_target = DUK_HSTRING_GET_BYTELEN(h_target);
43420 	blen_search = DUK_HSTRING_GET_BYTELEN(h_search);
43421 
43422 #if 0
43423 	/* If search string is longer than the target string, we can
43424 	 * never match.  Could check explicitly, but should be handled
43425 	 * correctly below.
43426 	 */
43427 	if (blen_search > blen_target) {
43428 		goto finish;
43429 	}
43430 #endif
43431 
43432 	off = 0;
43433 	if (duk_is_undefined(thr, 1)) {
43434 		if (magic) {
43435 			off = (duk_int_t) blen_target - (duk_int_t) blen_search;
43436 		} else {
43437 			DUK_ASSERT(off == 0);
43438 		}
43439 	} else {
43440 		duk_int_t len;
43441 		duk_int_t pos;
43442 
43443 		DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= DUK_INT_MAX);
43444 		len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h_target);
43445 		pos = duk_to_int_clamped(thr, 1, 0, len);
43446 		DUK_ASSERT(pos >= 0 && pos <= len);
43447 
43448 		off = (duk_int_t) duk_heap_strcache_offset_char2byte(thr, h_target, (duk_uint_fast32_t) pos);
43449 		if (magic) {
43450 			off -= (duk_int_t) blen_search;
43451 		}
43452 	}
43453 	if (off < 0 || off > (duk_int_t) blen_target) {
43454 		goto finish;
43455 	}
43456 
43457 	/* The main comparison can be done using a memcmp() rather than
43458 	 * doing codepoint comparisons: for CESU-8 strings there is a
43459 	 * canonical representation for every codepoint.  But we do need
43460 	 * to deal with the char/byte offset translation to find the
43461 	 * comparison range.
43462 	 */
43463 
43464 	DUK_ASSERT(off >= 0);
43465 	DUK_ASSERT((duk_size_t) off <= blen_target);
43466 	blen_left = blen_target - (duk_size_t) off;
43467 	if (blen_left >= blen_search) {
43468 		const duk_uint8_t *p_cmp_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_target) + off;
43469 		const duk_uint8_t *p_search = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_search);
43470 		if (duk_memcmp_unsafe((const void *) p_cmp_start, (const void *) p_search, (size_t) blen_search) == 0) {
43471 			result = 1;
43472 		}
43473 	}
43474 
43475  finish:
43476 	duk_push_boolean(thr, result);
43477 	return 1;
43478 }
43479 #endif  /* DUK_USE_ES6 */
43480 
43481 #if defined(DUK_USE_ES6)
43482 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_includes(duk_hthread *thr) {
43483 	duk_hstring *h;
43484 	duk_hstring *h_search;
43485 	duk_int_t len;
43486 	duk_int_t pos;
43487 
43488 	h = duk_push_this_coercible_to_string(thr);
43489 	DUK_ASSERT(h != NULL);
43490 
43491 	h_search = duk__str_tostring_notregexp(thr, 0);
43492 	DUK_ASSERT(h_search != NULL);
43493 
43494 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
43495 	pos = duk_to_int_clamped(thr, 1, 0, len);
43496 	DUK_ASSERT(pos >= 0 && pos <= len);
43497 
43498 	pos = duk__str_search_shared(thr, h, h_search, pos, 0 /*backwards*/);
43499 	duk_push_boolean(thr, pos >= 0);
43500 	return 1;
43501 }
43502 #endif  /* DUK_USE_ES6 */
43503 #endif  /* DUK_USE_STRING_BUILTIN */
43504 #line 1 "duk_bi_symbol.c"
43505 /*
43506  *  Symbol built-in
43507  */
43508 
43509 /* #include duk_internal.h -> already included */
43510 
43511 #if defined(DUK_USE_SYMBOL_BUILTIN)
43512 
43513 /*
43514  *  Constructor
43515  */
43516 
43517 DUK_INTERNAL duk_ret_t duk_bi_symbol_constructor_shared(duk_hthread *thr) {
43518 	const duk_uint8_t *desc;
43519 	duk_size_t len;
43520 	duk_uint8_t *buf;
43521 	duk_uint8_t *p;
43522 	duk_int_t magic;
43523 
43524 	magic = duk_get_current_magic(thr);
43525 	if (duk_is_undefined(thr, 0) && (magic == 0)) {
43526 		/* Symbol() accepts undefined and empty string, but they are
43527 		 * treated differently.
43528 		 */
43529 		desc = NULL;
43530 		len = 0;
43531 	} else {
43532 		/* Symbol.for() coerces undefined to 'undefined' */
43533 		desc = (const duk_uint8_t *) duk_to_lstring(thr, 0, &len);
43534 	}
43535 
43536 	/* Maximum symbol data length:
43537 	 *   +1    initial byte (0x80 or 0x81)
43538 	 *   +len  description
43539 	 *   +1    0xff after description, before unique suffix
43540 	 *   +17   autogenerated unique suffix: 'ffffffff-ffffffff' is longest
43541 	 *   +1    0xff after unique suffix for symbols with undefined description
43542 	 */
43543 	buf = (duk_uint8_t *) duk_push_fixed_buffer(thr, 1 + len + 1 + 17 + 1);
43544 	DUK_ASSERT(buf != NULL);
43545 	p = buf + 1;
43546 	DUK_ASSERT(desc != NULL || len == 0);  /* may be NULL if len is 0 */
43547 	duk_memcpy_unsafe((void *) p, (const void *) desc, len);
43548 	p += len;
43549 	if (magic == 0) {
43550 		/* Symbol(): create unique symbol.  Use two 32-bit values
43551 		 * to avoid dependency on 64-bit types and 64-bit integer
43552 		 * formatting (at least for now).
43553 		 */
43554 		if (++thr->heap->sym_counter[0] == 0) {
43555 			thr->heap->sym_counter[1]++;
43556 		}
43557 		p += DUK_SPRINTF((char *) p, "\xFF" "%lx-%lx",
43558 		                 (unsigned long) thr->heap->sym_counter[1],
43559 		                 (unsigned long) thr->heap->sym_counter[0]);
43560 		if (desc == NULL) {
43561 			/* Special case for 'undefined' description, trailing
43562 			 * 0xff distinguishes from empty string description,
43563 			 * but needs minimal special case handling elsewhere.
43564 			 */
43565 			*p++ = 0xff;
43566 		}
43567 		buf[0] = 0x81;
43568 	} else {
43569 		/* Symbol.for(): create a global symbol */
43570 		buf[0] = 0x80;
43571 	}
43572 
43573 	duk_push_lstring(thr, (const char *) buf, (duk_size_t) (p - buf));
43574 	DUK_DDD(DUK_DDDPRINT("created symbol: %!T", duk_get_tval(thr, -1)));
43575 	return 1;
43576 }
43577 
43578 DUK_LOCAL duk_hstring *duk__auto_unbox_symbol(duk_hthread *thr, duk_tval *tv_arg) {
43579 	duk_tval *tv;
43580 	duk_hobject *h_obj;
43581 	duk_hstring *h_str;
43582 
43583 	DUK_ASSERT(tv_arg != NULL);
43584 
43585 	/* XXX: add internal helper: duk_auto_unbox_tval(thr, tv, mask); */
43586 	/* XXX: add internal helper: duk_auto_unbox(thr, tv, idx); */
43587 
43588 	tv = tv_arg;
43589 	if (DUK_TVAL_IS_OBJECT(tv)) {
43590 		h_obj = DUK_TVAL_GET_OBJECT(tv);
43591 		DUK_ASSERT(h_obj != NULL);
43592 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_SYMBOL) {
43593 			tv = duk_hobject_get_internal_value_tval_ptr(thr->heap, h_obj);
43594 			if (tv == NULL) {
43595 				return NULL;
43596 			}
43597 		} else {
43598 			return NULL;
43599 		}
43600 	}
43601 
43602 	if (!DUK_TVAL_IS_STRING(tv)) {
43603 		return NULL;
43604 	}
43605 	h_str = DUK_TVAL_GET_STRING(tv);
43606 	DUK_ASSERT(h_str != NULL);
43607 
43608 	/* Here symbol is more expected than not. */
43609 	if (DUK_UNLIKELY(!DUK_HSTRING_HAS_SYMBOL(h_str))) {
43610 		return NULL;
43611 	}
43612 
43613 	return h_str;
43614 }
43615 
43616 DUK_INTERNAL duk_ret_t duk_bi_symbol_tostring_shared(duk_hthread *thr) {
43617 	duk_hstring *h_str;
43618 
43619 	h_str = duk__auto_unbox_symbol(thr, DUK_HTHREAD_THIS_PTR(thr));
43620 	if (h_str == NULL) {
43621 		return DUK_RET_TYPE_ERROR;
43622 	}
43623 
43624 	if (duk_get_current_magic(thr) == 0) {
43625 		/* .toString() */
43626 		duk_push_symbol_descriptive_string(thr, h_str);
43627 	} else {
43628 		/* .valueOf() */
43629 		duk_push_hstring(thr, h_str);
43630 	}
43631 	return 1;
43632 }
43633 
43634 DUK_INTERNAL duk_ret_t duk_bi_symbol_key_for(duk_hthread *thr) {
43635 	duk_hstring *h;
43636 	const duk_uint8_t *p;
43637 
43638 	/* Argument must be a symbol but not checked here.  The initial byte
43639 	 * check will catch non-symbol strings.
43640 	 */
43641 	h = duk_require_hstring(thr, 0);
43642 	DUK_ASSERT(h != NULL);
43643 
43644 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
43645 	DUK_ASSERT(p != NULL);
43646 
43647 	/* Even for zero length strings there's at least one NUL byte so
43648 	 * we can safely check the initial byte.
43649 	 */
43650 	if (p[0] == 0x80) {
43651 		/* Global symbol, return its key (bytes just after the initial byte). */
43652 		duk_push_lstring(thr, (const char *) (p + 1), (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h) - 1));
43653 		return 1;
43654 	} else if (p[0] == 0x81 || p[0] == 0x82 || p[0] == 0xff) {
43655 		/* Local symbol or hidden symbol, return undefined. */
43656 		return 0;
43657 	}
43658 
43659 	/* Covers normal strings and unknown initial bytes. */
43660 	return DUK_RET_TYPE_ERROR;
43661 }
43662 
43663 DUK_INTERNAL duk_ret_t duk_bi_symbol_toprimitive(duk_hthread *thr) {
43664 	duk_hstring *h_str;
43665 
43666 	h_str = duk__auto_unbox_symbol(thr, DUK_HTHREAD_THIS_PTR(thr));
43667 	if (h_str == NULL) {
43668 		return DUK_RET_TYPE_ERROR;
43669 	}
43670 	duk_push_hstring(thr, h_str);
43671 	return 1;
43672 }
43673 
43674 #endif  /* DUK_USE_SYMBOL_BUILTIN */
43675 #line 1 "duk_bi_thread.c"
43676 /*
43677  *  Thread builtins
43678  */
43679 
43680 /* #include duk_internal.h -> already included */
43681 
43682 /*
43683  *  Constructor
43684  */
43685 
43686 #if defined(DUK_USE_COROUTINE_SUPPORT)
43687 DUK_INTERNAL duk_ret_t duk_bi_thread_constructor(duk_hthread *thr) {
43688 	duk_hthread *new_thr;
43689 	duk_hobject *func;
43690 
43691 	/* Check that the argument is callable; this is not 100% because we
43692 	 * don't allow native functions to be a thread's initial function.
43693 	 * Resume will reject such functions in any case.
43694 	 */
43695 	/* XXX: need a duk_require_func_promote_lfunc() */
43696 	func = duk_require_hobject_promote_lfunc(thr, 0);
43697 	DUK_ASSERT(func != NULL);
43698 	duk_require_callable(thr, 0);
43699 
43700 	duk_push_thread(thr);
43701 	new_thr = (duk_hthread *) duk_known_hobject(thr, -1);
43702 	new_thr->state = DUK_HTHREAD_STATE_INACTIVE;
43703 
43704 	/* push initial function call to new thread stack; this is
43705 	 * picked up by resume().
43706 	 */
43707 	duk_push_hobject(new_thr, func);
43708 
43709 	return 1;  /* return thread */
43710 }
43711 #endif
43712 
43713 /*
43714  *  Resume a thread.
43715  *
43716  *  The thread must be in resumable state, either (a) new thread which hasn't
43717  *  yet started, or (b) a thread which has previously yielded.  This method
43718  *  must be called from an ECMAScript function.
43719  *
43720  *  Args:
43721  *    - thread
43722  *    - value
43723  *    - isError (defaults to false)
43724  *
43725  *  Note: yield and resume handling is currently asymmetric.
43726  */
43727 
43728 #if defined(DUK_USE_COROUTINE_SUPPORT)
43729 DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_hthread *ctx) {
43730 	duk_hthread *thr = (duk_hthread *) ctx;
43731 	duk_hthread *thr_resume;
43732 	duk_hobject *caller_func;
43733 	duk_small_uint_t is_error;
43734 
43735 	DUK_DDD(DUK_DDDPRINT("Duktape.Thread.resume(): thread=%!T, value=%!T, is_error=%!T",
43736 	                     (duk_tval *) duk_get_tval(thr, 0),
43737 	                     (duk_tval *) duk_get_tval(thr, 1),
43738 	                     (duk_tval *) duk_get_tval(thr, 2)));
43739 
43740 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
43741 	DUK_ASSERT(thr->heap->curr_thread == thr);
43742 
43743 	thr_resume = duk_require_hthread(thr, 0);
43744 	DUK_ASSERT(duk_get_top(thr) == 3);
43745 	is_error = (duk_small_uint_t) duk_to_boolean_top_pop(thr);
43746 	DUK_ASSERT(duk_get_top(thr) == 2);
43747 
43748 	/* [ thread value ] */
43749 
43750 	/*
43751 	 *  Thread state and calling context checks
43752 	 */
43753 
43754 	if (thr->callstack_top < 2) {
43755 		DUK_DD(DUK_DDPRINT("resume state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.resume)"));
43756 		goto state_error;
43757 	}
43758 	DUK_ASSERT(thr->callstack_curr != NULL);
43759 	DUK_ASSERT(thr->callstack_curr->parent != NULL);
43760 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);  /* us */
43761 	DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
43762 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL);  /* caller */
43763 
43764 	caller_func = DUK_ACT_GET_FUNC(thr->callstack_curr->parent);
43765 	if (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) {
43766 		DUK_DD(DUK_DDPRINT("resume state invalid: caller must be ECMAScript code"));
43767 		goto state_error;
43768 	}
43769 
43770 	/* Note: there is no requirement that: 'thr->callstack_preventcount == 1'
43771 	 * like for yield.
43772 	 */
43773 
43774 	if (thr_resume->state != DUK_HTHREAD_STATE_INACTIVE &&
43775 	    thr_resume->state != DUK_HTHREAD_STATE_YIELDED) {
43776 		DUK_DD(DUK_DDPRINT("resume state invalid: target thread must be INACTIVE or YIELDED"));
43777 		goto state_error;
43778 	}
43779 
43780 	DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE ||
43781 	           thr_resume->state == DUK_HTHREAD_STATE_YIELDED);
43782 
43783 	/* Further state-dependent pre-checks */
43784 
43785 	if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
43786 		/* no pre-checks now, assume a previous yield() has left things in
43787 		 * tip-top shape (longjmp handler will assert for these).
43788 		 */
43789 	} else {
43790 		duk_hobject *h_fun;
43791 
43792 		DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE);
43793 
43794 		/* The initial function must be an ECMAScript function (but
43795 		 * can be bound).  We must make sure of that before we longjmp
43796 		 * because an error in the RESUME handler call processing will
43797 		 * not be handled very cleanly.
43798 		 */
43799 		if ((thr_resume->callstack_top != 0) ||
43800 		    (thr_resume->valstack_top - thr_resume->valstack != 1)) {
43801 			goto state_error;
43802 		}
43803 
43804 		duk_push_tval(thr, DUK_GET_TVAL_NEGIDX(thr_resume, -1));
43805 		duk_resolve_nonbound_function(thr);
43806 		h_fun = duk_require_hobject(thr, -1);  /* reject lightfuncs on purpose */
43807 		if (!DUK_HOBJECT_IS_CALLABLE(h_fun) || !DUK_HOBJECT_IS_COMPFUNC(h_fun)) {
43808 			goto state_error;
43809 		}
43810 		duk_pop(thr);
43811 	}
43812 
43813 #if 0
43814 	/* This check would prevent a heap destruction time finalizer from
43815 	 * launching a coroutine, which would ensure that during finalization
43816 	 * 'thr' would always equal heap_thread.  Normal runtime finalizers
43817 	 * run with ms_running == 0, i.e. outside mark-and-sweep.  See GH-2030.
43818 	 */
43819 	if (thr->heap->ms_running) {
43820 		DUK_D(DUK_DPRINT("refuse Duktape.Thread.resume() when ms_running != 0"));
43821 		goto state_error;
43822 	}
43823 #endif
43824 
43825 	/*
43826 	 *  The error object has been augmented with a traceback and other
43827 	 *  info from its creation point -- usually another thread.  The
43828 	 *  error handler is called here right before throwing, but it also
43829 	 *  runs in the resumer's thread.  It might be nice to get a traceback
43830 	 *  from the resumee but this is not the case now.
43831 	 */
43832 
43833 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
43834 	if (is_error) {
43835 		DUK_ASSERT_TOP(thr, 2);  /* value (error) is at stack top */
43836 		duk_err_augment_error_throw(thr);  /* in resumer's context */
43837 	}
43838 #endif
43839 
43840 #if defined(DUK_USE_DEBUG)
43841 	if (is_error) {
43842 		DUK_DDD(DUK_DDDPRINT("RESUME ERROR: thread=%!T, value=%!T",
43843 		                     (duk_tval *) duk_get_tval(thr, 0),
43844 		                     (duk_tval *) duk_get_tval(thr, 1)));
43845 	} else if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
43846 		DUK_DDD(DUK_DDDPRINT("RESUME NORMAL: thread=%!T, value=%!T",
43847 		                     (duk_tval *) duk_get_tval(thr, 0),
43848 		                     (duk_tval *) duk_get_tval(thr, 1)));
43849 	} else {
43850 		DUK_DDD(DUK_DDDPRINT("RESUME INITIAL: thread=%!T, value=%!T",
43851 		                     (duk_tval *) duk_get_tval(thr, 0),
43852 		                     (duk_tval *) duk_get_tval(thr, 1)));
43853 	}
43854 #endif
43855 
43856 	thr->heap->lj.type = DUK_LJ_TYPE_RESUME;
43857 
43858 	/* lj value2: thread */
43859 	DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
43860 	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value2, &thr->valstack_bottom[0]);  /* side effects */
43861 
43862 	/* lj value1: value */
43863 	DUK_ASSERT(thr->valstack_bottom + 1 < thr->valstack_top);
43864 	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[1]);  /* side effects */
43865 	DUK_TVAL_CHKFAST_INPLACE_SLOW(&thr->heap->lj.value1);
43866 
43867 	thr->heap->lj.iserror = is_error;
43868 
43869 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* call is from executor, so we know we have a jmpbuf */
43870 	duk_err_longjmp(thr);  /* execution resumes in bytecode executor */
43871 	DUK_UNREACHABLE();
43872 	/* Never here, fall through to error (from compiler point of view). */
43873 
43874  state_error:
43875 	DUK_DCERROR_TYPE_INVALID_STATE(thr);
43876 }
43877 #endif
43878 
43879 /*
43880  *  Yield the current thread.
43881  *
43882  *  The thread must be in yieldable state: it must have a resumer, and there
43883  *  must not be any yield-preventing calls (native calls and constructor calls,
43884  *  currently) in the thread's call stack (otherwise a resume would not be
43885  *  possible later).  This method must be called from an ECMAScript function.
43886  *
43887  *  Args:
43888  *    - value
43889  *    - isError (defaults to false)
43890  *
43891  *  Note: yield and resume handling is currently asymmetric.
43892  */
43893 
43894 #if defined(DUK_USE_COROUTINE_SUPPORT)
43895 DUK_INTERNAL duk_ret_t duk_bi_thread_yield(duk_hthread *thr) {
43896 	duk_hobject *caller_func;
43897 	duk_small_uint_t is_error;
43898 
43899 	DUK_DDD(DUK_DDDPRINT("Duktape.Thread.yield(): value=%!T, is_error=%!T",
43900 	                     (duk_tval *) duk_get_tval(thr, 0),
43901 	                     (duk_tval *) duk_get_tval(thr, 1)));
43902 
43903 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
43904 	DUK_ASSERT(thr->heap->curr_thread == thr);
43905 
43906 	DUK_ASSERT(duk_get_top(thr) == 2);
43907 	is_error = (duk_small_uint_t) duk_to_boolean_top_pop(thr);
43908 	DUK_ASSERT(duk_get_top(thr) == 1);
43909 
43910 	/* [ value ] */
43911 
43912 	/*
43913 	 *  Thread state and calling context checks
43914 	 */
43915 
43916 	if (!thr->resumer) {
43917 		DUK_DD(DUK_DDPRINT("yield state invalid: current thread must have a resumer"));
43918 		goto state_error;
43919 	}
43920 	DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);
43921 
43922 	if (thr->callstack_top < 2) {
43923 		DUK_DD(DUK_DDPRINT("yield state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.yield)"));
43924 		goto state_error;
43925 	}
43926 	DUK_ASSERT(thr->callstack_curr != NULL);
43927 	DUK_ASSERT(thr->callstack_curr->parent != NULL);
43928 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);  /* us */
43929 	DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
43930 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL);  /* caller */
43931 
43932 	caller_func = DUK_ACT_GET_FUNC(thr->callstack_curr->parent);
43933 	if (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) {
43934 		DUK_DD(DUK_DDPRINT("yield state invalid: caller must be ECMAScript code"));
43935 		goto state_error;
43936 	}
43937 
43938 	DUK_ASSERT(thr->callstack_preventcount >= 1);  /* should never be zero, because we (Duktape.Thread.yield) are on the stack */
43939 	if (thr->callstack_preventcount != 1) {
43940 		/* Note: the only yield-preventing call is Duktape.Thread.yield(), hence check for 1, not 0 */
43941 		DUK_DD(DUK_DDPRINT("yield state invalid: there must be no yield-preventing calls in current thread callstack (preventcount is %ld)",
43942 		                   (long) thr->callstack_preventcount));
43943 		goto state_error;
43944 	}
43945 
43946 	/*
43947 	 *  The error object has been augmented with a traceback and other
43948 	 *  info from its creation point -- usually the current thread.
43949 	 *  The error handler, however, is called right before throwing
43950 	 *  and runs in the yielder's thread.
43951 	 */
43952 
43953 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
43954 	if (is_error) {
43955 		DUK_ASSERT_TOP(thr, 1);  /* value (error) is at stack top */
43956 		duk_err_augment_error_throw(thr);  /* in yielder's context */
43957 	}
43958 #endif
43959 
43960 #if defined(DUK_USE_DEBUG)
43961 	if (is_error) {
43962 		DUK_DDD(DUK_DDDPRINT("YIELD ERROR: value=%!T",
43963 		                     (duk_tval *) duk_get_tval(thr, 0)));
43964 	} else {
43965 		DUK_DDD(DUK_DDDPRINT("YIELD NORMAL: value=%!T",
43966 		                     (duk_tval *) duk_get_tval(thr, 0)));
43967 	}
43968 #endif
43969 
43970 	/*
43971 	 *  Process yield
43972 	 *
43973 	 *  After longjmp(), processing continues in bytecode executor longjmp
43974 	 *  handler, which will e.g. update thr->resumer to NULL.
43975 	 */
43976 
43977 	thr->heap->lj.type = DUK_LJ_TYPE_YIELD;
43978 
43979 	/* lj value1: value */
43980 	DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
43981 	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[0]);  /* side effects */
43982 	DUK_TVAL_CHKFAST_INPLACE_SLOW(&thr->heap->lj.value1);
43983 
43984 	thr->heap->lj.iserror = is_error;
43985 
43986 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* call is from executor, so we know we have a jmpbuf */
43987 	duk_err_longjmp(thr);  /* execution resumes in bytecode executor */
43988 	DUK_UNREACHABLE();
43989 	/* Never here, fall through to error (from compiler point of view). */
43990 
43991  state_error:
43992 	DUK_DCERROR_TYPE_INVALID_STATE(thr);
43993 }
43994 #endif
43995 
43996 #if defined(DUK_USE_COROUTINE_SUPPORT)
43997 DUK_INTERNAL duk_ret_t duk_bi_thread_current(duk_hthread *thr) {
43998 	duk_push_current_thread(thr);
43999 	return 1;
44000 }
44001 #endif
44002 #line 1 "duk_bi_thrower.c"
44003 /*
44004  *  Type error thrower, E5 Section 13.2.3.
44005  */
44006 
44007 /* #include duk_internal.h -> already included */
44008 
44009 DUK_INTERNAL duk_ret_t duk_bi_type_error_thrower(duk_hthread *thr) {
44010 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
44011 }
44012 #line 1 "duk_debug_fixedbuffer.c"
44013 /*
44014  *  Fixed buffer helper useful for debugging, requires no allocation
44015  *  which is critical for debugging.
44016  */
44017 
44018 /* #include duk_internal.h -> already included */
44019 
44020 #if defined(DUK_USE_DEBUG)
44021 
44022 DUK_INTERNAL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length) {
44023 	duk_size_t avail;
44024 	duk_size_t copylen;
44025 
44026 	avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
44027 	if (length > avail) {
44028 		copylen = avail;
44029 		fb->truncated = 1;
44030 	} else {
44031 		copylen = length;
44032 	}
44033 	duk_memcpy_unsafe(fb->buffer + fb->offset, buffer, copylen);
44034 	fb->offset += copylen;
44035 }
44036 
44037 DUK_INTERNAL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x) {
44038 	duk_fb_put_bytes(fb, (const duk_uint8_t *) &x, 1);
44039 }
44040 
44041 DUK_INTERNAL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x) {
44042 	duk_fb_put_bytes(fb, (const duk_uint8_t *) x, (duk_size_t) DUK_STRLEN(x));
44043 }
44044 
44045 DUK_INTERNAL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...) {
44046 	duk_size_t avail;
44047 	va_list ap;
44048 
44049 	va_start(ap, fmt);
44050 	avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
44051 	if (avail > 0) {
44052 		duk_int_t res = (duk_int_t) DUK_VSNPRINTF((char *) (fb->buffer + fb->offset), avail, fmt, ap);
44053 		if (res < 0) {
44054 			/* error */
44055 		} else if ((duk_size_t) res >= avail) {
44056 			/* (maybe) truncated */
44057 			fb->offset += avail;
44058 			if ((duk_size_t) res > avail) {
44059 				/* actual chars dropped (not just NUL term) */
44060 				fb->truncated = 1;
44061 			}
44062 		} else {
44063 			/* normal */
44064 			fb->offset += (duk_size_t) res;
44065 		}
44066 	}
44067 	va_end(ap);
44068 }
44069 
44070 DUK_INTERNAL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size) {
44071 	char buf[64+1];
44072 	duk_debug_format_funcptr(buf, sizeof(buf), fptr, fptr_size);
44073 	buf[sizeof(buf) - 1] = (char) 0;
44074 	duk_fb_put_cstring(fb, buf);
44075 }
44076 
44077 DUK_INTERNAL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb) {
44078 	return (fb->offset >= fb->length);
44079 }
44080 
44081 #endif  /* DUK_USE_DEBUG */
44082 #line 1 "duk_debug_vsnprintf.c"
44083 /*
44084  *  Custom formatter for debug printing, allowing Duktape specific data
44085  *  structures (such as tagged values and heap objects) to be printed with
44086  *  a nice format string.  Because debug printing should not affect execution
44087  *  state, formatting here must be independent of execution (see implications
44088  *  below) and must not allocate memory.
44089  *
44090  *  Custom format tags begin with a '%!' to safely distinguish them from
44091  *  standard format tags.  The following conversions are supported:
44092  *
44093  *     %!T    tagged value (duk_tval *)
44094  *     %!O    heap object (duk_heaphdr *)
44095  *     %!I    decoded bytecode instruction
44096  *     %!X    bytecode instruction opcode name (arg is long)
44097  *     %!C    catcher (duk_catcher *)
44098  *     %!A    activation (duk_activation *)
44099  *
44100  *  Everything is serialized in a JSON-like manner.  The default depth is one
44101  *  level, internal prototype is not followed, and internal properties are not
44102  *  serialized.  The following modifiers change this behavior:
44103  *
44104  *     @      print pointers
44105  *     #      print binary representations (where applicable)
44106  *     d      deep traversal of own properties (not prototype)
44107  *     p      follow prototype chain (useless without 'd')
44108  *     i      include internal properties (other than prototype)
44109  *     x      hexdump buffers
44110  *     h      heavy formatting
44111  *
44112  *  For instance, the following serializes objects recursively, but does not
44113  *  follow the prototype chain nor print internal properties: "%!dO".
44114  *
44115  *  Notes:
44116  *
44117  *    * Standard snprintf return value semantics seem to vary.  This
44118  *      implementation returns the number of bytes it actually wrote
44119  *      (excluding the null terminator).  If retval == buffer size,
44120  *      output was truncated (except for corner cases).
44121  *
44122  *    * Output format is intentionally different from ECMAScript
44123  *      formatting requirements, as formatting here serves debugging
44124  *      of internals.
44125  *
44126  *    * Depth checking (and updating) is done in each type printer
44127  *      separately, to allow them to call each other freely.
44128  *
44129  *    * Some pathological structures might take ages to print (e.g.
44130  *      self recursion with 100 properties pointing to the object
44131  *      itself).  To guard against these, each printer also checks
44132  *      whether the output buffer is full; if so, early exit.
44133  *
44134  *    * Reference loops are detected using a loop stack.
44135  */
44136 
44137 /* #include duk_internal.h -> already included */
44138 
44139 #if defined(DUK_USE_DEBUG)
44140 
44141 /* #include stdio.h -> already included */
44142 /* #include stdarg.h -> already included */
44143 #include <string.h>
44144 
44145 /* list of conversion specifiers that terminate a format tag;
44146  * this is unfortunately guesswork.
44147  */
44148 #define DUK__ALLOWED_STANDARD_SPECIFIERS  "diouxXeEfFgGaAcsCSpnm"
44149 
44150 /* maximum length of standard format tag that we support */
44151 #define DUK__MAX_FORMAT_TAG_LENGTH  32
44152 
44153 /* heapobj recursion depth when deep printing is selected */
44154 #define DUK__DEEP_DEPTH_LIMIT  8
44155 
44156 /* maximum recursion depth for loop detection stacks */
44157 #define DUK__LOOP_STACK_DEPTH  256
44158 
44159 /* must match bytecode defines now; build autogenerate? */
44160 DUK_LOCAL const char * const duk__bc_optab[256] = {
44161 	"LDREG", "STREG", "JUMP", "LDCONST", "LDINT", "LDINTX", "LDTHIS", "LDUNDEF",
44162 	"LDNULL", "LDTRUE", "LDFALSE", "GETVAR", "BNOT", "LNOT", "UNM", "UNP",
44163 	"EQ_RR", "EQ_CR", "EQ_RC", "EQ_CC", "NEQ_RR", "NEQ_CR", "NEQ_RC", "NEQ_CC",
44164 	"SEQ_RR", "SEQ_CR", "SEQ_RC", "SEQ_CC", "SNEQ_RR", "SNEQ_CR", "SNEQ_RC", "SNEQ_CC",
44165 
44166 	"GT_RR", "GT_CR", "GT_RC", "GT_CC", "GE_RR", "GE_CR", "GE_RC", "GE_CC",
44167 	"LT_RR", "LT_CR", "LT_RC", "LT_CC", "LE_RR", "LE_CR", "LE_RC", "LE_CC",
44168 	"IFTRUE_R", "IFTRUE_C", "IFFALSE_R", "IFFALSE_C", "ADD_RR", "ADD_CR", "ADD_RC", "ADD_CC",
44169 	"SUB_RR", "SUB_CR", "SUB_RC", "SUB_CC", "MUL_RR", "MUL_CR", "MUL_RC", "MUL_CC",
44170 
44171 	"DIV_RR", "DIV_CR", "DIV_RC", "DIV_CC", "MOD_RR", "MOD_CR", "MOD_RC", "MOD_CC",
44172 	"EXP_RR", "EXP_CR", "EXP_RC", "EXP_CC", "BAND_RR", "BAND_CR", "BAND_RC", "BAND_CC",
44173 	"BOR_RR", "BOR_CR", "BOR_RC", "BOR_CC", "BXOR_RR", "BXOR_CR", "BXOR_RC", "BXOR_CC",
44174 	"BASL_RR", "BASL_CR", "BASL_RC", "BASL_CC", "BLSR_RR", "BLSR_CR", "BLSR_RC", "BLSR_CC",
44175 
44176 	"BASR_RR", "BASR_CR", "BASR_RC", "BASR_CC", "INSTOF_RR", "INSTOF_CR", "INSTOF_RC", "INSTOF_CC",
44177 	"IN_RR", "IN_CR", "IN_RC", "IN_CC", "GETPROP_RR", "GETPROP_CR", "GETPROP_RC", "GETPROP_CC",
44178 	"PUTPROP_RR", "PUTPROP_CR", "PUTPROP_RC", "PUTPROP_CC", "DELPROP_RR", "DELPROP_CR", "DELPROP_RC", "DELPROP_CC",
44179 	"PREINCR", "PREDECR", "POSTINCR", "POSTDECR", "PREINCV", "PREDECV", "POSTINCV", "POSTDECV",
44180 
44181 	"PREINCP_RR", "PREINCP_CR", "PREINCP_RC", "PREINCP_CC", "PREDECP_RR", "PREDECP_CR", "PREDECP_RC", "PREDECP_CC",
44182 	"POSTINCP_RR", "POSTINCP_CR", "POSTINCP_RC", "POSTINCP_CC", "POSTDECP_RR", "POSTDECP_CR", "POSTDECP_RC", "POSTDECP_CC",
44183 	"DECLVAR_RR", "DECLVAR_CR", "DECLVAR_RC", "DECLVAR_CC", "REGEXP_RR", "REGEXP_RC", "REGEXP_CR", "REGEXP_CC",
44184 	"CLOSURE", "TYPEOF", "TYPEOFID", "PUTVAR", "DELVAR", "RETREG", "RETUNDEF", "RETCONST",
44185 
44186 	"RETCONSTN", "LABEL", "ENDLABEL", "BREAK", "CONTINUE", "TRYCATCH", "ENDTRY", "ENDCATCH",
44187 	"ENDFIN", "THROW", "INVLHS", "CSREG", "CSVAR_RR", "CSVAR_CR", "CSVAR_RC", "CSVAR_CC",
44188 	"CALL0", "CALL1", "CALL2", "CALL3", "CALL4", "CALL5", "CALL6", "CALL7",
44189 	"CALL8", "CALL9", "CALL10", "CALL11", "CALL12", "CALL13", "CALL14", "CALL15",
44190 
44191 	"NEWOBJ", "NEWARR", "MPUTOBJ", "MPUTOBJI", "INITSET", "INITGET", "MPUTARR", "MPUTARRI",
44192 	"SETALEN", "INITENUM", "NEXTENUM", "NEWTARGET", "DEBUGGER", "NOP", "INVALID", "UNUSED207",
44193 	"GETPROPC_RR", "GETPROPC_CR", "GETPROPC_RC", "GETPROPC_CC", "UNUSED212", "UNUSED213", "UNUSED214", "UNUSED215",
44194 	"UNUSED216", "UNUSED217", "UNUSED218", "UNUSED219", "UNUSED220", "UNUSED221", "UNUSED222", "UNUSED223",
44195 
44196 	"UNUSED224", "UNUSED225", "UNUSED226", "UNUSED227", "UNUSED228", "UNUSED229", "UNUSED230", "UNUSED231",
44197 	"UNUSED232", "UNUSED233", "UNUSED234", "UNUSED235", "UNUSED236", "UNUSED237", "UNUSED238", "UNUSED239",
44198 	"UNUSED240", "UNUSED241", "UNUSED242", "UNUSED243", "UNUSED244", "UNUSED245", "UNUSED246", "UNUSED247",
44199 	"UNUSED248", "UNUSED249", "UNUSED250", "UNUSED251", "UNUSED252", "UNUSED253", "UNUSED254", "UNUSED255"
44200 };
44201 
44202 typedef struct duk__dprint_state duk__dprint_state;
44203 struct duk__dprint_state {
44204 	duk_fixedbuffer *fb;
44205 
44206 	/* loop_stack_index could be perhaps be replaced by 'depth', but it's nice
44207 	 * to not couple these two mechanisms unnecessarily.
44208 	 */
44209 	duk_hobject *loop_stack[DUK__LOOP_STACK_DEPTH];
44210 	duk_int_t loop_stack_index;
44211 	duk_int_t loop_stack_limit;
44212 
44213 	duk_int_t depth;
44214 	duk_int_t depth_limit;
44215 
44216 	duk_bool_t pointer;
44217 	duk_bool_t heavy;
44218 	duk_bool_t binary;
44219 	duk_bool_t follow_proto;
44220 	duk_bool_t internal;
44221 	duk_bool_t hexdump;
44222 };
44223 
44224 /* helpers */
44225 DUK_LOCAL_DECL void duk__print_hstring(duk__dprint_state *st, duk_hstring *k, duk_bool_t quotes);
44226 DUK_LOCAL_DECL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h);
44227 DUK_LOCAL_DECL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h);
44228 DUK_LOCAL_DECL void duk__print_tval(duk__dprint_state *st, duk_tval *tv);
44229 DUK_LOCAL_DECL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins);
44230 DUK_LOCAL_DECL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
44231 DUK_LOCAL_DECL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
44232 DUK_LOCAL_DECL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h);
44233 
44234 DUK_LOCAL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
44235 	duk_fixedbuffer *fb = st->fb;
44236 
44237 	if (st->heavy) {
44238 		duk_fb_sprintf(fb, "(%p)", (void *) h);
44239 	}
44240 
44241 	if (!h) {
44242 		return;
44243 	}
44244 
44245 	if (st->binary) {
44246 		duk_size_t i;
44247 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
44248 		for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
44249 			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
44250 		}
44251 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
44252 	}
44253 
44254 #if defined(DUK_USE_REFERENCE_COUNTING)  /* currently implicitly also DUK_USE_DOUBLE_LINKED_HEAP */
44255 	if (st->heavy) {
44256 		duk_fb_sprintf(fb, "[h_next=%p,h_prev=%p,h_refcount=%lu,h_flags=%08lx,type=%ld,"
44257 		               "reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
44258 		               (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
44259 		               (void *) DUK_HEAPHDR_GET_PREV(NULL, h),
44260 		               (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(h),
44261 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
44262 		               (long) DUK_HEAPHDR_GET_TYPE(h),
44263 		               (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
44264 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
44265 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
44266 		               (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
44267 	}
44268 #else
44269 	if (st->heavy) {
44270 		duk_fb_sprintf(fb, "[h_next=%p,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
44271 		               (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
44272 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
44273 		               (long) DUK_HEAPHDR_GET_TYPE(h),
44274 		               (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
44275 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
44276 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
44277 		               (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
44278 	}
44279 #endif
44280 }
44281 
44282 DUK_LOCAL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h) {
44283 	duk_fixedbuffer *fb = st->fb;
44284 
44285 	if (st->heavy) {
44286 		duk_fb_sprintf(fb, "(%p)", (void *) h);
44287 	}
44288 
44289 	if (!h) {
44290 		return;
44291 	}
44292 
44293 	if (st->binary) {
44294 		duk_size_t i;
44295 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
44296 		for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
44297 			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
44298 		}
44299 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
44300 	}
44301 
44302 #if defined(DUK_USE_REFERENCE_COUNTING)
44303 	if (st->heavy) {
44304 		duk_fb_sprintf(fb, "[h_refcount=%lu,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
44305 		               (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h),
44306 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
44307 		               (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
44308 		               (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
44309 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
44310 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
44311 		               (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
44312 	}
44313 #else
44314 	if (st->heavy) {
44315 		duk_fb_sprintf(fb, "[h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
44316 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
44317 		               (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
44318 		               (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
44319 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
44320 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
44321 		               (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
44322 	}
44323 #endif
44324 }
44325 
44326 DUK_LOCAL void duk__print_hstring(duk__dprint_state *st, duk_hstring *h, duk_bool_t quotes) {
44327 	duk_fixedbuffer *fb = st->fb;
44328 	const duk_uint8_t *p;
44329 	const duk_uint8_t *p_end;
44330 
44331 	/* terminal type: no depth check */
44332 
44333 	if (duk_fb_is_full(fb)) {
44334 		return;
44335 	}
44336 
44337 	duk__print_shared_heaphdr_string(st, &h->hdr);
44338 
44339 	if (!h) {
44340 		duk_fb_put_cstring(fb, "NULL");
44341 		return;
44342 	}
44343 
44344 	p = DUK_HSTRING_GET_DATA(h);
44345 	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
44346 
44347 	if (p_end > p && p[0] == DUK_ASC_UNDERSCORE) {
44348 		/* If property key begins with underscore, encode it with
44349 		 * forced quotes (e.g. "_Foo") to distinguish it from encoded
44350 		 * internal properties (e.g. \x82Bar -> _Bar).
44351 		 */
44352 		quotes = 1;
44353 	}
44354 
44355 	if (quotes) {
44356 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
44357 	}
44358 	while (p < p_end) {
44359 		duk_uint8_t ch = *p++;
44360 
44361 		/* two special escapes: '\' and '"', other printables as is */
44362 		if (ch == '\\') {
44363 			duk_fb_sprintf(fb, "\\\\");
44364 		} else if (ch == '"') {
44365 			duk_fb_sprintf(fb, "\\\"");
44366 		} else if (ch >= 0x20 && ch <= 0x7e) {
44367 			duk_fb_put_byte(fb, ch);
44368 		} else if (ch == 0x82 && !quotes) {
44369 			/* encode \x82Bar as _Bar if no quotes are
44370 			 * applied, this is for readable internal keys.
44371 			 */
44372 			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_UNDERSCORE);
44373 		} else {
44374 			duk_fb_sprintf(fb, "\\x%02lx", (unsigned long) ch);
44375 		}
44376 	}
44377 	if (quotes) {
44378 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
44379 	}
44380 #if defined(DUK_USE_REFERENCE_COUNTING)
44381 	/* XXX: limit to quoted strings only, to save keys from being cluttered? */
44382 	duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
44383 #endif
44384 }
44385 
44386 #define DUK__COMMA()  do { \
44387 		if (first) { \
44388 			first = 0; \
44389 		} else { \
44390 			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA); \
44391 		} \
44392 	} while (0)
44393 
44394 DUK_LOCAL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h) {
44395 	duk_fixedbuffer *fb = st->fb;
44396 	duk_uint_fast32_t i;
44397 	duk_tval *tv;
44398 	duk_hstring *key;
44399 	duk_bool_t first = 1;
44400 	const char *brace1 = "{";
44401 	const char *brace2 = "}";
44402 	duk_bool_t pushed_loopstack = 0;
44403 
44404 	if (duk_fb_is_full(fb)) {
44405 		return;
44406 	}
44407 
44408 	duk__print_shared_heaphdr(st, &h->hdr);
44409 
44410 	if (h && DUK_HOBJECT_HAS_ARRAY_PART(h)) {
44411 		brace1 = "[";
44412 		brace2 = "]";
44413 	}
44414 
44415 	if (!h) {
44416 		duk_fb_put_cstring(fb, "NULL");
44417 		goto finished;
44418 	}
44419 
44420 	if (st->depth >= st->depth_limit) {
44421 		const char *subtype = "generic";
44422 
44423 		if (DUK_HOBJECT_IS_COMPFUNC(h)) {
44424 			subtype = "compfunc";
44425 		} else if (DUK_HOBJECT_IS_NATFUNC(h)) {
44426 			subtype = "natfunc";
44427 		} else if (DUK_HOBJECT_IS_THREAD(h)) {
44428 			subtype = "thread";
44429 		} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
44430 			subtype = "bufobj";
44431 		} else if (DUK_HOBJECT_IS_ARRAY(h)) {
44432 			subtype = "array";
44433 		}
44434 		duk_fb_sprintf(fb, "%sobject/%s %p%s", (const char *) brace1, subtype, (void *) h, (const char *) brace2);
44435 		return;
44436 	}
44437 
44438 	for (i = 0; i < (duk_uint_fast32_t) st->loop_stack_index; i++) {
44439 		if (st->loop_stack[i] == h) {
44440 			duk_fb_sprintf(fb, "%sLOOP:%p%s", (const char *) brace1, (void *) h, (const char *) brace2);
44441 			return;
44442 		}
44443 	}
44444 
44445 	/* after this, return paths should 'goto finished' for decrement */
44446 	st->depth++;
44447 
44448 	if (st->loop_stack_index >= st->loop_stack_limit) {
44449 		duk_fb_sprintf(fb, "%sOUT-OF-LOOP-STACK%s", (const char *) brace1, (const char *) brace2);
44450 		goto finished;
44451 	}
44452 	st->loop_stack[st->loop_stack_index++] = h;
44453 	pushed_loopstack = 1;
44454 
44455 	/*
44456 	 *  Notation: double underscore used for internal properties which are not
44457 	 *  stored in the property allocation (e.g. '__valstack').
44458 	 */
44459 
44460 	duk_fb_put_cstring(fb, brace1);
44461 
44462 	if (DUK_HOBJECT_GET_PROPS(NULL, h)) {
44463 		duk_uint32_t a_limit;
44464 
44465 		a_limit = DUK_HOBJECT_GET_ASIZE(h);
44466 		if (st->internal) {
44467 			/* dump all allocated entries, unused entries print as 'unused',
44468 			 * note that these may extend beyond current 'length' and look
44469 			 * a bit funny.
44470 			 */
44471 		} else {
44472 			/* leave out trailing 'unused' elements */
44473 			while (a_limit > 0) {
44474 				tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, a_limit - 1);
44475 				if (!DUK_TVAL_IS_UNUSED(tv)) {
44476 					break;
44477 				}
44478 				a_limit--;
44479 			}
44480 		}
44481 
44482 		for (i = 0; i < a_limit; i++) {
44483 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, i);
44484 			DUK__COMMA();
44485 			duk__print_tval(st, tv);
44486 		}
44487 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(h); i++) {
44488 			key = DUK_HOBJECT_E_GET_KEY(NULL, h, i);
44489 			if (!key) {
44490 				continue;
44491 			}
44492 			if (!st->internal && DUK_HSTRING_HAS_HIDDEN(key)) {
44493 				continue;
44494 			}
44495 			DUK__COMMA();
44496 			duk__print_hstring(st, key, 0);
44497 			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COLON);
44498 			if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(NULL, h, i)) {
44499 				duk_fb_sprintf(fb, "[get:%p,set:%p]",
44500 				               (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.get,
44501 				               (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.set);
44502 			} else {
44503 				tv = &DUK_HOBJECT_E_GET_VALUE(NULL, h, i).v;
44504 				duk__print_tval(st, tv);
44505 			}
44506 			if (st->heavy) {
44507 				duk_fb_sprintf(fb, "<%02lx>", (unsigned long) DUK_HOBJECT_E_GET_FLAGS(NULL, h, i));
44508 			}
44509 		}
44510 	}
44511 	if (st->internal) {
44512 		if (DUK_HOBJECT_IS_ARRAY(h)) {
44513 			DUK__COMMA(); duk_fb_sprintf(fb, "__array:true");
44514 		}
44515 		if (DUK_HOBJECT_HAS_EXTENSIBLE(h)) {
44516 			DUK__COMMA(); duk_fb_sprintf(fb, "__extensible:true");
44517 		}
44518 		if (DUK_HOBJECT_HAS_CONSTRUCTABLE(h)) {
44519 			DUK__COMMA(); duk_fb_sprintf(fb, "__constructable:true");
44520 		}
44521 		if (DUK_HOBJECT_HAS_BOUNDFUNC(h)) {
44522 			DUK__COMMA(); duk_fb_sprintf(fb, "__boundfunc:true");
44523 		}
44524 		if (DUK_HOBJECT_HAS_COMPFUNC(h)) {
44525 			DUK__COMMA(); duk_fb_sprintf(fb, "__compfunc:true");
44526 		}
44527 		if (DUK_HOBJECT_HAS_NATFUNC(h)) {
44528 			DUK__COMMA(); duk_fb_sprintf(fb, "__natfunc:true");
44529 		}
44530 		if (DUK_HOBJECT_HAS_BUFOBJ(h)) {
44531 			DUK__COMMA(); duk_fb_sprintf(fb, "__bufobj:true");
44532 		}
44533 		if (DUK_HOBJECT_IS_THREAD(h)) {
44534 			DUK__COMMA(); duk_fb_sprintf(fb, "__thread:true");
44535 		}
44536 		if (DUK_HOBJECT_HAS_ARRAY_PART(h)) {
44537 			DUK__COMMA(); duk_fb_sprintf(fb, "__array_part:true");
44538 		}
44539 		if (DUK_HOBJECT_HAS_STRICT(h)) {
44540 			DUK__COMMA(); duk_fb_sprintf(fb, "__strict:true");
44541 		}
44542 		if (DUK_HOBJECT_HAS_NOTAIL(h)) {
44543 			DUK__COMMA(); duk_fb_sprintf(fb, "__notail:true");
44544 		}
44545 		if (DUK_HOBJECT_HAS_NEWENV(h)) {
44546 			DUK__COMMA(); duk_fb_sprintf(fb, "__newenv:true");
44547 		}
44548 		if (DUK_HOBJECT_HAS_NAMEBINDING(h)) {
44549 			DUK__COMMA(); duk_fb_sprintf(fb, "__namebinding:true");
44550 		}
44551 		if (DUK_HOBJECT_HAS_CREATEARGS(h)) {
44552 			DUK__COMMA(); duk_fb_sprintf(fb, "__createargs:true");
44553 		}
44554 		if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)) {
44555 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_array:true");
44556 		}
44557 		if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)) {
44558 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_stringobj:true");
44559 		}
44560 		if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)) {
44561 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_arguments:true");
44562 		}
44563 		if (DUK_HOBJECT_IS_BUFOBJ(h)) {
44564 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_bufobj:true");
44565 		}
44566 		if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)) {
44567 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_proxyobj:true");
44568 		}
44569 	}
44570 
44571 	if (st->internal && DUK_HOBJECT_IS_ARRAY(h)) {
44572 		duk_harray *a = (duk_harray *) h;
44573 		DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) a->length);
44574 		DUK__COMMA(); duk_fb_sprintf(fb, "__length_nonwritable:%ld", (long) a->length_nonwritable);
44575 	} else if (st->internal && DUK_HOBJECT_IS_COMPFUNC(h)) {
44576 		duk_hcompfunc *f = (duk_hcompfunc *) h;
44577 		DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
44578 		duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));
44579 		DUK__COMMA(); duk_fb_put_cstring(fb, "__lexenv:"); duk__print_hobject(st, DUK_HCOMPFUNC_GET_LEXENV(NULL, f));
44580 		DUK__COMMA(); duk_fb_put_cstring(fb, "__varenv:"); duk__print_hobject(st, DUK_HCOMPFUNC_GET_VARENV(NULL, f));
44581 		DUK__COMMA(); duk_fb_sprintf(fb, "__nregs:%ld", (long) f->nregs);
44582 		DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
44583 #if defined(DUK_USE_DEBUGGER_SUPPORT)
44584 		DUK__COMMA(); duk_fb_sprintf(fb, "__start_line:%ld", (long) f->start_line);
44585 		DUK__COMMA(); duk_fb_sprintf(fb, "__end_line:%ld", (long) f->end_line);
44586 #endif
44587 		DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
44588 		duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));
44589 	} else if (st->internal && DUK_HOBJECT_IS_NATFUNC(h)) {
44590 		duk_hnatfunc *f = (duk_hnatfunc *) h;
44591 		DUK__COMMA(); duk_fb_sprintf(fb, "__func:");
44592 		duk_fb_put_funcptr(fb, (duk_uint8_t *) &f->func, sizeof(f->func));
44593 		DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
44594 		DUK__COMMA(); duk_fb_sprintf(fb, "__magic:%ld", (long) f->magic);
44595 	} else if (st->internal && DUK_HOBJECT_IS_DECENV(h)) {
44596 		duk_hdecenv *e = (duk_hdecenv *) h;
44597 		DUK__COMMA(); duk_fb_sprintf(fb, "__thread:"); duk__print_hobject(st, (duk_hobject *) e->thread);
44598 		DUK__COMMA(); duk_fb_sprintf(fb, "__varmap:"); duk__print_hobject(st, (duk_hobject *) e->varmap);
44599 		DUK__COMMA(); duk_fb_sprintf(fb, "__regbase_byteoff:%ld", (long) e->regbase_byteoff);
44600 	} else if (st->internal && DUK_HOBJECT_IS_OBJENV(h)) {
44601 		duk_hobjenv *e = (duk_hobjenv *) h;
44602 		DUK__COMMA(); duk_fb_sprintf(fb, "__target:"); duk__print_hobject(st, (duk_hobject *) e->target);
44603 		DUK__COMMA(); duk_fb_sprintf(fb, "__has_this:%ld", (long) e->has_this);
44604 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
44605 	} else if (st->internal && DUK_HOBJECT_IS_BUFOBJ(h)) {
44606 		duk_hbufobj *b = (duk_hbufobj *) h;
44607 		DUK__COMMA(); duk_fb_sprintf(fb, "__buf:");
44608 		duk__print_hbuffer(st, (duk_hbuffer *) b->buf);
44609 		DUK__COMMA(); duk_fb_sprintf(fb, "__buf_prop:");
44610 		duk__print_hobject(st, (duk_hobject *) b->buf_prop);
44611 		DUK__COMMA(); duk_fb_sprintf(fb, "__offset:%ld", (long) b->offset);
44612 		DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) b->length);
44613 		DUK__COMMA(); duk_fb_sprintf(fb, "__shift:%ld", (long) b->shift);
44614 		DUK__COMMA(); duk_fb_sprintf(fb, "__elemtype:%ld", (long) b->elem_type);
44615 #endif
44616 	} else if (st->internal && DUK_HOBJECT_IS_PROXY(h)) {
44617 		duk_hproxy *p = (duk_hproxy *) h;
44618 		DUK__COMMA(); duk_fb_sprintf(fb, "__target:");
44619 		duk__print_hobject(st, p->target);
44620 		DUK__COMMA(); duk_fb_sprintf(fb, "__handler:");
44621 		duk__print_hobject(st, p->handler);
44622 	} else if (st->internal && DUK_HOBJECT_IS_THREAD(h)) {
44623 		duk_hthread *t = (duk_hthread *) h;
44624 		DUK__COMMA(); duk_fb_sprintf(fb, "__ptr_curr_pc:%p", (void *) t->ptr_curr_pc);
44625 		DUK__COMMA(); duk_fb_sprintf(fb, "__heap:%p", (void *) t->heap);
44626 		DUK__COMMA(); duk_fb_sprintf(fb, "__strict:%ld", (long) t->strict);
44627 		DUK__COMMA(); duk_fb_sprintf(fb, "__state:%ld", (long) t->state);
44628 		DUK__COMMA(); duk_fb_sprintf(fb, "__unused1:%ld", (long) t->unused1);
44629 		DUK__COMMA(); duk_fb_sprintf(fb, "__unused2:%ld", (long) t->unused2);
44630 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack:%p", (void *) t->valstack);
44631 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_end:%p/%ld", (void *) t->valstack_end, (long) (t->valstack_end - t->valstack));
44632 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_alloc_end:%p/%ld", (void *) t->valstack_alloc_end, (long) (t->valstack_alloc_end - t->valstack));
44633 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_bottom:%p/%ld", (void *) t->valstack_bottom, (long) (t->valstack_bottom - t->valstack));
44634 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_top:%p/%ld", (void *) t->valstack_top, (long) (t->valstack_top - t->valstack));
44635 		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_curr:%p", (void *) t->callstack_curr);
44636 		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_top:%ld", (long) t->callstack_top);
44637 		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_preventcount:%ld", (long) t->callstack_preventcount);
44638 		DUK__COMMA(); duk_fb_sprintf(fb, "__resumer:"); duk__print_hobject(st, (duk_hobject *) t->resumer);
44639 		DUK__COMMA(); duk_fb_sprintf(fb, "__compile_ctx:%p", (void *) t->compile_ctx);
44640 #if defined(DUK_USE_INTERRUPT_COUNTER)
44641 		DUK__COMMA(); duk_fb_sprintf(fb, "__interrupt_counter:%ld", (long) t->interrupt_counter);
44642 		DUK__COMMA(); duk_fb_sprintf(fb, "__interrupt_init:%ld", (long) t->interrupt_init);
44643 #endif
44644 
44645 		/* XXX: print built-ins array? */
44646 
44647 	}
44648 #if defined(DUK_USE_REFERENCE_COUNTING)
44649 	if (st->internal) {
44650 		DUK__COMMA(); duk_fb_sprintf(fb, "__refcount:%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h));
44651 	}
44652 #endif
44653 	if (st->internal) {
44654 		DUK__COMMA(); duk_fb_sprintf(fb, "__class:%ld", (long) DUK_HOBJECT_GET_CLASS_NUMBER(h));
44655 	}
44656 
44657 	DUK__COMMA(); duk_fb_sprintf(fb, "__heapptr:%p", (void *) h);  /* own pointer */
44658 
44659 	/* prototype should be last, for readability */
44660 	if (DUK_HOBJECT_GET_PROTOTYPE(NULL, h)) {
44661 		if (st->follow_proto) {
44662 			DUK__COMMA(); duk_fb_put_cstring(fb, "__prototype:"); duk__print_hobject(st, DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
44663 		} else {
44664 			DUK__COMMA(); duk_fb_sprintf(fb, "__prototype:%p", (void *) DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
44665 		}
44666 	}
44667 
44668 	duk_fb_put_cstring(fb, brace2);
44669 
44670 #if defined(DUK_USE_HOBJECT_HASH_PART)
44671 	if (st->heavy && DUK_HOBJECT_GET_HSIZE(h) > 0) {
44672 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
44673 		for (i = 0; i < DUK_HOBJECT_GET_HSIZE(h); i++) {
44674 			duk_uint_t h_idx = DUK_HOBJECT_H_GET_INDEX(NULL, h, i);
44675 			if (i > 0) {
44676 				duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA);
44677 			}
44678 			if (h_idx == DUK_HOBJECT_HASHIDX_UNUSED) {
44679 				duk_fb_sprintf(fb, "u");
44680 			} else if (h_idx == DUK_HOBJECT_HASHIDX_DELETED) {
44681 				duk_fb_sprintf(fb, "d");
44682 			} else {
44683 				duk_fb_sprintf(fb, "%ld", (long) h_idx);
44684 			}
44685 		}
44686 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
44687 	}
44688 #endif
44689 
44690  finished:
44691 	st->depth--;
44692 	if (pushed_loopstack) {
44693 		st->loop_stack_index--;
44694 		st->loop_stack[st->loop_stack_index] = NULL;
44695 	}
44696 }
44697 
44698 DUK_LOCAL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h) {
44699 	duk_fixedbuffer *fb = st->fb;
44700 	duk_size_t i, n;
44701 	duk_uint8_t *p;
44702 
44703 	if (duk_fb_is_full(fb)) {
44704 		return;
44705 	}
44706 
44707 	/* terminal type: no depth check */
44708 
44709 	if (!h) {
44710 		duk_fb_put_cstring(fb, "NULL");
44711 		return;
44712 	}
44713 
44714 	if (DUK_HBUFFER_HAS_DYNAMIC(h)) {
44715 		if (DUK_HBUFFER_HAS_EXTERNAL(h)) {
44716 			duk_hbuffer_external *g = (duk_hbuffer_external *) h;
44717 			duk_fb_sprintf(fb, "buffer:external:%p:%ld",
44718 			               (void *) DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(NULL, g),
44719 			               (long) DUK_HBUFFER_EXTERNAL_GET_SIZE(g));
44720 		} else {
44721 			duk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;
44722 			duk_fb_sprintf(fb, "buffer:dynamic:%p:%ld",
44723 			               (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(NULL, g),
44724 			               (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(g));
44725 		}
44726 	} else {
44727 		duk_fb_sprintf(fb, "buffer:fixed:%ld", (long) DUK_HBUFFER_GET_SIZE(h));
44728 	}
44729 
44730 #if defined(DUK_USE_REFERENCE_COUNTING)
44731 	duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
44732 #endif
44733 
44734 	if (st->hexdump) {
44735 		duk_fb_sprintf(fb, "=[");
44736 		n = DUK_HBUFFER_GET_SIZE(h);
44737 		p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(NULL, h);
44738 		for (i = 0; i < n; i++) {
44739 			duk_fb_sprintf(fb, "%02lx", (unsigned long) p[i]);
44740 		}
44741 		duk_fb_sprintf(fb, "]");
44742 	}
44743 }
44744 
44745 DUK_LOCAL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
44746 	duk_fixedbuffer *fb = st->fb;
44747 
44748 	if (duk_fb_is_full(fb)) {
44749 		return;
44750 	}
44751 
44752 	if (!h) {
44753 		duk_fb_put_cstring(fb, "NULL");
44754 		return;
44755 	}
44756 
44757 	switch (DUK_HEAPHDR_GET_TYPE(h)) {
44758 	case DUK_HTYPE_STRING:
44759 		duk__print_hstring(st, (duk_hstring *) h, 1);
44760 		break;
44761 	case DUK_HTYPE_OBJECT:
44762 		duk__print_hobject(st, (duk_hobject *) h);
44763 		break;
44764 	case DUK_HTYPE_BUFFER:
44765 		duk__print_hbuffer(st, (duk_hbuffer *) h);
44766 		break;
44767 	default:
44768 		duk_fb_sprintf(fb, "[unknown htype %ld]", (long) DUK_HEAPHDR_GET_TYPE(h));
44769 		break;
44770 	}
44771 }
44772 
44773 DUK_LOCAL void duk__print_tval(duk__dprint_state *st, duk_tval *tv) {
44774 	duk_fixedbuffer *fb = st->fb;
44775 
44776 	if (duk_fb_is_full(fb)) {
44777 		return;
44778 	}
44779 
44780 	/* depth check is done when printing an actual type */
44781 
44782 	if (st->heavy) {
44783 		duk_fb_sprintf(fb, "(%p)", (void *) tv);
44784 	}
44785 
44786 	if (!tv) {
44787 		duk_fb_put_cstring(fb, "NULL");
44788 		return;
44789 	}
44790 
44791 	if (st->binary) {
44792 		duk_size_t i;
44793 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
44794 		for (i = 0; i < (duk_size_t) sizeof(*tv); i++) {
44795 			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)tv)[i]);
44796 		}
44797 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
44798 	}
44799 
44800 	if (st->heavy) {
44801 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
44802 	}
44803 	switch (DUK_TVAL_GET_TAG(tv)) {
44804 	case DUK_TAG_UNDEFINED: {
44805 		duk_fb_put_cstring(fb, "undefined");
44806 		break;
44807 	}
44808 	case DUK_TAG_UNUSED: {
44809 		duk_fb_put_cstring(fb, "unused");
44810 		break;
44811 	}
44812 	case DUK_TAG_NULL: {
44813 		duk_fb_put_cstring(fb, "null");
44814 		break;
44815 	}
44816 	case DUK_TAG_BOOLEAN: {
44817 		duk_fb_put_cstring(fb, DUK_TVAL_GET_BOOLEAN(tv) ? "true" : "false");
44818 		break;
44819 	}
44820 	case DUK_TAG_STRING: {
44821 		/* Note: string is a terminal heap object, so no depth check here */
44822 		duk__print_hstring(st, DUK_TVAL_GET_STRING(tv), 1);
44823 		break;
44824 	}
44825 	case DUK_TAG_OBJECT: {
44826 		duk__print_hobject(st, DUK_TVAL_GET_OBJECT(tv));
44827 		break;
44828 	}
44829 	case DUK_TAG_BUFFER: {
44830 		duk__print_hbuffer(st, DUK_TVAL_GET_BUFFER(tv));
44831 		break;
44832 	}
44833 	case DUK_TAG_POINTER: {
44834 		duk_fb_sprintf(fb, "pointer:%p", (void *) DUK_TVAL_GET_POINTER(tv));
44835 		break;
44836 	}
44837 	case DUK_TAG_LIGHTFUNC: {
44838 		duk_c_function func;
44839 		duk_small_uint_t lf_flags;
44840 
44841 		DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
44842 		duk_fb_sprintf(fb, "lightfunc:");
44843 		duk_fb_put_funcptr(fb, (duk_uint8_t *) &func, sizeof(func));
44844 		duk_fb_sprintf(fb, ":%04lx", (long) lf_flags);
44845 		break;
44846 	}
44847 #if defined(DUK_USE_FASTINT)
44848 	case DUK_TAG_FASTINT:
44849 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
44850 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
44851 		duk_fb_sprintf(fb, "%.18g_F", (double) DUK_TVAL_GET_NUMBER(tv));
44852 		break;
44853 #endif
44854 	default: {
44855 		/* IEEE double is approximately 16 decimal digits; print a couple extra */
44856 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
44857 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
44858 		duk_fb_sprintf(fb, "%.18g", (double) DUK_TVAL_GET_NUMBER(tv));
44859 		break;
44860 	}
44861 	}
44862 	if (st->heavy) {
44863 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
44864 	}
44865 }
44866 
44867 DUK_LOCAL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins) {
44868 	duk_fixedbuffer *fb = st->fb;
44869 	duk_small_int_t op;
44870 	const char *op_name;
44871 
44872 	op = (duk_small_int_t) DUK_DEC_OP(ins);
44873 	op_name = duk__bc_optab[op];
44874 
44875 	/* XXX: option to fix opcode length so it lines up nicely */
44876 
44877 	if (op == DUK_OP_JUMP) {
44878 		duk_int_t diff1 = (duk_int_t) (DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS);  /* from next pc */
44879 		duk_int_t diff2 = diff1 + 1;                                          /* from curr pc */
44880 
44881 		duk_fb_sprintf(fb, "%s %ld (to pc%c%ld)",
44882 		               (const char *) op_name, (long) diff1,
44883 		               (int) (diff2 >= 0 ? '+' : '-'),  /* char format: use int */
44884 		               (long) (diff2 >= 0 ? diff2 : -diff2));
44885 	} else {
44886 		duk_fb_sprintf(fb, "%s %ld, %ld, %ld",
44887 		               (const char *) op_name, (long) DUK_DEC_A(ins),
44888 		               (long) DUK_DEC_B(ins), (long) DUK_DEC_C(ins));
44889 	}
44890 }
44891 
44892 DUK_LOCAL void duk__print_opcode(duk__dprint_state *st, duk_small_int_t opcode) {
44893 	duk_fixedbuffer *fb = st->fb;
44894 
44895 	if (opcode < DUK_BC_OP_MIN || opcode > DUK_BC_OP_MAX) {
44896 		duk_fb_sprintf(fb, "?(%ld)", (long) opcode);
44897 	} else {
44898 		duk_fb_sprintf(fb, "%s", (const char *) duk__bc_optab[opcode]);
44899 	}
44900 }
44901 
44902 DUK_LOCAL void duk__print_catcher(duk__dprint_state *st, duk_catcher *cat) {
44903 	duk_fixedbuffer *fb = st->fb;
44904 
44905 	if (duk_fb_is_full(fb)) {
44906 		return;
44907 	}
44908 
44909 	if (!cat) {
44910 		duk_fb_put_cstring(fb, "NULL");
44911 		return;
44912 	}
44913 
44914 	duk_fb_sprintf(fb, "[catcher ptr=%p parent=%p varname=%p pc_base=%p, idx_base=%ld, flags=0x%08lx]",
44915 	               (void *) cat,
44916 	               (void *) cat->parent, (void *) cat->h_varname, (void *) cat->pc_base,
44917 		       (long) cat->idx_base, (unsigned long) cat->flags);
44918 }
44919 
44920 
44921 DUK_LOCAL void duk__print_activation(duk__dprint_state *st, duk_activation *act) {
44922 	duk_fixedbuffer *fb = st->fb;
44923 
44924 	if (duk_fb_is_full(fb)) {
44925 		return;
44926 	}
44927 
44928 	if (!act) {
44929 		duk_fb_put_cstring(fb, "NULL");
44930 		return;
44931 	}
44932 
44933 	/* prev_caller: conditional, omitted on purpose, it's rarely used. */
44934 	/* prev_line: conditional, omitted on purpose (but would be nice). */
44935 	duk_fb_sprintf(fb, "[activation ptr=%p tv_func=<omit> func=%p parent=%p var_env=%p lex_env=%p cat=%p curr_pc=%p bottom_byteoff=%ld retval_byteoff=%ld reserve_byteoff=%ld flags=%ld]",
44936 	               (void *) act,
44937 	               (void *) act->func, (void *) act->parent, (void *) act->var_env,
44938 		       (void *) act->lex_env, (void *) act->cat, (void *) act->curr_pc,
44939 		       (long) act->bottom_byteoff, (long) act->retval_byteoff, (long) act->reserve_byteoff,
44940 		       (long) act->flags);
44941 }
44942 
44943 DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap) {
44944 	duk_fixedbuffer fb;
44945 	const char *p = format;
44946 	const char *p_end = p + DUK_STRLEN(format);
44947 	duk_int_t retval;
44948 
44949 	duk_memzero(&fb, sizeof(fb));
44950 	fb.buffer = (duk_uint8_t *) str;
44951 	fb.length = size;
44952 	fb.offset = 0;
44953 	fb.truncated = 0;
44954 
44955 	while (p < p_end) {
44956 		char ch = *p++;
44957 		const char *p_begfmt = NULL;
44958 		duk_bool_t got_exclamation = 0;
44959 		duk_bool_t got_long = 0;  /* %lf, %ld etc */
44960 		duk__dprint_state st;
44961 
44962 		if (ch != DUK_ASC_PERCENT) {
44963 			duk_fb_put_byte(&fb, (duk_uint8_t) ch);
44964 			continue;
44965 		}
44966 
44967 		/*
44968 		 *  Format tag parsing.  Since we don't understand all the
44969 		 *  possible format tags allowed, we just scan for a terminating
44970 		 *  specifier and keep track of relevant modifiers that we do
44971 		 *  understand.  See man 3 printf.
44972 		 */
44973 
44974 		duk_memzero(&st, sizeof(st));
44975 		st.fb = &fb;
44976 		st.depth = 0;
44977 		st.depth_limit = 1;
44978 		st.loop_stack_index = 0;
44979 		st.loop_stack_limit = DUK__LOOP_STACK_DEPTH;
44980 
44981 		p_begfmt = p - 1;
44982 		while (p < p_end) {
44983 			ch = *p++;
44984 
44985 			if (ch == DUK_ASC_STAR) {
44986 				/* unsupported: would consume multiple args */
44987 				goto format_error;
44988 			} else if (ch == DUK_ASC_PERCENT) {
44989 				duk_fb_put_byte(&fb, (duk_uint8_t) DUK_ASC_PERCENT);
44990 				break;
44991 			} else if (ch == DUK_ASC_EXCLAMATION) {
44992 				got_exclamation = 1;
44993 			} else if (!got_exclamation && ch == DUK_ASC_LC_L) {
44994 				got_long = 1;
44995 			} else if (got_exclamation && ch == DUK_ASC_LC_D) {
44996 				st.depth_limit = DUK__DEEP_DEPTH_LIMIT;
44997 			} else if (got_exclamation && ch == DUK_ASC_LC_P) {
44998 				st.follow_proto = 1;
44999 			} else if (got_exclamation && ch == DUK_ASC_LC_I) {
45000 				st.internal = 1;
45001 			} else if (got_exclamation && ch == DUK_ASC_LC_X) {
45002 				st.hexdump = 1;
45003 			} else if (got_exclamation && ch == DUK_ASC_LC_H) {
45004 				st.heavy = 1;
45005 			} else if (got_exclamation && ch == DUK_ASC_ATSIGN) {
45006 				st.pointer = 1;
45007 			} else if (got_exclamation && ch == DUK_ASC_HASH) {
45008 				st.binary = 1;
45009 			} else if (got_exclamation && ch == DUK_ASC_UC_T) {
45010 				duk_tval *t = va_arg(ap, duk_tval *);
45011 				if (st.pointer && !st.heavy) {
45012 					duk_fb_sprintf(&fb, "(%p)", (void *) t);
45013 				}
45014 				duk__print_tval(&st, t);
45015 				break;
45016 			} else if (got_exclamation && ch == DUK_ASC_UC_O) {
45017 				duk_heaphdr *t = va_arg(ap, duk_heaphdr *);
45018 				if (st.pointer && !st.heavy) {
45019 					duk_fb_sprintf(&fb, "(%p)", (void *) t);
45020 				}
45021 				duk__print_heaphdr(&st, t);
45022 				break;
45023 			} else if (got_exclamation && ch == DUK_ASC_UC_I) {
45024 				duk_instr_t t = va_arg(ap, duk_instr_t);
45025 				duk__print_instr(&st, t);
45026 				break;
45027 			} else if (got_exclamation && ch == DUK_ASC_UC_X) {
45028 				long t = va_arg(ap, long);
45029 				duk__print_opcode(&st, (duk_small_int_t) t);
45030 				break;
45031 			} else if (got_exclamation && ch == DUK_ASC_UC_C) {
45032 				duk_catcher *t = va_arg(ap, duk_catcher *);
45033 				duk__print_catcher(&st, t);
45034 				break;
45035 			} else if (got_exclamation && ch == DUK_ASC_UC_A) {
45036 				duk_activation *t = va_arg(ap, duk_activation *);
45037 				duk__print_activation(&st, t);
45038 				break;
45039 			} else if (!got_exclamation && strchr(DUK__ALLOWED_STANDARD_SPECIFIERS, (int) ch)) {
45040 				char fmtbuf[DUK__MAX_FORMAT_TAG_LENGTH];
45041 				duk_size_t fmtlen;
45042 
45043 				DUK_ASSERT(p >= p_begfmt);
45044 				fmtlen = (duk_size_t) (p - p_begfmt);
45045 				if (fmtlen >= sizeof(fmtbuf)) {
45046 					/* format is too large, abort */
45047 					goto format_error;
45048 				}
45049 				duk_memzero(fmtbuf, sizeof(fmtbuf));
45050 				duk_memcpy(fmtbuf, p_begfmt, fmtlen);
45051 
45052 				/* assume exactly 1 arg, which is why '*' is forbidden; arg size still
45053 				 * depends on type though.
45054 				 */
45055 
45056 				if (ch == DUK_ASC_LC_F || ch == DUK_ASC_LC_G || ch == DUK_ASC_LC_E) {
45057 					/* %f and %lf both consume a 'long' */
45058 					double arg = va_arg(ap, double);
45059 					duk_fb_sprintf(&fb, fmtbuf, arg);
45060 				} else if (ch == DUK_ASC_LC_D && got_long) {
45061 					/* %ld */
45062 					long arg = va_arg(ap, long);
45063 					duk_fb_sprintf(&fb, fmtbuf, arg);
45064 				} else if (ch == DUK_ASC_LC_D) {
45065 					/* %d; only 16 bits are guaranteed */
45066 					int arg = va_arg(ap, int);
45067 					duk_fb_sprintf(&fb, fmtbuf, arg);
45068 				} else if (ch == DUK_ASC_LC_U && got_long) {
45069 					/* %lu */
45070 					unsigned long arg = va_arg(ap, unsigned long);
45071 					duk_fb_sprintf(&fb, fmtbuf, arg);
45072 				} else if (ch == DUK_ASC_LC_U) {
45073 					/* %u; only 16 bits are guaranteed */
45074 					unsigned int arg = va_arg(ap, unsigned int);
45075 					duk_fb_sprintf(&fb, fmtbuf, arg);
45076 				} else if (ch == DUK_ASC_LC_X && got_long) {
45077 					/* %lx */
45078 					unsigned long arg = va_arg(ap, unsigned long);
45079 					duk_fb_sprintf(&fb, fmtbuf, arg);
45080 				} else if (ch == DUK_ASC_LC_X) {
45081 					/* %x; only 16 bits are guaranteed */
45082 					unsigned int arg = va_arg(ap, unsigned int);
45083 					duk_fb_sprintf(&fb, fmtbuf, arg);
45084 				} else if (ch == DUK_ASC_LC_S) {
45085 					/* %s */
45086 					const char *arg = va_arg(ap, const char *);
45087 					if (arg == NULL) {
45088 						/* '%s' and NULL is not portable, so special case
45089 						 * it for debug printing.
45090 						 */
45091 						duk_fb_sprintf(&fb, "NULL");
45092 					} else {
45093 						duk_fb_sprintf(&fb, fmtbuf, arg);
45094 					}
45095 				} else if (ch == DUK_ASC_LC_P) {
45096 					/* %p */
45097 					void *arg = va_arg(ap, void *);
45098 					if (arg == NULL) {
45099 						/* '%p' and NULL is portable, but special case it
45100 						 * anyway to get a standard NULL marker in logs.
45101 						 */
45102 						duk_fb_sprintf(&fb, "NULL");
45103 					} else {
45104 						duk_fb_sprintf(&fb, fmtbuf, arg);
45105 					}
45106 				} else if (ch == DUK_ASC_LC_C) {
45107 					/* '%c', passed concretely as int */
45108 					int arg = va_arg(ap, int);
45109 					duk_fb_sprintf(&fb, fmtbuf, arg);
45110 				} else {
45111 					/* Should not happen. */
45112 					duk_fb_sprintf(&fb, "INVALID-FORMAT(%s)", (const char *) fmtbuf);
45113 				}
45114 				break;
45115 			} else {
45116 				/* ignore */
45117 			}
45118 		}
45119 	}
45120 	goto done;
45121 
45122  format_error:
45123 	duk_fb_put_cstring(&fb, "FMTERR");
45124 	/* fall through */
45125 
45126  done:
45127 	retval = (duk_int_t) fb.offset;
45128 	duk_fb_put_byte(&fb, (duk_uint8_t) 0);
45129 
45130 	/* return total chars written excluding terminator */
45131 	return retval;
45132 }
45133 
45134 #if 0  /*unused*/
45135 DUK_INTERNAL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...) {
45136 	duk_int_t retval;
45137 	va_list ap;
45138 	va_start(ap, format);
45139 	retval = duk_debug_vsnprintf(str, size, format, ap);
45140 	va_end(ap);
45141 	return retval;
45142 }
45143 #endif
45144 
45145 /* Formatting function pointers is tricky: there is no standard pointer for
45146  * function pointers and the size of a function pointer may depend on the
45147  * specific pointer type.  This helper formats a function pointer based on
45148  * its memory layout to get something useful on most platforms.
45149  */
45150 DUK_INTERNAL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size) {
45151 	duk_size_t i;
45152 	duk_uint8_t *p = (duk_uint8_t *) buf;
45153 	duk_uint8_t *p_end = (duk_uint8_t *) (buf + buf_size - 1);
45154 
45155 	DUK_ASSERT(buf != NULL);
45156 	duk_memzero(buf, buf_size);
45157 
45158 	for (i = 0; i < fptr_size; i++) {
45159 		duk_int_t left = (duk_int_t) (p_end - p);
45160 		duk_uint8_t ch;
45161 		if (left <= 0) {
45162 			break;
45163 		}
45164 
45165 		/* Quite approximate but should be useful for little and big endian. */
45166 #if defined(DUK_USE_INTEGER_BE)
45167 		ch = fptr[i];
45168 #else
45169 		ch = fptr[fptr_size - 1 - i];
45170 #endif
45171 		p += DUK_SNPRINTF((char *) p, (duk_size_t) left, "%02lx", (unsigned long) ch);
45172 	}
45173 }
45174 
45175 #endif  /* DUK_USE_DEBUG */
45176 
45177 /* automatic undefs */
45178 #undef DUK__ALLOWED_STANDARD_SPECIFIERS
45179 #undef DUK__COMMA
45180 #undef DUK__DEEP_DEPTH_LIMIT
45181 #undef DUK__LOOP_STACK_DEPTH
45182 #undef DUK__MAX_FORMAT_TAG_LENGTH
45183 #line 1 "duk_debugger.c"
45184 /*
45185  *  Duktape debugger
45186  */
45187 
45188 /* #include duk_internal.h -> already included */
45189 
45190 #if defined(DUK_USE_DEBUGGER_SUPPORT)
45191 
45192 /*
45193  *  Assert helpers
45194  */
45195 
45196 #if defined(DUK_USE_ASSERTIONS)
45197 #define DUK__DBG_TPORT_ENTER() do { \
45198 		DUK_ASSERT(heap->dbg_calling_transport == 0); \
45199 		heap->dbg_calling_transport = 1; \
45200 	} while (0)
45201 #define DUK__DBG_TPORT_EXIT() do { \
45202 		DUK_ASSERT(heap->dbg_calling_transport == 1); \
45203 		heap->dbg_calling_transport = 0; \
45204 	} while (0)
45205 #else
45206 #define DUK__DBG_TPORT_ENTER() do {} while (0)
45207 #define DUK__DBG_TPORT_EXIT() do {} while (0)
45208 #endif
45209 
45210 /*
45211  *  Helper structs
45212  */
45213 
45214 typedef union {
45215 	void *p;
45216 	duk_uint_t b[1];
45217 	/* Use b[] to access the size of the union, which is strictly not
45218 	 * correct.  Can't use fixed size unless there's feature detection
45219 	 * for pointer byte size.
45220 	 */
45221 } duk__ptr_union;
45222 
45223 /*
45224  *  Detach handling
45225  */
45226 
45227 #define DUK__SET_CONN_BROKEN(thr,reason) do { \
45228 		/* For now shared handler is fine. */ \
45229 		duk__debug_do_detach1((thr)->heap, (reason)); \
45230 	} while (0)
45231 
45232 DUK_LOCAL void duk__debug_do_detach1(duk_heap *heap, duk_int_t reason) {
45233 	/* Can be called multiple times with no harm.  Mark the transport
45234 	 * bad (dbg_read_cb == NULL) and clear state except for the detached
45235 	 * callback and the udata field.  The detached callback is delayed
45236 	 * to the message loop so that it can be called between messages;
45237 	 * this avoids corner cases related to immediate debugger reattach
45238 	 * inside the detached callback.
45239 	 */
45240 
45241 	if (heap->dbg_detaching) {
45242 		DUK_D(DUK_DPRINT("debugger already detaching, ignore detach1"));
45243 		return;
45244 	}
45245 
45246 	DUK_D(DUK_DPRINT("debugger transport detaching, marking transport broken"));
45247 
45248 	heap->dbg_detaching = 1;  /* prevent multiple in-progress detaches */
45249 
45250 	if (heap->dbg_write_cb != NULL) {
45251 		duk_hthread *thr;
45252 
45253 		thr = heap->heap_thread;
45254 		DUK_ASSERT(thr != NULL);
45255 
45256 		duk_debug_write_notify(thr, DUK_DBG_CMD_DETACHING);
45257 		duk_debug_write_int(thr, reason);
45258 		duk_debug_write_eom(thr);
45259 	}
45260 
45261 	heap->dbg_read_cb = NULL;
45262 	heap->dbg_write_cb = NULL;
45263 	heap->dbg_peek_cb = NULL;
45264 	heap->dbg_read_flush_cb = NULL;
45265 	heap->dbg_write_flush_cb = NULL;
45266 	heap->dbg_request_cb = NULL;
45267 	/* heap->dbg_detached_cb: keep */
45268 	/* heap->dbg_udata: keep */
45269 	/* heap->dbg_processing: keep on purpose to avoid debugger re-entry in detaching state */
45270 	heap->dbg_state_dirty = 0;
45271 	heap->dbg_force_restart = 0;
45272 	heap->dbg_pause_flags = 0;
45273 	heap->dbg_pause_act = NULL;
45274 	heap->dbg_pause_startline = 0;
45275 	heap->dbg_have_next_byte = 0;
45276 	duk_debug_clear_paused(heap);  /* XXX: some overlap with field inits above */
45277 	heap->dbg_state_dirty = 0;     /* XXX: clear_paused sets dirty; rework? */
45278 
45279 	/* Ensure there are no stale active breakpoint pointers.
45280 	 * Breakpoint list is currently kept - we could empty it
45281 	 * here but we'd need to handle refcounts correctly, and
45282 	 * we'd need a 'thr' reference for that.
45283 	 *
45284 	 * XXX: clear breakpoint on either attach or detach?
45285 	 */
45286 	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
45287 }
45288 
45289 DUK_LOCAL void duk__debug_do_detach2(duk_heap *heap) {
45290 	duk_debug_detached_function detached_cb;
45291 	void *detached_udata;
45292 	duk_hthread *thr;
45293 
45294 	thr = heap->heap_thread;
45295 	if (thr == NULL) {
45296 		DUK_ASSERT(heap->dbg_detached_cb == NULL);
45297 		return;
45298 	}
45299 
45300 	/* Safe to call multiple times. */
45301 
45302 	detached_cb = heap->dbg_detached_cb;
45303 	detached_udata = heap->dbg_udata;
45304 	heap->dbg_detached_cb = NULL;
45305 	heap->dbg_udata = NULL;
45306 
45307 	if (detached_cb) {
45308 		/* Careful here: state must be wiped before the call
45309 		 * so that we can cleanly handle a re-attach from
45310 		 * inside the callback.
45311 		 */
45312 		DUK_D(DUK_DPRINT("detached during message loop, delayed call to detached_cb"));
45313 		detached_cb(thr, detached_udata);
45314 	}
45315 
45316 	heap->dbg_detaching = 0;
45317 }
45318 
45319 DUK_INTERNAL void duk_debug_do_detach(duk_heap *heap) {
45320 	duk__debug_do_detach1(heap, 0);
45321 	duk__debug_do_detach2(heap);
45322 }
45323 
45324 /* Called on a read/write error: NULL all callbacks except the detached
45325  * callback so that we never accidentally call them after a read/write
45326  * error has been indicated.  This is especially important for the transport
45327  * I/O callbacks to fulfill guaranteed callback semantics.
45328  */
45329 DUK_LOCAL void duk__debug_null_most_callbacks(duk_hthread *thr) {
45330 	duk_heap *heap;
45331 
45332 	DUK_ASSERT(thr != NULL);
45333 
45334 	heap = thr->heap;
45335 	DUK_D(DUK_DPRINT("transport read/write error, NULL all callbacks expected detached"));
45336 	heap->dbg_read_cb = NULL;
45337 	heap->dbg_write_cb = NULL;  /* this is especially critical to avoid another write call in detach1() */
45338 	heap->dbg_peek_cb = NULL;
45339 	heap->dbg_read_flush_cb = NULL;
45340 	heap->dbg_write_flush_cb = NULL;
45341 	heap->dbg_request_cb = NULL;
45342 	/* keep heap->dbg_detached_cb */
45343 }
45344 
45345 /*
45346  *  Pause handling
45347  */
45348 
45349 DUK_LOCAL void duk__debug_set_pause_state(duk_hthread *thr, duk_heap *heap, duk_small_uint_t pause_flags) {
45350 	duk_uint_fast32_t line;
45351 
45352 	line = duk_debug_curr_line(thr);
45353 	if (line == 0) {
45354 		/* No line info for current function. */
45355 		duk_small_uint_t updated_flags;
45356 
45357 		updated_flags = pause_flags & ~(DUK_PAUSE_FLAG_LINE_CHANGE);
45358 		DUK_D(DUK_DPRINT("no line info for current activation, disable line-based pause flags: 0x%08lx -> 0x%08lx",
45359 		                 (long) pause_flags, (long) updated_flags));
45360 		pause_flags = updated_flags;
45361 	}
45362 
45363 	heap->dbg_pause_flags = pause_flags;
45364 	heap->dbg_pause_act = thr->callstack_curr;
45365 	heap->dbg_pause_startline = (duk_uint32_t) line;
45366 	heap->dbg_state_dirty = 1;
45367 
45368 	DUK_D(DUK_DPRINT("set state for automatic pause triggers, flags=0x%08lx, act=%p, startline=%ld",
45369 	                 (long) heap->dbg_pause_flags, (void *) heap->dbg_pause_act,
45370 	                 (long) heap->dbg_pause_startline));
45371 }
45372 
45373 /*
45374  *  Debug connection peek and flush primitives
45375  */
45376 
45377 DUK_INTERNAL duk_bool_t duk_debug_read_peek(duk_hthread *thr) {
45378 	duk_heap *heap;
45379 	duk_bool_t ret;
45380 
45381 	DUK_ASSERT(thr != NULL);
45382 	heap = thr->heap;
45383 	DUK_ASSERT(heap != NULL);
45384 
45385 	if (heap->dbg_read_cb == NULL) {
45386 		DUK_D(DUK_DPRINT("attempt to peek in detached state, return zero (= no data)"));
45387 		return 0;
45388 	}
45389 	if (heap->dbg_peek_cb == NULL) {
45390 		DUK_DD(DUK_DDPRINT("no peek callback, return zero (= no data)"));
45391 		return 0;
45392 	}
45393 
45394 	DUK__DBG_TPORT_ENTER();
45395 	ret = (duk_bool_t) (heap->dbg_peek_cb(heap->dbg_udata) > 0);
45396 	DUK__DBG_TPORT_EXIT();
45397 	return ret;
45398 }
45399 
45400 DUK_INTERNAL void duk_debug_read_flush(duk_hthread *thr) {
45401 	duk_heap *heap;
45402 
45403 	DUK_ASSERT(thr != NULL);
45404 	heap = thr->heap;
45405 	DUK_ASSERT(heap != NULL);
45406 
45407 	if (heap->dbg_read_cb == NULL) {
45408 		DUK_D(DUK_DPRINT("attempt to read flush in detached state, ignore"));
45409 		return;
45410 	}
45411 	if (heap->dbg_read_flush_cb == NULL) {
45412 		DUK_DD(DUK_DDPRINT("no read flush callback, ignore"));
45413 		return;
45414 	}
45415 
45416 	DUK__DBG_TPORT_ENTER();
45417 	heap->dbg_read_flush_cb(heap->dbg_udata);
45418 	DUK__DBG_TPORT_EXIT();
45419 }
45420 
45421 DUK_INTERNAL void duk_debug_write_flush(duk_hthread *thr) {
45422 	duk_heap *heap;
45423 
45424 	DUK_ASSERT(thr != NULL);
45425 	heap = thr->heap;
45426 	DUK_ASSERT(heap != NULL);
45427 
45428 	if (heap->dbg_read_cb == NULL) {
45429 		DUK_D(DUK_DPRINT("attempt to write flush in detached state, ignore"));
45430 		return;
45431 	}
45432 	if (heap->dbg_write_flush_cb == NULL) {
45433 		DUK_DD(DUK_DDPRINT("no write flush callback, ignore"));
45434 		return;
45435 	}
45436 
45437 	DUK__DBG_TPORT_ENTER();
45438 	heap->dbg_write_flush_cb(heap->dbg_udata);
45439 	DUK__DBG_TPORT_EXIT();
45440 }
45441 
45442 /*
45443  *  Debug connection skip primitives
45444  */
45445 
45446 /* Skip fully. */
45447 DUK_INTERNAL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length) {
45448 	duk_uint8_t dummy[64];
45449 	duk_size_t now;
45450 
45451 	DUK_ASSERT(thr != NULL);
45452 
45453 	while (length > 0) {
45454 		now = (length > sizeof(dummy) ? sizeof(dummy) : length);
45455 		duk_debug_read_bytes(thr, dummy, now);
45456 		length -= now;
45457 	}
45458 }
45459 
45460 DUK_INTERNAL void duk_debug_skip_byte(duk_hthread *thr) {
45461 	DUK_ASSERT(thr != NULL);
45462 
45463 	(void) duk_debug_read_byte(thr);
45464 }
45465 
45466 /*
45467  *  Debug connection read primitives
45468  */
45469 
45470 /* Peek ahead in the stream one byte. */
45471 DUK_INTERNAL uint8_t duk_debug_peek_byte(duk_hthread *thr) {
45472 	/* It is important not to call this if the last byte read was an EOM.
45473 	 * Reading ahead in this scenario would cause unnecessary blocking if
45474 	 * another message is not available.
45475 	 */
45476 
45477 	duk_uint8_t x;
45478 
45479 	x = duk_debug_read_byte(thr);
45480 	thr->heap->dbg_have_next_byte = 1;
45481 	thr->heap->dbg_next_byte = x;
45482 	return x;
45483 }
45484 
45485 /* Read fully. */
45486 DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length) {
45487 	duk_heap *heap;
45488 	duk_uint8_t *p;
45489 	duk_size_t left;
45490 	duk_size_t got;
45491 
45492 	DUK_ASSERT(thr != NULL);
45493 	heap = thr->heap;
45494 	DUK_ASSERT(heap != NULL);
45495 	DUK_ASSERT(data != NULL);
45496 
45497 	if (heap->dbg_read_cb == NULL) {
45498 		DUK_D(DUK_DPRINT("attempt to read %ld bytes in detached state, return zero data", (long) length));
45499 		goto fail;
45500 	}
45501 
45502 	/* NOTE: length may be zero */
45503 	p = data;
45504 	if (length >= 1 && heap->dbg_have_next_byte) {
45505 		heap->dbg_have_next_byte = 0;
45506 		*p++ = heap->dbg_next_byte;
45507 	}
45508 	for (;;) {
45509 		left = (duk_size_t) ((data + length) - p);
45510 		if (left == 0) {
45511 			break;
45512 		}
45513 		DUK_ASSERT(heap->dbg_read_cb != NULL);
45514 		DUK_ASSERT(left >= 1);
45515 #if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
45516 		left = 1;
45517 #endif
45518 		DUK__DBG_TPORT_ENTER();
45519 		got = heap->dbg_read_cb(heap->dbg_udata, (char *) p, left);
45520 		DUK__DBG_TPORT_EXIT();
45521 
45522 		if (got == 0 || got > left) {
45523 			DUK_D(DUK_DPRINT("connection error during read, return zero data"));
45524 			duk__debug_null_most_callbacks(thr);  /* avoid calling write callback in detach1() */
45525 			DUK__SET_CONN_BROKEN(thr, 1);
45526 			goto fail;
45527 		}
45528 		p += got;
45529 	}
45530 	return;
45531 
45532  fail:
45533 	duk_memzero((void *) data, (size_t) length);
45534 }
45535 
45536 DUK_INTERNAL duk_uint8_t duk_debug_read_byte(duk_hthread *thr) {
45537 	duk_uint8_t x;
45538 
45539 	x = 0;  /* just in case callback is broken and won't write 'x' */
45540 	duk_debug_read_bytes(thr, &x, 1);
45541 	return x;
45542 }
45543 
45544 DUK_LOCAL duk_uint32_t duk__debug_read_uint32_raw(duk_hthread *thr) {
45545 	duk_uint8_t buf[4];
45546 
45547 	DUK_ASSERT(thr != NULL);
45548 
45549 	duk_debug_read_bytes(thr, buf, 4);
45550 	return ((duk_uint32_t) buf[0] << 24) |
45551 	       ((duk_uint32_t) buf[1] << 16) |
45552 	       ((duk_uint32_t) buf[2] << 8) |
45553 	       (duk_uint32_t) buf[3];
45554 }
45555 
45556 DUK_LOCAL duk_int32_t duk__debug_read_int32_raw(duk_hthread *thr) {
45557 	return (duk_int32_t) duk__debug_read_uint32_raw(thr);
45558 }
45559 
45560 DUK_LOCAL duk_uint16_t duk__debug_read_uint16_raw(duk_hthread *thr) {
45561 	duk_uint8_t buf[2];
45562 
45563 	DUK_ASSERT(thr != NULL);
45564 
45565 	duk_debug_read_bytes(thr, buf, 2);
45566 	return ((duk_uint16_t) buf[0] << 8) |
45567 	       (duk_uint16_t) buf[1];
45568 }
45569 
45570 DUK_INTERNAL duk_int32_t duk_debug_read_int(duk_hthread *thr) {
45571 	duk_small_uint_t x;
45572 	duk_small_uint_t t;
45573 
45574 	DUK_ASSERT(thr != NULL);
45575 
45576 	x = duk_debug_read_byte(thr);
45577 	if (x >= 0xc0) {
45578 		t = duk_debug_read_byte(thr);
45579 		return (duk_int32_t) (((x - 0xc0) << 8) + t);
45580 	} else if (x >= 0x80) {
45581 		return (duk_int32_t) (x - 0x80);
45582 	} else if (x == DUK_DBG_IB_INT4) {
45583 		return (duk_int32_t) duk__debug_read_uint32_raw(thr);
45584 	}
45585 
45586 	DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
45587 	DUK__SET_CONN_BROKEN(thr, 1);
45588 	return 0;
45589 }
45590 
45591 DUK_LOCAL duk_hstring *duk__debug_read_hstring_raw(duk_hthread *thr, duk_uint32_t len) {
45592 	duk_uint8_t buf[31];
45593 	duk_uint8_t *p;
45594 
45595 	if (len <= sizeof(buf)) {
45596 		duk_debug_read_bytes(thr, buf, (duk_size_t) len);
45597 		duk_push_lstring(thr, (const char *) buf, (duk_size_t) len);
45598 	} else {
45599 		p = (duk_uint8_t *) duk_push_fixed_buffer(thr, (duk_size_t) len);  /* zero for paranoia */
45600 		DUK_ASSERT(p != NULL);
45601 		duk_debug_read_bytes(thr, p, (duk_size_t) len);
45602 		(void) duk_buffer_to_string(thr, -1);  /* Safety relies on debug client, which is OK. */
45603 	}
45604 
45605 	return duk_require_hstring(thr, -1);
45606 }
45607 
45608 DUK_INTERNAL duk_hstring *duk_debug_read_hstring(duk_hthread *thr) {
45609 	duk_small_uint_t x;
45610 	duk_uint32_t len;
45611 
45612 	DUK_ASSERT(thr != NULL);
45613 
45614 	x = duk_debug_read_byte(thr);
45615 	if (x >= 0x60 && x <= 0x7f) {
45616 		/* For short strings, use a fixed temp buffer. */
45617 		len = (duk_uint32_t) (x - 0x60);
45618 	} else if (x == DUK_DBG_IB_STR2) {
45619 		len = (duk_uint32_t) duk__debug_read_uint16_raw(thr);
45620 	} else if (x == DUK_DBG_IB_STR4) {
45621 		len = (duk_uint32_t) duk__debug_read_uint32_raw(thr);
45622 	} else {
45623 		goto fail;
45624 	}
45625 
45626 	return duk__debug_read_hstring_raw(thr, len);
45627 
45628  fail:
45629 	DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
45630 	DUK__SET_CONN_BROKEN(thr, 1);
45631 	duk_push_hstring_empty(thr);  /* always push some string */
45632 	return duk_require_hstring(thr, -1);
45633 }
45634 
45635 DUK_LOCAL duk_hbuffer *duk__debug_read_hbuffer_raw(duk_hthread *thr, duk_uint32_t len) {
45636 	duk_uint8_t *p;
45637 
45638 	p = (duk_uint8_t *) duk_push_fixed_buffer(thr, (duk_size_t) len);  /* zero for paranoia */
45639 	DUK_ASSERT(p != NULL);
45640 	duk_debug_read_bytes(thr, p, (duk_size_t) len);
45641 
45642 	return duk_require_hbuffer(thr, -1);
45643 }
45644 
45645 DUK_LOCAL void *duk__debug_read_pointer_raw(duk_hthread *thr) {
45646 	duk_small_uint_t x;
45647 	duk__ptr_union pu;
45648 
45649 	DUK_ASSERT(thr != NULL);
45650 
45651 	x = duk_debug_read_byte(thr);
45652 	if (x != sizeof(pu)) {
45653 		goto fail;
45654 	}
45655 	duk_debug_read_bytes(thr, (duk_uint8_t *) &pu.p, sizeof(pu));
45656 #if defined(DUK_USE_INTEGER_LE)
45657 	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
45658 #endif
45659 	return (void *) pu.p;
45660 
45661  fail:
45662 	DUK_D(DUK_DPRINT("debug connection error: failed to decode pointer"));
45663 	DUK__SET_CONN_BROKEN(thr, 1);
45664 	return (void *) NULL;
45665 }
45666 
45667 DUK_LOCAL duk_double_t duk__debug_read_double_raw(duk_hthread *thr) {
45668 	duk_double_union du;
45669 
45670 	DUK_ASSERT(sizeof(du.uc) == 8);
45671 	duk_debug_read_bytes(thr, (duk_uint8_t *) du.uc, sizeof(du.uc));
45672 	DUK_DBLUNION_DOUBLE_NTOH(&du);
45673 	return du.d;
45674 }
45675 
45676 #if 0
45677 DUK_INTERNAL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr) {
45678 	duk_small_uint_t x;
45679 
45680 	DUK_ASSERT(thr != NULL);
45681 
45682 	x = duk_debug_read_byte(thr);
45683 	if (x != DUK_DBG_IB_HEAPPTR) {
45684 		goto fail;
45685 	}
45686 
45687 	return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
45688 
45689  fail:
45690 	DUK_D(DUK_DPRINT("debug connection error: failed to decode heapptr"));
45691 	DUK__SET_CONN_BROKEN(thr, 1);
45692 	return NULL;
45693 }
45694 #endif
45695 
45696 DUK_INTERNAL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr) {
45697 	duk_small_uint_t x;
45698 
45699 	DUK_ASSERT(thr != NULL);
45700 
45701 	x = duk_debug_read_byte(thr);
45702 	switch (x) {
45703 	case DUK_DBG_IB_OBJECT:
45704 	case DUK_DBG_IB_POINTER:
45705 	case DUK_DBG_IB_HEAPPTR:
45706 		/* Accept any pointer-like value; for 'object' dvalue, read
45707 		 * and ignore the class number.
45708 		 */
45709 		if (x == DUK_DBG_IB_OBJECT) {
45710 			duk_debug_skip_byte(thr);
45711 		}
45712 		break;
45713 	default:
45714 		goto fail;
45715 	}
45716 
45717 	return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
45718 
45719  fail:
45720 	DUK_D(DUK_DPRINT("debug connection error: failed to decode any pointer (object, pointer, heapptr)"));
45721 	DUK__SET_CONN_BROKEN(thr, 1);
45722 	return NULL;
45723 }
45724 
45725 DUK_INTERNAL duk_tval *duk_debug_read_tval(duk_hthread *thr) {
45726 	duk_uint8_t x;
45727 	duk_uint_t t;
45728 	duk_uint32_t len;
45729 
45730 	DUK_ASSERT(thr != NULL);
45731 
45732 	x = duk_debug_read_byte(thr);
45733 
45734 	if (x >= 0xc0) {
45735 		t = (duk_uint_t) (x - 0xc0);
45736 		t = (t << 8) + duk_debug_read_byte(thr);
45737 		duk_push_uint(thr, (duk_uint_t) t);
45738 		goto return_ptr;
45739 	}
45740 	if (x >= 0x80) {
45741 		duk_push_uint(thr, (duk_uint_t) (x - 0x80));
45742 		goto return_ptr;
45743 	}
45744 	if (x >= 0x60) {
45745 		len = (duk_uint32_t) (x - 0x60);
45746 		duk__debug_read_hstring_raw(thr, len);
45747 		goto return_ptr;
45748 	}
45749 
45750 	switch (x) {
45751 	case DUK_DBG_IB_INT4: {
45752 		duk_int32_t i = duk__debug_read_int32_raw(thr);
45753 		duk_push_i32(thr, i);
45754 		break;
45755 	}
45756 	case DUK_DBG_IB_STR4: {
45757 		len = duk__debug_read_uint32_raw(thr);
45758 		duk__debug_read_hstring_raw(thr, len);
45759 		break;
45760 	}
45761 	case DUK_DBG_IB_STR2: {
45762 		len = duk__debug_read_uint16_raw(thr);
45763 		duk__debug_read_hstring_raw(thr, len);
45764 		break;
45765 	}
45766 	case DUK_DBG_IB_BUF4: {
45767 		len = duk__debug_read_uint32_raw(thr);
45768 		duk__debug_read_hbuffer_raw(thr, len);
45769 		break;
45770 	}
45771 	case DUK_DBG_IB_BUF2: {
45772 		len = duk__debug_read_uint16_raw(thr);
45773 		duk__debug_read_hbuffer_raw(thr, len);
45774 		break;
45775 	}
45776 	case DUK_DBG_IB_UNDEFINED: {
45777 		duk_push_undefined(thr);
45778 		break;
45779 	}
45780 	case DUK_DBG_IB_NULL: {
45781 		duk_push_null(thr);
45782 		break;
45783 	}
45784 	case DUK_DBG_IB_TRUE: {
45785 		duk_push_true(thr);
45786 		break;
45787 	}
45788 	case DUK_DBG_IB_FALSE: {
45789 		duk_push_false(thr);
45790 		break;
45791 	}
45792 	case DUK_DBG_IB_NUMBER: {
45793 		duk_double_t d;
45794 		d = duk__debug_read_double_raw(thr);
45795 		duk_push_number(thr, d);
45796 		break;
45797 	}
45798 	case DUK_DBG_IB_OBJECT: {
45799 		duk_heaphdr *h;
45800 		duk_debug_skip_byte(thr);
45801 		h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
45802 		duk_push_heapptr(thr, (void *) h);
45803 		break;
45804 	}
45805 	case DUK_DBG_IB_POINTER: {
45806 		void *ptr;
45807 		ptr = duk__debug_read_pointer_raw(thr);
45808 		duk_push_pointer(thr, ptr);
45809 		break;
45810 	}
45811 	case DUK_DBG_IB_LIGHTFUNC: {
45812 		/* XXX: Not needed for now, so not implemented.  Note that
45813 		 * function pointers may have different size/layout than
45814 		 * a void pointer.
45815 		 */
45816 		DUK_D(DUK_DPRINT("reading lightfunc values unimplemented"));
45817 		goto fail;
45818 	}
45819 	case DUK_DBG_IB_HEAPPTR: {
45820 		duk_heaphdr *h;
45821 		h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
45822 		duk_push_heapptr(thr, (void *) h);
45823 		break;
45824 	}
45825 	case DUK_DBG_IB_UNUSED:  /* unused: not accepted in inbound messages */
45826 	default:
45827 		goto fail;
45828 	}
45829 
45830  return_ptr:
45831 	return DUK_GET_TVAL_NEGIDX(thr, -1);
45832 
45833  fail:
45834 	DUK_D(DUK_DPRINT("debug connection error: failed to decode tval"));
45835 	DUK__SET_CONN_BROKEN(thr, 1);
45836 	return NULL;
45837 }
45838 
45839 /*
45840  *  Debug connection write primitives
45841  */
45842 
45843 /* Write fully. */
45844 DUK_INTERNAL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length) {
45845 	duk_heap *heap;
45846 	const duk_uint8_t *p;
45847 	duk_size_t left;
45848 	duk_size_t got;
45849 
45850 	DUK_ASSERT(thr != NULL);
45851 	DUK_ASSERT(length == 0 || data != NULL);
45852 	heap = thr->heap;
45853 	DUK_ASSERT(heap != NULL);
45854 
45855 	if (heap->dbg_write_cb == NULL) {
45856 		DUK_D(DUK_DPRINT("attempt to write %ld bytes in detached state, ignore", (long) length));
45857 		return;
45858 	}
45859 	if (length == 0) {
45860 		/* Avoid doing an actual write callback with length == 0,
45861 		 * because that's reserved for a write flush.
45862 		 */
45863 		return;
45864 	}
45865 	DUK_ASSERT(data != NULL);
45866 
45867 	p = data;
45868 	for (;;) {
45869 		left = (duk_size_t) ((data + length) - p);
45870 		if (left == 0) {
45871 			break;
45872 		}
45873 		DUK_ASSERT(heap->dbg_write_cb != NULL);
45874 		DUK_ASSERT(left >= 1);
45875 #if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
45876 		left = 1;
45877 #endif
45878 		DUK__DBG_TPORT_ENTER();
45879 		got = heap->dbg_write_cb(heap->dbg_udata, (const char *) p, left);
45880 		DUK__DBG_TPORT_EXIT();
45881 
45882 		if (got == 0 || got > left) {
45883 			duk__debug_null_most_callbacks(thr);  /* avoid calling write callback in detach1() */
45884 			DUK_D(DUK_DPRINT("connection error during write"));
45885 			DUK__SET_CONN_BROKEN(thr, 1);
45886 			return;
45887 		}
45888 		p += got;
45889 	}
45890 }
45891 
45892 DUK_INTERNAL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x) {
45893 	duk_debug_write_bytes(thr, (const duk_uint8_t *) &x, 1);
45894 }
45895 
45896 DUK_INTERNAL void duk_debug_write_unused(duk_hthread *thr) {
45897 	duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
45898 }
45899 
45900 DUK_INTERNAL void duk_debug_write_undefined(duk_hthread *thr) {
45901 	duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
45902 }
45903 
45904 #if defined(DUK_USE_DEBUGGER_INSPECT)
45905 DUK_INTERNAL void duk_debug_write_null(duk_hthread *thr) {
45906 	duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
45907 }
45908 #endif
45909 
45910 DUK_INTERNAL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val) {
45911 	duk_debug_write_byte(thr, val ? DUK_DBG_IB_TRUE : DUK_DBG_IB_FALSE);
45912 }
45913 
45914 /* Write signed 32-bit integer. */
45915 DUK_INTERNAL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x) {
45916 	duk_uint8_t buf[5];
45917 	duk_size_t len;
45918 
45919 	DUK_ASSERT(thr != NULL);
45920 
45921 	if (x >= 0 && x <= 0x3fL) {
45922 		buf[0] = (duk_uint8_t) (0x80 + x);
45923 		len = 1;
45924 	} else if (x >= 0 && x <= 0x3fffL) {
45925 		buf[0] = (duk_uint8_t) (0xc0 + (x >> 8));
45926 		buf[1] = (duk_uint8_t) (x & 0xff);
45927 		len = 2;
45928 	} else {
45929 		/* Signed integers always map to 4 bytes now. */
45930 		buf[0] = (duk_uint8_t) DUK_DBG_IB_INT4;
45931 		buf[1] = (duk_uint8_t) ((x >> 24) & 0xff);
45932 		buf[2] = (duk_uint8_t) ((x >> 16) & 0xff);
45933 		buf[3] = (duk_uint8_t) ((x >> 8) & 0xff);
45934 		buf[4] = (duk_uint8_t) (x & 0xff);
45935 		len = 5;
45936 	}
45937 	duk_debug_write_bytes(thr, buf, len);
45938 }
45939 
45940 /* Write unsigned 32-bit integer. */
45941 DUK_INTERNAL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x) {
45942 	/* The debugger protocol doesn't support a plain integer encoding for
45943 	 * the full 32-bit unsigned range (only 32-bit signed).  For now,
45944 	 * unsigned 32-bit values simply written as signed ones.  This is not
45945 	 * a concrete issue except for 32-bit heaphdr fields.  Proper solutions
45946 	 * would be to (a) write such integers as IEEE doubles or (b) add an
45947 	 * unsigned 32-bit dvalue.
45948 	 */
45949 	if (x >= 0x80000000UL) {
45950 		DUK_D(DUK_DPRINT("writing unsigned integer 0x%08lx as signed integer",
45951 		                 (long) x));
45952 	}
45953 	duk_debug_write_int(thr, (duk_int32_t) x);
45954 }
45955 
45956 DUK_INTERNAL void duk_debug_write_strbuf(duk_hthread *thr, const char *data, duk_size_t length, duk_uint8_t marker_base) {
45957 	duk_uint8_t buf[5];
45958 	duk_size_t buflen;
45959 
45960 	DUK_ASSERT(thr != NULL);
45961 	DUK_ASSERT(length == 0 || data != NULL);
45962 
45963 	if (length <= 0x1fUL && marker_base == DUK_DBG_IB_STR4) {
45964 		/* For strings, special form for short lengths. */
45965 		buf[0] = (duk_uint8_t) (0x60 + length);
45966 		buflen = 1;
45967 	} else if (length <= 0xffffUL) {
45968 		buf[0] = (duk_uint8_t) (marker_base + 1);
45969 		buf[1] = (duk_uint8_t) (length >> 8);
45970 		buf[2] = (duk_uint8_t) (length & 0xff);
45971 		buflen = 3;
45972 	} else {
45973 		buf[0] = (duk_uint8_t) marker_base;
45974 		buf[1] = (duk_uint8_t) (length >> 24);
45975 		buf[2] = (duk_uint8_t) ((length >> 16) & 0xff);
45976 		buf[3] = (duk_uint8_t) ((length >> 8) & 0xff);
45977 		buf[4] = (duk_uint8_t) (length & 0xff);
45978 		buflen = 5;
45979 	}
45980 
45981 	duk_debug_write_bytes(thr, (const duk_uint8_t *) buf, buflen);
45982 	duk_debug_write_bytes(thr, (const duk_uint8_t *) data, length);
45983 }
45984 
45985 DUK_INTERNAL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length) {
45986 	duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_STR4);
45987 }
45988 
45989 DUK_INTERNAL void duk_debug_write_cstring(duk_hthread *thr, const char *data) {
45990 	DUK_ASSERT(thr != NULL);
45991 
45992 	duk_debug_write_string(thr,
45993 	                       data,
45994 	                       data ? DUK_STRLEN(data) : 0);
45995 }
45996 
45997 DUK_INTERNAL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h) {
45998 	DUK_ASSERT(thr != NULL);
45999 
46000 	/* XXX: differentiate null pointer from empty string? */
46001 	duk_debug_write_string(thr,
46002 	                       (h != NULL ? (const char *) DUK_HSTRING_GET_DATA(h) : NULL),
46003 	                       (h != NULL ? (duk_size_t) DUK_HSTRING_GET_BYTELEN(h) : 0));
46004 }
46005 
46006 DUK_LOCAL void duk__debug_write_hstring_safe_top(duk_hthread *thr) {
46007 	duk_debug_write_hstring(thr, duk_safe_to_hstring(thr, -1));
46008 }
46009 
46010 DUK_INTERNAL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length) {
46011 	duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_BUF4);
46012 }
46013 
46014 DUK_INTERNAL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h) {
46015 	DUK_ASSERT(thr != NULL);
46016 
46017 	duk_debug_write_buffer(thr,
46018 	                       (h != NULL ? (const char *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h) : NULL),
46019 	                       (h != NULL ? (duk_size_t) DUK_HBUFFER_GET_SIZE(h) : 0));
46020 }
46021 
46022 DUK_LOCAL void duk__debug_write_pointer_raw(duk_hthread *thr, void *ptr, duk_uint8_t ibyte) {
46023 	duk_uint8_t buf[2];
46024 	duk__ptr_union pu;
46025 
46026 	DUK_ASSERT(thr != NULL);
46027 	DUK_ASSERT(sizeof(ptr) >= 1 && sizeof(ptr) <= 16);
46028 	/* ptr may be NULL */
46029 
46030 	buf[0] = ibyte;
46031 	buf[1] = sizeof(pu);
46032 	duk_debug_write_bytes(thr, buf, 2);
46033 	pu.p = (void *) ptr;
46034 #if defined(DUK_USE_INTEGER_LE)
46035 	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
46036 #endif
46037 	duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
46038 }
46039 
46040 DUK_INTERNAL void duk_debug_write_pointer(duk_hthread *thr, void *ptr) {
46041 	duk__debug_write_pointer_raw(thr, ptr, DUK_DBG_IB_POINTER);
46042 }
46043 
46044 #if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
46045 DUK_INTERNAL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h) {
46046 	duk__debug_write_pointer_raw(thr, (void *) h, DUK_DBG_IB_HEAPPTR);
46047 }
46048 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP || DUK_USE_DEBUGGER_INSPECT */
46049 
46050 DUK_INTERNAL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj) {
46051 	duk_uint8_t buf[3];
46052 	duk__ptr_union pu;
46053 
46054 	DUK_ASSERT(thr != NULL);
46055 	DUK_ASSERT(sizeof(obj) >= 1 && sizeof(obj) <= 16);
46056 	DUK_ASSERT(obj != NULL);
46057 
46058 	buf[0] = DUK_DBG_IB_OBJECT;
46059 	buf[1] = (duk_uint8_t) DUK_HOBJECT_GET_CLASS_NUMBER(obj);
46060 	buf[2] = sizeof(pu);
46061 	duk_debug_write_bytes(thr, buf, 3);
46062 	pu.p = (void *) obj;
46063 #if defined(DUK_USE_INTEGER_LE)
46064 	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
46065 #endif
46066 	duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
46067 }
46068 
46069 DUK_INTERNAL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv) {
46070 	duk_c_function lf_func;
46071 	duk_small_uint_t lf_flags;
46072 	duk_uint8_t buf[4];
46073 	duk_double_union du1;
46074 	duk_double_union du2;
46075 	duk_int32_t i32;
46076 
46077 	DUK_ASSERT(thr != NULL);
46078 	DUK_ASSERT(tv != NULL);
46079 
46080 	switch (DUK_TVAL_GET_TAG(tv)) {
46081 	case DUK_TAG_UNDEFINED:
46082 		duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
46083 		break;
46084 	case DUK_TAG_UNUSED:
46085 		duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
46086 		break;
46087 	case DUK_TAG_NULL:
46088 		duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
46089 		break;
46090 	case DUK_TAG_BOOLEAN:
46091 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 ||
46092 		           DUK_TVAL_GET_BOOLEAN(tv) == 1);
46093 		duk_debug_write_boolean(thr, DUK_TVAL_GET_BOOLEAN(tv));
46094 		break;
46095 	case DUK_TAG_POINTER:
46096 		duk_debug_write_pointer(thr, (void *) DUK_TVAL_GET_POINTER(tv));
46097 		break;
46098 	case DUK_TAG_LIGHTFUNC:
46099 		DUK_TVAL_GET_LIGHTFUNC(tv, lf_func, lf_flags);
46100 		buf[0] = DUK_DBG_IB_LIGHTFUNC;
46101 		buf[1] = (duk_uint8_t) (lf_flags >> 8);
46102 		buf[2] = (duk_uint8_t) (lf_flags & 0xff);
46103 		buf[3] = sizeof(lf_func);
46104 		duk_debug_write_bytes(thr, buf, 4);
46105 		duk_debug_write_bytes(thr, (const duk_uint8_t *) &lf_func, sizeof(lf_func));
46106 		break;
46107 	case DUK_TAG_STRING:
46108 		duk_debug_write_hstring(thr, DUK_TVAL_GET_STRING(tv));
46109 		break;
46110 	case DUK_TAG_OBJECT:
46111 		duk_debug_write_hobject(thr, DUK_TVAL_GET_OBJECT(tv));
46112 		break;
46113 	case DUK_TAG_BUFFER:
46114 		duk_debug_write_hbuffer(thr, DUK_TVAL_GET_BUFFER(tv));
46115 		break;
46116 #if defined(DUK_USE_FASTINT)
46117 	case DUK_TAG_FASTINT:
46118 #endif
46119 	default:
46120 		/* Numbers are normalized to big (network) endian.  We can
46121 		 * (but are not required) to use integer dvalues when there's
46122 		 * no loss of precision.
46123 		 *
46124 		 * XXX: share check with other code; this check is slow but
46125 		 * reliable and doesn't require careful exponent/mantissa
46126 		 * mask tricks as in the fastint downgrade code.
46127 		 */
46128 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
46129 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
46130 		du1.d = DUK_TVAL_GET_NUMBER(tv);
46131 		i32 = (duk_int32_t) du1.d;
46132 		du2.d = (duk_double_t) i32;
46133 
46134 		DUK_DD(DUK_DDPRINT("i32=%ld du1=%02x%02x%02x%02x%02x%02x%02x%02x "
46135 		                   "du2=%02x%02x%02x%02x%02x%02x%02x%02x",
46136 		                   (long) i32,
46137 		                   (unsigned int) du1.uc[0], (unsigned int) du1.uc[1],
46138 		                   (unsigned int) du1.uc[2], (unsigned int) du1.uc[3],
46139 		                   (unsigned int) du1.uc[4], (unsigned int) du1.uc[5],
46140 		                   (unsigned int) du1.uc[6], (unsigned int) du1.uc[7],
46141 		                   (unsigned int) du2.uc[0], (unsigned int) du2.uc[1],
46142 		                   (unsigned int) du2.uc[2], (unsigned int) du2.uc[3],
46143 		                   (unsigned int) du2.uc[4], (unsigned int) du2.uc[5],
46144 		                   (unsigned int) du2.uc[6], (unsigned int) du2.uc[7]));
46145 
46146 		if (duk_memcmp((const void *) du1.uc, (const void *) du2.uc, sizeof(du1.uc)) == 0) {
46147 			duk_debug_write_int(thr, i32);
46148 		} else {
46149 			DUK_DBLUNION_DOUBLE_HTON(&du1);
46150 			duk_debug_write_byte(thr, DUK_DBG_IB_NUMBER);
46151 			duk_debug_write_bytes(thr, (const duk_uint8_t *) du1.uc, sizeof(du1.uc));
46152 		}
46153 	}
46154 }
46155 
46156 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
46157 /* Variant for writing duk_tvals so that any heap allocated values are
46158  * written out as tagged heap pointers.
46159  */
46160 DUK_LOCAL void duk__debug_write_tval_heapptr(duk_hthread *thr, duk_tval *tv) {
46161 	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
46162 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
46163 		duk_debug_write_heapptr(thr, h);
46164 	} else {
46165 		duk_debug_write_tval(thr, tv);
46166 	}
46167 }
46168 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
46169 
46170 /*
46171  *  Debug connection message write helpers
46172  */
46173 
46174 #if 0  /* unused */
46175 DUK_INTERNAL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command) {
46176 	duk_debug_write_byte(thr, DUK_DBG_IB_REQUEST);
46177 	duk_debug_write_int(thr, command);
46178 }
46179 #endif
46180 
46181 DUK_INTERNAL void duk_debug_write_reply(duk_hthread *thr) {
46182 	duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
46183 }
46184 
46185 DUK_INTERNAL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg) {
46186 	/* Allow NULL 'msg' */
46187 	duk_debug_write_byte(thr, DUK_DBG_IB_ERROR);
46188 	duk_debug_write_int(thr, (duk_int32_t) err_code);
46189 	duk_debug_write_cstring(thr, msg);
46190 	duk_debug_write_eom(thr);
46191 }
46192 
46193 DUK_INTERNAL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command) {
46194 	duk_debug_write_byte(thr, DUK_DBG_IB_NOTIFY);
46195 	duk_debug_write_int(thr, (duk_int32_t) command);
46196 }
46197 
46198 DUK_INTERNAL void duk_debug_write_eom(duk_hthread *thr) {
46199 	duk_debug_write_byte(thr, DUK_DBG_IB_EOM);
46200 
46201 	/* As an initial implementation, write flush after every EOM (and the
46202 	 * version identifier).  A better implementation would flush only when
46203 	 * Duktape is finished processing messages so that a flush only happens
46204 	 * after all outbound messages are finished on that occasion.
46205 	 */
46206 	duk_debug_write_flush(thr);
46207 }
46208 
46209 /*
46210  *  Status message and helpers
46211  */
46212 
46213 DUK_INTERNAL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr) {
46214 	duk_activation *act;
46215 	duk_uint_fast32_t line;
46216 	duk_uint_fast32_t pc;
46217 
46218 	act = thr->callstack_curr;
46219 	if (act == NULL) {
46220 		return 0;
46221 	}
46222 
46223 	/* We're conceptually between two opcodes; act->pc indicates the next
46224 	 * instruction to be executed.  This is usually the correct pc/line to
46225 	 * indicate in Status.  (For the 'debugger' statement this now reports
46226 	 * the pc/line after the debugger statement because the debugger opcode
46227 	 * has already been executed.)
46228 	 */
46229 
46230 	pc = duk_hthread_get_act_curr_pc(thr, act);
46231 
46232 	/* XXX: this should be optimized to be a raw query and avoid valstack
46233 	 * operations if possible.
46234 	 */
46235 	duk_push_tval(thr, &act->tv_func);
46236 	line = duk_hobject_pc2line_query(thr, -1, pc);
46237 	duk_pop(thr);
46238 	return line;
46239 }
46240 
46241 DUK_INTERNAL void duk_debug_send_status(duk_hthread *thr) {
46242 	duk_activation *act;
46243 
46244 	duk_debug_write_notify(thr, DUK_DBG_CMD_STATUS);
46245 	duk_debug_write_int(thr, (DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) ? 1 : 0));
46246 
46247 	act = thr->callstack_curr;
46248 	if (act == NULL) {
46249 		duk_debug_write_undefined(thr);
46250 		duk_debug_write_undefined(thr);
46251 		duk_debug_write_int(thr, 0);
46252 		duk_debug_write_int(thr, 0);
46253 	} else {
46254 		duk_push_tval(thr, &act->tv_func);
46255 		duk_get_prop_literal(thr, -1, "fileName");
46256 		duk__debug_write_hstring_safe_top(thr);
46257 		duk_get_prop_literal(thr, -2, "name");
46258 		duk__debug_write_hstring_safe_top(thr);
46259 		duk_pop_3(thr);
46260 		/* Report next pc/line to be executed. */
46261 		duk_debug_write_uint(thr, (duk_uint32_t) duk_debug_curr_line(thr));
46262 		duk_debug_write_uint(thr, (duk_uint32_t) duk_hthread_get_act_curr_pc(thr, act));
46263 	}
46264 
46265 	duk_debug_write_eom(thr);
46266 }
46267 
46268 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
46269 DUK_INTERNAL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal) {
46270 	/*
46271 	 *  NFY <int: 5> <int: fatal> <str: msg> <str: filename> <int: linenumber> EOM
46272 	 */
46273 
46274 	duk_activation *act;
46275 	duk_uint32_t pc;
46276 
46277 	DUK_ASSERT(thr->valstack_top > thr->valstack);  /* At least: ... [err] */
46278 
46279 	duk_debug_write_notify(thr, DUK_DBG_CMD_THROW);
46280 	duk_debug_write_int(thr, (duk_int32_t) fatal);
46281 
46282 	/* Report thrown value to client coerced to string */
46283 	duk_dup_top(thr);
46284 	duk__debug_write_hstring_safe_top(thr);
46285 	duk_pop(thr);
46286 
46287 	if (duk_is_error(thr, -1)) {
46288 		/* Error instance, use augmented error data directly */
46289 		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);
46290 		duk__debug_write_hstring_safe_top(thr);
46291 		duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_LINE_NUMBER);
46292 		duk_debug_write_uint(thr, duk_get_uint(thr, -1));
46293 		duk_pop_2(thr);
46294 	} else {
46295 		/* For anything other than an Error instance, we calculate the
46296 		 * error location directly from the current activation if one
46297 		 * exists.
46298 		 */
46299 		act = thr->callstack_curr;
46300 		if (act != NULL) {
46301 			duk_push_tval(thr, &act->tv_func);
46302 			duk_get_prop_literal(thr, -1, "fileName");
46303 			duk__debug_write_hstring_safe_top(thr);
46304 			pc = (duk_uint32_t) duk_hthread_get_act_prev_pc(thr, act);
46305 			duk_debug_write_uint(thr, (duk_uint32_t) duk_hobject_pc2line_query(thr, -2, pc));
46306 			duk_pop_2(thr);
46307 		} else {
46308 			/* Can happen if duk_throw() is called on an empty
46309 			 * callstack.
46310 			 */
46311 			duk_debug_write_cstring(thr, "");
46312 			duk_debug_write_uint(thr, 0);
46313 		}
46314 	}
46315 
46316 	duk_debug_write_eom(thr);
46317 }
46318 #endif  /* DUK_USE_DEBUGGER_THROW_NOTIFY */
46319 
46320 /*
46321  *  Debug message processing
46322  */
46323 
46324 /* Skip dvalue. */
46325 DUK_LOCAL duk_bool_t duk__debug_skip_dvalue(duk_hthread *thr) {
46326 	duk_uint8_t x;
46327 	duk_uint32_t len;
46328 
46329 	x = duk_debug_read_byte(thr);
46330 
46331 	if (x >= 0xc0) {
46332 		duk_debug_skip_byte(thr);
46333 		return 0;
46334 	}
46335 	if (x >= 0x80) {
46336 		return 0;
46337 	}
46338 	if (x >= 0x60) {
46339 		duk_debug_skip_bytes(thr, (duk_size_t) (x - 0x60));
46340 		return 0;
46341 	}
46342 	switch(x) {
46343 	case DUK_DBG_IB_EOM:
46344 		return 1;  /* Return 1: got EOM */
46345 	case DUK_DBG_IB_REQUEST:
46346 	case DUK_DBG_IB_REPLY:
46347 	case DUK_DBG_IB_ERROR:
46348 	case DUK_DBG_IB_NOTIFY:
46349 		break;
46350 	case DUK_DBG_IB_INT4:
46351 		(void) duk__debug_read_uint32_raw(thr);
46352 		break;
46353 	case DUK_DBG_IB_STR4:
46354 	case DUK_DBG_IB_BUF4:
46355 		len = duk__debug_read_uint32_raw(thr);
46356 		duk_debug_skip_bytes(thr, len);
46357 		break;
46358 	case DUK_DBG_IB_STR2:
46359 	case DUK_DBG_IB_BUF2:
46360 		len = duk__debug_read_uint16_raw(thr);
46361 		duk_debug_skip_bytes(thr, len);
46362 		break;
46363 	case DUK_DBG_IB_UNUSED:
46364 	case DUK_DBG_IB_UNDEFINED:
46365 	case DUK_DBG_IB_NULL:
46366 	case DUK_DBG_IB_TRUE:
46367 	case DUK_DBG_IB_FALSE:
46368 		break;
46369 	case DUK_DBG_IB_NUMBER:
46370 		duk_debug_skip_bytes(thr, 8);
46371 		break;
46372 	case DUK_DBG_IB_OBJECT:
46373 		duk_debug_skip_byte(thr);
46374 		len = duk_debug_read_byte(thr);
46375 		duk_debug_skip_bytes(thr, len);
46376 		break;
46377 	case DUK_DBG_IB_POINTER:
46378 	case DUK_DBG_IB_HEAPPTR:
46379 		len = duk_debug_read_byte(thr);
46380 		duk_debug_skip_bytes(thr, len);
46381 		break;
46382 	case DUK_DBG_IB_LIGHTFUNC:
46383 		duk_debug_skip_bytes(thr, 2);
46384 		len = duk_debug_read_byte(thr);
46385 		duk_debug_skip_bytes(thr, len);
46386 		break;
46387 	default:
46388 		goto fail;
46389 	}
46390 
46391 	return 0;
46392 
46393  fail:
46394 	DUK__SET_CONN_BROKEN(thr, 1);
46395 	return 1;  /* Pretend like we got EOM */
46396 }
46397 
46398 /* Skip dvalues to EOM. */
46399 DUK_LOCAL void duk__debug_skip_to_eom(duk_hthread *thr) {
46400 	for (;;) {
46401 		if (duk__debug_skip_dvalue(thr)) {
46402 			break;
46403 		}
46404 	}
46405 }
46406 
46407 /* Read and validate a call stack index.  If index is invalid, write out an
46408  * error message and return zero.
46409  */
46410 DUK_LOCAL duk_int32_t duk__debug_read_validate_csindex(duk_hthread *thr) {
46411 	duk_int32_t level;
46412 	level = duk_debug_read_int(thr);
46413 	if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
46414 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
46415 		return 0;  /* zero indicates failure */
46416 	}
46417 	return level;
46418 }
46419 
46420 /* Read a call stack index and lookup the corresponding duk_activation.
46421  * If index is invalid, write out an error message and return NULL.
46422  */
46423 DUK_LOCAL duk_activation *duk__debug_read_level_get_activation(duk_hthread *thr) {
46424 	duk_activation *act;
46425 	duk_int32_t level;
46426 
46427 	level = duk_debug_read_int(thr);
46428 	act = duk_hthread_get_activation_for_level(thr, level);
46429 	if (act == NULL) {
46430 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
46431 	}
46432 	return act;
46433 }
46434 
46435 /*
46436  *  Simple commands
46437  */
46438 
46439 DUK_LOCAL void duk__debug_handle_basic_info(duk_hthread *thr, duk_heap *heap) {
46440 	DUK_UNREF(heap);
46441 	DUK_D(DUK_DPRINT("debug command Version"));
46442 
46443 	duk_debug_write_reply(thr);
46444 	duk_debug_write_int(thr, DUK_VERSION);
46445 	duk_debug_write_cstring(thr, DUK_GIT_DESCRIBE);
46446 	duk_debug_write_cstring(thr, DUK_USE_TARGET_INFO);
46447 #if defined(DUK_USE_DOUBLE_LE)
46448 	duk_debug_write_int(thr, 1);
46449 #elif defined(DUK_USE_DOUBLE_ME)
46450 	duk_debug_write_int(thr, 2);
46451 #elif defined(DUK_USE_DOUBLE_BE)
46452 	duk_debug_write_int(thr, 3);
46453 #else
46454 	duk_debug_write_int(thr, 0);
46455 #endif
46456 	duk_debug_write_int(thr, (duk_int_t) sizeof(void *));
46457 	duk_debug_write_eom(thr);
46458 }
46459 
46460 DUK_LOCAL void duk__debug_handle_trigger_status(duk_hthread *thr, duk_heap *heap) {
46461 	DUK_UNREF(heap);
46462 	DUK_D(DUK_DPRINT("debug command TriggerStatus"));
46463 
46464 	duk_debug_write_reply(thr);
46465 	duk_debug_write_eom(thr);
46466 	heap->dbg_state_dirty = 1;
46467 }
46468 
46469 DUK_LOCAL void duk__debug_handle_pause(duk_hthread *thr, duk_heap *heap) {
46470 	DUK_D(DUK_DPRINT("debug command Pause"));
46471 	duk_debug_set_paused(heap);
46472 	duk_debug_write_reply(thr);
46473 	duk_debug_write_eom(thr);
46474 }
46475 
46476 DUK_LOCAL void duk__debug_handle_resume(duk_hthread *thr, duk_heap *heap) {
46477 	duk_small_uint_t pause_flags;
46478 
46479 	DUK_D(DUK_DPRINT("debug command Resume"));
46480 
46481 	duk_debug_clear_paused(heap);
46482 
46483 	pause_flags = 0;
46484 #if 0  /* manual testing */
46485 	pause_flags |= DUK_PAUSE_FLAG_ONE_OPCODE;
46486 	pause_flags |= DUK_PAUSE_FLAG_CAUGHT_ERROR;
46487 	pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
46488 #endif
46489 #if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
46490 	pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
46491 #endif
46492 
46493 	duk__debug_set_pause_state(thr, heap, pause_flags);
46494 
46495 	duk_debug_write_reply(thr);
46496 	duk_debug_write_eom(thr);
46497 }
46498 
46499 DUK_LOCAL void duk__debug_handle_step(duk_hthread *thr, duk_heap *heap, duk_int32_t cmd) {
46500 	duk_small_uint_t pause_flags;
46501 
46502 	DUK_D(DUK_DPRINT("debug command StepInto/StepOver/StepOut: %d", (int) cmd));
46503 
46504 	if (cmd == DUK_DBG_CMD_STEPINTO) {
46505 		pause_flags = DUK_PAUSE_FLAG_LINE_CHANGE |
46506 		              DUK_PAUSE_FLAG_FUNC_ENTRY |
46507 		              DUK_PAUSE_FLAG_FUNC_EXIT;
46508 	} else if (cmd == DUK_DBG_CMD_STEPOVER) {
46509 		pause_flags = DUK_PAUSE_FLAG_LINE_CHANGE |
46510 		              DUK_PAUSE_FLAG_FUNC_EXIT;
46511 	} else {
46512 		DUK_ASSERT(cmd == DUK_DBG_CMD_STEPOUT);
46513 		pause_flags = DUK_PAUSE_FLAG_FUNC_EXIT;
46514 	}
46515 #if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
46516 	pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
46517 #endif
46518 
46519 	/* If current activation doesn't have line information, line-based
46520 	 * pause flags are automatically disabled.  As a result, e.g.
46521 	 * StepInto will then pause on (native) function entry or exit.
46522 	 */
46523 	duk_debug_clear_paused(heap);
46524 	duk__debug_set_pause_state(thr, heap, pause_flags);
46525 
46526 	duk_debug_write_reply(thr);
46527 	duk_debug_write_eom(thr);
46528 }
46529 
46530 DUK_LOCAL void duk__debug_handle_list_break(duk_hthread *thr, duk_heap *heap) {
46531 	duk_small_int_t i;
46532 
46533 	DUK_D(DUK_DPRINT("debug command ListBreak"));
46534 	duk_debug_write_reply(thr);
46535 	for (i = 0; i < (duk_small_int_t) heap->dbg_breakpoint_count; i++) {
46536 		duk_debug_write_hstring(thr, heap->dbg_breakpoints[i].filename);
46537 		duk_debug_write_uint(thr, (duk_uint32_t) heap->dbg_breakpoints[i].line);
46538 	}
46539 	duk_debug_write_eom(thr);
46540 }
46541 
46542 DUK_LOCAL void duk__debug_handle_add_break(duk_hthread *thr, duk_heap *heap) {
46543 	duk_hstring *filename;
46544 	duk_uint32_t linenumber;
46545 	duk_small_int_t idx;
46546 
46547 	DUK_UNREF(heap);
46548 
46549 	filename = duk_debug_read_hstring(thr);
46550 	linenumber = (duk_uint32_t) duk_debug_read_int(thr);
46551 	DUK_D(DUK_DPRINT("debug command AddBreak: %!O:%ld", (duk_hobject *) filename, (long) linenumber));
46552 	idx = duk_debug_add_breakpoint(thr, filename, linenumber);
46553 	if (idx >= 0) {
46554 		duk_debug_write_reply(thr);
46555 		duk_debug_write_int(thr, (duk_int32_t) idx);
46556 		duk_debug_write_eom(thr);
46557 	} else {
46558 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_TOOMANY, "no space for breakpoint");
46559 	}
46560 }
46561 
46562 DUK_LOCAL void duk__debug_handle_del_break(duk_hthread *thr, duk_heap *heap) {
46563 	duk_small_uint_t idx;
46564 
46565 	DUK_UNREF(heap);
46566 
46567 	DUK_D(DUK_DPRINT("debug command DelBreak"));
46568 	idx = (duk_small_uint_t) duk_debug_read_int(thr);
46569 	if (duk_debug_remove_breakpoint(thr, idx)) {
46570 		duk_debug_write_reply(thr);
46571 		duk_debug_write_eom(thr);
46572 	} else {
46573 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid breakpoint index");
46574 	}
46575 }
46576 
46577 DUK_LOCAL void duk__debug_handle_get_var(duk_hthread *thr, duk_heap *heap) {
46578 	duk_activation *act;
46579 	duk_hstring *str;
46580 	duk_bool_t rc;
46581 
46582 	DUK_UNREF(heap);
46583 	DUK_D(DUK_DPRINT("debug command GetVar"));
46584 
46585 	act = duk__debug_read_level_get_activation(thr);
46586 	if (act == NULL) {
46587 		return;
46588 	}
46589 	str = duk_debug_read_hstring(thr);  /* push to stack */
46590 	DUK_ASSERT(str != NULL);
46591 
46592 	rc = duk_js_getvar_activation(thr, act, str, 0);
46593 
46594 	duk_debug_write_reply(thr);
46595 	if (rc) {
46596 		duk_debug_write_int(thr, 1);
46597 		DUK_ASSERT(duk_get_tval(thr, -2) != NULL);
46598 		duk_debug_write_tval(thr, duk_get_tval(thr, -2));
46599 	} else {
46600 		duk_debug_write_int(thr, 0);
46601 		duk_debug_write_unused(thr);
46602 	}
46603 	duk_debug_write_eom(thr);
46604 }
46605 
46606 DUK_LOCAL void duk__debug_handle_put_var(duk_hthread *thr, duk_heap *heap) {
46607 	duk_activation *act;
46608 	duk_hstring *str;
46609 	duk_tval *tv;
46610 
46611 	DUK_UNREF(heap);
46612 	DUK_D(DUK_DPRINT("debug command PutVar"));
46613 
46614 	act = duk__debug_read_level_get_activation(thr);
46615 	if (act == NULL) {
46616 		return;
46617 	}
46618 	str = duk_debug_read_hstring(thr);  /* push to stack */
46619 	DUK_ASSERT(str != NULL);
46620 	tv = duk_debug_read_tval(thr);
46621 	if (tv == NULL) {
46622 		/* detached */
46623 		return;
46624 	}
46625 
46626 	duk_js_putvar_activation(thr, act, str, tv, 0);
46627 
46628 	/* XXX: Current putvar implementation doesn't have a success flag,
46629 	 * add one and send to debug client?
46630 	 */
46631 	duk_debug_write_reply(thr);
46632 	duk_debug_write_eom(thr);
46633 }
46634 
46635 DUK_LOCAL void duk__debug_handle_get_call_stack(duk_hthread *thr, duk_heap *heap) {
46636 	duk_hthread *curr_thr = thr;
46637 	duk_activation *curr_act;
46638 	duk_uint_fast32_t pc;
46639 	duk_uint_fast32_t line;
46640 
46641 	DUK_ASSERT(thr != NULL);
46642 	DUK_UNREF(heap);
46643 
46644 	duk_debug_write_reply(thr);
46645 	while (curr_thr != NULL) {
46646 		for (curr_act = curr_thr->callstack_curr; curr_act != NULL; curr_act = curr_act->parent) {
46647 			/* PC/line semantics here are:
46648 			 *   - For callstack top we're conceptually between two
46649 			 *     opcodes and current PC indicates next line to
46650 			 *     execute, so report that (matches Status).
46651 			 *   - For other activations we're conceptually still
46652 			 *     executing the instruction at PC-1, so report that
46653 			 *     (matches error stacktrace behavior).
46654 			 *   - See: https://github.com/svaarala/duktape/issues/281
46655 			 */
46656 
46657 			/* XXX: optimize to use direct reads, i.e. avoid
46658 			 * value stack operations.
46659 			 */
46660 			duk_push_tval(thr, &curr_act->tv_func);
46661 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);
46662 			duk__debug_write_hstring_safe_top(thr);
46663 			duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);
46664 			duk__debug_write_hstring_safe_top(thr);
46665 			pc = duk_hthread_get_act_curr_pc(thr, curr_act);
46666 			if (curr_act != curr_thr->callstack_curr && pc > 0) {
46667 				pc--;
46668 			}
46669 			line = duk_hobject_pc2line_query(thr, -3, pc);
46670 			duk_debug_write_uint(thr, (duk_uint32_t) line);
46671 			duk_debug_write_uint(thr, (duk_uint32_t) pc);
46672 			duk_pop_3(thr);
46673 		}
46674 		curr_thr = curr_thr->resumer;
46675 	}
46676 	/* SCANBUILD: warning about 'thr' potentially being NULL here,
46677 	 * warning is incorrect because thr != NULL always here.
46678 	 */
46679 	duk_debug_write_eom(thr);
46680 }
46681 
46682 DUK_LOCAL void duk__debug_handle_get_locals(duk_hthread *thr, duk_heap *heap) {
46683 	duk_activation *act;
46684 	duk_hstring *varname;
46685 
46686 	DUK_UNREF(heap);
46687 
46688 	act = duk__debug_read_level_get_activation(thr);
46689 	if (act == NULL) {
46690 		return;
46691 	}
46692 
46693 	duk_debug_write_reply(thr);
46694 
46695 	/* XXX: several nice-to-have improvements here:
46696 	 *   - Use direct reads avoiding value stack operations
46697 	 *   - Avoid triggering getters, indicate getter values to debug client
46698 	 *   - If side effects are possible, add error catching
46699 	 */
46700 
46701 	if (DUK_TVAL_IS_OBJECT(&act->tv_func)) {
46702 		duk_hobject *h_func = DUK_TVAL_GET_OBJECT(&act->tv_func);
46703 		duk_hobject *h_varmap;
46704 
46705 		h_varmap = duk_hobject_get_varmap(thr, h_func);
46706 		if (h_varmap != NULL) {
46707 			duk_push_hobject(thr, h_varmap);
46708 			duk_enum(thr, -1, 0 /*enum_flags*/);
46709 			while (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {
46710 				varname = duk_known_hstring(thr, -1);
46711 
46712 				duk_js_getvar_activation(thr, act, varname, 0 /*throw_flag*/);
46713 				/* [ ... func varmap enum key value this ] */
46714 				duk_debug_write_hstring(thr, duk_get_hstring(thr, -3));
46715 				duk_debug_write_tval(thr, duk_get_tval(thr, -2));
46716 				duk_pop_3(thr);  /* -> [ ... func varmap enum ] */
46717 			}
46718 		} else {
46719 			DUK_D(DUK_DPRINT("varmap missing in GetLocals, ignore"));
46720 		}
46721 	} else {
46722 		DUK_D(DUK_DPRINT("varmap is not an object in GetLocals, ignore"));
46723 	}
46724 
46725 	duk_debug_write_eom(thr);
46726 }
46727 
46728 DUK_LOCAL void duk__debug_handle_eval(duk_hthread *thr, duk_heap *heap) {
46729 	duk_small_uint_t call_flags;
46730 	duk_int_t call_ret;
46731 	duk_small_int_t eval_err;
46732 	duk_bool_t direct_eval;
46733 	duk_int32_t level;
46734 	duk_idx_t idx_func;
46735 
46736 	DUK_UNREF(heap);
46737 
46738 	DUK_D(DUK_DPRINT("debug command Eval"));
46739 
46740 	/* The eval code is executed within the lexical environment of a specified
46741 	 * activation.  For now, use global object eval() function, with the eval
46742 	 * considered a 'direct call to eval'.
46743 	 *
46744 	 * Callstack index for debug commands only affects scope -- the callstack
46745 	 * as seen by, e.g. Duktape.act() will be the same regardless.
46746 	 */
46747 
46748 	/* nargs == 2 so we can pass a callstack index to eval(). */
46749 	idx_func = duk_get_top(thr);
46750 	duk_push_c_function(thr, duk_bi_global_object_eval, 2 /*nargs*/);
46751 	duk_push_undefined(thr);  /* 'this' binding shouldn't matter here */
46752 
46753 	/* Read callstack index, if non-null. */
46754 	if (duk_debug_peek_byte(thr) == DUK_DBG_IB_NULL) {
46755 		direct_eval = 0;
46756 		level = -1;  /* Not needed, but silences warning. */
46757 		(void) duk_debug_read_byte(thr);
46758 	} else {
46759 		direct_eval = 1;
46760 		level = duk__debug_read_validate_csindex(thr);
46761 		if (level == 0) {
46762 			return;
46763 		}
46764 	}
46765 
46766 	DUK_ASSERT(!direct_eval ||
46767 	           (level < 0 && -level <= (duk_int32_t) thr->callstack_top));
46768 
46769 	(void) duk_debug_read_hstring(thr);
46770 	if (direct_eval) {
46771 		duk_push_int(thr, level - 1);  /* compensate for eval() call */
46772 	}
46773 
46774 	/* [ ... eval "eval" eval_input level? ] */
46775 
46776 	call_flags = 0;
46777 	if (direct_eval) {
46778 		duk_activation *act;
46779 		duk_hobject *fun;
46780 
46781 		act = duk_hthread_get_activation_for_level(thr, level);
46782 		if (act != NULL) {
46783 			fun = DUK_ACT_GET_FUNC(act);
46784 			if (fun != NULL && DUK_HOBJECT_IS_COMPFUNC(fun)) {
46785 				/* Direct eval requires that there's a current
46786 				 * activation and it is an ECMAScript function.
46787 				 * When Eval is executed from e.g. cooperate API
46788 				 * call we'll need to do an indirect eval instead.
46789 				 */
46790 				call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
46791 			}
46792 		}
46793 	}
46794 
46795 	call_ret = duk_pcall_method_flags(thr, duk_get_top(thr) - (idx_func + 2), call_flags);
46796 
46797 	if (call_ret == DUK_EXEC_SUCCESS) {
46798 		eval_err = 0;
46799 		/* Use result value as is. */
46800 	} else {
46801 		/* For errors a string coerced result is most informative
46802 		 * right now, as the debug client doesn't have the capability
46803 		 * to traverse the error object.
46804 		 */
46805 		eval_err = 1;
46806 		duk_safe_to_string(thr, -1);
46807 	}
46808 
46809 	/* [ ... result ] */
46810 
46811 	duk_debug_write_reply(thr);
46812 	duk_debug_write_int(thr, (duk_int32_t) eval_err);
46813 	DUK_ASSERT(duk_get_tval(thr, -1) != NULL);
46814 	duk_debug_write_tval(thr, duk_get_tval(thr, -1));
46815 	duk_debug_write_eom(thr);
46816 }
46817 
46818 DUK_LOCAL void duk__debug_handle_detach(duk_hthread *thr, duk_heap *heap) {
46819 	DUK_UNREF(heap);
46820 	DUK_D(DUK_DPRINT("debug command Detach"));
46821 
46822 	duk_debug_write_reply(thr);
46823 	duk_debug_write_eom(thr);
46824 
46825 	DUK_D(DUK_DPRINT("debug connection detached, mark broken"));
46826 	DUK__SET_CONN_BROKEN(thr, 0);  /* not an error */
46827 }
46828 
46829 DUK_LOCAL void duk__debug_handle_apprequest(duk_hthread *thr, duk_heap *heap) {
46830 	duk_idx_t old_top;
46831 
46832 	DUK_D(DUK_DPRINT("debug command AppRequest"));
46833 
46834 	old_top = duk_get_top(thr);  /* save stack top */
46835 
46836 	if (heap->dbg_request_cb != NULL) {
46837 		duk_idx_t nrets;
46838 		duk_idx_t nvalues = 0;
46839 		duk_idx_t top, idx;
46840 
46841 		/* Read tvals from the message and push them onto the valstack,
46842 		 * then call the request callback to process the request.
46843 		 */
46844 		while (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
46845 			duk_tval *tv;
46846 			if (!duk_check_stack(thr, 1)) {
46847 				DUK_D(DUK_DPRINT("failed to allocate space for request dvalue(s)"));
46848 				goto fail;
46849 			}
46850 			tv = duk_debug_read_tval(thr);  /* push to stack */
46851 			if (tv == NULL) {
46852 				/* detached */
46853 				return;
46854 			}
46855 			nvalues++;
46856 		}
46857 		DUK_ASSERT(duk_get_top(thr) == old_top + nvalues);
46858 
46859 		/* Request callback should push values for reply to client onto valstack */
46860 		DUK_D(DUK_DPRINT("calling into AppRequest request_cb with nvalues=%ld, old_top=%ld, top=%ld",
46861 		                 (long) nvalues, (long) old_top, (long) duk_get_top(thr)));
46862 		nrets = heap->dbg_request_cb(thr, heap->dbg_udata, nvalues);
46863 		DUK_D(DUK_DPRINT("returned from AppRequest request_cb; nvalues=%ld -> nrets=%ld, old_top=%ld, top=%ld",
46864 		                 (long) nvalues, (long) nrets, (long) old_top, (long) duk_get_top(thr)));
46865 		if (nrets >= 0) {
46866 			DUK_ASSERT(duk_get_top(thr) >= old_top + nrets);
46867 			if (duk_get_top(thr) < old_top + nrets) {
46868 				DUK_D(DUK_DPRINT("AppRequest callback doesn't match value stack configuration, "
46869 				                 "top=%ld < old_top=%ld + nrets=%ld; "
46870 				                 "this might mean it's unsafe to continue!",
46871 				                 (long) duk_get_top(thr), (long) old_top, (long) nrets));
46872 				goto fail;
46873 			}
46874 
46875 			/* Reply with tvals pushed by request callback */
46876 			duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
46877 			top = duk_get_top(thr);
46878 			for (idx = top - nrets; idx < top; idx++) {
46879 				duk_debug_write_tval(thr, DUK_GET_TVAL_POSIDX(thr, idx));
46880 			}
46881 			duk_debug_write_eom(thr);
46882 		} else {
46883 			DUK_ASSERT(duk_get_top(thr) >= old_top + 1);
46884 			if (duk_get_top(thr) < old_top + 1) {
46885 				DUK_D(DUK_DPRINT("request callback return value doesn't match value stack configuration"));
46886 				goto fail;
46887 			}
46888 			duk_debug_write_error_eom(thr, DUK_DBG_ERR_APPLICATION, duk_get_string(thr, -1));
46889 		}
46890 
46891 		duk_set_top(thr, old_top);  /* restore stack top */
46892 	} else {
46893 		DUK_D(DUK_DPRINT("no request callback, treat AppRequest as unsupported"));
46894 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "AppRequest unsupported by target");
46895 	}
46896 
46897 	return;
46898 
46899  fail:
46900 	duk_set_top(thr, old_top);  /* restore stack top */
46901 	DUK__SET_CONN_BROKEN(thr, 1);
46902 }
46903 
46904 /*
46905  *  DumpHeap command
46906  */
46907 
46908 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
46909 /* XXX: this has some overlap with object inspection; remove this and make
46910  * DumpHeap return lists of heapptrs instead?
46911  */
46912 DUK_LOCAL void duk__debug_dump_heaphdr(duk_hthread *thr, duk_heap *heap, duk_heaphdr *hdr) {
46913 	DUK_UNREF(heap);
46914 
46915 	duk_debug_write_heapptr(thr, hdr);
46916 	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_TYPE(hdr));
46917 	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_FLAGS_RAW(hdr));
46918 #if defined(DUK_USE_REFERENCE_COUNTING)
46919 	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_REFCOUNT(hdr));
46920 #else
46921 	duk_debug_write_int(thr, (duk_int32_t) -1);
46922 #endif
46923 
46924 	switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
46925 	case DUK_HTYPE_STRING: {
46926 		duk_hstring *h = (duk_hstring *) hdr;
46927 
46928 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_BYTELEN(h));
46929 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_CHARLEN(h));
46930 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_HASH(h));
46931 		duk_debug_write_hstring(thr, h);
46932 		break;
46933 	}
46934 	case DUK_HTYPE_OBJECT: {
46935 		duk_hobject *h = (duk_hobject *) hdr;
46936 		duk_hstring *k;
46937 		duk_uint_fast32_t i;
46938 
46939 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_CLASS_NUMBER(h));
46940 		duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
46941 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ESIZE(h));
46942 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ENEXT(h));
46943 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ASIZE(h));
46944 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_HSIZE(h));
46945 
46946 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
46947 			duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_E_GET_FLAGS(heap, h, i));
46948 			k = DUK_HOBJECT_E_GET_KEY(heap, h, i);
46949 			duk_debug_write_heapptr(thr, (duk_heaphdr *) k);
46950 			if (k == NULL) {
46951 				duk_debug_write_int(thr, 0);  /* isAccessor */
46952 				duk_debug_write_unused(thr);
46953 				continue;
46954 			}
46955 			if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
46956 				duk_debug_write_int(thr, 1);  /* isAccessor */
46957 				duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
46958 				duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
46959 			} else {
46960 				duk_debug_write_int(thr, 0);  /* isAccessor */
46961 
46962 				duk__debug_write_tval_heapptr(thr, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
46963 			}
46964 		}
46965 
46966 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
46967 			/* Note: array dump will include elements beyond
46968 			 * 'length'.
46969 			 */
46970 			duk__debug_write_tval_heapptr(thr, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
46971 		}
46972 		break;
46973 	}
46974 	case DUK_HTYPE_BUFFER: {
46975 		duk_hbuffer *h = (duk_hbuffer *) hdr;
46976 
46977 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HBUFFER_GET_SIZE(h));
46978 		duk_debug_write_buffer(thr, (const char *) DUK_HBUFFER_GET_DATA_PTR(heap, h), (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
46979 		break;
46980 	}
46981 	default: {
46982 		DUK_D(DUK_DPRINT("invalid htype: %d", (int) DUK_HEAPHDR_GET_TYPE(hdr)));
46983 	}
46984 	}
46985 }
46986 
46987 DUK_LOCAL void duk__debug_dump_heap_allocated(duk_hthread *thr, duk_heap *heap) {
46988 	duk_heaphdr *hdr;
46989 
46990 	hdr = heap->heap_allocated;
46991 	while (hdr != NULL) {
46992 		duk__debug_dump_heaphdr(thr, heap, hdr);
46993 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
46994 	}
46995 }
46996 
46997 DUK_LOCAL void duk__debug_dump_strtab(duk_hthread *thr, duk_heap *heap) {
46998 	duk_uint32_t i;
46999 	duk_hstring *h;
47000 
47001 	for (i = 0; i < heap->st_size; i++) {
47002 #if defined(DUK_USE_STRTAB_PTRCOMP)
47003 		h = DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, heap->strtable16[i]);
47004 #else
47005 		h = heap->strtable[i];
47006 #endif
47007 		while (h != NULL) {
47008 			duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
47009 			h = h->hdr.h_next;
47010 		}
47011 	}
47012 }
47013 
47014 DUK_LOCAL void duk__debug_handle_dump_heap(duk_hthread *thr, duk_heap *heap) {
47015 	DUK_D(DUK_DPRINT("debug command DumpHeap"));
47016 
47017 	duk_debug_write_reply(thr);
47018 	duk__debug_dump_heap_allocated(thr, heap);
47019 	duk__debug_dump_strtab(thr, heap);
47020 	duk_debug_write_eom(thr);
47021 }
47022 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
47023 
47024 DUK_LOCAL void duk__debug_handle_get_bytecode(duk_hthread *thr, duk_heap *heap) {
47025 	duk_activation *act;
47026 	duk_hcompfunc *fun = NULL;
47027 	duk_size_t i, n;
47028 	duk_tval *tv;
47029 	duk_hobject **fn;
47030 	duk_int32_t level = -1;
47031 	duk_uint8_t ibyte;
47032 
47033 	DUK_UNREF(heap);
47034 
47035 	DUK_D(DUK_DPRINT("debug command GetBytecode"));
47036 
47037 	ibyte = duk_debug_peek_byte(thr);
47038 	if (ibyte != DUK_DBG_IB_EOM) {
47039 		tv = duk_debug_read_tval(thr);
47040 		if (tv == NULL) {
47041 			/* detached */
47042 			return;
47043 		}
47044 		if (DUK_TVAL_IS_OBJECT(tv)) {
47045 			/* tentative, checked later */
47046 			fun = (duk_hcompfunc *) DUK_TVAL_GET_OBJECT(tv);
47047 			DUK_ASSERT(fun != NULL);
47048 		} else if (DUK_TVAL_IS_NUMBER(tv)) {
47049 			level = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv);
47050 		} else {
47051 			DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!T", tv));
47052 			goto fail_args;
47053 		}
47054 	}
47055 
47056 	if (fun == NULL) {
47057 		act = duk_hthread_get_activation_for_level(thr, level);
47058 		if (act == NULL) {
47059 			goto fail_index;
47060 		}
47061 		fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
47062 	}
47063 
47064 	if (fun == NULL || !DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun)) {
47065 		DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!O", fun));
47066 		goto fail_args;
47067 	}
47068 	DUK_ASSERT(fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun));
47069 
47070 	duk_debug_write_reply(thr);
47071 	n = DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap, fun);
47072 	duk_debug_write_int(thr, (duk_int32_t) n);
47073 	tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, fun);
47074 	for (i = 0; i < n; i++) {
47075 		duk_debug_write_tval(thr, tv);
47076 		tv++;
47077 	}
47078 	n = DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap, fun);
47079 	duk_debug_write_int(thr, (duk_int32_t) n);
47080 	fn = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, fun);
47081 	for (i = 0; i < n; i++) {
47082 		duk_debug_write_hobject(thr, *fn);
47083 		fn++;
47084 	}
47085 	duk_debug_write_string(thr,
47086 	                       (const char *) DUK_HCOMPFUNC_GET_CODE_BASE(heap, fun),
47087 	                       (duk_size_t) DUK_HCOMPFUNC_GET_CODE_SIZE(heap, fun));
47088 	duk_debug_write_eom(thr);
47089 	return;
47090 
47091  fail_args:
47092 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid argument");
47093 	return;
47094 
47095  fail_index:
47096 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
47097 	return;
47098 }
47099 
47100 /*
47101  *  Object inspection commands: GetHeapObjInfo, GetObjPropDesc,
47102  *  GetObjPropDescRange
47103  */
47104 
47105 #if defined(DUK_USE_DEBUGGER_INSPECT)
47106 
47107 #if 0 /* pruned */
47108 DUK_LOCAL const char * const duk__debug_getinfo_heaphdr_keys[] = {
47109 	"reachable",
47110 	"temproot",
47111 	"finalizable",
47112 	"finalized",
47113 	"readonly"
47114 	/* NULL not needed here */
47115 };
47116 DUK_LOCAL duk_uint_t duk__debug_getinfo_heaphdr_masks[] = {
47117 	DUK_HEAPHDR_FLAG_REACHABLE,
47118 	DUK_HEAPHDR_FLAG_TEMPROOT,
47119 	DUK_HEAPHDR_FLAG_FINALIZABLE,
47120 	DUK_HEAPHDR_FLAG_FINALIZED,
47121 	DUK_HEAPHDR_FLAG_READONLY,
47122 	0  /* terminator */
47123 };
47124 #endif
47125 DUK_LOCAL const char * const duk__debug_getinfo_hstring_keys[] = {
47126 #if 0
47127 	"arridx",
47128 	"symbol",
47129 	"hidden",
47130 	"reserved_word",
47131 	"strict_reserved_word",
47132 	"eval_or_arguments",
47133 #endif
47134 	"extdata"
47135 	/* NULL not needed here */
47136 };
47137 DUK_LOCAL duk_uint_t duk__debug_getinfo_hstring_masks[] = {
47138 #if 0
47139 	DUK_HSTRING_FLAG_ARRIDX,
47140 	DUK_HSTRING_FLAG_SYMBOL,
47141 	DUK_HSTRING_FLAG_HIDDEN,
47142 	DUK_HSTRING_FLAG_RESERVED_WORD,
47143 	DUK_HSTRING_FLAG_STRICT_RESERVED_WORD,
47144 	DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS,
47145 #endif
47146 	DUK_HSTRING_FLAG_EXTDATA,
47147 	0  /* terminator */
47148 };
47149 DUK_LOCAL const char * const duk__debug_getinfo_hobject_keys[] = {
47150 	"extensible",
47151 	"constructable",
47152 	"callable",
47153 	"boundfunc",
47154 	"compfunc",
47155 	"natfunc",
47156 	"bufobj",
47157 	"fastrefs",
47158 	"array_part",
47159 	"strict",
47160 	"notail",
47161 	"newenv",
47162 	"namebinding",
47163 	"createargs",
47164 	"have_finalizer",
47165 	"exotic_array",
47166 	"exotic_stringobj",
47167 	"exotic_arguments",
47168 	"exotic_proxyobj",
47169 	"special_call"
47170 	/* NULL not needed here */
47171 };
47172 DUK_LOCAL duk_uint_t duk__debug_getinfo_hobject_masks[] = {
47173 	DUK_HOBJECT_FLAG_EXTENSIBLE,
47174 	DUK_HOBJECT_FLAG_CONSTRUCTABLE,
47175 	DUK_HOBJECT_FLAG_CALLABLE,
47176 	DUK_HOBJECT_FLAG_BOUNDFUNC,
47177 	DUK_HOBJECT_FLAG_COMPFUNC,
47178 	DUK_HOBJECT_FLAG_NATFUNC,
47179 	DUK_HOBJECT_FLAG_BUFOBJ,
47180 	DUK_HOBJECT_FLAG_FASTREFS,
47181 	DUK_HOBJECT_FLAG_ARRAY_PART,
47182 	DUK_HOBJECT_FLAG_STRICT,
47183 	DUK_HOBJECT_FLAG_NOTAIL,
47184 	DUK_HOBJECT_FLAG_NEWENV,
47185 	DUK_HOBJECT_FLAG_NAMEBINDING,
47186 	DUK_HOBJECT_FLAG_CREATEARGS,
47187 	DUK_HOBJECT_FLAG_HAVE_FINALIZER,
47188 	DUK_HOBJECT_FLAG_EXOTIC_ARRAY,
47189 	DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ,
47190 	DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS,
47191 	DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ,
47192 	DUK_HOBJECT_FLAG_SPECIAL_CALL,
47193 	0  /* terminator */
47194 };
47195 DUK_LOCAL const char * const duk__debug_getinfo_hbuffer_keys[] = {
47196 	"dynamic",
47197 	"external"
47198 	/* NULL not needed here */
47199 };
47200 DUK_LOCAL duk_uint_t duk__debug_getinfo_hbuffer_masks[] = {
47201 	DUK_HBUFFER_FLAG_DYNAMIC,
47202 	DUK_HBUFFER_FLAG_EXTERNAL,
47203 	0  /* terminator */
47204 };
47205 
47206 DUK_LOCAL void duk__debug_getinfo_flags_key(duk_hthread *thr, const char *key) {
47207 	duk_debug_write_uint(thr, 0);
47208 	duk_debug_write_cstring(thr, key);
47209 }
47210 
47211 DUK_LOCAL void duk__debug_getinfo_prop_uint(duk_hthread *thr, const char *key, duk_uint_t val) {
47212 	duk_debug_write_uint(thr, 0);
47213 	duk_debug_write_cstring(thr, key);
47214 	duk_debug_write_uint(thr, val);
47215 }
47216 
47217 DUK_LOCAL void duk__debug_getinfo_prop_int(duk_hthread *thr, const char *key, duk_int_t val) {
47218 	duk_debug_write_uint(thr, 0);
47219 	duk_debug_write_cstring(thr, key);
47220 	duk_debug_write_int(thr, val);
47221 }
47222 
47223 DUK_LOCAL void duk__debug_getinfo_prop_bool(duk_hthread *thr, const char *key, duk_bool_t val) {
47224 	duk_debug_write_uint(thr, 0);
47225 	duk_debug_write_cstring(thr, key);
47226 	duk_debug_write_boolean(thr, val);
47227 }
47228 
47229 DUK_LOCAL void duk__debug_getinfo_bitmask(duk_hthread *thr, const char * const * keys, duk_uint_t *masks, duk_uint_t flags) {
47230 	const char *key;
47231 	duk_uint_t mask;
47232 
47233 	for (;;) {
47234 		mask = *masks++;
47235 		if (mask == 0) {
47236 			break;
47237 		}
47238 		key = *keys++;
47239 		DUK_ASSERT(key != NULL);
47240 
47241 		DUK_DD(DUK_DDPRINT("inspect bitmask: key=%s, mask=0x%08lx, flags=0x%08lx", key, (unsigned long) mask, (unsigned long) flags));
47242 		duk__debug_getinfo_prop_bool(thr, key, flags & mask);
47243 	}
47244 }
47245 
47246 /* Inspect a property using a virtual index into a conceptual property list
47247  * consisting of (1) all array part items from [0,a_size[ (even when above
47248  * .length) and (2) all entry part items from [0,e_next[.  Unused slots are
47249  * indicated using dvalue 'unused'.
47250  */
47251 DUK_LOCAL duk_bool_t duk__debug_getprop_index(duk_hthread *thr, duk_heap *heap, duk_hobject *h_obj, duk_uint_t idx) {
47252 	duk_uint_t a_size;
47253 	duk_tval *tv;
47254 	duk_hstring *h_key;
47255 	duk_hobject *h_getset;
47256 	duk_uint_t flags;
47257 
47258 	DUK_UNREF(heap);
47259 
47260 	a_size = DUK_HOBJECT_GET_ASIZE(h_obj);
47261 	if (idx < a_size) {
47262 		duk_debug_write_uint(thr, DUK_PROPDESC_FLAGS_WEC);
47263 		duk_debug_write_uint(thr, idx);
47264 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, h_obj, idx);
47265 		duk_debug_write_tval(thr, tv);
47266 		return 1;
47267 	}
47268 
47269 	idx -= a_size;
47270 	if (idx >= DUK_HOBJECT_GET_ENEXT(h_obj)) {
47271 		return 0;
47272 	}
47273 
47274 	h_key = DUK_HOBJECT_E_GET_KEY(heap, h_obj, idx);
47275 	if (h_key == NULL) {
47276 		duk_debug_write_uint(thr, 0);
47277 		duk_debug_write_null(thr);
47278 		duk_debug_write_unused(thr);
47279 		return 1;
47280 	}
47281 
47282 	flags = DUK_HOBJECT_E_GET_FLAGS(heap, h_obj, idx);
47283 	if (DUK_HSTRING_HAS_SYMBOL(h_key)) {
47284 		flags |= DUK_DBG_PROPFLAG_SYMBOL;
47285 	}
47286 	if (DUK_HSTRING_HAS_HIDDEN(h_key)) {
47287 		flags |= DUK_DBG_PROPFLAG_HIDDEN;
47288 	}
47289 	duk_debug_write_uint(thr, flags);
47290 	duk_debug_write_hstring(thr, h_key);
47291 	if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
47292 		h_getset = DUK_HOBJECT_E_GET_VALUE_GETTER(heap, h_obj, idx);
47293 		if (h_getset) {
47294 			duk_debug_write_hobject(thr, h_getset);
47295 		} else {
47296 			duk_debug_write_null(thr);
47297 		}
47298 		h_getset = DUK_HOBJECT_E_GET_VALUE_SETTER(heap, h_obj, idx);
47299 		if (h_getset) {
47300 			duk_debug_write_hobject(thr, h_getset);
47301 		} else {
47302 			duk_debug_write_null(thr);
47303 		}
47304 	} else {
47305 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, h_obj, idx);
47306 		duk_debug_write_tval(thr, tv);
47307 	}
47308 	return 1;
47309 }
47310 
47311 DUK_LOCAL void duk__debug_handle_get_heap_obj_info(duk_hthread *thr, duk_heap *heap) {
47312 	duk_heaphdr *h;
47313 
47314 	DUK_D(DUK_DPRINT("debug command GetHeapObjInfo"));
47315 	DUK_UNREF(heap);
47316 
47317 	DUK_ASSERT(sizeof(duk__debug_getinfo_hstring_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hstring_masks) / sizeof(duk_uint_t) - 1);
47318 	DUK_ASSERT(sizeof(duk__debug_getinfo_hobject_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hobject_masks) / sizeof(duk_uint_t) - 1);
47319 	DUK_ASSERT(sizeof(duk__debug_getinfo_hbuffer_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hbuffer_masks) / sizeof(duk_uint_t) - 1);
47320 
47321 	h = duk_debug_read_any_ptr(thr);
47322 	if (!h) {
47323 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
47324 		return;
47325 	}
47326 
47327 	duk_debug_write_reply(thr);
47328 
47329 	/* As with all inspection code, we rely on the debug client providing
47330 	 * a valid, non-stale pointer: there's no portable way to safely
47331 	 * validate the pointer here.
47332 	 */
47333 
47334 	duk__debug_getinfo_flags_key(thr, "heapptr");
47335 	duk_debug_write_heapptr(thr, h);
47336 
47337 	/* XXX: comes out as signed now */
47338 	duk__debug_getinfo_prop_uint(thr, "heaphdr_flags", (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));
47339 	duk__debug_getinfo_prop_uint(thr, "heaphdr_type", (duk_uint_t) DUK_HEAPHDR_GET_TYPE(h));
47340 #if defined(DUK_USE_REFERENCE_COUNTING)
47341 	duk__debug_getinfo_prop_uint(thr, "refcount", (duk_uint_t) DUK_HEAPHDR_GET_REFCOUNT(h));
47342 #endif
47343 #if 0 /* pruned */
47344 	duk__debug_getinfo_bitmask(thr,
47345 	                           duk__debug_getinfo_heaphdr_keys,
47346 	                           duk__debug_getinfo_heaphdr_masks,
47347 	                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
47348 #endif
47349 
47350 	switch (DUK_HEAPHDR_GET_TYPE(h)) {
47351 	case DUK_HTYPE_STRING: {
47352 		duk_hstring *h_str;
47353 
47354 		h_str = (duk_hstring *) h;
47355 		duk__debug_getinfo_bitmask(thr,
47356 		                           duk__debug_getinfo_hstring_keys,
47357 		                           duk__debug_getinfo_hstring_masks,
47358 		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
47359 		duk__debug_getinfo_prop_uint(thr, "bytelen", (duk_uint_t) DUK_HSTRING_GET_BYTELEN(h_str));
47360 		duk__debug_getinfo_prop_uint(thr, "charlen", (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h_str));
47361 		duk__debug_getinfo_prop_uint(thr, "hash", (duk_uint_t) DUK_HSTRING_GET_HASH(h_str));
47362 		duk__debug_getinfo_flags_key(thr, "data");
47363 		duk_debug_write_hstring(thr, h_str);
47364 		break;
47365 	}
47366 	case DUK_HTYPE_OBJECT: {
47367 		duk_hobject *h_obj;
47368 		duk_hobject *h_proto;
47369 
47370 		h_obj = (duk_hobject *) h;
47371 		h_proto = DUK_HOBJECT_GET_PROTOTYPE(heap, h_obj);
47372 
47373 		/* duk_hobject specific fields. */
47374 		duk__debug_getinfo_bitmask(thr,
47375 		                           duk__debug_getinfo_hobject_keys,
47376 		                           duk__debug_getinfo_hobject_masks,
47377 		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
47378 		duk__debug_getinfo_prop_uint(thr, "class_number", DUK_HOBJECT_GET_CLASS_NUMBER(h_obj));
47379 		duk__debug_getinfo_flags_key(thr, "class_name");
47380 		duk_debug_write_hstring(thr, DUK_HOBJECT_GET_CLASS_STRING(heap, h_obj));
47381 		duk__debug_getinfo_flags_key(thr, "prototype");
47382 		if (h_proto != NULL) {
47383 			duk_debug_write_hobject(thr, h_proto);
47384 		} else {
47385 			duk_debug_write_null(thr);
47386 		}
47387 		duk__debug_getinfo_flags_key(thr, "props");
47388 		duk_debug_write_pointer(thr, (void *) DUK_HOBJECT_GET_PROPS(heap, h_obj));
47389 		duk__debug_getinfo_prop_uint(thr, "e_size", (duk_uint_t) DUK_HOBJECT_GET_ESIZE(h_obj));
47390 		duk__debug_getinfo_prop_uint(thr, "e_next", (duk_uint_t) DUK_HOBJECT_GET_ENEXT(h_obj));
47391 		duk__debug_getinfo_prop_uint(thr, "a_size", (duk_uint_t) DUK_HOBJECT_GET_ASIZE(h_obj));
47392 		duk__debug_getinfo_prop_uint(thr, "h_size", (duk_uint_t) DUK_HOBJECT_GET_HSIZE(h_obj));
47393 
47394 		if (DUK_HOBJECT_IS_ARRAY(h_obj)) {
47395 			duk_harray *h_arr;
47396 			h_arr = (duk_harray *) h_obj;
47397 
47398 			duk__debug_getinfo_prop_uint(thr, "length", (duk_uint_t) h_arr->length);
47399 			duk__debug_getinfo_prop_bool(thr, "length_nonwritable", h_arr->length_nonwritable);
47400 		}
47401 
47402 		if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
47403 			duk_hnatfunc *h_fun;
47404 			h_fun = (duk_hnatfunc *) h_obj;
47405 
47406 			duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
47407 			duk__debug_getinfo_prop_int(thr, "magic", h_fun->magic);
47408 			duk__debug_getinfo_prop_bool(thr, "varargs", h_fun->magic == DUK_HNATFUNC_NARGS_VARARGS);
47409 			/* Native function pointer may be different from a void pointer,
47410 			 * and we serialize it from memory directly now (no byte swapping etc).
47411 			 */
47412 			duk__debug_getinfo_flags_key(thr, "funcptr");
47413 			duk_debug_write_buffer(thr, (const char *) &h_fun->func, sizeof(h_fun->func));
47414 		}
47415 
47416 		if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
47417 			duk_hcompfunc *h_fun;
47418 			duk_hbuffer *h_buf;
47419 			duk_hobject *h_lexenv;
47420 			duk_hobject *h_varenv;
47421 			h_fun = (duk_hcompfunc *) h_obj;
47422 
47423 			duk__debug_getinfo_prop_int(thr, "nregs", h_fun->nregs);
47424 			duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
47425 
47426 			duk__debug_getinfo_flags_key(thr, "lex_env");
47427 			h_lexenv = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, h_fun);
47428 			if (h_lexenv != NULL) {
47429 				duk_debug_write_hobject(thr, h_lexenv);
47430 			} else {
47431 				duk_debug_write_null(thr);
47432 			}
47433 			duk__debug_getinfo_flags_key(thr, "var_env");
47434 			h_varenv = DUK_HCOMPFUNC_GET_VARENV(thr->heap, h_fun);
47435 			if (h_varenv != NULL) {
47436 				duk_debug_write_hobject(thr, h_varenv);
47437 			} else {
47438 				duk_debug_write_null(thr);
47439 			}
47440 
47441 			duk__debug_getinfo_prop_uint(thr, "start_line", h_fun->start_line);
47442 			duk__debug_getinfo_prop_uint(thr, "end_line", h_fun->end_line);
47443 			h_buf = (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(thr->heap, h_fun);
47444 			if (h_buf != NULL) {
47445 				duk__debug_getinfo_flags_key(thr, "data");
47446 				duk_debug_write_heapptr(thr, (duk_heaphdr *) h_buf);
47447 			}
47448 		}
47449 
47450 		if (DUK_HOBJECT_IS_BOUNDFUNC(h_obj)) {
47451 			duk_hboundfunc *h_bfun;
47452 			h_bfun = (duk_hboundfunc *) (void *) h_obj;
47453 
47454 			duk__debug_getinfo_flags_key(thr, "target");
47455 			duk_debug_write_tval(thr, &h_bfun->target);
47456 			duk__debug_getinfo_flags_key(thr, "this_binding");
47457 			duk_debug_write_tval(thr, &h_bfun->this_binding);
47458 			duk__debug_getinfo_flags_key(thr, "nargs");
47459 			duk_debug_write_int(thr, h_bfun->nargs);
47460 			/* h_bfun->args not exposed now */
47461 		}
47462 
47463 		if (DUK_HOBJECT_IS_THREAD(h_obj)) {
47464 			/* XXX: Currently no inspection of threads, e.g. value stack, call
47465 			 * stack, catch stack, etc.
47466 			 */
47467 			duk_hthread *h_thr;
47468 			h_thr = (duk_hthread *) h_obj;
47469 			DUK_UNREF(h_thr);
47470 		}
47471 
47472 		if (DUK_HOBJECT_IS_DECENV(h_obj)) {
47473 			duk_hdecenv *h_env;
47474 			h_env = (duk_hdecenv *) h_obj;
47475 
47476 			duk__debug_getinfo_flags_key(thr, "thread");
47477 			duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->thread));
47478 			duk__debug_getinfo_flags_key(thr, "varmap");
47479 			duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->varmap));
47480 			duk__debug_getinfo_prop_uint(thr, "regbase", (duk_uint_t) h_env->regbase_byteoff);
47481 		}
47482 
47483 		if (DUK_HOBJECT_IS_OBJENV(h_obj)) {
47484 			duk_hobjenv *h_env;
47485 			h_env = (duk_hobjenv *) h_obj;
47486 
47487 			duk__debug_getinfo_flags_key(thr, "target");
47488 			duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->target));
47489 			duk__debug_getinfo_prop_bool(thr, "has_this", h_env->has_this);
47490 		}
47491 
47492 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
47493 		if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
47494 			duk_hbufobj *h_bufobj;
47495 			h_bufobj = (duk_hbufobj *) h_obj;
47496 
47497 			duk__debug_getinfo_prop_uint(thr, "slice_offset", h_bufobj->offset);
47498 			duk__debug_getinfo_prop_uint(thr, "slice_length", h_bufobj->length);
47499 			duk__debug_getinfo_prop_uint(thr, "elem_shift", (duk_uint_t) h_bufobj->shift);
47500 			duk__debug_getinfo_prop_uint(thr, "elem_type", (duk_uint_t) h_bufobj->elem_type);
47501 			duk__debug_getinfo_prop_bool(thr, "is_typedarray", (duk_uint_t) h_bufobj->is_typedarray);
47502 			if (h_bufobj->buf != NULL) {
47503 				duk__debug_getinfo_flags_key(thr, "buffer");
47504 				duk_debug_write_heapptr(thr, (duk_heaphdr *) h_bufobj->buf);
47505 			}
47506 		}
47507 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
47508 		break;
47509 	}
47510 	case DUK_HTYPE_BUFFER: {
47511 		duk_hbuffer *h_buf;
47512 
47513 		h_buf = (duk_hbuffer *) h;
47514 		duk__debug_getinfo_bitmask(thr,
47515 		                           duk__debug_getinfo_hbuffer_keys,
47516 		                           duk__debug_getinfo_hbuffer_masks,
47517 		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
47518 		duk__debug_getinfo_prop_uint(thr, "size", (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));
47519 		duk__debug_getinfo_flags_key(thr, "dataptr");
47520 		duk_debug_write_pointer(thr, (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf));
47521 		duk__debug_getinfo_flags_key(thr, "data");
47522 		duk_debug_write_hbuffer(thr, h_buf);  /* tolerates NULL h_buf */
47523 		break;
47524 	}
47525 	default: {
47526 		/* Since we already started writing the reply, just emit nothing. */
47527 		DUK_D(DUK_DPRINT("inspect target pointer has invalid heaphdr type"));
47528 	}
47529 	}
47530 
47531 	duk_debug_write_eom(thr);
47532 }
47533 
47534 DUK_LOCAL void duk__debug_handle_get_obj_prop_desc(duk_hthread *thr, duk_heap *heap) {
47535 	duk_heaphdr *h;
47536 	duk_hobject *h_obj;
47537 	duk_hstring *h_key;
47538 	duk_propdesc desc;
47539 
47540 	DUK_D(DUK_DPRINT("debug command GetObjPropDesc"));
47541 	DUK_UNREF(heap);
47542 
47543 	h = duk_debug_read_any_ptr(thr);
47544 	if (!h) {
47545 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
47546 		return;
47547 	}
47548 	h_key = duk_debug_read_hstring(thr);
47549 	if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT || h_key == NULL) {
47550 		goto fail_args;
47551 	}
47552 	h_obj = (duk_hobject *) h;
47553 
47554 	if (duk_hobject_get_own_propdesc(thr, h_obj, h_key, &desc, 0 /*flags*/)) {
47555 		duk_int_t virtual_idx;
47556 		duk_bool_t rc;
47557 
47558 		/* To use the shared helper need the virtual index. */
47559 		DUK_ASSERT(desc.e_idx >= 0 || desc.a_idx >= 0);
47560 		virtual_idx = (desc.a_idx >= 0 ? desc.a_idx :
47561 		               (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj) + desc.e_idx);
47562 
47563 		duk_debug_write_reply(thr);
47564 		rc = duk__debug_getprop_index(thr, heap, h_obj, (duk_uint_t) virtual_idx);
47565 		DUK_ASSERT(rc == 1);
47566 		DUK_UNREF(rc);
47567 		duk_debug_write_eom(thr);
47568 	} else {
47569 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "not found");
47570 	}
47571 	return;
47572 
47573  fail_args:
47574 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
47575 }
47576 
47577 DUK_LOCAL void duk__debug_handle_get_obj_prop_desc_range(duk_hthread *thr, duk_heap *heap) {
47578 	duk_heaphdr *h;
47579 	duk_hobject *h_obj;
47580 	duk_uint_t idx, idx_start, idx_end;
47581 
47582 	DUK_D(DUK_DPRINT("debug command GetObjPropDescRange"));
47583 	DUK_UNREF(heap);
47584 
47585 	h = duk_debug_read_any_ptr(thr);
47586 	idx_start = (duk_uint_t) duk_debug_read_int(thr);
47587 	idx_end = (duk_uint_t) duk_debug_read_int(thr);
47588 	if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT) {
47589 		goto fail_args;
47590 	}
47591 	h_obj = (duk_hobject *) h;
47592 
47593 	/* The index range space is conceptually the array part followed by the
47594 	 * entry part.  Unlike normal enumeration all slots are exposed here as
47595 	 * is and return 'unused' if the slots are not in active use.  In particular
47596 	 * the array part is included for the full a_size regardless of what the
47597 	 * array .length is.
47598 	 */
47599 
47600 	duk_debug_write_reply(thr);
47601 	for (idx = idx_start; idx < idx_end; idx++) {
47602 		if (!duk__debug_getprop_index(thr, heap, h_obj, idx)) {
47603 			break;
47604 		}
47605 	}
47606 	duk_debug_write_eom(thr);
47607 	return;
47608 
47609  fail_args:
47610 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
47611 }
47612 
47613 #endif  /* DUK_USE_DEBUGGER_INSPECT */
47614 
47615 /*
47616  *  Process incoming debug requests
47617  *
47618  *  Individual request handlers can push temporaries on the value stack and
47619  *  rely on duk__debug_process_message() to restore the value stack top
47620  *  automatically.
47621  */
47622 
47623 /* Process one debug message.  Automatically restore value stack top to its
47624  * entry value, so that individual message handlers don't need exact value
47625  * stack handling which is convenient.
47626  */
47627 DUK_LOCAL void duk__debug_process_message(duk_hthread *thr) {
47628 	duk_heap *heap;
47629 	duk_uint8_t x;
47630 	duk_int32_t cmd;
47631 	duk_idx_t entry_top;
47632 
47633 	DUK_ASSERT(thr != NULL);
47634 	heap = thr->heap;
47635 	DUK_ASSERT(heap != NULL);
47636 
47637 	entry_top = duk_get_top(thr);
47638 
47639 	x = duk_debug_read_byte(thr);
47640 	switch (x) {
47641 	case DUK_DBG_IB_REQUEST: {
47642 		cmd = duk_debug_read_int(thr);
47643 		switch (cmd) {
47644 		case DUK_DBG_CMD_BASICINFO: {
47645 			duk__debug_handle_basic_info(thr, heap);
47646 			break;
47647 		}
47648 		case DUK_DBG_CMD_TRIGGERSTATUS: {
47649 			duk__debug_handle_trigger_status(thr, heap);
47650 			break;
47651 		}
47652 		case DUK_DBG_CMD_PAUSE: {
47653 			duk__debug_handle_pause(thr, heap);
47654 			break;
47655 		}
47656 		case DUK_DBG_CMD_RESUME: {
47657 			duk__debug_handle_resume(thr, heap);
47658 			break;
47659 		}
47660 		case DUK_DBG_CMD_STEPINTO:
47661 		case DUK_DBG_CMD_STEPOVER:
47662 		case DUK_DBG_CMD_STEPOUT: {
47663 			duk__debug_handle_step(thr, heap, cmd);
47664 			break;
47665 		}
47666 		case DUK_DBG_CMD_LISTBREAK: {
47667 			duk__debug_handle_list_break(thr, heap);
47668 			break;
47669 		}
47670 		case DUK_DBG_CMD_ADDBREAK: {
47671 			duk__debug_handle_add_break(thr, heap);
47672 			break;
47673 		}
47674 		case DUK_DBG_CMD_DELBREAK: {
47675 			duk__debug_handle_del_break(thr, heap);
47676 			break;
47677 		}
47678 		case DUK_DBG_CMD_GETVAR: {
47679 			duk__debug_handle_get_var(thr, heap);
47680 			break;
47681 		}
47682 		case DUK_DBG_CMD_PUTVAR: {
47683 			duk__debug_handle_put_var(thr, heap);
47684 			break;
47685 		}
47686 		case DUK_DBG_CMD_GETCALLSTACK: {
47687 			duk__debug_handle_get_call_stack(thr, heap);
47688 			break;
47689 		}
47690 		case DUK_DBG_CMD_GETLOCALS: {
47691 			duk__debug_handle_get_locals(thr, heap);
47692 			break;
47693 		}
47694 		case DUK_DBG_CMD_EVAL: {
47695 			duk__debug_handle_eval(thr, heap);
47696 			break;
47697 		}
47698 		case DUK_DBG_CMD_DETACH: {
47699 			/* The actual detached_cb call is postponed to message loop so
47700 			 * we don't need any special precautions here (just skip to EOM
47701 			 * on the already closed connection).
47702 			 */
47703 			duk__debug_handle_detach(thr, heap);
47704 			break;
47705 		}
47706 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
47707 		case DUK_DBG_CMD_DUMPHEAP: {
47708 			duk__debug_handle_dump_heap(thr, heap);
47709 			break;
47710 		}
47711 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
47712 		case DUK_DBG_CMD_GETBYTECODE: {
47713 			duk__debug_handle_get_bytecode(thr, heap);
47714 			break;
47715 		}
47716 		case DUK_DBG_CMD_APPREQUEST: {
47717 			duk__debug_handle_apprequest(thr, heap);
47718 			break;
47719 		}
47720 #if defined(DUK_USE_DEBUGGER_INSPECT)
47721 		case DUK_DBG_CMD_GETHEAPOBJINFO: {
47722 			duk__debug_handle_get_heap_obj_info(thr, heap);
47723 			break;
47724 		}
47725 		case DUK_DBG_CMD_GETOBJPROPDESC: {
47726 			duk__debug_handle_get_obj_prop_desc(thr, heap);
47727 			break;
47728 		}
47729 		case DUK_DBG_CMD_GETOBJPROPDESCRANGE: {
47730 			duk__debug_handle_get_obj_prop_desc_range(thr, heap);
47731 			break;
47732 		}
47733 #endif  /* DUK_USE_DEBUGGER_INSPECT */
47734 		default: {
47735 			DUK_D(DUK_DPRINT("debug command unsupported: %d", (int) cmd));
47736 			duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "unsupported command");
47737 		}
47738 		}  /* switch cmd */
47739 		break;
47740 	}
47741 	case DUK_DBG_IB_REPLY: {
47742 		DUK_D(DUK_DPRINT("debug reply, skipping"));
47743 		break;
47744 	}
47745 	case DUK_DBG_IB_ERROR: {
47746 		DUK_D(DUK_DPRINT("debug error, skipping"));
47747 		break;
47748 	}
47749 	case DUK_DBG_IB_NOTIFY: {
47750 		DUK_D(DUK_DPRINT("debug notify, skipping"));
47751 		break;
47752 	}
47753 	default: {
47754 		DUK_D(DUK_DPRINT("invalid initial byte, drop connection: %d", (int) x));
47755 		goto fail;
47756 	}
47757 	}  /* switch initial byte */
47758 
47759 	DUK_ASSERT(duk_get_top(thr) >= entry_top);
47760 	duk_set_top(thr, entry_top);
47761 	duk__debug_skip_to_eom(thr);
47762 	return;
47763 
47764  fail:
47765 	DUK_ASSERT(duk_get_top(thr) >= entry_top);
47766 	duk_set_top(thr, entry_top);
47767 	DUK__SET_CONN_BROKEN(thr, 1);
47768 	return;
47769 }
47770 
47771 DUK_LOCAL void duk__check_resend_status(duk_hthread *thr) {
47772 	if (thr->heap->dbg_read_cb != NULL && thr->heap->dbg_state_dirty) {
47773 		duk_debug_send_status(thr);
47774 		thr->heap->dbg_state_dirty = 0;
47775 	}
47776 }
47777 
47778 DUK_INTERNAL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block) {
47779 #if defined(DUK_USE_ASSERTIONS)
47780 	duk_idx_t entry_top;
47781 #endif
47782 	duk_bool_t retval = 0;
47783 
47784 	DUK_ASSERT(thr != NULL);
47785 	DUK_ASSERT(thr->heap != NULL);
47786 #if defined(DUK_USE_ASSERTIONS)
47787 	entry_top = duk_get_top(thr);
47788 #endif
47789 
47790 	DUK_D(DUK_DPRINT("process debug messages: read_cb=%s, no_block=%ld, detaching=%ld, processing=%ld",
47791 	                 thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) no_block,
47792 	                 (long) thr->heap->dbg_detaching, (long) thr->heap->dbg_processing));
47793 	DUK_DD(DUK_DDPRINT("top at entry: %ld", (long) duk_get_top(thr)));
47794 
47795 	/* thr->heap->dbg_detaching may be != 0 if a debugger write outside
47796 	 * the message loop caused a transport error and detach1() to run.
47797 	 */
47798 	DUK_ASSERT(thr->heap->dbg_detaching == 0 || thr->heap->dbg_detaching == 1);
47799 	DUK_ASSERT(thr->heap->dbg_processing == 0);
47800 	thr->heap->dbg_processing = 1;
47801 
47802 	/* Ensure dirty state causes a Status even if never process any
47803 	 * messages.  This is expected by the bytecode executor when in
47804 	 * the running state.
47805 	 */
47806 	duk__check_resend_status(thr);
47807 
47808 	for (;;) {
47809 		/* Process messages until we're no longer paused or we peek
47810 		 * and see there's nothing to read right now.
47811 		 */
47812 		DUK_DD(DUK_DDPRINT("top at loop top: %ld", (long) duk_get_top(thr)));
47813 		DUK_ASSERT(thr->heap->dbg_processing == 1);
47814 
47815 		while (thr->heap->dbg_read_cb == NULL && thr->heap->dbg_detaching) {
47816 			/* Detach is pending; can be triggered from outside the
47817 			 * debugger loop (e.g. Status notify write error) or by
47818 			 * previous message handling.  Call detached callback
47819 			 * here, in a controlled state, to ensure a possible
47820 			 * reattach inside the detached_cb is handled correctly.
47821 			 *
47822 			 * Recheck for detach in a while loop: an immediate
47823 			 * reattach involves a call to duk_debugger_attach()
47824 			 * which writes a debugger handshake line immediately
47825 			 * inside the API call.  If the transport write fails
47826 			 * for that handshake, we can immediately end up in a
47827 			 * "transport broken, detaching" case several times here.
47828 			 * Loop back until we're either cleanly attached or
47829 			 * fully detached.
47830 			 *
47831 			 * NOTE: Reset dbg_processing = 1 forcibly, in case we
47832 			 * re-attached; duk_debugger_attach() sets dbg_processing
47833 			 * to 0 at the moment.
47834 			 */
47835 
47836 			DUK_D(DUK_DPRINT("detach pending (dbg_read_cb == NULL, dbg_detaching != 0), call detach2"));
47837 
47838 			duk__debug_do_detach2(thr->heap);
47839 			thr->heap->dbg_processing = 1;  /* may be set to 0 by duk_debugger_attach() inside callback */
47840 
47841 			DUK_D(DUK_DPRINT("after detach2 (and possible reattach): dbg_read_cb=%s, dbg_detaching=%ld",
47842 			                 thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) thr->heap->dbg_detaching));
47843 		}
47844 		DUK_ASSERT(thr->heap->dbg_detaching == 0);  /* true even with reattach */
47845 		DUK_ASSERT(thr->heap->dbg_processing == 1);  /* even after a detach and possible reattach */
47846 
47847 		if (thr->heap->dbg_read_cb == NULL) {
47848 			DUK_D(DUK_DPRINT("debug connection broken (and not detaching), stop processing messages"));
47849 			break;
47850 		}
47851 
47852 		if (!DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || no_block) {
47853 			if (!duk_debug_read_peek(thr)) {
47854 				/* Note: peek cannot currently trigger a detach
47855 				 * so the dbg_detaching == 0 assert outside the
47856 				 * loop is correct.
47857 				 */
47858 				DUK_D(DUK_DPRINT("processing debug message, peek indicated no data, stop processing messages"));
47859 				break;
47860 			}
47861 			DUK_D(DUK_DPRINT("processing debug message, peek indicated there is data, handle it"));
47862 		} else {
47863 			DUK_D(DUK_DPRINT("paused, process debug message, blocking if necessary"));
47864 		}
47865 
47866 		duk__check_resend_status(thr);
47867 		duk__debug_process_message(thr);
47868 		duk__check_resend_status(thr);
47869 
47870 		retval = 1;  /* processed one or more messages */
47871 	}
47872 
47873 	DUK_ASSERT(thr->heap->dbg_detaching == 0);
47874 	DUK_ASSERT(thr->heap->dbg_processing == 1);
47875 	thr->heap->dbg_processing = 0;
47876 
47877 	/* As an initial implementation, read flush after exiting the message
47878 	 * loop.  If transport is broken, this is a no-op (with debug logs).
47879 	 */
47880 	duk_debug_read_flush(thr);  /* this cannot initiate a detach */
47881 	DUK_ASSERT(thr->heap->dbg_detaching == 0);
47882 
47883 	DUK_DD(DUK_DDPRINT("top at exit: %ld", (long) duk_get_top(thr)));
47884 
47885 #if defined(DUK_USE_ASSERTIONS)
47886 	/* Easy to get wrong, so assert for it. */
47887 	DUK_ASSERT(entry_top == duk_get_top(thr));
47888 #endif
47889 
47890 	return retval;
47891 }
47892 
47893 /*
47894  *  Halt execution helper
47895  */
47896 
47897 /* Halt execution and enter a debugger message loop until execution is resumed
47898  * by the client.  PC for the current activation may be temporarily decremented
47899  * so that the "current" instruction will be shown by the client.  This helper
47900  * is callable from anywhere, also outside bytecode executor.
47901  */
47902 
47903 DUK_INTERNAL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc) {
47904 	duk_activation *act;
47905 	duk_hcompfunc *fun;
47906 	duk_instr_t *old_pc = NULL;
47907 
47908 	DUK_ASSERT(thr != NULL);
47909 	DUK_ASSERT(thr->heap != NULL);
47910 	DUK_ASSERT(duk_debug_is_attached(thr->heap));
47911 	DUK_ASSERT(thr->heap->dbg_processing == 0);
47912 	DUK_ASSERT(!duk_debug_is_paused(thr->heap));
47913 
47914 	duk_debug_set_paused(thr->heap);
47915 
47916 	act = thr->callstack_curr;
47917 
47918 	/* NOTE: act may be NULL if an error is thrown outside of any activation,
47919 	 * which may happen in the case of, e.g. syntax errors.
47920 	 */
47921 
47922 	/* Decrement PC if that was requested, this requires a PC sync. */
47923 	if (act != NULL) {
47924 		duk_hthread_sync_currpc(thr);
47925 		old_pc = act->curr_pc;
47926 		fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
47927 
47928 		/* Short circuit if is safe: if act->curr_pc != NULL, 'fun' is
47929 		 * guaranteed to be a non-NULL ECMAScript function.
47930 		 */
47931 		DUK_ASSERT(act->curr_pc == NULL ||
47932 		           (fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun)));
47933 		if (use_prev_pc &&
47934 		    act->curr_pc != NULL &&
47935 		    act->curr_pc > DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, fun)) {
47936 			act->curr_pc--;
47937 		}
47938 	}
47939 
47940 	/* Process debug messages until we are no longer paused. */
47941 
47942 	/* NOTE: This is a bit fragile.  It's important to ensure that
47943 	 * duk_debug_process_messages() never throws an error or
47944 	 * act->curr_pc will never be reset.
47945 	 */
47946 
47947 	thr->heap->dbg_state_dirty = 1;
47948 	while (DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap)) {
47949 		DUK_ASSERT(duk_debug_is_attached(thr->heap));
47950 		DUK_ASSERT(thr->heap->dbg_processing == 0);
47951 		duk_debug_process_messages(thr, 0 /*no_block*/);
47952 	}
47953 
47954 	/* XXX: Decrementing and restoring act->curr_pc works now, but if the
47955 	 * debugger message loop gains the ability to adjust the current PC
47956 	 * (e.g. a forced jump) restoring the PC here will break.  Another
47957 	 * approach would be to use a state flag for the "decrement 1 from
47958 	 * topmost activation's PC" and take it into account whenever dealing
47959 	 * with PC values.
47960 	 */
47961 	if (act != NULL) {
47962 		act->curr_pc = old_pc;  /* restore PC */
47963 	}
47964 }
47965 
47966 /*
47967  *  Breakpoint management
47968  */
47969 
47970 DUK_INTERNAL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line) {
47971 	duk_heap *heap;
47972 	duk_breakpoint *b;
47973 
47974 	/* Caller must trigger recomputation of active breakpoint list.  To
47975 	 * ensure stale values are not used if that doesn't happen, clear the
47976 	 * active breakpoint list here.
47977 	 */
47978 
47979 	DUK_ASSERT(thr != NULL);
47980 	DUK_ASSERT(filename != NULL);
47981 	heap = thr->heap;
47982 	DUK_ASSERT(heap != NULL);
47983 
47984 	if (heap->dbg_breakpoint_count >= DUK_HEAP_MAX_BREAKPOINTS) {
47985 		DUK_D(DUK_DPRINT("failed to add breakpoint for %O:%ld, all breakpoint slots used",
47986 		                 (duk_heaphdr *) filename, (long) line));
47987 		return -1;
47988 	}
47989 	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
47990 	b = heap->dbg_breakpoints + (heap->dbg_breakpoint_count++);
47991 	b->filename = filename;
47992 	b->line = line;
47993 	DUK_HSTRING_INCREF(thr, filename);
47994 
47995 	return (duk_small_int_t) (heap->dbg_breakpoint_count - 1);  /* index */
47996 }
47997 
47998 DUK_INTERNAL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index) {
47999 	duk_heap *heap;
48000 	duk_hstring *h;
48001 	duk_breakpoint *b;
48002 	duk_size_t move_size;
48003 
48004 	/* Caller must trigger recomputation of active breakpoint list.  To
48005 	 * ensure stale values are not used if that doesn't happen, clear the
48006 	 * active breakpoint list here.
48007 	 */
48008 
48009 	DUK_ASSERT(thr != NULL);
48010 	heap = thr->heap;
48011 	DUK_ASSERT(heap != NULL);
48012 	DUK_ASSERT(duk_debug_is_attached(thr->heap));
48013 	DUK_ASSERT_DISABLE(breakpoint_index >= 0);  /* unsigned */
48014 
48015 	if (breakpoint_index >= heap->dbg_breakpoint_count) {
48016 		DUK_D(DUK_DPRINT("invalid breakpoint index: %ld", (long) breakpoint_index));
48017 		return 0;
48018 	}
48019 	b = heap->dbg_breakpoints + breakpoint_index;
48020 
48021 	h = b->filename;
48022 	DUK_ASSERT(h != NULL);
48023 
48024 	move_size = sizeof(duk_breakpoint) * (heap->dbg_breakpoint_count - breakpoint_index - 1);
48025 	duk_memmove((void *) b,
48026 	            (const void *) (b + 1),
48027 	            (size_t) move_size);
48028 
48029 	heap->dbg_breakpoint_count--;
48030 	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
48031 
48032 	DUK_HSTRING_DECREF(thr, h);  /* side effects */
48033 	DUK_UNREF(h);  /* w/o refcounting */
48034 
48035 	/* Breakpoint entries above the used area are left as garbage. */
48036 
48037 	return 1;
48038 }
48039 
48040 /*
48041  *  Misc state management
48042  */
48043 
48044 DUK_INTERNAL duk_bool_t duk_debug_is_attached(duk_heap *heap) {
48045 	return (heap->dbg_read_cb != NULL);
48046 }
48047 
48048 DUK_INTERNAL duk_bool_t duk_debug_is_paused(duk_heap *heap) {
48049 	return (DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) != 0);
48050 }
48051 
48052 DUK_INTERNAL void duk_debug_set_paused(duk_heap *heap) {
48053 	if (duk_debug_is_paused(heap)) {
48054 		DUK_D(DUK_DPRINT("trying to set paused state when already paused, ignoring"));
48055 	} else {
48056 		DUK_HEAP_SET_DEBUGGER_PAUSED(heap);
48057 		heap->dbg_state_dirty = 1;
48058 		duk_debug_clear_pause_state(heap);
48059 		DUK_ASSERT(heap->ms_running == 0);  /* debugger can't be triggered within mark-and-sweep */
48060 		heap->ms_running = 2;  /* prevent mark-and-sweep, prevent refzero queueing */
48061 		heap->ms_prevent_count++;
48062 		DUK_ASSERT(heap->ms_prevent_count != 0);  /* Wrap. */
48063 		DUK_ASSERT(heap->heap_thread != NULL);
48064 	}
48065 }
48066 
48067 DUK_INTERNAL void duk_debug_clear_paused(duk_heap *heap) {
48068 	if (duk_debug_is_paused(heap)) {
48069 		DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap);
48070 		heap->dbg_state_dirty = 1;
48071 		duk_debug_clear_pause_state(heap);
48072 		DUK_ASSERT(heap->ms_running == 2);
48073 		DUK_ASSERT(heap->ms_prevent_count > 0);
48074 		heap->ms_prevent_count--;
48075 		heap->ms_running = 0;
48076 		DUK_ASSERT(heap->heap_thread != NULL);
48077 	} else {
48078 		DUK_D(DUK_DPRINT("trying to clear paused state when not paused, ignoring"));
48079 	}
48080 }
48081 
48082 DUK_INTERNAL void duk_debug_clear_pause_state(duk_heap *heap) {
48083 	heap->dbg_pause_flags = 0;
48084 	heap->dbg_pause_act = NULL;
48085 	heap->dbg_pause_startline = 0;
48086 }
48087 
48088 #else  /* DUK_USE_DEBUGGER_SUPPORT */
48089 
48090 /* No debugger support. */
48091 
48092 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
48093 
48094 /* automatic undefs */
48095 #undef DUK__DBG_TPORT_ENTER
48096 #undef DUK__DBG_TPORT_EXIT
48097 #undef DUK__SET_CONN_BROKEN
48098 #line 1 "duk_error_augment.c"
48099 /*
48100  *  Augmenting errors at their creation site and their throw site.
48101  *
48102  *  When errors are created, traceback data is added by built-in code
48103  *  and a user error handler (if defined) can process or replace the
48104  *  error.  Similarly, when errors are thrown, a user error handler
48105  *  (if defined) can process or replace the error.
48106  *
48107  *  Augmentation and other processing at error creation time is nice
48108  *  because an error is only created once, but it may be thrown and
48109  *  rethrown multiple times.  User error handler registered for processing
48110  *  an error at its throw site must be careful to handle rethrowing in
48111  *  a useful manner.
48112  *
48113  *  Error augmentation may throw an internal error (e.g. alloc error).
48114  *
48115  *  ECMAScript allows throwing any values, so all values cannot be
48116  *  augmented.  Currently, the built-in augmentation at error creation
48117  *  only augments error values which are Error instances (= have the
48118  *  built-in Error.prototype in their prototype chain) and are also
48119  *  extensible.  User error handlers have no limitations in this respect.
48120  */
48121 
48122 /* #include duk_internal.h -> already included */
48123 
48124 /*
48125  *  Helper for calling a user error handler.
48126  *
48127  *  'thr' must be the currently active thread; the error handler is called
48128  *  in its context.  The valstack of 'thr' must have the error value on
48129  *  top, and will be replaced by another error value based on the return
48130  *  value of the error handler.
48131  *
48132  *  The helper calls duk_handle_call() recursively in protected mode.
48133  *  Before that call happens, no longjmps should happen; as a consequence,
48134  *  we must assume that the valstack contains enough temporary space for
48135  *  arguments and such.
48136  *
48137  *  While the error handler runs, any errors thrown will not trigger a
48138  *  recursive error handler call (this is implemented using a heap level
48139  *  flag which will "follow" through any coroutines resumed inside the
48140  *  error handler).  If the error handler is not callable or throws an
48141  *  error, the resulting error replaces the original error (for Duktape
48142  *  internal errors, duk_error_throw.c further substitutes this error with
48143  *  a DoubleError which is not ideal).  This would be easy to change and
48144  *  even signal to the caller.
48145  *
48146  *  The user error handler is stored in 'Duktape.errCreate' or
48147  *  'Duktape.errThrow' depending on whether we're augmenting the error at
48148  *  creation or throw time.  There are several alternatives to this approach,
48149  *  see doc/error-objects.rst for discussion.
48150  *
48151  *  Note: since further longjmp()s may occur while calling the error handler
48152  *  (for many reasons, e.g. a labeled 'break' inside the handler), the
48153  *  caller can make no assumptions on the thr->heap->lj state after the
48154  *  call (this affects especially duk_error_throw.c).  This is not an issue
48155  *  as long as the caller writes to the lj state only after the error handler
48156  *  finishes.
48157  */
48158 
48159 #if defined(DUK_USE_ERRTHROW) || defined(DUK_USE_ERRCREATE)
48160 DUK_LOCAL void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_cb) {
48161 	duk_tval *tv_hnd;
48162 	duk_int_t rc;
48163 
48164 	DUK_ASSERT(thr != NULL);
48165 	DUK_ASSERT(thr->heap != NULL);
48166 	DUK_ASSERT_STRIDX_VALID(stridx_cb);
48167 
48168 	if (thr->heap->augmenting_error) {
48169 		DUK_D(DUK_DPRINT("recursive call to error augmentation, ignore"));
48170 		return;
48171 	}
48172 
48173 	/*
48174 	 *  Check whether or not we have an error handler.
48175 	 *
48176 	 *  We must be careful of not triggering an error when looking up the
48177 	 *  property.  For instance, if the property is a getter, we don't want
48178 	 *  to call it, only plain values are allowed.  The value, if it exists,
48179 	 *  is not checked.  If the value is not a function, a TypeError happens
48180 	 *  when it is called and that error replaces the original one.
48181 	 */
48182 
48183 	DUK_ASSERT_VALSTACK_SPACE(thr, 4);  /* 3 entries actually needed below */
48184 
48185 	/* [ ... errval ] */
48186 
48187 	if (thr->builtins[DUK_BIDX_DUKTAPE] == NULL) {
48188 		/* When creating built-ins, some of the built-ins may not be set
48189 		 * and we want to tolerate that when throwing errors.
48190 		 */
48191 		DUK_DD(DUK_DDPRINT("error occurred when DUK_BIDX_DUKTAPE is NULL, ignoring"));
48192 		return;
48193 	}
48194 	tv_hnd = duk_hobject_find_entry_tval_ptr_stridx(thr->heap,
48195 	                                                thr->builtins[DUK_BIDX_DUKTAPE],
48196 	                                                stridx_cb);
48197 	if (tv_hnd == NULL) {
48198 		DUK_DD(DUK_DDPRINT("error handler does not exist or is not a plain value: %!T",
48199 		                   (duk_tval *) tv_hnd));
48200 		return;
48201 	}
48202 	DUK_DDD(DUK_DDDPRINT("error handler dump (callability not checked): %!T",
48203 	                     (duk_tval *) tv_hnd));
48204 	duk_push_tval(thr, tv_hnd);
48205 
48206 	/* [ ... errval errhandler ] */
48207 
48208 	duk_insert(thr, -2);  /* -> [ ... errhandler errval ] */
48209 	duk_push_undefined(thr);
48210 	duk_insert(thr, -2);  /* -> [ ... errhandler undefined(= this) errval ] */
48211 
48212 	/* [ ... errhandler undefined errval ] */
48213 
48214 	/*
48215 	 *  heap->augmenting_error prevents recursive re-entry and also causes
48216 	 *  call handling to use a larger (but not unbounded) call stack limit
48217 	 *  for the duration of error augmentation.
48218 	 *
48219 	 *  We ignore errors now: a success return and an error value both
48220 	 *  replace the original error value.  (This would be easy to change.)
48221 	 */
48222 
48223 	DUK_ASSERT(thr->heap->augmenting_error == 0);
48224 	thr->heap->augmenting_error = 1;
48225 
48226 	rc = duk_pcall_method(thr, 1);
48227 	DUK_UNREF(rc);  /* no need to check now: both success and error are OK */
48228 
48229 	DUK_ASSERT(thr->heap->augmenting_error == 1);
48230 	thr->heap->augmenting_error = 0;
48231 
48232 	/* [ ... errval ] */
48233 }
48234 #endif  /* DUK_USE_ERRTHROW || DUK_USE_ERRCREATE */
48235 
48236 /*
48237  *  Add ._Tracedata to an error on the stack top.
48238  */
48239 
48240 #if defined(DUK_USE_TRACEBACKS)
48241 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) {
48242 	duk_activation *act;
48243 	duk_int_t depth;
48244 	duk_int_t arr_size;
48245 	duk_tval *tv;
48246 	duk_hstring *s;
48247 	duk_uint32_t u32;
48248 	duk_double_t d;
48249 
48250 	DUK_ASSERT(thr != NULL);
48251 	DUK_ASSERT(thr_callstack != NULL);
48252 
48253 	/* [ ... error ] */
48254 
48255 	/*
48256 	 *  The traceback format is pretty arcane in an attempt to keep it compact
48257 	 *  and cheap to create.  It may change arbitrarily from version to version.
48258 	 *  It should be decoded/accessed through version specific accessors only.
48259 	 *
48260 	 *  See doc/error-objects.rst.
48261 	 */
48262 
48263 	DUK_DDD(DUK_DDDPRINT("adding traceback to object: %!T",
48264 	                     (duk_tval *) duk_get_tval(thr, -1)));
48265 
48266 	/* Preallocate array to correct size, so that we can just write out
48267 	 * the _Tracedata values into the array part.
48268 	 */
48269 	act = thr->callstack_curr;
48270 	depth = DUK_USE_TRACEBACK_DEPTH;
48271 	DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX);  /* callstack limits */
48272 	if (depth > (duk_int_t) thr_callstack->callstack_top) {
48273 		depth = (duk_int_t) thr_callstack->callstack_top;
48274 	}
48275 	if (depth > 0) {
48276 		if (flags & DUK_AUGMENT_FLAG_SKIP_ONE) {
48277 			DUK_ASSERT(act != NULL);
48278 			act = act->parent;
48279 			depth--;
48280 		}
48281 	}
48282 	arr_size = depth * 2;
48283 	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
48284 		arr_size += 2;
48285 	}
48286 	if (c_filename) {
48287 		/* We need the C filename to be interned before getting the
48288 		 * array part pointer to avoid any GC interference while the
48289 		 * array part is populated.
48290 		 */
48291 		duk_push_string(thr, c_filename);
48292 		arr_size += 2;
48293 	}
48294 
48295 	/* XXX: Uninitialized would be OK.  Maybe add internal primitive to
48296 	 * push bare duk_harray with size?
48297 	 */
48298 	DUK_D(DUK_DPRINT("preallocated _Tracedata to %ld items", (long) arr_size));
48299 	tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) arr_size);
48300 	duk_clear_prototype(thr, -1);
48301 	DUK_ASSERT(duk_is_bare_object(thr, -1));
48302 	DUK_ASSERT(arr_size == 0 || tv != NULL);
48303 
48304 	/* Compiler SyntaxErrors (and other errors) come first, and are
48305 	 * blamed by default (not flagged "noblame").
48306 	 */
48307 	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
48308 		s = thr->compile_ctx->h_filename;
48309 		DUK_TVAL_SET_STRING(tv, s);
48310 		DUK_HSTRING_INCREF(thr, s);
48311 		tv++;
48312 
48313 		u32 = (duk_uint32_t) thr->compile_ctx->curr_token.start_line;  /* (flags<<32) + (line), flags = 0 */
48314 		DUK_TVAL_SET_U32(tv, u32);
48315 		tv++;
48316 	}
48317 
48318 	/* Filename/line from C macros (__FILE__, __LINE__) are added as an
48319 	 * entry with a special format: (string, number).  The number contains
48320 	 * the line and flags.
48321 	 */
48322 
48323 	/* [ ... error c_filename? arr ] */
48324 
48325 	if (c_filename) {
48326 		DUK_ASSERT(DUK_TVAL_IS_STRING(thr->valstack_top - 2));
48327 		s = DUK_TVAL_GET_STRING(thr->valstack_top - 2);  /* interned c_filename */
48328 		DUK_ASSERT(s != NULL);
48329 		DUK_TVAL_SET_STRING(tv, s);
48330 		DUK_HSTRING_INCREF(thr, s);
48331 		tv++;
48332 
48333 		d = ((flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE) ? ((duk_double_t) DUK_TB_FLAG_NOBLAME_FILELINE) * DUK_DOUBLE_2TO32 : 0.0) +
48334 		    (duk_double_t) c_line;
48335 		DUK_TVAL_SET_DOUBLE(tv, d);
48336 		tv++;
48337 	}
48338 
48339 	/* Traceback depth doesn't take into account the filename/line
48340 	 * special handling above (intentional).
48341 	 */
48342 	for (; depth-- > 0; act = act->parent) {
48343 		duk_uint32_t pc;
48344 		duk_tval *tv_src;
48345 
48346 		/* [... arr] */
48347 
48348 		DUK_ASSERT(act != NULL);  /* depth check above, assumes book-keeping is correct */
48349 		DUK_ASSERT_DISABLE(act->pc >= 0);  /* unsigned */
48350 
48351 		/* Add function object. */
48352 		tv_src = &act->tv_func;  /* object (function) or lightfunc */
48353 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_src) || DUK_TVAL_IS_LIGHTFUNC(tv_src));
48354 		DUK_TVAL_SET_TVAL(tv, tv_src);
48355 		DUK_TVAL_INCREF(thr, tv);
48356 		tv++;
48357 
48358 		/* Add a number containing: pc, activation flags.
48359 		 *
48360 		 * PC points to next instruction, find offending PC.  Note that
48361 		 * PC == 0 for native code.
48362 		 */
48363 		pc = (duk_uint32_t) duk_hthread_get_act_prev_pc(thr_callstack, act);
48364 		DUK_ASSERT_DISABLE(pc >= 0);  /* unsigned */
48365 		DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32);  /* assume PC is at most 32 bits and non-negative */
48366 		d = ((duk_double_t) act->flags) * DUK_DOUBLE_2TO32 + (duk_double_t) pc;
48367 		DUK_TVAL_SET_DOUBLE(tv, d);
48368 		tv++;
48369 	}
48370 
48371 #if defined(DUK_USE_ASSERTIONS)
48372 	{
48373 		duk_harray *a;
48374 		a = (duk_harray *) duk_known_hobject(thr, -1);
48375 		DUK_ASSERT(a != NULL);
48376 		DUK_ASSERT((duk_uint32_t) (tv - DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a)) == a->length);
48377 		DUK_ASSERT(a->length == (duk_uint32_t) arr_size);
48378 		DUK_ASSERT(duk_is_bare_object(thr, -1));
48379 	}
48380 #endif
48381 
48382 	/* [ ... error c_filename? arr ] */
48383 
48384 	if (c_filename) {
48385 		duk_remove_m2(thr);
48386 	}
48387 
48388 	/* [ ... error arr ] */
48389 
48390 	duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INT_TRACEDATA);  /* -> [ ... error ] */
48391 }
48392 #endif  /* DUK_USE_TRACEBACKS */
48393 
48394 /*
48395  *  Add .fileName and .lineNumber to an error on the stack top.
48396  */
48397 
48398 #if defined(DUK_USE_AUGMENT_ERROR_CREATE) && !defined(DUK_USE_TRACEBACKS)
48399 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) {
48400 #if defined(DUK_USE_ASSERTIONS)
48401 	duk_int_t entry_top;
48402 #endif
48403 
48404 #if defined(DUK_USE_ASSERTIONS)
48405 	entry_top = duk_get_top(thr);
48406 #endif
48407 
48408 	/*
48409 	 *  If tracebacks are disabled, 'fileName' and 'lineNumber' are added
48410 	 *  as plain own properties.  Since Error.prototype has accessors of
48411 	 *  the same name, we need to define own properties directly (cannot
48412 	 *  just use e.g. duk_put_prop_stridx).  Existing properties are not
48413 	 *  overwritten in case they already exist.
48414 	 */
48415 
48416 	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
48417 		/* Compiler SyntaxError (or other error) gets the primary blame.
48418 		 * Currently no flag to prevent blaming.
48419 		 */
48420 		duk_push_uint(thr, (duk_uint_t) thr->compile_ctx->curr_token.start_line);
48421 		duk_push_hstring(thr, thr->compile_ctx->h_filename);
48422 	} else if (c_filename && (flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE) == 0) {
48423 		/* C call site gets blamed next, unless flagged not to do so.
48424 		 * XXX: file/line is disabled in minimal builds, so disable this
48425 		 * too when appropriate.
48426 		 */
48427 		duk_push_int(thr, c_line);
48428 		duk_push_string(thr, c_filename);
48429 	} else {
48430 		/* Finally, blame the innermost callstack entry which has a
48431 		 * .fileName property.
48432 		 */
48433 		duk_small_uint_t depth;
48434 		duk_uint32_t ecma_line;
48435 		duk_activation *act;
48436 
48437 		DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX);  /* callstack limits */
48438 		depth = DUK_USE_TRACEBACK_DEPTH;
48439 		if (depth > thr_callstack->callstack_top) {
48440 			depth = thr_callstack->callstack_top;
48441 		}
48442 		for (act = thr_callstack->callstack_curr; depth-- > 0; act = act->parent) {
48443 			duk_hobject *func;
48444 			duk_uint32_t pc;
48445 
48446 			DUK_ASSERT(act != NULL);
48447 			func = DUK_ACT_GET_FUNC(act);
48448 			if (func == NULL) {
48449 				/* Lightfunc, not blamed now. */
48450 				continue;
48451 			}
48452 
48453 			/* PC points to next instruction, find offending PC,
48454 			 * PC == 0 for native code.
48455 			 */
48456 			pc = duk_hthread_get_act_prev_pc(thr, act);  /* thr argument only used for thr->heap, so specific thread doesn't matter */
48457 			DUK_UNREF(pc);
48458 			DUK_ASSERT_DISABLE(pc >= 0);  /* unsigned */
48459 			DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32);  /* assume PC is at most 32 bits and non-negative */
48460 
48461 			duk_push_hobject(thr, func);
48462 
48463 			/* [ ... error func ] */
48464 
48465 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);
48466 			if (!duk_is_string_notsymbol(thr, -1)) {
48467 				duk_pop_2(thr);
48468 				continue;
48469 			}
48470 
48471 			/* [ ... error func fileName ] */
48472 
48473 			ecma_line = 0;
48474 #if defined(DUK_USE_PC2LINE)
48475 			if (DUK_HOBJECT_IS_COMPFUNC(func)) {
48476 				ecma_line = duk_hobject_pc2line_query(thr, -2, (duk_uint_fast32_t) pc);
48477 			} else {
48478 				/* Native function, no relevant lineNumber. */
48479 			}
48480 #endif  /* DUK_USE_PC2LINE */
48481 			duk_push_u32(thr, ecma_line);
48482 
48483 			/* [ ... error func fileName lineNumber ] */
48484 
48485 			duk_replace(thr, -3);
48486 
48487 			/* [ ... error lineNumber fileName ] */
48488 			goto define_props;
48489 		}
48490 
48491 		/* No activation matches, use undefined for both .fileName and
48492 		 * .lineNumber (matches what we do with a _Tracedata based
48493 		 * no-match lookup.
48494 		 */
48495 		duk_push_undefined(thr);
48496 		duk_push_undefined(thr);
48497 	}
48498 
48499  define_props:
48500 	/* [ ... error lineNumber fileName ] */
48501 #if defined(DUK_USE_ASSERTIONS)
48502 	DUK_ASSERT(duk_get_top(thr) == entry_top + 2);
48503 #endif
48504 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C | DUK_PROPDESC_FLAG_NO_OVERWRITE);
48505 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LINE_NUMBER, DUK_PROPDESC_FLAGS_C | DUK_PROPDESC_FLAG_NO_OVERWRITE);
48506 }
48507 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE && !DUK_USE_TRACEBACKS */
48508 
48509 /*
48510  *  Add line number to a compiler error.
48511  */
48512 
48513 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
48514 DUK_LOCAL void duk__add_compiler_error_line(duk_hthread *thr) {
48515 
48516 	/* Append a "(line NNN)" to the "message" property of any error
48517 	 * thrown during compilation.  Usually compilation errors are
48518 	 * SyntaxErrors but they can also be out-of-memory errors and
48519 	 * the like.
48520 	 */
48521 
48522 	/* [ ... error ] */
48523 
48524 	DUK_ASSERT(duk_is_object(thr, -1));
48525 
48526 	if (!(thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL)) {
48527 		return;
48528 	}
48529 
48530 	DUK_DDD(DUK_DDDPRINT("compile error, before adding line info: %!T",
48531 	                     (duk_tval *) duk_get_tval(thr, -1)));
48532 
48533 	if (duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_MESSAGE)) {
48534 		duk_bool_t at_end;
48535 
48536 		/* Best guesstimate that error occurred at end of input, token
48537 		 * truncated by end of input, etc.
48538 		 */
48539 #if 0
48540 		at_end = (thr->compile_ctx->curr_token.start_offset + 1 >= thr->compile_ctx->lex.input_length);
48541 		at_end = (thr->compile_ctx->lex.window[0].codepoint < 0 || thr->compile_ctx->lex.window[1].codepoint < 0);
48542 #endif
48543 		at_end = (thr->compile_ctx->lex.window[0].codepoint < 0);
48544 
48545 		DUK_D(DUK_DPRINT("syntax error, determined at_end=%ld; curr_token.start_offset=%ld, "
48546 		                 "lex.input_length=%ld, window[0].codepoint=%ld, window[1].codepoint=%ld",
48547 		                 (long) at_end,
48548 		                 (long) thr->compile_ctx->curr_token.start_offset,
48549 		                 (long) thr->compile_ctx->lex.input_length,
48550 		                 (long) thr->compile_ctx->lex.window[0].codepoint,
48551 		                 (long) thr->compile_ctx->lex.window[1].codepoint));
48552 
48553 		duk_push_sprintf(thr, " (line %ld%s)",
48554 		                 (long) thr->compile_ctx->curr_token.start_line,
48555 		                 at_end ? ", end of input" : "");
48556 		duk_concat(thr, 2);
48557 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE);
48558 	} else {
48559 		duk_pop(thr);
48560 	}
48561 
48562 	DUK_DDD(DUK_DDDPRINT("compile error, after adding line info: %!T",
48563 	                     (duk_tval *) duk_get_tval(thr, -1)));
48564 }
48565 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE */
48566 
48567 /*
48568  *  Augment an error being created using Duktape specific properties
48569  *  like _Tracedata or .fileName/.lineNumber.
48570  */
48571 
48572 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
48573 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) {
48574 #if defined(DUK_USE_ASSERTIONS)
48575 	duk_int_t entry_top;
48576 #endif
48577 
48578 #if defined(DUK_USE_ASSERTIONS)
48579 	entry_top = duk_get_top(thr);
48580 #endif
48581 	DUK_ASSERT(obj != NULL);
48582 
48583 	DUK_UNREF(obj);  /* unreferenced w/o tracebacks */
48584 
48585 	duk__add_compiler_error_line(thr);
48586 
48587 #if defined(DUK_USE_TRACEBACKS)
48588 	/* If tracebacks are enabled, the '_Tracedata' property is the only
48589 	 * thing we need: 'fileName' and 'lineNumber' are virtual properties
48590 	 * which use '_Tracedata'.  (Check _Tracedata only as own property.)
48591 	 */
48592 	if (duk_hobject_find_entry_tval_ptr_stridx(thr->heap, obj, DUK_STRIDX_INT_TRACEDATA) != NULL) {
48593 		DUK_DDD(DUK_DDDPRINT("error value already has a '_Tracedata' property, not modifying it"));
48594 	} else {
48595 		duk__add_traceback(thr, thr_callstack, c_filename, c_line, flags);
48596 	}
48597 #else
48598 	/* Without tracebacks the concrete .fileName and .lineNumber need
48599 	 * to be added directly.
48600 	 */
48601 	duk__add_fileline(thr, thr_callstack, c_filename, c_line, flags);
48602 #endif
48603 
48604 #if defined(DUK_USE_ASSERTIONS)
48605 	DUK_ASSERT(duk_get_top(thr) == entry_top);
48606 #endif
48607 }
48608 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE */
48609 
48610 /*
48611  *  Augment an error at creation time with _Tracedata/fileName/lineNumber
48612  *  and allow a user error handler (if defined) to process/replace the error.
48613  *  The error to be augmented is at the stack top.
48614  *
48615  *  thr: thread containing the error value
48616  *  thr_callstack: thread which should be used for generating callstack etc.
48617  *  c_filename: C __FILE__ related to the error
48618  *  c_line: C __LINE__ related to the error
48619  *  flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE:
48620  *      if true, don't fileName/line as error source, otherwise use traceback
48621  *      (needed because user code filename/line are reported but internal ones
48622  *      are not)
48623  */
48624 
48625 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
48626 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) {
48627 	duk_hobject *obj;
48628 
48629 	DUK_ASSERT(thr != NULL);
48630 	DUK_ASSERT(thr_callstack != NULL);
48631 
48632 	/* [ ... error ] */
48633 
48634 	/*
48635 	 *  Criteria for augmenting:
48636 	 *
48637 	 *   - augmentation enabled in build (naturally)
48638 	 *   - error value internal prototype chain contains the built-in
48639 	 *     Error prototype object (i.e. 'val instanceof Error')
48640 	 *
48641 	 *  Additional criteria for built-in augmenting:
48642 	 *
48643 	 *   - error value is an extensible object
48644 	 */
48645 
48646 	obj = duk_get_hobject(thr, -1);
48647 	if (!obj) {
48648 		DUK_DDD(DUK_DDDPRINT("value is not an object, skip both built-in and user augment"));
48649 		return;
48650 	}
48651 	if (!duk_hobject_prototype_chain_contains(thr, obj, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {
48652 		/* If the value has a prototype loop, it's critical not to
48653 		 * throw here.  Instead, assume the value is not to be
48654 		 * augmented.
48655 		 */
48656 		DUK_DDD(DUK_DDDPRINT("value is not an error instance, skip both built-in and user augment"));
48657 		return;
48658 	}
48659 	if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
48660 		DUK_DDD(DUK_DDDPRINT("error meets criteria, built-in augment"));
48661 		duk__err_augment_builtin_create(thr, thr_callstack, c_filename, c_line, obj, flags);
48662 	} else {
48663 		DUK_DDD(DUK_DDDPRINT("error does not meet criteria, no built-in augment"));
48664 	}
48665 
48666 	/* [ ... error ] */
48667 
48668 #if defined(DUK_USE_ERRCREATE)
48669 	duk__err_augment_user(thr, DUK_STRIDX_ERR_CREATE);
48670 #endif
48671 }
48672 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE */
48673 
48674 /*
48675  *  Augment an error at throw time; allow a user error handler (if defined)
48676  *  to process/replace the error.  The error to be augmented is at the
48677  *  stack top.
48678  */
48679 
48680 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
48681 DUK_INTERNAL void duk_err_augment_error_throw(duk_hthread *thr) {
48682 #if defined(DUK_USE_ERRTHROW)
48683 	duk__err_augment_user(thr, DUK_STRIDX_ERR_THROW);
48684 #endif  /* DUK_USE_ERRTHROW */
48685 }
48686 #endif  /* DUK_USE_AUGMENT_ERROR_THROW */
48687 #line 1 "duk_error_longjmp.c"
48688 /*
48689  *  Do a longjmp call, calling the fatal error handler if no
48690  *  catchpoint exists.
48691  */
48692 
48693 /* #include duk_internal.h -> already included */
48694 
48695 #if defined(DUK_USE_PREFER_SIZE)
48696 DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_minimal(duk_hthread *thr));
48697 DUK_LOCAL void duk__uncaught_minimal(duk_hthread *thr) {
48698 	(void) duk_fatal(thr, "uncaught error");
48699 	DUK_WO_NORETURN(return;);
48700 }
48701 #endif
48702 
48703 #if 0
48704 DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_readable(duk_hthread *thr));
48705 DUK_LOCAL void duk__uncaught_readable(duk_hthread *thr) {
48706 	const char *summary;
48707 	char buf[DUK_USE_FATAL_MAXLEN];
48708 
48709 	summary = duk_push_string_tval_readable(thr, &thr->heap->lj.value1);
48710 	DUK_SNPRINTF(buf, sizeof(buf), "uncaught: %s", summary);
48711 	buf[sizeof(buf) - 1] = (char) 0;
48712 	(void) duk_fatal(thr, (const char *) buf);
48713 	DUK_WO_NORETURN(return;);
48714 }
48715 #endif
48716 
48717 #if !defined(DUK_USE_PREFER_SIZE)
48718 DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_error_aware(duk_hthread *thr));
48719 DUK_LOCAL void duk__uncaught_error_aware(duk_hthread *thr) {
48720 	const char *summary;
48721 	char buf[DUK_USE_FATAL_MAXLEN];
48722 
48723 	summary = duk_push_string_tval_readable_error(thr, &thr->heap->lj.value1);
48724 	DUK_ASSERT(summary != NULL);
48725 	DUK_SNPRINTF(buf, sizeof(buf), "uncaught: %s", summary);
48726 	buf[sizeof(buf) - 1] = (char) 0;
48727 	(void) duk_fatal(thr, (const char *) buf);
48728 	DUK_WO_NORETURN(return;);
48729 }
48730 #endif
48731 
48732 DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr) {
48733 	DUK_ASSERT(thr != NULL);
48734 	DUK_ASSERT(thr->heap != NULL);
48735 
48736 	DUK_DD(DUK_DDPRINT("longjmp error: type=%d iserror=%d value1=%!T value2=%!T",
48737 	                   (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
48738 	                   &thr->heap->lj.value1, &thr->heap->lj.value2));
48739 
48740 	/* Prevent finalizer execution during error handling.  All error
48741 	 * handling sites will process pending finalizers once error handling
48742 	 * is complete and we're ready for the side effects.  Does not prevent
48743 	 * refzero freeing or mark-and-sweep during error handling.
48744 	 *
48745 	 * NOTE: when we come here some calling code may have used DECREF
48746 	 * NORZ macros without an explicit DUK_REFZERO_CHECK_xxx() call.
48747 	 * We don't want to do it here because it would just check for
48748 	 * pending finalizers and we prevent that explicitly.  Instead,
48749 	 * the error catcher will run the finalizers once error handling
48750 	 * is complete.
48751 	 */
48752 
48753 	DUK_ASSERT_LJSTATE_SET(thr->heap);
48754 
48755 	thr->heap->pf_prevent_count++;
48756 	DUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */
48757 
48758 #if defined(DUK_USE_ASSERTIONS)
48759 	/* XXX: set this immediately when longjmp state is set */
48760 	DUK_ASSERT(thr->heap->error_not_allowed == 0);  /* Detect error within critical section. */
48761 	thr->heap->error_not_allowed = 1;
48762 #endif
48763 
48764 	DUK_DD(DUK_DDPRINT("about to longjmp, pf_prevent_count=%ld", (long) thr->heap->pf_prevent_count));
48765 
48766 	/* If we don't have a jmpbuf_ptr, there is little we can do except
48767 	 * cause a fatal error.  The caller's expectation is that we never
48768 	 * return.
48769 	 */
48770 	if (!thr->heap->lj.jmpbuf_ptr) {
48771 		DUK_D(DUK_DPRINT("uncaught error: type=%d iserror=%d value1=%!T value2=%!T",
48772 		                 (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
48773 		                 &thr->heap->lj.value1, &thr->heap->lj.value2));
48774 
48775 #if defined(DUK_USE_PREFER_SIZE)
48776 		duk__uncaught_minimal(thr);
48777 #else
48778 		duk__uncaught_error_aware(thr);
48779 #endif
48780 		DUK_UNREACHABLE();
48781 	}
48782 
48783 #if defined(DUK_USE_CPP_EXCEPTIONS)
48784 	throw duk_internal_exception();  /* dummy */
48785 #else
48786 	DUK_LONGJMP(thr->heap->lj.jmpbuf_ptr->jb);
48787 #endif
48788 
48789 	DUK_UNREACHABLE();
48790 }
48791 #line 1 "duk_error_misc.c"
48792 /*
48793  *  Error helpers
48794  */
48795 
48796 /* #include duk_internal.h -> already included */
48797 
48798 /*
48799  *  Helper to walk the thread chain and see if there is an active error
48800  *  catcher.  Protected calls or finally blocks aren't considered catching.
48801  */
48802 
48803 #if defined(DUK_USE_DEBUGGER_SUPPORT)
48804 DUK_LOCAL duk_bool_t duk__have_active_catcher(duk_hthread *thr) {
48805 	/* As noted above, a protected API call won't be counted as a
48806 	 * catcher.  This is usually convenient, e.g. in the case of a top-
48807 	 * level duk_pcall(), but may not always be desirable.  Perhaps add
48808 	 * an argument to treat them as catchers?
48809 	 */
48810 
48811 	duk_activation *act;
48812 	duk_catcher *cat;
48813 
48814 	DUK_ASSERT(thr != NULL);
48815 
48816 	for (; thr != NULL; thr = thr->resumer) {
48817 		for (act = thr->callstack_curr; act != NULL; act = act->parent) {
48818 			for (cat = act->cat; cat != NULL; cat = cat->parent) {
48819 				if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
48820 					return 1;  /* all we need to know */
48821 				}
48822 			}
48823 		}
48824 	}
48825 	return 0;
48826 }
48827 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
48828 
48829 /*
48830  *  Get prototype object for an integer error code.
48831  */
48832 
48833 DUK_INTERNAL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t code) {
48834 	switch (code) {
48835 	case DUK_ERR_EVAL_ERROR:
48836 		return thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE];
48837 	case DUK_ERR_RANGE_ERROR:
48838 		return thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE];
48839 	case DUK_ERR_REFERENCE_ERROR:
48840 		return thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE];
48841 	case DUK_ERR_SYNTAX_ERROR:
48842 		return thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE];
48843 	case DUK_ERR_TYPE_ERROR:
48844 		return thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE];
48845 	case DUK_ERR_URI_ERROR:
48846 		return thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE];
48847 	case DUK_ERR_ERROR:
48848 	default:
48849 		return thr->builtins[DUK_BIDX_ERROR_PROTOTYPE];
48850 	}
48851 }
48852 
48853 /*
48854  *  Helper for debugger throw notify and pause-on-uncaught integration.
48855  */
48856 
48857 #if defined(DUK_USE_DEBUGGER_SUPPORT)
48858 DUK_INTERNAL void duk_err_check_debugger_integration(duk_hthread *thr) {
48859 	duk_bool_t uncaught;
48860 	duk_tval *tv_obj;
48861 
48862 	/* If something is thrown with the debugger attached and nobody will
48863 	 * catch it, execution is paused before the longjmp, turning over
48864 	 * control to the debug client.  This allows local state to be examined
48865 	 * before the stack is unwound.  Errors are not intercepted when debug
48866 	 * message loop is active (e.g. for Eval).
48867 	 */
48868 
48869 	DUK_ASSERT(thr != NULL);
48870 	DUK_ASSERT(thr->heap != NULL);
48871 
48872 	/* XXX: Allow customizing the pause and notify behavior at runtime
48873 	 * using debugger runtime flags.  For now the behavior is fixed using
48874 	 * config options.
48875 	 */
48876 
48877 	if (!duk_debug_is_attached(thr->heap) ||
48878 	    thr->heap->dbg_processing ||
48879 	    thr->heap->lj.type != DUK_LJ_TYPE_THROW ||
48880 	    thr->heap->creating_error) {
48881 		DUK_D(DUK_DPRINT("skip debugger error integration; not attached, debugger processing, not THROW, or error thrown while creating error"));
48882 		return;
48883 	}
48884 
48885 	/* Don't intercept a DoubleError, we may have caused the initial double
48886 	 * fault and attempting to intercept it will cause us to be called
48887 	 * recursively and exhaust the C stack.  (This should no longer happen
48888 	 * for the initial throw because DoubleError path doesn't do a debugger
48889 	 * integration check, but it might happen for rethrows.)
48890 	 */
48891 	tv_obj = &thr->heap->lj.value1;
48892 	if (DUK_TVAL_IS_OBJECT(tv_obj) && DUK_TVAL_GET_OBJECT(tv_obj) == thr->builtins[DUK_BIDX_DOUBLE_ERROR]) {
48893 		DUK_D(DUK_DPRINT("built-in DoubleError instance (re)thrown, not intercepting"));
48894 		return;
48895 	}
48896 
48897 	uncaught = !duk__have_active_catcher(thr);
48898 
48899 	/* Debugger code expects the value at stack top.  This also serves
48900 	 * as a backup: we need to store/restore the longjmp state because
48901 	 * when the debugger is paused Eval commands may be executed and
48902 	 * they can arbitrarily clobber the longjmp state.
48903 	 */
48904 	duk_push_tval(thr, tv_obj);
48905 
48906 	/* Store and reset longjmp state. */
48907 	DUK_ASSERT_LJSTATE_SET(thr->heap);
48908 	DUK_TVAL_DECREF_NORZ(thr, tv_obj);
48909 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));  /* Always for THROW type. */
48910 	DUK_TVAL_SET_UNDEFINED(tv_obj);
48911 	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
48912 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
48913 
48914 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
48915 	/* Report it to the debug client */
48916 	DUK_D(DUK_DPRINT("throw with debugger attached, report to client"));
48917 	duk_debug_send_throw(thr, uncaught);
48918 #endif
48919 
48920 	if (uncaught) {
48921 		if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_UNCAUGHT_ERROR) {
48922 			DUK_D(DUK_DPRINT("PAUSE TRIGGERED by uncaught error"));
48923 			duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
48924 		}
48925 	} else {
48926 		if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_CAUGHT_ERROR) {
48927 			DUK_D(DUK_DPRINT("PAUSE TRIGGERED by caught error"));
48928 			duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
48929 		}
48930 	}
48931 
48932 	/* Restore longjmp state. */
48933 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
48934 	thr->heap->lj.type = DUK_LJ_TYPE_THROW;
48935 	tv_obj = DUK_GET_TVAL_NEGIDX(thr, -1);
48936 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
48937 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
48938 	DUK_TVAL_SET_TVAL(&thr->heap->lj.value1, tv_obj);
48939 	DUK_TVAL_INCREF(thr, tv_obj);
48940 	DUK_ASSERT_LJSTATE_SET(thr->heap);
48941 
48942 	duk_pop(thr);
48943 }
48944 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
48945 
48946 /*
48947  *  Helpers for setting up heap longjmp state.
48948  */
48949 
48950 DUK_INTERNAL void duk_err_setup_ljstate1(duk_hthread *thr, duk_small_uint_t lj_type, duk_tval *tv_val) {
48951 	duk_heap *heap;
48952 
48953 	DUK_ASSERT(thr != NULL);
48954 	heap = thr->heap;
48955 	DUK_ASSERT(heap != NULL);
48956 	DUK_ASSERT(tv_val != NULL);
48957 
48958 	DUK_ASSERT_LJSTATE_UNSET(heap);
48959 
48960 	heap->lj.type = lj_type;
48961 	DUK_TVAL_SET_TVAL(&heap->lj.value1, tv_val);
48962 	DUK_TVAL_INCREF(thr, tv_val);
48963 
48964 	DUK_ASSERT_LJSTATE_SET(heap);
48965 }
48966 #line 1 "duk_error_throw.c"
48967 /*
48968  *  Create and throw an ECMAScript error object based on a code and a message.
48969  *
48970  *  Used when we throw errors internally.  ECMAScript generated error objects
48971  *  are created by ECMAScript code, and the throwing is handled by the bytecode
48972  *  executor.
48973  */
48974 
48975 /* #include duk_internal.h -> already included */
48976 
48977 /*
48978  *  Create and throw an error (originating from Duktape internally)
48979  *
48980  *  Push an error object on top of the stack, possibly throw augmenting
48981  *  the error, and finally longjmp.
48982  *
48983  *  If an error occurs while we're dealing with the current error, we might
48984  *  enter an infinite recursion loop.  This is prevented by detecting a
48985  *  "double fault" through the heap->creating_error flag; the recursion
48986  *  then stops at the second level.
48987  */
48988 
48989 #if defined(DUK_USE_VERBOSE_ERRORS)
48990 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) {
48991 #else
48992 DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code) {
48993 #endif
48994 #if defined(DUK_USE_VERBOSE_ERRORS)
48995 	DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld, msg=%s, filename=%s, line=%ld",
48996 	                   (long) code, (const char *) msg,
48997 	                   (const char *) filename, (long) line));
48998 #else
48999 	DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld", (long) code));
49000 #endif
49001 
49002 	DUK_ASSERT(thr != NULL);
49003 
49004 	/* Even though nested call is possible because we throw an error when
49005 	 * trying to create an error, the potential errors must happen before
49006 	 * the longjmp state is configured.
49007 	 */
49008 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
49009 
49010 	/* Sync so that augmentation sees up-to-date activations, NULL
49011 	 * thr->ptr_curr_pc so that it's not used if side effects occur
49012 	 * in augmentation or longjmp handling.
49013 	 */
49014 	duk_hthread_sync_and_null_currpc(thr);
49015 
49016 	/*
49017 	 *  Create and push an error object onto the top of stack.
49018 	 *  The error is potentially augmented before throwing.
49019 	 *
49020 	 *  If a "double error" occurs, use a fixed error instance
49021 	 *  to avoid further trouble.
49022 	 */
49023 
49024 	if (thr->heap->creating_error) {
49025 		duk_tval tv_val;
49026 		duk_hobject *h_err;
49027 
49028 		thr->heap->creating_error = 0;
49029 
49030 		h_err = thr->builtins[DUK_BIDX_DOUBLE_ERROR];
49031 		if (h_err != NULL) {
49032 			DUK_D(DUK_DPRINT("double fault detected -> use built-in fixed 'double error' instance"));
49033 			DUK_TVAL_SET_OBJECT(&tv_val, h_err);
49034 		} else {
49035 			DUK_D(DUK_DPRINT("double fault detected; there is no built-in fixed 'double error' instance "
49036 			                 "-> use the error code as a number"));
49037 			DUK_TVAL_SET_I32(&tv_val, (duk_int32_t) code);
49038 		}
49039 
49040 		duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, &tv_val);
49041 
49042 		/* No augmentation to avoid any allocations or side effects. */
49043 	} else {
49044 		/* Prevent infinite recursion.  Extra call stack and C
49045 		 * recursion headroom (see GH-191) is added for augmentation.
49046 		 * That is now signalled by heap->augmenting error and taken
49047 		 * into account in call handling without an explicit limit bump.
49048 		 */
49049 		thr->heap->creating_error = 1;
49050 
49051 		duk_require_stack(thr, 1);
49052 
49053 		/* XXX: usually unnecessary '%s' formatting here, but cannot
49054 		 * use 'msg' as a format string directly.
49055 		 */
49056 #if defined(DUK_USE_VERBOSE_ERRORS)
49057 		duk_push_error_object_raw(thr,
49058 		                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
49059 		                          filename,
49060 		                          line,
49061 		                          "%s",
49062 		                          (const char *) msg);
49063 #else
49064 		duk_push_error_object_raw(thr,
49065 		                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
49066 		                          NULL,
49067 		                          0,
49068 		                          NULL);
49069 #endif
49070 
49071 		/* Note that an alloc error may happen during error augmentation.
49072 		 * This may happen both when the original error is an alloc error
49073 		 * and when it's something else.  Because any error in augmentation
49074 		 * must be handled correctly anyway, there's no special check for
49075 		 * avoiding it for alloc errors (this differs from Duktape 1.x).
49076 		 */
49077 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
49078 		DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT (before throw augment)",
49079 		                     (duk_tval *) duk_get_tval(thr, -1)));
49080 		duk_err_augment_error_throw(thr);
49081 #endif
49082 
49083 		duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, DUK_GET_TVAL_NEGIDX(thr, -1));
49084 		thr->heap->creating_error = 0;
49085 
49086 		/* Error is now created and we assume no errors can occur any
49087 		 * more.  Check for debugger Throw integration only when the
49088 		 * error is complete.  If we enter debugger message loop,
49089 		 * creating_error must be 0 so that errors can be thrown in
49090 		 * the paused state, e.g. in Eval commands.
49091 		 */
49092 #if defined(DUK_USE_DEBUGGER_SUPPORT)
49093 		duk_err_check_debugger_integration(thr);
49094 #endif
49095 	}
49096 
49097 	/*
49098 	 *  Finally, longjmp
49099 	 */
49100 
49101 	DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT, %!iT (after throw augment)",
49102 	                     (duk_tval *) &thr->heap->lj.value1, (duk_tval *) &thr->heap->lj.value2));
49103 
49104 	duk_err_longjmp(thr);
49105 	DUK_UNREACHABLE();
49106 }
49107 
49108 /*
49109  *  Helper for C function call negative return values.
49110  */
49111 
49112 DUK_INTERNAL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc) {
49113 	DUK_ASSERT(thr != NULL);
49114 	DUK_ASSERT(rc < 0);
49115 
49116 	/*
49117 	 *  The __FILE__ and __LINE__ information is intentionally not used in the
49118 	 *  creation of the error object, as it isn't useful in the tracedata.  The
49119 	 *  tracedata still contains the function which returned the negative return
49120 	 *  code, and having the file/line of this function isn't very useful.
49121 	 *
49122 	 *  The error messages for DUK_RET_xxx shorthand are intentionally very
49123 	 *  minimal: they're only really useful for low memory targets.
49124 	 */
49125 
49126 	duk_error_raw(thr, -rc, NULL, 0, "error (rc %ld)", (long) rc);
49127 	DUK_WO_NORETURN(return;);
49128 }
49129 #line 1 "duk_hbuffer_alloc.c"
49130 /*
49131  *  duk_hbuffer allocation and freeing.
49132  */
49133 
49134 /* #include duk_internal.h -> already included */
49135 
49136 /* Allocate a new duk_hbuffer of a certain type and return a pointer to it
49137  * (NULL on error).  Write buffer data pointer to 'out_bufdata' (only if
49138  * allocation successful).
49139  */
49140 DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata) {
49141 	duk_hbuffer *res = NULL;
49142 	duk_size_t header_size;
49143 	duk_size_t alloc_size;
49144 
49145 	DUK_ASSERT(heap != NULL);
49146 	DUK_ASSERT(out_bufdata != NULL);
49147 
49148 	DUK_DDD(DUK_DDDPRINT("allocate hbuffer"));
49149 
49150 	/* Size sanity check.  Should not be necessary because caller is
49151 	 * required to check this, but we don't want to cause a segfault
49152 	 * if the size wraps either in duk_size_t computation or when
49153 	 * storing the size in a 16-bit field.
49154 	 */
49155 	if (size > DUK_HBUFFER_MAX_BYTELEN) {
49156 		DUK_D(DUK_DPRINT("hbuffer alloc failed: size too large: %ld", (long) size));
49157 		return NULL;  /* no need to write 'out_bufdata' */
49158 	}
49159 
49160 	if (flags & DUK_BUF_FLAG_EXTERNAL) {
49161 		header_size = sizeof(duk_hbuffer_external);
49162 		alloc_size = sizeof(duk_hbuffer_external);
49163 	} else if (flags & DUK_BUF_FLAG_DYNAMIC) {
49164 		header_size = sizeof(duk_hbuffer_dynamic);
49165 		alloc_size = sizeof(duk_hbuffer_dynamic);
49166 	} else {
49167 		header_size = sizeof(duk_hbuffer_fixed);
49168 		alloc_size = sizeof(duk_hbuffer_fixed) + size;
49169 		DUK_ASSERT(alloc_size >= sizeof(duk_hbuffer_fixed));  /* no wrapping */
49170 	}
49171 
49172 	res = (duk_hbuffer *) DUK_ALLOC(heap, alloc_size);
49173 	if (DUK_UNLIKELY(res == NULL)) {
49174 		goto alloc_error;
49175 	}
49176 
49177 	/* zero everything unless requested not to do so */
49178 #if defined(DUK_USE_ZERO_BUFFER_DATA)
49179 	duk_memzero((void *) res,
49180 	            (flags & DUK_BUF_FLAG_NOZERO) ? header_size : alloc_size);
49181 #else
49182 	duk_memzero((void *) res, header_size);
49183 #endif
49184 
49185 	if (flags & DUK_BUF_FLAG_EXTERNAL) {
49186 		duk_hbuffer_external *h;
49187 		h = (duk_hbuffer_external *) res;
49188 		DUK_UNREF(h);
49189 		*out_bufdata = NULL;
49190 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
49191 #if defined(DUK_USE_HEAPPTR16)
49192 /* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
49193 #else
49194 		DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap, h, NULL);
49195 #endif
49196 #endif
49197 		DUK_ASSERT(DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap, h) == NULL);
49198 	} else if (flags & DUK_BUF_FLAG_DYNAMIC) {
49199 		duk_hbuffer_dynamic *h = (duk_hbuffer_dynamic *) res;
49200 		void *ptr;
49201 
49202 		if (size > 0) {
49203 			DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));  /* alloc external with size zero */
49204 			DUK_DDD(DUK_DDDPRINT("dynamic buffer with nonzero size, alloc actual buffer"));
49205 #if defined(DUK_USE_ZERO_BUFFER_DATA)
49206 			ptr = DUK_ALLOC_ZEROED(heap, size);
49207 #else
49208 			ptr = DUK_ALLOC(heap, size);
49209 #endif
49210 			if (DUK_UNLIKELY(ptr == NULL)) {
49211 				/* Because size > 0, NULL check is correct */
49212 				goto alloc_error;
49213 			}
49214 			*out_bufdata = ptr;
49215 
49216 			DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, ptr);
49217 		} else {
49218 			*out_bufdata = NULL;
49219 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
49220 #if defined(DUK_USE_HEAPPTR16)
49221 /* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
49222 #else
49223 			DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, NULL);
49224 #endif
49225 #endif
49226 			DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, h) == NULL);
49227 		}
49228 	} else {
49229 		*out_bufdata = (void *) ((duk_hbuffer_fixed *) (void *) res + 1);
49230 	}
49231 
49232 	DUK_HBUFFER_SET_SIZE(res, size);
49233 
49234 	DUK_HEAPHDR_SET_TYPE(&res->hdr, DUK_HTYPE_BUFFER);
49235 	if (flags & DUK_BUF_FLAG_DYNAMIC) {
49236 		DUK_HBUFFER_SET_DYNAMIC(res);
49237 		if (flags & DUK_BUF_FLAG_EXTERNAL) {
49238 			DUK_HBUFFER_SET_EXTERNAL(res);
49239 		}
49240 	} else {
49241 		DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));
49242 	}
49243         DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &res->hdr);
49244 
49245 	DUK_DDD(DUK_DDDPRINT("allocated hbuffer: %p", (void *) res));
49246 	return res;
49247 
49248  alloc_error:
49249 	DUK_DD(DUK_DDPRINT("hbuffer allocation failed"));
49250 
49251 	DUK_FREE(heap, res);
49252 	return NULL;  /* no need to write 'out_bufdata' */
49253 }
49254 
49255 /* For indirect allocs. */
49256 
49257 DUK_INTERNAL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud) {
49258 	duk_hbuffer_dynamic *buf = (duk_hbuffer_dynamic *) ud;
49259 	DUK_UNREF(heap);
49260 	return (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, buf);
49261 }
49262 #line 1 "duk_hbuffer_assert.c"
49263 /*
49264  *  duk_hbuffer assertion helpers
49265  */
49266 
49267 /* #include duk_internal.h -> already included */
49268 
49269 #if defined(DUK_USE_ASSERTIONS)
49270 
49271 DUK_INTERNAL void duk_hbuffer_assert_valid(duk_hbuffer *h) {
49272 	DUK_ASSERT(h != NULL);
49273 }
49274 
49275 #endif  /* DUK_USE_ASSERTIONS */
49276 #line 1 "duk_hbuffer_ops.c"
49277 /*
49278  *  duk_hbuffer operations such as resizing and inserting/appending data to
49279  *  a dynamic buffer.
49280  */
49281 
49282 /* #include duk_internal.h -> already included */
49283 
49284 /*
49285  *  Resizing
49286  */
49287 
49288 DUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size) {
49289 	void *res;
49290 	duk_size_t prev_size;
49291 
49292 	DUK_ASSERT(thr != NULL);
49293 	DUK_ASSERT(buf != NULL);
49294 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
49295 	DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));
49296 
49297 	/*
49298 	 *  Maximum size check
49299 	 */
49300 
49301 	if (new_size > DUK_HBUFFER_MAX_BYTELEN) {
49302 		DUK_ERROR_RANGE(thr, "buffer too long");
49303 		DUK_WO_NORETURN(return;);
49304 	}
49305 
49306 	/*
49307 	 *  Note: use indirect realloc variant just in case mark-and-sweep
49308 	 *  (finalizers) might resize this same buffer during garbage
49309 	 *  collection.
49310 	 */
49311 
49312 	res = DUK_REALLOC_INDIRECT(thr->heap, duk_hbuffer_get_dynalloc_ptr, (void *) buf, new_size);
49313 	if (DUK_LIKELY(res != NULL || new_size == 0)) {
49314 		/* 'res' may be NULL if new allocation size is 0. */
49315 
49316 		DUK_DDD(DUK_DDDPRINT("resized dynamic buffer %p:%ld -> %p:%ld",
49317 		                     (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf),
49318 		                     (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(buf),
49319 		                     (void *) res,
49320 		                     (long) new_size));
49321 
49322 		/*
49323 		 *  The entire allocated buffer area, regardless of actual used
49324 		 *  size, is kept zeroed in resizes for simplicity.  If the buffer
49325 		 *  is grown, zero the new part.
49326 		 */
49327 
49328 		prev_size = DUK_HBUFFER_DYNAMIC_GET_SIZE(buf);
49329 		if (new_size > prev_size) {
49330 			DUK_ASSERT(new_size - prev_size > 0);
49331 #if defined(DUK_USE_ZERO_BUFFER_DATA)
49332 			duk_memzero((void *) ((char *) res + prev_size),
49333 			            (duk_size_t) (new_size - prev_size));
49334 #endif
49335 		}
49336 
49337 		DUK_HBUFFER_DYNAMIC_SET_SIZE(buf, new_size);
49338 		DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(thr->heap, buf, res);
49339 	} else {
49340 		DUK_ERROR_ALLOC_FAILED(thr);
49341 		DUK_WO_NORETURN(return;);
49342 	}
49343 
49344 	DUK_ASSERT(res != NULL || new_size == 0);
49345 }
49346 
49347 DUK_INTERNAL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf) {
49348 	DUK_ASSERT(thr != NULL);
49349 	DUK_ASSERT(buf != NULL);
49350 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
49351 	DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));
49352 
49353 	duk_hbuffer_resize(thr, buf, 0);
49354 }
49355 /* #include duk_internal.h -> already included */
49356 #line 2 "duk_hbufobj_misc.c"
49357 
49358 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
49359 DUK_INTERNAL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_uint_t len) {
49360 	duk_uint_t buf_size;
49361 	duk_uint_t buf_avail;
49362 
49363 	DUK_ASSERT(h_bufobj != NULL);
49364 	DUK_ASSERT(h_bufobj->buf != NULL);
49365 
49366 	buf_size = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_bufobj->buf);
49367 	if (h_bufobj->offset > buf_size) {
49368 		/* Slice starting point is beyond current length. */
49369 		return 0;
49370 	}
49371 	buf_avail = buf_size - h_bufobj->offset;
49372 
49373 	return buf_avail >= len ? len : buf_avail;
49374 }
49375 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
49376 #line 1 "duk_heap_alloc.c"
49377 /*
49378  *  duk_heap allocation and freeing.
49379  */
49380 
49381 /* #include duk_internal.h -> already included */
49382 
49383 #if defined(DUK_USE_ROM_STRINGS)
49384 /* Fixed seed value used with ROM strings. */
49385 #define DUK__FIXED_HASH_SEED       0xabcd1234
49386 #endif
49387 
49388 /*
49389  *  Free a heap object.
49390  *
49391  *  Free heap object and its internal (non-heap) pointers.  Assumes that
49392  *  caller has removed the object from heap allocated list or the string
49393  *  intern table, and any weak references (which strings may have) have
49394  *  been already dealt with.
49395  */
49396 
49397 DUK_INTERNAL void duk_free_hobject(duk_heap *heap, duk_hobject *h) {
49398 	DUK_ASSERT(heap != NULL);
49399 	DUK_ASSERT(h != NULL);
49400 
49401 	DUK_FREE(heap, DUK_HOBJECT_GET_PROPS(heap, h));
49402 
49403 	if (DUK_HOBJECT_IS_COMPFUNC(h)) {
49404 		duk_hcompfunc *f = (duk_hcompfunc *) h;
49405 		DUK_UNREF(f);
49406 		/* Currently nothing to free; 'data' is a heap object */
49407 	} else if (DUK_HOBJECT_IS_NATFUNC(h)) {
49408 		duk_hnatfunc *f = (duk_hnatfunc *) h;
49409 		DUK_UNREF(f);
49410 		/* Currently nothing to free */
49411 	} else if (DUK_HOBJECT_IS_THREAD(h)) {
49412 		duk_hthread *t = (duk_hthread *) h;
49413 		duk_activation *act;
49414 
49415 		DUK_FREE(heap, t->valstack);
49416 
49417 		/* Don't free h->resumer because it exists in the heap.
49418 		 * Callstack entries also contain function pointers which
49419 		 * are not freed for the same reason.  They are decref
49420 		 * finalized and the targets are freed if necessary based
49421 		 * on their refcount (or reachability).
49422 		 */
49423 		for (act = t->callstack_curr; act != NULL;) {
49424 			duk_activation *act_next;
49425 			duk_catcher *cat;
49426 
49427 			for (cat = act->cat; cat != NULL;) {
49428 				duk_catcher *cat_next;
49429 
49430 				cat_next = cat->parent;
49431 				DUK_FREE(heap, (void *) cat);
49432 				cat = cat_next;
49433 			}
49434 
49435 			act_next = act->parent;
49436 			DUK_FREE(heap, (void *) act);
49437 			act = act_next;
49438 		}
49439 
49440 		/* XXX: with 'caller' property the callstack would need
49441 		 * to be unwound to update the 'caller' properties of
49442 		 * functions in the callstack.
49443 		 */
49444 	} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
49445 		duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
49446 
49447 		DUK_FREE(heap, f->args);
49448 	}
49449 
49450 	DUK_FREE(heap, (void *) h);
49451 }
49452 
49453 DUK_INTERNAL void duk_free_hbuffer(duk_heap *heap, duk_hbuffer *h) {
49454 	DUK_ASSERT(heap != NULL);
49455 	DUK_ASSERT(h != NULL);
49456 
49457 	if (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h)) {
49458 		duk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;
49459 		DUK_DDD(DUK_DDDPRINT("free dynamic buffer %p", (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g)));
49460 		DUK_FREE(heap, DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g));
49461 	}
49462 	DUK_FREE(heap, (void *) h);
49463 }
49464 
49465 DUK_INTERNAL void duk_free_hstring(duk_heap *heap, duk_hstring *h) {
49466 	DUK_ASSERT(heap != NULL);
49467 	DUK_ASSERT(h != NULL);
49468 
49469 	DUK_UNREF(heap);
49470 	DUK_UNREF(h);
49471 
49472 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_FREE)
49473 	if (DUK_HSTRING_HAS_EXTDATA(h)) {
49474 		DUK_DDD(DUK_DDDPRINT("free extstr: hstring %!O, extdata: %p",
49475 		                     h, DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h)));
49476 		DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h));
49477 	}
49478 #endif
49479 	DUK_FREE(heap, (void *) h);
49480 }
49481 
49482 DUK_INTERNAL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr) {
49483 	DUK_ASSERT(heap);
49484 	DUK_ASSERT(hdr);
49485 
49486 	DUK_DDD(DUK_DDDPRINT("free heaphdr %p, htype %ld", (void *) hdr, (long) DUK_HEAPHDR_GET_TYPE(hdr)));
49487 
49488 	switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
49489 	case DUK_HTYPE_STRING:
49490 		duk_free_hstring(heap, (duk_hstring *) hdr);
49491 		break;
49492 	case DUK_HTYPE_OBJECT:
49493 		duk_free_hobject(heap, (duk_hobject *) hdr);
49494 		break;
49495 	default:
49496 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) == DUK_HTYPE_BUFFER);
49497 		duk_free_hbuffer(heap, (duk_hbuffer *) hdr);
49498 	}
49499 
49500 }
49501 
49502 /*
49503  *  Free the heap.
49504  *
49505  *  Frees heap-related non-heap-tracked allocations such as the
49506  *  string intern table; then frees the heap allocated objects;
49507  *  and finally frees the heap structure itself.  Reference counts
49508  *  and GC markers are ignored (and not updated) in this process,
49509  *  and finalizers won't be called.
49510  *
49511  *  The heap pointer and heap object pointers must not be used
49512  *  after this call.
49513  */
49514 
49515 #if defined(DUK_USE_CACHE_ACTIVATION)
49516 DUK_LOCAL duk_size_t duk__heap_free_activation_freelist(duk_heap *heap) {
49517 	duk_activation *act;
49518 	duk_activation *act_next;
49519 	duk_size_t count_act = 0;
49520 
49521 	for (act = heap->activation_free; act != NULL;) {
49522 		act_next = act->parent;
49523 		DUK_FREE(heap, (void *) act);
49524 		act = act_next;
49525 #if defined(DUK_USE_DEBUG)
49526 		count_act++;
49527 #endif
49528 	}
49529 	heap->activation_free = NULL;  /* needed when called from mark-and-sweep */
49530 	return count_act;
49531 }
49532 #endif  /* DUK_USE_CACHE_ACTIVATION */
49533 
49534 #if defined(DUK_USE_CACHE_CATCHER)
49535 DUK_LOCAL duk_size_t duk__heap_free_catcher_freelist(duk_heap *heap) {
49536 	duk_catcher *cat;
49537 	duk_catcher *cat_next;
49538 	duk_size_t count_cat = 0;
49539 
49540 	for (cat = heap->catcher_free; cat != NULL;) {
49541 		cat_next = cat->parent;
49542 		DUK_FREE(heap, (void *) cat);
49543 		cat = cat_next;
49544 #if defined(DUK_USE_DEBUG)
49545 		count_cat++;
49546 #endif
49547 	}
49548 	heap->catcher_free = NULL;  /* needed when called from mark-and-sweep */
49549 
49550 	return count_cat;
49551 }
49552 #endif  /* DUK_USE_CACHE_CATCHER */
49553 
49554 DUK_INTERNAL void duk_heap_free_freelists(duk_heap *heap) {
49555 	duk_size_t count_act = 0;
49556 	duk_size_t count_cat = 0;
49557 
49558 #if defined(DUK_USE_CACHE_ACTIVATION)
49559 	count_act = duk__heap_free_activation_freelist(heap);
49560 #endif
49561 #if defined(DUK_USE_CACHE_CATCHER)
49562 	count_cat = duk__heap_free_catcher_freelist(heap);
49563 #endif
49564 	DUK_UNREF(heap);
49565 	DUK_UNREF(count_act);
49566 	DUK_UNREF(count_cat);
49567 
49568 	DUK_D(DUK_DPRINT("freed %ld activation freelist entries, %ld catcher freelist entries",
49569 	                 (long) count_act, (long) count_cat));
49570 }
49571 
49572 DUK_LOCAL void duk__free_allocated(duk_heap *heap) {
49573 	duk_heaphdr *curr;
49574 	duk_heaphdr *next;
49575 
49576 	curr = heap->heap_allocated;
49577 	while (curr) {
49578 		/* We don't log or warn about freeing zero refcount objects
49579 		 * because they may happen with finalizer processing.
49580 		 */
49581 
49582 		DUK_DDD(DUK_DDDPRINT("FINALFREE (allocated): %!iO",
49583 		                     (duk_heaphdr *) curr));
49584 		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
49585 		duk_heap_free_heaphdr_raw(heap, curr);
49586 		curr = next;
49587 	}
49588 }
49589 
49590 #if defined(DUK_USE_FINALIZER_SUPPORT)
49591 DUK_LOCAL void duk__free_finalize_list(duk_heap *heap) {
49592 	duk_heaphdr *curr;
49593 	duk_heaphdr *next;
49594 
49595 	curr = heap->finalize_list;
49596 	while (curr) {
49597 		DUK_DDD(DUK_DDDPRINT("FINALFREE (finalize_list): %!iO",
49598 		                     (duk_heaphdr *) curr));
49599 		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
49600 		duk_heap_free_heaphdr_raw(heap, curr);
49601 		curr = next;
49602 	}
49603 }
49604 #endif  /* DUK_USE_FINALIZER_SUPPORT */
49605 
49606 DUK_LOCAL void duk__free_stringtable(duk_heap *heap) {
49607 	/* strings are only tracked by stringtable */
49608 	duk_heap_strtable_free(heap);
49609 }
49610 
49611 #if defined(DUK_USE_FINALIZER_SUPPORT)
49612 DUK_LOCAL void duk__free_run_finalizers(duk_heap *heap) {
49613 	duk_heaphdr *curr;
49614 	duk_uint_t round_no;
49615 	duk_size_t count_all;
49616 	duk_size_t count_finalized;
49617 	duk_size_t curr_limit;
49618 
49619 	DUK_ASSERT(heap != NULL);
49620 
49621 #if defined(DUK_USE_REFERENCE_COUNTING)
49622 	DUK_ASSERT(heap->refzero_list == NULL);  /* refzero not running -> must be empty */
49623 #endif
49624 	DUK_ASSERT(heap->finalize_list == NULL);  /* mark-and-sweep last pass */
49625 
49626 	if (heap->heap_thread == NULL) {
49627 		/* May happen when heap allocation fails right off.  There
49628 		 * cannot be any finalizable objects in this case.
49629 		 */
49630 		DUK_D(DUK_DPRINT("no heap_thread in heap destruct, assume no finalizable objects"));
49631 		return;
49632 	}
49633 
49634 	/* Prevent finalize_list processing and mark-and-sweep entirely.
49635 	 * Setting ms_running != 0 also prevents refzero handling from moving
49636 	 * objects away from the heap_allocated list.  The flag name is a bit
49637 	 * misleading here.
49638 	 *
49639 	 * Use a distinct value for ms_running here (== 2) so that assertions
49640 	 * can detect this situation separate from the normal runtime
49641 	 * mark-and-sweep case.  This allows better assertions (GH-2030).
49642 	 */
49643 	DUK_ASSERT(heap->pf_prevent_count == 0);
49644 	DUK_ASSERT(heap->ms_running == 0);
49645 	DUK_ASSERT(heap->ms_prevent_count == 0);
49646 	heap->pf_prevent_count = 1;
49647 	heap->ms_running = 2;  /* Use distinguishable value. */
49648 	heap->ms_prevent_count = 1;  /* Bump, because mark-and-sweep assumes it's bumped when ms_running is set. */
49649 
49650 	curr_limit = 0;  /* suppress warning, not used */
49651 	for (round_no = 0; ; round_no++) {
49652 		curr = heap->heap_allocated;
49653 		count_all = 0;
49654 		count_finalized = 0;
49655 		while (curr) {
49656 			count_all++;
49657 			if (DUK_HEAPHDR_IS_OBJECT(curr)) {
49658 				/* Only objects in heap_allocated may have finalizers.  Check that
49659 				 * the object itself has a _Finalizer property (own or inherited)
49660 				 * so that we don't execute finalizers for e.g. Proxy objects.
49661 				 */
49662 				DUK_ASSERT(curr != NULL);
49663 
49664 				if (DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) curr)) {
49665 					if (!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) curr)) {
49666 						DUK_ASSERT(DUK_HEAP_HAS_FINALIZER_NORESCUE(heap));  /* maps to finalizer 2nd argument */
49667 						duk_heap_run_finalizer(heap, (duk_hobject *) curr);
49668 						count_finalized++;
49669 					}
49670 				}
49671 			}
49672 			curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
49673 		}
49674 
49675 		/* Each round of finalizer execution may spawn new finalizable objects
49676 		 * which is normal behavior for some applications.  Allow multiple
49677 		 * rounds of finalization, but use a shrinking limit based on the
49678 		 * first round to detect the case where a runaway finalizer creates
49679 		 * an unbounded amount of new finalizable objects.  Finalizer rescue
49680 		 * is not supported: the semantics are unclear because most of the
49681 		 * objects being finalized here are already reachable.  The finalizer
49682 		 * is given a boolean to indicate that rescue is not possible.
49683 		 *
49684 		 * See discussion in: https://github.com/svaarala/duktape/pull/473
49685 		 */
49686 
49687 		if (round_no == 0) {
49688 			/* Cannot wrap: each object is at least 8 bytes so count is
49689 			 * at most 1/8 of that.
49690 			 */
49691 			curr_limit = count_all * 2;
49692 		} else {
49693 			curr_limit = (curr_limit * 3) / 4;   /* Decrease by 25% every round */
49694 		}
49695 		DUK_D(DUK_DPRINT("finalizer round %ld complete, %ld objects, tried to execute %ld finalizers, current limit is %ld",
49696 		                 (long) round_no, (long) count_all, (long) count_finalized, (long) curr_limit));
49697 
49698 		if (count_finalized == 0) {
49699 			DUK_D(DUK_DPRINT("no more finalizable objects, forced finalization finished"));
49700 			break;
49701 		}
49702 		if (count_finalized >= curr_limit) {
49703 			DUK_D(DUK_DPRINT("finalizer count above limit, potentially runaway finalizer; skip remaining finalizers"));
49704 			break;
49705 		}
49706 	}
49707 
49708 	DUK_ASSERT(heap->ms_running == 2);
49709 	DUK_ASSERT(heap->pf_prevent_count == 1);
49710 	heap->ms_running = 0;
49711 	heap->pf_prevent_count = 0;
49712 }
49713 #endif  /* DUK_USE_FINALIZER_SUPPORT */
49714 
49715 DUK_INTERNAL void duk_heap_free(duk_heap *heap) {
49716 	DUK_D(DUK_DPRINT("free heap: %p", (void *) heap));
49717 
49718 #if defined(DUK_USE_DEBUG)
49719 	duk_heap_strtable_dump(heap);
49720 #endif
49721 
49722 #if defined(DUK_USE_DEBUGGER_SUPPORT)
49723 	/* Detach a debugger if attached (can be called multiple times)
49724 	 * safely.
49725 	 */
49726 	/* XXX: Add a flag to reject an attempt to re-attach?  Otherwise
49727 	 * the detached callback may immediately reattach.
49728 	 */
49729 	duk_debug_do_detach(heap);
49730 #endif
49731 
49732 	/* Execute finalizers before freeing the heap, even for reachable
49733 	 * objects.  This gives finalizers the chance to free any native
49734 	 * resources like file handles, allocations made outside Duktape,
49735 	 * etc.  This is quite tricky to get right, so that all finalizer
49736 	 * guarantees are honored.
49737 	 *
49738 	 * Run mark-and-sweep a few times just in case (unreachable object
49739 	 * finalizers run already here).  The last round must rescue objects
49740 	 * from the previous round without running any more finalizers.  This
49741 	 * ensures rescued objects get their FINALIZED flag cleared so that
49742 	 * their finalizer is called once more in forced finalization to
49743 	 * satisfy finalizer guarantees.  However, we don't want to run any
49744 	 * more finalizers because that'd required one more loop, and so on.
49745 	 *
49746 	 * XXX: this perhaps requires an execution time limit.
49747 	 */
49748 	DUK_D(DUK_DPRINT("execute finalizers before freeing heap"));
49749 	DUK_ASSERT(heap->pf_skip_finalizers == 0);
49750 	DUK_D(DUK_DPRINT("forced gc #1 in heap destruction"));
49751 	duk_heap_mark_and_sweep(heap, 0);
49752 	DUK_D(DUK_DPRINT("forced gc #2 in heap destruction"));
49753 	duk_heap_mark_and_sweep(heap, 0);
49754 	DUK_D(DUK_DPRINT("forced gc #3 in heap destruction (don't run finalizers)"));
49755 	heap->pf_skip_finalizers = 1;
49756 	duk_heap_mark_and_sweep(heap, 0);  /* Skip finalizers; queue finalizable objects to heap_allocated. */
49757 
49758 	/* There are never objects in refzero_list at this point, or at any
49759 	 * point beyond a DECREF (even a DECREF_NORZ).  Since Duktape 2.1
49760 	 * refzero_list processing is side effect free, so it is always
49761 	 * processed to completion by a DECREF initially triggering a zero
49762 	 * refcount.
49763 	 */
49764 #if defined(DUK_USE_REFERENCE_COUNTING)
49765 	DUK_ASSERT(heap->refzero_list == NULL);  /* Always processed to completion inline. */
49766 #endif
49767 #if defined(DUK_USE_FINALIZER_SUPPORT)
49768 	DUK_ASSERT(heap->finalize_list == NULL);  /* Last mark-and-sweep with skip_finalizers. */
49769 #endif
49770 
49771 #if defined(DUK_USE_FINALIZER_SUPPORT)
49772 	DUK_D(DUK_DPRINT("run finalizers for remaining finalizable objects"));
49773 	DUK_HEAP_SET_FINALIZER_NORESCUE(heap);  /* Rescue no longer supported. */
49774 	duk__free_run_finalizers(heap);
49775 #endif  /* DUK_USE_FINALIZER_SUPPORT */
49776 
49777 	/* Note: heap->heap_thread, heap->curr_thread, and heap->heap_object
49778 	 * are on the heap allocated list.
49779 	 */
49780 
49781 	DUK_D(DUK_DPRINT("freeing temporary freelists"));
49782 	duk_heap_free_freelists(heap);
49783 
49784 	DUK_D(DUK_DPRINT("freeing heap_allocated of heap: %p", (void *) heap));
49785 	duk__free_allocated(heap);
49786 
49787 #if defined(DUK_USE_REFERENCE_COUNTING)
49788 	DUK_ASSERT(heap->refzero_list == NULL);  /* Always processed to completion inline. */
49789 #endif
49790 
49791 #if defined(DUK_USE_FINALIZER_SUPPORT)
49792 	DUK_D(DUK_DPRINT("freeing finalize_list of heap: %p", (void *) heap));
49793 	duk__free_finalize_list(heap);
49794 #endif
49795 
49796 	DUK_D(DUK_DPRINT("freeing string table of heap: %p", (void *) heap));
49797 	duk__free_stringtable(heap);
49798 
49799 	DUK_D(DUK_DPRINT("freeing heap structure: %p", (void *) heap));
49800 	heap->free_func(heap->heap_udata, heap);
49801 }
49802 
49803 /*
49804  *  Allocate a heap.
49805  *
49806  *  String table is initialized with built-in strings from genbuiltins.py,
49807  *  either by dynamically creating the strings or by referring to ROM strings.
49808  */
49809 
49810 #if defined(DUK_USE_ROM_STRINGS)
49811 DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
49812 #if defined(DUK_USE_ASSERTIONS)
49813 	duk_small_uint_t i;
49814 #endif
49815 
49816 	DUK_UNREF(heap);
49817 
49818 	/* With ROM-based strings, heap->strs[] and thr->strs[] are omitted
49819 	 * so nothing to initialize for strs[].
49820 	 */
49821 
49822 #if defined(DUK_USE_ASSERTIONS)
49823 	for (i = 0; i < sizeof(duk_rom_strings_lookup) / sizeof(const duk_hstring *); i++) {
49824 		const duk_hstring *h;
49825 		duk_uint32_t hash;
49826 
49827 		h = duk_rom_strings_lookup[i];
49828 		while (h != NULL) {
49829 			hash = duk_heap_hashstring(heap, (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
49830 			DUK_DD(DUK_DDPRINT("duk_rom_strings_lookup[%d] -> hash 0x%08lx, computed 0x%08lx",
49831 			                   (int) i, (unsigned long) DUK_HSTRING_GET_HASH(h), (unsigned long) hash));
49832 			DUK_ASSERT(hash == (duk_uint32_t) DUK_HSTRING_GET_HASH(h));
49833 
49834 			h = (const duk_hstring *) h->hdr.h_next;
49835 		}
49836 	}
49837 #endif
49838 	return 1;
49839 }
49840 #else  /* DUK_USE_ROM_STRINGS */
49841 
49842 DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
49843 	duk_bitdecoder_ctx bd_ctx;
49844 	duk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */
49845 	duk_small_uint_t i;
49846 
49847 	duk_memzero(&bd_ctx, sizeof(bd_ctx));
49848 	bd->data = (const duk_uint8_t *) duk_strings_data;
49849 	bd->length = (duk_size_t) DUK_STRDATA_DATA_LENGTH;
49850 
49851 	for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
49852 		duk_uint8_t tmp[DUK_STRDATA_MAX_STRLEN];
49853 		duk_small_uint_t len;
49854 		duk_hstring *h;
49855 
49856 		len = duk_bd_decode_bitpacked_string(bd, tmp);
49857 
49858 		/* No need to length check string: it will never exceed even
49859 		 * the 16-bit length maximum.
49860 		 */
49861 		DUK_ASSERT(len <= 0xffffUL);
49862 		DUK_DDD(DUK_DDDPRINT("intern built-in string %ld", (long) i));
49863 		h = duk_heap_strtable_intern(heap, tmp, len);
49864 		if (!h) {
49865 			goto failed;
49866 		}
49867 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));
49868 
49869 		/* Special flags checks.  Since these strings are always
49870 		 * reachable and a string cannot appear twice in the string
49871 		 * table, there's no need to check/set these flags elsewhere.
49872 		 * The 'internal' flag is set by string intern code.
49873 		 */
49874 		if (i == DUK_STRIDX_EVAL || i == DUK_STRIDX_LC_ARGUMENTS) {
49875 			DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(h);
49876 		}
49877 		if (i >= DUK_STRIDX_START_RESERVED && i < DUK_STRIDX_END_RESERVED) {
49878 			DUK_HSTRING_SET_RESERVED_WORD(h);
49879 			if (i >= DUK_STRIDX_START_STRICT_RESERVED) {
49880 				DUK_HSTRING_SET_STRICT_RESERVED_WORD(h);
49881 			}
49882 		}
49883 
49884 		DUK_DDD(DUK_DDDPRINT("interned: %!O", (duk_heaphdr *) h));
49885 
49886 		/* XXX: The incref macro takes a thread pointer but doesn't
49887 		 * use it right now.
49888 		 */
49889 		DUK_HSTRING_INCREF(_never_referenced_, h);
49890 
49891 #if defined(DUK_USE_HEAPPTR16)
49892 		heap->strs16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
49893 #else
49894 		heap->strs[i] = h;
49895 #endif
49896 	}
49897 
49898 	return 1;
49899 
49900  failed:
49901 	return 0;
49902 }
49903 #endif  /* DUK_USE_ROM_STRINGS */
49904 
49905 DUK_LOCAL duk_bool_t duk__init_heap_thread(duk_heap *heap) {
49906 	duk_hthread *thr;
49907 
49908 	DUK_D(DUK_DPRINT("heap init: alloc heap thread"));
49909 	thr = duk_hthread_alloc_unchecked(heap,
49910 	                                  DUK_HOBJECT_FLAG_EXTENSIBLE |
49911 	                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
49912 	if (thr == NULL) {
49913 		DUK_D(DUK_DPRINT("failed to alloc heap_thread"));
49914 		return 0;
49915 	}
49916 	thr->state = DUK_HTHREAD_STATE_INACTIVE;
49917 #if defined(DUK_USE_ROM_STRINGS)
49918 	/* No strs[] pointer. */
49919 #else  /* DUK_USE_ROM_STRINGS */
49920 #if defined(DUK_USE_HEAPPTR16)
49921 	thr->strs16 = heap->strs16;
49922 #else
49923 	thr->strs = heap->strs;
49924 #endif
49925 #endif  /* DUK_USE_ROM_STRINGS */
49926 
49927 	heap->heap_thread = thr;
49928 	DUK_HTHREAD_INCREF(thr, thr);  /* Note: first argument not really used */
49929 
49930 	/* 'thr' is now reachable */
49931 
49932 	DUK_D(DUK_DPRINT("heap init: init heap thread stacks"));
49933 	if (!duk_hthread_init_stacks(heap, thr)) {
49934 		return 0;
49935 	}
49936 
49937 	/* XXX: this may now fail, and is not handled correctly */
49938 	duk_hthread_create_builtin_objects(thr);
49939 
49940 	/* default prototype */
49941 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) thr, thr->builtins[DUK_BIDX_THREAD_PROTOTYPE]);
49942 
49943 	return 1;
49944 }
49945 
49946 #if defined(DUK_USE_DEBUG)
49947 #define DUK__DUMPSZ(t)  do { \
49948 		DUK_D(DUK_DPRINT("" #t "=%ld", (long) sizeof(t))); \
49949 	} while (0)
49950 
49951 /* These is not 100% because format would need to be non-portable "long long".
49952  * Also print out as doubles to catch cases where the "long" type is not wide
49953  * enough; the limits will then not be printed accurately but the magnitude
49954  * will be correct.
49955  */
49956 #define DUK__DUMPLM_SIGNED_RAW(t,a,b)  do { \
49957 		DUK_D(DUK_DPRINT(t "=[%ld,%ld]=[%lf,%lf]", \
49958 		                 (long) (a), (long) (b), \
49959 		                 (double) (a), (double) (b))); \
49960 	} while (0)
49961 #define DUK__DUMPLM_UNSIGNED_RAW(t,a,b)  do { \
49962 		DUK_D(DUK_DPRINT(t "=[%lu,%lu]=[%lf,%lf]", \
49963 		                 (unsigned long) (a), (unsigned long) (b), \
49964 		                 (double) (a), (double) (b))); \
49965 	} while (0)
49966 #define DUK__DUMPLM_SIGNED(t)  do { \
49967 		DUK__DUMPLM_SIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
49968 	} while (0)
49969 #define DUK__DUMPLM_UNSIGNED(t)  do { \
49970 		DUK__DUMPLM_UNSIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
49971 	} while (0)
49972 
49973 DUK_LOCAL void duk__dump_type_sizes(void) {
49974 	DUK_D(DUK_DPRINT("sizeof()"));
49975 
49976 	/* basic platform types */
49977 	DUK__DUMPSZ(char);
49978 	DUK__DUMPSZ(short);
49979 	DUK__DUMPSZ(int);
49980 	DUK__DUMPSZ(long);
49981 	DUK__DUMPSZ(double);
49982 	DUK__DUMPSZ(void *);
49983 	DUK__DUMPSZ(size_t);
49984 
49985 	/* basic types from duk_features.h */
49986 	DUK__DUMPSZ(duk_uint8_t);
49987 	DUK__DUMPSZ(duk_int8_t);
49988 	DUK__DUMPSZ(duk_uint16_t);
49989 	DUK__DUMPSZ(duk_int16_t);
49990 	DUK__DUMPSZ(duk_uint32_t);
49991 	DUK__DUMPSZ(duk_int32_t);
49992 	DUK__DUMPSZ(duk_uint64_t);
49993 	DUK__DUMPSZ(duk_int64_t);
49994 	DUK__DUMPSZ(duk_uint_least8_t);
49995 	DUK__DUMPSZ(duk_int_least8_t);
49996 	DUK__DUMPSZ(duk_uint_least16_t);
49997 	DUK__DUMPSZ(duk_int_least16_t);
49998 	DUK__DUMPSZ(duk_uint_least32_t);
49999 	DUK__DUMPSZ(duk_int_least32_t);
50000 #if defined(DUK_USE_64BIT_OPS)
50001 	DUK__DUMPSZ(duk_uint_least64_t);
50002 	DUK__DUMPSZ(duk_int_least64_t);
50003 #endif
50004 	DUK__DUMPSZ(duk_uint_fast8_t);
50005 	DUK__DUMPSZ(duk_int_fast8_t);
50006 	DUK__DUMPSZ(duk_uint_fast16_t);
50007 	DUK__DUMPSZ(duk_int_fast16_t);
50008 	DUK__DUMPSZ(duk_uint_fast32_t);
50009 	DUK__DUMPSZ(duk_int_fast32_t);
50010 #if defined(DUK_USE_64BIT_OPS)
50011 	DUK__DUMPSZ(duk_uint_fast64_t);
50012 	DUK__DUMPSZ(duk_int_fast64_t);
50013 #endif
50014 	DUK__DUMPSZ(duk_uintptr_t);
50015 	DUK__DUMPSZ(duk_intptr_t);
50016 	DUK__DUMPSZ(duk_uintmax_t);
50017 	DUK__DUMPSZ(duk_intmax_t);
50018 	DUK__DUMPSZ(duk_double_t);
50019 
50020 	/* important chosen base types */
50021 	DUK__DUMPSZ(duk_int_t);
50022 	DUK__DUMPSZ(duk_uint_t);
50023 	DUK__DUMPSZ(duk_int_fast_t);
50024 	DUK__DUMPSZ(duk_uint_fast_t);
50025 	DUK__DUMPSZ(duk_small_int_t);
50026 	DUK__DUMPSZ(duk_small_uint_t);
50027 	DUK__DUMPSZ(duk_small_int_fast_t);
50028 	DUK__DUMPSZ(duk_small_uint_fast_t);
50029 
50030 	/* some derived types */
50031 	DUK__DUMPSZ(duk_codepoint_t);
50032 	DUK__DUMPSZ(duk_ucodepoint_t);
50033 	DUK__DUMPSZ(duk_idx_t);
50034 	DUK__DUMPSZ(duk_errcode_t);
50035 	DUK__DUMPSZ(duk_uarridx_t);
50036 
50037 	/* tval */
50038 	DUK__DUMPSZ(duk_double_union);
50039 	DUK__DUMPSZ(duk_tval);
50040 
50041 	/* structs from duk_forwdecl.h */
50042 	DUK__DUMPSZ(duk_jmpbuf);  /* just one 'int' for C++ exceptions */
50043 	DUK__DUMPSZ(duk_heaphdr);
50044 	DUK__DUMPSZ(duk_heaphdr_string);
50045 	DUK__DUMPSZ(duk_hstring);
50046 	DUK__DUMPSZ(duk_hstring_external);
50047 	DUK__DUMPSZ(duk_hobject);
50048 	DUK__DUMPSZ(duk_harray);
50049 	DUK__DUMPSZ(duk_hcompfunc);
50050 	DUK__DUMPSZ(duk_hnatfunc);
50051 	DUK__DUMPSZ(duk_hdecenv);
50052 	DUK__DUMPSZ(duk_hobjenv);
50053 	DUK__DUMPSZ(duk_hthread);
50054 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
50055 	DUK__DUMPSZ(duk_hbufobj);
50056 #endif
50057 	DUK__DUMPSZ(duk_hproxy);
50058 	DUK__DUMPSZ(duk_hbuffer);
50059 	DUK__DUMPSZ(duk_hbuffer_fixed);
50060 	DUK__DUMPSZ(duk_hbuffer_dynamic);
50061 	DUK__DUMPSZ(duk_hbuffer_external);
50062 	DUK__DUMPSZ(duk_propaccessor);
50063 	DUK__DUMPSZ(duk_propvalue);
50064 	DUK__DUMPSZ(duk_propdesc);
50065 	DUK__DUMPSZ(duk_heap);
50066 	DUK__DUMPSZ(duk_activation);
50067 	DUK__DUMPSZ(duk_catcher);
50068 	DUK__DUMPSZ(duk_strcache_entry);
50069 	DUK__DUMPSZ(duk_litcache_entry);
50070 	DUK__DUMPSZ(duk_ljstate);
50071 	DUK__DUMPSZ(duk_fixedbuffer);
50072 	DUK__DUMPSZ(duk_bitdecoder_ctx);
50073 	DUK__DUMPSZ(duk_bitencoder_ctx);
50074 	DUK__DUMPSZ(duk_token);
50075 	DUK__DUMPSZ(duk_re_token);
50076 	DUK__DUMPSZ(duk_lexer_point);
50077 	DUK__DUMPSZ(duk_lexer_ctx);
50078 	DUK__DUMPSZ(duk_compiler_instr);
50079 	DUK__DUMPSZ(duk_compiler_func);
50080 	DUK__DUMPSZ(duk_compiler_ctx);
50081 	DUK__DUMPSZ(duk_re_matcher_ctx);
50082 	DUK__DUMPSZ(duk_re_compiler_ctx);
50083 }
50084 DUK_LOCAL void duk__dump_type_limits(void) {
50085 	DUK_D(DUK_DPRINT("limits"));
50086 
50087 	/* basic types */
50088 	DUK__DUMPLM_SIGNED(INT8);
50089 	DUK__DUMPLM_UNSIGNED(UINT8);
50090 	DUK__DUMPLM_SIGNED(INT_FAST8);
50091 	DUK__DUMPLM_UNSIGNED(UINT_FAST8);
50092 	DUK__DUMPLM_SIGNED(INT_LEAST8);
50093 	DUK__DUMPLM_UNSIGNED(UINT_LEAST8);
50094 	DUK__DUMPLM_SIGNED(INT16);
50095 	DUK__DUMPLM_UNSIGNED(UINT16);
50096 	DUK__DUMPLM_SIGNED(INT_FAST16);
50097 	DUK__DUMPLM_UNSIGNED(UINT_FAST16);
50098 	DUK__DUMPLM_SIGNED(INT_LEAST16);
50099 	DUK__DUMPLM_UNSIGNED(UINT_LEAST16);
50100 	DUK__DUMPLM_SIGNED(INT32);
50101 	DUK__DUMPLM_UNSIGNED(UINT32);
50102 	DUK__DUMPLM_SIGNED(INT_FAST32);
50103 	DUK__DUMPLM_UNSIGNED(UINT_FAST32);
50104 	DUK__DUMPLM_SIGNED(INT_LEAST32);
50105 	DUK__DUMPLM_UNSIGNED(UINT_LEAST32);
50106 #if defined(DUK_USE_64BIT_OPS)
50107 	DUK__DUMPLM_SIGNED(INT64);
50108 	DUK__DUMPLM_UNSIGNED(UINT64);
50109 	DUK__DUMPLM_SIGNED(INT_FAST64);
50110 	DUK__DUMPLM_UNSIGNED(UINT_FAST64);
50111 	DUK__DUMPLM_SIGNED(INT_LEAST64);
50112 	DUK__DUMPLM_UNSIGNED(UINT_LEAST64);
50113 #endif
50114 	DUK__DUMPLM_SIGNED(INTPTR);
50115 	DUK__DUMPLM_UNSIGNED(UINTPTR);
50116 	DUK__DUMPLM_SIGNED(INTMAX);
50117 	DUK__DUMPLM_UNSIGNED(UINTMAX);
50118 
50119 	/* derived types */
50120 	DUK__DUMPLM_SIGNED(INT);
50121 	DUK__DUMPLM_UNSIGNED(UINT);
50122 	DUK__DUMPLM_SIGNED(INT_FAST);
50123 	DUK__DUMPLM_UNSIGNED(UINT_FAST);
50124 	DUK__DUMPLM_SIGNED(SMALL_INT);
50125 	DUK__DUMPLM_UNSIGNED(SMALL_UINT);
50126 	DUK__DUMPLM_SIGNED(SMALL_INT_FAST);
50127 	DUK__DUMPLM_UNSIGNED(SMALL_UINT_FAST);
50128 }
50129 
50130 DUK_LOCAL void duk__dump_misc_options(void) {
50131 	DUK_D(DUK_DPRINT("DUK_VERSION: %ld", (long) DUK_VERSION));
50132 	DUK_D(DUK_DPRINT("DUK_GIT_DESCRIBE: %s", DUK_GIT_DESCRIBE));
50133 	DUK_D(DUK_DPRINT("OS string: %s", DUK_USE_OS_STRING));
50134 	DUK_D(DUK_DPRINT("architecture string: %s", DUK_USE_ARCH_STRING));
50135 	DUK_D(DUK_DPRINT("compiler string: %s", DUK_USE_COMPILER_STRING));
50136 	DUK_D(DUK_DPRINT("debug level: %ld", (long) DUK_USE_DEBUG_LEVEL));
50137 #if defined(DUK_USE_PACKED_TVAL)
50138 	DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: yes"));
50139 #else
50140 	DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: no"));
50141 #endif
50142 #if defined(DUK_USE_VARIADIC_MACROS)
50143 	DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: yes"));
50144 #else
50145 	DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: no"));
50146 #endif
50147 #if defined(DUK_USE_INTEGER_LE)
50148 	DUK_D(DUK_DPRINT("integer endianness: little"));
50149 #elif defined(DUK_USE_INTEGER_ME)
50150 	DUK_D(DUK_DPRINT("integer endianness: mixed"));
50151 #elif defined(DUK_USE_INTEGER_BE)
50152 	DUK_D(DUK_DPRINT("integer endianness: big"));
50153 #else
50154 	DUK_D(DUK_DPRINT("integer endianness: ???"));
50155 #endif
50156 #if defined(DUK_USE_DOUBLE_LE)
50157 	DUK_D(DUK_DPRINT("IEEE double endianness: little"));
50158 #elif defined(DUK_USE_DOUBLE_ME)
50159 	DUK_D(DUK_DPRINT("IEEE double endianness: mixed"));
50160 #elif defined(DUK_USE_DOUBLE_BE)
50161 	DUK_D(DUK_DPRINT("IEEE double endianness: big"));
50162 #else
50163 	DUK_D(DUK_DPRINT("IEEE double endianness: ???"));
50164 #endif
50165 }
50166 #endif  /* DUK_USE_DEBUG */
50167 
50168 DUK_INTERNAL
50169 duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
50170                          duk_realloc_function realloc_func,
50171                          duk_free_function free_func,
50172                          void *heap_udata,
50173                          duk_fatal_function fatal_func) {
50174 	duk_heap *res = NULL;
50175 	duk_uint32_t st_initsize;
50176 
50177 	DUK_D(DUK_DPRINT("allocate heap"));
50178 
50179 	/*
50180 	 *  Random config sanity asserts
50181 	 */
50182 
50183 	DUK_ASSERT(DUK_USE_STRTAB_MINSIZE >= 64);
50184 
50185 	DUK_ASSERT((DUK_HTYPE_STRING & 0x01U) == 0);
50186 	DUK_ASSERT((DUK_HTYPE_BUFFER & 0x01U) == 0);
50187 	DUK_ASSERT((DUK_HTYPE_OBJECT & 0x01U) == 1);  /* DUK_HEAPHDR_IS_OBJECT() relies ont his. */
50188 
50189 	/*
50190 	 *  Debug dump type sizes
50191 	 */
50192 
50193 #if defined(DUK_USE_DEBUG)
50194 	duk__dump_misc_options();
50195 	duk__dump_type_sizes();
50196 	duk__dump_type_limits();
50197 #endif
50198 
50199 	/*
50200 	 *  If selftests enabled, run them as early as possible.
50201 	 */
50202 
50203 #if defined(DUK_USE_SELF_TESTS)
50204 	DUK_D(DUK_DPRINT("run self tests"));
50205 	if (duk_selftest_run_tests(alloc_func, realloc_func, free_func, heap_udata) > 0) {
50206 		fatal_func(heap_udata, "self test(s) failed");
50207 	}
50208 	DUK_D(DUK_DPRINT("self tests passed"));
50209 #endif
50210 
50211 	/*
50212 	 *  Important assert-like checks that should be enabled even
50213 	 *  when assertions are otherwise not enabled.
50214 	 */
50215 
50216 #if defined(DUK_USE_EXEC_REGCONST_OPTIMIZE)
50217 	/* Can't check sizeof() using preprocessor so explicit check.
50218 	 * This will be optimized away in practice; unfortunately a
50219 	 * warning is generated on some compilers as a result.
50220 	 */
50221 #if defined(DUK_USE_PACKED_TVAL)
50222 	if (sizeof(duk_tval) != 8) {
50223 #else
50224 	if (sizeof(duk_tval) != 16) {
50225 #endif
50226 		fatal_func(heap_udata, "sizeof(duk_tval) not 8 or 16, cannot use DUK_USE_EXEC_REGCONST_OPTIMIZE option");
50227 	}
50228 #endif  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
50229 
50230 	/*
50231 	 *  Computed values (e.g. INFINITY)
50232 	 */
50233 
50234 #if defined(DUK_USE_COMPUTED_NAN)
50235 	do {
50236 		/* Workaround for some exotic platforms where NAN is missing
50237 		 * and the expression (0.0 / 0.0) does NOT result in a NaN.
50238 		 * Such platforms use the global 'duk_computed_nan' which must
50239 		 * be initialized at runtime.  Use 'volatile' to ensure that
50240 		 * the compiler will actually do the computation and not try
50241 		 * to do constant folding which might result in the original
50242 		 * problem.
50243 		 */
50244 		volatile double dbl1 = 0.0;
50245 		volatile double dbl2 = 0.0;
50246 		duk_computed_nan = dbl1 / dbl2;
50247 	} while (0);
50248 #endif
50249 
50250 #if defined(DUK_USE_COMPUTED_INFINITY)
50251 	do {
50252 		/* Similar workaround for INFINITY. */
50253 		volatile double dbl1 = 1.0;
50254 		volatile double dbl2 = 0.0;
50255 		duk_computed_infinity = dbl1 / dbl2;
50256 	} while (0);
50257 #endif
50258 
50259 	/*
50260 	 *  Allocate heap struct
50261 	 *
50262 	 *  Use a raw call, all macros expect the heap to be initialized
50263 	 */
50264 
50265 #if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 1)
50266 	goto failed;
50267 #endif
50268 	DUK_D(DUK_DPRINT("alloc duk_heap object"));
50269 	res = (duk_heap *) alloc_func(heap_udata, sizeof(duk_heap));
50270 	if (!res) {
50271 		goto failed;
50272 	}
50273 
50274 	/*
50275 	 *  Zero the struct, and start initializing roughly in order
50276 	 */
50277 
50278 	duk_memzero(res, sizeof(*res));
50279 #if defined(DUK_USE_ASSERTIONS)
50280 	res->heap_initializing = 1;
50281 #endif
50282 
50283 	/* explicit NULL inits */
50284 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
50285 	res->heap_udata = NULL;
50286 	res->heap_allocated = NULL;
50287 #if defined(DUK_USE_REFERENCE_COUNTING)
50288 	res->refzero_list = NULL;
50289 #endif
50290 #if defined(DUK_USE_FINALIZER_SUPPORT)
50291 	res->finalize_list = NULL;
50292 #if defined(DUK_USE_ASSERTIONS)
50293 	res->currently_finalizing = NULL;
50294 #endif
50295 #endif
50296 #if defined(DUK_USE_CACHE_ACTIVATION)
50297 	res->activation_free = NULL;
50298 #endif
50299 #if defined(DUK_USE_CACHE_CATCHER)
50300 	res->catcher_free = NULL;
50301 #endif
50302 	res->heap_thread = NULL;
50303 	res->curr_thread = NULL;
50304 	res->heap_object = NULL;
50305 #if defined(DUK_USE_STRTAB_PTRCOMP)
50306 	res->strtable16 = NULL;
50307 #else
50308 	res->strtable = NULL;
50309 #endif
50310 #if defined(DUK_USE_ROM_STRINGS)
50311 	/* no res->strs[] */
50312 #else  /* DUK_USE_ROM_STRINGS */
50313 #if defined(DUK_USE_HEAPPTR16)
50314 	/* res->strs16[] is zeroed and zero decodes to NULL, so no NULL inits. */
50315 #else
50316 	{
50317 		duk_small_uint_t i;
50318 	        for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
50319 			res->strs[i] = NULL;
50320 	        }
50321 	}
50322 #endif
50323 #endif  /* DUK_USE_ROM_STRINGS */
50324 #if defined(DUK_USE_DEBUGGER_SUPPORT)
50325 	res->dbg_read_cb = NULL;
50326 	res->dbg_write_cb = NULL;
50327 	res->dbg_peek_cb = NULL;
50328 	res->dbg_read_flush_cb = NULL;
50329 	res->dbg_write_flush_cb = NULL;
50330 	res->dbg_request_cb = NULL;
50331 	res->dbg_udata = NULL;
50332 	res->dbg_pause_act = NULL;
50333 #endif
50334 #endif  /* DUK_USE_EXPLICIT_NULL_INIT */
50335 
50336 	res->alloc_func = alloc_func;
50337 	res->realloc_func = realloc_func;
50338 	res->free_func = free_func;
50339 	res->heap_udata = heap_udata;
50340 	res->fatal_func = fatal_func;
50341 
50342 	/* XXX: for now there's a pointer packing zero assumption, i.e.
50343 	 * NULL <=> compressed pointer 0.  If this is removed, may need
50344 	 * to precompute e.g. null16 here.
50345 	 */
50346 
50347 	/* res->ms_trigger_counter == 0 -> now causes immediate GC; which is OK */
50348 
50349 	/* Prevent mark-and-sweep and finalizer execution until heap is completely
50350 	 * initialized.
50351 	 */
50352 	DUK_ASSERT(res->ms_prevent_count == 0);
50353 	DUK_ASSERT(res->pf_prevent_count == 0);
50354 	res->ms_prevent_count = 1;
50355 	res->pf_prevent_count = 1;
50356 	DUK_ASSERT(res->ms_running == 0);
50357 
50358 	res->call_recursion_depth = 0;
50359 	res->call_recursion_limit = DUK_USE_NATIVE_CALL_RECLIMIT;
50360 
50361 	/* XXX: use the pointer as a seed for now: mix in time at least */
50362 
50363 	/* The casts through duk_uintptr_t is to avoid the following GCC warning:
50364 	 *
50365 	 *   warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
50366 	 *
50367 	 * This still generates a /Wp64 warning on VS2010 when compiling for x86.
50368 	 */
50369 #if defined(DUK_USE_ROM_STRINGS)
50370 	/* XXX: make a common DUK_USE_ option, and allow custom fixed seed? */
50371 	DUK_D(DUK_DPRINT("using rom strings, force heap hash_seed to fixed value 0x%08lx", (long) DUK__FIXED_HASH_SEED));
50372 	res->hash_seed = (duk_uint32_t) DUK__FIXED_HASH_SEED;
50373 #else  /* DUK_USE_ROM_STRINGS */
50374 	res->hash_seed = (duk_uint32_t) (duk_uintptr_t) res;
50375 #if !defined(DUK_USE_STRHASH_DENSE)
50376 	res->hash_seed ^= 5381;  /* Bernstein hash init value is normally 5381; XOR it in in case pointer low bits are 0 */
50377 #endif
50378 #endif  /* DUK_USE_ROM_STRINGS */
50379 
50380 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
50381 	res->lj.jmpbuf_ptr = NULL;
50382 #endif
50383 	DUK_ASSERT(res->lj.type == DUK_LJ_TYPE_UNKNOWN);  /* zero */
50384 	DUK_ASSERT(res->lj.iserror == 0);
50385 	DUK_TVAL_SET_UNDEFINED(&res->lj.value1);
50386 	DUK_TVAL_SET_UNDEFINED(&res->lj.value2);
50387 
50388 	DUK_ASSERT_LJSTATE_UNSET(res);
50389 
50390 	/*
50391 	 *  Init stringtable: fixed variant
50392 	 */
50393 
50394 	st_initsize = DUK_USE_STRTAB_MINSIZE;
50395 #if defined(DUK_USE_STRTAB_PTRCOMP)
50396 	res->strtable16 = (duk_uint16_t *) alloc_func(heap_udata, sizeof(duk_uint16_t) * st_initsize);
50397 	if (res->strtable16 == NULL) {
50398 		goto failed;
50399 	}
50400 #else
50401 	res->strtable = (duk_hstring **) alloc_func(heap_udata, sizeof(duk_hstring *) * st_initsize);
50402 	if (res->strtable == NULL) {
50403 		goto failed;
50404 	}
50405 #endif
50406 	res->st_size = st_initsize;
50407 	res->st_mask = st_initsize - 1;
50408 #if (DUK_USE_STRTAB_MINSIZE != DUK_USE_STRTAB_MAXSIZE)
50409 	DUK_ASSERT(res->st_count == 0);
50410 #endif
50411 
50412 #if defined(DUK_USE_STRTAB_PTRCOMP)
50413 	/* zero assumption */
50414 	duk_memzero(res->strtable16, sizeof(duk_uint16_t) * st_initsize);
50415 #else
50416 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
50417 	{
50418 		duk_uint32_t i;
50419 	        for (i = 0; i < st_initsize; i++) {
50420 			res->strtable[i] = NULL;
50421 	        }
50422 	}
50423 #else
50424 	duk_memzero(res->strtable, sizeof(duk_hstring *) * st_initsize);
50425 #endif  /* DUK_USE_EXPLICIT_NULL_INIT */
50426 #endif  /* DUK_USE_STRTAB_PTRCOMP */
50427 
50428 	/*
50429 	 *  Init stringcache
50430 	 */
50431 
50432 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
50433 	{
50434 		duk_uint_t i;
50435 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
50436 			res->strcache[i].h = NULL;
50437 		}
50438 	}
50439 #endif
50440 
50441 	/*
50442 	 *  Init litcache
50443 	 */
50444 #if defined(DUK_USE_LITCACHE_SIZE)
50445 	DUK_ASSERT(DUK_USE_LITCACHE_SIZE > 0);
50446 	DUK_ASSERT(DUK_IS_POWER_OF_TWO((duk_uint_t) DUK_USE_LITCACHE_SIZE));
50447 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
50448 	{
50449 		duk_uint_t i;
50450 		for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
50451 			res->litcache[i].addr = NULL;
50452 			res->litcache[i].h = NULL;
50453 		}
50454 	}
50455 #endif
50456 #endif  /* DUK_USE_LITCACHE_SIZE */
50457 
50458 	/* XXX: error handling is incomplete.  It would be cleanest if
50459 	 * there was a setjmp catchpoint, so that all init code could
50460 	 * freely throw errors.  If that were the case, the return code
50461 	 * passing here could be removed.
50462 	 */
50463 
50464 	/*
50465 	 *  Init built-in strings
50466 	 */
50467 
50468 #if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 2)
50469 	goto failed;
50470 #endif
50471 	DUK_D(DUK_DPRINT("heap init: initialize heap strings"));
50472 	if (!duk__init_heap_strings(res)) {
50473 		goto failed;
50474 	}
50475 
50476 	/*
50477 	 *  Init the heap thread
50478 	 */
50479 
50480 #if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 3)
50481 	goto failed;
50482 #endif
50483 	DUK_D(DUK_DPRINT("heap init: initialize heap thread"));
50484 	if (!duk__init_heap_thread(res)) {
50485 		goto failed;
50486 	}
50487 
50488 	/*
50489 	 *  Init the heap object
50490 	 */
50491 
50492 #if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 4)
50493 	goto failed;
50494 #endif
50495 	DUK_D(DUK_DPRINT("heap init: initialize heap object"));
50496 	DUK_ASSERT(res->heap_thread != NULL);
50497 	res->heap_object = duk_hobject_alloc_unchecked(res, DUK_HOBJECT_FLAG_EXTENSIBLE |
50498 	                                                    DUK_HOBJECT_FLAG_FASTREFS |
50499 	                                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT));
50500 	if (res->heap_object == NULL) {
50501 		goto failed;
50502 	}
50503 	DUK_HOBJECT_INCREF(res->heap_thread, res->heap_object);
50504 
50505 	/*
50506 	 *  Odds and ends depending on the heap thread
50507 	 */
50508 
50509 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
50510 #if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
50511 	res->rnd_state = (duk_uint32_t) duk_time_get_ecmascript_time(res->heap_thread);
50512 	duk_util_tinyrandom_prepare_seed(res->heap_thread);
50513 #else
50514 	res->rnd_state[0] = (duk_uint64_t) duk_time_get_ecmascript_time(res->heap_thread);
50515 	DUK_ASSERT(res->rnd_state[1] == 0);  /* Not filled here, filled in by seed preparation. */
50516 #if 0  /* Manual test values matching misc/xoroshiro128plus_test.c. */
50517 	res->rnd_state[0] = DUK_U64_CONSTANT(0xdeadbeef12345678);
50518 	res->rnd_state[1] = DUK_U64_CONSTANT(0xcafed00d12345678);
50519 #endif
50520 	duk_util_tinyrandom_prepare_seed(res->heap_thread);
50521 	/* Mix in heap pointer: this ensures that if two Duktape heaps are
50522 	 * created on the same millisecond, they get a different PRNG
50523 	 * sequence (unless e.g. virtual memory addresses cause also the
50524 	 * heap object pointer to be the same).
50525 	 */
50526 	{
50527 		duk_uint64_t tmp_u64;
50528 		tmp_u64 = 0;
50529 		duk_memcpy((void *) &tmp_u64,
50530 		           (const void *) &res,
50531 		           (size_t) (sizeof(void *) >= sizeof(duk_uint64_t) ? sizeof(duk_uint64_t) : sizeof(void *)));
50532 		res->rnd_state[1] ^= tmp_u64;
50533 	}
50534 	do {
50535 		duk_small_uint_t i;
50536 		for (i = 0; i < 10; i++) {
50537 			/* Throw away a few initial random numbers just in
50538 			 * case.  Probably unnecessary due to SplitMix64
50539 			 * preparation.
50540 			 */
50541 			(void) duk_util_tinyrandom_get_double(res->heap_thread);
50542 		}
50543 	} while (0);
50544 #endif
50545 #endif
50546 
50547 	/*
50548 	 *  Allow finalizer and mark-and-sweep processing.
50549 	 */
50550 
50551 	DUK_D(DUK_DPRINT("heap init: allow finalizer/mark-and-sweep processing"));
50552 	DUK_ASSERT(res->ms_prevent_count == 1);
50553 	DUK_ASSERT(res->pf_prevent_count == 1);
50554 	res->ms_prevent_count = 0;
50555 	res->pf_prevent_count = 0;
50556 	DUK_ASSERT(res->ms_running == 0);
50557 #if defined(DUK_USE_ASSERTIONS)
50558 	res->heap_initializing = 0;
50559 #endif
50560 
50561 	/*
50562 	 *  All done.
50563 	 */
50564 
50565 	DUK_D(DUK_DPRINT("allocated heap: %p", (void *) res));
50566 	return res;
50567 
50568  failed:
50569 	DUK_D(DUK_DPRINT("heap allocation failed"));
50570 
50571 	if (res != NULL) {
50572 		/* Assumes that allocated pointers and alloc funcs are valid
50573 		 * if res exists.
50574 		 */
50575 		DUK_ASSERT(res->ms_prevent_count == 1);
50576 		DUK_ASSERT(res->pf_prevent_count == 1);
50577 		DUK_ASSERT(res->ms_running == 0);
50578 		if (res->heap_thread != NULL) {
50579 			res->ms_prevent_count = 0;
50580 			res->pf_prevent_count = 0;
50581 		}
50582 #if defined(DUK_USE_ASSERTIONS)
50583 		res->heap_initializing = 0;
50584 #endif
50585 
50586 		DUK_ASSERT(res->alloc_func != NULL);
50587 		DUK_ASSERT(res->realloc_func != NULL);
50588 		DUK_ASSERT(res->free_func != NULL);
50589 		duk_heap_free(res);
50590 	}
50591 
50592 	return NULL;
50593 }
50594 
50595 /* automatic undefs */
50596 #undef DUK__DUMPLM_SIGNED
50597 #undef DUK__DUMPLM_SIGNED_RAW
50598 #undef DUK__DUMPLM_UNSIGNED
50599 #undef DUK__DUMPLM_UNSIGNED_RAW
50600 #undef DUK__DUMPSZ
50601 #undef DUK__FIXED_HASH_SEED
50602 #line 1 "duk_heap_finalize.c"
50603 /*
50604  *  Finalizer handling.
50605  */
50606 
50607 /* #include duk_internal.h -> already included */
50608 
50609 #if defined(DUK_USE_FINALIZER_SUPPORT)
50610 
50611 /*
50612  *  Fake torture finalizer.
50613  */
50614 
50615 #if defined(DUK_USE_FINALIZER_TORTURE)
50616 DUK_LOCAL duk_ret_t duk__fake_global_finalizer(duk_hthread *thr) {
50617 	DUK_DD(DUK_DDPRINT("fake global torture finalizer executed"));
50618 
50619 	/* Require a lot of stack to force a value stack grow/shrink. */
50620 	duk_require_stack(thr, 100000);
50621 
50622 	/* Force a reallocation with pointer change for value stack
50623 	 * to maximize side effects.
50624 	 */
50625 	duk_hthread_valstack_torture_realloc(thr);
50626 
50627 	/* Inner function call, error throw. */
50628 	duk_eval_string_noresult(thr,
50629 		"(function dummy() {\n"
50630 		"    dummy.prototype = null;  /* break reference loop */\n"
50631 		"    try {\n"
50632 		"        throw 'fake-finalizer-dummy-error';\n"
50633 		"    } catch (e) {\n"
50634 		"        void e;\n"
50635 		"    }\n"
50636 		"})()");
50637 
50638 	/* The above creates garbage (e.g. a function instance).  Because
50639 	 * the function/prototype reference loop is broken, it gets collected
50640 	 * immediately by DECREF.  If Function.prototype has a _Finalizer
50641 	 * property (happens in some test cases), the garbage gets queued to
50642 	 * finalize_list.  This still won't cause an infinite loop because
50643 	 * the torture finalizer is called once per finalize_list run and
50644 	 * the garbage gets handled in the same run.  (If the garbage needs
50645 	 * mark-and-sweep collection, an infinite loop might ensue.)
50646 	 */
50647 	return 0;
50648 }
50649 
50650 DUK_LOCAL void duk__run_global_torture_finalizer(duk_hthread *thr) {
50651 	DUK_ASSERT(thr != NULL);
50652 
50653 	/* Avoid fake finalization when callstack limit is near.  Otherwise
50654 	 * a callstack limit error will be created, then refzero'ed.  The
50655 	 * +5 headroom is conservative.
50656 	 */
50657 	if (thr->heap->call_recursion_depth + 5 >= thr->heap->call_recursion_limit ||
50658 	    thr->callstack_top + 5 >= DUK_USE_CALLSTACK_LIMIT) {
50659 		DUK_D(DUK_DPRINT("skip global torture finalizer, too little headroom for call recursion or call stack size"));
50660 		return;
50661 	}
50662 
50663 	/* Run fake finalizer.  Avoid creating unnecessary garbage. */
50664 	duk_push_c_function(thr, duk__fake_global_finalizer, 0 /*nargs*/);
50665 	(void) duk_pcall(thr, 0 /*nargs*/);
50666 	duk_pop(thr);
50667 }
50668 #endif  /* DUK_USE_FINALIZER_TORTURE */
50669 
50670 /*
50671  *  Process the finalize_list to completion.
50672  *
50673  *  An object may be placed on finalize_list by either refcounting or
50674  *  mark-and-sweep.  The refcount of objects placed by refcounting will be
50675  *  zero; the refcount of objects placed by mark-and-sweep is > 0.  In both
50676  *  cases the refcount is bumped by 1 artificially so that a REFZERO event
50677  *  can never happen while an object is waiting for finalization.  Without
50678  *  this bump a REFZERO could now happen because user code may call
50679  *  duk_push_heapptr() and then pop a value even when it's on finalize_list.
50680  *
50681  *  List processing assumes refcounts are kept up-to-date at all times, so
50682  *  that once the finalizer returns, a zero refcount is a reliable reason to
50683  *  free the object immediately rather than place it back to the heap.  This
50684  *  is the case because we run outside of refzero_list processing so that
50685  *  DECREF cascades are handled fully inline.
50686  *
50687  *  For mark-and-sweep queued objects (had_zero_refcount false) the object
50688  *  may be freed immediately if its refcount is zero after the finalizer call
50689  *  (i.e. finalizer removed the reference loop for the object).  If not, the
50690  *  next mark-and-sweep will collect the object unless it has become reachable
50691  *  (i.e. rescued) by that time and its refcount hasn't fallen to zero before
50692  *  that.  Mark-and-sweep detects these objects because their FINALIZED flag
50693  *  is set.
50694  *
50695  *  There's an inherent limitation for mark-and-sweep finalizer rescuing: an
50696  *  object won't get refinalized if (1) it's rescued, but (2) becomes
50697  *  unreachable before mark-and-sweep has had time to notice it.  The next
50698  *  mark-and-sweep round simply doesn't have any information of whether the
50699  *  object has been unreachable the whole time or not (the only way to get
50700  *  that information would be a mark-and-sweep pass for *every finalized
50701  *  object*).  This is awkward for the application because the mark-and-sweep
50702  *  round is not generally visible or under full application control.
50703  *
50704  *  For refcount queued objects (had_zero_refcount true) the object is either
50705  *  immediately freed or rescued, and waiting for a mark-and-sweep round is not
50706  *  necessary (or desirable); FINALIZED is cleared when a rescued object is
50707  *  queued back to heap_allocated.  The object is eligible for finalization
50708  *  again (either via refcounting or mark-and-sweep) immediately after being
50709  *  rescued.  If a refcount finalized object is placed into an unreachable
50710  *  reference loop by its finalizer, it will get collected by mark-and-sweep
50711  *  and currently the finalizer will execute again.
50712  *
50713  *  There's a special case where:
50714  *
50715  *    - Mark-and-sweep queues an object to finalize_list for finalization.
50716  *    - The finalizer is executed, FINALIZED is set, and object is queued
50717  *      back to heap_allocated, waiting for a new mark-and-sweep round.
50718  *    - The object's refcount drops to zero before mark-and-sweep has a
50719  *      chance to run another round and make a rescue/free decision.
50720  *
50721  *  This is now handled by refzero code: if an object has a finalizer but
50722  *  FINALIZED is already set, the object is freed without finalizer processing.
50723  *  The outcome is the same as if mark-and-sweep was executed at that point;
50724  *  mark-and-sweep would also free the object without another finalizer run.
50725  *  This could also be changed so that the refzero-triggered finalizer *IS*
50726  *  executed: being refzero collected implies someone has operated on the
50727  *  object so it hasn't been totally unreachable the whole time.  This would
50728  *  risk a finalizer loop however.
50729  */
50730 
50731 DUK_INTERNAL void duk_heap_process_finalize_list(duk_heap *heap) {
50732 	duk_heaphdr *curr;
50733 #if defined(DUK_USE_DEBUG)
50734 	duk_size_t count = 0;
50735 #endif
50736 
50737 	DUK_DDD(DUK_DDDPRINT("duk_heap_process_finalize_list: %p", (void *) heap));
50738 
50739 	if (heap->pf_prevent_count != 0) {
50740 		DUK_DDD(DUK_DDDPRINT("skip finalize_list processing: pf_prevent_count != 0"));
50741 		return;
50742 	}
50743 
50744 	/* Heap alloc prevents mark-and-sweep before heap_thread is ready. */
50745 	DUK_ASSERT(heap != NULL);
50746 	DUK_ASSERT(heap->heap_thread != NULL);
50747 	DUK_ASSERT(heap->heap_thread->valstack != NULL);
50748 #if defined(DUK_USE_REFERENCE_COUNTING)
50749 	DUK_ASSERT(heap->refzero_list == NULL);
50750 #endif
50751 
50752 	DUK_ASSERT(heap->pf_prevent_count == 0);
50753 	heap->pf_prevent_count = 1;
50754 
50755 	/* Mark-and-sweep no longer needs to be prevented when running
50756 	 * finalizers: mark-and-sweep skips any rescue decisions if there
50757 	 * are any objects in finalize_list when mark-and-sweep is entered.
50758 	 * This protects finalized objects from incorrect rescue decisions
50759 	 * caused by finalize_list being a reachability root and only
50760 	 * partially processed.  Freeing decisions are not postponed.
50761 	 */
50762 
50763 	/* When finalizer torture is enabled, make a fake finalizer call with
50764 	 * maximum side effects regardless of whether finalize_list is empty.
50765 	 */
50766 #if defined(DUK_USE_FINALIZER_TORTURE)
50767 	duk__run_global_torture_finalizer(heap->heap_thread);
50768 #endif
50769 
50770 	/* Process finalize_list until it becomes empty.  There's currently no
50771 	 * protection against a finalizer always creating more garbage.
50772 	 */
50773 	while ((curr = heap->finalize_list) != NULL) {
50774 #if defined(DUK_USE_REFERENCE_COUNTING)
50775 		duk_bool_t queue_back;
50776 #endif
50777 
50778 		DUK_DD(DUK_DDPRINT("processing finalize_list entry: %p -> %!iO", (void *) curr, curr));
50779 
50780 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* Only objects have finalizers. */
50781 		DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr));
50782 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(curr));
50783 		DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(curr));  /* All objects on finalize_list will have this flag (except object being finalized right now). */
50784 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));   /* Queueing code ensures. */
50785 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr));  /* ROM objects never get freed (or finalized). */
50786 
50787 #if defined(DUK_USE_ASSERTIONS)
50788 		DUK_ASSERT(heap->currently_finalizing == NULL);
50789 		heap->currently_finalizing = curr;
50790 #endif
50791 
50792 		/* Clear FINALIZABLE for object being finalized, so that
50793 		 * duk_push_heapptr() can properly ignore the object.
50794 		 */
50795 		DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
50796 
50797 		if (DUK_LIKELY(!heap->pf_skip_finalizers)) {
50798 			/* Run the finalizer, duk_heap_run_finalizer() sets
50799 			 * and checks for FINALIZED to prevent the finalizer
50800 			 * from executing multiple times per finalization cycle.
50801 			 * (This safeguard shouldn't be actually needed anymore).
50802 			 */
50803 
50804 #if defined(DUK_USE_REFERENCE_COUNTING)
50805 			duk_bool_t had_zero_refcount;
50806 #endif
50807 
50808 			/* The object's refcount is >0 throughout so it won't be
50809 			 * refzero processed prematurely.
50810 			 */
50811 #if defined(DUK_USE_REFERENCE_COUNTING)
50812 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);
50813 			had_zero_refcount = (DUK_HEAPHDR_GET_REFCOUNT(curr) == 1);  /* Preincremented on finalize_list insert. */
50814 #endif
50815 
50816 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
50817 			duk_heap_run_finalizer(heap, (duk_hobject *) curr);  /* must never longjmp */
50818 			DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(curr));
50819 			/* XXX: assert that object is still in finalize_list
50820 			 * when duk_push_heapptr() allows automatic rescue.
50821 			 */
50822 
50823 #if defined(DUK_USE_REFERENCE_COUNTING)
50824 			DUK_DD(DUK_DDPRINT("refcount after finalizer (includes bump): %ld", (long) DUK_HEAPHDR_GET_REFCOUNT(curr)));
50825 			if (DUK_HEAPHDR_GET_REFCOUNT(curr) == 1) {  /* Only artificial bump in refcount? */
50826 #if defined(DUK_USE_DEBUG)
50827 				if (had_zero_refcount) {
50828 					DUK_DD(DUK_DDPRINT("finalized object's refcount is zero -> free immediately (refcount queued)"));
50829 				} else {
50830 					DUK_DD(DUK_DDPRINT("finalized object's refcount is zero -> free immediately (mark-and-sweep queued)"));
50831 				}
50832 #endif
50833 				queue_back = 0;
50834 			} else
50835 #endif
50836 			{
50837 #if defined(DUK_USE_REFERENCE_COUNTING)
50838 				queue_back = 1;
50839 				if (had_zero_refcount) {
50840 					/* When finalization is triggered
50841 					 * by refzero and we queue the object
50842 					 * back, clear FINALIZED right away
50843 					 * so that the object can be refinalized
50844 					 * immediately if necessary.
50845 					 */
50846 					DUK_HEAPHDR_CLEAR_FINALIZED(curr);
50847 				}
50848 #endif
50849 			}
50850 		} else {
50851 			/* Used during heap destruction: don't actually run finalizers
50852 			 * because we're heading into forced finalization.  Instead,
50853 			 * queue finalizable objects back to the heap_allocated list.
50854 			 */
50855 			DUK_D(DUK_DPRINT("skip finalizers flag set, queue object to heap_allocated without finalizing"));
50856 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
50857 #if defined(DUK_USE_REFERENCE_COUNTING)
50858 			queue_back = 1;
50859 #endif
50860 		}
50861 
50862 		/* Dequeue object from finalize_list.  Note that 'curr' may no
50863 		 * longer be finalize_list head because new objects may have
50864 		 * been queued to the list.  As a result we can't optimize for
50865 		 * the single-linked heap case and must scan the list for
50866 		 * removal, typically the scan is very short however.
50867 		 */
50868 		DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(heap, curr);
50869 
50870 		/* Queue back to heap_allocated or free immediately. */
50871 #if defined(DUK_USE_REFERENCE_COUNTING)
50872 		if (queue_back) {
50873 			/* FINALIZED is only cleared if object originally
50874 			 * queued for finalization by refcounting.  For
50875 			 * mark-and-sweep FINALIZED is left set, so that
50876 			 * next mark-and-sweep round can make a rescue/free
50877 			 * decision.
50878 			 */
50879 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);
50880 			DUK_HEAPHDR_PREDEC_REFCOUNT(curr);  /* Remove artificial refcount bump. */
50881 			DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
50882 			DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, curr);
50883 		} else {
50884 			/* No need to remove the refcount bump here. */
50885 			DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* currently, always the case */
50886 			DUK_DD(DUK_DDPRINT("refcount finalize after finalizer call: %!O", curr));
50887 			duk_hobject_refcount_finalize_norz(heap, (duk_hobject *) curr);
50888 			duk_free_hobject(heap, (duk_hobject *) curr);
50889 			DUK_DD(DUK_DDPRINT("freed hobject after finalization: %p", (void *) curr));
50890 		}
50891 #else  /* DUK_USE_REFERENCE_COUNTING */
50892 		DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
50893 		DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, curr);
50894 #endif  /* DUK_USE_REFERENCE_COUNTING */
50895 
50896 #if defined(DUK_USE_DEBUG)
50897 		count++;
50898 #endif
50899 
50900 #if defined(DUK_USE_ASSERTIONS)
50901 		DUK_ASSERT(heap->currently_finalizing != NULL);
50902 		heap->currently_finalizing = NULL;
50903 #endif
50904 	}
50905 
50906 	/* finalize_list will always be processed completely. */
50907 	DUK_ASSERT(heap->finalize_list == NULL);
50908 
50909 #if 0
50910 	/* While NORZ macros are used above, this is unnecessary because the
50911 	 * only pending side effects are now finalizers, and finalize_list is
50912 	 * empty.
50913 	 */
50914 	DUK_REFZERO_CHECK_SLOW(heap->heap_thread);
50915 #endif
50916 
50917 	/* Prevent count may be bumped while finalizers run, but should always
50918 	 * be reliably unbumped by the time we get here.
50919 	 */
50920 	DUK_ASSERT(heap->pf_prevent_count == 1);
50921 	heap->pf_prevent_count = 0;
50922 
50923 #if defined(DUK_USE_DEBUG)
50924 	DUK_DD(DUK_DDPRINT("duk_heap_process_finalize_list: %ld finalizers called", (long) count));
50925 #endif
50926 }
50927 
50928 /*
50929  *  Run an duk_hobject finalizer.  Must never throw an uncaught error
50930  *  (but may throw caught errors).
50931  *
50932  *  There is no return value.  Any return value or error thrown by
50933  *  the finalizer is ignored (although errors are debug logged).
50934  *
50935  *  Notes:
50936  *
50937  *    - The finalizer thread 'top' assertions are there because it is
50938  *      critical that strict stack policy is observed (i.e. no cruft
50939  *      left on the finalizer stack).
50940  */
50941 
50942 DUK_LOCAL duk_ret_t duk__finalize_helper(duk_hthread *thr, void *udata) {
50943 	DUK_ASSERT(thr != NULL);
50944 	DUK_UNREF(udata);
50945 
50946 	DUK_DDD(DUK_DDDPRINT("protected finalization helper running"));
50947 
50948 	/* [... obj] */
50949 
50950 	/* _Finalizer property is read without checking if the value is
50951 	 * callable or even exists.  This is intentional, and handled
50952 	 * by throwing an error which is caught by the safe call wrapper.
50953 	 *
50954 	 * XXX: Finalizer lookup should traverse the prototype chain (to allow
50955 	 * inherited finalizers) but should not invoke accessors or proxy object
50956 	 * behavior.  At the moment this lookup will invoke proxy behavior, so
50957 	 * caller must ensure that this function is not called if the target is
50958 	 * a Proxy.
50959 	 */
50960 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_FINALIZER);  /* -> [... obj finalizer] */
50961 	duk_dup_m2(thr);
50962 	duk_push_boolean(thr, DUK_HEAP_HAS_FINALIZER_NORESCUE(thr->heap));
50963 	DUK_DDD(DUK_DDDPRINT("calling finalizer"));
50964 	duk_call(thr, 2);  /* [ ... obj finalizer obj heapDestruct ]  -> [ ... obj retval ] */
50965 	DUK_DDD(DUK_DDDPRINT("finalizer returned successfully"));
50966 	return 0;
50967 
50968 	/* Note: we rely on duk_safe_call() to fix up the stack for the caller,
50969 	 * so we don't need to pop stuff here.  There is no return value;
50970 	 * caller determines rescued status based on object refcount.
50971 	 */
50972 }
50973 
50974 DUK_INTERNAL void duk_heap_run_finalizer(duk_heap *heap, duk_hobject *obj) {
50975 	duk_hthread *thr;
50976 	duk_ret_t rc;
50977 #if defined(DUK_USE_ASSERTIONS)
50978 	duk_idx_t entry_top;
50979 #endif
50980 
50981 	DUK_DD(DUK_DDPRINT("running duk_hobject finalizer for object: %p", (void *) obj));
50982 
50983 	DUK_ASSERT(heap != NULL);
50984 	DUK_ASSERT(heap->heap_thread != NULL);
50985 	thr = heap->heap_thread;
50986 	DUK_ASSERT(obj != NULL);
50987 	DUK_ASSERT_VALSTACK_SPACE(heap->heap_thread, 1);
50988 
50989 #if defined(DUK_USE_ASSERTIONS)
50990 	entry_top = duk_get_top(thr);
50991 #endif
50992 	/*
50993 	 *  Get and call the finalizer.  All of this must be wrapped
50994 	 *  in a protected call, because even getting the finalizer
50995 	 *  may trigger an error (getter may throw one, for instance).
50996 	 */
50997 
50998 	/* ROM objects could inherit a finalizer, but they are never deemed
50999 	 * unreachable by mark-and-sweep, and their refcount never falls to 0.
51000 	 */
51001 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
51002 
51003 	/* Duktape 2.1: finalize_list never contains objects with FINALIZED
51004 	 * set, so no need to check here.
51005 	 */
51006 	DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) obj));
51007 #if 0
51008 	if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) obj)) {
51009 		DUK_D(DUK_DPRINT("object already finalized, avoid running finalizer twice: %!O", obj));
51010 		return;
51011 	}
51012 #endif
51013 	DUK_HEAPHDR_SET_FINALIZED((duk_heaphdr *) obj);  /* ensure never re-entered until rescue cycle complete */
51014 
51015 #if defined(DUK_USE_ES6_PROXY)
51016 	if (DUK_HOBJECT_IS_PROXY(obj)) {
51017 		/* This may happen if duk_set_finalizer() or Duktape.fin() is
51018 		 * called for a Proxy object.  In such cases the fast finalizer
51019 		 * flag will be set on the Proxy, not the target, and neither
51020 		 * will be finalized.
51021 		 */
51022 		DUK_D(DUK_DPRINT("object is a Proxy, skip finalizer call"));
51023 		return;
51024 	}
51025 #endif  /* DUK_USE_ES6_PROXY */
51026 
51027 	duk_push_hobject(thr, obj);  /* this also increases refcount by one */
51028 	rc = duk_safe_call(thr, duk__finalize_helper, NULL /*udata*/, 0 /*nargs*/, 1 /*nrets*/);  /* -> [... obj retval/error] */
51029 	DUK_ASSERT_TOP(thr, entry_top + 2);  /* duk_safe_call discipline */
51030 
51031 	if (rc != DUK_EXEC_SUCCESS) {
51032 		/* Note: we ask for one return value from duk_safe_call to get this
51033 		 * error debugging here.
51034 		 */
51035 		DUK_D(DUK_DPRINT("wrapped finalizer call failed for object %p (ignored); error: %!T",
51036 		                 (void *) obj, (duk_tval *) duk_get_tval(thr, -1)));
51037 	}
51038 	duk_pop_2(thr);  /* -> [...] */
51039 
51040 	DUK_ASSERT_TOP(thr, entry_top);
51041 }
51042 
51043 #else  /* DUK_USE_FINALIZER_SUPPORT */
51044 
51045 /* nothing */
51046 
51047 #endif  /* DUK_USE_FINALIZER_SUPPORT */
51048 #line 1 "duk_heap_hashstring.c"
51049 /*
51050  *  String hash computation (interning).
51051  *
51052  *  String hashing is performance critical because a string hash is computed
51053  *  for all new strings which are candidates to be added to the string table.
51054  *  However, strings actually added to the string table go through a codepoint
51055  *  length calculation which dominates performance because it goes through
51056  *  every byte of the input string (but only for strings added).
51057  *
51058  *  The string hash algorithm should be fast, but on the other hand provide
51059  *  good enough hashes to ensure both string table and object property table
51060  *  hash tables work reasonably well (i.e., there aren't too many collisions
51061  *  with real world inputs).  Unless the hash is cryptographic, it's always
51062  *  possible to craft inputs with maximal hash collisions.
51063  *
51064  *  NOTE: The hash algorithms must match tools/dukutil.py:duk_heap_hashstring()
51065  *  for ROM string support!
51066  */
51067 
51068 /* #include duk_internal.h -> already included */
51069 
51070 #if defined(DUK_USE_STRHASH_DENSE)
51071 /* Constants for duk_hashstring(). */
51072 #define DUK__STRHASH_SHORTSTRING   4096L
51073 #define DUK__STRHASH_MEDIUMSTRING  (256L * 1024L)
51074 #define DUK__STRHASH_BLOCKSIZE     256L
51075 
51076 DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
51077 	duk_uint32_t hash;
51078 
51079 	/* Use Murmurhash2 directly for short strings, and use "block skipping"
51080 	 * for long strings: hash an initial part and then sample the rest of
51081 	 * the string with reasonably sized chunks.  An initial offset for the
51082 	 * sampling is computed based on a hash of the initial part of the string;
51083 	 * this is done to (usually) avoid the case where all long strings have
51084 	 * certain offset ranges which are never sampled.
51085 	 *
51086 	 * Skip should depend on length and bound the total time to roughly
51087 	 * logarithmic.  With current values:
51088 	 *
51089 	 *   1M string => 256 * 241 = 61696 bytes (0.06M) of hashing
51090 	 *   1G string => 256 * 16321 = 4178176 bytes (3.98M) of hashing
51091 	 *
51092 	 * XXX: It would be better to compute the skip offset more "smoothly"
51093 	 * instead of having a few boundary values.
51094 	 */
51095 
51096 	/* note: mixing len into seed improves hashing when skipping */
51097 	duk_uint32_t str_seed = heap->hash_seed ^ ((duk_uint32_t) len);
51098 
51099 	if (len <= DUK__STRHASH_SHORTSTRING) {
51100 		hash = duk_util_hashbytes(str, len, str_seed);
51101 	} else {
51102 		duk_size_t off;
51103 		duk_size_t skip;
51104 
51105 		if (len <= DUK__STRHASH_MEDIUMSTRING) {
51106 			skip = (duk_size_t) (16 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
51107 		} else {
51108 			skip = (duk_size_t) (256 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
51109 		}
51110 
51111 		hash = duk_util_hashbytes(str, (duk_size_t) DUK__STRHASH_SHORTSTRING, str_seed);
51112 		off = DUK__STRHASH_SHORTSTRING + (skip * (hash % 256)) / 256;
51113 
51114 		/* XXX: inefficient loop */
51115 		while (off < len) {
51116 			duk_size_t left = len - off;
51117 			duk_size_t now = (duk_size_t) (left > DUK__STRHASH_BLOCKSIZE ? DUK__STRHASH_BLOCKSIZE : left);
51118 			hash ^= duk_util_hashbytes(str + off, now, str_seed);
51119 			off += skip;
51120 		}
51121 	}
51122 
51123 #if defined(DUK_USE_STRHASH16)
51124 	/* Truncate to 16 bits here, so that a computed hash can be compared
51125 	 * against a hash stored in a 16-bit field.
51126 	 */
51127 	hash &= 0x0000ffffUL;
51128 #endif
51129 	return hash;
51130 }
51131 #else  /* DUK_USE_STRHASH_DENSE */
51132 DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
51133 	duk_uint32_t hash;
51134 	duk_size_t step;
51135 	duk_size_t off;
51136 
51137 	/* Slightly modified "Bernstein hash" from:
51138 	 *
51139 	 *     http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
51140 	 *
51141 	 * Modifications: string skipping and reverse direction similar to
51142 	 * Lua 5.1.5, and different hash initializer.
51143 	 *
51144 	 * The reverse direction ensures last byte it always included in the
51145 	 * hash which is a good default as changing parts of the string are
51146 	 * more often in the suffix than in the prefix.
51147 	 */
51148 
51149 	hash = heap->hash_seed ^ ((duk_uint32_t) len);  /* Bernstein hash init value is normally 5381 */
51150 	step = (len >> DUK_USE_STRHASH_SKIP_SHIFT) + 1;
51151 	for (off = len; off >= step; off -= step) {
51152 		DUK_ASSERT(off >= 1);  /* off >= step, and step >= 1 */
51153 		hash = (hash * 33) + str[off - 1];
51154 	}
51155 
51156 #if defined(DUK_USE_STRHASH16)
51157 	/* Truncate to 16 bits here, so that a computed hash can be compared
51158 	 * against a hash stored in a 16-bit field.
51159 	 */
51160 	hash &= 0x0000ffffUL;
51161 #endif
51162 	return hash;
51163 }
51164 #endif  /* DUK_USE_STRHASH_DENSE */
51165 
51166 /* automatic undefs */
51167 #undef DUK__STRHASH_BLOCKSIZE
51168 #undef DUK__STRHASH_MEDIUMSTRING
51169 #undef DUK__STRHASH_SHORTSTRING
51170 #line 1 "duk_heap_markandsweep.c"
51171 /*
51172  *  Mark-and-sweep garbage collection.
51173  */
51174 
51175 /* #include duk_internal.h -> already included */
51176 
51177 DUK_LOCAL_DECL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h);
51178 DUK_LOCAL_DECL void duk__mark_heaphdr_nonnull(duk_heap *heap, duk_heaphdr *h);
51179 DUK_LOCAL_DECL void duk__mark_tval(duk_heap *heap, duk_tval *tv);
51180 DUK_LOCAL_DECL void duk__mark_tvals(duk_heap *heap, duk_tval *tv, duk_idx_t count);
51181 
51182 /*
51183  *  Marking functions for heap types: mark children recursively.
51184  */
51185 
51186 DUK_LOCAL void duk__mark_hstring(duk_heap *heap, duk_hstring *h) {
51187 	DUK_UNREF(heap);
51188 	DUK_UNREF(h);
51189 
51190 	DUK_DDD(DUK_DDDPRINT("duk__mark_hstring: %p", (void *) h));
51191 	DUK_ASSERT(h);
51192 	DUK_HSTRING_ASSERT_VALID(h);
51193 
51194 	/* nothing to process */
51195 }
51196 
51197 DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h) {
51198 	duk_uint_fast32_t i;
51199 
51200 	DUK_DDD(DUK_DDDPRINT("duk__mark_hobject: %p", (void *) h));
51201 
51202 	DUK_ASSERT(h);
51203 	DUK_HOBJECT_ASSERT_VALID(h);
51204 
51205 	/* XXX: use advancing pointers instead of index macros -> faster and smaller? */
51206 
51207 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
51208 		duk_hstring *key = DUK_HOBJECT_E_GET_KEY(heap, h, i);
51209 		if (key == NULL) {
51210 			continue;
51211 		}
51212 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) key);
51213 		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
51214 			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
51215 			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
51216 		} else {
51217 			duk__mark_tval(heap, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
51218 		}
51219 	}
51220 
51221 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
51222 		duk__mark_tval(heap, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
51223 	}
51224 
51225 	/* Hash part is a 'weak reference' and does not contribute. */
51226 
51227 	duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
51228 
51229 	/* Fast path for objects which don't have a subclass struct, or have a
51230 	 * subclass struct but nothing that needs marking in the subclass struct.
51231 	 */
51232 	if (DUK_HOBJECT_HAS_FASTREFS(h)) {
51233 		DUK_ASSERT(DUK_HOBJECT_ALLOWS_FASTREFS(h));
51234 		return;
51235 	}
51236 	DUK_ASSERT(DUK_HOBJECT_PROHIBITS_FASTREFS(h));
51237 
51238 	/* XXX: reorg, more common first */
51239 	if (DUK_HOBJECT_IS_COMPFUNC(h)) {
51240 		duk_hcompfunc *f = (duk_hcompfunc *) h;
51241 		duk_tval *tv, *tv_end;
51242 		duk_hobject **fn, **fn_end;
51243 
51244 		DUK_HCOMPFUNC_ASSERT_VALID(f);
51245 
51246 		/* 'data' is reachable through every compiled function which
51247 		 * contains a reference.
51248 		 */
51249 
51250 		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_DATA(heap, f));
51251 		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_LEXENV(heap, f));
51252 		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_VARENV(heap, f));
51253 
51254 		if (DUK_HCOMPFUNC_GET_DATA(heap, f) != NULL) {
51255 			tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);
51256 			tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(heap, f);
51257 			while (tv < tv_end) {
51258 				duk__mark_tval(heap, tv);
51259 				tv++;
51260 			}
51261 
51262 			fn = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, f);
51263 			fn_end = DUK_HCOMPFUNC_GET_FUNCS_END(heap, f);
51264 			while (fn < fn_end) {
51265 				duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) *fn);
51266 				fn++;
51267 			}
51268 		} else {
51269 			/* May happen in some out-of-memory corner cases. */
51270 			DUK_D(DUK_DPRINT("duk_hcompfunc 'data' is NULL, skipping marking"));
51271 		}
51272 	} else if (DUK_HOBJECT_IS_DECENV(h)) {
51273 		duk_hdecenv *e = (duk_hdecenv *) h;
51274 		DUK_HDECENV_ASSERT_VALID(e);
51275 		duk__mark_heaphdr(heap, (duk_heaphdr *) e->thread);
51276 		duk__mark_heaphdr(heap, (duk_heaphdr *) e->varmap);
51277 	} else if (DUK_HOBJECT_IS_OBJENV(h)) {
51278 		duk_hobjenv *e = (duk_hobjenv *) h;
51279 		DUK_HOBJENV_ASSERT_VALID(e);
51280 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) e->target);
51281 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
51282 	} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
51283 		duk_hbufobj *b = (duk_hbufobj *) h;
51284 		DUK_HBUFOBJ_ASSERT_VALID(b);
51285 		duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf);
51286 		duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf_prop);
51287 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
51288 	} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
51289 		duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
51290 		DUK_HBOUNDFUNC_ASSERT_VALID(f);
51291 		duk__mark_tval(heap, &f->target);
51292 		duk__mark_tval(heap, &f->this_binding);
51293 		duk__mark_tvals(heap, f->args, f->nargs);
51294 #if defined(DUK_USE_ES6_PROXY)
51295 	} else if (DUK_HOBJECT_IS_PROXY(h)) {
51296 		duk_hproxy *p = (duk_hproxy *) h;
51297 		DUK_HPROXY_ASSERT_VALID(p);
51298 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) p->target);
51299 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) p->handler);
51300 #endif  /* DUK_USE_ES6_PROXY */
51301 	} else if (DUK_HOBJECT_IS_THREAD(h)) {
51302 		duk_hthread *t = (duk_hthread *) h;
51303 		duk_activation *act;
51304 		duk_tval *tv;
51305 
51306 		DUK_HTHREAD_ASSERT_VALID(t);
51307 
51308 		tv = t->valstack;
51309 		while (tv < t->valstack_top) {
51310 			duk__mark_tval(heap, tv);
51311 			tv++;
51312 		}
51313 
51314 		for (act = t->callstack_curr; act != NULL; act = act->parent) {
51315 			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_ACT_GET_FUNC(act));
51316 			duk__mark_heaphdr(heap, (duk_heaphdr *) act->var_env);
51317 			duk__mark_heaphdr(heap, (duk_heaphdr *) act->lex_env);
51318 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
51319 			duk__mark_heaphdr(heap, (duk_heaphdr *) act->prev_caller);
51320 #endif
51321 #if 0  /* nothing now */
51322 			for (cat = act->cat; cat != NULL; cat = cat->parent) {
51323 			}
51324 #endif
51325 		}
51326 
51327 		duk__mark_heaphdr(heap, (duk_heaphdr *) t->resumer);
51328 
51329 		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
51330 			duk__mark_heaphdr(heap, (duk_heaphdr *) t->builtins[i]);
51331 		}
51332 	} else {
51333 		/* We may come here if the object should have a FASTREFS flag
51334 		 * but it's missing for some reason.  Assert for never getting
51335 		 * here; however, other than performance, this is harmless.
51336 		 */
51337 		DUK_D(DUK_DPRINT("missing FASTREFS flag for: %!iO", h));
51338 		DUK_ASSERT(0);
51339 	}
51340 }
51341 
51342 /* Mark any duk_heaphdr type.  Recursion tracking happens only here. */
51343 DUK_LOCAL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h) {
51344 	DUK_DDD(DUK_DDDPRINT("duk__mark_heaphdr %p, type %ld",
51345 	                     (void *) h,
51346 	                     (h != NULL ? (long) DUK_HEAPHDR_GET_TYPE(h) : (long) -1)));
51347 
51348 	/* XXX: add non-null variant? */
51349 	if (h == NULL) {
51350 		return;
51351 	}
51352 
51353 	DUK_HEAPHDR_ASSERT_VALID(h);
51354 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(h) || DUK_HEAPHDR_HAS_REACHABLE(h));
51355 
51356 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
51357 	if (!DUK_HEAPHDR_HAS_READONLY(h)) {
51358 		h->h_assert_refcount++;  /* Comparison refcount: bump even if already reachable. */
51359 	}
51360 #endif
51361 	if (DUK_HEAPHDR_HAS_REACHABLE(h)) {
51362 		DUK_DDD(DUK_DDDPRINT("already marked reachable, skip"));
51363 		return;
51364 	}
51365 #if defined(DUK_USE_ROM_OBJECTS)
51366 	/* READONLY objects always have REACHABLE set, so the check above
51367 	 * will prevent READONLY objects from being marked here.
51368 	 */
51369 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(h));
51370 #endif
51371 
51372 	DUK_HEAPHDR_SET_REACHABLE(h);
51373 
51374 	if (heap->ms_recursion_depth >= DUK_USE_MARK_AND_SWEEP_RECLIMIT) {
51375 		DUK_D(DUK_DPRINT("mark-and-sweep recursion limit reached, marking as temproot: %p", (void *) h));
51376 		DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap);
51377 		DUK_HEAPHDR_SET_TEMPROOT(h);
51378 		return;
51379 	}
51380 
51381 	heap->ms_recursion_depth++;
51382 	DUK_ASSERT(heap->ms_recursion_depth != 0);  /* Wrap. */
51383 
51384 	switch (DUK_HEAPHDR_GET_TYPE(h)) {
51385 	case DUK_HTYPE_STRING:
51386 		duk__mark_hstring(heap, (duk_hstring *) h);
51387 		break;
51388 	case DUK_HTYPE_OBJECT:
51389 		duk__mark_hobject(heap, (duk_hobject *) h);
51390 		break;
51391 	case DUK_HTYPE_BUFFER:
51392 		/* nothing to mark */
51393 		break;
51394 	default:
51395 		DUK_D(DUK_DPRINT("attempt to mark heaphdr %p with invalid htype %ld", (void *) h, (long) DUK_HEAPHDR_GET_TYPE(h)));
51396 		DUK_UNREACHABLE();
51397 	}
51398 
51399 	DUK_ASSERT(heap->ms_recursion_depth > 0);
51400 	heap->ms_recursion_depth--;
51401 }
51402 
51403 DUK_LOCAL void duk__mark_tval(duk_heap *heap, duk_tval *tv) {
51404 	DUK_DDD(DUK_DDDPRINT("duk__mark_tval %p", (void *) tv));
51405 	if (tv == NULL) {
51406 		return;
51407 	}
51408 	DUK_TVAL_ASSERT_VALID(tv);
51409 	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
51410 		duk_heaphdr *h;
51411 		h = DUK_TVAL_GET_HEAPHDR(tv);
51412 		DUK_ASSERT(h != NULL);
51413 		duk__mark_heaphdr_nonnull(heap, h);
51414 	}
51415 }
51416 
51417 DUK_LOCAL void duk__mark_tvals(duk_heap *heap, duk_tval *tv, duk_idx_t count) {
51418 	DUK_ASSERT(count == 0 || tv != NULL);
51419 
51420 	while (count-- > 0) {
51421 		DUK_TVAL_ASSERT_VALID(tv);
51422 		if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
51423 			duk_heaphdr *h;
51424 			h = DUK_TVAL_GET_HEAPHDR(tv);
51425 			DUK_ASSERT(h != NULL);
51426 			duk__mark_heaphdr_nonnull(heap, h);
51427 		}
51428 		tv++;
51429 	}
51430 }
51431 
51432 /* Mark any duk_heaphdr type, caller guarantees a non-NULL pointer. */
51433 DUK_LOCAL void duk__mark_heaphdr_nonnull(duk_heap *heap, duk_heaphdr *h) {
51434 	/* For now, just call the generic handler.  Change when call sites
51435 	 * are changed too.
51436 	 */
51437 	duk__mark_heaphdr(heap, h);
51438 }
51439 
51440 /*
51441  *  Mark the heap.
51442  */
51443 
51444 DUK_LOCAL void duk__mark_roots_heap(duk_heap *heap) {
51445 	duk_small_uint_t i;
51446 
51447 	DUK_DD(DUK_DDPRINT("duk__mark_roots_heap: %p", (void *) heap));
51448 
51449 	duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_thread);
51450 	duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_object);
51451 
51452 	for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
51453 		duk_hstring *h = DUK_HEAP_GET_STRING(heap, i);
51454 		duk__mark_heaphdr(heap, (duk_heaphdr *) h);
51455 	}
51456 
51457 	duk__mark_tval(heap, &heap->lj.value1);
51458 	duk__mark_tval(heap, &heap->lj.value2);
51459 
51460 #if defined(DUK_USE_DEBUGGER_SUPPORT)
51461 	for (i = 0; i < heap->dbg_breakpoint_count; i++) {
51462 		duk__mark_heaphdr(heap, (duk_heaphdr *) heap->dbg_breakpoints[i].filename);
51463 	}
51464 #endif
51465 }
51466 
51467 /*
51468  *  Mark unreachable, finalizable objects.
51469  *
51470  *  Such objects will be moved aside and their finalizers run later.  They
51471  *  have to be treated as reachability roots for their properties etc to
51472  *  remain allocated.  This marking is only done for unreachable values which
51473  *  would be swept later.
51474  *
51475  *  Objects are first marked FINALIZABLE and only then marked as reachability
51476  *  roots; otherwise circular references might be handled inconsistently.
51477  */
51478 
51479 #if defined(DUK_USE_FINALIZER_SUPPORT)
51480 DUK_LOCAL void duk__mark_finalizable(duk_heap *heap) {
51481 	duk_heaphdr *hdr;
51482 	duk_size_t count_finalizable = 0;
51483 
51484 	DUK_DD(DUK_DDPRINT("duk__mark_finalizable: %p", (void *) heap));
51485 
51486 	DUK_ASSERT(heap->heap_thread != NULL);
51487 
51488 	hdr = heap->heap_allocated;
51489 	while (hdr != NULL) {
51490 		/* A finalizer is looked up from the object and up its
51491 		 * prototype chain (which allows inherited finalizers).
51492 		 * The finalizer is checked for using a duk_hobject flag
51493 		 * which is kept in sync with the presence and callability
51494 		 * of a _Finalizer hidden symbol.
51495 		 */
51496 
51497 		if (!DUK_HEAPHDR_HAS_REACHABLE(hdr) &&
51498 		    DUK_HEAPHDR_IS_OBJECT(hdr) &&
51499 		    !DUK_HEAPHDR_HAS_FINALIZED(hdr) &&
51500 		    DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) hdr)) {
51501 			/* heaphdr:
51502 			 *  - is not reachable
51503 			 *  - is an object
51504 			 *  - is not a finalized object waiting for rescue/keep decision
51505 			 *  - has a finalizer
51506 			 */
51507 
51508 			DUK_DD(DUK_DDPRINT("unreachable heap object will be "
51509 			                   "finalized -> mark as finalizable "
51510 			                   "and treat as a reachability root: %p",
51511 			                   (void *) hdr));
51512 			DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(hdr));
51513 			DUK_HEAPHDR_SET_FINALIZABLE(hdr);
51514 			count_finalizable++;
51515 		}
51516 
51517 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
51518 	}
51519 
51520 	if (count_finalizable == 0) {
51521 		return;
51522 	}
51523 
51524 	DUK_DD(DUK_DDPRINT("marked %ld heap objects as finalizable, now mark them reachable",
51525 	                   (long) count_finalizable));
51526 
51527 	hdr = heap->heap_allocated;
51528 	while (hdr != NULL) {
51529 		if (DUK_HEAPHDR_HAS_FINALIZABLE(hdr)) {
51530 			duk__mark_heaphdr_nonnull(heap, hdr);
51531 		}
51532 
51533 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
51534 	}
51535 
51536 	/* Caller will finish the marking process if we hit a recursion limit. */
51537 }
51538 #endif  /* DUK_USE_FINALIZER_SUPPORT */
51539 
51540 /*
51541  *  Mark objects on finalize_list.
51542  */
51543 
51544 #if defined(DUK_USE_FINALIZER_SUPPORT)
51545 DUK_LOCAL void duk__mark_finalize_list(duk_heap *heap) {
51546 	duk_heaphdr *hdr;
51547 #if defined(DUK_USE_DEBUG)
51548 	duk_size_t count_finalize_list = 0;
51549 #endif
51550 
51551 	DUK_DD(DUK_DDPRINT("duk__mark_finalize_list: %p", (void *) heap));
51552 
51553 	hdr = heap->finalize_list;
51554 	while (hdr != NULL) {
51555 		duk__mark_heaphdr_nonnull(heap, hdr);
51556 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
51557 #if defined(DUK_USE_DEBUG)
51558 		count_finalize_list++;
51559 #endif
51560 	}
51561 
51562 #if defined(DUK_USE_DEBUG)
51563 	if (count_finalize_list > 0) {
51564 		DUK_D(DUK_DPRINT("marked %ld objects on the finalize_list as reachable (previous finalizer run skipped)",
51565 		                 (long) count_finalize_list));
51566 	}
51567 #endif
51568 }
51569 #endif  /* DUK_USE_FINALIZER_SUPPORT */
51570 
51571 /*
51572  *  Fallback marking handler if recursion limit is reached.
51573  *
51574  *  Iterates 'temproots' until recursion limit is no longer hit.  Temproots
51575  *  can be in heap_allocated or finalize_list; refzero_list is now always
51576  *  empty for mark-and-sweep.  A temproot may occur in finalize_list now if
51577  *  there are objects on the finalize_list and user code creates a reference
51578  *  from an object in heap_allocated to the object in finalize_list (which is
51579  *  now allowed), and it happened to coincide with the recursion depth limit.
51580  *
51581  *  This is a slow scan, but guarantees that we finish with a bounded C stack.
51582  *
51583  *  Note that nodes may have been marked as temproots before this scan begun,
51584  *  OR they may have been marked during the scan (as we process nodes
51585  *  recursively also during the scan).  This is intended behavior.
51586  */
51587 
51588 #if defined(DUK_USE_DEBUG)
51589 DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr, duk_size_t *count) {
51590 #else
51591 DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr) {
51592 #endif
51593 	DUK_ASSERT(hdr != NULL);
51594 
51595 	if (!DUK_HEAPHDR_HAS_TEMPROOT(hdr)) {
51596 		DUK_DDD(DUK_DDDPRINT("not a temp root: %p", (void *) hdr));
51597 		return;
51598 	}
51599 
51600 	DUK_DDD(DUK_DDDPRINT("found a temp root: %p", (void *) hdr));
51601 	DUK_HEAPHDR_CLEAR_TEMPROOT(hdr);
51602 	DUK_HEAPHDR_CLEAR_REACHABLE(hdr);  /* Done so that duk__mark_heaphdr() works correctly. */
51603 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
51604 	hdr->h_assert_refcount--;  /* Same node visited twice. */
51605 #endif
51606 	duk__mark_heaphdr_nonnull(heap, hdr);
51607 
51608 #if defined(DUK_USE_DEBUG)
51609 	(*count)++;
51610 #endif
51611 }
51612 
51613 DUK_LOCAL void duk__mark_temproots_by_heap_scan(duk_heap *heap) {
51614 	duk_heaphdr *hdr;
51615 #if defined(DUK_USE_DEBUG)
51616 	duk_size_t count;
51617 #endif
51618 
51619 	DUK_DD(DUK_DDPRINT("duk__mark_temproots_by_heap_scan: %p", (void *) heap));
51620 
51621 	while (DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)) {
51622 		DUK_DD(DUK_DDPRINT("recursion limit reached, doing heap scan to continue from temproots"));
51623 
51624 #if defined(DUK_USE_DEBUG)
51625 		count = 0;
51626 #endif
51627 		DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap);
51628 
51629 		hdr = heap->heap_allocated;
51630 		while (hdr) {
51631 #if defined(DUK_USE_DEBUG)
51632 			duk__handle_temproot(heap, hdr, &count);
51633 #else
51634 			duk__handle_temproot(heap, hdr);
51635 #endif
51636 			hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
51637 		}
51638 
51639 #if defined(DUK_USE_FINALIZER_SUPPORT)
51640 		hdr = heap->finalize_list;
51641 		while (hdr) {
51642 #if defined(DUK_USE_DEBUG)
51643 			duk__handle_temproot(heap, hdr, &count);
51644 #else
51645 			duk__handle_temproot(heap, hdr);
51646 #endif
51647 			hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
51648 		}
51649 #endif
51650 
51651 #if defined(DUK_USE_DEBUG)
51652 		DUK_DD(DUK_DDPRINT("temproot mark heap scan processed %ld temp roots", (long) count));
51653 #endif
51654 	}
51655 }
51656 
51657 /*
51658  *  Finalize refcounts for heap elements just about to be freed.
51659  *  This must be done for all objects before freeing to avoid any
51660  *  stale pointer dereferences.
51661  *
51662  *  Note that this must deduce the set of objects to be freed
51663  *  identically to duk__sweep_heap().
51664  */
51665 
51666 #if defined(DUK_USE_REFERENCE_COUNTING)
51667 DUK_LOCAL void duk__finalize_refcounts(duk_heap *heap) {
51668 	duk_heaphdr *hdr;
51669 
51670 	DUK_ASSERT(heap->heap_thread != NULL);
51671 
51672 	DUK_DD(DUK_DDPRINT("duk__finalize_refcounts: heap=%p", (void *) heap));
51673 
51674 	hdr = heap->heap_allocated;
51675 	while (hdr) {
51676 		if (!DUK_HEAPHDR_HAS_REACHABLE(hdr)) {
51677 			/*
51678 			 *  Unreachable object about to be swept.  Finalize target refcounts
51679 			 *  (objects which the unreachable object points to) without doing
51680 			 *  refzero processing.  Recursive decrefs are also prevented when
51681 			 *  refzero processing is disabled.
51682 			 *
51683 			 *  Value cannot be a finalizable object, as they have been made
51684 			 *  temporarily reachable for this round.
51685 			 */
51686 
51687 			DUK_DDD(DUK_DDDPRINT("unreachable object, refcount finalize before sweeping: %p", (void *) hdr));
51688 
51689 			/* Finalize using heap->heap_thread; DECREF has a
51690 			 * suppress check for mark-and-sweep which is based
51691 			 * on heap->ms_running.
51692 			 */
51693 			duk_heaphdr_refcount_finalize_norz(heap, hdr);
51694 		}
51695 
51696 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
51697 	}
51698 }
51699 #endif  /* DUK_USE_REFERENCE_COUNTING */
51700 
51701 /*
51702  *  Clear (reachable) flags of finalize_list.
51703  *
51704  *  We could mostly do in the sweep phase when we move objects from the
51705  *  heap into the finalize_list.  However, if a finalizer run is skipped
51706  *  during a mark-and-sweep, the objects on the finalize_list will be marked
51707  *  reachable during the next mark-and-sweep.  Since they're already on the
51708  *  finalize_list, no-one will be clearing their REACHABLE flag so we do it
51709  *  here.  (This now overlaps with the sweep handling in a harmless way.)
51710  */
51711 
51712 #if defined(DUK_USE_FINALIZER_SUPPORT)
51713 DUK_LOCAL void duk__clear_finalize_list_flags(duk_heap *heap) {
51714 	duk_heaphdr *hdr;
51715 
51716 	DUK_DD(DUK_DDPRINT("duk__clear_finalize_list_flags: %p", (void *) heap));
51717 
51718 	hdr = heap->finalize_list;
51719 	while (hdr) {
51720 		DUK_HEAPHDR_CLEAR_REACHABLE(hdr);
51721 #if defined(DUK_USE_ASSERTIONS)
51722 		DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(hdr) || \
51723 		           (heap->currently_finalizing == hdr));
51724 #endif
51725 		/* DUK_HEAPHDR_FLAG_FINALIZED may be set. */
51726 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
51727 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
51728 	}
51729 }
51730 #endif  /* DUK_USE_FINALIZER_SUPPORT */
51731 
51732 /*
51733  *  Sweep stringtable.
51734  */
51735 
51736 DUK_LOCAL void duk__sweep_stringtable(duk_heap *heap, duk_size_t *out_count_keep) {
51737 	duk_hstring *h;
51738 	duk_hstring *prev;
51739 	duk_uint32_t i;
51740 #if defined(DUK_USE_DEBUG)
51741 	duk_size_t count_free = 0;
51742 #endif
51743 	duk_size_t count_keep = 0;
51744 
51745 	DUK_DD(DUK_DDPRINT("duk__sweep_stringtable: %p", (void *) heap));
51746 
51747 #if defined(DUK_USE_STRTAB_PTRCOMP)
51748 	if (heap->strtable16 == NULL) {
51749 #else
51750 	if (heap->strtable == NULL) {
51751 #endif
51752 		goto done;
51753 	}
51754 
51755 	for (i = 0; i < heap->st_size; i++) {
51756 #if defined(DUK_USE_STRTAB_PTRCOMP)
51757 		h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
51758 #else
51759 		h = heap->strtable[i];
51760 #endif
51761 		prev = NULL;
51762 		while (h != NULL) {
51763 			duk_hstring *next;
51764 			next = h->hdr.h_next;
51765 
51766 			if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h))
51767 			{
51768 				DUK_HEAPHDR_CLEAR_REACHABLE((duk_heaphdr *) h);
51769 				count_keep++;
51770 				prev = h;
51771 			} else {
51772 #if defined(DUK_USE_DEBUG)
51773 				count_free++;
51774 #endif
51775 
51776 				/* For pinned strings the refcount has been
51777 				 * bumped.  We could unbump it here before
51778 				 * freeing, but that's actually not necessary
51779 				 * except for assertions.
51780 				 */
51781 #if 0
51782 				if (DUK_HSTRING_HAS_PINNED_LITERAL(h)) {
51783 					DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) > 0U);
51784 					DUK_HSTRING_DECREF_NORZ(heap->heap_thread, h);
51785 					DUK_HSTRING_CLEAR_PINNED_LITERAL(h);
51786 				}
51787 #endif
51788 #if defined(DUK_USE_REFERENCE_COUNTING)
51789 				/* Non-zero refcounts should not happen for unreachable strings,
51790 				 * because we refcount finalize all unreachable objects which
51791 				 * should have decreased unreachable string refcounts to zero
51792 				 * (even for cycles).  However, pinned strings have a +1 bump.
51793 				 */
51794 				DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) ==
51795 				           DUK_HSTRING_HAS_PINNED_LITERAL(h) ? 1U : 0U);
51796 #endif
51797 
51798 				/* Deal with weak references first. */
51799 				duk_heap_strcache_string_remove(heap, (duk_hstring *) h);
51800 
51801 				/* Remove the string from the string table. */
51802 				duk_heap_strtable_unlink_prev(heap, (duk_hstring *) h, (duk_hstring *) prev);
51803 
51804 				/* Free inner references (these exist e.g. when external
51805 				 * strings are enabled) and the struct itself.
51806 				 */
51807 				duk_free_hstring(heap, (duk_hstring *) h);
51808 
51809 				/* Don't update 'prev'; it should be last string kept. */
51810 			}
51811 
51812 			h = next;
51813 		}
51814 	}
51815 
51816  done:
51817 #if defined(DUK_USE_DEBUG)
51818 	DUK_D(DUK_DPRINT("mark-and-sweep sweep stringtable: %ld freed, %ld kept",
51819 	                 (long) count_free, (long) count_keep));
51820 #endif
51821 	*out_count_keep = count_keep;
51822 }
51823 
51824 /*
51825  *  Sweep heap.
51826  */
51827 
51828 DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_small_uint_t flags, duk_size_t *out_count_keep) {
51829 	duk_heaphdr *prev;  /* last element that was left in the heap */
51830 	duk_heaphdr *curr;
51831 	duk_heaphdr *next;
51832 #if defined(DUK_USE_DEBUG)
51833 	duk_size_t count_free = 0;
51834 	duk_size_t count_finalize = 0;
51835 	duk_size_t count_rescue = 0;
51836 #endif
51837 	duk_size_t count_keep = 0;
51838 
51839 	DUK_DD(DUK_DDPRINT("duk__sweep_heap: %p", (void *) heap));
51840 
51841 	prev = NULL;
51842 	curr = heap->heap_allocated;
51843 	heap->heap_allocated = NULL;
51844 	while (curr) {
51845 		/* Strings and ROM objects are never placed on the heap allocated list. */
51846 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_STRING);
51847 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr));
51848 
51849 		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
51850 
51851 		if (DUK_HEAPHDR_HAS_REACHABLE(curr)) {
51852 			/*
51853 			 *  Reachable object:
51854 			 *    - If FINALIZABLE -> actually unreachable (but marked
51855 			 *      artificially reachable), queue to finalize_list.
51856 			 *    - If !FINALIZABLE but FINALIZED -> rescued after
51857 			 *      finalizer execution.
51858 			 *    - Otherwise just a normal, reachable object.
51859 			 *
51860 			 *  Objects which are kept are queued to heap_allocated
51861 			 *  tail (we're essentially filtering heap_allocated in
51862 			 *  practice).
51863 			 */
51864 
51865 #if defined(DUK_USE_FINALIZER_SUPPORT)
51866 			if (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZABLE(curr))) {
51867 				DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
51868 				DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);
51869 				DUK_DD(DUK_DDPRINT("sweep; reachable, finalizable --> move to finalize_list: %p", (void *) curr));
51870 
51871 #if defined(DUK_USE_REFERENCE_COUNTING)
51872 				DUK_HEAPHDR_PREINC_REFCOUNT(curr);  /* Bump refcount so that refzero never occurs when pending a finalizer call. */
51873 #endif
51874 				DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap, curr);
51875 #if defined(DUK_USE_DEBUG)
51876 				count_finalize++;
51877 #endif
51878 			}
51879 			else
51880 #endif  /* DUK_USE_FINALIZER_SUPPORT */
51881 			{
51882 				if (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZED(curr))) {
51883 					DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
51884 					DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);
51885 
51886 					if (flags & DUK_MS_FLAG_POSTPONE_RESCUE) {
51887 						DUK_DD(DUK_DDPRINT("sweep; reachable, finalized, but postponing rescue decisions --> keep object (with FINALIZED set): %!iO", curr));
51888 						count_keep++;
51889 					} else {
51890 						DUK_DD(DUK_DDPRINT("sweep; reachable, finalized --> rescued after finalization: %p", (void *) curr));
51891 #if defined(DUK_USE_FINALIZER_SUPPORT)
51892 						DUK_HEAPHDR_CLEAR_FINALIZED(curr);
51893 #endif
51894 #if defined(DUK_USE_DEBUG)
51895 						count_rescue++;
51896 #endif
51897 					}
51898 				} else {
51899 					DUK_DD(DUK_DDPRINT("sweep; reachable --> keep: %!iO", curr));
51900 					count_keep++;
51901 				}
51902 
51903 				if (prev != NULL) {
51904 					DUK_ASSERT(heap->heap_allocated != NULL);
51905 					DUK_HEAPHDR_SET_NEXT(heap, prev, curr);
51906 				} else {
51907 					DUK_ASSERT(heap->heap_allocated == NULL);
51908 					heap->heap_allocated = curr;
51909 				}
51910 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
51911 				DUK_HEAPHDR_SET_PREV(heap, curr, prev);
51912 #endif
51913 				DUK_HEAPHDR_ASSERT_LINKS(heap, prev);
51914 				DUK_HEAPHDR_ASSERT_LINKS(heap, curr);
51915 				prev = curr;
51916 			}
51917 
51918 			/*
51919 			 *  Shrink check for value stacks here.  We're inside
51920 			 *  ms_prevent_count protection which prevents recursive
51921 			 *  mark-and-sweep and refzero finalizers, so there are
51922 			 *  no side effects that would affect the heap lists.
51923 			 */
51924 			if (DUK_HEAPHDR_IS_OBJECT(curr) && DUK_HOBJECT_IS_THREAD((duk_hobject *) curr)) {
51925 				duk_hthread *thr_curr = (duk_hthread *) curr;
51926 				DUK_DD(DUK_DDPRINT("value stack shrink check for thread: %!O", curr));
51927 				duk_valstack_shrink_check_nothrow(thr_curr, flags & DUK_MS_FLAG_EMERGENCY /*snug*/);
51928 			}
51929 
51930 			DUK_HEAPHDR_CLEAR_REACHABLE(curr);
51931 			/* Keep FINALIZED if set, used if rescue decisions are postponed. */
51932 			/* Keep FINALIZABLE for objects on finalize_list. */
51933 			DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr));
51934 		} else {
51935 			/*
51936 			 *  Unreachable object:
51937 			 *    - If FINALIZED, object was finalized but not
51938 			 *      rescued.  This doesn't affect freeing.
51939 			 *    - Otherwise normal unreachable object.
51940 			 *
51941 			 *  There's no guard preventing a FINALIZED object
51942 			 *  from being freed while finalizers execute: the
51943 			 *  artificial finalize_list reachability roots can't
51944 			 *  cause an incorrect free decision (but can cause
51945 			 *  an incorrect rescue decision).
51946 			 */
51947 
51948 #if defined(DUK_USE_REFERENCE_COUNTING)
51949 			/* Non-zero refcounts should not happen because we refcount
51950 			 * finalize all unreachable objects which should cancel out
51951 			 * refcounts (even for cycles).
51952 			 */
51953 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) == 0);
51954 #endif
51955 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
51956 
51957 #if defined(DUK_USE_DEBUG)
51958 			if (DUK_HEAPHDR_HAS_FINALIZED(curr)) {
51959 				DUK_DD(DUK_DDPRINT("sweep; unreachable, finalized --> finalized object not rescued: %p", (void *) curr));
51960 			} else {
51961 				DUK_DD(DUK_DDPRINT("sweep; not reachable --> free: %p", (void *) curr));
51962 			}
51963 
51964 #endif
51965 
51966 			/* Note: object cannot be a finalizable unreachable object, as
51967 			 * they have been marked temporarily reachable for this round,
51968 			 * and are handled above.
51969 			 */
51970 
51971 #if defined(DUK_USE_DEBUG)
51972 			count_free++;
51973 #endif
51974 
51975 			/* Weak refs should be handled here, but no weak refs for
51976 			 * any non-string objects exist right now.
51977 			 */
51978 
51979 			/* Free object and all auxiliary (non-heap) allocs. */
51980 			duk_heap_free_heaphdr_raw(heap, curr);
51981 		}
51982 
51983 		curr = next;
51984 	}
51985 
51986 	if (prev != NULL) {
51987 		DUK_HEAPHDR_SET_NEXT(heap, prev, NULL);
51988 	}
51989 	DUK_HEAPHDR_ASSERT_LINKS(heap, prev);
51990 
51991 #if defined(DUK_USE_DEBUG)
51992 	DUK_D(DUK_DPRINT("mark-and-sweep sweep objects (non-string): %ld freed, %ld kept, %ld rescued, %ld queued for finalization",
51993 	                 (long) count_free, (long) count_keep, (long) count_rescue, (long) count_finalize));
51994 #endif
51995 	*out_count_keep = count_keep;
51996 }
51997 
51998 /*
51999  *  Litcache helpers.
52000  */
52001 
52002 #if defined(DUK_USE_LITCACHE_SIZE)
52003 DUK_LOCAL void duk__wipe_litcache(duk_heap *heap) {
52004 	duk_uint_t i;
52005 	duk_litcache_entry *e;
52006 
52007 	e = heap->litcache;
52008 	for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
52009 		e->addr = NULL;
52010 		/* e->h does not need to be invalidated: when e->addr is
52011 		 * NULL, e->h is considered garbage.
52012 		 */
52013 		e++;
52014 	}
52015 }
52016 #endif  /* DUK_USE_LITCACHE_SIZE */
52017 
52018 /*
52019  *  Object compaction.
52020  *
52021  *  Compaction is assumed to never throw an error.
52022  */
52023 
52024 DUK_LOCAL int duk__protected_compact_object(duk_hthread *thr, void *udata) {
52025 	duk_hobject *obj;
52026 	/* XXX: for threads, compact stacks? */
52027 
52028 	DUK_UNREF(udata);
52029 	obj = duk_known_hobject(thr, -1);
52030 	duk_hobject_compact_props(thr, obj);
52031 	return 0;
52032 }
52033 
52034 #if defined(DUK_USE_DEBUG)
52035 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) {
52036 #else
52037 DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start) {
52038 #endif
52039 	duk_heaphdr *curr;
52040 #if defined(DUK_USE_DEBUG)
52041 	duk_size_t old_size, new_size;
52042 #endif
52043 	duk_hobject *obj;
52044 
52045 	DUK_UNREF(heap);
52046 
52047 	curr = start;
52048 	while (curr) {
52049 		DUK_DDD(DUK_DDDPRINT("mark-and-sweep compact: %p", (void *) curr));
52050 
52051 		if (DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_OBJECT) {
52052 			goto next;
52053 		}
52054 		obj = (duk_hobject *) curr;
52055 
52056 #if defined(DUK_USE_DEBUG)
52057 		old_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
52058 		                                      DUK_HOBJECT_GET_ASIZE(obj),
52059 		                                      DUK_HOBJECT_GET_HSIZE(obj));
52060 #endif
52061 
52062 		DUK_DD(DUK_DDPRINT("compact object: %p", (void *) obj));
52063 		duk_push_hobject(thr, obj);
52064 		/* XXX: disable error handlers for duration of compaction? */
52065 		duk_safe_call(thr, duk__protected_compact_object, NULL, 1, 0);
52066 
52067 #if defined(DUK_USE_DEBUG)
52068 		new_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
52069 		                                      DUK_HOBJECT_GET_ASIZE(obj),
52070 		                                      DUK_HOBJECT_GET_HSIZE(obj));
52071 #endif
52072 
52073 #if defined(DUK_USE_DEBUG)
52074 		(*p_count_compact)++;
52075 		(*p_count_bytes_saved) += (duk_size_t) (old_size - new_size);
52076 #endif
52077 
52078 	 next:
52079 		curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
52080 #if defined(DUK_USE_DEBUG)
52081 		(*p_count_check)++;
52082 #endif
52083 	}
52084 }
52085 
52086 DUK_LOCAL void duk__compact_objects(duk_heap *heap) {
52087 	/* XXX: which lists should participate?  to be finalized? */
52088 #if defined(DUK_USE_DEBUG)
52089 	duk_size_t count_check = 0;
52090 	duk_size_t count_compact = 0;
52091 	duk_size_t count_bytes_saved = 0;
52092 #endif
52093 
52094 	DUK_DD(DUK_DDPRINT("duk__compact_objects: %p", (void *) heap));
52095 
52096 	DUK_ASSERT(heap->heap_thread != NULL);
52097 
52098 #if defined(DUK_USE_DEBUG)
52099 	duk__compact_object_list(heap, heap->heap_thread, heap->heap_allocated, &count_check, &count_compact, &count_bytes_saved);
52100 #if defined(DUK_USE_FINALIZER_SUPPORT)
52101 	duk__compact_object_list(heap, heap->heap_thread, heap->finalize_list, &count_check, &count_compact, &count_bytes_saved);
52102 #endif
52103 #else
52104 	duk__compact_object_list(heap, heap->heap_thread, heap->heap_allocated);
52105 #if defined(DUK_USE_FINALIZER_SUPPORT)
52106 	duk__compact_object_list(heap, heap->heap_thread, heap->finalize_list);
52107 #endif
52108 #endif
52109 #if defined(DUK_USE_REFERENCE_COUNTING)
52110 	DUK_ASSERT(heap->refzero_list == NULL);  /* Always handled to completion inline in DECREF. */
52111 #endif
52112 
52113 #if defined(DUK_USE_DEBUG)
52114 	DUK_D(DUK_DPRINT("mark-and-sweep compact objects: %ld checked, %ld compaction attempts, %ld bytes saved by compaction",
52115 	                 (long) count_check, (long) count_compact, (long) count_bytes_saved));
52116 #endif
52117 }
52118 
52119 /*
52120  *  Assertion helpers.
52121  */
52122 
52123 #if defined(DUK_USE_ASSERTIONS)
52124 typedef void (*duk__gc_heaphdr_assert)(duk_heap *heap, duk_heaphdr *h);
52125 typedef void (*duk__gc_hstring_assert)(duk_heap *heap, duk_hstring *h);
52126 
52127 DUK_LOCAL void duk__assert_walk_list(duk_heap *heap, duk_heaphdr *start, duk__gc_heaphdr_assert func) {
52128 	duk_heaphdr *curr;
52129 	for (curr = start; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
52130 		func(heap, curr);
52131 	}
52132 }
52133 
52134 DUK_LOCAL void duk__assert_walk_strtable(duk_heap *heap, duk__gc_hstring_assert func) {
52135 	duk_uint32_t i;
52136 
52137 	for (i = 0; i < heap->st_size; i++) {
52138 		duk_hstring *h;
52139 
52140 #if defined(DUK_USE_STRTAB_PTRCOMP)
52141 		h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
52142 #else
52143 		h = heap->strtable[i];
52144 #endif
52145 		while (h != NULL) {
52146 			func(heap, h);
52147 			h = h->hdr.h_next;
52148 		}
52149 	}
52150 }
52151 
52152 DUK_LOCAL void duk__assert_heaphdr_flags_cb(duk_heap *heap, duk_heaphdr *h) {
52153 	DUK_UNREF(heap);
52154 	DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(h));
52155 	DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(h));
52156 	DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(h));
52157 	/* may have FINALIZED */
52158 }
52159 DUK_LOCAL void duk__assert_heaphdr_flags(duk_heap *heap) {
52160 	duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_heaphdr_flags_cb);
52161 #if defined(DUK_USE_REFERENCE_COUNTING)
52162 	DUK_ASSERT(heap->refzero_list == NULL);  /* Always handled to completion inline in DECREF. */
52163 #endif
52164 	/* XXX: Assertions for finalize_list? */
52165 }
52166 
52167 DUK_LOCAL void duk__assert_validity_cb1(duk_heap *heap, duk_heaphdr *h) {
52168 	DUK_UNREF(heap);
52169 	DUK_ASSERT(DUK_HEAPHDR_IS_OBJECT(h) || DUK_HEAPHDR_IS_BUFFER(h));
52170 	duk_heaphdr_assert_valid_subclassed(h);
52171 }
52172 DUK_LOCAL void duk__assert_validity_cb2(duk_heap *heap, duk_hstring *h) {
52173 	DUK_UNREF(heap);
52174 	DUK_ASSERT(DUK_HEAPHDR_IS_STRING((duk_heaphdr *) h));
52175 	duk_heaphdr_assert_valid_subclassed((duk_heaphdr *) h);
52176 }
52177 DUK_LOCAL void duk__assert_validity(duk_heap *heap) {
52178 	duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_validity_cb1);
52179 #if defined(DUK_USE_FINALIZER_SUPPORT)
52180 	duk__assert_walk_list(heap, heap->finalize_list, duk__assert_validity_cb1);
52181 #endif
52182 #if defined(DUK_USE_REFERENCE_COUNTING)
52183 	duk__assert_walk_list(heap, heap->refzero_list, duk__assert_validity_cb1);
52184 #endif
52185 	duk__assert_walk_strtable(heap, duk__assert_validity_cb2);
52186 }
52187 
52188 #if defined(DUK_USE_REFERENCE_COUNTING)
52189 DUK_LOCAL void duk__assert_valid_refcounts_cb(duk_heap *heap, duk_heaphdr *h) {
52190 	/* Cannot really assert much w.r.t. refcounts now. */
52191 
52192 	DUK_UNREF(heap);
52193 	if (DUK_HEAPHDR_GET_REFCOUNT(h) == 0 &&
52194 	    DUK_HEAPHDR_HAS_FINALIZED(h)) {
52195 		/* An object may be in heap_allocated list with a zero
52196 		 * refcount if it has just been finalized and is waiting
52197 		 * to be collected by the next cycle.
52198 		 * (This doesn't currently happen however.)
52199 		 */
52200 	} else if (DUK_HEAPHDR_GET_REFCOUNT(h) == 0) {
52201 		/* An object may be in heap_allocated list with a zero
52202 		 * refcount also if it is a temporary object created
52203 		 * during debugger paused state.  It will get collected
52204 		 * by mark-and-sweep based on its reachability status
52205 		 * (presumably not reachable because refcount is 0).
52206 		 */
52207 	}
52208 	DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);  /* Unsigned. */
52209 }
52210 DUK_LOCAL void duk__assert_valid_refcounts(duk_heap *heap) {
52211 	duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_valid_refcounts_cb);
52212 }
52213 
52214 DUK_LOCAL void duk__clear_assert_refcounts_cb1(duk_heap *heap, duk_heaphdr *h) {
52215 	DUK_UNREF(heap);
52216 	h->h_assert_refcount = 0;
52217 }
52218 DUK_LOCAL void duk__clear_assert_refcounts_cb2(duk_heap *heap, duk_hstring *h) {
52219 	DUK_UNREF(heap);
52220 	((duk_heaphdr *) h)->h_assert_refcount = 0;
52221 }
52222 DUK_LOCAL void duk__clear_assert_refcounts(duk_heap *heap) {
52223 	duk__assert_walk_list(heap, heap->heap_allocated, duk__clear_assert_refcounts_cb1);
52224 #if defined(DUK_USE_FINALIZER_SUPPORT)
52225 	duk__assert_walk_list(heap, heap->finalize_list, duk__clear_assert_refcounts_cb1);
52226 #endif
52227 #if defined(DUK_USE_REFERENCE_COUNTING)
52228 	duk__assert_walk_list(heap, heap->refzero_list, duk__clear_assert_refcounts_cb1);
52229 #endif
52230 	duk__assert_walk_strtable(heap, duk__clear_assert_refcounts_cb2);
52231 }
52232 
52233 DUK_LOCAL void duk__check_refcount_heaphdr(duk_heaphdr *hdr) {
52234 	duk_bool_t count_ok;
52235 	duk_size_t expect_refc;
52236 
52237 	/* The refcount check only makes sense for reachable objects on
52238 	 * heap_allocated or string table, after the sweep phase.  Prior to
52239 	 * sweep phase refcounts will include references that are not visible
52240 	 * via reachability roots.
52241 	 *
52242 	 * Because we're called after the sweep phase, all heap objects on
52243 	 * heap_allocated are reachable.  REACHABLE flags have already been
52244 	 * cleared so we can't check them.
52245 	 */
52246 
52247 	/* ROM objects have intentionally incorrect refcount (1), but we won't
52248 	 * check them.
52249 	 */
52250 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(hdr));
52251 
52252 	expect_refc = hdr->h_assert_refcount;
52253 	if (DUK_HEAPHDR_IS_STRING(hdr) && DUK_HSTRING_HAS_PINNED_LITERAL((duk_hstring *) hdr)) {
52254 		expect_refc++;
52255 	}
52256 	count_ok = ((duk_size_t) DUK_HEAPHDR_GET_REFCOUNT(hdr) == expect_refc);
52257 	if (!count_ok) {
52258 		DUK_D(DUK_DPRINT("refcount mismatch for: %p: header=%ld counted=%ld --> %!iO",
52259 		                 (void *) hdr, (long) DUK_HEAPHDR_GET_REFCOUNT(hdr),
52260 		                 (long) hdr->h_assert_refcount, hdr));
52261 		DUK_ASSERT(0);
52262 	}
52263 }
52264 
52265 DUK_LOCAL void duk__check_assert_refcounts_cb1(duk_heap *heap, duk_heaphdr *h) {
52266 	DUK_UNREF(heap);
52267 	duk__check_refcount_heaphdr(h);
52268 }
52269 DUK_LOCAL void duk__check_assert_refcounts_cb2(duk_heap *heap, duk_hstring *h) {
52270 	DUK_UNREF(heap);
52271 	duk__check_refcount_heaphdr((duk_heaphdr *) h);
52272 }
52273 DUK_LOCAL void duk__check_assert_refcounts(duk_heap *heap) {
52274 	duk__assert_walk_list(heap, heap->heap_allocated, duk__check_assert_refcounts_cb1);
52275 #if defined(DUK_USE_FINALIZER_SUPPORT)
52276 	duk__assert_walk_list(heap, heap->finalize_list, duk__check_assert_refcounts_cb1);
52277 #endif
52278 	/* XXX: Assert anything for refzero_list? */
52279 	duk__assert_walk_strtable(heap, duk__check_assert_refcounts_cb2);
52280 }
52281 #endif  /* DUK_USE_REFERENCE_COUNTING */
52282 
52283 #if defined(DUK_USE_LITCACHE_SIZE)
52284 DUK_LOCAL void duk__assert_litcache_nulls(duk_heap *heap) {
52285 	duk_uint_t i;
52286 	duk_litcache_entry *e;
52287 
52288 	e = heap->litcache;
52289 	for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
52290 		/* Entry addresses were NULLed before mark-and-sweep, check
52291 		 * that they're still NULL afterwards to ensure no pointers
52292 		 * were recorded through any side effects.
52293 		 */
52294 		DUK_ASSERT(e->addr == NULL);
52295 	}
52296 }
52297 #endif  /* DUK_USE_LITCACHE_SIZE */
52298 #endif  /* DUK_USE_ASSERTIONS */
52299 
52300 /*
52301  *  Stats dump.
52302  */
52303 
52304 #if defined(DUK_USE_DEBUG)
52305 DUK_LOCAL void duk__dump_stats(duk_heap *heap) {
52306 	DUK_D(DUK_DPRINT("stats executor: opcodes=%ld, interrupt=%ld, throw=%ld",
52307 	                 (long) heap->stats_exec_opcodes, (long) heap->stats_exec_interrupt,
52308 	                 (long) heap->stats_exec_throw));
52309 	DUK_D(DUK_DPRINT("stats call: all=%ld, tailcall=%ld, ecmatoecma=%ld",
52310 	                 (long) heap->stats_call_all, (long) heap->stats_call_tailcall,
52311 	                 (long) heap->stats_call_ecmatoecma));
52312 	DUK_D(DUK_DPRINT("stats safecall: all=%ld, nothrow=%ld, throw=%ld",
52313 	                 (long) heap->stats_safecall_all, (long) heap->stats_safecall_nothrow,
52314 	                 (long) heap->stats_safecall_throw));
52315 	DUK_D(DUK_DPRINT("stats mark-and-sweep: try_count=%ld, skip_count=%ld, emergency_count=%ld",
52316 	                 (long) heap->stats_ms_try_count, (long) heap->stats_ms_skip_count,
52317 	                 (long) heap->stats_ms_emergency_count));
52318 	DUK_D(DUK_DPRINT("stats stringtable: intern_hit=%ld, intern_miss=%ld, "
52319 	                 "resize_check=%ld, resize_grow=%ld, resize_shrink=%ld, "
52320 	                 "litcache_hit=%ld, litcache_miss=%ld, litcache_pin=%ld",
52321 	                 (long) heap->stats_strtab_intern_hit, (long) heap->stats_strtab_intern_miss,
52322 	                 (long) heap->stats_strtab_resize_check, (long) heap->stats_strtab_resize_grow,
52323 	                 (long) heap->stats_strtab_resize_shrink, (long) heap->stats_strtab_litcache_hit,
52324 	                 (long) heap->stats_strtab_litcache_miss, (long) heap->stats_strtab_litcache_pin));
52325 	DUK_D(DUK_DPRINT("stats object: realloc_props=%ld, abandon_array=%ld",
52326 	                 (long) heap->stats_object_realloc_props, (long) heap->stats_object_abandon_array));
52327 	DUK_D(DUK_DPRINT("stats getownpropdesc: count=%ld, hit=%ld, miss=%ld",
52328 	                 (long) heap->stats_getownpropdesc_count, (long) heap->stats_getownpropdesc_hit,
52329 	                 (long) heap->stats_getownpropdesc_miss));
52330 	DUK_D(DUK_DPRINT("stats getpropdesc: count=%ld, hit=%ld, miss=%ld",
52331 	                 (long) heap->stats_getpropdesc_count, (long) heap->stats_getpropdesc_hit,
52332 	                 (long) heap->stats_getpropdesc_miss));
52333 	DUK_D(DUK_DPRINT("stats getprop: all=%ld, arrayidx=%ld, bufobjidx=%ld, "
52334 	                 "bufferidx=%ld, bufferlen=%ld, stringidx=%ld, stringlen=%ld, "
52335 	                 "proxy=%ld, arguments=%ld",
52336 	                 (long) heap->stats_getprop_all, (long) heap->stats_getprop_arrayidx,
52337 	                 (long) heap->stats_getprop_bufobjidx, (long) heap->stats_getprop_bufferidx,
52338 	                 (long) heap->stats_getprop_bufferlen, (long) heap->stats_getprop_stringidx,
52339 	                 (long) heap->stats_getprop_stringlen, (long) heap->stats_getprop_proxy,
52340 	                 (long) heap->stats_getprop_arguments));
52341 	DUK_D(DUK_DPRINT("stats putprop: all=%ld, arrayidx=%ld, bufobjidx=%ld, "
52342 	                 "bufferidx=%ld, proxy=%ld",
52343 	                 (long) heap->stats_putprop_all, (long) heap->stats_putprop_arrayidx,
52344 	                 (long) heap->stats_putprop_bufobjidx, (long) heap->stats_putprop_bufferidx,
52345 	                 (long) heap->stats_putprop_proxy));
52346 	DUK_D(DUK_DPRINT("stats getvar: all=%ld",
52347 	                 (long) heap->stats_getvar_all));
52348 	DUK_D(DUK_DPRINT("stats putvar: all=%ld",
52349 	                 (long) heap->stats_putvar_all));
52350 	DUK_D(DUK_DPRINT("stats envrec: delayedcreate=%ld, create=%ld, newenv=%ld, oldenv=%ld, pushclosure=%ld",
52351 	                 (long) heap->stats_envrec_delayedcreate,
52352 	                 (long) heap->stats_envrec_create,
52353 	                 (long) heap->stats_envrec_newenv,
52354 	                 (long) heap->stats_envrec_oldenv,
52355 	                 (long) heap->stats_envrec_pushclosure));
52356 }
52357 #endif  /* DUK_USE_DEBUG */
52358 
52359 /*
52360  *  Main mark-and-sweep function.
52361  *
52362  *  'flags' represents the features requested by the caller.  The current
52363  *  heap->ms_base_flags is ORed automatically into the flags; the base flags
52364  *  mask typically prevents certain mark-and-sweep operation to avoid trouble.
52365  */
52366 
52367 DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags) {
52368 	duk_size_t count_keep_obj;
52369 	duk_size_t count_keep_str;
52370 #if defined(DUK_USE_VOLUNTARY_GC)
52371 	duk_size_t tmp;
52372 #endif
52373 	duk_bool_t entry_creating_error;
52374 
52375 	DUK_STATS_INC(heap, stats_ms_try_count);
52376 #if defined(DUK_USE_DEBUG)
52377 	if (flags & DUK_MS_FLAG_EMERGENCY) {
52378 		DUK_STATS_INC(heap, stats_ms_emergency_count);
52379 	}
52380 #endif
52381 
52382 	/* If debugger is paused, garbage collection is disabled by default.
52383 	 * This is achieved by bumping ms_prevent_count when becoming paused.
52384 	 */
52385 	DUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) || heap->ms_prevent_count > 0);
52386 
52387 	/* Prevention/recursion check as soon as possible because we may
52388 	 * be called a number of times when voluntary mark-and-sweep is
52389 	 * pending.
52390 	 */
52391 	if (heap->ms_prevent_count != 0) {
52392 		DUK_DD(DUK_DDPRINT("reject recursive mark-and-sweep"));
52393 		DUK_STATS_INC(heap, stats_ms_skip_count);
52394 		return;
52395 	}
52396 	DUK_ASSERT(heap->ms_running == 0);  /* ms_prevent_count is bumped when ms_running is set */
52397 
52398 	/* Heap_thread is used during mark-and-sweep for refcount finalization
52399 	 * (it's also used for finalizer execution once mark-and-sweep is
52400 	 * complete).  Heap allocation code ensures heap_thread is set and
52401 	 * properly initialized before setting ms_prevent_count to 0.
52402 	 */
52403 	DUK_ASSERT(heap->heap_thread != NULL);
52404 	DUK_ASSERT(heap->heap_thread->valstack != NULL);
52405 
52406 	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) starting, requested flags: 0x%08lx, effective flags: 0x%08lx",
52407 	                 (unsigned long) flags, (unsigned long) (flags | heap->ms_base_flags)));
52408 
52409 	flags |= heap->ms_base_flags;
52410 #if defined(DUK_USE_FINALIZER_SUPPORT)
52411 	if (heap->finalize_list != NULL) {
52412 		flags |= DUK_MS_FLAG_POSTPONE_RESCUE;
52413 	}
52414 #endif
52415 
52416 	/*
52417 	 *  Assertions before
52418 	 */
52419 
52420 #if defined(DUK_USE_ASSERTIONS)
52421 	DUK_ASSERT(heap->ms_prevent_count == 0);
52422 	DUK_ASSERT(heap->ms_running == 0);
52423 	DUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(heap));
52424 	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
52425 	DUK_ASSERT(heap->ms_recursion_depth == 0);
52426 	duk__assert_heaphdr_flags(heap);
52427 	duk__assert_validity(heap);
52428 #if defined(DUK_USE_REFERENCE_COUNTING)
52429 	/* Note: heap->refzero_free_running may be true; a refcount
52430 	 * finalizer may trigger a mark-and-sweep.
52431 	 */
52432 	duk__assert_valid_refcounts(heap);
52433 #endif  /* DUK_USE_REFERENCE_COUNTING */
52434 #endif  /* DUK_USE_ASSERTIONS */
52435 
52436 	/*
52437 	 *  Begin
52438 	 */
52439 
52440 	DUK_ASSERT(heap->ms_prevent_count == 0);
52441 	DUK_ASSERT(heap->ms_running == 0);
52442 	heap->ms_prevent_count = 1;
52443 	heap->ms_running = 1;
52444 	entry_creating_error = heap->creating_error;
52445 	heap->creating_error = 0;
52446 
52447 	/*
52448 	 *  Free activation/catcher freelists on every mark-and-sweep for now.
52449 	 *  This is an initial rough draft; ideally we'd keep count of the
52450 	 *  freelist size and free only excess entries.
52451 	 */
52452 
52453 	DUK_D(DUK_DPRINT("freeing temporary freelists"));
52454 	duk_heap_free_freelists(heap);
52455 
52456 	/*
52457 	 *  Mark roots, hoping that recursion limit is not normally hit.
52458 	 *  If recursion limit is hit, run additional reachability rounds
52459 	 *  starting from "temproots" until marking is complete.
52460 	 *
52461 	 *  Marking happens in two phases: first we mark actual reachability
52462 	 *  roots (and run "temproots" to complete the process).  Then we
52463 	 *  check which objects are unreachable and are finalizable; such
52464 	 *  objects are marked as FINALIZABLE and marked as reachability
52465 	 *  (and "temproots" is run again to complete the process).
52466 	 *
52467 	 *  The heap finalize_list must also be marked as a reachability root.
52468 	 *  There may be objects on the list from a previous round if the
52469 	 *  previous run had finalizer skip flag.
52470 	 */
52471 
52472 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
52473 	duk__clear_assert_refcounts(heap);
52474 #endif
52475 #if defined(DUK_USE_LITCACHE_SIZE)
52476 	duk__wipe_litcache(heap);
52477 #endif
52478 	duk__mark_roots_heap(heap);               /* Mark main reachability roots. */
52479 #if defined(DUK_USE_REFERENCE_COUNTING)
52480 	DUK_ASSERT(heap->refzero_list == NULL);   /* Always handled to completion inline in DECREF. */
52481 #endif
52482 	duk__mark_temproots_by_heap_scan(heap);   /* Temproots. */
52483 
52484 #if defined(DUK_USE_FINALIZER_SUPPORT)
52485 	duk__mark_finalizable(heap);              /* Mark finalizable as reachability roots. */
52486 	duk__mark_finalize_list(heap);            /* Mark finalizer work list as reachability roots. */
52487 #endif
52488 	duk__mark_temproots_by_heap_scan(heap);   /* Temproots. */
52489 
52490 	/*
52491 	 *  Sweep garbage and remove marking flags, and move objects with
52492 	 *  finalizers to the finalizer work list.
52493 	 *
52494 	 *  Objects to be swept need to get their refcounts finalized before
52495 	 *  they are swept.  In other words, their target object refcounts
52496 	 *  need to be decreased.  This has to be done before freeing any
52497 	 *  objects to avoid decref'ing dangling pointers (which may happen
52498 	 *  even without bugs, e.g. with reference loops)
52499 	 *
52500 	 *  Because strings don't point to other heap objects, similar
52501 	 *  finalization is not necessary for strings.
52502 	 */
52503 
52504 	/* XXX: more emergency behavior, e.g. find smaller hash sizes etc */
52505 
52506 #if defined(DUK_USE_REFERENCE_COUNTING)
52507 	duk__finalize_refcounts(heap);
52508 #endif
52509 	duk__sweep_heap(heap, flags, &count_keep_obj);
52510 	duk__sweep_stringtable(heap, &count_keep_str);
52511 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
52512 	duk__check_assert_refcounts(heap);
52513 #endif
52514 #if defined(DUK_USE_REFERENCE_COUNTING)
52515 	DUK_ASSERT(heap->refzero_list == NULL);   /* Always handled to completion inline in DECREF. */
52516 #endif
52517 #if defined(DUK_USE_FINALIZER_SUPPORT)
52518 	duk__clear_finalize_list_flags(heap);
52519 #endif
52520 
52521 	/*
52522 	 *  Object compaction (emergency only).
52523 	 *
52524 	 *  Object compaction is a separate step after sweeping, as there is
52525 	 *  more free memory for it to work with.  Also, currently compaction
52526 	 *  may insert new objects into the heap allocated list and the string
52527 	 *  table which we don't want to do during a sweep (the reachability
52528 	 *  flags of such objects would be incorrect).  The objects inserted
52529 	 *  are currently:
52530 	 *
52531 	 *    - a temporary duk_hbuffer for a new properties allocation
52532 	 *    - if array part is abandoned, string keys are interned
52533 	 *
52534 	 *  The object insertions go to the front of the list, so they do not
52535 	 *  cause an infinite loop (they are not compacted).
52536 	 *
52537 	 *  At present compaction is not allowed when mark-and-sweep runs
52538 	 *  during error handling because it involves a duk_safe_call()
52539 	 *  interfering with error state.
52540 	 */
52541 
52542 	if ((flags & DUK_MS_FLAG_EMERGENCY) &&
52543 	    !(flags & DUK_MS_FLAG_NO_OBJECT_COMPACTION)) {
52544 		if (heap->lj.type != DUK_LJ_TYPE_UNKNOWN) {
52545 			DUK_D(DUK_DPRINT("lj.type (%ld) not DUK_LJ_TYPE_UNKNOWN, skip object compaction", (long) heap->lj.type));
52546 		} else {
52547 			DUK_D(DUK_DPRINT("object compaction"));
52548 			duk__compact_objects(heap);
52549 		}
52550 	}
52551 
52552 	/*
52553 	 *  String table resize check.
52554 	 *
52555 	 *  This is mainly useful in emergency GC: if the string table load
52556 	 *  factor is really low for some reason, we can shrink the string
52557 	 *  table to a smaller size and free some memory in the process.
52558 	 *  Only execute in emergency GC.  String table has internal flags
52559 	 *  to protect against recursive resizing if this mark-and-sweep pass
52560 	 *  was triggered by a string table resize.
52561 	 */
52562 
52563 	if (flags & DUK_MS_FLAG_EMERGENCY) {
52564 		DUK_D(DUK_DPRINT("stringtable resize check in emergency gc"));
52565 		duk_heap_strtable_force_resize(heap);
52566 	}
52567 
52568 	/*
52569 	 *  Finish
52570 	 */
52571 
52572 	DUK_ASSERT(heap->ms_prevent_count == 1);
52573 	DUK_ASSERT(heap->ms_running == 1);
52574 	heap->ms_prevent_count = 0;
52575 	heap->ms_running = 0;
52576 	heap->creating_error = entry_creating_error;  /* for nested error handling, see GH-2278 */
52577 
52578 	/*
52579 	 *  Assertions after
52580 	 */
52581 
52582 #if defined(DUK_USE_ASSERTIONS)
52583 	DUK_ASSERT(heap->ms_prevent_count == 0);
52584 	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
52585 	DUK_ASSERT(heap->ms_recursion_depth == 0);
52586 	duk__assert_heaphdr_flags(heap);
52587 	duk__assert_validity(heap);
52588 #if defined(DUK_USE_REFERENCE_COUNTING)
52589 	/* Note: heap->refzero_free_running may be true; a refcount
52590 	 * finalizer may trigger a mark-and-sweep.
52591 	 */
52592 	duk__assert_valid_refcounts(heap);
52593 #endif  /* DUK_USE_REFERENCE_COUNTING */
52594 #if defined(DUK_USE_LITCACHE_SIZE)
52595 	duk__assert_litcache_nulls(heap);
52596 #endif  /* DUK_USE_LITCACHE_SIZE */
52597 #endif  /* DUK_USE_ASSERTIONS */
52598 
52599 	/*
52600 	 *  Reset trigger counter
52601 	 */
52602 
52603 #if defined(DUK_USE_VOLUNTARY_GC)
52604 	tmp = (count_keep_obj + count_keep_str) / 256;
52605 	heap->ms_trigger_counter = (duk_int_t) (
52606 	    (tmp * DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT) +
52607 	    DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD);
52608 	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, trigger reset to %ld",
52609 	                 (long) count_keep_obj, (long) count_keep_str, (long) heap->ms_trigger_counter));
52610 #else
52611 	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, no voluntary trigger",
52612 	                 (long) count_keep_obj, (long) count_keep_str));
52613 #endif
52614 
52615 	/*
52616 	 *  Stats dump
52617 	 */
52618 
52619 #if defined(DUK_USE_DEBUG)
52620 	duk__dump_stats(heap);
52621 #endif
52622 
52623 	/*
52624 	 *  Finalize objects in the finalization work list.  Finalized
52625 	 *  objects are queued back to heap_allocated with FINALIZED set.
52626 	 *
52627 	 *  Since finalizers may cause arbitrary side effects, they are
52628 	 *  prevented e.g. during string table and object property allocation
52629 	 *  resizing using heap->pf_prevent_count.  In this case the objects
52630 	 *  remain in the finalization work list after mark-and-sweep exits
52631 	 *  and they may be finalized on the next pass or any DECREF checking
52632 	 *  for finalize_list.
52633 	 *
52634 	 *  As of Duktape 2.1 finalization happens outside mark-and-sweep
52635 	 *  protection.  Mark-and-sweep is allowed while the finalize_list
52636 	 *  is being processed, but no rescue decisions are done while the
52637 	 *  process is on-going.  This avoids incorrect rescue decisions
52638 	 *  if an object is considered reachable (and thus rescued) because
52639 	 *  of a reference via finalize_list (which is considered a reachability
52640 	 *  root).  When finalize_list is being processed, reachable objects
52641 	 *  with FINALIZED set will just keep their FINALIZED flag for later
52642 	 *  mark-and-sweep processing.
52643 	 *
52644 	 *  This could also be handled (a bit better) by having a more refined
52645 	 *  notion of reachability for rescue/free decisions.
52646 	 *
52647 	 *  XXX: avoid finalizer execution when doing emergency GC?
52648 	 */
52649 
52650 #if defined(DUK_USE_FINALIZER_SUPPORT)
52651 	/* Attempt to process finalize_list, pf_prevent_count check
52652 	 * is inside the target.
52653 	 */
52654 	duk_heap_process_finalize_list(heap);
52655 #endif  /* DUK_USE_FINALIZER_SUPPORT */
52656 }
52657 #line 1 "duk_heap_memory.c"
52658 /*
52659  *  Memory allocation handling.
52660  */
52661 
52662 /* #include duk_internal.h -> already included */
52663 
52664 /*
52665  *  Allocate memory with garbage collection.
52666  */
52667 
52668 /* Slow path: voluntary GC triggered, first alloc attempt failed, or zero size. */
52669 DUK_LOCAL DUK_NOINLINE_PERF DUK_COLD void *duk__heap_mem_alloc_slowpath(duk_heap *heap, duk_size_t size) {
52670 	void *res;
52671 	duk_small_int_t i;
52672 
52673 	DUK_ASSERT(heap != NULL);
52674 	DUK_ASSERT(heap->alloc_func != NULL);
52675 	DUK_ASSERT_DISABLE(size >= 0);
52676 
52677 	if (size == 0) {
52678 		DUK_D(DUK_DPRINT("zero size alloc in slow path, return NULL"));
52679 		return NULL;
52680 	}
52681 
52682 	DUK_D(DUK_DPRINT("first alloc attempt failed or voluntary GC limit reached, attempt to gc and retry"));
52683 
52684 #if 0
52685 	/*
52686 	 *  If GC is already running there is no point in attempting a GC
52687 	 *  because it will be skipped.  This could be checked for explicitly,
52688 	 *  but it isn't actually needed: the loop below will eventually
52689 	 *  fail resulting in a NULL.
52690 	 */
52691 
52692 	if (heap->ms_prevent_count != 0) {
52693 		DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed, gc in progress (gc skipped), alloc size %ld", (long) size));
52694 		return NULL;
52695 	}
52696 #endif
52697 
52698 	/*
52699 	 *  Retry with several GC attempts.  Initial attempts are made without
52700 	 *  emergency mode; later attempts use emergency mode which minimizes
52701 	 *  memory allocations forcibly.
52702 	 */
52703 
52704 	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
52705 		duk_small_uint_t flags;
52706 
52707 		flags = 0;
52708 		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
52709 			flags |= DUK_MS_FLAG_EMERGENCY;
52710 		}
52711 
52712 		duk_heap_mark_and_sweep(heap, flags);
52713 
52714 		DUK_ASSERT(size > 0);
52715 		res = heap->alloc_func(heap->heap_udata, size);
52716 		if (res != NULL) {
52717 			DUK_D(DUK_DPRINT("duk_heap_mem_alloc() succeeded after gc (pass %ld), alloc size %ld",
52718 			                 (long) (i + 1), (long) size));
52719 			return res;
52720 		}
52721 	}
52722 
52723 	DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed even after gc, alloc size %ld", (long) size));
52724 	return NULL;
52725 }
52726 
52727 DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
52728 	void *res;
52729 
52730 	DUK_ASSERT(heap != NULL);
52731 	DUK_ASSERT(heap->alloc_func != NULL);
52732 	DUK_ASSERT_DISABLE(size >= 0);
52733 
52734 #if defined(DUK_USE_VOLUNTARY_GC)
52735 	/* Voluntary periodic GC (if enabled). */
52736 	if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
52737 		goto slowpath;
52738 	}
52739 #endif
52740 
52741 #if defined(DUK_USE_GC_TORTURE)
52742 	/* Simulate alloc failure on every alloc, except when mark-and-sweep
52743 	 * is running.
52744 	 */
52745 	if (heap->ms_prevent_count == 0) {
52746 		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first alloc attempt fails"));
52747 		res = NULL;
52748 		DUK_UNREF(res);
52749 		goto slowpath;
52750 	}
52751 #endif
52752 
52753 	/* Zero-size allocation should happen very rarely (if at all), so
52754 	 * don't check zero size on NULL; handle it in the slow path
52755 	 * instead.  This reduces size of inlined code.
52756 	 */
52757 	res = heap->alloc_func(heap->heap_udata, size);
52758 	if (DUK_LIKELY(res != NULL)) {
52759 		return res;
52760 	}
52761 
52762  slowpath:
52763 
52764 	if (size == 0) {
52765 		DUK_D(DUK_DPRINT("first alloc attempt returned NULL for zero size alloc, use slow path to deal with it"));
52766 	} else {
52767 		DUK_D(DUK_DPRINT("first alloc attempt failed, attempt to gc and retry"));
52768 	}
52769 	return duk__heap_mem_alloc_slowpath(heap, size);
52770 }
52771 
52772 DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size) {
52773 	void *res;
52774 
52775 	DUK_ASSERT(heap != NULL);
52776 	DUK_ASSERT(heap->alloc_func != NULL);
52777 	DUK_ASSERT_DISABLE(size >= 0);
52778 
52779 	res = DUK_ALLOC(heap, size);
52780 	if (DUK_LIKELY(res != NULL)) {
52781 		duk_memzero(res, size);
52782 	}
52783 	return res;
52784 }
52785 
52786 DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size) {
52787 	void *res;
52788 
52789 	DUK_ASSERT(thr != NULL);
52790 	DUK_ASSERT(thr->heap != NULL);
52791 	DUK_ASSERT(thr->heap->alloc_func != NULL);
52792 
52793 	res = duk_heap_mem_alloc(thr->heap, size);
52794 	if (DUK_LIKELY(res != NULL)) {
52795 		return res;
52796 	} else if (size == 0) {
52797 		DUK_ASSERT(res == NULL);
52798 		return res;
52799 	}
52800 	DUK_ERROR_ALLOC_FAILED(thr);
52801 	DUK_WO_NORETURN(return NULL;);
52802 }
52803 
52804 DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size) {
52805 	void *res;
52806 
52807 	DUK_ASSERT(thr != NULL);
52808 	DUK_ASSERT(thr->heap != NULL);
52809 	DUK_ASSERT(thr->heap->alloc_func != NULL);
52810 
52811 	res = duk_heap_mem_alloc(thr->heap, size);
52812 	if (DUK_LIKELY(res != NULL)) {
52813 		duk_memzero(res, size);
52814 		return res;
52815 	} else if (size == 0) {
52816 		DUK_ASSERT(res == NULL);
52817 		return res;
52818 	}
52819 	DUK_ERROR_ALLOC_FAILED(thr);
52820 	DUK_WO_NORETURN(return NULL;);
52821 }
52822 
52823 /*
52824  *  Reallocate memory with garbage collection.
52825  */
52826 
52827 /* Slow path: voluntary GC triggered, first realloc attempt failed, or zero size. */
52828 DUK_LOCAL DUK_NOINLINE_PERF DUK_COLD void *duk__heap_mem_realloc_slowpath(duk_heap *heap, void *ptr, duk_size_t newsize) {
52829 	void *res;
52830 	duk_small_int_t i;
52831 
52832 	DUK_ASSERT(heap != NULL);
52833 	DUK_ASSERT(heap->realloc_func != NULL);
52834 	/* ptr may be NULL */
52835 	DUK_ASSERT_DISABLE(newsize >= 0);
52836 
52837 	/* Newsize was 0 and realloc() returned NULL, this has the semantics
52838 	 * of free(oldptr), i.e. memory was successfully freed.
52839 	 */
52840 	if (newsize == 0) {
52841 		DUK_D(DUK_DPRINT("zero size realloc in slow path, return NULL"));
52842 		return NULL;
52843 	}
52844 
52845 	DUK_D(DUK_DPRINT("first realloc attempt failed, attempt to gc and retry"));
52846 
52847 #if 0
52848 	/*
52849 	 *  Avoid a GC if GC is already running.  See duk_heap_mem_alloc().
52850 	 */
52851 
52852 	if (heap->ms_prevent_count != 0) {
52853 		DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
52854 		return NULL;
52855 	}
52856 #endif
52857 
52858 	/*
52859 	 *  Retry with several GC attempts.  Initial attempts are made without
52860 	 *  emergency mode; later attempts use emergency mode which minimizes
52861 	 *  memory allocations forcibly.
52862 	 */
52863 
52864 	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
52865 		duk_small_uint_t flags;
52866 
52867 		flags = 0;
52868 		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
52869 			flags |= DUK_MS_FLAG_EMERGENCY;
52870 		}
52871 
52872 		duk_heap_mark_and_sweep(heap, flags);
52873 
52874 		DUK_ASSERT(newsize > 0);
52875 		res = heap->realloc_func(heap->heap_udata, ptr, newsize);
52876 		if (res || newsize == 0) {
52877 			DUK_D(DUK_DPRINT("duk_heap_mem_realloc() succeeded after gc (pass %ld), alloc size %ld",
52878 			                 (long) (i + 1), (long) newsize));
52879 			return res;
52880 		}
52881 	}
52882 
52883 	DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed even after gc, alloc size %ld", (long) newsize));
52884 	return NULL;
52885 }
52886 
52887 DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
52888 	void *res;
52889 
52890 	DUK_ASSERT(heap != NULL);
52891 	DUK_ASSERT(heap->realloc_func != NULL);
52892 	/* ptr may be NULL */
52893 	DUK_ASSERT_DISABLE(newsize >= 0);
52894 
52895 #if defined(DUK_USE_VOLUNTARY_GC)
52896 	/* Voluntary periodic GC (if enabled). */
52897 	if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
52898 		goto slowpath;
52899 	}
52900 #endif
52901 
52902 #if defined(DUK_USE_GC_TORTURE)
52903 	/* Simulate alloc failure on every realloc, except when mark-and-sweep
52904 	 * is running.
52905 	 */
52906 	if (heap->ms_prevent_count == 0) {
52907 		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first realloc attempt fails"));
52908 		res = NULL;
52909 		DUK_UNREF(res);
52910 		goto slowpath;
52911 	}
52912 #endif
52913 
52914 	res = heap->realloc_func(heap->heap_udata, ptr, newsize);
52915 	if (DUK_LIKELY(res != NULL)) {
52916 		return res;
52917 	}
52918 
52919  slowpath:
52920 
52921 	if (newsize == 0) {
52922 		DUK_D(DUK_DPRINT("first realloc attempt returned NULL for zero size realloc, use slow path to deal with it"));
52923 	} else {
52924 		DUK_D(DUK_DPRINT("first realloc attempt failed, attempt to gc and retry"));
52925 	}
52926 	return duk__heap_mem_realloc_slowpath(heap, ptr, newsize);
52927 }
52928 
52929 /*
52930  *  Reallocate memory with garbage collection, using a callback to provide
52931  *  the current allocated pointer.  This variant is used when a mark-and-sweep
52932  *  (e.g. finalizers) might change the original pointer.
52933  */
52934 
52935 /* Slow path: voluntary GC triggered, first realloc attempt failed, or zero size. */
52936 DUK_LOCAL DUK_NOINLINE_PERF DUK_COLD void *duk__heap_mem_realloc_indirect_slowpath(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
52937 	void *res;
52938 	duk_small_int_t i;
52939 
52940 	DUK_ASSERT(heap != NULL);
52941 	DUK_ASSERT(heap->realloc_func != NULL);
52942 	DUK_ASSERT_DISABLE(newsize >= 0);
52943 
52944 	if (newsize == 0) {
52945 		DUK_D(DUK_DPRINT("zero size indirect realloc in slow path, return NULL"));
52946 		return NULL;
52947 	}
52948 
52949 	DUK_D(DUK_DPRINT("first indirect realloc attempt failed, attempt to gc and retry"));
52950 
52951 #if 0
52952 	/*
52953 	 *  Avoid a GC if GC is already running.  See duk_heap_mem_alloc().
52954 	 */
52955 
52956 	if (heap->ms_prevent_count != 0) {
52957 		DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
52958 		return NULL;
52959 	}
52960 #endif
52961 
52962 	/*
52963 	 *  Retry with several GC attempts.  Initial attempts are made without
52964 	 *  emergency mode; later attempts use emergency mode which minimizes
52965 	 *  memory allocations forcibly.
52966 	 */
52967 
52968 	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
52969 		duk_small_uint_t flags;
52970 
52971 #if defined(DUK_USE_DEBUG)
52972 		void *ptr_pre;
52973 		void *ptr_post;
52974 #endif
52975 
52976 #if defined(DUK_USE_DEBUG)
52977 		ptr_pre = cb(heap, ud);
52978 #endif
52979 		flags = 0;
52980 		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
52981 			flags |= DUK_MS_FLAG_EMERGENCY;
52982 		}
52983 
52984 		duk_heap_mark_and_sweep(heap, flags);
52985 #if defined(DUK_USE_DEBUG)
52986 		ptr_post = cb(heap, ud);
52987 		if (ptr_pre != ptr_post) {
52988 			DUK_DD(DUK_DDPRINT("realloc base pointer changed by mark-and-sweep: %p -> %p",
52989 			                   (void *) ptr_pre, (void *) ptr_post));
52990 		}
52991 #endif
52992 
52993 		/* Note: key issue here is to re-lookup the base pointer on every attempt.
52994 		 * The pointer being reallocated may change after every mark-and-sweep.
52995 		 */
52996 
52997 		DUK_ASSERT(newsize > 0);
52998 		res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
52999 		if (res || newsize == 0) {
53000 			DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() succeeded after gc (pass %ld), alloc size %ld",
53001 			                 (long) (i + 1), (long) newsize));
53002 			return res;
53003 		}
53004 	}
53005 
53006 	DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed even after gc, alloc size %ld", (long) newsize));
53007 	return NULL;
53008 }
53009 
53010 DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
53011 	void *res;
53012 
53013 	DUK_ASSERT(heap != NULL);
53014 	DUK_ASSERT(heap->realloc_func != NULL);
53015 	DUK_ASSERT_DISABLE(newsize >= 0);
53016 
53017 #if defined(DUK_USE_VOLUNTARY_GC)
53018 	/* Voluntary periodic GC (if enabled). */
53019 	if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
53020 		goto slowpath;
53021 	}
53022 #endif
53023 
53024 #if defined(DUK_USE_GC_TORTURE)
53025 	/* Simulate alloc failure on every realloc, except when mark-and-sweep
53026 	 * is running.
53027 	 */
53028 	if (heap->ms_prevent_count == 0) {
53029 		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first indirect realloc attempt fails"));
53030 		res = NULL;
53031 		DUK_UNREF(res);
53032 		goto slowpath;
53033 	}
53034 #endif
53035 
53036 	res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
53037 	if (DUK_LIKELY(res != NULL)) {
53038 		return res;
53039 	}
53040 
53041  slowpath:
53042 
53043 	if (newsize == 0) {
53044 		DUK_D(DUK_DPRINT("first indirect realloc attempt returned NULL for zero size realloc, use slow path to deal with it"));
53045 	} else {
53046 		DUK_D(DUK_DPRINT("first indirect realloc attempt failed, attempt to gc and retry"));
53047 	}
53048 	return duk__heap_mem_realloc_indirect_slowpath(heap, cb, ud, newsize);
53049 }
53050 
53051 /*
53052  *  Free memory
53053  */
53054 
53055 DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void duk_heap_mem_free(duk_heap *heap, void *ptr) {
53056 	DUK_ASSERT(heap != NULL);
53057 	DUK_ASSERT(heap->free_func != NULL);
53058 	/* ptr may be NULL */
53059 
53060 	/* Must behave like a no-op with NULL and any pointer returned from
53061 	 * malloc/realloc with zero size.
53062 	 */
53063 	heap->free_func(heap->heap_udata, ptr);
53064 
53065 	/* Never perform a GC (even voluntary) in a memory free, otherwise
53066 	 * all call sites doing frees would need to deal with the side effects.
53067 	 * No need to update voluntary GC counter either.
53068 	 */
53069 }
53070 #line 1 "duk_heap_misc.c"
53071 /*
53072  *  Support functions for duk_heap.
53073  */
53074 
53075 /* #include duk_internal.h -> already included */
53076 
53077 DUK_INTERNAL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
53078 	duk_heaphdr *root;
53079 
53080 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);
53081 
53082 	root = heap->heap_allocated;
53083 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
53084 	if (root != NULL) {
53085 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);
53086 		DUK_HEAPHDR_SET_PREV(heap, root, hdr);
53087 	}
53088 	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
53089 #endif
53090 	DUK_HEAPHDR_SET_NEXT(heap, hdr, root);
53091 	DUK_HEAPHDR_ASSERT_LINKS(heap, hdr);
53092 	DUK_HEAPHDR_ASSERT_LINKS(heap, root);
53093 	heap->heap_allocated = hdr;
53094 }
53095 
53096 #if defined(DUK_USE_REFERENCE_COUNTING)
53097 DUK_INTERNAL void duk_heap_remove_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
53098 	duk_heaphdr *prev;
53099 	duk_heaphdr *next;
53100 
53101 	/* Strings are in string table. */
53102 	DUK_ASSERT(hdr != NULL);
53103 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);
53104 
53105 	/* Target 'hdr' must be in heap_allocated (not e.g. finalize_list).
53106 	 * If not, heap lists will become corrupted so assert early for it.
53107 	 */
53108 #if defined(DUK_USE_ASSERTIONS)
53109 	{
53110 		duk_heaphdr *tmp;
53111 		for (tmp = heap->heap_allocated; tmp != NULL; tmp = DUK_HEAPHDR_GET_NEXT(heap, tmp)) {
53112 			if (tmp == hdr) {
53113 				break;
53114 			}
53115 		}
53116 		DUK_ASSERT(tmp == hdr);
53117 	}
53118 #endif
53119 
53120 	/* Read/write only once to minimize pointer compression calls. */
53121 	prev = DUK_HEAPHDR_GET_PREV(heap, hdr);
53122 	next = DUK_HEAPHDR_GET_NEXT(heap, hdr);
53123 
53124 	if (prev != NULL) {
53125 		DUK_ASSERT(heap->heap_allocated != hdr);
53126 		DUK_HEAPHDR_SET_NEXT(heap, prev, next);
53127 	} else {
53128 		DUK_ASSERT(heap->heap_allocated == hdr);
53129 		heap->heap_allocated = next;
53130 	}
53131 	if (next != NULL) {
53132 		DUK_HEAPHDR_SET_PREV(heap, next, prev);
53133 	} else {
53134 		;
53135 	}
53136 }
53137 #endif  /* DUK_USE_REFERENCE_COUNTING */
53138 
53139 #if defined(DUK_USE_FINALIZER_SUPPORT)
53140 DUK_INTERNAL void duk_heap_insert_into_finalize_list(duk_heap *heap, duk_heaphdr *hdr) {
53141 	duk_heaphdr *root;
53142 
53143 	root = heap->finalize_list;
53144 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
53145 	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
53146 	if (root != NULL) {
53147 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);
53148 		DUK_HEAPHDR_SET_PREV(heap, root, hdr);
53149 	}
53150 #endif
53151 	DUK_HEAPHDR_SET_NEXT(heap, hdr, root);
53152 	DUK_HEAPHDR_ASSERT_LINKS(heap, hdr);
53153 	DUK_HEAPHDR_ASSERT_LINKS(heap, root);
53154 	heap->finalize_list = hdr;
53155 }
53156 #endif  /* DUK_USE_FINALIZER_SUPPORT */
53157 
53158 #if defined(DUK_USE_FINALIZER_SUPPORT)
53159 DUK_INTERNAL void duk_heap_remove_from_finalize_list(duk_heap *heap, duk_heaphdr *hdr) {
53160 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
53161 	duk_heaphdr *next;
53162 	duk_heaphdr *prev;
53163 
53164 	next = DUK_HEAPHDR_GET_NEXT(heap, hdr);
53165 	prev = DUK_HEAPHDR_GET_PREV(heap, hdr);
53166 	if (next != NULL) {
53167 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, next) == hdr);
53168 		DUK_HEAPHDR_SET_PREV(heap, next, prev);
53169 	}
53170 	if (prev == NULL) {
53171 		DUK_ASSERT(hdr == heap->finalize_list);
53172 		heap->finalize_list = next;
53173 	} else {
53174 		DUK_ASSERT(hdr != heap->finalize_list);
53175 		DUK_HEAPHDR_SET_NEXT(heap, prev, next);
53176 	}
53177 #else
53178 	duk_heaphdr *next;
53179 	duk_heaphdr *curr;
53180 
53181 	/* Random removal is expensive: we need to locate the previous element
53182 	 * because we don't have a 'prev' pointer.
53183 	 */
53184 	curr = heap->finalize_list;
53185 	if (curr == hdr) {
53186 		heap->finalize_list = DUK_HEAPHDR_GET_NEXT(heap, curr);
53187 	} else {
53188 		DUK_ASSERT(hdr != heap->finalize_list);
53189 		for (;;) {
53190 			DUK_ASSERT(curr != NULL);  /* Caller responsibility. */
53191 
53192 			next = DUK_HEAPHDR_GET_NEXT(heap, curr);
53193 			if (next == hdr) {
53194 				next = DUK_HEAPHDR_GET_NEXT(heap, hdr);
53195 				DUK_HEAPHDR_SET_NEXT(heap, curr, next);
53196 				break;
53197 			}
53198 		}
53199 	}
53200 #endif
53201 }
53202 #endif  /* DUK_USE_FINALIZER_SUPPORT */
53203 
53204 #if defined(DUK_USE_ASSERTIONS)
53205 DUK_INTERNAL duk_bool_t duk_heap_in_heap_allocated(duk_heap *heap, duk_heaphdr *ptr) {
53206 	duk_heaphdr *curr;
53207 	DUK_ASSERT(heap != NULL);
53208 
53209 	for (curr = heap->heap_allocated; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
53210 		if (curr == ptr) {
53211 			return 1;
53212 		}
53213 	}
53214 	return 0;
53215 }
53216 #endif  /* DUK_USE_ASSERTIONS */
53217 
53218 #if defined(DUK_USE_INTERRUPT_COUNTER)
53219 DUK_INTERNAL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr) {
53220 	duk_hthread *curr_thr;
53221 
53222 	DUK_ASSERT(heap != NULL);
53223 
53224 	if (new_thr != NULL) {
53225 		curr_thr = heap->curr_thread;
53226 		if (curr_thr == NULL) {
53227 			/* For initial entry use default value; zero forces an
53228 			 * interrupt before executing the first insturction.
53229 			 */
53230 			DUK_DD(DUK_DDPRINT("switch thread, initial entry, init default interrupt counter"));
53231 			new_thr->interrupt_counter = 0;
53232 			new_thr->interrupt_init = 0;
53233 		} else {
53234 			/* Copy interrupt counter/init value state to new thread (if any).
53235 			 * It's OK for new_thr to be the same as curr_thr.
53236 			 */
53237 #if defined(DUK_USE_DEBUG)
53238 			if (new_thr != curr_thr) {
53239 				DUK_DD(DUK_DDPRINT("switch thread, not initial entry, copy interrupt counter"));
53240 			}
53241 #endif
53242 			new_thr->interrupt_counter = curr_thr->interrupt_counter;
53243 			new_thr->interrupt_init = curr_thr->interrupt_init;
53244 		}
53245 	} else {
53246 		DUK_DD(DUK_DDPRINT("switch thread, new thread is NULL, no interrupt counter changes"));
53247 	}
53248 
53249 	heap->curr_thread = new_thr;  /* may be NULL */
53250 }
53251 #endif  /* DUK_USE_INTERRUPT_COUNTER */
53252 
53253 #if defined(DUK_USE_ASSERTIONS)
53254 DUK_INTERNAL void duk_heap_assert_valid(duk_heap *heap) {
53255 	DUK_ASSERT(heap != NULL);
53256 }
53257 #endif
53258 #line 1 "duk_heap_refcount.c"
53259 /*
53260  *  Reference counting implementation.
53261  *
53262  *  INCREF/DECREF, finalization and freeing of objects whose refcount reaches
53263  *  zero (refzero).  These operations are very performance sensitive, so
53264  *  various small tricks are used in an attempt to maximize speed.
53265  */
53266 
53267 /* #include duk_internal.h -> already included */
53268 
53269 #if defined(DUK_USE_REFERENCE_COUNTING)
53270 
53271 #if !defined(DUK_USE_DOUBLE_LINKED_HEAP)
53272 #error internal error, reference counting requires a double linked heap
53273 #endif
53274 
53275 /*
53276  *  Heap object refcount finalization.
53277  *
53278  *  When an object is about to be freed, all other objects it refers to must
53279  *  be decref'd.  Refcount finalization does NOT free the object or its inner
53280  *  allocations (mark-and-sweep shares these helpers), it just manipulates
53281  *  the refcounts.
53282  *
53283  *  Note that any of the DECREFs may cause a refcount to drop to zero.  If so,
53284  *  the object won't be refzero processed inline, but will just be queued to
53285  *  refzero_list and processed by an earlier caller working on refzero_list,
53286  *  eliminating C recursion from even long refzero cascades.  If refzero
53287  *  finalization is triggered by mark-and-sweep, refzero conditions are ignored
53288  *  (objects are not even queued to refzero_list) because mark-and-sweep deals
53289  *  with them; refcounts are still updated so that they remain in sync with
53290  *  actual references.
53291  */
53292 
53293 DUK_LOCAL void duk__decref_tvals_norz(duk_hthread *thr, duk_tval *tv, duk_idx_t count) {
53294 	DUK_ASSERT(count == 0 || tv != NULL);
53295 
53296 	while (count-- > 0) {
53297 		DUK_TVAL_DECREF_NORZ(thr, tv);
53298 		tv++;
53299 	}
53300 }
53301 
53302 DUK_INTERNAL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject *h) {
53303 	duk_hthread *thr;
53304 	duk_uint_fast32_t i;
53305 	duk_uint_fast32_t n;
53306 	duk_propvalue *p_val;
53307 	duk_tval *p_tv;
53308 	duk_hstring **p_key;
53309 	duk_uint8_t *p_flag;
53310 	duk_hobject *h_proto;
53311 
53312 	DUK_ASSERT(heap != NULL);
53313 	DUK_ASSERT(heap->heap_thread != NULL);
53314 	DUK_ASSERT(h);
53315 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h) == DUK_HTYPE_OBJECT);
53316 
53317 	thr = heap->heap_thread;
53318 	DUK_ASSERT(thr != NULL);
53319 
53320 	p_key = DUK_HOBJECT_E_GET_KEY_BASE(heap, h);
53321 	p_val = DUK_HOBJECT_E_GET_VALUE_BASE(heap, h);
53322 	p_flag = DUK_HOBJECT_E_GET_FLAGS_BASE(heap, h);
53323 	n = DUK_HOBJECT_GET_ENEXT(h);
53324 	while (n-- > 0) {
53325 		duk_hstring *key;
53326 
53327 		key = p_key[n];
53328 		if (DUK_UNLIKELY(key == NULL)) {
53329 			continue;
53330 		}
53331 		DUK_HSTRING_DECREF_NORZ(thr, key);
53332 		if (DUK_UNLIKELY(p_flag[n] & DUK_PROPDESC_FLAG_ACCESSOR)) {
53333 			duk_hobject *h_getset;
53334 			h_getset = p_val[n].a.get;
53335 			DUK_ASSERT(h_getset == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_getset));
53336 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_getset);
53337 			h_getset = p_val[n].a.set;
53338 			DUK_ASSERT(h_getset == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_getset));
53339 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_getset);
53340 		} else {
53341 			duk_tval *tv_val;
53342 			tv_val = &p_val[n].v;
53343 			DUK_TVAL_DECREF_NORZ(thr, tv_val);
53344 		}
53345 	}
53346 
53347 	p_tv = DUK_HOBJECT_A_GET_BASE(heap, h);
53348 	n = DUK_HOBJECT_GET_ASIZE(h);
53349 	while (n-- > 0) {
53350 		duk_tval *tv_val;
53351 		tv_val = p_tv + n;
53352 		DUK_TVAL_DECREF_NORZ(thr, tv_val);
53353 	}
53354 
53355 	/* Hash part is a 'weak reference' and doesn't contribute to refcounts. */
53356 
53357 	h_proto = (duk_hobject *) DUK_HOBJECT_GET_PROTOTYPE(heap, h);
53358 	DUK_ASSERT(h_proto == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_proto));
53359 	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_proto);
53360 
53361 	/* XXX: Object subclass tests are quite awkward at present, ideally
53362 	 * we should be able to switch-case here with a dense index (subtype
53363 	 * number or something).  For now, fast path plain objects and arrays
53364 	 * and bit test the rest individually.
53365 	 */
53366 
53367 	if (DUK_HOBJECT_HAS_FASTREFS(h)) {
53368 		/* Plain object or array, nothing more to do.  While a
53369 		 * duk_harray has additional fields, none of them need
53370 		 * DECREF updates.
53371 		 */
53372 		DUK_ASSERT(DUK_HOBJECT_ALLOWS_FASTREFS(h));
53373 		return;
53374 	}
53375 	DUK_ASSERT(DUK_HOBJECT_PROHIBITS_FASTREFS(h));
53376 
53377 	/* Slow path: special object, start bit checks from most likely. */
53378 
53379 	/* XXX: reorg, more common first */
53380 	if (DUK_HOBJECT_IS_COMPFUNC(h)) {
53381 		duk_hcompfunc *f = (duk_hcompfunc *) h;
53382 		duk_tval *tv, *tv_end;
53383 		duk_hobject **funcs, **funcs_end;
53384 
53385 		DUK_HCOMPFUNC_ASSERT_VALID(f);
53386 
53387 		if (DUK_LIKELY(DUK_HCOMPFUNC_GET_DATA(heap, f) != NULL)) {
53388 			tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);
53389 			tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(heap, f);
53390 			while (tv < tv_end) {
53391 				DUK_TVAL_DECREF_NORZ(thr, tv);
53392 				tv++;
53393 			}
53394 
53395 			funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, f);
53396 			funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(heap, f);
53397 			while (funcs < funcs_end) {
53398 				duk_hobject *h_func;
53399 				h_func = *funcs;
53400 				DUK_ASSERT(h_func != NULL);
53401 				DUK_ASSERT(DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_func));
53402 				DUK_HCOMPFUNC_DECREF_NORZ(thr, (duk_hcompfunc *) h_func);
53403 				funcs++;
53404 			}
53405 		} else {
53406 			/* May happen in some out-of-memory corner cases. */
53407 			DUK_D(DUK_DPRINT("duk_hcompfunc 'data' is NULL, skipping decref"));
53408 		}
53409 
53410 		DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_heaphdr *) DUK_HCOMPFUNC_GET_LEXENV(heap, f));
53411 		DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_heaphdr *) DUK_HCOMPFUNC_GET_VARENV(heap, f));
53412 		DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(heap, f));
53413 	} else if (DUK_HOBJECT_IS_DECENV(h)) {
53414 		duk_hdecenv *e = (duk_hdecenv *) h;
53415 		DUK_HDECENV_ASSERT_VALID(e);
53416 		DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr, e->thread);
53417 		DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, e->varmap);
53418 	} else if (DUK_HOBJECT_IS_OBJENV(h)) {
53419 		duk_hobjenv *e = (duk_hobjenv *) h;
53420 		DUK_HOBJENV_ASSERT_VALID(e);
53421 		DUK_ASSERT(e->target != NULL);  /* Required for object environments. */
53422 		DUK_HOBJECT_DECREF_NORZ(thr, e->target);
53423 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
53424 	} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
53425 		duk_hbufobj *b = (duk_hbufobj *) h;
53426 		DUK_HBUFOBJ_ASSERT_VALID(b);
53427 		DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr, (duk_hbuffer *) b->buf);
53428 		DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) b->buf_prop);
53429 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
53430 	} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
53431 		duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
53432 		DUK_HBOUNDFUNC_ASSERT_VALID(f);
53433 		DUK_TVAL_DECREF_NORZ(thr, &f->target);
53434 		DUK_TVAL_DECREF_NORZ(thr, &f->this_binding);
53435 		duk__decref_tvals_norz(thr, f->args, f->nargs);
53436 #if defined(DUK_USE_ES6_PROXY)
53437 	} else if (DUK_HOBJECT_IS_PROXY(h)) {
53438 		duk_hproxy *p = (duk_hproxy *) h;
53439 		DUK_HPROXY_ASSERT_VALID(p);
53440 		DUK_HOBJECT_DECREF_NORZ(thr, p->target);
53441 		DUK_HOBJECT_DECREF_NORZ(thr, p->handler);
53442 #endif  /* DUK_USE_ES6_PROXY */
53443 	} else if (DUK_HOBJECT_IS_THREAD(h)) {
53444 		duk_hthread *t = (duk_hthread *) h;
53445 		duk_activation *act;
53446 		duk_tval *tv;
53447 
53448 		DUK_HTHREAD_ASSERT_VALID(t);
53449 
53450 		tv = t->valstack;
53451 		while (tv < t->valstack_top) {
53452 			DUK_TVAL_DECREF_NORZ(thr, tv);
53453 			tv++;
53454 		}
53455 
53456 		for (act = t->callstack_curr; act != NULL; act = act->parent) {
53457 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) DUK_ACT_GET_FUNC(act));
53458 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->var_env);
53459 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->lex_env);
53460 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
53461 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->prev_caller);
53462 #endif
53463 #if 0  /* nothing now */
53464 			for (cat = act->cat; cat != NULL; cat = cat->parent) {
53465 			}
53466 #endif
53467 		}
53468 
53469 
53470 		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
53471 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) t->builtins[i]);
53472 		}
53473 
53474 		DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr, (duk_hthread *) t->resumer);
53475 	} else {
53476 		/* We may come here if the object should have a FASTREFS flag
53477 		 * but it's missing for some reason.  Assert for never getting
53478 		 * here; however, other than performance, this is harmless.
53479 		 */
53480 		DUK_D(DUK_DPRINT("missing FASTREFS flag for: %!iO", h));
53481 		DUK_ASSERT(0);
53482 	}
53483 }
53484 
53485 DUK_INTERNAL void duk_heaphdr_refcount_finalize_norz(duk_heap *heap, duk_heaphdr *hdr) {
53486 	DUK_ASSERT(heap != NULL);
53487 	DUK_ASSERT(heap->heap_thread != NULL);
53488 	DUK_ASSERT(hdr != NULL);
53489 
53490 	if (DUK_HEAPHDR_IS_OBJECT(hdr)) {
53491 		duk_hobject_refcount_finalize_norz(heap, (duk_hobject *) hdr);
53492 	}
53493 	/* DUK_HTYPE_BUFFER: nothing to finalize */
53494 	/* DUK_HTYPE_STRING: nothing to finalize */
53495 }
53496 
53497 /*
53498  *  Refzero processing for duk_hobject: queue a refzero'ed object to either
53499  *  finalize_list or refzero_list and process the relevent list(s) if
53500  *  necessary.
53501  *
53502  *  Refzero_list is single linked, with only 'prev' pointers set and valid.
53503  *  All 'next' pointers are intentionally left as garbage.  This doesn't
53504  *  matter because refzero_list is processed to completion before any other
53505  *  code (like mark-and-sweep) might walk the list.
53506  *
53507  *  In more detail:
53508  *
53509  *  - On first insert refzero_list is NULL and the new object becomes the
53510  *    first and only element on the list; duk__refcount_free_pending() is
53511  *    called and it starts processing the list from the initial element,
53512  *    i.e. the list tail.
53513  *
53514  *  - As each object is refcount finalized, new objects may be queued to
53515  *    refzero_list head.  Their 'next' pointers are left as garbage, but
53516  *    'prev' points are set correctly, with the element at refzero_list
53517  *    having a NULL 'prev' pointer.  The fact that refzero_list is non-NULL
53518  *    is used to reject (1) recursive duk__refcount_free_pending() and
53519  *    (2) finalize_list processing calls.
53520  *
53521  *  - When we're done with the current object, read its 'prev' pointer and
53522  *    free the object.  If 'prev' is NULL, we've reached head of list and are
53523  *    done: set refzero_list to NULL and process pending finalizers.  Otherwise
53524  *    continue processing the list.
53525  *
53526  *  A refzero cascade is free of side effects because it only involves
53527  *  queueing more objects and freeing memory; finalizer execution is blocked
53528  *  in the code path queueing objects to finalize_list.  As a result the
53529  *  initial refzero call (which triggers duk__refcount_free_pending()) must
53530  *  check finalize_list so that finalizers are executed snappily.
53531  *
53532  *  If finalize_list processing starts first, refzero may occur while we're
53533  *  processing finalizers.  That's fine: that particular refzero cascade is
53534  *  handled to completion without side effects.  Once the cascade is complete,
53535  *  we'll run pending finalizers but notice that we're already doing that and
53536  *  return.
53537  *
53538  *  This could be expanded to allow incremental freeing: just bail out
53539  *  early and resume at a future alloc/decref/refzero.  However, if that
53540  *  were done, the list structure would need to be kept consistent at all
53541  *  times, mark-and-sweep would need to handle refzero_list, etc.
53542  */
53543 
53544 DUK_LOCAL void duk__refcount_free_pending(duk_heap *heap) {
53545 	duk_heaphdr *curr;
53546 #if defined(DUK_USE_DEBUG)
53547 	duk_int_t count = 0;
53548 #endif
53549 
53550 	DUK_ASSERT(heap != NULL);
53551 
53552 	curr = heap->refzero_list;
53553 	DUK_ASSERT(curr != NULL);
53554 	DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, curr) == NULL);  /* We're called on initial insert only. */
53555 	/* curr->next is GARBAGE. */
53556 
53557 	do {
53558 		duk_heaphdr *prev;
53559 
53560 		DUK_DDD(DUK_DDDPRINT("refzero processing %p: %!O", (void *) curr, (duk_heaphdr *) curr));
53561 
53562 #if defined(DUK_USE_DEBUG)
53563 		count++;
53564 #endif
53565 
53566 		DUK_ASSERT(curr != NULL);
53567 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* currently, always the case */
53568 		/* FINALIZED may be set; don't care about flags here. */
53569 
53570 		/* Refcount finalize 'curr'.  Refzero_list must be non-NULL
53571 		 * here to prevent recursive entry to duk__refcount_free_pending().
53572 		 */
53573 		DUK_ASSERT(heap->refzero_list != NULL);
53574 		duk_hobject_refcount_finalize_norz(heap, (duk_hobject *) curr);
53575 
53576 		prev = DUK_HEAPHDR_GET_PREV(heap, curr);
53577 		DUK_ASSERT((prev == NULL && heap->refzero_list == curr) || \
53578 		           (prev != NULL && heap->refzero_list != curr));
53579 		/* prev->next is intentionally not updated and is garbage. */
53580 
53581 		duk_free_hobject(heap, (duk_hobject *) curr);  /* Invalidates 'curr'. */
53582 
53583 		curr = prev;
53584 	} while (curr != NULL);
53585 
53586 	heap->refzero_list = NULL;
53587 
53588 	DUK_DD(DUK_DDPRINT("refzero processed %ld objects", (long) count));
53589 }
53590 
53591 DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hobject(duk_heap *heap, duk_hobject *obj, duk_bool_t skip_free_pending) {
53592 	duk_heaphdr *hdr;
53593 	duk_heaphdr *root;
53594 
53595 	DUK_ASSERT(heap != NULL);
53596 	DUK_ASSERT(heap->heap_thread != NULL);
53597 	DUK_ASSERT(obj != NULL);
53598 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) obj) == DUK_HTYPE_OBJECT);
53599 
53600 	hdr = (duk_heaphdr *) obj;
53601 
53602 	/* Refzero'd objects must be in heap_allocated.  They can't be in
53603 	 * finalize_list because all objects on finalize_list have an
53604 	 * artificial +1 refcount bump.
53605 	 */
53606 #if defined(DUK_USE_ASSERTIONS)
53607 	DUK_ASSERT(duk_heap_in_heap_allocated(heap, (duk_heaphdr *) obj));
53608 #endif
53609 
53610 	DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap, hdr);
53611 
53612 #if defined(DUK_USE_FINALIZER_SUPPORT)
53613 	/* This finalizer check MUST BE side effect free.  It should also be
53614 	 * as fast as possible because it's applied to every object freed.
53615 	 */
53616 	if (DUK_UNLIKELY(DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) hdr) != 0U)) {
53617 		/* Special case: FINALIZED may be set if mark-and-sweep queued
53618 		 * object for finalization, the finalizer was executed (and
53619 		 * FINALIZED set), mark-and-sweep hasn't yet processed the
53620 		 * object again, but its refcount drops to zero.  Free without
53621 		 * running the finalizer again.
53622 		 */
53623 		if (DUK_HEAPHDR_HAS_FINALIZED(hdr)) {
53624 			DUK_D(DUK_DPRINT("refzero'd object has finalizer and FINALIZED is set -> free"));
53625 		} else {
53626 			/* Set FINALIZABLE flag so that all objects on finalize_list
53627 			 * will have it set and are thus detectable based on the
53628 			 * flag alone.
53629 			 */
53630 			DUK_HEAPHDR_SET_FINALIZABLE(hdr);
53631 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(hdr));
53632 
53633 #if defined(DUK_USE_REFERENCE_COUNTING)
53634 			/* Bump refcount on finalize_list insert so that a
53635 			 * refzero can never occur when an object is waiting
53636 			 * for its finalizer call.  Refzero might otherwise
53637 			 * now happen because we allow duk_push_heapptr() for
53638 			 * objects pending finalization.
53639 			 */
53640 			DUK_HEAPHDR_PREINC_REFCOUNT(hdr);
53641 #endif
53642 			DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap, hdr);
53643 
53644 			/* Process finalizers unless skipping is explicitly
53645 			 * requested (NORZ) or refzero_list is being processed
53646 			 * (avoids side effects during a refzero cascade).
53647 			 * If refzero_list is processed, the initial refzero
53648 			 * call will run pending finalizers when refzero_list
53649 			 * is done.
53650 			 */
53651 			if (!skip_free_pending && heap->refzero_list == NULL) {
53652 				duk_heap_process_finalize_list(heap);
53653 			}
53654 			return;
53655 		}
53656 	}
53657 #endif  /* DUK_USE_FINALIZER_SUPPORT */
53658 
53659 	/* No need to finalize, free object via refzero_list. */
53660 
53661 	root = heap->refzero_list;
53662 
53663 	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
53664 	/* 'next' is left as GARBAGE. */
53665 	heap->refzero_list = hdr;
53666 
53667 	if (root == NULL) {
53668 		/* Object is now queued.  Refzero_list was NULL so
53669 		 * no-one is currently processing it; do it here.
53670 		 * With refzero processing just doing a cascade of
53671 		 * free calls, we can process it directly even when
53672 		 * NORZ macros are used: there are no side effects.
53673 		 */
53674 		duk__refcount_free_pending(heap);
53675 		DUK_ASSERT(heap->refzero_list == NULL);
53676 
53677 		/* Process finalizers only after the entire cascade
53678 		 * is finished.  In most cases there's nothing to
53679 		 * finalize, so fast path check to avoid a call.
53680 		 */
53681 #if defined(DUK_USE_FINALIZER_SUPPORT)
53682 		if (!skip_free_pending && DUK_UNLIKELY(heap->finalize_list != NULL)) {
53683 			duk_heap_process_finalize_list(heap);
53684 		}
53685 #endif
53686 	} else {
53687 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);
53688 		DUK_HEAPHDR_SET_PREV(heap, root, hdr);
53689 
53690 		/* Object is now queued.  Because refzero_list was
53691 		 * non-NULL, it's already being processed by someone
53692 		 * in the C call stack, so we're done.
53693 		 */
53694 	}
53695 }
53696 
53697 #if defined(DUK_USE_FINALIZER_SUPPORT)
53698 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_refzero_check_fast(duk_hthread *thr) {
53699 	DUK_ASSERT(thr != NULL);
53700 	DUK_ASSERT(thr->heap != NULL);
53701 	DUK_ASSERT(thr->heap->refzero_list == NULL);  /* Processed to completion inline. */
53702 
53703 	if (DUK_UNLIKELY(thr->heap->finalize_list != NULL)) {
53704 		duk_heap_process_finalize_list(thr->heap);
53705 	}
53706 }
53707 
53708 DUK_INTERNAL void duk_refzero_check_slow(duk_hthread *thr) {
53709 	DUK_ASSERT(thr != NULL);
53710 	DUK_ASSERT(thr->heap != NULL);
53711 	DUK_ASSERT(thr->heap->refzero_list == NULL);  /* Processed to completion inline. */
53712 
53713 	if (DUK_UNLIKELY(thr->heap->finalize_list != NULL)) {
53714 		duk_heap_process_finalize_list(thr->heap);
53715 	}
53716 }
53717 #endif  /* DUK_USE_FINALIZER_SUPPORT */
53718 
53719 /*
53720  *  Refzero processing for duk_hstring.
53721  */
53722 
53723 DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hstring(duk_heap *heap, duk_hstring *str) {
53724 	DUK_ASSERT(heap != NULL);
53725 	DUK_ASSERT(heap->heap_thread != NULL);
53726 	DUK_ASSERT(str != NULL);
53727 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) str) == DUK_HTYPE_STRING);
53728 
53729 	duk_heap_strcache_string_remove(heap, str);
53730 	duk_heap_strtable_unlink(heap, str);
53731 	duk_free_hstring(heap, str);
53732 }
53733 
53734 /*
53735  *  Refzero processing for duk_hbuffer.
53736  */
53737 
53738 DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hbuffer(duk_heap *heap, duk_hbuffer *buf) {
53739 	DUK_ASSERT(heap != NULL);
53740 	DUK_ASSERT(heap->heap_thread != NULL);
53741 	DUK_ASSERT(buf != NULL);
53742 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) buf) == DUK_HTYPE_BUFFER);
53743 
53744 	DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap, (duk_heaphdr *) buf);
53745 	duk_free_hbuffer(heap, buf);
53746 }
53747 
53748 /*
53749  *  Incref and decref functions.
53750  *
53751  *  Decref may trigger immediate refzero handling, which may free and finalize
53752  *  an arbitrary number of objects (a "DECREF cascade").
53753  *
53754  *  Refzero handling is skipped entirely if (1) mark-and-sweep is running or
53755  *  (2) execution is paused in the debugger.  The objects are left in the heap,
53756  *  and will be freed by mark-and-sweep or eventual heap destruction.
53757  *
53758  *  This is necessary during mark-and-sweep because refcounts are also updated
53759  *  during the sweep phase (otherwise objects referenced by a swept object
53760  *  would have incorrect refcounts) which then calls here.  This could be
53761  *  avoided by using separate decref macros in mark-and-sweep; however,
53762  *  mark-and-sweep also calls finalizers which would use the ordinary decref
53763  *  macros anyway.
53764  *
53765  *  We can't process refzeros (= free objects) when the debugger is running
53766  *  as the debugger might make an object unreachable but still continue
53767  *  inspecting it (or even cause it to be pushed back).  So we must rely on
53768  *  mark-and-sweep to collect them.
53769  *
53770  *  The DUK__RZ_SUPPRESS_CHECK() condition is also used in heap destruction
53771  *  when running finalizers for remaining objects: the flag prevents objects
53772  *  from being moved around in heap linked lists while that's being done.
53773  *
53774  *  The suppress condition is important to performance.
53775  */
53776 
53777 #define DUK__RZ_SUPPRESS_ASSERT1() do { \
53778 		DUK_ASSERT(thr != NULL); \
53779 		DUK_ASSERT(thr->heap != NULL); \
53780 		/* When mark-and-sweep runs, heap_thread must exist. */ \
53781 		DUK_ASSERT(thr->heap->ms_running == 0 || thr->heap->heap_thread != NULL); \
53782 		/* In normal operation finalizers are executed with ms_running == 0 \
53783 		 * so we should never see ms_running == 1 and thr != heap_thread. \
53784 		 * In heap destruction finalizers are executed with ms_running != 0 \
53785 		 * to e.g. prevent refzero; a special value ms_running == 2 is used \
53786 		 * in that case so it can be distinguished from the normal runtime \
53787 		 * case, and allows a stronger assertion here (GH-2030). \
53788 		 */ \
53789 		DUK_ASSERT(!(thr->heap->ms_running == 1 && thr != thr->heap->heap_thread)); \
53790 		/* We may be called when the heap is initializing and we process \
53791 		 * refzeros normally, but mark-and-sweep and finalizers are prevented \
53792 		 * if that's the case. \
53793 		 */ \
53794 		DUK_ASSERT(thr->heap->heap_initializing == 0 || thr->heap->ms_prevent_count > 0); \
53795 		DUK_ASSERT(thr->heap->heap_initializing == 0 || thr->heap->pf_prevent_count > 0); \
53796 	} while (0)
53797 
53798 #if defined(DUK_USE_DEBUGGER_SUPPORT)
53799 #define DUK__RZ_SUPPRESS_ASSERT2() do { \
53800 		/* When debugger is paused, ms_running is set. */ \
53801 		DUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || thr->heap->ms_running != 0); \
53802 	} while (0)
53803 #define DUK__RZ_SUPPRESS_COND()  (heap->ms_running != 0)
53804 #else
53805 #define DUK__RZ_SUPPRESS_ASSERT2() do { } while (0)
53806 #define DUK__RZ_SUPPRESS_COND()  (heap->ms_running != 0)
53807 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
53808 
53809 #define DUK__RZ_SUPPRESS_CHECK() do { \
53810 		DUK__RZ_SUPPRESS_ASSERT1(); \
53811 		DUK__RZ_SUPPRESS_ASSERT2(); \
53812 		if (DUK_UNLIKELY(DUK__RZ_SUPPRESS_COND())) { \
53813 			DUK_DDD(DUK_DDDPRINT("refzero handling suppressed (not even queued) when mark-and-sweep running, object: %p", (void *) h)); \
53814 			return; \
53815 		} \
53816 	} while (0)
53817 
53818 #define DUK__RZ_STRING() do { \
53819 		duk__refcount_refzero_hstring(heap, (duk_hstring *) h); \
53820 	} while (0)
53821 #define DUK__RZ_BUFFER() do { \
53822 		duk__refcount_refzero_hbuffer(heap, (duk_hbuffer *) h); \
53823 	} while (0)
53824 #define DUK__RZ_OBJECT() do { \
53825 		duk__refcount_refzero_hobject(heap, (duk_hobject *) h, skip_free_pending); \
53826 	} while (0)
53827 
53828 /* XXX: test the effect of inlining here vs. NOINLINE in refzero helpers */
53829 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
53830 #define DUK__RZ_INLINE DUK_ALWAYS_INLINE
53831 #else
53832 #define DUK__RZ_INLINE /*nop*/
53833 #endif
53834 
53835 DUK_LOCAL DUK__RZ_INLINE void duk__hstring_refzero_helper(duk_hthread *thr, duk_hstring *h) {
53836 	duk_heap *heap;
53837 
53838 	DUK_ASSERT(thr != NULL);
53839 	DUK_ASSERT(h != NULL);
53840 	heap = thr->heap;
53841 
53842 	DUK__RZ_SUPPRESS_CHECK();
53843 	DUK__RZ_STRING();
53844 }
53845 
53846 DUK_LOCAL DUK__RZ_INLINE void duk__hbuffer_refzero_helper(duk_hthread *thr, duk_hbuffer *h) {
53847 	duk_heap *heap;
53848 
53849 	DUK_ASSERT(thr != NULL);
53850 	DUK_ASSERT(h != NULL);
53851 	heap = thr->heap;
53852 
53853 	DUK__RZ_SUPPRESS_CHECK();
53854 	DUK__RZ_BUFFER();
53855 }
53856 
53857 DUK_LOCAL DUK__RZ_INLINE void duk__hobject_refzero_helper(duk_hthread *thr, duk_hobject *h, duk_bool_t skip_free_pending) {
53858 	duk_heap *heap;
53859 
53860 	DUK_ASSERT(thr != NULL);
53861 	DUK_ASSERT(h != NULL);
53862 	heap = thr->heap;
53863 
53864 	DUK__RZ_SUPPRESS_CHECK();
53865 	DUK__RZ_OBJECT();
53866 }
53867 
53868 DUK_LOCAL DUK__RZ_INLINE void duk__heaphdr_refzero_helper(duk_hthread *thr, duk_heaphdr *h, duk_bool_t skip_free_pending) {
53869 	duk_heap *heap;
53870 	duk_small_uint_t htype;
53871 
53872 	DUK_ASSERT(thr != NULL);
53873 	DUK_ASSERT(h != NULL);
53874 	heap = thr->heap;
53875 
53876 	htype = (duk_small_uint_t) DUK_HEAPHDR_GET_TYPE(h);
53877 	DUK_DDD(DUK_DDDPRINT("ms_running=%ld, heap_thread=%p", (long) thr->heap->ms_running, thr->heap->heap_thread));
53878 	DUK__RZ_SUPPRESS_CHECK();
53879 
53880 	switch (htype) {
53881 	case DUK_HTYPE_STRING:
53882 		/* Strings have no internal references but do have "weak"
53883 		 * references in the string cache.  Also note that strings
53884 		 * are not on the heap_allocated list like other heap
53885 		 * elements.
53886 		 */
53887 
53888 		DUK__RZ_STRING();
53889 		break;
53890 
53891 	case DUK_HTYPE_OBJECT:
53892 		/* Objects have internal references.  Must finalize through
53893 		 * the "refzero" work list.
53894 		 */
53895 
53896 		DUK__RZ_OBJECT();
53897 		break;
53898 
53899 	default:
53900 		/* Buffers have no internal references.  However, a dynamic
53901 		 * buffer has a separate allocation for the buffer.  This is
53902 		 * freed by duk_heap_free_heaphdr_raw().
53903 		 */
53904 
53905 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(h) == DUK_HTYPE_BUFFER);
53906 		DUK__RZ_BUFFER();
53907 		break;
53908 	}
53909 }
53910 
53911 DUK_INTERNAL DUK_NOINLINE void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h) {
53912 	duk__heaphdr_refzero_helper(thr, h, 0 /*skip_free_pending*/);
53913 }
53914 
53915 DUK_INTERNAL DUK_NOINLINE void duk_heaphdr_refzero_norz(duk_hthread *thr, duk_heaphdr *h) {
53916 	duk__heaphdr_refzero_helper(thr, h, 1 /*skip_free_pending*/);
53917 }
53918 
53919 DUK_INTERNAL DUK_NOINLINE void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h) {
53920 	duk__hstring_refzero_helper(thr, h);
53921 }
53922 
53923 DUK_INTERNAL DUK_NOINLINE void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h) {
53924 	duk__hbuffer_refzero_helper(thr, h);
53925 }
53926 
53927 DUK_INTERNAL DUK_NOINLINE void duk_hobject_refzero(duk_hthread *thr, duk_hobject *h) {
53928 	duk__hobject_refzero_helper(thr, h, 0 /*skip_free_pending*/);
53929 }
53930 
53931 DUK_INTERNAL DUK_NOINLINE void duk_hobject_refzero_norz(duk_hthread *thr, duk_hobject *h) {
53932 	duk__hobject_refzero_helper(thr, h, 1 /*skip_free_pending*/);
53933 }
53934 
53935 #if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
53936 DUK_INTERNAL void duk_tval_incref(duk_tval *tv) {
53937 	DUK_ASSERT(tv != NULL);
53938 
53939 	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
53940 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
53941 		DUK_ASSERT(h != NULL);
53942 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
53943 		DUK_ASSERT_DISABLE(h->h_refcount >= 0);
53944 		DUK_HEAPHDR_PREINC_REFCOUNT(h);
53945 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) != 0);  /* No wrapping. */
53946 	}
53947 }
53948 
53949 DUK_INTERNAL void duk_tval_decref(duk_hthread *thr, duk_tval *tv) {
53950 	DUK_ASSERT(thr != NULL);
53951 	DUK_ASSERT(tv != NULL);
53952 
53953 	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
53954 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
53955 		DUK_ASSERT(h != NULL);
53956 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
53957 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);
53958 #if 0
53959 		if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
53960 			return;
53961 		}
53962 		duk_heaphdr_refzero(thr, h);
53963 #else
53964 		duk_heaphdr_decref(thr, h);
53965 #endif
53966 	}
53967 }
53968 
53969 DUK_INTERNAL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv) {
53970 	DUK_ASSERT(thr != NULL);
53971 	DUK_ASSERT(tv != NULL);
53972 
53973 	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
53974 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
53975 		DUK_ASSERT(h != NULL);
53976 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
53977 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);
53978 #if 0
53979 		if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
53980 			return;
53981 		}
53982 		duk_heaphdr_refzero_norz(thr, h);
53983 #else
53984 		duk_heaphdr_decref_norz(thr, h);
53985 #endif
53986 	}
53987 }
53988 #endif  /* !DUK_USE_FAST_REFCOUNT_DEFAULT */
53989 
53990 #define DUK__DECREF_ASSERTS() do { \
53991 		DUK_ASSERT(thr != NULL); \
53992 		DUK_ASSERT(thr->heap != NULL); \
53993 		DUK_ASSERT(h != NULL); \
53994 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID((duk_heaphdr *) h)); \
53995 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) >= 1); \
53996 	} while (0)
53997 #if defined(DUK_USE_ROM_OBJECTS)
53998 #define DUK__INCREF_SHARED() do { \
53999 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
54000 			return; \
54001 		} \
54002 		DUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \
54003 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) != 0);  /* No wrapping. */ \
54004 	} while (0)
54005 #define DUK__DECREF_SHARED() do { \
54006 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
54007 			return; \
54008 		} \
54009 		if (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \
54010 			return; \
54011 		} \
54012 	} while (0)
54013 #else
54014 #define DUK__INCREF_SHARED() do { \
54015 		DUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \
54016 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) != 0);  /* No wrapping. */ \
54017 	} while (0)
54018 #define DUK__DECREF_SHARED() do { \
54019 		if (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \
54020 			return; \
54021 		} \
54022 	} while (0)
54023 #endif
54024 
54025 #if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
54026 /* This will in practice be inlined because it's just an INC instructions
54027  * and a bit test + INC when ROM objects are enabled.
54028  */
54029 DUK_INTERNAL void duk_heaphdr_incref(duk_heaphdr *h) {
54030 	DUK_ASSERT(h != NULL);
54031 	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
54032 	DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);
54033 
54034 	DUK__INCREF_SHARED();
54035 }
54036 
54037 DUK_INTERNAL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h) {
54038 	DUK__DECREF_ASSERTS();
54039 	DUK__DECREF_SHARED();
54040 	duk_heaphdr_refzero(thr, h);
54041 
54042 	/* Forced mark-and-sweep when GC torture enabled; this could happen
54043 	 * on any DECREF (but not DECREF_NORZ).
54044 	 */
54045 	DUK_GC_TORTURE(thr->heap);
54046 }
54047 DUK_INTERNAL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h) {
54048 	DUK__DECREF_ASSERTS();
54049 	DUK__DECREF_SHARED();
54050 	duk_heaphdr_refzero_norz(thr, h);
54051 }
54052 #endif  /* !DUK_USE_FAST_REFCOUNT_DEFAULT */
54053 
54054 #if 0  /* Not needed. */
54055 DUK_INTERNAL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h) {
54056 	DUK__DECREF_ASSERTS();
54057 	DUK__DECREF_SHARED();
54058 	duk_hstring_refzero(thr, h);
54059 }
54060 DUK_INTERNAL void duk_hstring_decref_norz(duk_hthread *thr, duk_hstring *h) {
54061 	DUK__DECREF_ASSERTS();
54062 	DUK__DECREF_SHARED();
54063 	duk_hstring_refzero_norz(thr, h);
54064 }
54065 DUK_INTERNAL void duk_hbuffer_decref(duk_hthread *thr, duk_hbuffer *h) {
54066 	DUK__DECREF_ASSERTS();
54067 	DUK__DECREF_SHARED();
54068 	duk_hbuffer_refzero(thr, h);
54069 }
54070 DUK_INTERNAL void duk_hbuffer_decref_norz(duk_hthread *thr, duk_hbuffer *h) {
54071 	DUK__DECREF_ASSERTS();
54072 	DUK__DECREF_SHARED();
54073 	duk_hbuffer_refzero_norz(thr, h);
54074 }
54075 DUK_INTERNAL void duk_hobject_decref(duk_hthread *thr, duk_hobject *h) {
54076 	DUK__DECREF_ASSERTS();
54077 	DUK__DECREF_SHARED();
54078 	duk_hobject_refzero(thr, h);
54079 }
54080 DUK_INTERNAL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h) {
54081 	DUK__DECREF_ASSERTS();
54082 	DUK__DECREF_SHARED();
54083 	duk_hobject_refzero_norz(thr, h);
54084 }
54085 #endif
54086 
54087 #else  /* DUK_USE_REFERENCE_COUNTING */
54088 
54089 /* no refcounting */
54090 
54091 #endif  /* DUK_USE_REFERENCE_COUNTING */
54092 
54093 /* automatic undefs */
54094 #undef DUK__DECREF_ASSERTS
54095 #undef DUK__DECREF_SHARED
54096 #undef DUK__INCREF_SHARED
54097 #undef DUK__RZ_BUFFER
54098 #undef DUK__RZ_INLINE
54099 #undef DUK__RZ_OBJECT
54100 #undef DUK__RZ_STRING
54101 #undef DUK__RZ_SUPPRESS_ASSERT1
54102 #undef DUK__RZ_SUPPRESS_ASSERT2
54103 #undef DUK__RZ_SUPPRESS_CHECK
54104 #undef DUK__RZ_SUPPRESS_COND
54105 #line 1 "duk_heap_stringcache.c"
54106 /*
54107  *  String cache.
54108  *
54109  *  Provides a cache to optimize indexed string lookups.  The cache keeps
54110  *  track of (byte offset, char offset) states for a fixed number of strings.
54111  *  Otherwise we'd need to scan from either end of the string, as we store
54112  *  strings in (extended) UTF-8.
54113  */
54114 
54115 /* #include duk_internal.h -> already included */
54116 
54117 /*
54118  *  Delete references to given hstring from the heap string cache.
54119  *
54120  *  String cache references are 'weak': they are not counted towards
54121  *  reference counts, nor serve as roots for mark-and-sweep.  When an
54122  *  object is about to be freed, such references need to be removed.
54123  */
54124 
54125 DUK_INTERNAL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h) {
54126 	duk_uint_t i;
54127 	for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
54128 		duk_strcache_entry *c = heap->strcache + i;
54129 		if (c->h == h) {
54130 			DUK_DD(DUK_DDPRINT("deleting weak strcache reference to hstring %p from heap %p",
54131 			                   (void *) h, (void *) heap));
54132 			c->h = NULL;
54133 
54134 			/* XXX: the string shouldn't appear twice, but we now loop to the
54135 			 * end anyway; if fixed, add a looping assertion to ensure there
54136 			 * is no duplicate.
54137 			 */
54138 		}
54139 	}
54140 }
54141 
54142 /*
54143  *  String scanning helpers
54144  *
54145  *  All bytes other than UTF-8 continuation bytes ([0x80,0xbf]) are
54146  *  considered to contribute a character.  This must match how string
54147  *  character length is computed.
54148  */
54149 
54150 DUK_LOCAL const duk_uint8_t *duk__scan_forwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
54151 	while (n > 0) {
54152 		for (;;) {
54153 			p++;
54154 			if (p >= q) {
54155 				return NULL;
54156 			}
54157 			if ((*p & 0xc0) != 0x80) {
54158 				break;
54159 			}
54160 		}
54161 		n--;
54162 	}
54163 	return p;
54164 }
54165 
54166 DUK_LOCAL const duk_uint8_t *duk__scan_backwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
54167 	while (n > 0) {
54168 		for (;;) {
54169 			p--;
54170 			if (p < q) {
54171 				return NULL;
54172 			}
54173 			if ((*p & 0xc0) != 0x80) {
54174 				break;
54175 			}
54176 		}
54177 		n--;
54178 	}
54179 	return p;
54180 }
54181 
54182 /*
54183  *  Convert char offset to byte offset
54184  *
54185  *  Avoid using the string cache if possible: for ASCII strings byte and
54186  *  char offsets are equal and for short strings direct scanning may be
54187  *  better than using the string cache (which may evict a more important
54188  *  entry).
54189  *
54190  *  Typing now assumes 32-bit string byte/char offsets (duk_uint_fast32_t).
54191  *  Better typing might be to use duk_size_t.
54192  *
54193  *  Caller should ensure 'char_offset' is within the string bounds [0,charlen]
54194  *  (endpoint is inclusive).  If this is not the case, no memory unsafe
54195  *  behavior will happen but an error will be thrown.
54196  */
54197 
54198 DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset) {
54199 	duk_heap *heap;
54200 	duk_strcache_entry *sce;
54201 	duk_uint_fast32_t byte_offset;
54202 	duk_uint_t i;
54203 	duk_bool_t use_cache;
54204 	duk_uint_fast32_t dist_start, dist_end, dist_sce;
54205 	duk_uint_fast32_t char_length;
54206 	const duk_uint8_t *p_start;
54207 	const duk_uint8_t *p_end;
54208 	const duk_uint8_t *p_found;
54209 
54210 	/*
54211 	 *  For ASCII strings, the answer is simple.
54212 	 */
54213 
54214 	if (DUK_LIKELY(DUK_HSTRING_IS_ASCII(h))) {
54215 		return char_offset;
54216 	}
54217 
54218 	char_length = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h);
54219 	DUK_ASSERT(char_offset <= char_length);
54220 
54221 	if (DUK_LIKELY(DUK_HSTRING_IS_ASCII(h))) {
54222 		/* Must recheck because the 'is ascii' flag may be set
54223 		 * lazily.  Alternatively, we could just compare charlen
54224 		 * to bytelen.
54225 		 */
54226 		return char_offset;
54227 	}
54228 
54229 	/*
54230 	 *  For non-ASCII strings, we need to scan forwards or backwards
54231 	 *  from some starting point.  The starting point may be the start
54232 	 *  or end of the string, or some cached midpoint in the string
54233 	 *  cache.
54234 	 *
54235 	 *  For "short" strings we simply scan without checking or updating
54236 	 *  the cache.  For longer strings we check and update the cache as
54237 	 *  necessary, inserting a new cache entry if none exists.
54238 	 */
54239 
54240 	DUK_DDD(DUK_DDDPRINT("non-ascii string %p, char_offset=%ld, clen=%ld, blen=%ld",
54241 	                     (void *) h, (long) char_offset,
54242 	                     (long) DUK_HSTRING_GET_CHARLEN(h),
54243 	                     (long) DUK_HSTRING_GET_BYTELEN(h)));
54244 
54245 	heap = thr->heap;
54246 	sce = NULL;
54247 	use_cache = (char_length > DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT);
54248 
54249 	if (use_cache) {
54250 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
54251 		DUK_DDD(DUK_DDDPRINT("stringcache before char2byte (using cache):"));
54252 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
54253 			duk_strcache_entry *c = heap->strcache + i;
54254 			DUK_DDD(DUK_DDDPRINT("  [%ld] -> h=%p, cidx=%ld, bidx=%ld",
54255 			                     (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
54256 		}
54257 #endif
54258 
54259 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
54260 			duk_strcache_entry *c = heap->strcache + i;
54261 
54262 			if (c->h == h) {
54263 				sce = c;
54264 				break;
54265 			}
54266 		}
54267 	}
54268 
54269 	/*
54270 	 *  Scan from shortest distance:
54271 	 *    - start of string
54272 	 *    - end of string
54273 	 *    - cache entry (if exists)
54274 	 */
54275 
54276 	DUK_ASSERT(DUK_HSTRING_GET_CHARLEN(h) >= char_offset);
54277 	dist_start = char_offset;
54278 	dist_end = char_length - char_offset;
54279 	dist_sce = 0; DUK_UNREF(dist_sce);  /* initialize for debug prints, needed if sce==NULL */
54280 
54281 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
54282 	p_end = (const duk_uint8_t *) (p_start + DUK_HSTRING_GET_BYTELEN(h));
54283 	p_found = NULL;
54284 
54285 	if (sce) {
54286 		if (char_offset >= sce->cidx) {
54287 			dist_sce = char_offset - sce->cidx;
54288 			if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
54289 				DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
54290 				                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
54291 				                     "scan forwards from sce",
54292 				                     (long) use_cache, (void *) (sce ? sce->h : NULL),
54293 				                     (sce ? (long) sce->cidx : (long) -1),
54294 				                     (sce ? (long) sce->bidx : (long) -1),
54295 				                     (long) dist_start, (long) dist_end, (long) dist_sce));
54296 
54297 				p_found = duk__scan_forwards(p_start + sce->bidx,
54298 				                             p_end,
54299 				                             dist_sce);
54300 				goto scan_done;
54301 			}
54302 		} else {
54303 			dist_sce = sce->cidx - char_offset;
54304 			if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
54305 				DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
54306 				                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
54307 				                     "scan backwards from sce",
54308 				                     (long) use_cache, (void *) (sce ? sce->h : NULL),
54309 				                     (sce ? (long) sce->cidx : (long) -1),
54310 				                     (sce ? (long) sce->bidx : (long) -1),
54311 				                     (long) dist_start, (long) dist_end, (long) dist_sce));
54312 
54313 				p_found = duk__scan_backwards(p_start + sce->bidx,
54314 				                              p_start,
54315 				                              dist_sce);
54316 				goto scan_done;
54317 			}
54318 		}
54319 	}
54320 
54321 	/* no sce, or sce scan not best */
54322 
54323 	if (dist_start <= dist_end) {
54324 		DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
54325 		                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
54326 		                     "scan forwards from string start",
54327 		                     (long) use_cache, (void *) (sce ? sce->h : NULL),
54328 		                     (sce ? (long) sce->cidx : (long) -1),
54329 		                     (sce ? (long) sce->bidx : (long) -1),
54330 		                     (long) dist_start, (long) dist_end, (long) dist_sce));
54331 
54332 		p_found = duk__scan_forwards(p_start,
54333 		                             p_end,
54334 		                             dist_start);
54335 	} else {
54336 		DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
54337 		                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
54338 		                     "scan backwards from string end",
54339 		                     (long) use_cache, (void *) (sce ? sce->h : NULL),
54340 		                     (sce ? (long) sce->cidx : (long) -1),
54341 		                     (sce ? (long) sce->bidx : (long) -1),
54342 		                     (long) dist_start, (long) dist_end, (long) dist_sce));
54343 
54344 		p_found = duk__scan_backwards(p_end,
54345 		                              p_start,
54346 		                              dist_end);
54347 	}
54348 
54349  scan_done:
54350 
54351 	if (DUK_UNLIKELY(p_found == NULL)) {
54352 		/* Scan error: this shouldn't normally happen; it could happen if
54353 		 * string is not valid UTF-8 data, and clen/blen are not consistent
54354 		 * with the scanning algorithm.
54355 		 */
54356 		goto scan_error;
54357 	}
54358 
54359 	DUK_ASSERT(p_found >= p_start);
54360 	DUK_ASSERT(p_found <= p_end);  /* may be equal */
54361 	byte_offset = (duk_uint32_t) (p_found - p_start);
54362 
54363 	DUK_DDD(DUK_DDDPRINT("-> string %p, cidx %ld -> bidx %ld",
54364 	                     (void *) h, (long) char_offset, (long) byte_offset));
54365 
54366 	/*
54367 	 *  Update cache entry (allocating if necessary), and move the
54368 	 *  cache entry to the first place (in an "LRU" policy).
54369 	 */
54370 
54371 	if (use_cache) {
54372 		/* update entry, allocating if necessary */
54373 		if (!sce) {
54374 			sce = heap->strcache + DUK_HEAP_STRCACHE_SIZE - 1;  /* take last entry */
54375 			sce->h = h;
54376 		}
54377 		DUK_ASSERT(sce != NULL);
54378 		sce->bidx = (duk_uint32_t) (p_found - p_start);
54379 		sce->cidx = (duk_uint32_t) char_offset;
54380 
54381 		/* LRU: move our entry to first */
54382 		if (sce > &heap->strcache[0]) {
54383 			/*
54384 			 *   A                  C
54385 			 *   B                  A
54386 			 *   C <- sce    ==>    B
54387 			 *   D                  D
54388 			 */
54389 			duk_strcache_entry tmp;
54390 
54391 			tmp = *sce;
54392 			duk_memmove((void *) (&heap->strcache[1]),
54393 			            (const void *) (&heap->strcache[0]),
54394 			            (size_t) (((char *) sce) - ((char *) &heap->strcache[0])));
54395 			heap->strcache[0] = tmp;
54396 
54397 			/* 'sce' points to the wrong entry here, but is no longer used */
54398 		}
54399 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
54400 		DUK_DDD(DUK_DDDPRINT("stringcache after char2byte (using cache):"));
54401 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
54402 			duk_strcache_entry *c = heap->strcache + i;
54403 			DUK_DDD(DUK_DDDPRINT("  [%ld] -> h=%p, cidx=%ld, bidx=%ld",
54404 			                     (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
54405 		}
54406 #endif
54407 	}
54408 
54409 	return byte_offset;
54410 
54411  scan_error:
54412 	DUK_ERROR_INTERNAL(thr);
54413 	DUK_WO_NORETURN(return 0;);
54414 }
54415 #line 1 "duk_heap_stringtable.c"
54416 /*
54417  *  Heap string table handling, string interning.
54418  */
54419 
54420 /* #include duk_internal.h -> already included */
54421 
54422 /* Resize checks not needed if minsize == maxsize, typical for low memory
54423  * targets.
54424  */
54425 #define DUK__STRTAB_RESIZE_CHECK
54426 #if (DUK_USE_STRTAB_MINSIZE == DUK_USE_STRTAB_MAXSIZE)
54427 #undef DUK__STRTAB_RESIZE_CHECK
54428 #endif
54429 
54430 #if defined(DUK_USE_STRTAB_PTRCOMP)
54431 #define DUK__HEAPPTR_ENC16(heap,ptr)    DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (ptr))
54432 #define DUK__HEAPPTR_DEC16(heap,val)    DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (val))
54433 #define DUK__GET_STRTABLE(heap)         ((heap)->strtable16)
54434 #else
54435 #define DUK__HEAPPTR_ENC16(heap,ptr)    (ptr)
54436 #define DUK__HEAPPTR_DEC16(heap,val)    (val)
54437 #define DUK__GET_STRTABLE(heap)         ((heap)->strtable)
54438 #endif
54439 
54440 #define DUK__STRTAB_U32_MAX_STRLEN      10               /* 4'294'967'295 */
54441 
54442 /*
54443  *  Debug dump stringtable.
54444  */
54445 
54446 #if defined(DUK_USE_DEBUG)
54447 DUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap) {
54448 #if defined(DUK_USE_STRTAB_PTRCOMP)
54449 	duk_uint16_t *strtable;
54450 #else
54451 	duk_hstring **strtable;
54452 #endif
54453 	duk_uint32_t i;
54454 	duk_hstring *h;
54455 	duk_size_t count_total = 0;
54456 	duk_size_t count_chain;
54457 	duk_size_t count_chain_min = DUK_SIZE_MAX;
54458 	duk_size_t count_chain_max = 0;
54459 	duk_size_t count_len[8];  /* chain lengths from 0 to 7 */
54460 
54461 	if (heap == NULL) {
54462 		DUK_D(DUK_DPRINT("string table, heap=NULL"));
54463 		return;
54464 	}
54465 
54466 	strtable = DUK__GET_STRTABLE(heap);
54467 	if (strtable == NULL) {
54468 		DUK_D(DUK_DPRINT("string table, strtab=NULL"));
54469 		return;
54470 	}
54471 
54472 	duk_memzero((void *) count_len, sizeof(count_len));
54473 	for (i = 0; i < heap->st_size; i++) {
54474 		h = DUK__HEAPPTR_DEC16(heap, strtable[i]);
54475 		count_chain = 0;
54476 		while (h != NULL) {
54477 			count_chain++;
54478 			h = h->hdr.h_next;
54479 		}
54480 		if (count_chain < sizeof(count_len) / sizeof(duk_size_t)) {
54481 			count_len[count_chain]++;
54482 		}
54483 		count_chain_max = (count_chain > count_chain_max ? count_chain : count_chain_max);
54484 		count_chain_min = (count_chain < count_chain_min ? count_chain : count_chain_min);
54485 		count_total += count_chain;
54486 	}
54487 
54488 	DUK_D(DUK_DPRINT("string table, strtab=%p, count=%lu, chain min=%lu max=%lu avg=%lf: "
54489 	                 "counts: %lu %lu %lu %lu %lu %lu %lu %lu ...",
54490 	                 (void *) heap->strtable, (unsigned long) count_total,
54491 	                 (unsigned long) count_chain_min, (unsigned long) count_chain_max,
54492 	                 (double) count_total / (double) heap->st_size,
54493 	                 (unsigned long) count_len[0], (unsigned long) count_len[1],
54494 	                 (unsigned long) count_len[2], (unsigned long) count_len[3],
54495 	                 (unsigned long) count_len[4], (unsigned long) count_len[5],
54496 	                 (unsigned long) count_len[6], (unsigned long) count_len[7]));
54497 }
54498 #endif  /* DUK_USE_DEBUG */
54499 
54500 /*
54501  *  Assertion helper to ensure strtable is populated correctly.
54502  */
54503 
54504 #if defined(DUK_USE_ASSERTIONS)
54505 DUK_LOCAL void duk__strtable_assert_checks(duk_heap *heap) {
54506 #if defined(DUK_USE_STRTAB_PTRCOMP)
54507 	duk_uint16_t *strtable;
54508 #else
54509 	duk_hstring **strtable;
54510 #endif
54511 	duk_uint32_t i;
54512 	duk_hstring *h;
54513 	duk_size_t count = 0;
54514 
54515 	DUK_ASSERT(heap != NULL);
54516 
54517 	strtable = DUK__GET_STRTABLE(heap);
54518 	if (strtable != NULL) {
54519 		DUK_ASSERT(heap->st_size != 0);
54520 		DUK_ASSERT(heap->st_mask == heap->st_size - 1);
54521 
54522 		for (i = 0; i < heap->st_size; i++) {
54523 			h = DUK__HEAPPTR_DEC16(heap, strtable[i]);
54524 			while (h != NULL) {
54525 				DUK_ASSERT((DUK_HSTRING_GET_HASH(h) & heap->st_mask) == i);
54526 				count++;
54527 				h = h->hdr.h_next;
54528 			}
54529 		}
54530 	} else {
54531 		DUK_ASSERT(heap->st_size == 0);
54532 		DUK_ASSERT(heap->st_mask == 0);
54533 	}
54534 
54535 #if defined(DUK__STRTAB_RESIZE_CHECK)
54536 	DUK_ASSERT(count == (duk_size_t) heap->st_count);
54537 #endif
54538 }
54539 #endif  /* DUK_USE_ASSERTIONS */
54540 
54541 /*
54542  *  Allocate and initialize a duk_hstring.
54543  *
54544  *  Returns a NULL if allocation or initialization fails for some reason.
54545  *
54546  *  The string won't be inserted into the string table and isn't tracked in
54547  *  any way (link pointers will be NULL).  The caller must place the string
54548  *  into the string table without any risk of a longjmp, otherwise the string
54549  *  is leaked.
54550  */
54551 
54552 DUK_LOCAL duk_hstring *duk__strtable_alloc_hstring(duk_heap *heap,
54553                                                    const duk_uint8_t *str,
54554                                                    duk_uint32_t blen,
54555                                                    duk_uint32_t strhash,
54556                                                    const duk_uint8_t *extdata) {
54557 	duk_hstring *res;
54558 	const duk_uint8_t *data;
54559 #if !defined(DUK_USE_HSTRING_ARRIDX)
54560 	duk_uarridx_t dummy;
54561 #endif
54562 
54563 	DUK_ASSERT(heap != NULL);
54564 	DUK_UNREF(extdata);
54565 
54566 #if defined(DUK_USE_STRLEN16)
54567 	/* If blen <= 0xffffUL, clen is also guaranteed to be <= 0xffffUL. */
54568 	if (blen > 0xffffUL) {
54569 		DUK_D(DUK_DPRINT("16-bit string blen/clen active and blen over 16 bits, reject intern"));
54570 		goto alloc_error;
54571 	}
54572 #endif
54573 
54574 	/* XXX: Memzeroing the allocated structure is not really necessary
54575 	 * because we could just initialize all fields explicitly (almost
54576 	 * all fields are initialized explicitly anyway).
54577 	 */
54578 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
54579 	if (extdata) {
54580 		res = (duk_hstring *) DUK_ALLOC(heap, sizeof(duk_hstring_external));
54581 		if (DUK_UNLIKELY(res == NULL)) {
54582 			goto alloc_error;
54583 		}
54584 		duk_memzero(res, sizeof(duk_hstring_external));
54585 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
54586 		DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
54587 #endif
54588 		DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, DUK_HSTRING_FLAG_EXTDATA);
54589 
54590 		DUK_ASSERT(extdata[blen] == 0);  /* Application responsibility. */
54591 		data = extdata;
54592 		((duk_hstring_external *) res)->extdata = extdata;
54593 	} else
54594 #endif  /* DUK_USE_HSTRING_EXTDATA && DUK_USE_EXTSTR_INTERN_CHECK */
54595 	{
54596 		duk_uint8_t *data_tmp;
54597 
54598 		/* NUL terminate for convenient C access */
54599 		DUK_ASSERT(sizeof(duk_hstring) + blen + 1 > blen);  /* No wrap, limits ensure. */
54600 		res = (duk_hstring *) DUK_ALLOC(heap, sizeof(duk_hstring) + blen + 1);
54601 		if (DUK_UNLIKELY(res == NULL)) {
54602 			goto alloc_error;
54603 		}
54604 		duk_memzero(res, sizeof(duk_hstring));
54605 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
54606 		DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
54607 #endif
54608 		DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0);
54609 
54610 		data_tmp = (duk_uint8_t *) (res + 1);
54611 		duk_memcpy(data_tmp, str, blen);
54612 		data_tmp[blen] = (duk_uint8_t) 0;
54613 		data = (const duk_uint8_t *) data_tmp;
54614 	}
54615 
54616 	DUK_HSTRING_SET_BYTELEN(res, blen);
54617 	DUK_HSTRING_SET_HASH(res, strhash);
54618 
54619 	DUK_ASSERT(!DUK_HSTRING_HAS_ARRIDX(res));
54620 #if defined(DUK_USE_HSTRING_ARRIDX)
54621 	res->arridx = duk_js_to_arrayindex_string(data, blen);
54622 	if (res->arridx != DUK_HSTRING_NO_ARRAY_INDEX) {
54623 #else
54624 	dummy = duk_js_to_arrayindex_string(data, blen);
54625 	if (dummy != DUK_HSTRING_NO_ARRAY_INDEX) {
54626 #endif
54627 		/* Array index strings cannot be symbol strings,
54628 		 * and they're always pure ASCII so blen == clen.
54629 		 */
54630 		DUK_HSTRING_SET_ARRIDX(res);
54631 		DUK_HSTRING_SET_ASCII(res);
54632 		DUK_ASSERT(duk_unicode_unvalidated_utf8_length(data, (duk_size_t) blen) == blen);
54633 	} else {
54634 		/* Because 'data' is NUL-terminated, we don't need a
54635 		 * blen > 0 check here.  For NUL (0x00) the symbol
54636 		 * checks will be false.
54637 		 */
54638 		if (DUK_UNLIKELY(data[0] >= 0x80U)) {
54639 			if (data[0] <= 0x81) {
54640 				DUK_HSTRING_SET_SYMBOL(res);
54641 			} else if (data[0] == 0x82U || data[0] == 0xffU) {
54642 				DUK_HSTRING_SET_HIDDEN(res);
54643 				DUK_HSTRING_SET_SYMBOL(res);
54644 			}
54645 		}
54646 
54647 		/* Using an explicit 'ASCII' flag has larger footprint (one call site
54648 		 * only) but is quite useful for the case when there's no explicit
54649 		 * 'clen' in duk_hstring.
54650 		 *
54651 		 * The flag is set lazily for RAM strings.
54652 		 */
54653 		DUK_ASSERT(!DUK_HSTRING_HAS_ASCII(res));
54654 
54655 #if defined(DUK_USE_HSTRING_LAZY_CLEN)
54656 		/* Charlen initialized to 0, updated on-the-fly. */
54657 #else
54658 		duk_hstring_init_charlen(res);  /* Also sets ASCII flag. */
54659 #endif
54660 	}
54661 
54662 	DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08lx, blen=%ld, has_arridx=%ld, has_extdata=%ld",
54663 	                     (unsigned long) DUK_HSTRING_GET_HASH(res),
54664 	                     (long) DUK_HSTRING_GET_BYTELEN(res),
54665 	                     (long) (DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0),
54666 	                     (long) (DUK_HSTRING_HAS_EXTDATA(res) ? 1 : 0)));
54667 
54668 	DUK_ASSERT(res != NULL);
54669 	return res;
54670 
54671  alloc_error:
54672 	return NULL;
54673 }
54674 
54675 /*
54676  *  Grow strtable allocation in-place.
54677  */
54678 
54679 #if defined(DUK__STRTAB_RESIZE_CHECK)
54680 DUK_LOCAL void duk__strtable_grow_inplace(duk_heap *heap) {
54681 	duk_uint32_t new_st_size;
54682 	duk_uint32_t old_st_size;
54683 	duk_uint32_t i;
54684 	duk_hstring *h;
54685 	duk_hstring *next;
54686 	duk_hstring *prev;
54687 #if defined(DUK_USE_STRTAB_PTRCOMP)
54688 	duk_uint16_t *new_ptr;
54689 	duk_uint16_t *new_ptr_high;
54690 #else
54691 	duk_hstring **new_ptr;
54692 	duk_hstring **new_ptr_high;
54693 #endif
54694 
54695 	DUK_DD(DUK_DDPRINT("grow in-place: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size * 2));
54696 
54697 	DUK_ASSERT(heap != NULL);
54698 	DUK_ASSERT(heap->st_resizing == 1);
54699 	DUK_ASSERT(heap->st_size >= 2);
54700 	DUK_ASSERT((heap->st_size & (heap->st_size - 1)) == 0);  /* 2^N */
54701 	DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
54702 
54703 	DUK_STATS_INC(heap, stats_strtab_resize_grow);
54704 
54705 	new_st_size = heap->st_size << 1U;
54706 	DUK_ASSERT(new_st_size > heap->st_size);  /* No overflow. */
54707 
54708 	/* Reallocate the strtable first and then work in-place to rehash
54709 	 * strings.  We don't need an indirect allocation here: even if GC
54710 	 * is triggered to satisfy the allocation, recursive strtable resize
54711 	 * is prevented by flags.  This is also why we don't need to use
54712 	 * DUK_REALLOC_INDIRECT().
54713 	 */
54714 
54715 #if defined(DUK_USE_STRTAB_PTRCOMP)
54716 	new_ptr = (duk_uint16_t *) DUK_REALLOC(heap, heap->strtable16, sizeof(duk_uint16_t) * new_st_size);
54717 #else
54718 	new_ptr = (duk_hstring **) DUK_REALLOC(heap, heap->strtable, sizeof(duk_hstring *) * new_st_size);
54719 #endif
54720 	if (DUK_UNLIKELY(new_ptr == NULL)) {
54721 		/* If realloc fails we can continue normally: the string table
54722 		 * won't "fill up" although chains will gradually get longer.
54723 		 * When string insertions continue, we'll quite soon try again
54724 		 * with no special handling.
54725 		 */
54726 		DUK_D(DUK_DPRINT("string table grow failed, ignoring"));
54727 		return;
54728 	}
54729 #if defined(DUK_USE_STRTAB_PTRCOMP)
54730 	heap->strtable16 = new_ptr;
54731 #else
54732 	heap->strtable = new_ptr;
54733 #endif
54734 
54735 	/* Rehash a single bucket into two separate ones.  When we grow
54736 	 * by x2 the highest 'new' bit determines whether a string remains
54737 	 * in its old position (bit is 0) or goes to a new one (bit is 1).
54738 	 */
54739 
54740 	old_st_size = heap->st_size;
54741 	new_ptr_high = new_ptr + old_st_size;
54742 	for (i = 0; i < old_st_size; i++) {
54743 		duk_hstring *new_root;
54744 		duk_hstring *new_root_high;
54745 
54746 		h = DUK__HEAPPTR_DEC16(heap, new_ptr[i]);
54747 		new_root = h;
54748 		new_root_high = NULL;
54749 
54750 		prev = NULL;
54751 		while (h != NULL) {
54752 			duk_uint32_t mask;
54753 
54754 			DUK_ASSERT((DUK_HSTRING_GET_HASH(h) & heap->st_mask) == i);
54755 			next = h->hdr.h_next;
54756 
54757 			/* Example: if previous size was 256, previous mask is 0xFF
54758 			 * and size is 0x100 which corresponds to the new bit that
54759 			 * comes into play.
54760 			 */
54761 			DUK_ASSERT(heap->st_mask == old_st_size - 1);
54762 			mask = old_st_size;
54763 			if (DUK_HSTRING_GET_HASH(h) & mask) {
54764 				if (prev != NULL) {
54765 					prev->hdr.h_next = h->hdr.h_next;
54766 				} else {
54767 					DUK_ASSERT(h == new_root);
54768 					new_root = h->hdr.h_next;
54769 				}
54770 
54771 				h->hdr.h_next = new_root_high;
54772 				new_root_high = h;
54773 			} else {
54774 				prev = h;
54775 			}
54776 			h = next;
54777 		}
54778 
54779 		new_ptr[i] = DUK__HEAPPTR_ENC16(heap, new_root);
54780 		new_ptr_high[i] = DUK__HEAPPTR_ENC16(heap, new_root_high);
54781 	}
54782 
54783 	heap->st_size = new_st_size;
54784 	heap->st_mask = new_st_size - 1;
54785 
54786 #if defined(DUK_USE_ASSERTIONS)
54787 	duk__strtable_assert_checks(heap);
54788 #endif
54789 }
54790 #endif  /* DUK__STRTAB_RESIZE_CHECK */
54791 
54792 /*
54793  *  Shrink strtable allocation in-place.
54794  */
54795 
54796 #if defined(DUK__STRTAB_RESIZE_CHECK)
54797 DUK_LOCAL void duk__strtable_shrink_inplace(duk_heap *heap) {
54798 	duk_uint32_t new_st_size;
54799 	duk_uint32_t i;
54800 	duk_hstring *h;
54801 	duk_hstring *other;
54802 	duk_hstring *root;
54803 #if defined(DUK_USE_STRTAB_PTRCOMP)
54804 	duk_uint16_t *old_ptr;
54805 	duk_uint16_t *old_ptr_high;
54806 	duk_uint16_t *new_ptr;
54807 #else
54808 	duk_hstring **old_ptr;
54809 	duk_hstring **old_ptr_high;
54810 	duk_hstring **new_ptr;
54811 #endif
54812 
54813 	DUK_DD(DUK_DDPRINT("shrink in-place: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size / 2));
54814 
54815 	DUK_ASSERT(heap != NULL);
54816 	DUK_ASSERT(heap->st_resizing == 1);
54817 	DUK_ASSERT(heap->st_size >= 2);
54818 	DUK_ASSERT((heap->st_size & (heap->st_size - 1)) == 0);  /* 2^N */
54819 	DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
54820 
54821 	DUK_STATS_INC(heap, stats_strtab_resize_shrink);
54822 
54823 	new_st_size = heap->st_size >> 1U;
54824 
54825 	/* Combine two buckets into a single one.  When we shrink, one hash
54826 	 * bit (highest) disappears.
54827 	 */
54828 	old_ptr = DUK__GET_STRTABLE(heap);
54829 	old_ptr_high = old_ptr + new_st_size;
54830 	for (i = 0; i < new_st_size; i++) {
54831 		h = DUK__HEAPPTR_DEC16(heap, old_ptr[i]);
54832 		other = DUK__HEAPPTR_DEC16(heap, old_ptr_high[i]);
54833 
54834 		if (h == NULL) {
54835 			/* First chain is empty, so use second one as is. */
54836 			root = other;
54837 		} else {
54838 			/* Find end of first chain, and link in the second. */
54839 			root = h;
54840 			while (h->hdr.h_next != NULL) {
54841 				h = h->hdr.h_next;
54842 			}
54843 			h->hdr.h_next = other;
54844 		}
54845 
54846 		old_ptr[i] = DUK__HEAPPTR_ENC16(heap, root);
54847 	}
54848 
54849 	heap->st_size = new_st_size;
54850 	heap->st_mask = new_st_size - 1;
54851 
54852 	/* The strtable is now consistent and we can realloc safely.  Even
54853 	 * if side effects cause string interning or removal the strtable
54854 	 * updates are safe.  Recursive resize has been prevented by caller.
54855 	 * This is also why we don't need to use DUK_REALLOC_INDIRECT().
54856 	 *
54857 	 * We assume a realloc() to a smaller size is guaranteed to succeed.
54858 	 * It would be relatively straightforward to handle the error by
54859 	 * essentially performing a "grow" step to recover.
54860 	 */
54861 
54862 #if defined(DUK_USE_STRTAB_PTRCOMP)
54863 	new_ptr = (duk_uint16_t *) DUK_REALLOC(heap, heap->strtable16, sizeof(duk_uint16_t) * new_st_size);
54864 	DUK_ASSERT(new_ptr != NULL);
54865 	heap->strtable16 = new_ptr;
54866 #else
54867 	new_ptr = (duk_hstring **) DUK_REALLOC(heap, heap->strtable, sizeof(duk_hstring *) * new_st_size);
54868 	DUK_ASSERT(new_ptr != NULL);
54869 	heap->strtable = new_ptr;
54870 #endif
54871 
54872 #if defined(DUK_USE_ASSERTIONS)
54873 	duk__strtable_assert_checks(heap);
54874 #endif
54875 }
54876 #endif  /* DUK__STRTAB_RESIZE_CHECK */
54877 
54878 /*
54879  *  Grow/shrink check.
54880  */
54881 
54882 #if defined(DUK__STRTAB_RESIZE_CHECK)
54883 DUK_LOCAL DUK_COLD DUK_NOINLINE void duk__strtable_resize_check(duk_heap *heap) {
54884 	duk_uint32_t load_factor;  /* fixed point */
54885 
54886 	DUK_ASSERT(heap != NULL);
54887 #if defined(DUK_USE_STRTAB_PTRCOMP)
54888 	DUK_ASSERT(heap->strtable16 != NULL);
54889 #else
54890 	DUK_ASSERT(heap->strtable != NULL);
54891 #endif
54892 
54893 	DUK_STATS_INC(heap, stats_strtab_resize_check);
54894 
54895 	/* Prevent recursive resizing. */
54896 	if (DUK_UNLIKELY(heap->st_resizing != 0U)) {
54897 		DUK_D(DUK_DPRINT("prevent recursive strtable resize"));
54898 		return;
54899 	}
54900 
54901 	heap->st_resizing = 1;
54902 
54903 	DUK_ASSERT(heap->st_size >= 16U);
54904 	DUK_ASSERT((heap->st_size >> 4U) >= 1);
54905 	load_factor = heap->st_count / (heap->st_size >> 4U);
54906 
54907 	DUK_DD(DUK_DDPRINT("resize check string table: size=%lu, count=%lu, load_factor=%lu (fixed point .4; float %lf)",
54908 	                   (unsigned long) heap->st_size, (unsigned long) heap->st_count,
54909 	                   (unsigned long) load_factor,
54910 	                   (double) heap->st_count / (double) heap->st_size));
54911 
54912 	if (load_factor >= DUK_USE_STRTAB_GROW_LIMIT) {
54913 		if (heap->st_size >= DUK_USE_STRTAB_MAXSIZE) {
54914 			DUK_DD(DUK_DDPRINT("want to grow strtable (based on load factor) but already maximum size"));
54915 		} else {
54916 			DUK_D(DUK_DPRINT("grow string table: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size * 2));
54917 #if defined(DUK_USE_DEBUG)
54918 			duk_heap_strtable_dump(heap);
54919 #endif
54920 			duk__strtable_grow_inplace(heap);
54921 		}
54922 	} else if (load_factor <= DUK_USE_STRTAB_SHRINK_LIMIT) {
54923 		if (heap->st_size <= DUK_USE_STRTAB_MINSIZE) {
54924 			DUK_DD(DUK_DDPRINT("want to shrink strtable (based on load factor) but already minimum size"));
54925 		} else {
54926 			DUK_D(DUK_DPRINT("shrink string table: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size / 2));
54927 #if defined(DUK_USE_DEBUG)
54928 			duk_heap_strtable_dump(heap);
54929 #endif
54930 			duk__strtable_shrink_inplace(heap);
54931 		}
54932 	} else {
54933 		DUK_DD(DUK_DDPRINT("no need for strtable resize"));
54934 	}
54935 
54936 	heap->st_resizing = 0;
54937 }
54938 #endif  /* DUK__STRTAB_RESIZE_CHECK */
54939 
54940 /*
54941  *  Torture grow/shrink: unconditionally grow and shrink back.
54942  */
54943 
54944 #if defined(DUK_USE_STRTAB_TORTURE) && defined(DUK__STRTAB_RESIZE_CHECK)
54945 DUK_LOCAL void duk__strtable_resize_torture(duk_heap *heap) {
54946 	duk_uint32_t old_st_size;
54947 
54948 	DUK_ASSERT(heap != NULL);
54949 
54950 	old_st_size = heap->st_size;
54951 	if (old_st_size >= DUK_USE_STRTAB_MAXSIZE) {
54952 		return;
54953 	}
54954 
54955 	heap->st_resizing = 1;
54956 	duk__strtable_grow_inplace(heap);
54957 	if (heap->st_size > old_st_size) {
54958 		duk__strtable_shrink_inplace(heap);
54959 	}
54960 	heap->st_resizing = 0;
54961 }
54962 #endif  /* DUK_USE_STRTAB_TORTURE && DUK__STRTAB_RESIZE_CHECK */
54963 
54964 /*
54965  *  Raw intern; string already checked not to be present.
54966  */
54967 
54968 DUK_LOCAL duk_hstring *duk__strtable_do_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
54969 	duk_hstring *res;
54970 	const duk_uint8_t *extdata;
54971 #if defined(DUK_USE_STRTAB_PTRCOMP)
54972 	duk_uint16_t *slot;
54973 #else
54974 	duk_hstring **slot;
54975 #endif
54976 
54977 	DUK_DDD(DUK_DDDPRINT("do_intern: heap=%p, str=%p, blen=%lu, strhash=%lx, st_size=%lu, st_count=%lu, load=%lf",
54978 	                     (void *) heap, (const void *) str, (unsigned long) blen, (unsigned long) strhash,
54979 	                     (unsigned long) heap->st_size, (unsigned long) heap->st_count,
54980 	                     (double) heap->st_count / (double) heap->st_size));
54981 
54982 	DUK_ASSERT(heap != NULL);
54983 
54984 	/* Prevent any side effects on the string table and the caller provided
54985 	 * str/blen arguments while interning is in progress.  For example, if
54986 	 * the caller provided str/blen from a dynamic buffer, a finalizer
54987 	 * might resize or modify that dynamic buffer, invalidating the call
54988 	 * arguments.
54989 	 *
54990 	 * While finalizers must be prevented, mark-and-sweep itself is fine.
54991 	 * Recursive string table resize is prevented explicitly here.
54992 	 */
54993 
54994 	heap->pf_prevent_count++;
54995 	DUK_ASSERT(heap->pf_prevent_count != 0);  /* Wrap. */
54996 
54997 #if defined(DUK_USE_STRTAB_TORTURE) && defined(DUK__STRTAB_RESIZE_CHECK)
54998 	duk__strtable_resize_torture(heap);
54999 #endif
55000 
55001 	/* String table grow/shrink check.  Because of chaining (and no
55002 	 * accumulation issues as with hash probe chains and DELETED
55003 	 * markers) there's never a mandatory need to resize right now.
55004 	 * Check for the resize only periodically, based on st_count
55005 	 * bit pattern.  Because string table removal doesn't do a shrink
55006 	 * check, we do that also here.
55007 	 *
55008 	 * Do the resize and possible grow/shrink before the new duk_hstring
55009 	 * has been allocated.  Otherwise we may trigger a GC when the result
55010 	 * duk_hstring is not yet strongly referenced.
55011 	 */
55012 
55013 #if defined(DUK__STRTAB_RESIZE_CHECK)
55014 	if (DUK_UNLIKELY((heap->st_count & DUK_USE_STRTAB_RESIZE_CHECK_MASK) == 0)) {
55015 		duk__strtable_resize_check(heap);
55016 	}
55017 #endif
55018 
55019 	/* External string check (low memory optimization). */
55020 
55021 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
55022 	extdata = (const duk_uint8_t *) DUK_USE_EXTSTR_INTERN_CHECK(heap->heap_udata, (void *) DUK_LOSE_CONST(str), (duk_size_t) blen);
55023 #else
55024 	extdata = (const duk_uint8_t *) NULL;
55025 #endif
55026 
55027 	/* Allocate and initialize string, not yet linked.  This may cause a
55028 	 * GC which may cause other strings to be interned and inserted into
55029 	 * the string table before we insert our string.  Finalizer execution
55030 	 * is disabled intentionally to avoid a finalizer from e.g. resizing
55031 	 * a buffer used as a data area for 'str'.
55032 	 */
55033 
55034 	res = duk__strtable_alloc_hstring(heap, str, blen, strhash, extdata);
55035 
55036 	/* Allow side effects again: GC must be avoided until duk_hstring
55037 	 * result (if successful) has been INCREF'd.
55038 	 */
55039 	DUK_ASSERT(heap->pf_prevent_count > 0);
55040 	heap->pf_prevent_count--;
55041 
55042 	/* Alloc error handling. */
55043 
55044 	if (DUK_UNLIKELY(res == NULL)) {
55045 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
55046 		if (extdata != NULL) {
55047 			DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) extdata);
55048 		}
55049 #endif
55050 		return NULL;
55051 	}
55052 
55053 	/* Insert into string table. */
55054 
55055 #if defined(DUK_USE_STRTAB_PTRCOMP)
55056 	slot = heap->strtable16 + (strhash & heap->st_mask);
55057 #else
55058 	slot = heap->strtable + (strhash & heap->st_mask);
55059 #endif
55060 	DUK_ASSERT(res->hdr.h_next == NULL);  /* This is the case now, but unnecessary zeroing/NULLing. */
55061 	res->hdr.h_next = DUK__HEAPPTR_DEC16(heap, *slot);
55062 	*slot = DUK__HEAPPTR_ENC16(heap, res);
55063 
55064 	/* Update string count only for successful inserts. */
55065 
55066 #if defined(DUK__STRTAB_RESIZE_CHECK)
55067 	heap->st_count++;
55068 #endif
55069 
55070 	/* The duk_hstring is in the string table but is not yet strongly
55071 	 * reachable.  Calling code MUST NOT make any allocations or other
55072 	 * side effects before the duk_hstring has been INCREF'd and made
55073 	 * reachable.
55074 	 */
55075 
55076 	return res;
55077 }
55078 
55079 /*
55080  *  Intern a string from str/blen, returning either an existing duk_hstring
55081  *  or adding a new one into the string table.  The input string does -not-
55082  *  need to be NUL terminated.
55083  *
55084  *  The input 'str' argument may point to a Duktape managed data area such as
55085  *  the data area of a dynamic buffer.  It's crucial to avoid any side effects
55086  *  that might affect the data area (e.g. resize the dynamic buffer, or write
55087  *  to the buffer) before the string is fully interned.
55088  */
55089 
55090 #if defined(DUK_USE_ROM_STRINGS)
55091 DUK_LOCAL duk_hstring *duk__strtab_romstring_lookup(duk_heap *heap, const duk_uint8_t *str, duk_size_t blen, duk_uint32_t strhash) {
55092 	duk_size_t lookup_hash;
55093 	duk_hstring *curr;
55094 
55095 	DUK_ASSERT(heap != NULL);
55096 	DUK_UNREF(heap);
55097 
55098 	lookup_hash = (blen << 4);
55099 	if (blen > 0) {
55100 		lookup_hash += str[0];
55101 	}
55102 	lookup_hash &= 0xff;
55103 
55104 	curr = (duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_lookup[lookup_hash]);
55105 	while (curr != NULL) {
55106 		/* Unsafe memcmp() because for zero blen, str may be NULL. */
55107 		if (strhash == DUK_HSTRING_GET_HASH(curr) &&
55108 		    blen == DUK_HSTRING_GET_BYTELEN(curr) &&
55109 		    duk_memcmp_unsafe((const void *) str, (const void *) DUK_HSTRING_GET_DATA(curr), blen) == 0) {
55110 			DUK_DDD(DUK_DDDPRINT("intern check: rom string: %!O, computed hash 0x%08lx, rom hash 0x%08lx",
55111 			                     curr, (unsigned long) strhash, (unsigned long) DUK_HSTRING_GET_HASH(curr)));
55112 			return curr;
55113 		}
55114 		curr = curr->hdr.h_next;
55115 	}
55116 
55117 	return NULL;
55118 }
55119 #endif  /* DUK_USE_ROM_STRINGS */
55120 
55121 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen) {
55122 	duk_uint32_t strhash;
55123 	duk_hstring *h;
55124 
55125 	DUK_DDD(DUK_DDDPRINT("intern check: heap=%p, str=%p, blen=%lu", (void *) heap, (const void *) str, (unsigned long) blen));
55126 
55127 	/* Preliminaries. */
55128 
55129 	/* XXX: maybe just require 'str != NULL' even for zero size? */
55130 	DUK_ASSERT(heap != NULL);
55131 	DUK_ASSERT(blen == 0 || str != NULL);
55132 	DUK_ASSERT(blen <= DUK_HSTRING_MAX_BYTELEN);  /* Caller is responsible for ensuring this. */
55133 	strhash = duk_heap_hashstring(heap, str, (duk_size_t) blen);
55134 
55135 	/* String table lookup. */
55136 
55137 	DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
55138 	DUK_ASSERT(heap->st_size > 0);
55139 	DUK_ASSERT(heap->st_size == heap->st_mask + 1);
55140 #if defined(DUK_USE_STRTAB_PTRCOMP)
55141 	h = DUK__HEAPPTR_DEC16(heap, heap->strtable16[strhash & heap->st_mask]);
55142 #else
55143 	h = heap->strtable[strhash & heap->st_mask];
55144 #endif
55145 	while (h != NULL) {
55146 		if (DUK_HSTRING_GET_HASH(h) == strhash &&
55147 		    DUK_HSTRING_GET_BYTELEN(h) == blen &&
55148 		    duk_memcmp_unsafe((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
55149 			/* Found existing entry. */
55150 			DUK_STATS_INC(heap, stats_strtab_intern_hit);
55151 			return h;
55152 		}
55153 		h = h->hdr.h_next;
55154 	}
55155 
55156 	/* ROM table lookup.  Because this lookup is slower, do it only after
55157 	 * RAM lookup.  This works because no ROM string is ever interned into
55158 	 * the RAM string table.
55159 	 */
55160 
55161 #if defined(DUK_USE_ROM_STRINGS)
55162 	h = duk__strtab_romstring_lookup(heap, str, blen, strhash);
55163 	if (h != NULL) {
55164 		DUK_STATS_INC(heap, stats_strtab_intern_hit);
55165 		return h;
55166 	}
55167 #endif
55168 
55169 	/* Not found in string table; insert. */
55170 
55171 	DUK_STATS_INC(heap, stats_strtab_intern_miss);
55172 	h = duk__strtable_do_intern(heap, str, blen, strhash);
55173 	return h;  /* may be NULL */
55174 }
55175 
55176 /*
55177  *  Intern a string from u32.
55178  */
55179 
55180 /* XXX: Could arrange some special handling because we know that the result
55181  * will have an arridx flag and an ASCII flag, won't need a clen check, etc.
55182  */
55183 
55184 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_u32(duk_heap *heap, duk_uint32_t val) {
55185 	duk_uint8_t buf[DUK__STRTAB_U32_MAX_STRLEN];
55186 	duk_uint8_t *p;
55187 
55188 	DUK_ASSERT(heap != NULL);
55189 
55190 	/* This is smaller and faster than a %lu sprintf. */
55191 	p = buf + sizeof(buf);
55192 	do {
55193 		p--;
55194 		*p = duk_lc_digits[val % 10];
55195 		val = val / 10;
55196 	} while (val != 0);  /* For val == 0, emit exactly one '0'. */
55197 	DUK_ASSERT(p >= buf);
55198 
55199 	return duk_heap_strtable_intern(heap, (const duk_uint8_t *) p, (duk_uint32_t) ((buf + sizeof(buf)) - p));
55200 }
55201 
55202 /*
55203  *  Checked convenience variants.
55204  *
55205  *  XXX: Because the main use case is for the checked variants, make them the
55206  *  main functionality and provide a safe variant separately (it is only needed
55207  *  during heap init).  The problem with that is that longjmp state and error
55208  *  creation must already be possible to throw.
55209  */
55210 
55211 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {
55212 	duk_hstring *res;
55213 
55214 	DUK_ASSERT(thr != NULL);
55215 	DUK_ASSERT(thr->heap != NULL);
55216 	DUK_ASSERT(blen == 0 || str != NULL);
55217 
55218 	res = duk_heap_strtable_intern(thr->heap, str, blen);
55219 	if (DUK_UNLIKELY(res == NULL)) {
55220 		DUK_ERROR_ALLOC_FAILED(thr);
55221 		DUK_WO_NORETURN(return NULL;);
55222 	}
55223 	return res;
55224 }
55225 
55226 #if defined(DUK_USE_LITCACHE_SIZE)
55227 DUK_LOCAL duk_uint_t duk__strtable_litcache_key(const duk_uint8_t *str, duk_uint32_t blen) {
55228 	duk_uintptr_t key;
55229 
55230 	DUK_ASSERT(DUK_USE_LITCACHE_SIZE > 0);
55231 	DUK_ASSERT(DUK_IS_POWER_OF_TWO((duk_uint_t) DUK_USE_LITCACHE_SIZE));
55232 
55233 	key = (duk_uintptr_t) blen ^ (duk_uintptr_t) str;
55234 	key &= (duk_uintptr_t) (DUK_USE_LITCACHE_SIZE - 1);  /* Assumes size is power of 2. */
55235 	/* Due to masking, cast is in 32-bit range. */
55236 	DUK_ASSERT(key <= DUK_UINT_MAX);
55237 	return (duk_uint_t) key;
55238 }
55239 
55240 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_literal_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {
55241 	duk_uint_t key;
55242 	duk_litcache_entry *ent;
55243 	duk_hstring *h;
55244 
55245 	/* Fast path check: literal exists in literal cache. */
55246 	key = duk__strtable_litcache_key(str, blen);
55247 	ent = thr->heap->litcache + key;
55248 	if (ent->addr == str) {
55249 		DUK_DD(DUK_DDPRINT("intern check for cached, pinned literal: str=%p, blen=%ld -> duk_hstring %!O",
55250 		                   (const void *) str, (long) blen, (duk_heaphdr *) ent->h));
55251 		DUK_ASSERT(ent->h != NULL);
55252 		DUK_ASSERT(DUK_HSTRING_HAS_PINNED_LITERAL(ent->h));
55253 		DUK_STATS_INC(thr->heap, stats_strtab_litcache_hit);
55254 		return ent->h;
55255 	}
55256 
55257 	/* Intern and update (overwrite) cache entry. */
55258 	h = duk_heap_strtable_intern_checked(thr, str, blen);
55259 	ent->addr = str;
55260 	ent->h = h;
55261 	DUK_STATS_INC(thr->heap, stats_strtab_litcache_miss);
55262 
55263 	/* Pin the duk_hstring until the next mark-and-sweep.  This means
55264 	 * litcache entries don't need to be invalidated until the next
55265 	 * mark-and-sweep as their target duk_hstring is not freed before
55266 	 * the mark-and-sweep happens.  The pin remains even if the literal
55267 	 * cache entry is overwritten, and is still useful to avoid string
55268 	 * table traffic.
55269 	 */
55270 	if (!DUK_HSTRING_HAS_PINNED_LITERAL(h)) {
55271 		DUK_DD(DUK_DDPRINT("pin duk_hstring because it is a literal: %!O", (duk_heaphdr *) h));
55272 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));
55273 		DUK_HSTRING_INCREF(thr, h);
55274 		DUK_HSTRING_SET_PINNED_LITERAL(h);
55275 		DUK_STATS_INC(thr->heap, stats_strtab_litcache_pin);
55276 	}
55277 
55278 	return h;
55279 }
55280 #endif  /* DUK_USE_LITCACHE_SIZE */
55281 
55282 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_u32_checked(duk_hthread *thr, duk_uint32_t val) {
55283 	duk_hstring *res;
55284 
55285 	DUK_ASSERT(thr != NULL);
55286 	DUK_ASSERT(thr->heap != NULL);
55287 
55288 	res = duk_heap_strtable_intern_u32(thr->heap, val);
55289 	if (DUK_UNLIKELY(res == NULL)) {
55290 		DUK_ERROR_ALLOC_FAILED(thr);
55291 		DUK_WO_NORETURN(return NULL;);
55292 	}
55293 	return res;
55294 }
55295 
55296 /*
55297  *  Remove (unlink) a string from the string table.
55298  *
55299  *  Just unlinks the duk_hstring, leaving link pointers as garbage.
55300  *  Caller must free the string itself.
55301  */
55302 
55303 #if defined(DUK_USE_REFERENCE_COUNTING)
55304 /* Unlink without a 'prev' pointer. */
55305 DUK_INTERNAL void duk_heap_strtable_unlink(duk_heap *heap, duk_hstring *h) {
55306 #if defined(DUK_USE_STRTAB_PTRCOMP)
55307 	duk_uint16_t *slot;
55308 #else
55309 	duk_hstring **slot;
55310 #endif
55311 	duk_hstring *other;
55312 	duk_hstring *prev;
55313 
55314 	DUK_DDD(DUK_DDDPRINT("remove: heap=%p, h=%p, blen=%lu, strhash=%lx",
55315 	                     (void *) heap, (void *) h,
55316 	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_BYTELEN(h) : 0),
55317 	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_HASH(h) : 0)));
55318 
55319 	DUK_ASSERT(heap != NULL);
55320 	DUK_ASSERT(h != NULL);
55321 
55322 #if defined(DUK__STRTAB_RESIZE_CHECK)
55323 	DUK_ASSERT(heap->st_count > 0);
55324 	heap->st_count--;
55325 #endif
55326 
55327 #if defined(DUK_USE_STRTAB_PTRCOMP)
55328 	slot = heap->strtable16 + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
55329 #else
55330 	slot = heap->strtable + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
55331 #endif
55332 	other = DUK__HEAPPTR_DEC16(heap, *slot);
55333 	DUK_ASSERT(other != NULL);  /* At least argument string is in the chain. */
55334 
55335 	prev = NULL;
55336 	while (other != h) {
55337 		prev = other;
55338 		other = other->hdr.h_next;
55339 		DUK_ASSERT(other != NULL);  /* We'll eventually find 'h'. */
55340 	}
55341 	if (prev != NULL) {
55342 		/* Middle of list. */
55343 		prev->hdr.h_next = h->hdr.h_next;
55344 	} else {
55345 		/* Head of list. */
55346 		*slot = DUK__HEAPPTR_ENC16(heap, h->hdr.h_next);
55347 	}
55348 
55349 	/* There's no resize check on a string free.  The next string
55350 	 * intern will do one.
55351 	 */
55352 }
55353 #endif  /* DUK_USE_REFERENCE_COUNTING */
55354 
55355 /* Unlink with a 'prev' pointer. */
55356 DUK_INTERNAL void duk_heap_strtable_unlink_prev(duk_heap *heap, duk_hstring *h, duk_hstring *prev) {
55357 #if defined(DUK_USE_STRTAB_PTRCOMP)
55358 	duk_uint16_t *slot;
55359 #else
55360 	duk_hstring **slot;
55361 #endif
55362 
55363 	DUK_DDD(DUK_DDDPRINT("remove: heap=%p, prev=%p, h=%p, blen=%lu, strhash=%lx",
55364 	                     (void *) heap, (void *) prev, (void *) h,
55365 	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_BYTELEN(h) : 0),
55366 	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_HASH(h) : 0)));
55367 
55368 	DUK_ASSERT(heap != NULL);
55369 	DUK_ASSERT(h != NULL);
55370 	DUK_ASSERT(prev == NULL || prev->hdr.h_next == h);
55371 
55372 #if defined(DUK__STRTAB_RESIZE_CHECK)
55373 	DUK_ASSERT(heap->st_count > 0);
55374 	heap->st_count--;
55375 #endif
55376 
55377 	if (prev != NULL) {
55378 		/* Middle of list. */
55379 		prev->hdr.h_next = h->hdr.h_next;
55380 	} else {
55381 		/* Head of list. */
55382 #if defined(DUK_USE_STRTAB_PTRCOMP)
55383 		slot = heap->strtable16 + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
55384 #else
55385 		slot = heap->strtable + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
55386 #endif
55387 		DUK_ASSERT(DUK__HEAPPTR_DEC16(heap, *slot) == h);
55388 		*slot = DUK__HEAPPTR_ENC16(heap, h->hdr.h_next);
55389 	}
55390 }
55391 
55392 /*
55393  *  Force string table resize check in mark-and-sweep.
55394  */
55395 
55396 DUK_INTERNAL void duk_heap_strtable_force_resize(duk_heap *heap) {
55397 	/* Does only one grow/shrink step if needed.  The heap->st_resizing
55398 	 * flag protects against recursive resizing.
55399 	 */
55400 
55401 	DUK_ASSERT(heap != NULL);
55402 	DUK_UNREF(heap);
55403 
55404 #if defined(DUK__STRTAB_RESIZE_CHECK)
55405 #if defined(DUK_USE_STRTAB_PTRCOMP)
55406 	if (heap->strtable16 != NULL) {
55407 #else
55408 	if (heap->strtable != NULL) {
55409 #endif
55410 		duk__strtable_resize_check(heap);
55411 	}
55412 #endif
55413 }
55414 
55415 /*
55416  *  Free strings in the string table and the string table itself.
55417  */
55418 
55419 DUK_INTERNAL void duk_heap_strtable_free(duk_heap *heap) {
55420 #if defined(DUK_USE_STRTAB_PTRCOMP)
55421 	duk_uint16_t *strtable;
55422 	duk_uint16_t *st;
55423 #else
55424 	duk_hstring **strtable;
55425 	duk_hstring **st;
55426 #endif
55427 	duk_hstring *h;
55428 
55429 	DUK_ASSERT(heap != NULL);
55430 
55431 #if defined(DUK_USE_ASSERTIONS)
55432 	duk__strtable_assert_checks(heap);
55433 #endif
55434 
55435 	/* Strtable can be NULL if heap init fails.  However, in that case
55436 	 * heap->st_size is 0, so strtable == strtable_end and we skip the
55437 	 * loop without a special check.
55438 	 */
55439 	strtable = DUK__GET_STRTABLE(heap);
55440 	st = strtable + heap->st_size;
55441 	DUK_ASSERT(strtable != NULL || heap->st_size == 0);
55442 
55443 	while (strtable != st) {
55444 		--st;
55445 		h = DUK__HEAPPTR_DEC16(heap, *st);
55446 		while (h) {
55447 			duk_hstring *h_next;
55448 			h_next = h->hdr.h_next;
55449 
55450 			/* Strings may have inner refs (extdata) in some cases. */
55451 			duk_free_hstring(heap, h);
55452 
55453 			h = h_next;
55454 		}
55455 	}
55456 
55457 	DUK_FREE(heap, strtable);
55458 }
55459 
55460 /* automatic undefs */
55461 #undef DUK__GET_STRTABLE
55462 #undef DUK__HEAPPTR_DEC16
55463 #undef DUK__HEAPPTR_ENC16
55464 #undef DUK__STRTAB_U32_MAX_STRLEN
55465 #line 1 "duk_heaphdr_assert.c"
55466 /*
55467  *  duk_heaphdr assertion helpers
55468  */
55469 
55470 /* #include duk_internal.h -> already included */
55471 
55472 #if defined(DUK_USE_ASSERTIONS)
55473 
55474 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
55475 DUK_INTERNAL void duk_heaphdr_assert_links(duk_heap *heap, duk_heaphdr *h) {
55476 	DUK_UNREF(heap);
55477 	if (h != NULL) {
55478 		duk_heaphdr *h_prev, *h_next;
55479 		h_prev = DUK_HEAPHDR_GET_PREV(heap, h);
55480 		h_next = DUK_HEAPHDR_GET_NEXT(heap, h);
55481 		DUK_ASSERT(h_prev == NULL || (DUK_HEAPHDR_GET_NEXT(heap, h_prev) == h));
55482 		DUK_ASSERT(h_next == NULL || (DUK_HEAPHDR_GET_PREV(heap, h_next) == h));
55483 	}
55484 }
55485 #else
55486 DUK_INTERNAL void duk_heaphdr_assert_links(duk_heap *heap, duk_heaphdr *h) {
55487 	DUK_UNREF(heap);
55488 	DUK_UNREF(h);
55489 }
55490 #endif
55491 
55492 DUK_INTERNAL void duk_heaphdr_assert_valid(duk_heaphdr *h) {
55493 	DUK_ASSERT(h != NULL);
55494 	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
55495 }
55496 
55497 /* Assert validity of a heaphdr, including all subclasses. */
55498 DUK_INTERNAL void duk_heaphdr_assert_valid_subclassed(duk_heaphdr *h) {
55499 	switch (DUK_HEAPHDR_GET_TYPE(h)) {
55500 	case DUK_HTYPE_OBJECT: {
55501 		duk_hobject *h_obj = (duk_hobject *) h;
55502 		DUK_HOBJECT_ASSERT_VALID(h_obj);
55503 		if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
55504 			DUK_HCOMPFUNC_ASSERT_VALID((duk_hcompfunc *) h_obj);
55505 		} else if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
55506 			DUK_HNATFUNC_ASSERT_VALID((duk_hnatfunc *) h_obj);
55507 		} else if (DUK_HOBJECT_IS_DECENV(h_obj)) {
55508 			DUK_HDECENV_ASSERT_VALID((duk_hdecenv *) h_obj);
55509 		} else if (DUK_HOBJECT_IS_OBJENV(h_obj)) {
55510 			DUK_HOBJENV_ASSERT_VALID((duk_hobjenv *) h_obj);
55511 		} else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
55512 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
55513 			DUK_HBUFOBJ_ASSERT_VALID((duk_hbufobj *) h_obj);
55514 #endif
55515 		} else if (DUK_HOBJECT_IS_BOUNDFUNC(h_obj)) {
55516 			DUK_HBOUNDFUNC_ASSERT_VALID((duk_hboundfunc *) h_obj);
55517 		} else if (DUK_HOBJECT_IS_PROXY(h_obj)) {
55518 			DUK_HPROXY_ASSERT_VALID((duk_hproxy *) h_obj);
55519 		} else if (DUK_HOBJECT_IS_THREAD(h_obj)) {
55520 			DUK_HTHREAD_ASSERT_VALID((duk_hthread *) h_obj);
55521 		} else {
55522 			/* Just a plain object. */
55523 			;
55524 		}
55525 		break;
55526 	}
55527 	case DUK_HTYPE_STRING: {
55528 		duk_hstring *h_str = (duk_hstring *) h;
55529 		DUK_HSTRING_ASSERT_VALID(h_str);
55530 		break;
55531 	}
55532 	case DUK_HTYPE_BUFFER: {
55533 		duk_hbuffer *h_buf = (duk_hbuffer *) h;
55534 		DUK_HBUFFER_ASSERT_VALID(h_buf);
55535 		break;
55536 	}
55537 	default: {
55538 		DUK_ASSERT(0);
55539 	}
55540 	}
55541 }
55542 
55543 #endif  /* DUK_USE_ASSERTIONS */
55544 #line 1 "duk_hobject_alloc.c"
55545 /*
55546  *  Hobject allocation.
55547  *
55548  *  Provides primitive allocation functions for all object types (plain object,
55549  *  compiled function, native function, thread).  The object return is not yet
55550  *  in "heap allocated" list and has a refcount of zero, so caller must careful.
55551  */
55552 
55553 /* XXX: In most cases there's no need for plain allocation without pushing
55554  * to the value stack.  Maybe rework contract?
55555  */
55556 
55557 /* #include duk_internal.h -> already included */
55558 
55559 /*
55560  *  Helpers.
55561  */
55562 
55563 DUK_LOCAL void duk__init_object_parts(duk_heap *heap, duk_uint_t hobject_flags, duk_hobject *obj) {
55564 	DUK_ASSERT(obj != NULL);
55565 	/* Zeroed by caller. */
55566 
55567 	obj->hdr.h_flags = hobject_flags | DUK_HTYPE_OBJECT;
55568 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(&obj->hdr) == DUK_HTYPE_OBJECT);  /* Assume zero shift. */
55569 
55570 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
55571 	DUK_HOBJECT_SET_PROTOTYPE(heap, obj, NULL);
55572 	DUK_HOBJECT_SET_PROPS(heap, obj, NULL);
55573 #endif
55574 #if defined(DUK_USE_HEAPPTR16)
55575 	/* Zero encoded pointer is required to match NULL. */
55576 	DUK_HEAPHDR_SET_NEXT(heap, &obj->hdr, NULL);
55577 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
55578 	DUK_HEAPHDR_SET_PREV(heap, &obj->hdr, NULL);
55579 #endif
55580 #endif
55581 	DUK_HEAPHDR_ASSERT_LINKS(heap, &obj->hdr);
55582 	DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &obj->hdr);
55583 
55584 	/* obj->props is intentionally left as NULL, and duk_hobject_props.c must deal
55585 	 * with this properly.  This is intentional: empty objects consume a minimum
55586 	 * amount of memory.  Further, an initial allocation might fail and cause
55587 	 * 'obj' to "leak" (require a mark-and-sweep) since it is not reachable yet.
55588 	 */
55589 }
55590 
55591 DUK_LOCAL void *duk__hobject_alloc_init(duk_hthread *thr, duk_uint_t hobject_flags, duk_size_t size) {
55592 	void *res;
55593 
55594 	res = (void *) DUK_ALLOC_CHECKED_ZEROED(thr, size);
55595 	DUK_ASSERT(res != NULL);
55596 	duk__init_object_parts(thr->heap, hobject_flags, (duk_hobject *) res);
55597 	return res;
55598 }
55599 
55600 /*
55601  *  Allocate an duk_hobject.
55602  *
55603  *  The allocated object has no allocation for properties; the caller may
55604  *  want to force a resize if a desired size is known.
55605  *
55606  *  The allocated object has zero reference count and is not reachable.
55607  *  The caller MUST make the object reachable and increase its reference
55608  *  count before invoking any operation that might require memory allocation.
55609  */
55610 
55611 DUK_INTERNAL duk_hobject *duk_hobject_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags) {
55612 	duk_hobject *res;
55613 
55614 	DUK_ASSERT(heap != NULL);
55615 
55616 	/* different memory layout, alloc size, and init */
55617 	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_COMPFUNC) == 0);
55618 	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_NATFUNC) == 0);
55619 	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_BOUNDFUNC) == 0);
55620 
55621 	res = (duk_hobject *) DUK_ALLOC_ZEROED(heap, sizeof(duk_hobject));
55622 	if (DUK_UNLIKELY(res == NULL)) {
55623 		return NULL;
55624 	}
55625 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(res));
55626 
55627 	duk__init_object_parts(heap, hobject_flags, res);
55628 
55629 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(res));
55630 	return res;
55631 }
55632 
55633 DUK_INTERNAL duk_hobject *duk_hobject_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
55634 	duk_hobject *res;
55635 
55636 	res = (duk_hobject *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hobject));
55637 	return res;
55638 }
55639 
55640 DUK_INTERNAL duk_hcompfunc *duk_hcompfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
55641 	duk_hcompfunc *res;
55642 
55643 	res = (duk_hcompfunc *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hcompfunc));
55644 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
55645 #if defined(DUK_USE_HEAPPTR16)
55646 	/* NULL pointer is required to encode to zero, so memset is enough. */
55647 #else
55648 	res->data = NULL;
55649 	res->funcs = NULL;
55650 	res->bytecode = NULL;
55651 #endif
55652 	res->lex_env = NULL;
55653 	res->var_env = NULL;
55654 #endif
55655 
55656 	return res;
55657 }
55658 
55659 DUK_INTERNAL duk_hnatfunc *duk_hnatfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
55660 	duk_hnatfunc *res;
55661 
55662 	res = (duk_hnatfunc *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hnatfunc));
55663 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
55664 	res->func = NULL;
55665 #endif
55666 
55667 	return res;
55668 }
55669 
55670 DUK_INTERNAL duk_hboundfunc *duk_hboundfunc_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
55671 	duk_hboundfunc *res;
55672 
55673 	res = (duk_hboundfunc *) DUK_ALLOC(heap, sizeof(duk_hboundfunc));
55674 	if (!res) {
55675 		return NULL;
55676 	}
55677 	duk_memzero(res, sizeof(duk_hboundfunc));
55678 
55679 	duk__init_object_parts(heap, hobject_flags, &res->obj);
55680 
55681 	DUK_TVAL_SET_UNDEFINED(&res->target);
55682 	DUK_TVAL_SET_UNDEFINED(&res->this_binding);
55683 
55684 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
55685 	res->args = NULL;
55686 #endif
55687 
55688 	return res;
55689 }
55690 
55691 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
55692 DUK_INTERNAL duk_hbufobj *duk_hbufobj_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
55693 	duk_hbufobj *res;
55694 
55695 	res = (duk_hbufobj *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hbufobj));
55696 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
55697 	res->buf = NULL;
55698 	res->buf_prop = NULL;
55699 #endif
55700 
55701 	DUK_HBUFOBJ_ASSERT_VALID(res);
55702 	return res;
55703 }
55704 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
55705 
55706 /* Allocate a new thread.
55707  *
55708  * Leaves the built-ins array uninitialized.  The caller must either
55709  * initialize a new global context or share existing built-ins from
55710  * another thread.
55711  */
55712 DUK_INTERNAL duk_hthread *duk_hthread_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags) {
55713 	duk_hthread *res;
55714 
55715 	res = (duk_hthread *) DUK_ALLOC(heap, sizeof(duk_hthread));
55716 	if (DUK_UNLIKELY(res == NULL)) {
55717 		return NULL;
55718 	}
55719 	duk_memzero(res, sizeof(duk_hthread));
55720 
55721 	duk__init_object_parts(heap, hobject_flags, &res->obj);
55722 
55723 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
55724 	res->ptr_curr_pc = NULL;
55725 	res->heap = NULL;
55726 	res->valstack = NULL;
55727 	res->valstack_end = NULL;
55728 	res->valstack_alloc_end = NULL;
55729 	res->valstack_bottom = NULL;
55730 	res->valstack_top = NULL;
55731 	res->callstack_curr = NULL;
55732 	res->resumer = NULL;
55733 	res->compile_ctx = NULL,
55734 #if defined(DUK_USE_HEAPPTR16)
55735 	res->strs16 = NULL;
55736 #else
55737 	res->strs = NULL;
55738 #endif
55739 	{
55740 		duk_small_uint_t i;
55741 		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
55742 			res->builtins[i] = NULL;
55743 		}
55744 	}
55745 #endif
55746 	/* When nothing is running, API calls are in non-strict mode. */
55747 	DUK_ASSERT(res->strict == 0);
55748 
55749 	res->heap = heap;
55750 
55751 	/* XXX: Any reason not to merge duk_hthread_alloc.c here? */
55752 	return res;
55753 }
55754 
55755 DUK_INTERNAL duk_hthread *duk_hthread_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
55756 	duk_hthread *res;
55757 
55758 	res = duk_hthread_alloc_unchecked(thr->heap, hobject_flags);
55759 	if (res == NULL) {
55760 		DUK_ERROR_ALLOC_FAILED(thr);
55761 		DUK_WO_NORETURN(return NULL;);
55762 	}
55763 	return res;
55764 }
55765 
55766 DUK_INTERNAL duk_harray *duk_harray_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
55767 	duk_harray *res;
55768 
55769 	res = (duk_harray *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_harray));
55770 
55771 	DUK_ASSERT(res->length == 0);
55772 
55773 	return res;
55774 }
55775 
55776 DUK_INTERNAL duk_hdecenv *duk_hdecenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
55777 	duk_hdecenv *res;
55778 
55779 	res = (duk_hdecenv *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hdecenv));
55780 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
55781 	res->thread = NULL;
55782 	res->varmap = NULL;
55783 #endif
55784 
55785 	DUK_ASSERT(res->thread == NULL);
55786 	DUK_ASSERT(res->varmap == NULL);
55787 	DUK_ASSERT(res->regbase_byteoff == 0);
55788 
55789 	return res;
55790 }
55791 
55792 DUK_INTERNAL duk_hobjenv *duk_hobjenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
55793 	duk_hobjenv *res;
55794 
55795 	res = (duk_hobjenv *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hobjenv));
55796 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
55797 	res->target = NULL;
55798 #endif
55799 
55800 	DUK_ASSERT(res->target == NULL);
55801 
55802 	return res;
55803 }
55804 
55805 DUK_INTERNAL duk_hproxy *duk_hproxy_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
55806 	duk_hproxy *res;
55807 
55808 	res = (duk_hproxy *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hproxy));
55809 
55810 	/* Leave ->target and ->handler uninitialized, as caller will always
55811 	 * explicitly initialize them before any side effects are possible.
55812 	 */
55813 
55814 	return res;
55815 }
55816 #line 1 "duk_hobject_assert.c"
55817 /*
55818  *  duk_hobject and subclass assertion helpers
55819  */
55820 
55821 /* #include duk_internal.h -> already included */
55822 
55823 #if defined(DUK_USE_ASSERTIONS)
55824 
55825 DUK_INTERNAL void duk_hobject_assert_valid(duk_hobject *h) {
55826 	DUK_ASSERT(h != NULL);
55827 	DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE(h) ||
55828 	           DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_FUNCTION);
55829 	DUK_ASSERT(!DUK_HOBJECT_IS_BUFOBJ(h) ||
55830 	           (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAYBUFFER ||
55831 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_DATAVIEW ||
55832 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_INT8ARRAY ||
55833 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_UINT8ARRAY ||
55834 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY ||
55835 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_INT16ARRAY ||
55836 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_UINT16ARRAY ||
55837 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_INT32ARRAY ||
55838 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_UINT32ARRAY ||
55839 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_FLOAT32ARRAY ||
55840 	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_FLOAT64ARRAY));
55841 	/* Object is an Array <=> object has exotic array behavior */
55842 	DUK_ASSERT((DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY && DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)) ||
55843 	           (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_ARRAY && !DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)));
55844 }
55845 
55846 DUK_INTERNAL void duk_harray_assert_valid(duk_harray *h) {
55847 	DUK_ASSERT(h != NULL);
55848 	DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) h));
55849 	DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY((duk_hobject *) h));
55850 }
55851 
55852 DUK_INTERNAL void duk_hboundfunc_assert_valid(duk_hboundfunc *h) {
55853 	DUK_ASSERT(h != NULL);
55854 	DUK_ASSERT(DUK_HOBJECT_IS_BOUNDFUNC((duk_hobject *) h));
55855 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(&h->target) ||
55856 	           (DUK_TVAL_IS_OBJECT(&h->target) &&
55857 	            DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(&h->target))));
55858 	DUK_ASSERT(!DUK_TVAL_IS_UNUSED(&h->this_binding));
55859 	DUK_ASSERT(h->nargs == 0 || h->args != NULL);
55860 }
55861 
55862 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
55863 DUK_INTERNAL void duk_hbufobj_assert_valid(duk_hbufobj *h) {
55864 	DUK_ASSERT(h != NULL);
55865 	DUK_ASSERT(h->shift <= 3);
55866 	DUK_ASSERT(h->elem_type <= DUK_HBUFOBJ_ELEM_MAX);
55867 	DUK_ASSERT((h->shift == 0 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT8) ||
55868 	           (h->shift == 0 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT8CLAMPED) ||
55869 	           (h->shift == 0 && h->elem_type == DUK_HBUFOBJ_ELEM_INT8) ||
55870 	           (h->shift == 1 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT16) ||
55871 	           (h->shift == 1 && h->elem_type == DUK_HBUFOBJ_ELEM_INT16) ||
55872 	           (h->shift == 2 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT32) ||
55873 	           (h->shift == 2 && h->elem_type == DUK_HBUFOBJ_ELEM_INT32) ||
55874 	           (h->shift == 2 && h->elem_type == DUK_HBUFOBJ_ELEM_FLOAT32) ||
55875 	           (h->shift == 3 && h->elem_type == DUK_HBUFOBJ_ELEM_FLOAT64));
55876 	DUK_ASSERT(h->is_typedarray == 0 || h->is_typedarray == 1);
55877 	DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h));
55878 	if (h->buf == NULL) {
55879 		DUK_ASSERT(h->offset == 0);
55880 		DUK_ASSERT(h->length == 0);
55881 	} else {
55882 		/* No assertions for offset or length; in particular,
55883 		 * it's OK for length to be longer than underlying
55884 		 * buffer.  Just ensure they don't wrap when added.
55885 		 */
55886 		DUK_ASSERT(h->offset + h->length >= h->offset);
55887 	}
55888 }
55889 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
55890 
55891 DUK_INTERNAL void duk_hcompfunc_assert_valid(duk_hcompfunc *h) {
55892 	DUK_ASSERT(h != NULL);
55893 }
55894 
55895 DUK_INTERNAL void duk_hnatfunc_assert_valid(duk_hnatfunc *h) {
55896 	DUK_ASSERT(h != NULL);
55897 }
55898 
55899 DUK_INTERNAL void duk_hdecenv_assert_valid(duk_hdecenv *h) {
55900 	DUK_ASSERT(h != NULL);
55901 	DUK_ASSERT(DUK_HOBJECT_IS_DECENV((duk_hobject *) h));
55902 	DUK_ASSERT(h->thread == NULL || h->varmap != NULL);
55903 }
55904 
55905 DUK_INTERNAL void duk_hobjenv_assert_valid(duk_hobjenv *h) {
55906 	DUK_ASSERT(h != NULL);
55907 	DUK_ASSERT(DUK_HOBJECT_IS_OBJENV((duk_hobject *) h));
55908 	DUK_ASSERT(h->target != NULL);
55909 	DUK_ASSERT(h->has_this == 0 || h->has_this == 1);
55910 }
55911 
55912 DUK_INTERNAL void duk_hproxy_assert_valid(duk_hproxy *h) {
55913 	DUK_ASSERT(h != NULL);
55914 	DUK_ASSERT(h->target != NULL);
55915 	DUK_ASSERT(h->handler != NULL);
55916 	DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((duk_hobject *) h));
55917 }
55918 
55919 DUK_INTERNAL void duk_hthread_assert_valid(duk_hthread *thr) {
55920 	DUK_ASSERT(thr != NULL);
55921 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) thr) == DUK_HTYPE_OBJECT);
55922 	DUK_ASSERT(DUK_HOBJECT_IS_THREAD((duk_hobject *) thr));
55923 	DUK_ASSERT(thr->unused1 == 0);
55924 	DUK_ASSERT(thr->unused2 == 0);
55925 }
55926 
55927 DUK_INTERNAL void duk_ctx_assert_valid(duk_hthread *thr) {
55928 	DUK_ASSERT(thr != NULL);
55929 	DUK_HTHREAD_ASSERT_VALID(thr);
55930 	DUK_ASSERT(thr->valstack != NULL);
55931 	DUK_ASSERT(thr->valstack_bottom != NULL);
55932 	DUK_ASSERT(thr->valstack_top != NULL);
55933 	DUK_ASSERT(thr->valstack_end != NULL);
55934 	DUK_ASSERT(thr->valstack_alloc_end != NULL);
55935 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack);
55936 	DUK_ASSERT(thr->valstack_end >= thr->valstack);
55937 	DUK_ASSERT(thr->valstack_top >= thr->valstack);
55938 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
55939 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
55940 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
55941 }
55942 
55943 #endif  /* DUK_USE_ASSERTIONS */
55944 #line 1 "duk_hobject_enum.c"
55945 /*
55946  *  Object enumeration support.
55947  *
55948  *  Creates an internal enumeration state object to be used e.g. with for-in
55949  *  enumeration.  The state object contains a snapshot of target object keys
55950  *  and internal control state for enumeration.  Enumerator flags allow caller
55951  *  to e.g. request internal/non-enumerable properties, and to enumerate only
55952  *  "own" properties.
55953  *
55954  *  Also creates the result value for e.g. Object.keys() based on the same
55955  *  internal structure.
55956  *
55957  *  This snapshot-based enumeration approach is used to simplify enumeration:
55958  *  non-snapshot-based approaches are difficult to reconcile with mutating
55959  *  the enumeration target, running multiple long-lived enumerators at the
55960  *  same time, garbage collection details, etc.  The downside is that the
55961  *  enumerator object is memory inefficient especially for iterating arrays.
55962  */
55963 
55964 /* #include duk_internal.h -> already included */
55965 
55966 /* XXX: identify enumeration target with an object index (not top of stack) */
55967 
55968 /* First enumerated key index in enumerator object, must match exactly the
55969  * number of control properties inserted to the enumerator.
55970  */
55971 #define DUK__ENUM_START_INDEX  2
55972 
55973 /* Current implementation suffices for ES2015 for now because there's no symbol
55974  * sorting, so commented out for now.
55975  */
55976 
55977 /*
55978  *  Helper to sort enumeration keys using a callback for pairwise duk_hstring
55979  *  comparisons.  The keys are in the enumeration object entry part, starting
55980  *  from DUK__ENUM_START_INDEX, and the entry part is dense.  Entry part values
55981  *  are all "true", e.g. "1" -> true, "3" -> true, "foo" -> true, "2" -> true,
55982  *  so it suffices to just switch keys without switching values.
55983  *
55984  *  ES2015 [[OwnPropertyKeys]] enumeration order for ordinary objects:
55985  *  (1) array indices in ascending order,
55986  *  (2) non-array-index keys in insertion order, and
55987  *  (3) symbols in insertion order.
55988  *  http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys.
55989  *
55990  *  This rule is applied to "own properties" at each inheritance level;
55991  *  non-duplicate parent keys always follow child keys.  For example,
55992  *  an inherited array index will enumerate -after- a symbol in the
55993  *  child.
55994  *
55995  *  Insertion sort is used because (1) it's simple and compact, (2) works
55996  *  in-place, (3) minimizes operations if data is already nearly sorted,
55997  *  (4) doesn't reorder elements considered equal.
55998  *  http://en.wikipedia.org/wiki/Insertion_sort
55999  */
56000 
56001 /* Sort key, must hold array indices, "not array index" marker, and one more
56002  * higher value for symbols.
56003  */
56004 #if !defined(DUK_USE_SYMBOL_BUILTIN)
56005 typedef duk_uint32_t duk__sort_key_t;
56006 #elif defined(DUK_USE_64BIT_OPS)
56007 typedef duk_uint64_t duk__sort_key_t;
56008 #else
56009 typedef duk_double_t duk__sort_key_t;
56010 #endif
56011 
56012 /* Get sort key for a duk_hstring. */
56013 DUK_LOCAL duk__sort_key_t duk__hstring_sort_key(duk_hstring *x) {
56014 	duk__sort_key_t val;
56015 
56016 	/* For array indices [0,0xfffffffe] use the array index as is.
56017 	 * For strings, use 0xffffffff, the marker 'arridx' already in
56018 	 * duk_hstring.  For symbols, any value above 0xffffffff works,
56019 	 * as long as it is the same for all symbols; currently just add
56020 	 * the masked flag field into the arridx temporary.
56021 	 */
56022 	DUK_ASSERT(x != NULL);
56023 	DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(x) || DUK_HSTRING_GET_ARRIDX_FAST(x) == DUK_HSTRING_NO_ARRAY_INDEX);
56024 
56025 	val = (duk__sort_key_t) DUK_HSTRING_GET_ARRIDX_FAST(x);
56026 
56027 #if defined(DUK_USE_SYMBOL_BUILTIN)
56028 	val = val + (duk__sort_key_t) (DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) x) & DUK_HSTRING_FLAG_SYMBOL);
56029 #endif
56030 
56031 	return (duk__sort_key_t) val;
56032 }
56033 
56034 /* Insert element 'b' after element 'a'? */
56035 DUK_LOCAL duk_bool_t duk__sort_compare_es6(duk_hstring *a, duk_hstring *b, duk__sort_key_t val_b) {
56036 	duk__sort_key_t val_a;
56037 
56038 	DUK_ASSERT(a != NULL);
56039 	DUK_ASSERT(b != NULL);
56040 	DUK_UNREF(b);  /* Not actually needed now, val_b suffices. */
56041 
56042 	val_a = duk__hstring_sort_key(a);
56043 
56044 	if (val_a > val_b) {
56045 		return 0;
56046 	} else {
56047 		return 1;
56048 	}
56049 }
56050 
56051 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) {
56052 	duk_hstring **keys;
56053 	duk_int_fast32_t idx;
56054 
56055 	DUK_ASSERT(h_obj != NULL);
56056 	DUK_ASSERT(idx_start >= DUK__ENUM_START_INDEX);
56057 	DUK_ASSERT(idx_end >= idx_start);
56058 	DUK_UNREF(thr);
56059 
56060 	if (idx_end <= idx_start + 1) {
56061 		return;  /* Zero or one element(s). */
56062 	}
56063 
56064 	keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, h_obj);
56065 
56066 	for (idx = idx_start + 1; idx < idx_end; idx++) {
56067 		duk_hstring *h_curr;
56068 		duk_int_fast32_t idx_insert;
56069 		duk__sort_key_t val_curr;
56070 
56071 		h_curr = keys[idx];
56072 		DUK_ASSERT(h_curr != NULL);
56073 
56074 		/* Scan backwards for insertion place.  This works very well
56075 		 * when the elements are nearly in order which is the common
56076 		 * (and optimized for) case.
56077 		 */
56078 
56079 		val_curr = duk__hstring_sort_key(h_curr);  /* Remains same during scanning. */
56080 		for (idx_insert = idx - 1; idx_insert >= idx_start; idx_insert--) {
56081 			duk_hstring *h_insert;
56082 			h_insert = keys[idx_insert];
56083 			DUK_ASSERT(h_insert != NULL);
56084 
56085 			if (duk__sort_compare_es6(h_insert, h_curr, val_curr)) {
56086 				break;
56087 			}
56088 		}
56089 		/* If we're out of indices, idx_insert == idx_start - 1 and idx_insert++
56090 		 * brings us back to idx_start.
56091 		 */
56092 		idx_insert++;
56093 		DUK_ASSERT(idx_insert >= 0 && idx_insert <= idx);
56094 
56095 		/*        .-- p_insert   .-- p_curr
56096 		 *        v              v
56097 		 *  | ... | insert | ... | curr
56098 		 */
56099 
56100 		/* This could also done when the keys are in order, i.e.
56101 		 * idx_insert == idx.  The result would be an unnecessary
56102 		 * memmove() but we use an explicit check because the keys
56103 		 * are very often in order already.
56104 		 */
56105 		if (idx != idx_insert) {
56106 			duk_memmove((void *) (keys + idx_insert + 1),
56107 			            (const void *) (keys + idx_insert),
56108 			            ((size_t) (idx - idx_insert) * sizeof(duk_hstring *)));
56109 			keys[idx_insert] = h_curr;
56110 		}
56111 	}
56112 
56113 	/* Entry part has been reordered now with no side effects.
56114 	 * If the object has a hash part, it will now be incorrect
56115 	 * and we need to rehash.  Do that by forcing a resize to
56116 	 * the current size.
56117 	 */
56118 	duk_hobject_resize_entrypart(thr, h_obj, DUK_HOBJECT_GET_ESIZE(h_obj));
56119 }
56120 
56121 /*
56122  *  Create an internal enumerator object E, which has its keys ordered
56123  *  to match desired enumeration ordering.  Also initialize internal control
56124  *  properties for enumeration.
56125  *
56126  *  Note: if an array was used to hold enumeration keys instead, an array
56127  *  scan would be needed to eliminate duplicates found in the prototype chain.
56128  */
56129 
56130 DUK_LOCAL void duk__add_enum_key(duk_hthread *thr, duk_hstring *k) {
56131 	/* 'k' may be unreachable on entry so must push without any
56132 	 * potential for GC.
56133 	 */
56134 	duk_push_hstring(thr, k);
56135 	duk_push_true(thr);
56136 	duk_put_prop(thr, -3);
56137 }
56138 
56139 DUK_LOCAL void duk__add_enum_key_stridx(duk_hthread *thr, duk_small_uint_t stridx) {
56140 	duk__add_enum_key(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
56141 }
56142 
56143 DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint_t enum_flags) {
56144 	duk_hobject *enum_target;
56145 	duk_hobject *curr;
56146 	duk_hobject *res;
56147 #if defined(DUK_USE_ES6_PROXY)
56148 	duk_hobject *h_proxy_target;
56149 	duk_hobject *h_proxy_handler;
56150 	duk_hobject *h_trap_result;
56151 #endif
56152 	duk_uint_fast32_t i, len;  /* used for array, stack, and entry indices */
56153 	duk_uint_fast32_t sort_start_index;
56154 
56155 	DUK_ASSERT(thr != NULL);
56156 
56157 	enum_target = duk_require_hobject(thr, -1);
56158 	DUK_ASSERT(enum_target != NULL);
56159 
56160 	duk_push_bare_object(thr);
56161 	res = duk_known_hobject(thr, -1);
56162 
56163 	/* [enum_target res] */
56164 
56165 	/* Target must be stored so that we can recheck whether or not
56166 	 * keys still exist when we enumerate.  This is not done if the
56167 	 * enumeration result comes from a proxy trap as there is no
56168 	 * real object to check against.
56169 	 */
56170 	duk_push_hobject(thr, enum_target);
56171 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_TARGET);  /* Target is bare, plain put OK. */
56172 
56173 	/* Initialize index so that we skip internal control keys. */
56174 	duk_push_int(thr, DUK__ENUM_START_INDEX);
56175 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_NEXT);  /* Target is bare, plain put OK. */
56176 
56177 	/*
56178 	 *  Proxy object handling
56179 	 */
56180 
56181 #if defined(DUK_USE_ES6_PROXY)
56182 	if (DUK_LIKELY((enum_flags & DUK_ENUM_NO_PROXY_BEHAVIOR) != 0)) {
56183 		goto skip_proxy;
56184 	}
56185 	if (DUK_LIKELY(!duk_hobject_proxy_check(enum_target,
56186 	                                        &h_proxy_target,
56187 	                                        &h_proxy_handler))) {
56188 		goto skip_proxy;
56189 	}
56190 
56191 	/* XXX: share code with Object.keys() Proxy handling */
56192 
56193 	/* In ES2015 for-in invoked the "enumerate" trap; in ES2016 "enumerate"
56194 	 * has been obsoleted and "ownKeys" is used instead.
56195 	 */
56196 	DUK_DDD(DUK_DDDPRINT("proxy enumeration"));
56197 	duk_push_hobject(thr, h_proxy_handler);
56198 	if (!duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_OWN_KEYS)) {
56199 		/* No need to replace the 'enum_target' value in stack, only the
56200 		 * enum_target reference.  This also ensures that the original
56201 		 * enum target is reachable, which keeps the proxy and the proxy
56202 		 * target reachable.  We do need to replace the internal _Target.
56203 		 */
56204 		DUK_DDD(DUK_DDDPRINT("no ownKeys trap, enumerate proxy target instead"));
56205 		DUK_DDD(DUK_DDDPRINT("h_proxy_target=%!O", (duk_heaphdr *) h_proxy_target));
56206 		enum_target = h_proxy_target;
56207 
56208 		duk_push_hobject(thr, enum_target);  /* -> [ ... enum_target res handler undefined target ] */
56209 		duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_INT_TARGET);  /* Target is bare, plain put OK. */
56210 
56211 		duk_pop_2(thr);  /* -> [ ... enum_target res ] */
56212 		goto skip_proxy;
56213 	}
56214 
56215 	/* [ ... enum_target res handler trap ] */
56216 	duk_insert(thr, -2);
56217 	duk_push_hobject(thr, h_proxy_target);    /* -> [ ... enum_target res trap handler target ] */
56218 	duk_call_method(thr, 1 /*nargs*/);        /* -> [ ... enum_target res trap_result ] */
56219 	h_trap_result = duk_require_hobject(thr, -1);
56220 	DUK_UNREF(h_trap_result);
56221 
56222 	duk_proxy_ownkeys_postprocess(thr, h_proxy_target, enum_flags);
56223 	/* -> [ ... enum_target res trap_result keys_array ] */
56224 
56225 	/* Copy cleaned up trap result keys into the enumerator object. */
56226 	/* XXX: result is a dense array; could make use of that. */
56227 	DUK_ASSERT(duk_is_array(thr, -1));
56228 	len = (duk_uint_fast32_t) duk_get_length(thr, -1);
56229 	for (i = 0; i < len; i++) {
56230 		(void) duk_get_prop_index(thr, -1, (duk_uarridx_t) i);
56231 		DUK_ASSERT(duk_is_string(thr, -1));  /* postprocess cleaned up */
56232 		/* [ ... enum_target res trap_result keys_array val ] */
56233 		duk_push_true(thr);
56234 		/* [ ... enum_target res trap_result keys_array val true ] */
56235 		duk_put_prop(thr, -5);
56236 	}
56237 	/* [ ... enum_target res trap_result keys_array ] */
56238 	duk_pop_2(thr);
56239 	duk_remove_m2(thr);
56240 
56241 	/* [ ... res ] */
56242 
56243 	/* The internal _Target property is kept pointing to the original
56244 	 * enumeration target (the proxy object), so that the enumerator
56245 	 * 'next' operation can read property values if so requested.  The
56246 	 * fact that the _Target is a proxy disables key existence check
56247 	 * during enumeration.
56248 	 */
56249 	DUK_DDD(DUK_DDDPRINT("proxy enumeration, final res: %!O", (duk_heaphdr *) res));
56250 	goto compact_and_return;
56251 
56252  skip_proxy:
56253 #endif  /* DUK_USE_ES6_PROXY */
56254 
56255 	curr = enum_target;
56256 	sort_start_index = DUK__ENUM_START_INDEX;
56257 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(res) == DUK__ENUM_START_INDEX);
56258 	while (curr) {
56259 		duk_uint_fast32_t sort_end_index;
56260 #if !defined(DUK_USE_PREFER_SIZE)
56261 		duk_bool_t need_sort = 0;
56262 #endif
56263 		duk_bool_t cond;
56264 
56265 		/* Enumeration proceeds by inheritance level.  Virtual
56266 		 * properties need to be handled specially, followed by
56267 		 * array part, and finally entry part.
56268 		 *
56269 		 * If there are array index keys in the entry part or any
56270 		 * other risk of the ES2015 [[OwnPropertyKeys]] order being
56271 		 * violated, need_sort is set and an explicit ES2015 sort is
56272 		 * done for the inheritance level.
56273 		 */
56274 
56275 		/* XXX: inheriting from proxy */
56276 
56277 		/*
56278 		 *  Virtual properties.
56279 		 *
56280 		 *  String and buffer indices are virtual and always enumerable,
56281 		 *  'length' is virtual and non-enumerable.  Array and arguments
56282 		 *  object props have special behavior but are concrete.
56283 		 *
56284 		 *  String and buffer objects don't have an array part so as long
56285 		 *  as virtual array index keys are enumerated first, we don't
56286 		 *  need to set need_sort.
56287 		 */
56288 
56289 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
56290 		cond = DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr) || DUK_HOBJECT_IS_BUFOBJ(curr);
56291 #else
56292 		cond = DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr);
56293 #endif
56294 		cond = cond && !(enum_flags & DUK_ENUM_EXCLUDE_STRINGS);
56295 		if (cond) {
56296 			duk_bool_t have_length = 1;
56297 
56298 			/* String and buffer enumeration behavior is identical now,
56299 			 * so use shared handler.
56300 			 */
56301 			if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr)) {
56302 				duk_hstring *h_val;
56303 				h_val = duk_hobject_get_internal_value_string(thr->heap, curr);
56304 				DUK_ASSERT(h_val != NULL);  /* string objects must not created without internal value */
56305 				len = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_val);
56306 			}
56307 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
56308 			else {
56309 				duk_hbufobj *h_bufobj;
56310 				DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ(curr));
56311 				h_bufobj = (duk_hbufobj *) curr;
56312 
56313 				if (h_bufobj == NULL || !h_bufobj->is_typedarray) {
56314 					/* Zero length seems like a good behavior for neutered buffers.
56315 					 * ArrayBuffer (non-view) and DataView don't have index properties
56316 					 * or .length property.
56317 					 */
56318 					len = 0;
56319 					have_length = 0;
56320 				} else {
56321 					/* There's intentionally no check for
56322 					 * current underlying buffer length.
56323 					 */
56324 					len = (duk_uint_fast32_t) (h_bufobj->length >> h_bufobj->shift);
56325 				}
56326 			}
56327 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
56328 
56329 			for (i = 0; i < len; i++) {
56330 				duk_hstring *k;
56331 
56332 				/* This is a bit fragile: the string is not
56333 				 * reachable until it is pushed by the helper.
56334 				 */
56335 				k = duk_heap_strtable_intern_u32_checked(thr, (duk_uint32_t) i);
56336 				DUK_ASSERT(k);
56337 
56338 				duk__add_enum_key(thr, k);
56339 
56340 				/* [enum_target res] */
56341 			}
56342 
56343 			/* 'length' and other virtual properties are not
56344 			 * enumerable, but are included if non-enumerable
56345 			 * properties are requested.
56346 			 */
56347 
56348 			if (have_length && (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
56349 				duk__add_enum_key_stridx(thr, DUK_STRIDX_LENGTH);
56350 			}
56351 		}
56352 
56353 		/*
56354 		 *  Array part
56355 		 */
56356 
56357 		cond = !(enum_flags & DUK_ENUM_EXCLUDE_STRINGS);
56358 		if (cond) {
56359 			for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(curr); i++) {
56360 				duk_hstring *k;
56361 				duk_tval *tv;
56362 
56363 				tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, curr, i);
56364 				if (DUK_TVAL_IS_UNUSED(tv)) {
56365 					continue;
56366 				}
56367 				k = duk_heap_strtable_intern_u32_checked(thr, (duk_uint32_t) i);  /* Fragile reachability. */
56368 				DUK_ASSERT(k);
56369 
56370 				duk__add_enum_key(thr, k);
56371 
56372 				/* [enum_target res] */
56373 			}
56374 
56375 			if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(curr)) {
56376 				/* Array .length comes after numeric indices. */
56377 				if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
56378 					duk__add_enum_key_stridx(thr, DUK_STRIDX_LENGTH);
56379 				}
56380 			}
56381 		}
56382 
56383 		/*
56384 		 *  Entries part
56385 		 */
56386 
56387 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(curr); i++) {
56388 			duk_hstring *k;
56389 
56390 			k = DUK_HOBJECT_E_GET_KEY(thr->heap, curr, i);
56391 			if (!k) {
56392 				continue;
56393 			}
56394 			if (!(enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) &&
56395 			    !DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(thr->heap, curr, i)) {
56396 				continue;
56397 			}
56398 			if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(k))) {
56399 				if (!(enum_flags & DUK_ENUM_INCLUDE_HIDDEN) &&
56400 				    DUK_HSTRING_HAS_HIDDEN(k)) {
56401 					continue;
56402 				}
56403 				if (!(enum_flags & DUK_ENUM_INCLUDE_SYMBOLS)) {
56404 					continue;
56405 				}
56406 #if !defined(DUK_USE_PREFER_SIZE)
56407 				need_sort = 1;
56408 #endif
56409 			} else {
56410 				DUK_ASSERT(!DUK_HSTRING_HAS_HIDDEN(k));  /* would also have symbol flag */
56411 				if (enum_flags & DUK_ENUM_EXCLUDE_STRINGS) {
56412 					continue;
56413 				}
56414 			}
56415 			if (DUK_HSTRING_HAS_ARRIDX(k)) {
56416 				/* This in currently only possible if the
56417 				 * object has no array part: the array part
56418 				 * is exhaustive when it is present.
56419 				 */
56420 #if !defined(DUK_USE_PREFER_SIZE)
56421 				need_sort = 1;
56422 #endif
56423 			} else {
56424 				if (enum_flags & DUK_ENUM_ARRAY_INDICES_ONLY) {
56425 					continue;
56426 				}
56427 			}
56428 
56429 			DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, curr, i) ||
56430 			           !DUK_TVAL_IS_UNUSED(&DUK_HOBJECT_E_GET_VALUE_PTR(thr->heap, curr, i)->v));
56431 
56432 			duk__add_enum_key(thr, k);
56433 
56434 			/* [enum_target res] */
56435 		}
56436 
56437 		/* Sort enumerated keys according to ES2015 requirements for
56438 		 * the "inheritance level" just processed.  This is far from
56439 		 * optimal, ES2015 semantics could be achieved more efficiently
56440 		 * by handling array index string keys (and symbol keys)
56441 		 * specially above in effect doing the sort inline.
56442 		 *
56443 		 * Skip the sort if array index sorting is requested because
56444 		 * we must consider all keys, also inherited, so an explicit
56445 		 * sort is done for the whole result after we're done with the
56446 		 * prototype chain.
56447 		 *
56448 		 * Also skip the sort if need_sort == 0, i.e. we know for
56449 		 * certain that the enumerated order is already correct.
56450 		 */
56451 		sort_end_index = DUK_HOBJECT_GET_ENEXT(res);
56452 
56453 		if (!(enum_flags & DUK_ENUM_SORT_ARRAY_INDICES)) {
56454 #if defined(DUK_USE_PREFER_SIZE)
56455 			duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) sort_start_index, (duk_int_fast32_t) sort_end_index);
56456 #else
56457 			if (need_sort) {
56458 				DUK_DDD(DUK_DDDPRINT("need to sort"));
56459 				duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) sort_start_index, (duk_int_fast32_t) sort_end_index);
56460 			} else {
56461 				DUK_DDD(DUK_DDDPRINT("no need to sort"));
56462 			}
56463 #endif
56464 		}
56465 
56466 		sort_start_index = sort_end_index;
56467 
56468 		if (enum_flags & DUK_ENUM_OWN_PROPERTIES_ONLY) {
56469 			break;
56470 		}
56471 
56472 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
56473 	}
56474 
56475 	/* [enum_target res] */
56476 
56477 	duk_remove_m2(thr);
56478 
56479 	/* [res] */
56480 
56481 	if (enum_flags & DUK_ENUM_SORT_ARRAY_INDICES) {
56482 		/* Some E5/E5.1 algorithms require that array indices are iterated
56483 		 * in a strictly ascending order.  This is the case for e.g.
56484 		 * Array.prototype.forEach() and JSON.stringify() PropertyList
56485 		 * handling.  The caller can request an explicit sort in these
56486 		 * cases.
56487 		 */
56488 
56489 		/* Sort to ES2015 order which works for pure array incides but
56490 		 * also for mixed keys.
56491 		 */
56492 		duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) DUK__ENUM_START_INDEX, (duk_int_fast32_t) DUK_HOBJECT_GET_ENEXT(res));
56493 	}
56494 
56495 #if defined(DUK_USE_ES6_PROXY)
56496  compact_and_return:
56497 #endif
56498 	/* compact; no need to seal because object is internal */
56499 	duk_hobject_compact_props(thr, res);
56500 
56501 	DUK_DDD(DUK_DDDPRINT("created enumerator object: %!iT", (duk_tval *) duk_get_tval(thr, -1)));
56502 }
56503 
56504 /*
56505  *  Returns non-zero if a key and/or value was enumerated, and:
56506  *
56507  *   [enum] -> [key]        (get_value == 0)
56508  *   [enum] -> [key value]  (get_value == 1)
56509  *
56510  *  Returns zero without pushing anything on the stack otherwise.
56511  */
56512 DUK_INTERNAL duk_bool_t duk_hobject_enumerator_next(duk_hthread *thr, duk_bool_t get_value) {
56513 	duk_hobject *e;
56514 	duk_hobject *enum_target;
56515 	duk_hstring *res = NULL;
56516 	duk_uint_fast32_t idx;
56517 	duk_bool_t check_existence;
56518 
56519 	DUK_ASSERT(thr != NULL);
56520 
56521 	/* [... enum] */
56522 
56523 	e = duk_require_hobject(thr, -1);
56524 
56525 	/* XXX use get tval ptr, more efficient */
56526 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_NEXT);
56527 	idx = (duk_uint_fast32_t) duk_require_uint(thr, -1);
56528 	duk_pop(thr);
56529 	DUK_DDD(DUK_DDDPRINT("enumeration: index is: %ld", (long) idx));
56530 
56531 	/* Enumeration keys are checked against the enumeration target (to see
56532 	 * that they still exist).  In the proxy enumeration case _Target will
56533 	 * be the proxy, and checking key existence against the proxy is not
56534 	 * required (or sensible, as the keys may be fully virtual).
56535 	 */
56536 	duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_TARGET);
56537 	enum_target = duk_require_hobject(thr, -1);
56538 	DUK_ASSERT(enum_target != NULL);
56539 #if defined(DUK_USE_ES6_PROXY)
56540 	check_existence = (!DUK_HOBJECT_IS_PROXY(enum_target));
56541 #else
56542 	check_existence = 1;
56543 #endif
56544 	duk_pop(thr);  /* still reachable */
56545 
56546 	DUK_DDD(DUK_DDDPRINT("getting next enum value, enum_target=%!iO, enumerator=%!iT",
56547 	                     (duk_heaphdr *) enum_target, (duk_tval *) duk_get_tval(thr, -1)));
56548 
56549 	/* no array part */
56550 	for (;;) {
56551 		duk_hstring *k;
56552 
56553 		if (idx >= DUK_HOBJECT_GET_ENEXT(e)) {
56554 			DUK_DDD(DUK_DDDPRINT("enumeration: ran out of elements"));
56555 			break;
56556 		}
56557 
56558 		/* we know these because enum objects are internally created */
56559 		k = DUK_HOBJECT_E_GET_KEY(thr->heap, e, idx);
56560 		DUK_ASSERT(k != NULL);
56561 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, e, idx));
56562 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(&DUK_HOBJECT_E_GET_VALUE(thr->heap, e, idx).v));
56563 
56564 		idx++;
56565 
56566 		/* recheck that the property still exists */
56567 		if (check_existence && !duk_hobject_hasprop_raw(thr, enum_target, k)) {
56568 			DUK_DDD(DUK_DDDPRINT("property deleted during enumeration, skip"));
56569 			continue;
56570 		}
56571 
56572 		DUK_DDD(DUK_DDDPRINT("enumeration: found element, key: %!O", (duk_heaphdr *) k));
56573 		res = k;
56574 		break;
56575 	}
56576 
56577 	DUK_DDD(DUK_DDDPRINT("enumeration: updating next index to %ld", (long) idx));
56578 
56579 	duk_push_u32(thr, (duk_uint32_t) idx);
56580 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_NEXT);
56581 
56582 	/* [... enum] */
56583 
56584 	if (res) {
56585 		duk_push_hstring(thr, res);
56586 		if (get_value) {
56587 			duk_push_hobject(thr, enum_target);
56588 			duk_dup_m2(thr);       /* -> [... enum key enum_target key] */
56589 			duk_get_prop(thr, -2); /* -> [... enum key enum_target val] */
56590 			duk_remove_m2(thr);    /* -> [... enum key val] */
56591 			duk_remove(thr, -3);   /* -> [... key val] */
56592 		} else {
56593 			duk_remove_m2(thr);    /* -> [... key] */
56594 		}
56595 		return 1;
56596 	} else {
56597 		duk_pop(thr);  /* -> [...] */
56598 		return 0;
56599 	}
56600 }
56601 
56602 /*
56603  *  Get enumerated keys in an ECMAScript array.  Matches Object.keys() behavior
56604  *  described in E5 Section 15.2.3.14.
56605  */
56606 
56607 DUK_INTERNAL duk_ret_t duk_hobject_get_enumerated_keys(duk_hthread *thr, duk_small_uint_t enum_flags) {
56608 	duk_hobject *e;
56609 	duk_hstring **keys;
56610 	duk_tval *tv;
56611 	duk_uint_fast32_t count;
56612 
56613 	DUK_ASSERT(thr != NULL);
56614 	DUK_ASSERT(duk_get_hobject(thr, -1) != NULL);
56615 
56616 	/* Create a temporary enumerator to get the (non-duplicated) key list;
56617 	 * the enumerator state is initialized without being needed, but that
56618 	 * has little impact.
56619 	 */
56620 
56621 	duk_hobject_enumerator_create(thr, enum_flags);
56622 	e = duk_known_hobject(thr, -1);
56623 
56624 	/* [enum_target enum res] */
56625 
56626 	/* Create dense result array to exact size. */
56627 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(e) >= DUK__ENUM_START_INDEX);
56628 	count = (duk_uint32_t) (DUK_HOBJECT_GET_ENEXT(e) - DUK__ENUM_START_INDEX);
56629 
56630 	/* XXX: uninit would be OK */
56631 	tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) count);
56632 	DUK_ASSERT(count == 0 || tv != NULL);
56633 	DUK_ASSERT(!duk_is_bare_object(thr, -1));
56634 
56635 	/* Fill result array, no side effects. */
56636 
56637 	keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, e);
56638 	keys += DUK__ENUM_START_INDEX;
56639 
56640 	while (count-- > 0) {
56641 		duk_hstring *k;
56642 
56643 		k = *keys++;
56644 		DUK_ASSERT(k != NULL);  /* enumerator must have no keys deleted */
56645 
56646 		DUK_TVAL_SET_STRING(tv, k);
56647 		tv++;
56648 		DUK_HSTRING_INCREF(thr, k);
56649 	}
56650 
56651 	/* [enum_target enum res] */
56652 	duk_remove_m2(thr);
56653 
56654 	/* [enum_target res] */
56655 
56656 	return 1;  /* return 1 to allow callers to tail call */
56657 }
56658 
56659 /* automatic undefs */
56660 #undef DUK__ENUM_START_INDEX
56661 #line 1 "duk_hobject_misc.c"
56662 /*
56663  *  Misc support functions
56664  */
56665 
56666 /* #include duk_internal.h -> already included */
56667 
56668 DUK_INTERNAL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h, duk_hobject *p, duk_bool_t ignore_loop) {
56669 	duk_uint_t sanity;
56670 
56671 	DUK_ASSERT(thr != NULL);
56672 
56673 	/* False if the object is NULL or the prototype 'p' is NULL.
56674 	 * In particular, false if both are NULL (don't compare equal).
56675 	 */
56676 	if (h == NULL || p == NULL) {
56677 		return 0;
56678 	}
56679 
56680 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
56681 	do {
56682 		if (h == p) {
56683 			return 1;
56684 		}
56685 
56686 		if (sanity-- == 0) {
56687 			if (ignore_loop) {
56688 				break;
56689 			} else {
56690 				DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
56691 				DUK_WO_NORETURN(return 0;);
56692 			}
56693 		}
56694 		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
56695 	} while (h);
56696 
56697 	return 0;
56698 }
56699 
56700 DUK_INTERNAL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p) {
56701 #if defined(DUK_USE_REFERENCE_COUNTING)
56702 	duk_hobject *tmp;
56703 
56704 	DUK_ASSERT(h);
56705 	tmp = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
56706 	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
56707 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, p);  /* avoid problems if p == h->prototype */
56708 	DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
56709 #else
56710 	DUK_ASSERT(h);
56711 	DUK_UNREF(thr);
56712 	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
56713 #endif
56714 }
56715 #line 1 "duk_hobject_pc2line.c"
56716 /*
56717  *  Helpers for creating and querying pc2line debug data, which
56718  *  converts a bytecode program counter to a source line number.
56719  *
56720  *  The run-time pc2line data is bit-packed, and documented in:
56721  *
56722  *    doc/function-objects.rst
56723  */
56724 
56725 /* #include duk_internal.h -> already included */
56726 
56727 #if defined(DUK_USE_PC2LINE)
56728 
56729 /* Generate pc2line data for an instruction sequence, leaving a buffer on stack top. */
56730 DUK_INTERNAL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length) {
56731 	duk_hbuffer_dynamic *h_buf;
56732 	duk_bitencoder_ctx be_ctx_alloc;
56733 	duk_bitencoder_ctx *be_ctx = &be_ctx_alloc;
56734 	duk_uint32_t *hdr;
56735 	duk_size_t new_size;
56736 	duk_uint_fast32_t num_header_entries;
56737 	duk_uint_fast32_t curr_offset;
56738 	duk_int_fast32_t curr_line, next_line, diff_line;
56739 	duk_uint_fast32_t curr_pc;
56740 	duk_uint_fast32_t hdr_index;
56741 
56742 	DUK_ASSERT(length <= DUK_COMPILER_MAX_BYTECODE_LENGTH);
56743 
56744 	num_header_entries = (length + DUK_PC2LINE_SKIP - 1) / DUK_PC2LINE_SKIP;
56745 	curr_offset = (duk_uint_fast32_t) (sizeof(duk_uint32_t) + num_header_entries * sizeof(duk_uint32_t) * 2);
56746 
56747 	duk_push_dynamic_buffer(thr, (duk_size_t) curr_offset);
56748 	h_buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, -1);
56749 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buf) && !DUK_HBUFFER_HAS_EXTERNAL(h_buf));
56750 
56751 	hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
56752 	DUK_ASSERT(hdr != NULL);
56753 	hdr[0] = (duk_uint32_t) length;  /* valid pc range is [0, length[ */
56754 
56755 	curr_pc = 0U;
56756 	while (curr_pc < length) {
56757 		new_size = (duk_size_t) (curr_offset + DUK_PC2LINE_MAX_DIFF_LENGTH);
56758 		duk_hbuffer_resize(thr, h_buf, new_size);
56759 
56760 		hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
56761 		DUK_ASSERT(hdr != NULL);
56762 		DUK_ASSERT(curr_pc < length);
56763 		hdr_index = 1 + (curr_pc / DUK_PC2LINE_SKIP) * 2;
56764 		curr_line = (duk_int_fast32_t) instrs[curr_pc].line;
56765 		hdr[hdr_index + 0] = (duk_uint32_t) curr_line;
56766 		hdr[hdr_index + 1] = (duk_uint32_t) curr_offset;
56767 
56768 #if 0
56769 		DUK_DDD(DUK_DDDPRINT("hdr[%ld]: pc=%ld line=%ld offset=%ld",
56770 		                     (long) (curr_pc / DUK_PC2LINE_SKIP),
56771 		                     (long) curr_pc,
56772 		                     (long) hdr[hdr_index + 0],
56773 		                     (long) hdr[hdr_index + 1]));
56774 #endif
56775 
56776 		duk_memzero(be_ctx, sizeof(*be_ctx));
56777 		be_ctx->data = ((duk_uint8_t *) hdr) + curr_offset;
56778 		be_ctx->length = (duk_size_t) DUK_PC2LINE_MAX_DIFF_LENGTH;
56779 
56780 		for (;;) {
56781 			curr_pc++;
56782 			if ( ((curr_pc % DUK_PC2LINE_SKIP) == 0) ||  /* end of diff run */
56783 			     (curr_pc >= length) ) {                 /* end of bytecode */
56784 				break;
56785 			}
56786 			DUK_ASSERT(curr_pc < length);
56787 			next_line = (duk_int32_t) instrs[curr_pc].line;
56788 			diff_line = next_line - curr_line;
56789 
56790 #if 0
56791 			DUK_DDD(DUK_DDDPRINT("curr_line=%ld, next_line=%ld -> diff_line=%ld",
56792 			                     (long) curr_line, (long) next_line, (long) diff_line));
56793 #endif
56794 
56795 			if (diff_line == 0) {
56796 				/* 0 */
56797 				duk_be_encode(be_ctx, 0, 1);
56798 			} else if (diff_line >= 1 && diff_line <= 4) {
56799 				/* 1 0 <2 bits> */
56800 				duk_be_encode(be_ctx, (duk_uint32_t) ((0x02 << 2) + (diff_line - 1)), 4);
56801 			} else if (diff_line >= -0x80 && diff_line <= 0x7f) {
56802 				/* 1 1 0 <8 bits> */
56803 				DUK_ASSERT(diff_line + 0x80 >= 0 && diff_line + 0x80 <= 0xff);
56804 				duk_be_encode(be_ctx, (duk_uint32_t) ((0x06 << 8) + (diff_line + 0x80)), 11);
56805 			} else {
56806 				/* 1 1 1 <32 bits>
56807 				 * Encode in two parts to avoid bitencode 24-bit limitation
56808 				 */
56809 				duk_be_encode(be_ctx, (duk_uint32_t) ((0x07 << 16) + ((next_line >> 16) & 0xffff)), 19);
56810 				duk_be_encode(be_ctx, (duk_uint32_t) (next_line & 0xffff), 16);
56811 			}
56812 
56813 			curr_line = next_line;
56814 		}
56815 
56816 		duk_be_finish(be_ctx);
56817 		DUK_ASSERT(!be_ctx->truncated);
56818 
56819 		/* be_ctx->offset == length of encoded bitstream */
56820 		curr_offset += (duk_uint_fast32_t) be_ctx->offset;
56821 	}
56822 
56823 	/* compact */
56824 	new_size = (duk_size_t) curr_offset;
56825 	duk_hbuffer_resize(thr, h_buf, new_size);
56826 
56827 	(void) duk_to_fixed_buffer(thr, -1, NULL);
56828 
56829 	DUK_DDD(DUK_DDDPRINT("final pc2line data: pc_limit=%ld, length=%ld, %lf bits/opcode --> %!ixT",
56830 	                     (long) length, (long) new_size, (double) new_size * 8.0 / (double) length,
56831 	                     (duk_tval *) duk_get_tval(thr, -1)));
56832 }
56833 
56834 /* PC is unsigned.  If caller does PC arithmetic and gets a negative result,
56835  * it will map to a large PC which is out of bounds and causes a zero to be
56836  * returned.
56837  */
56838 DUK_LOCAL duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hthread *thr, duk_hbuffer_fixed *buf, duk_uint_fast32_t pc) {
56839 	duk_bitdecoder_ctx bd_ctx_alloc;
56840 	duk_bitdecoder_ctx *bd_ctx = &bd_ctx_alloc;
56841 	duk_uint32_t *hdr;
56842 	duk_uint_fast32_t start_offset;
56843 	duk_uint_fast32_t pc_limit;
56844 	duk_uint_fast32_t hdr_index;
56845 	duk_uint_fast32_t pc_base;
56846 	duk_uint_fast32_t n;
56847 	duk_uint_fast32_t curr_line;
56848 
56849 	DUK_ASSERT(buf != NULL);
56850 	DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) buf) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) buf));
56851 	DUK_UNREF(thr);
56852 
56853 	/*
56854 	 *  Use the index in the header to find the right starting point
56855 	 */
56856 
56857 	hdr_index = pc / DUK_PC2LINE_SKIP;
56858 	pc_base = hdr_index * DUK_PC2LINE_SKIP;
56859 	n = pc - pc_base;
56860 
56861 	if (DUK_HBUFFER_FIXED_GET_SIZE(buf) <= sizeof(duk_uint32_t)) {
56862 		DUK_DD(DUK_DDPRINT("pc2line lookup failed: buffer is smaller than minimal header"));
56863 		goto pc2line_error;
56864 	}
56865 
56866 	hdr = (duk_uint32_t *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, buf);
56867 	pc_limit = hdr[0];
56868 	if (pc >= pc_limit) {
56869 		/* Note: pc is unsigned and cannot be negative */
56870 		DUK_DD(DUK_DDPRINT("pc2line lookup failed: pc out of bounds (pc=%ld, limit=%ld)",
56871 		                   (long) pc, (long) pc_limit));
56872 		goto pc2line_error;
56873 	}
56874 
56875 	curr_line = hdr[1 + hdr_index * 2];
56876 	start_offset = hdr[1 + hdr_index * 2 + 1];
56877 	if ((duk_size_t) start_offset > DUK_HBUFFER_FIXED_GET_SIZE(buf)) {
56878 		DUK_DD(DUK_DDPRINT("pc2line lookup failed: start_offset out of bounds (start_offset=%ld, buffer_size=%ld)",
56879 		                   (long) start_offset, (long) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) buf)));
56880 		goto pc2line_error;
56881 	}
56882 
56883 	/*
56884 	 *  Iterate the bitstream (line diffs) until PC is reached
56885 	 */
56886 
56887 	duk_memzero(bd_ctx, sizeof(*bd_ctx));
56888 	bd_ctx->data = ((duk_uint8_t *) hdr) + start_offset;
56889 	bd_ctx->length = (duk_size_t) (DUK_HBUFFER_FIXED_GET_SIZE(buf) - start_offset);
56890 
56891 #if 0
56892 	DUK_DDD(DUK_DDDPRINT("pc2line lookup: pc=%ld -> hdr_index=%ld, pc_base=%ld, n=%ld, start_offset=%ld",
56893 	                     (long) pc, (long) hdr_index, (long) pc_base, (long) n, (long) start_offset));
56894 #endif
56895 
56896 	while (n > 0) {
56897 #if 0
56898 		DUK_DDD(DUK_DDDPRINT("lookup: n=%ld, curr_line=%ld", (long) n, (long) curr_line));
56899 #endif
56900 
56901 		if (duk_bd_decode_flag(bd_ctx)) {
56902 			if (duk_bd_decode_flag(bd_ctx)) {
56903 				if (duk_bd_decode_flag(bd_ctx)) {
56904 					/* 1 1 1 <32 bits> */
56905 					duk_uint_fast32_t t;
56906 					t = duk_bd_decode(bd_ctx, 16);  /* workaround: max nbits = 24 now */
56907 					t = (t << 16) + duk_bd_decode(bd_ctx, 16);
56908 					curr_line = t;
56909 				} else {
56910 					/* 1 1 0 <8 bits> */
56911 					duk_uint_fast32_t t;
56912 					t = duk_bd_decode(bd_ctx, 8);
56913 					curr_line = curr_line + t - 0x80;
56914 				}
56915 			} else {
56916 				/* 1 0 <2 bits> */
56917 				duk_uint_fast32_t t;
56918 				t = duk_bd_decode(bd_ctx, 2);
56919 				curr_line = curr_line + t + 1;
56920 			}
56921 		} else {
56922 			/* 0: no change */
56923 		}
56924 
56925 		n--;
56926 	}
56927 
56928 	DUK_DDD(DUK_DDDPRINT("pc2line lookup result: pc %ld -> line %ld", (long) pc, (long) curr_line));
56929 	return curr_line;
56930 
56931  pc2line_error:
56932 	DUK_D(DUK_DPRINT("pc2line conversion failed for pc=%ld", (long) pc));
56933 	return 0;
56934 }
56935 
56936 DUK_INTERNAL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_idx_t idx_func, duk_uint_fast32_t pc) {
56937 	duk_hbuffer_fixed *pc2line;
56938 	duk_uint_fast32_t line;
56939 
56940 	/* XXX: now that pc2line is used by the debugger quite heavily in
56941 	 * checked execution, this should be optimized to avoid value stack
56942 	 * and perhaps also implement some form of pc2line caching (see
56943 	 * future work in debugger.rst).
56944 	 */
56945 
56946 	duk_xget_owndataprop_stridx_short(thr, idx_func, DUK_STRIDX_INT_PC2LINE);
56947 	pc2line = (duk_hbuffer_fixed *) (void *) duk_get_hbuffer(thr, -1);
56948 	if (pc2line != NULL) {
56949 		DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) pc2line) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) pc2line));
56950 		line = duk__hobject_pc2line_query_raw(thr, pc2line, (duk_uint_fast32_t) pc);
56951 	} else {
56952 		line = 0;
56953 	}
56954 	duk_pop(thr);
56955 
56956 	return line;
56957 }
56958 
56959 #endif  /* DUK_USE_PC2LINE */
56960 #line 1 "duk_hobject_props.c"
56961 /*
56962  *  duk_hobject property access functionality.
56963  *
56964  *  This is very central functionality for size, performance, and compliance.
56965  *  It is also rather intricate; see hobject-algorithms.rst for discussion on
56966  *  the algorithms and memory-management.rst for discussion on refcounts and
56967  *  side effect issues.
56968  *
56969  *  Notes:
56970  *
56971  *    - It might be tempting to assert "refcount nonzero" for objects
56972  *      being operated on, but that's not always correct: objects with
56973  *      a zero refcount may be operated on by the refcount implementation
56974  *      (finalization) for instance.  Hence, no refcount assertions are made.
56975  *
56976  *    - Many operations (memory allocation, identifier operations, etc)
56977  *      may cause arbitrary side effects (e.g. through GC and finalization).
56978  *      These side effects may invalidate duk_tval pointers which point to
56979  *      areas subject to reallocation (like value stack).  Heap objects
56980  *      themselves have stable pointers.  Holding heap object pointers or
56981  *      duk_tval copies is not problematic with respect to side effects;
56982  *      care must be taken when holding and using argument duk_tval pointers.
56983  *
56984  *    - If a finalizer is executed, it may operate on the the same object
56985  *      we're currently dealing with.  For instance, the finalizer might
56986  *      delete a certain property which has already been looked up and
56987  *      confirmed to exist.  Ideally finalizers would be disabled if GC
56988  *      happens during property access.  At the moment property table realloc
56989  *      disables finalizers, and all DECREFs may cause arbitrary changes so
56990  *      handle DECREF carefully.
56991  *
56992  *    - The order of operations for a DECREF matters.  When DECREF is executed,
56993  *      the entire object graph must be consistent; note that a refzero may
56994  *      lead to a mark-and-sweep through a refcount finalizer.  Use NORZ macros
56995  *      and an explicit DUK_REFZERO_CHECK_xxx() if achieving correct order is hard.
56996  */
56997 
56998 /*
56999  *  XXX: array indices are mostly typed as duk_uint32_t here; duk_uarridx_t
57000  *  might be more appropriate.
57001  */
57002 
57003 /* #include duk_internal.h -> already included */
57004 
57005 /*
57006  *  Local defines
57007  */
57008 
57009 #define DUK__NO_ARRAY_INDEX             DUK_HSTRING_NO_ARRAY_INDEX
57010 
57011 /* Marker values for hash part. */
57012 #define DUK__HASH_UNUSED                DUK_HOBJECT_HASHIDX_UNUSED
57013 #define DUK__HASH_DELETED               DUK_HOBJECT_HASHIDX_DELETED
57014 
57015 /* Valstack space that suffices for all local calls, excluding any recursion
57016  * into ECMAScript or Duktape/C calls (Proxy, getters, etc).
57017  */
57018 #define DUK__VALSTACK_SPACE             10
57019 
57020 /* Valstack space allocated especially for proxy lookup which does a
57021  * recursive property lookup.
57022  */
57023 #define DUK__VALSTACK_PROXY_LOOKUP      20
57024 
57025 /*
57026  *  Local prototypes
57027  */
57028 
57029 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);
57030 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);
57031 DUK_LOCAL_DECL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc);
57032 
57033 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);
57034 DUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj);
57035 
57036 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);
57037 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);
57038 
57039 DUK_LOCAL_DECL void duk__abandon_array_part(duk_hthread *thr, duk_hobject *obj);
57040 DUK_LOCAL_DECL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx);
57041 
57042 /*
57043  *  Misc helpers
57044  */
57045 
57046 /* Convert a duk_tval number (caller checks) to a 32-bit index.  Returns
57047  * DUK__NO_ARRAY_INDEX if the number is not whole or not a valid array
57048  * index.
57049  */
57050 /* XXX: for fastints, could use a variant which assumes a double duk_tval
57051  * (and doesn't need to check for fastint again).
57052  */
57053 DUK_LOCAL duk_uint32_t duk__tval_number_to_arr_idx(duk_tval *tv) {
57054 	duk_double_t dbl;
57055 	duk_uint32_t idx;
57056 
57057 	DUK_ASSERT(tv != NULL);
57058 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
57059 
57060 	/* -0 is accepted here as index 0 because ToString(-0) == "0" which is
57061 	 * in canonical form and thus an array index.
57062 	 */
57063 	dbl = DUK_TVAL_GET_NUMBER(tv);
57064 	idx = (duk_uint32_t) dbl;
57065 	if (duk_double_equals((duk_double_t) idx, dbl)) {
57066 	        /* Is whole and within 32 bit range.  If the value happens to be 0xFFFFFFFF,
57067 		 * it's not a valid array index but will then match DUK__NO_ARRAY_INDEX.
57068 		 */
57069 		return idx;
57070 	}
57071 	return DUK__NO_ARRAY_INDEX;
57072 }
57073 
57074 #if defined(DUK_USE_FASTINT)
57075 /* Convert a duk_tval fastint (caller checks) to a 32-bit index. */
57076 DUK_LOCAL duk_uint32_t duk__tval_fastint_to_arr_idx(duk_tval *tv) {
57077 	duk_int64_t t;
57078 
57079 	DUK_ASSERT(tv != NULL);
57080 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
57081 
57082 	t = DUK_TVAL_GET_FASTINT(tv);
57083 	if (((duk_uint64_t) t & ~DUK_U64_CONSTANT(0xffffffff)) != 0) {
57084 		/* Catches >0x100000000 and negative values. */
57085 		return DUK__NO_ARRAY_INDEX;
57086 	}
57087 
57088 	/* If the value happens to be 0xFFFFFFFF, it's not a valid array index
57089 	 * but will then match DUK__NO_ARRAY_INDEX.
57090 	 */
57091 	return (duk_uint32_t) t;
57092 }
57093 #endif  /* DUK_USE_FASTINT */
57094 
57095 /* Convert a duk_tval on the value stack (in a trusted index we don't validate)
57096  * to a string or symbol using ES2015 ToPropertyKey():
57097  * http://www.ecma-international.org/ecma-262/6.0/#sec-topropertykey.
57098  *
57099  * Also check if it's a valid array index and return that (or DUK__NO_ARRAY_INDEX
57100  * if not).
57101  */
57102 DUK_LOCAL duk_uint32_t duk__to_property_key(duk_hthread *thr, duk_idx_t idx, duk_hstring **out_h) {
57103 	duk_uint32_t arr_idx;
57104 	duk_hstring *h;
57105 	duk_tval *tv_dst;
57106 
57107 	DUK_ASSERT(thr != NULL);
57108 	DUK_ASSERT(out_h != NULL);
57109 	DUK_ASSERT(duk_is_valid_index(thr, idx));
57110 	DUK_ASSERT(idx < 0);
57111 
57112 	/* XXX: The revised ES2015 ToPropertyKey() handling (ES5.1 was just
57113 	 * ToString()) involves a ToPrimitive(), a symbol check, and finally
57114 	 * a ToString().  Figure out the best way to have a good fast path
57115 	 * but still be compliant and share code.
57116 	 */
57117 
57118 	tv_dst = DUK_GET_TVAL_NEGIDX(thr, idx);  /* intentionally unvalidated */
57119 	if (DUK_TVAL_IS_STRING(tv_dst)) {
57120 		/* Most important path: strings and plain symbols are used as
57121 		 * is.  For symbols the array index check below is unnecessary
57122 		 * (they're never valid array indices) but checking that the
57123 		 * string is a symbol would make the plain string path slower
57124 		 * unnecessarily.
57125 		 */
57126 		h = DUK_TVAL_GET_STRING(tv_dst);
57127 	} else {
57128 		h = duk_to_property_key_hstring(thr, idx);
57129 	}
57130 	DUK_ASSERT(h != NULL);
57131 	*out_h = h;
57132 
57133 	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(h);
57134 	return arr_idx;
57135 }
57136 
57137 DUK_LOCAL duk_uint32_t duk__push_tval_to_property_key(duk_hthread *thr, duk_tval *tv_key, duk_hstring **out_h) {
57138 	duk_push_tval(thr, tv_key);  /* XXX: could use an unsafe push here */
57139 	return duk__to_property_key(thr, -1, out_h);
57140 }
57141 
57142 /* String is an own (virtual) property of a plain buffer. */
57143 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) {
57144 	DUK_UNREF(thr);
57145 
57146 	/* Virtual index properties.  Checking explicitly for
57147 	 * 'arr_idx != DUK__NO_ARRAY_INDEX' is not necessary
57148 	 * because DUK__NO_ARRAY_INDEXi is always larger than
57149 	 * maximum allowed buffer size.
57150 	 */
57151 	DUK_ASSERT(DUK__NO_ARRAY_INDEX >= DUK_HBUFFER_GET_SIZE(buf));
57152 	if (arr_idx < DUK_HBUFFER_GET_SIZE(buf)) {
57153 		return 1;
57154 	}
57155 
57156 	/* Other virtual properties. */
57157 	return (key == DUK_HTHREAD_STRING_LENGTH(thr));
57158 }
57159 
57160 /*
57161  *  Helpers for managing property storage size
57162  */
57163 
57164 /* Get default hash part size for a certain entry part size. */
57165 #if defined(DUK_USE_HOBJECT_HASH_PART)
57166 DUK_LOCAL duk_uint32_t duk__get_default_h_size(duk_uint32_t e_size) {
57167 	DUK_ASSERT(e_size <= DUK_HOBJECT_MAX_PROPERTIES);
57168 
57169 	if (e_size >= DUK_USE_HOBJECT_HASH_PROP_LIMIT) {
57170 		duk_uint32_t res;
57171 		duk_uint32_t tmp;
57172 
57173 		/* Hash size should be 2^N where N is chosen so that 2^N is
57174 		 * larger than e_size.  Extra shifting is used to ensure hash
57175 		 * is relatively sparse.
57176 		 */
57177 		tmp = e_size;
57178 		res = 2;  /* Result will be 2 ** (N + 1). */
57179 		while (tmp >= 0x40) {
57180 			tmp >>= 6;
57181 			res <<= 6;
57182 		}
57183 		while (tmp != 0) {
57184 			tmp >>= 1;
57185 			res <<= 1;
57186 		}
57187 		DUK_ASSERT((DUK_HOBJECT_MAX_PROPERTIES << 2U) > DUK_HOBJECT_MAX_PROPERTIES);  /* Won't wrap, even shifted by 2. */
57188 		DUK_ASSERT(res > e_size);
57189 		return res;
57190 	} else {
57191 		return 0;
57192 	}
57193 }
57194 #endif  /* USE_PROP_HASH_PART */
57195 
57196 /* Get minimum entry part growth for a certain size. */
57197 DUK_LOCAL duk_uint32_t duk__get_min_grow_e(duk_uint32_t e_size) {
57198 	duk_uint32_t res;
57199 
57200 	res = (e_size + DUK_USE_HOBJECT_ENTRY_MINGROW_ADD) / DUK_USE_HOBJECT_ENTRY_MINGROW_DIVISOR;
57201 	DUK_ASSERT(res >= 1);  /* important for callers */
57202 	return res;
57203 }
57204 
57205 /* Get minimum array part growth for a certain size. */
57206 DUK_LOCAL duk_uint32_t duk__get_min_grow_a(duk_uint32_t a_size) {
57207 	duk_uint32_t res;
57208 
57209 	res = (a_size + DUK_USE_HOBJECT_ARRAY_MINGROW_ADD) / DUK_USE_HOBJECT_ARRAY_MINGROW_DIVISOR;
57210 	DUK_ASSERT(res >= 1);  /* important for callers */
57211 	return res;
57212 }
57213 
57214 /* Count actually used entry part entries (non-NULL keys). */
57215 DUK_LOCAL duk_uint32_t duk__count_used_e_keys(duk_hthread *thr, duk_hobject *obj) {
57216 	duk_uint_fast32_t i;
57217 	duk_uint_fast32_t n = 0;
57218 	duk_hstring **e;
57219 
57220 	DUK_ASSERT(obj != NULL);
57221 	DUK_UNREF(thr);
57222 
57223 	e = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, obj);
57224 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
57225 		if (*e++) {
57226 			n++;
57227 		}
57228 	}
57229 	return (duk_uint32_t) n;
57230 }
57231 
57232 /* Count actually used array part entries and array minimum size.
57233  * NOTE: 'out_min_size' can be computed much faster by starting from the
57234  * end and breaking out early when finding first used entry, but this is
57235  * not needed now.
57236  */
57237 DUK_LOCAL void duk__compute_a_stats(duk_hthread *thr, duk_hobject *obj, duk_uint32_t *out_used, duk_uint32_t *out_min_size) {
57238 	duk_uint_fast32_t i;
57239 	duk_uint_fast32_t used = 0;
57240 	duk_uint_fast32_t highest_idx = (duk_uint_fast32_t) -1;  /* see below */
57241 	duk_tval *a;
57242 
57243 	DUK_ASSERT(obj != NULL);
57244 	DUK_ASSERT(out_used != NULL);
57245 	DUK_ASSERT(out_min_size != NULL);
57246 	DUK_UNREF(thr);
57247 
57248 	a = DUK_HOBJECT_A_GET_BASE(thr->heap, obj);
57249 	for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
57250 		duk_tval *tv = a++;
57251 		if (!DUK_TVAL_IS_UNUSED(tv)) {
57252 			used++;
57253 			highest_idx = i;
57254 		}
57255 	}
57256 
57257 	/* Initial value for highest_idx is -1 coerced to unsigned.  This
57258 	 * is a bit odd, but (highest_idx + 1) will then wrap to 0 below
57259 	 * for out_min_size as intended.
57260 	 */
57261 
57262 	*out_used = (duk_uint32_t) used;
57263 	*out_min_size = (duk_uint32_t) (highest_idx + 1);  /* 0 if no used entries */
57264 }
57265 
57266 /* Check array density and indicate whether or not the array part should be abandoned. */
57267 DUK_LOCAL duk_bool_t duk__abandon_array_density_check(duk_uint32_t a_used, duk_uint32_t a_size) {
57268 	/*
57269 	 *  Array abandon check; abandon if:
57270 	 *
57271 	 *    new_used / new_size < limit
57272 	 *    new_used < limit * new_size        || limit is 3 bits fixed point
57273 	 *    new_used < limit' / 8 * new_size   || *8
57274 	 *    8*new_used < limit' * new_size     || :8
57275 	 *    new_used < limit' * (new_size / 8)
57276 	 *
57277 	 *  Here, new_used = a_used, new_size = a_size.
57278 	 *
57279 	 *  Note: some callers use approximate values for a_used and/or a_size
57280 	 *  (e.g. dropping a '+1' term).  This doesn't affect the usefulness
57281 	 *  of the check, but may confuse debugging.
57282 	 */
57283 
57284 	return (a_used < DUK_USE_HOBJECT_ARRAY_ABANDON_LIMIT * (a_size >> 3));
57285 }
57286 
57287 /* Fast check for extending array: check whether or not a slow density check is required. */
57288 DUK_LOCAL duk_bool_t duk__abandon_array_slow_check_required(duk_uint32_t arr_idx, duk_uint32_t old_size) {
57289 	duk_uint32_t new_size_min;
57290 
57291 	/*
57292 	 *  In a fast check we assume old_size equals old_used (i.e., existing
57293 	 *  array is fully dense).
57294 	 *
57295 	 *  Slow check if:
57296 	 *
57297 	 *    (new_size - old_size) / old_size > limit
57298 	 *    new_size - old_size > limit * old_size
57299 	 *    new_size > (1 + limit) * old_size        || limit' is 3 bits fixed point
57300 	 *    new_size > (1 + (limit' / 8)) * old_size || * 8
57301 	 *    8 * new_size > (8 + limit') * old_size   || : 8
57302 	 *    new_size > (8 + limit') * (old_size / 8)
57303 	 *    new_size > limit'' * (old_size / 8)      || limit'' = 9 -> max 25% increase
57304 	 *    arr_idx + 1 > limit'' * (old_size / 8)
57305 	 *
57306 	 *  This check doesn't work well for small values, so old_size is rounded
57307 	 *  up for the check (and the '+ 1' of arr_idx can be ignored in practice):
57308 	 *
57309 	 *    arr_idx > limit'' * ((old_size + 7) / 8)
57310 	 */
57311 
57312 	new_size_min = arr_idx + 1;
57313 	return (new_size_min >= DUK_USE_HOBJECT_ARRAY_ABANDON_MINSIZE) &&
57314 	       (arr_idx > DUK_USE_HOBJECT_ARRAY_FAST_RESIZE_LIMIT * ((old_size + 7) >> 3));
57315 }
57316 
57317 DUK_LOCAL duk_bool_t duk__abandon_array_check(duk_hthread *thr, duk_uint32_t arr_idx, duk_hobject *obj) {
57318 	duk_uint32_t min_size;
57319 	duk_uint32_t old_used;
57320 	duk_uint32_t old_size;
57321 
57322 	if (!duk__abandon_array_slow_check_required(arr_idx, DUK_HOBJECT_GET_ASIZE(obj))) {
57323 		DUK_DDD(DUK_DDDPRINT("=> fast resize is OK"));
57324 		return 0;
57325 	}
57326 
57327 	duk__compute_a_stats(thr, obj, &old_used, &old_size);
57328 
57329 	DUK_DDD(DUK_DDDPRINT("abandon check, array stats: old_used=%ld, old_size=%ld, arr_idx=%ld",
57330 	                     (long) old_used, (long) old_size, (long) arr_idx));
57331 
57332 	min_size = arr_idx + 1;
57333 #if defined(DUK_USE_OBJSIZES16)
57334 	if (min_size > DUK_UINT16_MAX) {
57335 		goto do_abandon;
57336 	}
57337 #endif
57338 	DUK_UNREF(min_size);
57339 
57340 	/* Note: intentionally use approximations to shave a few instructions:
57341 	 *   a_used = old_used  (accurate: old_used + 1)
57342 	 *   a_size = arr_idx   (accurate: arr_idx + 1)
57343 	 */
57344 	if (duk__abandon_array_density_check(old_used, arr_idx)) {
57345 		DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
57346 		                   "decided to abandon array part (would become too sparse)"));
57347 
57348 		/* Abandoning requires a props allocation resize and
57349 		 * 'rechecks' the valstack, invalidating any existing
57350 		 * valstack value pointers.
57351 		 */
57352 		goto do_abandon;
57353 	}
57354 
57355 	DUK_DDD(DUK_DDDPRINT("=> decided to keep array part"));
57356 	return 0;
57357 
57358  do_abandon:
57359 	duk__abandon_array_part(thr, obj);
57360 	DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(obj));
57361 	return 1;
57362 }
57363 
57364 DUK_LOCAL duk_tval *duk__obtain_arridx_slot_slowpath(duk_hthread *thr, duk_uint32_t arr_idx, duk_hobject *obj) {
57365 	/*
57366 	 *  Array needs to grow, but we don't want it becoming too sparse.
57367 	 *  If it were to become sparse, abandon array part, moving all
57368 	 *  array entries into the entries part (for good).
57369 	 *
57370 	 *  Since we don't keep track of actual density (used vs. size) of
57371 	 *  the array part, we need to estimate somehow.  The check is made
57372 	 *  in two parts:
57373 	 *
57374 	 *    - Check whether the resize need is small compared to the
57375 	 *      current size (relatively); if so, resize without further
57376 	 *      checking (essentially we assume that the original part is
57377 	 *      "dense" so that the result would be dense enough).
57378 	 *
57379 	 *    - Otherwise, compute the resize using an actual density
57380 	 *      measurement based on counting the used array entries.
57381 	 */
57382 
57383 	DUK_DDD(DUK_DDDPRINT("write to new array requires array resize, decide whether to do a "
57384 	                     "fast resize without abandon check (arr_idx=%ld, old_size=%ld)",
57385 	                     (long) arr_idx, (long) DUK_HOBJECT_GET_ASIZE(obj)));
57386 
57387 	if (DUK_UNLIKELY(duk__abandon_array_check(thr, arr_idx, obj) != 0)) {
57388 		DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(obj));
57389 		return NULL;
57390 	}
57391 
57392 	DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
57393 	                   "decided to extend current allocation"));
57394 
57395 	/* In principle it's possible to run out of memory extending the
57396 	 * array but with the allocation going through if we were to abandon
57397 	 * the array part and try again.  In practice this should be rare
57398 	 * because abandoned arrays have a higher per-entry footprint.
57399 	 */
57400 
57401 	duk__grow_props_for_array_item(thr, obj, arr_idx);
57402 
57403 	DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(obj));
57404 	DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
57405 	return DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
57406 }
57407 
57408 DUK_LOCAL DUK_INLINE duk_tval *duk__obtain_arridx_slot(duk_hthread *thr, duk_uint32_t arr_idx, duk_hobject *obj) {
57409 	if (DUK_LIKELY(arr_idx < DUK_HOBJECT_GET_ASIZE(obj))) {
57410 		return DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
57411 	} else {
57412 		return duk__obtain_arridx_slot_slowpath(thr, arr_idx, obj);
57413 	}
57414 }
57415 
57416 /*
57417  *  Proxy helpers
57418  */
57419 
57420 #if defined(DUK_USE_ES6_PROXY)
57421 DUK_INTERNAL duk_bool_t duk_hobject_proxy_check(duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler) {
57422 	duk_hproxy *h_proxy;
57423 
57424 	DUK_ASSERT(obj != NULL);
57425 	DUK_ASSERT(out_target != NULL);
57426 	DUK_ASSERT(out_handler != NULL);
57427 
57428 	/* Caller doesn't need to check exotic proxy behavior (but does so for
57429 	 * some fast paths).
57430 	 */
57431 	if (DUK_LIKELY(!DUK_HOBJECT_IS_PROXY(obj))) {
57432 		return 0;
57433 	}
57434 	h_proxy = (duk_hproxy *) obj;
57435 	DUK_HPROXY_ASSERT_VALID(h_proxy);
57436 
57437 	DUK_ASSERT(h_proxy->handler != NULL);
57438 	DUK_ASSERT(h_proxy->target != NULL);
57439 	*out_handler = h_proxy->handler;
57440 	*out_target = h_proxy->target;
57441 
57442 	return 1;
57443 }
57444 #endif  /* DUK_USE_ES6_PROXY */
57445 
57446 /* Get Proxy target object.  If the argument is not a Proxy, return it as is.
57447  * If a Proxy is revoked, an error is thrown.
57448  */
57449 #if defined(DUK_USE_ES6_PROXY)
57450 DUK_INTERNAL duk_hobject *duk_hobject_resolve_proxy_target(duk_hobject *obj) {
57451 	DUK_ASSERT(obj != NULL);
57452 
57453 	/* Resolve Proxy targets until Proxy chain ends.  No explicit check for
57454 	 * a Proxy loop: user code cannot create such a loop (it would only be
57455 	 * possible by editing duk_hproxy references directly).
57456 	 */
57457 
57458 	while (DUK_HOBJECT_IS_PROXY(obj)) {
57459 		duk_hproxy *h_proxy;
57460 
57461 		h_proxy = (duk_hproxy *) obj;
57462 		DUK_HPROXY_ASSERT_VALID(h_proxy);
57463 		obj = h_proxy->target;
57464 		DUK_ASSERT(obj != NULL);
57465 	}
57466 
57467 	DUK_ASSERT(obj != NULL);
57468 	return obj;
57469 }
57470 #endif  /* DUK_USE_ES6_PROXY */
57471 
57472 #if defined(DUK_USE_ES6_PROXY)
57473 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) {
57474 	duk_hobject *h_handler;
57475 
57476 	DUK_ASSERT(thr != NULL);
57477 	DUK_ASSERT(obj != NULL);
57478 	DUK_ASSERT(tv_key != NULL);
57479 	DUK_ASSERT(out_target != NULL);
57480 
57481 	if (!duk_hobject_proxy_check(obj, out_target, &h_handler)) {
57482 		return 0;
57483 	}
57484 	DUK_ASSERT(*out_target != NULL);
57485 	DUK_ASSERT(h_handler != NULL);
57486 
57487 	/* XXX: At the moment Duktape accesses internal keys like _Finalizer using a
57488 	 * normal property set/get which would allow a proxy handler to interfere with
57489 	 * such behavior and to get access to internal key strings.  This is not a problem
57490 	 * as such because internal key strings can be created in other ways too (e.g.
57491 	 * through buffers).  The best fix is to change Duktape internal lookups to
57492 	 * skip proxy behavior.  Until that, internal property accesses bypass the
57493 	 * proxy and are applied to the target (as if the handler did not exist).
57494 	 * This has some side effects, see test-bi-proxy-internal-keys.js.
57495 	 */
57496 
57497 	if (DUK_TVAL_IS_STRING(tv_key)) {
57498 		duk_hstring *h_key = (duk_hstring *) DUK_TVAL_GET_STRING(tv_key);
57499 		DUK_ASSERT(h_key != NULL);
57500 		if (DUK_HSTRING_HAS_HIDDEN(h_key)) {
57501 			/* Symbol accesses must go through proxy lookup in ES2015.
57502 			 * Hidden symbols behave like Duktape 1.x internal keys
57503 			 * and currently won't.
57504 			 */
57505 			DUK_DDD(DUK_DDDPRINT("hidden key, skip proxy handler and apply to target"));
57506 			return 0;
57507 		}
57508 	}
57509 
57510 	/* The handler is looked up with a normal property lookup; it may be an
57511 	 * accessor or the handler object itself may be a proxy object.  If the
57512 	 * handler is a proxy, we need to extend the valstack as we make a
57513 	 * recursive proxy check without a function call in between (in fact
57514 	 * there is no limit to the potential recursion here).
57515 	 *
57516 	 * (For sanity, proxy creation rejects another proxy object as either
57517 	 * the handler or the target at the moment so recursive proxy cases
57518 	 * are not realized now.)
57519 	 */
57520 
57521 	/* XXX: C recursion limit if proxies are allowed as handler/target values */
57522 
57523 	duk_require_stack(thr, DUK__VALSTACK_PROXY_LOOKUP);
57524 	duk_push_hobject(thr, h_handler);
57525 	if (duk_get_prop_stridx_short(thr, -1, stridx_trap)) {
57526 		/* -> [ ... handler trap ] */
57527 		duk_insert(thr, -2);  /* -> [ ... trap handler ] */
57528 
57529 		/* stack prepped for func call: [ ... trap handler ] */
57530 		return 1;
57531 	} else {
57532 		duk_pop_2_unsafe(thr);
57533 		return 0;
57534 	}
57535 }
57536 #endif  /* DUK_USE_ES6_PROXY */
57537 
57538 /*
57539  *  Reallocate property allocation, moving properties to the new allocation.
57540  *
57541  *  Includes key compaction, rehashing, and can also optionally abandon
57542  *  the array part, 'migrating' array entries into the beginning of the
57543  *  new entry part.
57544  *
57545  *  There is no support for in-place reallocation or just compacting keys
57546  *  without resizing the property allocation.  This is intentional to keep
57547  *  code size minimal, but would be useful future work.
57548  *
57549  *  The implementation is relatively straightforward, except for the array
57550  *  abandonment process.  Array abandonment requires that new string keys
57551  *  are interned, which may trigger GC.  All keys interned so far must be
57552  *  reachable for GC at all times and correctly refcounted for; valstack is
57553  *  used for that now.
57554  *
57555  *  Also, a GC triggered during this reallocation process must not interfere
57556  *  with the object being resized.  This is currently controlled by preventing
57557  *  finalizers (as they may affect ANY object) and object compaction in
57558  *  mark-and-sweep.  It would suffice to protect only this particular object
57559  *  from compaction, however.  DECREF refzero cascades are side effect free
57560  *  and OK.
57561  *
57562  *  Note: because we need to potentially resize the valstack (as part
57563  *  of abandoning the array part), any tval pointers to the valstack
57564  *  will become invalid after this call.
57565  */
57566 
57567 DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
57568                                             duk_hobject *obj,
57569                                             duk_uint32_t new_e_size,
57570                                             duk_uint32_t new_a_size,
57571                                             duk_uint32_t new_h_size,
57572                                             duk_bool_t abandon_array) {
57573 	duk_small_uint_t prev_ms_base_flags;
57574 	duk_uint32_t new_alloc_size;
57575 	duk_uint32_t new_e_size_adjusted;
57576 	duk_uint8_t *new_p;
57577 	duk_hstring **new_e_k;
57578 	duk_propvalue *new_e_pv;
57579 	duk_uint8_t *new_e_f;
57580 	duk_tval *new_a;
57581 	duk_uint32_t *new_h;
57582 	duk_uint32_t new_e_next;
57583 	duk_uint_fast32_t i;
57584 	duk_size_t array_copy_size;
57585 #if defined(DUK_USE_ASSERTIONS)
57586 	duk_bool_t prev_error_not_allowed;
57587 #endif
57588 
57589 	DUK_ASSERT(thr != NULL);
57590 	DUK_ASSERT(obj != NULL);
57591 	DUK_ASSERT(!abandon_array || new_a_size == 0);  /* if abandon_array, new_a_size must be 0 */
57592 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || (DUK_HOBJECT_GET_ESIZE(obj) == 0 && DUK_HOBJECT_GET_ASIZE(obj) == 0));
57593 	DUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size);  /* required to guarantee success of rehashing,
57594 	                                                           * intentionally use unadjusted new_e_size
57595 	                                                           */
57596 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
57597 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
57598 
57599 	DUK_STATS_INC(thr->heap, stats_object_realloc_props);
57600 
57601 	/*
57602 	 *  Pre resize assertions.
57603 	 */
57604 
57605 #if defined(DUK_USE_ASSERTIONS)
57606 	/* XXX: pre-checks (such as no duplicate keys) */
57607 #endif
57608 
57609 	/*
57610 	 *  For property layout 1, tweak e_size to ensure that the whole entry
57611 	 *  part (key + val + flags) is a suitable multiple for alignment
57612 	 *  (platform specific).
57613 	 *
57614 	 *  Property layout 2 does not require this tweaking and is preferred
57615 	 *  on low RAM platforms requiring alignment.
57616 	 */
57617 
57618 #if defined(DUK_USE_HOBJECT_LAYOUT_2) || defined(DUK_USE_HOBJECT_LAYOUT_3)
57619 	DUK_DDD(DUK_DDDPRINT("using layout 2 or 3, no need to pad e_size: %ld", (long) new_e_size));
57620 	new_e_size_adjusted = new_e_size;
57621 #elif defined(DUK_USE_HOBJECT_LAYOUT_1) && (DUK_HOBJECT_ALIGN_TARGET == 1)
57622 	DUK_DDD(DUK_DDDPRINT("using layout 1, but no need to pad e_size: %ld", (long) new_e_size));
57623 	new_e_size_adjusted = new_e_size;
57624 #elif defined(DUK_USE_HOBJECT_LAYOUT_1) && ((DUK_HOBJECT_ALIGN_TARGET == 4) || (DUK_HOBJECT_ALIGN_TARGET == 8))
57625 	new_e_size_adjusted = (new_e_size + (duk_uint32_t) DUK_HOBJECT_ALIGN_TARGET - 1U) &
57626 	                      (~((duk_uint32_t) DUK_HOBJECT_ALIGN_TARGET - 1U));
57627 	DUK_DDD(DUK_DDDPRINT("using layout 1, and alignment target is %ld, adjusted e_size: %ld -> %ld",
57628 	                     (long) DUK_HOBJECT_ALIGN_TARGET, (long) new_e_size, (long) new_e_size_adjusted));
57629 	DUK_ASSERT(new_e_size_adjusted >= new_e_size);
57630 #else
57631 #error invalid hobject layout defines
57632 #endif
57633 
57634 	/*
57635 	 *  Debug logging after adjustment.
57636 	 */
57637 
57638 	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 "
57639 	                     "{e_size=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
57640 	                     (void *) obj,
57641 	                     (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
57642 	                                                       DUK_HOBJECT_GET_ASIZE(obj),
57643 	                                                       DUK_HOBJECT_GET_HSIZE(obj)),
57644 	                     (long) DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size),
57645 	                     (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
57646 	                     (long) DUK_HOBJECT_GET_ESIZE(obj),
57647 	                     (long) DUK_HOBJECT_GET_ENEXT(obj),
57648 	                     (long) DUK_HOBJECT_GET_ASIZE(obj),
57649 	                     (long) DUK_HOBJECT_GET_HSIZE(obj),
57650 	                     (long) new_e_size_adjusted,
57651 	                     (long) new_a_size,
57652 	                     (long) new_h_size,
57653 	                     (long) abandon_array,
57654 	                     (long) new_e_size));
57655 
57656 	/*
57657 	 *  Property count check.  This is the only point where we ensure that
57658 	 *  we don't get more (allocated) property space that we can handle.
57659 	 *  There aren't hard limits as such, but some algorithms may fail
57660 	 *  if we get too close to the 4G property limit.
57661 	 *
57662 	 *  Since this works based on allocation size (not actually used size),
57663 	 *  the limit is a bit approximate but good enough in practice.
57664 	 */
57665 
57666 	if (new_e_size_adjusted + new_a_size > DUK_HOBJECT_MAX_PROPERTIES) {
57667 		DUK_ERROR_ALLOC_FAILED(thr);
57668 		DUK_WO_NORETURN(return;);
57669 	}
57670 #if defined(DUK_USE_OBJSIZES16)
57671 	if (new_e_size_adjusted > DUK_UINT16_MAX || new_a_size > DUK_UINT16_MAX) {
57672 		/* If caller gave us sizes larger than what we can store,
57673 		 * fail memory safely with an internal error rather than
57674 		 * truncating the sizes.
57675 		 */
57676 		DUK_ERROR_INTERNAL(thr);
57677 		DUK_WO_NORETURN(return;);
57678 	}
57679 #endif
57680 
57681 	/*
57682 	 *  Compute new alloc size and alloc new area.
57683 	 *
57684 	 *  The new area is not tracked in the heap at all, so it's critical
57685 	 *  we get to free/keep it in a controlled manner.
57686 	 */
57687 
57688 #if defined(DUK_USE_ASSERTIONS)
57689 	/* Whole path must be error throw free, but we may be called from
57690 	 * within error handling so can't assert for error_not_allowed == 0.
57691 	 */
57692 	prev_error_not_allowed = thr->heap->error_not_allowed;
57693 	thr->heap->error_not_allowed = 1;
57694 #endif
57695 	prev_ms_base_flags = thr->heap->ms_base_flags;
57696 	thr->heap->ms_base_flags |=
57697 	        DUK_MS_FLAG_NO_OBJECT_COMPACTION;      /* Avoid attempt to compact the current object (all objects really). */
57698 	thr->heap->pf_prevent_count++;                 /* Avoid finalizers. */
57699 	DUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */
57700 
57701 	new_alloc_size = DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size);
57702 	DUK_DDD(DUK_DDDPRINT("new hobject allocation size is %ld", (long) new_alloc_size));
57703 	if (new_alloc_size == 0) {
57704 		DUK_ASSERT(new_e_size_adjusted == 0);
57705 		DUK_ASSERT(new_a_size == 0);
57706 		DUK_ASSERT(new_h_size == 0);
57707 		new_p = NULL;
57708 	} else {
57709 		/* Alloc may trigger mark-and-sweep but no compaction, and
57710 		 * cannot throw.
57711 		 */
57712 #if 0  /* XXX: inject test */
57713 		if (1) {
57714 			new_p = NULL;
57715 			goto alloc_failed;
57716 		}
57717 #endif
57718 		new_p = (duk_uint8_t *) DUK_ALLOC(thr->heap, new_alloc_size);
57719 		if (new_p == NULL) {
57720 			/* NULL always indicates alloc failure because
57721 			 * new_alloc_size > 0.
57722 			 */
57723 			goto alloc_failed;
57724 		}
57725 	}
57726 
57727 	/* Set up pointers to the new property area: this is hidden behind a macro
57728 	 * because it is memory layout specific.
57729 	 */
57730 	DUK_HOBJECT_P_SET_REALLOC_PTRS(new_p, new_e_k, new_e_pv, new_e_f, new_a, new_h,
57731 	                               new_e_size_adjusted, new_a_size, new_h_size);
57732 	DUK_UNREF(new_h);  /* happens when hash part dropped */
57733 	new_e_next = 0;
57734 
57735 	/* if new_p == NULL, all of these pointers are NULL */
57736 	DUK_ASSERT((new_p != NULL) ||
57737 	           (new_e_k == NULL && new_e_pv == NULL && new_e_f == NULL &&
57738 	            new_a == NULL && new_h == NULL));
57739 
57740 	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",
57741 	                     (long) new_alloc_size, (void *) new_e_k, (void *) new_e_pv, (void *) new_e_f,
57742 	                     (void *) new_a, (void *) new_h));
57743 
57744 	/*
57745 	 *  Migrate array part to start of entries if requested.
57746 	 *
57747 	 *  Note: from an enumeration perspective the order of entry keys matters.
57748 	 *  Array keys should appear wherever they appeared before the array abandon
57749 	 *  operation.  (This no longer matters much because keys are ES2015 sorted.)
57750 	 */
57751 
57752 	if (abandon_array) {
57753 		/* Assuming new_a_size == 0, and that entry part contains
57754 		 * no conflicting keys, refcounts do not need to be adjusted for
57755 		 * the values, as they remain exactly the same.
57756 		 *
57757 		 * The keys, however, need to be interned, incref'd, and be
57758 		 * reachable for GC.  Any intern attempt may trigger a GC and
57759 		 * claim any non-reachable strings, so every key must be reachable
57760 		 * at all times.  Refcounts must be correct to satisfy refcount
57761 		 * assertions.
57762 		 *
57763 		 * A longjmp must not occur here, as the new_p allocation would
57764 		 * leak.  Refcounts would come out correctly as the interned
57765 		 * strings are valstack tracked.
57766 		 */
57767 		DUK_ASSERT(new_a_size == 0);
57768 
57769 		DUK_STATS_INC(thr->heap, stats_object_abandon_array);
57770 
57771 		for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
57772 			duk_tval *tv1;
57773 			duk_tval *tv2;
57774 			duk_hstring *key;
57775 
57776 			DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
57777 
57778 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
57779 			if (DUK_TVAL_IS_UNUSED(tv1)) {
57780 				continue;
57781 			}
57782 
57783 			DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
57784 			           new_e_pv != NULL && new_e_f != NULL);
57785 
57786 			/*
57787 			 *  Intern key via the valstack to ensure reachability behaves
57788 			 *  properly.  We must avoid longjmp's here so use non-checked
57789 			 *  primitives.
57790 			 *
57791 			 *  Note: duk_check_stack() potentially reallocs the valstack,
57792 			 *  invalidating any duk_tval pointers to valstack.  Callers
57793 			 *  must be careful.
57794 			 */
57795 
57796 #if 0  /* XXX: inject test */
57797 			if (1) {
57798 				goto abandon_error;
57799 			}
57800 #endif
57801 			/* Never shrinks; auto-adds DUK_VALSTACK_INTERNAL_EXTRA, which
57802 			 * is generous.
57803 			 */
57804 			if (!duk_check_stack(thr, 1)) {
57805 				goto abandon_error;
57806 			}
57807 			DUK_ASSERT_VALSTACK_SPACE(thr, 1);
57808 			key = duk_heap_strtable_intern_u32(thr->heap, (duk_uint32_t) i);
57809 			if (key == NULL) {
57810 				goto abandon_error;
57811 			}
57812 			duk_push_hstring(thr, key);  /* keep key reachable for GC etc; guaranteed not to fail */
57813 
57814 			/* Key is now reachable in the valstack, don't INCREF
57815 			 * the new allocation yet (we'll steal the refcounts
57816 			 * from the value stack once all keys are done).
57817 			 */
57818 
57819 			new_e_k[new_e_next] = key;
57820 			tv2 = &new_e_pv[new_e_next].v;  /* array entries are all plain values */
57821 			DUK_TVAL_SET_TVAL(tv2, tv1);
57822 			new_e_f[new_e_next] = DUK_PROPDESC_FLAG_WRITABLE |
57823 			                      DUK_PROPDESC_FLAG_ENUMERABLE |
57824 			                      DUK_PROPDESC_FLAG_CONFIGURABLE;
57825 			new_e_next++;
57826 
57827 			/* Note: new_e_next matches pushed temp key count, and nothing can
57828 			 * fail above between the push and this point.
57829 			 */
57830 		}
57831 
57832 		/* Steal refcounts from value stack. */
57833 		DUK_DDD(DUK_DDDPRINT("abandon array: pop %ld key temps from valstack", (long) new_e_next));
57834 		duk_pop_n_nodecref_unsafe(thr, (duk_idx_t) new_e_next);
57835 	}
57836 
57837 	/*
57838 	 *  Copy keys and values in the entry part (compacting them at the same time).
57839 	 */
57840 
57841 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
57842 		duk_hstring *key;
57843 
57844 		DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
57845 
57846 		key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
57847 		if (key == NULL) {
57848 			continue;
57849 		}
57850 
57851 		DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
57852 		           new_e_pv != NULL && new_e_f != NULL);
57853 
57854 		new_e_k[new_e_next] = key;
57855 		new_e_pv[new_e_next] = DUK_HOBJECT_E_GET_VALUE(thr->heap, obj, i);
57856 		new_e_f[new_e_next] = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
57857 		new_e_next++;
57858 	}
57859 	/* the entries [new_e_next, new_e_size_adjusted[ are left uninitialized on purpose (ok, not gc reachable) */
57860 
57861 	/*
57862 	 *  Copy array elements to new array part.  If the new array part is
57863 	 *  larger, initialize the unused entries as UNUSED because they are
57864 	 *  GC reachable.
57865 	 */
57866 
57867 #if defined(DUK_USE_ASSERTIONS)
57868 	/* Caller must have decref'd values above new_a_size (if that is necessary). */
57869 	if (!abandon_array) {
57870 		for (i = new_a_size; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
57871 			duk_tval *tv;
57872 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
57873 			DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));
57874 		}
57875 	}
57876 #endif
57877 	if (new_a_size > DUK_HOBJECT_GET_ASIZE(obj)) {
57878 		array_copy_size = sizeof(duk_tval) * DUK_HOBJECT_GET_ASIZE(obj);
57879 	} else {
57880 		array_copy_size = sizeof(duk_tval) * new_a_size;
57881 	}
57882 
57883 	DUK_ASSERT(new_a != NULL || array_copy_size == 0U);
57884 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || array_copy_size == 0U);
57885 	DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) > 0 || array_copy_size == 0U);
57886 	duk_memcpy_unsafe((void *) new_a,
57887 	                  (const void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj),
57888 	                  array_copy_size);
57889 
57890 	for (i = DUK_HOBJECT_GET_ASIZE(obj); i < new_a_size; i++) {
57891 		duk_tval *tv = &new_a[i];
57892 		DUK_TVAL_SET_UNUSED(tv);
57893 	}
57894 
57895 	/*
57896 	 *  Rebuild the hash part always from scratch (guaranteed to finish
57897 	 *  as long as caller gave consistent parameters).
57898 	 *
57899 	 *  Any resize of hash part requires rehashing.  In addition, by rehashing
57900 	 *  get rid of any elements marked deleted (DUK__HASH_DELETED) which is critical
57901 	 *  to ensuring the hash part never fills up.
57902 	 */
57903 
57904 #if defined(DUK_USE_HOBJECT_HASH_PART)
57905 	if (new_h_size == 0) {
57906 		DUK_DDD(DUK_DDDPRINT("no hash part, no rehash"));
57907 	} else {
57908 		duk_uint32_t mask;
57909 
57910 		DUK_ASSERT(new_h != NULL);
57911 
57912 		/* fill new_h with u32 0xff = UNUSED */
57913 		DUK_ASSERT(new_h_size > 0);
57914 		duk_memset(new_h, 0xff, sizeof(duk_uint32_t) * new_h_size);
57915 
57916 		DUK_ASSERT(new_e_next <= new_h_size);  /* equality not actually possible */
57917 
57918 		mask = new_h_size - 1;
57919 		for (i = 0; i < new_e_next; i++) {
57920 			duk_hstring *key = new_e_k[i];
57921 			duk_uint32_t j, step;
57922 
57923 			DUK_ASSERT(key != NULL);
57924 			j = DUK_HSTRING_GET_HASH(key) & mask;
57925 			step = 1;  /* Cache friendly but clustering prone. */
57926 
57927 			for (;;) {
57928 				DUK_ASSERT(new_h[j] != DUK__HASH_DELETED);  /* should never happen */
57929 				if (new_h[j] == DUK__HASH_UNUSED) {
57930 					DUK_DDD(DUK_DDDPRINT("rebuild hit %ld -> %ld", (long) j, (long) i));
57931 					new_h[j] = (duk_uint32_t) i;
57932 					break;
57933 				}
57934 				DUK_DDD(DUK_DDDPRINT("rebuild miss %ld, step %ld", (long) j, (long) step));
57935 				j = (j + step) & mask;
57936 
57937 				/* Guaranteed to finish (hash is larger than #props). */
57938 			}
57939 		}
57940 	}
57941 #endif  /* DUK_USE_HOBJECT_HASH_PART */
57942 
57943 	/*
57944 	 *  Nice debug log.
57945 	 */
57946 
57947 	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 "
57948 	                   "{p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
57949 	                   (void *) obj,
57950 	                   (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
57951 	                                                     DUK_HOBJECT_GET_ASIZE(obj),
57952 	                                                     DUK_HOBJECT_GET_HSIZE(obj)),
57953 	                   (long) new_alloc_size,
57954 	                   (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
57955 	                   (long) DUK_HOBJECT_GET_ESIZE(obj),
57956 	                   (long) DUK_HOBJECT_GET_ENEXT(obj),
57957 	                   (long) DUK_HOBJECT_GET_ASIZE(obj),
57958 	                   (long) DUK_HOBJECT_GET_HSIZE(obj),
57959 	                   (void *) new_p,
57960 	                   (long) new_e_size_adjusted,
57961 	                   (long) new_e_next,
57962 	                   (long) new_a_size,
57963 	                   (long) new_h_size,
57964 	                   (long) abandon_array,
57965 	                   (long) new_e_size));
57966 
57967 	/*
57968 	 *  All done, switch properties ('p') allocation to new one.
57969 	 */
57970 
57971 	DUK_FREE_CHECKED(thr, DUK_HOBJECT_GET_PROPS(thr->heap, obj));  /* NULL obj->p is OK */
57972 	DUK_HOBJECT_SET_PROPS(thr->heap, obj, new_p);
57973 	DUK_HOBJECT_SET_ESIZE(obj, new_e_size_adjusted);
57974 	DUK_HOBJECT_SET_ENEXT(obj, new_e_next);
57975 	DUK_HOBJECT_SET_ASIZE(obj, new_a_size);
57976 	DUK_HOBJECT_SET_HSIZE(obj, new_h_size);
57977 
57978 	/* Clear array part flag only after switching. */
57979 	if (abandon_array) {
57980 		DUK_HOBJECT_CLEAR_ARRAY_PART(obj);
57981 	}
57982 
57983 	DUK_DDD(DUK_DDDPRINT("resize result: %!O", (duk_heaphdr *) obj));
57984 
57985 	DUK_ASSERT(thr->heap->pf_prevent_count > 0);
57986 	thr->heap->pf_prevent_count--;
57987 	thr->heap->ms_base_flags = prev_ms_base_flags;
57988 #if defined(DUK_USE_ASSERTIONS)
57989 	DUK_ASSERT(thr->heap->error_not_allowed == 1);
57990 	thr->heap->error_not_allowed = prev_error_not_allowed;
57991 #endif
57992 
57993 	/*
57994 	 *  Post resize assertions.
57995 	 */
57996 
57997 #if defined(DUK_USE_ASSERTIONS)
57998 	/* XXX: post-checks (such as no duplicate keys) */
57999 #endif
58000 	return;
58001 
58002 	/*
58003 	 *  Abandon array failed.  We don't need to DECREF anything
58004 	 *  because the references in the new allocation are not
58005 	 *  INCREF'd until abandon is complete.  The string interned
58006 	 *  keys are on the value stack and are handled normally by
58007 	 *  unwind.
58008 	 */
58009 
58010  abandon_error:
58011  alloc_failed:
58012 	DUK_D(DUK_DPRINT("object property table resize failed"));
58013 
58014 	DUK_FREE_CHECKED(thr, new_p);  /* OK for NULL. */
58015 
58016 	thr->heap->pf_prevent_count--;
58017 	thr->heap->ms_base_flags = prev_ms_base_flags;
58018 #if defined(DUK_USE_ASSERTIONS)
58019 	DUK_ASSERT(thr->heap->error_not_allowed == 1);
58020 	thr->heap->error_not_allowed = prev_error_not_allowed;
58021 #endif
58022 
58023 	DUK_ERROR_ALLOC_FAILED(thr);
58024 	DUK_WO_NORETURN(return;);
58025 }
58026 
58027 /*
58028  *  Helpers to resize properties allocation on specific needs.
58029  */
58030 
58031 DUK_INTERNAL void duk_hobject_resize_entrypart(duk_hthread *thr,
58032                                                duk_hobject *obj,
58033                                                duk_uint32_t new_e_size) {
58034 	duk_uint32_t old_e_size;
58035 	duk_uint32_t new_a_size;
58036 	duk_uint32_t new_h_size;
58037 
58038 	DUK_ASSERT(thr != NULL);
58039 	DUK_ASSERT(obj != NULL);
58040 
58041 	old_e_size = DUK_HOBJECT_GET_ESIZE(obj);
58042 	if (old_e_size > new_e_size) {
58043 		new_e_size = old_e_size;
58044 	}
58045 #if defined(DUK_USE_HOBJECT_HASH_PART)
58046 	new_h_size = duk__get_default_h_size(new_e_size);
58047 #else
58048 	new_h_size = 0;
58049 #endif
58050 	new_a_size = DUK_HOBJECT_GET_ASIZE(obj);
58051 
58052 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
58053 }
58054 
58055 /* Grow entry part allocation for one additional entry. */
58056 DUK_LOCAL void duk__grow_props_for_new_entry_item(duk_hthread *thr, duk_hobject *obj) {
58057 	duk_uint32_t old_e_used;  /* actually used, non-NULL entries */
58058 	duk_uint32_t new_e_size_minimum;
58059 	duk_uint32_t new_e_size;
58060 	duk_uint32_t new_a_size;
58061 	duk_uint32_t new_h_size;
58062 
58063 	DUK_ASSERT(thr != NULL);
58064 	DUK_ASSERT(obj != NULL);
58065 
58066 	/* Duktape 0.11.0 and prior tried to optimize the resize by not
58067 	 * counting the number of actually used keys prior to the resize.
58068 	 * This worked mostly well but also caused weird leak-like behavior
58069 	 * as in: test-bug-object-prop-alloc-unbounded.js.  So, now we count
58070 	 * the keys explicitly to compute the new entry part size.
58071 	 */
58072 
58073 	old_e_used = duk__count_used_e_keys(thr, obj);
58074 	new_e_size_minimum = old_e_used + 1;
58075 	new_e_size = old_e_used + duk__get_min_grow_e(old_e_used);
58076 #if defined(DUK_USE_HOBJECT_HASH_PART)
58077 	new_h_size = duk__get_default_h_size(new_e_size);
58078 #else
58079 	new_h_size = 0;
58080 #endif
58081 	new_a_size = DUK_HOBJECT_GET_ASIZE(obj);
58082 
58083 #if defined(DUK_USE_OBJSIZES16)
58084 	if (new_e_size > DUK_UINT16_MAX) {
58085 		new_e_size = DUK_UINT16_MAX;
58086 	}
58087 	if (new_h_size > DUK_UINT16_MAX) {
58088 		new_h_size = DUK_UINT16_MAX;
58089 	}
58090 	if (new_a_size > DUK_UINT16_MAX) {
58091 		new_a_size = DUK_UINT16_MAX;
58092 	}
58093 #endif
58094 	DUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size);
58095 
58096 	if (!(new_e_size >= new_e_size_minimum)) {
58097 		DUK_ERROR_ALLOC_FAILED(thr);
58098 		DUK_WO_NORETURN(return;);
58099 	}
58100 
58101 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
58102 }
58103 
58104 /* Grow array part for a new highest array index. */
58105 DUK_LOCAL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx) {
58106 	duk_uint32_t new_e_size;
58107 	duk_uint32_t new_a_size;
58108 	duk_uint32_t new_a_size_minimum;
58109 	duk_uint32_t new_h_size;
58110 
58111 	DUK_ASSERT(thr != NULL);
58112 	DUK_ASSERT(obj != NULL);
58113 	DUK_ASSERT(highest_arr_idx >= DUK_HOBJECT_GET_ASIZE(obj));
58114 
58115 	new_e_size = DUK_HOBJECT_GET_ESIZE(obj);
58116 	new_h_size = DUK_HOBJECT_GET_HSIZE(obj);
58117 	new_a_size_minimum = highest_arr_idx + 1;
58118 	new_a_size = highest_arr_idx + duk__get_min_grow_a(highest_arr_idx);
58119 	DUK_ASSERT(new_a_size >= highest_arr_idx + 1);  /* duk__get_min_grow_a() is always >= 1 */
58120 
58121 #if defined(DUK_USE_OBJSIZES16)
58122 	if (new_e_size > DUK_UINT16_MAX) {
58123 		new_e_size = DUK_UINT16_MAX;
58124 	}
58125 	if (new_h_size > DUK_UINT16_MAX) {
58126 		new_h_size = DUK_UINT16_MAX;
58127 	}
58128 	if (new_a_size > DUK_UINT16_MAX) {
58129 		new_a_size = DUK_UINT16_MAX;
58130 	}
58131 #endif
58132 
58133 	if (!(new_a_size >= new_a_size_minimum)) {
58134 		DUK_ERROR_ALLOC_FAILED(thr);
58135 		DUK_WO_NORETURN(return;);
58136 	}
58137 
58138 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
58139 }
58140 
58141 /* Abandon array part, moving array entries into entries part.
58142  * This requires a props resize, which is a heavy operation.
58143  * We also compact the entries part while we're at it, although
58144  * this is not strictly required.
58145  */
58146 DUK_LOCAL void duk__abandon_array_part(duk_hthread *thr, duk_hobject *obj) {
58147 	duk_uint32_t new_e_size_minimum;
58148 	duk_uint32_t new_e_size;
58149 	duk_uint32_t new_a_size;
58150 	duk_uint32_t new_h_size;
58151 	duk_uint32_t e_used;  /* actually used, non-NULL keys */
58152 	duk_uint32_t a_used;
58153 	duk_uint32_t a_size;
58154 
58155 	DUK_ASSERT(thr != NULL);
58156 	DUK_ASSERT(obj != NULL);
58157 
58158 	e_used = duk__count_used_e_keys(thr, obj);
58159 	duk__compute_a_stats(thr, obj, &a_used, &a_size);
58160 
58161 	/*
58162 	 *  Must guarantee all actually used array entries will fit into
58163 	 *  new entry part.  Add one growth step to ensure we don't run out
58164 	 *  of space right away.
58165 	 */
58166 
58167 	new_e_size_minimum = e_used + a_used;
58168 	new_e_size = new_e_size_minimum + duk__get_min_grow_e(new_e_size_minimum);
58169 	new_a_size = 0;
58170 #if defined(DUK_USE_HOBJECT_HASH_PART)
58171 	new_h_size = duk__get_default_h_size(new_e_size);
58172 #else
58173 	new_h_size = 0;
58174 #endif
58175 
58176 #if defined(DUK_USE_OBJSIZES16)
58177 	if (new_e_size > DUK_UINT16_MAX) {
58178 		new_e_size = DUK_UINT16_MAX;
58179 	}
58180 	if (new_h_size > DUK_UINT16_MAX) {
58181 		new_h_size = DUK_UINT16_MAX;
58182 	}
58183 	if (new_a_size > DUK_UINT16_MAX) {
58184 		new_a_size = DUK_UINT16_MAX;
58185 	}
58186 #endif
58187 
58188 	if (!(new_e_size >= new_e_size_minimum)) {
58189 		DUK_ERROR_ALLOC_FAILED(thr);
58190 		DUK_WO_NORETURN(return;);
58191 	}
58192 
58193 	DUK_DD(DUK_DDPRINT("abandon array part for hobject %p, "
58194 	                   "array stats before: e_used=%ld, a_used=%ld, a_size=%ld; "
58195 	                   "resize to e_size=%ld, a_size=%ld, h_size=%ld",
58196 	                   (void *) obj, (long) e_used, (long) a_used, (long) a_size,
58197 	                   (long) new_e_size, (long) new_a_size, (long) new_h_size));
58198 
58199 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 1);
58200 }
58201 
58202 /*
58203  *  Compact an object.  Minimizes allocation size for objects which are
58204  *  not likely to be extended.  This is useful for internal and non-
58205  *  extensible objects, but can also be called for non-extensible objects.
58206  *  May abandon the array part if it is computed to be too sparse.
58207  *
58208  *  This call is relatively expensive, as it needs to scan both the
58209  *  entries and the array part.
58210  *
58211  *  The call may fail due to allocation error.
58212  */
58213 
58214 DUK_INTERNAL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj) {
58215 	duk_uint32_t e_size;       /* currently used -> new size */
58216 	duk_uint32_t a_size;       /* currently required */
58217 	duk_uint32_t a_used;       /* actually used */
58218 	duk_uint32_t h_size;
58219 	duk_bool_t abandon_array;
58220 
58221 	DUK_ASSERT(thr != NULL);
58222 	DUK_ASSERT(obj != NULL);
58223 
58224 #if defined(DUK_USE_ROM_OBJECTS)
58225 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
58226 		DUK_DD(DUK_DDPRINT("ignore attempt to compact a rom object"));
58227 		return;
58228 	}
58229 #endif
58230 
58231 	e_size = duk__count_used_e_keys(thr, obj);
58232 	duk__compute_a_stats(thr, obj, &a_used, &a_size);
58233 
58234 	DUK_DD(DUK_DDPRINT("compacting hobject, used e keys %ld, used a keys %ld, min a size %ld, "
58235 	                   "resized array density would be: %ld/%ld = %lf",
58236 	                   (long) e_size, (long) a_used, (long) a_size,
58237 	                   (long) a_used, (long) a_size,
58238 	                   (double) a_used / (double) a_size));
58239 
58240 	if (duk__abandon_array_density_check(a_used, a_size)) {
58241 		DUK_DD(DUK_DDPRINT("decided to abandon array during compaction, a_used=%ld, a_size=%ld",
58242 		                   (long) a_used, (long) a_size));
58243 		abandon_array = 1;
58244 		e_size += a_used;
58245 		a_size = 0;
58246 	} else {
58247 		DUK_DD(DUK_DDPRINT("decided to keep array during compaction"));
58248 		abandon_array = 0;
58249 	}
58250 
58251 #if defined(DUK_USE_HOBJECT_HASH_PART)
58252 	if (e_size >= DUK_USE_HOBJECT_HASH_PROP_LIMIT) {
58253 		h_size = duk__get_default_h_size(e_size);
58254 	} else {
58255 		h_size = 0;
58256 	}
58257 #else
58258 	h_size = 0;
58259 #endif
58260 
58261 	DUK_DD(DUK_DDPRINT("compacting hobject -> new e_size %ld, new a_size=%ld, new h_size=%ld, abandon_array=%ld",
58262 	                   (long) e_size, (long) a_size, (long) h_size, (long) abandon_array));
58263 
58264 	duk_hobject_realloc_props(thr, obj, e_size, a_size, h_size, abandon_array);
58265 }
58266 
58267 /*
58268  *  Find an existing key from entry part either by linear scan or by
58269  *  using the hash index (if it exists).
58270  *
58271  *  Sets entry index (and possibly the hash index) to output variables,
58272  *  which allows the caller to update the entry and hash entries in-place.
58273  *  If entry is not found, both values are set to -1.  If entry is found
58274  *  but there is no hash part, h_idx is set to -1.
58275  */
58276 
58277 DUK_INTERNAL duk_bool_t duk_hobject_find_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx) {
58278 	DUK_ASSERT(obj != NULL);
58279 	DUK_ASSERT(key != NULL);
58280 	DUK_ASSERT(e_idx != NULL);
58281 	DUK_ASSERT(h_idx != NULL);
58282 	DUK_UNREF(heap);
58283 
58284 	if (DUK_LIKELY(DUK_HOBJECT_GET_HSIZE(obj) == 0))
58285 	{
58286 		/* Linear scan: more likely because most objects are small.
58287 		 * This is an important fast path.
58288 		 *
58289 		 * XXX: this might be worth inlining for property lookups.
58290 		 */
58291 		duk_uint_fast32_t i;
58292 		duk_uint_fast32_t n;
58293 		duk_hstring **h_keys_base;
58294 		DUK_DDD(DUK_DDDPRINT("duk_hobject_find_entry() using linear scan for lookup"));
58295 
58296 		h_keys_base = DUK_HOBJECT_E_GET_KEY_BASE(heap, obj);
58297 		n = DUK_HOBJECT_GET_ENEXT(obj);
58298 		for (i = 0; i < n; i++) {
58299 			if (h_keys_base[i] == key) {
58300 				*e_idx = (duk_int_t) i;
58301 				*h_idx = -1;
58302 				return 1;
58303 			}
58304 		}
58305 	}
58306 #if defined(DUK_USE_HOBJECT_HASH_PART)
58307 	else
58308 	{
58309 		/* hash lookup */
58310 		duk_uint32_t n;
58311 		duk_uint32_t i, step;
58312 		duk_uint32_t *h_base;
58313 		duk_uint32_t mask;
58314 
58315 		DUK_DDD(DUK_DDDPRINT("duk_hobject_find_entry() using hash part for lookup"));
58316 
58317 		h_base = DUK_HOBJECT_H_GET_BASE(heap, obj);
58318 		n = DUK_HOBJECT_GET_HSIZE(obj);
58319 		mask = n - 1;
58320 		i = DUK_HSTRING_GET_HASH(key) & mask;
58321 		step = 1;  /* Cache friendly but clustering prone. */
58322 
58323 		for (;;) {
58324 			duk_uint32_t t;
58325 
58326 			DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
58327 			DUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));
58328 			t = h_base[i];
58329 			DUK_ASSERT(t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED ||
58330 			           (t < DUK_HOBJECT_GET_ESIZE(obj)));  /* t >= 0 always true, unsigned */
58331 
58332 			if (t == DUK__HASH_UNUSED) {
58333 				break;
58334 			} else if (t == DUK__HASH_DELETED) {
58335 				DUK_DDD(DUK_DDDPRINT("lookup miss (deleted) i=%ld, t=%ld",
58336 				                     (long) i, (long) t));
58337 			} else {
58338 				DUK_ASSERT(t < DUK_HOBJECT_GET_ESIZE(obj));
58339 				if (DUK_HOBJECT_E_GET_KEY(heap, obj, t) == key) {
58340 					DUK_DDD(DUK_DDDPRINT("lookup hit i=%ld, t=%ld -> key %p",
58341 					                     (long) i, (long) t, (void *) key));
58342 					*e_idx = (duk_int_t) t;
58343 					*h_idx = (duk_int_t) i;
58344 					return 1;
58345 				}
58346 				DUK_DDD(DUK_DDDPRINT("lookup miss i=%ld, t=%ld",
58347 				                     (long) i, (long) t));
58348 			}
58349 			i = (i + step) & mask;
58350 
58351 			/* Guaranteed to finish (hash is larger than #props). */
58352 		}
58353 	}
58354 #endif  /* DUK_USE_HOBJECT_HASH_PART */
58355 
58356 	/* Not found, leave e_idx and h_idx unset. */
58357 	return 0;
58358 }
58359 
58360 /* For internal use: get non-accessor entry value */
58361 DUK_INTERNAL duk_tval *duk_hobject_find_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key) {
58362 	duk_int_t e_idx;
58363 	duk_int_t h_idx;
58364 
58365 	DUK_ASSERT(obj != NULL);
58366 	DUK_ASSERT(key != NULL);
58367 	DUK_UNREF(heap);
58368 
58369 	if (duk_hobject_find_entry(heap, obj, key, &e_idx, &h_idx)) {
58370 		DUK_ASSERT(e_idx >= 0);
58371 		if (!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
58372 			return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
58373 		}
58374 	}
58375 	return NULL;
58376 }
58377 
58378 DUK_INTERNAL duk_tval *duk_hobject_find_entry_tval_ptr_stridx(duk_heap *heap, duk_hobject *obj, duk_small_uint_t stridx) {
58379 	return duk_hobject_find_entry_tval_ptr(heap, obj, DUK_HEAP_GET_STRING(heap, stridx));
58380 }
58381 
58382 /* For internal use: get non-accessor entry value and attributes */
58383 DUK_INTERNAL duk_tval *duk_hobject_find_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_uint_t *out_attrs) {
58384 	duk_int_t e_idx;
58385 	duk_int_t h_idx;
58386 
58387 	DUK_ASSERT(obj != NULL);
58388 	DUK_ASSERT(key != NULL);
58389 	DUK_ASSERT(out_attrs != NULL);
58390 	DUK_UNREF(heap);
58391 
58392 	if (duk_hobject_find_entry(heap, obj, key, &e_idx, &h_idx)) {
58393 		DUK_ASSERT(e_idx >= 0);
58394 		if (!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
58395 			*out_attrs = DUK_HOBJECT_E_GET_FLAGS(heap, obj, e_idx);
58396 			return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
58397 		}
58398 	}
58399 	/* If not found, out_attrs is left unset. */
58400 	return NULL;
58401 }
58402 
58403 /* For internal use: get array part value */
58404 DUK_INTERNAL duk_tval *duk_hobject_find_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i) {
58405 	duk_tval *tv;
58406 
58407 	DUK_ASSERT(obj != NULL);
58408 	DUK_UNREF(heap);
58409 
58410 	if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
58411 		return NULL;
58412 	}
58413 	if (i >= DUK_HOBJECT_GET_ASIZE(obj)) {
58414 		return NULL;
58415 	}
58416 	tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, obj, i);
58417 	return tv;
58418 }
58419 
58420 /*
58421  *  Allocate and initialize a new entry, resizing the properties allocation
58422  *  if necessary.  Returns entry index (e_idx) or throws an error if alloc fails.
58423  *
58424  *  Sets the key of the entry (increasing the key's refcount), and updates
58425  *  the hash part if it exists.  Caller must set value and flags, and update
58426  *  the entry value refcount.  A decref for the previous value is not necessary.
58427  */
58428 
58429 DUK_LOCAL duk_int_t duk__hobject_alloc_entry_checked(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {
58430 	duk_uint32_t idx;
58431 
58432 	DUK_ASSERT(thr != NULL);
58433 	DUK_ASSERT(obj != NULL);
58434 	DUK_ASSERT(key != NULL);
58435 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(obj) <= DUK_HOBJECT_GET_ESIZE(obj));
58436 
58437 #if defined(DUK_USE_ASSERTIONS)
58438 	/* key must not already exist in entry part */
58439 	{
58440 		duk_uint_fast32_t i;
58441 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
58442 			DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != key);
58443 		}
58444 	}
58445 #endif
58446 
58447 	if (DUK_HOBJECT_GET_ENEXT(obj) >= DUK_HOBJECT_GET_ESIZE(obj)) {
58448 		/* only need to guarantee 1 more slot, but allocation growth is in chunks */
58449 		DUK_DDD(DUK_DDDPRINT("entry part full, allocate space for one more entry"));
58450 		duk__grow_props_for_new_entry_item(thr, obj);
58451 	}
58452 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(obj) < DUK_HOBJECT_GET_ESIZE(obj));
58453 	idx = DUK_HOBJECT_POSTINC_ENEXT(obj);
58454 
58455 	/* previous value is assumed to be garbage, so don't touch it */
58456 	DUK_HOBJECT_E_SET_KEY(thr->heap, obj, idx, key);
58457 	DUK_HSTRING_INCREF(thr, key);
58458 
58459 #if defined(DUK_USE_HOBJECT_HASH_PART)
58460 	if (DUK_UNLIKELY(DUK_HOBJECT_GET_HSIZE(obj) > 0)) {
58461 		duk_uint32_t n, mask;
58462 		duk_uint32_t i, step;
58463 		duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
58464 
58465 		n = DUK_HOBJECT_GET_HSIZE(obj);
58466 		mask = n - 1;
58467 		i = DUK_HSTRING_GET_HASH(key) & mask;
58468 		step = 1;  /* Cache friendly but clustering prone. */
58469 
58470 		for (;;) {
58471 			duk_uint32_t t = h_base[i];
58472 			if (t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED) {
58473 				DUK_DDD(DUK_DDDPRINT("duk__hobject_alloc_entry_checked() inserted key into hash part, %ld -> %ld",
58474 				                     (long) i, (long) idx));
58475 				DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
58476 				DUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));
58477 				DUK_ASSERT_DISABLE(idx >= 0);
58478 				DUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));
58479 				h_base[i] = idx;
58480 				break;
58481 			}
58482 			DUK_DDD(DUK_DDDPRINT("duk__hobject_alloc_entry_checked() miss %ld", (long) i));
58483 			i = (i + step) & mask;
58484 
58485 			/* Guaranteed to finish (hash is larger than #props). */
58486 		}
58487 	}
58488 #endif  /* DUK_USE_HOBJECT_HASH_PART */
58489 
58490 	/* Note: we could return the hash index here too, but it's not
58491 	 * needed right now.
58492 	 */
58493 
58494 	DUK_ASSERT_DISABLE(idx >= 0);
58495 	DUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));
58496 	DUK_ASSERT(idx < DUK_HOBJECT_GET_ENEXT(obj));
58497 	return (duk_int_t) idx;
58498 }
58499 
58500 /*
58501  *  Object internal value
58502  *
58503  *  Returned value is guaranteed to be reachable / incref'd, caller does not need
58504  *  to incref OR decref.  No proxies or accessors are invoked, no prototype walk.
58505  */
58506 
58507 DUK_INTERNAL duk_tval *duk_hobject_get_internal_value_tval_ptr(duk_heap *heap, duk_hobject *obj) {
58508 	return duk_hobject_find_entry_tval_ptr_stridx(heap, obj, DUK_STRIDX_INT_VALUE);
58509 }
58510 
58511 DUK_LOCAL duk_heaphdr *duk_hobject_get_internal_value_heaphdr(duk_heap *heap, duk_hobject *obj) {
58512 	duk_tval *tv;
58513 
58514 	DUK_ASSERT(heap != NULL);
58515 	DUK_ASSERT(obj != NULL);
58516 
58517 	tv = duk_hobject_get_internal_value_tval_ptr(heap, obj);
58518 	if (tv != NULL) {
58519 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
58520 		DUK_ASSERT(h != NULL);
58521 		return h;
58522 	}
58523 
58524 	return NULL;
58525 }
58526 
58527 DUK_INTERNAL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj) {
58528 	duk_hstring *h;
58529 
58530 	h = (duk_hstring *) duk_hobject_get_internal_value_heaphdr(heap, obj);
58531 	if (h != NULL) {
58532 		DUK_ASSERT(DUK_HEAPHDR_IS_STRING((duk_heaphdr *) h));
58533 	}
58534 	return h;
58535 }
58536 
58537 DUK_LOCAL duk_hobject *duk__hobject_get_entry_object_stridx(duk_heap *heap, duk_hobject *obj, duk_small_uint_t stridx) {
58538 	duk_tval *tv;
58539 	duk_hobject *h;
58540 
58541 	tv = duk_hobject_find_entry_tval_ptr_stridx(heap, obj, stridx);
58542 	if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
58543 		h = DUK_TVAL_GET_OBJECT(tv);
58544 		DUK_ASSERT(h != NULL);
58545 		return h;
58546 	}
58547 	return NULL;
58548 }
58549 
58550 DUK_INTERNAL duk_harray *duk_hobject_get_formals(duk_hthread *thr, duk_hobject *obj) {
58551 	duk_harray *h;
58552 
58553 	h = (duk_harray *) duk__hobject_get_entry_object_stridx(thr->heap, obj, DUK_STRIDX_INT_FORMALS);
58554 	if (h != NULL) {
58555 		DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) h));
58556 		DUK_ASSERT(h->length <= DUK_HOBJECT_GET_ASIZE((duk_hobject *) h));
58557 	}
58558 	return h;
58559 }
58560 
58561 DUK_INTERNAL duk_hobject *duk_hobject_get_varmap(duk_hthread *thr, duk_hobject *obj) {
58562 	duk_hobject *h;
58563 
58564 	h = duk__hobject_get_entry_object_stridx(thr->heap, obj, DUK_STRIDX_INT_VARMAP);
58565 	return h;
58566 }
58567 
58568 /*
58569  *  Arguments handling helpers (argument map mainly).
58570  *
58571  *  An arguments object has exotic behavior for some numeric indices.
58572  *  Accesses may translate to identifier operations which may have
58573  *  arbitrary side effects (potentially invalidating any duk_tval
58574  *  pointers).
58575  */
58576 
58577 /* Lookup 'key' from arguments internal 'map', perform a variable lookup
58578  * if mapped, and leave the result on top of stack (and return non-zero).
58579  * Used in E5 Section 10.6 algorithms [[Get]] and [[GetOwnProperty]].
58580  */
58581 DUK_LOCAL
58582 duk_bool_t duk__lookup_arguments_map(duk_hthread *thr,
58583                                      duk_hobject *obj,
58584                                      duk_hstring *key,
58585                                      duk_propdesc *temp_desc,
58586                                      duk_hobject **out_map,
58587                                      duk_hobject **out_varenv) {
58588 	duk_hobject *map;
58589 	duk_hobject *varenv;
58590 	duk_bool_t rc;
58591 
58592 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
58593 
58594 	DUK_DDD(DUK_DDDPRINT("arguments map lookup: thr=%p, obj=%p, key=%p, temp_desc=%p "
58595 	                     "(obj -> %!O, key -> %!O)",
58596 	                     (void *) thr, (void *) obj, (void *) key, (void *) temp_desc,
58597 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
58598 
58599 	if (!duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
58600 		DUK_DDD(DUK_DDDPRINT("-> no 'map'"));
58601 		return 0;
58602 	}
58603 
58604 	map = duk_require_hobject(thr, -1);
58605 	DUK_ASSERT(map != NULL);
58606 	duk_pop_unsafe(thr);  /* map is reachable through obj */
58607 
58608 	if (!duk_hobject_get_own_propdesc(thr, map, key, temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
58609 		DUK_DDD(DUK_DDDPRINT("-> 'map' exists, but key not in map"));
58610 		return 0;
58611 	}
58612 
58613 	/* [... varname] */
58614 	DUK_DDD(DUK_DDDPRINT("-> 'map' exists, and contains key, key is mapped to argument/variable binding %!T",
58615 	                     (duk_tval *) duk_get_tval(thr, -1)));
58616 	DUK_ASSERT(duk_is_string(thr, -1));  /* guaranteed when building arguments */
58617 
58618 	/* get varenv for varname (callee's declarative lexical environment) */
58619 	rc = duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_VARENV(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE);
58620 	DUK_UNREF(rc);
58621 	DUK_ASSERT(rc != 0);  /* arguments MUST have an initialized lexical environment reference */
58622 	varenv = duk_require_hobject(thr, -1);
58623 	DUK_ASSERT(varenv != NULL);
58624 	duk_pop_unsafe(thr);  /* varenv remains reachable through 'obj' */
58625 
58626 	DUK_DDD(DUK_DDDPRINT("arguments varenv is: %!dO", (duk_heaphdr *) varenv));
58627 
58628 	/* success: leave varname in stack */
58629 	*out_map = map;
58630 	*out_varenv = varenv;
58631 	return 1;  /* [... varname] */
58632 }
58633 
58634 /* Lookup 'key' from arguments internal 'map', and leave replacement value
58635  * on stack top if mapped (and return non-zero).
58636  * Used in E5 Section 10.6 algorithm for [[GetOwnProperty]] (used by [[Get]]).
58637  */
58638 DUK_LOCAL duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
58639 	duk_hobject *map;
58640 	duk_hobject *varenv;
58641 	duk_hstring *varname;
58642 
58643 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
58644 
58645 	if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
58646 		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic get behavior"));
58647 		return 0;
58648 	}
58649 
58650 	/* [... varname] */
58651 
58652 	varname = duk_require_hstring(thr, -1);
58653 	DUK_ASSERT(varname != NULL);
58654 	duk_pop_unsafe(thr);  /* varname is still reachable */
58655 
58656 	DUK_DDD(DUK_DDDPRINT("arguments object automatic getvar for a bound variable; "
58657 	                     "key=%!O, varname=%!O",
58658 	                     (duk_heaphdr *) key,
58659 	                     (duk_heaphdr *) varname));
58660 
58661 	(void) duk_js_getvar_envrec(thr, varenv, varname, 1 /*throw*/);
58662 
58663 	/* [... value this_binding] */
58664 
58665 	duk_pop_unsafe(thr);
58666 
58667 	/* leave result on stack top */
58668 	return 1;
58669 }
58670 
58671 /* Lookup 'key' from arguments internal 'map', perform a variable write if mapped.
58672  * Used in E5 Section 10.6 algorithm for [[DefineOwnProperty]] (used by [[Put]]).
58673  * Assumes stack top contains 'put' value (which is NOT popped).
58674  */
58675 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) {
58676 	duk_hobject *map;
58677 	duk_hobject *varenv;
58678 	duk_hstring *varname;
58679 
58680 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
58681 
58682 	if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
58683 		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic put behavior"));
58684 		return;
58685 	}
58686 
58687 	/* [... put_value varname] */
58688 
58689 	varname = duk_require_hstring(thr, -1);
58690 	DUK_ASSERT(varname != NULL);
58691 	duk_pop_unsafe(thr);  /* varname is still reachable */
58692 
58693 	DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
58694 	                     "key=%!O, varname=%!O, value=%!T",
58695 	                     (duk_heaphdr *) key,
58696 	                     (duk_heaphdr *) varname,
58697 	                     (duk_tval *) duk_require_tval(thr, -1)));
58698 
58699 	/* [... put_value] */
58700 
58701 	/*
58702 	 *  Note: although arguments object variable mappings are only established
58703 	 *  for non-strict functions (and a call to a non-strict function created
58704 	 *  the arguments object in question), an inner strict function may be doing
58705 	 *  the actual property write.  Hence the throw_flag applied here comes from
58706 	 *  the property write call.
58707 	 */
58708 
58709 	duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(thr, -1), throw_flag);
58710 
58711 	/* [... put_value] */
58712 }
58713 
58714 /* Lookup 'key' from arguments internal 'map', delete mapping if found.
58715  * Used in E5 Section 10.6 algorithm for [[Delete]].  Note that the
58716  * variable/argument itself (where the map points) is not deleted.
58717  */
58718 DUK_LOCAL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
58719 	duk_hobject *map;
58720 
58721 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
58722 
58723 	if (!duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
58724 		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic delete behavior"));
58725 		return;
58726 	}
58727 
58728 	map = duk_require_hobject(thr, -1);
58729 	DUK_ASSERT(map != NULL);
58730 	duk_pop_unsafe(thr);  /* map is reachable through obj */
58731 
58732 	DUK_DDD(DUK_DDDPRINT("-> have 'map', delete key %!O from map (if exists)); ignore result",
58733 	                     (duk_heaphdr *) key));
58734 
58735 	/* Note: no recursion issue, we can trust 'map' to behave */
58736 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(map));
58737 	DUK_DDD(DUK_DDDPRINT("map before deletion: %!O", (duk_heaphdr *) map));
58738 	(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
58739 	DUK_DDD(DUK_DDDPRINT("map after deletion: %!O", (duk_heaphdr *) map));
58740 }
58741 
58742 /*
58743  *  ECMAScript compliant [[GetOwnProperty]](P), for internal use only.
58744  *
58745  *  If property is found:
58746  *    - Fills descriptor fields to 'out_desc'
58747  *    - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
58748  *      property onto the stack ('undefined' for accessor properties).
58749  *    - Returns non-zero
58750  *
58751  *  If property is not found:
58752  *    - 'out_desc' is left in untouched state (possibly garbage)
58753  *    - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
58754  *      set)
58755  *    - Returns zero
58756  *
58757  *  Notes:
58758  *
58759  *    - Getting a property descriptor may cause an allocation (and hence
58760  *      GC) to take place, hence reachability and refcount of all related
58761  *      values matter.  Reallocation of value stack, properties, etc may
58762  *      invalidate many duk_tval pointers (concretely, those which reside
58763  *      in memory areas subject to reallocation).  However, heap object
58764  *      pointers are never affected (heap objects have stable pointers).
58765  *
58766  *    - The value of a plain property is always reachable and has a non-zero
58767  *      reference count.
58768  *
58769  *    - The value of a virtual property is not necessarily reachable from
58770  *      elsewhere and may have a refcount of zero.  Hence we push it onto
58771  *      the valstack for the caller, which ensures it remains reachable
58772  *      while it is needed.
58773  *
58774  *    - There are no virtual accessor properties.  Hence, all getters and
58775  *      setters are always related to concretely stored properties, which
58776  *      ensures that the get/set functions in the resulting descriptor are
58777  *      reachable and have non-zero refcounts.  Should there be virtual
58778  *      accessor properties later, this would need to change.
58779  */
58780 
58781 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) {
58782 	duk_tval *tv;
58783 
58784 	DUK_DDD(DUK_DDDPRINT("duk_hobject_get_own_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
58785 	                     "arr_idx=%ld (obj -> %!O, key -> %!O)",
58786 	                     (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
58787 	                     (long) flags, (long) arr_idx,
58788 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
58789 
58790 	DUK_ASSERT(thr != NULL);
58791 	DUK_ASSERT(thr->heap != NULL);
58792 	DUK_ASSERT(obj != NULL);
58793 	DUK_ASSERT(key != NULL);
58794 	DUK_ASSERT(out_desc != NULL);
58795 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
58796 
58797 	DUK_STATS_INC(thr->heap, stats_getownpropdesc_count);
58798 
58799 	/* Each code path returning 1 (= found) must fill in all the output
58800 	 * descriptor fields.  We don't do it beforehand because it'd be
58801 	 * unnecessary work if the property isn't found and would happen
58802 	 * multiple times for an inheritance chain.
58803 	 */
58804 	DUK_ASSERT_SET_GARBAGE(out_desc, sizeof(*out_desc));
58805 #if 0
58806 	out_desc->flags = 0;
58807 	out_desc->get = NULL;
58808 	out_desc->set = NULL;
58809 	out_desc->e_idx = -1;
58810 	out_desc->h_idx = -1;
58811 	out_desc->a_idx = -1;
58812 #endif
58813 
58814 	/*
58815 	 *  Try entries part first because it's the common case.
58816 	 *
58817 	 *  Array part lookups are usually handled by the array fast path, and
58818 	 *  are not usually inherited.  Array and entry parts never contain the
58819 	 *  same keys so the entry part vs. array part order doesn't matter.
58820 	 */
58821 
58822 	if (duk_hobject_find_entry(thr->heap, obj, key, &out_desc->e_idx, &out_desc->h_idx)) {
58823 		duk_int_t e_idx = out_desc->e_idx;
58824 		DUK_ASSERT(out_desc->e_idx >= 0);
58825 		out_desc->a_idx = -1;
58826 		out_desc->flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, e_idx);
58827 		out_desc->get = NULL;
58828 		out_desc->set = NULL;
58829 		if (DUK_UNLIKELY(out_desc->flags & DUK_PROPDESC_FLAG_ACCESSOR)) {
58830 			DUK_DDD(DUK_DDDPRINT("-> found accessor property in entry part"));
58831 			out_desc->get = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, e_idx);
58832 			out_desc->set = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, e_idx);
58833 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
58834 				/* a dummy undefined value is pushed to make valstack
58835 				 * behavior uniform for caller
58836 				 */
58837 				duk_push_undefined(thr);
58838 			}
58839 		} else {
58840 			DUK_DDD(DUK_DDDPRINT("-> found plain property in entry part"));
58841 			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
58842 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
58843 				duk_push_tval(thr, tv);
58844 			}
58845 		}
58846 		goto prop_found;
58847 	}
58848 
58849 	/*
58850 	 *  Try array part.
58851 	 */
58852 
58853 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj) && arr_idx != DUK__NO_ARRAY_INDEX) {
58854 		if (arr_idx < DUK_HOBJECT_GET_ASIZE(obj)) {
58855 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
58856 			if (!DUK_TVAL_IS_UNUSED(tv)) {
58857 				DUK_DDD(DUK_DDDPRINT("-> found in array part"));
58858 				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
58859 					duk_push_tval(thr, tv);
58860 				}
58861 				/* implicit attributes */
58862 				out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
58863 				                  DUK_PROPDESC_FLAG_CONFIGURABLE |
58864 				                  DUK_PROPDESC_FLAG_ENUMERABLE;
58865 				out_desc->get = NULL;
58866 				out_desc->set = NULL;
58867 				out_desc->e_idx = -1;
58868 				out_desc->h_idx = -1;
58869 				out_desc->a_idx = (duk_int_t) arr_idx;  /* XXX: limit 2G due to being signed */
58870 				goto prop_found;
58871 			}
58872 		}
58873 	}
58874 
58875 	DUK_DDD(DUK_DDDPRINT("-> not found as a concrete property"));
58876 
58877 	/*
58878 	 *  Not found as a concrete property, check for virtual properties.
58879 	 */
58880 
58881 	if (!DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(obj)) {
58882 		/* Quick skip. */
58883 		goto prop_not_found;
58884 	}
58885 
58886 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
58887 		duk_harray *a;
58888 
58889 		DUK_DDD(DUK_DDDPRINT("array object exotic property get for key: %!O, arr_idx: %ld",
58890 		                     (duk_heaphdr *) key, (long) arr_idx));
58891 
58892 		a = (duk_harray *) obj;
58893 		DUK_HARRAY_ASSERT_VALID(a);
58894 
58895 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
58896 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
58897 
58898 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
58899 				duk_push_uint(thr, (duk_uint_t) a->length);
58900 			}
58901 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
58902 			if (DUK_HARRAY_LENGTH_WRITABLE(a)) {
58903 				out_desc->flags |= DUK_PROPDESC_FLAG_WRITABLE;
58904 			}
58905 			out_desc->get = NULL;
58906 			out_desc->set = NULL;
58907 			out_desc->e_idx = -1;
58908 			out_desc->h_idx = -1;
58909 			out_desc->a_idx = -1;
58910 
58911 			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
58912 			goto prop_found_noexotic;  /* cannot be arguments exotic */
58913 		}
58914 	} else if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj)) {
58915 		DUK_DDD(DUK_DDDPRINT("string object exotic property get for key: %!O, arr_idx: %ld",
58916 		                     (duk_heaphdr *) key, (long) arr_idx));
58917 
58918 		/* XXX: charlen; avoid multiple lookups? */
58919 
58920 		if (arr_idx != DUK__NO_ARRAY_INDEX) {
58921 			duk_hstring *h_val;
58922 
58923 			DUK_DDD(DUK_DDDPRINT("array index exists"));
58924 
58925 			h_val = duk_hobject_get_internal_value_string(thr->heap, obj);
58926 			DUK_ASSERT(h_val);
58927 			if (arr_idx < DUK_HSTRING_GET_CHARLEN(h_val)) {
58928 				DUK_DDD(DUK_DDDPRINT("-> found, array index inside string"));
58929 				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
58930 					duk_push_hstring(thr, h_val);
58931 					duk_substring(thr, -1, arr_idx, arr_idx + 1);  /* [str] -> [substr] */
58932 				}
58933 				out_desc->flags = DUK_PROPDESC_FLAG_ENUMERABLE |  /* E5 Section 15.5.5.2 */
58934 				                  DUK_PROPDESC_FLAG_VIRTUAL;
58935 				out_desc->get = NULL;
58936 				out_desc->set = NULL;
58937 				out_desc->e_idx = -1;
58938 				out_desc->h_idx = -1;
58939 				out_desc->a_idx = -1;
58940 
58941 				DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
58942 				goto prop_found_noexotic;  /* cannot be arguments exotic */
58943 			} else {
58944 				/* index is above internal string length -> property is fully normal */
58945 				DUK_DDD(DUK_DDDPRINT("array index outside string -> normal property"));
58946 			}
58947 		} else if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
58948 			duk_hstring *h_val;
58949 
58950 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
58951 
58952 			h_val = duk_hobject_get_internal_value_string(thr->heap, obj);
58953 			DUK_ASSERT(h_val != NULL);
58954 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
58955 				duk_push_uint(thr, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h_val));
58956 			}
58957 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;  /* E5 Section 15.5.5.1 */
58958 			out_desc->get = NULL;
58959 			out_desc->set = NULL;
58960 			out_desc->e_idx = -1;
58961 			out_desc->h_idx = -1;
58962 			out_desc->a_idx = -1;
58963 
58964 			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
58965 			goto prop_found_noexotic;  /* cannot be arguments exotic */
58966 		}
58967 	}
58968 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
58969 	else if (DUK_HOBJECT_IS_BUFOBJ(obj)) {
58970 		duk_hbufobj *h_bufobj;
58971 		duk_uint_t byte_off;
58972 		duk_small_uint_t elem_size;
58973 
58974 		h_bufobj = (duk_hbufobj *) obj;
58975 		DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
58976 		DUK_DDD(DUK_DDDPRINT("bufobj property get for key: %!O, arr_idx: %ld",
58977 		                     (duk_heaphdr *) key, (long) arr_idx));
58978 
58979 		if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
58980 			DUK_DDD(DUK_DDDPRINT("array index exists"));
58981 
58982 			/* Careful with wrapping: arr_idx upshift may easily wrap, whereas
58983 			 * length downshift won't.
58984 			 */
58985 			if (arr_idx < (h_bufobj->length >> h_bufobj->shift)) {
58986 				byte_off = arr_idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
58987 				elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
58988 				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
58989 					duk_uint8_t *data;
58990 
58991 					if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
58992 						data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
58993 						duk_hbufobj_push_validated_read(thr, h_bufobj, data, elem_size);
58994 					} else {
58995 						DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (read zero)"));
58996 						duk_push_uint(thr, 0);
58997 					}
58998 				}
58999 				out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
59000 				                  DUK_PROPDESC_FLAG_VIRTUAL;
59001 				if (DUK_HOBJECT_GET_CLASS_NUMBER(obj) != DUK_HOBJECT_CLASS_ARRAYBUFFER) {
59002 					/* ArrayBuffer indices are non-standard and are
59003 					 * non-enumerable to avoid their serialization.
59004 					 */
59005 					out_desc->flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
59006 				}
59007 				out_desc->get = NULL;
59008 				out_desc->set = NULL;
59009 				out_desc->e_idx = -1;
59010 				out_desc->h_idx = -1;
59011 				out_desc->a_idx = -1;
59012 
59013 				DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
59014 				goto prop_found_noexotic;  /* cannot be e.g. arguments exotic, since exotic 'traits' are mutually exclusive */
59015 			} else {
59016 				/* index is above internal buffer length -> property is fully normal */
59017 				DUK_DDD(DUK_DDDPRINT("array index outside buffer -> normal property"));
59018 			}
59019 		} else if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
59020 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
59021 
59022 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
59023 				/* Length in elements: take into account shift, but
59024 				 * intentionally don't check the underlying buffer here.
59025 				 */
59026 				duk_push_uint(thr, h_bufobj->length >> h_bufobj->shift);
59027 			}
59028 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
59029 			out_desc->get = NULL;
59030 			out_desc->set = NULL;
59031 			out_desc->e_idx = -1;
59032 			out_desc->h_idx = -1;
59033 			out_desc->a_idx = -1;
59034 
59035 			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
59036 			goto prop_found_noexotic;  /* cannot be arguments exotic */
59037 		}
59038 	}
59039 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
59040 
59041 	/* Array properties have exotic behavior but they are concrete,
59042 	 * so no special handling here.
59043 	 *
59044 	 * Arguments exotic behavior (E5 Section 10.6, [[GetOwnProperty]]
59045 	 * is only relevant as a post-check implemented below; hence no
59046 	 * check here.
59047 	 */
59048 
59049 	/*
59050 	 *  Not found as concrete or virtual.
59051 	 */
59052 
59053  prop_not_found:
59054 	DUK_DDD(DUK_DDDPRINT("-> not found (virtual, entry part, or array part)"));
59055 	DUK_STATS_INC(thr->heap, stats_getownpropdesc_miss);
59056 	return 0;
59057 
59058 	/*
59059 	 *  Found.
59060 	 *
59061 	 *  Arguments object has exotic post-processing, see E5 Section 10.6,
59062 	 *  description of [[GetOwnProperty]] variant for arguments.
59063 	 */
59064 
59065  prop_found:
59066 	DUK_DDD(DUK_DDDPRINT("-> property found, checking for arguments exotic post-behavior"));
59067 
59068 	/* Notes:
59069 	 *  - Only numbered indices are relevant, so arr_idx fast reject is good
59070 	 *    (this is valid unless there are more than 4**32-1 arguments).
59071 	 *  - Since variable lookup has no side effects, this can be skipped if
59072 	 *    DUK_GETDESC_FLAG_PUSH_VALUE is not set.
59073 	 */
59074 
59075 	if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&
59076 	                 arr_idx != DUK__NO_ARRAY_INDEX &&
59077 	                 (flags & DUK_GETDESC_FLAG_PUSH_VALUE))) {
59078 		duk_propdesc temp_desc;
59079 
59080 		/* Magically bound variable cannot be an accessor.  However,
59081 		 * there may be an accessor property (or a plain property) in
59082 		 * place with magic behavior removed.  This happens e.g. when
59083 		 * a magic property is redefined with defineProperty().
59084 		 * Cannot assert for "not accessor" here.
59085 		 */
59086 
59087 		/* replaces top of stack with new value if necessary */
59088 		DUK_ASSERT((flags & DUK_GETDESC_FLAG_PUSH_VALUE) != 0);
59089 
59090 		/* This can perform a variable lookup but only into a declarative
59091 		 * environment which has no side effects.
59092 		 */
59093 		if (duk__check_arguments_map_for_get(thr, obj, key, &temp_desc)) {
59094 			DUK_DDD(DUK_DDDPRINT("-> arguments exotic behavior overrides result: %!T -> %!T",
59095 			                     (duk_tval *) duk_get_tval(thr, -2),
59096 			                     (duk_tval *) duk_get_tval(thr, -1)));
59097 			/* [... old_result result] -> [... result] */
59098 			duk_remove_m2(thr);
59099 		}
59100 	}
59101 
59102  prop_found_noexotic:
59103 	DUK_STATS_INC(thr->heap, stats_getownpropdesc_hit);
59104 	return 1;
59105 }
59106 
59107 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) {
59108 	DUK_ASSERT(thr != NULL);
59109 	DUK_ASSERT(obj != NULL);
59110 	DUK_ASSERT(key != NULL);
59111 	DUK_ASSERT(out_desc != NULL);
59112 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
59113 
59114 	return duk__get_own_propdesc_raw(thr, obj, key, DUK_HSTRING_GET_ARRIDX_SLOW(key), out_desc, flags);
59115 }
59116 
59117 /*
59118  *  ECMAScript compliant [[GetProperty]](P), for internal use only.
59119  *
59120  *  If property is found:
59121  *    - Fills descriptor fields to 'out_desc'
59122  *    - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
59123  *      property onto the stack ('undefined' for accessor properties).
59124  *    - Returns non-zero
59125  *
59126  *  If property is not found:
59127  *    - 'out_desc' is left in untouched state (possibly garbage)
59128  *    - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
59129  *      set)
59130  *    - Returns zero
59131  *
59132  *  May cause arbitrary side effects and invalidate (most) duk_tval
59133  *  pointers.
59134  */
59135 
59136 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) {
59137 	duk_hobject *curr;
59138 	duk_uint32_t arr_idx;
59139 	duk_uint_t sanity;
59140 
59141 	DUK_ASSERT(thr != NULL);
59142 	DUK_ASSERT(thr->heap != NULL);
59143 	DUK_ASSERT(obj != NULL);
59144 	DUK_ASSERT(key != NULL);
59145 	DUK_ASSERT(out_desc != NULL);
59146 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
59147 
59148 	DUK_STATS_INC(thr->heap, stats_getpropdesc_count);
59149 
59150 	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
59151 
59152 	DUK_DDD(DUK_DDDPRINT("duk__get_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
59153 	                     "arr_idx=%ld (obj -> %!O, key -> %!O)",
59154 	                     (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
59155 	                     (long) flags, (long) arr_idx,
59156 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
59157 
59158 	curr = obj;
59159 	DUK_ASSERT(curr != NULL);
59160 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
59161 	do {
59162 		if (duk__get_own_propdesc_raw(thr, curr, key, arr_idx, out_desc, flags)) {
59163 			/* stack contains value (if requested), 'out_desc' is set */
59164 			DUK_STATS_INC(thr->heap, stats_getpropdesc_hit);
59165 			return 1;
59166 		}
59167 
59168 		/* not found in 'curr', next in prototype chain; impose max depth */
59169 		if (DUK_UNLIKELY(sanity-- == 0)) {
59170 			if (flags & DUK_GETDESC_FLAG_IGNORE_PROTOLOOP) {
59171 				/* treat like property not found */
59172 				break;
59173 			} else {
59174 				DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
59175 				DUK_WO_NORETURN(return 0;);
59176 			}
59177 		}
59178 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
59179 	} while (curr != NULL);
59180 
59181 	/* out_desc is left untouched (possibly garbage), caller must use return
59182 	 * value to determine whether out_desc can be looked up
59183 	 */
59184 
59185 	DUK_STATS_INC(thr->heap, stats_getpropdesc_miss);
59186 	return 0;
59187 }
59188 
59189 /*
59190  *  Shallow fast path checks for accessing array elements with numeric
59191  *  indices.  The goal is to try to avoid coercing an array index to an
59192  *  (interned) string for the most common lookups, in particular, for
59193  *  standard Array objects.
59194  *
59195  *  Interning is avoided but only for a very narrow set of cases:
59196  *    - Object has array part, index is within array allocation, and
59197  *      value is not unused (= key exists)
59198  *    - Object has no interfering exotic behavior (e.g. arguments or
59199  *      string object exotic behaviors interfere, array exotic
59200  *      behavior does not).
59201  *
59202  *  Current shortcoming: if key does not exist (even if it is within
59203  *  the array allocation range) a slow path lookup with interning is
59204  *  always required.  This can probably be fixed so that there is a
59205  *  quick fast path for non-existent elements as well, at least for
59206  *  standard Array objects.
59207  */
59208 
59209 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
59210 DUK_LOCAL duk_tval *duk__getprop_shallow_fastpath_array_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) {
59211 	duk_tval *tv;
59212 	duk_uint32_t idx;
59213 
59214 	DUK_UNREF(thr);
59215 
59216 	if (!(DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
59217 	     !DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&
59218 	     !DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj) &&
59219 	     !DUK_HOBJECT_IS_BUFOBJ(obj) &&
59220 	     !DUK_HOBJECT_IS_PROXY(obj))) {
59221 		/* Must have array part and no conflicting exotic behaviors.
59222 		 * Doesn't need to have array special behavior, e.g. Arguments
59223 		 * object has array part.
59224 		 */
59225 		return NULL;
59226 	}
59227 
59228 	/* Arrays never have other exotic behaviors. */
59229 
59230 	DUK_DDD(DUK_DDDPRINT("fast path attempt (no exotic string/arguments/buffer "
59231 	                     "behavior, object has array part)"));
59232 
59233 #if defined(DUK_USE_FASTINT)
59234 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
59235 		idx = duk__tval_fastint_to_arr_idx(tv_key);
59236 	} else
59237 #endif
59238 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
59239 		idx = duk__tval_number_to_arr_idx(tv_key);
59240 	} else {
59241 		DUK_DDD(DUK_DDDPRINT("key is not a number"));
59242 		return NULL;
59243 	}
59244 
59245 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
59246 	 * is 0xffffffffUL.  We don't need to check for that explicitly
59247 	 * because 0xffffffffUL will never be inside object 'a_size'.
59248 	 */
59249 
59250 	if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
59251 		DUK_DDD(DUK_DDDPRINT("key is not an array index or outside array part"));
59252 		return NULL;
59253 	}
59254 	DUK_ASSERT(idx != 0xffffffffUL);
59255 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
59256 
59257 	/* XXX: for array instances we could take a shortcut here and assume
59258 	 * Array.prototype doesn't contain an array index property.
59259 	 */
59260 
59261 	DUK_DDD(DUK_DDDPRINT("key is a valid array index and inside array part"));
59262 	tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
59263 	if (!DUK_TVAL_IS_UNUSED(tv)) {
59264 		DUK_DDD(DUK_DDDPRINT("-> fast path successful"));
59265 		return tv;
59266 	}
59267 
59268 	DUK_DDD(DUK_DDDPRINT("fast path attempt failed, fall back to slow path"));
59269 	return NULL;
59270 }
59271 
59272 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) {
59273 	duk_tval *tv;
59274 	duk_harray *a;
59275 	duk_uint32_t idx;
59276 	duk_uint32_t old_len, new_len;
59277 
59278 	if (!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj) &&
59279 	      DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
59280 	      DUK_HOBJECT_HAS_EXTENSIBLE(obj))) {
59281 		return 0;
59282 	}
59283 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));  /* caller ensures */
59284 
59285 	a = (duk_harray *) obj;
59286 	DUK_HARRAY_ASSERT_VALID(a);
59287 
59288 #if defined(DUK_USE_FASTINT)
59289 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
59290 		idx = duk__tval_fastint_to_arr_idx(tv_key);
59291 	} else
59292 #endif
59293 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
59294 		idx = duk__tval_number_to_arr_idx(tv_key);
59295 	} else {
59296 		DUK_DDD(DUK_DDDPRINT("key is not a number"));
59297 		return 0;
59298 	}
59299 
59300 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
59301 	 * is 0xffffffffUL.  We don't need to check for that explicitly
59302 	 * because 0xffffffffUL will never be inside object 'a_size'.
59303 	 */
59304 
59305 	if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {  /* for resizing of array part, use slow path */
59306 		return 0;
59307 	}
59308 	DUK_ASSERT(idx != 0xffffffffUL);
59309 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
59310 
59311 	old_len = a->length;
59312 
59313 	if (idx >= old_len) {
59314 		DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
59315 		                     "(arr_idx=%ld, old_len=%ld)",
59316 		                     (long) idx, (long) old_len));
59317 		if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
59318 			/* The correct behavior here is either a silent error
59319 			 * or a TypeError, depending on strictness.  Fall back
59320 			 * to the slow path to handle the situation.
59321 			 */
59322 			return 0;
59323 		}
59324 		new_len = idx + 1;
59325 
59326 		((duk_harray *) obj)->length = new_len;
59327 	}
59328 
59329 	tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
59330 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects */
59331 
59332 	DUK_DDD(DUK_DDDPRINT("array fast path success for index %ld", (long) idx));
59333 	return 1;
59334 }
59335 #endif  /* DUK_USE_ARRAY_PROP_FASTPATH */
59336 
59337 /*
59338  *  Fast path for bufobj getprop/putprop
59339  */
59340 
59341 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
59342 DUK_LOCAL duk_bool_t duk__getprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) {
59343 	duk_uint32_t idx;
59344 	duk_hbufobj *h_bufobj;
59345 	duk_uint_t byte_off;
59346 	duk_small_uint_t elem_size;
59347 	duk_uint8_t *data;
59348 
59349 	if (!DUK_HOBJECT_IS_BUFOBJ(obj)) {
59350 		return 0;
59351 	}
59352 	h_bufobj = (duk_hbufobj *) obj;
59353 	if (!DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
59354 		return 0;
59355 	}
59356 
59357 #if defined(DUK_USE_FASTINT)
59358 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
59359 		idx = duk__tval_fastint_to_arr_idx(tv_key);
59360 	} else
59361 #endif
59362 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
59363 		idx = duk__tval_number_to_arr_idx(tv_key);
59364 	} else {
59365 		return 0;
59366 	}
59367 
59368 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
59369 	 * is 0xffffffffUL.  We don't need to check for that explicitly
59370 	 * because 0xffffffffUL will never be inside bufobj length.
59371 	 */
59372 
59373 	/* Careful with wrapping (left shifting idx would be unsafe). */
59374 	if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
59375 		return 0;
59376 	}
59377 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
59378 
59379 	byte_off = idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
59380 	elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
59381 
59382 	if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
59383 		data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
59384 		duk_hbufobj_push_validated_read(thr, h_bufobj, data, elem_size);
59385 	} else {
59386 		DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (read zero)"));
59387 		duk_push_uint(thr, 0);
59388 	}
59389 
59390 	return 1;
59391 }
59392 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
59393 
59394 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
59395 DUK_LOCAL duk_bool_t duk__putprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key, duk_tval *tv_val) {
59396 	duk_uint32_t idx;
59397 	duk_hbufobj *h_bufobj;
59398 	duk_uint_t byte_off;
59399 	duk_small_uint_t elem_size;
59400 	duk_uint8_t *data;
59401 
59402 	if (!(DUK_HOBJECT_IS_BUFOBJ(obj) &&
59403 	      DUK_TVAL_IS_NUMBER(tv_val))) {
59404 		return 0;
59405 	}
59406 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));  /* caller ensures; rom objects are never bufobjs now */
59407 
59408 	h_bufobj = (duk_hbufobj *) obj;
59409 	if (!DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
59410 		return 0;
59411 	}
59412 
59413 #if defined(DUK_USE_FASTINT)
59414 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
59415 		idx = duk__tval_fastint_to_arr_idx(tv_key);
59416 	} else
59417 #endif
59418 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
59419 		idx = duk__tval_number_to_arr_idx(tv_key);
59420 	} else {
59421 		return 0;
59422 	}
59423 
59424 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
59425 	 * is 0xffffffffUL.  We don't need to check for that explicitly
59426 	 * because 0xffffffffUL will never be inside bufobj length.
59427 	 */
59428 
59429 	/* Careful with wrapping (left shifting idx would be unsafe). */
59430 	if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
59431 		return 0;
59432 	}
59433 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
59434 
59435 	byte_off = idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
59436 	elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
59437 
59438 	/* Value is required to be a number in the fast path so there
59439 	 * are no side effects in write coercion.
59440 	 */
59441 	duk_push_tval(thr, tv_val);
59442 	DUK_ASSERT(duk_is_number(thr, -1));
59443 
59444 	if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
59445 		data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
59446 		duk_hbufobj_validated_write(thr, h_bufobj, data, elem_size);
59447 	} else {
59448 		DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (write skipped)"));
59449 	}
59450 
59451 	duk_pop_unsafe(thr);
59452 	return 1;
59453 }
59454 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
59455 
59456 /*
59457  *  GETPROP: ECMAScript property read.
59458  */
59459 
59460 DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
59461 	duk_tval tv_obj_copy;
59462 	duk_tval tv_key_copy;
59463 	duk_hobject *curr = NULL;
59464 	duk_hstring *key = NULL;
59465 	duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
59466 	duk_propdesc desc;
59467 	duk_uint_t sanity;
59468 
59469 	DUK_DDD(DUK_DDDPRINT("getprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
59470 	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
59471 	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));
59472 
59473 	DUK_ASSERT(thr != NULL);
59474 	DUK_ASSERT(thr->heap != NULL);
59475 	DUK_ASSERT(tv_obj != NULL);
59476 	DUK_ASSERT(tv_key != NULL);
59477 
59478 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
59479 
59480 	DUK_STATS_INC(thr->heap, stats_getprop_all);
59481 
59482 	/*
59483 	 *  Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
59484 	 *  them being invalidated by a valstack resize.
59485 	 *
59486 	 *  XXX: this is now an overkill for many fast paths.  Rework this
59487 	 *  to be faster (although switching to a valstack discipline might
59488 	 *  be a better solution overall).
59489 	 */
59490 
59491 	DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
59492 	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
59493 	tv_obj = &tv_obj_copy;
59494 	tv_key = &tv_key_copy;
59495 
59496 	/*
59497 	 *  Coercion and fast path processing
59498 	 */
59499 
59500 	switch (DUK_TVAL_GET_TAG(tv_obj)) {
59501 	case DUK_TAG_UNDEFINED:
59502 	case DUK_TAG_NULL: {
59503 		/* Note: unconditional throw */
59504 		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
59505 #if defined(DUK_USE_PARANOID_ERRORS)
59506 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
59507 #else
59508 		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot read property %s of %s",
59509 		               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
59510 #endif
59511 		DUK_WO_NORETURN(return 0;);
59512 		break;
59513 	}
59514 
59515 	case DUK_TAG_BOOLEAN: {
59516 		DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
59517 		curr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];
59518 		break;
59519 	}
59520 
59521 	case DUK_TAG_STRING: {
59522 		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
59523 		duk_int_t pop_count;
59524 
59525 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
59526 			/* Symbols (ES2015 or hidden) don't have virtual properties. */
59527 			DUK_DDD(DUK_DDDPRINT("base object is a symbol, start lookup from symbol prototype"));
59528 			curr = thr->builtins[DUK_BIDX_SYMBOL_PROTOTYPE];
59529 			break;
59530 		}
59531 
59532 #if defined(DUK_USE_FASTINT)
59533 		if (DUK_TVAL_IS_FASTINT(tv_key)) {
59534 			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
59535 			DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
59536 			pop_count = 0;
59537 		} else
59538 #endif
59539 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
59540 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
59541 			DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path number; arr_idx %ld", (long) arr_idx));
59542 			pop_count = 0;
59543 		} else {
59544 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59545 			DUK_ASSERT(key != NULL);
59546 			DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
59547 			                     "coercion key is %!T, arr_idx %ld",
59548 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
59549 			pop_count = 1;
59550 		}
59551 
59552 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
59553 		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
59554 			duk_pop_n_unsafe(thr, pop_count);
59555 			duk_push_hstring(thr, h);
59556 			duk_substring(thr, -1, arr_idx, arr_idx + 1);  /* [str] -> [substr] */
59557 
59558 			DUK_STATS_INC(thr->heap, stats_getprop_stringidx);
59559 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is an index inside string length "
59560 			                     "after coercion -> return char)",
59561 			                     (duk_tval *) duk_get_tval(thr, -1)));
59562 			return 1;
59563 		}
59564 
59565 		if (pop_count == 0) {
59566 			/* This is a pretty awkward control flow, but we need to recheck the
59567 			 * key coercion here.
59568 			 */
59569 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59570 			DUK_ASSERT(key != NULL);
59571 			DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
59572 			                     "coercion key is %!T, arr_idx %ld",
59573 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
59574 		}
59575 
59576 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
59577 			duk_pop_unsafe(thr);  /* [key] -> [] */
59578 			duk_push_uint(thr, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h));  /* [] -> [res] */
59579 
59580 			DUK_STATS_INC(thr->heap, stats_getprop_stringlen);
59581 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is 'length' after coercion -> "
59582 			                     "return string length)",
59583 			                     (duk_tval *) duk_get_tval(thr, -1)));
59584 			return 1;
59585 		}
59586 
59587 		DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
59588 		curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
59589 		goto lookup;  /* avoid double coercion */
59590 	}
59591 
59592 	case DUK_TAG_OBJECT: {
59593 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
59594 		duk_tval *tmp;
59595 #endif
59596 
59597 		curr = DUK_TVAL_GET_OBJECT(tv_obj);
59598 		DUK_ASSERT(curr != NULL);
59599 
59600 		/* XXX: array .length fast path (important in e.g. loops)? */
59601 
59602 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
59603 		tmp = duk__getprop_shallow_fastpath_array_tval(thr, curr, tv_key);
59604 		if (tmp) {
59605 			duk_push_tval(thr, tmp);
59606 
59607 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is object, key is a number, array part "
59608 			                     "fast path)",
59609 			                     (duk_tval *) duk_get_tval(thr, -1)));
59610 			DUK_STATS_INC(thr->heap, stats_getprop_arrayidx);
59611 			return 1;
59612 		}
59613 #endif
59614 
59615 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
59616 		if (duk__getprop_fastpath_bufobj_tval(thr, curr, tv_key) != 0) {
59617 			/* Read value pushed on stack. */
59618 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is bufobj, key is a number, bufobj "
59619 			                     "fast path)",
59620 			                     (duk_tval *) duk_get_tval(thr, -1)));
59621 			DUK_STATS_INC(thr->heap, stats_getprop_bufobjidx);
59622 			return 1;
59623 		}
59624 #endif
59625 
59626 #if defined(DUK_USE_ES6_PROXY)
59627 		if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(curr))) {
59628 			duk_hobject *h_target;
59629 
59630 			if (duk__proxy_check_prop(thr, curr, DUK_STRIDX_GET, tv_key, &h_target)) {
59631 				/* -> [ ... trap handler ] */
59632 				DUK_DDD(DUK_DDDPRINT("-> proxy object 'get' for key %!T", (duk_tval *) tv_key));
59633 				DUK_STATS_INC(thr->heap, stats_getprop_proxy);
59634 				duk_push_hobject(thr, h_target);  /* target */
59635 				duk_push_tval(thr, tv_key);       /* P */
59636 				duk_push_tval(thr, tv_obj);       /* Receiver: Proxy object */
59637 				duk_call_method(thr, 3 /*nargs*/);
59638 
59639 				/* Target object must be checked for a conflicting
59640 				 * non-configurable property.
59641 				 */
59642 				arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59643 				DUK_ASSERT(key != NULL);
59644 
59645 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
59646 					duk_tval *tv_hook = duk_require_tval(thr, -3);  /* value from hook */
59647 					duk_tval *tv_targ = duk_require_tval(thr, -1);  /* value from target */
59648 					duk_bool_t datadesc_reject;
59649 					duk_bool_t accdesc_reject;
59650 
59651 					DUK_DDD(DUK_DDDPRINT("proxy 'get': target has matching property %!O, check for "
59652 					                     "conflicting property; tv_hook=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
59653 					                     "desc.get=%p, desc.set=%p",
59654 					                     (duk_heaphdr *) key, (duk_tval *) tv_hook, (duk_tval *) tv_targ,
59655 					                     (unsigned long) desc.flags,
59656 					                     (void *) desc.get, (void *) desc.set));
59657 
59658 					datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
59659 					                  !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
59660 					                  !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) &&
59661 					                  !duk_js_samevalue(tv_hook, tv_targ);
59662 					accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
59663 					                 !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
59664 					                 (desc.get == NULL) &&
59665 					                 !DUK_TVAL_IS_UNDEFINED(tv_hook);
59666 					if (datadesc_reject || accdesc_reject) {
59667 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
59668 						DUK_WO_NORETURN(return 0;);
59669 					}
59670 
59671 					duk_pop_2_unsafe(thr);
59672 				} else {
59673 					duk_pop_unsafe(thr);
59674 				}
59675 				return 1;  /* return value */
59676 			}
59677 
59678 			curr = h_target;  /* resume lookup from target */
59679 			DUK_TVAL_SET_OBJECT(tv_obj, curr);
59680 		}
59681 #endif  /* DUK_USE_ES6_PROXY */
59682 
59683 		if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(curr)) {
59684 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59685 			DUK_ASSERT(key != NULL);
59686 
59687 			DUK_STATS_INC(thr->heap, stats_getprop_arguments);
59688 			if (duk__check_arguments_map_for_get(thr, curr, key, &desc)) {
59689 				DUK_DDD(DUK_DDDPRINT("-> %!T (base is object with arguments exotic behavior, "
59690 				                     "key matches magically bound property -> skip standard "
59691 				                     "Get with replacement value)",
59692 				                     (duk_tval *) duk_get_tval(thr, -1)));
59693 
59694 				/* no need for 'caller' post-check, because 'key' must be an array index */
59695 
59696 				duk_remove_m2(thr);  /* [key result] -> [result] */
59697 				return 1;
59698 			}
59699 
59700 			goto lookup;  /* avoid double coercion */
59701 		}
59702 		break;
59703 	}
59704 
59705 	/* Buffer has virtual properties similar to string, but indexed values
59706 	 * are numbers, not 1-byte buffers/strings which would perform badly.
59707 	 */
59708 	case DUK_TAG_BUFFER: {
59709 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
59710 		duk_int_t pop_count;
59711 
59712 		/*
59713 		 *  Because buffer values are often looped over, a number fast path
59714 		 *  is important.
59715 		 */
59716 
59717 #if defined(DUK_USE_FASTINT)
59718 		if (DUK_TVAL_IS_FASTINT(tv_key)) {
59719 			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
59720 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
59721 			pop_count = 0;
59722 		}
59723 		else
59724 #endif
59725 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
59726 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
59727 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
59728 			pop_count = 0;
59729 		} else {
59730 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59731 			DUK_ASSERT(key != NULL);
59732 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
59733 			                     "coercion key is %!T, arr_idx %ld",
59734 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
59735 			pop_count = 1;
59736 		}
59737 
59738 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
59739 		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
59740 			duk_pop_n_unsafe(thr, pop_count);
59741 			duk_push_uint(thr, ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h))[arr_idx]);
59742 			DUK_STATS_INC(thr->heap, stats_getprop_bufferidx);
59743 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is an index inside buffer length "
59744 			                     "after coercion -> return byte as number)",
59745 			                     (duk_tval *) duk_get_tval(thr, -1)));
59746 			return 1;
59747 		}
59748 
59749 		if (pop_count == 0) {
59750 			/* This is a pretty awkward control flow, but we need to recheck the
59751 			 * key coercion here.
59752 			 */
59753 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59754 			DUK_ASSERT(key != NULL);
59755 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
59756 			                     "coercion key is %!T, arr_idx %ld",
59757 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
59758 		}
59759 
59760 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
59761 			duk_pop_unsafe(thr);  /* [key] -> [] */
59762 			duk_push_uint(thr, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h));  /* [] -> [res] */
59763 			DUK_STATS_INC(thr->heap, stats_getprop_bufferlen);
59764 
59765 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'length' "
59766 			                     "after coercion -> return buffer length)",
59767 			                     (duk_tval *) duk_get_tval(thr, -1)));
59768 			return 1;
59769 		}
59770 
59771 		DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from Uint8Array prototype"));
59772 		curr = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
59773 		goto lookup;  /* avoid double coercion */
59774 	}
59775 
59776 	case DUK_TAG_POINTER: {
59777 		DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
59778 		curr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
59779 		break;
59780 	}
59781 
59782 	case DUK_TAG_LIGHTFUNC: {
59783 		/* Lightfuncs inherit getter .name and .length from %NativeFunctionPrototype%. */
59784 		DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
59785 		curr = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];
59786 		break;
59787 	}
59788 
59789 #if defined(DUK_USE_FASTINT)
59790 	case DUK_TAG_FASTINT:
59791 #endif
59792 	default: {
59793 		/* number */
59794 		DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
59795 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_obj));
59796 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_obj));
59797 		curr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];
59798 		break;
59799 	}
59800 	}
59801 
59802 	/* key coercion (unless already coerced above) */
59803 	DUK_ASSERT(key == NULL);
59804 	arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59805 	DUK_ASSERT(key != NULL);
59806 	/*
59807 	 *  Property lookup
59808 	 */
59809 
59810  lookup:
59811 	/* [key] (coerced) */
59812 	DUK_ASSERT(curr != NULL);
59813 	DUK_ASSERT(key != NULL);
59814 
59815 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
59816 	do {
59817 		if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
59818 			goto next_in_chain;
59819 		}
59820 
59821 		if (desc.get != NULL) {
59822 			/* accessor with defined getter */
59823 			DUK_ASSERT((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0);
59824 
59825 			duk_pop_unsafe(thr);              /* [key undefined] -> [key] */
59826 			duk_push_hobject(thr, desc.get);
59827 			duk_push_tval(thr, tv_obj);       /* note: original, uncoerced base */
59828 #if defined(DUK_USE_NONSTD_GETTER_KEY_ARGUMENT)
59829 			duk_dup_m3(thr);
59830 			duk_call_method(thr, 1);          /* [key getter this key] -> [key retval] */
59831 #else
59832 			duk_call_method(thr, 0);          /* [key getter this] -> [key retval] */
59833 #endif
59834 		} else {
59835 			/* [key value] or [key undefined] */
59836 
59837 			/* data property or accessor without getter */
59838 			DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) ||
59839 			           (desc.get == NULL));
59840 
59841 			/* if accessor without getter, return value is undefined */
59842 			DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) ||
59843 			           duk_is_undefined(thr, -1));
59844 
59845 			/* Note: for an accessor without getter, falling through to
59846 			 * check for "caller" exotic behavior is unnecessary as
59847 			 * "undefined" will never activate the behavior.  But it does
59848 			 * no harm, so we'll do it anyway.
59849 			 */
59850 		}
59851 
59852 		goto found;  /* [key result] */
59853 
59854 	 next_in_chain:
59855 		/* XXX: option to pretend property doesn't exist if sanity limit is
59856 		 * hit might be useful.
59857 		 */
59858 		if (DUK_UNLIKELY(sanity-- == 0)) {
59859 			DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
59860 			DUK_WO_NORETURN(return 0;);
59861 		}
59862 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
59863 	} while (curr != NULL);
59864 
59865 	/*
59866 	 *  Not found
59867 	 */
59868 
59869 	duk_to_undefined(thr, -1);  /* [key] -> [undefined] (default value) */
59870 
59871 	DUK_DDD(DUK_DDDPRINT("-> %!T (not found)", (duk_tval *) duk_get_tval(thr, -1)));
59872 	return 0;
59873 
59874 	/*
59875 	 *  Found; post-processing (Function and arguments objects)
59876 	 */
59877 
59878  found:
59879 	/* [key result] */
59880 
59881 #if !defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
59882 	/* Special behavior for 'caller' property of (non-bound) function objects
59883 	 * and non-strict Arguments objects: if 'caller' -value- (!) is a strict
59884 	 * mode function, throw a TypeError (E5 Sections 15.3.5.4, 10.6).
59885 	 * Quite interestingly, a non-strict function with no formal arguments
59886 	 * will get an arguments object -without- special 'caller' behavior!
59887 	 *
59888 	 * The E5.1 spec is a bit ambiguous if this special behavior applies when
59889 	 * a bound function is the base value (not the 'caller' value): Section
59890 	 * 15.3.4.5 (describing bind()) states that [[Get]] for bound functions
59891 	 * matches that of Section 15.3.5.4 ([[Get]] for Function instances).
59892 	 * However, Section 13.3.5.4 has "NOTE: Function objects created using
59893 	 * Function.prototype.bind use the default [[Get]] internal method."
59894 	 * The current implementation assumes this means that bound functions
59895 	 * should not have the special [[Get]] behavior.
59896 	 *
59897 	 * The E5.1 spec is also a bit unclear if the TypeError throwing is
59898 	 * applied if the 'caller' value is a strict bound function.  The
59899 	 * current implementation will throw even for both strict non-bound
59900 	 * and strict bound functions.
59901 	 *
59902 	 * See test-dev-strict-func-as-caller-prop-value.js for quite extensive
59903 	 * tests.
59904 	 *
59905 	 * This exotic behavior is disabled when the non-standard 'caller' property
59906 	 * is enabled, as it conflicts with the free use of 'caller'.
59907 	 */
59908 	if (key == DUK_HTHREAD_STRING_CALLER(thr) &&
59909 	    DUK_TVAL_IS_OBJECT(tv_obj)) {
59910 		duk_hobject *orig = DUK_TVAL_GET_OBJECT(tv_obj);
59911 		DUK_ASSERT(orig != NULL);
59912 
59913 		if (DUK_HOBJECT_IS_NONBOUND_FUNCTION(orig) ||
59914 		    DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
59915 			duk_hobject *h;
59916 
59917 			/* XXX: The TypeError is currently not applied to bound
59918 			 * functions because the 'strict' flag is not copied by
59919 			 * bind().  This may or may not be correct, the specification
59920 			 * only refers to the value being a "strict mode Function
59921 			 * object" which is ambiguous.
59922 			 */
59923 			DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(orig));
59924 
59925 			h = duk_get_hobject(thr, -1);  /* NULL if not an object */
59926 			if (h &&
59927 			    DUK_HOBJECT_IS_FUNCTION(h) &&
59928 			    DUK_HOBJECT_HAS_STRICT(h)) {
59929 				/* XXX: sufficient to check 'strict', assert for 'is function' */
59930 				DUK_ERROR_TYPE(thr, DUK_STR_STRICT_CALLER_READ);
59931 				DUK_WO_NORETURN(return 0;);
59932 			}
59933 		}
59934 	}
59935 #endif   /* !DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
59936 
59937 	duk_remove_m2(thr);  /* [key result] -> [result] */
59938 
59939 	DUK_DDD(DUK_DDDPRINT("-> %!T (found)", (duk_tval *) duk_get_tval(thr, -1)));
59940 	return 1;
59941 }
59942 
59943 /*
59944  *  HASPROP: ECMAScript property existence check ("in" operator).
59945  *
59946  *  Interestingly, the 'in' operator does not do any coercion of
59947  *  the target object.
59948  */
59949 
59950 DUK_INTERNAL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
59951 	duk_tval tv_key_copy;
59952 	duk_hobject *obj;
59953 	duk_hstring *key;
59954 	duk_uint32_t arr_idx;
59955 	duk_bool_t rc;
59956 	duk_propdesc desc;
59957 
59958 	DUK_DDD(DUK_DDDPRINT("hasprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
59959 	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
59960 	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));
59961 
59962 	DUK_ASSERT(thr != NULL);
59963 	DUK_ASSERT(thr->heap != NULL);
59964 	DUK_ASSERT(tv_obj != NULL);
59965 	DUK_ASSERT(tv_key != NULL);
59966 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
59967 
59968 	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
59969 	tv_key = &tv_key_copy;
59970 
59971 	/*
59972 	 *  The 'in' operator requires an object as its right hand side,
59973 	 *  throwing a TypeError unconditionally if this is not the case.
59974 	 *
59975 	 *  However, lightfuncs need to behave like fully fledged objects
59976 	 *  here to be maximally transparent, so we need to handle them
59977 	 *  here.  Same goes for plain buffers which behave like ArrayBuffers.
59978 	 */
59979 
59980 	/* XXX: Refactor key coercion so that it's only called once.  It can't
59981 	 * be trivially lifted here because the object must be type checked
59982 	 * first.
59983 	 */
59984 
59985 	if (DUK_TVAL_IS_OBJECT(tv_obj)) {
59986 		obj = DUK_TVAL_GET_OBJECT(tv_obj);
59987 		DUK_ASSERT(obj != NULL);
59988 
59989 		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59990 	} else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
59991 		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59992 		if (duk__key_is_plain_buf_ownprop(thr, DUK_TVAL_GET_BUFFER(tv_obj), key, arr_idx)) {
59993 			rc = 1;
59994 			goto pop_and_return;
59995 		}
59996 		obj = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
59997 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
59998 		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
59999 
60000 		/* If not found, resume existence check from %NativeFunctionPrototype%.
60001 		 * We can just substitute the value in this case; nothing will
60002 		 * need the original base value (as would be the case with e.g.
60003 		 * setters/getters.
60004 		 */
60005 		obj = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];
60006 	} else {
60007 		/* Note: unconditional throw */
60008 		DUK_DDD(DUK_DDDPRINT("base object is not an object -> reject"));
60009 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
60010 		DUK_WO_NORETURN(return 0;);
60011 	}
60012 
60013 	/* XXX: fast path for arrays? */
60014 
60015 	DUK_ASSERT(key != NULL);
60016 	DUK_ASSERT(obj != NULL);
60017 	DUK_UNREF(arr_idx);
60018 
60019 #if defined(DUK_USE_ES6_PROXY)
60020 	if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(obj))) {
60021 		duk_hobject *h_target;
60022 		duk_bool_t tmp_bool;
60023 
60024 		/* XXX: the key in 'key in obj' is string coerced before we're called
60025 		 * (which is the required behavior in E5/E5.1/E6) so the key is a string
60026 		 * here already.
60027 		 */
60028 
60029 		if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_HAS, tv_key, &h_target)) {
60030 			/* [ ... key trap handler ] */
60031 			DUK_DDD(DUK_DDDPRINT("-> proxy object 'has' for key %!T", (duk_tval *) tv_key));
60032 			duk_push_hobject(thr, h_target);  /* target */
60033 			duk_push_tval(thr, tv_key);       /* P */
60034 			duk_call_method(thr, 2 /*nargs*/);
60035 			tmp_bool = duk_to_boolean_top_pop(thr);
60036 			if (!tmp_bool) {
60037 				/* Target object must be checked for a conflicting
60038 				 * non-configurable property.
60039 				 */
60040 
60041 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
60042 					DUK_DDD(DUK_DDDPRINT("proxy 'has': target has matching property %!O, check for "
60043 					                     "conflicting property; desc.flags=0x%08lx, "
60044 					                     "desc.get=%p, desc.set=%p",
60045 					                     (duk_heaphdr *) key, (unsigned long) desc.flags,
60046 					                     (void *) desc.get, (void *) desc.set));
60047 					/* XXX: Extensibility check for target uses IsExtensible().  If we
60048 					 * implemented the isExtensible trap and didn't reject proxies as
60049 					 * proxy targets, it should be respected here.
60050 					 */
60051 					if (!((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&  /* property is configurable and */
60052 					      DUK_HOBJECT_HAS_EXTENSIBLE(h_target))) {          /* ... target is extensible */
60053 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
60054 						DUK_WO_NORETURN(return 0;);
60055 					}
60056 				}
60057 			}
60058 
60059 			duk_pop_unsafe(thr);  /* [ key ] -> [] */
60060 			return tmp_bool;
60061 		}
60062 
60063 		obj = h_target;  /* resume check from proxy target */
60064 	}
60065 #endif  /* DUK_USE_ES6_PROXY */
60066 
60067 	/* XXX: inline into a prototype walking loop? */
60068 
60069 	rc = duk__get_propdesc(thr, obj, key, &desc, 0 /*flags*/);  /* don't push value */
60070 	/* fall through */
60071 
60072  pop_and_return:
60073 	duk_pop_unsafe(thr);  /* [ key ] -> [] */
60074 	return rc;
60075 }
60076 
60077 /*
60078  *  HASPROP variant used internally.
60079  *
60080  *  This primitive must never throw an error, callers rely on this.
60081  *  In particular, don't throw an error for prototype loops; instead,
60082  *  pretend like the property doesn't exist if a prototype sanity limit
60083  *  is reached.
60084  *
60085  *  Does not implement proxy behavior: if applied to a proxy object,
60086  *  returns key existence on the proxy object itself.
60087  */
60088 
60089 DUK_INTERNAL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {
60090 	duk_propdesc dummy;
60091 
60092 	DUK_ASSERT(thr != NULL);
60093 	DUK_ASSERT(thr->heap != NULL);
60094 	DUK_ASSERT(obj != NULL);
60095 	DUK_ASSERT(key != NULL);
60096 
60097 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
60098 
60099 	return duk__get_propdesc(thr, obj, key, &dummy, DUK_GETDESC_FLAG_IGNORE_PROTOLOOP);  /* don't push value */
60100 }
60101 
60102 /*
60103  *  Helper: handle Array object 'length' write which automatically
60104  *  deletes properties, see E5 Section 15.4.5.1, step 3.  This is
60105  *  quite tricky to get right.
60106  *
60107  *  Used by duk_hobject_putprop().
60108  */
60109 
60110 /* Coerce a new .length candidate to a number and check that it's a valid
60111  * .length.
60112  */
60113 DUK_LOCAL duk_uint32_t duk__to_new_array_length_checked(duk_hthread *thr, duk_tval *tv) {
60114 	duk_uint32_t res;
60115 	duk_double_t d;
60116 
60117 #if !defined(DUK_USE_PREFER_SIZE)
60118 #if defined(DUK_USE_FASTINT)
60119 	/* When fastints are enabled, the most interesting case is assigning
60120 	 * a fastint to .length (e.g. arr.length = 0).
60121 	 */
60122 	if (DUK_TVAL_IS_FASTINT(tv)) {
60123 		/* Very common case. */
60124 		duk_int64_t fi;
60125 		fi = DUK_TVAL_GET_FASTINT(tv);
60126 		if (fi < 0 || fi > DUK_I64_CONSTANT(0xffffffff)) {
60127 			goto fail_range;
60128 		}
60129 		return (duk_uint32_t) fi;
60130 	}
60131 #else  /* DUK_USE_FASTINT */
60132 	/* When fastints are not enabled, the most interesting case is any
60133 	 * number.
60134 	 */
60135 	if (DUK_TVAL_IS_DOUBLE(tv)) {
60136 		d = DUK_TVAL_GET_NUMBER(tv);
60137 	}
60138 #endif  /* DUK_USE_FASTINT */
60139 	else
60140 #endif  /* !DUK_USE_PREFER_SIZE */
60141 	{
60142 		/* In all other cases, and when doing a size optimized build,
60143 		 * fall back to the comprehensive handler.
60144 		 */
60145 		d = duk_js_tonumber(thr, tv);
60146 	}
60147 
60148 	/* Refuse to update an Array's 'length' to a value outside the
60149 	 * 32-bit range.  Negative zero is accepted as zero.
60150 	 */
60151 	res = duk_double_to_uint32_t(d);
60152 	if (!duk_double_equals((duk_double_t) res, d)) {
60153 		goto fail_range;
60154 	}
60155 
60156 	return res;
60157 
60158  fail_range:
60159 	DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARRAY_LENGTH);
60160 	DUK_WO_NORETURN(return 0;);
60161 }
60162 
60163 /* Delete elements required by a smaller length, taking into account
60164  * potentially non-configurable elements.  Returns non-zero if all
60165  * elements could be deleted, and zero if all or some elements could
60166  * not be deleted.  Also writes final "target length" to 'out_result_len'.
60167  * This is the length value that should go into the 'length' property
60168  * (must be set by the caller).  Never throws an error.
60169  */
60170 DUK_LOCAL
60171 duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
60172                                                 duk_hobject *obj,
60173                                                 duk_uint32_t old_len,
60174                                                 duk_uint32_t new_len,
60175                                                 duk_bool_t force_flag,
60176                                                 duk_uint32_t *out_result_len) {
60177 	duk_uint32_t target_len;
60178 	duk_uint_fast32_t i;
60179 	duk_uint32_t arr_idx;
60180 	duk_hstring *key;
60181 	duk_tval *tv;
60182 	duk_bool_t rc;
60183 
60184 	DUK_DDD(DUK_DDDPRINT("new array length smaller than old (%ld -> %ld), "
60185 	                     "probably need to remove elements",
60186 	                     (long) old_len, (long) new_len));
60187 
60188 	/*
60189 	 *  New length is smaller than old length, need to delete properties above
60190 	 *  the new length.
60191 	 *
60192 	 *  If array part exists, this is straightforward: array entries cannot
60193 	 *  be non-configurable so this is guaranteed to work.
60194 	 *
60195 	 *  If array part does not exist, array-indexed values are scattered
60196 	 *  in the entry part, and some may not be configurable (preventing length
60197 	 *  from becoming lower than their index + 1).  To handle the algorithm
60198 	 *  in E5 Section 15.4.5.1, step l correctly, we scan the entire property
60199 	 *  set twice.
60200 	 */
60201 
60202 	DUK_ASSERT(thr != NULL);
60203 	DUK_ASSERT(obj != NULL);
60204 	DUK_ASSERT(new_len < old_len);
60205 	DUK_ASSERT(out_result_len != NULL);
60206 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
60207 
60208 	DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));
60209 	DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(obj));
60210 
60211 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
60212 		/*
60213 		 *  All defined array-indexed properties are in the array part
60214 		 *  (we assume the array part is comprehensive), and all array
60215 		 *  entries are writable, configurable, and enumerable.  Thus,
60216 		 *  nothing can prevent array entries from being deleted.
60217 		 */
60218 
60219 		DUK_DDD(DUK_DDDPRINT("have array part, easy case"));
60220 
60221 		if (old_len < DUK_HOBJECT_GET_ASIZE(obj)) {
60222 			/* XXX: assertion that entries >= old_len are already unused */
60223 			i = old_len;
60224 		} else {
60225 			i = DUK_HOBJECT_GET_ASIZE(obj);
60226 		}
60227 		DUK_ASSERT(i <= DUK_HOBJECT_GET_ASIZE(obj));
60228 
60229 		while (i > new_len) {
60230 			i--;
60231 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
60232 			DUK_TVAL_SET_UNUSED_UPDREF(thr, tv);  /* side effects */
60233 		}
60234 
60235 		*out_result_len = new_len;
60236 		return 1;
60237 	} else {
60238 		/*
60239 		 *  Entries part is a bit more complex.
60240 		 */
60241 
60242 		/* Stage 1: find highest preventing non-configurable entry (if any).
60243 		 * When forcing, ignore non-configurability.
60244 		 */
60245 
60246 		DUK_DDD(DUK_DDDPRINT("no array part, slow case"));
60247 
60248 		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 1: find target_len "
60249 		                     "(highest preventing non-configurable entry (if any))"));
60250 
60251 		target_len = new_len;
60252 		if (force_flag) {
60253 			DUK_DDD(DUK_DDDPRINT("array length write, no array part; force flag -> skip stage 1"));
60254 			goto skip_stage1;
60255 		}
60256 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
60257 			key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
60258 			if (!key) {
60259 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
60260 				continue;
60261 			}
60262 			if (!DUK_HSTRING_HAS_ARRIDX(key)) {
60263 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
60264 				continue;
60265 			}
60266 
60267 			DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key));  /* XXX: macro checks for array index flag, which is unnecessary here */
60268 			arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
60269 			DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
60270 			DUK_ASSERT(arr_idx < old_len);  /* consistency requires this */
60271 
60272 			if (arr_idx < new_len) {
60273 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below new_len",
60274 				                     (long) i, (long) arr_idx));
60275 				continue;
60276 			}
60277 			if (DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i)) {
60278 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is a relevant array index %ld, but configurable",
60279 				                     (long) i, (long) arr_idx));
60280 				continue;
60281 			}
60282 
60283 			/* relevant array index is non-configurable, blocks write */
60284 			if (arr_idx >= target_len) {
60285 				DUK_DDD(DUK_DDDPRINT("entry at index %ld has arr_idx %ld, is not configurable, "
60286 				                     "update target_len %ld -> %ld",
60287 				                     (long) i, (long) arr_idx, (long) target_len,
60288 				                     (long) (arr_idx + 1)));
60289 				target_len = arr_idx + 1;
60290 			}
60291 		}
60292 	 skip_stage1:
60293 
60294 		/* stage 2: delete configurable entries above target length */
60295 
60296 		DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld, target_len=%ld",
60297 		                     (long) old_len, (long) new_len, (long) target_len));
60298 
60299 		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 2: remove "
60300 		                     "entries >= target_len"));
60301 
60302 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
60303 			key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
60304 			if (!key) {
60305 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
60306 				continue;
60307 			}
60308 			if (!DUK_HSTRING_HAS_ARRIDX(key)) {
60309 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
60310 				continue;
60311 			}
60312 
60313 			DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key));  /* XXX: macro checks for array index flag, which is unnecessary here */
60314 			arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
60315 			DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
60316 			DUK_ASSERT(arr_idx < old_len);  /* consistency requires this */
60317 
60318 			if (arr_idx < target_len) {
60319 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below target_len",
60320 				                     (long) i, (long) arr_idx));
60321 				continue;
60322 			}
60323 			DUK_ASSERT(force_flag || DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i));  /* stage 1 guarantees */
60324 
60325 			DUK_DDD(DUK_DDDPRINT("delete entry index %ld: key is array index %ld",
60326 			                     (long) i, (long) arr_idx));
60327 
60328 			/*
60329 			 *  Slow delete, but we don't care as we're already in a very slow path.
60330 			 *  The delete always succeeds: key has no exotic behavior, property
60331 			 *  is configurable, and no resize occurs.
60332 			 */
60333 			rc = duk_hobject_delprop_raw(thr, obj, key, force_flag ? DUK_DELPROP_FLAG_FORCE : 0);
60334 			DUK_UNREF(rc);
60335 			DUK_ASSERT(rc != 0);
60336 		}
60337 
60338 		/* stage 3: update length (done by caller), decide return code */
60339 
60340 		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 3: update length (done by caller)"));
60341 
60342 		*out_result_len = target_len;
60343 
60344 		if (target_len == new_len) {
60345 			DUK_DDD(DUK_DDDPRINT("target_len matches new_len, return success"));
60346 			return 1;
60347 		}
60348 		DUK_DDD(DUK_DDDPRINT("target_len does not match new_len (some entry prevented "
60349 		                     "full length adjustment), return error"));
60350 		return 0;
60351 	}
60352 
60353 	DUK_UNREACHABLE();
60354 }
60355 
60356 /* XXX: is valstack top best place for argument? */
60357 DUK_LOCAL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj) {
60358 	duk_harray *a;
60359 	duk_uint32_t old_len;
60360 	duk_uint32_t new_len;
60361 	duk_uint32_t result_len;
60362 	duk_bool_t rc;
60363 
60364 	DUK_DDD(DUK_DDDPRINT("handling a put operation to array 'length' exotic property, "
60365 	                     "new val: %!T",
60366 	                     (duk_tval *) duk_get_tval(thr, -1)));
60367 
60368 	DUK_ASSERT(thr != NULL);
60369 	DUK_ASSERT(obj != NULL);
60370 
60371 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
60372 
60373 	DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));
60374 	DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(obj));
60375 	a = (duk_harray *) obj;
60376 	DUK_HARRAY_ASSERT_VALID(a);
60377 
60378 	DUK_ASSERT(duk_is_valid_index(thr, -1));
60379 
60380 	/*
60381 	 *  Get old and new length
60382 	 */
60383 
60384 	old_len = a->length;
60385 	new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_NEGIDX(thr, -1));
60386 	DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) old_len, (long) new_len));
60387 
60388 	/*
60389 	 *  Writability check
60390 	 */
60391 
60392 	if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
60393 		DUK_DDD(DUK_DDDPRINT("length is not writable, fail"));
60394 		return 0;
60395 	}
60396 
60397 	/*
60398 	 *  New length not lower than old length => no changes needed
60399 	 *  (not even array allocation).
60400 	 */
60401 
60402 	if (new_len >= old_len) {
60403 		DUK_DDD(DUK_DDDPRINT("new length is same or higher than old length, just update length, no deletions"));
60404 		a->length = new_len;
60405 		return 1;
60406 	}
60407 
60408 	DUK_DDD(DUK_DDDPRINT("new length is lower than old length, probably must delete entries"));
60409 
60410 	/*
60411 	 *  New length lower than old length => delete elements, then
60412 	 *  update length.
60413 	 *
60414 	 *  Note: even though a bunch of elements have been deleted, the 'desc' is
60415 	 *  still valid as properties haven't been resized (and entries compacted).
60416 	 */
60417 
60418 	rc = duk__handle_put_array_length_smaller(thr, obj, old_len, new_len, 0 /*force_flag*/, &result_len);
60419 	DUK_ASSERT(result_len >= new_len && result_len <= old_len);
60420 
60421 	a->length = result_len;
60422 
60423 	/* XXX: shrink array allocation or entries compaction here? */
60424 
60425 	return rc;
60426 }
60427 
60428 /*
60429  *  PUTPROP: ECMAScript property write.
60430  *
60431  *  Unlike ECMAScript primitive which returns nothing, returns 1 to indicate
60432  *  success and 0 to indicate failure (assuming throw is not set).
60433  *
60434  *  This is an extremely tricky function.  Some examples:
60435  *
60436  *    * Currently a decref may trigger a GC, which may compact an object's
60437  *      property allocation.  Consequently, any entry indices (e_idx) will
60438  *      be potentially invalidated by a decref.
60439  *
60440  *    * Exotic behaviors (strings, arrays, arguments object) require,
60441  *      among other things:
60442  *
60443  *      - Preprocessing before and postprocessing after an actual property
60444  *        write.  For example, array index write requires pre-checking the
60445  *        array 'length' property for access control, and may require an
60446  *        array 'length' update after the actual write has succeeded (but
60447  *        not if it fails).
60448  *
60449  *      - Deletion of multiple entries, as a result of array 'length' write.
60450  *
60451  *    * Input values are taken as pointers which may point to the valstack.
60452  *      If valstack is resized because of the put (this may happen at least
60453  *      when the array part is abandoned), the pointers can be invalidated.
60454  *      (We currently make a copy of all of the input values to avoid issues.)
60455  */
60456 
60457 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) {
60458 	duk_tval tv_obj_copy;
60459 	duk_tval tv_key_copy;
60460 	duk_tval tv_val_copy;
60461 	duk_hobject *orig = NULL;  /* NULL if tv_obj is primitive */
60462 	duk_hobject *curr;
60463 	duk_hstring *key = NULL;
60464 	duk_propdesc desc;
60465 	duk_tval *tv;
60466 	duk_uint32_t arr_idx;
60467 	duk_bool_t rc;
60468 	duk_int_t e_idx;
60469 	duk_uint_t sanity;
60470 	duk_uint32_t new_array_length = 0;  /* 0 = no update */
60471 
60472 	DUK_DDD(DUK_DDDPRINT("putprop: thr=%p, obj=%p, key=%p, val=%p, throw=%ld "
60473 	                     "(obj -> %!T, key -> %!T, val -> %!T)",
60474 	                     (void *) thr, (void *) tv_obj, (void *) tv_key, (void *) tv_val,
60475 	                     (long) throw_flag, (duk_tval *) tv_obj, (duk_tval *) tv_key, (duk_tval *) tv_val));
60476 
60477 	DUK_ASSERT(thr != NULL);
60478 	DUK_ASSERT(thr->heap != NULL);
60479 	DUK_ASSERT(tv_obj != NULL);
60480 	DUK_ASSERT(tv_key != NULL);
60481 	DUK_ASSERT(tv_val != NULL);
60482 
60483 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
60484 
60485 	DUK_STATS_INC(thr->heap, stats_putprop_all);
60486 
60487 	/*
60488 	 *  Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
60489 	 *  them being invalidated by a valstack resize.
60490 	 *
60491 	 *  XXX: this is an overkill for some paths, so optimize this later
60492 	 *  (or maybe switch to a stack arguments model entirely).
60493 	 */
60494 
60495 	DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
60496 	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
60497 	DUK_TVAL_SET_TVAL(&tv_val_copy, tv_val);
60498 	tv_obj = &tv_obj_copy;
60499 	tv_key = &tv_key_copy;
60500 	tv_val = &tv_val_copy;
60501 
60502 	/*
60503 	 *  Coercion and fast path processing.
60504 	 */
60505 
60506 	switch (DUK_TVAL_GET_TAG(tv_obj)) {
60507 	case DUK_TAG_UNDEFINED:
60508 	case DUK_TAG_NULL: {
60509 		/* Note: unconditional throw */
60510 		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject (object=%!iT)",
60511 		                     (duk_tval *) tv_obj));
60512 #if defined(DUK_USE_PARANOID_ERRORS)
60513 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
60514 #else
60515 		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
60516 		               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
60517 #endif
60518 		DUK_WO_NORETURN(return 0;);
60519 		break;
60520 	}
60521 
60522 	case DUK_TAG_BOOLEAN: {
60523 		DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
60524 		curr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];
60525 		break;
60526 	}
60527 
60528 	case DUK_TAG_STRING: {
60529 		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
60530 
60531 		/*
60532 		 *  Note: currently no fast path for array index writes.
60533 		 *  They won't be possible anyway as strings are immutable.
60534 		 */
60535 
60536 		DUK_ASSERT(key == NULL);
60537 		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
60538 		DUK_ASSERT(key != NULL);
60539 
60540 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
60541 			/* Symbols (ES2015 or hidden) don't have virtual properties. */
60542 			curr = thr->builtins[DUK_BIDX_SYMBOL_PROTOTYPE];
60543 			goto lookup;
60544 		}
60545 
60546 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
60547 			goto fail_not_writable;
60548 		}
60549 
60550 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
60551 		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
60552 			goto fail_not_writable;
60553 		}
60554 
60555 		DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
60556 		curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
60557 		goto lookup;  /* avoid double coercion */
60558 	}
60559 
60560 	case DUK_TAG_OBJECT: {
60561 		orig = DUK_TVAL_GET_OBJECT(tv_obj);
60562 		DUK_ASSERT(orig != NULL);
60563 
60564 #if defined(DUK_USE_ROM_OBJECTS)
60565 		/* With this check in place fast paths won't need read-only
60566 		 * object checks.  This is technically incorrect if there are
60567 		 * setters that cause no writes to ROM objects, but current
60568 		 * built-ins don't have such setters.
60569 		 */
60570 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
60571 			DUK_DD(DUK_DDPRINT("attempt to putprop on read-only target object"));
60572 			goto fail_not_writable_no_pop;  /* Must avoid duk_pop() in exit path */
60573 		}
60574 #endif
60575 
60576 		/* The fast path for array property put is not fully compliant:
60577 		 * If one places conflicting number-indexed properties into
60578 		 * Array.prototype (for example, a non-writable Array.prototype[7])
60579 		 * the fast path will incorrectly ignore them.
60580 		 *
60581 		 * This fast path could be made compliant by falling through
60582 		 * to the slow path if the previous value was UNUSED.  This would
60583 		 * also remove the need to check for extensibility.  Right now a
60584 		 * non-extensible array is slower than an extensible one as far
60585 		 * as writes are concerned.
60586 		 *
60587 		 * The fast path behavior is documented in more detail here:
60588 		 * tests/ecmascript/test-misc-array-fast-write.js
60589 		 */
60590 
60591 		/* XXX: array .length? */
60592 
60593 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
60594 		if (duk__putprop_shallow_fastpath_array_tval(thr, orig, tv_key, tv_val) != 0) {
60595 			DUK_DDD(DUK_DDDPRINT("array fast path success"));
60596 			DUK_STATS_INC(thr->heap, stats_putprop_arrayidx);
60597 			return 1;
60598 		}
60599 #endif
60600 
60601 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
60602 		if (duk__putprop_fastpath_bufobj_tval(thr, orig, tv_key, tv_val) != 0) {
60603 			DUK_DDD(DUK_DDDPRINT("base is bufobj, key is a number, bufobj fast path"));
60604 			DUK_STATS_INC(thr->heap, stats_putprop_bufobjidx);
60605 			return 1;
60606 		}
60607 #endif
60608 
60609 #if defined(DUK_USE_ES6_PROXY)
60610 		if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(orig))) {
60611 			duk_hobject *h_target;
60612 			duk_bool_t tmp_bool;
60613 
60614 			if (duk__proxy_check_prop(thr, orig, DUK_STRIDX_SET, tv_key, &h_target)) {
60615 				/* -> [ ... trap handler ] */
60616 				DUK_DDD(DUK_DDDPRINT("-> proxy object 'set' for key %!T", (duk_tval *) tv_key));
60617 				DUK_STATS_INC(thr->heap, stats_putprop_proxy);
60618 				duk_push_hobject(thr, h_target);  /* target */
60619 				duk_push_tval(thr, tv_key);       /* P */
60620 				duk_push_tval(thr, tv_val);       /* V */
60621 				duk_push_tval(thr, tv_obj);       /* Receiver: Proxy object */
60622 				duk_call_method(thr, 4 /*nargs*/);
60623 				tmp_bool = duk_to_boolean_top_pop(thr);
60624 				if (!tmp_bool) {
60625 					goto fail_proxy_rejected;
60626 				}
60627 
60628 				/* Target object must be checked for a conflicting
60629 				 * non-configurable property.
60630 				 */
60631 				arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
60632 				DUK_ASSERT(key != NULL);
60633 
60634 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
60635 					duk_tval *tv_targ = duk_require_tval(thr, -1);
60636 					duk_bool_t datadesc_reject;
60637 					duk_bool_t accdesc_reject;
60638 
60639 					DUK_DDD(DUK_DDDPRINT("proxy 'set': target has matching property %!O, check for "
60640 					                     "conflicting property; tv_val=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
60641 					                     "desc.get=%p, desc.set=%p",
60642 					                     (duk_heaphdr *) key, (duk_tval *) tv_val, (duk_tval *) tv_targ,
60643 					                     (unsigned long) desc.flags,
60644 					                     (void *) desc.get, (void *) desc.set));
60645 
60646 					datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
60647 					                  !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
60648 					                  !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) &&
60649 					                  !duk_js_samevalue(tv_val, tv_targ);
60650 					accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
60651 					                 !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
60652 					                 (desc.set == NULL);
60653 					if (datadesc_reject || accdesc_reject) {
60654 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
60655 						DUK_WO_NORETURN(return 0;);
60656 					}
60657 
60658 					duk_pop_2_unsafe(thr);
60659 				} else {
60660 					duk_pop_unsafe(thr);
60661 				}
60662 				return 1;  /* success */
60663 			}
60664 
60665 			orig = h_target;  /* resume write to target */
60666 			DUK_TVAL_SET_OBJECT(tv_obj, orig);
60667 		}
60668 #endif  /* DUK_USE_ES6_PROXY */
60669 
60670 		curr = orig;
60671 		break;
60672 	}
60673 
60674 	case DUK_TAG_BUFFER: {
60675 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
60676 		duk_int_t pop_count = 0;
60677 
60678 		/*
60679 		 *  Because buffer values may be looped over and read/written
60680 		 *  from, an array index fast path is important.
60681 		 */
60682 
60683 #if defined(DUK_USE_FASTINT)
60684 		if (DUK_TVAL_IS_FASTINT(tv_key)) {
60685 			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
60686 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
60687 			pop_count = 0;
60688 		} else
60689 #endif
60690 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
60691 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
60692 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
60693 			pop_count = 0;
60694 		} else {
60695 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
60696 			DUK_ASSERT(key != NULL);
60697 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
60698 			                     "coercion key is %!T, arr_idx %ld",
60699 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
60700 			pop_count = 1;
60701 		}
60702 
60703 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
60704 		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
60705 			duk_uint8_t *data;
60706 			DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
60707 			data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);
60708 
60709 			/* XXX: duk_to_int() ensures we'll get 8 lowest bits as
60710 			 * as input is within duk_int_t range (capped outside it).
60711 			 */
60712 #if defined(DUK_USE_FASTINT)
60713 			/* Buffer writes are often integers. */
60714 			if (DUK_TVAL_IS_FASTINT(tv_val)) {
60715 				data[arr_idx] = (duk_uint8_t) DUK_TVAL_GET_FASTINT_U32(tv_val);
60716 			}
60717 			else
60718 #endif
60719 			{
60720 				duk_push_tval(thr, tv_val);
60721 				data[arr_idx] = (duk_uint8_t) duk_to_uint32(thr, -1);
60722 				pop_count++;
60723 			}
60724 
60725 			duk_pop_n_unsafe(thr, pop_count);
60726 			DUK_DDD(DUK_DDDPRINT("result: success (buffer data write)"));
60727 			DUK_STATS_INC(thr->heap, stats_putprop_bufferidx);
60728 			return 1;
60729 		}
60730 
60731 		if (pop_count == 0) {
60732 			/* This is a pretty awkward control flow, but we need to recheck the
60733 			 * key coercion here.
60734 			 */
60735 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
60736 			DUK_ASSERT(key != NULL);
60737 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
60738 			                     "coercion key is %!T, arr_idx %ld",
60739 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
60740 		}
60741 
60742 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
60743 			goto fail_not_writable;
60744 		}
60745 
60746 		DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from Uint8Array prototype"));
60747 		curr = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
60748 		goto lookup;  /* avoid double coercion */
60749 	}
60750 
60751 	case DUK_TAG_POINTER: {
60752 		DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
60753 		curr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
60754 		break;
60755 	}
60756 
60757 	case DUK_TAG_LIGHTFUNC: {
60758 		/* Lightfuncs have no own properties and are considered non-extensible.
60759 		 * However, the write may be captured by an inherited setter which
60760 		 * means we can't stop the lookup here.
60761 		 */
60762 		DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
60763 		curr = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];
60764 		break;
60765 	}
60766 
60767 #if defined(DUK_USE_FASTINT)
60768 	case DUK_TAG_FASTINT:
60769 #endif
60770 	default: {
60771 		/* number */
60772 		DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
60773 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_obj));
60774 		curr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];
60775 		break;
60776 	}
60777 	}
60778 
60779 	DUK_ASSERT(key == NULL);
60780 	arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
60781 	DUK_ASSERT(key != NULL);
60782 
60783  lookup:
60784 
60785 	/*
60786 	 *  Check whether the property already exists in the prototype chain.
60787 	 *  Note that the actual write goes into the original base object
60788 	 *  (except if an accessor property captures the write).
60789 	 */
60790 
60791 	/* [key] */
60792 
60793 	DUK_ASSERT(curr != NULL);
60794 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
60795 	do {
60796 		if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
60797 			goto next_in_chain;
60798 		}
60799 
60800 		if (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
60801 			/*
60802 			 *  Found existing accessor property (own or inherited).
60803 			 *  Call setter with 'this' set to orig, and value as the only argument.
60804 			 *  Setter calls are OK even for ROM objects.
60805 			 *
60806 			 *  Note: no exotic arguments object behavior, because [[Put]] never
60807 			 *  calls [[DefineOwnProperty]] (E5 Section 8.12.5, step 5.b).
60808 			 */
60809 
60810 			duk_hobject *setter;
60811 
60812 			DUK_DD(DUK_DDPRINT("put to an own or inherited accessor, calling setter"));
60813 
60814 			setter = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, curr, desc.e_idx);
60815 			if (!setter) {
60816 				goto fail_no_setter;
60817 			}
60818 			duk_push_hobject(thr, setter);
60819 			duk_push_tval(thr, tv_obj);  /* note: original, uncoerced base */
60820 			duk_push_tval(thr, tv_val);  /* [key setter this val] */
60821 #if defined(DUK_USE_NONSTD_SETTER_KEY_ARGUMENT)
60822 			duk_dup_m4(thr);
60823 			duk_call_method(thr, 2);     /* [key setter this val key] -> [key retval] */
60824 #else
60825 			duk_call_method(thr, 1);     /* [key setter this val] -> [key retval] */
60826 #endif
60827 			duk_pop_unsafe(thr);         /* ignore retval -> [key] */
60828 			goto success_no_arguments_exotic;
60829 		}
60830 
60831 		if (orig == NULL) {
60832 			/*
60833 			 *  Found existing own or inherited plain property, but original
60834 			 *  base is a primitive value.
60835 			 */
60836 			DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
60837 			goto fail_base_primitive;
60838 		}
60839 
60840 		if (curr != orig) {
60841 			/*
60842 			 *  Found existing inherited plain property.
60843 			 *  Do an access control check, and if OK, write
60844 			 *  new property to 'orig'.
60845 			 */
60846 			if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
60847 				DUK_DD(DUK_DDPRINT("found existing inherited plain property, but original object is not extensible"));
60848 				goto fail_not_extensible;
60849 			}
60850 			if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
60851 				DUK_DD(DUK_DDPRINT("found existing inherited plain property, original object is extensible, but inherited property is not writable"));
60852 				goto fail_not_writable;
60853 			}
60854 			DUK_DD(DUK_DDPRINT("put to new property, object extensible, inherited property found and is writable"));
60855 			goto create_new;
60856 		} else {
60857 			/*
60858 			 *  Found existing own (non-inherited) plain property.
60859 			 *  Do an access control check and update in place.
60860 			 */
60861 
60862 			if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
60863 				DUK_DD(DUK_DDPRINT("found existing own (non-inherited) plain property, but property is not writable"));
60864 				goto fail_not_writable;
60865 			}
60866 			if (desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) {
60867 				DUK_DD(DUK_DDPRINT("found existing own (non-inherited) virtual property, property is writable"));
60868 
60869 				if (DUK_HOBJECT_IS_ARRAY(curr)) {
60870 					/*
60871 					 *  Write to 'length' of an array is a very complex case
60872 					 *  handled in a helper which updates both the array elements
60873 					 *  and writes the new 'length'.  The write may result in an
60874 					 *  unconditional RangeError or a partial write (indicated
60875 					 *  by a return code).
60876 					 *
60877 					 *  Note: the helper has an unnecessary writability check
60878 					 *  for 'length', we already know it is writable.
60879 					 */
60880 					DUK_ASSERT(key == DUK_HTHREAD_STRING_LENGTH(thr));  /* only virtual array property */
60881 
60882 					DUK_DDD(DUK_DDDPRINT("writing existing 'length' property to array exotic, invoke complex helper"));
60883 
60884 					/* XXX: the helper currently assumes stack top contains new
60885 					 * 'length' value and the whole calling convention is not very
60886 					 * compatible with what we need.
60887 					 */
60888 
60889 					duk_push_tval(thr, tv_val);  /* [key val] */
60890 					rc = duk__handle_put_array_length(thr, orig);
60891 					duk_pop_unsafe(thr);  /* [key val] -> [key] */
60892 					if (!rc) {
60893 						goto fail_array_length_partial;
60894 					}
60895 
60896 					/* key is 'length', cannot match argument exotic behavior */
60897 					goto success_no_arguments_exotic;
60898 				}
60899 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
60900 				else if (DUK_HOBJECT_IS_BUFOBJ(curr)) {
60901 					duk_hbufobj *h_bufobj;
60902 					duk_uint_t byte_off;
60903 					duk_small_uint_t elem_size;
60904 
60905 					h_bufobj = (duk_hbufobj *) curr;
60906 					DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
60907 
60908 					DUK_DD(DUK_DDPRINT("writable virtual property is in buffer object"));
60909 
60910 					/* Careful with wrapping: arr_idx upshift may easily wrap, whereas
60911 					 * length downshift won't.
60912 					 */
60913 					if (arr_idx < (h_bufobj->length >> h_bufobj->shift) && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
60914 						duk_uint8_t *data;
60915 						DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
60916 
60917 						DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);  /* index/length check guarantees */
60918 						byte_off = arr_idx << h_bufobj->shift;       /* no wrap assuming h_bufobj->length is valid */
60919 						elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
60920 
60921 						/* Coerce to number before validating pointers etc so that the
60922 						 * number coercions in duk_hbufobj_validated_write() are
60923 						 * guaranteed to be side effect free and not invalidate the
60924 						 * pointer checks we do here.
60925 						 */
60926 						duk_push_tval(thr, tv_val);
60927 						(void) duk_to_number_m1(thr);
60928 
60929 						if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
60930 							data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
60931 							duk_hbufobj_validated_write(thr, h_bufobj, data, elem_size);
60932 						} else {
60933 							DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (write skipped)"));
60934 						}
60935 						duk_pop_unsafe(thr);
60936 						goto success_no_arguments_exotic;
60937 					}
60938 				}
60939 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
60940 
60941 				DUK_D(DUK_DPRINT("should not happen, key %!O", key));
60942 				goto fail_internal;  /* should not happen */
60943 			}
60944 			DUK_DD(DUK_DDPRINT("put to existing own plain property, property is writable"));
60945 			goto update_old;
60946 		}
60947 		DUK_UNREACHABLE();
60948 
60949 	 next_in_chain:
60950 		/* XXX: option to pretend property doesn't exist if sanity limit is
60951 		 * hit might be useful.
60952 		 */
60953 		if (DUK_UNLIKELY(sanity-- == 0)) {
60954 			DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
60955 			DUK_WO_NORETURN(return 0;);
60956 		}
60957 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
60958 	} while (curr != NULL);
60959 
60960 	/*
60961 	 *  Property not found in prototype chain.
60962 	 */
60963 
60964 	DUK_DDD(DUK_DDDPRINT("property not found in prototype chain"));
60965 
60966 	if (orig == NULL) {
60967 		DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
60968 		goto fail_base_primitive;
60969 	}
60970 
60971 	if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
60972 		DUK_DD(DUK_DDPRINT("put to a new property (not found in prototype chain), but original object not extensible"));
60973 		goto fail_not_extensible;
60974 	}
60975 
60976 	goto create_new;
60977 
60978  update_old:
60979 
60980 	/*
60981 	 *  Update an existing property of the base object.
60982 	 */
60983 
60984 	/* [key] */
60985 
60986 	DUK_DDD(DUK_DDDPRINT("update an existing property of the original object"));
60987 
60988 	DUK_ASSERT(orig != NULL);
60989 #if defined(DUK_USE_ROM_OBJECTS)
60990 	/* This should not happen because DUK_TAG_OBJECT case checks
60991 	 * for this already, but check just in case.
60992 	 */
60993 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
60994 		goto fail_not_writable;
60995 	}
60996 #endif
60997 
60998 	/* Although there are writable virtual properties (e.g. plain buffer
60999 	 * and buffer object number indices), they are handled before we come
61000 	 * here.
61001 	 */
61002 	DUK_ASSERT((desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) == 0);
61003 	DUK_ASSERT(desc.a_idx >= 0 || desc.e_idx >= 0);
61004 
61005 	/* Array own property .length is handled above. */
61006 	DUK_ASSERT(!(DUK_HOBJECT_IS_ARRAY(orig) && key == DUK_HTHREAD_STRING_LENGTH(thr)));
61007 
61008 	if (desc.e_idx >= 0) {
61009 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, desc.e_idx);
61010 		DUK_DDD(DUK_DDDPRINT("previous entry value: %!iT", (duk_tval *) tv));
61011 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects; e_idx may be invalidated */
61012 		/* don't touch property attributes or hash part */
61013 		DUK_DD(DUK_DDPRINT("put to an existing entry at index %ld -> new value %!iT",
61014 		                   (long) desc.e_idx, (duk_tval *) tv));
61015 	} else {
61016 		/* Note: array entries are always writable, so the writability check
61017 		 * above is pointless for them.  The check could be avoided with some
61018 		 * refactoring but is probably not worth it.
61019 		 */
61020 
61021 		DUK_ASSERT(desc.a_idx >= 0);
61022 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, desc.a_idx);
61023 		DUK_DDD(DUK_DDDPRINT("previous array value: %!iT", (duk_tval *) tv));
61024 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects; a_idx may be invalidated */
61025 		DUK_DD(DUK_DDPRINT("put to an existing array entry at index %ld -> new value %!iT",
61026 		                   (long) desc.a_idx, (duk_tval *) tv));
61027 	}
61028 
61029 	/* Regardless of whether property is found in entry or array part,
61030 	 * it may have arguments exotic behavior (array indices may reside
61031 	 * in entry part for abandoned / non-existent array parts).
61032 	 */
61033 	goto success_with_arguments_exotic;
61034 
61035  create_new:
61036 
61037 	/*
61038 	 *  Create a new property in the original object.
61039 	 *
61040 	 *  Exotic properties need to be reconsidered here from a write
61041 	 *  perspective (not just property attributes perspective).
61042 	 *  However, the property does not exist in the object already,
61043 	 *  so this limits the kind of exotic properties that apply.
61044 	 */
61045 
61046 	/* [key] */
61047 
61048 	DUK_DDD(DUK_DDDPRINT("create new property to original object"));
61049 
61050 	DUK_ASSERT(orig != NULL);
61051 
61052 	/* Array own property .length is handled above. */
61053 	DUK_ASSERT(!(DUK_HOBJECT_IS_ARRAY(orig) && key == DUK_HTHREAD_STRING_LENGTH(thr)));
61054 
61055 #if defined(DUK_USE_ROM_OBJECTS)
61056 	/* This should not happen because DUK_TAG_OBJECT case checks
61057 	 * for this already, but check just in case.
61058 	 */
61059 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
61060 		goto fail_not_writable;
61061 	}
61062 #endif
61063 
61064 	/* Not possible because array object 'length' is present
61065 	 * from its creation and cannot be deleted, and is thus
61066 	 * caught as an existing property above.
61067 	 */
61068 	DUK_ASSERT(!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
61069 	             key == DUK_HTHREAD_STRING_LENGTH(thr)));
61070 
61071 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
61072 	    arr_idx != DUK__NO_ARRAY_INDEX) {
61073 		/* automatic length update */
61074 		duk_uint32_t old_len;
61075 		duk_harray *a;
61076 
61077 		a = (duk_harray *) orig;
61078 		DUK_HARRAY_ASSERT_VALID(a);
61079 
61080 		old_len = a->length;
61081 
61082 		if (arr_idx >= old_len) {
61083 			DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
61084 			                     "(arr_idx=%ld, old_len=%ld)",
61085 			                     (long) arr_idx, (long) old_len));
61086 
61087 			if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
61088 				DUK_DD(DUK_DDPRINT("attempt to extend array, but array 'length' is not writable"));
61089 				goto fail_not_writable;
61090 			}
61091 
61092 			/* Note: actual update happens once write has been completed
61093 			 * without error below.  The write should always succeed
61094 			 * from a specification viewpoint, but we may e.g. run out
61095 			 * of memory.  It's safer in this order.
61096 			 */
61097 
61098 			DUK_ASSERT(arr_idx != 0xffffffffUL);
61099 			new_array_length = arr_idx + 1;  /* flag for later write */
61100 		} else {
61101 			DUK_DDD(DUK_DDDPRINT("write new array entry does not require length update "
61102 			                     "(arr_idx=%ld, old_len=%ld)",
61103 			                     (long) arr_idx, (long) old_len));
61104 		}
61105 	}
61106 
61107  /* write_to_array_part: */
61108 
61109 	/*
61110 	 *  Write to array part?
61111 	 *
61112 	 *  Note: array abandonding requires a property resize which uses
61113 	 *  'rechecks' valstack for temporaries and may cause any existing
61114 	 *  valstack pointers to be invalidated.  To protect against this,
61115 	 *  tv_obj, tv_key, and tv_val are copies of the original inputs.
61116 	 */
61117 
61118 	if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(orig)) {
61119 		tv = duk__obtain_arridx_slot(thr, arr_idx, orig);
61120 		if (tv == NULL) {
61121 			DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(orig));
61122 			goto write_to_entry_part;
61123 		}
61124 
61125 		/* prev value must be unused, no decref */
61126 		DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));
61127 		DUK_TVAL_SET_TVAL(tv, tv_val);
61128 		DUK_TVAL_INCREF(thr, tv);
61129 		DUK_DD(DUK_DDPRINT("put to new array entry: %ld -> %!T",
61130 		                   (long) arr_idx, (duk_tval *) tv));
61131 
61132 		/* Note: array part values are [[Writable]], [[Enumerable]],
61133 		 * and [[Configurable]] which matches the required attributes
61134 		 * here.
61135 		 */
61136 		goto entry_updated;
61137 	}
61138 
61139  write_to_entry_part:
61140 
61141 	/*
61142 	 *  Write to entry part
61143 	 */
61144 
61145 	/* entry allocation updates hash part and increases the key
61146 	 * refcount; may need a props allocation resize but doesn't
61147 	 * 'recheck' the valstack.
61148 	 */
61149 	e_idx = duk__hobject_alloc_entry_checked(thr, orig, key);
61150 	DUK_ASSERT(e_idx >= 0);
61151 
61152 	tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, e_idx);
61153 	/* prev value can be garbage, no decref */
61154 	DUK_TVAL_SET_TVAL(tv, tv_val);
61155 	DUK_TVAL_INCREF(thr, tv);
61156 	DUK_HOBJECT_E_SET_FLAGS(thr->heap, orig, e_idx, DUK_PROPDESC_FLAGS_WEC);
61157 	goto entry_updated;
61158 
61159  entry_updated:
61160 
61161 	/*
61162 	 *  Possible pending array length update, which must only be done
61163 	 *  if the actual entry write succeeded.
61164 	 */
61165 
61166 	if (new_array_length > 0) {
61167 		/* Note: zero works as a "no update" marker because the new length
61168 		 * can never be zero after a new property is written.
61169 		 */
61170 
61171 		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig));
61172 
61173 		DUK_DDD(DUK_DDDPRINT("write successful, pending array length update to: %ld",
61174 		                     (long) new_array_length));
61175 
61176 		((duk_harray *) orig)->length = new_array_length;
61177 	}
61178 
61179 	/*
61180 	 *  Arguments exotic behavior not possible for new properties: all
61181 	 *  magically bound properties are initially present in the arguments
61182 	 *  object, and if they are deleted, the binding is also removed from
61183 	 *  parameter map.
61184 	 */
61185 
61186 	goto success_no_arguments_exotic;
61187 
61188  success_with_arguments_exotic:
61189 
61190 	/*
61191 	 *  Arguments objects have exotic [[DefineOwnProperty]] which updates
61192 	 *  the internal 'map' of arguments for writes to currently mapped
61193 	 *  arguments.  More conretely, writes to mapped arguments generate
61194 	 *  a write to a bound variable.
61195 	 *
61196 	 *  The [[Put]] algorithm invokes [[DefineOwnProperty]] for existing
61197 	 *  data properties and new properties, but not for existing accessors.
61198 	 *  Hence, in E5 Section 10.6 ([[DefinedOwnProperty]] algorithm), we
61199 	 *  have a Desc with 'Value' (and possibly other properties too), and
61200 	 *  we end up in step 5.b.i.
61201 	 */
61202 
61203 	if (arr_idx != DUK__NO_ARRAY_INDEX &&
61204 	    DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
61205 		/* Note: only numbered indices are relevant, so arr_idx fast reject
61206 		 * is good (this is valid unless there are more than 4**32-1 arguments).
61207 		 */
61208 
61209 		DUK_DDD(DUK_DDDPRINT("putprop successful, arguments exotic behavior needed"));
61210 
61211 		/* Note: we can reuse 'desc' here */
61212 
61213 		/* XXX: top of stack must contain value, which helper doesn't touch,
61214 		 * rework to use tv_val directly?
61215 		 */
61216 
61217 		duk_push_tval(thr, tv_val);
61218 		(void) duk__check_arguments_map_for_put(thr, orig, key, &desc, throw_flag);
61219 		duk_pop_unsafe(thr);
61220 	}
61221 	/* fall thru */
61222 
61223  success_no_arguments_exotic:
61224 	/* shared exit path now */
61225 	DUK_DDD(DUK_DDDPRINT("result: success"));
61226 	duk_pop_unsafe(thr);  /* remove key */
61227 	return 1;
61228 
61229 #if defined(DUK_USE_ES6_PROXY)
61230  fail_proxy_rejected:
61231 	DUK_DDD(DUK_DDDPRINT("result: error, proxy rejects"));
61232 	if (throw_flag) {
61233 		DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
61234 		DUK_WO_NORETURN(return 0;);
61235 	}
61236 	/* Note: no key on stack */
61237 	return 0;
61238 #endif
61239 
61240  fail_base_primitive:
61241 	DUK_DDD(DUK_DDDPRINT("result: error, base primitive"));
61242 	if (throw_flag) {
61243 #if defined(DUK_USE_PARANOID_ERRORS)
61244 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
61245 #else
61246 		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
61247 		               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
61248 #endif
61249 		DUK_WO_NORETURN(return 0;);
61250 	}
61251 	duk_pop_unsafe(thr);  /* remove key */
61252 	return 0;
61253 
61254  fail_not_extensible:
61255 	DUK_DDD(DUK_DDDPRINT("result: error, not extensible"));
61256 	if (throw_flag) {
61257 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE);
61258 		DUK_WO_NORETURN(return 0;);
61259 	}
61260 	duk_pop_unsafe(thr);  /* remove key */
61261 	return 0;
61262 
61263  fail_not_writable:
61264 	DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
61265 	if (throw_flag) {
61266 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);
61267 		DUK_WO_NORETURN(return 0;);
61268 	}
61269 	duk_pop_unsafe(thr);  /* remove key */
61270 	return 0;
61271 
61272 #if defined(DUK_USE_ROM_OBJECTS)
61273  fail_not_writable_no_pop:
61274 	DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
61275 	if (throw_flag) {
61276 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);
61277 		DUK_WO_NORETURN(return 0;);
61278 	}
61279 	return 0;
61280 #endif
61281 
61282  fail_array_length_partial:
61283 	DUK_DD(DUK_DDPRINT("result: error, array length write only partially successful"));
61284 	if (throw_flag) {
61285 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
61286 		DUK_WO_NORETURN(return 0;);
61287 	}
61288 	duk_pop_unsafe(thr);  /* remove key */
61289 	return 0;
61290 
61291  fail_no_setter:
61292 	DUK_DDD(DUK_DDDPRINT("result: error, accessor property without setter"));
61293 	if (throw_flag) {
61294 		DUK_ERROR_TYPE(thr, DUK_STR_SETTER_UNDEFINED);
61295 		DUK_WO_NORETURN(return 0;);
61296 	}
61297 	duk_pop_unsafe(thr);  /* remove key */
61298 	return 0;
61299 
61300  fail_internal:
61301 	DUK_DDD(DUK_DDDPRINT("result: error, internal"));
61302 	if (throw_flag) {
61303 		DUK_ERROR_INTERNAL(thr);
61304 		DUK_WO_NORETURN(return 0;);
61305 	}
61306 	duk_pop_unsafe(thr);  /* remove key */
61307 	return 0;
61308 }
61309 
61310 /*
61311  *  ECMAScript compliant [[Delete]](P, Throw).
61312  */
61313 
61314 DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
61315 	duk_propdesc desc;
61316 	duk_tval *tv;
61317 	duk_uint32_t arr_idx;
61318 	duk_bool_t throw_flag;
61319 	duk_bool_t force_flag;
61320 
61321 	throw_flag = (flags & DUK_DELPROP_FLAG_THROW);
61322 	force_flag = (flags & DUK_DELPROP_FLAG_FORCE);
61323 
61324 	DUK_DDD(DUK_DDDPRINT("delprop_raw: thr=%p, obj=%p, key=%p, throw=%ld, force=%ld (obj -> %!O, key -> %!O)",
61325 	                     (void *) thr, (void *) obj, (void *) key, (long) throw_flag, (long) force_flag,
61326 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
61327 
61328 	DUK_ASSERT(thr != NULL);
61329 	DUK_ASSERT(thr->heap != NULL);
61330 	DUK_ASSERT(obj != NULL);
61331 	DUK_ASSERT(key != NULL);
61332 
61333 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
61334 
61335 	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
61336 
61337 	/* 0 = don't push current value */
61338 	if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
61339 		DUK_DDD(DUK_DDDPRINT("property not found, succeed always"));
61340 		goto success;
61341 	}
61342 
61343 #if defined(DUK_USE_ROM_OBJECTS)
61344 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
61345 		DUK_DD(DUK_DDPRINT("attempt to delprop on read-only target object"));
61346 		goto fail_not_configurable;
61347 	}
61348 #endif
61349 
61350 	if ((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) == 0 && !force_flag) {
61351 		goto fail_not_configurable;
61352 	}
61353 	if (desc.a_idx < 0 && desc.e_idx < 0) {
61354 		/* Currently there are no deletable virtual properties, but
61355 		 * with force_flag we might attempt to delete one.
61356 		 */
61357 		DUK_DD(DUK_DDPRINT("delete failed: property found, force flag, but virtual (and implicitly non-configurable)"));
61358 		goto fail_virtual;
61359 	}
61360 
61361 	if (desc.a_idx >= 0) {
61362 		DUK_ASSERT(desc.e_idx < 0);
61363 
61364 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
61365 		DUK_TVAL_SET_UNUSED_UPDREF(thr, tv);  /* side effects */
61366 		goto success;
61367 	} else {
61368 		DUK_ASSERT(desc.a_idx < 0);
61369 
61370 		/* remove hash entry (no decref) */
61371 #if defined(DUK_USE_HOBJECT_HASH_PART)
61372 		if (desc.h_idx >= 0) {
61373 			duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
61374 
61375 			DUK_DDD(DUK_DDDPRINT("removing hash entry at h_idx %ld", (long) desc.h_idx));
61376 			DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) > 0);
61377 			DUK_ASSERT((duk_uint32_t) desc.h_idx < DUK_HOBJECT_GET_HSIZE(obj));
61378 			h_base[desc.h_idx] = DUK__HASH_DELETED;
61379 		} else {
61380 			DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) == 0);
61381 		}
61382 #else
61383 		DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) == 0);
61384 #endif
61385 
61386 		/* Remove value.  This requires multiple writes so avoid side
61387 		 * effects via no-refzero macros so that e_idx is not
61388 		 * invalidated.
61389 		 */
61390 		DUK_DDD(DUK_DDDPRINT("before removing value, e_idx %ld, key %p, key at slot %p",
61391 		                     (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
61392 		DUK_DDD(DUK_DDDPRINT("removing value at e_idx %ld", (long) desc.e_idx));
61393 		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx)) {
61394 			duk_hobject *tmp;
61395 
61396 			tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, desc.e_idx);
61397 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, desc.e_idx, NULL);
61398 			DUK_UNREF(tmp);
61399 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
61400 
61401 			tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, desc.e_idx);
61402 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, desc.e_idx, NULL);
61403 			DUK_UNREF(tmp);
61404 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
61405 		} else {
61406 			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
61407 			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
61408 		}
61409 #if 0
61410 		/* Not strictly necessary because if key == NULL, flag MUST be ignored. */
61411 		DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, 0);
61412 #endif
61413 
61414 		/* Remove key. */
61415 		DUK_DDD(DUK_DDDPRINT("before removing key, e_idx %ld, key %p, key at slot %p",
61416 		                     (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
61417 		DUK_DDD(DUK_DDDPRINT("removing key at e_idx %ld", (long) desc.e_idx));
61418 		DUK_ASSERT(key == DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx));
61419 		DUK_HOBJECT_E_SET_KEY(thr->heap, obj, desc.e_idx, NULL);
61420 		DUK_HSTRING_DECREF_NORZ(thr, key);
61421 
61422 		/* Trigger refzero side effects only when we're done as a
61423 		 * finalizer might operate on the object and affect the
61424 		 * e_idx we're supposed to use.
61425 		 */
61426 		DUK_REFZERO_CHECK_SLOW(thr);
61427 		goto success;
61428 	}
61429 
61430 	DUK_UNREACHABLE();
61431 
61432  success:
61433 	/*
61434 	 *  Argument exotic [[Delete]] behavior (E5 Section 10.6) is
61435 	 *  a post-check, keeping arguments internal 'map' in sync with
61436 	 *  any successful deletes (note that property does not need to
61437 	 *  exist for delete to 'succeed').
61438 	 *
61439 	 *  Delete key from 'map'.  Since 'map' only contains array index
61440 	 *  keys, we can use arr_idx for a fast skip.
61441 	 */
61442 
61443 	DUK_DDD(DUK_DDDPRINT("delete successful, check for arguments exotic behavior"));
61444 
61445 	if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {
61446 		/* Note: only numbered indices are relevant, so arr_idx fast reject
61447 		 * is good (this is valid unless there are more than 4**32-1 arguments).
61448 		 */
61449 
61450 		DUK_DDD(DUK_DDDPRINT("delete successful, arguments exotic behavior needed"));
61451 
61452 		/* Note: we can reuse 'desc' here */
61453 		(void) duk__check_arguments_map_for_delete(thr, obj, key, &desc);
61454 	}
61455 
61456 	DUK_DDD(DUK_DDDPRINT("delete successful"));
61457 	return 1;
61458 
61459  fail_virtual:  /* just use the same "not configurable" error message */
61460  fail_not_configurable:
61461 	DUK_DDD(DUK_DDDPRINT("delete failed: property found, not configurable"));
61462 
61463 	if (throw_flag) {
61464 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
61465 		DUK_WO_NORETURN(return 0;);
61466 	}
61467 	return 0;
61468 }
61469 
61470 /*
61471  *  DELPROP: ECMAScript property deletion.
61472  */
61473 
61474 DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag) {
61475 	duk_hstring *key = NULL;
61476 #if defined(DUK_USE_ES6_PROXY)
61477 	duk_propdesc desc;
61478 #endif
61479 	duk_int_t entry_top;
61480 	duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
61481 	duk_bool_t rc;
61482 
61483 	DUK_DDD(DUK_DDDPRINT("delprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
61484 	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
61485 	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));
61486 
61487 	DUK_ASSERT(thr != NULL);
61488 	DUK_ASSERT(thr->heap != NULL);
61489 	DUK_ASSERT(tv_obj != NULL);
61490 	DUK_ASSERT(tv_key != NULL);
61491 
61492 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
61493 
61494 	/* Storing the entry top is cheaper here to ensure stack is correct at exit,
61495 	 * as there are several paths out.
61496 	 */
61497 	entry_top = duk_get_top(thr);
61498 
61499 	if (DUK_TVAL_IS_UNDEFINED(tv_obj) ||
61500 	    DUK_TVAL_IS_NULL(tv_obj)) {
61501 		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
61502 		goto fail_invalid_base_uncond;
61503 	}
61504 
61505 	duk_push_tval(thr, tv_obj);
61506 	duk_push_tval(thr, tv_key);
61507 
61508 	tv_obj = DUK_GET_TVAL_NEGIDX(thr, -2);
61509 	if (DUK_TVAL_IS_OBJECT(tv_obj)) {
61510 		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_obj);
61511 		DUK_ASSERT(obj != NULL);
61512 
61513 #if defined(DUK_USE_ES6_PROXY)
61514 		if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(obj))) {
61515 			duk_hobject *h_target;
61516 			duk_bool_t tmp_bool;
61517 
61518 			/* Note: proxy handling must happen before key is string coerced. */
61519 
61520 			if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_DELETE_PROPERTY, tv_key, &h_target)) {
61521 				/* -> [ ... obj key trap handler ] */
61522 				DUK_DDD(DUK_DDDPRINT("-> proxy object 'deleteProperty' for key %!T", (duk_tval *) tv_key));
61523 				duk_push_hobject(thr, h_target);  /* target */
61524 				duk_dup_m4(thr);  /* P */
61525 				duk_call_method(thr, 2 /*nargs*/);
61526 				tmp_bool = duk_to_boolean_top_pop(thr);
61527 				if (!tmp_bool) {
61528 					goto fail_proxy_rejected;  /* retval indicates delete failed */
61529 				}
61530 
61531 				/* Target object must be checked for a conflicting
61532 				 * non-configurable property.
61533 				 */
61534 				tv_key = DUK_GET_TVAL_NEGIDX(thr, -1);
61535 				arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
61536 				DUK_ASSERT(key != NULL);
61537 
61538 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
61539 					duk_small_int_t desc_reject;
61540 
61541 					DUK_DDD(DUK_DDDPRINT("proxy 'deleteProperty': target has matching property %!O, check for "
61542 					                     "conflicting property; desc.flags=0x%08lx, "
61543 					                     "desc.get=%p, desc.set=%p",
61544 					                     (duk_heaphdr *) key, (unsigned long) desc.flags,
61545 					                     (void *) desc.get, (void *) desc.set));
61546 
61547 					desc_reject = !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE);
61548 					if (desc_reject) {
61549 						/* unconditional */
61550 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
61551 						DUK_WO_NORETURN(return 0;);
61552 					}
61553 				}
61554 				rc = 1;  /* success */
61555 				goto done_rc;
61556 			}
61557 
61558 			obj = h_target;  /* resume delete to target */
61559 		}
61560 #endif  /* DUK_USE_ES6_PROXY */
61561 
61562 		arr_idx = duk__to_property_key(thr, -1, &key);
61563 		DUK_ASSERT(key != NULL);
61564 
61565 		rc = duk_hobject_delprop_raw(thr, obj, key, throw_flag ? DUK_DELPROP_FLAG_THROW : 0);
61566 		goto done_rc;
61567 	} else if (DUK_TVAL_IS_STRING(tv_obj)) {
61568 		/* String has .length and array index virtual properties
61569 		 * which can't be deleted.  No need for a symbol check;
61570 		 * no offending virtual symbols exist.
61571 		 */
61572 		/* XXX: unnecessary string coercion for array indices,
61573 		 * intentional to keep small.
61574 		 */
61575 		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
61576 		DUK_ASSERT(h != NULL);
61577 
61578 		arr_idx = duk__to_property_key(thr, -1, &key);
61579 		DUK_ASSERT(key != NULL);
61580 
61581 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
61582 			goto fail_not_configurable;
61583 		}
61584 
61585 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
61586 		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
61587 			goto fail_not_configurable;
61588 		}
61589 	} else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
61590 		/* XXX: unnecessary string coercion for array indices,
61591 		 * intentional to keep small; some overlap with string
61592 		 * handling.
61593 		 */
61594 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
61595 		DUK_ASSERT(h != NULL);
61596 
61597 		arr_idx = duk__to_property_key(thr, -1, &key);
61598 		DUK_ASSERT(key != NULL);
61599 
61600 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
61601 			goto fail_not_configurable;
61602 		}
61603 
61604 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
61605 		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
61606 			goto fail_not_configurable;
61607 		}
61608 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
61609 		/* Lightfunc has no virtual properties since Duktape 2.2
61610 		 * so success.  Still must coerce key for side effects.
61611 		 */
61612 
61613 		arr_idx = duk__to_property_key(thr, -1, &key);
61614 		DUK_ASSERT(key != NULL);
61615 		DUK_UNREF(key);
61616 	}
61617 
61618 	/* non-object base, no offending virtual property */
61619 	rc = 1;
61620 	goto done_rc;
61621 
61622  done_rc:
61623 	duk_set_top_unsafe(thr, entry_top);
61624 	return rc;
61625 
61626  fail_invalid_base_uncond:
61627 	/* Note: unconditional throw */
61628 	DUK_ASSERT(duk_get_top(thr) == entry_top);
61629 #if defined(DUK_USE_PARANOID_ERRORS)
61630 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
61631 #else
61632 	DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot delete property %s of %s",
61633 	               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
61634 #endif
61635 	DUK_WO_NORETURN(return 0;);
61636 
61637 #if defined(DUK_USE_ES6_PROXY)
61638  fail_proxy_rejected:
61639 	if (throw_flag) {
61640 		DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
61641 		DUK_WO_NORETURN(return 0;);
61642 	}
61643 	duk_set_top_unsafe(thr, entry_top);
61644 	return 0;
61645 #endif
61646 
61647  fail_not_configurable:
61648 	if (throw_flag) {
61649 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
61650 		DUK_WO_NORETURN(return 0;);
61651 	}
61652 	duk_set_top_unsafe(thr, entry_top);
61653 	return 0;
61654 }
61655 
61656 /*
61657  *  Internal helper to define a property with specific flags, ignoring
61658  *  normal semantics such as extensibility, write protection etc.
61659  *  Overwrites any existing value and attributes unless caller requests
61660  *  that value only be updated if it doesn't already exists.
61661  *
61662  *  Does not support:
61663  *    - virtual properties (error if write attempted)
61664  *    - getter/setter properties (error if write attempted)
61665  *    - non-default (!= WEC) attributes for array entries (error if attempted)
61666  *    - array abandoning: if array part exists, it is always extended
61667  *    - array 'length' updating
61668  *
61669  *  Stack: [... in_val] -> []
61670  *
61671  *  Used for e.g. built-in initialization and environment record
61672  *  operations.
61673  */
61674 
61675 DUK_INTERNAL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
61676 	duk_propdesc desc;
61677 	duk_uint32_t arr_idx;
61678 	duk_int_t e_idx;
61679 	duk_tval *tv1 = NULL;
61680 	duk_tval *tv2 = NULL;
61681 	duk_small_uint_t propflags = flags & DUK_PROPDESC_FLAGS_MASK;  /* mask out flags not actually stored */
61682 
61683 	DUK_DDD(DUK_DDDPRINT("define new property (internal): thr=%p, obj=%!O, key=%!O, flags=0x%02lx, val=%!T",
61684 	                     (void *) thr, (duk_heaphdr *) obj, (duk_heaphdr *) key,
61685 	                     (unsigned long) flags, (duk_tval *) duk_get_tval(thr, -1)));
61686 
61687 	DUK_ASSERT(thr != NULL);
61688 	DUK_ASSERT(thr->heap != NULL);
61689 	DUK_ASSERT(obj != NULL);
61690 	DUK_ASSERT(key != NULL);
61691 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
61692 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
61693 	DUK_ASSERT(duk_is_valid_index(thr, -1));  /* contains value */
61694 
61695 	arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
61696 
61697 	if (duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
61698 		if (desc.e_idx >= 0) {
61699 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
61700 				DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> skip as requested"));
61701 				goto pop_exit;
61702 			}
61703 			DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> update value and attributes"));
61704 			if (DUK_UNLIKELY(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx))) {
61705 				DUK_D(DUK_DPRINT("existing property is an accessor, not supported"));
61706 				goto error_internal;
61707 			}
61708 
61709 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, propflags);
61710 			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
61711 		} else if (desc.a_idx >= 0) {
61712 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
61713 				DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> skip as requested"));
61714 				goto pop_exit;
61715 			}
61716 			DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> update value (assert attributes)"));
61717 			if (propflags != DUK_PROPDESC_FLAGS_WEC) {
61718 				DUK_D(DUK_DPRINT("existing property in array part, but propflags not WEC (0x%02lx)",
61719 				                 (unsigned long) propflags));
61720 				goto error_internal;
61721 			}
61722 
61723 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
61724 		} else {
61725 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
61726 				DUK_DDD(DUK_DDDPRINT("property already exists but is virtual -> skip as requested"));
61727 				goto pop_exit;
61728 			}
61729 			if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
61730 				duk_uint32_t new_len;
61731 #if defined(DUK_USE_DEBUG)
61732 				duk_uint32_t prev_len;
61733 				prev_len = ((duk_harray *) obj)->length;
61734 #endif
61735 				new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_NEGIDX(thr, -1));
61736 				((duk_harray *) obj)->length = new_len;
61737 				DUK_DD(DUK_DDPRINT("internal define property for array .length: %ld -> %ld",
61738 				                   (long) prev_len, (long) ((duk_harray *) obj)->length));
61739 				goto pop_exit;
61740 			}
61741 			DUK_DD(DUK_DDPRINT("property already exists but is virtual -> failure"));
61742 			goto error_virtual;
61743 		}
61744 
61745 		goto write_value;
61746 	}
61747 
61748 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
61749 		if (arr_idx != DUK__NO_ARRAY_INDEX) {
61750 			DUK_DDD(DUK_DDDPRINT("property does not exist, object has array part -> possibly extend array part and write value (assert attributes)"));
61751 			DUK_ASSERT(propflags == DUK_PROPDESC_FLAGS_WEC);
61752 
61753 			tv1 = duk__obtain_arridx_slot(thr, arr_idx, obj);
61754 			if (tv1 == NULL) {
61755 				DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(obj));
61756 				goto write_to_entry_part;
61757 			}
61758 
61759 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
61760 			goto write_value;
61761 		}
61762 	}
61763 
61764  write_to_entry_part:
61765 	DUK_DDD(DUK_DDDPRINT("property does not exist, object belongs in entry part -> allocate new entry and write value and attributes"));
61766 	e_idx = duk__hobject_alloc_entry_checked(thr, obj, key);  /* increases key refcount */
61767 	DUK_ASSERT(e_idx >= 0);
61768 	DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, propflags);
61769 	tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
61770 	/* new entry: previous value is garbage; set to undefined to share write_value */
61771 	DUK_TVAL_SET_UNDEFINED(tv1);
61772 	goto write_value;
61773 
61774  write_value:
61775 	/* tv1 points to value storage */
61776 
61777 	tv2 = duk_require_tval(thr, -1);  /* late lookup, avoid side effects */
61778 	DUK_DDD(DUK_DDDPRINT("writing/updating value: %!T -> %!T",
61779 	                     (duk_tval *) tv1, (duk_tval *) tv2));
61780 
61781 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
61782 	goto pop_exit;
61783 
61784  pop_exit:
61785 	duk_pop_unsafe(thr);  /* remove in_val */
61786 	return;
61787 
61788  error_virtual:  /* share error message */
61789  error_internal:
61790 	DUK_ERROR_INTERNAL(thr);
61791 	DUK_WO_NORETURN(return;);
61792 }
61793 
61794 /*
61795  *  Fast path for defining array indexed values without interning the key.
61796  *  This is used by e.g. code for Array prototype and traceback creation so
61797  *  must avoid interning.
61798  */
61799 
61800 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) {
61801 	duk_hstring *key;
61802 	duk_tval *tv1, *tv2;
61803 
61804 	DUK_DDD(DUK_DDDPRINT("define new property (internal) arr_idx fast path: thr=%p, obj=%!O, "
61805 	                     "arr_idx=%ld, flags=0x%02lx, val=%!T",
61806 	                     (void *) thr, obj, (long) arr_idx, (unsigned long) flags,
61807 	                     (duk_tval *) duk_get_tval(thr, -1)));
61808 
61809 	DUK_ASSERT(thr != NULL);
61810 	DUK_ASSERT(thr->heap != NULL);
61811 	DUK_ASSERT(obj != NULL);
61812 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
61813 
61814 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
61815 	    arr_idx != DUK__NO_ARRAY_INDEX &&
61816 	    flags == DUK_PROPDESC_FLAGS_WEC) {
61817 		DUK_ASSERT((flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) == 0);  /* covered by comparison */
61818 
61819 		DUK_DDD(DUK_DDDPRINT("define property to array part (property may or may not exist yet)"));
61820 
61821 		tv1 = duk__obtain_arridx_slot(thr, arr_idx, obj);
61822 		if (tv1 == NULL) {
61823 			DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(obj));
61824 			goto write_slow;
61825 		}
61826 		tv2 = duk_require_tval(thr, -1);
61827 
61828 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
61829 
61830 		duk_pop_unsafe(thr);  /* [ ...val ] -> [ ... ] */
61831 		return;
61832 	}
61833 
61834  write_slow:
61835 	DUK_DDD(DUK_DDDPRINT("define property fast path didn't work, use slow path"));
61836 
61837 	key = duk_push_uint_to_hstring(thr, (duk_uint_t) arr_idx);
61838 	DUK_ASSERT(key != NULL);
61839 	duk_insert(thr, -2);  /* [ ... val key ] -> [ ... key val ] */
61840 
61841 	duk_hobject_define_property_internal(thr, obj, key, flags);
61842 
61843 	duk_pop_unsafe(thr);  /* [ ... key ] -> [ ... ] */
61844 }
61845 
61846 /*
61847  *  Internal helpers for managing object 'length'
61848  */
61849 
61850 DUK_INTERNAL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj) {
61851 	duk_double_t val;
61852 
61853 	DUK_CTX_ASSERT_VALID(thr);
61854 	DUK_ASSERT(obj != NULL);
61855 
61856 	/* Fast path for Arrays. */
61857 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
61858 		return ((duk_harray *) obj)->length;
61859 	}
61860 
61861 	/* Slow path, .length can be e.g. accessor, obj can be a Proxy, etc. */
61862 	duk_push_hobject(thr, obj);
61863 	duk_push_hstring_stridx(thr, DUK_STRIDX_LENGTH);
61864 	(void) duk_hobject_getprop(thr,
61865 	                           DUK_GET_TVAL_NEGIDX(thr, -2),
61866 	                           DUK_GET_TVAL_NEGIDX(thr, -1));
61867 	val = duk_to_number_m1(thr);
61868 	duk_pop_3_unsafe(thr);
61869 
61870 	/* This isn't part of ECMAScript semantics; return a value within
61871 	 * duk_size_t range, or 0 otherwise.
61872 	 */
61873 	if (val >= 0.0 && val <= (duk_double_t) DUK_SIZE_MAX) {
61874 		return (duk_size_t) val;
61875 	}
61876 	return 0;
61877 }
61878 
61879 /*
61880  *  Fast finalizer check for an object.  Walks the prototype chain, checking
61881  *  for finalizer presence using DUK_HOBJECT_FLAG_HAVE_FINALIZER which is kept
61882  *  in sync with the actual property when setting/removing the finalizer.
61883  */
61884 
61885 #if defined(DUK_USE_HEAPPTR16)
61886 DUK_INTERNAL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_heap *heap, duk_hobject *obj) {
61887 #else
61888 DUK_INTERNAL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_hobject *obj) {
61889 #endif
61890 	duk_uint_t sanity;
61891 
61892 	DUK_ASSERT(obj != NULL);
61893 
61894 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
61895 	do {
61896 		if (DUK_UNLIKELY(DUK_HOBJECT_HAS_HAVE_FINALIZER(obj))) {
61897 			return 1;
61898 		}
61899 		if (DUK_UNLIKELY(sanity-- == 0)) {
61900 			DUK_D(DUK_DPRINT("prototype loop when checking for finalizer existence; returning false"));
61901 			return 0;
61902 		}
61903 #if defined(DUK_USE_HEAPPTR16)
61904 		DUK_ASSERT(heap != NULL);
61905 		obj = DUK_HOBJECT_GET_PROTOTYPE(heap, obj);
61906 #else
61907 		obj = DUK_HOBJECT_GET_PROTOTYPE(NULL, obj);  /* 'heap' arg ignored */
61908 #endif
61909 	} while (obj != NULL);
61910 
61911 	return 0;
61912 }
61913 
61914 /*
61915  *  Object.getOwnPropertyDescriptor()  (E5 Sections 15.2.3.3, 8.10.4)
61916  *
61917  *  [ ... key ] -> [ ... desc/undefined ]
61918  */
61919 
61920 DUK_INTERNAL void duk_hobject_object_get_own_property_descriptor(duk_hthread *thr, duk_idx_t obj_idx) {
61921 	duk_hobject *obj;
61922 	duk_hstring *key;
61923 	duk_propdesc pd;
61924 
61925 	DUK_ASSERT(thr != NULL);
61926 	DUK_ASSERT(thr->heap != NULL);
61927 
61928 	obj = duk_require_hobject_promote_mask(thr, obj_idx, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
61929 	key = duk_to_property_key_hstring(thr, -1);
61930 	DUK_ASSERT(key != NULL);
61931 
61932 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
61933 
61934 	if (!duk_hobject_get_own_propdesc(thr, obj, key, &pd, DUK_GETDESC_FLAG_PUSH_VALUE)) {
61935 		duk_push_undefined(thr);
61936 		duk_remove_m2(thr);
61937 		return;
61938 	}
61939 
61940 	duk_push_object(thr);
61941 
61942 	/* [ ... key value desc ] */
61943 
61944 	if (DUK_PROPDESC_IS_ACCESSOR(&pd)) {
61945 		/* If a setter/getter is missing (undefined), the descriptor must
61946 		 * still have the property present with the value 'undefined'.
61947 		 */
61948 		if (pd.get) {
61949 			duk_push_hobject(thr, pd.get);
61950 		} else {
61951 			duk_push_undefined(thr);
61952 		}
61953 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_GET);
61954 		if (pd.set) {
61955 			duk_push_hobject(thr, pd.set);
61956 		} else {
61957 			duk_push_undefined(thr);
61958 		}
61959 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_SET);
61960 	} else {
61961 		duk_dup_m2(thr);
61962 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_VALUE);
61963 		duk_push_boolean(thr, DUK_PROPDESC_IS_WRITABLE(&pd));
61964 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_WRITABLE);
61965 	}
61966 	duk_push_boolean(thr, DUK_PROPDESC_IS_ENUMERABLE(&pd));
61967 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_ENUMERABLE);
61968 	duk_push_boolean(thr, DUK_PROPDESC_IS_CONFIGURABLE(&pd));
61969 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_CONFIGURABLE);
61970 
61971 	/* [ ... key value desc ] */
61972 
61973 	duk_replace(thr, -3);
61974 	duk_pop_unsafe(thr);  /* -> [ ... desc ] */
61975 }
61976 
61977 /*
61978  *  NormalizePropertyDescriptor() related helper.
61979  *
61980  *  Internal helper which validates and normalizes a property descriptor
61981  *  represented as an ECMAScript object (e.g. argument to defineProperty()).
61982  *  The output of this conversion is a set of defprop_flags and possibly
61983  *  some values pushed on the value stack to (1) ensure borrowed pointers
61984  *  remain valid, and (2) avoid unnecessary pops for footprint reasons.
61985  *  Caller must manage stack top carefully because the number of values
61986  *  pushed depends on the input property descriptor.
61987  *
61988  *  The original descriptor object must not be altered in the process.
61989  */
61990 
61991 /* XXX: very basic optimization -> duk_get_prop_stridx_top */
61992 
61993 DUK_INTERNAL
61994 void duk_hobject_prepare_property_descriptor(duk_hthread *thr,
61995                                              duk_idx_t idx_in,
61996                                              duk_uint_t *out_defprop_flags,
61997                                              duk_idx_t *out_idx_value,
61998                                              duk_hobject **out_getter,
61999                                              duk_hobject **out_setter) {
62000 	duk_idx_t idx_value = -1;
62001 	duk_hobject *getter = NULL;
62002 	duk_hobject *setter = NULL;
62003 	duk_bool_t is_data_desc = 0;
62004 	duk_bool_t is_acc_desc = 0;
62005 	duk_uint_t defprop_flags = 0;
62006 
62007 	DUK_ASSERT(out_defprop_flags != NULL);
62008 	DUK_ASSERT(out_idx_value != NULL);
62009 	DUK_ASSERT(out_getter != NULL);
62010 	DUK_ASSERT(out_setter != NULL);
62011 	DUK_ASSERT(idx_in <= 0x7fffL);  /* short variants would be OK, but not used to avoid shifts */
62012 
62013 	/* Must be an object, otherwise TypeError (E5.1 Section 8.10.5, step 1). */
62014 	idx_in = duk_require_normalize_index(thr, idx_in);
62015 	(void) duk_require_hobject(thr, idx_in);
62016 
62017 	/* The coercion order must match the ToPropertyDescriptor() algorithm
62018 	 * so that side effects in coercion happen in the correct order.
62019 	 * (This order also happens to be compatible with duk_def_prop(),
62020 	 * although it doesn't matter in practice.)
62021 	 */
62022 
62023 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_VALUE)) {
62024 		is_data_desc = 1;
62025 		defprop_flags |= DUK_DEFPROP_HAVE_VALUE;
62026 		idx_value = duk_get_top_index(thr);
62027 	}
62028 
62029 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_WRITABLE)) {
62030 		is_data_desc = 1;
62031 		if (duk_to_boolean_top_pop(thr)) {
62032 			defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE;
62033 		} else {
62034 			defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE;
62035 		}
62036 	}
62037 
62038 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_GET)) {
62039 		duk_tval *tv = duk_require_tval(thr, -1);
62040 		duk_hobject *h_get;
62041 
62042 		if (DUK_TVAL_IS_UNDEFINED(tv)) {
62043 			/* undefined is accepted */
62044 			DUK_ASSERT(getter == NULL);
62045 		} else {
62046 			/* NOTE: lightfuncs are coerced to full functions because
62047 			 * lightfuncs don't fit into a property value slot.  This
62048 			 * has some side effects, see test-dev-lightfunc-accessor.js.
62049 			 */
62050 			h_get = duk_get_hobject_promote_lfunc(thr, -1);
62051 			if (h_get == NULL || !DUK_HOBJECT_IS_CALLABLE(h_get)) {
62052 				goto type_error;
62053 			}
62054 			getter = h_get;
62055 		}
62056 		is_acc_desc = 1;
62057 		defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
62058 	}
62059 
62060 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_SET)) {
62061 		duk_tval *tv = duk_require_tval(thr, -1);
62062 		duk_hobject *h_set;
62063 
62064 		if (DUK_TVAL_IS_UNDEFINED(tv)) {
62065 			/* undefined is accepted */
62066 			DUK_ASSERT(setter == NULL);
62067 		}  else {
62068 			/* NOTE: lightfuncs are coerced to full functions because
62069 			 * lightfuncs don't fit into a property value slot.  This
62070 			 * has some side effects, see test-dev-lightfunc-accessor.js.
62071 			 */
62072 			h_set = duk_get_hobject_promote_lfunc(thr, -1);
62073 			if (h_set == NULL || !DUK_HOBJECT_IS_CALLABLE(h_set)) {
62074 				goto type_error;
62075 			}
62076 			setter = h_set;
62077 		}
62078 		is_acc_desc = 1;
62079 		defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
62080 	}
62081 
62082 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_ENUMERABLE)) {
62083 		if (duk_to_boolean_top_pop(thr)) {
62084 			defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE;
62085 		} else {
62086 			defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE;
62087 		}
62088 	}
62089 
62090 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_CONFIGURABLE)) {
62091 		if (duk_to_boolean_top_pop(thr)) {
62092 			defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE;
62093 		} else {
62094 			defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE;
62095 		}
62096 	}
62097 
62098 	if (is_data_desc && is_acc_desc) {
62099 		goto type_error;
62100 	}
62101 
62102 	*out_defprop_flags = defprop_flags;
62103 	*out_idx_value = idx_value;
62104 	*out_getter = getter;
62105 	*out_setter = setter;
62106 
62107 	/* [ ... [multiple values] ] */
62108 	return;
62109 
62110  type_error:
62111 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);
62112 	DUK_WO_NORETURN(return;);
62113 }
62114 
62115 /*
62116  *  Object.defineProperty() related helper (E5 Section 15.2.3.6).
62117  *  Also handles ES2015 Reflect.defineProperty().
62118  *
62119  *  Inlines all [[DefineOwnProperty]] exotic behaviors.
62120  *
62121  *  Note: ECMAScript compliant [[DefineOwnProperty]](P, Desc, Throw) is not
62122  *  implemented directly, but Object.defineProperty() serves its purpose.
62123  *  We don't need the [[DefineOwnProperty]] internally and we don't have a
62124  *  property descriptor with 'missing values' so it's easier to avoid it
62125  *  entirely.
62126  *
62127  *  Note: this is only called for actual objects, not primitive values.
62128  *  This must support virtual properties for full objects (e.g. Strings)
62129  *  but not for plain values (e.g. strings).  Lightfuncs, even though
62130  *  primitive in a sense, are treated like objects and accepted as target
62131  *  values.
62132  */
62133 
62134 /* XXX: this is a major target for size optimization */
62135 DUK_INTERNAL
62136 duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
62137                                               duk_uint_t defprop_flags,
62138                                               duk_hobject *obj,
62139                                               duk_hstring *key,
62140                                               duk_idx_t idx_value,
62141                                               duk_hobject *get,
62142                                               duk_hobject *set,
62143                                               duk_bool_t throw_flag) {
62144 	duk_uint32_t arr_idx;
62145 	duk_tval tv;
62146 	duk_bool_t has_enumerable;
62147 	duk_bool_t has_configurable;
62148 	duk_bool_t has_writable;
62149 	duk_bool_t has_value;
62150 	duk_bool_t has_get;
62151 	duk_bool_t has_set;
62152 	duk_bool_t is_enumerable;
62153 	duk_bool_t is_configurable;
62154 	duk_bool_t is_writable;
62155 	duk_bool_t force_flag;
62156 	duk_small_uint_t new_flags;
62157 	duk_propdesc curr;
62158 	duk_uint32_t arridx_new_array_length;  /* != 0 => post-update for array 'length' (used when key is an array index) */
62159 	duk_uint32_t arrlen_old_len;
62160 	duk_uint32_t arrlen_new_len;
62161 	duk_bool_t pending_write_protect;
62162 
62163 	DUK_ASSERT(thr != NULL);
62164 	DUK_ASSERT(thr->heap != NULL);
62165 	DUK_ASSERT(obj != NULL);
62166 	DUK_ASSERT(key != NULL);
62167 	/* idx_value may be < 0 (no value), set and get may be NULL */
62168 
62169 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
62170 
62171 	/* All the flags fit in 16 bits, so will fit into duk_bool_t. */
62172 
62173 	has_writable = (defprop_flags & DUK_DEFPROP_HAVE_WRITABLE);
62174 	has_enumerable = (defprop_flags & DUK_DEFPROP_HAVE_ENUMERABLE);
62175 	has_configurable = (defprop_flags & DUK_DEFPROP_HAVE_CONFIGURABLE);
62176 	has_value = (defprop_flags & DUK_DEFPROP_HAVE_VALUE);
62177 	has_get = (defprop_flags & DUK_DEFPROP_HAVE_GETTER);
62178 	has_set = (defprop_flags & DUK_DEFPROP_HAVE_SETTER);
62179 	is_writable = (defprop_flags & DUK_DEFPROP_WRITABLE);
62180 	is_enumerable = (defprop_flags & DUK_DEFPROP_ENUMERABLE);
62181 	is_configurable = (defprop_flags & DUK_DEFPROP_CONFIGURABLE);
62182 	force_flag = (defprop_flags & DUK_DEFPROP_FORCE);
62183 
62184 	arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
62185 
62186 	arridx_new_array_length = 0;
62187 	pending_write_protect = 0;
62188 	arrlen_old_len = 0;
62189 	arrlen_new_len = 0;
62190 
62191 	DUK_DDD(DUK_DDDPRINT("has_enumerable=%ld is_enumerable=%ld "
62192 	                     "has_configurable=%ld is_configurable=%ld "
62193 	                     "has_writable=%ld is_writable=%ld "
62194 	                     "has_value=%ld value=%!T "
62195 	                     "has_get=%ld get=%p=%!O "
62196 	                     "has_set=%ld set=%p=%!O "
62197 	                     "arr_idx=%ld throw_flag=!%ld",
62198 	                     (long) has_enumerable, (long) is_enumerable,
62199 	                     (long) has_configurable, (long) is_configurable,
62200 	                     (long) has_writable, (long) is_writable,
62201 	                     (long) has_value, (duk_tval *) (idx_value >= 0 ? duk_get_tval(thr, idx_value) : NULL),
62202 	                     (long) has_get, (void *) get, (duk_heaphdr *) get,
62203 	                     (long) has_set, (void *) set, (duk_heaphdr *) set,
62204 	                     (long) arr_idx, (long) throw_flag));
62205 
62206 	/*
62207 	 *  Array exotic behaviors can be implemented at this point.  The local variables
62208 	 *  are essentially a 'value copy' of the input descriptor (Desc), which is modified
62209 	 *  by the Array [[DefineOwnProperty]] (E5 Section 15.4.5.1).
62210 	 */
62211 
62212 	if (!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
62213 		goto skip_array_exotic;
62214 	}
62215 
62216 	if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
62217 		duk_harray *a;
62218 
62219 		/* E5 Section 15.4.5.1, step 3, steps a - i are implemented here, j - n at the end */
62220 		if (!has_value) {
62221 			DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', but no value in descriptor -> normal behavior"));
62222 			goto skip_array_exotic;
62223 		}
62224 
62225 		DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', value present in descriptor -> exotic behavior"));
62226 
62227 		/*
62228 		 *  Get old and new length
62229 		 */
62230 
62231 		a = (duk_harray *) obj;
62232 		DUK_HARRAY_ASSERT_VALID(a);
62233 		arrlen_old_len = a->length;
62234 
62235 		DUK_ASSERT(idx_value >= 0);
62236 		arrlen_new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_POSIDX(thr, idx_value));
62237 		duk_push_u32(thr, arrlen_new_len);
62238 		duk_replace(thr, idx_value);  /* step 3.e: replace 'Desc.[[Value]]' */
62239 
62240 		DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) arrlen_old_len, (long) arrlen_new_len));
62241 
62242 		if (arrlen_new_len >= arrlen_old_len) {
62243 			/* standard behavior, step 3.f.i */
62244 			DUK_DDD(DUK_DDDPRINT("new length is same or higher as previous => standard behavior"));
62245 			goto skip_array_exotic;
62246 		}
62247 		DUK_DDD(DUK_DDDPRINT("new length is smaller than previous => exotic post behavior"));
62248 
62249 		/* XXX: consolidated algorithm step 15.f -> redundant? */
62250 		if (DUK_HARRAY_LENGTH_NONWRITABLE(a) && !force_flag) {
62251 			/* Array .length is always non-configurable; if it's also
62252 			 * non-writable, don't allow it to be written.
62253 			 */
62254 			goto fail_not_configurable;
62255 		}
62256 
62257 		/* steps 3.h and 3.i */
62258 		if (has_writable && !is_writable) {
62259 			DUK_DDD(DUK_DDDPRINT("desc writable is false, force it back to true, and flag pending write protect"));
62260 			is_writable = 1;
62261 			pending_write_protect = 1;
62262 		}
62263 
62264 		/* remaining actual steps are carried out if standard DefineOwnProperty succeeds */
62265 	} else if (arr_idx != DUK__NO_ARRAY_INDEX) {
62266 		/* XXX: any chance of unifying this with the 'length' key handling? */
62267 
62268 		/* E5 Section 15.4.5.1, step 4 */
62269 		duk_uint32_t old_len;
62270 		duk_harray *a;
62271 
62272 		a = (duk_harray *) obj;
62273 		DUK_HARRAY_ASSERT_VALID(a);
62274 
62275 		old_len = a->length;
62276 
62277 		if (arr_idx >= old_len) {
62278 			DUK_DDD(DUK_DDDPRINT("defineProperty requires array length update "
62279 			                     "(arr_idx=%ld, old_len=%ld)",
62280 			                     (long) arr_idx, (long) old_len));
62281 
62282 			if (DUK_HARRAY_LENGTH_NONWRITABLE(a) && !force_flag) {
62283 				/* Array .length is always non-configurable, so
62284 				 * if it's also non-writable, don't allow a value
62285 				 * write.  With force flag allow writing.
62286 				 */
62287 				goto fail_not_configurable;
62288 			}
62289 
62290 			/* actual update happens once write has been completed without
62291 			 * error below.
62292 			 */
62293 			DUK_ASSERT(arr_idx != 0xffffffffUL);
62294 			arridx_new_array_length = arr_idx + 1;
62295 		} else {
62296 			DUK_DDD(DUK_DDDPRINT("defineProperty does not require length update "
62297 			                     "(arr_idx=%ld, old_len=%ld) -> standard behavior",
62298 			                     (long) arr_idx, (long) old_len));
62299 		}
62300 	}
62301  skip_array_exotic:
62302 
62303 	/* XXX: There is currently no support for writing buffer object
62304 	 * indexed elements here.  Attempt to do so will succeed and
62305 	 * write a concrete property into the buffer object.  This should
62306 	 * be fixed at some point but because buffers are a custom feature
62307 	 * anyway, this is relatively unimportant.
62308 	 */
62309 
62310 	/*
62311 	 *  Actual Object.defineProperty() default algorithm.
62312 	 */
62313 
62314 	/*
62315 	 *  First check whether property exists; if not, simple case.  This covers
62316 	 *  steps 1-4.
62317 	 */
62318 
62319 	if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE)) {
62320 		DUK_DDD(DUK_DDDPRINT("property does not exist"));
62321 
62322 		if (!DUK_HOBJECT_HAS_EXTENSIBLE(obj) && !force_flag) {
62323 			goto fail_not_extensible;
62324 		}
62325 
62326 #if defined(DUK_USE_ROM_OBJECTS)
62327 		/* ROM objects are never extensible but force flag may
62328 		 * allow us to come here anyway.
62329 		 */
62330 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj) || !DUK_HOBJECT_HAS_EXTENSIBLE(obj));
62331 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
62332 			DUK_D(DUK_DPRINT("attempt to define property on a read-only target object"));
62333 			goto fail_not_configurable;
62334 		}
62335 #endif
62336 
62337 		/* XXX: share final setting code for value and flags?  difficult because
62338 		 * refcount code is different.  Share entry allocation?  But can't allocate
62339 		 * until array index checked.
62340 		 */
62341 
62342 		/* steps 4.a and 4.b are tricky */
62343 		if (has_set || has_get) {
62344 			duk_int_t e_idx;
62345 
62346 			DUK_DDD(DUK_DDDPRINT("create new accessor property"));
62347 
62348 			DUK_ASSERT(has_set || set == NULL);
62349 			DUK_ASSERT(has_get || get == NULL);
62350 			DUK_ASSERT(!has_value);
62351 			DUK_ASSERT(!has_writable);
62352 
62353 			new_flags = DUK_PROPDESC_FLAG_ACCESSOR;  /* defaults, E5 Section 8.6.1, Table 7 */
62354 			if (has_enumerable && is_enumerable) {
62355 				new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
62356 			}
62357 			if (has_configurable && is_configurable) {
62358 				new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
62359 			}
62360 
62361 			if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
62362 				DUK_DDD(DUK_DDDPRINT("accessor cannot go to array part, abandon array"));
62363 				duk__abandon_array_part(thr, obj);
62364 			}
62365 
62366 			/* write to entry part */
62367 			e_idx = duk__hobject_alloc_entry_checked(thr, obj, key);
62368 			DUK_ASSERT(e_idx >= 0);
62369 
62370 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, e_idx, get);
62371 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, e_idx, set);
62372 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, get);
62373 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, set);
62374 
62375 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
62376 			goto success_exotics;
62377 		} else {
62378 			duk_int_t e_idx;
62379 			duk_tval *tv2;
62380 
62381 			DUK_DDD(DUK_DDDPRINT("create new data property"));
62382 
62383 			DUK_ASSERT(!has_set);
62384 			DUK_ASSERT(!has_get);
62385 
62386 			new_flags = 0;  /* defaults, E5 Section 8.6.1, Table 7 */
62387 			if (has_writable && is_writable) {
62388 				new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
62389 			}
62390 			if (has_enumerable && is_enumerable) {
62391 				new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
62392 			}
62393 			if (has_configurable && is_configurable) {
62394 				new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
62395 			}
62396 			if (has_value) {
62397 				duk_tval *tv_tmp = duk_require_tval(thr, idx_value);
62398 				DUK_TVAL_SET_TVAL(&tv, tv_tmp);
62399 			} else {
62400 				DUK_TVAL_SET_UNDEFINED(&tv);  /* default value */
62401 			}
62402 
62403 			if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
62404 				if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
62405 					DUK_DDD(DUK_DDDPRINT("new data property attributes match array defaults, attempt to write to array part"));
62406 					tv2 = duk__obtain_arridx_slot(thr, arr_idx, obj);
62407 					if (tv2 == NULL) {
62408 						DUK_DDD(DUK_DDDPRINT("failed writing to array part, abandoned array"));
62409 					} else {
62410 						DUK_DDD(DUK_DDDPRINT("success in writing to array part"));
62411 						DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(obj));
62412 						DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv2));
62413 						DUK_TVAL_SET_TVAL(tv2, &tv);
62414 						DUK_TVAL_INCREF(thr, tv2);
62415 						goto success_exotics;
62416 					}
62417 				} else {
62418 					DUK_DDD(DUK_DDDPRINT("new data property cannot go to array part, abandon array"));
62419 					duk__abandon_array_part(thr, obj);
62420 				}
62421 				/* fall through */
62422 			}
62423 
62424 			/* write to entry part */
62425 			e_idx = duk__hobject_alloc_entry_checked(thr, obj, key);
62426 			DUK_ASSERT(e_idx >= 0);
62427 			tv2 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
62428 			DUK_TVAL_SET_TVAL(tv2, &tv);
62429 			DUK_TVAL_INCREF(thr, tv2);
62430 
62431 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
62432 			goto success_exotics;
62433 		}
62434 		DUK_UNREACHABLE();
62435 	}
62436 
62437 	/* we currently assume virtual properties are not configurable (as none of them are) */
62438 	DUK_ASSERT((curr.e_idx >= 0 || curr.a_idx >= 0) || !(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE));
62439 
62440 	/* [obj key desc value get set curr_value] */
62441 
62442 	/*
62443 	 *  Property already exists.  Steps 5-6 detect whether any changes need
62444 	 *  to be made.
62445 	 */
62446 
62447 	if (has_enumerable) {
62448 		if (is_enumerable) {
62449 			if (!(curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE)) {
62450 				goto need_check;
62451 			}
62452 		} else {
62453 			if (curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE) {
62454 				goto need_check;
62455 			}
62456 		}
62457 	}
62458 	if (has_configurable) {
62459 		if (is_configurable) {
62460 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
62461 				goto need_check;
62462 			}
62463 		} else {
62464 			if (curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
62465 				goto need_check;
62466 			}
62467 		}
62468 	}
62469 	if (has_value) {
62470 		duk_tval *tmp1;
62471 		duk_tval *tmp2;
62472 
62473 		/* attempt to change from accessor to data property */
62474 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
62475 			goto need_check;
62476 		}
62477 
62478 		tmp1 = duk_require_tval(thr, -1);         /* curr value */
62479 		tmp2 = duk_require_tval(thr, idx_value);  /* new value */
62480 		if (!duk_js_samevalue(tmp1, tmp2)) {
62481 			goto need_check;
62482 		}
62483 	}
62484 	if (has_writable) {
62485 		/* attempt to change from accessor to data property */
62486 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
62487 			goto need_check;
62488 		}
62489 
62490 		if (is_writable) {
62491 			if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
62492 				goto need_check;
62493 			}
62494 		} else {
62495 			if (curr.flags & DUK_PROPDESC_FLAG_WRITABLE) {
62496 				goto need_check;
62497 			}
62498 		}
62499 	}
62500 	if (has_set) {
62501 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
62502 			if (set != curr.set) {
62503 				goto need_check;
62504 			}
62505 		} else {
62506 			goto need_check;
62507 		}
62508 	}
62509 	if (has_get) {
62510 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
62511 			if (get != curr.get) {
62512 				goto need_check;
62513 			}
62514 		} else {
62515 			goto need_check;
62516 		}
62517 	}
62518 
62519 	/* property exists, either 'desc' is empty, or all values
62520 	 * match (SameValue)
62521 	 */
62522 	goto success_no_exotics;
62523 
62524  need_check:
62525 
62526 	/*
62527 	 *  Some change(s) need to be made.  Steps 7-11.
62528 	 */
62529 
62530 	/* shared checks for all descriptor types */
62531 	if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
62532 		if (has_configurable && is_configurable) {
62533 			goto fail_not_configurable;
62534 		}
62535 		if (has_enumerable) {
62536 			if (curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE) {
62537 				if (!is_enumerable) {
62538 					goto fail_not_configurable;
62539 				}
62540 			} else {
62541 				if (is_enumerable) {
62542 					goto fail_not_configurable;
62543 				}
62544 			}
62545 		}
62546 	}
62547 
62548 	/* Virtual properties don't have backing so they can't mostly be
62549 	 * edited.  Some virtual properties are, however, writable: for
62550 	 * example, virtual index properties of buffer objects and Array
62551 	 * instance .length.  These are not configurable so the checks
62552 	 * above mostly cover attempts to change them, except when the
62553 	 * duk_def_prop() call is used with DUK_DEFPROP_FORCE; even in
62554 	 * that case we can't forcibly change the property attributes
62555 	 * because they don't have concrete backing.
62556 	 */
62557 
62558 	/* XXX: for ROM objects too it'd be best if value modify was
62559 	 * allowed if the value matches SameValue.
62560 	 */
62561 	/* Reject attempt to change a read-only object. */
62562 #if defined(DUK_USE_ROM_OBJECTS)
62563 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
62564 		DUK_DD(DUK_DDPRINT("attempt to define property on read-only target object"));
62565 		goto fail_not_configurable;
62566 	}
62567 #endif
62568 
62569 	/* descriptor type specific checks */
62570 	if (has_set || has_get) {
62571 		/* IsAccessorDescriptor(desc) == true */
62572 		DUK_ASSERT(!has_writable);
62573 		DUK_ASSERT(!has_value);
62574 
62575 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
62576 			/* curr and desc are accessors */
62577 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
62578 				if (has_set && set != curr.set) {
62579 					goto fail_not_configurable;
62580 				}
62581 				if (has_get && get != curr.get) {
62582 					goto fail_not_configurable;
62583 				}
62584 			}
62585 		} else {
62586 			duk_bool_t rc;
62587 			duk_tval *tv1;
62588 
62589 			/* curr is data, desc is accessor */
62590 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
62591 				goto fail_not_configurable;
62592 			}
62593 
62594 			DUK_DDD(DUK_DDDPRINT("convert property to accessor property"));
62595 			if (curr.a_idx >= 0) {
62596 				DUK_DDD(DUK_DDDPRINT("property to convert is stored in an array entry, abandon array and re-lookup"));
62597 				duk__abandon_array_part(thr, obj);
62598 				duk_pop_unsafe(thr);  /* remove old value */
62599 				rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
62600 				DUK_UNREF(rc);
62601 				DUK_ASSERT(rc != 0);
62602 				DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
62603 			}
62604 			if (curr.e_idx < 0) {
62605 				DUK_ASSERT(curr.a_idx < 0 && curr.e_idx < 0);
62606 				goto fail_virtual;  /* safeguard for virtual property */
62607 			}
62608 
62609 			DUK_ASSERT(curr.e_idx >= 0);
62610 			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
62611 
62612 			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
62613 			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv1);  /* XXX: just decref */
62614 
62615 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
62616 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
62617 			DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);
62618 			DUK_HOBJECT_E_SLOT_SET_ACCESSOR(thr->heap, obj, curr.e_idx);
62619 
62620 			DUK_DDD(DUK_DDDPRINT("flags after data->accessor conversion: 0x%02lx",
62621 			                     (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
62622 			/* Update curr.flags; faster than a re-lookup. */
62623 			curr.flags &= ~DUK_PROPDESC_FLAG_WRITABLE;
62624 			curr.flags |= DUK_PROPDESC_FLAG_ACCESSOR;
62625 		}
62626 	} else if (has_value || has_writable) {
62627 		/* IsDataDescriptor(desc) == true */
62628 		DUK_ASSERT(!has_set);
62629 		DUK_ASSERT(!has_get);
62630 
62631 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
62632 			duk_hobject *tmp;
62633 
62634 			/* curr is accessor, desc is data */
62635 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
62636 				goto fail_not_configurable;
62637 			}
62638 
62639 			/* curr is accessor -> cannot be in array part. */
62640 			DUK_ASSERT(curr.a_idx < 0);
62641 			if (curr.e_idx < 0) {
62642 				goto fail_virtual;  /* safeguard; no virtual accessors now */
62643 			}
62644 
62645 			DUK_DDD(DUK_DDDPRINT("convert property to data property"));
62646 
62647 			DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
62648 			tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
62649 			DUK_UNREF(tmp);
62650 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
62651 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
62652 			tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
62653 			DUK_UNREF(tmp);
62654 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
62655 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
62656 
62657 			DUK_TVAL_SET_UNDEFINED(DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx));
62658 			DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);
62659 			DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(thr->heap, obj, curr.e_idx);
62660 
62661 			DUK_DDD(DUK_DDDPRINT("flags after accessor->data conversion: 0x%02lx",
62662 			                     (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
62663 
62664 			/* Update curr.flags; faster than a re-lookup. */
62665 			curr.flags &= ~(DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ACCESSOR);
62666 		} else {
62667 			/* curr and desc are data */
62668 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
62669 				if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_writable && is_writable) {
62670 					goto fail_not_configurable;
62671 				}
62672 				/* Note: changing from writable to non-writable is OK */
62673 				if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_value) {
62674 					duk_tval *tmp1 = duk_require_tval(thr, -1);         /* curr value */
62675 					duk_tval *tmp2 = duk_require_tval(thr, idx_value);  /* new value */
62676 					if (!duk_js_samevalue(tmp1, tmp2)) {
62677 						goto fail_not_configurable;
62678 					}
62679 				}
62680 			}
62681 		}
62682 	} else {
62683 		/* IsGenericDescriptor(desc) == true; this means in practice that 'desc'
62684 		 * only has [[Enumerable]] or [[Configurable]] flag updates, which are
62685 		 * allowed at this point.
62686 		 */
62687 
62688 		DUK_ASSERT(!has_value && !has_writable && !has_get && !has_set);
62689 	}
62690 
62691 	/*
62692 	 *  Start doing property attributes updates.  Steps 12-13.
62693 	 *
62694 	 *  Start by computing new attribute flags without writing yet.
62695 	 *  Property type conversion is done above if necessary.
62696 	 */
62697 
62698 	new_flags = curr.flags;
62699 
62700 	if (has_enumerable) {
62701 		if (is_enumerable) {
62702 			new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
62703 		} else {
62704 			new_flags &= ~DUK_PROPDESC_FLAG_ENUMERABLE;
62705 		}
62706 	}
62707 	if (has_configurable) {
62708 		if (is_configurable) {
62709 			new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
62710 		} else {
62711 			new_flags &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
62712 		}
62713 	}
62714 	if (has_writable) {
62715 		if (is_writable) {
62716 			new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
62717 		} else {
62718 			new_flags &= ~DUK_PROPDESC_FLAG_WRITABLE;
62719 		}
62720 	}
62721 
62722 	/* XXX: write protect after flag? -> any chance of handling it here? */
62723 
62724 	DUK_DDD(DUK_DDDPRINT("new flags that we want to write: 0x%02lx",
62725 	                     (unsigned long) new_flags));
62726 
62727 	/*
62728 	 *  Check whether we need to abandon an array part (if it exists)
62729 	 */
62730 
62731 	if (curr.a_idx >= 0) {
62732 		duk_bool_t rc;
62733 
62734 		DUK_ASSERT(curr.e_idx < 0);
62735 
62736 		if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
62737 			duk_tval *tv1, *tv2;
62738 
62739 			DUK_DDD(DUK_DDDPRINT("array index, new property attributes match array defaults, update in-place"));
62740 
62741 			DUK_ASSERT(curr.flags == DUK_PROPDESC_FLAGS_WEC);  /* must have been, since in array part */
62742 			DUK_ASSERT(!has_set);
62743 			DUK_ASSERT(!has_get);
62744 			DUK_ASSERT(idx_value >= 0);  /* must be: if attributes match and we get here the value must differ (otherwise no change) */
62745 
62746 			tv2 = duk_require_tval(thr, idx_value);
62747 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, curr.a_idx);
62748 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects; may invalidate a_idx */
62749 			goto success_exotics;
62750 		}
62751 
62752 		DUK_DDD(DUK_DDDPRINT("array index, new property attributes do not match array defaults, abandon array and re-lookup"));
62753 		duk__abandon_array_part(thr, obj);
62754 		duk_pop_unsafe(thr);  /* remove old value */
62755 		rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
62756 		DUK_UNREF(rc);
62757 		DUK_ASSERT(rc != 0);
62758 		DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
62759 	}
62760 
62761 	DUK_DDD(DUK_DDDPRINT("updating existing property in entry part"));
62762 
62763 	/* Array case is handled comprehensively above: either in entry
62764 	 * part or a virtual property.
62765 	 */
62766 	DUK_ASSERT(curr.a_idx < 0);
62767 
62768 	DUK_DDD(DUK_DDDPRINT("update existing property attributes"));
62769 	if (curr.e_idx >= 0) {
62770 		DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, curr.e_idx, new_flags);
62771 	} else {
62772 		/* For Array .length the only allowed transition is for .length
62773 		 * to become non-writable.
62774 		 */
62775 		if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
62776 			duk_harray *a;
62777 			a = (duk_harray *) obj;
62778 			DUK_DD(DUK_DDPRINT("Object.defineProperty() attribute update for duk_harray .length -> %02lx", (unsigned long) new_flags));
62779 			DUK_HARRAY_ASSERT_VALID(a);
62780 			if ((new_flags & DUK_PROPDESC_FLAGS_EC) != (curr.flags & DUK_PROPDESC_FLAGS_EC)) {
62781 				DUK_D(DUK_DPRINT("Object.defineProperty() attempt to change virtual array .length enumerable or configurable attribute, fail"));
62782 				goto fail_virtual;
62783 			}
62784 			if (new_flags & DUK_PROPDESC_FLAG_WRITABLE) {
62785 				DUK_HARRAY_SET_LENGTH_WRITABLE(a);
62786 			} else {
62787 				DUK_HARRAY_SET_LENGTH_NONWRITABLE(a);
62788 			}
62789 		}
62790 	}
62791 
62792 	if (has_set) {
62793 		duk_hobject *tmp;
62794 
62795 		/* Virtual properties are non-configurable but with a 'force'
62796 		 * flag we might come here so check explicitly for virtual.
62797 		 */
62798 		if (curr.e_idx < 0) {
62799 			goto fail_virtual;
62800 		}
62801 
62802 		DUK_DDD(DUK_DDDPRINT("update existing property setter"));
62803 		DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
62804 
62805 		tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
62806 		DUK_UNREF(tmp);
62807 		DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, set);
62808 		DUK_HOBJECT_INCREF_ALLOWNULL(thr, set);
62809 		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects; may invalidate e_idx */
62810 	}
62811 	if (has_get) {
62812 		duk_hobject *tmp;
62813 
62814 		if (curr.e_idx < 0) {
62815 			goto fail_virtual;
62816 		}
62817 
62818 		DUK_DDD(DUK_DDDPRINT("update existing property getter"));
62819 		DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
62820 
62821 		tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
62822 		DUK_UNREF(tmp);
62823 		DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, get);
62824 		DUK_HOBJECT_INCREF_ALLOWNULL(thr, get);
62825 		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects; may invalidate e_idx */
62826 	}
62827 	if (has_value) {
62828 		duk_tval *tv1, *tv2;
62829 
62830 		DUK_DDD(DUK_DDDPRINT("update existing property value"));
62831 
62832 		if (curr.e_idx >= 0) {
62833 			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
62834 			tv2 = duk_require_tval(thr, idx_value);
62835 			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
62836 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects; may invalidate e_idx */
62837 		} else {
62838 			DUK_ASSERT(curr.a_idx < 0);  /* array part case handled comprehensively previously */
62839 
62840 			DUK_DD(DUK_DDPRINT("Object.defineProperty(), value update for virtual property"));
62841 			/* XXX: Uint8Array and other typed array virtual writes not currently
62842 			 * handled.
62843 			 */
62844 			if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
62845 				duk_harray *a;
62846 				a = (duk_harray *) obj;
62847 				DUK_DD(DUK_DDPRINT("Object.defineProperty() value update for duk_harray .length -> %ld", (long) arrlen_new_len));
62848 				DUK_HARRAY_ASSERT_VALID(a);
62849 				a->length = arrlen_new_len;
62850 			} else {
62851 				goto fail_virtual;  /* should not happen */
62852 			}
62853 		}
62854 	}
62855 
62856 	/*
62857 	 *  Standard algorithm succeeded without errors, check for exotic post-behaviors.
62858 	 *
62859 	 *  Arguments exotic behavior in E5 Section 10.6 occurs after the standard
62860 	 *  [[DefineOwnProperty]] has completed successfully.
62861 	 *
62862 	 *  Array exotic behavior in E5 Section 15.4.5.1 is implemented partly
62863 	 *  prior to the default [[DefineOwnProperty]], but:
62864 	 *    - for an array index key (e.g. "10") the final 'length' update occurs here
62865 	 *    - for 'length' key the element deletion and 'length' update occurs here
62866 	 */
62867 
62868  success_exotics:
62869 
62870 	/* curr.a_idx or curr.e_idx may have been invalidated by side effects
62871 	 * above.
62872 	 */
62873 
62874 	/* [obj key desc value get set curr_value] */
62875 
62876 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
62877 		duk_harray *a;
62878 
62879 		a = (duk_harray *) obj;
62880 		DUK_HARRAY_ASSERT_VALID(a);
62881 
62882 		if (arridx_new_array_length > 0) {
62883 			/*
62884 			 *  Note: zero works as a "no update" marker because the new length
62885 			 *  can never be zero after a new property is written.
62886 			 */
62887 
62888 			/* E5 Section 15.4.5.1, steps 4.e.i - 4.e.ii */
62889 
62890 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, pending array length update to: %ld",
62891 			                     (long) arridx_new_array_length));
62892 
62893 			a->length = arridx_new_array_length;
62894 		}
62895 
62896 		if (key == DUK_HTHREAD_STRING_LENGTH(thr) && arrlen_new_len < arrlen_old_len) {
62897 			/*
62898 			 *  E5 Section 15.4.5.1, steps 3.k - 3.n.  The order at the end combines
62899 			 *  the error case 3.l.iii and the success case 3.m-3.n.
62900 			 */
62901 
62902 			/* XXX: investigate whether write protect can be handled above, if we
62903 			 * just update length here while ignoring its protected status
62904 			 */
62905 
62906 			duk_uint32_t result_len;
62907 			duk_bool_t rc;
62908 
62909 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key is 'length', exotic array behavior, "
62910 			                     "doing array element deletion and length update"));
62911 
62912 			rc = duk__handle_put_array_length_smaller(thr, obj, arrlen_old_len, arrlen_new_len, force_flag, &result_len);
62913 
62914 			/* update length (curr points to length, and we assume it's still valid) */
62915 			DUK_ASSERT(result_len >= arrlen_new_len && result_len <= arrlen_old_len);
62916 
62917 			a->length = result_len;
62918 
62919 			if (pending_write_protect) {
62920 				DUK_DDD(DUK_DDDPRINT("setting array length non-writable (pending writability update)"));
62921 				DUK_HARRAY_SET_LENGTH_NONWRITABLE(a);
62922 			}
62923 
62924 			/* XXX: shrink array allocation or entries compaction here? */
62925 			if (!rc) {
62926 				DUK_DD(DUK_DDPRINT("array length write only partially successful"));
62927 				goto fail_not_configurable;
62928 			}
62929 		}
62930 	} else if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {
62931 		duk_hobject *map;
62932 		duk_hobject *varenv;
62933 
62934 		DUK_ASSERT(arridx_new_array_length == 0);
62935 		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));  /* traits are separate; in particular, arguments not an array */
62936 
62937 		map = NULL;
62938 		varenv = NULL;
62939 		if (!duk__lookup_arguments_map(thr, obj, key, &curr, &map, &varenv)) {
62940 			goto success_no_exotics;
62941 		}
62942 		DUK_ASSERT(map != NULL);
62943 		DUK_ASSERT(varenv != NULL);
62944 
62945 		/* [obj key desc value get set curr_value varname] */
62946 
62947 		if (has_set || has_get) {
62948 			/* = IsAccessorDescriptor(Desc) */
62949 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map' "
62950 			                     "changed to an accessor, delete arguments binding"));
62951 
62952 			(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
62953 		} else {
62954 			/* Note: this order matters (final value before deleting map entry must be done) */
62955 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
62956 			                     "check for value update / binding deletion"));
62957 
62958 			if (has_value) {
62959 				duk_hstring *varname;
62960 
62961 				DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
62962 				                     "update bound value (variable/argument)"));
62963 
62964 				varname = duk_require_hstring(thr, -1);
62965 				DUK_ASSERT(varname != NULL);
62966 
62967 				DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
62968 				                     "key=%!O, varname=%!O, value=%!T",
62969 				                     (duk_heaphdr *) key,
62970 				                     (duk_heaphdr *) varname,
62971 				                     (duk_tval *) duk_require_tval(thr, idx_value)));
62972 
62973 				/* strict flag for putvar comes from our caller (currently: fixed) */
62974 				duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(thr, idx_value), 1 /*throw_flag*/);
62975 			}
62976 			if (has_writable && !is_writable) {
62977 				DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
62978 				                     "changed to non-writable, delete arguments binding"));
62979 
62980 				(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
62981 			}
62982 		}
62983 
62984 		/* 'varname' is in stack in this else branch, leaving an unbalanced stack below,
62985 		 * but this doesn't matter now.
62986 		 */
62987 	}
62988 
62989  success_no_exotics:
62990 	/* Some code paths use NORZ macros for simplicity, ensure refzero
62991 	 * handling is completed.
62992 	 */
62993 	DUK_REFZERO_CHECK_SLOW(thr);
62994 	return 1;
62995 
62996  fail_not_extensible:
62997 	if (throw_flag) {
62998 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE);
62999 		DUK_WO_NORETURN(return 0;);
63000 	}
63001 	return 0;
63002 
63003  fail_virtual:  /* just use the same "not configurable" error message" */
63004  fail_not_configurable:
63005 	if (throw_flag) {
63006 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
63007 		DUK_WO_NORETURN(return 0;);
63008 	}
63009 	return 0;
63010 }
63011 
63012 /*
63013  *  Object.prototype.hasOwnProperty() and Object.prototype.propertyIsEnumerable().
63014  */
63015 
63016 DUK_INTERNAL duk_bool_t duk_hobject_object_ownprop_helper(duk_hthread *thr, duk_small_uint_t required_desc_flags) {
63017 	duk_hstring *h_v;
63018 	duk_hobject *h_obj;
63019 	duk_propdesc desc;
63020 	duk_bool_t ret;
63021 
63022 	/* coercion order matters */
63023 	h_v = duk_to_hstring_acceptsymbol(thr, 0);
63024 	DUK_ASSERT(h_v != NULL);
63025 
63026 	h_obj = duk_push_this_coercible_to_object(thr);
63027 	DUK_ASSERT(h_obj != NULL);
63028 
63029 	ret = duk_hobject_get_own_propdesc(thr, h_obj, h_v, &desc, 0 /*flags*/);  /* don't push value */
63030 
63031 	duk_push_boolean(thr, ret && ((desc.flags & required_desc_flags) == required_desc_flags));
63032 	return 1;
63033 }
63034 
63035 /*
63036  *  Object.seal() and Object.freeze()  (E5 Sections 15.2.3.8 and 15.2.3.9)
63037  *
63038  *  Since the algorithms are similar, a helper provides both functions.
63039  *  Freezing is essentially sealing + making plain properties non-writable.
63040  *
63041  *  Note: virtual (non-concrete) properties which are non-configurable but
63042  *  writable would pose some problems, but such properties do not currently
63043  *  exist (all virtual properties are non-configurable and non-writable).
63044  *  If they did exist, the non-configurability does NOT prevent them from
63045  *  becoming non-writable.  However, this change should be recorded somehow
63046  *  so that it would turn up (e.g. when getting the property descriptor),
63047  *  requiring some additional flags in the object.
63048  */
63049 
63050 DUK_INTERNAL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze) {
63051 	duk_uint_fast32_t i;
63052 
63053 	DUK_ASSERT(thr != NULL);
63054 	DUK_ASSERT(thr->heap != NULL);
63055 	DUK_ASSERT(obj != NULL);
63056 
63057 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
63058 
63059 #if defined(DUK_USE_ROM_OBJECTS)
63060 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
63061 		DUK_DD(DUK_DDPRINT("attempt to seal/freeze a readonly object, reject"));
63062 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
63063 		DUK_WO_NORETURN(return;);
63064 	}
63065 #endif
63066 
63067 	/*
63068 	 *  Abandon array part because all properties must become non-configurable.
63069 	 *  Note that this is now done regardless of whether this is always the case
63070 	 *  (skips check, but performance problem if caller would do this many times
63071 	 *  for the same object; not likely).
63072 	 */
63073 
63074 	duk__abandon_array_part(thr, obj);
63075 	DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) == 0);
63076 
63077 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
63078 		duk_uint8_t *fp;
63079 
63080 		/* since duk__abandon_array_part() causes a resize, there should be no gaps in keys */
63081 		DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != NULL);
63082 
63083 		/* avoid multiple computations of flags address; bypasses macros */
63084 		fp = DUK_HOBJECT_E_GET_FLAGS_PTR(thr->heap, obj, i);
63085 		if (is_freeze && !((*fp) & DUK_PROPDESC_FLAG_ACCESSOR)) {
63086 			*fp &= ~(DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE);
63087 		} else {
63088 			*fp &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
63089 		}
63090 	}
63091 
63092 	DUK_HOBJECT_CLEAR_EXTENSIBLE(obj);
63093 
63094 	/* no need to compact since we already did that in duk__abandon_array_part()
63095 	 * (regardless of whether an array part existed or not.
63096 	 */
63097 
63098 	return;
63099 }
63100 
63101 /*
63102  *  Object.isSealed() and Object.isFrozen()  (E5 Sections 15.2.3.11, 15.2.3.13)
63103  *
63104  *  Since the algorithms are similar, a helper provides both functions.
63105  *  Freezing is essentially sealing + making plain properties non-writable.
63106  *
63107  *  Note: all virtual (non-concrete) properties are currently non-configurable
63108  *  and non-writable (and there are no accessor virtual properties), so they don't
63109  *  need to be considered here now.
63110  */
63111 
63112 DUK_INTERNAL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen) {
63113 	duk_uint_fast32_t i;
63114 
63115 	DUK_ASSERT(obj != NULL);
63116 	DUK_UNREF(thr);
63117 
63118 	/* Note: no allocation pressure, no need to check refcounts etc */
63119 
63120 	/* must not be extensible */
63121 	if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
63122 		return 0;
63123 	}
63124 
63125 	/* all virtual properties are non-configurable and non-writable */
63126 
63127 	/* entry part must not contain any configurable properties, or
63128 	 * writable properties (if is_frozen).
63129 	 */
63130 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
63131 		duk_small_uint_t flags;
63132 
63133 		if (!DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i)) {
63134 			continue;
63135 		}
63136 
63137 		/* avoid multiple computations of flags address; bypasses macros */
63138 		flags = (duk_small_uint_t) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
63139 
63140 		if (flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
63141 			return 0;
63142 		}
63143 		if (is_frozen &&
63144 		    !(flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
63145 		    (flags & DUK_PROPDESC_FLAG_WRITABLE)) {
63146 			return 0;
63147 		}
63148 	}
63149 
63150 	/* array part must not contain any non-unused properties, as they would
63151 	 * be configurable and writable.
63152 	 */
63153 	for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
63154 		duk_tval *tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
63155 		if (!DUK_TVAL_IS_UNUSED(tv)) {
63156 			return 0;
63157 		}
63158 	}
63159 
63160 	return 1;
63161 }
63162 
63163 /*
63164  *  Object.preventExtensions() and Object.isExtensible()  (E5 Sections 15.2.3.10, 15.2.3.13)
63165  *
63166  *  Not needed, implemented by macros DUK_HOBJECT_{HAS,CLEAR,SET}_EXTENSIBLE
63167  *  and the Object built-in bindings.
63168  */
63169 
63170 /* automatic undefs */
63171 #undef DUK__HASH_DELETED
63172 #undef DUK__HASH_UNUSED
63173 #undef DUK__NO_ARRAY_INDEX
63174 #undef DUK__VALSTACK_PROXY_LOOKUP
63175 #undef DUK__VALSTACK_SPACE
63176 #line 1 "duk_hstring_assert.c"
63177 /*
63178  *  duk_hstring assertion helpers.
63179  */
63180 
63181 /* #include duk_internal.h -> already included */
63182 
63183 #if defined(DUK_USE_ASSERTIONS)
63184 
63185 DUK_INTERNAL void duk_hstring_assert_valid(duk_hstring *h) {
63186 	DUK_ASSERT(h != NULL);
63187 }
63188 
63189 #endif  /* DUK_USE_ASSERTIONS */
63190 #line 1 "duk_hstring_misc.c"
63191 /*
63192  *  Misc support functions
63193  */
63194 
63195 /* #include duk_internal.h -> already included */
63196 
63197 /*
63198  *  duk_hstring charCodeAt, with and without surrogate awareness
63199  */
63200 
63201 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) {
63202 	duk_uint32_t boff;
63203 	const duk_uint8_t *p, *p_start, *p_end;
63204 	duk_ucodepoint_t cp1;
63205 	duk_ucodepoint_t cp2;
63206 
63207 	/* Caller must check character offset to be inside the string. */
63208 	DUK_ASSERT(thr != NULL);
63209 	DUK_ASSERT(h != NULL);
63210 	DUK_ASSERT_DISABLE(pos >= 0);  /* unsigned */
63211 	DUK_ASSERT(pos < (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h));
63212 
63213 	boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint32_t) pos);
63214 	DUK_DDD(DUK_DDDPRINT("charCodeAt: pos=%ld -> boff=%ld, str=%!O",
63215 	                     (long) pos, (long) boff, (duk_heaphdr *) h));
63216 	DUK_ASSERT_DISABLE(boff >= 0);
63217 	DUK_ASSERT(boff < DUK_HSTRING_GET_BYTELEN(h));
63218 
63219 	p_start = DUK_HSTRING_GET_DATA(h);
63220 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
63221 	p = p_start + boff;
63222 	DUK_DDD(DUK_DDDPRINT("p_start=%p, p_end=%p, p=%p",
63223 	                     (const void *) p_start, (const void *) p_end,
63224 	                     (const void *) p));
63225 
63226 	/* For invalid UTF-8 (never happens for standard ECMAScript strings)
63227 	 * return U+FFFD replacement character.
63228 	 */
63229 	if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp1)) {
63230 		if (surrogate_aware && cp1 >= 0xd800UL && cp1 <= 0xdbffUL) {
63231 			/* The decode helper is memory safe even if 'cp1' was
63232 			 * decoded at the end of the string and 'p' is no longer
63233 			 * within string memory range.
63234 			 */
63235 			cp2 = 0;  /* If call fails, this is left untouched and won't match cp2 check. */
63236 			(void) duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp2);
63237 			if (cp2 >= 0xdc00UL && cp2 <= 0xdfffUL) {
63238 				cp1 = (duk_ucodepoint_t) (((cp1 - 0xd800UL) << 10) + (cp2 - 0xdc00UL) + 0x10000UL);
63239 			}
63240 		}
63241 	} else {
63242 		cp1 = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
63243 	}
63244 
63245 	return cp1;
63246 }
63247 
63248 /*
63249  *  duk_hstring charlen, when lazy charlen disabled
63250  */
63251 
63252 #if !defined(DUK_USE_HSTRING_LAZY_CLEN)
63253 #if !defined(DUK_USE_HSTRING_CLEN)
63254 #error non-lazy duk_hstring charlen but DUK_USE_HSTRING_CLEN not set
63255 #endif
63256 DUK_INTERNAL void duk_hstring_init_charlen(duk_hstring *h) {
63257 	duk_uint32_t clen;
63258 
63259 	DUK_ASSERT(h != NULL);
63260 	DUK_ASSERT(!DUK_HSTRING_HAS_ASCII(h));
63261 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));
63262 
63263 	clen = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
63264 #if defined(DUK_USE_STRLEN16)
63265 	DUK_ASSERT(clen <= 0xffffUL);  /* Bytelength checked during interning. */
63266 	h->clen16 = (duk_uint16_t) clen;
63267 #else
63268 	h->clen = (duk_uint32_t) clen;
63269 #endif
63270 	if (DUK_LIKELY(clen == DUK_HSTRING_GET_BYTELEN(h))) {
63271 		DUK_HSTRING_SET_ASCII(h);
63272 	}
63273 }
63274 
63275 DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
63276 #if defined(DUK_USE_STRLEN16)
63277 	return h->clen16;
63278 #else
63279 	return h->clen;
63280 #endif
63281 }
63282 #endif  /* !DUK_USE_HSTRING_LAZY_CLEN */
63283 
63284 /*
63285  *  duk_hstring charlen, when lazy charlen enabled
63286  */
63287 
63288 #if defined(DUK_USE_HSTRING_LAZY_CLEN)
63289 #if defined(DUK_USE_HSTRING_CLEN)
63290 DUK_LOCAL DUK_COLD duk_size_t duk__hstring_get_charlen_slowpath(duk_hstring *h) {
63291 	duk_size_t res;
63292 
63293 	DUK_ASSERT(h->clen == 0);  /* Checked by caller. */
63294 
63295 #if defined(DUK_USE_ROM_STRINGS)
63296 	/* ROM strings have precomputed clen, but if the computed clen is zero
63297 	 * we can still come here and can't write anything.
63298 	 */
63299 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) {
63300 		return 0;
63301 	}
63302 #endif
63303 
63304 	res = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
63305 #if defined(DUK_USE_STRLEN16)
63306 	DUK_ASSERT(res <= 0xffffUL);  /* Bytelength checked during interning. */
63307 	h->clen16 = (duk_uint16_t) res;
63308 #else
63309 	h->clen = (duk_uint32_t) res;
63310 #endif
63311 	if (DUK_LIKELY(res == DUK_HSTRING_GET_BYTELEN(h))) {
63312 		DUK_HSTRING_SET_ASCII(h);
63313 	}
63314 	return res;
63315 }
63316 #else  /* DUK_USE_HSTRING_CLEN */
63317 DUK_LOCAL duk_size_t duk__hstring_get_charlen_slowpath(duk_hstring *h) {
63318 	if (DUK_LIKELY(DUK_HSTRING_HAS_ASCII(h))) {
63319 		/* Most practical strings will go here. */
63320 		return DUK_HSTRING_GET_BYTELEN(h);
63321 	} else {
63322 		/* ASCII flag is lazy, so set it here. */
63323 		duk_size_t res;
63324 
63325 		/* XXX: here we could use the strcache to speed up the
63326 		 * computation (matters for 'i < str.length' loops).
63327 		 */
63328 
63329 		res = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
63330 
63331 #if defined(DUK_USE_ROM_STRINGS)
63332 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) {
63333 			/* For ROM strings, can't write anything; ASCII flag
63334 			 * is preset so we don't need to update it.
63335 			 */
63336 			return res;
63337 		}
63338 #endif
63339 		if (DUK_LIKELY(res == DUK_HSTRING_GET_BYTELEN(h))) {
63340 			DUK_HSTRING_SET_ASCII(h);
63341 		}
63342 		return res;
63343 	}
63344 }
63345 #endif  /* DUK_USE_HSTRING_CLEN */
63346 
63347 #if defined(DUK_USE_HSTRING_CLEN)
63348 DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
63349 #if defined(DUK_USE_STRLEN16)
63350 	if (DUK_LIKELY(h->clen16 != 0)) {
63351 		return h->clen16;
63352 	}
63353 #else
63354 	if (DUK_LIKELY(h->clen != 0)) {
63355 		return h->clen;
63356 	}
63357 #endif
63358 	return duk__hstring_get_charlen_slowpath(h);
63359 }
63360 #else  /* DUK_USE_HSTRING_CLEN */
63361 DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
63362 	/* Always use slow path. */
63363 	return duk__hstring_get_charlen_slowpath(h);
63364 }
63365 #endif  /* DUK_USE_HSTRING_CLEN */
63366 #endif  /* DUK_USE_HSTRING_LAZY_CLEN */
63367 
63368 /*
63369  *  Compare duk_hstring to an ASCII cstring.
63370  */
63371 
63372 DUK_INTERNAL duk_bool_t duk_hstring_equals_ascii_cstring(duk_hstring *h, const char *cstr) {
63373 	duk_size_t len;
63374 
63375 	DUK_ASSERT(h != NULL);
63376 	DUK_ASSERT(cstr != NULL);
63377 
63378 	len = DUK_STRLEN(cstr);
63379 	if (len != DUK_HSTRING_GET_BYTELEN(h)) {
63380 		return 0;
63381 	}
63382 	if (duk_memcmp((const void *) cstr, (const void *) DUK_HSTRING_GET_DATA(h), len) == 0) {
63383 		return 1;
63384 	}
63385 	return 0;
63386 }
63387 #line 1 "duk_hthread_alloc.c"
63388 /*
63389  *  duk_hthread allocation and freeing.
63390  */
63391 
63392 /* #include duk_internal.h -> already included */
63393 
63394 /*
63395  *  Allocate initial stacks for a thread.  Note that 'thr' must be reachable
63396  *  as a garbage collection may be triggered by the allocation attempts.
63397  *  Returns zero (without leaking memory) if init fails.
63398  */
63399 
63400 DUK_INTERNAL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr) {
63401 	duk_size_t alloc_size;
63402 	duk_size_t i;
63403 
63404 	DUK_ASSERT(heap != NULL);
63405 	DUK_ASSERT(thr != NULL);
63406 	DUK_ASSERT(thr->valstack == NULL);
63407 	DUK_ASSERT(thr->valstack_end == NULL);
63408 	DUK_ASSERT(thr->valstack_alloc_end == NULL);
63409 	DUK_ASSERT(thr->valstack_bottom == NULL);
63410 	DUK_ASSERT(thr->valstack_top == NULL);
63411 	DUK_ASSERT(thr->callstack_curr == NULL);
63412 
63413 	/* valstack */
63414 	DUK_ASSERT(DUK_VALSTACK_API_ENTRY_MINIMUM <= DUK_VALSTACK_INITIAL_SIZE);
63415 	alloc_size = sizeof(duk_tval) * DUK_VALSTACK_INITIAL_SIZE;
63416 	thr->valstack = (duk_tval *) DUK_ALLOC(heap, alloc_size);
63417 	if (!thr->valstack) {
63418 		goto fail;
63419 	}
63420 	duk_memzero(thr->valstack, alloc_size);
63421 	thr->valstack_end = thr->valstack + DUK_VALSTACK_API_ENTRY_MINIMUM;
63422 	thr->valstack_alloc_end = thr->valstack + DUK_VALSTACK_INITIAL_SIZE;
63423 	thr->valstack_bottom = thr->valstack;
63424 	thr->valstack_top = thr->valstack;
63425 
63426 	for (i = 0; i < DUK_VALSTACK_INITIAL_SIZE; i++) {
63427 		DUK_TVAL_SET_UNDEFINED(&thr->valstack[i]);
63428 	}
63429 
63430 	return 1;
63431 
63432  fail:
63433 	DUK_FREE(heap, thr->valstack);
63434 	DUK_ASSERT(thr->callstack_curr == NULL);
63435 
63436 	thr->valstack = NULL;
63437 	return 0;
63438 }
63439 
63440 /* For indirect allocs. */
63441 
63442 DUK_INTERNAL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud) {
63443 	duk_hthread *thr = (duk_hthread *) ud;
63444 	DUK_UNREF(heap);
63445 	return (void *) thr->valstack;
63446 }
63447 #line 1 "duk_hthread_builtins.c"
63448 /*
63449  *  Initialize built-in objects.  Current thread must have a valstack
63450  *  and initialization errors may longjmp, so a setjmp() catch point
63451  *  must exist.
63452  */
63453 
63454 /* #include duk_internal.h -> already included */
63455 
63456 /*
63457  *  Encoding constants, must match genbuiltins.py
63458  */
63459 
63460 #define DUK__PROP_FLAGS_BITS             3
63461 #define DUK__LENGTH_PROP_BITS            3
63462 #define DUK__NARGS_BITS                  3
63463 #define DUK__PROP_TYPE_BITS              3
63464 
63465 #define DUK__NARGS_VARARGS_MARKER        0x07
63466 
63467 #define DUK__PROP_TYPE_DOUBLE            0
63468 #define DUK__PROP_TYPE_STRING            1
63469 #define DUK__PROP_TYPE_STRIDX            2
63470 #define DUK__PROP_TYPE_BUILTIN           3
63471 #define DUK__PROP_TYPE_UNDEFINED         4
63472 #define DUK__PROP_TYPE_BOOLEAN_TRUE      5
63473 #define DUK__PROP_TYPE_BOOLEAN_FALSE     6
63474 #define DUK__PROP_TYPE_ACCESSOR          7
63475 
63476 /*
63477  *  Create built-in objects by parsing an init bitstream generated
63478  *  by genbuiltins.py.
63479  */
63480 
63481 #if defined(DUK_USE_ROM_OBJECTS)
63482 #if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
63483 DUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) {
63484 	duk_hobject *h_global;
63485 #if defined(DUK_USE_ROM_GLOBAL_CLONE)
63486 	duk_hobject *h_oldglobal;
63487 	duk_uint8_t *props;
63488 	duk_size_t alloc_size;
63489 #endif
63490 	duk_hobject *h_objenv;
63491 
63492 	/* XXX: refactor into internal helper, duk_clone_hobject() */
63493 
63494 #if defined(DUK_USE_ROM_GLOBAL_INHERIT)
63495 	/* Inherit from ROM-based global object: less RAM usage, less transparent. */
63496 	h_global = duk_push_object_helper(thr,
63497 	                                  DUK_HOBJECT_FLAG_EXTENSIBLE |
63498 	                                  DUK_HOBJECT_FLAG_FASTREFS |
63499 	                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),
63500 	                                  DUK_BIDX_GLOBAL);
63501 	DUK_ASSERT(h_global != NULL);
63502 #elif defined(DUK_USE_ROM_GLOBAL_CLONE)
63503 	/* Clone the properties of the ROM-based global object to create a
63504 	 * fully RAM-based global object.  Uses more memory than the inherit
63505 	 * model but more compliant.
63506 	 */
63507 	h_global = duk_push_object_helper(thr,
63508 	                                  DUK_HOBJECT_FLAG_EXTENSIBLE |
63509 	                                  DUK_HOBJECT_FLAG_FASTREFS |
63510 	                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),
63511 	                                  DUK_BIDX_OBJECT_PROTOTYPE);
63512 	DUK_ASSERT(h_global != NULL);
63513 	h_oldglobal = thr->builtins[DUK_BIDX_GLOBAL];
63514 	DUK_ASSERT(h_oldglobal != NULL);
63515 
63516 	/* Copy the property table verbatim; this handles attributes etc.
63517 	 * For ROM objects it's not necessary (or possible) to update
63518 	 * refcounts so leave them as is.
63519 	 */
63520 	alloc_size = DUK_HOBJECT_P_ALLOC_SIZE(h_oldglobal);
63521 	DUK_ASSERT(alloc_size > 0);
63522 	props = DUK_ALLOC_CHECKED(thr, alloc_size);
63523 	DUK_ASSERT(props != NULL);
63524 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal) != NULL);
63525 	duk_memcpy((void *) props, (const void *) DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal), alloc_size);
63526 
63527 	/* XXX: keep property attributes or tweak them here?
63528 	 * Properties will now be non-configurable even when they're
63529 	 * normally configurable for the global object.
63530 	 */
63531 
63532 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h_global) == NULL);
63533 	DUK_HOBJECT_SET_PROPS(thr->heap, h_global, props);
63534 	DUK_HOBJECT_SET_ESIZE(h_global, DUK_HOBJECT_GET_ESIZE(h_oldglobal));
63535 	DUK_HOBJECT_SET_ENEXT(h_global, DUK_HOBJECT_GET_ENEXT(h_oldglobal));
63536 	DUK_HOBJECT_SET_ASIZE(h_global, DUK_HOBJECT_GET_ASIZE(h_oldglobal));
63537 	DUK_HOBJECT_SET_HSIZE(h_global, DUK_HOBJECT_GET_HSIZE(h_oldglobal));
63538 #else
63539 #error internal error in config defines
63540 #endif
63541 
63542 	duk_hobject_compact_props(thr, h_global);
63543 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
63544 	DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL]));  /* no need to decref: ROM object */
63545 	thr->builtins[DUK_BIDX_GLOBAL] = h_global;
63546 	DUK_HOBJECT_INCREF(thr, h_global);
63547 	DUK_D(DUK_DPRINT("duplicated global object: %!O", h_global));
63548 
63549 	/* Create a fresh object environment for the global scope.  This is
63550 	 * needed so that the global scope points to the newly created RAM-based
63551 	 * global object.
63552 	 */
63553 	h_objenv = (duk_hobject *) duk_hobjenv_alloc(thr,
63554 	                                             DUK_HOBJECT_FLAG_EXTENSIBLE |
63555 	                                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
63556 	DUK_ASSERT(h_objenv != NULL);
63557 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_objenv) == NULL);
63558 	duk_push_hobject(thr, h_objenv);
63559 
63560 	DUK_ASSERT(h_global != NULL);
63561 	((duk_hobjenv *) h_objenv)->target = h_global;
63562 	DUK_HOBJECT_INCREF(thr, h_global);
63563 	DUK_ASSERT(((duk_hobjenv *) h_objenv)->has_this == 0);
63564 
63565 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL);
63566 	DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL_ENV]));  /* no need to decref: ROM object */
63567 	thr->builtins[DUK_BIDX_GLOBAL_ENV] = h_objenv;
63568 	DUK_HOBJECT_INCREF(thr, h_objenv);
63569 	DUK_D(DUK_DPRINT("duplicated global env: %!O", h_objenv));
63570 
63571 	DUK_HOBJENV_ASSERT_VALID((duk_hobjenv *) h_objenv);
63572 
63573 	duk_pop_2(thr);  /* Pop global object and global env. */
63574 }
63575 #endif  /* DUK_USE_ROM_GLOBAL_CLONE || DUK_USE_ROM_GLOBAL_INHERIT */
63576 
63577 DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
63578 	/* Setup builtins from ROM objects.  All heaps/threads will share
63579 	 * the same readonly objects.
63580 	 */
63581 	duk_small_uint_t i;
63582 
63583 	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
63584 		duk_hobject *h;
63585 		h = (duk_hobject *) DUK_LOSE_CONST(duk_rom_builtins_bidx[i]);
63586 		DUK_ASSERT(h != NULL);
63587 		thr->builtins[i] = h;
63588 	}
63589 
63590 #if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
63591 	/* By default the global object is read-only which is often much
63592 	 * more of an issue than having read-only built-in objects (like
63593 	 * RegExp, Date, etc).  Use a RAM-based copy of the global object
63594 	 * and the global environment object for convenience.
63595 	 */
63596 	duk__duplicate_ram_global_object(thr);
63597 #endif
63598 }
63599 #else  /* DUK_USE_ROM_OBJECTS */
63600 DUK_LOCAL void duk__push_stridx(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
63601 	duk_small_uint_t n;
63602 
63603 	n = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63604 	DUK_ASSERT_DISABLE(n >= 0);  /* unsigned */
63605 	DUK_ASSERT(n < DUK_HEAP_NUM_STRINGS);
63606 	duk_push_hstring_stridx(thr, n);
63607 }
63608 DUK_LOCAL void duk__push_string(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
63609 	/* XXX: built-ins data could provide a maximum length that is
63610 	 * actually needed; bitpacked max length is now 256 bytes.
63611 	 */
63612 	duk_uint8_t tmp[DUK_BD_BITPACKED_STRING_MAXLEN];
63613 	duk_small_uint_t len;
63614 
63615 	len = duk_bd_decode_bitpacked_string(bd, tmp);
63616 	duk_push_lstring(thr, (const char *) tmp, (duk_size_t) len);
63617 }
63618 DUK_LOCAL void duk__push_stridx_or_string(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
63619 	duk_small_uint_t n;
63620 
63621 	n = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63622 	if (n == 0) {
63623 		duk__push_string(thr, bd);
63624 	} else {
63625 		n--;
63626 		DUK_ASSERT(n < DUK_HEAP_NUM_STRINGS);
63627 		duk_push_hstring_stridx(thr, n);
63628 	}
63629 }
63630 DUK_LOCAL void duk__push_double(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
63631 	duk_double_union du;
63632 	duk_small_uint_t i;
63633 
63634 	for (i = 0; i < 8; i++) {
63635 		/* Encoding endianness must match target memory layout,
63636 		 * build scripts and genbuiltins.py must ensure this.
63637 		 */
63638 		du.uc[i] = (duk_uint8_t) duk_bd_decode(bd, 8);
63639 	}
63640 
63641 	duk_push_number(thr, du.d);  /* push operation normalizes NaNs */
63642 }
63643 
63644 DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
63645 	duk_bitdecoder_ctx bd_ctx;
63646 	duk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */
63647 	duk_hobject *h;
63648 	duk_small_uint_t i, j;
63649 
63650 	DUK_D(DUK_DPRINT("INITBUILTINS BEGIN: DUK_NUM_BUILTINS=%d, DUK_NUM_BUILTINS_ALL=%d", (int) DUK_NUM_BUILTINS, (int) DUK_NUM_ALL_BUILTINS));
63651 
63652 	duk_memzero(&bd_ctx, sizeof(bd_ctx));
63653 	bd->data = (const duk_uint8_t *) duk_builtins_data;
63654 	bd->length = (duk_size_t) DUK_BUILTINS_DATA_LENGTH;
63655 
63656 	/*
63657 	 *  First create all built-in bare objects on the empty valstack.
63658 	 *
63659 	 *  Built-ins in the index range [0,DUK_NUM_BUILTINS-1] have value
63660 	 *  stack indices matching their eventual thr->builtins[] index.
63661 	 *
63662 	 *  Built-ins in the index range [DUK_NUM_BUILTINS,DUK_NUM_ALL_BUILTINS]
63663 	 *  will exist on the value stack during init but won't be placed
63664 	 *  into thr->builtins[].  These are objects referenced in some way
63665 	 *  from thr->builtins[] roots but which don't need to be indexed by
63666 	 *  Duktape through thr->builtins[] (e.g. user custom objects).
63667 	 *
63668 	 *  Internal prototypes will be incorrect (NULL) at this stage.
63669 	 */
63670 
63671 	duk_require_stack(thr, DUK_NUM_ALL_BUILTINS);
63672 
63673 	DUK_DD(DUK_DDPRINT("create empty built-ins"));
63674 	DUK_ASSERT_TOP(thr, 0);
63675 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
63676 		duk_small_uint_t class_num;
63677 		duk_small_int_t len = -1;  /* must be signed */
63678 
63679 		class_num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63680 		len = (duk_small_int_t) duk_bd_decode_flagged_signed(bd, DUK__LENGTH_PROP_BITS, (duk_int32_t) -1 /*def_value*/);
63681 
63682 		if (class_num == DUK_HOBJECT_CLASS_FUNCTION) {
63683 			duk_small_uint_t natidx;
63684 			duk_small_int_t c_nargs;  /* must hold DUK_VARARGS */
63685 			duk_c_function c_func;
63686 			duk_int16_t magic;
63687 
63688 			DUK_DDD(DUK_DDDPRINT("len=%ld", (long) len));
63689 			DUK_ASSERT(len >= 0);
63690 
63691 			natidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63692 			DUK_ASSERT(natidx != 0);
63693 			c_func = duk_bi_native_functions[natidx];
63694 			DUK_ASSERT(c_func != NULL);
63695 
63696 			c_nargs = (duk_small_int_t) duk_bd_decode_flagged_signed(bd, DUK__NARGS_BITS, len /*def_value*/);
63697 			if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
63698 				c_nargs = DUK_VARARGS;
63699 			}
63700 
63701 			/* XXX: set magic directly here? (it could share the c_nargs arg) */
63702 			(void) duk_push_c_function_builtin(thr, c_func, c_nargs);
63703 			h = duk_known_hobject(thr, -1);
63704 
63705 			/* Currently all built-in native functions are strict.
63706 			 * duk_push_c_function() now sets strict flag, so
63707 			 * assert for it.
63708 			 */
63709 			DUK_ASSERT(DUK_HOBJECT_HAS_STRICT(h));
63710 
63711 			/* XXX: function properties */
63712 
63713 			duk__push_stridx_or_string(thr, bd);
63714 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
63715 			duk_xdef_prop_stridx_short(thr,
63716 			                           -2,
63717 			                           DUK_STRIDX_NAME,
63718 			                           DUK_PROPDESC_FLAGS_C);
63719 #else
63720 			duk_pop(thr);  /* Not very ideal but good enough for now. */
63721 #endif
63722 
63723 			/* Almost all global level Function objects are constructable
63724 			 * but not all: Function.prototype is a non-constructable,
63725 			 * callable Function.
63726 			 */
63727 			if (duk_bd_decode_flag(bd)) {
63728 				DUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE(h));
63729 			} else {
63730 				DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h);
63731 			}
63732 
63733 			/* Cast converts magic to 16-bit signed value */
63734 			magic = (duk_int16_t) duk_bd_decode_varuint(bd);
63735 			((duk_hnatfunc *) h)->magic = magic;
63736 		} else if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
63737 			duk_push_array(thr);
63738 		} else if (class_num == DUK_HOBJECT_CLASS_OBJENV) {
63739 			duk_hobjenv *env;
63740 			duk_hobject *global;
63741 
63742 			DUK_ASSERT(i == DUK_BIDX_GLOBAL_ENV);
63743 			DUK_ASSERT(DUK_BIDX_GLOBAL_ENV > DUK_BIDX_GLOBAL);
63744 
63745 			env = duk_hobjenv_alloc(thr,
63746 	                                        DUK_HOBJECT_FLAG_EXTENSIBLE |
63747 	                                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
63748 			DUK_ASSERT(env->target == NULL);
63749 			duk_push_hobject(thr, (duk_hobject *) env);
63750 
63751 			global = duk_known_hobject(thr, DUK_BIDX_GLOBAL);
63752 			DUK_ASSERT(global != NULL);
63753 			env->target = global;
63754 			DUK_HOBJECT_INCREF(thr, global);
63755 			DUK_ASSERT(env->has_this == 0);
63756 
63757 			DUK_HOBJENV_ASSERT_VALID(env);
63758 		} else {
63759 			DUK_ASSERT(class_num != DUK_HOBJECT_CLASS_DECENV);
63760 
63761 			(void) duk_push_object_helper(thr,
63762 			                              DUK_HOBJECT_FLAG_FASTREFS |
63763 			                              DUK_HOBJECT_FLAG_EXTENSIBLE,
63764 			                              -1);  /* no prototype or class yet */
63765 
63766 		}
63767 
63768 		h = duk_known_hobject(thr, -1);
63769 		DUK_HOBJECT_SET_CLASS_NUMBER(h, class_num);
63770 
63771 		if (i < DUK_NUM_BUILTINS) {
63772 			thr->builtins[i] = h;
63773 			DUK_HOBJECT_INCREF(thr, &h->hdr);
63774 		}
63775 
63776 		if (len >= 0) {
63777 			/* In ES2015+ built-in function object .length property
63778 			 * has property attributes C (configurable only):
63779 			 * http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-standard-built-in-objects
63780 			 *
63781 			 * Array.prototype remains an Array instance in ES2015+
63782 			 * and its length has attributes W (writable only).
63783 			 * Because .length is now virtual for duk_harray, it is
63784 			 * not encoded explicitly in init data.
63785 			 */
63786 
63787 			DUK_ASSERT(class_num != DUK_HOBJECT_CLASS_ARRAY);  /* .length is virtual */
63788 			duk_push_int(thr, len);
63789 			duk_xdef_prop_stridx_short(thr,
63790 			                           -2,
63791 			                           DUK_STRIDX_LENGTH,
63792 			                           DUK_PROPDESC_FLAGS_C);
63793 		}
63794 
63795 		/* enable exotic behaviors last */
63796 
63797 		if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
63798 			DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h));  /* set by duk_push_array() */
63799 		}
63800 		if (class_num == DUK_HOBJECT_CLASS_STRING) {
63801 			DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h);
63802 		}
63803 
63804 		/* some assertions */
63805 
63806 		DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h));
63807 		/* DUK_HOBJECT_FLAG_CONSTRUCTABLE varies */
63808 		DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(h));
63809 		DUK_ASSERT(!DUK_HOBJECT_HAS_COMPFUNC(h));
63810 		/* DUK_HOBJECT_FLAG_NATFUNC varies */
63811 		DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(h));
63812 		DUK_ASSERT(!DUK_HOBJECT_IS_PROXY(h));
63813 		DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(h) || class_num == DUK_HOBJECT_CLASS_ARRAY);
63814 		/* DUK_HOBJECT_FLAG_STRICT varies */
63815 		DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(h) ||  /* all native functions have NEWENV */
63816 		           DUK_HOBJECT_HAS_NEWENV(h));
63817 		DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(h));
63818 		DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(h));
63819 		/* DUK_HOBJECT_FLAG_EXOTIC_ARRAY varies */
63820 		/* DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ varies */
63821 		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h));
63822 
63823 		DUK_DDD(DUK_DDDPRINT("created built-in %ld, class=%ld, length=%ld", (long) i, (long) class_num, (long) len));
63824 	}
63825 
63826 	/*
63827 	 *  Then decode the builtins init data (see genbuiltins.py) to
63828 	 *  init objects.  Internal prototypes are set at this stage,
63829 	 *  with thr->builtins[] populated.
63830 	 */
63831 
63832 	DUK_DD(DUK_DDPRINT("initialize built-in object properties"));
63833 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
63834 		duk_small_uint_t t;
63835 		duk_small_uint_t num;
63836 
63837 		DUK_DDD(DUK_DDDPRINT("initializing built-in object at index %ld", (long) i));
63838 		h = duk_known_hobject(thr, (duk_idx_t) i);
63839 
63840 		t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63841 		if (t > 0) {
63842 			t--;
63843 			DUK_DDD(DUK_DDDPRINT("set internal prototype: built-in %ld", (long) t));
63844 			DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, duk_known_hobject(thr, (duk_idx_t) t));
63845 		} else if (DUK_HOBJECT_IS_NATFUNC(h)) {
63846 			/* Standard native built-ins cannot inherit from
63847 			 * %NativeFunctionPrototype%, they are required to
63848 			 * inherit from Function.prototype directly.
63849 			 */
63850 			DUK_ASSERT(thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE] != NULL);
63851 			DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
63852 		}
63853 
63854 		t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63855 		if (t > 0) {
63856 			/* 'prototype' property for all built-in objects (which have it) has attributes:
63857 			 *  [[Writable]] = false,
63858 			 *  [[Enumerable]] = false,
63859 			 *  [[Configurable]] = false
63860 			 */
63861 			t--;
63862 			DUK_DDD(DUK_DDDPRINT("set external prototype: built-in %ld", (long) t));
63863 			duk_dup(thr, (duk_idx_t) t);
63864 			duk_xdef_prop_stridx(thr, (duk_idx_t) i, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_NONE);
63865 		}
63866 
63867 		t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63868 		if (t > 0) {
63869 			/* 'constructor' property for all built-in objects (which have it) has attributes:
63870 			 *  [[Writable]] = true,
63871 			 *  [[Enumerable]] = false,
63872 			 *  [[Configurable]] = true
63873 			 */
63874 			t--;
63875 			DUK_DDD(DUK_DDDPRINT("set external constructor: built-in %ld", (long) t));
63876 			duk_dup(thr, (duk_idx_t) t);
63877 			duk_xdef_prop_stridx(thr, (duk_idx_t) i, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);
63878 		}
63879 
63880 		/* normal valued properties */
63881 		num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63882 		DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld normal valued properties", (long) i, (long) num));
63883 		for (j = 0; j < num; j++) {
63884 			duk_small_uint_t defprop_flags;
63885 
63886 			duk__push_stridx_or_string(thr, bd);
63887 
63888 			/*
63889 			 *  Property attribute defaults are defined in E5 Section 15 (first
63890 			 *  few pages); there is a default for all properties and a special
63891 			 *  default for 'length' properties.  Variation from the defaults is
63892 			 *  signaled using a single flag bit in the bitstream.
63893 			 */
63894 
63895 			defprop_flags = (duk_small_uint_t) duk_bd_decode_flagged(bd,
63896 			                                                         DUK__PROP_FLAGS_BITS,
63897 			                                                         (duk_uint32_t) DUK_PROPDESC_FLAGS_WC);
63898 			defprop_flags |= DUK_DEFPROP_FORCE |
63899 			                 DUK_DEFPROP_HAVE_VALUE |
63900 			                 DUK_DEFPROP_HAVE_WRITABLE |
63901 			                 DUK_DEFPROP_HAVE_ENUMERABLE |
63902 			                 DUK_DEFPROP_HAVE_CONFIGURABLE;  /* Defaults for data properties. */
63903 
63904 			/* The writable, enumerable, configurable flags in prop_flags
63905 			 * match both duk_def_prop() and internal property flags.
63906 			 */
63907 			DUK_ASSERT(DUK_PROPDESC_FLAG_WRITABLE == DUK_DEFPROP_WRITABLE);
63908 			DUK_ASSERT(DUK_PROPDESC_FLAG_ENUMERABLE == DUK_DEFPROP_ENUMERABLE);
63909 			DUK_ASSERT(DUK_PROPDESC_FLAG_CONFIGURABLE == DUK_DEFPROP_CONFIGURABLE);
63910 
63911 			t = (duk_small_uint_t) duk_bd_decode(bd, DUK__PROP_TYPE_BITS);
63912 
63913 			DUK_DDD(DUK_DDDPRINT("built-in %ld, normal-valued property %ld, key %!T, flags 0x%02lx, type %ld",
63914 			                     (long) i, (long) j, duk_get_tval(thr, -1), (unsigned long) defprop_flags, (long) t));
63915 
63916 			switch (t) {
63917 			case DUK__PROP_TYPE_DOUBLE: {
63918 				duk__push_double(thr, bd);
63919 				break;
63920 			}
63921 			case DUK__PROP_TYPE_STRING: {
63922 				duk__push_string(thr, bd);
63923 				break;
63924 			}
63925 			case DUK__PROP_TYPE_STRIDX: {
63926 				duk__push_stridx(thr, bd);
63927 				break;
63928 			}
63929 			case DUK__PROP_TYPE_BUILTIN: {
63930 				duk_small_uint_t bidx;
63931 
63932 				bidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63933 				duk_dup(thr, (duk_idx_t) bidx);
63934 				break;
63935 			}
63936 			case DUK__PROP_TYPE_UNDEFINED: {
63937 				duk_push_undefined(thr);
63938 				break;
63939 			}
63940 			case DUK__PROP_TYPE_BOOLEAN_TRUE: {
63941 				duk_push_true(thr);
63942 				break;
63943 			}
63944 			case DUK__PROP_TYPE_BOOLEAN_FALSE: {
63945 				duk_push_false(thr);
63946 				break;
63947 			}
63948 			case DUK__PROP_TYPE_ACCESSOR: {
63949 				duk_small_uint_t natidx_getter = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63950 				duk_small_uint_t natidx_setter = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63951 				duk_small_uint_t accessor_magic = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63952 				duk_c_function c_func_getter;
63953 				duk_c_function c_func_setter;
63954 
63955 				DUK_DDD(DUK_DDDPRINT("built-in accessor property: objidx=%ld, key=%!T, getteridx=%ld, setteridx=%ld, flags=0x%04lx",
63956 				                     (long) i, duk_get_tval(thr, -1), (long) natidx_getter, (long) natidx_setter, (unsigned long) defprop_flags));
63957 
63958 				c_func_getter = duk_bi_native_functions[natidx_getter];
63959 				if (c_func_getter != NULL) {
63960 					duk_push_c_function_builtin_noconstruct(thr, c_func_getter, 0);  /* always 0 args */
63961 					duk_set_magic(thr, -1, (duk_int_t) accessor_magic);
63962 					defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
63963 				}
63964 				c_func_setter = duk_bi_native_functions[natidx_setter];
63965 				if (c_func_setter != NULL) {
63966 					duk_push_c_function_builtin_noconstruct(thr, c_func_setter, 1);  /* always 1 arg */
63967 					duk_set_magic(thr, -1, (duk_int_t) accessor_magic);
63968 					defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
63969 				}
63970 
63971 				/* Writable flag doesn't make sense for an accessor. */
63972 				DUK_ASSERT((defprop_flags & DUK_PROPDESC_FLAG_WRITABLE) == 0);  /* genbuiltins.py ensures */
63973 
63974 				defprop_flags &= ~(DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);
63975 				defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_HAVE_CONFIGURABLE;
63976 				break;
63977 			}
63978 			default: {
63979 				/* exhaustive */
63980 				DUK_UNREACHABLE();
63981 			}
63982 			}
63983 
63984 			duk_def_prop(thr, (duk_idx_t) i, defprop_flags);
63985 			DUK_ASSERT_TOP(thr, DUK_NUM_ALL_BUILTINS);
63986 		}
63987 
63988 		/* native function properties */
63989 		num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
63990 		DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld function valued properties", (long) i, (long) num));
63991 		for (j = 0; j < num; j++) {
63992 			duk_hstring *h_key;
63993 			duk_small_uint_t natidx;
63994 			duk_int_t c_nargs;  /* must hold DUK_VARARGS */
63995 			duk_small_uint_t c_length;
63996 			duk_int16_t magic;
63997 			duk_c_function c_func;
63998 			duk_hnatfunc *h_func;
63999 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
64000 			duk_small_int_t lightfunc_eligible;
64001 #endif
64002 			duk_small_uint_t defprop_flags;
64003 
64004 			duk__push_stridx_or_string(thr, bd);
64005 			h_key = duk_known_hstring(thr, -1);
64006 			DUK_UNREF(h_key);
64007 			natidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);
64008 
64009 			c_length = (duk_small_uint_t) duk_bd_decode(bd, DUK__LENGTH_PROP_BITS);
64010 			c_nargs = (duk_int_t) duk_bd_decode_flagged(bd, DUK__NARGS_BITS, (duk_uint32_t) c_length /*def_value*/);
64011 			if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
64012 				c_nargs = DUK_VARARGS;
64013 			}
64014 
64015 			c_func = duk_bi_native_functions[natidx];
64016 
64017 			DUK_DDD(DUK_DDDPRINT("built-in %ld, function-valued property %ld, key %!O, natidx %ld, length %ld, nargs %ld",
64018 			                     (long) i, (long) j, (duk_heaphdr *) h_key, (long) natidx, (long) c_length,
64019 			                     (c_nargs == DUK_VARARGS ? (long) -1 : (long) c_nargs)));
64020 
64021 			/* Cast converts magic to 16-bit signed value */
64022 			magic = (duk_int16_t) duk_bd_decode_varuint(bd);
64023 
64024 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
64025 			lightfunc_eligible =
64026 				((c_nargs >= DUK_LFUNC_NARGS_MIN && c_nargs <= DUK_LFUNC_NARGS_MAX) || (c_nargs == DUK_VARARGS)) &&
64027 				(c_length <= DUK_LFUNC_LENGTH_MAX) &&
64028 				(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX);
64029 
64030 			/* These functions have trouble working as lightfuncs.
64031 			 * Some of them have specific asserts and some may have
64032 		         * additional properties (e.g. 'require.id' may be written).
64033 			 */
64034 			if (c_func == duk_bi_global_object_eval) {
64035 				lightfunc_eligible = 0;
64036 			}
64037 #if defined(DUK_USE_COROUTINE_SUPPORT)
64038 			if (c_func == duk_bi_thread_yield ||
64039 			    c_func == duk_bi_thread_resume) {
64040 				lightfunc_eligible = 0;
64041 			}
64042 #endif
64043 			if (c_func == duk_bi_function_prototype_call ||
64044 			    c_func == duk_bi_function_prototype_apply ||
64045 			    c_func == duk_bi_reflect_apply ||
64046 			    c_func == duk_bi_reflect_construct) {
64047 				lightfunc_eligible = 0;
64048 			}
64049 
64050 			if (lightfunc_eligible) {
64051 				duk_tval tv_lfunc;
64052 				duk_small_uint_t lf_nargs = (duk_small_uint_t) (c_nargs == DUK_VARARGS ? DUK_LFUNC_NARGS_VARARGS : c_nargs);
64053 				duk_small_uint_t lf_flags = DUK_LFUNC_FLAGS_PACK(magic, c_length, lf_nargs);
64054 				DUK_TVAL_SET_LIGHTFUNC(&tv_lfunc, c_func, lf_flags);
64055 				duk_push_tval(thr, &tv_lfunc);
64056 				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)));
64057 				goto lightfunc_skip;
64058 			}
64059 
64060 			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));
64061 #endif  /* DUK_USE_LIGHTFUNC_BUILTINS */
64062 
64063 			/* [ (builtin objects) name ] */
64064 
64065 			duk_push_c_function_builtin_noconstruct(thr, c_func, c_nargs);
64066 			h_func = duk_known_hnatfunc(thr, -1);
64067 			DUK_UNREF(h_func);
64068 
64069 			/* XXX: add into init data? */
64070 
64071 			/* Special call handling, not described in init data. */
64072 			if (c_func == duk_bi_global_object_eval ||
64073 			    c_func == duk_bi_function_prototype_call ||
64074 			    c_func == duk_bi_function_prototype_apply ||
64075 			    c_func == duk_bi_reflect_apply ||
64076 			    c_func == duk_bi_reflect_construct) {
64077 				DUK_HOBJECT_SET_SPECIAL_CALL((duk_hobject *) h_func);
64078 			}
64079 
64080 			/* Currently all built-in native functions are strict.
64081 			 * This doesn't matter for many functions, but e.g.
64082 			 * String.prototype.charAt (and other string functions)
64083 			 * rely on being strict so that their 'this' binding is
64084 			 * not automatically coerced.
64085 			 */
64086 			DUK_HOBJECT_SET_STRICT((duk_hobject *) h_func);
64087 
64088 			/* No built-in functions are constructable except the top
64089 			 * level ones (Number, etc).
64090 			 */
64091 			DUK_ASSERT(!DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_func));
64092 
64093 			/* XXX: any way to avoid decoding magic bit; there are quite
64094 			 * many function properties and relatively few with magic values.
64095 			 */
64096 			h_func->magic = magic;
64097 
64098 			/* [ (builtin objects) name func ] */
64099 
64100 			duk_push_uint(thr, c_length);
64101 			duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
64102 
64103 			duk_dup_m2(thr);
64104 			duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
64105 
64106 			/* XXX: other properties of function instances; 'arguments', 'caller'. */
64107 
64108 			DUK_DD(DUK_DDPRINT("built-in object %ld, function property %ld -> %!T",
64109 			                   (long) i, (long) j, (duk_tval *) duk_get_tval(thr, -1)));
64110 
64111 			/* [ (builtin objects) name func ] */
64112 
64113 			/*
64114 			 *  The default property attributes are correct for all
64115 			 *  function valued properties of built-in objects now.
64116 			 */
64117 
64118 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
64119 		 lightfunc_skip:
64120 #endif
64121 
64122 			defprop_flags = (duk_small_uint_t) duk_bd_decode_flagged(bd,
64123 			                                                         DUK__PROP_FLAGS_BITS,
64124 			                                                         (duk_uint32_t) DUK_PROPDESC_FLAGS_WC);
64125 			defprop_flags |= DUK_DEFPROP_FORCE |
64126 			                 DUK_DEFPROP_HAVE_VALUE |
64127 			                 DUK_DEFPROP_HAVE_WRITABLE |
64128 			                 DUK_DEFPROP_HAVE_ENUMERABLE |
64129 			                 DUK_DEFPROP_HAVE_CONFIGURABLE;
64130 			DUK_ASSERT(DUK_PROPDESC_FLAG_WRITABLE == DUK_DEFPROP_WRITABLE);
64131 			DUK_ASSERT(DUK_PROPDESC_FLAG_ENUMERABLE == DUK_DEFPROP_ENUMERABLE);
64132 			DUK_ASSERT(DUK_PROPDESC_FLAG_CONFIGURABLE == DUK_DEFPROP_CONFIGURABLE);
64133 
64134 			duk_def_prop(thr, (duk_idx_t) i, defprop_flags);
64135 
64136 			/* [ (builtin objects) ] */
64137 		}
64138 	}
64139 
64140 	/*
64141 	 *  Special post-tweaks, for cases not covered by the init data format.
64142 	 *
64143 	 *  - Set Date.prototype.toGMTString to Date.prototype.toUTCString.
64144 	 *    toGMTString is required to have the same Function object as
64145 	 *    toUTCString in E5 Section B.2.6.  Note that while Smjs respects
64146 	 *    this, V8 does not (the Function objects are distinct).
64147 	 *
64148 	 *  - Make DoubleError non-extensible.
64149 	 *
64150 	 *  - Add info about most important effective compile options to Duktape.
64151 	 *
64152 	 *  - Possibly remove some properties (values or methods) which are not
64153 	 *    desirable with current feature options but are not currently
64154 	 *    conditional in init data.
64155 	 */
64156 
64157 #if defined(DUK_USE_DATE_BUILTIN)
64158 	duk_get_prop_stridx_short(thr, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_UTC_STRING);
64159 	duk_xdef_prop_stridx_short(thr, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_GMT_STRING, DUK_PROPDESC_FLAGS_WC);
64160 #endif
64161 
64162 	h = duk_known_hobject(thr, DUK_BIDX_DOUBLE_ERROR);
64163 	DUK_HOBJECT_CLEAR_EXTENSIBLE(h);
64164 
64165 #if !defined(DUK_USE_ES6_OBJECT_PROTO_PROPERTY)
64166 	DUK_DD(DUK_DDPRINT("delete Object.prototype.__proto__ built-in which is not enabled in features"));
64167 	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_PROTOTYPE], DUK_HTHREAD_STRING___PROTO__(thr), DUK_DELPROP_FLAG_THROW);
64168 #endif
64169 
64170 #if !defined(DUK_USE_ES6_OBJECT_SETPROTOTYPEOF)
64171 	DUK_DD(DUK_DDPRINT("delete Object.setPrototypeOf built-in which is not enabled in features"));
64172 	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_CONSTRUCTOR], DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr), DUK_DELPROP_FLAG_THROW);
64173 #endif
64174 
64175 	/* XXX: relocate */
64176 	duk_push_string(thr,
64177 			/* Endianness indicator */
64178 #if defined(DUK_USE_INTEGER_LE)
64179 	                "l"
64180 #elif defined(DUK_USE_INTEGER_BE)
64181 	                "b"
64182 #elif defined(DUK_USE_INTEGER_ME)  /* integer mixed endian not really used now */
64183 	                "m"
64184 #else
64185 	                "?"
64186 #endif
64187 #if defined(DUK_USE_DOUBLE_LE)
64188 	                "l"
64189 #elif defined(DUK_USE_DOUBLE_BE)
64190 	                "b"
64191 #elif defined(DUK_USE_DOUBLE_ME)
64192 	                "m"
64193 #else
64194 	                "?"
64195 #endif
64196 	                " "
64197 			/* Packed or unpacked tval */
64198 #if defined(DUK_USE_PACKED_TVAL)
64199 	                "p"
64200 #else
64201 	                "u"
64202 #endif
64203 #if defined(DUK_USE_FASTINT)
64204 			"f"
64205 #endif
64206 			" "
64207 			/* Low memory/performance options */
64208 #if defined(DUK_USE_STRTAB_PTRCOMP)
64209 			"s"
64210 #endif
64211 #if !defined(DUK_USE_HEAPPTR16) && !defined(DUK_DATAPTR16) && !defined(DUK_FUNCPTR16)
64212 			"n"
64213 #endif
64214 #if defined(DUK_USE_HEAPPTR16)
64215 			"h"
64216 #endif
64217 #if defined(DUK_USE_DATAPTR16)
64218 			"d"
64219 #endif
64220 #if defined(DUK_USE_FUNCPTR16)
64221 			"f"
64222 #endif
64223 #if defined(DUK_USE_REFCOUNT16)
64224 			"R"
64225 #endif
64226 #if defined(DUK_USE_STRHASH16)
64227 			"H"
64228 #endif
64229 #if defined(DUK_USE_STRLEN16)
64230 			"S"
64231 #endif
64232 #if defined(DUK_USE_BUFLEN16)
64233 			"B"
64234 #endif
64235 #if defined(DUK_USE_OBJSIZES16)
64236 			"O"
64237 #endif
64238 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
64239 			"L"
64240 #endif
64241 #if defined(DUK_USE_ROM_STRINGS) || defined(DUK_USE_ROM_OBJECTS)
64242 			/* XXX: This won't be shown in practice now
64243 			 * because this code is not run when builtins
64244 			 * are in ROM.
64245 			 */
64246 			"Z"
64247 #endif
64248 #if defined(DUK_USE_LITCACHE_SIZE)
64249 			"l"
64250 #endif
64251 	                " "
64252 			/* Object property allocation layout */
64253 #if defined(DUK_USE_HOBJECT_LAYOUT_1)
64254 			"p1"
64255 #elif defined(DUK_USE_HOBJECT_LAYOUT_2)
64256 			"p2"
64257 #elif defined(DUK_USE_HOBJECT_LAYOUT_3)
64258 			"p3"
64259 #else
64260 			"p?"
64261 #endif
64262 			" "
64263 			/* Alignment guarantee */
64264 #if (DUK_USE_ALIGN_BY == 4)
64265 			"a4"
64266 #elif (DUK_USE_ALIGN_BY == 8)
64267 			"a8"
64268 #elif (DUK_USE_ALIGN_BY == 1)
64269 			"a1"
64270 #else
64271 #error invalid DUK_USE_ALIGN_BY
64272 #endif
64273 			" "
64274 			/* Architecture, OS, and compiler strings */
64275 	                DUK_USE_ARCH_STRING
64276 			" "
64277 	                DUK_USE_OS_STRING
64278 			" "
64279 	                DUK_USE_COMPILER_STRING);
64280 	duk_xdef_prop_stridx_short(thr, DUK_BIDX_DUKTAPE, DUK_STRIDX_ENV, DUK_PROPDESC_FLAGS_WC);
64281 
64282 	/*
64283 	 *  Since built-ins are not often extended, compact them.
64284 	 */
64285 
64286 	DUK_DD(DUK_DDPRINT("compact built-ins"));
64287 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
64288 		duk_hobject_compact_props(thr, duk_known_hobject(thr, (duk_idx_t) i));
64289 	}
64290 
64291 	DUK_D(DUK_DPRINT("INITBUILTINS END"));
64292 
64293 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
64294 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
64295 		DUK_DD(DUK_DDPRINT("built-in object %ld after initialization and compacting: %!@iO",
64296 		                   (long) i, (duk_heaphdr *) duk_require_hobject(thr, (duk_idx_t) i)));
64297 	}
64298 #endif
64299 
64300 	/*
64301 	 *  Pop built-ins from stack: they are now INCREF'd and
64302 	 *  reachable from the builtins[] array or indirectly
64303 	 *  through builtins[].
64304 	 */
64305 
64306 	duk_set_top(thr, 0);
64307 	DUK_ASSERT_TOP(thr, 0);
64308 }
64309 #endif  /* DUK_USE_ROM_OBJECTS */
64310 
64311 DUK_INTERNAL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to) {
64312 	duk_small_uint_t i;
64313 
64314 	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
64315 		thr_to->builtins[i] = thr_from->builtins[i];
64316 		DUK_HOBJECT_INCREF_ALLOWNULL(thr_to, thr_to->builtins[i]);  /* side effect free */
64317 	}
64318 }
64319 
64320 /* automatic undefs */
64321 #undef DUK__LENGTH_PROP_BITS
64322 #undef DUK__NARGS_BITS
64323 #undef DUK__NARGS_VARARGS_MARKER
64324 #undef DUK__PROP_FLAGS_BITS
64325 #undef DUK__PROP_TYPE_ACCESSOR
64326 #undef DUK__PROP_TYPE_BITS
64327 #undef DUK__PROP_TYPE_BOOLEAN_FALSE
64328 #undef DUK__PROP_TYPE_BOOLEAN_TRUE
64329 #undef DUK__PROP_TYPE_BUILTIN
64330 #undef DUK__PROP_TYPE_DOUBLE
64331 #undef DUK__PROP_TYPE_STRIDX
64332 #undef DUK__PROP_TYPE_STRING
64333 #undef DUK__PROP_TYPE_UNDEFINED
64334 #line 1 "duk_hthread_misc.c"
64335 /*
64336  *  Thread support.
64337  */
64338 
64339 /* #include duk_internal.h -> already included */
64340 
64341 DUK_INTERNAL void duk_hthread_terminate(duk_hthread *thr) {
64342 	DUK_ASSERT(thr != NULL);
64343 
64344 	while (thr->callstack_curr != NULL) {
64345 		duk_hthread_activation_unwind_norz(thr);
64346 	}
64347 
64348 	thr->valstack_bottom = thr->valstack;
64349 	duk_set_top(thr, 0);  /* unwinds valstack, updating refcounts */
64350 
64351 	thr->state = DUK_HTHREAD_STATE_TERMINATED;
64352 
64353 	/* Here we could remove references to built-ins, but it may not be
64354 	 * worth the effort because built-ins are quite likely to be shared
64355 	 * with another (unterminated) thread, and terminated threads are also
64356 	 * usually garbage collected quite quickly.
64357 	 *
64358 	 * We could also shrink the value stack here, but that also may not
64359 	 * be worth the effort for the same reason.
64360 	 */
64361 
64362 	DUK_REFZERO_CHECK_SLOW(thr);
64363 }
64364 
64365 #if defined(DUK_USE_DEBUGGER_SUPPORT)
64366 DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act) {
64367 	duk_instr_t *bcode;
64368 
64369 	DUK_ASSERT(thr != NULL);
64370 	DUK_ASSERT(act != NULL);
64371 	DUK_UNREF(thr);
64372 
64373 	/* XXX: store 'bcode' pointer to activation for faster lookup? */
64374 	if (act->func && DUK_HOBJECT_IS_COMPFUNC(act->func)) {
64375 		bcode = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) (act->func));
64376 		return (duk_uint_fast32_t) (act->curr_pc - bcode);
64377 	}
64378 	return 0;
64379 }
64380 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
64381 
64382 DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act) {
64383 	duk_instr_t *bcode;
64384 	duk_uint_fast32_t ret;
64385 
64386 	DUK_ASSERT(thr != NULL);
64387 	DUK_ASSERT(act != NULL);
64388 	DUK_UNREF(thr);
64389 
64390 	if (act->func && DUK_HOBJECT_IS_COMPFUNC(act->func)) {
64391 		bcode = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) (act->func));
64392 		ret = (duk_uint_fast32_t) (act->curr_pc - bcode);
64393 		if (ret > 0) {
64394 			ret--;
64395 		}
64396 		return ret;
64397 	}
64398 	return 0;
64399 }
64400 
64401 /* Write bytecode executor's curr_pc back to topmost activation (if any). */
64402 DUK_INTERNAL void duk_hthread_sync_currpc(duk_hthread *thr) {
64403 	duk_activation *act;
64404 
64405 	DUK_ASSERT(thr != NULL);
64406 
64407 	if (thr->ptr_curr_pc != NULL) {
64408 		/* ptr_curr_pc != NULL only when bytecode executor is active. */
64409 		DUK_ASSERT(thr->callstack_top > 0);
64410 		DUK_ASSERT(thr->callstack_curr != NULL);
64411 		act = thr->callstack_curr;
64412 		DUK_ASSERT(act != NULL);
64413 		act->curr_pc = *thr->ptr_curr_pc;
64414 	}
64415 }
64416 
64417 DUK_INTERNAL void duk_hthread_sync_and_null_currpc(duk_hthread *thr) {
64418 	duk_activation *act;
64419 
64420 	DUK_ASSERT(thr != NULL);
64421 
64422 	if (thr->ptr_curr_pc != NULL) {
64423 		/* ptr_curr_pc != NULL only when bytecode executor is active. */
64424 		DUK_ASSERT(thr->callstack_top > 0);
64425 		DUK_ASSERT(thr->callstack_curr != NULL);
64426 		act = thr->callstack_curr;
64427 		DUK_ASSERT(act != NULL);
64428 		act->curr_pc = *thr->ptr_curr_pc;
64429 		thr->ptr_curr_pc = NULL;
64430 	}
64431 }
64432 #line 1 "duk_hthread_stacks.c"
64433 /*
64434  *  Thread stack (mainly call stack) primitives: allocation of activations,
64435  *  unwinding catchers and activations, etc.
64436  *
64437  *  Value stack handling is a part of the API implementation.
64438  */
64439 
64440 /* #include duk_internal.h -> already included */
64441 
64442 /* Unwind the topmost catcher of the current activation (caller must check that
64443  * both exist) without side effects.
64444  */
64445 DUK_INTERNAL void duk_hthread_catcher_unwind_norz(duk_hthread *thr, duk_activation *act) {
64446 	duk_catcher *cat;
64447 
64448 	DUK_ASSERT(thr != NULL);
64449 	DUK_ASSERT(act != NULL);
64450 	DUK_ASSERT(act->cat != NULL);  /* caller must check */
64451 	cat = act->cat;
64452 	DUK_ASSERT(cat != NULL);
64453 
64454 	DUK_DDD(DUK_DDDPRINT("unwinding catch stack entry %p (lexenv check is done)", (void *) cat));
64455 
64456 	if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
64457 		duk_hobject *env;
64458 
64459 		env = act->lex_env;             /* current lex_env of the activation (created for catcher) */
64460 		DUK_ASSERT(env != NULL);        /* must be, since env was created when catcher was created */
64461 		act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);  /* prototype is lex_env before catcher created */
64462 		DUK_HOBJECT_INCREF(thr, act->lex_env);
64463 		DUK_HOBJECT_DECREF_NORZ(thr, env);
64464 
64465 		/* There is no need to decref anything else than 'env': if 'env'
64466 		 * becomes unreachable, refzero will handle decref'ing its prototype.
64467 		 */
64468 	}
64469 
64470 	act->cat = cat->parent;
64471 	duk_hthread_catcher_free(thr, cat);
64472 }
64473 
64474 /* Same as above, but caller is certain no catcher-related lexenv may exist. */
64475 DUK_INTERNAL void duk_hthread_catcher_unwind_nolexenv_norz(duk_hthread *thr, duk_activation *act) {
64476 	duk_catcher *cat;
64477 
64478 	DUK_ASSERT(thr != NULL);
64479 	DUK_ASSERT(act != NULL);
64480 	DUK_ASSERT(act->cat != NULL);  /* caller must check */
64481 	cat = act->cat;
64482 	DUK_ASSERT(cat != NULL);
64483 
64484 	DUK_DDD(DUK_DDDPRINT("unwinding catch stack entry %p (lexenv check is not done)", (void *) cat));
64485 
64486 	DUK_ASSERT(!DUK_CAT_HAS_LEXENV_ACTIVE(cat));
64487 
64488 	act->cat = cat->parent;
64489 	duk_hthread_catcher_free(thr, cat);
64490 }
64491 
64492 DUK_LOCAL
64493 #if defined(DUK_USE_CACHE_CATCHER)
64494 DUK_NOINLINE
64495 #endif
64496 duk_catcher *duk__hthread_catcher_alloc_slow(duk_hthread *thr) {
64497 	duk_catcher *cat;
64498 
64499 	cat = (duk_catcher *) DUK_ALLOC_CHECKED(thr, sizeof(duk_catcher));
64500 	DUK_ASSERT(cat != NULL);
64501 	return cat;
64502 }
64503 
64504 #if defined(DUK_USE_CACHE_CATCHER)
64505 DUK_INTERNAL DUK_INLINE duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr) {
64506 	duk_catcher *cat;
64507 
64508 	DUK_ASSERT(thr != NULL);
64509 
64510 	cat = thr->heap->catcher_free;
64511 	if (DUK_LIKELY(cat != NULL)) {
64512 		thr->heap->catcher_free = cat->parent;
64513 		return cat;
64514 	}
64515 
64516 	return duk__hthread_catcher_alloc_slow(thr);
64517 }
64518 #else  /* DUK_USE_CACHE_CATCHER */
64519 DUK_INTERNAL duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr) {
64520 	return duk__hthread_catcher_alloc_slow(thr);
64521 }
64522 #endif  /* DUK_USE_CACHE_CATCHER */
64523 
64524 DUK_INTERNAL void duk_hthread_catcher_free(duk_hthread *thr, duk_catcher *cat) {
64525 	DUK_ASSERT(thr != NULL);
64526 	DUK_ASSERT(cat != NULL);
64527 
64528 #if defined(DUK_USE_CACHE_CATCHER)
64529 	/* Unconditional caching for now; freed in mark-and-sweep. */
64530 	cat->parent = thr->heap->catcher_free;
64531 	thr->heap->catcher_free = cat;
64532 #else
64533 	DUK_FREE_CHECKED(thr, (void *) cat);
64534 #endif
64535 }
64536 
64537 DUK_LOCAL
64538 #if defined(DUK_USE_CACHE_ACTIVATION)
64539 DUK_NOINLINE
64540 #endif
64541 duk_activation *duk__hthread_activation_alloc_slow(duk_hthread *thr) {
64542 	duk_activation *act;
64543 
64544 	act = (duk_activation *) DUK_ALLOC_CHECKED(thr, sizeof(duk_activation));
64545 	DUK_ASSERT(act != NULL);
64546 	return act;
64547 }
64548 
64549 #if defined(DUK_USE_CACHE_ACTIVATION)
64550 DUK_INTERNAL DUK_INLINE duk_activation *duk_hthread_activation_alloc(duk_hthread *thr) {
64551 	duk_activation *act;
64552 
64553 	DUK_ASSERT(thr != NULL);
64554 
64555 	act = thr->heap->activation_free;
64556 	if (DUK_LIKELY(act != NULL)) {
64557 		thr->heap->activation_free = act->parent;
64558 		return act;
64559 	}
64560 
64561 	return duk__hthread_activation_alloc_slow(thr);
64562 }
64563 #else  /* DUK_USE_CACHE_ACTIVATION */
64564 DUK_INTERNAL duk_activation *duk_hthread_activation_alloc(duk_hthread *thr) {
64565 	return duk__hthread_activation_alloc_slow(thr);
64566 }
64567 #endif  /* DUK_USE_CACHE_ACTIVATION */
64568 
64569 
64570 DUK_INTERNAL void duk_hthread_activation_free(duk_hthread *thr, duk_activation *act) {
64571 	DUK_ASSERT(thr != NULL);
64572 	DUK_ASSERT(act != NULL);
64573 
64574 #if defined(DUK_USE_CACHE_ACTIVATION)
64575 	/* Unconditional caching for now; freed in mark-and-sweep. */
64576 	act->parent = thr->heap->activation_free;
64577 	thr->heap->activation_free = act;
64578 #else
64579 	DUK_FREE_CHECKED(thr, (void *) act);
64580 #endif
64581 }
64582 
64583 /* Internal helper: process the unwind for the topmost activation of a thread,
64584  * but leave the duk_activation in place for possible tailcall reuse.
64585  */
64586 DUK_LOCAL void duk__activation_unwind_nofree_norz(duk_hthread *thr) {
64587 #if defined(DUK_USE_DEBUGGER_SUPPORT)
64588 	duk_heap *heap;
64589 #endif
64590 	duk_activation *act;
64591 	duk_hobject *func;
64592 	duk_hobject *tmp;
64593 
64594 	DUK_ASSERT(thr != NULL);
64595 	DUK_ASSERT(thr->callstack_curr != NULL);  /* caller must check */
64596 	DUK_ASSERT(thr->callstack_top > 0);
64597 	act = thr->callstack_curr;
64598 	DUK_ASSERT(act != NULL);
64599 	/* With lightfuncs, act 'func' may be NULL. */
64600 
64601 	/* With duk_activation records allocated separately, 'act' is a stable
64602 	 * pointer and not affected by side effects.
64603 	 */
64604 
64605 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
64606 	/*
64607 	 *  Restore 'caller' property for non-strict callee functions.
64608 	 */
64609 
64610 	func = DUK_ACT_GET_FUNC(act);
64611 	if (func != NULL && !DUK_HOBJECT_HAS_STRICT(func)) {
64612 		duk_tval *tv_caller;
64613 		duk_tval tv_tmp;
64614 		duk_hobject *h_tmp;
64615 
64616 		tv_caller = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, func, DUK_STRIDX_CALLER);
64617 
64618 		/* The act->prev_caller should only be set if the entry for 'caller'
64619 		 * exists (as it is only set in that case, and the property is not
64620 		 * configurable), but handle all the cases anyway.
64621 		 */
64622 
64623 		if (tv_caller) {
64624 			DUK_TVAL_SET_TVAL(&tv_tmp, tv_caller);
64625 			if (act->prev_caller) {
64626 				/* Just transfer the refcount from act->prev_caller to tv_caller,
64627 				 * so no need for a refcount update.  This is the expected case.
64628 				 */
64629 				DUK_TVAL_SET_OBJECT(tv_caller, act->prev_caller);
64630 				act->prev_caller = NULL;
64631 			} else {
64632 				DUK_TVAL_SET_NULL(tv_caller);   /* no incref needed */
64633 				DUK_ASSERT(act->prev_caller == NULL);
64634 			}
64635 			DUK_TVAL_DECREF_NORZ(thr, &tv_tmp);
64636 		} else {
64637 			h_tmp = act->prev_caller;
64638 			if (h_tmp) {
64639 				act->prev_caller = NULL;
64640 				DUK_HOBJECT_DECREF_NORZ(thr, h_tmp);
64641 			}
64642 		}
64643 		DUK_ASSERT(act->prev_caller == NULL);
64644 	}
64645 #endif
64646 
64647 	/*
64648 	 *  Unwind debugger state.  If we unwind while stepping
64649 	 *  (for any step type), pause execution.  This is the
64650 	 *  only place explicitly handling a step out.
64651 	 */
64652 
64653 #if defined(DUK_USE_DEBUGGER_SUPPORT)
64654 	heap = thr->heap;
64655 	if (heap->dbg_pause_act == thr->callstack_curr) {
64656 		if (heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_EXIT) {
64657 			DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function exit"));
64658 			duk_debug_set_paused(heap);
64659 		} else {
64660 			DUK_D(DUK_DPRINT("unwound past dbg_pause_act, set to NULL"));
64661 			heap->dbg_pause_act = NULL;  /* avoid stale pointers */
64662 		}
64663 		DUK_ASSERT(heap->dbg_pause_act == NULL);
64664 	}
64665 #endif
64666 
64667 	/*
64668 	 *  Unwind catchers.
64669 	 *
64670 	 *  Since there are no references in the catcher structure,
64671 	 *  unwinding is quite simple.  The only thing we need to
64672 	 *  look out for is popping a possible lexical environment
64673 	 *  established for an active catch clause.
64674 	 */
64675 
64676 	while (act->cat != NULL) {
64677 		duk_hthread_catcher_unwind_norz(thr, act);
64678 	}
64679 
64680 	/*
64681 	 *  Close environment record(s) if they exist.
64682 	 *
64683 	 *  Only variable environments are closed.  If lex_env != var_env, it
64684 	 *  cannot currently contain any register bound declarations.
64685 	 *
64686 	 *  Only environments created for a NEWENV function are closed.  If an
64687 	 *  environment is created for e.g. an eval call, it must not be closed.
64688 	 */
64689 
64690 	func = DUK_ACT_GET_FUNC(act);
64691 	if (func != NULL && !DUK_HOBJECT_HAS_NEWENV(func)) {
64692 		DUK_DDD(DUK_DDDPRINT("skip closing environments, envs not owned by this activation"));
64693 		goto skip_env_close;
64694 	}
64695 	/* func is NULL for lightfunc */
64696 
64697 	/* Catch sites are required to clean up their environments
64698 	 * in FINALLY part before propagating, so this should
64699 	 * always hold here.
64700 	 */
64701 	DUK_ASSERT(act->lex_env == act->var_env);
64702 
64703 	/* XXX: Closing the environment record copies values from registers
64704 	 * into the scope object.  It's side effect free as such, but may
64705 	 * currently run out of memory which causes an error throw.  This is
64706 	 * an actual sandboxing problem for error unwinds, and needs to be
64707 	 * fixed e.g. by preallocating the scope property slots.
64708 	 */
64709 	if (act->var_env != NULL) {
64710 		DUK_DDD(DUK_DDDPRINT("closing var_env record %p -> %!O",
64711 		                     (void *) act->var_env, (duk_heaphdr *) act->var_env));
64712 		duk_js_close_environment_record(thr, act->var_env);
64713 	}
64714 
64715  skip_env_close:
64716 
64717 	/*
64718 	 *  Update preventcount
64719 	 */
64720 
64721 	if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
64722 		DUK_ASSERT(thr->callstack_preventcount >= 1);
64723 		thr->callstack_preventcount--;
64724 	}
64725 
64726 	/*
64727 	 *  Reference count updates, using NORZ macros so we don't
64728 	 *  need to handle side effects.
64729 	 *
64730 	 *  duk_activation pointers like act->var_env are intentionally
64731 	 *  left as garbage and not NULLed.  Without side effects they
64732 	 *  can't be used when the values are dangling/garbage.
64733 	 */
64734 
64735 	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, act->var_env);
64736 	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, act->lex_env);
64737 	tmp = DUK_ACT_GET_FUNC(act);
64738 	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
64739 	DUK_UNREF(tmp);
64740 }
64741 
64742 /* Unwind topmost duk_activation of a thread, caller must ensure that an
64743  * activation exists.  The call is side effect free, except that scope
64744  * closure may currently throw an out-of-memory error.
64745  */
64746 DUK_INTERNAL void duk_hthread_activation_unwind_norz(duk_hthread *thr) {
64747 	duk_activation *act;
64748 
64749 	duk__activation_unwind_nofree_norz(thr);
64750 
64751 	DUK_ASSERT(thr->callstack_curr != NULL);
64752 	DUK_ASSERT(thr->callstack_top > 0);
64753 	act = thr->callstack_curr;
64754 	thr->callstack_curr = act->parent;
64755 	thr->callstack_top--;
64756 
64757 	/* Ideally we'd restore value stack reserve here to caller's value.
64758 	 * This doesn't work for current unwind call sites however, because
64759 	 * the current (unwound) value stack top may be above the reserve.
64760 	 * Thus value stack reserve is restored by the call sites.
64761 	 */
64762 
64763 	/* XXX: inline for performance builds? */
64764 	duk_hthread_activation_free(thr, act);
64765 
64766 	/* We could clear the book-keeping variables like retval_byteoff for
64767 	 * the topmost activation, but don't do so now as it's not necessary.
64768 	 */
64769 }
64770 
64771 DUK_INTERNAL void duk_hthread_activation_unwind_reuse_norz(duk_hthread *thr) {
64772 	duk__activation_unwind_nofree_norz(thr);
64773 }
64774 
64775 /* Get duk_activation for given callstack level or NULL if level is invalid
64776  * or deeper than the call stack.  Level -1 refers to current activation, -2
64777  * to its caller, etc.  Starting from Duktape 2.2 finding the activation is
64778  * a linked list scan which gets more expensive the deeper the lookup is.
64779  */
64780 DUK_INTERNAL duk_activation *duk_hthread_get_activation_for_level(duk_hthread *thr, duk_int_t level) {
64781 	duk_activation *act;
64782 
64783 	if (level >= 0) {
64784 		return NULL;
64785 	}
64786 	act = thr->callstack_curr;
64787 	for (;;) {
64788 		if (act == NULL) {
64789 			return act;
64790 		}
64791 		if (level == -1) {
64792 			return act;
64793 		}
64794 		level++;
64795 		act = act->parent;
64796 	}
64797 	/* never here */
64798 }
64799 
64800 #if defined(DUK_USE_FINALIZER_TORTURE)
64801 DUK_INTERNAL void duk_hthread_valstack_torture_realloc(duk_hthread *thr) {
64802 	duk_size_t alloc_size;
64803 	duk_tval *new_ptr;
64804 	duk_ptrdiff_t alloc_end_off;
64805 	duk_ptrdiff_t end_off;
64806 	duk_ptrdiff_t bottom_off;
64807 	duk_ptrdiff_t top_off;
64808 
64809 	if (thr->valstack == NULL) {
64810 		DUK_D(DUK_DPRINT("skip valstack torture realloc, valstack is NULL"));
64811 		return;
64812 	}
64813 
64814 	alloc_end_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_alloc_end - (duk_uint8_t *) thr->valstack);
64815 	end_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
64816 	bottom_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
64817 	top_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack);
64818 	alloc_size = (duk_size_t) alloc_end_off;
64819 	if (alloc_size == 0) {
64820 		DUK_D(DUK_DPRINT("skip valstack torture realloc, alloc_size is zero"));
64821 		return;
64822 	}
64823 
64824 	/* Use DUK_ALLOC_RAW() to avoid side effects. */
64825 	new_ptr = (duk_tval *) DUK_ALLOC_RAW(thr->heap, alloc_size);
64826 	if (new_ptr != NULL) {
64827 		duk_memcpy((void *) new_ptr, (const void *) thr->valstack, alloc_size);
64828 		duk_memset((void *) thr->valstack, 0x55, alloc_size);
64829 		DUK_FREE_CHECKED(thr, (void *) thr->valstack);
64830 		thr->valstack = new_ptr;
64831 		thr->valstack_alloc_end = (duk_tval *) ((duk_uint8_t *) new_ptr + alloc_end_off);
64832 		thr->valstack_end = (duk_tval *) ((duk_uint8_t *) new_ptr + end_off);
64833 		thr->valstack_bottom = (duk_tval *) ((duk_uint8_t *) new_ptr + bottom_off);
64834 		thr->valstack_top = (duk_tval *) ((duk_uint8_t *) new_ptr + top_off);
64835 	} else {
64836 		DUK_D(DUK_DPRINT("failed to realloc valstack for torture, ignore"));
64837 	}
64838 }
64839 #endif  /* DUK_USE_FINALIZER_TORTURE */
64840 #line 1 "duk_js_arith.c"
64841 /*
64842  *  Shared helpers for arithmetic operations
64843  */
64844 
64845 /* #include duk_internal.h -> already included */
64846 
64847 /* ECMAScript modulus ('%') does not match IEEE 754 "remainder" operation
64848  * (implemented by remainder() in C99) but does seem to match ANSI C fmod().
64849  * Compare E5 Section 11.5.3 and "man fmod".
64850  */
64851 DUK_INTERNAL double duk_js_arith_mod(double d1, double d2) {
64852 #if defined(DUK_USE_POW_WORKAROUNDS)
64853 	/* Specific fixes to common fmod() implementation issues:
64854 	 * - test-bug-mingw-math-issues.js
64855 	 */
64856 	if (DUK_ISINF(d2)) {
64857 		if (DUK_ISINF(d1)) {
64858 			return DUK_DOUBLE_NAN;
64859 		} else {
64860 			return d1;
64861 		}
64862 	} else if (duk_double_equals(d1, 0.0)) {
64863 		/* d1 +/-0 is returned as is (preserving sign) except when
64864 		 * d2 is zero or NaN.
64865 		 */
64866 		if (duk_double_equals(d2, 0.0) || DUK_ISNAN(d2)) {
64867 			return DUK_DOUBLE_NAN;
64868 		} else {
64869 			return d1;
64870 		}
64871 	}
64872 #else
64873 	/* Some ISO C assumptions. */
64874 	DUK_ASSERT(duk_double_equals(DUK_FMOD(1.0, DUK_DOUBLE_INFINITY), 1.0));
64875 	DUK_ASSERT(duk_double_equals(DUK_FMOD(-1.0, DUK_DOUBLE_INFINITY), -1.0));
64876 	DUK_ASSERT(duk_double_equals(DUK_FMOD(1.0, -DUK_DOUBLE_INFINITY), 1.0));
64877 	DUK_ASSERT(duk_double_equals(DUK_FMOD(-1.0, -DUK_DOUBLE_INFINITY), -1.0));
64878 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY)));
64879 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY)));
64880 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY)));
64881 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY)));
64882 	DUK_ASSERT(duk_double_equals(DUK_FMOD(0.0, 1.0), 0.0) && DUK_SIGNBIT(DUK_FMOD(0.0, 1.0)) == 0);
64883 	DUK_ASSERT(duk_double_equals(DUK_FMOD(-0.0, 1.0), 0.0) && DUK_SIGNBIT(DUK_FMOD(-0.0, 1.0)) != 0);
64884 	DUK_ASSERT(duk_double_equals(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY), 0.0) && DUK_SIGNBIT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY)) == 0);
64885 	DUK_ASSERT(duk_double_equals(DUK_FMOD(-0.0, DUK_DOUBLE_INFINITY), 0.0) && DUK_SIGNBIT(DUK_FMOD(-0.0, DUK_DOUBLE_INFINITY)) != 0);
64886 	DUK_ASSERT(duk_double_equals(DUK_FMOD(0.0, -DUK_DOUBLE_INFINITY), 0.0) && DUK_SIGNBIT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY)) == 0);
64887 	DUK_ASSERT(duk_double_equals(DUK_FMOD(-0.0, -DUK_DOUBLE_INFINITY), 0.0) && DUK_SIGNBIT(DUK_FMOD(-0.0, -DUK_DOUBLE_INFINITY)) != 0);
64888 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, 0.0)));
64889 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, 0.0)));
64890 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, -0.0)));
64891 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, -0.0)));
64892 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, DUK_DOUBLE_NAN)));
64893 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, DUK_DOUBLE_NAN)));
64894 #endif
64895 
64896 	return (duk_double_t) DUK_FMOD((double) d1, (double) d2);
64897 }
64898 
64899 /* Shared helper for Math.pow() and exponentiation operator. */
64900 DUK_INTERNAL double duk_js_arith_pow(double x, double y) {
64901 	/* The ANSI C pow() semantics differ from ECMAScript.
64902 	 *
64903 	 * E.g. when x==1 and y is +/- infinite, the ECMAScript required
64904 	 * result is NaN, while at least Linux pow() returns 1.
64905 	 */
64906 
64907 	duk_small_int_t cx, cy, sx;
64908 
64909 	DUK_UNREF(cx);
64910 	DUK_UNREF(sx);
64911 	cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
64912 
64913 	if (cy == DUK_FP_NAN) {
64914 		goto ret_nan;
64915 	}
64916 	if (duk_double_equals(DUK_FABS(x), 1.0) && cy == DUK_FP_INFINITE) {
64917 		goto ret_nan;
64918 	}
64919 
64920 #if defined(DUK_USE_POW_WORKAROUNDS)
64921 	/* Specific fixes to common pow() implementation issues:
64922 	 *   - test-bug-netbsd-math-pow.js: NetBSD 6.0 on x86 (at least)
64923 	 *   - test-bug-mingw-math-issues.js
64924 	 */
64925 	cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
64926 	if (cx == DUK_FP_ZERO && y < 0.0) {
64927 		sx = (duk_small_int_t) DUK_SIGNBIT(x);
64928 		if (sx == 0) {
64929 			/* Math.pow(+0,y) should be Infinity when y<0.  NetBSD pow()
64930 			 * returns -Infinity instead when y is <0 and finite.  The
64931 			 * if-clause also catches y == -Infinity (which works even
64932 			 * without the fix).
64933 			 */
64934 			return DUK_DOUBLE_INFINITY;
64935 		} else {
64936 			/* Math.pow(-0,y) where y<0 should be:
64937 			 *   - -Infinity if y<0 and an odd integer
64938 			 *   - Infinity if y<0 but not an odd integer
64939 			 * NetBSD pow() returns -Infinity for all finite y<0.  The
64940 			 * if-clause also catches y == -Infinity (which works even
64941 			 * without the fix).
64942 			 */
64943 
64944 			/* fmod() return value has same sign as input (negative) so
64945 			 * the result here will be in the range ]-2,0], -1 indicates
64946 			 * odd.  If x is -Infinity, NaN is returned and the odd check
64947 			 * always concludes "not odd" which results in desired outcome.
64948 			 */
64949 			double tmp = DUK_FMOD(y, 2);
64950 			if (tmp == -1.0) {
64951 				return -DUK_DOUBLE_INFINITY;
64952 			} else {
64953 				/* Not odd, or y == -Infinity */
64954 				return DUK_DOUBLE_INFINITY;
64955 			}
64956 		}
64957 	} else if (cx == DUK_FP_NAN) {
64958 		if (duk_double_equals(y, 0.0)) {
64959 			/* NaN ** +/- 0 should always be 1, but is NaN on
64960 			 * at least some Cygwin/MinGW versions.
64961 			 */
64962 			return 1.0;
64963 		}
64964 	}
64965 #else
64966 	/* Some ISO C assumptions. */
64967 	DUK_ASSERT(duk_double_equals(DUK_POW(DUK_DOUBLE_NAN, 0.0), 1.0));
64968 	DUK_ASSERT(DUK_ISINF(DUK_POW(0.0, -1.0)) && DUK_SIGNBIT(DUK_POW(0.0, -1.0)) == 0);
64969 	DUK_ASSERT(DUK_ISINF(DUK_POW(-0.0, -2.0)) && DUK_SIGNBIT(DUK_POW(-0.0, -2.0)) == 0);
64970 	DUK_ASSERT(DUK_ISINF(DUK_POW(-0.0, -3.0)) && DUK_SIGNBIT(DUK_POW(-0.0, -3.0)) != 0);
64971 #endif
64972 
64973 	return DUK_POW(x, y);
64974 
64975  ret_nan:
64976 	return DUK_DOUBLE_NAN;
64977 }
64978 #line 1 "duk_js_call.c"
64979 /*
64980  *  Call handling.
64981  *
64982  *  duk_handle_call_unprotected():
64983  *
64984  *    - Unprotected call to ECMAScript or Duktape/C function, from native
64985  *      code or bytecode executor.
64986  *
64987  *    - Also handles Ecma-to-Ecma calls which reuses a currently running
64988  *      executor instance to avoid native recursion.  Call setup is done
64989  *      normally, but just before calling the bytecode executor a special
64990  *      return code is used to indicate that a calling executor is reused.
64991  *
64992  *    - Also handles tailcalls, i.e. reuse of current duk_activation.
64993  *
64994  *    - Also handles setup for initial Duktape.Thread.resume().
64995  *
64996  *  duk_handle_safe_call():
64997  *
64998  *    - Protected C call within current activation.
64999  *
65000  *  setjmp() and local variables have a nasty interaction, see execution.rst;
65001  *  non-volatile locals modified after setjmp() call are not guaranteed to
65002  *  keep their value and can cause compiler or compiler version specific
65003  *  difficult to replicate issues.
65004  *
65005  *  See 'execution.rst'.
65006  */
65007 
65008 /* #include duk_internal.h -> already included */
65009 
65010 /* XXX: heap->error_not_allowed for success path too? */
65011 
65012 /*
65013  *  Limit check helpers.
65014  */
65015 
65016 /* Check native stack space if DUK_USE_NATIVE_STACK_CHECK() defined. */
65017 DUK_INTERNAL void duk_native_stack_check(duk_hthread *thr) {
65018 #if defined(DUK_USE_NATIVE_STACK_CHECK)
65019 	if (DUK_USE_NATIVE_STACK_CHECK() != 0) {
65020 		DUK_ERROR_RANGE(thr, DUK_STR_NATIVE_STACK_LIMIT);
65021 	}
65022 #else
65023 	DUK_UNREF(thr);
65024 #endif
65025 }
65026 
65027 /* Allow headroom for calls during error augmentation (see GH-191).
65028  * We allow space for 10 additional recursions, with one extra
65029  * for, e.g. a print() call at the deepest level, and an extra
65030  * +1 for protected call wrapping.
65031  */
65032 #define DUK__AUGMENT_CALL_RELAX_COUNT  (10 + 2)
65033 
65034 /* Stack space required by call handling entry. */
65035 #define DUK__CALL_HANDLING_REQUIRE_STACK  8
65036 
65037 DUK_LOCAL DUK_NOINLINE void duk__call_c_recursion_limit_check_slowpath(duk_hthread *thr) {
65038 	/* When augmenting an error, the effective limit is a bit higher.
65039 	 * Check for it only if the fast path check fails.
65040 	 */
65041 #if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
65042 	if (thr->heap->augmenting_error) {
65043 		if (thr->heap->call_recursion_depth < thr->heap->call_recursion_limit + DUK__AUGMENT_CALL_RELAX_COUNT) {
65044 			DUK_D(DUK_DPRINT("C recursion limit reached but augmenting error and within relaxed limit"));
65045 			return;
65046 		}
65047 	}
65048 #endif
65049 
65050 	DUK_D(DUK_DPRINT("call prevented because C recursion limit reached"));
65051 	DUK_ERROR_RANGE(thr, DUK_STR_NATIVE_STACK_LIMIT);
65052 	DUK_WO_NORETURN(return;);
65053 }
65054 
65055 DUK_LOCAL DUK_ALWAYS_INLINE void duk__call_c_recursion_limit_check(duk_hthread *thr) {
65056 	DUK_ASSERT(thr->heap->call_recursion_depth >= 0);
65057 	DUK_ASSERT(thr->heap->call_recursion_depth <= thr->heap->call_recursion_limit);
65058 
65059 	duk_native_stack_check(thr);
65060 
65061 	/* This check is forcibly inlined because it's very cheap and almost
65062 	 * always passes.  The slow path is forcibly noinline.
65063 	 */
65064 	if (DUK_LIKELY(thr->heap->call_recursion_depth < thr->heap->call_recursion_limit)) {
65065 		return;
65066 	}
65067 
65068 	duk__call_c_recursion_limit_check_slowpath(thr);
65069 }
65070 
65071 DUK_LOCAL DUK_NOINLINE void duk__call_callstack_limit_check_slowpath(duk_hthread *thr) {
65072 	/* When augmenting an error, the effective limit is a bit higher.
65073 	 * Check for it only if the fast path check fails.
65074 	 */
65075 #if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
65076 	if (thr->heap->augmenting_error) {
65077 		if (thr->callstack_top < DUK_USE_CALLSTACK_LIMIT + DUK__AUGMENT_CALL_RELAX_COUNT) {
65078 			DUK_D(DUK_DPRINT("call stack limit reached but augmenting error and within relaxed limit"));
65079 			return;
65080 		}
65081 	}
65082 #endif
65083 
65084 	/* XXX: error message is a bit misleading: we reached a recursion
65085 	 * limit which is also essentially the same as a C callstack limit
65086 	 * (except perhaps with some relaxed threading assumptions).
65087 	 */
65088 	DUK_D(DUK_DPRINT("call prevented because call stack limit reached"));
65089 	DUK_ERROR_RANGE(thr, DUK_STR_CALLSTACK_LIMIT);
65090 	DUK_WO_NORETURN(return;);
65091 }
65092 
65093 DUK_LOCAL DUK_ALWAYS_INLINE void duk__call_callstack_limit_check(duk_hthread *thr) {
65094 	/* This check is forcibly inlined because it's very cheap and almost
65095 	 * always passes.  The slow path is forcibly noinline.
65096 	 */
65097 	if (DUK_LIKELY(thr->callstack_top < DUK_USE_CALLSTACK_LIMIT)) {
65098 		return;
65099 	}
65100 
65101 	duk__call_callstack_limit_check_slowpath(thr);
65102 }
65103 
65104 /*
65105  *  Interrupt counter fixup (for development only).
65106  */
65107 
65108 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
65109 DUK_LOCAL void duk__interrupt_fixup(duk_hthread *thr, duk_hthread *entry_curr_thread) {
65110 	/* Currently the bytecode executor and executor interrupt
65111 	 * instruction counts are off because we don't execute the
65112 	 * interrupt handler when we're about to exit from the initial
65113 	 * user call into Duktape.
65114 	 *
65115 	 * If we were to execute the interrupt handler here, the counts
65116 	 * would match.  You can enable this block manually to check
65117 	 * that this is the case.
65118 	 */
65119 
65120 	DUK_ASSERT(thr != NULL);
65121 	DUK_ASSERT(thr->heap != NULL);
65122 
65123 #if defined(DUK_USE_INTERRUPT_DEBUG_FIXUP)
65124 	if (entry_curr_thread == NULL) {
65125 		thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
65126 		thr->heap->inst_count_interrupt += thr->interrupt_init;
65127 		DUK_DD(DUK_DDPRINT("debug test: updated interrupt count on exit to "
65128 		                   "user code, instruction counts: executor=%ld, interrupt=%ld",
65129 		                   (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
65130 		DUK_ASSERT(thr->heap->inst_count_exec == thr->heap->inst_count_interrupt);
65131 	}
65132 #else
65133 	DUK_UNREF(thr);
65134 	DUK_UNREF(entry_curr_thread);
65135 #endif
65136 }
65137 #endif
65138 
65139 /*
65140  *  Arguments object creation.
65141  *
65142  *  Creating arguments objects involves many small details, see E5 Section
65143  *  10.6 for the specific requirements.  Much of the arguments object exotic
65144  *  behavior is implemented in duk_hobject_props.c, and is enabled by the
65145  *  object flag DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS.
65146  */
65147 
65148 DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
65149                                             duk_hobject *func,
65150                                             duk_hobject *varenv,
65151                                             duk_idx_t idx_args) {
65152 	duk_hobject *arg;          /* 'arguments' */
65153 	duk_hobject *formals;      /* formals for 'func' (may be NULL if func is a C function) */
65154 	duk_idx_t i_arg;
65155 	duk_idx_t i_map;
65156 	duk_idx_t i_mappednames;
65157 	duk_idx_t i_formals;
65158 	duk_idx_t i_argbase;
65159 	duk_idx_t n_formals;
65160 	duk_idx_t idx;
65161 	duk_idx_t num_stack_args;
65162 	duk_bool_t need_map;
65163 
65164 	DUK_ASSERT(thr != NULL);
65165 	DUK_ASSERT(func != NULL);
65166 	DUK_ASSERT(DUK_HOBJECT_IS_NONBOUND_FUNCTION(func));
65167 	DUK_ASSERT(varenv != NULL);
65168 
65169 	/* [ ... func this arg1(@idx_args) ... argN envobj ]
65170 	 * [ arg1(@idx_args) ... argN envobj ] (for tailcalls)
65171 	 */
65172 
65173 	need_map = 0;
65174 
65175 	i_argbase = idx_args;
65176 	num_stack_args = duk_get_top(thr) - i_argbase - 1;
65177 	DUK_ASSERT(i_argbase >= 0);
65178 	DUK_ASSERT(num_stack_args >= 0);
65179 
65180 	formals = (duk_hobject *) duk_hobject_get_formals(thr, (duk_hobject *) func);
65181 	if (formals) {
65182 		n_formals = (duk_idx_t) ((duk_harray *) formals)->length;
65183 		duk_push_hobject(thr, formals);
65184 	} else {
65185 		/* This shouldn't happen without tampering of internal
65186 		 * properties: if a function accesses 'arguments', _Formals
65187 		 * is kept.  Check for the case anyway in case internal
65188 		 * properties have been modified manually.
65189 		 */
65190 		DUK_D(DUK_DPRINT("_Formals is undefined when creating arguments, use n_formals == 0"));
65191 		n_formals = 0;
65192 		duk_push_undefined(thr);
65193 	}
65194 	i_formals = duk_require_top_index(thr);
65195 
65196 	DUK_ASSERT(n_formals >= 0);
65197 	DUK_ASSERT(formals != NULL || n_formals == 0);
65198 
65199 	DUK_DDD(DUK_DDDPRINT("func=%!O, formals=%!O, n_formals=%ld",
65200 	                     (duk_heaphdr *) func, (duk_heaphdr *) formals,
65201 	                     (long) n_formals));
65202 
65203 	/* [ ... formals ] */
65204 
65205 	/*
65206 	 *  Create required objects:
65207 	 *    - 'arguments' object: array-like, but not an array
65208 	 *    - 'map' object: internal object, tied to 'arguments' (bare)
65209 	 *    - 'mappedNames' object: temporary value used during construction (bare)
65210 	 */
65211 
65212 	arg = duk_push_object_helper(thr,
65213 	                             DUK_HOBJECT_FLAG_EXTENSIBLE |
65214 	                             DUK_HOBJECT_FLAG_FASTREFS |
65215 	                             DUK_HOBJECT_FLAG_ARRAY_PART |
65216 	                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARGUMENTS),
65217 	                             DUK_BIDX_OBJECT_PROTOTYPE);
65218 	DUK_ASSERT(arg != NULL);
65219 	(void) duk_push_object_helper(thr,
65220 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
65221 	                              DUK_HOBJECT_FLAG_FASTREFS |
65222 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
65223 	                              -1);  /* no prototype */
65224 	(void) duk_push_object_helper(thr,
65225 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
65226 	                              DUK_HOBJECT_FLAG_FASTREFS |
65227 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
65228 	                              -1);  /* no prototype */
65229 	i_arg = duk_get_top(thr) - 3;
65230 	i_map = i_arg + 1;
65231 	i_mappednames = i_arg + 2;
65232 	DUK_ASSERT(!duk_is_bare_object(thr, -3));  /* arguments */
65233 	DUK_ASSERT(duk_is_bare_object(thr, -2));  /* map */
65234 	DUK_ASSERT(duk_is_bare_object(thr, -1));  /* mappedNames */
65235 
65236 	/* [ ... formals arguments map mappedNames ] */
65237 
65238 	DUK_DDD(DUK_DDDPRINT("created arguments related objects: "
65239 	                     "arguments at index %ld -> %!O "
65240 	                     "map at index %ld -> %!O "
65241 	                     "mappednames at index %ld -> %!O",
65242 	                     (long) i_arg, (duk_heaphdr *) duk_get_hobject(thr, i_arg),
65243 	                     (long) i_map, (duk_heaphdr *) duk_get_hobject(thr, i_map),
65244 	                     (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(thr, i_mappednames)));
65245 
65246 	/*
65247 	 *  Init arguments properties, map, etc.
65248 	 */
65249 
65250 	duk_push_int(thr, num_stack_args);
65251 	duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_WC);
65252 
65253 	/*
65254 	 *  Init argument related properties.
65255 	 */
65256 
65257 	/* step 11 */
65258 	idx = num_stack_args - 1;
65259 	while (idx >= 0) {
65260 		DUK_DDD(DUK_DDDPRINT("arg idx %ld, argbase=%ld, argidx=%ld",
65261 		                     (long) idx, (long) i_argbase, (long) (i_argbase + idx)));
65262 
65263 		DUK_DDD(DUK_DDDPRINT("define arguments[%ld]=arg", (long) idx));
65264 		duk_dup(thr, i_argbase + idx);
65265 		duk_xdef_prop_index_wec(thr, i_arg, (duk_uarridx_t) idx);
65266 		DUK_DDD(DUK_DDDPRINT("defined arguments[%ld]=arg", (long) idx));
65267 
65268 		/* step 11.c is relevant only if non-strict (checked in 11.c.ii) */
65269 		if (!DUK_HOBJECT_HAS_STRICT(func) && idx < n_formals) {
65270 			DUK_ASSERT(formals != NULL);
65271 
65272 			DUK_DDD(DUK_DDDPRINT("strict function, index within formals (%ld < %ld)",
65273 			                     (long) idx, (long) n_formals));
65274 
65275 			duk_get_prop_index(thr, i_formals, (duk_uarridx_t) idx);
65276 			DUK_ASSERT(duk_is_string(thr, -1));
65277 
65278 			duk_dup_top(thr);  /* [ ... name name ] */
65279 
65280 			if (!duk_has_prop(thr, i_mappednames)) {
65281 				/* steps 11.c.ii.1 - 11.c.ii.4, but our internal book-keeping
65282 				 * differs from the reference model
65283 				 */
65284 
65285 				/* [ ... name ] */
65286 
65287 				need_map = 1;
65288 
65289 				DUK_DDD(DUK_DDDPRINT("set mappednames[%s]=%ld",
65290 				                     (const char *) duk_get_string(thr, -1),
65291 				                     (long) idx));
65292 				duk_dup_top(thr);                      /* name */
65293 				(void) duk_push_uint_to_hstring(thr, (duk_uint_t) idx);  /* index */
65294 				duk_xdef_prop_wec(thr, i_mappednames);  /* out of spec, must be configurable */
65295 
65296 				DUK_DDD(DUK_DDDPRINT("set map[%ld]=%s",
65297 				                     (long) idx,
65298 				                     duk_get_string(thr, -1)));
65299 				duk_dup_top(thr);         /* name */
65300 				duk_xdef_prop_index_wec(thr, i_map, (duk_uarridx_t) idx);  /* out of spec, must be configurable */
65301 			} else {
65302 				/* duk_has_prop() popped the second 'name' */
65303 			}
65304 
65305 			/* [ ... name ] */
65306 			duk_pop(thr);  /* pop 'name' */
65307 		}
65308 
65309 		idx--;
65310 	}
65311 
65312 	DUK_DDD(DUK_DDDPRINT("actual arguments processed"));
65313 
65314 	/* step 12 */
65315 	if (need_map) {
65316 		DUK_DDD(DUK_DDDPRINT("adding 'map' and 'varenv' to arguments object"));
65317 
65318 		/* should never happen for a strict callee */
65319 		DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(func));
65320 
65321 		duk_dup(thr, i_map);
65322 		duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_INT_MAP, DUK_PROPDESC_FLAGS_NONE);  /* out of spec, don't care */
65323 
65324 		/* The variable environment for magic variable bindings needs to be
65325 		 * given by the caller and recorded in the arguments object.
65326 		 *
65327 		 * See E5 Section 10.6, the creation of setters/getters.
65328 		 *
65329 		 * The variable environment also provides access to the callee, so
65330 		 * an explicit (internal) callee property is not needed.
65331 		 */
65332 
65333 		duk_push_hobject(thr, varenv);
65334 		duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_INT_VARENV, DUK_PROPDESC_FLAGS_NONE);  /* out of spec, don't care */
65335 	}
65336 
65337 	/* steps 13-14 */
65338 	if (DUK_HOBJECT_HAS_STRICT(func)) {
65339 		/* Callee/caller are throwers and are not deletable etc.  They
65340 		 * could be implemented as virtual properties, but currently
65341 		 * there is no support for virtual properties which are accessors
65342 		 * (only plain virtual properties).  This would not be difficult
65343 		 * to change in duk_hobject_props, but we can make the throwers
65344 		 * normal, concrete properties just as easily.
65345 		 *
65346 		 * Note that the specification requires that the *same* thrower
65347 		 * built-in object is used here!  See E5 Section 10.6 main
65348 		 * algoritm, step 14, and Section 13.2.3 which describes the
65349 		 * thrower.  See test case test-arguments-throwers.js.
65350 		 */
65351 
65352 		DUK_DDD(DUK_DDDPRINT("strict function, setting caller/callee to throwers"));
65353 
65354 		/* In ES2017 .caller is no longer set at all. */
65355 		duk_xdef_prop_stridx_thrower(thr, i_arg, DUK_STRIDX_CALLEE);
65356 	} else {
65357 		DUK_DDD(DUK_DDDPRINT("non-strict function, setting callee to actual value"));
65358 		duk_push_hobject(thr, func);
65359 		duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_CALLEE, DUK_PROPDESC_FLAGS_WC);
65360 	}
65361 
65362 	/* set exotic behavior only after we're done */
65363 	if (need_map) {
65364 		/* Exotic behaviors are only enabled for arguments objects
65365 		 * which have a parameter map (see E5 Section 10.6 main
65366 		 * algorithm, step 12).
65367 		 *
65368 		 * In particular, a non-strict arguments object with no
65369 		 * mapped formals does *NOT* get exotic behavior, even
65370 		 * for e.g. "caller" property.  This seems counterintuitive
65371 		 * but seems to be the case.
65372 		 */
65373 
65374 		/* cannot be strict (never mapped variables) */
65375 		DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(func));
65376 
65377 		DUK_DDD(DUK_DDDPRINT("enabling exotic behavior for arguments object"));
65378 		DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(arg);
65379 	} else {
65380 		DUK_DDD(DUK_DDDPRINT("not enabling exotic behavior for arguments object"));
65381 	}
65382 
65383 	DUK_DDD(DUK_DDDPRINT("final arguments related objects: "
65384 	                     "arguments at index %ld -> %!O "
65385 	                     "map at index %ld -> %!O "
65386 	                     "mappednames at index %ld -> %!O",
65387 	                     (long) i_arg, (duk_heaphdr *) duk_get_hobject(thr, i_arg),
65388 	                     (long) i_map, (duk_heaphdr *) duk_get_hobject(thr, i_map),
65389 	                     (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(thr, i_mappednames)));
65390 
65391 	/* [ args(n) envobj formals arguments map mappednames ] */
65392 
65393 	duk_pop_2(thr);
65394 	duk_remove_m2(thr);
65395 
65396 	/* [ args(n) envobj arguments ] */
65397 }
65398 
65399 /* Helper for creating the arguments object and adding it to the env record
65400  * on top of the value stack.
65401  */
65402 DUK_LOCAL void duk__handle_createargs_for_call(duk_hthread *thr,
65403                                                duk_hobject *func,
65404                                                duk_hobject *env,
65405                                                duk_idx_t idx_args) {
65406 	DUK_DDD(DUK_DDDPRINT("creating arguments object for function call"));
65407 
65408 	DUK_ASSERT(thr != NULL);
65409 	DUK_ASSERT(func != NULL);
65410 	DUK_ASSERT(env != NULL);
65411 	DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
65412 
65413 	/* [ ... arg1 ... argN envobj ] */
65414 
65415 	duk__create_arguments_object(thr,
65416 	                             func,
65417 	                             env,
65418 	                             idx_args);
65419 
65420 	/* [ ... arg1 ... argN envobj argobj ] */
65421 
65422 	duk_xdef_prop_stridx_short(thr,
65423 	                           -2,
65424 	                           DUK_STRIDX_LC_ARGUMENTS,
65425 	                           DUK_HOBJECT_HAS_STRICT(func) ? DUK_PROPDESC_FLAGS_E :   /* strict: non-deletable, non-writable */
65426 	                                                          DUK_PROPDESC_FLAGS_WE);  /* non-strict: non-deletable, writable */
65427 	/* [ ... arg1 ... argN envobj ] */
65428 }
65429 
65430 /*
65431  *  Helpers for constructor call handling.
65432  *
65433  *  There are two [[Construct]] operations in the specification:
65434  *
65435  *    - E5 Section 13.2.2: for Function objects
65436  *    - E5 Section 15.3.4.5.2: for "bound" Function objects
65437  *
65438  *  The chain of bound functions is resolved in Section 15.3.4.5.2,
65439  *  with arguments "piling up" until the [[Construct]] internal
65440  *  method is called on the final, actual Function object.  Note
65441  *  that the "prototype" property is looked up *only* from the
65442  *  final object, *before* calling the constructor.
65443  *
65444  *  Since Duktape 2.2 bound functions are represented with the
65445  *  duk_hboundfunc internal type, and bound function chains are
65446  *  collapsed when a bound function is created.  As a result, the
65447  *  direct target of a duk_hboundfunc is always non-bound and the
65448  *  this/argument lists have been resolved.
65449  *
65450  *  When constructing new Array instances, an unnecessary object is
65451  *  created and discarded now: the standard [[Construct]] creates an
65452  *  object, and calls the Array constructor.  The Array constructor
65453  *  returns an Array instance, which is used as the result value for
65454  *  the "new" operation; the object created before the Array constructor
65455  *  call is discarded.
65456  *
65457  *  This would be easy to fix, e.g. by knowing that the Array constructor
65458  *  will always create a replacement object and skip creating the fallback
65459  *  object in that case.
65460  */
65461 
65462 /* Update default instance prototype for constructor call. */
65463 DUK_LOCAL void duk__update_default_instance_proto(duk_hthread *thr, duk_idx_t idx_func) {
65464 	duk_hobject *proto;
65465 	duk_hobject *fallback;
65466 
65467 	DUK_ASSERT(duk_is_constructable(thr, idx_func));
65468 
65469 	duk_get_prop_stridx_short(thr, idx_func, DUK_STRIDX_PROTOTYPE);
65470 	proto = duk_get_hobject(thr, -1);
65471 	if (proto == NULL) {
65472 		DUK_DDD(DUK_DDDPRINT("constructor has no 'prototype' property, or value not an object "
65473 		                     "-> leave standard Object prototype as fallback prototype"));
65474 	} else {
65475 		DUK_DDD(DUK_DDDPRINT("constructor has 'prototype' property with object value "
65476 		                     "-> set fallback prototype to that value: %!iO", (duk_heaphdr *) proto));
65477 		/* Original fallback (default instance) is untouched when
65478 		 * resolving bound functions etc.
65479 		 */
65480 		fallback = duk_known_hobject(thr, idx_func + 1);
65481 		DUK_ASSERT(fallback != NULL);
65482 		DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, fallback, proto);
65483 	}
65484 	duk_pop(thr);
65485 }
65486 
65487 /* Postprocess: return value special handling, error augmentation. */
65488 DUK_INTERNAL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uint_t proxy_invariant) {
65489 	/* Use either fallback (default instance) or retval depending
65490 	 * on retval type.  Needs to be called before unwind because
65491 	 * the default instance is read from the current (immutable)
65492 	 * 'this' binding.
65493 	 *
65494 	 * For Proxy 'construct' calls the return value must be an
65495 	 * Object (we accept object-like values like buffers and
65496 	 * lightfuncs too).  If not, TypeError.
65497 	 */
65498 	if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |
65499 	                                 DUK_TYPE_MASK_BUFFER |
65500 	                                 DUK_TYPE_MASK_LIGHTFUNC)) {
65501 		DUK_DDD(DUK_DDDPRINT("replacement value"));
65502 	} else {
65503 		if (DUK_UNLIKELY(proxy_invariant != 0U)) {
65504 			/* Proxy 'construct' return value invariant violated. */
65505 			DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr);
65506 			DUK_WO_NORETURN(return;);
65507 		}
65508 		/* XXX: direct value stack access */
65509 		duk_pop(thr);
65510 		duk_push_this(thr);
65511 	}
65512 
65513 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
65514 	/* Augment created errors upon creation, not when they are thrown or
65515 	 * rethrown.  __FILE__ and __LINE__ are not desirable here; the call
65516 	 * stack reflects the caller which is correct.  Skip topmost, unwound
65517 	 * activation when creating a traceback.  If thr->ptr_curr_pc was !=
65518 	 * NULL we'd need to sync the current PC so that the traceback comes
65519 	 * out right; however it is always synced here so just assert for it.
65520 	 */
65521 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
65522 	duk_err_augment_error_create(thr, thr, NULL, 0, DUK_AUGMENT_FLAG_NOBLAME_FILELINE |
65523 	                                                DUK_AUGMENT_FLAG_SKIP_ONE);
65524 #endif
65525 }
65526 
65527 /*
65528  *  Helper for handling a bound function when a call is being made.
65529  *
65530  *  Assumes that bound function chains have been "collapsed" so that either
65531  *  the target is non-bound or there is one bound function that points to a
65532  *  nonbound target.
65533  *
65534  *  Prepends the bound arguments to the value stack (at idx_func + 2).
65535  *  The 'this' binding is also updated if necessary (at idx_func + 1).
65536  *  Note that for constructor calls the 'this' binding is never updated by
65537  *  [[BoundThis]].
65538  */
65539 
65540 DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr,
65541                                                 duk_idx_t idx_func,
65542                                                 duk_bool_t is_constructor_call) {
65543 	duk_tval *tv_func;
65544 	duk_hobject *func;
65545 	duk_idx_t len;
65546 
65547 	DUK_ASSERT(thr != NULL);
65548 
65549 	/* On entry, item at idx_func is a bound, non-lightweight function,
65550 	 * but we don't rely on that below.
65551 	 */
65552 
65553 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
65554 
65555 	tv_func = duk_require_tval(thr, idx_func);
65556 	DUK_ASSERT(tv_func != NULL);
65557 
65558 	if (DUK_TVAL_IS_OBJECT(tv_func)) {
65559 		func = DUK_TVAL_GET_OBJECT(tv_func);
65560 
65561 		/* XXX: separate helper function, out of fast path? */
65562 		if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
65563 			duk_hboundfunc *h_bound;
65564 			duk_tval *tv_args;
65565 			duk_tval *tv_gap;
65566 
65567 			h_bound = (duk_hboundfunc *) (void *) func;
65568 			tv_args = h_bound->args;
65569 			len = h_bound->nargs;
65570 			DUK_ASSERT(len == 0 || tv_args != NULL);
65571 
65572 			DUK_DDD(DUK_DDDPRINT("bound function encountered, ptr=%p: %!T",
65573 			                     (void *) DUK_TVAL_GET_OBJECT(tv_func), tv_func));
65574 
65575 			/* [ ... func this arg1 ... argN ] */
65576 
65577 			if (is_constructor_call) {
65578 				/* See: tests/ecmascript/test-spec-bound-constructor.js */
65579 				DUK_DDD(DUK_DDDPRINT("constructor call: don't update this binding"));
65580 			} else {
65581 				/* XXX: duk_replace_tval */
65582 				duk_push_tval(thr, &h_bound->this_binding);
65583 				duk_replace(thr, idx_func + 1);  /* idx_this = idx_func + 1 */
65584 			}
65585 
65586 			/* [ ... func this arg1 ... argN ] */
65587 
65588 			duk_require_stack(thr, len);
65589 
65590 			tv_gap = duk_reserve_gap(thr, idx_func + 2, len);
65591 			duk_copy_tvals_incref(thr, tv_gap, tv_args, (duk_size_t) len);
65592 
65593 			/* [ ... func this <bound args> arg1 ... argN ] */
65594 
65595 			duk_push_tval(thr, &h_bound->target);
65596 			duk_replace(thr, idx_func);  /* replace in stack */
65597 
65598 			DUK_DDD(DUK_DDDPRINT("bound function handled, idx_func=%ld, curr func=%!T",
65599 			                     (long) idx_func, duk_get_tval(thr, idx_func)));
65600 		}
65601 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
65602 		/* Lightweight function: never bound, so terminate. */
65603 		;
65604 	} else {
65605 		/* Shouldn't happen, so ugly error is enough. */
65606 		DUK_ERROR_INTERNAL(thr);
65607 		DUK_WO_NORETURN(return;);
65608 	}
65609 
65610 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
65611 
65612 	DUK_DDD(DUK_DDDPRINT("final non-bound function is: %!T", duk_get_tval(thr, idx_func)));
65613 
65614 #if defined(DUK_USE_ASSERTIONS)
65615 	tv_func = duk_require_tval(thr, idx_func);
65616 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func) || DUK_TVAL_IS_OBJECT(tv_func));
65617 	if (DUK_TVAL_IS_OBJECT(tv_func)) {
65618 		func = DUK_TVAL_GET_OBJECT(tv_func);
65619 		DUK_ASSERT(func != NULL);
65620 		DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
65621 		DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func) ||
65622 		           DUK_HOBJECT_HAS_NATFUNC(func) ||
65623 		           DUK_HOBJECT_IS_PROXY(func));
65624 	}
65625 #endif
65626 }
65627 
65628 /*
65629  *  Helper for inline handling of .call(), .apply(), and .construct().
65630  */
65631 
65632 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) {
65633 #if defined(DUK_USE_ASSERTIONS)
65634 	duk_c_function natfunc;
65635 #endif
65636 	duk_tval *tv_args;
65637 
65638 	DUK_ASSERT(func != NULL);
65639 	DUK_ASSERT((*call_flags & DUK_CALL_FLAG_CONSTRUCT) == 0);  /* Caller. */
65640 
65641 #if defined(DUK_USE_ASSERTIONS)
65642 	natfunc = ((duk_hnatfunc *) func)->func;
65643 	DUK_ASSERT(natfunc != NULL);
65644 #endif
65645 
65646 	/* On every round of function resolution at least target function and
65647 	 * 'this' binding are set.  We can assume that here, and must guarantee
65648 	 * it on exit.  Value stack reserve is extended for bound function and
65649 	 * .apply() unpacking so we don't need to extend it here when we need a
65650 	 * few slots.
65651 	 */
65652 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
65653 
65654 	/* Handle native 'eval' specially.  A direct eval check is only made
65655 	 * for the first resolution attempt; e.g. a bound eval call is -not-
65656 	 * a direct eval call.
65657 	 */
65658 	if (DUK_UNLIKELY(((duk_hnatfunc *) func)->magic == 15)) {
65659 		/* For now no special handling except for direct eval
65660 		 * detection.
65661 		 */
65662 		DUK_ASSERT(((duk_hnatfunc *) func)->func == duk_bi_global_object_eval);
65663 		if (first && (*call_flags & DUK_CALL_FLAG_CALLED_AS_EVAL)) {
65664 			*call_flags = (*call_flags & ~DUK_CALL_FLAG_CALLED_AS_EVAL) | DUK_CALL_FLAG_DIRECT_EVAL;
65665 		}
65666 		DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
65667 		return 1;  /* stop resolving */
65668 	}
65669 
65670 	/* Handle special functions based on the DUK_HOBJECT_FLAG_SPECIAL_CALL
65671 	 * flag; their magic value is used for switch-case.
65672 	 *
65673 	 * NOTE: duk_unpack_array_like() reserves value stack space
65674 	 * for the result values (unlike most other value stack calls).
65675 	 */
65676 	switch (((duk_hnatfunc *) func)->magic) {
65677 	case 0: {  /* 0=Function.prototype.call() */
65678 		/* Value stack:
65679 		 * idx_func + 0: Function.prototype.call()  [removed]
65680 		 * idx_func + 1: this binding for .call (target function)
65681 		 * idx_func + 2: 1st argument to .call, desired 'this' binding
65682 		 * idx_func + 3: 2nd argument to .call, desired 1st argument for ultimate target
65683 		 * ...
65684 		 *
65685 		 * Remove idx_func + 0 to get:
65686 		 * idx_func + 0: target function
65687 		 * idx_func + 1: this binding
65688 		 * idx_func + 2: call arguments
65689 		 * ...
65690 		 */
65691 		DUK_ASSERT(natfunc == duk_bi_function_prototype_call);
65692 		duk_remove_unsafe(thr, idx_func);
65693 		tv_args = thr->valstack_bottom + idx_func + 2;
65694 		if (thr->valstack_top < tv_args) {
65695 			DUK_ASSERT(tv_args <= thr->valstack_end);
65696 			thr->valstack_top = tv_args;  /* at least target function and 'this' binding present */
65697 		}
65698 		break;
65699 	}
65700 	case 1: {  /* 1=Function.prototype.apply() */
65701 		/* Value stack:
65702 		 * idx_func + 0: Function.prototype.apply()  [removed]
65703 		 * idx_func + 1: this binding for .apply (target function)
65704 		 * idx_func + 2: 1st argument to .apply, desired 'this' binding
65705 		 * idx_func + 3: 2nd argument to .apply, argArray
65706 		 * [anything after this MUST be ignored]
65707 		 *
65708 		 * Remove idx_func + 0 and unpack the argArray to get:
65709 		 * idx_func + 0: target function
65710 		 * idx_func + 1: this binding
65711 		 * idx_func + 2: call arguments
65712 		 * ...
65713 		 */
65714 		DUK_ASSERT(natfunc == duk_bi_function_prototype_apply);
65715 		duk_remove_unsafe(thr, idx_func);
65716 		goto apply_shared;
65717 	}
65718 #if defined(DUK_USE_REFLECT_BUILTIN)
65719 	case 2: {  /* 2=Reflect.apply() */
65720 		/* Value stack:
65721 		 * idx_func + 0: Reflect.apply()  [removed]
65722 		 * idx_func + 1: this binding for .apply (ignored, usually Reflect)  [removed]
65723 		 * idx_func + 2: 1st argument to .apply, target function
65724 		 * idx_func + 3: 2nd argument to .apply, desired 'this' binding
65725 		 * idx_func + 4: 3rd argument to .apply, argArray
65726 		 * [anything after this MUST be ignored]
65727 		 *
65728 		 * Remove idx_func + 0 and idx_func + 1, and unpack the argArray to get:
65729 		 * idx_func + 0: target function
65730 		 * idx_func + 1: this binding
65731 		 * idx_func + 2: call arguments
65732 		 * ...
65733 		 */
65734 		DUK_ASSERT(natfunc == duk_bi_reflect_apply);
65735 		duk_remove_n_unsafe(thr, idx_func, 2);
65736 		goto apply_shared;
65737 	}
65738 	case 3: {  /* 3=Reflect.construct() */
65739 		/* Value stack:
65740 		 * idx_func + 0: Reflect.construct()  [removed]
65741 		 * idx_func + 1: this binding for .construct (ignored, usually Reflect)  [removed]
65742 		 * idx_func + 2: 1st argument to .construct, target function
65743 		 * idx_func + 3: 2nd argument to .construct, argArray
65744 		 * idx_func + 4: 3rd argument to .construct, newTarget
65745 		 * [anything after this MUST be ignored]
65746 		 *
65747 		 * Remove idx_func + 0 and idx_func + 1, unpack the argArray,
65748 		 * and insert default instance (prototype not yet updated), to get:
65749 		 * idx_func + 0: target function
65750 		 * idx_func + 1: this binding (default instance)
65751 		 * idx_func + 2: constructor call arguments
65752 		 * ...
65753 		 *
65754 		 * Call flags must be updated to reflect the fact that we're
65755 		 * now dealing with a constructor call, and e.g. the 'this'
65756 		 * binding cannot be overwritten if the target is bound.
65757 		 *
65758 		 * newTarget is checked but not yet passed onwards.
65759 		 */
65760 
65761 		duk_idx_t top;
65762 
65763 		DUK_ASSERT(natfunc == duk_bi_reflect_construct);
65764 		*call_flags |= DUK_CALL_FLAG_CONSTRUCT;
65765 		duk_remove_n_unsafe(thr, idx_func, 2);
65766 		top = duk_get_top(thr);
65767 		if (!duk_is_constructable(thr, idx_func)) {
65768 			/* Target constructability must be checked before
65769 			 * unpacking argArray (which may cause side effects).
65770 			 * Just return; caller will throw the error.
65771 			 */
65772 			duk_set_top_unsafe(thr, idx_func + 2);  /* satisfy asserts */
65773 			break;
65774 		}
65775 		duk_push_object(thr);
65776 		duk_insert(thr, idx_func + 1);  /* default instance */
65777 
65778 		/* [ ... func default_instance argArray newTarget? ] */
65779 
65780 		top = duk_get_top(thr);
65781 		if (top < idx_func + 3) {
65782 			/* argArray is a mandatory argument for Reflect.construct(). */
65783 			DUK_ERROR_TYPE_INVALID_ARGS(thr);
65784 			DUK_WO_NORETURN(return 0;);
65785 		}
65786 		if (top > idx_func + 3) {
65787 			if (!duk_strict_equals(thr, idx_func, idx_func + 3)) {
65788 				/* XXX: [[Construct]] newTarget currently unsupported */
65789 				DUK_ERROR_UNSUPPORTED(thr);
65790 				DUK_WO_NORETURN(return 0;);
65791 			}
65792 			duk_set_top_unsafe(thr, idx_func + 3);  /* remove any args beyond argArray */
65793 		}
65794 		DUK_ASSERT(duk_get_top(thr) == idx_func + 3);
65795 		DUK_ASSERT(duk_is_valid_index(thr, idx_func + 2));
65796 		(void) duk_unpack_array_like(thr, idx_func + 2);  /* XXX: should also remove target to be symmetric with duk_pack()? */
65797 		duk_remove(thr, idx_func + 2);
65798 		DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
65799 		break;
65800 	}
65801 #endif  /* DUK_USE_REFLECT_BUILTIN */
65802 	default: {
65803 		DUK_ASSERT(0);
65804 		DUK_UNREACHABLE();
65805 	}
65806 	}
65807 
65808 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
65809 	return 0;  /* keep resolving */
65810 
65811  apply_shared:
65812 	tv_args = thr->valstack_bottom + idx_func + 2;
65813 	if (thr->valstack_top <= tv_args) {
65814 		DUK_ASSERT(tv_args <= thr->valstack_end);
65815 		thr->valstack_top = tv_args;  /* at least target func and 'this' binding present */
65816 		/* No need to check for argArray. */
65817 	} else {
65818 		DUK_ASSERT(duk_get_top(thr) >= idx_func + 3);  /* idx_func + 2 covered above */
65819 		if (thr->valstack_top > tv_args + 1) {
65820 			duk_set_top_unsafe(thr, idx_func + 3);  /* remove any args beyond argArray */
65821 		}
65822 		DUK_ASSERT(duk_is_valid_index(thr, idx_func + 2));
65823 		if (!duk_is_callable(thr, idx_func)) {
65824 			/* Avoid unpack side effects if the target isn't callable.
65825 			 * Calling code will throw the actual error.
65826 			 */
65827 		} else {
65828 			(void) duk_unpack_array_like(thr, idx_func + 2);
65829 			duk_remove(thr, idx_func + 2);
65830 		}
65831 	}
65832 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
65833 	return 0;  /* keep resolving */
65834 }
65835 
65836 /*
65837  *  Helper for Proxy handling.
65838  */
65839 
65840 #if defined(DUK_USE_ES6_PROXY)
65841 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) {
65842 	duk_bool_t rc;
65843 
65844 	/* Value stack:
65845 	 * idx_func + 0: Proxy object
65846 	 * idx_func + 1: this binding for call
65847 	 * idx_func + 2: 1st argument for call
65848 	 * idx_func + 3: 2nd argument for call
65849 	 * ...
65850 	 *
65851 	 * If Proxy doesn't have a trap for the call ('apply' or 'construct'),
65852 	 * replace Proxy object with target object.
65853 	 *
65854 	 * If we're dealing with a normal call and the Proxy has an 'apply'
65855 	 * trap, manipulate value stack to:
65856 	 *
65857 	 * idx_func + 0: trap
65858 	 * idx_func + 1: Proxy's handler
65859 	 * idx_func + 2: Proxy's target
65860 	 * idx_func + 3: this binding for call (from idx_func + 1)
65861 	 * idx_func + 4: call arguments packed to an array
65862 	 *
65863 	 * If we're dealing with a constructor call and the Proxy has a
65864 	 * 'construct' trap, manipulate value stack to:
65865 	 *
65866 	 * idx_func + 0: trap
65867 	 * idx_func + 1: Proxy's handler
65868 	 * idx_func + 2: Proxy's target
65869 	 * idx_func + 3: call arguments packed to an array
65870 	 * idx_func + 4: newTarget == Proxy object here
65871 	 *
65872 	 * As we don't yet have proper newTarget support, the newTarget at
65873 	 * idx_func + 3 is just the original constructor being called, i.e.
65874 	 * the Proxy object (not the target).  Note that the default instance
65875 	 * (original 'this' binding) is dropped and ignored.
65876 	 */
65877 
65878 	duk_push_hobject(thr, h_proxy->handler);
65879 	rc = duk_get_prop_stridx_short(thr, -1, (*call_flags & DUK_CALL_FLAG_CONSTRUCT) ? DUK_STRIDX_CONSTRUCT : DUK_STRIDX_APPLY);
65880 	if (rc == 0) {
65881 		/* Not found, continue to target.  If this is a construct
65882 		 * call, update default instance prototype using the Proxy,
65883 		 * not the target.
65884 		 */
65885 		if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
65886 			if (!(*call_flags & DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED)) {
65887 				*call_flags |= DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED;
65888 				duk__update_default_instance_proto(thr, idx_func);
65889 			}
65890 		}
65891 		duk_pop_2(thr);
65892 		duk_push_hobject(thr, h_proxy->target);
65893 		duk_replace(thr, idx_func);
65894 		return;
65895 	}
65896 
65897 	/* Here we must be careful not to replace idx_func while
65898 	 * h_proxy is still needed, otherwise h_proxy may become
65899 	 * dangling.  This could be improved e.g. using a
65900 	 * duk_pack_slice() with a freeform slice.
65901 	 */
65902 
65903 	/* Here:
65904 	 * idx_func + 0: Proxy object
65905 	 * idx_func + 1: this binding for call
65906 	 * idx_func + 2: 1st argument for call
65907 	 * idx_func + 3: 2nd argument for call
65908 	 * ...
65909 	 * idx_func + N: handler
65910 	 * idx_func + N + 1: trap
65911 	 */
65912 
65913 	duk_insert(thr, idx_func + 1);
65914 	duk_insert(thr, idx_func + 2);
65915 	duk_push_hobject(thr, h_proxy->target);
65916 	duk_insert(thr, idx_func + 3);
65917 	duk_pack(thr, duk_get_top(thr) - (idx_func + 5));
65918 	DUK_ASSERT(!duk_is_bare_object(thr, -1));
65919 
65920 	/* Here:
65921 	 * idx_func + 0: Proxy object
65922 	 * idx_func + 1: trap
65923 	 * idx_func + 2: Proxy's handler
65924 	 * idx_func + 3: Proxy's target
65925 	 * idx_func + 4: this binding for call
65926 	 * idx_func + 5: arguments array
65927 	 */
65928 	DUK_ASSERT(duk_get_top(thr) == idx_func + 6);
65929 
65930 	if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
65931 		*call_flags |= DUK_CALL_FLAG_CONSTRUCT_PROXY;  /* Enable 'construct' trap return invariant check. */
65932 		*call_flags &= ~(DUK_CALL_FLAG_CONSTRUCT);     /* Resume as non-constructor call to the trap. */
65933 
65934 		/* 'apply' args: target, thisArg, argArray
65935 		 * 'construct' args: target, argArray, newTarget
65936 		 */
65937 		duk_remove(thr, idx_func + 4);
65938 		duk_push_hobject(thr, (duk_hobject *) h_proxy);
65939 	}
65940 
65941 	/* Finalize value stack layout by removing Proxy reference. */
65942 	duk_remove(thr, idx_func);
65943 	h_proxy = NULL;  /* invalidated */
65944 	DUK_ASSERT(duk_get_top(thr) == idx_func + 5);
65945 }
65946 #endif  /* DUK_USE_ES6_PROXY */
65947 
65948 /*
65949  *  Helper for setting up var_env and lex_env of an activation,
65950  *  assuming it does NOT have the DUK_HOBJECT_FLAG_NEWENV flag.
65951  */
65952 
65953 DUK_LOCAL void duk__handle_oldenv_for_call(duk_hthread *thr,
65954                                            duk_hobject *func,
65955                                            duk_activation *act) {
65956 	duk_hcompfunc *f;
65957 	duk_hobject *h_lex;
65958 	duk_hobject *h_var;
65959 
65960 	DUK_ASSERT(thr != NULL);
65961 	DUK_ASSERT(func != NULL);
65962 	DUK_ASSERT(act != NULL);
65963 	DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV(func));
65964 	DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
65965 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(func));
65966 	DUK_UNREF(thr);
65967 
65968 	f = (duk_hcompfunc *) func;
65969 	h_lex = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
65970 	h_var = DUK_HCOMPFUNC_GET_VARENV(thr->heap, f);
65971 	DUK_ASSERT(h_lex != NULL);  /* Always true for closures (not for templates) */
65972 	DUK_ASSERT(h_var != NULL);
65973 	act->lex_env = h_lex;
65974 	act->var_env = h_var;
65975 	DUK_HOBJECT_INCREF(thr, h_lex);
65976 	DUK_HOBJECT_INCREF(thr, h_var);
65977 }
65978 
65979 /*
65980  *  Helper for updating callee 'caller' property.
65981  */
65982 
65983 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
65984 DUK_LOCAL void duk__update_func_caller_prop(duk_hthread *thr, duk_hobject *func) {
65985 	duk_tval *tv_caller;
65986 	duk_hobject *h_tmp;
65987 	duk_activation *act_callee;
65988 	duk_activation *act_caller;
65989 
65990 	DUK_ASSERT(thr != NULL);
65991 	DUK_ASSERT(func != NULL);
65992 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound chain resolved */
65993 	DUK_ASSERT(thr->callstack_top >= 1);
65994 
65995 	if (DUK_HOBJECT_HAS_STRICT(func)) {
65996 		/* Strict functions don't get their 'caller' updated. */
65997 		return;
65998 	}
65999 
66000 	DUK_ASSERT(thr->callstack_top > 0);
66001 	act_callee = thr->callstack_curr;
66002 	DUK_ASSERT(act_callee != NULL);
66003 	act_caller = (thr->callstack_top >= 2 ? act_callee->parent : NULL);
66004 
66005 	/* XXX: check .caller writability? */
66006 
66007 	/* Backup 'caller' property and update its value. */
66008 	tv_caller = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, func, DUK_STRIDX_CALLER);
66009 	if (tv_caller) {
66010 		/* If caller is global/eval code, 'caller' should be set to
66011 		 * 'null'.
66012 		 *
66013 		 * XXX: there is no exotic flag to infer this correctly now.
66014 		 * The NEWENV flag is used now which works as intended for
66015 		 * everything (global code, non-strict eval code, and functions)
66016 		 * except strict eval code.  Bound functions are never an issue
66017 		 * because 'func' has been resolved to a non-bound function.
66018 		 */
66019 
66020 		if (act_caller != NULL) {
66021 			/* act_caller->func may be NULL in some finalization cases,
66022 			 * just treat like we don't know the caller.
66023 			 */
66024 			if (act_caller->func && !DUK_HOBJECT_HAS_NEWENV(act_caller->func)) {
66025 				/* Setting to NULL causes 'caller' to be set to
66026 				 * 'null' as desired.
66027 				 */
66028 				act_caller = NULL;
66029 			}
66030 		}
66031 
66032 		if (DUK_TVAL_IS_OBJECT(tv_caller)) {
66033 			h_tmp = DUK_TVAL_GET_OBJECT(tv_caller);
66034 			DUK_ASSERT(h_tmp != NULL);
66035 			act_callee->prev_caller = h_tmp;
66036 
66037 			/* Previous value doesn't need refcount changes because its ownership
66038 			 * is transferred to prev_caller.
66039 			 */
66040 
66041 			if (act_caller != NULL) {
66042 				DUK_ASSERT(act_caller->func != NULL);
66043 				DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
66044 				DUK_TVAL_INCREF(thr, tv_caller);
66045 			} else {
66046 				DUK_TVAL_SET_NULL(tv_caller);  /* no incref */
66047 			}
66048 		} else {
66049 			/* 'caller' must only take on 'null' or function value */
66050 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_caller));
66051 			DUK_ASSERT(act_callee->prev_caller == NULL);
66052 			if (act_caller != NULL && act_caller->func) {
66053 				/* Tolerate act_caller->func == NULL which happens in
66054 				 * some finalization cases; treat like unknown caller.
66055 				 */
66056 				DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
66057 				DUK_TVAL_INCREF(thr, tv_caller);
66058 			} else {
66059 				DUK_TVAL_SET_NULL(tv_caller);  /* no incref */
66060 			}
66061 		}
66062 	}
66063 }
66064 #endif  /* DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
66065 
66066 /*
66067  *  Shared helpers for resolving the final, non-bound target function of the
66068  *  call and the effective 'this' binding.  Resolves bound functions and
66069  *  applies .call(), .apply(), and .construct() inline.
66070  *
66071  *  Proxy traps are also handled inline so that if the target is a Proxy with
66072  *  a 'call' or 'construct' trap, the trap handler is called with a modified
66073  *  argument list.
66074  *
66075  *  Once the bound function / .call() / .apply() / .construct() sequence has
66076  *  been resolved, the value at idx_func + 1 may need coercion described in
66077  *  E5 Section 10.4.3.
66078  *
66079  *  A call that begins as a non-constructor call may be converted into a
66080  *  constructor call during the resolution process if Reflect.construct()
66081  *  is invoked.  This is handled by updating the caller's call_flags.
66082  *
66083  *  For global and eval code (E5 Sections 10.4.1 and 10.4.2), we assume
66084  *  that the caller has provided the correct 'this' binding explicitly
66085  *  when calling, i.e.:
66086  *
66087  *    - global code: this=global object
66088  *    - direct eval: this=copy from eval() caller's this binding
66089  *    - other eval:  this=global object
66090  *
66091  *  The 'this' coercion may cause a recursive function call with arbitrary
66092  *  side effects, because ToObject() may be called.
66093  */
66094 
66095 DUK_LOCAL DUK_INLINE void duk__coerce_nonstrict_this_binding(duk_hthread *thr, duk_idx_t idx_this) {
66096 	duk_tval *tv_this;
66097 	duk_hobject *obj_global;
66098 
66099 	tv_this = thr->valstack_bottom + idx_this;
66100 	switch (DUK_TVAL_GET_TAG(tv_this)) {
66101 	case DUK_TAG_OBJECT:
66102 		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, object -> use directly"));
66103 		break;
66104 	case DUK_TAG_UNDEFINED:
66105 	case DUK_TAG_NULL:
66106 		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, undefined/null -> use global object"));
66107 		obj_global = thr->builtins[DUK_BIDX_GLOBAL];
66108 		/* XXX: avoid this check somehow */
66109 		if (DUK_LIKELY(obj_global != NULL)) {
66110 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this));  /* no need to decref previous value */
66111 			DUK_TVAL_SET_OBJECT(tv_this, obj_global);
66112 			DUK_HOBJECT_INCREF(thr, obj_global);
66113 		} else {
66114 			/* This may only happen if built-ins are being "torn down".
66115 			 * This behavior is out of specification scope.
66116 			 */
66117 			DUK_D(DUK_DPRINT("this binding: wanted to use global object, but it is NULL -> using undefined instead"));
66118 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this));  /* no need to decref previous value */
66119 			DUK_TVAL_SET_UNDEFINED(tv_this);  /* nothing to incref */
66120 		}
66121 		break;
66122 	default:
66123 		/* Plain buffers and lightfuncs are object coerced.  Lightfuncs
66124 		 * very rarely come here however, because the call target would
66125 		 * need to be a non-strict non-lightfunc (lightfuncs are considered
66126 		 * strict) with an explicit lightfunc 'this' binding.
66127 		 */
66128 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_this));
66129 		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, not object/undefined/null -> use ToObject(value)"));
66130 		duk_to_object(thr, idx_this);  /* may have side effects */
66131 		break;
66132 	}
66133 }
66134 
66135 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) {
66136 #if defined(DUK_USE_PREFER_SIZE)
66137 	DUK_UNREF(thr);
66138 	DUK_UNREF(idx_func);
66139 	DUK_UNREF(out_func);
66140 	DUK_UNREF(call_flags);
66141 #else  /* DUK_USE_PREFER_SIZE */
66142 	duk_tval *tv_func;
66143 	duk_hobject *func;
66144 
66145 	if (DUK_UNLIKELY(call_flags & DUK_CALL_FLAG_CONSTRUCT)) {
66146 		return 0;
66147 	}
66148 
66149 	tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
66150 	DUK_ASSERT(tv_func != NULL);
66151 
66152 	if (DUK_LIKELY(DUK_TVAL_IS_OBJECT(tv_func))) {
66153 		func = DUK_TVAL_GET_OBJECT(tv_func);
66154 		if (DUK_HOBJECT_IS_CALLABLE(func) &&
66155 		    !DUK_HOBJECT_HAS_BOUNDFUNC(func) &&
66156 		    !DUK_HOBJECT_HAS_SPECIAL_CALL(func)) {
66157 			*out_func = func;
66158 
66159 			if (DUK_HOBJECT_HAS_STRICT(func)) {
66160 				/* Strict function: no 'this' coercion. */
66161 				return 1;
66162 			}
66163 
66164 			duk__coerce_nonstrict_this_binding(thr, idx_func + 1);
66165 			return 1;
66166 		}
66167 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
66168 		*out_func = NULL;
66169 
66170 		/* Lightfuncs are considered strict, so 'this' binding is
66171 		 * used as is.  They're never bound, always constructable,
66172 		 * and never special functions.
66173 		 */
66174 		return 1;
66175 	}
66176 #endif  /* DUK_USE_PREFER_SIZE */
66177 	return 0;  /* let slow path deal with it */
66178 }
66179 
66180 DUK_LOCAL duk_hobject *duk__resolve_target_func_and_this_binding(duk_hthread *thr,
66181                                                                  duk_idx_t idx_func,
66182                                                                  duk_small_uint_t *call_flags) {
66183 	duk_tval *tv_func;
66184 	duk_hobject *func;
66185 	duk_bool_t first;
66186 
66187 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
66188 
66189 	for (first = 1;; first = 0) {
66190 		DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
66191 
66192 		tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
66193 		DUK_ASSERT(tv_func != NULL);
66194 
66195 		DUK_DD(DUK_DDPRINT("target func: %!iT", tv_func));
66196 
66197 		if (DUK_TVAL_IS_OBJECT(tv_func)) {
66198 			func = DUK_TVAL_GET_OBJECT(tv_func);
66199 
66200 			if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
66201 				if (DUK_UNLIKELY(!DUK_HOBJECT_HAS_CONSTRUCTABLE(func))) {
66202 					goto not_constructable;
66203 				}
66204 			} else {
66205 				if (DUK_UNLIKELY(!DUK_HOBJECT_IS_CALLABLE(func))) {
66206 					goto not_callable;
66207 				}
66208 			}
66209 
66210 			if (DUK_LIKELY(!DUK_HOBJECT_HAS_BOUNDFUNC(func) &&
66211 			               !DUK_HOBJECT_HAS_SPECIAL_CALL(func) &&
66212 			               !DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(func))) {
66213 				/* Common case, so test for using a single bitfield test.
66214 				 * Break out to handle this coercion etc.
66215 				 */
66216 				break;
66217 			}
66218 
66219 			/* XXX: could set specialcall for boundfuncs too, simplify check above */
66220 
66221 			if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
66222 				DUK_ASSERT(!DUK_HOBJECT_HAS_SPECIAL_CALL(func));
66223 				DUK_ASSERT(!DUK_HOBJECT_IS_NATFUNC(func));
66224 
66225 				/* Callable/constructable flags are the same
66226 				 * for the bound function and its target, so
66227 				 * we don't need to check them here, we can
66228 				 * check them from the target only.
66229 				 */
66230 				duk__handle_bound_chain_for_call(thr, idx_func, *call_flags & DUK_CALL_FLAG_CONSTRUCT);
66231 
66232 				DUK_ASSERT(DUK_TVAL_IS_OBJECT(duk_require_tval(thr, idx_func)) ||
66233 				           DUK_TVAL_IS_LIGHTFUNC(duk_require_tval(thr, idx_func)));
66234 			} else {
66235 				DUK_ASSERT(DUK_HOBJECT_HAS_SPECIAL_CALL(func));
66236 
66237 #if defined(DUK_USE_ES6_PROXY)
66238 				if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(func)) {
66239 					/* If no trap, resume processing from Proxy trap.
66240 					 * If trap exists, helper converts call into a trap
66241 					 * call; this may change a constructor call into a
66242 					 * normal (non-constructor) trap call.  We must
66243 					 * continue processing even when a trap is found as
66244 					 * the trap may be bound.
66245 					 */
66246 					duk__handle_proxy_for_call(thr, idx_func, (duk_hproxy *) func, call_flags);
66247 				}
66248 				else
66249 #endif
66250 				{
66251 					DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(func));
66252 					DUK_ASSERT(DUK_HOBJECT_HAS_CALLABLE(func));
66253 					DUK_ASSERT(!DUK_HOBJECT_HAS_CONSTRUCTABLE(func));
66254 					/* Constructable check already done above. */
66255 
66256 					if (duk__handle_specialfuncs_for_call(thr, idx_func, func, call_flags, first) != 0) {
66257 						/* Encountered native eval call, normal call
66258 						 * context.  Break out, handle this coercion etc.
66259 						 */
66260 						break;
66261 					}
66262 				}
66263 			}
66264 			/* Retry loop. */
66265 		} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
66266 			/* Lightfuncs are:
66267 			 *   - Always strict, so no 'this' coercion.
66268 			 *   - Always callable.
66269 			 *   - Always constructable.
66270 			 *   - Never specialfuncs.
66271 			 */
66272 			func = NULL;
66273 			goto finished;
66274 		} else {
66275 			goto not_callable;
66276 		}
66277 	}
66278 
66279 	DUK_ASSERT(func != NULL);
66280 
66281 	if (!DUK_HOBJECT_HAS_STRICT(func)) {
66282 		/* Non-strict target needs 'this' coercion.
66283 		 * This has potential side effects invalidating
66284 		 * 'tv_func'.
66285 		 */
66286 		duk__coerce_nonstrict_this_binding(thr, idx_func + 1);
66287 	}
66288 	if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
66289 		if (!(*call_flags & DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED)) {
66290 			*call_flags |= DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED;
66291 			duk__update_default_instance_proto(thr, idx_func);
66292 		}
66293 	}
66294 
66295  finished:
66296 
66297 #if defined(DUK_USE_ASSERTIONS)
66298 	{
66299 		duk_tval *tv_tmp;
66300 
66301 		tv_tmp = duk_get_tval(thr, idx_func);
66302 		DUK_ASSERT(tv_tmp != NULL);
66303 
66304 		DUK_ASSERT((DUK_TVAL_IS_OBJECT(tv_tmp) && DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(tv_tmp))) ||
66305 		           DUK_TVAL_IS_LIGHTFUNC(tv_tmp));
66306 		DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
66307 		DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) ||
66308 		                            DUK_HOBJECT_IS_NATFUNC(func)));
66309 		DUK_ASSERT(func == NULL || (DUK_HOBJECT_HAS_CONSTRUCTABLE(func) ||
66310 		                            (*call_flags & DUK_CALL_FLAG_CONSTRUCT) == 0));
66311 	}
66312 #endif
66313 
66314 	return func;
66315 
66316  not_callable:
66317 	DUK_ASSERT(tv_func != NULL);
66318 
66319 #if defined(DUK_USE_VERBOSE_ERRORS)
66320 	/* GETPROPC delayed error handling: when target is not callable,
66321 	 * GETPROPC replaces idx_func+0 with a non-callable wrapper object
66322 	 * with a hidden Symbol to signify it's to be handled here.  If
66323 	 * found, unwrap the original Error and throw it as is here.  The
66324 	 * hidden Symbol is only checked as an own property, not inherited
66325 	 * (which would be dangerous).
66326 	 */
66327 	if (DUK_TVAL_IS_OBJECT(tv_func)) {
66328 		duk_tval *tv_wrap = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, DUK_TVAL_GET_OBJECT(tv_func), DUK_STRIDX_INT_TARGET);
66329 		if (tv_wrap != NULL) {
66330 			DUK_DD(DUK_DDPRINT("delayed error from GETPROPC: %!T", tv_wrap));
66331 			duk_push_tval(thr, tv_wrap);
66332 			(void) duk_throw(thr);
66333 			DUK_WO_NORETURN(return NULL;);
66334 		}
66335 	}
66336 #endif
66337 
66338 #if defined(DUK_USE_VERBOSE_ERRORS)
66339 #if defined(DUK_USE_PARANOID_ERRORS)
66340 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not callable", duk_get_type_name(thr, idx_func));
66341 #else
66342 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not callable", duk_push_string_tval_readable(thr, tv_func));
66343 #endif
66344 #else
66345 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
66346 #endif
66347 	DUK_WO_NORETURN(return NULL;);
66348 
66349  not_constructable:
66350 	/* For now GETPROPC delayed error not needed for constructor calls. */
66351 #if defined(DUK_USE_VERBOSE_ERRORS)
66352 #if defined(DUK_USE_PARANOID_ERRORS)
66353 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not constructable", duk_get_type_name(thr, idx_func));
66354 #else
66355 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not constructable", duk_push_string_tval_readable(thr, tv_func));
66356 #endif
66357 #else
66358 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONSTRUCTABLE);
66359 #endif
66360 	DUK_WO_NORETURN(return NULL;);
66361 }
66362 
66363 /*
66364  *  Manipulate value stack so that exactly 'num_stack_rets' return
66365  *  values are at 'idx_retbase' in every case, assuming there are
66366  *  'rc' return values on top of stack.
66367  *
66368  *  This is a bit tricky, because the called C function operates in
66369  *  the same activation record and may have e.g. popped the stack
66370  *  empty (below idx_retbase).
66371  */
66372 
66373 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) {
66374 	duk_idx_t idx_rcbase;
66375 
66376 	DUK_ASSERT(thr != NULL);
66377 	DUK_ASSERT(idx_retbase >= 0);
66378 	DUK_ASSERT(num_stack_rets >= 0);
66379 	DUK_ASSERT(num_actual_rets >= 0);
66380 
66381 	idx_rcbase = duk_get_top(thr) - num_actual_rets;  /* base of known return values */
66382 	if (DUK_UNLIKELY(idx_rcbase < 0)) {
66383 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_CFUNC_RC);
66384 		DUK_WO_NORETURN(return;);
66385 	}
66386 
66387 	DUK_DDD(DUK_DDDPRINT("adjust valstack after func call: "
66388 	                     "num_stack_rets=%ld, num_actual_rets=%ld, stack_top=%ld, idx_retbase=%ld, idx_rcbase=%ld",
66389 	                     (long) num_stack_rets, (long) num_actual_rets, (long) duk_get_top(thr),
66390 	                     (long) idx_retbase, (long) idx_rcbase));
66391 
66392 	DUK_ASSERT(idx_rcbase >= 0);  /* caller must check */
66393 
66394 	/* Space for num_stack_rets was reserved before the safe call.
66395 	 * Because value stack reserve cannot shrink except in call returns,
66396 	 * the reserve is still in place.  Adjust valstack, carefully
66397 	 * ensuring we don't overstep the reserve.
66398 	 */
66399 
66400 	/* Match idx_rcbase with idx_retbase so that the return values
66401 	 * start at the correct index.
66402 	 */
66403 	if (idx_rcbase > idx_retbase) {
66404 		duk_idx_t count = idx_rcbase - idx_retbase;
66405 
66406 		DUK_DDD(DUK_DDDPRINT("elements at/after idx_retbase have enough to cover func retvals "
66407 		                     "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
66408 
66409 		/* Remove values between irc_rcbase (start of intended return
66410 		 * values) and idx_retbase to lower return values to idx_retbase.
66411 		 */
66412 		DUK_ASSERT(count > 0);
66413 		duk_remove_n(thr, idx_retbase, count);  /* may be NORZ */
66414 	} else {
66415 		duk_idx_t count = idx_retbase - idx_rcbase;
66416 
66417 		DUK_DDD(DUK_DDDPRINT("not enough elements at/after idx_retbase to cover func retvals "
66418 		                     "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
66419 
66420 		/* Insert 'undefined' at idx_rcbase (start of intended return
66421 		 * values) to lift return values to idx_retbase.
66422 		 */
66423 		DUK_ASSERT(count >= 0);
66424 		DUK_ASSERT(thr->valstack_end - thr->valstack_top >= count);  /* reserve cannot shrink */
66425 		duk_insert_undefined_n(thr, idx_rcbase, count);
66426 	}
66427 
66428 	/* Chop extra retvals away / extend with undefined. */
66429 	duk_set_top_unsafe(thr, idx_retbase + num_stack_rets);
66430 }
66431 
66432 /*
66433  *  Activation setup for tailcalls and non-tailcalls.
66434  */
66435 
66436 #if defined(DUK_USE_TAILCALL)
66437 DUK_LOCAL duk_small_uint_t duk__call_setup_act_attempt_tailcall(duk_hthread *thr,
66438                                                                 duk_small_uint_t call_flags,
66439                                                                 duk_idx_t idx_func,
66440                                                                 duk_hobject *func,
66441                                                                 duk_size_t entry_valstack_bottom_byteoff,
66442                                                                 duk_size_t entry_valstack_end_byteoff,
66443                                                                 duk_idx_t *out_nargs,
66444                                                                 duk_idx_t *out_nregs,
66445                                                                 duk_size_t *out_vs_min_bytes,
66446                                                                 duk_activation **out_act) {
66447 	duk_activation *act;
66448 	duk_tval *tv1, *tv2;
66449 	duk_idx_t idx_args;
66450 	duk_small_uint_t flags1, flags2;
66451 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66452 	duk_activation *prev_pause_act;
66453 #endif
66454 
66455 	DUK_UNREF(entry_valstack_end_byteoff);
66456 
66457 	/* Tailcall cannot be flagged to resume calls, and a
66458 	 * previous frame must exist.
66459 	 */
66460 	DUK_ASSERT(thr->callstack_top >= 1);
66461 
66462 	act = thr->callstack_curr;
66463 	DUK_ASSERT(act != NULL);
66464 	*out_act = act;
66465 
66466 	if (func == NULL || !DUK_HOBJECT_IS_COMPFUNC(func)) {
66467 		DUK_DDD(DUK_DDDPRINT("tail call prevented by target not being ecma function"));
66468 		return 0;
66469 	}
66470 	if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
66471 		DUK_DDD(DUK_DDDPRINT("tail call prevented by current activation having DUK_ACT_FLAG_PREVENT_YIELD"));
66472 		return 0;
66473 	}
66474 	/* Tailcall is only allowed if current and candidate
66475 	 * function have identical return value handling.  There
66476 	 * are three possible return value handling cases:
66477 	 *   1. Normal function call, no special return value handling.
66478 	 *   2. Constructor call, return value replacement object check.
66479 	 *   3. Proxy 'construct' trap call, return value invariant check.
66480 	 */
66481 	flags1 = (duk_small_uint_t) ((act->flags & DUK_ACT_FLAG_CONSTRUCT) ? 1 : 0)
66482 #if defined(DUK_USE_ES6_PROXY)
66483 	         | (duk_small_uint_t) ((act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) ? 2 : 0)
66484 #endif
66485 	         ;
66486 	flags2 = (duk_small_uint_t) ((call_flags & DUK_CALL_FLAG_CONSTRUCT) ? 1 : 0)
66487 #if defined(DUK_USE_ES6_PROXY)
66488 	         | (duk_small_uint_t) ((call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) ? 2 : 0);
66489 #endif
66490 	         ;
66491 	if (flags1 != flags2) {
66492 		DUK_DDD(DUK_DDDPRINT("tail call prevented by incompatible return value handling"));
66493 		return 0;
66494 	}
66495 	DUK_ASSERT(((act->flags & DUK_ACT_FLAG_CONSTRUCT) && (call_flags & DUK_CALL_FLAG_CONSTRUCT)) ||
66496 	           (!(act->flags & DUK_ACT_FLAG_CONSTRUCT) && !(call_flags & DUK_CALL_FLAG_CONSTRUCT)));
66497 	DUK_ASSERT(((act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) && (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY)) ||
66498 	           (!(act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) && !(call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY)));
66499 	if (DUK_HOBJECT_HAS_NOTAIL(func)) {
66500 		/* See: test-bug-tailcall-preventyield-assert.c. */
66501 		DUK_DDD(DUK_DDDPRINT("tail call prevented by function having a notail flag"));
66502 		return 0;
66503 	}
66504 
66505 	/*
66506 	 *  Tailcall handling
66507 	 *
66508 	 *  Although the callstack entry is reused, we need to explicitly unwind
66509 	 *  the current activation (or simulate an unwind).  In particular, the
66510 	 *  current activation must be closed, otherwise something like
66511 	 *  test-bug-reduce-judofyr.js results.  Also catchers need to be unwound
66512 	 *  because there may be non-error-catching label entries in valid tail calls.
66513 	 *
66514 	 *  Special attention is needed for debugger and pause behavior when
66515 	 *  reusing an activation.
66516 	 *    - Disable StepOut processing for the activation unwind because
66517 	 *      we reuse the activation, see:
66518 	 *      https://github.com/svaarala/duktape/issues/1684.
66519 	 *    - Disable line change pause flag permanently if act == dbg_pause_act
66520 	 *      (if set) because it would no longer be relevant, see:
66521 	 *      https://github.com/svaarala/duktape/issues/1726,
66522 	 *      https://github.com/svaarala/duktape/issues/1786.
66523 	 *    - Check for function entry (e.g. StepInto) pause flag here, because
66524 	 *      the executor pause check won't trigger due to shared activation, see:
66525 	 *      https://github.com/svaarala/duktape/issues/1726.
66526 	 */
66527 
66528 	DUK_DDD(DUK_DDDPRINT("is tail call, reusing activation at callstack top, at index %ld",
66529                              (long) (thr->callstack_top - 1)));
66530 
66531 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
66532 	DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(func));
66533 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
66534 	DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
66535 	DUK_ASSERT(call_flags & DUK_CALL_FLAG_ALLOW_ECMATOECMA);
66536 
66537 	/* Unwind the topmost callstack entry before reusing it.  This
66538 	 * also unwinds the catchers related to the topmost entry.
66539 	 */
66540 	DUK_ASSERT(thr->callstack_top > 0);
66541 	DUK_ASSERT(thr->callstack_curr != NULL);
66542 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66543 	if (act == thr->heap->dbg_pause_act) {
66544 		thr->heap->dbg_pause_flags &= ~DUK_PAUSE_FLAG_LINE_CHANGE;
66545 	}
66546 
66547 	prev_pause_act = thr->heap->dbg_pause_act;
66548 	thr->heap->dbg_pause_act = NULL;
66549 	if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_ENTRY) {
66550 		DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function entry (tailcall)"));
66551 		duk_debug_set_paused(thr->heap);
66552 	}
66553 #endif
66554 	duk_hthread_activation_unwind_reuse_norz(thr);
66555 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66556 	thr->heap->dbg_pause_act = prev_pause_act;
66557 #endif
66558 	DUK_ASSERT(act == thr->callstack_curr);
66559 
66560 	/* XXX: We could restore the caller's value stack reserve
66561 	 * here, as if we did an actual unwind-and-call.  Without
66562 	 * the restoration, value stack reserve may remain higher
66563 	 * than would otherwise be possible until we return to a
66564 	 * non-tailcall.
66565 	 */
66566 
66567 	/* Then reuse the unwound activation. */
66568 	act->cat = NULL;
66569 	act->var_env = NULL;
66570 	act->lex_env = NULL;
66571 	DUK_ASSERT(func != NULL);
66572 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
66573 	act->func = func;  /* don't want an intermediate exposed state with func == NULL */
66574 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
66575 	act->prev_caller = NULL;
66576 #endif
66577 	/* don't want an intermediate exposed state with invalid pc */
66578 	act->curr_pc = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) func);
66579 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66580 	act->prev_line = 0;
66581 #endif
66582 	DUK_TVAL_SET_OBJECT(&act->tv_func, func);  /* borrowed, no refcount */
66583 	DUK_HOBJECT_INCREF(thr, func);
66584 
66585 	act->flags = DUK_ACT_FLAG_TAILCALLED;
66586 	if (DUK_HOBJECT_HAS_STRICT(func)) {
66587 		act->flags |= DUK_ACT_FLAG_STRICT;
66588 	}
66589 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
66590 		act->flags |= DUK_ACT_FLAG_CONSTRUCT;
66591 	}
66592 #if defined(DUK_USE_ES6_PROXY)
66593 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) {
66594 		act->flags |= DUK_ACT_FLAG_CONSTRUCT_PROXY;
66595 	}
66596 #endif
66597 
66598 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) == func);      /* already updated */
66599 	DUK_ASSERT(act->var_env == NULL);
66600 	DUK_ASSERT(act->lex_env == NULL);
66601 	act->bottom_byteoff = entry_valstack_bottom_byteoff;  /* tail call -> reuse current "frame" */
66602 #if 0
66603 	/* Topmost activation retval_byteoff is considered garbage, no need to init. */
66604 	act->retval_byteoff = 0;
66605 #endif
66606 	/* Filled in when final reserve is known, dummy value doesn't matter
66607 	 * even in error unwind because reserve_byteoff is only used when
66608 	 * returning to -this- activation.
66609 	 */
66610 	act->reserve_byteoff = 0;
66611 
66612 	/*
66613 	 *  Manipulate valstack so that args are on the current bottom and the
66614 	 *  previous caller's 'this' binding (which is the value preceding the
66615 	 *  current bottom) is replaced with the new 'this' binding:
66616 	 *
66617 	 *       [ ... this_old | (crud) func this_new arg1 ... argN ]
66618 	 *  -->  [ ... this_new | arg1 ... argN ]
66619 	 *
66620 	 *  For tail calling to work properly, the valstack bottom must not grow
66621 	 *  here; otherwise crud would accumulate on the valstack.
66622 	 */
66623 
66624 	tv1 = thr->valstack_bottom - 1;
66625 	tv2 = thr->valstack_bottom + idx_func + 1;
66626 	DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);  /* tv1 is -below- valstack_bottom */
66627 	DUK_ASSERT(tv2 >= thr->valstack_bottom && tv2 < thr->valstack_top);
66628 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
66629 
66630 	idx_args = idx_func + 2;
66631 	duk_remove_n(thr, 0, idx_args);  /* may be NORZ */
66632 
66633 	idx_func = 0; DUK_UNREF(idx_func);  /* really 'not applicable' anymore, should not be referenced after this */
66634 	idx_args = 0;
66635 
66636 	*out_nargs = ((duk_hcompfunc *) func)->nargs;
66637 	*out_nregs = ((duk_hcompfunc *) func)->nregs;
66638 	DUK_ASSERT(*out_nregs >= 0);
66639 	DUK_ASSERT(*out_nregs >= *out_nargs);
66640 	*out_vs_min_bytes = entry_valstack_bottom_byteoff + sizeof(duk_tval) * ((duk_size_t) *out_nregs + DUK_VALSTACK_INTERNAL_EXTRA);
66641 
66642 
66643 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
66644 #if defined(DUK_USE_TAILCALL)
66645 #error incorrect options: tail calls enabled with function caller property
66646 #endif
66647 	/* XXX: This doesn't actually work properly for tail calls, so
66648 	 * tail calls are disabled when DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
66649 	 * is in use.
66650 	 */
66651 	duk__update_func_caller_prop(thr, func);
66652 #endif
66653 
66654 	/* [ ... this_new | arg1 ... argN ] */
66655 
66656 	return 1;
66657 }
66658 #endif  /* DUK_USE_TAILCALL */
66659 
66660 DUK_LOCAL void duk__call_setup_act_not_tailcall(duk_hthread *thr,
66661                                                 duk_small_uint_t call_flags,
66662                                                 duk_idx_t idx_func,
66663                                                 duk_hobject *func,
66664                                                 duk_size_t entry_valstack_bottom_byteoff,
66665                                                 duk_size_t entry_valstack_end_byteoff,
66666                                                 duk_idx_t *out_nargs,
66667                                                 duk_idx_t *out_nregs,
66668                                                 duk_size_t *out_vs_min_bytes,
66669                                                 duk_activation **out_act) {
66670 	duk_activation *act;
66671 	duk_activation *new_act;
66672 
66673 	DUK_UNREF(entry_valstack_end_byteoff);
66674 
66675 	DUK_DDD(DUK_DDDPRINT("not a tail call, pushing a new activation to callstack, to index %ld",
66676 	                     (long) (thr->callstack_top)));
66677 
66678 	duk__call_callstack_limit_check(thr);
66679 	new_act = duk_hthread_activation_alloc(thr);
66680 	DUK_ASSERT(new_act != NULL);
66681 
66682 	act = thr->callstack_curr;
66683 	if (act != NULL) {
66684 		/*
66685 		 *  Update return value stack index of current activation (if any).
66686 		 *
66687 		 *  Although it might seem this is not necessary (bytecode executor
66688 		 *  does this for ECMAScript-to-ECMAScript calls; other calls are
66689 		 *  handled here), this turns out to be necessary for handling yield
66690 		 *  and resume.  For them, an ECMAScript-to-native call happens, and
66691 		 *  the ECMAScript call's retval_byteoff must be set for things to work.
66692 		 */
66693 
66694 		act->retval_byteoff = entry_valstack_bottom_byteoff + (duk_size_t) idx_func * sizeof(duk_tval);
66695 	}
66696 
66697 	new_act->parent = act;
66698 	thr->callstack_curr = new_act;
66699 	thr->callstack_top++;
66700 	act = new_act;
66701 	*out_act = act;
66702 
66703 	DUK_ASSERT(thr->valstack_top > thr->valstack_bottom);  /* at least effective 'this' */
66704 	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
66705 
66706 	act->cat = NULL;
66707 
66708 	act->flags = 0;
66709 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
66710 		act->flags |= DUK_ACT_FLAG_CONSTRUCT;
66711 	}
66712 #if defined(DUK_USE_ES6_PROXY)
66713 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) {
66714 		act->flags |= DUK_ACT_FLAG_CONSTRUCT_PROXY;
66715 	}
66716 #endif
66717 	if (call_flags & DUK_CALL_FLAG_DIRECT_EVAL) {
66718 		act->flags |= DUK_ACT_FLAG_DIRECT_EVAL;
66719 	}
66720 
66721 	/* start of arguments: idx_func + 2. */
66722 	act->func = func;  /* NULL for lightfunc */
66723 	if (DUK_LIKELY(func != NULL)) {
66724 		DUK_TVAL_SET_OBJECT(&act->tv_func, func);  /* borrowed, no refcount */
66725 		if (DUK_HOBJECT_HAS_STRICT(func)) {
66726 			act->flags |= DUK_ACT_FLAG_STRICT;
66727 		}
66728 		if (DUK_HOBJECT_IS_COMPFUNC(func)) {
66729 			*out_nargs = ((duk_hcompfunc *) func)->nargs;
66730 			*out_nregs = ((duk_hcompfunc *) func)->nregs;
66731 			DUK_ASSERT(*out_nregs >= 0);
66732 			DUK_ASSERT(*out_nregs >= *out_nargs);
66733 			*out_vs_min_bytes = entry_valstack_bottom_byteoff +
66734 				sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nregs + DUK_VALSTACK_INTERNAL_EXTRA);
66735 		} else {
66736 			/* True because of call target lookup checks. */
66737 			DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(func));
66738 
66739 			*out_nargs = ((duk_hnatfunc *) func)->nargs;
66740 			*out_nregs = *out_nargs;
66741 			if (*out_nargs >= 0) {
66742 				*out_vs_min_bytes = entry_valstack_bottom_byteoff +
66743 					sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nregs + DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
66744 			} else {
66745 				/* Vararg function. */
66746 				duk_size_t valstack_top_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - ((duk_uint8_t *) thr->valstack));
66747 				*out_vs_min_bytes = valstack_top_byteoff +
66748 					sizeof(duk_tval) * (DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
66749 			}
66750 		}
66751 	} else {
66752 		duk_small_uint_t lf_flags;
66753 		duk_tval *tv_func;
66754 
66755 		act->flags |= DUK_ACT_FLAG_STRICT;
66756 
66757 		tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
66758 		DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func));
66759 		DUK_TVAL_SET_TVAL(&act->tv_func, tv_func);  /* borrowed, no refcount */
66760 
66761 		lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv_func);
66762 		*out_nargs = DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
66763 		if (*out_nargs != DUK_LFUNC_NARGS_VARARGS) {
66764 			*out_vs_min_bytes = entry_valstack_bottom_byteoff +
66765 				sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nargs + DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
66766 		} else {
66767 			duk_size_t valstack_top_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - ((duk_uint8_t *) thr->valstack));
66768 			*out_vs_min_bytes = valstack_top_byteoff +
66769 				sizeof(duk_tval) * (DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
66770 			*out_nargs = -1;  /* vararg */
66771 		}
66772 		*out_nregs = *out_nargs;
66773 	}
66774 
66775 	act->var_env = NULL;
66776 	act->lex_env = NULL;
66777 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
66778 	act->prev_caller = NULL;
66779 #endif
66780 	act->curr_pc = NULL;
66781 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66782 	act->prev_line = 0;
66783 #endif
66784 	act->bottom_byteoff = entry_valstack_bottom_byteoff + sizeof(duk_tval) * ((duk_size_t) idx_func + 2U);
66785 #if 0
66786 	act->retval_byteoff = 0;   /* topmost activation retval_byteoff is considered garbage, no need to init */
66787 #endif
66788 	/* Filled in when final reserve is known, dummy value doesn't matter
66789 	 * even in error unwind because reserve_byteoff is only used when
66790 	 * returning to -this- activation.
66791 	 */
66792 	act->reserve_byteoff = 0;  /* filled in by caller */
66793 
66794 	/* XXX: Is this INCREF necessary? 'func' is always a borrowed
66795 	 * reference reachable through the value stack?  If changed, stack
66796 	 * unwind code also needs to be fixed to match.
66797 	 */
66798 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, func);  /* act->func */
66799 
66800 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
66801 	if (func) {
66802 		duk__update_func_caller_prop(thr, func);
66803 	}
66804 #endif
66805 }
66806 
66807 /*
66808  *  Environment setup.
66809  */
66810 
66811 DUK_LOCAL void duk__call_env_setup(duk_hthread *thr, duk_hobject *func, duk_activation *act, duk_idx_t idx_args) {
66812 	duk_hobject *env;
66813 
66814 	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound function has already been resolved */
66815 
66816 	if (DUK_LIKELY(func != NULL)) {
66817 		if (DUK_LIKELY(DUK_HOBJECT_HAS_NEWENV(func))) {
66818 			DUK_STATS_INC(thr->heap, stats_envrec_newenv);
66819 			if (DUK_LIKELY(!DUK_HOBJECT_HAS_CREATEARGS(func))) {
66820 				/* Use a new environment but there's no 'arguments' object;
66821 				 * delayed environment initialization.  This is the most
66822 				 * common case.
66823 				 */
66824 				DUK_ASSERT(act->lex_env == NULL);
66825 				DUK_ASSERT(act->var_env == NULL);
66826 			} else {
66827 				/* Use a new environment and there's an 'arguments' object.
66828 				 * We need to initialize it right now.
66829 				 */
66830 
66831 				/* third arg: absolute index (to entire valstack) of bottom_byteoff of new activation */
66832 				env = duk_create_activation_environment_record(thr, func, act->bottom_byteoff);
66833 				DUK_ASSERT(env != NULL);
66834 
66835 				/* [ ... func this arg1 ... argN envobj ] */
66836 
66837 				DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
66838 				duk__handle_createargs_for_call(thr, func, env, idx_args);
66839 
66840 				/* [ ... func this arg1 ... argN envobj ] */
66841 
66842 				act->lex_env = env;
66843 				act->var_env = env;
66844 				DUK_HOBJECT_INCREF(thr, env);
66845 				DUK_HOBJECT_INCREF(thr, env);  /* XXX: incref by count (2) directly */
66846 				duk_pop(thr);
66847 			}
66848 		} else {
66849 			/* Use existing env (e.g. for non-strict eval); cannot have
66850 			 * an own 'arguments' object (but can refer to an existing one).
66851 			 */
66852 
66853 			DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
66854 
66855 			DUK_STATS_INC(thr->heap, stats_envrec_oldenv);
66856 			duk__handle_oldenv_for_call(thr, func, act);
66857 
66858 			DUK_ASSERT(act->lex_env != NULL);
66859 			DUK_ASSERT(act->var_env != NULL);
66860 		}
66861 	} else {
66862 		/* Lightfuncs are always native functions and have "newenv". */
66863 		DUK_ASSERT(act->lex_env == NULL);
66864 		DUK_ASSERT(act->var_env == NULL);
66865 		DUK_STATS_INC(thr->heap, stats_envrec_newenv);
66866 	}
66867 }
66868 
66869 /*
66870  *  Misc shared helpers.
66871  */
66872 
66873 /* Check thread state, update current thread. */
66874 DUK_LOCAL void duk__call_thread_state_update(duk_hthread *thr) {
66875 	DUK_ASSERT(thr != NULL);
66876 
66877 	if (DUK_LIKELY(thr == thr->heap->curr_thread)) {
66878 		if (DUK_UNLIKELY(thr->state != DUK_HTHREAD_STATE_RUNNING)) {
66879 			/* Should actually never happen, but check anyway. */
66880 			goto thread_state_error;
66881 		}
66882 	} else {
66883 		DUK_ASSERT(thr->heap->curr_thread == NULL ||
66884 		           thr->heap->curr_thread->state == DUK_HTHREAD_STATE_RUNNING);
66885 		if (DUK_UNLIKELY(thr->state != DUK_HTHREAD_STATE_INACTIVE)) {
66886 			goto thread_state_error;
66887 		}
66888 		DUK_HEAP_SWITCH_THREAD(thr->heap, thr);
66889 		thr->state = DUK_HTHREAD_STATE_RUNNING;
66890 
66891 		/* Multiple threads may be simultaneously in the RUNNING
66892 		 * state, but not in the same "resume chain".
66893 		 */
66894 	}
66895 	DUK_ASSERT(thr->heap->curr_thread == thr);
66896 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
66897 	return;
66898 
66899  thread_state_error:
66900 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "invalid thread state (%ld)", (long) thr->state);
66901 	DUK_WO_NORETURN(return;);
66902 }
66903 
66904 /*
66905  *  Main unprotected call handler, handles:
66906  *
66907  *    - All combinations of native/ECMAScript caller and native/ECMAScript
66908  *      target.
66909  *
66910  *    - Optimized ECMAScript-to-ECMAScript call where call handling only
66911  *      sets up a new duk_activation but reuses an existing bytecode executor
66912  *      (the caller) without native recursion.
66913  *
66914  *    - Tailcalls, where an activation is reused without increasing call
66915  *      stack (duk_activation) depth.
66916  *
66917  *    - Setup for an initial Duktape.Thread.resume().
66918  *
66919  *  The call handler doesn't provide any protection guarantees, protected calls
66920  *  must be implemented e.g. by wrapping the call in a duk_safe_call().
66921  *  Call setup may fail at any stage, even when the new activation is in
66922  *  place; the only guarantee is that the state is consistent for unwinding.
66923  */
66924 
66925 DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
66926                                          duk_idx_t idx_func,
66927                                          duk_small_uint_t call_flags) {
66928 #if defined(DUK_USE_ASSERTIONS)
66929 	duk_activation *entry_act;
66930 	duk_size_t entry_callstack_top;
66931 #endif
66932 	duk_size_t entry_valstack_bottom_byteoff;
66933 	duk_size_t entry_valstack_end_byteoff;
66934 	duk_int_t entry_call_recursion_depth;
66935 	duk_hthread *entry_curr_thread;
66936 	duk_uint_fast8_t entry_thread_state;
66937 	duk_instr_t **entry_ptr_curr_pc;
66938 	duk_idx_t idx_args;
66939 	duk_idx_t nargs;            /* # argument registers target function wants (< 0 => "as is") */
66940 	duk_idx_t nregs;            /* # total registers target function wants on entry (< 0 => "as is") */
66941 	duk_size_t vs_min_bytes;    /* minimum value stack size (bytes) for handling call */
66942 	duk_hobject *func;          /* 'func' on stack (borrowed reference) */
66943 	duk_activation *act;
66944 	duk_ret_t rc;
66945 	duk_small_uint_t use_tailcall;
66946 
66947 	DUK_ASSERT(thr != NULL);
66948 	DUK_ASSERT(thr->heap != NULL);
66949 	/* Asserts for heap->curr_thread omitted: it may be NULL, 'thr', or
66950 	 * any other thread (e.g. when heap thread is used to run finalizers).
66951 	 */
66952 	DUK_CTX_ASSERT_VALID(thr);
66953 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
66954 	DUK_ASSERT(idx_func >= 0);
66955 
66956 	DUK_STATS_INC(thr->heap, stats_call_all);
66957 
66958 	/* If a tail call:
66959 	 *   - an ECMAScript activation must be on top of the callstack
66960 	 *   - there cannot be any catch stack entries that would catch
66961 	 *     a return
66962 	 */
66963 #if defined(DUK_USE_ASSERTIONS)
66964 	if (call_flags & DUK_CALL_FLAG_TAILCALL) {
66965 		duk_activation *tmp_act;
66966 		duk_catcher *tmp_cat;
66967 
66968 		DUK_ASSERT(thr->callstack_top >= 1);
66969 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
66970 		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
66971 
66972 		/* No entry in the catch stack which would actually catch a
66973 		 * throw can refer to the callstack entry being reused.
66974 		 * There *can* be catch stack entries referring to the current
66975 		 * callstack entry as long as they don't catch (e.g. label sites).
66976 		 */
66977 
66978 		tmp_act = thr->callstack_curr;
66979 		for (tmp_cat = tmp_act->cat; tmp_cat != NULL; tmp_cat = tmp_cat->parent) {
66980 			DUK_ASSERT(DUK_CAT_GET_TYPE(tmp_cat) == DUK_CAT_TYPE_LABEL); /* a non-catching entry */
66981 		}
66982 	}
66983 #endif  /* DUK_USE_ASSERTIONS */
66984 
66985 	/*
66986 	 *  Store entry state.
66987 	 */
66988 
66989 #if defined(DUK_USE_ASSERTIONS)
66990 	entry_act = thr->callstack_curr;
66991 	entry_callstack_top = thr->callstack_top;
66992 #endif
66993 	entry_valstack_bottom_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
66994 	entry_valstack_end_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
66995 	entry_call_recursion_depth = thr->heap->call_recursion_depth;
66996 	entry_curr_thread = thr->heap->curr_thread;  /* may be NULL if first call */
66997 	entry_thread_state = thr->state;
66998 	entry_ptr_curr_pc = thr->ptr_curr_pc;  /* may be NULL */
66999 
67000 	/* If thr->ptr_curr_pc is set, sync curr_pc to act->pc.  Then NULL
67001 	 * thr->ptr_curr_pc so that it's not accidentally used with an incorrect
67002 	 * activation when side effects occur.
67003 	 */
67004 	duk_hthread_sync_and_null_currpc(thr);
67005 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
67006 
67007 	DUK_DD(DUK_DDPRINT("duk__handle_call_raw: thr=%p, idx_func=%ld, "
67008 	                   "call_flags=0x%08lx (constructor=%ld), "
67009 	                   "valstack_top=%ld, idx_func=%ld, idx_args=%ld, rec_depth=%ld/%ld, "
67010 	                   "entry_valstack_bottom_byteoff=%ld, entry_valstack_end_byteoff=%ld, "
67011 	                   "entry_call_recursion_depth=%ld, "
67012 	                   "entry_curr_thread=%p, entry_thread_state=%ld",
67013 	                   (void *) thr,
67014 	                   (long) idx_func,
67015 	                   (unsigned long) call_flags,
67016 	                   (long) ((call_flags & DUK_CALL_FLAG_CONSTRUCT) != 0 ? 1 : 0),
67017 	                   (long) duk_get_top(thr),
67018 	                   (long) idx_func,
67019 	                   (long) (idx_func + 2),
67020 	                   (long) thr->heap->call_recursion_depth,
67021 	                   (long) thr->heap->call_recursion_limit,
67022 	                   (long) entry_valstack_bottom_byteoff,
67023 	                   (long) entry_valstack_end_byteoff,
67024 	                   (long) entry_call_recursion_depth,
67025 	                   (void *) entry_curr_thread,
67026 	                   (long) entry_thread_state));
67027 
67028 	/*
67029 	 *  Thread state check and book-keeping.
67030 	 */
67031 
67032 	duk__call_thread_state_update(thr);
67033 
67034 	/*
67035 	 *  Increase call recursion depth as early as possible so that if we
67036 	 *  enter a recursive call for any reason there's a backstop to native
67037 	 *  recursion.  This can happen e.g. for almost any property read
67038 	 *  because it may cause a getter call or a Proxy trap (GC and finalizers
67039 	 *  are not an issue because they are not recursive).  If we end up
67040 	 *  doing an Ecma-to-Ecma call, revert the increase.  (See GH-2032.)
67041 	 *
67042 	 *  For similar reasons, ensure there is a known value stack spare
67043 	 *  even before we actually prepare the value stack for the target
67044 	 *  function.  If this isn't done, early recursion may consume the
67045 	 *  value stack space.
67046 	 *
67047 	 *  XXX: Should bump yield preventcount early, for the same reason.
67048 	 */
67049 
67050 	duk__call_c_recursion_limit_check(thr);
67051 	thr->heap->call_recursion_depth++;
67052 	duk_require_stack(thr, DUK__CALL_HANDLING_REQUIRE_STACK);
67053 
67054 	/*
67055 	 *  Resolve final target function; handle bound functions and special
67056 	 *  functions like .call() and .apply().  Also figure out the effective
67057 	 *  'this' binding, which replaces the current value at idx_func + 1.
67058 	 */
67059 
67060 	if (DUK_LIKELY(duk__resolve_target_fastpath_check(thr, idx_func, &func, call_flags) != 0U)) {
67061 		DUK_DDD(DUK_DDDPRINT("fast path target resolve"));
67062 	} else {
67063 		DUK_DDD(DUK_DDDPRINT("slow path target resolve"));
67064 		func = duk__resolve_target_func_and_this_binding(thr, idx_func, &call_flags);
67065 	}
67066 	DUK_ASSERT(duk_get_top(thr) - idx_func >= 2);  /* at least func and this present */
67067 
67068 	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
67069 	DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) ||
67070 	                            DUK_HOBJECT_IS_NATFUNC(func)));
67071 
67072 	/* [ ... func this arg1 ... argN ] */
67073 
67074 	/*
67075 	 *  Setup a preliminary activation and figure out nargs/nregs and
67076 	 *  value stack minimum size.
67077 	 *
67078 	 *  Don't touch valstack_bottom or valstack_top yet so that Duktape API
67079 	 *  calls work normally.
67080 	 *
67081 	 *  Because 'act' is not zeroed, all fields must be filled in.
67082 	 */
67083 
67084 	/* Should not be necessary, but initialize to silence warnings. */
67085 	act = NULL;
67086 	nargs = 0;
67087 	nregs = 0;
67088 	vs_min_bytes = 0;
67089 
67090 #if defined(DUK_USE_TAILCALL)
67091 	use_tailcall = (call_flags & DUK_CALL_FLAG_TAILCALL);
67092 	if (use_tailcall) {
67093 		use_tailcall = duk__call_setup_act_attempt_tailcall(thr,
67094 		                                                    call_flags,
67095 		                                                    idx_func,
67096 		                                                    func,
67097 		                                                    entry_valstack_bottom_byteoff,
67098 		                                                    entry_valstack_end_byteoff,
67099 		                                                    &nargs,
67100 		                                                    &nregs,
67101 		                                                    &vs_min_bytes,
67102 		                                                    &act);
67103 	}
67104 #else
67105 	DUK_ASSERT((call_flags & DUK_CALL_FLAG_TAILCALL) == 0);  /* compiler ensures this */
67106 	use_tailcall = 0;
67107 #endif
67108 
67109 	if (use_tailcall) {
67110 		idx_args = 0;
67111 		DUK_STATS_INC(thr->heap, stats_call_tailcall);
67112 	} else {
67113 		duk__call_setup_act_not_tailcall(thr,
67114 		                                 call_flags,
67115 		                                 idx_func,
67116 		                                 func,
67117 		                                 entry_valstack_bottom_byteoff,
67118 		                                 entry_valstack_end_byteoff,
67119 		                                 &nargs,
67120 		                                 &nregs,
67121 		                                 &vs_min_bytes,
67122 		                                 &act);
67123 		idx_args = idx_func + 2;
67124 	}
67125 	/* After this point idx_func is no longer valid for tailcalls. */
67126 
67127 	DUK_ASSERT(act != NULL);
67128 
67129 	/* [ ... func this arg1 ... argN ] */
67130 
67131 	/*
67132 	 *  Environment record creation and 'arguments' object creation.
67133 	 *  Named function expression name binding is handled by the
67134 	 *  compiler; the compiled function's parent env will contain
67135 	 *  the (immutable) binding already.
67136 	 *
67137 	 *  This handling is now identical for C and ECMAScript functions.
67138 	 *  C functions always have the 'NEWENV' flag set, so their
67139 	 *  environment record initialization is delayed (which is good).
67140 	 *
67141 	 *  Delayed creation (on demand) is handled in duk_js_var.c.
67142 	 */
67143 
67144 	duk__call_env_setup(thr, func, act, idx_args);
67145 
67146 	/* [ ... func this arg1 ... argN ] */
67147 
67148 	/*
67149 	 *  Setup value stack: clamp to 'nargs', fill up to 'nregs',
67150 	 *  ensure value stack size matches target requirements, and
67151 	 *  switch value stack bottom.  Valstack top is kept.
67152 	 *
67153 	 *  Value stack can only grow here.
67154 	 */
67155 
67156 	duk_valstack_grow_check_throw(thr, vs_min_bytes);
67157 	act->reserve_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
67158 
67159 	if (use_tailcall) {
67160 		DUK_ASSERT(nregs >= 0);
67161 		DUK_ASSERT(nregs >= nargs);
67162 		duk_set_top_and_wipe(thr, nregs, nargs);
67163 	} else {
67164 		if (nregs >= 0) {
67165 			DUK_ASSERT(nregs >= nargs);
67166 			duk_set_top_and_wipe(thr, idx_func + 2 + nregs, idx_func + 2 + nargs);
67167 		} else {
67168 			;
67169 		}
67170 		thr->valstack_bottom = thr->valstack_bottom + idx_func + 2;
67171 	}
67172 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
67173 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
67174 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
67175 
67176 	/*
67177 	 *  Make the actual call.  For Ecma-to-Ecma calls detect that
67178 	 *  setup is complete, then return with a status code that allows
67179 	 *  the caller to reuse the running executor.
67180 	 */
67181 
67182 	if (func != NULL && DUK_HOBJECT_IS_COMPFUNC(func)) {
67183 		/*
67184 		 *  ECMAScript call.
67185 		 */
67186 
67187 		DUK_ASSERT(func != NULL);
67188 		DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
67189 		act->curr_pc = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) func);
67190 
67191 		if (call_flags & DUK_CALL_FLAG_ALLOW_ECMATOECMA) {
67192 			DUK_DD(DUK_DDPRINT("avoid native call, use existing executor"));
67193 			DUK_STATS_INC(thr->heap, stats_call_ecmatoecma);
67194 			DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
67195 			DUK_REFZERO_CHECK_FAST(thr);
67196 			DUK_ASSERT(thr->ptr_curr_pc == NULL);
67197 			thr->heap->call_recursion_depth--;  /* No recursion increase for this case. */
67198 			return 1;  /* 1=reuse executor */
67199 		}
67200 		DUK_ASSERT(use_tailcall == 0);
67201 
67202 		/* duk_hthread_activation_unwind_norz() will decrease this on unwind */
67203 		DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
67204 		act->flags |= DUK_ACT_FLAG_PREVENT_YIELD;
67205 		thr->callstack_preventcount++;
67206 
67207 		/* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
67208 
67209 		/*
67210 		 *  Bytecode executor call.
67211 		 *
67212 		 *  Execute bytecode, handling any recursive function calls and
67213 		 *  thread resumptions.  Returns when execution would return from
67214 		 *  the entry level activation.  When the executor returns, a
67215 		 *  single return value is left on the stack top.
67216 		 *
67217 		 *  The only possible longjmp() is an error (DUK_LJ_TYPE_THROW),
67218 		 *  other types are handled internally by the executor.
67219 		 */
67220 
67221 		/* thr->ptr_curr_pc is set by bytecode executor early on entry */
67222 		DUK_ASSERT(thr->ptr_curr_pc == NULL);
67223 		DUK_DDD(DUK_DDDPRINT("entering bytecode execution"));
67224 		duk_js_execute_bytecode(thr);
67225 		DUK_DDD(DUK_DDDPRINT("returned from bytecode execution"));
67226 	} else {
67227 		/*
67228 		 *  Native call.
67229 		 */
67230 
67231 		DUK_ASSERT(func == NULL || ((duk_hnatfunc *) func)->func != NULL);
67232 		DUK_ASSERT(use_tailcall == 0);
67233 
67234 		/* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
67235 
67236 		/* duk_hthread_activation_unwind_norz() will decrease this on unwind */
67237 		DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
67238 		act->flags |= DUK_ACT_FLAG_PREVENT_YIELD;
67239 		thr->callstack_preventcount++;
67240 
67241 		/* For native calls must be NULL so we don't sync back */
67242 		DUK_ASSERT(thr->ptr_curr_pc == NULL);
67243 
67244 		/* XXX: native funcptr could come out of call setup. */
67245 		if (func) {
67246 			rc = ((duk_hnatfunc *) func)->func(thr);
67247 		} else {
67248 			duk_tval *tv_func;
67249 			duk_c_function funcptr;
67250 
67251 			tv_func = &act->tv_func;
67252 			DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func));
67253 			funcptr = DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv_func);
67254 			rc = funcptr(thr);
67255 		}
67256 
67257 		/* Automatic error throwing, retval check. */
67258 
67259 		if (rc == 0) {
67260 			DUK_ASSERT(thr->valstack < thr->valstack_end);
67261 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
67262 			thr->valstack_top++;
67263 		} else if (rc == 1) {
67264 			;
67265 		} else if (rc < 0) {
67266 			duk_error_throw_from_negative_rc(thr, rc);
67267 			DUK_WO_NORETURN(return 0;);
67268 		} else {
67269 			DUK_ERROR_TYPE(thr, DUK_STR_INVALID_CFUNC_RC);
67270 			DUK_WO_NORETURN(return 0;);
67271 		}
67272 	}
67273 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
67274 	DUK_ASSERT(use_tailcall == 0);
67275 
67276 	/*
67277 	 *  Constructor call post processing.
67278 	 */
67279 
67280 #if defined(DUK_USE_ES6_PROXY)
67281 	if (call_flags & (DUK_CALL_FLAG_CONSTRUCT | DUK_CALL_FLAG_CONSTRUCT_PROXY)) {
67282 		duk_call_construct_postprocess(thr, call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY);
67283 	}
67284 #else
67285 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
67286 		duk_call_construct_postprocess(thr, 0);
67287 	}
67288 #endif
67289 
67290 	/*
67291 	 *  Unwind, restore valstack bottom and other book-keeping.
67292 	 */
67293 
67294 	DUK_ASSERT(thr->callstack_curr != NULL);
67295 	DUK_ASSERT(thr->callstack_curr->parent == entry_act);
67296 	DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
67297 	duk_hthread_activation_unwind_norz(thr);
67298 	DUK_ASSERT(thr->callstack_curr == entry_act);
67299 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
67300 
67301 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_bottom_byteoff);
67302 	/* keep current valstack_top */
67303 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
67304 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
67305 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
67306 	DUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= idx_func + 1);
67307 
67308 	/* Return value handling. */
67309 
67310 	/* [ ... func this (crud) retval ] */
67311 
67312 	{
67313 		duk_tval *tv_ret;
67314 		duk_tval *tv_funret;
67315 
67316 		tv_ret = thr->valstack_bottom + idx_func;
67317 		tv_funret = thr->valstack_top - 1;
67318 #if defined(DUK_USE_FASTINT)
67319 		/* Explicit check for fastint downgrade. */
67320 		DUK_TVAL_CHKFAST_INPLACE_FAST(tv_funret);
67321 #endif
67322 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret);  /* side effects */
67323 	}
67324 
67325 	duk_set_top_unsafe(thr, idx_func + 1);
67326 
67327 	/* [ ... retval ] */
67328 
67329 	/* Restore caller's value stack reserve (cannot fail). */
67330 	DUK_ASSERT((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff >= (duk_uint8_t *) thr->valstack_top);
67331 	DUK_ASSERT((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff <= (duk_uint8_t *) thr->valstack_alloc_end);
67332 	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff);
67333 
67334 	/* XXX: Trial value stack shrink would be OK here, but we'd need
67335 	 * to prevent side effects of the potential realloc.
67336 	 */
67337 
67338 	/* Restore entry thread executor curr_pc stack frame pointer. */
67339 	thr->ptr_curr_pc = entry_ptr_curr_pc;
67340 
67341 	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
67342 	thr->state = (duk_uint8_t) entry_thread_state;
67343 
67344 	/* Disabled assert: triggered with some torture tests. */
67345 #if 0
67346 	DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) ||  /* first call */
67347 	           (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) ||  /* other call */
67348 	           (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr));     /* current thread */
67349 #endif
67350 
67351 	thr->heap->call_recursion_depth = entry_call_recursion_depth;
67352 
67353 	/* If the debugger is active we need to force an interrupt so that
67354 	 * debugger breakpoints are rechecked.  This is important for function
67355 	 * calls caused by side effects (e.g. when doing a DUK_OP_GETPROP), see
67356 	 * GH-303.  Only needed for success path, error path always causes a
67357 	 * breakpoint recheck in the executor.  It would be enough to set this
67358 	 * only when returning to an ECMAScript activation, but setting the flag
67359 	 * on every return should have no ill effect.
67360 	 */
67361 #if defined(DUK_USE_DEBUGGER_SUPPORT)
67362 	if (duk_debug_is_attached(thr->heap)) {
67363 		DUK_DD(DUK_DDPRINT("returning with debugger enabled, force interrupt"));
67364 		DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
67365 		thr->interrupt_init -= thr->interrupt_counter;
67366 		thr->interrupt_counter = 0;
67367 		thr->heap->dbg_force_restart = 1;
67368 	}
67369 #endif
67370 
67371 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
67372 	duk__interrupt_fixup(thr, entry_curr_thread);
67373 #endif
67374 
67375 	/* Restored by success path. */
67376 	DUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);
67377 	DUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);
67378 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
67379 
67380 	DUK_REFZERO_CHECK_FAST(thr);
67381 
67382 	return 0;  /* 0=call handled inline */
67383 }
67384 
67385 DUK_INTERNAL duk_int_t duk_handle_call_unprotected_nargs(duk_hthread *thr,
67386                                                          duk_idx_t nargs,
67387                                                          duk_small_uint_t call_flags) {
67388 	duk_idx_t idx_func;
67389 	DUK_ASSERT(duk_get_top(thr) >= nargs + 2);
67390 	idx_func = duk_get_top(thr) - (nargs + 2);
67391 	DUK_ASSERT(idx_func >= 0);
67392 	return duk_handle_call_unprotected(thr, idx_func, call_flags);
67393 }
67394 
67395 DUK_INTERNAL duk_int_t duk_handle_call_unprotected(duk_hthread *thr,
67396                                                    duk_idx_t idx_func,
67397                                                    duk_small_uint_t call_flags) {
67398 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
67399 	DUK_ASSERT(idx_func >= 0);
67400 	return duk__handle_call_raw(thr, idx_func, call_flags);
67401 }
67402 
67403 /*
67404  *  duk_handle_safe_call(): make a "C protected call" within the
67405  *  current activation.
67406  *
67407  *  The allowed thread states for making a call are the same as for
67408  *  duk_handle_call_protected().
67409  *
67410  *  Even though this call is protected, errors are thrown for insane arguments
67411  *  and may result in a fatal error unless there's another protected call which
67412  *  catches such errors.
67413  *
67414  *  The error handling path should be error free, even for out-of-memory
67415  *  errors, to ensure safe sandboxing.  (As of Duktape 2.2.0 this is not
67416  *  yet the case for environment closing which may run out of memory, see
67417  *  XXX notes below.)
67418  */
67419 
67420 DUK_LOCAL void duk__handle_safe_call_inner(duk_hthread *thr,
67421                                            duk_safe_call_function func,
67422                                            void *udata,
67423 #if defined(DUK_USE_ASSERTIONS)
67424                                            duk_size_t entry_valstack_bottom_byteoff,
67425                                            duk_size_t entry_callstack_top,
67426 #endif
67427                                            duk_hthread *entry_curr_thread,
67428                                            duk_uint_fast8_t entry_thread_state,
67429                                            duk_idx_t idx_retbase,
67430                                            duk_idx_t num_stack_rets) {
67431 	duk_ret_t rc;
67432 
67433 	DUK_ASSERT(thr != NULL);
67434 	DUK_CTX_ASSERT_VALID(thr);
67435 
67436 	/*
67437 	 *  Thread state check and book-keeping.
67438 	 */
67439 
67440 	duk__call_thread_state_update(thr);
67441 
67442 	/*
67443 	 *  Recursion limit check.
67444 	 */
67445 
67446 	duk__call_c_recursion_limit_check(thr);
67447 	thr->heap->call_recursion_depth++;
67448 
67449 	/*
67450 	 *  Make the C call.
67451 	 */
67452 
67453 	rc = func(thr, udata);
67454 
67455 	DUK_DDD(DUK_DDDPRINT("safe_call, func rc=%ld", (long) rc));
67456 
67457 	/*
67458 	 *  Valstack manipulation for results.
67459 	 */
67460 
67461 	/* we're running inside the caller's activation, so no change in call/catch stack or valstack bottom */
67462 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
67463 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
67464 	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) == entry_valstack_bottom_byteoff);
67465 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
67466 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
67467 
67468 	if (DUK_UNLIKELY(rc < 0)) {
67469 		duk_error_throw_from_negative_rc(thr, rc);
67470 		DUK_WO_NORETURN(return;);
67471 	}
67472 	DUK_ASSERT(rc >= 0);
67473 
67474 	duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, rc);  /* throws for insane rc */
67475 
67476 	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
67477 	thr->state = (duk_uint8_t) entry_thread_state;
67478 }
67479 
67480 DUK_LOCAL void duk__handle_safe_call_error(duk_hthread *thr,
67481                                            duk_activation *entry_act,
67482 #if defined(DUK_USE_ASSERTIONS)
67483                                            duk_size_t entry_callstack_top,
67484 #endif
67485                                            duk_hthread *entry_curr_thread,
67486                                            duk_uint_fast8_t entry_thread_state,
67487                                            duk_idx_t idx_retbase,
67488                                            duk_idx_t num_stack_rets,
67489                                            duk_size_t entry_valstack_bottom_byteoff,
67490                                            duk_jmpbuf *old_jmpbuf_ptr) {
67491 	DUK_ASSERT(thr != NULL);
67492 	DUK_CTX_ASSERT_VALID(thr);
67493 
67494 	/*
67495 	 *  Error during call.  The error value is at heap->lj.value1.
67496 	 *
67497 	 *  The very first thing we do is restore the previous setjmp catcher.
67498 	 *  This means that any error in error handling will propagate outwards
67499 	 *  instead of causing a setjmp() re-entry above.
67500 	 */
67501 
67502 	DUK_DDD(DUK_DDDPRINT("error caught during protected duk_handle_safe_call()"));
67503 
67504 	/* Other longjmp types are handled by executor before propagating
67505 	 * the error here.
67506 	 */
67507 	DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);
67508 	DUK_ASSERT_LJSTATE_SET(thr->heap);
67509 
67510 	/* Either pointer may be NULL (at entry), so don't assert. */
67511 	thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
67512 
67513 	/* XXX: callstack unwind may now throw an error when closing
67514 	 * scopes; this is a sandboxing issue, described in:
67515 	 * https://github.com/svaarala/duktape/issues/476
67516 	 */
67517 	/* XXX: "unwind to" primitive? */
67518 
67519 	DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
67520 	while (thr->callstack_curr != entry_act) {
67521 		DUK_ASSERT(thr->callstack_curr != NULL);
67522 		duk_hthread_activation_unwind_norz(thr);
67523 	}
67524 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
67525 
67526 	/* Switch active thread before any side effects to avoid a
67527 	 * dangling curr_thread pointer.
67528 	 */
67529 	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
67530 	thr->state = (duk_uint8_t) entry_thread_state;
67531 
67532 	DUK_ASSERT(thr->heap->curr_thread == entry_curr_thread);
67533 	DUK_ASSERT(thr->state == entry_thread_state);
67534 
67535 	/* Restore valstack bottom. */
67536 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_bottom_byteoff);
67537 
67538 	/* [ ... | (crud) ] */
67539 
67540 	/* XXX: ensure space in valstack (now relies on internal reserve)? */
67541 	duk_push_tval(thr, &thr->heap->lj.value1);
67542 
67543 	/* [ ... | (crud) errobj ] */
67544 
67545 	DUK_ASSERT(duk_get_top(thr) >= 1);  /* at least errobj must be on stack */
67546 
67547 	duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, 1);  /* 1 = num actual 'return values' */
67548 
67549 	/* [ ... | ] or [ ... | errobj (M * undefined)] where M = num_stack_rets - 1 */
67550 
67551 	/* Reset longjmp state. */
67552 	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
67553 	thr->heap->lj.iserror = 0;
67554 	DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, &thr->heap->lj.value1);
67555 	DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, &thr->heap->lj.value2);
67556 
67557 	/* Error handling complete, remove side effect protections.  Caller
67558 	 * will process pending finalizers.
67559 	 */
67560 #if defined(DUK_USE_ASSERTIONS)
67561 	DUK_ASSERT(thr->heap->error_not_allowed == 1);
67562 	thr->heap->error_not_allowed = 0;
67563 #endif
67564 	DUK_ASSERT(thr->heap->pf_prevent_count > 0);
67565 	thr->heap->pf_prevent_count--;
67566 	DUK_DD(DUK_DDPRINT("safe call error handled, pf_prevent_count updated to %ld", (long) thr->heap->pf_prevent_count));
67567 
67568 	/* thr->ptr_curr_pc is restored by
67569 	 * duk__handle_safe_call_shared_unwind() which is also used for
67570 	 * success path.
67571 	 */
67572 }
67573 
67574 DUK_LOCAL void duk__handle_safe_call_shared_unwind(duk_hthread *thr,
67575                                                    duk_idx_t idx_retbase,
67576                                                    duk_idx_t num_stack_rets,
67577 #if defined(DUK_USE_ASSERTIONS)
67578                                                    duk_size_t entry_callstack_top,
67579 #endif
67580                                                    duk_int_t entry_call_recursion_depth,
67581                                                    duk_hthread *entry_curr_thread,
67582                                                    duk_instr_t **entry_ptr_curr_pc) {
67583 	DUK_ASSERT(thr != NULL);
67584 	DUK_CTX_ASSERT_VALID(thr);
67585 	DUK_UNREF(idx_retbase);
67586 	DUK_UNREF(num_stack_rets);
67587 	DUK_UNREF(entry_curr_thread);
67588 
67589 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
67590 
67591 	/* Restore entry thread executor curr_pc stack frame pointer.
67592 	 * XXX: would be enough to do in error path only, should nest
67593 	 * cleanly in success path.
67594 	 */
67595 	thr->ptr_curr_pc = entry_ptr_curr_pc;
67596 
67597 	thr->heap->call_recursion_depth = entry_call_recursion_depth;
67598 
67599 	/* stack discipline consistency check */
67600 	DUK_ASSERT(duk_get_top(thr) == idx_retbase + num_stack_rets);
67601 
67602 	/* A debugger forced interrupt check is not needed here, as
67603 	 * problematic safe calls are not caused by side effects.
67604 	 */
67605 
67606 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
67607 	duk__interrupt_fixup(thr, entry_curr_thread);
67608 #endif
67609 }
67610 
67611 DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr,
67612                                             duk_safe_call_function func,
67613                                             void *udata,
67614                                             duk_idx_t num_stack_args,
67615                                             duk_idx_t num_stack_rets) {
67616 	duk_activation *entry_act;
67617 	duk_size_t entry_valstack_bottom_byteoff;
67618 #if defined(DUK_USE_ASSERTIONS)
67619 	duk_size_t entry_valstack_end_byteoff;
67620 	duk_size_t entry_callstack_top;
67621 	duk_size_t entry_callstack_preventcount;
67622 #endif
67623 	duk_int_t entry_call_recursion_depth;
67624 	duk_hthread *entry_curr_thread;
67625 	duk_uint_fast8_t entry_thread_state;
67626 	duk_instr_t **entry_ptr_curr_pc;
67627 	duk_jmpbuf *old_jmpbuf_ptr = NULL;
67628 	duk_jmpbuf our_jmpbuf;
67629 	duk_idx_t idx_retbase;
67630 	duk_int_t retval;
67631 
67632 	DUK_ASSERT(thr != NULL);
67633 	DUK_ASSERT(duk_get_top(thr) >= num_stack_args);  /* Caller ensures. */
67634 
67635 	DUK_STATS_INC(thr->heap, stats_safecall_all);
67636 
67637 	/* Value stack reserve handling: safe call assumes caller has reserved
67638 	 * space for nrets (assuming optimal unwind processing).  Value stack
67639 	 * reserve is not stored/restored as for normal calls because a safe
67640 	 * call conceptually happens in the same activation.
67641 	 */
67642 
67643 	/* Careful with indices like '-x'; if 'x' is zero, it refers to bottom */
67644 	entry_act = thr->callstack_curr;
67645 	entry_valstack_bottom_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
67646 #if defined(DUK_USE_ASSERTIONS)
67647 	entry_valstack_end_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
67648 	entry_callstack_top = thr->callstack_top;
67649 	entry_callstack_preventcount = thr->callstack_preventcount;
67650 #endif
67651 	entry_call_recursion_depth = thr->heap->call_recursion_depth;
67652 	entry_curr_thread = thr->heap->curr_thread;  /* may be NULL if first call */
67653 	entry_thread_state = thr->state;
67654 	entry_ptr_curr_pc = thr->ptr_curr_pc;  /* may be NULL */
67655 	idx_retbase = duk_get_top(thr) - num_stack_args;  /* not a valid stack index if num_stack_args == 0 */
67656 	DUK_ASSERT(idx_retbase >= 0);
67657 
67658 	DUK_ASSERT((duk_idx_t) (thr->valstack_top - thr->valstack_bottom) >= num_stack_args);  /* Caller ensures. */
67659 	DUK_ASSERT((duk_idx_t) (thr->valstack_end - (thr->valstack_bottom + idx_retbase)) >= num_stack_rets);  /* Caller ensures. */
67660 
67661 	/* Cannot portably debug print a function pointer, hence 'func' not printed! */
67662 	DUK_DD(DUK_DDPRINT("duk_handle_safe_call: thr=%p, num_stack_args=%ld, num_stack_rets=%ld, "
67663 	                   "valstack_top=%ld, idx_retbase=%ld, rec_depth=%ld/%ld, "
67664 	                   "entry_act=%p, entry_valstack_bottom_byteoff=%ld, entry_call_recursion_depth=%ld, "
67665 	                   "entry_curr_thread=%p, entry_thread_state=%ld",
67666 	                   (void *) thr,
67667 	                   (long) num_stack_args,
67668 	                   (long) num_stack_rets,
67669 	                   (long) duk_get_top(thr),
67670 	                   (long) idx_retbase,
67671 	                   (long) thr->heap->call_recursion_depth,
67672 	                   (long) thr->heap->call_recursion_limit,
67673 	                   (void *) entry_act,
67674 	                   (long) entry_valstack_bottom_byteoff,
67675 	                   (long) entry_call_recursion_depth,
67676 	                   (void *) entry_curr_thread,
67677 	                   (long) entry_thread_state));
67678 
67679 	/* Setjmp catchpoint setup. */
67680 	old_jmpbuf_ptr = thr->heap->lj.jmpbuf_ptr;
67681 	thr->heap->lj.jmpbuf_ptr = &our_jmpbuf;
67682 
67683 	/* Prevent yields for the duration of the safe call.  This only
67684 	 * matters if the executor makes safe calls to functions that
67685 	 * yield, this doesn't currently happen.
67686 	 */
67687 	thr->callstack_preventcount++;
67688 
67689 #if defined(DUK_USE_CPP_EXCEPTIONS)
67690 	try {
67691 #else
67692 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == &our_jmpbuf);
67693 	if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
67694 		/* Success path. */
67695 #endif
67696 		DUK_DDD(DUK_DDDPRINT("safe_call setjmp catchpoint setup complete"));
67697 
67698 		duk__handle_safe_call_inner(thr,
67699 		                            func,
67700 		                            udata,
67701 #if defined(DUK_USE_ASSERTIONS)
67702 		                            entry_valstack_bottom_byteoff,
67703 		                            entry_callstack_top,
67704 #endif
67705 		                            entry_curr_thread,
67706 		                            entry_thread_state,
67707 		                            idx_retbase,
67708 		                            num_stack_rets);
67709 
67710 		DUK_STATS_INC(thr->heap, stats_safecall_nothrow);
67711 
67712 		/* Either pointer may be NULL (at entry), so don't assert */
67713 		thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
67714 
67715 		/* If calls happen inside the safe call, these are restored by
67716 		 * whatever calls are made.  Reserve cannot decrease.
67717 		 */
67718 		DUK_ASSERT(thr->callstack_curr == entry_act);
67719 		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
67720 
67721 		retval = DUK_EXEC_SUCCESS;
67722 #if defined(DUK_USE_CPP_EXCEPTIONS)
67723 	} catch (duk_internal_exception &exc) {
67724 		DUK_UNREF(exc);
67725 #else
67726 	} else {
67727 		/* Error path. */
67728 #endif
67729 		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
67730 
67731 		DUK_STATS_INC(thr->heap, stats_safecall_throw);
67732 
67733 		duk__handle_safe_call_error(thr,
67734 		                            entry_act,
67735 #if defined(DUK_USE_ASSERTIONS)
67736 		                            entry_callstack_top,
67737 #endif
67738 		                            entry_curr_thread,
67739 		                            entry_thread_state,
67740 		                            idx_retbase,
67741 		                            num_stack_rets,
67742 		                            entry_valstack_bottom_byteoff,
67743 		                            old_jmpbuf_ptr);
67744 
67745 		retval = DUK_EXEC_ERROR;
67746 	}
67747 #if defined(DUK_USE_CPP_EXCEPTIONS)
67748 	catch (duk_fatal_exception &exc) {
67749 		DUK_D(DUK_DPRINT("rethrow duk_fatal_exception"));
67750 		DUK_UNREF(exc);
67751 		throw;
67752 	} catch (std::exception &exc) {
67753 		const char *what = exc.what();
67754 		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
67755 		DUK_STATS_INC(thr->heap, stats_safecall_throw);
67756 		if (!what) {
67757 			what = "unknown";
67758 		}
67759 		DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
67760 		try {
67761 			DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
67762 			DUK_WO_NORETURN(return 0;);
67763 		} catch (duk_internal_exception exc) {
67764 			DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
67765 			DUK_UNREF(exc);
67766 			duk__handle_safe_call_error(thr,
67767 			                            entry_act,
67768 #if defined(DUK_USE_ASSERTIONS)
67769 			                            entry_callstack_top,
67770 #endif
67771 			                            entry_curr_thread,
67772 			                            entry_thread_state,
67773 			                            idx_retbase,
67774 			                            num_stack_rets,
67775 			                            entry_valstack_bottom_byteoff,
67776 			                            old_jmpbuf_ptr);
67777 			retval = DUK_EXEC_ERROR;
67778 		}
67779 	} catch (...) {
67780 		DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
67781 		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
67782 		DUK_STATS_INC(thr->heap, stats_safecall_throw);
67783 		try {
67784 			DUK_ERROR_TYPE(thr, "caught invalid c++ exception (perhaps thrown by user code)");
67785 			DUK_WO_NORETURN(return 0;);
67786 		} catch (duk_internal_exception exc) {
67787 			DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
67788 			DUK_UNREF(exc);
67789 			duk__handle_safe_call_error(thr,
67790 			                            entry_act,
67791 #if defined(DUK_USE_ASSERTIONS)
67792 			                            entry_callstack_top,
67793 #endif
67794 			                            entry_curr_thread,
67795 			                            entry_thread_state,
67796 			                            idx_retbase,
67797 			                            num_stack_rets,
67798 			                            entry_valstack_bottom_byteoff,
67799 			                            old_jmpbuf_ptr);
67800 			retval = DUK_EXEC_ERROR;
67801 		}
67802 	}
67803 #endif
67804 
67805 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == old_jmpbuf_ptr);  /* success/error path both do this */
67806 
67807 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
67808 
67809 	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
67810 	duk__handle_safe_call_shared_unwind(thr,
67811 	                                    idx_retbase,
67812 	                                    num_stack_rets,
67813 #if defined(DUK_USE_ASSERTIONS)
67814 	                                    entry_callstack_top,
67815 #endif
67816 	                                    entry_call_recursion_depth,
67817 	                                    entry_curr_thread,
67818 	                                    entry_ptr_curr_pc);
67819 
67820 	/* Restore preventcount. */
67821 	thr->callstack_preventcount--;
67822 	DUK_ASSERT(thr->callstack_preventcount == entry_callstack_preventcount);
67823 
67824 	/* Final asserts. */
67825 	DUK_ASSERT(thr->callstack_curr == entry_act);
67826 	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) == entry_valstack_bottom_byteoff);
67827 	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
67828 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
67829 	DUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);
67830 	DUK_ASSERT(thr->heap->curr_thread == entry_curr_thread);
67831 	DUK_ASSERT(thr->state == entry_thread_state);
67832 	DUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);
67833 	DUK_ASSERT(duk_get_top(thr) == idx_retbase + num_stack_rets);
67834 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
67835 
67836 	/* Pending side effects. */
67837 	DUK_REFZERO_CHECK_FAST(thr);
67838 
67839 	return retval;
67840 }
67841 
67842 /*
67843  *  Property-based call (foo.noSuch()) error setup: replace target function
67844  *  on stack top with a hidden Symbol tagged non-callable wrapper object
67845  *  holding the error.  The error gets thrown in call handling at the
67846  *  proper spot to follow ECMAScript semantics.
67847  */
67848 
67849 #if defined(DUK_USE_VERBOSE_ERRORS)
67850 DUK_INTERNAL DUK_NOINLINE DUK_COLD void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_base, duk_tval *tv_key) {
67851 	const char *str_targ, *str_key, *str_base;
67852 	duk_idx_t entry_top;
67853 
67854 	entry_top = duk_get_top(thr);
67855 
67856 	/* [ <nargs> target ] */
67857 
67858 	/* Must stabilize pointers first.  tv_targ is already on stack top. */
67859 	duk_push_tval(thr, tv_base);
67860 	duk_push_tval(thr, tv_key);
67861 
67862 	DUK_GC_TORTURE(thr->heap);
67863 
67864 	duk_push_bare_object(thr);
67865 
67866 	/* [ <nargs> target base key {} ] */
67867 
67868 	/* We only push a wrapped error, replacing the call target (at
67869 	 * idx_func) with the error to ensure side effects come out
67870 	 * correctly:
67871 	 * - Property read
67872 	 * - Call argument evaluation
67873 	 * - Callability check and error thrown
67874 	 *
67875 	 * A hidden Symbol on the wrapper object pushed above is used by
67876 	 * call handling to figure out the error is to be thrown as is.
67877 	 * It is CRITICAL that the hidden Symbol can never occur on a
67878 	 * user visible object that may get thrown.
67879 	 */
67880 
67881 #if defined(DUK_USE_PARANOID_ERRORS)
67882 	str_targ = duk_get_type_name(thr, -4);
67883 	str_key = duk_get_type_name(thr, -2);
67884 	str_base = duk_get_type_name(thr, -3);
67885 	duk_push_error_object(thr,
67886 	                      DUK_ERR_TYPE_ERROR | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
67887 	                      "%s not callable (property %s of %s)", str_targ, str_key, str_base);
67888 	duk_xdef_prop_stridx(thr, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);  /* Marker property, reuse _Target. */
67889 	/* [ <nargs> target base key { _Target: error } ] */
67890 	duk_replace(thr, entry_top - 1);
67891 #else
67892 	str_targ = duk_push_string_readable(thr, -4);
67893 	str_key = duk_push_string_readable(thr, -3);
67894 	str_base = duk_push_string_readable(thr, -5);
67895 	duk_push_error_object(thr,
67896 	                      DUK_ERR_TYPE_ERROR | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
67897 	                      "%s not callable (property %s of %s)", str_targ, str_key, str_base);
67898 	/* [ <nargs> target base key {} str_targ str_key str_base error ] */
67899 	duk_xdef_prop_stridx(thr, -5, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);  /* Marker property, reuse _Target. */
67900 	/* [ <nargs> target base key { _Target: error } str_targ str_key str_base ] */
67901 	duk_swap(thr, -4, entry_top - 1);
67902 	/* [ <nargs> { _Target: error } base key target str_targ str_key str_base ] */
67903 #endif
67904 
67905 	/* [ <nregs> { _Target: error } <variable> */
67906 	duk_set_top(thr, entry_top);
67907 
67908 	/* [ <nregs> { _Target: error } */
67909 	DUK_ASSERT(!duk_is_callable(thr, -1));  /* Critical so that call handling will throw the error. */
67910 }
67911 #endif  /* DUK_USE_VERBOSE_ERRORS */
67912 
67913 /* automatic undefs */
67914 #undef DUK__AUGMENT_CALL_RELAX_COUNT
67915 #undef DUK__CALL_HANDLING_REQUIRE_STACK
67916 #line 1 "duk_js_compiler.c"
67917 /*
67918  *  ECMAScript compiler.
67919  *
67920  *  Parses an input string and generates a function template result.
67921  *  Compilation may happen in multiple contexts (global code, eval
67922  *  code, function code).
67923  *
67924  *  The parser uses a traditional top-down recursive parsing for the
67925  *  statement level, and an operator precedence based top-down approach
67926  *  for the expression level.  The attempt is to minimize the C stack
67927  *  depth.  Bytecode is generated directly without an intermediate
67928  *  representation (tree), at the cost of needing two (and sometimes
67929  *  three) passes over each function.
67930  *
67931  *  The top-down recursive parser functions are named "duk__parse_XXX".
67932  *
67933  *  Recursion limits are in key functions to prevent arbitrary C recursion:
67934  *  function body parsing, statement parsing, and expression parsing.
67935  *
67936  *  See doc/compiler.rst for discussion on the design.
67937  *
67938  *  A few typing notes:
67939  *
67940  *    - duk_regconst_t: signed, highest bit set (< 0) means constant,
67941  *      some call sites use -1 for "none" (equivalent to constant 0x7fffffff)
67942  *    - PC values: duk_int_t, negative values used as markers
67943  */
67944 
67945 /* #include duk_internal.h -> already included */
67946 
67947 /* If highest bit of a register number is set, it refers to a constant instead.
67948  * When interpreted as a signed value, this means const values are always
67949  * negative (when interpreted as two's complement).  For example DUK__ISREG_TEMP()
67950  * uses this approach to avoid an explicit DUK__ISREG() check (the condition is
67951  * logically "'x' is a register AND 'x' >= temp_first").
67952  */
67953 #define DUK__CONST_MARKER                   DUK_REGCONST_CONST_MARKER
67954 #define DUK__REMOVECONST(x)                 ((x) & ~DUK__CONST_MARKER)
67955 #define DUK__ISREG(x)                       ((x) >= 0)
67956 #define DUK__ISCONST(x)                     ((x) < 0)
67957 #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. */
67958 #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. */
67959 #define DUK__GETTEMP(comp_ctx)              ((comp_ctx)->curr_func.temp_next)
67960 #define DUK__SETTEMP(comp_ctx,x)            ((comp_ctx)->curr_func.temp_next = (x))  /* dangerous: must only lower (temp_max not updated) */
67961 #define DUK__SETTEMP_CHECKMAX(comp_ctx,x)   duk__settemp_checkmax((comp_ctx),(x))
67962 #define DUK__ALLOCTEMP(comp_ctx)            duk__alloctemp((comp_ctx))
67963 #define DUK__ALLOCTEMPS(comp_ctx,count)     duk__alloctemps((comp_ctx),(count))
67964 
67965 /* Init value set size for array and object literals. */
67966 #define DUK__MAX_ARRAY_INIT_VALUES        20
67967 #define DUK__MAX_OBJECT_INIT_PAIRS        10
67968 
67969 /* XXX: hack, remove when const lookup is not O(n) */
67970 #define DUK__GETCONST_MAX_CONSTS_CHECK    256
67971 
67972 /* These limits are based on bytecode limits.  Max temps is limited
67973  * by duk_hcompfunc nargs/nregs fields being 16 bits.
67974  */
67975 #define DUK__MAX_CONSTS                   DUK_BC_BC_MAX
67976 #define DUK__MAX_FUNCS                    DUK_BC_BC_MAX
67977 #define DUK__MAX_TEMPS                    0xffffL
67978 
67979 /* Initial bytecode size allocation. */
67980 #if defined(DUK_USE_PREFER_SIZE)
67981 #define DUK__BC_INITIAL_INSTS             16
67982 #else
67983 #define DUK__BC_INITIAL_INSTS             256
67984 #endif
67985 
67986 #define DUK__RECURSION_INCREASE(comp_ctx,thr)  do { \
67987 		DUK_DDD(DUK_DDDPRINT("RECURSION INCREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
67988 		duk__comp_recursion_increase((comp_ctx)); \
67989 	} while (0)
67990 
67991 #define DUK__RECURSION_DECREASE(comp_ctx,thr)  do { \
67992 		DUK_DDD(DUK_DDDPRINT("RECURSION DECREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
67993 		duk__comp_recursion_decrease((comp_ctx)); \
67994 	} while (0)
67995 
67996 /* Value stack slot limits: these are quite approximate right now, and
67997  * because they overlap in control flow, some could be eliminated.
67998  */
67999 #define DUK__COMPILE_ENTRY_SLOTS          8
68000 #define DUK__FUNCTION_INIT_REQUIRE_SLOTS  16
68001 #define DUK__FUNCTION_BODY_REQUIRE_SLOTS  16
68002 #define DUK__PARSE_STATEMENTS_SLOTS       16
68003 #define DUK__PARSE_EXPR_SLOTS             16
68004 
68005 /* Temporary structure used to pass a stack allocated region through
68006  * duk_safe_call().
68007  */
68008 typedef struct {
68009 	duk_small_uint_t flags;
68010 	duk_compiler_ctx comp_ctx_alloc;
68011 	duk_lexer_point lex_pt_alloc;
68012 } duk__compiler_stkstate;
68013 
68014 /*
68015  *  Prototypes
68016  */
68017 
68018 /* lexing */
68019 DUK_LOCAL_DECL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);
68020 DUK_LOCAL_DECL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);
68021 DUK_LOCAL_DECL void duk__advance(duk_compiler_ctx *ctx);
68022 
68023 /* function helpers */
68024 DUK_LOCAL_DECL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx);
68025 DUK_LOCAL_DECL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx);
68026 DUK_LOCAL_DECL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_regconst_t *out_stmt_value_reg);
68027 DUK_LOCAL_DECL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx);
68028 DUK_LOCAL_DECL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx);
68029 
68030 /* code emission */
68031 DUK_LOCAL_DECL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx);
68032 DUK_LOCAL_DECL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc);
68033 DUK_LOCAL_DECL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins);
68034 DUK_LOCAL_DECL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op);
68035 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);
68036 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);
68037 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);
68038 #if 0  /* unused */
68039 DUK_LOCAL_DECL void duk__emit_a(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a);
68040 DUK_LOCAL_DECL void duk__emit_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b);
68041 #endif
68042 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);
68043 DUK_LOCAL_DECL void duk__emit_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t bc);
68044 DUK_LOCAL_DECL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc);
68045 DUK_LOCAL_DECL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val);
68046 DUK_LOCAL_DECL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val);
68047 DUK_LOCAL_DECL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc);
68048 DUK_LOCAL_DECL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx);
68049 DUK_LOCAL_DECL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
68050 DUK_LOCAL_DECL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc);
68051 DUK_LOCAL_DECL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
68052 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);
68053 DUK_LOCAL_DECL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
68054 DUK_LOCAL_DECL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
68055 DUK_LOCAL_DECL void duk__emit_invalid(duk_compiler_ctx *comp_ctx);
68056 
68057 /* ivalue/ispec helpers */
68058 DUK_LOCAL_DECL void duk__ivalue_regconst(duk_ivalue *x, duk_regconst_t regconst);
68059 DUK_LOCAL_DECL void duk__ivalue_plain_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
68060 DUK_LOCAL_DECL void duk__ivalue_var_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
68061 DUK_LOCAL_DECL void duk__ivalue_var_hstring(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_hstring *h);
68062 DUK_LOCAL_DECL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst);
68063 DUK_LOCAL_DECL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst);
68064 DUK_LOCAL_DECL duk_regconst_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num);
68065 DUK_LOCAL_DECL duk_regconst_t duk__alloctemp(duk_compiler_ctx *comp_ctx);
68066 DUK_LOCAL_DECL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_regconst_t temp_next);
68067 DUK_LOCAL_DECL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx);
68068 DUK_LOCAL_DECL
68069 duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
68070                                          duk_ispec *x,
68071                                          duk_regconst_t forced_reg,
68072                                          duk_small_uint_t flags);
68073 DUK_LOCAL_DECL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_regconst_t forced_reg);
68074 DUK_LOCAL_DECL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_regconst_t forced_reg);
68075 DUK_LOCAL_DECL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
68076 DUK_LOCAL_DECL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
68077 DUK_LOCAL_DECL
68078 duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
68079                                           duk_ivalue *x,
68080                                           duk_regconst_t forced_reg,
68081                                           duk_small_uint_t flags);
68082 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
68083 #if 0  /* unused */
68084 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
68085 #endif
68086 DUK_LOCAL_DECL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg);
68087 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
68088 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
68089 
68090 /* identifier handling */
68091 DUK_LOCAL_DECL duk_regconst_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx);
68092 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);
68093 
68094 /* label handling */
68095 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);
68096 DUK_LOCAL_DECL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags);
68097 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);
68098 DUK_LOCAL_DECL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_size_t len);
68099 
68100 /* top-down expression parser */
68101 DUK_LOCAL_DECL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
68102 DUK_LOCAL_DECL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res);
68103 DUK_LOCAL_DECL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx);
68104 DUK_LOCAL_DECL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx);
68105 
68106 /* exprtop is the top level variant which resets nud/led counts */
68107 DUK_LOCAL_DECL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
68108 DUK_LOCAL_DECL void duk__exprtop(duk_compiler_ctx *ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
68109 
68110 /* convenience helpers */
68111 #if 0  /* unused */
68112 DUK_LOCAL_DECL duk_regconst_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
68113 #endif
68114 #if 0  /* unused */
68115 DUK_LOCAL_DECL duk_regconst_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
68116 #endif
68117 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);
68118 DUK_LOCAL_DECL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
68119 #if 0  /* unused */
68120 DUK_LOCAL_DECL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
68121 #endif
68122 DUK_LOCAL_DECL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
68123 DUK_LOCAL_DECL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
68124 DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
68125 #if 0  /* unused */
68126 DUK_LOCAL_DECL duk_regconst_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
68127 #endif
68128 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);
68129 DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
68130 #if 0  /* unused */
68131 DUK_LOCAL_DECL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
68132 #endif
68133 
68134 /* expression parsing helpers */
68135 DUK_LOCAL_DECL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
68136 DUK_LOCAL_DECL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
68137 DUK_LOCAL_DECL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
68138 
68139 /* statement parsing */
68140 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);
68141 DUK_LOCAL_DECL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags);
68142 DUK_LOCAL_DECL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
68143 DUK_LOCAL_DECL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
68144 DUK_LOCAL_DECL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
68145 DUK_LOCAL_DECL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
68146 DUK_LOCAL_DECL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
68147 DUK_LOCAL_DECL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
68148 DUK_LOCAL_DECL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
68149 DUK_LOCAL_DECL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
68150 DUK_LOCAL_DECL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
68151 DUK_LOCAL_DECL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
68152 DUK_LOCAL_DECL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem);
68153 DUK_LOCAL_DECL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id);
68154 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);
68155 
68156 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);
68157 DUK_LOCAL_DECL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx);
68158 DUK_LOCAL_DECL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags);
68159 DUK_LOCAL_DECL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags);
68160 
68161 #define DUK__FUNC_FLAG_DECL            (1 << 0)   /* Parsing a function declaration. */
68162 #define DUK__FUNC_FLAG_GETSET          (1 << 1)   /* Parsing an object literal getter/setter. */
68163 #define DUK__FUNC_FLAG_METDEF          (1 << 2)   /* Parsing an object literal method definition shorthand. */
68164 #define DUK__FUNC_FLAG_PUSHNAME_PASS1  (1 << 3)   /* Push function name when creating template (first pass only). */
68165 #define DUK__FUNC_FLAG_USE_PREVTOKEN   (1 << 4)   /* Use prev_token to start function parsing (workaround for object literal). */
68166 
68167 /*
68168  *  Parser control values for tokens.  The token table is ordered by the
68169  *  DUK_TOK_XXX defines.
68170  *
68171  *  The binding powers are for lbp() use (i.e. for use in led() context).
68172  *  Binding powers are positive for typing convenience, and bits at the
68173  *  top should be reserved for flags.  Binding power step must be higher
68174  *  than 1 so that binding power "lbp - 1" can be used for right associative
68175  *  operators.  Currently a step of 2 is used (which frees one more bit for
68176  *  flags).
68177  */
68178 
68179 /* XXX: actually single step levels would work just fine, clean up */
68180 
68181 /* binding power "levels" (see doc/compiler.rst) */
68182 #define DUK__BP_INVALID                0             /* always terminates led() */
68183 #define DUK__BP_EOF                    2
68184 #define DUK__BP_CLOSING                4             /* token closes expression, e.g. ')', ']' */
68185 #define DUK__BP_FOR_EXPR               DUK__BP_CLOSING    /* bp to use when parsing a top level Expression */
68186 #define DUK__BP_COMMA                  6
68187 #define DUK__BP_ASSIGNMENT             8
68188 #define DUK__BP_CONDITIONAL            10
68189 #define DUK__BP_LOR                    12
68190 #define DUK__BP_LAND                   14
68191 #define DUK__BP_BOR                    16
68192 #define DUK__BP_BXOR                   18
68193 #define DUK__BP_BAND                   20
68194 #define DUK__BP_EQUALITY               22
68195 #define DUK__BP_RELATIONAL             24
68196 #define DUK__BP_SHIFT                  26
68197 #define DUK__BP_ADDITIVE               28
68198 #define DUK__BP_MULTIPLICATIVE         30
68199 #define DUK__BP_EXPONENTIATION         32
68200 #define DUK__BP_POSTFIX                34
68201 #define DUK__BP_CALL                   36
68202 #define DUK__BP_MEMBER                 38
68203 
68204 #define DUK__TOKEN_LBP_BP_MASK         0x1f
68205 #define DUK__TOKEN_LBP_FLAG_NO_REGEXP  (1 << 5)   /* regexp literal must not follow this token */
68206 #define DUK__TOKEN_LBP_FLAG_TERMINATES (1 << 6)   /* terminates expression; e.g. post-increment/-decrement */
68207 #define DUK__TOKEN_LBP_FLAG_UNUSED     (1 << 7)   /* unused */
68208 
68209 #define DUK__TOKEN_LBP_GET_BP(x)       ((duk_small_uint_t) (((x) & DUK__TOKEN_LBP_BP_MASK) * 2))
68210 
68211 #define DUK__MK_LBP(bp)                ((bp) >> 1)    /* bp is assumed to be even */
68212 #define DUK__MK_LBP_FLAGS(bp,flags)    (((bp) >> 1) | (flags))
68213 
68214 DUK_LOCAL const duk_uint8_t duk__token_lbp[] = {
68215 	DUK__MK_LBP(DUK__BP_EOF),                                 /* DUK_TOK_EOF */
68216 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_IDENTIFIER */
68217 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_BREAK */
68218 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CASE */
68219 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CATCH */
68220 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CONTINUE */
68221 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DEBUGGER */
68222 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DEFAULT */
68223 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DELETE */
68224 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DO */
68225 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_ELSE */
68226 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FINALLY */
68227 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FOR */
68228 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FUNCTION */
68229 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IF */
68230 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_IN */
68231 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_INSTANCEOF */
68232 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_NEW */
68233 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_RETURN */
68234 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SWITCH */
68235 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_THIS */
68236 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_THROW */
68237 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_TRY */
68238 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_TYPEOF */
68239 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_VAR */
68240 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CONST */
68241 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_VOID */
68242 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_WHILE */
68243 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_WITH */
68244 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CLASS */
68245 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_ENUM */
68246 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_EXPORT */
68247 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_EXTENDS */
68248 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IMPORT */
68249 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SUPER */
68250 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_NULL */
68251 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_TRUE */
68252 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_FALSE */
68253 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_GET */
68254 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SET */
68255 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IMPLEMENTS */
68256 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_INTERFACE */
68257 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LET */
68258 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PACKAGE */
68259 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PRIVATE */
68260 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PROTECTED */
68261 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PUBLIC */
68262 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_STATIC */
68263 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_YIELD */
68264 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LCURLY */
68265 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RCURLY */
68266 	DUK__MK_LBP(DUK__BP_MEMBER),                              /* DUK_TOK_LBRACKET */
68267 	DUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RBRACKET */
68268 	DUK__MK_LBP(DUK__BP_CALL),                                /* DUK_TOK_LPAREN */
68269 	DUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RPAREN */
68270 	DUK__MK_LBP(DUK__BP_MEMBER),                              /* DUK_TOK_PERIOD */
68271 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SEMICOLON */
68272 	DUK__MK_LBP(DUK__BP_COMMA),                               /* DUK_TOK_COMMA */
68273 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_LT */
68274 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_GT */
68275 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_LE */
68276 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_GE */
68277 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_EQ */
68278 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_NEQ */
68279 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_SEQ */
68280 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_SNEQ */
68281 	DUK__MK_LBP(DUK__BP_ADDITIVE),                            /* DUK_TOK_ADD */
68282 	DUK__MK_LBP(DUK__BP_ADDITIVE),                            /* DUK_TOK_SUB */
68283 	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_MUL */
68284 	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_DIV */
68285 	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_MOD */
68286 	DUK__MK_LBP(DUK__BP_EXPONENTIATION),                      /* DUK_TOK_EXP */
68287 	DUK__MK_LBP_FLAGS(DUK__BP_POSTFIX, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_INCREMENT */
68288 	DUK__MK_LBP_FLAGS(DUK__BP_POSTFIX, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_DECREMENT */
68289 	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_ALSHIFT */
68290 	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_ARSHIFT */
68291 	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_RSHIFT */
68292 	DUK__MK_LBP(DUK__BP_BAND),                                /* DUK_TOK_BAND */
68293 	DUK__MK_LBP(DUK__BP_BOR),                                 /* DUK_TOK_BOR */
68294 	DUK__MK_LBP(DUK__BP_BXOR),                                /* DUK_TOK_BXOR */
68295 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LNOT */
68296 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_BNOT */
68297 	DUK__MK_LBP(DUK__BP_LAND),                                /* DUK_TOK_LAND */
68298 	DUK__MK_LBP(DUK__BP_LOR),                                 /* DUK_TOK_LOR */
68299 	DUK__MK_LBP(DUK__BP_CONDITIONAL),                         /* DUK_TOK_QUESTION */
68300 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_COLON */
68301 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_EQUALSIGN */
68302 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ADD_EQ */
68303 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_SUB_EQ */
68304 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_MUL_EQ */
68305 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_DIV_EQ */
68306 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_MOD_EQ */
68307 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_EXP_EQ */
68308 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ALSHIFT_EQ */
68309 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ARSHIFT_EQ */
68310 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_RSHIFT_EQ */
68311 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BAND_EQ */
68312 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BOR_EQ */
68313 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BXOR_EQ */
68314 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_NUMBER */
68315 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_STRING */
68316 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_REGEXP */
68317 };
68318 
68319 /*
68320  *  Misc helpers
68321  */
68322 
68323 DUK_LOCAL void duk__comp_recursion_increase(duk_compiler_ctx *comp_ctx) {
68324 	DUK_ASSERT(comp_ctx != NULL);
68325 	DUK_ASSERT(comp_ctx->recursion_depth >= 0);
68326 	if (comp_ctx->recursion_depth >= comp_ctx->recursion_limit) {
68327 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_COMPILER_RECURSION_LIMIT);
68328 		DUK_WO_NORETURN(return;);
68329 	}
68330 	comp_ctx->recursion_depth++;
68331 }
68332 
68333 DUK_LOCAL void duk__comp_recursion_decrease(duk_compiler_ctx *comp_ctx) {
68334 	DUK_ASSERT(comp_ctx != NULL);
68335 	DUK_ASSERT(comp_ctx->recursion_depth > 0);
68336 	comp_ctx->recursion_depth--;
68337 }
68338 
68339 DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
68340 	DUK_UNREF(comp_ctx);
68341 	DUK_ASSERT(h != NULL);
68342 	return DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h);
68343 }
68344 
68345 DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments_in_strict_mode(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
68346 	DUK_ASSERT(h != NULL);
68347 	return (comp_ctx->curr_func.is_strict &&
68348 	        DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h));
68349 }
68350 
68351 /*
68352  *  Parser duk__advance() token eating functions
68353  */
68354 
68355 /* XXX: valstack handling is awkward.  Add a valstack helper which
68356  * avoids dup():ing; valstack_copy(src, dst)?
68357  */
68358 
68359 DUK_LOCAL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {
68360 	duk_hthread *thr = comp_ctx->thr;
68361 	duk_bool_t regexp;
68362 
68363 	DUK_ASSERT_DISABLE(comp_ctx->curr_token.t >= 0);  /* unsigned */
68364 	DUK_ASSERT(comp_ctx->curr_token.t <= DUK_TOK_MAXVAL);  /* MAXVAL is inclusive */
68365 
68366 	/*
68367 	 *  Use current token to decide whether a RegExp can follow.
68368 	 *
68369 	 *  We can use either 't' or 't_nores'; the latter would not
68370 	 *  recognize keywords.  Some keywords can be followed by a
68371 	 *  RegExp (e.g. "return"), so using 't' is better.  This is
68372 	 *  not trivial, see doc/compiler.rst.
68373 	 */
68374 
68375 	regexp = 1;
68376 	if (duk__token_lbp[comp_ctx->curr_token.t] & DUK__TOKEN_LBP_FLAG_NO_REGEXP) {
68377 		regexp = 0;
68378 	}
68379 	if (comp_ctx->curr_func.reject_regexp_in_adv) {
68380 		comp_ctx->curr_func.reject_regexp_in_adv = 0;
68381 		regexp = 0;
68382 	}
68383 	if (comp_ctx->curr_func.allow_regexp_in_adv) {
68384 		comp_ctx->curr_func.allow_regexp_in_adv = 0;
68385 		regexp = 1;
68386 	}
68387 
68388 	if (expect >= 0 && comp_ctx->curr_token.t != (duk_small_uint_t) expect) {
68389 		DUK_D(DUK_DPRINT("parse error: expect=%ld, got=%ld",
68390 		                 (long) expect, (long) comp_ctx->curr_token.t));
68391 		DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
68392 		DUK_WO_NORETURN(return;);
68393 	}
68394 
68395 	/* make current token the previous; need to fiddle with valstack "backing store" */
68396 	duk_memcpy(&comp_ctx->prev_token, &comp_ctx->curr_token, sizeof(duk_token));
68397 	duk_copy(thr, comp_ctx->tok11_idx, comp_ctx->tok21_idx);
68398 	duk_copy(thr, comp_ctx->tok12_idx, comp_ctx->tok22_idx);
68399 
68400 	/* parse new token */
68401 	duk_lexer_parse_js_input_element(&comp_ctx->lex,
68402 	                                 &comp_ctx->curr_token,
68403 	                                 comp_ctx->curr_func.is_strict,
68404 	                                 regexp);
68405 
68406 	DUK_DDD(DUK_DDDPRINT("advance: curr: tok=%ld/%ld,%ld,term=%ld,%!T,%!T "
68407 	                     "prev: tok=%ld/%ld,%ld,term=%ld,%!T,%!T",
68408 	                     (long) comp_ctx->curr_token.t,
68409 	                     (long) comp_ctx->curr_token.t_nores,
68410 	                     (long) comp_ctx->curr_token.start_line,
68411 	                     (long) comp_ctx->curr_token.lineterm,
68412 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok11_idx),
68413 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok12_idx),
68414 	                     (long) comp_ctx->prev_token.t,
68415 	                     (long) comp_ctx->prev_token.t_nores,
68416 	                     (long) comp_ctx->prev_token.start_line,
68417 	                     (long) comp_ctx->prev_token.lineterm,
68418 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok21_idx),
68419 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok22_idx)));
68420 }
68421 
68422 /* advance, expecting current token to be a specific token; parse next token in regexp context */
68423 DUK_LOCAL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {
68424 	duk__advance_helper(comp_ctx, expect);
68425 }
68426 
68427 /* advance, whatever the current token is; parse next token in regexp context */
68428 DUK_LOCAL void duk__advance(duk_compiler_ctx *comp_ctx) {
68429 	duk__advance_helper(comp_ctx, -1);
68430 }
68431 
68432 /*
68433  *  Helpers for duk_compiler_func.
68434  */
68435 
68436 /* init function state: inits valstack allocations */
68437 DUK_LOCAL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) {
68438 	duk_compiler_func *func = &comp_ctx->curr_func;
68439 	duk_hthread *thr = comp_ctx->thr;
68440 	duk_idx_t entry_top;
68441 
68442 	entry_top = duk_get_top(thr);
68443 
68444 	duk_memzero(func, sizeof(*func));  /* intentional overlap with earlier memzero */
68445 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
68446 	func->h_name = NULL;
68447 	func->h_consts = NULL;
68448 	func->h_funcs = NULL;
68449 	func->h_decls = NULL;
68450 	func->h_labelnames = NULL;
68451 	func->h_labelinfos = NULL;
68452 	func->h_argnames = NULL;
68453 	func->h_varmap = NULL;
68454 #endif
68455 
68456 	duk_require_stack(thr, DUK__FUNCTION_INIT_REQUIRE_SLOTS);
68457 
68458 	DUK_BW_INIT_PUSHBUF(thr, &func->bw_code, DUK__BC_INITIAL_INSTS * sizeof(duk_compiler_instr));
68459 	/* code_idx = entry_top + 0 */
68460 
68461 	duk_push_bare_array(thr);
68462 	func->consts_idx = entry_top + 1;
68463 	func->h_consts = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 1);
68464 	DUK_ASSERT(func->h_consts != NULL);
68465 
68466 	duk_push_bare_array(thr);
68467 	func->funcs_idx = entry_top + 2;
68468 	func->h_funcs = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 2);
68469 	DUK_ASSERT(func->h_funcs != NULL);
68470 	DUK_ASSERT(func->fnum_next == 0);
68471 
68472 	duk_push_bare_array(thr);
68473 	func->decls_idx = entry_top + 3;
68474 	func->h_decls = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 3);
68475 	DUK_ASSERT(func->h_decls != NULL);
68476 
68477 	duk_push_bare_array(thr);
68478 	func->labelnames_idx = entry_top + 4;
68479 	func->h_labelnames = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 4);
68480 	DUK_ASSERT(func->h_labelnames != NULL);
68481 
68482 	duk_push_dynamic_buffer(thr, 0);
68483 	func->labelinfos_idx = entry_top + 5;
68484 	func->h_labelinfos = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, entry_top + 5);
68485 	DUK_ASSERT(func->h_labelinfos != NULL);
68486 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(func->h_labelinfos) && !DUK_HBUFFER_HAS_EXTERNAL(func->h_labelinfos));
68487 
68488 	duk_push_bare_array(thr);
68489 	func->argnames_idx = entry_top + 6;
68490 	func->h_argnames = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 6);
68491 	DUK_ASSERT(func->h_argnames != NULL);
68492 
68493 	duk_push_bare_object(thr);
68494 	func->varmap_idx = entry_top + 7;
68495 	func->h_varmap = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 7);
68496 	DUK_ASSERT(func->h_varmap != NULL);
68497 }
68498 
68499 /* reset function state (prepare for pass 2) */
68500 DUK_LOCAL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx) {
68501 	duk_compiler_func *func = &comp_ctx->curr_func;
68502 	duk_hthread *thr = comp_ctx->thr;
68503 
68504 	/* reset bytecode buffer but keep current size; pass 2 will
68505 	 * require same amount or more.
68506 	 */
68507 	DUK_BW_RESET_SIZE(thr, &func->bw_code);
68508 
68509 	duk_set_length(thr, func->consts_idx, 0);
68510 	/* keep func->h_funcs; inner functions are not reparsed to avoid O(depth^2) parsing */
68511 	func->fnum_next = 0;
68512 	/* duk_set_length(thr, func->funcs_idx, 0); */
68513 	duk_set_length(thr, func->labelnames_idx, 0);
68514 	duk_hbuffer_reset(thr, func->h_labelinfos);
68515 	/* keep func->h_argnames; it is fixed for all passes */
68516 
68517 	/* truncated in case pass 3 needed */
68518 	duk_push_bare_object(thr);
68519 	duk_replace(thr, func->varmap_idx);
68520 	func->h_varmap = DUK_GET_HOBJECT_POSIDX(thr, func->varmap_idx);
68521 	DUK_ASSERT(func->h_varmap != NULL);
68522 }
68523 
68524 /* cleanup varmap from any null entries, compact it, etc; returns number
68525  * of final entries after cleanup.
68526  */
68527 DUK_LOCAL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx) {
68528 	duk_hthread *thr = comp_ctx->thr;
68529 	duk_hobject *h_varmap;
68530 	duk_hstring *h_key;
68531 	duk_tval *tv;
68532 	duk_uint32_t i, e_next;
68533 	duk_int_t ret;
68534 
68535 	/* [ ... varmap ] */
68536 
68537 	h_varmap = DUK_GET_HOBJECT_NEGIDX(thr, -1);
68538 	DUK_ASSERT(h_varmap != NULL);
68539 
68540 	ret = 0;
68541 	e_next = DUK_HOBJECT_GET_ENEXT(h_varmap);
68542 	for (i = 0; i < e_next; i++) {
68543 		h_key = DUK_HOBJECT_E_GET_KEY(thr->heap, h_varmap, i);
68544 		if (!h_key) {
68545 			continue;
68546 		}
68547 
68548 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h_varmap, i));
68549 
68550 		/* The entries can either be register numbers or 'null' values.
68551 		 * Thus, no need to DECREF them and get side effects.  DECREF'ing
68552 		 * the keys (strings) can cause memory to be freed but no side
68553 		 * effects as strings don't have finalizers.  This is why we can
68554 		 * rely on the object properties not changing from underneath us.
68555 		 */
68556 
68557 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h_varmap, i);
68558 		if (!DUK_TVAL_IS_NUMBER(tv)) {
68559 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv));
68560 			DUK_HOBJECT_E_SET_KEY(thr->heap, h_varmap, i, NULL);
68561 			DUK_HSTRING_DECREF(thr, h_key);
68562 			/* when key is NULL, value is garbage so no need to set */
68563 		} else {
68564 			ret++;
68565 		}
68566 	}
68567 
68568 	duk_compact_m1(thr);
68569 
68570 	return ret;
68571 }
68572 
68573 /* Convert duk_compiler_func into a function template, leaving the result
68574  * on top of stack.
68575  */
68576 /* XXX: awkward and bloated asm -- use faster internal accesses */
68577 DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
68578 	duk_compiler_func *func = &comp_ctx->curr_func;
68579 	duk_hthread *thr = comp_ctx->thr;
68580 	duk_hcompfunc *h_res;
68581 	duk_hbuffer_fixed *h_data;
68582 	duk_size_t consts_count;
68583 	duk_size_t funcs_count;
68584 	duk_size_t code_count;
68585 	duk_size_t code_size;
68586 	duk_size_t data_size;
68587 	duk_size_t i;
68588 	duk_tval *p_const;
68589 	duk_hobject **p_func;
68590 	duk_instr_t *p_instr;
68591 	duk_compiler_instr *q_instr;
68592 	duk_tval *tv;
68593 	duk_bool_t keep_varmap;
68594 	duk_bool_t keep_formals;
68595 #if !defined(DUK_USE_DEBUGGER_SUPPORT)
68596 	duk_size_t formals_length;
68597 #endif
68598 
68599 	DUK_DDD(DUK_DDDPRINT("converting duk_compiler_func to function/template"));
68600 
68601 	/*
68602 	 *  Push result object and init its flags
68603 	 */
68604 
68605 	/* Valstack should suffice here, required on function valstack init */
68606 
68607 	h_res = duk_push_hcompfunc(thr);
68608 	DUK_ASSERT(h_res != NULL);
68609 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_res) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
68610 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) h_res, NULL);  /* Function templates are "bare objects". */
68611 
68612 	if (func->is_function) {
68613 		DUK_DDD(DUK_DDDPRINT("function -> set NEWENV"));
68614 		DUK_HOBJECT_SET_NEWENV((duk_hobject *) h_res);
68615 
68616 		if (!func->is_arguments_shadowed) {
68617 			/* arguments object would be accessible; note that shadowing
68618 			 * bindings are arguments or function declarations, neither
68619 			 * of which are deletable, so this is safe.
68620 			 */
68621 
68622 			if (func->id_access_arguments || func->may_direct_eval) {
68623 				DUK_DDD(DUK_DDDPRINT("function may access 'arguments' object directly or "
68624 				                     "indirectly -> set CREATEARGS"));
68625 				DUK_HOBJECT_SET_CREATEARGS((duk_hobject *) h_res);
68626 			}
68627 		}
68628 	} else if (func->is_eval && func->is_strict) {
68629 		DUK_DDD(DUK_DDDPRINT("strict eval code -> set NEWENV"));
68630 		DUK_HOBJECT_SET_NEWENV((duk_hobject *) h_res);
68631 	} else {
68632 		/* non-strict eval: env is caller's env or global env (direct vs. indirect call)
68633 		 * global code: env is is global env
68634 		 */
68635 		DUK_DDD(DUK_DDDPRINT("non-strict eval code or global code -> no NEWENV"));
68636 		DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV((duk_hobject *) h_res));
68637 	}
68638 
68639 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
68640 	if (func->is_function && func->is_namebinding && func->h_name != NULL) {
68641 		/* Object literal set/get functions have a name (property
68642 		 * name) but must not have a lexical name binding, see
68643 		 * test-bug-getset-func-name.js.
68644 		 */
68645 		DUK_DDD(DUK_DDDPRINT("function expression with a name -> set NAMEBINDING"));
68646 		DUK_HOBJECT_SET_NAMEBINDING((duk_hobject *) h_res);
68647 	}
68648 #endif
68649 
68650 	if (func->is_strict) {
68651 		DUK_DDD(DUK_DDDPRINT("function is strict -> set STRICT"));
68652 		DUK_HOBJECT_SET_STRICT((duk_hobject *) h_res);
68653 	}
68654 
68655 	if (func->is_notail) {
68656 		DUK_DDD(DUK_DDDPRINT("function is notail -> set NOTAIL"));
68657 		DUK_HOBJECT_SET_NOTAIL((duk_hobject *) h_res);
68658 	}
68659 
68660 	if (func->is_constructable) {
68661 		DUK_DDD(DUK_DDDPRINT("function is constructable -> set CONSTRUCTABLE"));
68662 		DUK_HOBJECT_SET_CONSTRUCTABLE((duk_hobject *) h_res);
68663 	}
68664 
68665 	/*
68666 	 *  Build function fixed size 'data' buffer, which contains bytecode,
68667 	 *  constants, and inner function references.
68668 	 *
68669 	 *  During the building phase 'data' is reachable but incomplete.
68670 	 *  Only incref's occur during building (no refzero or GC happens),
68671 	 *  so the building process is atomic.
68672 	 */
68673 
68674 	consts_count = duk_hobject_get_length(thr, func->h_consts);
68675 	funcs_count = duk_hobject_get_length(thr, func->h_funcs) / 3;
68676 	code_count = DUK_BW_GET_SIZE(thr, &func->bw_code) / sizeof(duk_compiler_instr);
68677 	code_size = code_count * sizeof(duk_instr_t);
68678 
68679 	data_size = consts_count * sizeof(duk_tval) +
68680 	            funcs_count * sizeof(duk_hobject *) +
68681 	            code_size;
68682 
68683 	DUK_DDD(DUK_DDDPRINT("consts_count=%ld, funcs_count=%ld, code_size=%ld -> "
68684 	                     "data_size=%ld*%ld + %ld*%ld + %ld = %ld",
68685 	                     (long) consts_count, (long) funcs_count, (long) code_size,
68686 	                     (long) consts_count, (long) sizeof(duk_tval),
68687 	                     (long) funcs_count, (long) sizeof(duk_hobject *),
68688 	                     (long) code_size, (long) data_size));
68689 
68690 	duk_push_fixed_buffer_nozero(thr, data_size);
68691 	h_data = (duk_hbuffer_fixed *) (void *) duk_known_hbuffer(thr, -1);
68692 
68693 	DUK_HCOMPFUNC_SET_DATA(thr->heap, h_res, (duk_hbuffer *) h_data);
68694 	DUK_HEAPHDR_INCREF(thr, h_data);
68695 
68696 	p_const = (duk_tval *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data);
68697 	for (i = 0; i < consts_count; i++) {
68698 		DUK_ASSERT(i <= DUK_UARRIDX_MAX);  /* const limits */
68699 		tv = duk_hobject_find_array_entry_tval_ptr(thr->heap, func->h_consts, (duk_uarridx_t) i);
68700 		DUK_ASSERT(tv != NULL);
68701 		DUK_TVAL_SET_TVAL(p_const, tv);
68702 		p_const++;
68703 		DUK_TVAL_INCREF(thr, tv);  /* may be a string constant */
68704 
68705 		DUK_DDD(DUK_DDDPRINT("constant: %!T", (duk_tval *) tv));
68706 	}
68707 
68708 	p_func = (duk_hobject **) p_const;
68709 	DUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_res, p_func);
68710 	for (i = 0; i < funcs_count; i++) {
68711 		duk_hobject *h;
68712 		DUK_ASSERT(i * 3 <= DUK_UARRIDX_MAX);  /* func limits */
68713 		tv = duk_hobject_find_array_entry_tval_ptr(thr->heap, func->h_funcs, (duk_uarridx_t) (i * 3));
68714 		DUK_ASSERT(tv != NULL);
68715 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
68716 		h = DUK_TVAL_GET_OBJECT(tv);
68717 		DUK_ASSERT(h != NULL);
68718 		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(h));
68719 		*p_func++ = h;
68720 		DUK_HOBJECT_INCREF(thr, h);
68721 
68722 		DUK_DDD(DUK_DDDPRINT("inner function: %p -> %!iO",
68723 		                     (void *) h, (duk_heaphdr *) h));
68724 	}
68725 
68726 	p_instr = (duk_instr_t *) p_func;
68727 	DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, h_res, p_instr);
68728 
68729 	/* copy bytecode instructions one at a time */
68730 	q_instr = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(thr, &func->bw_code);
68731 	for (i = 0; i < code_count; i++) {
68732 		p_instr[i] = q_instr[i].ins;
68733 	}
68734 	/* Note: 'q_instr' is still used below */
68735 
68736 	DUK_ASSERT((duk_uint8_t *) (p_instr + code_count) == DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data) + data_size);
68737 
68738 	duk_pop(thr);  /* 'data' (and everything in it) is reachable through h_res now */
68739 
68740 	/*
68741 	 *  Init non-property result fields
68742 	 *
68743 	 *  'nregs' controls how large a register frame is allocated.
68744 	 *
68745 	 *  'nargs' controls how many formal arguments are written to registers:
68746 	 *  r0, ... r(nargs-1).  The remaining registers are initialized to
68747 	 *  undefined.
68748 	 */
68749 
68750 	DUK_ASSERT(func->temp_max >= 0);
68751 	h_res->nregs = (duk_uint16_t) func->temp_max;
68752 	h_res->nargs = (duk_uint16_t) duk_hobject_get_length(thr, func->h_argnames);
68753 	DUK_ASSERT(h_res->nregs >= h_res->nargs);  /* pass2 allocation handles this */
68754 #if defined(DUK_USE_DEBUGGER_SUPPORT)
68755 	h_res->start_line = (duk_uint32_t) func->min_line;
68756 	h_res->end_line = (duk_uint32_t) func->max_line;
68757 #endif
68758 
68759 	/*
68760 	 *  Init object properties
68761 	 *
68762 	 *  Properties should be added in decreasing order of access frequency.
68763 	 *  (Not very critical for function templates.)
68764 	 */
68765 
68766 	DUK_DDD(DUK_DDDPRINT("init function properties"));
68767 
68768 	/* [ ... res ] */
68769 
68770 	/* _Varmap: omitted if function is guaranteed not to do a slow path
68771 	 * identifier access that might be caught by locally declared variables.
68772 	 * The varmap can also be omitted if it turns out empty of actual
68773 	 * register mappings after a cleanup.  When debugging is enabled, we
68774 	 * always need the varmap to be able to lookup variables at any point.
68775 	 */
68776 
68777 #if defined(DUK_USE_DEBUGGER_SUPPORT)
68778 	DUK_DD(DUK_DDPRINT("keeping _Varmap because debugger support is enabled"));
68779 	keep_varmap = 1;
68780 #else
68781 	if (func->id_access_slow_own ||   /* directly uses slow accesses that may match own variables */
68782 	    func->id_access_arguments ||  /* accesses 'arguments' directly */
68783 	    func->may_direct_eval ||      /* may indirectly slow access through a direct eval */
68784 	    funcs_count > 0) {            /* has inner functions which may slow access (XXX: this can be optimized by looking at the inner functions) */
68785 		DUK_DD(DUK_DDPRINT("keeping _Varmap because of direct eval, slow path access that may match local variables, or presence of inner functions"));
68786 		keep_varmap = 1;
68787 	} else {
68788 		DUK_DD(DUK_DDPRINT("dropping _Varmap"));
68789 		keep_varmap = 0;
68790 	}
68791 #endif
68792 
68793 	if (keep_varmap) {
68794 		duk_int_t num_used;
68795 		duk_dup(thr, func->varmap_idx);
68796 		num_used = duk__cleanup_varmap(comp_ctx);
68797 		DUK_DDD(DUK_DDDPRINT("cleaned up varmap: %!T (num_used=%ld)",
68798 		                     (duk_tval *) duk_get_tval(thr, -1), (long) num_used));
68799 
68800 		if (num_used > 0) {
68801 			duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);
68802 		} else {
68803 			DUK_DD(DUK_DDPRINT("varmap is empty after cleanup -> no need to add"));
68804 			duk_pop(thr);
68805 		}
68806 	}
68807 
68808 	/* _Formals: omitted if function is guaranteed not to need a (non-strict)
68809 	 * arguments object, and _Formals.length matches nargs exactly.
68810 	 *
68811 	 * Non-arrow functions can't see an outer function's 'argument' binding
68812 	 * (because they have their own), but arrow functions can.  When arrow
68813 	 * functions are added, this condition would need to be added:
68814 	 *     inner_arrow_funcs_count > 0   inner arrow functions may access 'arguments'
68815 	 */
68816 #if defined(DUK_USE_DEBUGGER_SUPPORT)
68817 	DUK_DD(DUK_DDPRINT("keeping _Formals because debugger support is enabled"));
68818 	keep_formals = 1;
68819 #else
68820 	formals_length = duk_get_length(thr, func->argnames_idx);
68821 	if (formals_length != (duk_size_t) h_res->nargs) {
68822 		/* Nargs not enough for closure .length: keep _Formals regardless
68823 		 * of its length.  Shouldn't happen in practice at the moment.
68824 		 */
68825 		DUK_DD(DUK_DDPRINT("keeping _Formals because _Formals.length != nargs"));
68826 		keep_formals = 1;
68827 	} else if ((func->id_access_arguments || func->may_direct_eval) &&
68828 	           (formals_length > 0)) {
68829 		/* Direct eval (may access 'arguments') or accesses 'arguments'
68830 		 * explicitly: keep _Formals unless it is zero length.
68831 		 */
68832 		DUK_DD(DUK_DDPRINT("keeping _Formals because of direct eval or explicit access to 'arguments', and _Formals.length != 0"));
68833 		keep_formals = 1;
68834 	} else {
68835 		DUK_DD(DUK_DDPRINT("omitting _Formals, nargs matches _Formals.length, so no properties added"));
68836 		keep_formals = 0;
68837 	}
68838 #endif
68839 
68840 	if (keep_formals) {
68841 		duk_dup(thr, func->argnames_idx);
68842 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);
68843 	}
68844 
68845 	/* name */
68846 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
68847 	if (func->h_name) {
68848 		duk_push_hstring(thr, func->h_name);
68849 		DUK_DD(DUK_DDPRINT("setting function template .name to %!T", duk_get_tval(thr, -1)));
68850 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
68851 	}
68852 #endif  /* DUK_USE_FUNC_NAME_PROPERTY */
68853 
68854 	/* _Source */
68855 #if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
68856 	if (0) {
68857 		/* XXX: Currently function source code is not stored, as it is not
68858 		 * required by the standard.  Source code should not be stored by
68859 		 * default (user should enable it explicitly), and the source should
68860 		 * probably be compressed with a trivial text compressor; average
68861 		 * compression of 20-30% is quite easy to achieve even with a trivial
68862 		 * compressor (RLE + backwards lookup).
68863 		 *
68864 		 * Debugging needs source code to be useful: sometimes input code is
68865 		 * not found in files as it may be generated and then eval()'d, given
68866 		 * by dynamic C code, etc.
68867 		 *
68868 		 * Other issues:
68869 		 *
68870 		 *   - Need tokenizer indices for start and end to substring
68871 		 *   - Always normalize function declaration part?
68872 		 *   - If we keep _Formals, only need to store body
68873 		 */
68874 
68875 		/*
68876 		 *  For global or eval code this is straightforward.  For functions
68877 		 *  created with the Function constructor we only get the source for
68878 		 *  the body and must manufacture the "function ..." part.
68879 		 *
68880 		 *  For instance, for constructed functions (v8):
68881 		 *
68882 		 *    > a = new Function("foo", "bar", "print(foo)");
68883 		 *    [Function]
68884 		 *    > a.toString()
68885 		 *    'function anonymous(foo,bar) {\nprint(foo)\n}'
68886 		 *
68887 		 *  Similarly for e.g. getters (v8):
68888 		 *
68889 		 *    > x = { get a(foo,bar) { print(foo); } }
68890 		 *    { a: [Getter] }
68891 		 *    > Object.getOwnPropertyDescriptor(x, 'a').get.toString()
68892 		 *    'function a(foo,bar) { print(foo); }'
68893 		 */
68894 
68895 #if 0
68896 		duk_push_literal(thr, "XXX");
68897 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE);
68898 #endif
68899 	}
68900 #endif  /* DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY */
68901 
68902 	/* _Pc2line */
68903 #if defined(DUK_USE_PC2LINE)
68904 	if (1) {
68905 		/*
68906 		 *  Size-optimized pc->line mapping.
68907 		 */
68908 
68909 		DUK_ASSERT(code_count <= DUK_COMPILER_MAX_BYTECODE_LENGTH);
68910 		duk_hobject_pc2line_pack(thr, q_instr, (duk_uint_fast32_t) code_count);  /* -> pushes fixed buffer */
68911 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_NONE);
68912 
68913 		/* XXX: if assertions enabled, walk through all valid PCs
68914 		 * and check line mapping.
68915 		 */
68916 	}
68917 #endif  /* DUK_USE_PC2LINE */
68918 
68919 	/* fileName */
68920 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
68921 	if (comp_ctx->h_filename) {
68922 		/*
68923 		 *  Source filename (or equivalent), for identifying thrown errors.
68924 		 */
68925 
68926 		duk_push_hstring(thr, comp_ctx->h_filename);
68927 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_NONE);
68928 	}
68929 #endif
68930 
68931 	DUK_DD(DUK_DDPRINT("converted function: %!ixT",
68932 	                   (duk_tval *) duk_get_tval(thr, -1)));
68933 
68934 	/*
68935 	 *  Compact the function template.
68936 	 */
68937 
68938 	duk_compact_m1(thr);
68939 
68940 	/*
68941 	 *  Debug dumping
68942 	 */
68943 
68944 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
68945 	{
68946 		duk_hcompfunc *h;
68947 		duk_instr_t *p, *p_start, *p_end;
68948 
68949 		h = (duk_hcompfunc *) duk_get_hobject(thr, -1);
68950 		p_start = (duk_instr_t *) DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, h);
68951 		p_end = (duk_instr_t *) DUK_HCOMPFUNC_GET_CODE_END(thr->heap, h);
68952 
68953 		p = p_start;
68954 		while (p < p_end) {
68955 			DUK_DDD(DUK_DDDPRINT("BC %04ld: %!I        ; 0x%08lx op=%ld (%!X) a=%ld b=%ld c=%ld",
68956 			                     (long) (p - p_start),
68957 			                     (duk_instr_t) (*p),
68958 			                     (unsigned long) (*p),
68959 			                     (long) DUK_DEC_OP(*p),
68960 			                     (long) DUK_DEC_OP(*p),
68961 			                     (long) DUK_DEC_A(*p),
68962 			                     (long) DUK_DEC_B(*p),
68963 			                     (long) DUK_DEC_C(*p)));
68964 			p++;
68965 		}
68966 	}
68967 #endif
68968 }
68969 
68970 /*
68971  *  Code emission helpers
68972  *
68973  *  Some emission helpers understand the range of target and source reg/const
68974  *  values and automatically emit shuffling code if necessary.  This is the
68975  *  case when the slot in question (A, B, C) is used in the standard way and
68976  *  for opcodes the emission helpers explicitly understand (like DUK_OP_MPUTOBJ).
68977  *
68978  *  The standard way is that:
68979  *    - slot A is a target register
68980  *    - slot B is a source register/constant
68981  *    - slot C is a source register/constant
68982  *
68983  *  If a slot is used in a non-standard way the caller must indicate this
68984  *  somehow.  If a slot is used as a target instead of a source (or vice
68985  *  versa), this can be indicated with a flag to trigger proper shuffling
68986  *  (e.g. DUK__EMIT_FLAG_B_IS_TARGET).  If the value in the slot is not
68987  *  register/const related at all, the caller must ensure that the raw value
68988  *  fits into the corresponding slot so as to not trigger shuffling.  The
68989  *  caller must set a "no shuffle" flag to ensure compilation fails if
68990  *  shuffling were to be triggered because of an internal error.
68991  *
68992  *  For slots B and C the raw slot size is 9 bits but one bit is reserved for
68993  *  the reg/const indicator.  To use the full 9-bit range for a raw value,
68994  *  shuffling must be disabled with the DUK__EMIT_FLAG_NO_SHUFFLE_{B,C} flag.
68995  *  Shuffling is only done for A, B, and C slots, not the larger BC or ABC slots.
68996  *
68997  *  There is call handling specific understanding in the A-B-C emitter to
68998  *  convert call setup and call instructions into indirect ones if necessary.
68999  */
69000 
69001 /* Code emission flags, passed in the 'opcode' field.  Opcode + flags
69002  * fit into 16 bits for now, so use duk_small_uint_t.
69003  */
69004 #define DUK__EMIT_FLAG_NO_SHUFFLE_A      (1 << 8)
69005 #define DUK__EMIT_FLAG_NO_SHUFFLE_B      (1 << 9)
69006 #define DUK__EMIT_FLAG_NO_SHUFFLE_C      (1 << 10)
69007 #define DUK__EMIT_FLAG_A_IS_SOURCE       (1 << 11)  /* slot A is a source (default: target) */
69008 #define DUK__EMIT_FLAG_B_IS_TARGET       (1 << 12)  /* slot B is a target (default: source) */
69009 #define DUK__EMIT_FLAG_C_IS_TARGET       (1 << 13)  /* slot C is a target (default: source) */
69010 #define DUK__EMIT_FLAG_BC_REGCONST       (1 << 14)  /* slots B and C are reg/const */
69011 #define DUK__EMIT_FLAG_RESERVE_JUMPSLOT  (1 << 15)  /* reserve a jumpslot after instr before target spilling, used for NEXTENUM */
69012 
69013 /* XXX: macro smaller than call? */
69014 DUK_LOCAL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx) {
69015 	duk_compiler_func *func;
69016 	func = &comp_ctx->curr_func;
69017 	return (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &func->bw_code) / sizeof(duk_compiler_instr));
69018 }
69019 
69020 DUK_LOCAL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc) {
69021 	DUK_ASSERT(pc >= 0);
69022 	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)));
69023 	return ((duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code)) + pc;
69024 }
69025 
69026 /* emit instruction; could return PC but that's not needed in the majority
69027  * of cases.
69028  */
69029 DUK_LOCAL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) {
69030 #if defined(DUK_USE_PC2LINE)
69031 	duk_int_t line;
69032 #endif
69033 	duk_compiler_instr *instr;
69034 
69035 	DUK_DDD(DUK_DDDPRINT("duk__emit: 0x%08lx curr_token.start_line=%ld prev_token.start_line=%ld pc=%ld --> %!I",
69036 	                     (unsigned long) ins,
69037 	                     (long) comp_ctx->curr_token.start_line,
69038 	                     (long) comp_ctx->prev_token.start_line,
69039 	                     (long) duk__get_current_pc(comp_ctx),
69040 	                     (duk_instr_t) ins));
69041 
69042 	instr = (duk_compiler_instr *) (void *) DUK_BW_ENSURE_GETPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
69043 	DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
69044 
69045 #if defined(DUK_USE_PC2LINE)
69046 	/* The line number tracking is a bit inconsistent right now, which
69047 	 * affects debugger accuracy.  Mostly call sites emit opcodes when
69048 	 * they have parsed a token (say a terminating semicolon) and called
69049 	 * duk__advance().  In this case the line number of the previous
69050 	 * token is the most accurate one (except in prologue where
69051 	 * prev_token.start_line is 0).  This is probably not 100% correct
69052 	 * right now.
69053 	 */
69054 	/* approximation, close enough */
69055 	line = comp_ctx->prev_token.start_line;
69056 	if (line == 0) {
69057 		line = comp_ctx->curr_token.start_line;
69058 	}
69059 #endif
69060 
69061 	instr->ins = ins;
69062 #if defined(DUK_USE_PC2LINE)
69063 	instr->line = (duk_uint32_t) line;
69064 #endif
69065 #if defined(DUK_USE_DEBUGGER_SUPPORT)
69066 	if (line < comp_ctx->curr_func.min_line) {
69067 		comp_ctx->curr_func.min_line = line;
69068 	}
69069 	if (line > comp_ctx->curr_func.max_line) {
69070 		comp_ctx->curr_func.max_line = line;
69071 	}
69072 #endif
69073 
69074 	/* Limit checks for bytecode byte size and line number. */
69075 	if (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) {
69076 		goto fail_bc_limit;
69077 	}
69078 #if defined(DUK_USE_PC2LINE) && defined(DUK_USE_ESBC_LIMITS)
69079 #if defined(DUK_USE_BUFLEN16)
69080 	/* Buffer length is bounded to 0xffff automatically, avoid compile warning. */
69081 	if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) {
69082 		goto fail_bc_limit;
69083 	}
69084 #else
69085 	if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) {
69086 		goto fail_bc_limit;
69087 	}
69088 #endif
69089 #endif
69090 
69091 	return;
69092 
69093   fail_bc_limit:
69094 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT);
69095 	DUK_WO_NORETURN(return;);
69096 }
69097 
69098 /* Update function min/max line from current token.  Needed to improve
69099  * function line range information for debugging, so that e.g. opening
69100  * curly brace is covered by line range even when no opcodes are emitted
69101  * for the line containing the brace.
69102  */
69103 DUK_LOCAL void duk__update_lineinfo_currtoken(duk_compiler_ctx *comp_ctx) {
69104 #if defined(DUK_USE_DEBUGGER_SUPPORT)
69105 	duk_int_t line;
69106 
69107 	line = comp_ctx->curr_token.start_line;
69108 	if (line == 0) {
69109 		return;
69110 	}
69111 	if (line < comp_ctx->curr_func.min_line) {
69112 		comp_ctx->curr_func.min_line = line;
69113 	}
69114 	if (line > comp_ctx->curr_func.max_line) {
69115 		comp_ctx->curr_func.max_line = line;
69116 	}
69117 #else
69118 	DUK_UNREF(comp_ctx);
69119 #endif
69120 }
69121 
69122 DUK_LOCAL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op) {
69123 	duk__emit(comp_ctx, DUK_ENC_OP_ABC(op, 0));
69124 }
69125 
69126 /* Important main primitive. */
69127 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) {
69128 	duk_instr_t ins = 0;
69129 	duk_int_t a_out = -1;
69130 	duk_int_t b_out = -1;
69131 	duk_int_t c_out = -1;
69132 	duk_int_t tmp;
69133 	duk_small_uint_t op = op_flags & 0xffU;
69134 
69135 	DUK_DDD(DUK_DDDPRINT("emit: op_flags=%04lx, a=%ld, b=%ld, c=%ld",
69136 	                     (unsigned long) op_flags, (long) a, (long) b, (long) c));
69137 
69138 	/* We could rely on max temp/const checks: if they don't exceed BC
69139 	 * limit, nothing here can either (just asserts would be enough).
69140 	 * Currently we check for the limits, which provides additional
69141 	 * protection against creating invalid bytecode due to compiler
69142 	 * bugs.
69143 	 */
69144 
69145 	DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN);  /* unsigned */
69146 	DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
69147 	DUK_ASSERT(DUK__ISREG(a));
69148 	DUK_ASSERT(b != -1);  /* Not 'none'. */
69149 	DUK_ASSERT(c != -1);  /* Not 'none'. */
69150 
69151 	/* Input shuffling happens before the actual operation, while output
69152 	 * shuffling happens afterwards.  Output shuffling decisions are still
69153 	 * made at the same time to reduce branch clutter; output shuffle decisions
69154 	 * are recorded into X_out variables.
69155 	 */
69156 
69157 	/* Slot A: currently no support for reg/const. */
69158 
69159 #if defined(DUK_USE_SHUFFLE_TORTURE)
69160 	if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
69161 #else
69162 	if (a <= DUK_BC_A_MAX) {
69163 #endif
69164 		;
69165 	} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
69166 		DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but shuffle prohibited, a: %ld", (long) a));
69167 		goto error_outofregs;
69168 	} else if (a <= DUK_BC_BC_MAX) {
69169 		comp_ctx->curr_func.needs_shuffle = 1;
69170 		tmp = comp_ctx->curr_func.shuffle1;
69171 		if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
69172 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
69173 		} else {
69174 			/* Output shuffle needed after main operation */
69175 			a_out = a;
69176 
69177 			/* The DUK_OP_CSVAR output shuffle assumes shuffle registers are
69178 			 * consecutive.
69179 			 */
69180 			DUK_ASSERT((comp_ctx->curr_func.shuffle1 == 0 && comp_ctx->curr_func.shuffle2 == 0) ||
69181 			           (comp_ctx->curr_func.shuffle2 == comp_ctx->curr_func.shuffle1 + 1));
69182 			if (op == DUK_OP_CSVAR) {
69183 				/* For CSVAR the limit is one smaller because output shuffle
69184 				 * must be able to express 'a + 1' in BC.
69185 				 */
69186 				if (a + 1 > DUK_BC_BC_MAX) {
69187 					goto error_outofregs;
69188 				}
69189 			}
69190 		}
69191 		a = tmp;
69192 	} else {
69193 		DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but does not fit into BC, a: %ld", (long) a));
69194 		goto error_outofregs;
69195 	}
69196 
69197 	/* Slot B: reg/const support, mapped to bit 0 of opcode. */
69198 
69199 	if ((b & DUK__CONST_MARKER) != 0) {
69200 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) == 0);
69201 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
69202 		b = b & ~DUK__CONST_MARKER;
69203 #if defined(DUK_USE_SHUFFLE_TORTURE)
69204 		if (0) {
69205 #else
69206 		if (b <= 0xff) {
69207 #endif
69208 			if (op_flags & DUK__EMIT_FLAG_BC_REGCONST) {
69209 				/* Opcode follows B/C reg/const convention. */
69210 				DUK_ASSERT((op & 0x01) == 0);
69211 				ins |= DUK_ENC_OP_A_B_C(0x01, 0, 0, 0);  /* const flag for B */
69212 			} else {
69213 				DUK_D(DUK_DPRINT("B is const, opcode is not B/C reg/const: %x", op_flags));
69214 			}
69215 		} else if (b <= DUK_BC_BC_MAX) {
69216 			comp_ctx->curr_func.needs_shuffle = 1;
69217 			tmp = comp_ctx->curr_func.shuffle2;
69218 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, b));
69219 			b = tmp;
69220 		} else {
69221 			DUK_D(DUK_DPRINT("out of regs: 'b' (const) needs shuffling but does not fit into BC, b: %ld", (long) b));
69222 			goto error_outofregs;
69223 		}
69224 	} else {
69225 #if defined(DUK_USE_SHUFFLE_TORTURE)
69226 		if (b <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B)) {
69227 #else
69228 		if (b <= 0xff) {
69229 #endif
69230 			;
69231 		} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) {
69232 			if (b > DUK_BC_B_MAX) {
69233 				/* Note: 0xff != DUK_BC_B_MAX */
69234 				DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but shuffle prohibited, b: %ld", (long) b));
69235 				goto error_outofregs;
69236 			}
69237 		} else if (b <= DUK_BC_BC_MAX) {
69238 			comp_ctx->curr_func.needs_shuffle = 1;
69239 			tmp = comp_ctx->curr_func.shuffle2;
69240 			if (op_flags & DUK__EMIT_FLAG_B_IS_TARGET) {
69241 				/* Output shuffle needed after main operation */
69242 				b_out = b;
69243 			}
69244 			if (!(op_flags & DUK__EMIT_FLAG_B_IS_TARGET)) {
69245 				if (op == DUK_OP_MPUTOBJ || op == DUK_OP_MPUTARR) {
69246 					/* Special handling for MPUTOBJ/MPUTARR shuffling.
69247 					 * For each, slot B identifies the first register of a range
69248 					 * of registers, so normal shuffling won't work.  Instead,
69249 					 * an indirect version of the opcode is used.
69250 					 */
69251 					DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
69252 					duk__emit_load_int32_noshuffle(comp_ctx, tmp, b);
69253 					DUK_ASSERT(DUK_OP_MPUTOBJI == DUK_OP_MPUTOBJ + 1);
69254 					DUK_ASSERT(DUK_OP_MPUTARRI == DUK_OP_MPUTARR + 1);
69255 					op_flags++;  /* indirect opcode follows direct */
69256 				} else {
69257 					duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, b));
69258 				}
69259 			}
69260 			b = tmp;
69261 		} else {
69262 			DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but does not fit into BC, b: %ld", (long) b));
69263 			goto error_outofregs;
69264 		}
69265 	}
69266 
69267 	/* Slot C: reg/const support, mapped to bit 1 of opcode. */
69268 
69269 	if ((c & DUK__CONST_MARKER) != 0) {
69270 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) == 0);
69271 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_C_IS_TARGET) == 0);
69272 		c = c & ~DUK__CONST_MARKER;
69273 #if defined(DUK_USE_SHUFFLE_TORTURE)
69274 		if (0) {
69275 #else
69276 		if (c <= 0xff) {
69277 #endif
69278 			if (op_flags & DUK__EMIT_FLAG_BC_REGCONST) {
69279 				/* Opcode follows B/C reg/const convention. */
69280 				DUK_ASSERT((op & 0x02) == 0);
69281 				ins |= DUK_ENC_OP_A_B_C(0x02, 0, 0, 0);  /* const flag for C */
69282 			} else {
69283 				DUK_D(DUK_DPRINT("C is const, opcode is not B/C reg/const: %x", op_flags));
69284 			}
69285 		} else if (c <= DUK_BC_BC_MAX) {
69286 			comp_ctx->curr_func.needs_shuffle = 1;
69287 			tmp = comp_ctx->curr_func.shuffle3;
69288 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, c));
69289 			c = tmp;
69290 		} else {
69291 			DUK_D(DUK_DPRINT("out of regs: 'c' (const) needs shuffling but does not fit into BC, c: %ld", (long) c));
69292 			goto error_outofregs;
69293 		}
69294 	} else {
69295 #if defined(DUK_USE_SHUFFLE_TORTURE)
69296 		if (c <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C)) {
69297 #else
69298 		if (c <= 0xff) {
69299 #endif
69300 			;
69301 		} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) {
69302 			if (c > DUK_BC_C_MAX) {
69303 				/* Note: 0xff != DUK_BC_C_MAX */
69304 				DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but shuffle prohibited, c: %ld", (long) c));
69305 				goto error_outofregs;
69306 			}
69307 		} else if (c <= DUK_BC_BC_MAX) {
69308 			comp_ctx->curr_func.needs_shuffle = 1;
69309 			tmp = comp_ctx->curr_func.shuffle3;
69310 			if (op_flags & DUK__EMIT_FLAG_C_IS_TARGET) {
69311 				/* Output shuffle needed after main operation */
69312 				c_out = c;
69313 			} else {
69314 				duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, c));
69315 			}
69316 			c = tmp;
69317 		} else {
69318 			DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but does not fit into BC, c: %ld", (long) c));
69319 			goto error_outofregs;
69320 		}
69321 	}
69322 
69323 	/* Main operation */
69324 
69325 	DUK_ASSERT(a >= DUK_BC_A_MIN);
69326 	DUK_ASSERT(a <= DUK_BC_A_MAX);
69327 	DUK_ASSERT(b >= DUK_BC_B_MIN);
69328 	DUK_ASSERT(b <= DUK_BC_B_MAX);
69329 	DUK_ASSERT(c >= DUK_BC_C_MIN);
69330 	DUK_ASSERT(c <= DUK_BC_C_MAX);
69331 
69332 	ins |= DUK_ENC_OP_A_B_C(op_flags & 0xff, a, b, c);
69333 	duk__emit(comp_ctx, ins);
69334 
69335 	/* NEXTENUM needs a jump slot right after the main instruction.
69336 	 * When the JUMP is taken, output spilling is not needed so this
69337 	 * workaround is possible.  The jump slot PC is exceptionally
69338 	 * plumbed through comp_ctx to minimize call sites.
69339 	 */
69340 	if (op_flags & DUK__EMIT_FLAG_RESERVE_JUMPSLOT) {
69341 		comp_ctx->emit_jumpslot_pc = duk__get_current_pc(comp_ctx);
69342 		duk__emit_abc(comp_ctx, DUK_OP_JUMP, 0);
69343 	}
69344 
69345 	/* Output shuffling: only one output register is realistically possible.
69346 	 *
69347 	 * (Zero would normally be an OK marker value: if the target register
69348 	 * was zero, it would never be shuffled.  But with DUK_USE_SHUFFLE_TORTURE
69349 	 * this is no longer true, so use -1 as a marker instead.)
69350 	 */
69351 
69352 	if (a_out >= 0) {
69353 		DUK_ASSERT(b_out < 0);
69354 		DUK_ASSERT(c_out < 0);
69355 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, a, a_out));
69356 
69357 		if (op == DUK_OP_CSVAR) {
69358 			/* Special handling for CSVAR shuffling.  The variable lookup
69359 			 * results in a <value, this binding> pair in successive
69360 			 * registers so use two shuffle registers and two output
69361 			 * loads.  (In practice this is dead code because temp/const
69362 			 * limit is reached first.)
69363 			 */
69364 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, a + 1, a_out + 1));
69365 		}
69366 	} else if (b_out >= 0) {
69367 		DUK_ASSERT(a_out < 0);
69368 		DUK_ASSERT(c_out < 0);
69369 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, b, b_out));
69370 	} else if (c_out >= 0) {
69371 		DUK_ASSERT(b_out < 0);
69372 		DUK_ASSERT(c_out < 0);
69373 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, c, c_out));
69374 	}
69375 
69376 	return;
69377 
69378  error_outofregs:
69379 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
69380 	DUK_WO_NORETURN(return;);
69381 }
69382 
69383 /* For many of the helpers below it'd be technically correct to add
69384  * "no shuffle" flags for parameters passed in as zero.  For example,
69385  * duk__emit_a_b() should call duk__emit_a_b_c() with C set to 0, and
69386  * DUK__EMIT_FLAG_NO_SHUFFLE_C added to op_flags.  However, since the
69387  * C value is 0, it'll never get shuffled so adding the flag is just
69388  * unnecessary additional code.  This is unfortunately not true for
69389  * "shuffle torture" mode which needs special handling.
69390  */
69391 
69392 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) {
69393 #if defined(DUK_USE_SHUFFLE_TORTURE)
69394 	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_C;
69395 #endif
69396 	duk__emit_a_b_c(comp_ctx, op_flags, a, b, 0);
69397 }
69398 
69399 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) {
69400 #if defined(DUK_USE_SHUFFLE_TORTURE)
69401 	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_A;
69402 #endif
69403 	duk__emit_a_b_c(comp_ctx, op_flags, 0, b, c);
69404 }
69405 
69406 #if 0  /* unused */
69407 DUK_LOCAL void duk__emit_a(duk_compiler_ctx *comp_ctx, int op_flags, int a) {
69408 #if defined(DUK_USE_SHUFFLE_TORTURE)
69409 	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_B | DUK__EMIT_FLAG_NO_SHUFFLE_C;
69410 #endif
69411 	duk__emit_a_b_c(comp_ctx, op_flags, a, 0, 0);
69412 }
69413 #endif
69414 
69415 #if 0  /* unused */
69416 DUK_LOCAL void duk__emit_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b) {
69417 #if defined(DUK_USE_SHUFFLE_TORTURE)
69418 	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_NO_SHUFFLE_C;
69419 #endif
69420 	duk__emit_a_b_c(comp_ctx, op_flags, 0, b, 0);
69421 }
69422 #endif
69423 
69424 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) {
69425 	duk_instr_t ins;
69426 	duk_int_t tmp;
69427 
69428 	/* allow caller to give a const number with the DUK__CONST_MARKER */
69429 	DUK_ASSERT(bc != -1);  /* Not 'none'. */
69430 	bc = bc & (~DUK__CONST_MARKER);
69431 
69432 	DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN);  /* unsigned */
69433 	DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
69434 	DUK_ASSERT(bc >= DUK_BC_BC_MIN);
69435 	DUK_ASSERT(bc <= DUK_BC_BC_MAX);
69436 	DUK_ASSERT((bc & DUK__CONST_MARKER) == 0);
69437 
69438 	if (bc <= DUK_BC_BC_MAX) {
69439 		;
69440 	} else {
69441 		/* No BC shuffling now. */
69442 		goto error_outofregs;
69443 	}
69444 
69445 #if defined(DUK_USE_SHUFFLE_TORTURE)
69446 	if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
69447 #else
69448 	if (a <= DUK_BC_A_MAX) {
69449 #endif
69450 		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, a, bc);
69451 		duk__emit(comp_ctx, ins);
69452 	} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
69453 		goto error_outofregs;
69454 	} else if ((op_flags & 0xf0U) == DUK_OP_CALL0) {
69455 		comp_ctx->curr_func.needs_shuffle = 1;
69456 		tmp = comp_ctx->curr_func.shuffle1;
69457 		duk__emit_load_int32_noshuffle(comp_ctx, tmp, a);
69458 		op_flags |= DUK_BC_CALL_FLAG_INDIRECT;
69459 		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, tmp, bc);
69460 		duk__emit(comp_ctx, ins);
69461 	} else if (a <= DUK_BC_BC_MAX) {
69462 		comp_ctx->curr_func.needs_shuffle = 1;
69463 		tmp = comp_ctx->curr_func.shuffle1;
69464 		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, tmp, bc);
69465 		if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
69466 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
69467 			duk__emit(comp_ctx, ins);
69468 		} else {
69469 			duk__emit(comp_ctx, ins);
69470 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, tmp, a));
69471 		}
69472 	} else {
69473 		goto error_outofregs;
69474 	}
69475 	return;
69476 
69477  error_outofregs:
69478 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
69479 	DUK_WO_NORETURN(return;);
69480 }
69481 
69482 DUK_LOCAL void duk__emit_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t bc) {
69483 #if defined(DUK_USE_SHUFFLE_TORTURE)
69484 	op |= DUK__EMIT_FLAG_NO_SHUFFLE_A;
69485 #endif
69486 	duk__emit_a_bc(comp_ctx, op, 0, bc);
69487 }
69488 
69489 DUK_LOCAL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc) {
69490 	duk_instr_t ins;
69491 
69492 	DUK_ASSERT_DISABLE(op >= DUK_BC_OP_MIN);  /* unsigned */
69493 	DUK_ASSERT(op <= DUK_BC_OP_MAX);
69494 	DUK_ASSERT_DISABLE(abc >= DUK_BC_ABC_MIN);  /* unsigned */
69495 	DUK_ASSERT(abc <= DUK_BC_ABC_MAX);
69496 	DUK_ASSERT((abc & DUK__CONST_MARKER) == 0);
69497 	DUK_ASSERT(abc != -1);  /* Not 'none'. */
69498 
69499 	if (abc <= DUK_BC_ABC_MAX) {
69500 		;
69501 	} else {
69502 		goto error_outofregs;
69503 	}
69504 	ins = DUK_ENC_OP_ABC(op, abc);
69505 	DUK_DDD(DUK_DDDPRINT("duk__emit_abc: 0x%08lx line=%ld pc=%ld op=%ld (%!X) abc=%ld (%!I)",
69506 	                     (unsigned long) ins, (long) comp_ctx->curr_token.start_line,
69507 	                     (long) duk__get_current_pc(comp_ctx), (long) op, (long) op,
69508 	                     (long) abc, (duk_instr_t) ins));
69509 	duk__emit(comp_ctx, ins);
69510 	return;
69511 
69512  error_outofregs:
69513 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
69514 	DUK_WO_NORETURN(return;);
69515 }
69516 
69517 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) {
69518 	/* XXX: Shuffling support could be implemented here so that LDINT+LDINTX
69519 	 * would only shuffle once (instead of twice).  The current code works
69520 	 * though, and has a smaller compiler footprint.
69521 	 */
69522 
69523 	if ((val >= (duk_int32_t) DUK_BC_BC_MIN - (duk_int32_t) DUK_BC_LDINT_BIAS) &&
69524 	    (val <= (duk_int32_t) DUK_BC_BC_MAX - (duk_int32_t) DUK_BC_LDINT_BIAS)) {
69525 		DUK_DDD(DUK_DDDPRINT("emit LDINT to reg %ld for %ld", (long) reg, (long) val));
69526 		duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (val + (duk_int32_t) DUK_BC_LDINT_BIAS));
69527 	} else {
69528 		duk_int32_t hi = val >> DUK_BC_LDINTX_SHIFT;
69529 		duk_int32_t lo = val & ((((duk_int32_t) 1) << DUK_BC_LDINTX_SHIFT) - 1);
69530 		DUK_ASSERT(lo >= 0);
69531 		DUK_DDD(DUK_DDDPRINT("emit LDINT+LDINTX to reg %ld for %ld -> hi %ld, lo %ld",
69532 		                     (long) reg, (long) val, (long) hi, (long) lo));
69533 		duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (hi + (duk_int32_t) DUK_BC_LDINT_BIAS));
69534 		duk__emit_a_bc(comp_ctx, DUK_OP_LDINTX | op_flags, reg, (duk_regconst_t) lo);
69535 	}
69536 }
69537 
69538 DUK_LOCAL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
69539 	duk__emit_load_int32_raw(comp_ctx, reg, val, 0 /*op_flags*/);
69540 }
69541 
69542 #if defined(DUK_USE_SHUFFLE_TORTURE)
69543 /* Used by duk__emit*() calls so that we don't shuffle the loadints that
69544  * are needed to handle indirect opcodes.
69545  */
69546 DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
69547 	duk__emit_load_int32_raw(comp_ctx, reg, val, DUK__EMIT_FLAG_NO_SHUFFLE_A /*op_flags*/);
69548 }
69549 #else
69550 DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
69551 	/* When torture not enabled, can just use the same helper because
69552 	 * 'reg' won't get spilled.
69553 	 */
69554 	DUK_ASSERT(reg <= DUK_BC_A_MAX);
69555 	duk__emit_load_int32(comp_ctx, reg, val);
69556 }
69557 #endif
69558 
69559 DUK_LOCAL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc) {
69560 	duk_int_t curr_pc;
69561 	duk_int_t offset;
69562 
69563 	curr_pc = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
69564 	offset = (duk_int_t) target_pc - (duk_int_t) curr_pc - 1;
69565 	DUK_ASSERT(offset + DUK_BC_JUMP_BIAS >= DUK_BC_ABC_MIN);
69566 	DUK_ASSERT(offset + DUK_BC_JUMP_BIAS <= DUK_BC_ABC_MAX);
69567 	duk__emit_abc(comp_ctx, DUK_OP_JUMP, (duk_regconst_t) (offset + DUK_BC_JUMP_BIAS));
69568 }
69569 
69570 DUK_LOCAL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx) {
69571 	duk_int_t ret;
69572 
69573 	ret = duk__get_current_pc(comp_ctx);  /* useful for patching jumps later */
69574 	duk__emit_op_only(comp_ctx, DUK_OP_JUMP);
69575 	return ret;
69576 }
69577 
69578 /* Insert an empty jump in the middle of code emitted earlier.  This is
69579  * currently needed for compiling for-in.
69580  */
69581 DUK_LOCAL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
69582 #if defined(DUK_USE_PC2LINE)
69583 	duk_int_t line;
69584 #endif
69585 	duk_compiler_instr *instr;
69586 	duk_size_t offset;
69587 
69588 	DUK_ASSERT(jump_pc >= 0);
69589 	offset = (duk_size_t) jump_pc * sizeof(duk_compiler_instr);
69590 	instr = (duk_compiler_instr *) (void *)
69591 	        DUK_BW_INSERT_ENSURE_AREA(comp_ctx->thr,
69592 	                                  &comp_ctx->curr_func.bw_code,
69593 	                                  offset,
69594 	                                  sizeof(duk_compiler_instr));
69595 
69596 #if defined(DUK_USE_PC2LINE)
69597 	line = comp_ctx->curr_token.start_line;  /* approximation, close enough */
69598 #endif
69599 	instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, 0);
69600 #if defined(DUK_USE_PC2LINE)
69601 	instr->line = (duk_uint32_t) line;
69602 #endif
69603 
69604 	DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
69605 	if (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) {
69606 		goto fail_bc_limit;
69607 	}
69608 	return;
69609 
69610   fail_bc_limit:
69611 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT);
69612 	DUK_WO_NORETURN(return;);
69613 }
69614 
69615 /* Does not assume that jump_pc contains a DUK_OP_JUMP previously; this is intentional
69616  * to allow e.g. an INVALID opcode be overwritten with a JUMP (label management uses this).
69617  */
69618 DUK_LOCAL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc) {
69619 	duk_compiler_instr *instr;
69620 	duk_int_t offset;
69621 
69622 	/* allow negative PCs, behave as a no-op */
69623 	if (jump_pc < 0) {
69624 		DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): nop call, jump_pc=%ld (<0), target_pc=%ld",
69625 		                     (long) jump_pc, (long) target_pc));
69626 		return;
69627 	}
69628 	DUK_ASSERT(jump_pc >= 0);
69629 
69630 	/* XXX: range assert */
69631 	instr = duk__get_instr_ptr(comp_ctx, jump_pc);
69632 	DUK_ASSERT(instr != NULL);
69633 
69634 	/* XXX: range assert */
69635 	offset = target_pc - jump_pc - 1;
69636 
69637 	instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, offset + DUK_BC_JUMP_BIAS);
69638 	DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): jump_pc=%ld, target_pc=%ld, offset=%ld",
69639 	                     (long) jump_pc, (long) target_pc, (long) offset));
69640 }
69641 
69642 DUK_LOCAL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
69643 	duk__patch_jump(comp_ctx, jump_pc, duk__get_current_pc(comp_ctx));
69644 }
69645 
69646 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) {
69647 	duk_compiler_instr *instr;
69648 
69649 	DUK_ASSERT(DUK__ISREG(reg_catch));
69650 
69651 	instr = duk__get_instr_ptr(comp_ctx, ldconst_pc);
69652 	DUK_ASSERT(DUK_DEC_OP(instr->ins) == DUK_OP_LDCONST);
69653 	DUK_ASSERT(instr != NULL);
69654 	if (const_varname & DUK__CONST_MARKER) {
69655 		/* Have a catch variable. */
69656 		const_varname = const_varname & (~DUK__CONST_MARKER);
69657 		if (reg_catch > DUK_BC_BC_MAX || const_varname > DUK_BC_BC_MAX) {
69658 			/* Catch attempts to use out-of-range reg/const.  Without this
69659 			 * check Duktape 0.12.0 could generate invalid code which caused
69660 			 * an assert failure on execution.  This error is triggered e.g.
69661 			 * for functions with a lot of constants and a try-catch statement.
69662 			 * Shuffling or opcode semantics change is needed to fix the issue.
69663 			 * See: test-bug-trycatch-many-constants.js.
69664 			 */
69665 			DUK_D(DUK_DPRINT("failed to patch trycatch: flags=%ld, reg_catch=%ld, const_varname=%ld (0x%08lx)",
69666 			                 (long) flags, (long) reg_catch, (long) const_varname, (long) const_varname));
69667 			DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
69668 			DUK_WO_NORETURN(return;);
69669 		}
69670 		instr->ins |= DUK_ENC_OP_A_BC(0, 0, const_varname);
69671 	} else {
69672 		/* No catch variable, e.g. a try-finally; replace LDCONST with
69673 		 * NOP to avoid a bogus LDCONST.
69674 		 */
69675 		instr->ins = DUK_ENC_OP(DUK_OP_NOP);
69676 	}
69677 
69678 	instr = duk__get_instr_ptr(comp_ctx, trycatch_pc);
69679 	DUK_ASSERT(instr != NULL);
69680 	DUK_ASSERT_DISABLE(flags >= DUK_BC_A_MIN);
69681 	DUK_ASSERT(flags <= DUK_BC_A_MAX);
69682 	instr->ins = DUK_ENC_OP_A_BC(DUK_OP_TRYCATCH, flags, reg_catch);
69683 }
69684 
69685 DUK_LOCAL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
69686 	duk_small_uint_t op;
69687 
69688 	op = DUK__ISREG(regconst) ? DUK_OP_IFFALSE_R : DUK_OP_IFFALSE_C;
69689 	duk__emit_bc(comp_ctx, op, regconst);  /* helper will remove const flag */
69690 }
69691 
69692 DUK_LOCAL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
69693 	duk_small_uint_t op;
69694 
69695 	op = DUK__ISREG(regconst) ? DUK_OP_IFTRUE_R : DUK_OP_IFTRUE_C;
69696 	duk__emit_bc(comp_ctx, op, regconst);  /* helper will remove const flag */
69697 }
69698 
69699 DUK_LOCAL void duk__emit_invalid(duk_compiler_ctx *comp_ctx) {
69700 	duk__emit_op_only(comp_ctx, DUK_OP_INVALID);
69701 }
69702 
69703 /*
69704  *  Peephole optimizer for finished bytecode.
69705  *
69706  *  Does not remove opcodes; currently only straightens out unconditional
69707  *  jump chains which are generated by several control structures.
69708  */
69709 
69710 DUK_LOCAL void duk__peephole_optimize_bytecode(duk_compiler_ctx *comp_ctx) {
69711 	duk_compiler_instr *bc;
69712 	duk_small_uint_t iter;
69713 	duk_int_t i, n;
69714 	duk_int_t count_opt;
69715 
69716 	bc = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code);
69717 #if defined(DUK_USE_BUFLEN16)
69718 	/* No need to assert, buffer size maximum is 0xffff. */
69719 #else
69720 	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 */
69721 #endif
69722 	n = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
69723 
69724 	for (iter = 0; iter < DUK_COMPILER_PEEPHOLE_MAXITER; iter++) {
69725 		count_opt = 0;
69726 
69727 		for (i = 0; i < n; i++) {
69728 			duk_instr_t ins;
69729 			duk_int_t target_pc1;
69730 			duk_int_t target_pc2;
69731 
69732 			ins = bc[i].ins;
69733 			if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
69734 				continue;
69735 			}
69736 
69737 			target_pc1 = i + 1 + (duk_int_t) DUK_DEC_ABC(ins) - (duk_int_t) DUK_BC_JUMP_BIAS;
69738 			DUK_DDD(DUK_DDDPRINT("consider jump at pc %ld; target_pc=%ld", (long) i, (long) target_pc1));
69739 			DUK_ASSERT(target_pc1 >= 0);
69740 			DUK_ASSERT(target_pc1 < n);
69741 
69742 			/* Note: if target_pc1 == i, we'll optimize a jump to itself.
69743 			 * This does not need to be checked for explicitly; the case
69744 			 * is rare and max iter breaks us out.
69745 			 */
69746 
69747 			ins = bc[target_pc1].ins;
69748 			if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
69749 				continue;
69750 			}
69751 
69752 			target_pc2 = target_pc1 + 1 + (duk_int_t) DUK_DEC_ABC(ins) - (duk_int_t) DUK_BC_JUMP_BIAS;
69753 
69754 			DUK_DDD(DUK_DDDPRINT("optimizing jump at pc %ld; old target is %ld -> new target is %ld",
69755 			                     (long) i, (long) target_pc1, (long) target_pc2));
69756 
69757 			bc[i].ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, target_pc2 - (i + 1) + DUK_BC_JUMP_BIAS);
69758 
69759 			count_opt++;
69760 		}
69761 
69762 		DUK_DD(DUK_DDPRINT("optimized %ld jumps on peephole round %ld", (long) count_opt, (long) (iter + 1)));
69763 
69764 		if (count_opt == 0) {
69765 			break;
69766 		}
69767 	}
69768 }
69769 
69770 /*
69771  *  Intermediate value helpers
69772  */
69773 
69774 /* Flags for intermediate value coercions.  A flag for using a forced reg
69775  * is not needed, the forced_reg argument suffices and generates better
69776  * code (it is checked as it is used).
69777  */
69778 /* XXX: DUK__IVAL_FLAG_REQUIRE_SHORT is passed but not currently implemented
69779  * by ispec/ivalue operations.
69780  */
69781 #define DUK__IVAL_FLAG_ALLOW_CONST          (1 << 0)  /* allow a constant to be returned */
69782 #define DUK__IVAL_FLAG_REQUIRE_TEMP         (1 << 1)  /* require a (mutable) temporary as a result (or a const if allowed) */
69783 #define DUK__IVAL_FLAG_REQUIRE_SHORT        (1 << 2)  /* require a short (8-bit) reg/const which fits into bytecode B/C slot */
69784 
69785 /* XXX: some code might benefit from DUK__SETTEMP_IFTEMP(thr,x) */
69786 
69787 #if 0  /* enable manually for dumping */
69788 #define DUK__DUMP_ISPEC(compctx,ispec) do { duk__dump_ispec((compctx), (ispec)); } while (0)
69789 #define DUK__DUMP_IVALUE(compctx,ivalue) do { duk__dump_ivalue((compctx), (ivalue)); } while (0)
69790 
69791 DUK_LOCAL void duk__dump_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *x) {
69792 	DUK_D(DUK_DPRINT("ispec dump: t=%ld regconst=0x%08lx, valstack_idx=%ld, value=%!T",
69793 	                 (long) x->t, (unsigned long) x->regconst, (long) x->valstack_idx,
69794 	                 duk_get_tval(comp_ctx->thr, x->valstack_idx)));
69795 }
69796 DUK_LOCAL void duk__dump_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
69797 	DUK_D(DUK_DPRINT("ivalue dump: t=%ld op=%ld "
69798 	                 "x1={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T} "
69799 	                 "x2={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T}",
69800 		         (long) x->t, (long) x->op,
69801 	                 (long) x->x1.t, (unsigned long) x->x1.regconst, (long) x->x1.valstack_idx,
69802 	                 duk_get_tval(comp_ctx->thr, x->x1.valstack_idx),
69803 	                 (long) x->x2.t, (unsigned long) x->x2.regconst, (long) x->x2.valstack_idx,
69804 	                 duk_get_tval(comp_ctx->thr, x->x2.valstack_idx)));
69805 }
69806 #else
69807 #define DUK__DUMP_ISPEC(comp_ctx,x) do {} while (0)
69808 #define DUK__DUMP_IVALUE(comp_ctx,x) do {} while (0)
69809 #endif
69810 
69811 DUK_LOCAL void duk__ivalue_regconst(duk_ivalue *x, duk_regconst_t regconst) {
69812 	x->t = DUK_IVAL_PLAIN;
69813 	x->x1.t = DUK_ISPEC_REGCONST;
69814 	x->x1.regconst = regconst;
69815 }
69816 
69817 DUK_LOCAL void duk__ivalue_plain_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
69818 	x->t = DUK_IVAL_PLAIN;
69819 	x->x1.t = DUK_ISPEC_VALUE;
69820 	duk_replace(comp_ctx->thr, x->x1.valstack_idx);
69821 }
69822 
69823 DUK_LOCAL void duk__ivalue_var_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
69824 	x->t = DUK_IVAL_VAR;
69825 	x->x1.t = DUK_ISPEC_VALUE;
69826 	duk_replace(comp_ctx->thr, x->x1.valstack_idx);
69827 }
69828 
69829 DUK_LOCAL_DECL void duk__ivalue_var_hstring(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_hstring *h) {
69830 	DUK_ASSERT(h != NULL);
69831 	duk_push_hstring(comp_ctx->thr, h);
69832 	duk__ivalue_var_fromstack(comp_ctx, x);
69833 }
69834 
69835 DUK_LOCAL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst) {
69836 	dst->t = src->t;
69837 	dst->regconst = src->regconst;
69838 	duk_copy(comp_ctx->thr, src->valstack_idx, dst->valstack_idx);
69839 }
69840 
69841 DUK_LOCAL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst) {
69842 	dst->t = src->t;
69843 	dst->op = src->op;
69844 	dst->x1.t = src->x1.t;
69845 	dst->x1.regconst = src->x1.regconst;
69846 	dst->x2.t = src->x2.t;
69847 	dst->x2.regconst = src->x2.regconst;
69848 	duk_copy(comp_ctx->thr, src->x1.valstack_idx, dst->x1.valstack_idx);
69849 	duk_copy(comp_ctx->thr, src->x2.valstack_idx, dst->x2.valstack_idx);
69850 }
69851 
69852 DUK_LOCAL duk_regconst_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num) {
69853 	duk_regconst_t res;
69854 
69855 	res = comp_ctx->curr_func.temp_next;
69856 	comp_ctx->curr_func.temp_next += num;
69857 
69858 	if (comp_ctx->curr_func.temp_next > DUK__MAX_TEMPS) {  /* == DUK__MAX_TEMPS is OK */
69859 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_TEMP_LIMIT);
69860 		DUK_WO_NORETURN(return 0;);
69861 	}
69862 
69863 	/* maintain highest 'used' temporary, needed to figure out nregs of function */
69864 	if (comp_ctx->curr_func.temp_next > comp_ctx->curr_func.temp_max) {
69865 		comp_ctx->curr_func.temp_max = comp_ctx->curr_func.temp_next;
69866 	}
69867 
69868 	return res;
69869 }
69870 
69871 DUK_LOCAL duk_regconst_t duk__alloctemp(duk_compiler_ctx *comp_ctx) {
69872 	return duk__alloctemps(comp_ctx, 1);
69873 }
69874 
69875 DUK_LOCAL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_regconst_t temp_next) {
69876 	comp_ctx->curr_func.temp_next = temp_next;
69877 	if (temp_next > comp_ctx->curr_func.temp_max) {
69878 		comp_ctx->curr_func.temp_max = temp_next;
69879 	}
69880 }
69881 
69882 /* get const for value at valstack top */
69883 DUK_LOCAL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx) {
69884 	duk_hthread *thr = comp_ctx->thr;
69885 	duk_compiler_func *f = &comp_ctx->curr_func;
69886 	duk_tval *tv1;
69887 	duk_int_t i, n, n_check;
69888 
69889 	n = (duk_int_t) duk_get_length(thr, f->consts_idx);
69890 
69891 	tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
69892 	DUK_ASSERT(tv1 != NULL);
69893 
69894 #if defined(DUK_USE_FASTINT)
69895 	/* Explicit check for fastint downgrade. */
69896 	DUK_TVAL_CHKFAST_INPLACE_SLOW(tv1);
69897 #endif
69898 
69899 	/* Sanity workaround for handling functions with a large number of
69900 	 * constants at least somewhat reasonably.  Otherwise checking whether
69901 	 * we already have the constant would grow very slow (as it is O(N^2)).
69902 	 */
69903 	n_check = (n > DUK__GETCONST_MAX_CONSTS_CHECK ? DUK__GETCONST_MAX_CONSTS_CHECK : n);
69904 	for (i = 0; i < n_check; i++) {
69905 		duk_tval *tv2 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, f->h_consts, i);
69906 
69907 		/* Strict equality is NOT enough, because we cannot use the same
69908 		 * constant for e.g. +0 and -0.
69909 		 */
69910 		if (duk_js_samevalue(tv1, tv2)) {
69911 			DUK_DDD(DUK_DDDPRINT("reused existing constant for %!T -> const index %ld",
69912 			                     (duk_tval *) tv1, (long) i));
69913 			duk_pop(thr);
69914 			return (duk_regconst_t) i | (duk_regconst_t) DUK__CONST_MARKER;
69915 		}
69916 	}
69917 
69918 	if (n > DUK__MAX_CONSTS) {
69919 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_CONST_LIMIT);
69920 		DUK_WO_NORETURN(return 0;);
69921 	}
69922 
69923 	DUK_DDD(DUK_DDDPRINT("allocating new constant for %!T -> const index %ld",
69924 	                     (duk_tval *) tv1, (long) n));
69925 	(void) duk_put_prop_index(thr, f->consts_idx, (duk_uarridx_t) n);  /* invalidates tv1, tv2 */
69926 	return (duk_regconst_t) n | (duk_regconst_t) DUK__CONST_MARKER;
69927 }
69928 
69929 DUK_LOCAL duk_bool_t duk__const_needs_refcount(duk_compiler_ctx *comp_ctx, duk_regconst_t rc) {
69930 #if defined(DUK_USE_REFERENCE_COUNTING)
69931 	duk_compiler_func *f = &comp_ctx->curr_func;
69932 	duk_bool_t ret;
69933 
69934 	DUK_ASSERT((rc & DUK__CONST_MARKER) == 0);  /* caller removes const marker */
69935 	(void) duk_get_prop_index(comp_ctx->thr, f->consts_idx, (duk_uarridx_t) rc);
69936 	ret = !duk_is_number(comp_ctx->thr, -1);  /* now only number/string, so conservative check */
69937 	duk_pop(comp_ctx->thr);
69938 	return ret;
69939 #else
69940 	DUK_UNREF(comp_ctx);
69941 	DUK_UNREF(rc);
69942 	DUK_ASSERT((rc & DUK__CONST_MARKER) == 0);  /* caller removes const marker */
69943 	return 0;
69944 #endif
69945 }
69946 
69947 /* Get the value represented by an duk_ispec to a register or constant.
69948  * The caller can control the result by indicating whether or not:
69949  *
69950  *   (1) a constant is allowed (sometimes the caller needs the result to
69951  *       be in a register)
69952  *
69953  *   (2) a temporary register is required (usually when caller requires
69954  *       the register to be safely mutable; normally either a bound
69955  *       register or a temporary register are both OK)
69956  *
69957  *   (3) a forced register target needs to be used
69958  *
69959  * Bytecode may be emitted to generate the necessary value.  The return
69960  * value is either a register or a constant.
69961  */
69962 
69963 DUK_LOCAL
69964 duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
69965                                          duk_ispec *x,
69966                                          duk_regconst_t forced_reg,
69967                                          duk_small_uint_t flags) {
69968 	duk_hthread *thr = comp_ctx->thr;
69969 
69970 	DUK_DDD(DUK_DDDPRINT("duk__ispec_toregconst_raw(): x={%ld:%ld:%!T}, "
69971 	                     "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
69972 	                     (long) x->t,
69973 	                     (long) x->regconst,
69974 	                     (duk_tval *) duk_get_tval(thr, x->valstack_idx),
69975 	                     (long) forced_reg,
69976 	                     (unsigned long) flags,
69977 	                     (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
69978 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
69979 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));
69980 
69981 	switch (x->t) {
69982 	case DUK_ISPEC_VALUE: {
69983 		duk_tval *tv;
69984 
69985 		tv = DUK_GET_TVAL_POSIDX(thr, x->valstack_idx);
69986 		DUK_ASSERT(tv != NULL);
69987 
69988 		switch (DUK_TVAL_GET_TAG(tv)) {
69989 		case DUK_TAG_UNDEFINED: {
69990 			/* Note: although there is no 'undefined' literal, undefined
69991 			 * values can occur during compilation as a result of e.g.
69992 			 * the 'void' operator.
69993 			 */
69994 			duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
69995 			duk__emit_bc(comp_ctx, DUK_OP_LDUNDEF, dest);
69996 			return dest;
69997 		}
69998 		case DUK_TAG_NULL: {
69999 			duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
70000 			duk__emit_bc(comp_ctx, DUK_OP_LDNULL, dest);
70001 			return dest;
70002 		}
70003 		case DUK_TAG_BOOLEAN: {
70004 			duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
70005 			duk__emit_bc(comp_ctx,
70006 			             (DUK_TVAL_GET_BOOLEAN(tv) ? DUK_OP_LDTRUE : DUK_OP_LDFALSE),
70007 			             dest);
70008 			return dest;
70009 		}
70010 		case DUK_TAG_POINTER: {
70011 			DUK_UNREACHABLE();
70012 			break;
70013 		}
70014 		case DUK_TAG_STRING: {
70015 			duk_hstring *h;
70016 			duk_regconst_t dest;
70017 			duk_regconst_t constidx;
70018 
70019 			h = DUK_TVAL_GET_STRING(tv);
70020 			DUK_UNREF(h);
70021 			DUK_ASSERT(h != NULL);
70022 
70023 #if 0  /* XXX: to be implemented? */
70024 			/* Use special opcodes to load short strings */
70025 			if (DUK_HSTRING_GET_BYTELEN(h) <= 2) {
70026 				/* Encode into a single opcode (18 bits can encode 1-2 bytes + length indicator) */
70027 			} else if (DUK_HSTRING_GET_BYTELEN(h) <= 6) {
70028 				/* Encode into a double constant (53 bits can encode 6*8 = 48 bits + 3-bit length */
70029 			}
70030 #endif
70031 			duk_dup(thr, x->valstack_idx);
70032 			constidx = duk__getconst(comp_ctx);
70033 
70034 			if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
70035 				return constidx;
70036 			}
70037 
70038 			dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
70039 			duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, constidx);
70040 			return dest;
70041 		}
70042 		case DUK_TAG_OBJECT: {
70043 			DUK_UNREACHABLE();
70044 			break;
70045 		}
70046 		case DUK_TAG_BUFFER: {
70047 			DUK_UNREACHABLE();
70048 			break;
70049 		}
70050 		case DUK_TAG_LIGHTFUNC: {
70051 			DUK_UNREACHABLE();
70052 			break;
70053 		}
70054 #if defined(DUK_USE_FASTINT)
70055 		case DUK_TAG_FASTINT:
70056 #endif
70057 		default: {
70058 			/* number */
70059 			duk_regconst_t dest;
70060 			duk_regconst_t constidx;
70061 			duk_double_t dval;
70062 			duk_int32_t ival;
70063 
70064 			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
70065 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
70066 			dval = DUK_TVAL_GET_NUMBER(tv);
70067 
70068 			if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
70069 				/* A number can be loaded either through a constant, using
70070 				 * LDINT, or using LDINT+LDINTX.  LDINT is always a size win,
70071 				 * LDINT+LDINTX is not if the constant is used multiple times.
70072 				 * Currently always prefer LDINT+LDINTX over a double constant.
70073 				 */
70074 
70075 				if (duk_is_whole_get_int32_nonegzero(dval, &ival)) {
70076 					dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
70077 					duk__emit_load_int32(comp_ctx, dest, ival);
70078 					return dest;
70079 				}
70080 			}
70081 
70082 			duk_dup(thr, x->valstack_idx);
70083 			constidx = duk__getconst(comp_ctx);
70084 
70085 			if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
70086 				return constidx;
70087 			} else {
70088 				dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
70089 				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, constidx);
70090 				return dest;
70091 			}
70092 		}
70093 		}  /* end switch */
70094 		goto fail_internal;  /* never here */
70095 	}
70096 	case DUK_ISPEC_REGCONST: {
70097 		if (forced_reg >= 0) {
70098 			if (DUK__ISCONST(x->regconst)) {
70099 				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, forced_reg, x->regconst);
70100 			} else if (x->regconst != forced_reg) {
70101 				duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, forced_reg, x->regconst);
70102 			} else {
70103 				; /* already in correct reg */
70104 			}
70105 			return forced_reg;
70106 		}
70107 
70108 		DUK_ASSERT(forced_reg < 0);
70109 		if (DUK__ISCONST(x->regconst)) {
70110 			if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
70111 				duk_regconst_t dest = DUK__ALLOCTEMP(comp_ctx);
70112 				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, x->regconst);
70113 				return dest;
70114 			}
70115 			return x->regconst;
70116 		}
70117 
70118 		DUK_ASSERT(forced_reg < 0 && !DUK__ISCONST(x->regconst));
70119 		if ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) && !DUK__ISREG_TEMP(comp_ctx, x->regconst)) {
70120 			duk_regconst_t dest = DUK__ALLOCTEMP(comp_ctx);
70121 			duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, dest, x->regconst);
70122 			return dest;
70123 		}
70124 		return x->regconst;
70125 	}
70126 	default: {
70127 		break;  /* never here */
70128 	}
70129 	}
70130 
70131  fail_internal:
70132 	DUK_ERROR_INTERNAL(thr);
70133 	DUK_WO_NORETURN(return 0;);
70134 }
70135 
70136 DUK_LOCAL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_regconst_t forced_reg) {
70137 	DUK_ASSERT(forced_reg >= 0);
70138 	(void) duk__ispec_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
70139 }
70140 
70141 /* Coerce an duk_ivalue to a 'plain' value by generating the necessary
70142  * arithmetic operations, property access, or variable access bytecode.
70143  * The duk_ivalue argument ('x') is converted into a plain value as a
70144  * side effect.
70145  */
70146 DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_regconst_t forced_reg) {
70147 	duk_hthread *thr = comp_ctx->thr;
70148 
70149 	DUK_DDD(DUK_DDDPRINT("duk__ivalue_toplain_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
70150 	                     "forced_reg=%ld",
70151 	                     (long) x->t, (long) x->op,
70152 	                     (long) x->x1.t, (long) x->x1.regconst,
70153 	                     (duk_tval *) duk_get_tval(thr, x->x1.valstack_idx),
70154 	                     (long) x->x2.t, (long) x->x2.regconst,
70155 	                     (duk_tval *) duk_get_tval(thr, x->x2.valstack_idx),
70156 	                     (long) forced_reg));
70157 
70158 	switch (x->t) {
70159 	case DUK_IVAL_PLAIN: {
70160 		return;
70161 	}
70162 	/* XXX: support unary arithmetic ivalues (useful?) */
70163 	case DUK_IVAL_ARITH: {
70164 		duk_regconst_t arg1;
70165 		duk_regconst_t arg2;
70166 		duk_regconst_t dest;
70167 		duk_tval *tv1;
70168 		duk_tval *tv2;
70169 
70170 		DUK_DDD(DUK_DDDPRINT("arith to plain conversion"));
70171 
70172 		/* inline arithmetic check for constant values */
70173 		/* XXX: use the exactly same arithmetic function here as in executor */
70174 		if (x->x1.t == DUK_ISPEC_VALUE && x->x2.t == DUK_ISPEC_VALUE && x->t == DUK_IVAL_ARITH) {
70175 			tv1 = DUK_GET_TVAL_POSIDX(thr, x->x1.valstack_idx);
70176 			tv2 = DUK_GET_TVAL_POSIDX(thr, x->x2.valstack_idx);
70177 			DUK_ASSERT(tv1 != NULL);
70178 			DUK_ASSERT(tv2 != NULL);
70179 
70180 			DUK_DDD(DUK_DDDPRINT("arith: tv1=%!T, tv2=%!T",
70181 			                     (duk_tval *) tv1,
70182 			                     (duk_tval *) tv2));
70183 
70184 			if (DUK_TVAL_IS_NUMBER(tv1) && DUK_TVAL_IS_NUMBER(tv2)) {
70185 				duk_double_t d1 = DUK_TVAL_GET_NUMBER(tv1);
70186 				duk_double_t d2 = DUK_TVAL_GET_NUMBER(tv2);
70187 				duk_double_t d3;
70188 				duk_bool_t accept_fold = 1;
70189 
70190 				DUK_DDD(DUK_DDDPRINT("arith inline check: d1=%lf, d2=%lf, op=%ld",
70191 				                     (double) d1, (double) d2, (long) x->op));
70192 				switch (x->op) {
70193 				case DUK_OP_ADD: {
70194 					d3 = d1 + d2;
70195 					break;
70196 				}
70197 				case DUK_OP_SUB: {
70198 					d3 = d1 - d2;
70199 					break;
70200 				}
70201 				case DUK_OP_MUL: {
70202 					d3 = d1 * d2;
70203 					break;
70204 				}
70205 				case DUK_OP_DIV: {
70206 					/* Division-by-zero is undefined
70207 					 * behavior, so rely on a helper.
70208 					 */
70209 					d3 = duk_double_div(d1, d2);
70210 					break;
70211 				}
70212 				case DUK_OP_EXP: {
70213 					d3 = (duk_double_t) duk_js_arith_pow((double) d1, (double) d2);
70214 					break;
70215 				}
70216 				default: {
70217 					d3 = 0.0;  /* Won't be used, but silence MSVC /W4 warning. */
70218 					accept_fold = 0;
70219 					break;
70220 				}
70221 				}
70222 
70223 				if (accept_fold) {
70224 					duk_double_union du;
70225 					du.d = d3;
70226 					DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
70227 					d3 = du.d;
70228 
70229 					x->t = DUK_IVAL_PLAIN;
70230 					DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
70231 					DUK_TVAL_SET_NUMBER(tv1, d3);  /* old value is number: no refcount */
70232 					return;
70233 				}
70234 			} else if (x->op == DUK_OP_ADD && DUK_TVAL_IS_STRING(tv1) && DUK_TVAL_IS_STRING(tv2)) {
70235 				/* Inline string concatenation.  No need to check for
70236 				 * symbols, as all inputs are valid ECMAScript strings.
70237 				 */
70238 				duk_dup(thr, x->x1.valstack_idx);
70239 				duk_dup(thr, x->x2.valstack_idx);
70240 				duk_concat(thr, 2);
70241 				duk_replace(thr, x->x1.valstack_idx);
70242 				x->t = DUK_IVAL_PLAIN;
70243 				DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
70244 				return;
70245 			}
70246 		}
70247 
70248 		arg1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
70249 		arg2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
70250 
70251 		/* If forced reg, use it as destination.  Otherwise try to
70252 		 * use either coerced ispec if it is a temporary.
70253 		 */
70254 		if (forced_reg >= 0) {
70255 			dest = forced_reg;
70256 		} else if (DUK__ISREG_TEMP(comp_ctx, arg1)) {
70257 			dest = arg1;
70258 		} else if (DUK__ISREG_TEMP(comp_ctx, arg2)) {
70259 			dest = arg2;
70260 		} else {
70261 			dest = DUK__ALLOCTEMP(comp_ctx);
70262 		}
70263 
70264 		DUK_ASSERT(DUK__ISREG(dest));
70265 		duk__emit_a_b_c(comp_ctx, x->op | DUK__EMIT_FLAG_BC_REGCONST, dest, arg1, arg2);
70266 
70267 		duk__ivalue_regconst(x, dest);
70268 		return;
70269 	}
70270 	case DUK_IVAL_PROP: {
70271 		/* XXX: very similar to DUK_IVAL_ARITH - merge? */
70272 		duk_regconst_t arg1;
70273 		duk_regconst_t arg2;
70274 		duk_regconst_t dest;
70275 
70276 		/* Need a short reg/const, does not have to be a mutable temp. */
70277 		arg1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
70278 		arg2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
70279 
70280 		/* Pick a destination register.  If either base value or key
70281 		 * happens to be a temp value, reuse it as the destination.
70282 		 *
70283 		 * XXX: The temp must be a "mutable" one, i.e. such that no
70284 		 * other expression is using it anymore.  Here this should be
70285 		 * the case because the value of a property access expression
70286 		 * is neither the base nor the key, but the lookup result.
70287 		 */
70288 
70289 		if (forced_reg >= 0) {
70290 			dest = forced_reg;
70291 		} else if (DUK__ISREG_TEMP(comp_ctx, arg1)) {
70292 			dest = arg1;
70293 		} else if (DUK__ISREG_TEMP(comp_ctx, arg2)) {
70294 			dest = arg2;
70295 		} else {
70296 			dest = DUK__ALLOCTEMP(comp_ctx);
70297 		}
70298 
70299 		duk__emit_a_b_c(comp_ctx,
70300 		                DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST,
70301 		                dest,
70302 		                arg1,
70303 		                arg2);
70304 
70305 		duk__ivalue_regconst(x, dest);
70306 		return;
70307 	}
70308 	case DUK_IVAL_VAR: {
70309 		/* x1 must be a string */
70310 		duk_regconst_t dest;
70311 		duk_regconst_t reg_varbind;
70312 		duk_regconst_t rc_varname;
70313 
70314 		DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
70315 
70316 		duk_dup(thr, x->x1.valstack_idx);
70317 		if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
70318 			duk__ivalue_regconst(x, reg_varbind);
70319 		} else {
70320 			dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
70321 			duk__emit_a_bc(comp_ctx, DUK_OP_GETVAR, dest, rc_varname);
70322 			duk__ivalue_regconst(x, dest);
70323 		}
70324 		return;
70325 	}
70326 	case DUK_IVAL_NONE:
70327 	default: {
70328 		DUK_D(DUK_DPRINT("invalid ivalue type: %ld", (long) x->t));
70329 		break;
70330 	}
70331 	}
70332 
70333 	DUK_ERROR_INTERNAL(thr);
70334 	DUK_WO_NORETURN(return;);
70335 }
70336 
70337 /* evaluate to plain value, no forced register (temp/bound reg both ok) */
70338 DUK_LOCAL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
70339 	duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
70340 }
70341 
70342 /* evaluate to final form (e.g. coerce GETPROP to code), throw away temp */
70343 DUK_LOCAL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
70344 	duk_regconst_t temp;
70345 
70346 	/* If duk__ivalue_toplain_raw() allocates a temp, forget it and
70347 	 * restore next temp state.
70348 	 */
70349 	temp = DUK__GETTEMP(comp_ctx);
70350 	duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
70351 	DUK__SETTEMP(comp_ctx, temp);
70352 }
70353 
70354 /* Coerce an duk_ivalue to a register or constant; result register may
70355  * be a temp or a bound register.
70356  *
70357  * The duk_ivalue argument ('x') is converted into a regconst as a
70358  * side effect.
70359  */
70360 DUK_LOCAL
70361 duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
70362                                           duk_ivalue *x,
70363                                           duk_regconst_t forced_reg,
70364                                           duk_small_uint_t flags) {
70365 	duk_hthread *thr = comp_ctx->thr;
70366 	duk_regconst_t reg;
70367 	DUK_UNREF(thr);
70368 
70369 	DUK_DDD(DUK_DDDPRINT("duk__ivalue_toregconst_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
70370 	                     "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
70371 	                     (long) x->t, (long) x->op,
70372 	                     (long) x->x1.t, (long) x->x1.regconst,
70373 	                     (duk_tval *) duk_get_tval(thr, x->x1.valstack_idx),
70374 	                     (long) x->x2.t, (long) x->x2.regconst,
70375 	                     (duk_tval *) duk_get_tval(thr, x->x2.valstack_idx),
70376 	                     (long) forced_reg,
70377 	                     (unsigned long) flags,
70378 	                     (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
70379 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
70380 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));
70381 
70382 	/* first coerce to a plain value */
70383 	duk__ivalue_toplain_raw(comp_ctx, x, forced_reg);
70384 	DUK_ASSERT(x->t == DUK_IVAL_PLAIN);
70385 
70386 	/* then to a register */
70387 	reg = duk__ispec_toregconst_raw(comp_ctx, &x->x1, forced_reg, flags);
70388 	duk__ivalue_regconst(x, reg);
70389 
70390 	return reg;
70391 }
70392 
70393 DUK_LOCAL duk_regconst_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
70394 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, 0 /*flags*/);
70395 }
70396 
70397 #if 0  /* unused */
70398 DUK_LOCAL duk_regconst_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
70399 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
70400 }
70401 #endif
70402 
70403 DUK_LOCAL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg) {
70404 	DUK_ASSERT(forced_reg >= 0);
70405 	(void) duk__ivalue_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
70406 }
70407 
70408 DUK_LOCAL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
70409 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
70410 }
70411 
70412 DUK_LOCAL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
70413 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
70414 }
70415 
70416 /* The issues below can be solved with better flags */
70417 
70418 /* XXX: many operations actually want toforcedtemp() -- brand new temp? */
70419 /* XXX: need a toplain_ignore() which will only coerce a value to a temp
70420  * register if it might have a side effect.  Side-effect free values do not
70421  * need to be coerced.
70422  */
70423 
70424 /*
70425  *  Identifier handling
70426  */
70427 
70428 DUK_LOCAL duk_regconst_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx) {
70429 	duk_hthread *thr = comp_ctx->thr;
70430 	duk_hstring *h_varname;
70431 	duk_regconst_t ret;
70432 
70433 	DUK_DDD(DUK_DDDPRINT("resolving identifier reference to '%!T'",
70434 	                     (duk_tval *) duk_get_tval(thr, -1)));
70435 
70436 	/*
70437 	 *  Special name handling
70438 	 */
70439 
70440 	h_varname = duk_known_hstring(thr, -1);
70441 
70442 	if (h_varname == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)) {
70443 		DUK_DDD(DUK_DDDPRINT("flagging function as accessing 'arguments'"));
70444 		comp_ctx->curr_func.id_access_arguments = 1;
70445 	}
70446 
70447 	/*
70448 	 *  Inside one or more 'with' statements fall back to slow path always.
70449 	 *  (See e.g. test-stmt-with.js.)
70450 	 */
70451 
70452 	if (comp_ctx->curr_func.with_depth > 0) {
70453 		DUK_DDD(DUK_DDDPRINT("identifier lookup inside a 'with' -> fall back to slow path"));
70454 		goto slow_path_own;
70455 	}
70456 
70457 	/*
70458 	 *  Any catch bindings ("catch (e)") also affect identifier binding.
70459 	 *
70460 	 *  Currently, the varmap is modified for the duration of the catch
70461 	 *  clause to ensure any identifier accesses with the catch variable
70462 	 *  name will use slow path.
70463 	 */
70464 
70465 	duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
70466 	if (duk_is_number(thr, -1)) {
70467 		ret = duk_to_int(thr, -1);
70468 		duk_pop(thr);
70469 	} else {
70470 		duk_pop(thr);
70471 		if (comp_ctx->curr_func.catch_depth > 0 || comp_ctx->curr_func.with_depth > 0) {
70472 			DUK_DDD(DUK_DDDPRINT("slow path access from inside a try-catch or with needs _Varmap"));
70473 			goto slow_path_own;
70474 		} else {
70475 			/* In this case we're doing a variable lookup that doesn't
70476 			 * match our own variables, so _Varmap won't be needed at
70477 			 * run time.
70478 			 */
70479 			DUK_DDD(DUK_DDDPRINT("slow path access outside of try-catch and with, no need for _Varmap"));
70480 			goto slow_path_notown;
70481 		}
70482 	}
70483 
70484 	DUK_DDD(DUK_DDDPRINT("identifier lookup -> reg %ld", (long) ret));
70485 	return ret;
70486 
70487  slow_path_notown:
70488 	DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path, not own variable"));
70489 
70490 	comp_ctx->curr_func.id_access_slow = 1;
70491 	return (duk_regconst_t) -1;
70492 
70493  slow_path_own:
70494 	DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path, may be own variable"));
70495 
70496 	comp_ctx->curr_func.id_access_slow = 1;
70497 	comp_ctx->curr_func.id_access_slow_own = 1;
70498 	return (duk_regconst_t) -1;
70499 }
70500 
70501 /* Lookup an identifier name in the current varmap, indicating whether the
70502  * identifier is register-bound and if not, allocating a constant for the
70503  * identifier name.  Returns 1 if register-bound, 0 otherwise.  Caller can
70504  * also check (out_reg_varbind >= 0) to check whether or not identifier is
70505  * register bound.  The caller must NOT use out_rc_varname at all unless
70506  * return code is 0 or out_reg_varbind is < 0; this is becuase out_rc_varname
70507  * is unsigned and doesn't have a "unused" / none value.
70508  */
70509 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) {
70510 	duk_hthread *thr = comp_ctx->thr;
70511 	duk_regconst_t reg_varbind;
70512 	duk_regconst_t rc_varname;
70513 
70514 	/* [ ... varname ] */
70515 
70516 	duk_dup_top(thr);
70517 	reg_varbind = duk__lookup_active_register_binding(comp_ctx);
70518 
70519 	if (reg_varbind >= 0) {
70520 		*out_reg_varbind = reg_varbind;
70521 		*out_rc_varname = 0;  /* duk_regconst_t is unsigned, so use 0 as dummy value (ignored by caller) */
70522 		duk_pop(thr);
70523 		return 1;
70524 	} else {
70525 		rc_varname = duk__getconst(comp_ctx);
70526 		*out_reg_varbind = -1;
70527 		*out_rc_varname = rc_varname;
70528 		return 0;
70529 	}
70530 }
70531 
70532 /*
70533  *  Label handling
70534  *
70535  *  Labels are initially added with flags prohibiting both break and continue.
70536  *  When the statement type is finally uncovered (after potentially multiple
70537  *  labels), all the labels are updated to allow/prohibit break and continue.
70538  */
70539 
70540 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) {
70541 	duk_hthread *thr = comp_ctx->thr;
70542 	duk_size_t n;
70543 	duk_size_t new_size;
70544 	duk_uint8_t *p;
70545 	duk_labelinfo *li_start, *li;
70546 
70547 	/* Duplicate (shadowing) labels are not allowed, except for the empty
70548 	 * labels (which are used as default labels for switch and iteration
70549 	 * statements).
70550 	 *
70551 	 * We could also allow shadowing of non-empty pending labels without any
70552 	 * other issues than breaking the required label shadowing requirements
70553 	 * of the E5 specification, see Section 12.12.
70554 	 */
70555 
70556 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
70557 	li_start = (duk_labelinfo *) (void *) p;
70558 	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
70559 	n = (duk_size_t) (li - li_start);
70560 
70561 	while (li > li_start) {
70562 		li--;
70563 
70564 		if (li->h_label == h_label && h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
70565 			DUK_ERROR_SYNTAX(thr, DUK_STR_DUPLICATE_LABEL);
70566 			DUK_WO_NORETURN(return;);
70567 		}
70568 	}
70569 
70570 	duk_push_hstring(thr, h_label);
70571 	DUK_ASSERT(n <= DUK_UARRIDX_MAX);  /* label limits */
70572 	(void) duk_put_prop_index(thr, comp_ctx->curr_func.labelnames_idx, (duk_uarridx_t) n);
70573 
70574 	new_size = (n + 1) * sizeof(duk_labelinfo);
70575 	duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size);
70576 	/* XXX: slack handling, slow now */
70577 
70578 	/* relookup after possible realloc */
70579 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
70580 	li_start = (duk_labelinfo *) (void *) p;
70581 	DUK_UNREF(li_start);  /* silence scan-build warning */
70582 	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
70583 	li--;
70584 
70585 	/* Labels can be used for iteration statements but also for other statements,
70586 	 * in particular a label can be used for a block statement.  All cases of a
70587 	 * named label accept a 'break' so that flag is set here.  Iteration statements
70588 	 * also allow 'continue', so that flag is updated when we figure out the
70589 	 * statement type.
70590 	 */
70591 
70592 	li->flags = DUK_LABEL_FLAG_ALLOW_BREAK;
70593 	li->label_id = label_id;
70594 	li->h_label = h_label;
70595 	li->catch_depth = comp_ctx->curr_func.catch_depth;   /* catch depth from current func */
70596 	li->pc_label = pc_label;
70597 
70598 	DUK_DDD(DUK_DDDPRINT("registered label: flags=0x%08lx, id=%ld, name=%!O, catch_depth=%ld, pc_label=%ld",
70599 	                     (unsigned long) li->flags, (long) li->label_id, (duk_heaphdr *) li->h_label,
70600 	                     (long) li->catch_depth, (long) li->pc_label));
70601 }
70602 
70603 /* Update all labels with matching label_id. */
70604 DUK_LOCAL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags) {
70605 	duk_uint8_t *p;
70606 	duk_labelinfo *li_start, *li;
70607 
70608 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(comp_ctx->thr->heap, comp_ctx->curr_func.h_labelinfos);
70609 	li_start = (duk_labelinfo *) (void *) p;
70610 	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
70611 
70612 	/* Match labels starting from latest; once label_id no longer matches, we can
70613 	 * safely exit without checking the rest of the labels (only the topmost labels
70614 	 * are ever updated).
70615 	 */
70616 	while (li > li_start) {
70617 		li--;
70618 
70619 		if (li->label_id != label_id) {
70620 			break;
70621 		}
70622 
70623 		DUK_DDD(DUK_DDDPRINT("updating (overwriting) label flags for li=%p, label_id=%ld, flags=%ld",
70624 		                     (void *) li, (long) label_id, (long) flags));
70625 
70626 		li->flags = flags;
70627 	}
70628 }
70629 
70630 /* Lookup active label information.  Break/continue distinction is necessary to handle switch
70631  * statement related labels correctly: a switch will only catch a 'break', not a 'continue'.
70632  *
70633  * An explicit label cannot appear multiple times in the active set, but empty labels (unlabelled
70634  * iteration and switch statements) can.  A break will match the closest unlabelled or labelled
70635  * statement.  A continue will match the closest unlabelled or labelled iteration statement.  It is
70636  * a syntax error if a continue matches a labelled switch statement; because an explicit label cannot
70637  * be duplicated, the continue cannot match any valid label outside the switch.
70638  *
70639  * A side effect of these rules is that a LABEL statement related to a switch should never actually
70640  * catch a continue abrupt completion at run-time.  Hence an INVALID opcode can be placed in the
70641  * continue slot of the switch's LABEL statement.
70642  */
70643 
70644 /* XXX: awkward, especially the bunch of separate output values -> output struct? */
70645 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) {
70646 	duk_hthread *thr = comp_ctx->thr;
70647 	duk_uint8_t *p;
70648 	duk_labelinfo *li_start, *li_end, *li;
70649 	duk_bool_t match = 0;
70650 
70651 	DUK_DDD(DUK_DDDPRINT("looking up active label: label='%!O', is_break=%ld",
70652 	                     (duk_heaphdr *) h_label, (long) is_break));
70653 
70654 	DUK_UNREF(thr);
70655 
70656 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
70657 	li_start = (duk_labelinfo *) (void *) p;
70658 	li_end = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
70659 	li = li_end;
70660 
70661 	/* Match labels starting from latest label because there can be duplicate empty
70662 	 * labels in the label set.
70663 	 */
70664 	while (li > li_start) {
70665 		li--;
70666 
70667 		if (li->h_label != h_label) {
70668 			DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] ->'%!O' != %!O",
70669 			                     (long) (li - li_start),
70670 			                     (duk_heaphdr *) li->h_label,
70671 			                     (duk_heaphdr *) h_label));
70672 			continue;
70673 		}
70674 
70675 		DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] -> '%!O' label name matches (still need to check type)",
70676 		                     (long) (li - li_start), (duk_heaphdr *) h_label));
70677 
70678 		/* currently all labels accept a break, so no explicit check for it now */
70679 		DUK_ASSERT(li->flags & DUK_LABEL_FLAG_ALLOW_BREAK);
70680 
70681 		if (is_break) {
70682 			/* break matches always */
70683 			match = 1;
70684 			break;
70685 		} else if (li->flags & DUK_LABEL_FLAG_ALLOW_CONTINUE) {
70686 			/* iteration statements allow continue */
70687 			match = 1;
70688 			break;
70689 		} else {
70690 			/* continue matched this label -- we can only continue if this is the empty
70691 			 * label, for which duplication is allowed, and thus there is hope of
70692 			 * finding a match deeper in the label stack.
70693 			 */
70694 			if (h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
70695 				DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL);
70696 				DUK_WO_NORETURN(return;);
70697 			} else {
70698 				DUK_DDD(DUK_DDDPRINT("continue matched an empty label which does not "
70699 				                     "allow a continue -> continue lookup deeper in label stack"));
70700 			}
70701 		}
70702 	}
70703 	/* XXX: match flag is awkward, rework */
70704 	if (!match) {
70705 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL);
70706 		DUK_WO_NORETURN(return;);
70707 	}
70708 
70709 	DUK_DDD(DUK_DDDPRINT("label match: %!O -> label_id %ld, catch_depth=%ld, pc_label=%ld",
70710 	                     (duk_heaphdr *) h_label, (long) li->label_id,
70711 	                     (long) li->catch_depth, (long) li->pc_label));
70712 
70713 	*out_label_id = li->label_id;
70714 	*out_label_catch_depth = li->catch_depth;
70715 	*out_label_pc = li->pc_label;
70716 	*out_is_closest = (li == li_end - 1);
70717 }
70718 
70719 DUK_LOCAL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_size_t len) {
70720 	duk_hthread *thr = comp_ctx->thr;
70721 
70722 	duk_set_length(thr, comp_ctx->curr_func.labelnames_idx, len);
70723 	duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, sizeof(duk_labelinfo) * len);
70724 }
70725 
70726 /*
70727  *  Expression parsing: duk__expr_nud(), duk__expr_led(), duk__expr_lbp(), and helpers.
70728  *
70729  *  - duk__expr_nud(): ("null denotation"): process prev_token as a "start" of an expression (e.g. literal)
70730  *  - duk__expr_led(): ("left denotation"): process prev_token in the "middle" of an expression (e.g. operator)
70731  *  - duk__expr_lbp(): ("left-binding power"): return left-binding power of curr_token
70732  */
70733 
70734 /* object literal key tracking flags */
70735 #define DUK__OBJ_LIT_KEY_PLAIN  (1 << 0)  /* key encountered as a plain property */
70736 #define DUK__OBJ_LIT_KEY_GET    (1 << 1)  /* key encountered as a getter */
70737 #define DUK__OBJ_LIT_KEY_SET    (1 << 2)  /* key encountered as a setter */
70738 
70739 DUK_LOCAL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
70740 	duk_hthread *thr = comp_ctx->thr;
70741 	duk_regconst_t reg_obj;                 /* result reg */
70742 	duk_regconst_t reg_temp;                /* temp reg */
70743 	duk_regconst_t temp_start;              /* temp reg value for start of loop */
70744 	duk_small_uint_t max_init_values;  /* max # of values initialized in one MPUTARR set */
70745 	duk_small_uint_t num_values;       /* number of values in current MPUTARR set */
70746 	duk_uarridx_t curr_idx;            /* current (next) array index */
70747 	duk_uarridx_t start_idx;           /* start array index of current MPUTARR set */
70748 	duk_uarridx_t init_idx;            /* last array index explicitly initialized, +1 */
70749 	duk_bool_t require_comma;          /* next loop requires a comma */
70750 #if !defined(DUK_USE_PREFER_SIZE)
70751 	duk_int_t pc_newarr;
70752 	duk_compiler_instr *instr;
70753 #endif
70754 
70755 	/* DUK_TOK_LBRACKET already eaten, current token is right after that */
70756 	DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LBRACKET);
70757 
70758 	max_init_values = DUK__MAX_ARRAY_INIT_VALUES;  /* XXX: depend on available temps? */
70759 
70760 	reg_obj = DUK__ALLOCTEMP(comp_ctx);
70761 #if !defined(DUK_USE_PREFER_SIZE)
70762 	pc_newarr = duk__get_current_pc(comp_ctx);
70763 #endif
70764 	duk__emit_bc(comp_ctx, DUK_OP_NEWARR, reg_obj);  /* XXX: patch initial size hint afterwards? */
70765 	temp_start = DUK__GETTEMP(comp_ctx);
70766 
70767 	/*
70768 	 *  Emit initializers in sets of maximum max_init_values.
70769 	 *  Corner cases such as single value initializers do not have
70770 	 *  special handling now.
70771 	 *
70772 	 *  Elided elements must not be emitted as 'undefined' values,
70773 	 *  because such values would be enumerable (which is incorrect).
70774 	 *  Also note that trailing elisions must be reflected in the
70775 	 *  length of the final array but cause no elements to be actually
70776 	 *  inserted.
70777 	 */
70778 
70779 	curr_idx = 0;
70780 	init_idx = 0;         /* tracks maximum initialized index + 1 */
70781 	start_idx = 0;
70782 	require_comma = 0;
70783 
70784 	for (;;) {
70785 		num_values = 0;
70786 		DUK__SETTEMP(comp_ctx, temp_start);
70787 
70788 		if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
70789 			break;
70790 		}
70791 
70792 		for (;;) {
70793 			if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
70794 				/* the outer loop will recheck and exit */
70795 				break;
70796 			}
70797 
70798 			/* comma check */
70799 			if (require_comma) {
70800 				if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
70801 					/* comma after a value, expected */
70802 					duk__advance(comp_ctx);
70803 					require_comma = 0;
70804 					continue;
70805 				} else {
70806 					goto syntax_error;
70807 				}
70808 			} else {
70809 				if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
70810 					/* elision - flush */
70811 					curr_idx++;
70812 					duk__advance(comp_ctx);
70813 					/* if num_values > 0, MPUTARR emitted by outer loop after break */
70814 					break;
70815 				}
70816 			}
70817 			/* else an array initializer element */
70818 
70819 			/* initial index */
70820 			if (num_values == 0) {
70821 				start_idx = curr_idx;
70822 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
70823 				duk__emit_load_int32(comp_ctx, reg_temp, (duk_int32_t) start_idx);
70824 			}
70825 
70826 			reg_temp = DUK__ALLOCTEMP(comp_ctx);   /* alloc temp just in case, to update max temp */
70827 			DUK__SETTEMP(comp_ctx, reg_temp);
70828 			duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);
70829 			DUK__SETTEMP(comp_ctx, reg_temp + 1);
70830 
70831 			num_values++;
70832 			curr_idx++;
70833 			require_comma = 1;
70834 
70835 			if (num_values >= max_init_values) {
70836 				/* MPUTARR emitted by outer loop */
70837 				break;
70838 			}
70839 		}
70840 
70841 		if (num_values > 0) {
70842 			/* - A is a source register (it's not a write target, but used
70843 			 *   to identify the target object) but can be shuffled.
70844 			 * - B cannot be shuffled normally because it identifies a range
70845 			 *   of registers, the emitter has special handling for this
70846 			 *   (the "no shuffle" flag must not be set).
70847 			 * - C is a non-register number and cannot be shuffled, but
70848 			 *   never needs to be.
70849 			 */
70850 			duk__emit_a_b_c(comp_ctx,
70851 			                DUK_OP_MPUTARR |
70852 			                    DUK__EMIT_FLAG_NO_SHUFFLE_C |
70853 			                    DUK__EMIT_FLAG_A_IS_SOURCE,
70854 			                reg_obj,
70855 			                temp_start,
70856 			                (duk_regconst_t) (num_values + 1));
70857 			init_idx = start_idx + num_values;
70858 
70859 			/* num_values and temp_start reset at top of outer loop */
70860 		}
70861 	}
70862 
70863 	/* Update initil size for NEWARR, doesn't need to be exact and is
70864 	 * capped at A field limit.
70865 	 */
70866 #if !defined(DUK_USE_PREFER_SIZE)
70867 	instr = duk__get_instr_ptr(comp_ctx, pc_newarr);
70868 	instr->ins |= DUK_ENC_OP_A(0, curr_idx > DUK_BC_A_MAX ? DUK_BC_A_MAX : curr_idx);
70869 #endif
70870 
70871 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RBRACKET);
70872 	duk__advance(comp_ctx);
70873 
70874 	DUK_DDD(DUK_DDDPRINT("array literal done, curridx=%ld, initidx=%ld",
70875 	                     (long) curr_idx, (long) init_idx));
70876 
70877 	/* trailing elisions? */
70878 	if (curr_idx > init_idx) {
70879 		/* yes, must set array length explicitly */
70880 		DUK_DDD(DUK_DDDPRINT("array literal has trailing elisions which affect its length"));
70881 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
70882 		duk__emit_load_int32(comp_ctx, reg_temp, (duk_int_t) curr_idx);
70883 		duk__emit_a_bc(comp_ctx,
70884 		               DUK_OP_SETALEN | DUK__EMIT_FLAG_A_IS_SOURCE,
70885 		               reg_obj,
70886 		               reg_temp);
70887 	}
70888 
70889 	DUK__SETTEMP(comp_ctx, temp_start);
70890 
70891 	duk__ivalue_regconst(res, reg_obj);
70892 	return;
70893 
70894  syntax_error:
70895 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARRAY_LITERAL);
70896 	DUK_WO_NORETURN(return;);
70897 }
70898 
70899 typedef struct {
70900 	duk_regconst_t reg_obj;
70901 	duk_regconst_t temp_start;
70902 	duk_small_uint_t num_pairs;
70903 	duk_small_uint_t num_total_pairs;
70904 } duk__objlit_state;
70905 
70906 DUK_LOCAL void duk__objlit_flush_keys(duk_compiler_ctx *comp_ctx, duk__objlit_state *st) {
70907 	if (st->num_pairs > 0) {
70908 		/* - A is a source register (it's not a write target, but used
70909 		 *   to identify the target object) but can be shuffled.
70910 		 * - B cannot be shuffled normally because it identifies a range
70911 		 *   of registers, the emitter has special handling for this
70912 		 *   (the "no shuffle" flag must not be set).
70913 		 * - C is a non-register number and cannot be shuffled, but
70914 		 *   never needs to be.
70915 		 */
70916 		DUK_ASSERT(st->num_pairs > 0);
70917 		duk__emit_a_b_c(comp_ctx,
70918 		                DUK_OP_MPUTOBJ |
70919 		                    DUK__EMIT_FLAG_NO_SHUFFLE_C |
70920 		                    DUK__EMIT_FLAG_A_IS_SOURCE,
70921 		                st->reg_obj,
70922 		                st->temp_start,
70923 		                (duk_regconst_t) (st->num_pairs * 2));
70924 		st->num_total_pairs += st->num_pairs;
70925 		st->num_pairs = 0;
70926 	}
70927 	DUK__SETTEMP(comp_ctx, st->temp_start);
70928 }
70929 
70930 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) {
70931 	if (tok->t_nores == DUK_TOK_IDENTIFIER || tok->t_nores == DUK_TOK_STRING) {
70932 		/* same handling for identifiers and strings */
70933 		DUK_ASSERT(tok->str1 != NULL);
70934 		duk_push_hstring(comp_ctx->thr, tok->str1);
70935 	} else if (tok->t == DUK_TOK_NUMBER) {
70936 		/* numbers can be loaded as numbers and coerced on the fly */
70937 		duk_push_number(comp_ctx->thr, tok->num);
70938 	} else {
70939 		return 1;  /* error */
70940 	}
70941 
70942 	duk__ivalue_plain_fromstack(comp_ctx, res);
70943 	DUK__SETTEMP(comp_ctx, reg_temp + 1);
70944 	duk__ivalue_toforcedreg(comp_ctx, res, reg_temp);
70945 	DUK__SETTEMP(comp_ctx, reg_temp + 1);
70946 	return 0;
70947 }
70948 
70949 DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
70950 	duk_hthread *thr = comp_ctx->thr;
70951 	duk__objlit_state st;
70952 	duk_regconst_t reg_temp;          /* temp reg */
70953 	duk_small_uint_t max_init_pairs;  /* max # of key-value pairs initialized in one MPUTOBJ set */
70954 	duk_bool_t first;                 /* first value: comma must not precede the value */
70955 	duk_bool_t is_set, is_get;        /* temps */
70956 #if !defined(DUK_USE_PREFER_SIZE)
70957 	duk_int_t pc_newobj;
70958 	duk_compiler_instr *instr;
70959 #endif
70960 
70961 	DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LCURLY);
70962 
70963 	max_init_pairs = DUK__MAX_OBJECT_INIT_PAIRS;  /* XXX: depend on available temps? */
70964 
70965 	st.reg_obj = DUK__ALLOCTEMP(comp_ctx);    /* target object */
70966 	st.temp_start = DUK__GETTEMP(comp_ctx);   /* start of MPUTOBJ argument list */
70967 	st.num_pairs = 0;                         /* number of key/value pairs emitted for current MPUTOBJ set */
70968 	st.num_total_pairs = 0;                   /* number of key/value pairs emitted overall */
70969 
70970 #if !defined(DUK_USE_PREFER_SIZE)
70971 	pc_newobj = duk__get_current_pc(comp_ctx);
70972 #endif
70973 	duk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, st.reg_obj);
70974 
70975 	/*
70976 	 *  Emit initializers in sets of maximum max_init_pairs keys.
70977 	 *  Setter/getter is handled separately and terminates the
70978 	 *  current set of initializer values.  Corner cases such as
70979 	 *  single value initializers do not have special handling now.
70980 	 */
70981 
70982 	first = 1;
70983 	for (;;) {
70984 		/*
70985 		 *  ES5 and ES2015+ provide a lot of different PropertyDefinition
70986 		 *  formats, see http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer.
70987 		 *
70988 		 *  PropertyName can be IdentifierName (includes reserved words), a string
70989 		 *  literal, or a number literal.  Note that IdentifierName allows 'get' and
70990 		 *  'set' too, so we need to look ahead to the next token to distinguish:
70991 		 *
70992 		 *     { get : 1 }
70993 		 *
70994 		 *  and
70995 		 *
70996 		 *     { get foo() { return 1 } }
70997 		 *     { get get() { return 1 } }    // 'get' as getter propertyname
70998 		 *
70999 		 *  Finally, a trailing comma is allowed.
71000 		 *
71001 		 *  Key name is coerced to string at compile time (and ends up as a
71002 		 *  a string constant) even for numeric keys (e.g. "{1:'foo'}").
71003 		 *  These could be emitted using e.g. LDINT, but that seems hardly
71004 		 *  worth the effort and would increase code size.
71005 		 */
71006 
71007 		DUK_DDD(DUK_DDDPRINT("object literal loop, curr_token->t = %ld",
71008 		                     (long) comp_ctx->curr_token.t));
71009 
71010 		if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
71011 			break;
71012 		}
71013 
71014 		if (first) {
71015 			first = 0;
71016 		} else {
71017 			if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
71018 				goto syntax_error;
71019 			}
71020 			duk__advance(comp_ctx);
71021 			if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
71022 				/* trailing comma followed by rcurly */
71023 				break;
71024 			}
71025 		}
71026 
71027 		/* Advance to get one step of lookup. */
71028 		duk__advance(comp_ctx);
71029 
71030 		/* Flush current MPUTOBJ if enough many pairs gathered. */
71031 		if (st.num_pairs >= max_init_pairs) {
71032 			duk__objlit_flush_keys(comp_ctx, &st);
71033 			DUK_ASSERT(st.num_pairs == 0);
71034 		}
71035 
71036 		/* Reset temp register state and reserve reg_temp and
71037 		 * reg_temp + 1 for handling the current property.
71038 		 */
71039 		DUK__SETTEMP(comp_ctx, st.temp_start + 2 * (duk_regconst_t) st.num_pairs);
71040 		reg_temp = DUK__ALLOCTEMPS(comp_ctx, 2);
71041 
71042 		/* NOTE: "get" and "set" are not officially ReservedWords and the lexer
71043 		 * currently treats them always like ordinary identifiers (DUK_TOK_GET
71044 		 * and DUK_TOK_SET are unused).  They need to be detected based on the
71045 		 * identifier string content.
71046 		 */
71047 
71048 		is_get = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
71049 		          comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_GET(thr));
71050 		is_set = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
71051 		          comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_SET(thr));
71052 		if ((is_get || is_set) && comp_ctx->curr_token.t != DUK_TOK_COLON) {
71053 			/* getter/setter */
71054 			duk_int_t fnum;
71055 
71056 			duk__objlit_flush_keys(comp_ctx, &st);
71057 			DUK_ASSERT(DUK__GETTEMP(comp_ctx) == st.temp_start);  /* 2 regs are guaranteed to be allocated w.r.t. temp_max */
71058 			reg_temp = DUK__ALLOCTEMPS(comp_ctx, 2);
71059 
71060 			if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->curr_token, reg_temp) != 0) {
71061 				goto syntax_error;
71062 			}
71063 
71064 			/* curr_token = get/set name */
71065 			fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_GETSET);
71066 
71067 			duk__emit_a_bc(comp_ctx,
71068 			               DUK_OP_CLOSURE,
71069 			               st.temp_start + 1,
71070 			               (duk_regconst_t) fnum);
71071 
71072 			/* Slot C is used in a non-standard fashion (range of regs),
71073 			 * emitter code has special handling for it (must not set the
71074 			 * "no shuffle" flag).
71075 			 */
71076 			duk__emit_a_bc(comp_ctx,
71077 			              (is_get ? DUK_OP_INITGET : DUK_OP_INITSET) | DUK__EMIT_FLAG_A_IS_SOURCE,
71078 			              st.reg_obj,
71079 			              st.temp_start);   /* temp_start+0 = key, temp_start+1 = closure */
71080 
71081 			DUK_ASSERT(st.num_pairs == 0);  /* temp state is reset on next loop */
71082 #if defined(DUK_USE_ES6)
71083 		} else if (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
71084 		           (comp_ctx->curr_token.t == DUK_TOK_COMMA || comp_ctx->curr_token.t == DUK_TOK_RCURLY)) {
71085 			duk_bool_t load_rc;
71086 
71087 			load_rc = duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp);
71088 			DUK_UNREF(load_rc);
71089 			DUK_ASSERT(load_rc == 0);  /* always succeeds because token is identifier */
71090 
71091 			duk__ivalue_var_hstring(comp_ctx, res, comp_ctx->prev_token.str1);
71092 			DUK_ASSERT(DUK__GETTEMP(comp_ctx) == reg_temp + 1);
71093 			duk__ivalue_toforcedreg(comp_ctx, res, reg_temp + 1);
71094 
71095 			st.num_pairs++;
71096 		} else if ((comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER ||
71097 		            comp_ctx->prev_token.t == DUK_TOK_STRING ||
71098 		            comp_ctx->prev_token.t == DUK_TOK_NUMBER) &&
71099 		           comp_ctx->curr_token.t == DUK_TOK_LPAREN) {
71100 			duk_int_t fnum;
71101 
71102 			/* Parsing-wise there's a small hickup here: the token parsing
71103 			 * state is one step too advanced for the function parse helper
71104 			 * compared to other cases.  The current solution is an extra
71105 			 * flag to indicate whether function parsing should use the
71106 			 * current or the previous token to starting parsing from.
71107 			 */
71108 
71109 			if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp) != 0) {
71110 				goto syntax_error;
71111 			}
71112 
71113 			fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_USE_PREVTOKEN | DUK__FUNC_FLAG_METDEF);
71114 
71115 			duk__emit_a_bc(comp_ctx,
71116 			               DUK_OP_CLOSURE,
71117 			               reg_temp + 1,
71118 			               (duk_regconst_t) fnum);
71119 
71120 			st.num_pairs++;
71121 #endif  /* DUK_USE_ES6 */
71122 		} else {
71123 #if defined(DUK_USE_ES6)
71124 			if (comp_ctx->prev_token.t == DUK_TOK_LBRACKET) {
71125 				/* ES2015 computed property name.  Executor ToPropertyKey()
71126 				 * coerces the key at runtime.
71127 				 */
71128 				DUK__SETTEMP(comp_ctx, reg_temp);
71129 				duk__expr_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR, reg_temp);
71130 				duk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);
71131 
71132 				/* XXX: If next token is '(' we're dealing with
71133 				 * the method shorthand with a computed name,
71134 				 * e.g. { [Symbol.for('foo')](a,b) {} }.  This
71135 				 * form is not yet supported and causes a
71136 				 * SyntaxError on the DUK_TOK_COLON check below.
71137 				 */
71138 			}
71139 			else
71140 #endif  /* DUK_USE_ES6 */
71141 			{
71142 				if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp) != 0) {
71143 					goto syntax_error;
71144 				}
71145 			}
71146 
71147 			duk__advance_expect(comp_ctx, DUK_TOK_COLON);
71148 
71149 			DUK__SETTEMP(comp_ctx, reg_temp + 1);
71150 			duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp + 1 /*forced_reg*/);
71151 
71152 			st.num_pairs++;
71153 		}
71154 	}  /* property loop */
71155 
71156 	/* Flush remaining properties. */
71157 	duk__objlit_flush_keys(comp_ctx, &st);
71158 	DUK_ASSERT(st.num_pairs == 0);
71159 	DUK_ASSERT(DUK__GETTEMP(comp_ctx) == st.temp_start);
71160 
71161 	/* Update initial size for NEWOBJ.  The init size doesn't need to be
71162 	 * exact as the purpose is just to avoid object resizes in common
71163 	 * cases.  The size is capped to field A limit, and will be too high
71164 	 * if the object literal contains duplicate keys (this is harmless but
71165 	 * increases memory traffic if the object is compacted later on).
71166 	 */
71167 #if !defined(DUK_USE_PREFER_SIZE)
71168 	instr = duk__get_instr_ptr(comp_ctx, pc_newobj);
71169 	instr->ins |= DUK_ENC_OP_A(0, st.num_total_pairs > DUK_BC_A_MAX ? DUK_BC_A_MAX : st.num_total_pairs);
71170 #endif
71171 
71172 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
71173 	duk__advance(comp_ctx);  /* No RegExp after object literal. */
71174 
71175 	duk__ivalue_regconst(res, st.reg_obj);
71176 	return;
71177 
71178  syntax_error:
71179 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_OBJECT_LITERAL);
71180 	DUK_WO_NORETURN(return;);
71181 }
71182 
71183 /* Parse argument list.  Arguments are written to temps starting from
71184  * "next temp".  Returns number of arguments parsed.  Expects left paren
71185  * to be already eaten, and eats the right paren before returning.
71186  */
71187 DUK_LOCAL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
71188 	duk_int_t nargs = 0;
71189 	duk_regconst_t reg_temp;
71190 
71191 	/* Note: expect that caller has already eaten the left paren */
71192 
71193 	DUK_DDD(DUK_DDDPRINT("start parsing arguments, prev_token.t=%ld, curr_token.t=%ld",
71194 	                     (long) comp_ctx->prev_token.t, (long) comp_ctx->curr_token.t));
71195 
71196 	for (;;) {
71197 		if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
71198 			break;
71199 		}
71200 		if (nargs > 0) {
71201 			duk__advance_expect(comp_ctx, DUK_TOK_COMMA);
71202 		}
71203 
71204 		/* We want the argument expression value to go to "next temp"
71205 		 * without additional moves.  That should almost always be the
71206 		 * case, but we double check after expression parsing.
71207 		 *
71208 		 * This is not the cleanest possible approach.
71209 		 */
71210 
71211 		reg_temp = DUK__ALLOCTEMP(comp_ctx);  /* bump up "allocated" reg count, just in case */
71212 		DUK__SETTEMP(comp_ctx, reg_temp);
71213 
71214 		/* binding power must be high enough to NOT allow comma expressions directly */
71215 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp);  /* always allow 'in', coerce to 'tr' just in case */
71216 
71217 		DUK__SETTEMP(comp_ctx, reg_temp + 1);
71218 		nargs++;
71219 
71220 		DUK_DDD(DUK_DDDPRINT("argument #%ld written into reg %ld", (long) nargs, (long) reg_temp));
71221 	}
71222 
71223 	/* eat the right paren */
71224 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* RegExp mode does not matter. */
71225 
71226 	DUK_DDD(DUK_DDDPRINT("end parsing arguments"));
71227 
71228 	return nargs;
71229 }
71230 
71231 DUK_LOCAL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx) {
71232 	/* empty expressions can be detected conveniently with nud/led counts */
71233 	return (comp_ctx->curr_func.nud_count == 0) &&
71234 	       (comp_ctx->curr_func.led_count == 0);
71235 }
71236 
71237 DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
71238 	duk_hthread *thr = comp_ctx->thr;
71239 	duk_token *tk;
71240 	duk_regconst_t temp_at_entry;
71241 	duk_small_uint_t tok;
71242 	duk_uint32_t args;  /* temp variable to pass constants and flags to shared code */
71243 
71244 	/*
71245 	 *  ctx->prev_token     token to process with duk__expr_nud()
71246 	 *  ctx->curr_token     updated by caller
71247 	 *
71248 	 *  Note: the token in the switch below has already been eaten.
71249 	 */
71250 
71251 	temp_at_entry = DUK__GETTEMP(comp_ctx);
71252 
71253 	comp_ctx->curr_func.nud_count++;
71254 
71255 	tk = &comp_ctx->prev_token;
71256 	tok = tk->t;
71257 	res->t = DUK_IVAL_NONE;
71258 
71259 	DUK_DDD(DUK_DDDPRINT("duk__expr_nud(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
71260 	                     (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));
71261 
71262 	switch (tok) {
71263 
71264 	/* PRIMARY EXPRESSIONS */
71265 
71266 	case DUK_TOK_THIS: {
71267 		duk_regconst_t reg_temp;
71268 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
71269 		duk__emit_bc(comp_ctx,
71270 		             DUK_OP_LDTHIS,
71271 		             reg_temp);
71272 		duk__ivalue_regconst(res, reg_temp);
71273 		return;
71274 	}
71275 	case DUK_TOK_IDENTIFIER: {
71276 		duk__ivalue_var_hstring(comp_ctx, res, tk->str1);
71277 		return;
71278 	}
71279 	case DUK_TOK_NULL: {
71280 		duk_push_null(thr);
71281 		goto plain_value;
71282 	}
71283 	case DUK_TOK_TRUE: {
71284 		duk_push_true(thr);
71285 		goto plain_value;
71286 	}
71287 	case DUK_TOK_FALSE: {
71288 		duk_push_false(thr);
71289 		goto plain_value;
71290 	}
71291 	case DUK_TOK_NUMBER: {
71292 		duk_push_number(thr, tk->num);
71293 		goto plain_value;
71294 	}
71295 	case DUK_TOK_STRING: {
71296 		DUK_ASSERT(tk->str1 != NULL);
71297 		duk_push_hstring(thr, tk->str1);
71298 		goto plain_value;
71299 	}
71300 	case DUK_TOK_REGEXP: {
71301 #if defined(DUK_USE_REGEXP_SUPPORT)
71302 		duk_regconst_t reg_temp;
71303 		duk_regconst_t rc_re_bytecode;  /* const */
71304 		duk_regconst_t rc_re_source;    /* const */
71305 
71306 		DUK_ASSERT(tk->str1 != NULL);
71307 		DUK_ASSERT(tk->str2 != NULL);
71308 
71309 		DUK_DDD(DUK_DDDPRINT("emitting regexp op, str1=%!O, str2=%!O",
71310 		                     (duk_heaphdr *) tk->str1,
71311 		                     (duk_heaphdr *) tk->str2));
71312 
71313 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
71314 		duk_push_hstring(thr, tk->str1);
71315 		duk_push_hstring(thr, tk->str2);
71316 
71317 		/* [ ... pattern flags ] */
71318 
71319 		duk_regexp_compile(thr);
71320 
71321 		/* [ ... escaped_source bytecode ] */
71322 
71323 		rc_re_bytecode = duk__getconst(comp_ctx);
71324 		rc_re_source = duk__getconst(comp_ctx);
71325 
71326 		duk__emit_a_b_c(comp_ctx,
71327 		                DUK_OP_REGEXP | DUK__EMIT_FLAG_BC_REGCONST,
71328 		                reg_temp /*a*/,
71329 		                rc_re_bytecode /*b*/,
71330 		                rc_re_source /*c*/);
71331 
71332 		duk__ivalue_regconst(res, reg_temp);
71333 		return;
71334 #else  /* DUK_USE_REGEXP_SUPPORT */
71335 		goto syntax_error;
71336 #endif  /* DUK_USE_REGEXP_SUPPORT */
71337 	}
71338 	case DUK_TOK_LBRACKET: {
71339 		DUK_DDD(DUK_DDDPRINT("parsing array literal"));
71340 		duk__nud_array_literal(comp_ctx, res);
71341 		return;
71342 	}
71343 	case DUK_TOK_LCURLY: {
71344 		DUK_DDD(DUK_DDDPRINT("parsing object literal"));
71345 		duk__nud_object_literal(comp_ctx, res);
71346 		return;
71347 	}
71348 	case DUK_TOK_LPAREN: {
71349 		duk_bool_t prev_allow_in;
71350 
71351 		comp_ctx->curr_func.paren_level++;
71352 		prev_allow_in = comp_ctx->curr_func.allow_in;
71353 		comp_ctx->curr_func.allow_in = 1; /* reset 'allow_in' for parenthesized expression */
71354 
71355 		duk__expr(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression, terminates at a ')' */
71356 
71357 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* No RegExp after parenthesized expression. */
71358 		comp_ctx->curr_func.allow_in = prev_allow_in;
71359 		comp_ctx->curr_func.paren_level--;
71360 		return;
71361 	}
71362 
71363 	/* MEMBER/NEW/CALL EXPRESSIONS */
71364 
71365 	case DUK_TOK_NEW: {
71366 		/*
71367 		 *  Parsing an expression starting with 'new' is tricky because
71368 		 *  there are multiple possible productions deriving from
71369 		 *  LeftHandSideExpression which begin with 'new'.
71370 		 *
71371 		 *  We currently resort to one-token lookahead to distinguish the
71372 		 *  cases.  Hopefully this is correct.  The binding power must be
71373 		 *  such that parsing ends at an LPAREN (CallExpression) but not at
71374 		 *  a PERIOD or LBRACKET (MemberExpression).
71375 		 *
71376 		 *  See doc/compiler.rst for discussion on the parsing approach,
71377 		 *  and testcases/test-dev-new.js for a bunch of documented tests.
71378 		 */
71379 
71380 		duk_regconst_t reg_target;
71381 		duk_int_t nargs;
71382 
71383 		DUK_DDD(DUK_DDDPRINT("begin parsing new expression"));
71384 
71385 		reg_target = DUK__ALLOCTEMPS(comp_ctx, 2);
71386 
71387 #if defined(DUK_USE_ES6)
71388 		if (comp_ctx->curr_token.t == DUK_TOK_PERIOD) {
71389 			/* new.target */
71390 			DUK_DDD(DUK_DDDPRINT("new.target"));
71391 			duk__advance(comp_ctx);
71392 			if (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER ||
71393 			    !duk_hstring_equals_ascii_cstring(comp_ctx->curr_token.str1, "target")) {
71394 				goto syntax_error_newtarget;
71395 			}
71396 			if (comp_ctx->curr_func.is_global) {
71397 				goto syntax_error_newtarget;
71398 			}
71399 			duk__advance(comp_ctx);
71400 			duk__emit_bc(comp_ctx,
71401 			             DUK_OP_NEWTARGET,
71402 			             reg_target);
71403 			duk__ivalue_regconst(res, reg_target);
71404 			return;
71405 		}
71406 #endif  /* DUK_USE_ES6 */
71407 
71408 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_CALL /*rbp_flags*/, reg_target /*forced_reg*/);
71409 		duk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, reg_target + 1);  /* default instance */
71410 		DUK__SETTEMP(comp_ctx, reg_target + 2);
71411 
71412 		/* XXX: 'new obj.noSuch()' doesn't use GETPROPC now which
71413 		 * makes the error message worse than for obj.noSuch().
71414 		 */
71415 
71416 		if (comp_ctx->curr_token.t == DUK_TOK_LPAREN) {
71417 			/* 'new' MemberExpression Arguments */
71418 			DUK_DDD(DUK_DDDPRINT("new expression has argument list"));
71419 			duk__advance(comp_ctx);
71420 			nargs = duk__parse_arguments(comp_ctx, res);  /* parse args starting from "next temp", reg_target + 1 */
71421 			/* right paren eaten */
71422 		} else {
71423 			/* 'new' MemberExpression */
71424 			DUK_DDD(DUK_DDDPRINT("new expression has no argument list"));
71425 			nargs = 0;
71426 		}
71427 
71428 		duk__emit_a_bc(comp_ctx,
71429 		              DUK_OP_CALL0 | DUK_BC_CALL_FLAG_CONSTRUCT,
71430 		              nargs /*num_args*/,
71431 		              reg_target /*target*/);
71432 
71433 		DUK_DDD(DUK_DDDPRINT("end parsing new expression"));
71434 
71435 		duk__ivalue_regconst(res, reg_target);
71436 		return;
71437 	}
71438 
71439 	/* FUNCTION EXPRESSIONS */
71440 
71441 	case DUK_TOK_FUNCTION: {
71442 		/* Function expression.  Note that any statement beginning with 'function'
71443 		 * is handled by the statement parser as a function declaration, or a
71444 		 * non-standard function expression/statement (or a SyntaxError).  We only
71445 		 * handle actual function expressions (occurring inside an expression) here.
71446 		 *
71447 		 * O(depth^2) parse count for inner functions is handled by recording a
71448 		 * lexer offset on the first compilation pass, so that the function can
71449 		 * be efficiently skipped on the second pass.  This is encapsulated into
71450 		 * duk__parse_func_like_fnum().
71451 		 */
71452 
71453 		duk_regconst_t reg_temp;
71454 		duk_int_t fnum;
71455 
71456 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
71457 
71458 		/* curr_token follows 'function' */
71459 		fnum = duk__parse_func_like_fnum(comp_ctx, 0 /*flags*/);
71460 		DUK_DDD(DUK_DDDPRINT("parsed inner function -> fnum %ld", (long) fnum));
71461 
71462 		duk__emit_a_bc(comp_ctx,
71463 		               DUK_OP_CLOSURE,
71464 		               reg_temp /*a*/,
71465 		               (duk_regconst_t) fnum /*bc*/);
71466 
71467 		duk__ivalue_regconst(res, reg_temp);
71468 		return;
71469 	}
71470 
71471 	/* UNARY EXPRESSIONS */
71472 
71473 	case DUK_TOK_DELETE: {
71474 		/* Delete semantics are a bit tricky.  The description in E5 specification
71475 		 * is kind of confusing, because it distinguishes between resolvability of
71476 		 * a reference (which is only known at runtime) seemingly at compile time
71477 		 * (= SyntaxError throwing).
71478 		 */
71479 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
71480 		if (res->t == DUK_IVAL_VAR) {
71481 			/* not allowed in strict mode, regardless of whether resolves;
71482 			 * in non-strict mode DELVAR handles both non-resolving and
71483 			 * resolving cases (the specification description is a bit confusing).
71484 			 */
71485 
71486 			duk_regconst_t reg_temp;
71487 			duk_regconst_t reg_varbind;
71488 			duk_regconst_t rc_varname;
71489 
71490 			if (comp_ctx->curr_func.is_strict) {
71491 				DUK_ERROR_SYNTAX(thr, DUK_STR_CANNOT_DELETE_IDENTIFIER);
71492 				DUK_WO_NORETURN(return;);
71493 			}
71494 
71495 			DUK__SETTEMP(comp_ctx, temp_at_entry);
71496 			reg_temp = DUK__ALLOCTEMP(comp_ctx);
71497 
71498 			duk_dup(thr, res->x1.valstack_idx);
71499 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
71500 				/* register bound variables are non-configurable -> always false */
71501 				duk__emit_bc(comp_ctx,
71502 				             DUK_OP_LDFALSE,
71503 				             reg_temp);
71504 			} else {
71505 				duk_dup(thr, res->x1.valstack_idx);
71506 				rc_varname = duk__getconst(comp_ctx);
71507 				duk__emit_a_bc(comp_ctx,
71508 				               DUK_OP_DELVAR,
71509 				               reg_temp,
71510 				               rc_varname);
71511 			}
71512 			duk__ivalue_regconst(res, reg_temp);
71513 		} else if (res->t == DUK_IVAL_PROP) {
71514 			duk_regconst_t reg_temp;
71515 			duk_regconst_t reg_obj;
71516 			duk_regconst_t rc_key;
71517 
71518 			DUK__SETTEMP(comp_ctx, temp_at_entry);
71519 			reg_temp = DUK__ALLOCTEMP(comp_ctx);
71520 			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
71521 			rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
71522 			duk__emit_a_b_c(comp_ctx,
71523 			                DUK_OP_DELPROP | DUK__EMIT_FLAG_BC_REGCONST,
71524 			                reg_temp,
71525 			                reg_obj,
71526 			                rc_key);
71527 
71528 			duk__ivalue_regconst(res, reg_temp);
71529 		} else {
71530 			/* non-Reference deletion is always 'true', even in strict mode */
71531 			duk_push_true(thr);
71532 			goto plain_value;
71533 		}
71534 		return;
71535 	}
71536 	case DUK_TOK_VOID: {
71537 		duk__expr_toplain_ignore(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
71538 		duk_push_undefined(thr);
71539 		goto plain_value;
71540 	}
71541 	case DUK_TOK_TYPEOF: {
71542 		/* 'typeof' must handle unresolvable references without throwing
71543 		 * a ReferenceError (E5 Section 11.4.3).  Register mapped values
71544 		 * will never be unresolvable so special handling is only required
71545 		 * when an identifier is a "slow path" one.
71546 		 */
71547 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
71548 
71549 		if (res->t == DUK_IVAL_VAR) {
71550 			duk_regconst_t reg_varbind;
71551 			duk_regconst_t rc_varname;
71552 			duk_regconst_t reg_temp;
71553 
71554 			duk_dup(thr, res->x1.valstack_idx);
71555 			if (!duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
71556 				DUK_DDD(DUK_DDDPRINT("typeof for an identifier name which could not be resolved "
71557 				                     "at compile time, need to use special run-time handling"));
71558 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
71559 				duk__emit_a_bc(comp_ctx,
71560 				               DUK_OP_TYPEOFID,
71561 				               reg_temp,
71562 				               rc_varname);
71563 				duk__ivalue_regconst(res, reg_temp);
71564 				return;
71565 			}
71566 		}
71567 
71568 		args = DUK_OP_TYPEOF;
71569 		goto unary;
71570 	}
71571 	case DUK_TOK_INCREMENT: {
71572 		args = (DUK_OP_PREINCP << 8) + DUK_OP_PREINCR;
71573 		goto preincdec;
71574 	}
71575 	case DUK_TOK_DECREMENT: {
71576 		args = (DUK_OP_PREDECP << 8) + DUK_OP_PREDECR;
71577 		goto preincdec;
71578 	}
71579 	case DUK_TOK_ADD: {
71580 		/* unary plus */
71581 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
71582 		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
71583 		    duk_is_number(thr, res->x1.valstack_idx)) {
71584 			/* unary plus of a number is identity */
71585 			return;
71586 		}
71587 		args = DUK_OP_UNP;
71588 		goto unary;
71589 	}
71590 	case DUK_TOK_SUB: {
71591 		/* unary minus */
71592 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
71593 		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
71594 		    duk_is_number(thr, res->x1.valstack_idx)) {
71595 			/* this optimization is important to handle negative literals
71596 			 * (which are not directly provided by the lexical grammar)
71597 			 */
71598 			duk_tval *tv_num;
71599 			duk_double_union du;
71600 
71601 			tv_num = DUK_GET_TVAL_POSIDX(thr, res->x1.valstack_idx);
71602 			DUK_ASSERT(tv_num != NULL);
71603 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_num));
71604 			du.d = DUK_TVAL_GET_NUMBER(tv_num);
71605 			du.d = -du.d;
71606 			DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
71607 			DUK_TVAL_SET_NUMBER(tv_num, du.d);
71608 			return;
71609 		}
71610 		args = DUK_OP_UNM;
71611 		goto unary;
71612 	}
71613 	case DUK_TOK_BNOT: {
71614 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
71615 		args = DUK_OP_BNOT;
71616 		goto unary;
71617 	}
71618 	case DUK_TOK_LNOT: {
71619 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
71620 		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE) {
71621 			/* Very minimal inlining to handle common idioms '!0' and '!1',
71622 			 * and also boolean arguments like '!false' and '!true'.
71623 			 */
71624 			duk_tval *tv_val;
71625 
71626 			tv_val = DUK_GET_TVAL_POSIDX(thr, res->x1.valstack_idx);
71627 			DUK_ASSERT(tv_val != NULL);
71628 			if (DUK_TVAL_IS_NUMBER(tv_val)) {
71629 				duk_double_t d;
71630 				d = DUK_TVAL_GET_NUMBER(tv_val);
71631 				if (duk_double_equals(d, 0.0)) {
71632 					/* Matches both +0 and -0 on purpose. */
71633 					DUK_DDD(DUK_DDDPRINT("inlined lnot: !0 -> true"));
71634 					DUK_TVAL_SET_BOOLEAN_TRUE(tv_val);
71635 					return;
71636 				} else if (duk_double_equals(d, 1.0)) {
71637 					DUK_DDD(DUK_DDDPRINT("inlined lnot: !1 -> false"));
71638 					DUK_TVAL_SET_BOOLEAN_FALSE(tv_val);
71639 					return;
71640 				}
71641 			} else if (DUK_TVAL_IS_BOOLEAN(tv_val)) {
71642 				duk_small_uint_t v;
71643 				v = DUK_TVAL_GET_BOOLEAN(tv_val);
71644 				DUK_DDD(DUK_DDDPRINT("inlined lnot boolean: %ld", (long) v));
71645 				DUK_ASSERT(v == 0 || v == 1);
71646 				DUK_TVAL_SET_BOOLEAN(tv_val, v ^ 0x01);
71647 				return;
71648 			}
71649 		}
71650 		args = DUK_OP_LNOT;
71651 		goto unary;
71652 	}
71653 
71654 	}  /* end switch */
71655 
71656 	DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
71657 	DUK_WO_NORETURN(return;);
71658 
71659  unary:
71660 	{
71661 		/* Unary opcodes use just the 'BC' register source because it
71662 		 * matches current shuffle limits, and maps cleanly to 16 high
71663 		 * bits of the opcode.
71664 		 */
71665 
71666 		duk_regconst_t reg_src, reg_res;
71667 
71668 		reg_src = duk__ivalue_toregconst_raw(comp_ctx, res, -1 /*forced_reg*/, 0 /*flags*/);
71669 		if (DUK__ISREG_TEMP(comp_ctx, reg_src)) {
71670 			reg_res = reg_src;
71671 		} else {
71672 			reg_res = DUK__ALLOCTEMP(comp_ctx);
71673 		}
71674 		duk__emit_a_bc(comp_ctx,
71675 		             args,
71676 		             reg_res,
71677 		             reg_src);
71678 		duk__ivalue_regconst(res, reg_res);
71679 		return;
71680 	}
71681 
71682  preincdec:
71683 	{
71684 		/* preincrement and predecrement */
71685 		duk_regconst_t reg_res;
71686 		duk_small_uint_t args_op1 = args & 0xff;  /* DUK_OP_PREINCR/DUK_OP_PREDECR */
71687 		duk_small_uint_t args_op2 = args >> 8;    /* DUK_OP_PREINCP_RR/DUK_OP_PREDECP_RR */
71688 
71689 		/* Specific assumptions for opcode numbering. */
71690 		DUK_ASSERT(DUK_OP_PREINCR + 4 == DUK_OP_PREINCV);
71691 		DUK_ASSERT(DUK_OP_PREDECR + 4 == DUK_OP_PREDECV);
71692 
71693 		reg_res = DUK__ALLOCTEMP(comp_ctx);
71694 
71695 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
71696 		if (res->t == DUK_IVAL_VAR) {
71697 			duk_hstring *h_varname;
71698 			duk_regconst_t reg_varbind;
71699 			duk_regconst_t rc_varname;
71700 
71701 			h_varname = duk_known_hstring(thr, res->x1.valstack_idx);
71702 
71703 			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
71704 				goto syntax_error;
71705 			}
71706 
71707 			duk_dup(thr, res->x1.valstack_idx);
71708 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
71709 				duk__emit_a_bc(comp_ctx,
71710 				               args_op1,  /* e.g. DUK_OP_PREINCR */
71711 				               reg_res,
71712 				               reg_varbind);
71713 			} else {
71714 				duk__emit_a_bc(comp_ctx,
71715 				                args_op1 + 4,  /* e.g. DUK_OP_PREINCV */
71716 				                reg_res,
71717 				                rc_varname);
71718 			}
71719 
71720 			DUK_DDD(DUK_DDDPRINT("preincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
71721 			                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
71722 		} else if (res->t == DUK_IVAL_PROP) {
71723 			duk_regconst_t reg_obj;  /* allocate to reg only (not const) */
71724 			duk_regconst_t rc_key;
71725 			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
71726 			rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
71727 			duk__emit_a_b_c(comp_ctx,
71728 			                args_op2 | DUK__EMIT_FLAG_BC_REGCONST,  /* e.g. DUK_OP_PREINCP */
71729 			                reg_res,
71730 			                reg_obj,
71731 			                rc_key);
71732 		} else {
71733 			/* Technically return value is not needed because INVLHS will
71734 			 * unconditially throw a ReferenceError.  Coercion is necessary
71735 			 * for proper semantics (consider ToNumber() called for an object).
71736 			 * Use DUK_OP_UNP with a dummy register to get ToNumber().
71737 			 */
71738 
71739 			duk__ivalue_toforcedreg(comp_ctx, res, reg_res);
71740 			duk__emit_bc(comp_ctx,
71741 			             DUK_OP_UNP,
71742 			             reg_res);  /* for side effects, result ignored */
71743 			duk__emit_op_only(comp_ctx,
71744 			                  DUK_OP_INVLHS);
71745 		}
71746 		DUK__SETTEMP(comp_ctx, reg_res + 1);
71747 		duk__ivalue_regconst(res, reg_res);
71748 		return;
71749 	}
71750 
71751  plain_value:
71752 	{
71753 		/* Stack top contains plain value */
71754 		duk__ivalue_plain_fromstack(comp_ctx, res);
71755 		return;
71756 	}
71757 
71758 #if defined(DUK_USE_ES6)
71759  syntax_error_newtarget:
71760 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_NEWTARGET);
71761 	DUK_WO_NORETURN(return;);
71762 #endif
71763 
71764  syntax_error:
71765 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);
71766 	DUK_WO_NORETURN(return;);
71767 }
71768 
71769 /* XXX: add flag to indicate whether caller cares about return value; this
71770  * affects e.g. handling of assignment expressions.  This change needs API
71771  * changes elsewhere too.
71772  */
71773 DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res) {
71774 	duk_hthread *thr = comp_ctx->thr;
71775 	duk_token *tk;
71776 	duk_small_uint_t tok;
71777 	duk_uint32_t args;  /* temp variable to pass constants and flags to shared code */
71778 
71779 	/*
71780 	 *  ctx->prev_token     token to process with duk__expr_led()
71781 	 *  ctx->curr_token     updated by caller
71782 	 */
71783 
71784 	comp_ctx->curr_func.led_count++;
71785 
71786 	/* The token in the switch has already been eaten here */
71787 	tk = &comp_ctx->prev_token;
71788 	tok = tk->t;
71789 
71790 	DUK_DDD(DUK_DDDPRINT("duk__expr_led(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
71791 	                     (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));
71792 
71793 	/* XXX: default priority for infix operators is duk__expr_lbp(tok) -> get it here? */
71794 
71795 	switch (tok) {
71796 
71797 	/* PRIMARY EXPRESSIONS */
71798 
71799 	case DUK_TOK_PERIOD: {
71800 		/* Property access expressions are critical for correct LHS ordering,
71801 		 * see comments in duk__expr()!
71802 		 *
71803 		 * A conservative approach would be to use duk__ivalue_totempconst()
71804 		 * for 'left'.  However, allowing a reg-bound variable seems safe here
71805 		 * and is nice because "foo.bar" is a common expression.  If the ivalue
71806 		 * is used in an expression a GETPROP will occur before any changes to
71807 		 * the base value can occur.  If the ivalue is used as an assignment
71808 		 * LHS, the assignment code will ensure the base value is safe from
71809 		 * RHS mutation.
71810 		 */
71811 
71812 		/* XXX: This now coerces an identifier into a GETVAR to a temp, which
71813 		 * causes an extra LDREG in call setup.  It's sufficient to coerce to a
71814 		 * unary ivalue?
71815 		 */
71816 		duk__ivalue_toplain(comp_ctx, left);
71817 
71818 		/* NB: must accept reserved words as property name */
71819 		if (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER) {
71820 			DUK_ERROR_SYNTAX(thr, DUK_STR_EXPECTED_IDENTIFIER);
71821 			DUK_WO_NORETURN(return;);
71822 		}
71823 
71824 		res->t = DUK_IVAL_PROP;
71825 		duk__copy_ispec(comp_ctx, &left->x1, &res->x1);  /* left.x1 -> res.x1 */
71826 		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
71827 		duk_push_hstring(thr, comp_ctx->curr_token.str1);
71828 		duk_replace(thr, res->x2.valstack_idx);
71829 		res->x2.t = DUK_ISPEC_VALUE;
71830 
71831 		/* special RegExp literal handling after IdentifierName */
71832 		comp_ctx->curr_func.reject_regexp_in_adv = 1;
71833 
71834 		duk__advance(comp_ctx);
71835 		return;
71836 	}
71837 	case DUK_TOK_LBRACKET: {
71838 		/* Property access expressions are critical for correct LHS ordering,
71839 		 * see comments in duk__expr()!
71840 		 */
71841 
71842 		/* XXX: optimize temp reg use */
71843 		/* XXX: similar coercion issue as in DUK_TOK_PERIOD */
71844 		/* XXX: coerce to regs? it might be better for enumeration use, where the
71845 		 * same PROP ivalue is used multiple times.  Or perhaps coerce PROP further
71846 		 * there?
71847 		 */
71848 		/* XXX: for simple cases like x['y'] an unnecessary LDREG is
71849 		 * emitted for the base value; could avoid it if we knew that
71850 		 * the key expression is safe (e.g. just a single literal).
71851 		 */
71852 
71853 		/* The 'left' value must not be a register bound variable
71854 		 * because it may be mutated during the rest of the expression
71855 		 * and E5.1 Section 11.2.1 specifies the order of evaluation
71856 		 * so that the base value is evaluated first.
71857 		 * See: test-bug-nested-prop-mutate.js.
71858 		 */
71859 		duk__ivalue_totempconst(comp_ctx, left);
71860 		duk__expr_toplain(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression, ']' terminates */
71861 		duk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);
71862 
71863 		res->t = DUK_IVAL_PROP;
71864 		duk__copy_ispec(comp_ctx, &res->x1, &res->x2);   /* res.x1 -> res.x2 */
71865 		duk__copy_ispec(comp_ctx, &left->x1, &res->x1);  /* left.x1 -> res.x1 */
71866 		return;
71867 	}
71868 	case DUK_TOK_LPAREN: {
71869 		/* function call */
71870 		duk_regconst_t reg_cs = DUK__ALLOCTEMPS(comp_ctx, 2);
71871 		duk_int_t nargs;
71872 		duk_small_uint_t call_op = DUK_OP_CALL0;
71873 
71874 		/* XXX: attempt to get the call result to "next temp" whenever
71875 		 * possible to avoid unnecessary register shuffles.
71876 		 */
71877 
71878 		/*
71879 		 *  Setup call: target and 'this' binding.  Three cases:
71880 		 *
71881 		 *    1. Identifier base (e.g. "foo()")
71882 		 *    2. Property base (e.g. "foo.bar()")
71883 		 *    3. Register base (e.g. "foo()()"; i.e. when a return value is a function)
71884 		 */
71885 
71886 		if (left->t == DUK_IVAL_VAR) {
71887 			duk_hstring *h_varname;
71888 			duk_regconst_t reg_varbind;
71889 			duk_regconst_t rc_varname;
71890 
71891 			DUK_DDD(DUK_DDDPRINT("function call with identifier base"));
71892 
71893 			h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
71894 			if (h_varname == DUK_HTHREAD_STRING_EVAL(thr)) {
71895 				/* Potential direct eval call detected, flag the CALL
71896 				 * so that a run-time "direct eval" check is made and
71897 				 * special behavior may be triggered.  Note that this
71898 				 * does not prevent 'eval' from being register bound.
71899 				 */
71900 				DUK_DDD(DUK_DDDPRINT("function call with identifier 'eval' "
71901 				                     "-> using EVALCALL, marking function "
71902 				                     "as may_direct_eval"));
71903 				call_op |= DUK_BC_CALL_FLAG_CALLED_AS_EVAL;
71904 				comp_ctx->curr_func.may_direct_eval = 1;
71905 			}
71906 
71907 			duk_dup(thr, left->x1.valstack_idx);
71908 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
71909 				duk__emit_a_bc(comp_ctx,
71910 				              DUK_OP_CSREG | DUK__EMIT_FLAG_A_IS_SOURCE,
71911 				              reg_varbind,
71912 				              reg_cs + 0);
71913 			} else {
71914 				/* XXX: expand target register or constant field to
71915 				 * reduce shuffling.
71916 				 */
71917 				DUK_ASSERT(DUK__ISCONST(rc_varname));
71918 				duk__emit_a_b(comp_ctx,
71919 				              DUK_OP_CSVAR | DUK__EMIT_FLAG_BC_REGCONST,
71920 				              reg_cs + 0,
71921 				              rc_varname);
71922 			}
71923 		} else if (left->t == DUK_IVAL_PROP) {
71924 			/* Call through a property lookup, E5 Section 11.2.3, step 6.a.i,
71925 			 * E5 Section 10.4.3.  There used to be a separate CSPROP opcode
71926 			 * but a typical call setup took 3 opcodes (e.g. LDREG, LDCONST,
71927 			 * CSPROP) and the same can be achieved with ordinary loads.
71928 			 */
71929 #if defined(DUK_USE_VERBOSE_ERRORS)
71930 			duk_regconst_t reg_key;
71931 #endif
71932 
71933 			DUK_DDD(DUK_DDDPRINT("function call with property base"));
71934 
71935 			/* XXX: For Math.sin() this generates: LDCONST + LDREG +
71936 			 * GETPROPC + call.  The LDREG is unnecessary because LDCONST
71937 			 * could be loaded directly into reg_cs + 1.  This doesn't
71938 			 * happen now because a variable cannot be in left->x1 of a
71939 			 * DUK_IVAL_PROP.  We could notice that left->x1 is a temp
71940 			 * and reuse, but it would still be in the wrong position
71941 			 * (reg_cs + 0 rather than reg_cs + 1).
71942 			 */
71943 			duk__ispec_toforcedreg(comp_ctx, &left->x1, reg_cs + 1);  /* base */
71944 #if defined(DUK_USE_VERBOSE_ERRORS)
71945 			reg_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
71946 			duk__emit_a_b_c(comp_ctx,
71947 			                DUK_OP_GETPROPC | DUK__EMIT_FLAG_BC_REGCONST,
71948 			                reg_cs + 0,
71949 			                reg_cs + 1,
71950 			                reg_key);
71951 #else
71952 			duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0);  /* base[key] */
71953 #endif
71954 		} else {
71955 			DUK_DDD(DUK_DDDPRINT("function call with register base"));
71956 
71957 			duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0);
71958 #if 0
71959 			duk__emit_a_bc(comp_ctx,
71960 			               DUK_OP_CSREG | DUK__EMIT_FLAG_A_IS_SOURCE,
71961 			               reg_cs + 0,
71962 			               reg_cs + 0);  /* in-place setup */
71963 #endif
71964 			/* Because of in-place setup, REGCS is equivalent to
71965 			 * just this LDUNDEF.
71966 			 */
71967 			duk__emit_bc(comp_ctx, DUK_OP_LDUNDEF, reg_cs + 1);
71968 		}
71969 
71970 		DUK__SETTEMP(comp_ctx, reg_cs + 2);
71971 		nargs = duk__parse_arguments(comp_ctx, res);  /* parse args starting from "next temp" */
71972 
71973 		/* Tailcalls are handled by back-patching the already emitted opcode
71974 		 * later in return statement parser.
71975 		 */
71976 
71977 		duk__emit_a_bc(comp_ctx,
71978 		               call_op,
71979 		               (duk_regconst_t) nargs /*numargs*/,
71980 		               reg_cs /*basereg*/);
71981 		DUK__SETTEMP(comp_ctx, reg_cs + 1);    /* result in csreg */
71982 
71983 		duk__ivalue_regconst(res, reg_cs);
71984 		return;
71985 	}
71986 
71987 	/* POSTFIX EXPRESSION */
71988 
71989 	case DUK_TOK_INCREMENT: {
71990 		args = (DUK_OP_POSTINCP_RR << 16) + (DUK_OP_POSTINCR << 8) + 0;
71991 		goto postincdec;
71992 	}
71993 	case DUK_TOK_DECREMENT: {
71994 		args = (DUK_OP_POSTDECP_RR << 16) + (DUK_OP_POSTDECR << 8) + 0;
71995 		goto postincdec;
71996 	}
71997 
71998 	/* EXPONENTIATION EXPRESSION */
71999 
72000 #if defined(DUK_USE_ES7_EXP_OPERATOR)
72001 	case DUK_TOK_EXP: {
72002 		args = (DUK_OP_EXP << 8) + DUK__BP_EXPONENTIATION - 1;  /* UnaryExpression */
72003 		goto binary;
72004 	}
72005 #endif
72006 
72007 	/* MULTIPLICATIVE EXPRESSION */
72008 
72009 	case DUK_TOK_MUL: {
72010 		args = (DUK_OP_MUL << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */
72011 		goto binary;
72012 	}
72013 	case DUK_TOK_DIV: {
72014 		args = (DUK_OP_DIV << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */
72015 		goto binary;
72016 	}
72017 	case DUK_TOK_MOD: {
72018 		args = (DUK_OP_MOD << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */
72019 		goto binary;
72020 	}
72021 
72022 	/* ADDITIVE EXPRESSION */
72023 
72024 	case DUK_TOK_ADD: {
72025 		args = (DUK_OP_ADD << 8) + DUK__BP_ADDITIVE;  /* MultiplicativeExpression */
72026 		goto binary;
72027 	}
72028 	case DUK_TOK_SUB: {
72029 		args = (DUK_OP_SUB << 8) + DUK__BP_ADDITIVE;  /* MultiplicativeExpression */
72030 		goto binary;
72031 	}
72032 
72033 	/* SHIFT EXPRESSION */
72034 
72035 	case DUK_TOK_ALSHIFT: {
72036 		/* << */
72037 		args = (DUK_OP_BASL << 8) + DUK__BP_SHIFT;
72038 		goto binary;
72039 	}
72040 	case DUK_TOK_ARSHIFT: {
72041 		/* >> */
72042 		args = (DUK_OP_BASR << 8) + DUK__BP_SHIFT;
72043 		goto binary;
72044 	}
72045 	case DUK_TOK_RSHIFT: {
72046 		/* >>> */
72047 		args = (DUK_OP_BLSR << 8) + DUK__BP_SHIFT;
72048 		goto binary;
72049 	}
72050 
72051 	/* RELATIONAL EXPRESSION */
72052 
72053 	case DUK_TOK_LT: {
72054 		/* < */
72055 		args = (DUK_OP_LT << 8) + DUK__BP_RELATIONAL;
72056 		goto binary;
72057 	}
72058 	case DUK_TOK_GT: {
72059 		args = (DUK_OP_GT << 8) + DUK__BP_RELATIONAL;
72060 		goto binary;
72061 	}
72062 	case DUK_TOK_LE: {
72063 		args = (DUK_OP_LE << 8) + DUK__BP_RELATIONAL;
72064 		goto binary;
72065 	}
72066 	case DUK_TOK_GE: {
72067 		args = (DUK_OP_GE << 8) + DUK__BP_RELATIONAL;
72068 		goto binary;
72069 	}
72070 	case DUK_TOK_INSTANCEOF: {
72071 		args = (DUK_OP_INSTOF << 8) + DUK__BP_RELATIONAL;
72072 		goto binary;
72073 	}
72074 	case DUK_TOK_IN: {
72075 		args = (DUK_OP_IN << 8) + DUK__BP_RELATIONAL;
72076 		goto binary;
72077 	}
72078 
72079 	/* EQUALITY EXPRESSION */
72080 
72081 	case DUK_TOK_EQ: {
72082 		args = (DUK_OP_EQ << 8) + DUK__BP_EQUALITY;
72083 		goto binary;
72084 	}
72085 	case DUK_TOK_NEQ: {
72086 		args = (DUK_OP_NEQ << 8) + DUK__BP_EQUALITY;
72087 		goto binary;
72088 	}
72089 	case DUK_TOK_SEQ: {
72090 		args = (DUK_OP_SEQ << 8) + DUK__BP_EQUALITY;
72091 		goto binary;
72092 	}
72093 	case DUK_TOK_SNEQ: {
72094 		args = (DUK_OP_SNEQ << 8) + DUK__BP_EQUALITY;
72095 		goto binary;
72096 	}
72097 
72098 	/* BITWISE EXPRESSIONS */
72099 
72100 	case DUK_TOK_BAND: {
72101 		args = (DUK_OP_BAND << 8) + DUK__BP_BAND;
72102 		goto binary;
72103 	}
72104 	case DUK_TOK_BXOR: {
72105 		args = (DUK_OP_BXOR << 8) + DUK__BP_BXOR;
72106 		goto binary;
72107 	}
72108 	case DUK_TOK_BOR: {
72109 		args = (DUK_OP_BOR << 8) + DUK__BP_BOR;
72110 		goto binary;
72111 	}
72112 
72113 	/* LOGICAL EXPRESSIONS */
72114 
72115 	case DUK_TOK_LAND: {
72116 		/* syntactically left-associative but parsed as right-associative */
72117 		args = (1 << 8) + DUK__BP_LAND - 1;
72118 		goto binary_logical;
72119 	}
72120 	case DUK_TOK_LOR: {
72121 		/* syntactically left-associative but parsed as right-associative */
72122 		args = (0 << 8) + DUK__BP_LOR - 1;
72123 		goto binary_logical;
72124 	}
72125 
72126 	/* CONDITIONAL EXPRESSION */
72127 
72128 	case DUK_TOK_QUESTION: {
72129 		/* XXX: common reg allocation need is to reuse a sub-expression's temp reg,
72130 		 * but only if it really is a temp.  Nothing fancy here now.
72131 		 */
72132 		duk_regconst_t reg_temp;
72133 		duk_int_t pc_jump1;
72134 		duk_int_t pc_jump2;
72135 
72136 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
72137 		duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
72138 		duk__emit_if_true_skip(comp_ctx, reg_temp);
72139 		pc_jump1 = duk__emit_jump_empty(comp_ctx);  /* jump to false */
72140 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);  /* AssignmentExpression */
72141 		duk__advance_expect(comp_ctx, DUK_TOK_COLON);
72142 		pc_jump2 = duk__emit_jump_empty(comp_ctx);  /* jump to end */
72143 		duk__patch_jump_here(comp_ctx, pc_jump1);
72144 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);  /* AssignmentExpression */
72145 		duk__patch_jump_here(comp_ctx, pc_jump2);
72146 
72147 		DUK__SETTEMP(comp_ctx, reg_temp + 1);
72148 		duk__ivalue_regconst(res, reg_temp);
72149 		return;
72150 	}
72151 
72152 	/* ASSIGNMENT EXPRESSION */
72153 
72154 	case DUK_TOK_EQUALSIGN: {
72155 		/*
72156 		 *  Assignments are right associative, allows e.g.
72157 		 *    a = 5;
72158 		 *    a += b = 9;   // same as a += (b = 9)
72159 		 *  -> expression value 14, a = 14, b = 9
72160 		 *
72161 		 *  Right associativiness is reflected in the BP for recursion,
72162 		 *  "-1" ensures assignment operations are allowed.
72163 		 *
72164 		 *  XXX: just use DUK__BP_COMMA (i.e. no need for 2-step bp levels)?
72165 		 */
72166 		args = (DUK_OP_NONE << 8) + DUK__BP_ASSIGNMENT - 1;   /* DUK_OP_NONE marks a 'plain' assignment */
72167 		goto assign;
72168 	}
72169 	case DUK_TOK_ADD_EQ: {
72170 		/* right associative */
72171 		args = (DUK_OP_ADD << 8) + DUK__BP_ASSIGNMENT - 1;
72172 		goto assign;
72173 	}
72174 	case DUK_TOK_SUB_EQ: {
72175 		/* right associative */
72176 		args = (DUK_OP_SUB << 8) + DUK__BP_ASSIGNMENT - 1;
72177 		goto assign;
72178 	}
72179 	case DUK_TOK_MUL_EQ: {
72180 		/* right associative */
72181 		args = (DUK_OP_MUL << 8) + DUK__BP_ASSIGNMENT - 1;
72182 		goto assign;
72183 	}
72184 	case DUK_TOK_DIV_EQ: {
72185 		/* right associative */
72186 		args = (DUK_OP_DIV << 8) + DUK__BP_ASSIGNMENT - 1;
72187 		goto assign;
72188 	}
72189 	case DUK_TOK_MOD_EQ: {
72190 		/* right associative */
72191 		args = (DUK_OP_MOD << 8) + DUK__BP_ASSIGNMENT - 1;
72192 		goto assign;
72193 	}
72194 #if defined(DUK_USE_ES7_EXP_OPERATOR)
72195 	case DUK_TOK_EXP_EQ: {
72196 		/* right associative */
72197 		args = (DUK_OP_EXP << 8) + DUK__BP_ASSIGNMENT - 1;
72198 		goto assign;
72199 	}
72200 #endif
72201 	case DUK_TOK_ALSHIFT_EQ: {
72202 		/* right associative */
72203 		args = (DUK_OP_BASL << 8) + DUK__BP_ASSIGNMENT - 1;
72204 		goto assign;
72205 	}
72206 	case DUK_TOK_ARSHIFT_EQ: {
72207 		/* right associative */
72208 		args = (DUK_OP_BASR << 8) + DUK__BP_ASSIGNMENT - 1;
72209 		goto assign;
72210 	}
72211 	case DUK_TOK_RSHIFT_EQ: {
72212 		/* right associative */
72213 		args = (DUK_OP_BLSR << 8) + DUK__BP_ASSIGNMENT - 1;
72214 		goto assign;
72215 	}
72216 	case DUK_TOK_BAND_EQ: {
72217 		/* right associative */
72218 		args = (DUK_OP_BAND << 8) + DUK__BP_ASSIGNMENT - 1;
72219 		goto assign;
72220 	}
72221 	case DUK_TOK_BOR_EQ: {
72222 		/* right associative */
72223 		args = (DUK_OP_BOR << 8) + DUK__BP_ASSIGNMENT - 1;
72224 		goto assign;
72225 	}
72226 	case DUK_TOK_BXOR_EQ: {
72227 		/* right associative */
72228 		args = (DUK_OP_BXOR << 8) + DUK__BP_ASSIGNMENT - 1;
72229 		goto assign;
72230 	}
72231 
72232 	/* COMMA */
72233 
72234 	case DUK_TOK_COMMA: {
72235 		/* right associative */
72236 
72237 		duk__ivalue_toplain_ignore(comp_ctx, left);  /* need side effects, not value */
72238 		duk__expr_toplain(comp_ctx, res, DUK__BP_COMMA - 1 /*rbp_flags*/);
72239 
72240 		/* return 'res' (of right part) as our result */
72241 		return;
72242 	}
72243 
72244 	default: {
72245 		break;
72246 	}
72247 	}
72248 
72249 	DUK_D(DUK_DPRINT("parse error: unexpected token: %ld", (long) tok));
72250 	DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
72251 	DUK_WO_NORETURN(return;);
72252 
72253 #if 0
72254 	/* XXX: shared handling for 'duk__expr_lhs'? */
72255 	if (comp_ctx->curr_func.paren_level == 0 && XXX) {
72256 		comp_ctx->curr_func.duk__expr_lhs = 0;
72257 	}
72258 #endif
72259 
72260  binary:
72261 	/*
72262 	 *  Shared handling of binary operations
72263 	 *
72264 	 *  args = (opcode << 8) + rbp
72265 	 */
72266 	{
72267 		duk__ivalue_toplain(comp_ctx, left);
72268 		duk__expr_toplain(comp_ctx, res, args & 0xff /*rbp_flags*/);
72269 
72270 		/* combine left->x1 and res->x1 (right->x1, really) -> (left->x1 OP res->x1) */
72271 		DUK_ASSERT(left->t == DUK_IVAL_PLAIN);
72272 		DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
72273 
72274 		res->t = DUK_IVAL_ARITH;
72275 		res->op = (args >> 8) & 0xff;
72276 
72277 		res->x2.t = res->x1.t;
72278 		res->x2.regconst = res->x1.regconst;
72279 		duk_copy(thr, res->x1.valstack_idx, res->x2.valstack_idx);
72280 
72281 		res->x1.t = left->x1.t;
72282 		res->x1.regconst = left->x1.regconst;
72283 		duk_copy(thr, left->x1.valstack_idx, res->x1.valstack_idx);
72284 
72285 		DUK_DDD(DUK_DDDPRINT("binary op, res: t=%ld, x1.t=%ld, x1.regconst=0x%08lx, x2.t=%ld, x2.regconst=0x%08lx",
72286 		                     (long) res->t, (long) res->x1.t, (unsigned long) res->x1.regconst, (long) res->x2.t, (unsigned long) res->x2.regconst));
72287 		return;
72288 	}
72289 
72290  binary_logical:
72291 	/*
72292 	 *  Shared handling for logical AND and logical OR.
72293 	 *
72294 	 *  args = (truthval << 8) + rbp
72295 	 *
72296 	 *  Truthval determines when to skip right-hand-side.
72297 	 *  For logical AND truthval=1, for logical OR truthval=0.
72298 	 *
72299 	 *  See doc/compiler.rst for discussion on compiling logical
72300 	 *  AND and OR expressions.  The approach here is very simplistic,
72301 	 *  generating extra jumps and multiple evaluations of truth values,
72302 	 *  but generates code on-the-fly with only local back-patching.
72303 	 *
72304 	 *  Both logical AND and OR are syntactically left-associated.
72305 	 *  However, logical ANDs are compiled as right associative
72306 	 *  expressions, i.e. "A && B && C" as "A && (B && C)", to allow
72307 	 *  skip jumps to skip over the entire tail.  Similarly for logical OR.
72308 	 */
72309 
72310 	{
72311 		duk_regconst_t reg_temp;
72312 		duk_int_t pc_jump;
72313 		duk_small_uint_t args_truthval = args >> 8;
72314 		duk_small_uint_t args_rbp = args & 0xff;
72315 
72316 		/* XXX: unoptimal use of temps, resetting */
72317 
72318 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
72319 
72320 		duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
72321 		DUK_ASSERT(DUK__ISREG(reg_temp));
72322 		duk__emit_bc(comp_ctx,
72323 		            (args_truthval ? DUK_OP_IFTRUE_R : DUK_OP_IFFALSE_R),
72324 		            reg_temp);  /* skip jump conditionally */
72325 		pc_jump = duk__emit_jump_empty(comp_ctx);
72326 		duk__expr_toforcedreg(comp_ctx, res, args_rbp /*rbp_flags*/, reg_temp /*forced_reg*/);
72327 		duk__patch_jump_here(comp_ctx, pc_jump);
72328 
72329 		duk__ivalue_regconst(res, reg_temp);
72330 		return;
72331 	}
72332 
72333  assign:
72334 	/*
72335 	 *  Shared assignment expression handling
72336 	 *
72337 	 *  args = (opcode << 8) + rbp
72338 	 *
72339 	 *  If 'opcode' is DUK_OP_NONE, plain assignment without arithmetic.
72340 	 *  Syntactically valid left-hand-side forms which are not accepted as
72341 	 *  left-hand-side values (e.g. as in "f() = 1") must NOT cause a
72342 	 *  SyntaxError, but rather a run-time ReferenceError.
72343 	 *
72344 	 *  When evaluating X <op>= Y, the LHS (X) is conceptually evaluated
72345 	 *  to a temporary first.  The RHS is then evaluated.  Finally, the
72346 	 *  <op> is applied to the initial value of RHS (not the value after
72347 	 *  RHS evaluation), and written to X.  Doing so concretely generates
72348 	 *  inefficient code so we'd like to avoid the temporary when possible.
72349 	 *  See: https://github.com/svaarala/duktape/pull/992.
72350 	 *
72351 	 *  The expression value (final LHS value, written to RHS) is
72352 	 *  conceptually copied into a fresh temporary so that it won't
72353 	 *  change even if the LHS/RHS values change in outer expressions.
72354 	 *  For example, it'd be generally incorrect for the expression value
72355 	 *  to be the RHS register binding, unless there's a guarantee that it
72356 	 *  won't change during further expression evaluation.  Using the
72357 	 *  temporary concretely produces inefficient bytecode, so we try to
72358 	 *  avoid the extra temporary for some known-to-be-safe cases.
72359 	 *  Currently the only safe case we detect is a "top level assignment",
72360 	 *  for example "x = y + z;", where the assignment expression value is
72361 	 *  ignored.
72362 	 *  See: test-dev-assign-expr.js and test-bug-assign-mutate-gh381.js.
72363 	 */
72364 
72365 	{
72366 		duk_small_uint_t args_op = args >> 8;
72367 		duk_small_uint_t args_rbp = args & 0xff;
72368 		duk_bool_t toplevel_assign;
72369 
72370 		/* XXX: here we need to know if 'left' is left-hand-side compatible.
72371 		 * That information is no longer available from current expr parsing
72372 		 * state; it would need to be carried into the 'left' ivalue or by
72373 		 * some other means.
72374 		 */
72375 
72376 		/* A top-level assignment is e.g. "x = y;".  For these it's safe
72377 		 * to use the RHS as-is as the expression value, even if the RHS
72378 		 * is a reg-bound identifier.  The RHS ('res') is right associative
72379 		 * so it has consumed all other assignment level operations; the
72380 		 * only relevant lower binding power construct is comma operator
72381 		 * which will ignore the expression value provided here.  Usually
72382 		 * the top level assignment expression value is ignored, but it
72383 		 * is relevant for e.g. eval code.
72384 		 */
72385 		toplevel_assign = (comp_ctx->curr_func.nud_count == 1 && /* one token before */
72386 		                   comp_ctx->curr_func.led_count == 1);  /* one operator (= assign) */
72387 		DUK_DDD(DUK_DDDPRINT("assignment: nud_count=%ld, led_count=%ld, toplevel_assign=%ld",
72388 		                     (long) comp_ctx->curr_func.nud_count,
72389 		                     (long) comp_ctx->curr_func.led_count,
72390 		                     (long) toplevel_assign));
72391 
72392 		if (left->t == DUK_IVAL_VAR) {
72393 			duk_hstring *h_varname;
72394 			duk_regconst_t reg_varbind;
72395 			duk_regconst_t rc_varname;
72396 
72397 			DUK_ASSERT(left->x1.t == DUK_ISPEC_VALUE);  /* LHS is already side effect free */
72398 
72399 			h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
72400 			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
72401 				/* E5 Section 11.13.1 (and others for other assignments), step 4. */
72402 				goto syntax_error_lvalue;
72403 			}
72404 			duk_dup(thr, left->x1.valstack_idx);
72405 			(void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
72406 
72407 			if (args_op == DUK_OP_NONE) {
72408 				duk__expr(comp_ctx, res, args_rbp /*rbp_flags*/);
72409 				if (toplevel_assign) {
72410 					/* Any 'res' will do. */
72411 					DUK_DDD(DUK_DDDPRINT("plain assignment, toplevel assign, use as is"));
72412 				} else {
72413 					/* 'res' must be a plain ivalue, and not register-bound variable. */
72414 					DUK_DDD(DUK_DDDPRINT("plain assignment, not toplevel assign, ensure not a reg-bound identifier"));
72415 					if (res->t != DUK_IVAL_PLAIN || (res->x1.t == DUK_ISPEC_REGCONST &&
72416 					                                 DUK__ISREG_NOTTEMP(comp_ctx, res->x1.regconst))) {
72417 						duk__ivalue_totempconst(comp_ctx, res);
72418 					}
72419 				}
72420 			} else {
72421 				/* For X <op>= Y we need to evaluate the pre-op
72422 				 * value of X before evaluating the RHS: the RHS
72423 				 * can change X, but when we do <op> we must use
72424 				 * the pre-op value.
72425 				 */
72426 				duk_regconst_t reg_temp;
72427 
72428 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
72429 
72430 				if (reg_varbind >= 0) {
72431 					duk_regconst_t reg_res;
72432 					duk_regconst_t reg_src;
72433 					duk_int_t pc_temp_load;
72434 					duk_int_t pc_before_rhs;
72435 					duk_int_t pc_after_rhs;
72436 
72437 					if (toplevel_assign) {
72438 						/* 'reg_varbind' is the operation result and can also
72439 						 * become the expression value for top level assignments
72440 						 * such as: "var x; x += y;".
72441 						 */
72442 						DUK_DD(DUK_DDPRINT("<op>= expression is top level, write directly to reg_varbind"));
72443 						reg_res = reg_varbind;
72444 					} else {
72445 						/* Not safe to use 'reg_varbind' as assignment expression
72446 						 * value, so go through a temp.
72447 						 */
72448 						DUK_DD(DUK_DDPRINT("<op>= expression is not top level, write to reg_temp"));
72449 						reg_res = reg_temp;  /* reg_res should be smallest possible */
72450 						reg_temp = DUK__ALLOCTEMP(comp_ctx);
72451 					}
72452 
72453 					/* Try to optimize X <op>= Y for reg-bound
72454 					 * variables.  Detect side-effect free RHS
72455 					 * narrowly by seeing whether it emits code.
72456 					 * If not, rewind the code emitter and overwrite
72457 					 * the unnecessary temp reg load.
72458 					 */
72459 
72460 					pc_temp_load = duk__get_current_pc(comp_ctx);
72461 					duk__emit_a_bc(comp_ctx,
72462 					               DUK_OP_LDREG,
72463 					               reg_temp,
72464 					               reg_varbind);
72465 
72466 					pc_before_rhs = duk__get_current_pc(comp_ctx);
72467 					duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
72468 					DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
72469 					pc_after_rhs = duk__get_current_pc(comp_ctx);
72470 
72471 					DUK_DD(DUK_DDPRINT("pc_temp_load=%ld, pc_before_rhs=%ld, pc_after_rhs=%ld",
72472 					                   (long) pc_temp_load, (long) pc_before_rhs,
72473 					                   (long) pc_after_rhs));
72474 
72475 					if (pc_after_rhs == pc_before_rhs) {
72476 						/* Note: if the reg_temp load generated shuffling
72477 						 * instructions, we may need to rewind more than
72478 						 * one instruction, so use explicit PC computation.
72479 						 */
72480 						DUK_DD(DUK_DDPRINT("rhs is side effect free, rewind and avoid unnecessary temp for reg-based <op>="));
72481 						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));
72482 						reg_src = reg_varbind;
72483 					} else {
72484 						DUK_DD(DUK_DDPRINT("rhs evaluation emitted code, not sure if rhs is side effect free; use temp reg for LHS"));
72485 						reg_src = reg_temp;
72486 					}
72487 
72488 					duk__emit_a_b_c(comp_ctx,
72489 					                args_op | DUK__EMIT_FLAG_BC_REGCONST,
72490 					                reg_res,
72491 					                reg_src,
72492 					                res->x1.regconst);
72493 
72494 					res->x1.regconst = reg_res;
72495 
72496 					/* Ensure compact use of temps. */
72497 					if (DUK__ISREG_TEMP(comp_ctx, reg_res)) {
72498 						DUK__SETTEMP(comp_ctx, reg_res + 1);
72499 					}
72500 				} else {
72501 					/* When LHS is not register bound, always go through a
72502 					 * temporary.  No optimization for top level assignment.
72503 					 */
72504 
72505 					duk__emit_a_bc(comp_ctx,
72506 					               DUK_OP_GETVAR,
72507 					               reg_temp,
72508 					               rc_varname);
72509 
72510 					duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
72511 					DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
72512 
72513 					duk__emit_a_b_c(comp_ctx,
72514 					                args_op | DUK__EMIT_FLAG_BC_REGCONST,
72515 					                reg_temp,
72516 					                reg_temp,
72517 					                res->x1.regconst);
72518 					res->x1.regconst = reg_temp;
72519 				}
72520 
72521 				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
72522 			}
72523 
72524 			/* At this point 'res' holds the potential expression value.
72525 			 * It can be basically any ivalue here, including a reg-bound
72526 			 * identifier (if code above deems it safe) or a unary/binary
72527 			 * operation.  Operations must be resolved to a side effect free
72528 			 * plain value, and the side effects must happen exactly once.
72529 			 */
72530 
72531 			if (reg_varbind >= 0) {
72532 				if (res->t != DUK_IVAL_PLAIN) {
72533 					/* Resolve 'res' directly into the LHS binding, and use
72534 					 * that as the expression value if safe.  If not safe,
72535 					 * resolve to a temp/const and copy to LHS.
72536 					 */
72537 					if (toplevel_assign) {
72538 						duk__ivalue_toforcedreg(comp_ctx, res, (duk_int_t) reg_varbind);
72539 					} else {
72540 						duk__ivalue_totempconst(comp_ctx, res);
72541 						duk__copy_ivalue(comp_ctx, res, left);  /* use 'left' as a temp */
72542 						duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
72543 					}
72544 				} else {
72545 					/* Use 'res' as the expression value (it's side effect
72546 					 * free and may be a plain value, a register, or a
72547 					 * constant) and write it to the LHS binding too.
72548 					 */
72549 					duk__copy_ivalue(comp_ctx, res, left);  /* use 'left' as a temp */
72550 					duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
72551 				}
72552 			} else {
72553 				/* Only a reg fits into 'A' so coerce 'res' into a register
72554 				 * for PUTVAR.
72555 				 *
72556 				 * XXX: here the current A/B/C split is suboptimal: we could
72557 				 * just use 9 bits for reg_res (and support constants) and 17
72558 				 * instead of 18 bits for the varname const index.
72559 				 */
72560 
72561 				duk__ivalue_toreg(comp_ctx, res);
72562 				duk__emit_a_bc(comp_ctx,
72563 				               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
72564 				               res->x1.regconst,
72565 				               rc_varname);
72566 			}
72567 
72568 			/* 'res' contains expression value */
72569 		} else if (left->t == DUK_IVAL_PROP) {
72570 			/* E5 Section 11.13.1 (and others) step 4 never matches for prop writes -> no check */
72571 			duk_regconst_t reg_obj;
72572 			duk_regconst_t rc_key;
72573 			duk_regconst_t rc_res;
72574 			duk_regconst_t reg_temp;
72575 
72576 			/* Property access expressions ('a[b]') are critical to correct
72577 			 * LHS evaluation ordering, see test-dev-assign-eval-order*.js.
72578 			 * We must make sure that the LHS target slot (base object and
72579 			 * key) don't change during RHS evaluation.  The only concrete
72580 			 * problem is a register reference to a variable-bound register
72581 			 * (i.e., non-temp).  Require temp regs for both key and base.
72582 			 *
72583 			 * Don't allow a constant for the object (even for a number
72584 			 * etc), as it goes into the 'A' field of the opcode.
72585 			 */
72586 
72587 			reg_obj = duk__ispec_toregconst_raw(comp_ctx,
72588 			                                    &left->x1,
72589 			                                    -1 /*forced_reg*/,
72590 			                                    DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
72591 
72592 			rc_key = duk__ispec_toregconst_raw(comp_ctx,
72593 			                                   &left->x2,
72594 			                                   -1 /*forced_reg*/,
72595 			                                   DUK__IVAL_FLAG_REQUIRE_TEMP | DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
72596 
72597 			/* Evaluate RHS only when LHS is safe. */
72598 
72599 			if (args_op == DUK_OP_NONE) {
72600 				duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
72601 				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
72602 				rc_res = res->x1.regconst;
72603 			} else {
72604 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
72605 				duk__emit_a_b_c(comp_ctx,
72606 				                DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST,
72607 				                reg_temp,
72608 				                reg_obj,
72609 				                rc_key);
72610 
72611 				duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
72612 				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
72613 
72614 				duk__emit_a_b_c(comp_ctx,
72615 				                args_op | DUK__EMIT_FLAG_BC_REGCONST,
72616 				                reg_temp,
72617 				                reg_temp,
72618 				                res->x1.regconst);
72619 				rc_res = reg_temp;
72620 			}
72621 
72622 			duk__emit_a_b_c(comp_ctx,
72623 			                DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE | DUK__EMIT_FLAG_BC_REGCONST,
72624 			                reg_obj,
72625 			                rc_key,
72626 			                rc_res);
72627 
72628 			duk__ivalue_regconst(res, rc_res);
72629 		} else {
72630 			/* No support for lvalues returned from new or function call expressions.
72631 			 * However, these must NOT cause compile-time SyntaxErrors, but run-time
72632 			 * ReferenceErrors.  Both left and right sides of the assignment must be
72633 			 * evaluated before throwing a ReferenceError.  For instance:
72634 			 *
72635 			 *     f() = g();
72636 			 *
72637 			 * must result in f() being evaluated, then g() being evaluated, and
72638 			 * finally, a ReferenceError being thrown.  See E5 Section 11.13.1.
72639 			 */
72640 
72641 			duk_regconst_t rc_res;
72642 
72643 			/* First evaluate LHS fully to ensure all side effects are out. */
72644 			duk__ivalue_toplain_ignore(comp_ctx, left);
72645 
72646 			/* Then evaluate RHS fully (its value becomes the expression value too).
72647 			 * Technically we'd need the side effect safety check here too, but because
72648 			 * we always throw using INVLHS the result doesn't matter.
72649 			 */
72650 			rc_res = duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
72651 
72652 			duk__emit_op_only(comp_ctx, DUK_OP_INVLHS);
72653 
72654 			duk__ivalue_regconst(res, rc_res);
72655 		}
72656 
72657 		return;
72658 	}
72659 
72660  postincdec:
72661 	{
72662 		/*
72663 		 *  Post-increment/decrement will return the original value as its
72664 		 *  result value.  However, even that value will be coerced using
72665 		 *  ToNumber() which is quite awkward.  Specific bytecode opcodes
72666 		 *  are used to handle these semantics.
72667 		 *
72668 		 *  Note that post increment/decrement has a "no LineTerminator here"
72669 		 *  restriction.  This is handled by duk__expr_lbp(), which forcibly terminates
72670 		 *  the previous expression if a LineTerminator occurs before '++'/'--'.
72671 		 */
72672 
72673 		duk_regconst_t reg_res;
72674 		duk_small_uint_t args_op1 = (args >> 8) & 0xff;  /* DUK_OP_POSTINCR/DUK_OP_POSTDECR */
72675 		duk_small_uint_t args_op2 = args >> 16;          /* DUK_OP_POSTINCP_RR/DUK_OP_POSTDECP_RR */
72676 
72677 		/* Specific assumptions for opcode numbering. */
72678 		DUK_ASSERT(DUK_OP_POSTINCR + 4 == DUK_OP_POSTINCV);
72679 		DUK_ASSERT(DUK_OP_POSTDECR + 4 == DUK_OP_POSTDECV);
72680 
72681 		reg_res = DUK__ALLOCTEMP(comp_ctx);
72682 
72683 		if (left->t == DUK_IVAL_VAR) {
72684 			duk_hstring *h_varname;
72685 			duk_regconst_t reg_varbind;
72686 			duk_regconst_t rc_varname;
72687 
72688 			h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
72689 
72690 			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
72691 				goto syntax_error;
72692 			}
72693 
72694 			duk_dup(thr, left->x1.valstack_idx);
72695 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
72696 				duk__emit_a_bc(comp_ctx,
72697 				               args_op1,  /* e.g. DUK_OP_POSTINCR */
72698 				               reg_res,
72699 				               reg_varbind);
72700 			} else {
72701 				duk__emit_a_bc(comp_ctx,
72702 				               args_op1 + 4,  /* e.g. DUK_OP_POSTINCV */
72703 				               reg_res,
72704 				               rc_varname);
72705 			}
72706 
72707 			DUK_DDD(DUK_DDDPRINT("postincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
72708 			                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
72709 		} else if (left->t == DUK_IVAL_PROP) {
72710 			duk_regconst_t reg_obj;  /* allocate to reg only (not const) */
72711 			duk_regconst_t rc_key;
72712 
72713 			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &left->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
72714 			rc_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
72715 			duk__emit_a_b_c(comp_ctx,
72716 			                args_op2 | DUK__EMIT_FLAG_BC_REGCONST,  /* e.g. DUK_OP_POSTINCP */
72717 			                reg_res,
72718 			                reg_obj,
72719 			                rc_key);
72720 		} else {
72721 			/* Technically return value is not needed because INVLHS will
72722 			 * unconditially throw a ReferenceError.  Coercion is necessary
72723 			 * for proper semantics (consider ToNumber() called for an object).
72724 			 * Use DUK_OP_UNP with a dummy register to get ToNumber().
72725 			 */
72726 			duk__ivalue_toforcedreg(comp_ctx, left, reg_res);
72727 			duk__emit_bc(comp_ctx,
72728 			             DUK_OP_UNP,
72729 			             reg_res);  /* for side effects, result ignored */
72730 			duk__emit_op_only(comp_ctx,
72731 			                  DUK_OP_INVLHS);
72732 		}
72733 
72734 		DUK__SETTEMP(comp_ctx, reg_res + 1);
72735 		duk__ivalue_regconst(res, reg_res);
72736 		return;
72737 	}
72738 
72739  syntax_error:
72740 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);
72741 	DUK_WO_NORETURN(return;);
72742 
72743  syntax_error_lvalue:
72744 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LVALUE);
72745 	DUK_WO_NORETURN(return;);
72746 }
72747 
72748 DUK_LOCAL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx) {
72749 	duk_small_uint_t tok = comp_ctx->curr_token.t;
72750 
72751 	DUK_ASSERT_DISABLE(tok >= DUK_TOK_MINVAL);  /* unsigned */
72752 	DUK_ASSERT(tok <= DUK_TOK_MAXVAL);
72753 	DUK_ASSERT(sizeof(duk__token_lbp) == DUK_TOK_MAXVAL + 1);
72754 
72755 	/* XXX: integrate support for this into led() instead?
72756 	 * Similar issue as post-increment/post-decrement.
72757 	 */
72758 
72759 	/* prevent duk__expr_led() by using a binding power less than anything valid */
72760 	if (tok == DUK_TOK_IN && !comp_ctx->curr_func.allow_in) {
72761 		return 0;
72762 	}
72763 
72764 	if ((tok == DUK_TOK_DECREMENT || tok == DUK_TOK_INCREMENT) &&
72765 	    (comp_ctx->curr_token.lineterm)) {
72766 		/* '++' or '--' in a post-increment/decrement position,
72767 		 * and a LineTerminator occurs between the operator and
72768 		 * the preceding expression.  Force the previous expr
72769 		 * to terminate, in effect treating e.g. "a,b\n++" as
72770 		 * "a,b;++" (= SyntaxError).
72771 		 */
72772 		return 0;
72773 	}
72774 
72775 	return DUK__TOKEN_LBP_GET_BP(duk__token_lbp[tok]);  /* format is bit packed */
72776 }
72777 
72778 /*
72779  *  Expression parsing.
72780  *
72781  *  Upon entry to 'expr' and its variants, 'curr_tok' is assumed to be the
72782  *  first token of the expression.  Upon exit, 'curr_tok' will be the first
72783  *  token not part of the expression (e.g. semicolon terminating an expression
72784  *  statement).
72785  */
72786 
72787 #define DUK__EXPR_RBP_MASK           0xff
72788 #define DUK__EXPR_FLAG_REJECT_IN     (1 << 8)   /* reject 'in' token (used for for-in) */
72789 #define DUK__EXPR_FLAG_ALLOW_EMPTY   (1 << 9)   /* allow empty expression */
72790 #define DUK__EXPR_FLAG_REQUIRE_INIT  (1 << 10)  /* require initializer for var/const */
72791 
72792 /* main expression parser function */
72793 DUK_LOCAL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72794 	duk_hthread *thr = comp_ctx->thr;
72795 	duk_ivalue tmp_alloc;   /* 'res' is used for "left", and 'tmp' for "right" */
72796 	duk_ivalue *tmp = &tmp_alloc;
72797 	duk_small_uint_t rbp;
72798 
72799 	DUK__RECURSION_INCREASE(comp_ctx, thr);
72800 
72801 	duk_require_stack(thr, DUK__PARSE_EXPR_SLOTS);
72802 
72803 	/* filter out flags from exprtop rbp_flags here to save space */
72804 	rbp = rbp_flags & DUK__EXPR_RBP_MASK;
72805 
72806 	DUK_DDD(DUK_DDDPRINT("duk__expr(), rbp_flags=%ld, rbp=%ld, allow_in=%ld, paren_level=%ld",
72807 	                     (long) rbp_flags, (long) rbp, (long) comp_ctx->curr_func.allow_in,
72808 	                     (long) comp_ctx->curr_func.paren_level));
72809 
72810 	duk_memzero(&tmp_alloc, sizeof(tmp_alloc));
72811 	tmp->x1.valstack_idx = duk_get_top(thr);
72812 	tmp->x2.valstack_idx = tmp->x1.valstack_idx + 1;
72813 	duk_push_undefined(thr);
72814 	duk_push_undefined(thr);
72815 
72816 	/* XXX: where to release temp regs in intermediate expressions?
72817 	 * e.g. 1+2+3 -> don't inflate temp register count when parsing this.
72818 	 * that particular expression temp regs can be forced here.
72819 	 */
72820 
72821 	/* XXX: increase ctx->expr_tokens here for every consumed token
72822 	 * (this would be a nice statistic)?
72823 	 */
72824 
72825 	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
72826 		/* XXX: possibly incorrect handling of empty expression */
72827 		DUK_DDD(DUK_DDDPRINT("empty expression"));
72828 		if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY)) {
72829 			DUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED);
72830 			DUK_WO_NORETURN(return;);
72831 		}
72832 		duk_push_undefined(thr);
72833 		duk__ivalue_plain_fromstack(comp_ctx, res);
72834 		goto cleanup;
72835 	}
72836 
72837 	duk__advance(comp_ctx);
72838 	duk__expr_nud(comp_ctx, res);  /* reuse 'res' as 'left' */
72839 	while (rbp < duk__expr_lbp(comp_ctx)) {
72840 		duk__advance(comp_ctx);
72841 		duk__expr_led(comp_ctx, res, tmp);
72842 		duk__copy_ivalue(comp_ctx, tmp, res);  /* tmp -> res */
72843 	}
72844 
72845  cleanup:
72846 	/* final result is already in 'res' */
72847 
72848 	duk_pop_2(thr);
72849 
72850 	DUK__RECURSION_DECREASE(comp_ctx, thr);
72851 }
72852 
72853 DUK_LOCAL void duk__exprtop(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72854 	duk_hthread *thr = comp_ctx->thr;
72855 
72856 	/* Note: these variables must reside in 'curr_func' instead of the global
72857 	 * context: when parsing function expressions, expression parsing is nested.
72858 	 */
72859 	comp_ctx->curr_func.nud_count = 0;
72860 	comp_ctx->curr_func.led_count = 0;
72861 	comp_ctx->curr_func.paren_level = 0;
72862 	comp_ctx->curr_func.expr_lhs = 1;
72863 	comp_ctx->curr_func.allow_in = (rbp_flags & DUK__EXPR_FLAG_REJECT_IN ? 0 : 1);
72864 
72865 	duk__expr(comp_ctx, res, rbp_flags);
72866 
72867 	if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY) && duk__expr_is_empty(comp_ctx)) {
72868 		DUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED);
72869 		DUK_WO_NORETURN(return;);
72870 	}
72871 }
72872 
72873 /* A bunch of helpers (for size optimization) that combine duk__expr()/duk__exprtop()
72874  * and result conversions.
72875  *
72876  * Each helper needs at least 2-3 calls to make it worth while to wrap.
72877  */
72878 
72879 #if 0  /* unused */
72880 DUK_LOCAL duk_regconst_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72881 	duk__expr(comp_ctx, res, rbp_flags);
72882 	return duk__ivalue_toreg(comp_ctx, res);
72883 }
72884 #endif
72885 
72886 #if 0  /* unused */
72887 DUK_LOCAL duk_regconst_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72888 	duk__expr(comp_ctx, res, rbp_flags);
72889 	return duk__ivalue_totemp(comp_ctx, res);
72890 }
72891 #endif
72892 
72893 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) {
72894 	DUK_ASSERT(forced_reg >= 0);
72895 	duk__expr(comp_ctx, res, rbp_flags);
72896 	duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
72897 }
72898 
72899 DUK_LOCAL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72900 	duk__expr(comp_ctx, res, rbp_flags);
72901 	return duk__ivalue_toregconst(comp_ctx, res);
72902 }
72903 
72904 #if 0  /* unused */
72905 DUK_LOCAL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72906 	duk__expr(comp_ctx, res, rbp_flags);
72907 	return duk__ivalue_totempconst(comp_ctx, res);
72908 }
72909 #endif
72910 
72911 DUK_LOCAL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72912 	duk__expr(comp_ctx, res, rbp_flags);
72913 	duk__ivalue_toplain(comp_ctx, res);
72914 }
72915 
72916 DUK_LOCAL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72917 	duk__expr(comp_ctx, res, rbp_flags);
72918 	duk__ivalue_toplain_ignore(comp_ctx, res);
72919 }
72920 
72921 DUK_LOCAL duk_regconst_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72922 	duk__exprtop(comp_ctx, res, rbp_flags);
72923 	return duk__ivalue_toreg(comp_ctx, res);
72924 }
72925 
72926 #if 0  /* unused */
72927 DUK_LOCAL duk_regconst_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72928 	duk__exprtop(comp_ctx, res, rbp_flags);
72929 	return duk__ivalue_totemp(comp_ctx, res);
72930 }
72931 #endif
72932 
72933 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) {
72934 	DUK_ASSERT(forced_reg >= 0);
72935 	duk__exprtop(comp_ctx, res, rbp_flags);
72936 	duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
72937 }
72938 
72939 DUK_LOCAL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
72940 	duk__exprtop(comp_ctx, res, rbp_flags);
72941 	return duk__ivalue_toregconst(comp_ctx, res);
72942 }
72943 
72944 #if 0  /* unused */
72945 DUK_LOCAL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, int rbp_flags) {
72946 	duk__exprtop(comp_ctx, res, rbp_flags);
72947 	duk__ivalue_toplain_ignore(comp_ctx, res);
72948 }
72949 #endif
72950 
72951 /*
72952  *  Parse an individual source element (top level statement) or a statement.
72953  *
72954  *  Handles labeled statements automatically (peeling away labels before
72955  *  parsing an expression that follows the label(s)).
72956  *
72957  *  Upon entry, 'curr_tok' contains the first token of the statement (parsed
72958  *  in "allow regexp literal" mode).  Upon exit, 'curr_tok' contains the first
72959  *  token following the statement (if the statement has a terminator, this is
72960  *  the token after the terminator).
72961  */
72962 
72963 #define DUK__HAS_VAL                  (1 << 0)  /* stmt has non-empty value */
72964 #define DUK__HAS_TERM                 (1 << 1)  /* stmt has explicit/implicit semicolon terminator */
72965 #define DUK__ALLOW_AUTO_SEMI_ALWAYS   (1 << 2)  /* allow automatic semicolon even without lineterm (compatibility) */
72966 #define DUK__STILL_PROLOGUE           (1 << 3)  /* statement does not terminate directive prologue */
72967 #define DUK__IS_TERMINAL              (1 << 4)  /* statement is guaranteed to be terminal (control doesn't flow to next statement) */
72968 
72969 /* Parse a single variable declaration (e.g. "i" or "i=10").  A leading 'var'
72970  * has already been eaten.  These is no return value in 'res', it is used only
72971  * as a temporary.
72972  *
72973  * When called from 'for-in' statement parser, the initializer expression must
72974  * not allow the 'in' token.  The caller supply additional expression parsing
72975  * flags (like DUK__EXPR_FLAG_REJECT_IN) in 'expr_flags'.
72976  *
72977  * Finally, out_rc_varname and out_reg_varbind are updated to reflect where
72978  * the identifier is bound:
72979  *
72980  *    If register bound:      out_reg_varbind >= 0, out_rc_varname == 0 (ignore)
72981  *    If not register bound:  out_reg_varbind < 0, out_rc_varname >= 0
72982  *
72983  * These allow the caller to use the variable for further assignment, e.g.
72984  * as is done in 'for-in' parsing.
72985  */
72986 
72987 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) {
72988 	duk_hthread *thr = comp_ctx->thr;
72989 	duk_hstring *h_varname;
72990 	duk_regconst_t reg_varbind;
72991 	duk_regconst_t rc_varname;
72992 
72993 	/* assume 'var' has been eaten */
72994 
72995 	/* Note: Identifier rejects reserved words */
72996 	if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
72997 		goto syntax_error;
72998 	}
72999 	h_varname = comp_ctx->curr_token.str1;
73000 
73001 	DUK_ASSERT(h_varname != NULL);
73002 
73003 	/* strict mode restrictions (E5 Section 12.2.1) */
73004 	if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
73005 		goto syntax_error;
73006 	}
73007 
73008 	/* register declarations in first pass */
73009 	if (comp_ctx->curr_func.in_scanning) {
73010 		duk_uarridx_t n;
73011 		DUK_DDD(DUK_DDDPRINT("register variable declaration %!O in pass 1",
73012 		                     (duk_heaphdr *) h_varname));
73013 		n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
73014 		duk_push_hstring(thr, h_varname);
73015 		duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n);
73016 		duk_push_int(thr, DUK_DECL_TYPE_VAR + (0 << 8));
73017 		duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n + 1);
73018 	}
73019 
73020 	duk_push_hstring(thr, h_varname);  /* push before advancing to keep reachable */
73021 
73022 	/* register binding lookup is based on varmap (even in first pass) */
73023 	duk_dup_top(thr);
73024 	(void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
73025 
73026 	duk__advance(comp_ctx);  /* eat identifier */
73027 
73028 	if (comp_ctx->curr_token.t == DUK_TOK_EQUALSIGN) {
73029 		duk__advance(comp_ctx);
73030 
73031 		DUK_DDD(DUK_DDDPRINT("vardecl, assign to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
73032 		                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
73033 
73034 		duk__exprtop(comp_ctx, res, DUK__BP_COMMA | expr_flags /*rbp_flags*/);  /* AssignmentExpression */
73035 
73036 		if (reg_varbind >= 0) {
73037 			duk__ivalue_toforcedreg(comp_ctx, res, reg_varbind);
73038 		} else {
73039 			duk_regconst_t reg_val;
73040 			reg_val = duk__ivalue_toreg(comp_ctx, res);
73041 			duk__emit_a_bc(comp_ctx,
73042 			               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
73043 			               reg_val,
73044 			               rc_varname);
73045 		}
73046 	} else {
73047 		if (expr_flags & DUK__EXPR_FLAG_REQUIRE_INIT) {
73048 			/* Used for minimal 'const': initializer required. */
73049 			goto syntax_error;
73050 		}
73051 	}
73052 
73053 	duk_pop(thr);  /* pop varname */
73054 
73055 	*out_rc_varname = rc_varname;
73056 	*out_reg_varbind = reg_varbind;
73057 
73058 	return;
73059 
73060  syntax_error:
73061 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_VAR_DECLARATION);
73062 	DUK_WO_NORETURN(return;);
73063 }
73064 
73065 DUK_LOCAL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags) {
73066 	duk_regconst_t reg_varbind;
73067 	duk_regconst_t rc_varname;
73068 
73069 	duk__advance(comp_ctx);  /* eat 'var' */
73070 
73071 	for (;;) {
73072 		/* rc_varname and reg_varbind are ignored here */
73073 		duk__parse_var_decl(comp_ctx, res, 0 | expr_flags, &reg_varbind, &rc_varname);
73074 
73075 		if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
73076 			break;
73077 		}
73078 		duk__advance(comp_ctx);
73079 	}
73080 }
73081 
73082 DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
73083 	duk_hthread *thr = comp_ctx->thr;
73084 	duk_int_t pc_v34_lhs;         /* start variant 3/4 left-hand-side code (L1 in doc/compiler.rst example) */
73085 	duk_regconst_t temp_reset;    /* knock back "next temp" to this whenever possible */
73086 	duk_regconst_t reg_temps;     /* preallocated temporaries (2) for variants 3 and 4 */
73087 
73088 	DUK_DDD(DUK_DDDPRINT("start parsing a for/for-in statement"));
73089 
73090 	/* Two temporaries are preallocated here for variants 3 and 4 which need
73091 	 * registers which are never clobbered by expressions in the loop
73092 	 * (concretely: for the enumerator object and the next enumerated value).
73093 	 * Variants 1 and 2 "release" these temps.
73094 	 */
73095 
73096 	reg_temps = DUK__ALLOCTEMPS(comp_ctx, 2);
73097 
73098 	temp_reset = DUK__GETTEMP(comp_ctx);
73099 
73100 	/*
73101 	 *  For/for-in main variants are:
73102 	 *
73103 	 *    1. for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement
73104 	 *    2. for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement
73105 	 *    3. for (LeftHandSideExpression in Expression) Statement
73106 	 *    4. for (var VariableDeclarationNoIn in Expression) Statement
73107 	 *
73108 	 *  Parsing these without arbitrary lookahead or backtracking is relatively
73109 	 *  tricky but we manage to do so for now.
73110 	 *
73111 	 *  See doc/compiler.rst for a detailed discussion of control flow
73112 	 *  issues, evaluation order issues, etc.
73113 	 */
73114 
73115 	duk__advance(comp_ctx);  /* eat 'for' */
73116 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
73117 
73118 	DUK_DDD(DUK_DDDPRINT("detecting for/for-in loop variant, pc=%ld", (long) duk__get_current_pc(comp_ctx)));
73119 
73120 	/* a label site has been emitted by duk__parse_stmt() automatically
73121 	 * (it will also emit the ENDLABEL).
73122 	 */
73123 
73124 	if (comp_ctx->curr_token.t == DUK_TOK_VAR) {
73125 		/*
73126 		 *  Variant 2 or 4
73127 		 */
73128 
73129 		duk_regconst_t reg_varbind;  /* variable binding register if register-bound (otherwise < 0) */
73130 		duk_regconst_t rc_varname;   /* variable name reg/const, if variable not register-bound */
73131 
73132 		duk__advance(comp_ctx);  /* eat 'var' */
73133 		duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
73134 		DUK__SETTEMP(comp_ctx, temp_reset);
73135 
73136 		if (comp_ctx->curr_token.t == DUK_TOK_IN) {
73137 			/*
73138 			 *  Variant 4
73139 			 */
73140 
73141 			DUK_DDD(DUK_DDDPRINT("detected for variant 4: for (var VariableDeclarationNoIn in Expression) Statement"));
73142 			pc_v34_lhs = duk__get_current_pc(comp_ctx);  /* jump is inserted here */
73143 			if (reg_varbind >= 0) {
73144 				duk__emit_a_bc(comp_ctx,
73145 				               DUK_OP_LDREG,
73146 				               reg_varbind,
73147 				               reg_temps + 0);
73148 			} else {
73149 				duk__emit_a_bc(comp_ctx,
73150 				               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
73151 				               reg_temps + 0,
73152 				               rc_varname);
73153 			}
73154 			goto parse_3_or_4;
73155 		} else {
73156 			/*
73157 			 *  Variant 2
73158 			 */
73159 
73160 			DUK_DDD(DUK_DDDPRINT("detected for variant 2: for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement"));
73161 			for (;;) {
73162 				/* more initializers */
73163 				if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
73164 					break;
73165 				}
73166 				DUK_DDD(DUK_DDDPRINT("variant 2 has another variable initializer"));
73167 
73168 				duk__advance(comp_ctx);  /* eat comma */
73169 				duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
73170 			}
73171 			goto parse_1_or_2;
73172 		}
73173 	} else {
73174 		/*
73175 		 *  Variant 1 or 3
73176 		 */
73177 
73178 		pc_v34_lhs = duk__get_current_pc(comp_ctx);  /* jump is inserted here (variant 3) */
73179 
73180 		/* Note that duk__exprtop() here can clobber any reg above current temp_next,
73181 		 * so any loop variables (e.g. enumerator) must be "preallocated".
73182 		 */
73183 
73184 		/* don't coerce yet to a plain value (variant 3 needs special handling) */
73185 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_REJECT_IN | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression */
73186 		if (comp_ctx->curr_token.t == DUK_TOK_IN) {
73187 			/*
73188 			 *  Variant 3
73189 			 */
73190 
73191 			/* XXX: need to determine LHS type, and check that it is LHS compatible */
73192 			DUK_DDD(DUK_DDDPRINT("detected for variant 3: for (LeftHandSideExpression in Expression) Statement"));
73193 			if (duk__expr_is_empty(comp_ctx)) {
73194 				goto syntax_error;  /* LeftHandSideExpression does not allow empty expression */
73195 			}
73196 
73197 			if (res->t == DUK_IVAL_VAR) {
73198 				duk_regconst_t reg_varbind;
73199 				duk_regconst_t rc_varname;
73200 
73201 				duk_dup(thr, res->x1.valstack_idx);
73202 				if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
73203 					duk__emit_a_bc(comp_ctx,
73204 					               DUK_OP_LDREG,
73205 					               reg_varbind,
73206 					               reg_temps + 0);
73207 				} else {
73208 					duk__emit_a_bc(comp_ctx,
73209 					               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
73210 					               reg_temps + 0,
73211 					               rc_varname);
73212 				}
73213 			} else if (res->t == DUK_IVAL_PROP) {
73214 				/* Don't allow a constant for the object (even for a number etc), as
73215 				 * it goes into the 'A' field of the opcode.
73216 				 */
73217 				duk_regconst_t reg_obj;
73218 				duk_regconst_t rc_key;
73219 				reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
73220 				rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
73221 				duk__emit_a_b_c(comp_ctx,
73222 				                DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE | DUK__EMIT_FLAG_BC_REGCONST,
73223 				                reg_obj,
73224 				                rc_key,
73225 				                reg_temps + 0);
73226 			} else {
73227 				duk__ivalue_toplain_ignore(comp_ctx, res);  /* just in case */
73228 				duk__emit_op_only(comp_ctx,
73229 				                  DUK_OP_INVLHS);
73230 			}
73231 			goto parse_3_or_4;
73232 		} else {
73233 			/*
73234 			 *  Variant 1
73235 			 */
73236 
73237 			DUK_DDD(DUK_DDDPRINT("detected for variant 1: for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement"));
73238 			duk__ivalue_toplain_ignore(comp_ctx, res);
73239 			goto parse_1_or_2;
73240 		}
73241 	}
73242 
73243  parse_1_or_2:
73244 	/*
73245 	 *  Parse variant 1 or 2.  The first part expression (which differs
73246 	 *  in the variants) has already been parsed and its code emitted.
73247 	 *
73248 	 *  reg_temps + 0: unused
73249 	 *  reg_temps + 1: unused
73250 	 */
73251 	{
73252 		duk_regconst_t rc_cond;
73253 		duk_int_t pc_l1, pc_l2, pc_l3, pc_l4;
73254 		duk_int_t pc_jumpto_l3, pc_jumpto_l4;
73255 		duk_bool_t expr_c_empty;
73256 
73257 		DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 1 and 2"));
73258 
73259 		/* "release" preallocated temps since we won't need them */
73260 		temp_reset = reg_temps + 0;
73261 		DUK__SETTEMP(comp_ctx, temp_reset);
73262 
73263 		duk__advance_expect(comp_ctx, DUK_TOK_SEMICOLON);
73264 
73265 		pc_l1 = duk__get_current_pc(comp_ctx);
73266 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression_opt */
73267 		if (duk__expr_is_empty(comp_ctx)) {
73268 			/* no need to coerce */
73269 			pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* to body */
73270 			pc_jumpto_l4 = -1;  /* omitted */
73271 		} else {
73272 			rc_cond = duk__ivalue_toregconst(comp_ctx, res);
73273 			duk__emit_if_false_skip(comp_ctx, rc_cond);
73274 			pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* to body */
73275 			pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);  /* to exit */
73276 		}
73277 		DUK__SETTEMP(comp_ctx, temp_reset);
73278 
73279 		duk__advance_expect(comp_ctx, DUK_TOK_SEMICOLON);
73280 
73281 		pc_l2 = duk__get_current_pc(comp_ctx);
73282 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression_opt */
73283 		if (duk__expr_is_empty(comp_ctx)) {
73284 			/* no need to coerce */
73285 			expr_c_empty = 1;
73286 			/* JUMP L1 omitted */
73287 		} else {
73288 			duk__ivalue_toplain_ignore(comp_ctx, res);
73289 			expr_c_empty = 0;
73290 			duk__emit_jump(comp_ctx, pc_l1);
73291 		}
73292 		DUK__SETTEMP(comp_ctx, temp_reset);
73293 
73294 		comp_ctx->curr_func.allow_regexp_in_adv = 1;
73295 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
73296 
73297 		pc_l3 = duk__get_current_pc(comp_ctx);
73298 		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
73299 		if (expr_c_empty) {
73300 			duk__emit_jump(comp_ctx, pc_l1);
73301 		} else {
73302 			duk__emit_jump(comp_ctx, pc_l2);
73303 		}
73304 		/* temp reset is not necessary after duk__parse_stmt(), which already does it */
73305 
73306 		pc_l4 = duk__get_current_pc(comp_ctx);
73307 
73308 		DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l3: %ld->%ld, jumpto_l4: %ld->%ld, "
73309 		                     "break: %ld->%ld, continue: %ld->%ld",
73310 			             (long) pc_jumpto_l3, (long) pc_l3, (long) pc_jumpto_l4, (long) pc_l4,
73311 		                     (long) (pc_label_site + 1), (long) pc_l4, (long) (pc_label_site + 2), (long) pc_l2));
73312 
73313 		duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
73314 		duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
73315 		duk__patch_jump(comp_ctx,
73316 		                pc_label_site + 1,
73317 		                pc_l4);                         /* break jump */
73318 		duk__patch_jump(comp_ctx,
73319 		                pc_label_site + 2,
73320 		                expr_c_empty ? pc_l1 : pc_l2);  /* continue jump */
73321 	}
73322 	goto finished;
73323 
73324  parse_3_or_4:
73325 	/*
73326 	 *  Parse variant 3 or 4.
73327 	 *
73328 	 *  For variant 3 (e.g. "for (A in C) D;") the code for A (except the
73329 	 *  final property/variable write) has already been emitted.  The first
73330 	 *  instruction of that code is at pc_v34_lhs; a JUMP needs to be inserted
73331 	 *  there to satisfy control flow needs.
73332 	 *
73333 	 *  For variant 4, if the variable declaration had an initializer
73334 	 *  (e.g. "for (var A = B in C) D;") the code for the assignment
73335 	 *  (B) has already been emitted.
73336 	 *
73337 	 *  Variables set before entering here:
73338 	 *
73339 	 *    pc_v34_lhs:    insert a "JUMP L2" here (see doc/compiler.rst example).
73340 	 *    reg_temps + 0: iteration target value (written to LHS)
73341 	 *    reg_temps + 1: enumerator object
73342 	 */
73343 	{
73344 		duk_int_t pc_l1, pc_l2, pc_l3, pc_l4, pc_l5;
73345 		duk_int_t pc_jumpto_l2, pc_jumpto_l3, pc_jumpto_l4, pc_jumpto_l5;
73346 		duk_regconst_t reg_target;
73347 
73348 		DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 3 and 4, pc_v34_lhs=%ld", (long) pc_v34_lhs));
73349 
73350 		DUK__SETTEMP(comp_ctx, temp_reset);
73351 
73352 		/* First we need to insert a jump in the middle of previously
73353 		 * emitted code to get the control flow right.  No jumps can
73354 		 * cross the position where the jump is inserted.  See doc/compiler.rst
73355 		 * for discussion on the intricacies of control flow and side effects
73356 		 * for variants 3 and 4.
73357 		 */
73358 
73359 		duk__insert_jump_entry(comp_ctx, pc_v34_lhs);
73360 		pc_jumpto_l2 = pc_v34_lhs;  /* inserted jump */
73361 		pc_l1 = pc_v34_lhs + 1;     /* +1, right after inserted jump */
73362 
73363 		/* The code for writing reg_temps + 0 to the left hand side has already
73364 		 * been emitted.
73365 		 */
73366 
73367 		pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* -> loop body */
73368 
73369 		duk__advance(comp_ctx);  /* eat 'in' */
73370 
73371 		/* Parse enumeration target and initialize enumerator.  For 'null' and 'undefined',
73372 		 * INITENUM will creates a 'null' enumerator which works like an empty enumerator
73373 		 * (E5 Section 12.6.4, step 3).  Note that INITENUM requires the value to be in a
73374 		 * register (constant not allowed).
73375 		 */
73376 
73377 		pc_l2 = duk__get_current_pc(comp_ctx);
73378 		reg_target = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression */
73379 		duk__emit_b_c(comp_ctx,
73380 		              DUK_OP_INITENUM | DUK__EMIT_FLAG_B_IS_TARGET,
73381 		              reg_temps + 1,
73382 		              reg_target);
73383 		pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);
73384 		DUK__SETTEMP(comp_ctx, temp_reset);
73385 
73386 		comp_ctx->curr_func.allow_regexp_in_adv = 1;
73387 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
73388 
73389 		pc_l3 = duk__get_current_pc(comp_ctx);
73390 		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
73391 		/* temp reset is not necessary after duk__parse_stmt(), which already does it */
73392 
73393 		/* NEXTENUM needs a jump slot right after the main opcode.
73394 		 * We need the code emitter to reserve the slot: if there's
73395 		 * target shuffling, the target shuffle opcodes must happen
73396 		 * after the jump slot (for NEXTENUM the shuffle opcodes are
73397 		 * not needed if the enum is finished).
73398 		 */
73399 		pc_l4 = duk__get_current_pc(comp_ctx);
73400 		duk__emit_b_c(comp_ctx,
73401 		              DUK_OP_NEXTENUM | DUK__EMIT_FLAG_B_IS_TARGET | DUK__EMIT_FLAG_RESERVE_JUMPSLOT,
73402 		              reg_temps + 0,
73403 		              reg_temps + 1);
73404 		pc_jumpto_l5 = comp_ctx->emit_jumpslot_pc;  /* NEXTENUM jump slot: executed when enum finished */
73405 		duk__emit_jump(comp_ctx, pc_l1);  /* jump to next loop, using reg_v34_iter as iterated value */
73406 
73407 		pc_l5 = duk__get_current_pc(comp_ctx);
73408 
73409 		/* XXX: since the enumerator may be a memory expensive object,
73410 		 * perhaps clear it explicitly here?  If so, break jump must
73411 		 * go through this clearing operation.
73412 		 */
73413 
73414 		DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l2: %ld->%ld, jumpto_l3: %ld->%ld, "
73415 		                     "jumpto_l4: %ld->%ld, jumpto_l5: %ld->%ld, "
73416 		                     "break: %ld->%ld, continue: %ld->%ld",
73417 			             (long) pc_jumpto_l2, (long) pc_l2, (long) pc_jumpto_l3, (long) pc_l3,
73418 			             (long) pc_jumpto_l4, (long) pc_l4, (long) pc_jumpto_l5, (long) pc_l5,
73419 		                     (long) (pc_label_site + 1), (long) pc_l5, (long) (pc_label_site + 2), (long) pc_l4));
73420 
73421 		duk__patch_jump(comp_ctx, pc_jumpto_l2, pc_l2);
73422 		duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
73423 		duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
73424 		duk__patch_jump(comp_ctx, pc_jumpto_l5, pc_l5);
73425 		duk__patch_jump(comp_ctx, pc_label_site + 1, pc_l5);  /* break jump */
73426 		duk__patch_jump(comp_ctx, pc_label_site + 2, pc_l4);  /* continue jump */
73427 	}
73428 	goto finished;
73429 
73430  finished:
73431 	DUK_DDD(DUK_DDDPRINT("end parsing a for/for-in statement"));
73432 	return;
73433 
73434  syntax_error:
73435 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FOR);
73436 	DUK_WO_NORETURN(return;);
73437 }
73438 
73439 DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
73440 	duk_hthread *thr = comp_ctx->thr;
73441 	duk_regconst_t temp_at_loop;
73442 	duk_regconst_t rc_switch;    /* reg/const for switch value */
73443 	duk_regconst_t rc_case;      /* reg/const for case value */
73444 	duk_regconst_t reg_temp;     /* general temp register */
73445 	duk_int_t pc_prevcase = -1;
73446 	duk_int_t pc_prevstmt = -1;
73447 	duk_int_t pc_default = -1;   /* -1 == not set, -2 == pending (next statement list) */
73448 
73449 	/* Note: negative pc values are ignored when patching jumps, so no explicit checks needed */
73450 
73451 	/*
73452 	 *  Switch is pretty complicated because of several conflicting concerns:
73453 	 *
73454 	 *    - Want to generate code without an intermediate representation,
73455 	 *      i.e., in one go
73456 	 *
73457 	 *    - Case selectors are expressions, not values, and may thus e.g. throw
73458 	 *      exceptions (which causes evaluation order concerns)
73459 	 *
73460 	 *    - Evaluation semantics of case selectors and default clause need to be
73461 	 *      carefully implemented to provide correct behavior even with case value
73462 	 *      side effects
73463 	 *
73464 	 *    - Fall through case and default clauses; avoiding dead JUMPs if case
73465 	 *      ends with an unconditional jump (a break or a continue)
73466 	 *
73467 	 *    - The same case value may occur multiple times, but evaluation rules
73468 	 *      only process the first match before switching to a "propagation" mode
73469 	 *      where case values are no longer evaluated
73470 	 *
73471 	 *  See E5 Section 12.11.  Also see doc/compiler.rst for compilation
73472 	 *  discussion.
73473 	 */
73474 
73475 	duk__advance(comp_ctx);
73476 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
73477 	rc_switch = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
73478 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* RegExp mode does not matter. */
73479 	duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
73480 
73481 	DUK_DDD(DUK_DDDPRINT("switch value in register %ld", (long) rc_switch));
73482 
73483 	temp_at_loop = DUK__GETTEMP(comp_ctx);
73484 
73485 	for (;;) {
73486 		duk_int_t num_stmts;
73487 		duk_small_uint_t tok;
73488 
73489 		/* sufficient for keeping temp reg numbers in check */
73490 		DUK__SETTEMP(comp_ctx, temp_at_loop);
73491 
73492 		if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
73493 			break;
73494 		}
73495 
73496 		/*
73497 		 *  Parse a case or default clause.
73498 		 */
73499 
73500 		if (comp_ctx->curr_token.t == DUK_TOK_CASE) {
73501 			/*
73502 			 *  Case clause.
73503 			 *
73504 			 *  Note: cannot use reg_case as a temp register (for SEQ target)
73505 			 *  because it may be a constant.
73506 			 */
73507 
73508 			duk__patch_jump_here(comp_ctx, pc_prevcase);  /* chain jumps for case
73509 			                                               * evaluation and checking
73510 			                                               */
73511 
73512 			duk__advance(comp_ctx);
73513 			rc_case = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
73514 			duk__advance_expect(comp_ctx, DUK_TOK_COLON);
73515 
73516 			reg_temp = DUK__ALLOCTEMP(comp_ctx);
73517 			duk__emit_a_b_c(comp_ctx,
73518 			                DUK_OP_SEQ | DUK__EMIT_FLAG_BC_REGCONST,
73519 			                reg_temp,
73520 			                rc_switch,
73521 			                rc_case);
73522 			duk__emit_if_true_skip(comp_ctx, reg_temp);
73523 
73524 			/* jump to next case clause */
73525 			pc_prevcase = duk__emit_jump_empty(comp_ctx);  /* no match, next case */
73526 
73527 			/* statements go here (if any) on next loop */
73528 		} else if (comp_ctx->curr_token.t == DUK_TOK_DEFAULT) {
73529 			/*
73530 			 *  Default clause.
73531 			 */
73532 
73533 			if (pc_default >= 0) {
73534 				goto syntax_error;
73535 			}
73536 			duk__advance(comp_ctx);
73537 			duk__advance_expect(comp_ctx, DUK_TOK_COLON);
73538 
73539 			/* Fix for https://github.com/svaarala/duktape/issues/155:
73540 			 * If 'default' is first clause (detected by pc_prevcase < 0)
73541 			 * we need to ensure we stay in the matching chain.
73542 			 */
73543 			if (pc_prevcase < 0) {
73544 				DUK_DD(DUK_DDPRINT("default clause is first, emit prevcase jump"));
73545 				pc_prevcase = duk__emit_jump_empty(comp_ctx);
73546 			}
73547 
73548 			/* default clause matches next statement list (if any) */
73549 			pc_default = -2;
73550 		} else {
73551 			/* Code is not accepted before the first case/default clause */
73552 			goto syntax_error;
73553 		}
73554 
73555 		/*
73556 		 *  Parse code after the clause.  Possible terminators are
73557 		 *  'case', 'default', and '}'.
73558 		 *
73559 		 *  Note that there may be no code at all, not even an empty statement,
73560 		 *  between case clauses.  This must be handled just like an empty statement
73561 		 *  (omitting seemingly pointless JUMPs), to avoid situations like
73562 		 *  test-bug-case-fallthrough.js.
73563 		 */
73564 
73565 		num_stmts = 0;
73566 		if (pc_default == -2) {
73567 			pc_default = duk__get_current_pc(comp_ctx);
73568 		}
73569 
73570 		/* Note: this is correct even for default clause statements:
73571 		 * they participate in 'fall-through' behavior even if the
73572 		 * default clause is in the middle.
73573 		 */
73574 		duk__patch_jump_here(comp_ctx, pc_prevstmt);  /* chain jumps for 'fall-through'
73575 		                                               * after a case matches.
73576 		                                               */
73577 
73578 		for (;;) {
73579 			tok = comp_ctx->curr_token.t;
73580 			if (tok == DUK_TOK_CASE || tok == DUK_TOK_DEFAULT ||
73581 			    tok == DUK_TOK_RCURLY) {
73582 				break;
73583 			}
73584 			num_stmts++;
73585 			duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
73586 		}
73587 
73588 		/* fall-through jump to next code of next case (backpatched) */
73589 		pc_prevstmt = duk__emit_jump_empty(comp_ctx);
73590 
73591 		/* XXX: would be nice to omit this jump when the jump is not
73592 		 * reachable, at least in the obvious cases (such as the case
73593 		 * ending with a 'break'.
73594 		 *
73595 		 * Perhaps duk__parse_stmt() could provide some info on whether
73596 		 * the statement is a "dead end"?
73597 		 *
73598 		 * If implemented, just set pc_prevstmt to -1 when not needed.
73599 		 */
73600 	}
73601 
73602 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
73603 	comp_ctx->curr_func.allow_regexp_in_adv = 1;
73604 	duk__advance(comp_ctx);  /* Allow RegExp as part of next stmt. */
73605 
73606 	/* default case control flow patchup; note that if pc_prevcase < 0
73607 	 * (i.e. no case clauses), control enters default case automatically.
73608 	 */
73609 	if (pc_default >= 0) {
73610 		/* default case exists: go there if no case matches */
73611 		duk__patch_jump(comp_ctx, pc_prevcase, pc_default);
73612 	} else {
73613 		/* default case does not exist, or no statements present
73614 		 * after default case: finish case evaluation
73615 		 */
73616 		duk__patch_jump_here(comp_ctx, pc_prevcase);
73617 	}
73618 
73619 	/* fall-through control flow patchup; note that pc_prevstmt may be
73620 	 * < 0 (i.e. no case clauses), in which case this is a no-op.
73621 	 */
73622 	duk__patch_jump_here(comp_ctx, pc_prevstmt);
73623 
73624 	/* continue jump not patched, an INVALID opcode remains there */
73625 	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */
73626 
73627 	/* Note: 'fast' breaks will jump to pc_label_site + 1, which will
73628 	 * then jump here.  The double jump will be eliminated by a
73629 	 * peephole pass, resulting in an optimal jump here.  The label
73630 	 * site jumps will remain in bytecode and will waste code size.
73631 	 */
73632 
73633 	return;
73634 
73635  syntax_error:
73636 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_SWITCH);
73637 	DUK_WO_NORETURN(return;);
73638 }
73639 
73640 DUK_LOCAL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
73641 	duk_regconst_t temp_reset;
73642 	duk_regconst_t rc_cond;
73643 	duk_int_t pc_jump_false;
73644 
73645 	DUK_DDD(DUK_DDDPRINT("begin parsing if statement"));
73646 
73647 	temp_reset = DUK__GETTEMP(comp_ctx);
73648 
73649 	duk__advance(comp_ctx);  /* eat 'if' */
73650 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
73651 
73652 	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
73653 	duk__emit_if_true_skip(comp_ctx, rc_cond);
73654 	pc_jump_false = duk__emit_jump_empty(comp_ctx);  /* jump to end or else part */
73655 	DUK__SETTEMP(comp_ctx, temp_reset);
73656 
73657 	comp_ctx->curr_func.allow_regexp_in_adv = 1;
73658 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
73659 
73660 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
73661 
73662 	/* The 'else' ambiguity is resolved by 'else' binding to the innermost
73663 	 * construct, so greedy matching is correct here.
73664 	 */
73665 
73666 	if (comp_ctx->curr_token.t == DUK_TOK_ELSE) {
73667 		duk_int_t pc_jump_end;
73668 
73669 		DUK_DDD(DUK_DDDPRINT("if has else part"));
73670 
73671 		duk__advance(comp_ctx);
73672 
73673 		pc_jump_end = duk__emit_jump_empty(comp_ctx);  /* jump from true part to end */
73674 		duk__patch_jump_here(comp_ctx, pc_jump_false);
73675 
73676 		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
73677 
73678 		duk__patch_jump_here(comp_ctx, pc_jump_end);
73679 	} else {
73680 		DUK_DDD(DUK_DDDPRINT("if does not have else part"));
73681 
73682 		duk__patch_jump_here(comp_ctx, pc_jump_false);
73683 	}
73684 
73685 	DUK_DDD(DUK_DDDPRINT("end parsing if statement"));
73686 }
73687 
73688 DUK_LOCAL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
73689 	duk_regconst_t rc_cond;
73690 	duk_int_t pc_start;
73691 
73692 	DUK_DDD(DUK_DDDPRINT("begin parsing do statement"));
73693 
73694 	duk__advance(comp_ctx);  /* Eat 'do'; allow RegExp as part of next stmt. */
73695 
73696 	pc_start = duk__get_current_pc(comp_ctx);
73697 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
73698 	duk__patch_jump_here(comp_ctx, pc_label_site + 2);  /* continue jump */
73699 
73700 	duk__advance_expect(comp_ctx, DUK_TOK_WHILE);
73701 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
73702 
73703 	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
73704 	duk__emit_if_false_skip(comp_ctx, rc_cond);
73705 	duk__emit_jump(comp_ctx, pc_start);
73706 	/* no need to reset temps, as we're finished emitting code */
73707 
73708 	comp_ctx->curr_func.allow_regexp_in_adv = 1;  /* Allow RegExp as part of next stmt. */
73709 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
73710 
73711 	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */
73712 
73713 	DUK_DDD(DUK_DDDPRINT("end parsing do statement"));
73714 }
73715 
73716 DUK_LOCAL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
73717 	duk_regconst_t temp_reset;
73718 	duk_regconst_t rc_cond;
73719 	duk_int_t pc_start;
73720 	duk_int_t pc_jump_false;
73721 
73722 	DUK_DDD(DUK_DDDPRINT("begin parsing while statement"));
73723 
73724 	temp_reset = DUK__GETTEMP(comp_ctx);
73725 
73726 	duk__advance(comp_ctx);  /* eat 'while' */
73727 
73728 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
73729 
73730 	pc_start = duk__get_current_pc(comp_ctx);
73731 	duk__patch_jump_here(comp_ctx, pc_label_site + 2);  /* continue jump */
73732 
73733 	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
73734 	duk__emit_if_true_skip(comp_ctx, rc_cond);
73735 	pc_jump_false = duk__emit_jump_empty(comp_ctx);
73736 	DUK__SETTEMP(comp_ctx, temp_reset);
73737 
73738 	comp_ctx->curr_func.allow_regexp_in_adv = 1;
73739 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
73740 
73741 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
73742 	duk__emit_jump(comp_ctx, pc_start);
73743 
73744 	duk__patch_jump_here(comp_ctx, pc_jump_false);
73745 	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */
73746 
73747 	DUK_DDD(DUK_DDDPRINT("end parsing while statement"));
73748 }
73749 
73750 DUK_LOCAL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
73751 	duk_hthread *thr = comp_ctx->thr;
73752 	duk_bool_t is_break = (comp_ctx->curr_token.t == DUK_TOK_BREAK);
73753 	duk_int_t label_id;
73754 	duk_int_t label_catch_depth;
73755 	duk_int_t label_pc;  /* points to LABEL; pc+1 = jump site for break; pc+2 = jump site for continue */
73756 	duk_bool_t label_is_closest;
73757 
73758 	DUK_UNREF(res);
73759 
73760 	duk__advance(comp_ctx);  /* eat 'break' or 'continue' */
73761 
73762 	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON ||  /* explicit semi follows */
73763 	    comp_ctx->curr_token.lineterm ||                /* automatic semi will be inserted */
73764 	    comp_ctx->curr_token.allow_auto_semi) {         /* automatic semi will be inserted */
73765 		/* break/continue without label */
73766 
73767 		duk__lookup_active_label(comp_ctx, DUK_HTHREAD_STRING_EMPTY_STRING(thr), is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
73768 	} else if (comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER) {
73769 		/* break/continue with label (label cannot be a reserved word, production is 'Identifier' */
73770 		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
73771 		duk__lookup_active_label(comp_ctx, comp_ctx->curr_token.str1, is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
73772 		duk__advance(comp_ctx);
73773 	} else {
73774 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BREAK_CONT_LABEL);
73775 		DUK_WO_NORETURN(return;);
73776 	}
73777 
73778 	/* Use a fast break/continue when possible.  A fast break/continue is
73779 	 * just a jump to the LABEL break/continue jump slot, which then jumps
73780 	 * to an appropriate place (for break, going through ENDLABEL correctly).
73781 	 * The peephole optimizer will optimize the jump to a direct one.
73782 	 */
73783 
73784 	if (label_catch_depth == comp_ctx->curr_func.catch_depth &&
73785 	    label_is_closest) {
73786 		DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
73787 		                     "label_catch_depth=%ld, catch_depth=%ld "
73788 		                     "-> use fast variant (direct jump)",
73789 		                     (long) is_break, (long) label_id, (long) label_is_closest,
73790 		                     (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
73791 
73792 		duk__emit_jump(comp_ctx, label_pc + (is_break ? 1 : 2));
73793 	} else {
73794 		DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
73795 		                     "label_catch_depth=%ld, catch_depth=%ld "
73796 		                     "-> use slow variant (longjmp)",
73797 		                     (long) is_break, (long) label_id, (long) label_is_closest,
73798 		                     (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
73799 
73800 		duk__emit_bc(comp_ctx,
73801 		             is_break ? DUK_OP_BREAK : DUK_OP_CONTINUE,
73802 		             (duk_regconst_t) label_id);
73803 	}
73804 }
73805 
73806 DUK_LOCAL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
73807 	duk_hthread *thr = comp_ctx->thr;
73808 	duk_regconst_t rc_val;
73809 
73810 	duk__advance(comp_ctx);  /* eat 'return' */
73811 
73812 	/* A 'return' statement is only allowed inside an actual function body,
73813 	 * not as part of eval or global code.
73814 	 */
73815 	if (!comp_ctx->curr_func.is_function) {
73816 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_RETURN);
73817 		DUK_WO_NORETURN(return;);
73818 	}
73819 
73820 	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON ||  /* explicit semi follows */
73821 	    comp_ctx->curr_token.lineterm ||                /* automatic semi will be inserted */
73822 	    comp_ctx->curr_token.allow_auto_semi) {         /* automatic semi will be inserted */
73823 		DUK_DDD(DUK_DDDPRINT("empty return value -> undefined"));
73824 		duk__emit_op_only(comp_ctx, DUK_OP_RETUNDEF);
73825 	} else {
73826 		duk_int_t pc_before_expr;
73827 		duk_int_t pc_after_expr;
73828 
73829 		DUK_DDD(DUK_DDDPRINT("return with a value"));
73830 
73831 		DUK_UNREF(pc_before_expr);
73832 		DUK_UNREF(pc_after_expr);
73833 
73834 		pc_before_expr = duk__get_current_pc(comp_ctx);
73835 		rc_val = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
73836 		pc_after_expr = duk__get_current_pc(comp_ctx);
73837 
73838 		/* Tail call check: if last opcode emitted was CALL, and
73839 		 * the context allows it, add a tailcall flag to the CALL.
73840 		 * This doesn't guarantee that a tail call will be allowed at
73841 		 * runtime, so the RETURN must still be emitted.  (Duktape
73842 		 * 0.10.0 avoided this and simulated a RETURN if a tail call
73843 		 * couldn't be used at runtime; but this didn't work
73844 		 * correctly with a thread yield/resume, see
73845 		 * test-bug-tailcall-thread-yield-resume.js for discussion.)
73846 		 *
73847 		 * In addition to the last opcode being CALL, we also need to
73848 		 * be sure that 'rc_val' is the result register of the CALL.
73849 		 * For instance, for the expression 'return 0, (function ()
73850 		 * { return 1; }), 2' the last opcode emitted is CALL (no
73851 		 * bytecode is emitted for '2') but 'rc_val' indicates
73852 		 * constant '2'.  Similarly if '2' is replaced by a register
73853 		 * bound variable, no opcodes are emitted but tail call would
73854 		 * be incorrect.
73855 		 *
73856 		 * This is tricky and easy to get wrong.  It would be best to
73857 		 * track enough expression metadata to check that 'rc_val' came
73858 		 * from that last CALL instruction.  We don't have that metadata
73859 		 * now, so we check that 'rc_val' is a temporary register result
73860 		 * (not a constant or a register bound variable).  There should
73861 		 * be no way currently for 'rc_val' to be a temporary for an
73862 		 * expression following the CALL instruction without emitting
73863 		 * some opcodes following the CALL.  This proxy check is used
73864 		 * below.
73865 		 *
73866 		 * See: test-bug-comma-expr-gh131.js.
73867 		 *
73868 		 * The non-standard 'caller' property disables tail calls
73869 		 * because they pose some special cases which haven't been
73870 		 * fixed yet.
73871 		 */
73872 
73873 #if defined(DUK_USE_TAILCALL)
73874 		if (comp_ctx->curr_func.catch_depth == 0 &&   /* no catchers */
73875 		    pc_after_expr > pc_before_expr) {         /* at least one opcode emitted */
73876 			duk_compiler_instr *instr;
73877 			duk_instr_t ins;
73878 			duk_small_uint_t op;
73879 
73880 			instr = duk__get_instr_ptr(comp_ctx, pc_after_expr - 1);
73881 			DUK_ASSERT(instr != NULL);
73882 
73883 			ins = instr->ins;
73884 			op = (duk_small_uint_t) DUK_DEC_OP(ins);
73885 			if ((op & ~0x0fU) == DUK_OP_CALL0 &&
73886 			    DUK__ISREG_TEMP(comp_ctx, rc_val) /* see above */) {
73887 				DUK_DDD(DUK_DDDPRINT("return statement detected a tail call opportunity: "
73888 				                     "catch depth is 0, duk__exprtop() emitted >= 1 instructions, "
73889 				                     "and last instruction is a CALL "
73890 				                     "-> change to TAILCALL"));
73891 				ins |= DUK_ENC_OP(DUK_BC_CALL_FLAG_TAILCALL);
73892 				instr->ins = ins;
73893 			}
73894 		}
73895 #endif  /* DUK_USE_TAILCALL */
73896 
73897 		if (DUK__ISREG(rc_val)) {
73898 			duk__emit_bc(comp_ctx, DUK_OP_RETREG, rc_val);
73899 		} else {
73900 			rc_val = DUK__REMOVECONST(rc_val);
73901 			if (duk__const_needs_refcount(comp_ctx, rc_val)) {
73902 				duk__emit_bc(comp_ctx, DUK_OP_RETCONST, rc_val);
73903 			} else {
73904 				duk__emit_bc(comp_ctx, DUK_OP_RETCONSTN, rc_val);
73905 			}
73906 		}
73907 	}
73908 }
73909 
73910 DUK_LOCAL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
73911 	duk_regconst_t reg_val;
73912 
73913 	duk__advance(comp_ctx);  /* eat 'throw' */
73914 
73915 	/* Unlike break/continue, throw statement does not allow an empty value. */
73916 
73917 	if (comp_ctx->curr_token.lineterm) {
73918 		DUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_INVALID_THROW);
73919 		DUK_WO_NORETURN(return;);
73920 	}
73921 
73922 	reg_val = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
73923 	duk__emit_bc(comp_ctx,
73924 	             DUK_OP_THROW,
73925 	             reg_val);
73926 }
73927 
73928 DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
73929 	duk_hthread *thr = comp_ctx->thr;
73930 	duk_regconst_t reg_catch;      /* reg_catch+0 and reg_catch+1 are reserved for TRYCATCH */
73931 	duk_regconst_t rc_varname = 0;
73932 	duk_small_uint_t trycatch_flags = 0;
73933 	duk_int_t pc_ldconst = -1;
73934 	duk_int_t pc_trycatch = -1;
73935 	duk_int_t pc_catch = -1;
73936 	duk_int_t pc_finally = -1;
73937 
73938 	DUK_UNREF(res);
73939 
73940 	/*
73941 	 *  See the following documentation for discussion:
73942 	 *
73943 	 *    doc/execution.rst: control flow details
73944 	 *
73945 	 *  Try, catch, and finally "parts" are Blocks, not Statements, so
73946 	 *  they must always be delimited by curly braces.  This is unlike e.g.
73947 	 *  the if statement, which accepts any Statement.  This eliminates any
73948 	 *  questions of matching parts of nested try statements.  The Block
73949 	 *  parsing is implemented inline here (instead of calling out).
73950 	 *
73951 	 *  Finally part has a 'let scoped' variable, which requires a few kinks
73952 	 *  here.
73953 	 */
73954 
73955 	comp_ctx->curr_func.catch_depth++;
73956 
73957 	duk__advance(comp_ctx);  /* eat 'try' */
73958 
73959 	reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
73960 
73961 	/* The target for this LDCONST may need output shuffling, but we assume
73962 	 * that 'pc_ldconst' will be the LDCONST that we can patch later.  This
73963 	 * should be the case because there's no input shuffling.  (If there's
73964 	 * no catch clause, this LDCONST will be replaced with a NOP.)
73965 	 */
73966 	pc_ldconst = duk__get_current_pc(comp_ctx);
73967 	duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, reg_catch, 0 /*patched later*/);
73968 
73969 	pc_trycatch = duk__get_current_pc(comp_ctx);
73970 	duk__emit_invalid(comp_ctx);  /* TRYCATCH, cannot emit now (not enough info) */
73971 	duk__emit_invalid(comp_ctx);  /* jump for 'catch' case */
73972 	duk__emit_invalid(comp_ctx);  /* jump for 'finally' case or end (if no finally) */
73973 
73974 	/* try part */
73975 	duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
73976 	duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
73977 	/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
73978 	duk__emit_op_only(comp_ctx, DUK_OP_ENDTRY);
73979 
73980 	if (comp_ctx->curr_token.t == DUK_TOK_CATCH) {
73981 		/*
73982 		 *  The catch variable must be updated to reflect the new allocated
73983 		 *  register for the duration of the catch clause.  We need to store
73984 		 *  and restore the original value for the varmap entry (if any).
73985 		 */
73986 
73987 		/*
73988 		 *  Note: currently register bindings must be fixed for the entire
73989 		 *  function.  So, even though the catch variable is in a register
73990 		 *  we know, we must use an explicit environment record and slow path
73991 		 *  accesses to read/write the catch binding to make closures created
73992 		 *  within the catch clause work correctly.  This restriction should
73993 		 *  be fixable (at least in common cases) later.
73994 		 *
73995 		 *  See: test-bug-catch-binding-2.js.
73996 		 *
73997 		 *  XXX: improve to get fast path access to most catch clauses.
73998 		 */
73999 
74000 		duk_hstring *h_var;
74001 		duk_int_t varmap_value;  /* for storing/restoring the varmap binding for catch variable */
74002 
74003 		DUK_DDD(DUK_DDDPRINT("stack top at start of catch clause: %ld", (long) duk_get_top(thr)));
74004 
74005 		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_CATCH;
74006 
74007 		pc_catch = duk__get_current_pc(comp_ctx);
74008 
74009 		duk__advance(comp_ctx);
74010 		duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
74011 
74012 		if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
74013 			/* Identifier, i.e. don't allow reserved words */
74014 			goto syntax_error;
74015 		}
74016 		h_var = comp_ctx->curr_token.str1;
74017 		DUK_ASSERT(h_var != NULL);
74018 
74019 		duk_push_hstring(thr, h_var);  /* keep in on valstack, use borrowed ref below */
74020 
74021 		if (comp_ctx->curr_func.is_strict &&
74022 		    ((h_var == DUK_HTHREAD_STRING_EVAL(thr)) ||
74023 		     (h_var == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)))) {
74024 			DUK_DDD(DUK_DDDPRINT("catch identifier 'eval' or 'arguments' in strict mode -> SyntaxError"));
74025 			goto syntax_error;
74026 		}
74027 
74028 		duk_dup_top(thr);
74029 		rc_varname = duk__getconst(comp_ctx);
74030 		DUK_DDD(DUK_DDDPRINT("catch clause, rc_varname=0x%08lx (%ld)",
74031 		                     (unsigned long) rc_varname, (long) rc_varname));
74032 
74033 		duk__advance(comp_ctx);
74034 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
74035 
74036 		duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
74037 
74038 		DUK_DDD(DUK_DDDPRINT("varmap before modifying for catch clause: %!iT",
74039 		                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
74040 
74041 		duk_dup_top(thr);
74042 		duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
74043 		if (duk_is_undefined(thr, -1)) {
74044 			varmap_value = -2;
74045 		} else if (duk_is_null(thr, -1)) {
74046 			varmap_value = -1;
74047 		} else {
74048 			DUK_ASSERT(duk_is_number(thr, -1));
74049 			varmap_value = duk_get_int(thr, -1);
74050 			DUK_ASSERT(varmap_value >= 0);
74051 		}
74052 		duk_pop(thr);
74053 
74054 #if 0
74055 		/* It'd be nice to do something like this - but it doesn't
74056 		 * work for closures created inside the catch clause.
74057 		 */
74058 		duk_dup_top(thr);
74059 		duk_push_int(thr, (duk_int_t) (reg_catch + 0));
74060 		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);
74061 #endif
74062 		duk_dup_top(thr);
74063 		duk_push_null(thr);
74064 		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);
74065 
74066 		duk__emit_a_bc(comp_ctx,
74067 		               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
74068 		               reg_catch + 0 /*value*/,
74069 		               rc_varname /*varname*/);
74070 
74071 		DUK_DDD(DUK_DDDPRINT("varmap before parsing catch clause: %!iT",
74072 		                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
74073 
74074 		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
74075 		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
74076 
74077 		if (varmap_value == -2) {
74078 			/* not present */
74079 			duk_del_prop(thr, comp_ctx->curr_func.varmap_idx);
74080 		} else {
74081 			if (varmap_value == -1) {
74082 				duk_push_null(thr);
74083 			} else {
74084 				DUK_ASSERT(varmap_value >= 0);
74085 				duk_push_int(thr, varmap_value);
74086 			}
74087 			duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);
74088 		}
74089 		/* varname is popped by above code */
74090 
74091 		DUK_DDD(DUK_DDDPRINT("varmap after restore catch clause: %!iT",
74092 		                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
74093 
74094 		duk__emit_op_only(comp_ctx,
74095 		                  DUK_OP_ENDCATCH);
74096 
74097 		/*
74098 		 *  XXX: for now, indicate that an expensive catch binding
74099 		 *  declarative environment is always needed.  If we don't
74100 		 *  need it, we don't need the const_varname either.
74101 		 */
74102 
74103 		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_CATCH_BINDING;
74104 
74105 		DUK_DDD(DUK_DDDPRINT("stack top at end of catch clause: %ld", (long) duk_get_top(thr)));
74106 	}
74107 
74108 	if (comp_ctx->curr_token.t == DUK_TOK_FINALLY) {
74109 		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY;
74110 
74111 		pc_finally = duk__get_current_pc(comp_ctx);
74112 
74113 		duk__advance(comp_ctx);
74114 
74115 		duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
74116 		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
74117 		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
74118 		duk__emit_abc(comp_ctx,
74119 		              DUK_OP_ENDFIN,
74120 		              reg_catch);  /* rethrow */
74121 	}
74122 
74123 	if (!(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) &&
74124 	    !(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY)) {
74125 		/* must have catch and/or finally */
74126 		goto syntax_error;
74127 	}
74128 
74129 	/* If there's no catch block, rc_varname will be 0 and duk__patch_trycatch()
74130 	 * will replace the LDCONST with a NOP.  For any actual constant (including
74131 	 * constant 0) the DUK__CONST_MARKER flag will be set in rc_varname.
74132 	 */
74133 
74134 	duk__patch_trycatch(comp_ctx,
74135 	                    pc_ldconst,
74136 	                    pc_trycatch,
74137 	                    reg_catch,
74138 	                    rc_varname,
74139 	                    trycatch_flags);
74140 
74141 	if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {
74142 		DUK_ASSERT(pc_catch >= 0);
74143 		duk__patch_jump(comp_ctx, pc_trycatch + 1, pc_catch);
74144 	}
74145 
74146 	if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {
74147 		DUK_ASSERT(pc_finally >= 0);
74148 		duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finally);
74149 	} else {
74150 		/* without finally, the second jump slot is used to jump to end of stmt */
74151 		duk__patch_jump_here(comp_ctx, pc_trycatch + 2);
74152 	}
74153 
74154 	comp_ctx->curr_func.catch_depth--;
74155 	return;
74156 
74157  syntax_error:
74158 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_TRY);
74159 	DUK_WO_NORETURN(return;);
74160 }
74161 
74162 DUK_LOCAL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
74163 	duk_int_t pc_trycatch;
74164 	duk_int_t pc_finished;
74165 	duk_regconst_t reg_catch;
74166 	duk_small_uint_t trycatch_flags;
74167 
74168 	if (comp_ctx->curr_func.is_strict) {
74169 		DUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_WITH_IN_STRICT_MODE);
74170 		DUK_WO_NORETURN(return;);
74171 	}
74172 
74173 	comp_ctx->curr_func.catch_depth++;
74174 
74175 	duk__advance(comp_ctx);  /* eat 'with' */
74176 
74177 	reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
74178 
74179 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
74180 	duk__exprtop_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/, reg_catch);
74181 	comp_ctx->curr_func.allow_regexp_in_adv = 1;
74182 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
74183 
74184 	pc_trycatch = duk__get_current_pc(comp_ctx);
74185 	trycatch_flags = DUK_BC_TRYCATCH_FLAG_WITH_BINDING;
74186 	duk__emit_a_bc(comp_ctx,
74187 	                DUK_OP_TRYCATCH | DUK__EMIT_FLAG_NO_SHUFFLE_A,
74188 	                (duk_regconst_t) trycatch_flags /*a*/,
74189 	                reg_catch /*bc*/);
74190 	duk__emit_invalid(comp_ctx);  /* catch jump */
74191 	duk__emit_invalid(comp_ctx);  /* finished jump */
74192 
74193 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
74194 	duk__emit_op_only(comp_ctx, DUK_OP_ENDTRY);
74195 
74196 	pc_finished = duk__get_current_pc(comp_ctx);
74197 
74198 	duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finished);
74199 
74200 	comp_ctx->curr_func.catch_depth--;
74201 }
74202 
74203 DUK_LOCAL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id) {
74204 	/* if a site already exists, nop: max one label site per statement */
74205 	if (label_id >= 0) {
74206 		return label_id;
74207 	}
74208 
74209 	label_id = comp_ctx->curr_func.label_next++;
74210 	DUK_DDD(DUK_DDDPRINT("allocated new label id for label site: %ld", (long) label_id));
74211 
74212 	duk__emit_bc(comp_ctx,
74213 	             DUK_OP_LABEL,
74214 	             (duk_regconst_t) label_id);
74215 	duk__emit_invalid(comp_ctx);
74216 	duk__emit_invalid(comp_ctx);
74217 
74218 	return label_id;
74219 }
74220 
74221 /* Parse a single statement.
74222  *
74223  * Creates a label site (with an empty label) automatically for iteration
74224  * statements.  Also "peels off" any label statements for explicit labels.
74225  */
74226 DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem) {
74227 	duk_hthread *thr = comp_ctx->thr;
74228 	duk_bool_t dir_prol_at_entry;    /* directive prologue status at entry */
74229 	duk_regconst_t temp_at_entry;
74230 	duk_size_t labels_len_at_entry;
74231 	duk_int_t pc_at_entry;           /* assumed to also be PC of "LABEL" */
74232 	duk_int_t stmt_id;
74233 	duk_small_uint_t stmt_flags = 0;
74234 	duk_int_t label_id = -1;
74235 	duk_small_uint_t tok;
74236 	duk_bool_t test_func_decl;
74237 
74238 	DUK__RECURSION_INCREASE(comp_ctx, thr);
74239 
74240 	temp_at_entry = DUK__GETTEMP(comp_ctx);
74241 	pc_at_entry = duk__get_current_pc(comp_ctx);
74242 	labels_len_at_entry = duk_get_length(thr, comp_ctx->curr_func.labelnames_idx);
74243 	stmt_id = comp_ctx->curr_func.stmt_next++;
74244 	dir_prol_at_entry = comp_ctx->curr_func.in_directive_prologue;
74245 
74246 	DUK_UNREF(stmt_id);
74247 
74248 	DUK_DDD(DUK_DDDPRINT("parsing a statement, stmt_id=%ld, temp_at_entry=%ld, labels_len_at_entry=%ld, "
74249 	                     "is_strict=%ld, in_directive_prologue=%ld, catch_depth=%ld",
74250 	                     (long) stmt_id, (long) temp_at_entry, (long) labels_len_at_entry,
74251 	                     (long) comp_ctx->curr_func.is_strict, (long) comp_ctx->curr_func.in_directive_prologue,
74252 	                     (long) comp_ctx->curr_func.catch_depth));
74253 
74254 	/* The directive prologue flag is cleared by default so that it is
74255 	 * unset for any recursive statement parsing.  It is only "revived"
74256 	 * if a directive is detected.  (We could also make directives only
74257 	 * allowed if 'allow_source_elem' was true.)
74258 	 */
74259 	comp_ctx->curr_func.in_directive_prologue = 0;
74260 
74261  retry_parse:
74262 
74263 	DUK_DDD(DUK_DDDPRINT("try stmt parse, stmt_id=%ld, label_id=%ld, allow_source_elem=%ld, catch_depth=%ld",
74264 	                     (long) stmt_id, (long) label_id, (long) allow_source_elem,
74265 	                     (long) comp_ctx->curr_func.catch_depth));
74266 
74267 	/*
74268 	 *  Detect iteration statements; if encountered, establish an
74269 	 *  empty label.
74270 	 */
74271 
74272 	tok = comp_ctx->curr_token.t;
74273 	if (tok == DUK_TOK_FOR || tok == DUK_TOK_DO || tok == DUK_TOK_WHILE ||
74274 	    tok == DUK_TOK_SWITCH) {
74275 		DUK_DDD(DUK_DDDPRINT("iteration/switch statement -> add empty label"));
74276 
74277 		label_id = duk__stmt_label_site(comp_ctx, label_id);
74278 		duk__add_label(comp_ctx,
74279 		               DUK_HTHREAD_STRING_EMPTY_STRING(thr),
74280 		               pc_at_entry /*pc_label*/,
74281 		               label_id);
74282 	}
74283 
74284 	/*
74285 	 *  Main switch for statement / source element type.
74286 	 */
74287 
74288 	switch (comp_ctx->curr_token.t) {
74289 	case DUK_TOK_FUNCTION: {
74290 		/*
74291 		 *  Function declaration, function expression, or (non-standard)
74292 		 *  function statement.
74293 		 *
74294 		 *  The E5 specification only allows function declarations at
74295 		 *  the top level (in "source elements").  An ExpressionStatement
74296 		 *  is explicitly not allowed to begin with a "function" keyword
74297 		 *  (E5 Section 12.4).  Hence any non-error semantics for such
74298 		 *  non-top-level statements are non-standard.  Duktape semantics
74299 		 *  for function statements are modelled after V8, see
74300 		 *  test-dev-func-decl-outside-top.js.
74301 		 */
74302 		test_func_decl = allow_source_elem;
74303 #if defined(DUK_USE_NONSTD_FUNC_STMT)
74304 		/* Lenient: allow function declarations outside top level in both
74305 		 * strict and non-strict modes.  However, don't allow labelled
74306 		 * function declarations in strict mode.
74307 		 */
74308 		test_func_decl = test_func_decl ||
74309 		                 !comp_ctx->curr_func.is_strict ||
74310 		                 label_id < 0;
74311 #endif  /* DUK_USE_NONSTD_FUNC_STMT */
74312 		/* Strict: never allow function declarations outside top level. */
74313 		if (test_func_decl) {
74314 			/* FunctionDeclaration: not strictly a statement but handled as such.
74315 			 *
74316 			 * O(depth^2) parse count for inner functions is handled by recording a
74317 			 * lexer offset on the first compilation pass, so that the function can
74318 			 * be efficiently skipped on the second pass.  This is encapsulated into
74319 			 * duk__parse_func_like_fnum().
74320 			 */
74321 
74322 			duk_int_t fnum;
74323 #if defined(DUK_USE_ASSERTIONS)
74324 			duk_idx_t top_before;
74325 #endif
74326 
74327 			DUK_DDD(DUK_DDDPRINT("function declaration statement"));
74328 
74329 #if defined(DUK_USE_ASSERTIONS)
74330 			top_before = duk_get_top(thr);
74331 #endif
74332 
74333 			duk__advance(comp_ctx);  /* eat 'function' */
74334 			fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_DECL | DUK__FUNC_FLAG_PUSHNAME_PASS1);
74335 
74336 			/* The value stack convention here is a bit odd: the function
74337 			 * name is only pushed on pass 1 (in_scanning), and is needed
74338 			 * to process function declarations.
74339 			 */
74340 			if (comp_ctx->curr_func.in_scanning) {
74341 				duk_uarridx_t n;
74342 
74343 #if defined(DUK_USE_ASSERTIONS)
74344 				DUK_ASSERT(duk_get_top(thr) == top_before + 1);
74345 #endif
74346 				DUK_DDD(DUK_DDDPRINT("register function declaration %!T in pass 1, fnum %ld",
74347 				                     duk_get_tval(thr, -1), (long) fnum));
74348 				n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
74349 				/* funcname is at index -1 */
74350 				duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n);
74351 				duk_push_int(thr, (duk_int_t) (DUK_DECL_TYPE_FUNC + (fnum << 8)));
74352 				duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n + 1);
74353 			} else {
74354 #if defined(DUK_USE_ASSERTIONS)
74355 				DUK_ASSERT(duk_get_top(thr) == top_before);
74356 #endif
74357 			}
74358 
74359 			/* no statement value (unlike function expression) */
74360 			stmt_flags = 0;
74361 			break;
74362 		} else {
74363 			DUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_STMT_NOT_ALLOWED);
74364 			DUK_WO_NORETURN(return;);
74365 		}
74366 		break;
74367 	}
74368 	case DUK_TOK_LCURLY: {
74369 		DUK_DDD(DUK_DDDPRINT("block statement"));
74370 		duk__advance(comp_ctx);
74371 		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
74372 		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
74373 		if (label_id >= 0) {
74374 			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
74375 		}
74376 		stmt_flags = 0;
74377 		break;
74378 	}
74379 	case DUK_TOK_CONST: {
74380 		DUK_DDD(DUK_DDDPRINT("constant declaration statement"));
74381 		duk__parse_var_stmt(comp_ctx, res, DUK__EXPR_FLAG_REQUIRE_INIT /*expr_flags*/);
74382 		stmt_flags = DUK__HAS_TERM;
74383 		break;
74384 	}
74385 	case DUK_TOK_VAR: {
74386 		DUK_DDD(DUK_DDDPRINT("variable declaration statement"));
74387 		duk__parse_var_stmt(comp_ctx, res, 0 /*expr_flags*/);
74388 		stmt_flags = DUK__HAS_TERM;
74389 		break;
74390 	}
74391 	case DUK_TOK_SEMICOLON: {
74392 		/* empty statement with an explicit semicolon */
74393 		DUK_DDD(DUK_DDDPRINT("empty statement"));
74394 		stmt_flags = DUK__HAS_TERM;
74395 		break;
74396 	}
74397 	case DUK_TOK_IF: {
74398 		DUK_DDD(DUK_DDDPRINT("if statement"));
74399 		duk__parse_if_stmt(comp_ctx, res);
74400 		if (label_id >= 0) {
74401 			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
74402 		}
74403 		stmt_flags = 0;
74404 		break;
74405 	}
74406 	case DUK_TOK_DO: {
74407 		/*
74408 		 *  Do-while statement is mostly trivial, but there is special
74409 		 *  handling for automatic semicolon handling (triggered by the
74410 		 *  DUK__ALLOW_AUTO_SEMI_ALWAYS) flag related to a bug filed at:
74411 		 *
74412 		 *    https://bugs.ecmascript.org/show_bug.cgi?id=8
74413 		 *
74414 		 *  See doc/compiler.rst for details.
74415 		 */
74416 		DUK_DDD(DUK_DDDPRINT("do statement"));
74417 		DUK_ASSERT(label_id >= 0);
74418 		duk__update_label_flags(comp_ctx,
74419 		                        label_id,
74420 		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
74421 		duk__parse_do_stmt(comp_ctx, res, pc_at_entry);
74422 		stmt_flags = DUK__HAS_TERM | DUK__ALLOW_AUTO_SEMI_ALWAYS;  /* DUK__ALLOW_AUTO_SEMI_ALWAYS workaround */
74423 		break;
74424 	}
74425 	case DUK_TOK_WHILE: {
74426 		DUK_DDD(DUK_DDDPRINT("while statement"));
74427 		DUK_ASSERT(label_id >= 0);
74428 		duk__update_label_flags(comp_ctx,
74429 		                        label_id,
74430 		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
74431 		duk__parse_while_stmt(comp_ctx, res, pc_at_entry);
74432 		stmt_flags = 0;
74433 		break;
74434 	}
74435 	case DUK_TOK_FOR: {
74436 		/*
74437 		 *  For/for-in statement is complicated to parse because
74438 		 *  determining the statement type (three-part for vs. a
74439 		 *  for-in) requires potential backtracking.
74440 		 *
74441 		 *  See the helper for the messy stuff.
74442 		 */
74443 		DUK_DDD(DUK_DDDPRINT("for/for-in statement"));
74444 		DUK_ASSERT(label_id >= 0);
74445 		duk__update_label_flags(comp_ctx,
74446 		                        label_id,
74447 		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
74448 		duk__parse_for_stmt(comp_ctx, res, pc_at_entry);
74449 		stmt_flags = 0;
74450 		break;
74451 	}
74452 	case DUK_TOK_CONTINUE:
74453 	case DUK_TOK_BREAK: {
74454 		DUK_DDD(DUK_DDDPRINT("break/continue statement"));
74455 		duk__parse_break_or_continue_stmt(comp_ctx, res);
74456 		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
74457 		break;
74458 	}
74459 	case DUK_TOK_RETURN: {
74460 		DUK_DDD(DUK_DDDPRINT("return statement"));
74461 		duk__parse_return_stmt(comp_ctx, res);
74462 		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
74463 		break;
74464 	}
74465 	case DUK_TOK_WITH: {
74466 		DUK_DDD(DUK_DDDPRINT("with statement"));
74467 		comp_ctx->curr_func.with_depth++;
74468 		duk__parse_with_stmt(comp_ctx, res);
74469 		if (label_id >= 0) {
74470 			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
74471 		}
74472 		comp_ctx->curr_func.with_depth--;
74473 		stmt_flags = 0;
74474 		break;
74475 	}
74476 	case DUK_TOK_SWITCH: {
74477 		/*
74478 		 *  The switch statement is pretty messy to compile.
74479 		 *  See the helper for details.
74480 		 */
74481 		DUK_DDD(DUK_DDDPRINT("switch statement"));
74482 		DUK_ASSERT(label_id >= 0);
74483 		duk__update_label_flags(comp_ctx,
74484 		                        label_id,
74485 		                        DUK_LABEL_FLAG_ALLOW_BREAK);  /* don't allow continue */
74486 		duk__parse_switch_stmt(comp_ctx, res, pc_at_entry);
74487 		stmt_flags = 0;
74488 		break;
74489 	}
74490 	case DUK_TOK_THROW: {
74491 		DUK_DDD(DUK_DDDPRINT("throw statement"));
74492 		duk__parse_throw_stmt(comp_ctx, res);
74493 		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
74494 		break;
74495 	}
74496 	case DUK_TOK_TRY: {
74497 		DUK_DDD(DUK_DDDPRINT("try statement"));
74498 		duk__parse_try_stmt(comp_ctx, res);
74499 		stmt_flags = 0;
74500 		break;
74501 	}
74502 	case DUK_TOK_DEBUGGER: {
74503 		duk__advance(comp_ctx);
74504 #if defined(DUK_USE_DEBUGGER_SUPPORT)
74505 		DUK_DDD(DUK_DDDPRINT("debugger statement: debugging enabled, emit debugger opcode"));
74506 		duk__emit_op_only(comp_ctx, DUK_OP_DEBUGGER);
74507 #else
74508 		DUK_DDD(DUK_DDDPRINT("debugger statement: ignored"));
74509 #endif
74510 		stmt_flags = DUK__HAS_TERM;
74511 		break;
74512 	}
74513 	default: {
74514 		/*
74515 		 *  Else, must be one of:
74516 		 *    - ExpressionStatement, possibly a directive (String)
74517 		 *    - LabelledStatement (Identifier followed by ':')
74518 		 *
74519 		 *  Expressions beginning with 'function' keyword are covered by a case
74520 		 *  above (such expressions are not allowed in standard E5 anyway).
74521 		 *  Also expressions starting with '{' are interpreted as block
74522 		 *  statements.  See E5 Section 12.4.
74523 		 *
74524 		 *  Directive detection is tricky; see E5 Section 14.1 on directive
74525 		 *  prologue.  A directive is an expression statement with a single
74526 		 *  string literal and an explicit or automatic semicolon.  Escape
74527 		 *  characters are significant and no parens etc are allowed:
74528 		 *
74529 		 *    'use strict';          // valid 'use strict' directive
74530 		 *    'use\u0020strict';     // valid directive, not a 'use strict' directive
74531 		 *    ('use strict');        // not a valid directive
74532 		 *
74533 		 *  The expression is determined to consist of a single string literal
74534 		 *  based on duk__expr_nud() and duk__expr_led() call counts.  The string literal
74535 		 *  of a 'use strict' directive is determined to lack any escapes based
74536 		 *  num_escapes count from the lexer.  Note that other directives may be
74537 		 *  allowed to contain escapes, so a directive with escapes does not
74538 		 *  terminate a directive prologue.
74539 		 *
74540 		 *  We rely on the fact that the expression parser will not emit any
74541 		 *  code for a single token expression.  However, it will generate an
74542 		 *  intermediate value which we will then successfully ignore.
74543 		 *
74544 		 *  A similar approach is used for labels.
74545 		 */
74546 
74547 		duk_bool_t single_token;
74548 
74549 		DUK_DDD(DUK_DDDPRINT("expression statement"));
74550 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
74551 
74552 		single_token = (comp_ctx->curr_func.nud_count == 1 &&  /* one token */
74553 		                comp_ctx->curr_func.led_count == 0);   /* no operators */
74554 
74555 		if (single_token &&
74556 		    comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
74557 		    comp_ctx->curr_token.t == DUK_TOK_COLON) {
74558 			/*
74559 			 *  Detected label
74560 			 */
74561 
74562 			duk_hstring *h_lab;
74563 
74564 			/* expected ival */
74565 			DUK_ASSERT(res->t == DUK_IVAL_VAR);
74566 			DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
74567 			DUK_ASSERT(DUK_TVAL_IS_STRING(duk_get_tval(thr, res->x1.valstack_idx)));
74568 			h_lab = comp_ctx->prev_token.str1;
74569 			DUK_ASSERT(h_lab != NULL);
74570 
74571 			DUK_DDD(DUK_DDDPRINT("explicit label site for label '%!O'",
74572 			                     (duk_heaphdr *) h_lab));
74573 
74574 			duk__advance(comp_ctx);  /* eat colon */
74575 
74576 			label_id = duk__stmt_label_site(comp_ctx, label_id);
74577 
74578 			duk__add_label(comp_ctx,
74579 			               h_lab,
74580 			               pc_at_entry /*pc_label*/,
74581 			               label_id);
74582 
74583 			/* a statement following a label cannot be a source element
74584 			 * (a function declaration).
74585 			 */
74586 			allow_source_elem = 0;
74587 
74588 			DUK_DDD(DUK_DDDPRINT("label handled, retry statement parsing"));
74589 			goto retry_parse;
74590 		}
74591 
74592 		stmt_flags = 0;
74593 
74594 		if (dir_prol_at_entry &&                           /* still in prologue */
74595 		    single_token &&                                /* single string token */
74596 		    comp_ctx->prev_token.t == DUK_TOK_STRING) {
74597 			/*
74598 			 *  Detected a directive
74599 			 */
74600 			duk_hstring *h_dir;
74601 
74602 			/* expected ival */
74603 			DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
74604 			DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
74605 			DUK_ASSERT(DUK_TVAL_IS_STRING(duk_get_tval(thr, res->x1.valstack_idx)));
74606 			h_dir = comp_ctx->prev_token.str1;
74607 			DUK_ASSERT(h_dir != NULL);
74608 
74609 			DUK_DDD(DUK_DDDPRINT("potential directive: %!O", h_dir));
74610 
74611 			stmt_flags |= DUK__STILL_PROLOGUE;
74612 
74613 			/* Note: escaped characters differentiate directives */
74614 
74615 			if (comp_ctx->prev_token.num_escapes > 0) {
74616 				DUK_DDD(DUK_DDDPRINT("directive contains escapes: valid directive "
74617 				                     "but we ignore such directives"));
74618 			} else {
74619 				/*
74620 				 * The length comparisons are present to handle
74621 				 * strings like "use strict\u0000foo" as required.
74622 				 */
74623 
74624 				if (DUK_HSTRING_GET_BYTELEN(h_dir) == 10 &&
74625 				    DUK_STRCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use strict") == 0) {
74626 #if defined(DUK_USE_STRICT_DECL)
74627 					DUK_DDD(DUK_DDDPRINT("use strict directive detected: strict flag %ld -> %ld",
74628 					                     (long) comp_ctx->curr_func.is_strict, (long) 1));
74629 					comp_ctx->curr_func.is_strict = 1;
74630 #else
74631 					DUK_DDD(DUK_DDDPRINT("use strict detected but strict declarations disabled, ignoring"));
74632 #endif
74633 				} else if (DUK_HSTRING_GET_BYTELEN(h_dir) == 14 &&
74634 				           DUK_STRCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use duk notail") == 0) {
74635 					DUK_DDD(DUK_DDDPRINT("use duk notail directive detected: notail flag %ld -> %ld",
74636 					                     (long) comp_ctx->curr_func.is_notail, (long) 1));
74637 					comp_ctx->curr_func.is_notail = 1;
74638 				} else {
74639 					DUK_DD(DUK_DDPRINT("unknown directive: '%!O', ignoring but not terminating "
74640 					                   "directive prologue", (duk_hobject *) h_dir));
74641 				}
74642 			}
74643 		} else {
74644 			DUK_DDD(DUK_DDDPRINT("non-directive expression statement or no longer in prologue; "
74645 			                     "prologue terminated if still active"));
74646                 }
74647 
74648 		stmt_flags |= DUK__HAS_VAL | DUK__HAS_TERM;
74649 	}
74650 	}  /* end switch (tok) */
74651 
74652 	/*
74653 	 *  Statement value handling.
74654 	 *
74655 	 *  Global code and eval code has an implicit return value
74656 	 *  which comes from the last statement with a value
74657 	 *  (technically a non-"empty" continuation, which is
74658 	 *  different from an empty statement).
74659 	 *
74660 	 *  Since we don't know whether a later statement will
74661 	 *  override the value of the current statement, we need
74662 	 *  to coerce the statement value to a register allocated
74663 	 *  for implicit return values.  In other cases we need
74664 	 *  to coerce the statement value to a plain value to get
74665 	 *  any side effects out (consider e.g. "foo.bar;").
74666 	 */
74667 
74668 	/* XXX: what about statements which leave a half-cooked value in 'res'
74669 	 * but have no stmt value?  Any such statements?
74670 	 */
74671 
74672 	if (stmt_flags & DUK__HAS_VAL) {
74673 		duk_regconst_t reg_stmt_value = comp_ctx->curr_func.reg_stmt_value;
74674 		if (reg_stmt_value >= 0) {
74675 			duk__ivalue_toforcedreg(comp_ctx, res, reg_stmt_value);
74676 		} else {
74677 			duk__ivalue_toplain_ignore(comp_ctx, res);
74678 		}
74679 	} else {
74680 		;
74681 	}
74682 
74683 	/*
74684 	 *  Statement terminator check, including automatic semicolon
74685 	 *  handling.  After this step, 'curr_tok' should be the first
74686 	 *  token after a possible statement terminator.
74687 	 */
74688 
74689 	if (stmt_flags & DUK__HAS_TERM) {
74690 		if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON) {
74691 			DUK_DDD(DUK_DDDPRINT("explicit semicolon terminates statement"));
74692 			duk__advance(comp_ctx);
74693 		} else {
74694 			if (comp_ctx->curr_token.allow_auto_semi) {
74695 				DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement"));
74696 			} else if (stmt_flags & DUK__ALLOW_AUTO_SEMI_ALWAYS) {
74697 				/* XXX: make this lenience dependent on flags or strictness? */
74698 				DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement (allowed for compatibility "
74699 				                     "even though no lineterm present before next token)"));
74700 			} else {
74701 				DUK_ERROR_SYNTAX(thr, DUK_STR_UNTERMINATED_STMT);
74702 				DUK_WO_NORETURN(return;);
74703 			}
74704 		}
74705 	} else {
74706 		DUK_DDD(DUK_DDDPRINT("statement has no terminator"));
74707 	}
74708 
74709 	/*
74710 	 *  Directive prologue tracking.
74711 	 */
74712 
74713 	if (stmt_flags & DUK__STILL_PROLOGUE) {
74714 		DUK_DDD(DUK_DDDPRINT("setting in_directive_prologue"));
74715 		comp_ctx->curr_func.in_directive_prologue = 1;
74716 	}
74717 
74718 	/*
74719 	 *  Cleanups (all statement parsing flows through here).
74720 	 *
74721 	 *  Pop label site and reset labels.  Reset 'next temp' to value at
74722 	 *  entry to reuse temps.
74723 	 */
74724 
74725 	if (label_id >= 0) {
74726 		duk__emit_bc(comp_ctx,
74727 		             DUK_OP_ENDLABEL,
74728 		             (duk_regconst_t) label_id);
74729 	}
74730 
74731 	DUK__SETTEMP(comp_ctx, temp_at_entry);
74732 
74733 	duk__reset_labels_to_length(comp_ctx, labels_len_at_entry);
74734 
74735 	/* XXX: return indication of "terminalness" (e.g. a 'throw' is terminal) */
74736 
74737 	DUK__RECURSION_DECREASE(comp_ctx, thr);
74738 }
74739 
74740 /*
74741  *  Parse a statement list.
74742  *
74743  *  Handles automatic semicolon insertion and implicit return value.
74744  *
74745  *  Upon entry, 'curr_tok' should contain the first token of the first
74746  *  statement (parsed in the "allow regexp literal" mode).  Upon exit,
74747  *  'curr_tok' contains the token following the statement list terminator
74748  *  (EOF or closing brace).
74749  */
74750 
74751 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) {
74752 	duk_hthread *thr = comp_ctx->thr;
74753 	duk_ivalue res_alloc;
74754 	duk_ivalue *res = &res_alloc;
74755 
74756 	/* Setup state.  Initial ivalue is 'undefined'. */
74757 
74758 	duk_require_stack(thr, DUK__PARSE_STATEMENTS_SLOTS);
74759 
74760 	/* XXX: 'res' setup can be moved to function body level; in fact, two 'res'
74761 	 * intermediate values suffice for parsing of each function.  Nesting is needed
74762 	 * for nested functions (which may occur inside expressions).
74763 	 */
74764 
74765 	duk_memzero(&res_alloc, sizeof(res_alloc));
74766 	res->t = DUK_IVAL_PLAIN;
74767 	res->x1.t = DUK_ISPEC_VALUE;
74768 	res->x1.valstack_idx = duk_get_top(thr);
74769 	res->x2.valstack_idx = res->x1.valstack_idx + 1;
74770 	duk_push_undefined(thr);
74771 	duk_push_undefined(thr);
74772 
74773 	/* Parse statements until a closing token (EOF or '}') is found. */
74774 
74775 	for (;;) {
74776 		/* Check whether statement list ends. */
74777 
74778 		if (expect_eof) {
74779 			if (comp_ctx->curr_token.t == DUK_TOK_EOF) {
74780 				break;
74781 			}
74782 		} else {
74783 			if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
74784 				break;
74785 			}
74786 		}
74787 
74788 		/* Check statement type based on the first token type.
74789 		 *
74790 		 * Note: expression parsing helpers expect 'curr_tok' to
74791 		 * contain the first token of the expression upon entry.
74792 		 */
74793 
74794 		DUK_DDD(DUK_DDDPRINT("TOKEN %ld (non-whitespace, non-comment)", (long) comp_ctx->curr_token.t));
74795 
74796 		duk__parse_stmt(comp_ctx, res, allow_source_elem);
74797 	}
74798 
74799 	/* RegExp is allowed / not allowed depending on context.  For function
74800 	 * declarations RegExp is allowed because it follows a function
74801 	 * declaration statement and may appear as part of the next statement.
74802 	 * For function expressions RegExp is not allowed, and it's possible
74803 	 * to do something like '(function () {} / 123)'.
74804 	 */
74805 	if (regexp_after) {
74806 		comp_ctx->curr_func.allow_regexp_in_adv = 1;
74807 	}
74808 	duk__advance(comp_ctx);
74809 
74810 	/* Tear down state. */
74811 
74812 	duk_pop_2(thr);
74813 }
74814 
74815 /*
74816  *  Declaration binding instantiation conceptually happens when calling a
74817  *  function; for us it essentially means that function prologue.  The
74818  *  conceptual process is described in E5 Section 10.5.
74819  *
74820  *  We need to keep track of all encountered identifiers to (1) create an
74821  *  identifier-to-register map ("varmap"); and (2) detect duplicate
74822  *  declarations.  Identifiers which are not bound to registers still need
74823  *  to be tracked for detecting duplicates.  Currently such identifiers
74824  *  are put into the varmap with a 'null' value, which is later cleaned up.
74825  *
74826  *  To support functions with a large number of variable and function
74827  *  declarations, registers are not allocated beyond a certain limit;
74828  *  after that limit, variables and functions need slow path access.
74829  *  Arguments are currently always register bound, which imposes a hard
74830  *  (and relatively small) argument count limit.
74831  *
74832  *  Some bindings in E5 are not configurable (= deletable) and almost all
74833  *  are mutable (writable).  Exceptions are:
74834  *
74835  *    - The 'arguments' binding, established only if no shadowing argument
74836  *      or function declaration exists.  We handle 'arguments' creation
74837  *      and binding through an explicit slow path environment record.
74838  *
74839  *    - The "name" binding for a named function expression.  This is also
74840  *      handled through an explicit slow path environment record.
74841  */
74842 
74843 /* XXX: add support for variables to not be register bound always, to
74844  * handle cases with a very large number of variables?
74845  */
74846 
74847 DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_regconst_t *out_stmt_value_reg) {
74848 	duk_hthread *thr = comp_ctx->thr;
74849 	duk_hstring *h_name;
74850 	duk_bool_t configurable_bindings;
74851 	duk_uarridx_t num_args;
74852 	duk_uarridx_t num_decls;
74853 	duk_regconst_t rc_name;
74854 	duk_small_uint_t declvar_flags;
74855 	duk_uarridx_t i;
74856 #if defined(DUK_USE_ASSERTIONS)
74857 	duk_idx_t entry_top;
74858 #endif
74859 
74860 #if defined(DUK_USE_ASSERTIONS)
74861 	entry_top = duk_get_top(thr);
74862 #endif
74863 
74864 	/*
74865 	 *  Preliminaries
74866 	 */
74867 
74868 	configurable_bindings = comp_ctx->curr_func.is_eval;
74869 	DUK_DDD(DUK_DDDPRINT("configurable_bindings=%ld", (long) configurable_bindings));
74870 
74871 	/* varmap is already in comp_ctx->curr_func.varmap_idx */
74872 
74873 	/*
74874 	 *  Function formal arguments, always bound to registers
74875 	 *  (there's no support for shuffling them now).
74876 	 */
74877 
74878 	num_args = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.argnames_idx);
74879 	DUK_DDD(DUK_DDDPRINT("num_args=%ld", (long) num_args));
74880 	/* XXX: check num_args */
74881 
74882 	for (i = 0; i < num_args; i++) {
74883 		duk_get_prop_index(thr, comp_ctx->curr_func.argnames_idx, i);
74884 		h_name = duk_known_hstring(thr, -1);
74885 
74886 		if (comp_ctx->curr_func.is_strict) {
74887 			if (duk__hstring_is_eval_or_arguments(comp_ctx, h_name)) {
74888 				DUK_DDD(DUK_DDDPRINT("arg named 'eval' or 'arguments' in strict mode -> SyntaxError"));
74889 				goto error_argname;
74890 			}
74891 			duk_dup_top(thr);
74892 			if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
74893 				DUK_DDD(DUK_DDDPRINT("duplicate arg name in strict mode -> SyntaxError"));
74894 				goto error_argname;
74895 			}
74896 
74897 			/* Ensure argument name is not a reserved word in current
74898 			 * (final) strictness.  Formal argument parsing may not
74899 			 * catch reserved names if strictness changes during
74900 			 * parsing.
74901 			 *
74902 			 * We only need to do this in strict mode because non-strict
74903 			 * keyword are always detected in formal argument parsing.
74904 			 */
74905 
74906 			if (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(h_name)) {
74907 				goto error_argname;
74908 			}
74909 		}
74910 
74911 		/* overwrite any previous binding of the same name; the effect is
74912 		 * that last argument of a certain name wins.
74913 		 */
74914 
74915 		/* only functions can have arguments */
74916 		DUK_ASSERT(comp_ctx->curr_func.is_function);
74917 		duk_push_uarridx(thr, i);  /* -> [ ... name index ] */
74918 		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx); /* -> [ ... ] */
74919 
74920 		/* no code needs to be emitted, the regs already have values */
74921 	}
74922 
74923 	/* use temp_next for tracking register allocations */
74924 	DUK__SETTEMP_CHECKMAX(comp_ctx, (duk_regconst_t) num_args);
74925 
74926 	/*
74927 	 *  After arguments, allocate special registers (like shuffling temps)
74928 	 */
74929 
74930 	if (out_stmt_value_reg) {
74931 		*out_stmt_value_reg = DUK__ALLOCTEMP(comp_ctx);
74932 	}
74933 	if (comp_ctx->curr_func.needs_shuffle) {
74934 		duk_regconst_t shuffle_base = DUK__ALLOCTEMPS(comp_ctx, 3);
74935 		comp_ctx->curr_func.shuffle1 = shuffle_base;
74936 		comp_ctx->curr_func.shuffle2 = shuffle_base + 1;
74937 		comp_ctx->curr_func.shuffle3 = shuffle_base + 2;
74938 		DUK_D(DUK_DPRINT("shuffle registers needed by function, allocated: %ld %ld %ld",
74939 		                 (long) comp_ctx->curr_func.shuffle1,
74940 		                 (long) comp_ctx->curr_func.shuffle2,
74941 		                 (long) comp_ctx->curr_func.shuffle3));
74942 	}
74943 	if (comp_ctx->curr_func.temp_next > 0x100) {
74944 		DUK_D(DUK_DPRINT("not enough 8-bit regs: temp_next=%ld", (long) comp_ctx->curr_func.temp_next));
74945 		goto error_outofregs;
74946 	}
74947 
74948 	/*
74949 	 *  Function declarations
74950 	 */
74951 
74952 	num_decls = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
74953 	DUK_DDD(DUK_DDDPRINT("num_decls=%ld -> %!T",
74954 	                     (long) num_decls,
74955 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.decls_idx)));
74956 	for (i = 0; i < num_decls; i += 2) {
74957 		duk_int_t decl_type;
74958 		duk_int_t fnum;
74959 
74960 		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i + 1);  /* decl type */
74961 		decl_type = duk_to_int(thr, -1);
74962 		fnum = decl_type >> 8;  /* XXX: macros */
74963 		decl_type = decl_type & 0xff;
74964 		duk_pop(thr);
74965 
74966 		if (decl_type != DUK_DECL_TYPE_FUNC) {
74967 			continue;
74968 		}
74969 
74970 		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */
74971 
74972 		/* XXX: spilling */
74973 		if (comp_ctx->curr_func.is_function) {
74974 			duk_regconst_t reg_bind;
74975 			duk_dup_top(thr);
74976 			if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
74977 				/* shadowed; update value */
74978 				duk_dup_top(thr);
74979 				duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
74980 				reg_bind = duk_to_int(thr, -1);  /* [ ... name reg_bind ] */
74981 				duk__emit_a_bc(comp_ctx,
74982 				               DUK_OP_CLOSURE,
74983 				               reg_bind,
74984 				               (duk_regconst_t) fnum);
74985 			} else {
74986 				/* function: always register bound */
74987 				reg_bind = DUK__ALLOCTEMP(comp_ctx);
74988 				duk__emit_a_bc(comp_ctx,
74989 				               DUK_OP_CLOSURE,
74990 				               reg_bind,
74991 				               (duk_regconst_t) fnum);
74992 				duk_push_int(thr, (duk_int_t) reg_bind);
74993 			}
74994 		} else {
74995 			/* Function declaration for global/eval code is emitted even
74996 			 * for duplicates, because of E5 Section 10.5, step 5.e of
74997 			 * E5.1 (special behavior for variable bound to global object).
74998 			 *
74999 			 * DECLVAR will not re-declare a variable as such, but will
75000 			 * update the binding value.
75001 			 */
75002 
75003 			duk_regconst_t reg_temp = DUK__ALLOCTEMP(comp_ctx);
75004 			duk_dup_top(thr);
75005 			rc_name = duk__getconst(comp_ctx);
75006 			duk_push_null(thr);
75007 
75008 			duk__emit_a_bc(comp_ctx,
75009 			               DUK_OP_CLOSURE,
75010 			               reg_temp,
75011 			               (duk_regconst_t) fnum);
75012 
75013 			declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
75014 			                DUK_PROPDESC_FLAG_ENUMERABLE |
75015 			                DUK_BC_DECLVAR_FLAG_FUNC_DECL;
75016 
75017 			if (configurable_bindings) {
75018 				declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
75019 			}
75020 
75021 			duk__emit_a_b_c(comp_ctx,
75022 			                DUK_OP_DECLVAR | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_BC_REGCONST,
75023 			                (duk_regconst_t) declvar_flags /*flags*/,
75024 			                rc_name /*name*/,
75025 			                reg_temp /*value*/);
75026 
75027 			DUK__SETTEMP(comp_ctx, reg_temp);  /* forget temp */
75028 		}
75029 
75030 		DUK_DDD(DUK_DDDPRINT("function declaration to varmap: %!T -> %!T",
75031 		                     (duk_tval *) duk_get_tval(thr, -2),
75032 		                     (duk_tval *) duk_get_tval(thr, -1)));
75033 
75034 #if defined(DUK_USE_FASTINT)
75035 		DUK_ASSERT(DUK_TVAL_IS_NULL(duk_get_tval(thr, -1)) || DUK_TVAL_IS_FASTINT(duk_get_tval(thr, -1)));
75036 #endif
75037 		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);  /* [ ... name reg/null ] -> [ ... ] */
75038 	}
75039 
75040 	/*
75041 	 *  'arguments' binding is special; if a shadowing argument or
75042 	 *  function declaration exists, an arguments object will
75043 	 *  definitely not be needed, regardless of whether the identifier
75044 	 *  'arguments' is referenced inside the function body.
75045 	 */
75046 
75047 	if (duk_has_prop_stridx(thr, comp_ctx->curr_func.varmap_idx, DUK_STRIDX_LC_ARGUMENTS)) {
75048 		DUK_DDD(DUK_DDDPRINT("'arguments' is shadowed by argument or function declaration "
75049 		                     "-> arguments object creation can be skipped"));
75050 		comp_ctx->curr_func.is_arguments_shadowed = 1;
75051 	}
75052 
75053 	/*
75054 	 *  Variable declarations.
75055 	 *
75056 	 *  Unlike function declarations, variable declaration values don't get
75057 	 *  assigned on entry.  If a binding of the same name already exists, just
75058 	 *  ignore it silently.
75059 	 */
75060 
75061 	for (i = 0; i < num_decls; i += 2) {
75062 		duk_int_t decl_type;
75063 
75064 		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i + 1);  /* decl type */
75065 		decl_type = duk_to_int(thr, -1);
75066 		decl_type = decl_type & 0xff;
75067 		duk_pop(thr);
75068 
75069 		if (decl_type != DUK_DECL_TYPE_VAR) {
75070 			continue;
75071 		}
75072 
75073 		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */
75074 
75075 		if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
75076 			/* shadowed, ignore */
75077 		} else {
75078 			duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */
75079 			h_name = duk_known_hstring(thr, -1);
75080 
75081 			if (h_name == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr) &&
75082 			    !comp_ctx->curr_func.is_arguments_shadowed) {
75083 				/* E5 Section steps 7-8 */
75084 				DUK_DDD(DUK_DDDPRINT("'arguments' not shadowed by a function declaration, "
75085 				                     "but appears as a variable declaration -> treat as "
75086 				                     "a no-op for variable declaration purposes"));
75087 				duk_pop(thr);
75088 				continue;
75089 			}
75090 
75091 			/* XXX: spilling */
75092 			if (comp_ctx->curr_func.is_function) {
75093 				duk_regconst_t reg_bind = DUK__ALLOCTEMP(comp_ctx);
75094 				/* no need to init reg, it will be undefined on entry */
75095 				duk_push_int(thr, (duk_int_t) reg_bind);
75096 			} else {
75097 				duk_dup_top(thr);
75098 				rc_name = duk__getconst(comp_ctx);
75099 				duk_push_null(thr);
75100 
75101 				declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
75102 			                        DUK_PROPDESC_FLAG_ENUMERABLE;
75103 				if (configurable_bindings) {
75104 					declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
75105 				}
75106 
75107 				duk__emit_a_b_c(comp_ctx,
75108 				                DUK_OP_DECLVAR | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_BC_REGCONST,
75109 				                (duk_regconst_t) declvar_flags /*flags*/,
75110 				                rc_name /*name*/,
75111 				                0 /*value*/);
75112 			}
75113 
75114 			duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);  /* [ ... name reg/null ] -> [ ... ] */
75115 		}
75116 	}
75117 
75118 	/*
75119 	 *  Wrap up
75120 	 */
75121 
75122 	DUK_DDD(DUK_DDDPRINT("varmap: %!T, is_arguments_shadowed=%ld",
75123 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx),
75124 	                     (long) comp_ctx->curr_func.is_arguments_shadowed));
75125 
75126 	DUK_ASSERT_TOP(thr, entry_top);
75127 	return;
75128 
75129  error_outofregs:
75130 	DUK_ERROR_RANGE(thr, DUK_STR_REG_LIMIT);
75131 	DUK_WO_NORETURN(return;);
75132 
75133  error_argname:
75134 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARG_NAME);
75135 	DUK_WO_NORETURN(return;);
75136 }
75137 
75138 /*
75139  *  Parse a function-body-like expression (FunctionBody or Program
75140  *  in E5 grammar) using a two-pass parse.  The productions appear
75141  *  in the following contexts:
75142  *
75143  *    - function expression
75144  *    - function statement
75145  *    - function declaration
75146  *    - getter in object literal
75147  *    - setter in object literal
75148  *    - global code
75149  *    - eval code
75150  *    - Function constructor body
75151  *
75152  *  This function only parses the statement list of the body; the argument
75153  *  list and possible function name must be initialized by the caller.
75154  *  For instance, for Function constructor, the argument names are originally
75155  *  on the value stack.  The parsing of statements ends either at an EOF or
75156  *  a closing brace; this is controlled by an input flag.
75157  *
75158  *  Note that there are many differences affecting parsing and even code
75159  *  generation:
75160  *
75161  *    - Global and eval code have an implicit return value generated
75162  *      by the last statement; function code does not
75163  *
75164  *    - Global code, eval code, and Function constructor body end in
75165  *      an EOF, other bodies in a closing brace ('}')
75166  *
75167  *  Upon entry, 'curr_tok' is ignored and the function will pull in the
75168  *  first token on its own.  Upon exit, 'curr_tok' is the terminating
75169  *  token (EOF or closing brace).
75170  */
75171 
75172 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) {
75173 	duk_compiler_func *func;
75174 	duk_hthread *thr;
75175 	duk_regconst_t reg_stmt_value = -1;
75176 	duk_lexer_point lex_pt;
75177 	duk_regconst_t temp_first;
75178 	duk_small_int_t compile_round = 1;
75179 
75180 	DUK_ASSERT(comp_ctx != NULL);
75181 
75182 	thr = comp_ctx->thr;
75183 	DUK_ASSERT(thr != NULL);
75184 
75185 	func = &comp_ctx->curr_func;
75186 	DUK_ASSERT(func != NULL);
75187 
75188 	DUK__RECURSION_INCREASE(comp_ctx, thr);
75189 
75190 	duk_require_stack(thr, DUK__FUNCTION_BODY_REQUIRE_SLOTS);
75191 
75192 	/*
75193 	 *  Store lexer position for a later rewind
75194 	 */
75195 
75196 	DUK_LEXER_GETPOINT(&comp_ctx->lex, &lex_pt);
75197 
75198 	/*
75199 	 *  Program code (global and eval code) has an implicit return value
75200 	 *  from the last statement value (e.g. eval("1; 2+3;") returns 3).
75201 	 *  This is not the case with functions.  If implicit statement return
75202 	 *  value is requested, all statements are coerced to a register
75203 	 *  allocated here, and used in the implicit return statement below.
75204 	 */
75205 
75206 	/* XXX: this is pointless here because pass 1 is throw-away */
75207 	if (implicit_return_value) {
75208 		reg_stmt_value = DUK__ALLOCTEMP(comp_ctx);
75209 
75210 		/* If an implicit return value is needed by caller, it must be
75211 		 * initialized to 'undefined' because we don't know whether any
75212 		 * non-empty (where "empty" is a continuation type, and different
75213 		 * from an empty statement) statements will be executed.
75214 		 *
75215 		 * However, since 1st pass is a throwaway one, no need to emit
75216 		 * it here.
75217 		 */
75218 #if 0
75219 		duk__emit_bc(comp_ctx,
75220 		             DUK_OP_LDUNDEF,
75221 		             0);
75222 #endif
75223 	}
75224 
75225 	/*
75226 	 *  First pass.
75227 	 *
75228 	 *  Gather variable/function declarations needed for second pass.
75229 	 *  Code generated is dummy and discarded.
75230 	 */
75231 
75232 	func->in_directive_prologue = 1;
75233 	func->in_scanning = 1;
75234 	func->may_direct_eval = 0;
75235 	func->id_access_arguments = 0;
75236 	func->id_access_slow = 0;
75237 	func->id_access_slow_own = 0;
75238 	func->reg_stmt_value = reg_stmt_value;
75239 #if defined(DUK_USE_DEBUGGER_SUPPORT)
75240 	func->min_line = DUK_INT_MAX;
75241 	func->max_line = 0;
75242 #endif
75243 
75244 	/* duk__parse_stmts() expects curr_tok to be set; parse in "allow
75245 	 * regexp literal" mode with current strictness.
75246 	 */
75247 	if (expect_token >= 0) {
75248 		/* Eating a left curly; regexp mode is allowed by left curly
75249 		 * based on duk__token_lbp[] automatically.
75250 		 */
75251 		DUK_ASSERT(expect_token == DUK_TOK_LCURLY);
75252 		duk__update_lineinfo_currtoken(comp_ctx);
75253 		duk__advance_expect(comp_ctx, expect_token);
75254 	} else {
75255 		/* Need to set curr_token.t because lexing regexp mode depends on current
75256 		 * token type.  Zero value causes "allow regexp" mode.
75257 		 */
75258 		comp_ctx->curr_token.t = 0;
75259 		duk__advance(comp_ctx);
75260 	}
75261 
75262 	DUK_DDD(DUK_DDDPRINT("begin 1st pass"));
75263 	duk__parse_stmts(comp_ctx,
75264 	                 1,             /* allow source elements */
75265 	                 expect_eof,    /* expect EOF instead of } */
75266 	                 regexp_after); /* regexp after */
75267 	DUK_DDD(DUK_DDDPRINT("end 1st pass"));
75268 
75269 	/*
75270 	 *  Second (and possibly third) pass.
75271 	 *
75272 	 *  Generate actual code.  In most cases the need for shuffle
75273 	 *  registers is detected during pass 1, but in some corner cases
75274 	 *  we'll only detect it during pass 2 and a third pass is then
75275 	 *  needed (see GH-115).
75276 	 */
75277 
75278 	for (;;) {
75279 		duk_bool_t needs_shuffle_before = comp_ctx->curr_func.needs_shuffle;
75280 		compile_round++;
75281 
75282 		/*
75283 		 *  Rewind lexer.
75284 		 *
75285 		 *  duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp
75286 		 *  literal" mode with current strictness.
75287 		 *
75288 		 *  curr_token line number info should be initialized for pass 2 before
75289 		 *  generating prologue, to ensure prologue bytecode gets nice line numbers.
75290 		 */
75291 
75292 		DUK_DDD(DUK_DDDPRINT("rewind lexer"));
75293 		DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
75294 		comp_ctx->curr_token.t = 0;  /* this is needed for regexp mode */
75295 		comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
75296 		duk__advance(comp_ctx);
75297 
75298 		/*
75299 		 *  Reset function state and perform register allocation, which creates
75300 		 *  'varmap' for second pass.  Function prologue for variable declarations,
75301 		 *  binding value initializations etc is emitted as a by-product.
75302 		 *
75303 		 *  Strict mode restrictions for duplicate and invalid argument
75304 		 *  names are checked here now that we know whether the function
75305 		 *  is actually strict.  See: test-dev-strict-mode-boundary.js.
75306 		 *
75307 		 *  Inner functions are compiled during pass 1 and are not reset.
75308 		 */
75309 
75310 		duk__reset_func_for_pass2(comp_ctx);
75311 		func->in_directive_prologue = 1;
75312 		func->in_scanning = 0;
75313 
75314 		/* must be able to emit code, alloc consts, etc. */
75315 
75316 		duk__init_varmap_and_prologue_for_pass2(comp_ctx,
75317 		                                        (implicit_return_value ? &reg_stmt_value : NULL));
75318 		func->reg_stmt_value = reg_stmt_value;
75319 
75320 		temp_first = DUK__GETTEMP(comp_ctx);
75321 
75322 		func->temp_first = temp_first;
75323 		func->temp_next = temp_first;
75324 		func->stmt_next = 0;
75325 		func->label_next = 0;
75326 
75327 		/* XXX: init or assert catch depth etc -- all values */
75328 		func->id_access_arguments = 0;
75329 		func->id_access_slow = 0;
75330 		func->id_access_slow_own = 0;
75331 
75332 		/*
75333 		 *  Check function name validity now that we know strictness.
75334 		 *  This only applies to function declarations and expressions,
75335 		 *  not setter/getter name.
75336 		 *
75337 		 *  See: test-dev-strict-mode-boundary.js
75338 		 */
75339 
75340 		if (func->is_function && !func->is_setget && func->h_name != NULL) {
75341 			if (func->is_strict) {
75342 				if (duk__hstring_is_eval_or_arguments(comp_ctx, func->h_name)) {
75343 					DUK_DDD(DUK_DDDPRINT("func name is 'eval' or 'arguments' in strict mode"));
75344 					goto error_funcname;
75345 				}
75346 				if (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {
75347 					DUK_DDD(DUK_DDDPRINT("func name is a reserved word in strict mode"));
75348 					goto error_funcname;
75349 				}
75350 			} else {
75351 				if (DUK_HSTRING_HAS_RESERVED_WORD(func->h_name) &&
75352 				    !DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {
75353 					DUK_DDD(DUK_DDDPRINT("func name is a reserved word in non-strict mode"));
75354 					goto error_funcname;
75355 				}
75356 			}
75357 		}
75358 
75359 		/*
75360 		 *  Second pass parsing.
75361 		 */
75362 
75363 		if (implicit_return_value) {
75364 			/* Default implicit return value. */
75365 			duk__emit_bc(comp_ctx,
75366 			             DUK_OP_LDUNDEF,
75367 			             0);
75368 		}
75369 
75370 		DUK_DDD(DUK_DDDPRINT("begin 2nd pass"));
75371 		duk__parse_stmts(comp_ctx,
75372 		                 1,             /* allow source elements */
75373 		                 expect_eof,    /* expect EOF instead of } */
75374 		                 regexp_after); /* regexp after */
75375 		DUK_DDD(DUK_DDDPRINT("end 2nd pass"));
75376 
75377 		duk__update_lineinfo_currtoken(comp_ctx);
75378 
75379 		if (needs_shuffle_before == comp_ctx->curr_func.needs_shuffle) {
75380 			/* Shuffle decision not changed. */
75381 			break;
75382 		}
75383 		if (compile_round >= 3) {
75384 			/* Should never happen but avoid infinite loop just in case. */
75385 			DUK_D(DUK_DPRINT("more than 3 compile passes needed, should never happen"));
75386 			DUK_ERROR_INTERNAL(thr);
75387 			DUK_WO_NORETURN(return;);
75388 		}
75389 		DUK_D(DUK_DPRINT("need additional round to compile function, round now %d", (int) compile_round));
75390 	}
75391 
75392 	/*
75393 	 *  Emit a final RETURN.
75394 	 *
75395 	 *  It would be nice to avoid emitting an unnecessary "return" opcode
75396 	 *  if the current PC is not reachable.  However, this cannot be reliably
75397 	 *  detected; even if the previous instruction is an unconditional jump,
75398 	 *  there may be a previous jump which jumps to current PC (which is the
75399 	 *  case for iteration and conditional statements, for instance).
75400 	 */
75401 
75402 	/* XXX: request a "last statement is terminal" from duk__parse_stmt() and duk__parse_stmts();
75403 	 * we could avoid the last RETURN if we could ensure there is no way to get here
75404 	 * (directly or via a jump)
75405 	 */
75406 
75407 	DUK_ASSERT(comp_ctx->curr_func.catch_depth == 0);
75408 	if (reg_stmt_value >= 0) {
75409 		DUK_ASSERT(DUK__ISREG(reg_stmt_value));
75410 		duk__emit_bc(comp_ctx, DUK_OP_RETREG, reg_stmt_value /*reg*/);
75411 	} else {
75412 		duk__emit_op_only(comp_ctx, DUK_OP_RETUNDEF);
75413 	}
75414 
75415 	/*
75416 	 *  Peephole optimize JUMP chains.
75417 	 */
75418 
75419 	duk__peephole_optimize_bytecode(comp_ctx);
75420 
75421 	/*
75422 	 *  comp_ctx->curr_func is now ready to be converted into an actual
75423 	 *  function template.
75424 	 */
75425 
75426 	DUK__RECURSION_DECREASE(comp_ctx, thr);
75427 	return;
75428 
75429  error_funcname:
75430 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FUNC_NAME);
75431 	DUK_WO_NORETURN(return;);
75432 }
75433 
75434 /*
75435  *  Parse a function-like expression:
75436  *
75437  *    - function expression
75438  *    - function declaration
75439  *    - function statement (non-standard)
75440  *    - setter/getter
75441  *
75442  *  Adds the function to comp_ctx->curr_func function table and returns the
75443  *  function number.
75444  *
75445  *  On entry, curr_token points to:
75446  *
75447  *    - the token after 'function' for function expression/declaration/statement
75448  *    - the token after 'set' or 'get' for setter/getter
75449  */
75450 
75451 /* Parse formals. */
75452 DUK_LOCAL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx) {
75453 	duk_hthread *thr = comp_ctx->thr;
75454 	duk_bool_t first = 1;
75455 	duk_uarridx_t n;
75456 
75457 	for (;;) {
75458 		if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
75459 			break;
75460 		}
75461 
75462 		if (first) {
75463 			/* no comma */
75464 			first = 0;
75465 		} else {
75466 			duk__advance_expect(comp_ctx, DUK_TOK_COMMA);
75467 		}
75468 
75469 		/* Note: when parsing a formal list in non-strict context, e.g.
75470 		 * "implements" is parsed as an identifier.  When the function is
75471 		 * later detected to be strict, the argument list must be rechecked
75472 		 * against a larger set of reserved words (that of strict mode).
75473 		 * This is handled by duk__parse_func_body().  Here we recognize
75474 		 * whatever tokens are considered reserved in current strictness
75475 		 * (which is not always enough).
75476 		 */
75477 
75478 		if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
75479 			DUK_ERROR_SYNTAX(thr, DUK_STR_EXPECTED_IDENTIFIER);
75480 			DUK_WO_NORETURN(return;);
75481 		}
75482 		DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER);
75483 		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
75484 		DUK_DDD(DUK_DDDPRINT("formal argument: %!O",
75485 		                     (duk_heaphdr *) comp_ctx->curr_token.str1));
75486 
75487 		/* XXX: append primitive */
75488 		duk_push_hstring(thr, comp_ctx->curr_token.str1);
75489 		n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.argnames_idx);
75490 		duk_put_prop_index(thr, comp_ctx->curr_func.argnames_idx, n);
75491 
75492 		duk__advance(comp_ctx);  /* eat identifier */
75493 	}
75494 }
75495 
75496 /* Parse a function-like expression, assuming that 'comp_ctx->curr_func' is
75497  * correctly set up.  Assumes that curr_token is just after 'function' (or
75498  * 'set'/'get' etc).
75499  */
75500 DUK_LOCAL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags) {
75501 	duk_hthread *thr = comp_ctx->thr;
75502 	duk_token *tok;
75503 	duk_bool_t no_advance;
75504 
75505 	DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
75506 	DUK_ASSERT(comp_ctx->curr_func.is_function == 1);
75507 	DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
75508 	DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
75509 	DUK_ASSERT(comp_ctx->curr_func.is_setget == ((flags & DUK__FUNC_FLAG_GETSET) != 0));
75510 
75511 	duk__update_lineinfo_currtoken(comp_ctx);
75512 
75513 	/*
75514 	 *  Function name (if any)
75515 	 *
75516 	 *  We don't check for prohibited names here, because we don't
75517 	 *  yet know whether the function will be strict.  Function body
75518 	 *  parsing handles this retroactively.
75519 	 *
75520 	 *  For function expressions and declarations function name must
75521 	 *  be an Identifer (excludes reserved words).  For setter/getter
75522 	 *  it is a PropertyName which allows reserved words and also
75523 	 *  strings and numbers (e.g. "{ get 1() { ... } }").
75524 	 *
75525 	 *  Function parsing may start either from prev_token or curr_token
75526 	 *  (object literal method definition uses prev_token for example).
75527 	 *  This is dealt with for the initial token.
75528 	 */
75529 
75530 	no_advance = (flags & DUK__FUNC_FLAG_USE_PREVTOKEN);
75531 	if (no_advance) {
75532 		tok = &comp_ctx->prev_token;
75533 	} else {
75534 		tok = &comp_ctx->curr_token;
75535 	}
75536 
75537 	if (flags & DUK__FUNC_FLAG_GETSET) {
75538 		/* PropertyName -> IdentifierName | StringLiteral | NumericLiteral */
75539 		if (tok->t_nores == DUK_TOK_IDENTIFIER || tok->t == DUK_TOK_STRING) {
75540 			duk_push_hstring(thr, tok->str1);       /* keep in valstack */
75541 		} else if (tok->t == DUK_TOK_NUMBER) {
75542 			duk_push_number(thr, tok->num);
75543 			duk_to_string(thr, -1);
75544 		} else {
75545 			DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_GETSET_NAME);
75546 			DUK_WO_NORETURN(return;);
75547 		}
75548 		comp_ctx->curr_func.h_name = duk_known_hstring(thr, -1);  /* borrowed reference */
75549 	} else {
75550 		/* Function name is an Identifier (not IdentifierName), but we get
75551 		 * the raw name (not recognizing keywords) here and perform the name
75552 		 * checks only after pass 1.
75553 		 */
75554 		if (tok->t_nores == DUK_TOK_IDENTIFIER) {
75555 			duk_push_hstring(thr, tok->str1);       /* keep in valstack */
75556 			comp_ctx->curr_func.h_name = duk_known_hstring(thr, -1);  /* borrowed reference */
75557 		} else {
75558 			/* valstack will be unbalanced, which is OK */
75559 			DUK_ASSERT((flags & DUK__FUNC_FLAG_GETSET) == 0);
75560 			DUK_ASSERT(comp_ctx->curr_func.h_name == NULL);
75561 			no_advance = 1;
75562 			if (flags & DUK__FUNC_FLAG_DECL) {
75563 				DUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_NAME_REQUIRED);
75564 				DUK_WO_NORETURN(return;);
75565 			}
75566 		}
75567 	}
75568 
75569 	DUK_DD(DUK_DDPRINT("function name: %!O",
75570 	                   (duk_heaphdr *) comp_ctx->curr_func.h_name));
75571 
75572 	if (!no_advance) {
75573 		duk__advance(comp_ctx);
75574 	}
75575 
75576 	/*
75577 	 *  Formal argument list
75578 	 *
75579 	 *  We don't check for prohibited names or for duplicate argument
75580 	 *  names here, becase we don't yet know whether the function will
75581 	 *  be strict.  Function body parsing handles this retroactively.
75582 	 */
75583 
75584 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
75585 
75586 	duk__parse_func_formals(comp_ctx);
75587 
75588 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RPAREN);
75589 	duk__advance(comp_ctx);
75590 
75591 	/*
75592 	 *  Parse function body
75593 	 */
75594 
75595 	duk__parse_func_body(comp_ctx,
75596 	                     0,   /* expect_eof */
75597 	                     0,   /* implicit_return_value */
75598 	                     flags & DUK__FUNC_FLAG_DECL, /* regexp_after */
75599 	                     DUK_TOK_LCURLY);  /* expect_token */
75600 
75601 	/*
75602 	 *  Convert duk_compiler_func to a function template and add it
75603 	 *  to the parent function table.
75604 	 */
75605 
75606 	duk__convert_to_func_template(comp_ctx);  /* -> [ ... func ] */
75607 }
75608 
75609 /* Parse an inner function, adding the function template to the current function's
75610  * function table.  Return a function number to be used by the outer function.
75611  *
75612  * Avoiding O(depth^2) inner function parsing is handled here.  On the first pass,
75613  * compile and register the function normally into the 'funcs' array, also recording
75614  * a lexer point (offset/line) to the closing brace of the function.  On the second
75615  * pass, skip the function and return the same 'fnum' as on the first pass by using
75616  * a running counter.
75617  *
75618  * An unfortunate side effect of this is that when parsing the inner function, almost
75619  * nothing is known of the outer function, i.e. the inner function's scope.  We don't
75620  * need that information at the moment, but it would allow some optimizations if it
75621  * were used.
75622  */
75623 DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags) {
75624 	duk_hthread *thr = comp_ctx->thr;
75625 	duk_compiler_func old_func;
75626 	duk_idx_t entry_top;
75627 	duk_int_t fnum;
75628 
75629 	/*
75630 	 *  On second pass, skip the function.
75631 	 */
75632 
75633 	if (!comp_ctx->curr_func.in_scanning) {
75634 		duk_lexer_point lex_pt;
75635 
75636 		fnum = comp_ctx->curr_func.fnum_next++;
75637 		duk_get_prop_index(thr, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
75638 		lex_pt.offset = (duk_size_t) duk_to_uint(thr, -1);
75639 		duk_pop(thr);
75640 		duk_get_prop_index(thr, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
75641 		lex_pt.line = duk_to_int(thr, -1);
75642 		duk_pop(thr);
75643 
75644 		DUK_DDD(DUK_DDDPRINT("second pass of an inner func, skip the function, reparse closing brace; lex offset=%ld, line=%ld",
75645 		                     (long) lex_pt.offset, (long) lex_pt.line));
75646 
75647 		DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
75648 		comp_ctx->curr_token.t = 0;  /* this is needed for regexp mode */
75649 		comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
75650 		duk__advance(comp_ctx);
75651 
75652 		/* RegExp is not allowed after a function expression, e.g. in
75653 		 * (function () {} / 123).  A RegExp *is* allowed after a
75654 		 * function declaration!
75655 		 */
75656 		if (flags & DUK__FUNC_FLAG_DECL) {
75657 			comp_ctx->curr_func.allow_regexp_in_adv = 1;
75658 		}
75659 		duk__advance_expect(comp_ctx, DUK_TOK_RCURLY);
75660 
75661 		return fnum;
75662 	}
75663 
75664 	/*
75665 	 *  On first pass, perform actual parsing.  Remember valstack top on entry
75666 	 *  to restore it later, and switch to using a new function in comp_ctx.
75667 	 */
75668 
75669 	entry_top = duk_get_top(thr);
75670 	DUK_DDD(DUK_DDDPRINT("before func: entry_top=%ld, curr_tok.start_offset=%ld",
75671 	                     (long) entry_top, (long) comp_ctx->curr_token.start_offset));
75672 
75673 	duk_memcpy(&old_func, &comp_ctx->curr_func, sizeof(duk_compiler_func));
75674 
75675 	duk_memzero(&comp_ctx->curr_func, sizeof(duk_compiler_func));
75676 	duk__init_func_valstack_slots(comp_ctx);
75677 	DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
75678 
75679 	/* inherit initial strictness from parent */
75680 	comp_ctx->curr_func.is_strict = old_func.is_strict;
75681 
75682 	/* XXX: It might be better to just store the flags into the curr_func
75683 	 * struct and use them as is without this flag interpretation step
75684 	 * here.
75685 	 */
75686 	DUK_ASSERT(comp_ctx->curr_func.is_notail == 0);
75687 	comp_ctx->curr_func.is_function = 1;
75688 	DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
75689 	DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
75690 	comp_ctx->curr_func.is_setget = ((flags & DUK__FUNC_FLAG_GETSET) != 0);
75691 	comp_ctx->curr_func.is_namebinding = !(flags & (DUK__FUNC_FLAG_GETSET |
75692 	                                                DUK__FUNC_FLAG_METDEF |
75693 	                                                DUK__FUNC_FLAG_DECL));  /* no name binding for: declarations, objlit getset, objlit method def */
75694 	comp_ctx->curr_func.is_constructable = !(flags & (DUK__FUNC_FLAG_GETSET |
75695 	                                                  DUK__FUNC_FLAG_METDEF));  /* not constructable: objlit getset, objlit method def */
75696 
75697 	/*
75698 	 *  Parse inner function
75699 	 */
75700 
75701 	duk__parse_func_like_raw(comp_ctx, flags);  /* pushes function template */
75702 
75703 	/* prev_token.start_offset points to the closing brace here; when skipping
75704 	 * we're going to reparse the closing brace to ensure semicolon insertion
75705 	 * etc work as expected.
75706 	 */
75707 	DUK_DDD(DUK_DDDPRINT("after func: prev_tok.start_offset=%ld, curr_tok.start_offset=%ld",
75708 	                     (long) comp_ctx->prev_token.start_offset, (long) comp_ctx->curr_token.start_offset));
75709 	DUK_ASSERT(comp_ctx->lex.input[comp_ctx->prev_token.start_offset] == (duk_uint8_t) DUK_ASC_RCURLY);
75710 
75711 	/* XXX: append primitive */
75712 	DUK_ASSERT(duk_get_length(thr, old_func.funcs_idx) == (duk_size_t) (old_func.fnum_next * 3));
75713 	fnum = old_func.fnum_next++;
75714 
75715 	if (fnum > DUK__MAX_FUNCS) {
75716 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_FUNC_LIMIT);
75717 		DUK_WO_NORETURN(return 0;);
75718 	}
75719 
75720 	/* array writes autoincrement length */
75721 	(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3));
75722 	duk_push_size_t(thr, comp_ctx->prev_token.start_offset);
75723 	(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
75724 	duk_push_int(thr, comp_ctx->prev_token.start_line);
75725 	(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
75726 
75727 	/*
75728 	 *  Cleanup: restore original function, restore valstack state.
75729 	 *
75730 	 *  Function declaration handling needs the function name to be pushed
75731 	 *  on the value stack.
75732 	 */
75733 
75734 	if (flags & DUK__FUNC_FLAG_PUSHNAME_PASS1) {
75735 		DUK_ASSERT(comp_ctx->curr_func.h_name != NULL);
75736 		duk_push_hstring(thr, comp_ctx->curr_func.h_name);
75737 		duk_replace(thr, entry_top);
75738 		duk_set_top(thr, entry_top + 1);
75739 	} else {
75740 		duk_set_top(thr, entry_top);
75741 	}
75742 	duk_memcpy((void *) &comp_ctx->curr_func, (void *) &old_func, sizeof(duk_compiler_func));
75743 
75744 	return fnum;
75745 }
75746 
75747 /*
75748  *  Compile input string into an executable function template without
75749  *  arguments.
75750  *
75751  *  The string is parsed as the "Program" production of ECMAScript E5.
75752  *  Compilation context can be either global code or eval code (see E5
75753  *  Sections 14 and 15.1.2.1).
75754  *
75755  *  Input stack:  [ ... filename ]
75756  *  Output stack: [ ... func_template ]
75757  */
75758 
75759 /* XXX: source code property */
75760 
75761 DUK_LOCAL duk_ret_t duk__js_compile_raw(duk_hthread *thr, void *udata) {
75762 	duk_hstring *h_filename;
75763 	duk__compiler_stkstate *comp_stk;
75764 	duk_compiler_ctx *comp_ctx;
75765 	duk_lexer_point *lex_pt;
75766 	duk_compiler_func *func;
75767 	duk_idx_t entry_top;
75768 	duk_bool_t is_strict;
75769 	duk_bool_t is_eval;
75770 	duk_bool_t is_funcexpr;
75771 	duk_small_uint_t flags;
75772 
75773 	DUK_ASSERT(thr != NULL);
75774 	DUK_ASSERT(udata != NULL);
75775 
75776 	/*
75777 	 *  Arguments check
75778 	 */
75779 
75780 	entry_top = duk_get_top(thr);
75781 	DUK_ASSERT(entry_top >= 1);
75782 
75783 	comp_stk = (duk__compiler_stkstate *) udata;
75784 	comp_ctx = &comp_stk->comp_ctx_alloc;
75785 	lex_pt = &comp_stk->lex_pt_alloc;
75786 	DUK_ASSERT(comp_ctx != NULL);
75787 	DUK_ASSERT(lex_pt != NULL);
75788 
75789 	flags = comp_stk->flags;
75790 	is_eval = (flags & DUK_COMPILE_EVAL ? 1 : 0);
75791 	is_strict = (flags & DUK_COMPILE_STRICT ? 1 : 0);
75792 	is_funcexpr = (flags & DUK_COMPILE_FUNCEXPR ? 1 : 0);
75793 
75794 	h_filename = duk_get_hstring(thr, -1);  /* may be undefined */
75795 
75796 	/*
75797 	 *  Init compiler and lexer contexts
75798 	 */
75799 
75800 	func = &comp_ctx->curr_func;
75801 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
75802 	comp_ctx->thr = NULL;
75803 	comp_ctx->h_filename = NULL;
75804 	comp_ctx->prev_token.str1 = NULL;
75805 	comp_ctx->prev_token.str2 = NULL;
75806 	comp_ctx->curr_token.str1 = NULL;
75807 	comp_ctx->curr_token.str2 = NULL;
75808 #endif
75809 
75810 	duk_require_stack(thr, DUK__COMPILE_ENTRY_SLOTS);
75811 
75812 	duk_push_dynamic_buffer(thr, 0);       /* entry_top + 0 */
75813 	duk_push_undefined(thr);               /* entry_top + 1 */
75814 	duk_push_undefined(thr);               /* entry_top + 2 */
75815 	duk_push_undefined(thr);               /* entry_top + 3 */
75816 	duk_push_undefined(thr);               /* entry_top + 4 */
75817 
75818 	comp_ctx->thr = thr;
75819 	comp_ctx->h_filename = h_filename;
75820 	comp_ctx->tok11_idx = entry_top + 1;
75821 	comp_ctx->tok12_idx = entry_top + 2;
75822 	comp_ctx->tok21_idx = entry_top + 3;
75823 	comp_ctx->tok22_idx = entry_top + 4;
75824 	comp_ctx->recursion_limit = DUK_USE_COMPILER_RECLIMIT;
75825 
75826 	/* comp_ctx->lex has been pre-initialized by caller: it has been
75827 	 * zeroed and input/input_length has been set.
75828 	 */
75829 	comp_ctx->lex.thr = thr;
75830 	/* comp_ctx->lex.input and comp_ctx->lex.input_length filled by caller */
75831 	comp_ctx->lex.slot1_idx = comp_ctx->tok11_idx;
75832 	comp_ctx->lex.slot2_idx = comp_ctx->tok12_idx;
75833 	comp_ctx->lex.buf_idx = entry_top + 0;
75834 	comp_ctx->lex.buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, entry_top + 0);
75835 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(comp_ctx->lex.buf) && !DUK_HBUFFER_HAS_EXTERNAL(comp_ctx->lex.buf));
75836 	comp_ctx->lex.token_limit = DUK_COMPILER_TOKEN_LIMIT;
75837 
75838 	lex_pt->offset = 0;
75839 	lex_pt->line = 1;
75840 	DUK_LEXER_SETPOINT(&comp_ctx->lex, lex_pt);    /* fills window */
75841 	comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
75842 
75843 	/*
75844 	 *  Initialize function state for a zero-argument function
75845 	 */
75846 
75847 	duk__init_func_valstack_slots(comp_ctx);
75848 	DUK_ASSERT(func->num_formals == 0);
75849 
75850 	if (is_funcexpr) {
75851 		/* Name will be filled from function expression, not by caller.
75852 		 * This case is used by Function constructor and duk_compile()
75853 		 * API with the DUK_COMPILE_FUNCTION option.
75854 		 */
75855 		DUK_ASSERT(func->h_name == NULL);
75856 	} else {
75857 		duk_push_hstring_stridx(thr, (is_eval ? DUK_STRIDX_EVAL :
75858 		                                        DUK_STRIDX_GLOBAL));
75859 		func->h_name = duk_get_hstring(thr, -1);
75860 	}
75861 
75862 	/*
75863 	 *  Parse a function body or a function-like expression, depending
75864 	 *  on flags.
75865 	 */
75866 
75867 	DUK_ASSERT(func->is_setget == 0);
75868 	func->is_strict = (duk_uint8_t) is_strict;
75869 	DUK_ASSERT(func->is_notail == 0);
75870 
75871 	if (is_funcexpr) {
75872 		func->is_function = 1;
75873 		DUK_ASSERT(func->is_eval == 0);
75874 		DUK_ASSERT(func->is_global == 0);
75875 		func->is_namebinding = 1;
75876 		func->is_constructable = 1;
75877 
75878 		duk__advance(comp_ctx);  /* init 'curr_token' */
75879 		duk__advance_expect(comp_ctx, DUK_TOK_FUNCTION);
75880 		(void) duk__parse_func_like_raw(comp_ctx, 0 /*flags*/);
75881 	} else {
75882 		DUK_ASSERT(func->is_function == 0);
75883 		DUK_ASSERT(is_eval == 0 || is_eval == 1);
75884 		func->is_eval = (duk_uint8_t) is_eval;
75885 		func->is_global = (duk_uint8_t) !is_eval;
75886 		DUK_ASSERT(func->is_namebinding == 0);
75887 		DUK_ASSERT(func->is_constructable == 0);
75888 
75889 		duk__parse_func_body(comp_ctx,
75890 		                     1,             /* expect_eof */
75891 		                     1,             /* implicit_return_value */
75892 		                     1,             /* regexp_after (does not matter) */
75893 		                     -1);           /* expect_token */
75894 	}
75895 
75896 	/*
75897 	 *  Convert duk_compiler_func to a function template
75898 	 */
75899 
75900 	duk__convert_to_func_template(comp_ctx);
75901 
75902 	/*
75903 	 *  Wrapping duk_safe_call() will mangle the stack, just return stack top
75904 	 */
75905 
75906 	/* [ ... filename (temps) func ] */
75907 
75908 	return 1;
75909 }
75910 
75911 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) {
75912 	duk__compiler_stkstate comp_stk;
75913 	duk_compiler_ctx *prev_ctx;
75914 	duk_ret_t safe_rc;
75915 
75916 	DUK_ASSERT(thr != NULL);
75917 	DUK_ASSERT(src_buffer != NULL);
75918 
75919 	/* preinitialize lexer state partially */
75920 	duk_memzero(&comp_stk, sizeof(comp_stk));
75921 	comp_stk.flags = flags;
75922 	DUK_LEXER_INITCTX(&comp_stk.comp_ctx_alloc.lex);
75923 	comp_stk.comp_ctx_alloc.lex.input = src_buffer;
75924 	comp_stk.comp_ctx_alloc.lex.input_length = src_length;
75925 	comp_stk.comp_ctx_alloc.lex.flags = flags;  /* Forward flags directly for now. */
75926 
75927 	/* [ ... filename ] */
75928 
75929 	prev_ctx = thr->compile_ctx;
75930 	thr->compile_ctx = &comp_stk.comp_ctx_alloc;  /* for duk_error_augment.c */
75931 	safe_rc = duk_safe_call(thr, duk__js_compile_raw, (void *) &comp_stk /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
75932 	thr->compile_ctx = prev_ctx;  /* must restore reliably before returning */
75933 
75934 	if (safe_rc != DUK_EXEC_SUCCESS) {
75935 		DUK_D(DUK_DPRINT("compilation failed: %!T", duk_get_tval(thr, -1)));
75936 		(void) duk_throw(thr);
75937 		DUK_WO_NORETURN(return;);
75938 	}
75939 
75940 	/* [ ... template ] */
75941 }
75942 
75943 /* automatic undefs */
75944 #undef DUK__ALLOCTEMP
75945 #undef DUK__ALLOCTEMPS
75946 #undef DUK__ALLOW_AUTO_SEMI_ALWAYS
75947 #undef DUK__BC_INITIAL_INSTS
75948 #undef DUK__BP_ADDITIVE
75949 #undef DUK__BP_ASSIGNMENT
75950 #undef DUK__BP_BAND
75951 #undef DUK__BP_BOR
75952 #undef DUK__BP_BXOR
75953 #undef DUK__BP_CALL
75954 #undef DUK__BP_CLOSING
75955 #undef DUK__BP_COMMA
75956 #undef DUK__BP_CONDITIONAL
75957 #undef DUK__BP_EOF
75958 #undef DUK__BP_EQUALITY
75959 #undef DUK__BP_EXPONENTIATION
75960 #undef DUK__BP_FOR_EXPR
75961 #undef DUK__BP_INVALID
75962 #undef DUK__BP_LAND
75963 #undef DUK__BP_LOR
75964 #undef DUK__BP_MEMBER
75965 #undef DUK__BP_MULTIPLICATIVE
75966 #undef DUK__BP_POSTFIX
75967 #undef DUK__BP_RELATIONAL
75968 #undef DUK__BP_SHIFT
75969 #undef DUK__COMPILE_ENTRY_SLOTS
75970 #undef DUK__CONST_MARKER
75971 #undef DUK__DUMP_ISPEC
75972 #undef DUK__DUMP_IVALUE
75973 #undef DUK__EMIT_FLAG_A_IS_SOURCE
75974 #undef DUK__EMIT_FLAG_BC_REGCONST
75975 #undef DUK__EMIT_FLAG_B_IS_TARGET
75976 #undef DUK__EMIT_FLAG_C_IS_TARGET
75977 #undef DUK__EMIT_FLAG_NO_SHUFFLE_A
75978 #undef DUK__EMIT_FLAG_NO_SHUFFLE_B
75979 #undef DUK__EMIT_FLAG_NO_SHUFFLE_C
75980 #undef DUK__EMIT_FLAG_RESERVE_JUMPSLOT
75981 #undef DUK__EXPR_FLAG_ALLOW_EMPTY
75982 #undef DUK__EXPR_FLAG_REJECT_IN
75983 #undef DUK__EXPR_FLAG_REQUIRE_INIT
75984 #undef DUK__EXPR_RBP_MASK
75985 #undef DUK__FUNCTION_BODY_REQUIRE_SLOTS
75986 #undef DUK__FUNCTION_INIT_REQUIRE_SLOTS
75987 #undef DUK__FUNC_FLAG_DECL
75988 #undef DUK__FUNC_FLAG_GETSET
75989 #undef DUK__FUNC_FLAG_METDEF
75990 #undef DUK__FUNC_FLAG_PUSHNAME_PASS1
75991 #undef DUK__FUNC_FLAG_USE_PREVTOKEN
75992 #undef DUK__GETCONST_MAX_CONSTS_CHECK
75993 #undef DUK__GETTEMP
75994 #undef DUK__HAS_TERM
75995 #undef DUK__HAS_VAL
75996 #undef DUK__ISCONST
75997 #undef DUK__ISREG
75998 #undef DUK__ISREG_NOTTEMP
75999 #undef DUK__ISREG_TEMP
76000 #undef DUK__IS_TERMINAL
76001 #undef DUK__IVAL_FLAG_ALLOW_CONST
76002 #undef DUK__IVAL_FLAG_REQUIRE_SHORT
76003 #undef DUK__IVAL_FLAG_REQUIRE_TEMP
76004 #undef DUK__MAX_ARRAY_INIT_VALUES
76005 #undef DUK__MAX_CONSTS
76006 #undef DUK__MAX_FUNCS
76007 #undef DUK__MAX_OBJECT_INIT_PAIRS
76008 #undef DUK__MAX_TEMPS
76009 #undef DUK__MK_LBP
76010 #undef DUK__MK_LBP_FLAGS
76011 #undef DUK__OBJ_LIT_KEY_GET
76012 #undef DUK__OBJ_LIT_KEY_PLAIN
76013 #undef DUK__OBJ_LIT_KEY_SET
76014 #undef DUK__PARSE_EXPR_SLOTS
76015 #undef DUK__PARSE_STATEMENTS_SLOTS
76016 #undef DUK__RECURSION_DECREASE
76017 #undef DUK__RECURSION_INCREASE
76018 #undef DUK__REMOVECONST
76019 #undef DUK__SETTEMP
76020 #undef DUK__SETTEMP_CHECKMAX
76021 #undef DUK__STILL_PROLOGUE
76022 #undef DUK__TOKEN_LBP_BP_MASK
76023 #undef DUK__TOKEN_LBP_FLAG_NO_REGEXP
76024 #undef DUK__TOKEN_LBP_FLAG_TERMINATES
76025 #undef DUK__TOKEN_LBP_FLAG_UNUSED
76026 #undef DUK__TOKEN_LBP_GET_BP
76027 #line 1 "duk_js_executor.c"
76028 /*
76029  *  ECMAScript bytecode executor.
76030  */
76031 
76032 /* #include duk_internal.h -> already included */
76033 
76034 /*
76035  *  Local declarations.
76036  */
76037 
76038 DUK_LOCAL_DECL void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_activation *entry_act);
76039 
76040 /*
76041  *  Misc helpers.
76042  */
76043 
76044 /* Replace value stack top to value at 'tv_ptr'.  Optimize for
76045  * performance by only applying the net refcount change.
76046  */
76047 #define DUK__REPLACE_TO_TVPTR(thr,tv_ptr) do { \
76048 		duk_hthread *duk__thr; \
76049 		duk_tval *duk__tvsrc; \
76050 		duk_tval *duk__tvdst; \
76051 		duk_tval duk__tvtmp; \
76052 		duk__thr = (thr); \
76053 		duk__tvsrc = DUK_GET_TVAL_NEGIDX(duk__thr, -1); \
76054 		duk__tvdst = (tv_ptr); \
76055 		DUK_TVAL_SET_TVAL(&duk__tvtmp, duk__tvdst); \
76056 		DUK_TVAL_SET_TVAL(duk__tvdst, duk__tvsrc); \
76057 		DUK_TVAL_SET_UNDEFINED(duk__tvsrc);  /* value stack init policy */ \
76058 		duk__thr->valstack_top = duk__tvsrc; \
76059 		DUK_TVAL_DECREF(duk__thr, &duk__tvtmp); \
76060 	} while (0)
76061 
76062 /* XXX: candidate of being an internal shared API call */
76063 #if 0  /* unused */
76064 DUK_LOCAL void duk__push_tvals_incref_only(duk_hthread *thr, duk_tval *tv_src, duk_small_uint_fast_t count) {
76065 	duk_tval *tv_dst;
76066 	duk_size_t copy_size;
76067 	duk_size_t i;
76068 
76069 	tv_dst = thr->valstack_top;
76070 	copy_size = sizeof(duk_tval) * count;
76071 	duk_memcpy((void *) tv_dst, (const void *) tv_src, copy_size);
76072 	for (i = 0; i < count; i++) {
76073 		DUK_TVAL_INCREF(thr, tv_dst);
76074 		tv_dst++;
76075 	}
76076 	thr->valstack_top = tv_dst;
76077 }
76078 #endif
76079 
76080 /*
76081  *  Arithmetic, binary, and logical helpers.
76082  *
76083  *  Note: there is no opcode for logical AND or logical OR; this is on
76084  *  purpose, because the evalution order semantics for them make such
76085  *  opcodes pretty pointless: short circuiting means they are most
76086  *  comfortably implemented as jumps.  However, a logical NOT opcode
76087  *  is useful.
76088  *
76089  *  Note: careful with duk_tval pointers here: they are potentially
76090  *  invalidated by any DECREF and almost any API call.  It's still
76091  *  preferable to work without making a copy but that's not always
76092  *  possible.
76093  */
76094 
76095 DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF duk_double_t duk__compute_mod(duk_double_t d1, duk_double_t d2) {
76096 	return (duk_double_t) duk_js_arith_mod((double) d1, (double) d2);
76097 }
76098 
76099 #if defined(DUK_USE_ES7_EXP_OPERATOR)
76100 DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF duk_double_t duk__compute_exp(duk_double_t d1, duk_double_t d2) {
76101 	return (duk_double_t) duk_js_arith_pow((double) d1, (double) d2);
76102 }
76103 #endif
76104 
76105 DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z) {
76106 	/*
76107 	 *  Addition operator is different from other arithmetic
76108 	 *  operations in that it also provides string concatenation.
76109 	 *  Hence it is implemented separately.
76110 	 *
76111 	 *  There is a fast path for number addition.  Other cases go
76112 	 *  through potentially multiple coercions as described in the
76113 	 *  E5 specification.  It may be possible to reduce the number
76114 	 *  of coercions, but this must be done carefully to preserve
76115 	 *  the exact semantics.
76116 	 *
76117 	 *  E5 Section 11.6.1.
76118 	 *
76119 	 *  Custom types also have special behavior implemented here.
76120 	 */
76121 
76122 	duk_double_union du;
76123 
76124 	DUK_ASSERT(thr != NULL);
76125 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
76126 	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
76127 	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
76128 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
76129 
76130 	/*
76131 	 *  Fast paths
76132 	 */
76133 
76134 #if defined(DUK_USE_FASTINT)
76135 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
76136 		duk_int64_t v1, v2, v3;
76137 		duk_int32_t v3_hi;
76138 		duk_tval *tv_z;
76139 
76140 		/* Input values are signed 48-bit so we can detect overflow
76141 		 * reliably from high bits or just a comparison.
76142 		 */
76143 
76144 		v1 = DUK_TVAL_GET_FASTINT(tv_x);
76145 		v2 = DUK_TVAL_GET_FASTINT(tv_y);
76146 		v3 = v1 + v2;
76147 		v3_hi = (duk_int32_t) (v3 >> 32);
76148 		if (DUK_LIKELY(v3_hi >= DUK_I64_CONSTANT(-0x8000) && v3_hi <= DUK_I64_CONSTANT(0x7fff))) {
76149 			tv_z = thr->valstack_bottom + idx_z;
76150 			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3);  /* side effects */
76151 			return;
76152 		} else {
76153 			/* overflow, fall through */
76154 			;
76155 		}
76156 	}
76157 #endif  /* DUK_USE_FASTINT */
76158 
76159 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
76160 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
76161 		duk_tval *tv_z;
76162 #endif
76163 
76164 		du.d = DUK_TVAL_GET_NUMBER(tv_x) + DUK_TVAL_GET_NUMBER(tv_y);
76165 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76166 		duk_push_number(thr, du.d);  /* will NaN normalize result */
76167 		duk_replace(thr, (duk_idx_t) idx_z);
76168 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76169 		DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
76170 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
76171 		tv_z = thr->valstack_bottom + idx_z;
76172 		DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d);  /* side effects */
76173 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76174 		return;
76175 	}
76176 
76177 	/*
76178 	 *  Slow path: potentially requires function calls for coercion
76179 	 */
76180 
76181 	duk_push_tval(thr, tv_x);
76182 	duk_push_tval(thr, tv_y);
76183 	duk_to_primitive(thr, -2, DUK_HINT_NONE);  /* side effects -> don't use tv_x, tv_y after */
76184 	duk_to_primitive(thr, -1, DUK_HINT_NONE);
76185 
76186 	/* Since Duktape 2.x plain buffers are treated like ArrayBuffer. */
76187 	if (duk_is_string(thr, -2) || duk_is_string(thr, -1)) {
76188 		/* Symbols shouldn't technically be handled here, but should
76189 		 * go into the default ToNumber() coercion path instead and
76190 		 * fail there with a TypeError.  However, there's a ToString()
76191 		 * in duk_concat_2() which also fails with TypeError so no
76192 		 * explicit check is needed.
76193 		 */
76194 		duk_concat_2(thr);  /* [... s1 s2] -> [... s1+s2] */
76195 	} else {
76196 		duk_double_t d1, d2;
76197 
76198 		d1 = duk_to_number_m2(thr);
76199 		d2 = duk_to_number_m1(thr);
76200 		DUK_ASSERT(duk_is_number(thr, -2));
76201 		DUK_ASSERT(duk_is_number(thr, -1));
76202 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d1);
76203 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d2);
76204 
76205 		du.d = d1 + d2;
76206 		duk_pop_2_unsafe(thr);
76207 		duk_push_number(thr, du.d);  /* will NaN normalize result */
76208 	}
76209 	duk_replace(thr, (duk_idx_t) idx_z);  /* side effects */
76210 }
76211 
76212 DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_arith_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_uint_fast_t idx_z, duk_small_uint_fast_t opcode) {
76213 	/*
76214 	 *  Arithmetic operations other than '+' have number-only semantics
76215 	 *  and are implemented here.  The separate switch-case here means a
76216 	 *  "double dispatch" of the arithmetic opcode, but saves code space.
76217 	 *
76218 	 *  E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
76219 	 */
76220 
76221 	duk_double_t d1, d2;
76222 	duk_double_union du;
76223 	duk_small_uint_fast_t opcode_shifted;
76224 #if defined(DUK_USE_FASTINT) || !defined(DUK_USE_EXEC_PREFER_SIZE)
76225 	duk_tval *tv_z;
76226 #endif
76227 
76228 	DUK_ASSERT(thr != NULL);
76229 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
76230 	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
76231 	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
76232 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
76233 
76234 	opcode_shifted = opcode >> 2;  /* Get base opcode without reg/const modifiers. */
76235 
76236 #if defined(DUK_USE_FASTINT)
76237 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
76238 		duk_int64_t v1, v2, v3;
76239 		duk_int32_t v3_hi;
76240 
76241 		v1 = DUK_TVAL_GET_FASTINT(tv_x);
76242 		v2 = DUK_TVAL_GET_FASTINT(tv_y);
76243 
76244 		switch (opcode_shifted) {
76245 		case DUK_OP_SUB >> 2: {
76246 			v3 = v1 - v2;
76247 			break;
76248 		}
76249 		case DUK_OP_MUL >> 2: {
76250 			/* Must ensure result is 64-bit (no overflow); a
76251 			 * simple and sufficient fast path is to allow only
76252 			 * 32-bit inputs.  Avoid zero inputs to avoid
76253 			 * negative zero issues (-1 * 0 = -0, for instance).
76254 			 */
76255 			if (v1 >= DUK_I64_CONSTANT(-0x80000000) && v1 <= DUK_I64_CONSTANT(0x7fffffff) && v1 != 0 &&
76256 			    v2 >= DUK_I64_CONSTANT(-0x80000000) && v2 <= DUK_I64_CONSTANT(0x7fffffff) && v2 != 0) {
76257 				v3 = v1 * v2;
76258 			} else {
76259 				goto skip_fastint;
76260 			}
76261 			break;
76262 		}
76263 		case DUK_OP_DIV >> 2: {
76264 			/* Don't allow a zero divisor.  Fast path check by
76265 			 * "verifying" with multiplication.  Also avoid zero
76266 			 * dividend to avoid negative zero issues (0 / -1 = -0
76267 			 * for instance).
76268 			 */
76269 			if (v1 == 0 || v2 == 0) {
76270 				goto skip_fastint;
76271 			}
76272 			v3 = v1 / v2;
76273 			if (v3 * v2 != v1) {
76274 				goto skip_fastint;
76275 			}
76276 			break;
76277 		}
76278 		case DUK_OP_MOD >> 2: {
76279 			/* Don't allow a zero divisor.  Restrict both v1 and
76280 			 * v2 to positive values to avoid compiler specific
76281 			 * behavior.
76282 			 */
76283 			if (v1 < 1 || v2 < 1) {
76284 				goto skip_fastint;
76285 			}
76286 			v3 = v1 % v2;
76287 			DUK_ASSERT(v3 >= 0);
76288 			DUK_ASSERT(v3 < v2);
76289 			DUK_ASSERT(v1 - (v1 / v2) * v2 == v3);
76290 			break;
76291 		}
76292 		default: {
76293 			/* Possible with DUK_OP_EXP. */
76294 			goto skip_fastint;
76295 		}
76296 		}
76297 
76298 		v3_hi = (duk_int32_t) (v3 >> 32);
76299 		if (DUK_LIKELY(v3_hi >= DUK_I64_CONSTANT(-0x8000) && v3_hi <= DUK_I64_CONSTANT(0x7fff))) {
76300 			tv_z = thr->valstack_bottom + idx_z;
76301 			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3);  /* side effects */
76302 			return;
76303 		}
76304 		/* fall through if overflow etc */
76305 	}
76306  skip_fastint:
76307 #endif  /* DUK_USE_FASTINT */
76308 
76309 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
76310 		/* fast path */
76311 		d1 = DUK_TVAL_GET_NUMBER(tv_x);
76312 		d2 = DUK_TVAL_GET_NUMBER(tv_y);
76313 	} else {
76314 		duk_push_tval(thr, tv_x);
76315 		duk_push_tval(thr, tv_y);
76316 		d1 = duk_to_number_m2(thr);  /* side effects */
76317 		d2 = duk_to_number_m1(thr);
76318 		DUK_ASSERT(duk_is_number(thr, -2));
76319 		DUK_ASSERT(duk_is_number(thr, -1));
76320 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d1);
76321 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d2);
76322 		duk_pop_2_unsafe(thr);
76323 	}
76324 
76325 	switch (opcode_shifted) {
76326 	case DUK_OP_SUB >> 2: {
76327 		du.d = d1 - d2;
76328 		break;
76329 	}
76330 	case DUK_OP_MUL >> 2: {
76331 		du.d = d1 * d2;
76332 		break;
76333 	}
76334 	case DUK_OP_DIV >> 2: {
76335 		/* Division-by-zero is undefined behavior, so
76336 		 * rely on a helper.
76337 		 */
76338 		du.d = duk_double_div(d1, d2);
76339 		break;
76340 	}
76341 	case DUK_OP_MOD >> 2: {
76342 		du.d = duk__compute_mod(d1, d2);
76343 		break;
76344 	}
76345 #if defined(DUK_USE_ES7_EXP_OPERATOR)
76346 	case DUK_OP_EXP >> 2: {
76347 		du.d = duk__compute_exp(d1, d2);
76348 		break;
76349 	}
76350 #endif
76351 	default: {
76352 		DUK_UNREACHABLE();
76353 		du.d = DUK_DOUBLE_NAN;  /* should not happen */
76354 		break;
76355 	}
76356 	}
76357 
76358 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76359 	duk_push_number(thr, du.d);  /* will NaN normalize result */
76360 	duk_replace(thr, (duk_idx_t) idx_z);
76361 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76362 	/* important to use normalized NaN with 8-byte tagged types */
76363 	DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
76364 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
76365 	tv_z = thr->valstack_bottom + idx_z;
76366 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d);  /* side effects */
76367 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76368 }
76369 
76370 DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_bitwise_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z, duk_small_uint_fast_t opcode) {
76371 	/*
76372 	 *  Binary bitwise operations use different coercions (ToInt32, ToUint32)
76373 	 *  depending on the operation.  We coerce the arguments first using
76374 	 *  ToInt32(), and then cast to an 32-bit value if necessary.  Note that
76375 	 *  such casts must be correct even if there is no native 32-bit type
76376 	 *  (e.g., duk_int32_t and duk_uint32_t are 64-bit).
76377 	 *
76378 	 *  E5 Sections 11.10, 11.7.1, 11.7.2, 11.7.3
76379 	 */
76380 
76381 	duk_int32_t i1, i2, i3;
76382 	duk_uint32_t u1, u2, u3;
76383 #if defined(DUK_USE_FASTINT)
76384 	duk_int64_t fi3;
76385 #else
76386 	duk_double_t d3;
76387 #endif
76388 	duk_small_uint_fast_t opcode_shifted;
76389 #if defined(DUK_USE_FASTINT) || !defined(DUK_USE_EXEC_PREFER_SIZE)
76390 	duk_tval *tv_z;
76391 #endif
76392 
76393 	DUK_ASSERT(thr != NULL);
76394 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
76395 	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
76396 	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
76397 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
76398 
76399 	opcode_shifted = opcode >> 2;  /* Get base opcode without reg/const modifiers. */
76400 
76401 #if defined(DUK_USE_FASTINT)
76402 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
76403 		i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_x);
76404 		i2 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_y);
76405 	}
76406 	else
76407 #endif  /* DUK_USE_FASTINT */
76408 	{
76409 		duk_push_tval(thr, tv_x);
76410 		duk_push_tval(thr, tv_y);
76411 		i1 = duk_to_int32(thr, -2);
76412 		i2 = duk_to_int32(thr, -1);
76413 		duk_pop_2_unsafe(thr);
76414 	}
76415 
76416 	switch (opcode_shifted) {
76417 	case DUK_OP_BAND >> 2: {
76418 		i3 = i1 & i2;
76419 		break;
76420 	}
76421 	case DUK_OP_BOR >> 2: {
76422 		i3 = i1 | i2;
76423 		break;
76424 	}
76425 	case DUK_OP_BXOR >> 2: {
76426 		i3 = i1 ^ i2;
76427 		break;
76428 	}
76429 	case DUK_OP_BASL >> 2: {
76430 		/* Signed shift, named "arithmetic" (asl) because the result
76431 		 * is signed, e.g. 4294967295 << 1 -> -2.  Note that result
76432 		 * must be masked.
76433 		 */
76434 
76435 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
76436 		i3 = (duk_int32_t) (((duk_uint32_t) i1) << (u2 & 0x1fUL));  /* E5 Section 11.7.1, steps 7 and 8 */
76437 		i3 = i3 & ((duk_int32_t) 0xffffffffUL);                     /* Note: left shift, should mask */
76438 		break;
76439 	}
76440 	case DUK_OP_BASR >> 2: {
76441 		/* signed shift */
76442 
76443 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
76444 		i3 = i1 >> (u2 & 0x1fUL);                      /* E5 Section 11.7.2, steps 7 and 8 */
76445 		break;
76446 	}
76447 	case DUK_OP_BLSR >> 2: {
76448 		/* unsigned shift */
76449 
76450 		u1 = ((duk_uint32_t) i1) & 0xffffffffUL;
76451 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
76452 
76453 		/* special result value handling */
76454 		u3 = u1 >> (u2 & 0x1fUL);     /* E5 Section 11.7.2, steps 7 and 8 */
76455 #if defined(DUK_USE_FASTINT)
76456 		fi3 = (duk_int64_t) u3;
76457 		goto fastint_result_set;
76458 #else
76459 		d3 = (duk_double_t) u3;
76460 		goto result_set;
76461 #endif
76462 	}
76463 	default: {
76464 		DUK_UNREACHABLE();
76465 		i3 = 0;  /* should not happen */
76466 		break;
76467 	}
76468 	}
76469 
76470 #if defined(DUK_USE_FASTINT)
76471 	/* Result is always fastint compatible. */
76472 	/* XXX: Set 32-bit result (but must then handle signed and
76473 	 * unsigned results separately).
76474 	 */
76475 	fi3 = (duk_int64_t) i3;
76476 
76477  fastint_result_set:
76478 	tv_z = thr->valstack_bottom + idx_z;
76479 	DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, fi3);  /* side effects */
76480 #else  /* DUK_USE_FASTINT */
76481 	d3 = (duk_double_t) i3;
76482 
76483  result_set:
76484 	DUK_ASSERT(!DUK_ISNAN(d3));            /* 'd3' is never NaN, so no need to normalize */
76485 	DUK_ASSERT_DOUBLE_IS_NORMALIZED(d3);   /* always normalized */
76486 
76487 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76488 	duk_push_number(thr, d3);  /* would NaN normalize result, but unnecessary */
76489 	duk_replace(thr, (duk_idx_t) idx_z);
76490 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76491 	tv_z = thr->valstack_bottom + idx_z;
76492 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, d3);  /* side effects */
76493 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76494 #endif  /* DUK_USE_FASTINT */
76495 }
76496 
76497 /* In-place unary operation. */
76498 DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_arith_unary_op(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst, duk_small_uint_fast_t opcode) {
76499 	/*
76500 	 *  Arithmetic operations other than '+' have number-only semantics
76501 	 *  and are implemented here.  The separate switch-case here means a
76502 	 *  "double dispatch" of the arithmetic opcode, but saves code space.
76503 	 *
76504 	 *  E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
76505 	 */
76506 
76507 	duk_tval *tv;
76508 	duk_double_t d1;
76509 	duk_double_union du;
76510 
76511 	DUK_ASSERT(thr != NULL);
76512 	DUK_ASSERT(opcode == DUK_OP_UNM || opcode == DUK_OP_UNP);
76513 	DUK_ASSERT_DISABLE(idx_src >= 0);
76514 	DUK_ASSERT_DISABLE(idx_dst >= 0);
76515 
76516 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);
76517 
76518 #if defined(DUK_USE_FASTINT)
76519 	if (DUK_TVAL_IS_FASTINT(tv)) {
76520 		duk_int64_t v1, v2;
76521 
76522 		v1 = DUK_TVAL_GET_FASTINT(tv);
76523 		if (opcode == DUK_OP_UNM) {
76524 			/* The smallest fastint is no longer 48-bit when
76525 			 * negated.  Positive zero becames negative zero
76526 			 * (cannot be represented) when negated.
76527 			 */
76528 			if (DUK_LIKELY(v1 != DUK_FASTINT_MIN && v1 != 0)) {
76529 				v2 = -v1;
76530 				tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
76531 				DUK_TVAL_SET_FASTINT_UPDREF(thr, tv, v2);
76532 				return;
76533 			}
76534 		} else {
76535 			/* ToNumber() for a fastint is a no-op. */
76536 			DUK_ASSERT(opcode == DUK_OP_UNP);
76537 			v2 = v1;
76538 			tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
76539 			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv, v2);
76540 			return;
76541 		}
76542 		/* fall through if overflow etc */
76543 	}
76544 #endif  /* DUK_USE_FASTINT */
76545 
76546 	if (DUK_TVAL_IS_NUMBER(tv)) {
76547 		d1 = DUK_TVAL_GET_NUMBER(tv);
76548 	} else {
76549 		d1 = duk_to_number_tval(thr, tv);  /* side effects */
76550 	}
76551 
76552 	if (opcode == DUK_OP_UNP) {
76553 		/* ToNumber() for a double is a no-op, but unary plus is
76554 		 * used to force a fastint check so do that here.
76555 		 */
76556 		du.d = d1;
76557 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
76558 #if defined(DUK_USE_FASTINT)
76559 		tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
76560 		DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF(thr, tv, du.d);  /* always 'fast', i.e. inlined */
76561 		return;
76562 #endif
76563 	} else {
76564 		DUK_ASSERT(opcode == DUK_OP_UNM);
76565 		du.d = -d1;
76566 		DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);  /* mandatory if du.d is a NaN */
76567 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
76568 	}
76569 
76570 	/* XXX: size optimize: push+replace? */
76571 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
76572 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, du.d);
76573 }
76574 
76575 DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_bitwise_not(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst) {
76576 	/*
76577 	 *  E5 Section 11.4.8
76578 	 */
76579 
76580 	duk_tval *tv;
76581 	duk_int32_t i1, i2;
76582 
76583 	DUK_ASSERT(thr != NULL);
76584 	DUK_ASSERT_DISABLE(idx_src >= 0);
76585 	DUK_ASSERT_DISABLE(idx_dst >= 0);
76586 	DUK_ASSERT((duk_uint_t) idx_src < (duk_uint_t) duk_get_top(thr));
76587 	DUK_ASSERT((duk_uint_t) idx_dst < (duk_uint_t) duk_get_top(thr));
76588 
76589 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);
76590 
76591 #if defined(DUK_USE_FASTINT)
76592 	if (DUK_TVAL_IS_FASTINT(tv)) {
76593 		i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv);
76594 	}
76595 	else
76596 #endif  /* DUK_USE_FASTINT */
76597 	{
76598 		duk_push_tval(thr, tv);
76599 		i1 = duk_to_int32(thr, -1);  /* side effects */
76600 		duk_pop_unsafe(thr);
76601 	}
76602 
76603 	/* Result is always fastint compatible. */
76604 	i2 = ~i1;
76605 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
76606 	DUK_TVAL_SET_I32_UPDREF(thr, tv, i2);  /* side effects */
76607 }
76608 
76609 DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_logical_not(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst) {
76610 	/*
76611 	 *  E5 Section 11.4.9
76612 	 */
76613 
76614 	duk_tval *tv;
76615 	duk_bool_t res;
76616 
76617 	DUK_ASSERT(thr != NULL);
76618 	DUK_ASSERT_DISABLE(idx_src >= 0);
76619 	DUK_ASSERT_DISABLE(idx_dst >= 0);
76620 	DUK_ASSERT((duk_uint_t) idx_src < (duk_uint_t) duk_get_top(thr));
76621 	DUK_ASSERT((duk_uint_t) idx_dst < (duk_uint_t) duk_get_top(thr));
76622 
76623 	/* ToBoolean() does not require any operations with side effects so
76624 	 * we can do it efficiently.  For footprint it would be better to use
76625 	 * duk_js_toboolean() and then push+replace to the result slot.
76626 	 */
76627 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);
76628 	res = duk_js_toboolean(tv);  /* does not modify 'tv' */
76629 	DUK_ASSERT(res == 0 || res == 1);
76630 	res ^= 1;
76631 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
76632 	/* XXX: size optimize: push+replace? */
76633 	DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, res);  /* side effects */
76634 }
76635 
76636 /* XXX: size optimized variant */
76637 DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__prepost_incdec_reg_helper(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_small_uint_t op) {
76638 	duk_double_t x, y, z;
76639 
76640 	/* Two lowest bits of opcode are used to distinguish
76641 	 * variants.  Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
76642 	 */
76643 	DUK_ASSERT((DUK_OP_PREINCR & 0x03) == 0x00);
76644 	DUK_ASSERT((DUK_OP_PREDECR & 0x03) == 0x01);
76645 	DUK_ASSERT((DUK_OP_POSTINCR & 0x03) == 0x02);
76646 	DUK_ASSERT((DUK_OP_POSTDECR & 0x03) == 0x03);
76647 
76648 #if defined(DUK_USE_FASTINT)
76649 	if (DUK_TVAL_IS_FASTINT(tv_src)) {
76650 		duk_int64_t x_fi, y_fi, z_fi;
76651 		x_fi = DUK_TVAL_GET_FASTINT(tv_src);
76652 		if (op & 0x01) {
76653 			if (DUK_UNLIKELY(x_fi == DUK_FASTINT_MIN)) {
76654 				goto skip_fastint;
76655 			}
76656 			y_fi = x_fi - 1;
76657 		} else {
76658 			if (DUK_UNLIKELY(x_fi == DUK_FASTINT_MAX)) {
76659 				goto skip_fastint;
76660 			}
76661 			y_fi = x_fi + 1;
76662 		}
76663 
76664 		DUK_TVAL_SET_FASTINT(tv_src, y_fi);  /* no need for refcount update */
76665 
76666 		z_fi = (op & 0x02) ? x_fi : y_fi;
76667 		DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_dst, z_fi);  /* side effects */
76668 		return;
76669 	}
76670  skip_fastint:
76671 #endif
76672 	if (DUK_TVAL_IS_NUMBER(tv_src)) {
76673 		/* Fast path for the case where the register
76674 		 * is a number (e.g. loop counter).
76675 		 */
76676 
76677 		x = DUK_TVAL_GET_NUMBER(tv_src);
76678 		if (op & 0x01) {
76679 			y = x - 1.0;
76680 		} else {
76681 			y = x + 1.0;
76682 		}
76683 
76684 		DUK_TVAL_SET_NUMBER(tv_src, y);  /* no need for refcount update */
76685 	} else {
76686 		/* Preserve duk_tval pointer(s) across a potential valstack
76687 		 * resize by converting them into offsets temporarily.
76688 		 */
76689 		duk_idx_t bc;
76690 		duk_size_t off_dst;
76691 
76692 		off_dst = (duk_size_t) ((duk_uint8_t *) tv_dst - (duk_uint8_t *) thr->valstack_bottom);
76693 		bc = (duk_idx_t) (tv_src - thr->valstack_bottom);  /* XXX: pass index explicitly? */
76694 		tv_src = NULL;  /* no longer referenced */
76695 
76696 		x = duk_to_number(thr, bc);
76697 		if (op & 0x01) {
76698 			y = x - 1.0;
76699 		} else {
76700 			y = x + 1.0;
76701 		}
76702 
76703 		duk_push_number(thr, y);
76704 		duk_replace(thr, bc);
76705 
76706 		tv_dst = (duk_tval *) (void *) (((duk_uint8_t *) thr->valstack_bottom) + off_dst);
76707 	}
76708 
76709 	z = (op & 0x02) ? x : y;
76710 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_dst, z);  /* side effects */
76711 }
76712 
76713 DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__prepost_incdec_var_helper(duk_hthread *thr, duk_small_uint_t idx_dst, duk_tval *tv_id, duk_small_uint_t op, duk_small_uint_t is_strict) {
76714 	duk_activation *act;
76715 	duk_double_t x, y;
76716 	duk_hstring *name;
76717 
76718 	/* XXX: The pre/post inc/dec for an identifier lookup is
76719 	 * missing the important fast path where the identifier
76720 	 * has a storage location e.g. in a scope object so that
76721 	 * it can be updated in-place.  In particular, the case
76722 	 * where the identifier has a storage location AND the
76723 	 * previous value is a number should be optimized because
76724 	 * it's side effect free.
76725 	 */
76726 
76727 	/* Two lowest bits of opcode are used to distinguish
76728 	 * variants.  Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
76729 	 */
76730 	DUK_ASSERT((DUK_OP_PREINCV & 0x03) == 0x00);
76731 	DUK_ASSERT((DUK_OP_PREDECV & 0x03) == 0x01);
76732 	DUK_ASSERT((DUK_OP_POSTINCV & 0x03) == 0x02);
76733 	DUK_ASSERT((DUK_OP_POSTDECV & 0x03) == 0x03);
76734 
76735 	DUK_ASSERT(DUK_TVAL_IS_STRING(tv_id));
76736 	name = DUK_TVAL_GET_STRING(tv_id);
76737 	DUK_ASSERT(name != NULL);
76738 	act = thr->callstack_curr;
76739 	(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [ ... val this ] */
76740 
76741 	/* XXX: Fastint fast path would be useful here.  Also fastints
76742 	 * now lose their fastint status in current handling which is
76743 	 * not intuitive.
76744 	 */
76745 
76746 	x = duk_to_number_m2(thr);
76747 	if (op & 0x01) {
76748 		y = x - 1.0;
76749 	} else {
76750 		y = x + 1.0;
76751 	}
76752 
76753 	/* [... x this] */
76754 
76755 	if (op & 0x02) {
76756 		duk_push_number(thr, y);  /* -> [ ... x this y ] */
76757 		DUK_ASSERT(act == thr->callstack_curr);
76758 		duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(thr, -1), is_strict);
76759 		duk_pop_2_unsafe(thr);  /* -> [ ... x ] */
76760 	} else {
76761 		duk_pop_2_unsafe(thr);  /* -> [ ... ] */
76762 		duk_push_number(thr, y);  /* -> [ ... y ] */
76763 		DUK_ASSERT(act == thr->callstack_curr);
76764 		duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(thr, -1), is_strict);
76765 	}
76766 
76767 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76768 	duk_replace(thr, (duk_idx_t) idx_dst);
76769 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76770 	DUK__REPLACE_TO_TVPTR(thr, DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst));
76771 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76772 }
76773 
76774 /*
76775  *  Longjmp and other control flow transfer for the bytecode executor.
76776  *
76777  *  The longjmp handler can handle all longjmp types: error, yield, and
76778  *  resume (pseudotypes are never actually thrown).
76779  *
76780  *  Error policy for longjmp: should not ordinarily throw errors; if errors
76781  *  occur (e.g. due to out-of-memory) they bubble outwards rather than being
76782  *  handled recursively.
76783  */
76784 
76785 #define DUK__LONGJMP_RESTART   0  /* state updated, restart bytecode execution */
76786 #define DUK__LONGJMP_RETHROW   1  /* exit bytecode executor by rethrowing an error to caller */
76787 
76788 #define DUK__RETHAND_RESTART   0  /* state updated, restart bytecode execution */
76789 #define DUK__RETHAND_FINISHED  1  /* exit bytecode execution with return value */
76790 
76791 /* XXX: optimize reconfig valstack operations so that resize, clamp, and setting
76792  * top are combined into one pass.
76793  */
76794 
76795 /* Reconfigure value stack for return to an ECMAScript function at
76796  * callstack top (caller unwinds).
76797  */
76798 DUK_LOCAL void duk__reconfig_valstack_ecma_return(duk_hthread *thr) {
76799 	duk_activation *act;
76800 	duk_hcompfunc *h_func;
76801 	duk_idx_t clamp_top;
76802 
76803 	DUK_ASSERT(thr != NULL);
76804 	act = thr->callstack_curr;
76805 	DUK_ASSERT(act != NULL);
76806 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
76807 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act)));
76808 
76809 	/* Clamp so that values at 'clamp_top' and above are wiped and won't
76810 	 * retain reachable garbage.  Then extend to 'nregs' because we're
76811 	 * returning to an ECMAScript function.
76812 	 */
76813 
76814 	h_func = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
76815 
76816 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
76817 	DUK_ASSERT(act->retval_byteoff >= act->bottom_byteoff);
76818 	clamp_top = (duk_idx_t) ((act->retval_byteoff - act->bottom_byteoff + sizeof(duk_tval)) / sizeof(duk_tval));  /* +1 = one retval */
76819 	duk_set_top_and_wipe(thr, h_func->nregs, clamp_top);
76820 
76821 	DUK_ASSERT((duk_uint8_t *) thr->valstack_end >= (duk_uint8_t *) thr->valstack + act->reserve_byteoff);
76822 	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->reserve_byteoff);
76823 
76824 	/* XXX: a best effort shrink check would be OK here */
76825 }
76826 
76827 /* Reconfigure value stack for an ECMAScript catcher.  Use topmost catcher
76828  * in 'act'.
76829  */
76830 DUK_LOCAL void duk__reconfig_valstack_ecma_catcher(duk_hthread *thr, duk_activation *act) {
76831 	duk_catcher *cat;
76832 	duk_hcompfunc *h_func;
76833 	duk_size_t idx_bottom;
76834 	duk_idx_t clamp_top;
76835 
76836 	DUK_ASSERT(thr != NULL);
76837 	DUK_ASSERT(act != NULL);
76838 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
76839 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act)));
76840 	cat = act->cat;
76841 	DUK_ASSERT(cat != NULL);
76842 
76843 	h_func = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
76844 
76845 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
76846 	idx_bottom = (duk_size_t) (thr->valstack_bottom - thr->valstack);
76847 	DUK_ASSERT(cat->idx_base >= idx_bottom);
76848 	clamp_top = (duk_idx_t) (cat->idx_base - idx_bottom + 2);  /* +2 = catcher value, catcher lj_type */
76849 	duk_set_top_and_wipe(thr, h_func->nregs, clamp_top);
76850 
76851 	DUK_ASSERT((duk_uint8_t *) thr->valstack_end >= (duk_uint8_t *) thr->valstack + act->reserve_byteoff);
76852 	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->reserve_byteoff);
76853 
76854 	/* XXX: a best effort shrink check would be OK here */
76855 }
76856 
76857 /* Set catcher regs: idx_base+0 = value, idx_base+1 = lj_type.
76858  * No side effects.
76859  */
76860 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) {
76861 	duk_tval *tv1;
76862 
76863 	DUK_ASSERT(thr != NULL);
76864 	DUK_ASSERT(tv_val_unstable != NULL);
76865 
76866 	tv1 = thr->valstack + cat->idx_base;
76867 	DUK_ASSERT(tv1 < thr->valstack_top);
76868 	DUK_TVAL_SET_TVAL_UPDREF_NORZ(thr, tv1, tv_val_unstable);
76869 
76870 	tv1++;
76871 	DUK_ASSERT(tv1 == thr->valstack + cat->idx_base + 1);
76872 	DUK_ASSERT(tv1 < thr->valstack_top);
76873 	DUK_TVAL_SET_U32_UPDREF_NORZ(thr, tv1, (duk_uint32_t) lj_type);
76874 }
76875 
76876 DUK_LOCAL void duk__handle_catch_part1(duk_hthread *thr, duk_tval *tv_val_unstable, duk_small_uint_t lj_type, volatile duk_bool_t *out_delayed_catch_setup) {
76877 	duk_activation *act;
76878 	duk_catcher *cat;
76879 
76880 	DUK_ASSERT(thr != NULL);
76881 	DUK_ASSERT(tv_val_unstable != NULL);
76882 
76883 	act = thr->callstack_curr;
76884 	DUK_ASSERT(act != NULL);
76885 	DUK_DD(DUK_DDPRINT("handle catch, part 1; act=%!A, cat=%!C", act, act->cat));
76886 
76887 	DUK_ASSERT(act->cat != NULL);
76888 	DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);
76889 
76890 	/* The part1/part2 split could also be made here at the very top
76891 	 * of catch handling.  Value stack would be reconfigured inside
76892 	 * part2's protection.  Value stack reconfiguration should be free
76893 	 * of allocs, however.
76894 	 */
76895 
76896 	duk__set_catcher_regs_norz(thr, act->cat, tv_val_unstable, lj_type);
76897 
76898 	DUK_ASSERT(thr->callstack_top >= 1);
76899 	DUK_ASSERT(thr->callstack_curr != NULL);
76900 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
76901 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
76902 
76903 	DUK_ASSERT(thr->callstack_top >= 1);
76904 	DUK_ASSERT(act == thr->callstack_curr);
76905 	DUK_ASSERT(act != NULL);
76906 	duk__reconfig_valstack_ecma_catcher(thr, act);
76907 
76908 	DUK_ASSERT(thr->callstack_top >= 1);
76909 	DUK_ASSERT(act == thr->callstack_curr);
76910 	DUK_ASSERT(act != NULL);
76911 	cat = act->cat;
76912 	DUK_ASSERT(cat != NULL);
76913 
76914 	act->curr_pc = cat->pc_base + 0;  /* +0 = catch */
76915 
76916 	/*
76917 	 *  If the catch block has an automatic catch variable binding,
76918 	 *  we need to create a lexical environment for it which requires
76919 	 *  allocations.  Move out of "error handling state" before the
76920 	 *  allocations to avoid e.g. out-of-memory errors (leading to
76921 	 *  GH-2022 or similar).
76922 	 */
76923 
76924 	if (DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat)) {
76925 		DUK_DDD(DUK_DDDPRINT("catcher has an automatic catch binding, handle in part 2"));
76926 		*out_delayed_catch_setup = 1;
76927 	} else {
76928 		DUK_DDD(DUK_DDDPRINT("catcher has no catch binding"));
76929 	}
76930 
76931 	DUK_CAT_CLEAR_CATCH_ENABLED(cat);
76932 }
76933 
76934 DUK_LOCAL void duk__handle_catch_part2(duk_hthread *thr) {
76935 	duk_activation *act;
76936 	duk_catcher *cat;
76937 	duk_hdecenv *new_env;
76938 
76939 	DUK_ASSERT(thr != NULL);
76940 
76941 	act = thr->callstack_curr;
76942 	DUK_ASSERT(act != NULL);
76943 	DUK_DD(DUK_DDPRINT("handle catch, part 2; act=%!A, cat=%!C", act, act->cat));
76944 
76945 	DUK_ASSERT(act->cat != NULL);
76946 	cat = act->cat;
76947 	DUK_ASSERT(cat != NULL);
76948 	DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
76949 	DUK_ASSERT(DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat));
76950 	DUK_ASSERT(thr->valstack + cat->idx_base < thr->valstack_top);
76951 
76952 	/*
76953 	 *  Create lexical environment for the catch clause, containing
76954 	 *  a binding for the caught value.
76955 	 *
76956 	 *  The binding is mutable (= writable) but not deletable.
76957 	 *  Step 4 for the catch production in E5 Section 12.14;
76958 	 *  no value is given for CreateMutableBinding 'D' argument,
76959 	 *  which implies the binding is not deletable.
76960 	 */
76961 
76962 	if (act->lex_env == NULL) {
76963 		DUK_ASSERT(act->var_env == NULL);
76964 		DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
76965 
76966 		duk_js_init_activation_environment_records_delayed(thr, act);
76967 		DUK_ASSERT(act == thr->callstack_curr);
76968 		DUK_ASSERT(act != NULL);
76969 	}
76970 	DUK_ASSERT(act->lex_env != NULL);
76971 	DUK_ASSERT(act->var_env != NULL);
76972 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
76973 
76974 	new_env = duk_hdecenv_alloc(thr,
76975 	                            DUK_HOBJECT_FLAG_EXTENSIBLE |
76976 	                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
76977 	DUK_ASSERT(new_env != NULL);
76978 	duk_push_hobject(thr, (duk_hobject *) new_env);
76979 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
76980 	DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));
76981 
76982 	/* Note: currently the catch binding is handled without a register
76983 	 * binding because we don't support dynamic register bindings (they
76984 	 * must be fixed for an entire function).  So, there is no need to
76985 	 * record regbases etc.
76986 	 */
76987 
76988 	/* [ ...env ] */
76989 
76990 	DUK_ASSERT(cat->h_varname != NULL);
76991 	duk_push_hstring(thr, cat->h_varname);
76992 	DUK_ASSERT(thr->valstack + cat->idx_base < thr->valstack_top);
76993 	duk_push_tval(thr, thr->valstack + cat->idx_base);
76994 	duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_W);  /* writable, not configurable */
76995 
76996 	/* [ ... env ] */
76997 
76998 	DUK_ASSERT(act == thr->callstack_curr);
76999 	DUK_ASSERT(act != NULL);
77000 	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, act->lex_env);
77001 	act->lex_env = (duk_hobject *) new_env;
77002 	DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);  /* reachable through activation */
77003 	/* Net refcount change to act->lex_env is 0: incref for new_env's
77004 	 * prototype, decref for act->lex_env overwrite.
77005 	 */
77006 
77007 	DUK_CAT_SET_LEXENV_ACTIVE(cat);
77008 
77009 	duk_pop_unsafe(thr);
77010 
77011 	DUK_DDD(DUK_DDDPRINT("new_env finished: %!iO", (duk_heaphdr *) new_env));
77012 }
77013 
77014 DUK_LOCAL void duk__handle_finally(duk_hthread *thr, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
77015 	duk_activation *act;
77016 	duk_catcher *cat;
77017 
77018 	DUK_ASSERT(thr != NULL);
77019 	DUK_ASSERT(tv_val_unstable != NULL);
77020 
77021 	act = thr->callstack_curr;
77022 	DUK_ASSERT(act != NULL);
77023 	DUK_ASSERT(act->cat != NULL);
77024 	DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);
77025 
77026 	duk__set_catcher_regs_norz(thr, act->cat, tv_val_unstable, lj_type);
77027 
77028 	DUK_ASSERT(thr->callstack_top >= 1);
77029 	DUK_ASSERT(thr->callstack_curr != NULL);
77030 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
77031 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
77032 
77033 	DUK_ASSERT(thr->callstack_top >= 1);
77034 	DUK_ASSERT(act == thr->callstack_curr);
77035 	DUK_ASSERT(act != NULL);
77036 	duk__reconfig_valstack_ecma_catcher(thr, act);
77037 
77038 	DUK_ASSERT(thr->callstack_top >= 1);
77039 	DUK_ASSERT(act == thr->callstack_curr);
77040 	DUK_ASSERT(act != NULL);
77041 	cat = act->cat;
77042 	DUK_ASSERT(cat != NULL);
77043 
77044 	act->curr_pc = cat->pc_base + 1;  /* +1 = finally */
77045 
77046 	DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
77047 }
77048 
77049 DUK_LOCAL void duk__handle_label(duk_hthread *thr, duk_small_uint_t lj_type) {
77050 	duk_activation *act;
77051 	duk_catcher *cat;
77052 
77053 	DUK_ASSERT(thr != NULL);
77054 
77055 	DUK_ASSERT(thr->callstack_top >= 1);
77056 	act = thr->callstack_curr;
77057 	DUK_ASSERT(act != NULL);
77058 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
77059 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(DUK_ACT_GET_FUNC(act)));
77060 
77061 	/* +0 = break, +1 = continue */
77062 	cat = act->cat;
77063 	DUK_ASSERT(cat != NULL);
77064 	DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL);
77065 
77066 	act->curr_pc = cat->pc_base + (lj_type == DUK_LJ_TYPE_CONTINUE ? 1 : 0);
77067 
77068 	/* valstack should not need changes */
77069 #if defined(DUK_USE_ASSERTIONS)
77070 	DUK_ASSERT(thr->callstack_top >= 1);
77071 	DUK_ASSERT(act == thr->callstack_curr);
77072 	DUK_ASSERT(act != NULL);
77073 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) ==
77074 	           (duk_size_t) ((duk_hcompfunc *) DUK_ACT_GET_FUNC(act))->nregs);
77075 #endif
77076 }
77077 
77078 /* Called for handling both a longjmp() with type DUK_LJ_TYPE_YIELD and
77079  * when a RETURN opcode terminates a thread and yields to the resumer.
77080  * Caller unwinds so that top of callstack is the activation we return to.
77081  */
77082 #if defined(DUK_USE_COROUTINE_SUPPORT)
77083 DUK_LOCAL void duk__handle_yield(duk_hthread *thr, duk_hthread *resumer, duk_tval *tv_val_unstable) {
77084 	duk_activation *act_resumer;
77085 	duk_tval *tv1;
77086 
77087 	DUK_ASSERT(thr != NULL);
77088 	DUK_ASSERT(resumer != NULL);
77089 	DUK_ASSERT(tv_val_unstable != NULL);
77090 	act_resumer = resumer->callstack_curr;
77091 	DUK_ASSERT(act_resumer != NULL);
77092 	DUK_ASSERT(DUK_ACT_GET_FUNC(act_resumer) != NULL);
77093 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act_resumer)));  /* resume caller must be an ECMAScript func */
77094 
77095 	tv1 = (duk_tval *) (void *) ((duk_uint8_t *) resumer->valstack + act_resumer->retval_byteoff);  /* return value from Duktape.Thread.resume() */
77096 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable);  /* side effects */  /* XXX: avoid side effects */
77097 
77098 	duk__reconfig_valstack_ecma_return(resumer);
77099 
77100 	/* caller must change active thread, and set thr->resumer to NULL */
77101 }
77102 #endif  /* DUK_USE_COROUTINE_SUPPORT */
77103 
77104 DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation *entry_act, volatile duk_bool_t *out_delayed_catch_setup) {
77105 	duk_small_uint_t retval = DUK__LONGJMP_RESTART;
77106 
77107 	DUK_ASSERT(thr != NULL);
77108 	DUK_ASSERT(entry_act != NULL);
77109 
77110 	/* 'thr' is the current thread, as no-one resumes except us and we
77111 	 * switch 'thr' in that case.
77112 	 */
77113 	DUK_ASSERT(thr == thr->heap->curr_thread);
77114 
77115 	/*
77116 	 *  (Re)try handling the longjmp.
77117 	 *
77118 	 *  A longjmp handler may convert the longjmp to a different type and
77119 	 *  "virtually" rethrow by goto'ing to 'check_longjmp'.  Before the goto,
77120 	 *  the following must be updated:
77121 	 *    - the heap 'lj' state
77122 	 *    - 'thr' must reflect the "throwing" thread
77123 	 */
77124 
77125  check_longjmp:
77126 
77127 	DUK_DD(DUK_DDPRINT("handling longjmp: type=%ld, value1=%!T, value2=%!T, iserror=%ld, top=%ld",
77128 	                   (long) thr->heap->lj.type,
77129 	                   (duk_tval *) &thr->heap->lj.value1,
77130 	                   (duk_tval *) &thr->heap->lj.value2,
77131 	                   (long) thr->heap->lj.iserror,
77132 			   (long) duk_get_top(thr)));
77133 
77134 	switch (thr->heap->lj.type) {
77135 
77136 #if defined(DUK_USE_COROUTINE_SUPPORT)
77137 	case DUK_LJ_TYPE_RESUME: {
77138 		/*
77139 		 *  Note: lj.value1 is 'value', lj.value2 is 'resumee'.
77140 		 *  This differs from YIELD.
77141 		 */
77142 
77143 		duk_tval *tv;
77144 		duk_tval *tv2;
77145 		duk_hthread *resumee;
77146 
77147 		/* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
77148 
77149 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);                                                         /* unchanged by Duktape.Thread.resume() */
77150 		DUK_ASSERT(thr->callstack_top >= 2);                                                                         /* ECMAScript activation + Duktape.Thread.resume() activation */
77151 		DUK_ASSERT(thr->callstack_curr != NULL);
77152 		DUK_ASSERT(thr->callstack_curr->parent != NULL);
77153 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL &&
77154 		           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)) &&
77155 		           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->callstack_curr))->func == duk_bi_thread_resume);
77156 
77157 		tv = &thr->heap->lj.value2;  /* resumee */
77158 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
77159 		DUK_ASSERT(DUK_TVAL_GET_OBJECT(tv) != NULL);
77160 		DUK_ASSERT(DUK_HOBJECT_IS_THREAD(DUK_TVAL_GET_OBJECT(tv)));
77161 		resumee = (duk_hthread *) DUK_TVAL_GET_OBJECT(tv);
77162 
77163 		DUK_ASSERT(resumee != NULL);
77164 		DUK_ASSERT(resumee->resumer == NULL);
77165 		DUK_ASSERT(resumee->state == DUK_HTHREAD_STATE_INACTIVE ||
77166 		           resumee->state == DUK_HTHREAD_STATE_YIELDED);                                                     /* checked by Duktape.Thread.resume() */
77167 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
77168 		           resumee->callstack_top >= 2);                                                                     /* YIELDED: ECMAScript activation + Duktape.Thread.yield() activation */
77169 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
77170 		           (DUK_ACT_GET_FUNC(resumee->callstack_curr) != NULL &&
77171 		            DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(resumee->callstack_curr)) &&
77172 		            ((duk_hnatfunc *) DUK_ACT_GET_FUNC(resumee->callstack_curr))->func == duk_bi_thread_yield));
77173 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_INACTIVE ||
77174 		           resumee->callstack_top == 0);                                                                     /* INACTIVE: no activation, single function value on valstack */
77175 
77176 		if (thr->heap->lj.iserror) {
77177 			/*
77178 			 *  Throw the error in the resumed thread's context; the
77179 			 *  error value is pushed onto the resumee valstack.
77180 			 *
77181 			 *  Note: the callstack of the target may empty in this case
77182 			 *  too (i.e. the target thread has never been resumed).  The
77183 			 *  value stack will contain the initial function in that case,
77184 			 *  which we simply ignore.
77185 			 */
77186 
77187 			DUK_ASSERT(resumee->resumer == NULL);
77188 			resumee->resumer = thr;
77189 			DUK_HTHREAD_INCREF(thr, thr);
77190 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
77191 			thr->state = DUK_HTHREAD_STATE_RESUMED;
77192 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
77193 			thr = resumee;
77194 
77195 			thr->heap->lj.type = DUK_LJ_TYPE_THROW;
77196 
77197 			/* thr->heap->lj.value1 is already the value to throw */
77198 			/* thr->heap->lj.value2 is 'thread', will be wiped out at the end */
77199 
77200 			DUK_ASSERT(thr->heap->lj.iserror);  /* already set */
77201 
77202 			DUK_DD(DUK_DDPRINT("-> resume with an error, converted to a throw in the resumee, propagate"));
77203 			goto check_longjmp;
77204 		} else if (resumee->state == DUK_HTHREAD_STATE_YIELDED) {
77205 			/* Unwind previous Duktape.Thread.yield() call.  The
77206 			 * activation remaining must always be an ECMAScript
77207 			 * call now (yield() accepts calls from ECMAScript
77208 			 * only).
77209 			 */
77210 			duk_activation *act_resumee;
77211 
77212 			DUK_ASSERT(resumee->callstack_top >= 2);
77213 			act_resumee = resumee->callstack_curr;  /* Duktape.Thread.yield() */
77214 			DUK_ASSERT(act_resumee != NULL);
77215 			act_resumee = act_resumee->parent;      /* ECMAScript call site for yield() */
77216 			DUK_ASSERT(act_resumee != NULL);
77217 
77218 			tv = (duk_tval *) (void *) ((duk_uint8_t *) resumee->valstack + act_resumee->retval_byteoff);  /* return value from Duktape.Thread.yield() */
77219 			DUK_ASSERT(tv >= resumee->valstack && tv < resumee->valstack_top);
77220 			tv2 = &thr->heap->lj.value1;
77221 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv2);  /* side effects */  /* XXX: avoid side effects */
77222 
77223 			duk_hthread_activation_unwind_norz(resumee);  /* unwind to 'yield' caller */
77224 			/* no need to unwind catch stack */
77225 
77226 			duk__reconfig_valstack_ecma_return(resumee);
77227 
77228 			DUK_ASSERT(resumee->resumer == NULL);
77229 			resumee->resumer = thr;
77230 			DUK_HTHREAD_INCREF(thr, thr);
77231 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
77232 			thr->state = DUK_HTHREAD_STATE_RESUMED;
77233 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
77234 #if 0
77235 			thr = resumee;  /* not needed, as we exit right away */
77236 #endif
77237 			DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
77238 			retval = DUK__LONGJMP_RESTART;
77239 			goto wipe_and_return;
77240 		} else {
77241 			/* Initial resume call. */
77242 			duk_small_uint_t call_flags;
77243 			duk_int_t setup_rc;
77244 
77245 			/* resumee: [... initial_func]  (currently actually: [initial_func]) */
77246 
77247 			duk_push_undefined(resumee);
77248 			tv = &thr->heap->lj.value1;
77249 			duk_push_tval(resumee, tv);
77250 
77251 			/* resumee: [... initial_func undefined(= this) resume_value ] */
77252 
77253 			call_flags = DUK_CALL_FLAG_ALLOW_ECMATOECMA;  /* not tailcall, ecma-to-ecma (assumed to succeed) */
77254 
77255 			setup_rc = duk_handle_call_unprotected_nargs(resumee, 1 /*nargs*/, call_flags);
77256 			if (setup_rc == 0) {
77257 				/* This shouldn't happen; Duktape.Thread.resume()
77258 				 * should make sure of that.  If it does happen
77259 				 * this internal error will propagate out of the
77260 				 * executor which can be quite misleading.
77261 				 */
77262 				DUK_ERROR_INTERNAL(thr);
77263 				DUK_WO_NORETURN(return 0;);
77264 			}
77265 
77266 			DUK_ASSERT(resumee->resumer == NULL);
77267 			resumee->resumer = thr;
77268 			DUK_HTHREAD_INCREF(thr, thr);
77269 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
77270 			thr->state = DUK_HTHREAD_STATE_RESUMED;
77271 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
77272 #if 0
77273 			thr = resumee;  /* not needed, as we exit right away */
77274 #endif
77275 			DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
77276 			retval = DUK__LONGJMP_RESTART;
77277 			goto wipe_and_return;
77278 		}
77279 		DUK_UNREACHABLE();
77280 		break;  /* never here */
77281 	}
77282 
77283 	case DUK_LJ_TYPE_YIELD: {
77284 		/*
77285 		 *  Currently only allowed only if yielding thread has only
77286 		 *  ECMAScript activations (except for the Duktape.Thread.yield()
77287 		 *  call at the callstack top) and none of them constructor
77288 		 *  calls.
77289 		 *
77290 		 *  This excludes the 'entry' thread which will always have
77291 		 *  a preventcount > 0.
77292 		 */
77293 
77294 		duk_hthread *resumer;
77295 
77296 		/* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
77297 
77298 #if 0  /* entry_thread not available for assert */
77299 		DUK_ASSERT(thr != entry_thread);                                                                             /* Duktape.Thread.yield() should prevent */
77300 #endif
77301 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);                                                         /* unchanged from Duktape.Thread.yield() */
77302 		DUK_ASSERT(thr->callstack_top >= 2);                                                                         /* ECMAScript activation + Duktape.Thread.yield() activation */
77303 		DUK_ASSERT(thr->callstack_curr != NULL);
77304 		DUK_ASSERT(thr->callstack_curr->parent != NULL);
77305 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL &&
77306 		           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)) &&
77307 		           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->callstack_curr))->func == duk_bi_thread_yield);
77308 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL &&
77309 		           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent)));                              /* an ECMAScript function */
77310 
77311 		resumer = thr->resumer;
77312 
77313 		DUK_ASSERT(resumer != NULL);
77314 		DUK_ASSERT(resumer->state == DUK_HTHREAD_STATE_RESUMED);                                                     /* written by a previous RESUME handling */
77315 		DUK_ASSERT(resumer->callstack_top >= 2);                                                                     /* ECMAScript activation + Duktape.Thread.resume() activation */
77316 		DUK_ASSERT(resumer->callstack_curr != NULL);
77317 		DUK_ASSERT(resumer->callstack_curr->parent != NULL);
77318 		DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack_curr) != NULL &&
77319 		           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr)) &&
77320 		           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(resumer->callstack_curr))->func == duk_bi_thread_resume);
77321 		DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent) != NULL &&
77322 		           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent)));                            /* an ECMAScript function */
77323 
77324 		if (thr->heap->lj.iserror) {
77325 			thr->state = DUK_HTHREAD_STATE_YIELDED;
77326 			thr->resumer = NULL;
77327 			DUK_HTHREAD_DECREF_NORZ(thr, resumer);
77328 			resumer->state = DUK_HTHREAD_STATE_RUNNING;
77329 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
77330 			thr = resumer;
77331 
77332 			thr->heap->lj.type = DUK_LJ_TYPE_THROW;
77333 			/* lj.value1 is already set */
77334 			DUK_ASSERT(thr->heap->lj.iserror);  /* already set */
77335 
77336 			DUK_DD(DUK_DDPRINT("-> yield an error, converted to a throw in the resumer, propagate"));
77337 			goto check_longjmp;
77338 		} else {
77339 			/* When handling the yield, the last reference to
77340 			 * 'thr' may disappear.
77341 			 */
77342 
77343 			DUK_GC_TORTURE(resumer->heap);
77344 			duk_hthread_activation_unwind_norz(resumer);
77345 			DUK_GC_TORTURE(resumer->heap);
77346 			thr->state = DUK_HTHREAD_STATE_YIELDED;
77347 			thr->resumer = NULL;
77348 			DUK_HTHREAD_DECREF_NORZ(thr, resumer);
77349 			resumer->state = DUK_HTHREAD_STATE_RUNNING;
77350 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
77351 			duk__handle_yield(thr, resumer, &thr->heap->lj.value1);
77352 			thr = resumer;
77353 			DUK_GC_TORTURE(resumer->heap);
77354 
77355 			DUK_DD(DUK_DDPRINT("-> yield a value, restart execution in resumer"));
77356 			retval = DUK__LONGJMP_RESTART;
77357 			goto wipe_and_return;
77358 		}
77359 		DUK_UNREACHABLE();
77360 		break;  /* never here */
77361 	}
77362 #endif  /* DUK_USE_COROUTINE_SUPPORT */
77363 
77364 	case DUK_LJ_TYPE_THROW: {
77365 		/*
77366 		 *  Three possible outcomes:
77367 		 *    * A try or finally catcher is found => resume there.
77368 		 *      (or)
77369 		 *    * The error propagates to the bytecode executor entry
77370 		 *      level (and we're in the entry thread) => rethrow
77371 		 *      with a new longjmp(), after restoring the previous
77372 		 *      catchpoint.
77373 		 *    * The error is not caught in the current thread, so
77374 		 *      the thread finishes with an error.  This works like
77375 		 *      a yielded error, except that the thread is finished
77376 		 *      and can no longer be resumed.  (There is always a
77377 		 *      resumer in this case.)
77378 		 *
77379 		 *  Note: until we hit the entry level, there can only be
77380 		 *  ECMAScript activations.
77381 		 */
77382 
77383 		duk_activation *act;
77384 		duk_catcher *cat;
77385 		duk_hthread *resumer;
77386 
77387 		for (;;) {
77388 			act = thr->callstack_curr;
77389 			if (act == NULL) {
77390 				break;
77391 			}
77392 
77393 			for (;;) {
77394 				cat = act->cat;
77395 				if (cat == NULL) {
77396 					break;
77397 				}
77398 
77399 				if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
77400 					DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
77401 
77402 					DUK_DDD(DUK_DDDPRINT("before catch part 1: thr=%p, act=%p, cat=%p",
77403 					                     (void *) thr, (void *) act, (void *) act->cat));
77404 					duk__handle_catch_part1(thr,
77405 					                        &thr->heap->lj.value1,
77406 					                        DUK_LJ_TYPE_THROW,
77407 							        out_delayed_catch_setup);
77408 
77409 					DUK_DD(DUK_DDPRINT("-> throw caught by a 'catch' clause, restart execution"));
77410 					retval = DUK__LONGJMP_RESTART;
77411 					goto wipe_and_return;
77412 				}
77413 
77414 				if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
77415 					DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
77416 					DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat));
77417 
77418 					duk__handle_finally(thr,
77419 					                    &thr->heap->lj.value1,
77420 					                    DUK_LJ_TYPE_THROW);
77421 
77422 					DUK_DD(DUK_DDPRINT("-> throw caught by a 'finally' clause, restart execution"));
77423 					retval = DUK__LONGJMP_RESTART;
77424 					goto wipe_and_return;
77425 				}
77426 
77427 				duk_hthread_catcher_unwind_norz(thr, act);
77428 			}
77429 
77430 			if (act == entry_act) {
77431 				/* Not caught by anything before entry level; rethrow and let the
77432 				 * final catcher finish unwinding (esp. value stack).
77433 				 */
77434 				DUK_D(DUK_DPRINT("-> throw propagated up to entry level, rethrow and exit bytecode executor"));
77435 				retval = DUK__LONGJMP_RETHROW;
77436 				goto just_return;
77437 			}
77438 
77439 			duk_hthread_activation_unwind_norz(thr);
77440 		}
77441 
77442 		DUK_DD(DUK_DDPRINT("-> throw not caught by current thread, yield error to resumer and recheck longjmp"));
77443 
77444 		/* Not caught by current thread, thread terminates (yield error to resumer);
77445 		 * note that this may cause a cascade if the resumer terminates with an uncaught
77446 		 * exception etc (this is OK, but needs careful testing).
77447 		 */
77448 
77449 		DUK_ASSERT(thr->resumer != NULL);
77450 		DUK_ASSERT(thr->resumer->callstack_top >= 2);  /* ECMAScript activation + Duktape.Thread.resume() activation */
77451 		DUK_ASSERT(thr->resumer->callstack_curr != NULL);
77452 		DUK_ASSERT(thr->resumer->callstack_curr->parent != NULL);
77453 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent) != NULL &&
77454 		           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent)));  /* an ECMAScript function */
77455 
77456 		resumer = thr->resumer;
77457 
77458 		/* reset longjmp */
77459 
77460 		DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);  /* already set */
77461 		/* lj.value1 already set */
77462 
77463 		duk_hthread_terminate(thr);  /* updates thread state, minimizes its allocations */
77464 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
77465 
77466 		thr->resumer = NULL;
77467 		DUK_HTHREAD_DECREF_NORZ(thr, resumer);
77468 		resumer->state = DUK_HTHREAD_STATE_RUNNING;
77469 		DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
77470 		thr = resumer;
77471 		goto check_longjmp;
77472 	}
77473 
77474 	case DUK_LJ_TYPE_BREAK:  /* pseudotypes, not used in actual longjmps */
77475 	case DUK_LJ_TYPE_CONTINUE:
77476 	case DUK_LJ_TYPE_RETURN:
77477 	case DUK_LJ_TYPE_NORMAL:
77478 	default: {
77479 		/* should never happen, but be robust */
77480 		DUK_D(DUK_DPRINT("caught unknown longjmp type %ld, treat as internal error", (long) thr->heap->lj.type));
77481 		goto convert_to_internal_error;
77482 	}
77483 
77484 	}  /* end switch */
77485 
77486 	DUK_UNREACHABLE();
77487 
77488  wipe_and_return:
77489 	DUK_DD(DUK_DDPRINT("handling longjmp done, wipe-and-return, top=%ld",
77490 	                   (long) duk_get_top(thr)));
77491 	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
77492 	thr->heap->lj.iserror = 0;
77493 
77494 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1);  /* side effects */
77495 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2);  /* side effects */
77496 
77497 	DUK_GC_TORTURE(thr->heap);
77498 
77499  just_return:
77500 	return retval;
77501 
77502  convert_to_internal_error:
77503 	/* This could also be thrown internally (set the error, goto check_longjmp),
77504 	 * but it's better for internal errors to bubble outwards so that we won't
77505 	 * infinite loop in this catchpoint.
77506 	 */
77507 	DUK_ERROR_INTERNAL(thr);
77508 	DUK_WO_NORETURN(return 0;);
77509 }
77510 
77511 /* Handle a BREAK/CONTINUE opcode.  Avoid using longjmp() for BREAK/CONTINUE
77512  * handling because it has a measurable performance impact in ordinary
77513  * environments and an extreme impact in Emscripten (GH-342).
77514  */
77515 DUK_LOCAL DUK_EXEC_NOINLINE_PERF void duk__handle_break_or_continue(duk_hthread *thr,
77516                                                                     duk_uint_t label_id,
77517                                                                     duk_small_uint_t lj_type) {
77518 	duk_activation *act;
77519 	duk_catcher *cat;
77520 
77521 	DUK_ASSERT(thr != NULL);
77522 
77523 	/* Find a matching label catcher or 'finally' catcher in
77524 	 * the same function, unwinding catchers as we go.
77525 	 *
77526 	 * A label catcher must always exist and will match unless
77527 	 * a 'finally' captures the break/continue first.  It is the
77528 	 * compiler's responsibility to ensure that labels are used
77529 	 * correctly.
77530 	 */
77531 
77532 	act = thr->callstack_curr;
77533 	DUK_ASSERT(act != NULL);
77534 
77535 	for (;;) {
77536 		cat = act->cat;
77537 		if (cat == NULL) {
77538 			break;
77539 		}
77540 
77541 		DUK_DDD(DUK_DDDPRINT("considering catcher %p: type=%ld label=%ld",
77542 		                     (void *) cat,
77543 		                     (long) DUK_CAT_GET_TYPE(cat),
77544 		                     (long) DUK_CAT_GET_LABEL(cat)));
77545 
77546 		/* XXX: bit mask test; FINALLY <-> TCF, single bit mask would suffice? */
77547 
77548 		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
77549 		    DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
77550 			duk_tval tv_tmp;
77551 
77552 			DUK_TVAL_SET_U32(&tv_tmp, (duk_uint32_t) label_id);
77553 			duk__handle_finally(thr, &tv_tmp, lj_type);
77554 
77555 			DUK_DD(DUK_DDPRINT("-> break/continue caught by 'finally', restart execution"));
77556 			return;
77557 		}
77558 		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL &&
77559 		    (duk_uint_t) DUK_CAT_GET_LABEL(cat) == label_id) {
77560 			duk__handle_label(thr, lj_type);
77561 
77562 			DUK_DD(DUK_DDPRINT("-> break/continue caught by a label catcher (in the same function), restart execution"));
77563 			return;
77564 		}
77565 
77566 		duk_hthread_catcher_unwind_norz(thr, act);
77567 	}
77568 
77569 	/* Should never happen, but be robust. */
77570 	DUK_D(DUK_DPRINT("-> break/continue not caught by anything in the current function (should never happen), throw internal error"));
77571 	DUK_ERROR_INTERNAL(thr);
77572 	DUK_WO_NORETURN(return;);
77573 }
77574 
77575 /* Handle a RETURN opcode.  Avoid using longjmp() for return handling because
77576  * it has a measurable performance impact in ordinary environments and an extreme
77577  * impact in Emscripten (GH-342).  Return value is on value stack top.
77578  */
77579 DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr, duk_activation *entry_act) {
77580 	duk_tval *tv1;
77581 	duk_tval *tv2;
77582 #if defined(DUK_USE_COROUTINE_SUPPORT)
77583 	duk_hthread *resumer;
77584 #endif
77585 	duk_activation *act;
77586 	duk_catcher *cat;
77587 
77588 	/* We can directly access value stack here. */
77589 
77590 	DUK_ASSERT(thr != NULL);
77591 	DUK_ASSERT(entry_act != NULL);
77592 	DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
77593 	tv1 = thr->valstack_top - 1;
77594 	DUK_TVAL_CHKFAST_INPLACE_FAST(tv1);  /* fastint downgrade check for return values */
77595 
77596 	/*
77597 	 *  Four possible outcomes:
77598 	 *
77599 	 *    1. A 'finally' in the same function catches the 'return'.
77600 	 *       It may continue to propagate when 'finally' is finished,
77601 	 *       or it may be neutralized by 'finally' (both handled by
77602 	 *       ENDFIN).
77603 	 *
77604 	 *    2. The return happens at the entry level of the bytecode
77605 	 *       executor, so return from the executor (in C stack).
77606 	 *
77607 	 *    3. There is a calling (ECMAScript) activation in the call
77608 	 *       stack => return to it, in the same executor instance.
77609 	 *
77610 	 *    4. There is no calling activation, and the thread is
77611 	 *       terminated.  There is always a resumer in this case,
77612 	 *       which gets the return value similarly to a 'yield'
77613 	 *       (except that the current thread can no longer be
77614 	 *       resumed).
77615 	 */
77616 
77617 	DUK_ASSERT(thr != NULL);
77618 	DUK_ASSERT(thr->callstack_top >= 1);
77619 
77620 	act = thr->callstack_curr;
77621 	DUK_ASSERT(act != NULL);
77622 
77623 	for (;;) {
77624 		cat = act->cat;
77625 		if (cat == NULL) {
77626 			break;
77627 		}
77628 
77629 		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
77630 		    DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
77631 			DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
77632 			duk__handle_finally(thr, thr->valstack_top - 1, DUK_LJ_TYPE_RETURN);
77633 
77634 			DUK_DD(DUK_DDPRINT("-> return caught by 'finally', restart execution"));
77635 			return DUK__RETHAND_RESTART;
77636 		}
77637 
77638 		duk_hthread_catcher_unwind_norz(thr, act);
77639 	}
77640 
77641 	if (act == entry_act) {
77642 		/* Return to the bytecode executor caller who will unwind stacks
77643 		 * and handle constructor post-processing.
77644 		 * Return value is already on the stack top: [ ... retval ].
77645 		 */
77646 
77647 		DUK_DDD(DUK_DDDPRINT("-> return propagated up to entry level, exit bytecode executor"));
77648 		return DUK__RETHAND_FINISHED;
77649 	}
77650 
77651 	if (thr->callstack_top >= 2) {
77652 		/* There is a caller; it MUST be an ECMAScript caller (otherwise it would
77653 		 * match entry_act check).
77654 		 */
77655 		DUK_DDD(DUK_DDDPRINT("return to ECMAScript caller, retval_byteoff=%ld, lj_value1=%!T",
77656 		                     (long) (thr->callstack_curr->parent->retval_byteoff),
77657 		                     (duk_tval *) &thr->heap->lj.value1));
77658 
77659 		DUK_ASSERT(thr->callstack_curr != NULL);
77660 		DUK_ASSERT(thr->callstack_curr->parent != NULL);
77661 		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent)));   /* must be ECMAScript */
77662 
77663 #if defined(DUK_USE_ES6_PROXY)
77664 		if (thr->callstack_curr->flags & (DUK_ACT_FLAG_CONSTRUCT | DUK_ACT_FLAG_CONSTRUCT_PROXY)) {
77665 			duk_call_construct_postprocess(thr, thr->callstack_curr->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY);  /* side effects */
77666 		}
77667 #else
77668 		if (thr->callstack_curr->flags & DUK_ACT_FLAG_CONSTRUCT) {
77669 			duk_call_construct_postprocess(thr, 0);  /* side effects */
77670 		}
77671 #endif
77672 
77673 		tv1 = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + thr->callstack_curr->parent->retval_byteoff);
77674 		DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
77675 		tv2 = thr->valstack_top - 1;
77676 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
77677 
77678 		/* Catch stack unwind happens inline in callstack unwind. */
77679 		duk_hthread_activation_unwind_norz(thr);
77680 
77681 		duk__reconfig_valstack_ecma_return(thr);
77682 
77683 		DUK_DD(DUK_DDPRINT("-> return not intercepted, restart execution in caller"));
77684 		return DUK__RETHAND_RESTART;
77685 	}
77686 
77687 #if defined(DUK_USE_COROUTINE_SUPPORT)
77688 	DUK_DD(DUK_DDPRINT("no calling activation, thread finishes (similar to yield)"));
77689 
77690 	DUK_ASSERT(thr->resumer != NULL);
77691 	DUK_ASSERT(thr->resumer->callstack_top >= 2);  /* ECMAScript activation + Duktape.Thread.resume() activation */
77692 	DUK_ASSERT(thr->resumer->callstack_curr != NULL);
77693 	DUK_ASSERT(thr->resumer->callstack_curr->parent != NULL);
77694 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr) != NULL &&
77695 			DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr)) &&
77696 			((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->resumer->callstack_curr))->func == duk_bi_thread_resume);  /* Duktape.Thread.resume() */
77697 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent) != NULL &&
77698 			DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent)));  /* an ECMAScript function */
77699 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
77700 	DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);
77701 
77702 	resumer = thr->resumer;
77703 
77704 	/* Share yield longjmp handler.
77705 	 *
77706 	 * This sequence of steps is a bit fragile (see GH-1845):
77707 	 * - We need the return value from 'thr' (resumed thread) value stack.
77708 	 *   The termination unwinds its value stack, losing the value.
77709 	 * - We need a refcounted reference for 'thr', which may only exist
77710 	 *   in the caller value stack.  We can't unwind or reconfigure the
77711 	 *   caller's value stack without potentially freeing 'thr'.
77712 	 *
77713 	 * Current approach is to capture the 'thr' return value and store
77714 	 * a reference to 'thr' in the caller value stack temporarily.  This
77715 	 * keeps 'thr' reachable until final yield/return handling which
77716 	 * removes the references atomatically.
77717 	 */
77718 
77719 	DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
77720 	duk_hthread_activation_unwind_norz(resumer);  /* May remove last reference to 'thr', but is NORZ. */
77721 	duk_push_tval(resumer, thr->valstack_top - 1);  /* Capture return value, side effect free. */
77722 	duk_push_hthread(resumer, thr);  /* Make 'thr' reachable again, before side effects. */
77723 
77724 	duk_hthread_terminate(thr);  /* Updates thread state, minimizes its allocations. */
77725 	thr->resumer = NULL;
77726 	DUK_HTHREAD_DECREF(thr, resumer);
77727 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
77728 
77729 	resumer->state = DUK_HTHREAD_STATE_RUNNING;
77730 	DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
77731 
77732 	DUK_ASSERT(resumer->valstack_top - 2 >= resumer->valstack_bottom);
77733 	duk__handle_yield(thr, resumer, resumer->valstack_top - 2);
77734 	thr = NULL;  /* 'thr' invalidated by call */
77735 
77736 #if 0
77737 	thr = resumer;  /* not needed */
77738 #endif
77739 
77740 	DUK_DD(DUK_DDPRINT("-> return not caught, thread terminated; handle like yield, restart execution in resumer"));
77741 	return DUK__RETHAND_RESTART;
77742 #else
77743 	/* Without coroutine support this case should never happen. */
77744 	DUK_ERROR_INTERNAL(thr);
77745 	DUK_WO_NORETURN(return 0;);
77746 #endif
77747 }
77748 
77749 /*
77750  *  Executor interrupt handling
77751  *
77752  *  The handler is called whenever the interrupt countdown reaches zero
77753  *  (or below).  The handler must perform whatever checks are activated,
77754  *  e.g. check for cumulative step count to impose an execution step
77755  *  limit or check for breakpoints or other debugger interaction.
77756  *
77757  *  When the actions are done, the handler must reinit the interrupt
77758  *  init and counter values.  The 'init' value must indicate how many
77759  *  bytecode instructions are executed before the next interrupt.  The
77760  *  counter must interface with the bytecode executor loop.  Concretely,
77761  *  the new init value is normally one higher than the new counter value.
77762  *  For instance, to execute exactly one bytecode instruction the init
77763  *  value is set to 1 and the counter to 0.  If an error is thrown by the
77764  *  interrupt handler, the counters are set to the same value (e.g. both
77765  *  to 0 to cause an interrupt when the next bytecode instruction is about
77766  *  to be executed after error handling).
77767  *
77768  *  Maintaining the init/counter value properly is important for accurate
77769  *  behavior.  For instance, executor step limit needs a cumulative step
77770  *  count which is simply computed as a sum of 'init' values.  This must
77771  *  work accurately even when single stepping.
77772  */
77773 
77774 #if defined(DUK_USE_INTERRUPT_COUNTER)
77775 
77776 #define DUK__INT_NOACTION    0    /* no specific action, resume normal execution */
77777 #define DUK__INT_RESTART     1    /* must "goto restart_execution", e.g. breakpoints changed */
77778 
77779 #if defined(DUK_USE_DEBUGGER_SUPPORT)
77780 DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_immediate, duk_small_uint_t *out_interrupt_retval) {
77781 	duk_activation *act;
77782 	duk_breakpoint *bp;
77783 	duk_breakpoint **bp_active;
77784 	duk_uint_fast32_t line = 0;
77785 	duk_bool_t process_messages;
77786 	duk_bool_t processed_messages = 0;
77787 
77788 	DUK_ASSERT(thr->heap->dbg_processing == 0);  /* don't re-enter e.g. during Eval */
77789 
77790 	act = thr->callstack_curr;
77791 	DUK_ASSERT(act != NULL);
77792 
77793 	/* It might seem that replacing 'thr->heap' with just 'heap' below
77794 	 * might be a good idea, but it increases code size slightly
77795 	 * (probably due to unnecessary spilling) at least on x64.
77796 	 */
77797 
77798 	/*
77799 	 *  Single opcode step check
77800 	 */
77801 
77802 	if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE) {
77803 		DUK_D(DUK_DPRINT("PAUSE TRIGGERED by one opcode step"));
77804 		duk_debug_set_paused(thr->heap);
77805 	}
77806 
77807 	/*
77808 	 *  Breakpoint and step state checks
77809 	 */
77810 
77811 	if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||
77812 	    (thr->heap->dbg_pause_act == thr->callstack_curr)) {
77813 		line = duk_debug_curr_line(thr);
77814 
77815 		if (act->prev_line != line) {
77816 			/* Stepped?  Step out is handled by callstack unwind. */
77817 			if ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
77818 			    (thr->heap->dbg_pause_act == thr->callstack_curr) &&
77819 			    (line != thr->heap->dbg_pause_startline)) {
77820 				DUK_D(DUK_DPRINT("PAUSE TRIGGERED by line change, at line %ld",
77821 				                 (long) line));
77822 				duk_debug_set_paused(thr->heap);
77823 			}
77824 
77825 			/* Check for breakpoints only on line transition.
77826 			 * Breakpoint is triggered when we enter the target
77827 			 * line from a different line, and the previous line
77828 			 * was within the same function.
77829 			 *
77830 			 * This condition is tricky: the condition used to be
77831 			 * that transition to -or across- the breakpoint line
77832 			 * triggered the breakpoint.  This seems intuitively
77833 			 * better because it handles breakpoints on lines with
77834 			 * no emitted opcodes; but this leads to the issue
77835 			 * described in: https://github.com/svaarala/duktape/issues/263.
77836 			 */
77837 			bp_active = thr->heap->dbg_breakpoints_active;
77838 			for (;;) {
77839 				bp = *bp_active++;
77840 				if (bp == NULL) {
77841 					break;
77842 				}
77843 
77844 				DUK_ASSERT(bp->filename != NULL);
77845 				if (act->prev_line != bp->line && line == bp->line) {
77846 					DUK_D(DUK_DPRINT("PAUSE TRIGGERED by breakpoint at %!O:%ld",
77847 					                 (duk_heaphdr *) bp->filename, (long) bp->line));
77848 					duk_debug_set_paused(thr->heap);
77849 				}
77850 			}
77851 		} else {
77852 			;
77853 		}
77854 
77855 		act->prev_line = (duk_uint32_t) line;
77856 	}
77857 
77858 	/*
77859 	 *  Rate limit check for sending status update or peeking into
77860 	 *  the debug transport.  Both can be expensive operations that
77861 	 *  we don't want to do on every opcode.
77862 	 *
77863 	 *  Making sure the interval remains reasonable on a wide variety
77864 	 *  of targets and bytecode is difficult without a timestamp, so
77865 	 *  we use a Date-provided timestamp for the rate limit check.
77866 	 *  But since it's also expensive to get a timestamp, a bytecode
77867 	 *  counter is used to rate limit getting timestamps.
77868 	 */
77869 
77870 	process_messages = 0;
77871 	if (thr->heap->dbg_state_dirty || DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || thr->heap->dbg_detaching) {
77872 		/* Enter message processing loop for sending Status notifys and
77873 		 * to finish a pending detach.
77874 		 */
77875 		process_messages = 1;
77876 	}
77877 
77878 	/* XXX: remove heap->dbg_exec_counter, use heap->inst_count_interrupt instead? */
77879 	DUK_ASSERT(thr->interrupt_init >= 0);
77880 	thr->heap->dbg_exec_counter += (duk_uint_t) thr->interrupt_init;
77881 	if (thr->heap->dbg_exec_counter - thr->heap->dbg_last_counter >= DUK_HEAP_DBG_RATELIMIT_OPCODES) {
77882 		/* Overflow of the execution counter is fine and doesn't break
77883 		 * anything here.
77884 		 */
77885 
77886 		duk_double_t now, diff_last;
77887 
77888 		thr->heap->dbg_last_counter = thr->heap->dbg_exec_counter;
77889 		now = duk_time_get_monotonic_time(thr);
77890 
77891 		diff_last = now - thr->heap->dbg_last_time;
77892 		if (diff_last < 0.0 || diff_last >= (duk_double_t) DUK_HEAP_DBG_RATELIMIT_MILLISECS) {
77893 			/* Monotonic time should not experience time jumps,
77894 			 * but the provider may be missing and we're actually
77895 			 * using ECMAScript time.  So, tolerate negative values
77896 			 * so that a time jump works reasonably.
77897 			 *
77898 			 * Same interval is now used for status sending and
77899 			 * peeking.
77900 			 */
77901 
77902 			thr->heap->dbg_last_time = now;
77903 			thr->heap->dbg_state_dirty = 1;
77904 			process_messages = 1;
77905 		}
77906 	}
77907 
77908 	/*
77909 	 *  Process messages and send status if necessary.
77910 	 *
77911 	 *  If we're paused, we'll block for new messages.  If we're not
77912 	 *  paused, we'll process anything we can peek but won't block
77913 	 *  for more.  Detach (and re-attach) handling is all localized
77914 	 *  to duk_debug_process_messages() too.
77915 	 *
77916 	 *  Debugger writes outside the message loop may cause debugger
77917 	 *  detach1 phase to run, after which dbg_read_cb == NULL and
77918 	 *  dbg_detaching != 0.  The message loop will finish the detach
77919 	 *  by running detach2 phase, so enter the message loop also when
77920 	 *  detaching.
77921 	 */
77922 
77923 	if (process_messages) {
77924 		DUK_ASSERT(thr->heap->dbg_processing == 0);
77925 		processed_messages = duk_debug_process_messages(thr, 0 /*no_block*/);
77926 		DUK_ASSERT(thr->heap->dbg_processing == 0);
77927 	}
77928 
77929 	/* Continue checked execution if there are breakpoints or we're stepping.
77930 	 * Also use checked execution if paused flag is active - it shouldn't be
77931 	 * because the debug message loop shouldn't terminate if it was.  Step out
77932 	 * is handled by callstack unwind and doesn't need checked execution.
77933 	 * Note that debugger may have detached due to error or explicit request
77934 	 * above, so we must recheck attach status.
77935 	 */
77936 
77937 	if (duk_debug_is_attached(thr->heap)) {
77938 		DUK_ASSERT(act == thr->callstack_curr);
77939 		DUK_ASSERT(act != NULL);
77940 		if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||
77941 		    (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE) ||
77942 		    ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
77943 		     thr->heap->dbg_pause_act == thr->callstack_curr) ||
77944 		     DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap)) {
77945 			*out_immediate = 1;
77946 		}
77947 
77948 		/* If we processed any debug messages breakpoints may have
77949 		 * changed; restart execution to re-check active breakpoints.
77950 		 */
77951 		if (processed_messages) {
77952 			DUK_D(DUK_DPRINT("processed debug messages, restart execution to recheck possibly changed breakpoints"));
77953 			*out_interrupt_retval = DUK__INT_RESTART;
77954 		} else {
77955 			if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE) {
77956 				/* Set 'pause after one opcode' active only when we're
77957 				 * actually just about to execute code.
77958 				 */
77959 				thr->heap->dbg_pause_flags |= DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE;
77960 			}
77961 		}
77962 	} else {
77963 		DUK_D(DUK_DPRINT("debugger became detached, resume normal execution"));
77964 	}
77965 }
77966 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
77967 
77968 DUK_LOCAL DUK_EXEC_NOINLINE_PERF DUK_COLD duk_small_uint_t duk__executor_interrupt(duk_hthread *thr) {
77969 	duk_int_t ctr;
77970 	duk_activation *act;
77971 	duk_hcompfunc *fun;
77972 	duk_bool_t immediate = 0;
77973 	duk_small_uint_t retval;
77974 
77975 	DUK_ASSERT(thr != NULL);
77976 	DUK_ASSERT(thr->heap != NULL);
77977 	DUK_ASSERT(thr->callstack_top > 0);
77978 
77979 #if defined(DUK_USE_DEBUG)
77980 	thr->heap->inst_count_interrupt += thr->interrupt_init;
77981 	DUK_DD(DUK_DDPRINT("execution interrupt, counter=%ld, init=%ld, "
77982 	                   "instruction counts: executor=%ld, interrupt=%ld",
77983 	                   (long) thr->interrupt_counter, (long) thr->interrupt_init,
77984 	                   (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
77985 #endif
77986 
77987 	retval = DUK__INT_NOACTION;
77988 	ctr = DUK_HTHREAD_INTCTR_DEFAULT;
77989 
77990 	/*
77991 	 *  Avoid nested calls.  Concretely this happens during debugging, e.g.
77992 	 *  when we eval() an expression.
77993 	 *
77994 	 *  Also don't interrupt if we're currently doing debug processing
77995 	 *  (which can be initiated outside the bytecode executor) as this
77996 	 *  may cause the debugger to be called recursively.  Check required
77997 	 *  for correct operation of throw intercept and other "exotic" halting
77998 	 * scenarios.
77999 	 */
78000 
78001 #if defined(DUK_USE_DEBUGGER_SUPPORT)
78002 	if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap) || thr->heap->dbg_processing) {
78003 #else
78004 	if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap)) {
78005 #endif
78006 		DUK_DD(DUK_DDPRINT("nested executor interrupt, ignoring"));
78007 
78008 		/* Set a high interrupt counter; the original executor
78009 		 * interrupt invocation will rewrite before exiting.
78010 		 */
78011 		thr->interrupt_init = ctr;
78012 		thr->interrupt_counter = ctr - 1;
78013 		return DUK__INT_NOACTION;
78014 	}
78015 	DUK_HEAP_SET_INTERRUPT_RUNNING(thr->heap);
78016 
78017 	act = thr->callstack_curr;
78018 	DUK_ASSERT(act != NULL);
78019 
78020 	fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
78021 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC((duk_hobject *) fun));
78022 
78023 	DUK_UNREF(fun);
78024 
78025 #if defined(DUK_USE_EXEC_TIMEOUT_CHECK)
78026 	/*
78027 	 *  Execution timeout check
78028 	 */
78029 
78030 	if (DUK_USE_EXEC_TIMEOUT_CHECK(thr->heap->heap_udata)) {
78031 		/* Keep throwing an error whenever we get here.  The unusual values
78032 		 * are set this way because no instruction is ever executed, we just
78033 		 * throw an error until all try/catch/finally and other catchpoints
78034 		 * have been exhausted.  Duktape/C code gets control at each protected
78035 		 * call but whenever it enters back into Duktape the RangeError gets
78036 		 * raised.  User exec timeout check must consistently indicate a timeout
78037 		 * until we've fully bubbled out of Duktape.
78038 		 */
78039 		DUK_D(DUK_DPRINT("execution timeout, throwing a RangeError"));
78040 		thr->interrupt_init = 0;
78041 		thr->interrupt_counter = 0;
78042 		DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);
78043 		DUK_ERROR_RANGE(thr, "execution timeout");
78044 		DUK_WO_NORETURN(return 0;);
78045 	}
78046 #endif  /* DUK_USE_EXEC_TIMEOUT_CHECK */
78047 
78048 #if defined(DUK_USE_DEBUGGER_SUPPORT)
78049 	if (!thr->heap->dbg_processing &&
78050 	    (thr->heap->dbg_read_cb != NULL || thr->heap->dbg_detaching)) {
78051 		/* Avoid recursive re-entry; enter when we're attached or
78052 		 * detaching (to finish off the pending detach).
78053 		 */
78054 		duk__interrupt_handle_debugger(thr, &immediate, &retval);
78055 		DUK_ASSERT(act == thr->callstack_curr);
78056 	}
78057 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
78058 
78059 	/*
78060 	 *  Update the interrupt counter
78061 	 */
78062 
78063 	if (immediate) {
78064 		/* Cause an interrupt after executing one instruction. */
78065 		ctr = 1;
78066 	}
78067 
78068 	/* The counter value is one less than the init value: init value should
78069 	 * indicate how many instructions are executed before interrupt.  To
78070 	 * execute 1 instruction (after interrupt handler return), counter must
78071 	 * be 0.
78072 	 */
78073 	DUK_ASSERT(ctr >= 1);
78074 	thr->interrupt_init = ctr;
78075 	thr->interrupt_counter = ctr - 1;
78076 	DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);
78077 
78078 	return retval;
78079 }
78080 #endif  /* DUK_USE_INTERRUPT_COUNTER */
78081 
78082 /*
78083  *  Debugger handling for executor restart
78084  *
78085  *  Check for breakpoints, stepping, etc, and figure out if we should execute
78086  *  in checked or normal mode.  Note that we can't do this when an activation
78087  *  is created, because breakpoint status (and stepping status) may change
78088  *  later, so we must recheck every time we're executing an activation.
78089  *  This primitive should be side effect free to avoid changes during check.
78090  */
78091 
78092 #if defined(DUK_USE_DEBUGGER_SUPPORT)
78093 DUK_LOCAL void duk__executor_recheck_debugger(duk_hthread *thr, duk_activation *act, duk_hcompfunc *fun) {
78094 	duk_heap *heap;
78095 	duk_tval *tv_tmp;
78096 	duk_hstring *filename;
78097 	duk_small_uint_t bp_idx;
78098 	duk_breakpoint **bp_active;
78099 
78100 	DUK_ASSERT(thr != NULL);
78101 	DUK_ASSERT(act != NULL);
78102 	DUK_ASSERT(fun != NULL);
78103 
78104 	heap = thr->heap;
78105 	bp_active = heap->dbg_breakpoints_active;
78106 	act->flags &= ~DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
78107 
78108 	tv_tmp = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) fun, DUK_STRIDX_FILE_NAME);
78109 	if (tv_tmp && DUK_TVAL_IS_STRING(tv_tmp)) {
78110 		filename = DUK_TVAL_GET_STRING(tv_tmp);
78111 
78112 		/* Figure out all active breakpoints.  A breakpoint is
78113 		 * considered active if the current function's fileName
78114 		 * matches the breakpoint's fileName, AND there is no
78115 		 * inner function that has matching line numbers
78116 		 * (otherwise a breakpoint would be triggered both
78117 		 * inside and outside of the inner function which would
78118 		 * be confusing).  Example:
78119 		 *
78120 		 *     function foo() {
78121 		 *         print('foo');
78122 		 *         function bar() {    <-.  breakpoints in these
78123 		 *             print('bar');     |  lines should not affect
78124 		 *         }                   <-'  foo() execution
78125 		 *         bar();
78126 		 *     }
78127 		 *
78128 		 * We need a few things that are only available when
78129 		 * debugger support is enabled: (1) a line range for
78130 		 * each function, and (2) access to the function
78131 		 * template to access the inner functions (and their
78132 		 * line ranges).
78133 		 *
78134 		 * It's important to have a narrow match for active
78135 		 * breakpoints so that we don't enter checked execution
78136 		 * when that's not necessary.  For instance, if we're
78137 		 * running inside a certain function and there's
78138 		 * breakpoint outside in (after the call site), we
78139 		 * don't want to slow down execution of the function.
78140 		 */
78141 
78142 		for (bp_idx = 0; bp_idx < heap->dbg_breakpoint_count; bp_idx++) {
78143 			duk_breakpoint *bp = heap->dbg_breakpoints + bp_idx;
78144 			duk_hobject **funcs, **funcs_end;
78145 			duk_hcompfunc *inner_fun;
78146 			duk_bool_t bp_match;
78147 
78148 			if (bp->filename == filename &&
78149 			    bp->line >= fun->start_line && bp->line <= fun->end_line) {
78150 				bp_match = 1;
78151 				DUK_DD(DUK_DDPRINT("breakpoint filename and line match: "
78152 				                   "%s:%ld vs. %s (line %ld vs. %ld-%ld)",
78153 				                   DUK_HSTRING_GET_DATA(bp->filename),
78154 				                   (long) bp->line,
78155 				                   DUK_HSTRING_GET_DATA(filename),
78156 				                   (long) bp->line,
78157 				                   (long) fun->start_line,
78158 				                   (long) fun->end_line));
78159 
78160 				funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, fun);
78161 				funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, fun);
78162 				while (funcs != funcs_end) {
78163 					inner_fun = (duk_hcompfunc *) *funcs;
78164 					DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) inner_fun));
78165 					if (bp->line >= inner_fun->start_line && bp->line <= inner_fun->end_line) {
78166 						DUK_DD(DUK_DDPRINT("inner function masks ('captures') breakpoint"));
78167 						bp_match = 0;
78168 						break;
78169 					}
78170 					funcs++;
78171 				}
78172 
78173 				if (bp_match) {
78174 					/* No need to check for size of bp_active list,
78175 					 * it's always larger than maximum number of
78176 					 * breakpoints.
78177 					 */
78178 					act->flags |= DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
78179 					*bp_active = heap->dbg_breakpoints + bp_idx;
78180 					bp_active++;
78181 				}
78182 			}
78183 		}
78184 	}
78185 
78186 	*bp_active = NULL;  /* terminate */
78187 
78188 	DUK_DD(DUK_DDPRINT("ACTIVE BREAKPOINTS: %ld", (long) (bp_active - thr->heap->dbg_breakpoints_active)));
78189 
78190 	/* Force pause if we were doing "step into" in another activation. */
78191 	if ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_ENTRY) &&
78192 	    thr->heap->dbg_pause_act != thr->callstack_curr) {
78193 		DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function entry"));
78194 		duk_debug_set_paused(thr->heap);
78195 	}
78196 
78197 	/* Force interrupt right away if we're paused or in "checked mode".
78198 	 * Step out is handled by callstack unwind.
78199 	 */
78200 	if ((act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE) ||
78201 	    DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) ||
78202 	    ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
78203 	     thr->heap->dbg_pause_act == thr->callstack_curr)) {
78204 		/* We'll need to interrupt early so recompute the init
78205 		 * counter to reflect the number of bytecode instructions
78206 		 * executed so that step counts for e.g. debugger rate
78207 		 * limiting are accurate.
78208 		 */
78209 		DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
78210 		thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
78211 		thr->interrupt_counter = 0;
78212 	}
78213 }
78214 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
78215 
78216 /*
78217  *  Opcode handlers for opcodes with a lot of code and which are relatively
78218  *  rare; NOINLINE to reduce amount of code in main bytecode dispatcher.
78219  */
78220 
78221 DUK_LOCAL DUK_EXEC_NOINLINE_PERF void duk__handle_op_initset_initget(duk_hthread *thr, duk_uint_fast32_t ins) {
78222 	duk_bool_t is_set = (DUK_DEC_OP(ins) == DUK_OP_INITSET);
78223 	duk_uint_fast_t idx;
78224 	duk_uint_t defprop_flags;
78225 
78226 	/* A -> object register (acts as a source)
78227 	 * BC -> BC+0 contains key, BC+1 closure (value)
78228 	 */
78229 
78230 	/* INITSET/INITGET are only used to initialize object literal keys.
78231 	 * There may be a previous propery in ES2015 because duplicate property
78232 	 * names are allowed.
78233 	 */
78234 
78235 	/* This could be made more optimal by accessing internals directly. */
78236 
78237 	idx = (duk_uint_fast_t) DUK_DEC_BC(ins);
78238 	duk_dup(thr, (duk_idx_t) (idx + 0));  /* key */
78239 	duk_dup(thr, (duk_idx_t) (idx + 1));  /* getter/setter */
78240 	if (is_set) {
78241 	        defprop_flags = DUK_DEFPROP_HAVE_SETTER |
78242 	                        DUK_DEFPROP_FORCE |
78243 	                        DUK_DEFPROP_SET_ENUMERABLE |
78244 	                        DUK_DEFPROP_SET_CONFIGURABLE;
78245 	} else {
78246 	        defprop_flags = DUK_DEFPROP_HAVE_GETTER |
78247 	                        DUK_DEFPROP_FORCE |
78248 	                        DUK_DEFPROP_SET_ENUMERABLE |
78249 	                        DUK_DEFPROP_SET_CONFIGURABLE;
78250 	}
78251 	duk_def_prop(thr, (duk_idx_t) DUK_DEC_A(ins), defprop_flags);
78252 }
78253 
78254 DUK_LOCAL DUK_EXEC_NOINLINE_PERF void duk__handle_op_trycatch(duk_hthread *thr, duk_uint_fast32_t ins, duk_instr_t *curr_pc) {
78255 	duk_activation *act;
78256 	duk_catcher *cat;
78257 	duk_tval *tv1;
78258 	duk_small_uint_fast_t a;
78259 	duk_small_uint_fast_t bc;
78260 
78261 	/* A -> flags
78262 	 * BC -> reg_catch; base register for two registers used both during
78263 	 *       trycatch setup and when catch is triggered
78264 	 *
78265 	 *      If DUK_BC_TRYCATCH_FLAG_CATCH_BINDING set:
78266 	 *          reg_catch + 0: catch binding variable name (string).
78267 	 *          Automatic declarative environment is established for
78268 	 *          the duration of the 'catch' clause.
78269 	 *
78270 	 *      If DUK_BC_TRYCATCH_FLAG_WITH_BINDING set:
78271 	 *          reg_catch + 0: with 'target value', which is coerced to
78272 	 *          an object and then used as a bindind object for an
78273 	 *          environment record.  The binding is initialized here, for
78274 	 *          the 'try' clause.
78275 	 *
78276 	 * Note that a TRYCATCH generated for a 'with' statement has no
78277 	 * catch or finally parts.
78278 	 */
78279 
78280 	/* XXX: TRYCATCH handling should be reworked to avoid creating
78281 	 * an explicit scope unless it is actually needed (e.g. function
78282 	 * instances or eval is executed inside the catch block).  This
78283 	 * rework is not trivial because the compiler doesn't have an
78284 	 * intermediate representation.  When the rework is done, the
78285 	 * opcode format can also be made more straightforward.
78286 	 */
78287 
78288 	/* XXX: side effect handling is quite awkward here */
78289 
78290 	DUK_DDD(DUK_DDDPRINT("TRYCATCH: reg_catch=%ld, have_catch=%ld, "
78291 	                     "have_finally=%ld, catch_binding=%ld, with_binding=%ld (flags=0x%02lx)",
78292 	                     (long) DUK_DEC_BC(ins),
78293 	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH ? 1 : 0),
78294 	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY ? 1 : 0),
78295 	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING ? 1 : 0),
78296 	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_WITH_BINDING ? 1 : 0),
78297 	                     (unsigned long) DUK_DEC_A(ins)));
78298 
78299 	a = DUK_DEC_A(ins);
78300 	bc = DUK_DEC_BC(ins);
78301 
78302 	/* Registers 'bc' and 'bc + 1' are written in longjmp handling
78303 	 * and if their previous values (which are temporaries) become
78304 	 * unreachable -and- have a finalizer, there'll be a function
78305 	 * call during error handling which is not supported now (GH-287).
78306 	 * Ensure that both 'bc' and 'bc + 1' have primitive values to
78307 	 * guarantee no finalizer calls in error handling.  Scrubbing also
78308 	 * ensures finalizers for the previous values run here rather than
78309 	 * later.  Error handling related values are also written to 'bc'
78310 	 * and 'bc + 1' but those values never become unreachable during
78311 	 * error handling, so there's no side effect problem even if the
78312 	 * error value has a finalizer.
78313 	 */
78314 	duk_dup(thr, (duk_idx_t) bc);  /* Stabilize value. */
78315 	duk_to_undefined(thr, (duk_idx_t) bc);
78316 	duk_to_undefined(thr, (duk_idx_t) (bc + 1));
78317 
78318 	/* Allocate catcher and populate it.  Doesn't have to
78319 	 * be fully atomic, but the catcher must be in a
78320 	 * consistent state if side effects (such as finalizer
78321 	 * calls) occur.
78322 	 */
78323 
78324 	cat = duk_hthread_catcher_alloc(thr);
78325 	DUK_ASSERT(cat != NULL);
78326 
78327 	cat->flags = DUK_CAT_TYPE_TCF;
78328 	cat->h_varname = NULL;
78329 	cat->pc_base = (duk_instr_t *) curr_pc;  /* pre-incremented, points to first jump slot */
78330 	cat->idx_base = (duk_size_t) (thr->valstack_bottom - thr->valstack) + bc;
78331 
78332 	act = thr->callstack_curr;
78333 	DUK_ASSERT(act != NULL);
78334 	cat->parent = act->cat;
78335 	act->cat = cat;
78336 
78337 	if (a & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {
78338 		cat->flags |= DUK_CAT_FLAG_CATCH_ENABLED;
78339 	}
78340 	if (a & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {
78341 		cat->flags |= DUK_CAT_FLAG_FINALLY_ENABLED;
78342 	}
78343 	if (a & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING) {
78344 		DUK_DDD(DUK_DDDPRINT("catch binding flag set to catcher"));
78345 		cat->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED;
78346 		tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
78347 		DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
78348 
78349 		/* borrowed reference; although 'tv1' comes from a register,
78350 		 * its value was loaded using LDCONST so the constant will
78351 		 * also exist and be reachable.
78352 		 */
78353 		cat->h_varname = DUK_TVAL_GET_STRING(tv1);
78354 	} else if (a & DUK_BC_TRYCATCH_FLAG_WITH_BINDING) {
78355 		duk_hobjenv *env;
78356 		duk_hobject *target;
78357 
78358 		/* Delayed env initialization for activation (if needed). */
78359 		DUK_ASSERT(thr->callstack_top >= 1);
78360 		DUK_ASSERT(act == thr->callstack_curr);
78361 		DUK_ASSERT(act != NULL);
78362 		if (act->lex_env == NULL) {
78363 			DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
78364 			DUK_ASSERT(act->var_env == NULL);
78365 
78366 			duk_js_init_activation_environment_records_delayed(thr, act);
78367 			DUK_ASSERT(act == thr->callstack_curr);
78368 			DUK_UNREF(act);  /* 'act' is no longer accessed, scanbuild fix */
78369 		}
78370 		DUK_ASSERT(act->lex_env != NULL);
78371 		DUK_ASSERT(act->var_env != NULL);
78372 
78373 		/* Coerce 'with' target. */
78374 		target = duk_to_hobject(thr, -1);
78375 		DUK_ASSERT(target != NULL);
78376 
78377 		/* Create an object environment; it is not pushed
78378 		 * so avoid side effects very carefully until it is
78379 		 * referenced.
78380 		 */
78381 		env = duk_hobjenv_alloc(thr,
78382 		                        DUK_HOBJECT_FLAG_EXTENSIBLE |
78383 		                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
78384 		DUK_ASSERT(env != NULL);
78385 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
78386 		env->target = target;  /* always provideThis=true */
78387 		DUK_HOBJECT_INCREF(thr, target);
78388 		env->has_this = 1;
78389 		DUK_HOBJENV_ASSERT_VALID(env);
78390 		DUK_DDD(DUK_DDDPRINT("environment for with binding: %!iO", env));
78391 
78392 		DUK_ASSERT(act == thr->callstack_curr);
78393 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
78394 		DUK_ASSERT(act->lex_env != NULL);
78395 		DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) env, act->lex_env);
78396 		act->lex_env = (duk_hobject *) env;  /* Now reachable. */
78397 		DUK_HOBJECT_INCREF(thr, (duk_hobject *) env);
78398 		/* Net refcount change to act->lex_env is 0: incref for env's
78399 		 * prototype, decref for act->lex_env overwrite.
78400 		 */
78401 
78402 		/* Set catcher lex_env active (affects unwind)
78403 		 * only when the whole setup is complete.
78404 		 */
78405 		cat = act->cat;  /* XXX: better to relookup? not mandatory because 'cat' is stable */
78406 		cat->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE;
78407 	} else {
78408 		;
78409 	}
78410 
78411 	DUK_DDD(DUK_DDDPRINT("TRYCATCH catcher: flags=0x%08lx, pc_base=%ld, "
78412 	                     "idx_base=%ld, h_varname=%!O",
78413 	                     (unsigned long) cat->flags,
78414 	                     (long) cat->pc_base, (long) cat->idx_base, (duk_heaphdr *) cat->h_varname));
78415 
78416 	duk_pop_unsafe(thr);
78417 }
78418 
78419 DUK_LOCAL DUK_EXEC_NOINLINE_PERF duk_instr_t *duk__handle_op_endtry(duk_hthread *thr, duk_uint_fast32_t ins) {
78420 	duk_activation *act;
78421 	duk_catcher *cat;
78422 	duk_tval *tv1;
78423 	duk_instr_t *pc_base;
78424 
78425 	DUK_UNREF(ins);
78426 
78427 	DUK_ASSERT(thr->callstack_top >= 1);
78428 	act = thr->callstack_curr;
78429 	DUK_ASSERT(act != NULL);
78430 	cat = act->cat;
78431 	DUK_ASSERT(cat != NULL);
78432 	DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);
78433 
78434 	DUK_DDD(DUK_DDDPRINT("ENDTRY: clearing catch active flag (regardless of whether it was set or not)"));
78435 	DUK_CAT_CLEAR_CATCH_ENABLED(cat);
78436 
78437 	pc_base = cat->pc_base;
78438 
78439 	if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
78440 		DUK_DDD(DUK_DDDPRINT("ENDTRY: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
78441 
78442 		tv1 = thr->valstack + cat->idx_base;
78443 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
78444 		DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
78445 		tv1 = NULL;
78446 
78447 		tv1 = thr->valstack + cat->idx_base + 1;
78448 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
78449 		DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL);  /* side effects */
78450 		tv1 = NULL;
78451 
78452 		DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
78453 	} else {
78454 		DUK_DDD(DUK_DDDPRINT("ENDTRY: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
78455 
78456 		duk_hthread_catcher_unwind_norz(thr, act);  /* lexenv may be set for 'with' binding */
78457 		/* no need to unwind callstack */
78458 	}
78459 
78460 	return pc_base + 1;  /* new curr_pc value */
78461 }
78462 
78463 DUK_LOCAL DUK_EXEC_NOINLINE_PERF duk_instr_t *duk__handle_op_endcatch(duk_hthread *thr, duk_uint_fast32_t ins) {
78464 	duk_activation *act;
78465 	duk_catcher *cat;
78466 	duk_tval *tv1;
78467 	duk_instr_t *pc_base;
78468 
78469 	DUK_UNREF(ins);
78470 
78471 	DUK_ASSERT(thr->callstack_top >= 1);
78472 	act = thr->callstack_curr;
78473 	DUK_ASSERT(act != NULL);
78474 	cat = act->cat;
78475 	DUK_ASSERT(cat != NULL);
78476 	DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat));  /* cleared before entering catch part */
78477 
78478 	if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
78479 		duk_hobject *prev_env;
78480 
78481 		/* 'with' binding has no catch clause, so can't be here unless a normal try-catch */
78482 		DUK_ASSERT(DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat));
78483 		DUK_ASSERT(act->lex_env != NULL);
78484 
78485 		DUK_DDD(DUK_DDDPRINT("ENDCATCH: popping catcher part lexical environment"));
78486 
78487 		prev_env = act->lex_env;
78488 		DUK_ASSERT(prev_env != NULL);
78489 		act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, prev_env);
78490 		DUK_CAT_CLEAR_LEXENV_ACTIVE(cat);
78491 		DUK_HOBJECT_INCREF(thr, act->lex_env);
78492 		DUK_HOBJECT_DECREF(thr, prev_env);  /* side effects */
78493 
78494 		DUK_ASSERT(act == thr->callstack_curr);
78495 		DUK_ASSERT(act != NULL);
78496 	}
78497 
78498 	pc_base = cat->pc_base;
78499 
78500 	if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
78501 		DUK_DDD(DUK_DDDPRINT("ENDCATCH: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
78502 
78503 		tv1 = thr->valstack + cat->idx_base;
78504 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
78505 		DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
78506 		tv1 = NULL;
78507 
78508 		tv1 = thr->valstack + cat->idx_base + 1;
78509 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
78510 		DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL);  /* side effects */
78511 		tv1 = NULL;
78512 
78513 		DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
78514 	} else {
78515 		DUK_DDD(DUK_DDDPRINT("ENDCATCH: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
78516 
78517 		duk_hthread_catcher_unwind_norz(thr, act);
78518 		/* no need to unwind callstack */
78519 	}
78520 
78521 	return pc_base + 1;  /* new curr_pc value */
78522 }
78523 
78524 DUK_LOCAL DUK_EXEC_NOINLINE_PERF duk_small_uint_t duk__handle_op_endfin(duk_hthread *thr, duk_uint_fast32_t ins, duk_activation *entry_act) {
78525 	duk_activation *act;
78526 	duk_tval *tv1;
78527 	duk_uint_t reg_catch;
78528 	duk_small_uint_t cont_type;
78529 	duk_small_uint_t ret_result;
78530 
78531 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
78532 	DUK_ASSERT(thr->callstack_top >= 1);
78533 	act = thr->callstack_curr;
78534 	DUK_ASSERT(act != NULL);
78535 	reg_catch = DUK_DEC_ABC(ins);
78536 
78537 	/* CATCH flag may be enabled or disabled here; it may be enabled if
78538 	 * the statement has a catch block but the try block does not throw
78539 	 * an error.
78540 	 */
78541 
78542 	DUK_DDD(DUK_DDDPRINT("ENDFIN: completion value=%!T, type=%!T",
78543 	                     (duk_tval *) (thr->valstack_bottom + reg_catch + 0),
78544 	                     (duk_tval *) (thr->valstack_bottom + reg_catch + 1)));
78545 
78546 	tv1 = thr->valstack_bottom + reg_catch + 1;  /* type */
78547 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
78548 #if defined(DUK_USE_FASTINT)
78549 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
78550 	cont_type = (duk_small_uint_t) DUK_TVAL_GET_FASTINT_U32(tv1);
78551 #else
78552 	cont_type = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
78553 #endif
78554 
78555 	tv1--;  /* value */
78556 
78557 	switch (cont_type) {
78558 	case DUK_LJ_TYPE_NORMAL: {
78559 		DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'normal' (non-abrupt) completion -> "
78560 		                     "dismantle catcher, resume execution after ENDFIN"));
78561 
78562 		duk_hthread_catcher_unwind_norz(thr, act);
78563 		/* no need to unwind callstack */
78564 		return 0;  /* restart execution */
78565 	}
78566 	case DUK_LJ_TYPE_RETURN: {
78567 		DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'return' complation -> dismantle "
78568 		                     "catcher, handle return, lj.value1=%!T", tv1));
78569 
78570 		/* Not necessary to unwind catch stack: return handling will
78571 		 * do it.  The finally flag of 'cat' is no longer set.  The
78572 		 * catch flag may be set, but it's not checked by return handling.
78573 		 */
78574 
78575 		duk_push_tval(thr, tv1);
78576 		ret_result = duk__handle_return(thr, entry_act);
78577 		if (ret_result == DUK__RETHAND_RESTART) {
78578 			return 0;  /* restart execution */
78579 		}
78580 		DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED);
78581 
78582 		DUK_DDD(DUK_DDDPRINT("exiting executor after ENDFIN and RETURN (pseudo) longjmp type"));
78583 		return 1;  /* exit executor */
78584 	}
78585 	case DUK_LJ_TYPE_BREAK:
78586 	case DUK_LJ_TYPE_CONTINUE: {
78587 		duk_uint_t label_id;
78588 		duk_small_uint_t lj_type;
78589 
78590 		/* Not necessary to unwind catch stack: break/continue
78591 		 * handling will do it.  The finally flag of 'cat' is
78592 		 * no longer set.  The catch flag may be set, but it's
78593 		 * not checked by break/continue handling.
78594 		 */
78595 
78596 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
78597 #if defined(DUK_USE_FASTINT)
78598 		DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
78599 		label_id = (duk_small_uint_t) DUK_TVAL_GET_FASTINT_U32(tv1);
78600 #else
78601 		label_id = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
78602 #endif
78603 		lj_type = cont_type;
78604 		duk__handle_break_or_continue(thr, label_id, lj_type);
78605 		return 0;  /* restart execution */
78606 	}
78607 	default: {
78608 		DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with abrupt completion, lj_type=%ld -> "
78609 		                     "dismantle catcher, re-throw error",
78610 		                     (long) cont_type));
78611 
78612 		duk_err_setup_ljstate1(thr, (duk_small_uint_t) cont_type, tv1);
78613 		/* No debugger Throw notify check on purpose (rethrow). */
78614 
78615 		DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* always in executor */
78616 		duk_err_longjmp(thr);
78617 		DUK_UNREACHABLE();
78618 	}
78619 	}
78620 
78621 	DUK_UNREACHABLE();
78622 	return 0;
78623 }
78624 
78625 DUK_LOCAL DUK_EXEC_NOINLINE_PERF void duk__handle_op_initenum(duk_hthread *thr, duk_uint_fast32_t ins) {
78626 	duk_small_uint_t b;
78627 	duk_small_uint_t c;
78628 
78629 	/*
78630 	 *  Enumeration semantics come from for-in statement, E5 Section 12.6.4.
78631 	 *  If called with 'null' or 'undefined', this opcode returns 'null' as
78632 	 *  the enumerator, which is special cased in NEXTENUM.  This simplifies
78633 	 *  the compiler part
78634 	 */
78635 
78636 	/* B -> register for writing enumerator object
78637 	 * C -> value to be enumerated (register)
78638 	 */
78639 	b = DUK_DEC_B(ins);
78640 	c = DUK_DEC_C(ins);
78641 
78642 	if (duk_is_null_or_undefined(thr, (duk_idx_t) c)) {
78643 		duk_push_null(thr);
78644 		duk_replace(thr, (duk_idx_t) b);
78645 	} else {
78646 		duk_dup(thr, (duk_idx_t) c);
78647 		duk_to_object(thr, -1);
78648 		duk_hobject_enumerator_create(thr, 0 /*enum_flags*/);  /* [ ... val ] --> [ ... enum ] */
78649 		duk_replace(thr, (duk_idx_t) b);
78650 	}
78651 }
78652 
78653 DUK_LOCAL DUK_EXEC_NOINLINE_PERF duk_small_uint_t duk__handle_op_nextenum(duk_hthread *thr, duk_uint_fast32_t ins) {
78654 	duk_small_uint_t b;
78655 	duk_small_uint_t c;
78656 	duk_small_uint_t pc_skip = 0;
78657 
78658 	/*
78659 	 *  NEXTENUM checks whether the enumerator still has unenumerated
78660 	 *  keys.  If so, the next key is loaded to the target register
78661 	 *  and the next instruction is skipped.  Otherwise the next instruction
78662 	 *  will be executed, jumping out of the enumeration loop.
78663 	 */
78664 
78665 	/* B -> target register for next key
78666 	 * C -> enum register
78667 	 */
78668 	b = DUK_DEC_B(ins);
78669 	c = DUK_DEC_C(ins);
78670 
78671 	DUK_DDD(DUK_DDDPRINT("NEXTENUM: b->%!T, c->%!T",
78672 	                     (duk_tval *) duk_get_tval(thr, (duk_idx_t) b),
78673 	                     (duk_tval *) duk_get_tval(thr, (duk_idx_t) c)));
78674 
78675 	if (duk_is_object(thr, (duk_idx_t) c)) {
78676 		/* XXX: assert 'c' is an enumerator */
78677 		duk_dup(thr, (duk_idx_t) c);
78678 		if (duk_hobject_enumerator_next(thr, 0 /*get_value*/)) {
78679 			/* [ ... enum ] -> [ ... next_key ] */
78680 			DUK_DDD(DUK_DDDPRINT("enum active, next key is %!T, skip jump slot ",
78681 			                     (duk_tval *) duk_get_tval(thr, -1)));
78682 			pc_skip = 1;
78683 		} else {
78684 			/* [ ... enum ] -> [ ... ] */
78685 			DUK_DDD(DUK_DDDPRINT("enum finished, execute jump slot"));
78686 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */
78687 			thr->valstack_top++;
78688 		}
78689 		duk_replace(thr, (duk_idx_t) b);
78690 	} else {
78691 		/* 'null' enumerator case -> behave as with an empty enumerator */
78692 		DUK_ASSERT(duk_is_null(thr, (duk_idx_t) c));
78693 		DUK_DDD(DUK_DDDPRINT("enum is null, execute jump slot"));
78694 	}
78695 
78696 	return pc_skip;
78697 }
78698 
78699 /*
78700  *  Call handling helpers.
78701  */
78702 
78703 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) {
78704 	duk_bool_t rc;
78705 
78706 	duk_set_top_unsafe(thr, (duk_idx_t) (idx + nargs + 2));   /* [ ... func this arg1 ... argN ] */
78707 
78708 	/* Attempt an Ecma-to-Ecma call setup.  If the call
78709 	 * target is (directly or indirectly) Reflect.construct(),
78710 	 * the call may change into a constructor call on the fly.
78711 	 */
78712 	rc = (duk_bool_t) duk_handle_call_unprotected(thr, idx, call_flags);
78713 	if (rc != 0) {
78714 		/* Ecma-to-ecma call possible, may or may not
78715 		 * be a tail call.  Avoid C recursion by
78716 		 * reusing current executor instance.
78717 		 */
78718 		DUK_DDD(DUK_DDDPRINT("ecma-to-ecma call setup possible, restart execution"));
78719 		/* curr_pc synced by duk_handle_call_unprotected() */
78720 		DUK_ASSERT(thr->ptr_curr_pc == NULL);
78721 		return rc;
78722 	} else {
78723 		/* Call was handled inline. */
78724 	}
78725 	DUK_ASSERT(thr->ptr_curr_pc != NULL);
78726 	return rc;
78727 }
78728 
78729 /*
78730  *  ECMAScript bytecode executor.
78731  *
78732  *  Resume execution for the current thread from its current activation.
78733  *  Returns when execution would return from the entry level activation,
78734  *  leaving a single return value on top of the stack.  Function calls
78735  *  and thread resumptions are handled internally.  If an error occurs,
78736  *  a longjmp() with type DUK_LJ_TYPE_THROW is called on the entry level
78737  *  setjmp() jmpbuf.
78738  *
78739  *  ECMAScript function calls and coroutine resumptions are handled
78740  *  internally (by the outer executor function) without recursive C calls.
78741  *  Other function calls are handled using duk_handle_call(), increasing
78742  *  C recursion depth.
78743  *
78744  *  Abrupt completions (= long control tranfers) are handled either
78745  *  directly by reconfiguring relevant stacks and restarting execution,
78746  *  or via a longjmp.  Longjmp-free handling is preferable for performance
78747  *  (especially Emscripten performance), and is used for: break, continue,
78748  *  and return.
78749  *
78750  *  For more detailed notes, see doc/execution.rst.
78751  *
78752  *  Also see doc/code-issues.rst for discussion of setjmp(), longjmp(),
78753  *  and volatile.
78754  */
78755 
78756 /* Presence of 'fun' is config based, there's a marginal performance
78757  * difference and the best option is architecture dependent.
78758  */
78759 #if defined(DUK_USE_EXEC_FUN_LOCAL)
78760 #define DUK__FUN()          fun
78761 #else
78762 #define DUK__FUN()          ((duk_hcompfunc *) DUK_ACT_GET_FUNC((thr)->callstack_curr))
78763 #endif
78764 
78765 /* Strict flag. */
78766 #define DUK__STRICT()       ((duk_small_uint_t) DUK_HOBJECT_HAS_STRICT((duk_hobject *) DUK__FUN()))
78767 
78768 /* Reg/const access macros: these are very footprint and performance sensitive
78769  * so modify with care.  Arguments are sometimes evaluated multiple times which
78770  * is not ideal.
78771  */
78772 #define DUK__REG(x)         (*(thr->valstack_bottom + (x)))
78773 #define DUK__REGP(x)        (thr->valstack_bottom + (x))
78774 #define DUK__CONST(x)       (*(consts + (x)))
78775 #define DUK__CONSTP(x)      (consts + (x))
78776 
78777 /* Reg/const access macros which take the 32-bit instruction and avoid an
78778  * explicit field decoding step by using shifts and masks.  These must be
78779  * kept in sync with duk_js_bytecode.h.  The shift/mask values are chosen
78780  * so that 'ins' can be shifted and masked and used as a -byte- offset
78781  * instead of a duk_tval offset which needs further shifting (which is an
78782  * issue on some, but not all, CPUs).
78783  */
78784 #define DUK__RCBIT_B           DUK_BC_REGCONST_B
78785 #define DUK__RCBIT_C           DUK_BC_REGCONST_C
78786 #if defined(DUK_USE_EXEC_REGCONST_OPTIMIZE)
78787 #if defined(DUK_USE_PACKED_TVAL)
78788 #define DUK__TVAL_SHIFT        3  /* sizeof(duk_tval) == 8 */
78789 #else
78790 #define DUK__TVAL_SHIFT        4  /* sizeof(duk_tval) == 16; not always the case so also asserted for */
78791 #endif
78792 #define DUK__SHIFT_A           (DUK_BC_SHIFT_A - DUK__TVAL_SHIFT)
78793 #define DUK__SHIFT_B           (DUK_BC_SHIFT_B - DUK__TVAL_SHIFT)
78794 #define DUK__SHIFT_C           (DUK_BC_SHIFT_C - DUK__TVAL_SHIFT)
78795 #define DUK__SHIFT_BC          (DUK_BC_SHIFT_BC - DUK__TVAL_SHIFT)
78796 #define DUK__MASK_A            (DUK_BC_UNSHIFTED_MASK_A << DUK__TVAL_SHIFT)
78797 #define DUK__MASK_B            (DUK_BC_UNSHIFTED_MASK_B << DUK__TVAL_SHIFT)
78798 #define DUK__MASK_C            (DUK_BC_UNSHIFTED_MASK_C << DUK__TVAL_SHIFT)
78799 #define DUK__MASK_BC           (DUK_BC_UNSHIFTED_MASK_BC << DUK__TVAL_SHIFT)
78800 #define DUK__BYTEOFF_A(ins)    (((ins) >> DUK__SHIFT_A) & DUK__MASK_A)
78801 #define DUK__BYTEOFF_B(ins)    (((ins) >> DUK__SHIFT_B) & DUK__MASK_B)
78802 #define DUK__BYTEOFF_C(ins)    (((ins) >> DUK__SHIFT_C) & DUK__MASK_C)
78803 #define DUK__BYTEOFF_BC(ins)   (((ins) >> DUK__SHIFT_BC) & DUK__MASK_BC)
78804 
78805 #define DUK__REGP_A(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_A((ins))))
78806 #define DUK__REGP_B(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_B((ins))))
78807 #define DUK__REGP_C(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_C((ins))))
78808 #define DUK__REGP_BC(ins)      ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_BC((ins))))
78809 #define DUK__CONSTP_A(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_A((ins))))
78810 #define DUK__CONSTP_B(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_B((ins))))
78811 #define DUK__CONSTP_C(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_C((ins))))
78812 #define DUK__CONSTP_BC(ins)    ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_BC((ins))))
78813 #define DUK__REGCONSTP_B(ins)  ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) & DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_B((ins))))
78814 #define DUK__REGCONSTP_C(ins)  ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) & DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_C((ins))))
78815 #else  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
78816 /* Safe alternatives, no assumption about duk_tval size. */
78817 #define DUK__REGP_A(ins)       DUK__REGP(DUK_DEC_A((ins)))
78818 #define DUK__REGP_B(ins)       DUK__REGP(DUK_DEC_B((ins)))
78819 #define DUK__REGP_C(ins)       DUK__REGP(DUK_DEC_C((ins)))
78820 #define DUK__REGP_BC(ins)      DUK__REGP(DUK_DEC_BC((ins)))
78821 #define DUK__CONSTP_A(ins)     DUK__CONSTP(DUK_DEC_A((ins)))
78822 #define DUK__CONSTP_B(ins)     DUK__CONSTP(DUK_DEC_B((ins)))
78823 #define DUK__CONSTP_C(ins)     DUK__CONSTP(DUK_DEC_C((ins)))
78824 #define DUK__CONSTP_BC(ins)    DUK__CONSTP(DUK_DEC_BC((ins)))
78825 #define DUK__REGCONSTP_B(ins)  ((((ins) & DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK_DEC_B((ins)))
78826 #define DUK__REGCONSTP_C(ins)  ((((ins) & DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK_DEC_C((ins)))
78827 #endif  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
78828 
78829 #if defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS)
78830 #define DUK__INTERNAL_ERROR(msg)  do { \
78831 		DUK_ERROR_ERROR(thr, (msg)); \
78832 		DUK_WO_NORETURN(return;); \
78833 	} while (0)
78834 #else
78835 #define DUK__INTERNAL_ERROR(msg)  do { \
78836 		goto internal_error; \
78837 	} while (0)
78838 #endif
78839 
78840 #define DUK__SYNC_CURR_PC()  do { \
78841 		duk_activation *duk__act; \
78842 		duk__act = thr->callstack_curr; \
78843 		duk__act->curr_pc = curr_pc; \
78844 	} while (0)
78845 #define DUK__SYNC_AND_NULL_CURR_PC()  do { \
78846 		duk_activation *duk__act; \
78847 		duk__act = thr->callstack_curr; \
78848 		duk__act->curr_pc = curr_pc; \
78849 		thr->ptr_curr_pc = NULL; \
78850 	} while (0)
78851 
78852 #if defined(DUK_USE_EXEC_PREFER_SIZE)
78853 #define DUK__LOOKUP_INDIRECT(idx) do { \
78854 		(idx) = (duk_uint_fast_t) duk_get_uint(thr, (duk_idx_t) (idx)); \
78855 	} while (0)
78856 #elif defined(DUK_USE_FASTINT)
78857 #define DUK__LOOKUP_INDIRECT(idx) do { \
78858 		duk_tval *tv_ind; \
78859 		tv_ind = DUK__REGP((idx)); \
78860 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind)); \
78861 		DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_ind));  /* compiler guarantees */ \
78862 		(idx) = (duk_uint_fast_t) DUK_TVAL_GET_FASTINT_U32(tv_ind); \
78863 	} while (0)
78864 #else
78865 #define DUK__LOOKUP_INDIRECT(idx) do { \
78866 		duk_tval *tv_ind; \
78867 		tv_ind = DUK__REGP(idx); \
78868 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind)); \
78869 		idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind); \
78870 	} while (0)
78871 #endif
78872 
78873 DUK_LOCAL void duk__handle_executor_error(duk_heap *heap,
78874                                           duk_activation *entry_act,
78875                                           duk_int_t entry_call_recursion_depth,
78876                                           duk_jmpbuf *entry_jmpbuf_ptr,
78877                                           volatile duk_bool_t *out_delayed_catch_setup) {
78878 	duk_small_uint_t lj_ret;
78879 
78880 	/* Longjmp callers are required to sync-and-null thr->ptr_curr_pc
78881 	 * before longjmp.
78882 	 */
78883 	DUK_ASSERT(heap->curr_thread != NULL);
78884 	DUK_ASSERT(heap->curr_thread->ptr_curr_pc == NULL);
78885 
78886 	/* XXX: signalling the need to shrink check (only if unwound) */
78887 
78888 	/* Must be restored here to handle e.g. yields properly. */
78889 	heap->call_recursion_depth = entry_call_recursion_depth;
78890 
78891 	/* Switch to caller's setjmp() catcher so that if an error occurs
78892 	 * during error handling, it is always propagated outwards instead
78893 	 * of causing an infinite loop in our own handler.
78894 	 */
78895 	heap->lj.jmpbuf_ptr = (duk_jmpbuf *) entry_jmpbuf_ptr;
78896 
78897 	lj_ret = duk__handle_longjmp(heap->curr_thread, entry_act, out_delayed_catch_setup);
78898 
78899 	/* Error handling complete, remove side effect protections.
78900 	 */
78901 #if defined(DUK_USE_ASSERTIONS)
78902 	DUK_ASSERT(heap->error_not_allowed == 1);
78903 	heap->error_not_allowed = 0;
78904 #endif
78905 	DUK_ASSERT(heap->pf_prevent_count > 0);
78906 	heap->pf_prevent_count--;
78907 	DUK_DD(DUK_DDPRINT("executor error handled, pf_prevent_count updated to %ld", (long) heap->pf_prevent_count));
78908 
78909 	if (lj_ret == DUK__LONGJMP_RESTART) {
78910 		/* Restart bytecode execution, possibly with a changed thread. */
78911 		DUK_REFZERO_CHECK_SLOW(heap->curr_thread);
78912 	} else {
78913 		/* If an error is propagated, don't run refzero checks here.
78914 		 * The next catcher will deal with that.  Pf_prevent_count
78915 		 * will be re-bumped by the longjmp.
78916 		 */
78917 
78918 		DUK_ASSERT(lj_ret == DUK__LONGJMP_RETHROW);  /* Rethrow error to calling state. */
78919 		DUK_ASSERT(heap->lj.jmpbuf_ptr == entry_jmpbuf_ptr);  /* Longjmp handling has restored jmpbuf_ptr. */
78920 
78921 		/* Thread may have changed, e.g. YIELD converted to THROW. */
78922 		duk_err_longjmp(heap->curr_thread);
78923 		DUK_UNREACHABLE();
78924 	}
78925 }
78926 
78927 /* Outer executor with setjmp/longjmp handling. */
78928 DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) {
78929 	/* Entry level info. */
78930 	duk_hthread *entry_thread;
78931 	duk_activation *entry_act;
78932 	duk_int_t entry_call_recursion_depth;
78933 	duk_jmpbuf *entry_jmpbuf_ptr;
78934 	duk_jmpbuf our_jmpbuf;
78935 	duk_heap *heap;
78936 	volatile duk_bool_t delayed_catch_setup = 0;
78937 
78938 	DUK_ASSERT(exec_thr != NULL);
78939 	DUK_ASSERT(exec_thr->heap != NULL);
78940 	DUK_ASSERT(exec_thr->heap->curr_thread != NULL);
78941 	DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR((duk_heaphdr *) exec_thr);
78942 	DUK_ASSERT(exec_thr->callstack_top >= 1);  /* at least one activation, ours */
78943 	DUK_ASSERT(exec_thr->callstack_curr != NULL);
78944 	DUK_ASSERT(DUK_ACT_GET_FUNC(exec_thr->callstack_curr) != NULL);
78945 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(exec_thr->callstack_curr)));
78946 
78947 	DUK_GC_TORTURE(exec_thr->heap);
78948 
78949 	entry_thread = exec_thr;
78950 	heap = entry_thread->heap;
78951 	entry_act = entry_thread->callstack_curr;
78952 	DUK_ASSERT(entry_act != NULL);
78953 	entry_call_recursion_depth = entry_thread->heap->call_recursion_depth;
78954 	entry_jmpbuf_ptr = entry_thread->heap->lj.jmpbuf_ptr;
78955 
78956 	/*
78957 	 *  Note: we currently assume that the setjmp() catchpoint is
78958 	 *  not re-entrant (longjmp() cannot be called more than once
78959 	 *  for a single setjmp()).
78960 	 *
78961 	 *  See doc/code-issues.rst for notes on variable assignment
78962 	 *  before and after setjmp().
78963 	 */
78964 
78965 	for (;;) {
78966 		heap->lj.jmpbuf_ptr = &our_jmpbuf;
78967 		DUK_ASSERT(heap->lj.jmpbuf_ptr != NULL);
78968 
78969 #if defined(DUK_USE_CPP_EXCEPTIONS)
78970 		try {
78971 #else
78972 		DUK_ASSERT(heap->lj.jmpbuf_ptr == &our_jmpbuf);
78973 		if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
78974 #endif
78975 			DUK_DDD(DUK_DDDPRINT("after setjmp, delayed catch setup: %ld\n", (long) delayed_catch_setup));
78976 
78977 			if (DUK_UNLIKELY(delayed_catch_setup != 0)) {
78978 				duk_hthread *thr = entry_thread->heap->curr_thread;
78979 
78980 				delayed_catch_setup = 0;
78981 				duk__handle_catch_part2(thr);
78982 				DUK_ASSERT(delayed_catch_setup == 0);
78983 				DUK_DDD(DUK_DDDPRINT("top after delayed catch setup: %ld", (long) duk_get_top(entry_thread)));
78984 			}
78985 
78986 			/* Execute bytecode until returned or longjmp(). */
78987 			duk__js_execute_bytecode_inner(entry_thread, entry_act);
78988 
78989 			/* Successful return: restore jmpbuf and return to caller. */
78990 			heap->lj.jmpbuf_ptr = entry_jmpbuf_ptr;
78991 
78992 			return;
78993 #if defined(DUK_USE_CPP_EXCEPTIONS)
78994 		} catch (duk_internal_exception &exc) {
78995 #else
78996 		} else {
78997 #endif
78998 #if defined(DUK_USE_CPP_EXCEPTIONS)
78999 			DUK_UNREF(exc);
79000 #endif
79001 			DUK_DDD(DUK_DDDPRINT("longjmp caught by bytecode executor"));
79002 			DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
79003 
79004 			duk__handle_executor_error(heap,
79005 			                           entry_act,
79006 			                           entry_call_recursion_depth,
79007 			                           entry_jmpbuf_ptr,
79008 						   &delayed_catch_setup);
79009 		}
79010 #if defined(DUK_USE_CPP_EXCEPTIONS)
79011 		catch (duk_fatal_exception &exc) {
79012 			DUK_D(DUK_DPRINT("rethrow duk_fatal_exception"));
79013 			DUK_UNREF(exc);
79014 			throw;
79015 		} catch (std::exception &exc) {
79016 			const char *what = exc.what();
79017 			if (!what) {
79018 				what = "unknown";
79019 			}
79020 			DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
79021 			DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
79022 			try {
79023 				DUK_ASSERT(heap->curr_thread != NULL);
79024 				DUK_ERROR_FMT1(heap->curr_thread, DUK_ERR_TYPE_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
79025 				DUK_WO_NORETURN(return;);
79026 			} catch (duk_internal_exception exc) {
79027 				DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
79028 				DUK_UNREF(exc);
79029 				duk__handle_executor_error(heap,
79030 				                           entry_act,
79031 				                           entry_call_recursion_depth,
79032 				                           entry_jmpbuf_ptr,
79033 							   &delayed_catch_setup);
79034 			}
79035 		} catch (...) {
79036 			DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
79037 			DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
79038 			try {
79039 				DUK_ASSERT(heap->curr_thread != NULL);
79040 				DUK_ERROR_TYPE(heap->curr_thread, "caught invalid c++ exception (perhaps thrown by user code)");
79041 				DUK_WO_NORETURN(return;);
79042 			} catch (duk_internal_exception exc) {
79043 				DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
79044 				DUK_UNREF(exc);
79045 				duk__handle_executor_error(heap,
79046 				                           entry_act,
79047 				                           entry_call_recursion_depth,
79048 				                           entry_jmpbuf_ptr,
79049 							   &delayed_catch_setup);
79050 			}
79051 		}
79052 #endif
79053 	}
79054 
79055 	DUK_WO_NORETURN(return;);
79056 }
79057 
79058 /* Inner executor, performance critical. */
79059 DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_activation *entry_act) {
79060 	/* Current PC, accessed by other functions through thr->ptr_to_curr_pc.
79061 	 * Critical for performance.  It would be safest to make this volatile,
79062 	 * but that eliminates performance benefits; aliasing guarantees
79063 	 * should be enough though.
79064 	 */
79065 	duk_instr_t *curr_pc;         /* bytecode has a stable pointer */
79066 
79067 	/* Hot variables for interpretation.  Critical for performance,
79068 	 * but must add sparingly to minimize register shuffling.
79069 	 */
79070 	duk_hthread *thr;             /* stable */
79071 	duk_tval *consts;             /* stable */
79072 	duk_uint_fast32_t ins;
79073 	/* 'funcs' is quite rarely used, so no local for it */
79074 #if defined(DUK_USE_EXEC_FUN_LOCAL)
79075 	duk_hcompfunc *fun;
79076 #else
79077 	/* 'fun' is quite rarely used, so no local for it */
79078 #endif
79079 
79080 #if defined(DUK_USE_INTERRUPT_COUNTER)
79081 	duk_int_t int_ctr;
79082 #endif
79083 
79084 #if defined(DUK_USE_ASSERTIONS)
79085 	duk_size_t valstack_top_base;    /* valstack top, should match before interpreting each op (no leftovers) */
79086 #endif
79087 
79088 	/* Optimized reg/const access macros assume sizeof(duk_tval) to be
79089 	 * either 8 or 16.  Heap allocation checks this even without asserts
79090 	 * enabled now because it can't be autodetected in duk_config.h.
79091 	 */
79092 #if 1
79093 #if defined(DUK_USE_PACKED_TVAL)
79094 	DUK_ASSERT(sizeof(duk_tval) == 8);
79095 #else
79096 	DUK_ASSERT(sizeof(duk_tval) == 16);
79097 #endif
79098 #endif
79099 
79100 	DUK_GC_TORTURE(entry_thread->heap);
79101 
79102 	/*
79103 	 *  Restart execution by reloading thread state.
79104 	 *
79105 	 *  Note that 'thr' and any thread configuration may have changed,
79106 	 *  so all local variables are suspect and we need to reinitialize.
79107 	 *
79108 	 *  The number of local variables should be kept to a minimum: if
79109 	 *  the variables are spilled, they will need to be loaded from
79110 	 *  memory anyway.
79111 	 *
79112 	 *  Any 'goto restart_execution;' code path in opcode dispatch must
79113 	 *  ensure 'curr_pc' is synced back to act->curr_pc before the goto
79114 	 *  takes place.
79115 	 *
79116 	 *  The interpreter must be very careful with memory pointers, as
79117 	 *  many pointers are not guaranteed to be 'stable' and may be
79118 	 *  reallocated and relocated on-the-fly quite easily (e.g. by a
79119 	 *  memory allocation or a property access).
79120 	 *
79121 	 *  The following are assumed to have stable pointers:
79122 	 *    - the current thread
79123 	 *    - the current function
79124 	 *    - the bytecode, constant table, inner function table of the
79125 	 *      current function (as they are a part of the function allocation)
79126 	 *
79127 	 *  The following are assumed to have semi-stable pointers:
79128 	 *    - the current activation entry: stable as long as callstack
79129 	 *      is not changed (reallocated by growing or shrinking), or
79130 	 *      by any garbage collection invocation (through finalizers)
79131 	 *    - Note in particular that ANY DECREF can invalidate the
79132 	 *      activation pointer, so for the most part a fresh lookup
79133 	 *      is required
79134 	 *
79135 	 *  The following are not assumed to have stable pointers at all:
79136 	 *    - the value stack (registers) of the current thread
79137 	 *
79138 	 *  See execution.rst for discussion.
79139 	 */
79140 
79141  restart_execution:
79142 
79143 	/* Lookup current thread; use the stable 'entry_thread' for this to
79144 	 * avoid clobber warnings.  Any valid, reachable 'thr' value would be
79145 	 * fine for this, so using 'entry_thread' is just to silence warnings.
79146 	 */
79147 	thr = entry_thread->heap->curr_thread;
79148 	DUK_ASSERT(thr != NULL);
79149 	DUK_ASSERT(thr->callstack_top >= 1);
79150 	DUK_ASSERT(thr->callstack_curr != NULL);
79151 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
79152 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
79153 
79154 	DUK_GC_TORTURE(thr->heap);
79155 
79156 	thr->ptr_curr_pc = &curr_pc;
79157 
79158 	/* Relookup and initialize dispatch loop variables.  Debugger check. */
79159 	{
79160 		duk_activation *act;
79161 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
79162 		duk_hcompfunc *fun;
79163 #endif
79164 
79165 		/* Assume interrupt init/counter are properly initialized here. */
79166 		/* Assume that thr->valstack_bottom has been set-up before getting here. */
79167 
79168 		act = thr->callstack_curr;
79169 		DUK_ASSERT(act != NULL);
79170 		fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
79171 		DUK_ASSERT(fun != NULL);
79172 		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == fun->nregs);
79173 		consts = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, fun);
79174 		DUK_ASSERT(consts != NULL);
79175 
79176 #if defined(DUK_USE_DEBUGGER_SUPPORT)
79177 		if (DUK_UNLIKELY(duk_debug_is_attached(thr->heap) && !thr->heap->dbg_processing)) {
79178 			duk__executor_recheck_debugger(thr, act, fun);
79179 			DUK_ASSERT(act == thr->callstack_curr);
79180 			DUK_ASSERT(act != NULL);
79181 		}
79182 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
79183 
79184 #if defined(DUK_USE_ASSERTIONS)
79185 		valstack_top_base = (duk_size_t) (thr->valstack_top - thr->valstack);
79186 #endif
79187 
79188 		/* Set up curr_pc for opcode dispatch. */
79189 		curr_pc = act->curr_pc;
79190 	}
79191 
79192 	DUK_DD(DUK_DDPRINT("restarting execution, thr %p, act idx %ld, fun %p,"
79193 	                   "consts %p, funcs %p, lev %ld, regbot %ld, regtop %ld, "
79194 	                   "preventcount=%ld",
79195 	                   (void *) thr,
79196 	                   (long) (thr->callstack_top - 1),
79197 	                   (void *) DUK__FUN(),
79198 	                   (void *) DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, DUK__FUN()),
79199 	                   (void *) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, DUK__FUN()),
79200 	                   (long) (thr->callstack_top - 1),
79201 	                   (long) (thr->valstack_bottom - thr->valstack),
79202 	                   (long) (thr->valstack_top - thr->valstack),
79203 	                   (long) thr->callstack_preventcount));
79204 
79205 	/* Dispatch loop. */
79206 
79207 	for (;;) {
79208 		duk_uint8_t op;
79209 
79210 		DUK_ASSERT(thr->callstack_top >= 1);
79211 		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == DUK__FUN()->nregs);
79212 		DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) == valstack_top_base);
79213 
79214 		/* Executor interrupt counter check, used to implement breakpoints,
79215 		 * debugging interface, execution timeouts, etc.  The counter is heap
79216 		 * specific but is maintained in the current thread to make the check
79217 		 * as fast as possible.  The counter is copied back to the heap struct
79218 		 * whenever a thread switch occurs by the DUK_HEAP_SWITCH_THREAD() macro.
79219 		 */
79220 #if defined(DUK_USE_INTERRUPT_COUNTER)
79221 		int_ctr = thr->interrupt_counter;
79222 		if (DUK_LIKELY(int_ctr > 0)) {
79223 			thr->interrupt_counter = int_ctr - 1;
79224 		} else {
79225 			/* Trigger at zero or below */
79226 			duk_small_uint_t exec_int_ret;
79227 
79228 			DUK_STATS_INC(thr->heap, stats_exec_interrupt);
79229 
79230 			/* Write curr_pc back for the debugger. */
79231 			{
79232 				duk_activation *act;
79233 				DUK_ASSERT(thr->callstack_top > 0);
79234 				act = thr->callstack_curr;
79235 				DUK_ASSERT(act != NULL);
79236 				act->curr_pc = (duk_instr_t *) curr_pc;
79237 			}
79238 
79239 			/* Forced restart caused by a function return; must recheck
79240 			 * debugger breakpoints before checking line transitions,
79241 			 * see GH-303.  Restart and then handle interrupt_counter
79242 			 * zero again.
79243 			 */
79244 #if defined(DUK_USE_DEBUGGER_SUPPORT)
79245 			if (thr->heap->dbg_force_restart) {
79246 				DUK_DD(DUK_DDPRINT("dbg_force_restart flag forced restart execution"));  /* GH-303 */
79247 				thr->heap->dbg_force_restart = 0;
79248 				goto restart_execution;
79249 			}
79250 #endif
79251 
79252 			exec_int_ret = duk__executor_interrupt(thr);
79253 			if (exec_int_ret == DUK__INT_RESTART) {
79254 				/* curr_pc synced back above */
79255 				goto restart_execution;
79256 			}
79257 		}
79258 #endif  /* DUK_USE_INTERRUPT_COUNTER */
79259 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
79260 		/* For cross-checking during development: ensure dispatch count
79261 		 * matches cumulative interrupt counter init value sums.
79262 		 */
79263 		thr->heap->inst_count_exec++;
79264 #endif
79265 
79266 #if defined(DUK_USE_ASSERTIONS) || defined(DUK_USE_DEBUG)
79267 		{
79268 			duk_activation *act;
79269 			act = thr->callstack_curr;
79270 			DUK_ASSERT(curr_pc >= DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN()));
79271 			DUK_ASSERT(curr_pc < DUK_HCOMPFUNC_GET_CODE_END(thr->heap, DUK__FUN()));
79272 			DUK_UNREF(act);  /* if debugging disabled */
79273 
79274 			DUK_DDD(DUK_DDDPRINT("executing bytecode: pc=%ld, ins=0x%08lx, op=%ld, valstack_top=%ld/%ld, nregs=%ld  -->  %!I",
79275 			                     (long) (curr_pc - DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN())),
79276 			                     (unsigned long) *curr_pc,
79277 			                     (long) DUK_DEC_OP(*curr_pc),
79278 			                     (long) (thr->valstack_top - thr->valstack),
79279 			                     (long) (thr->valstack_end - thr->valstack),
79280 			                     (long) (DUK__FUN() ? DUK__FUN()->nregs : -1),
79281 			                     (duk_instr_t) *curr_pc));
79282 		}
79283 #endif
79284 
79285 #if defined(DUK_USE_ASSERTIONS)
79286 		/* Quite heavy assert: check valstack policy.  Improper
79287 		 * shuffle instructions can write beyond valstack_top/end
79288 		 * so this check catches them in the act.
79289 		 */
79290 		{
79291 			duk_tval *tv;
79292 			tv = thr->valstack_top;
79293 			while (tv != thr->valstack_end) {
79294 				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
79295 				tv++;
79296 			}
79297 		}
79298 #endif
79299 
79300 		ins = *curr_pc++;
79301 		DUK_STATS_INC(thr->heap, stats_exec_opcodes);
79302 
79303 		/* Typing: use duk_small_(u)int_fast_t when decoding small
79304 		 * opcode fields (op, A, B, C, BC) which fit into 16 bits
79305 		 * and duk_(u)int_fast_t when decoding larger fields (e.g.
79306 		 * ABC).  Use unsigned variant by default, signed when the
79307 		 * value is used in signed arithmetic.  Using variable names
79308 		 * such as 'a', 'b', 'c', 'bc', etc makes it easier to spot
79309 		 * typing mismatches.
79310 		 */
79311 
79312 		/* Switch based on opcode.  Cast to 8-bit unsigned value and
79313 		 * use a fully populated case clauses so that the compiler
79314 		 * will (at least usually) omit a bounds check.
79315 		 */
79316 		op = (duk_uint8_t) DUK_DEC_OP(ins);
79317 		switch (op) {
79318 
79319 		/* Some useful macros.  These access inner executor variables
79320 		 * directly so they only apply within the executor.
79321 		 */
79322 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79323 #define DUK__REPLACE_TOP_A_BREAK() { goto replace_top_a; }
79324 #define DUK__REPLACE_TOP_BC_BREAK() { goto replace_top_bc; }
79325 #define DUK__REPLACE_BOOL_A_BREAK(bval) { \
79326 		duk_bool_t duk__bval; \
79327 		duk__bval = (bval); \
79328 		DUK_ASSERT(duk__bval == 0 || duk__bval == 1); \
79329 		duk_push_boolean(thr, duk__bval); \
79330 		DUK__REPLACE_TOP_A_BREAK(); \
79331 	}
79332 #else
79333 #define DUK__REPLACE_TOP_A_BREAK() { DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_A(ins)); break; }
79334 #define DUK__REPLACE_TOP_BC_BREAK() { DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_BC(ins)); break; }
79335 #define DUK__REPLACE_BOOL_A_BREAK(bval) { \
79336 		duk_bool_t duk__bval; \
79337 		duk_tval *duk__tvdst; \
79338 		duk__bval = (bval); \
79339 		DUK_ASSERT(duk__bval == 0 || duk__bval == 1); \
79340 		duk__tvdst = DUK__REGP_A(ins); \
79341 		DUK_TVAL_SET_BOOLEAN_UPDREF(thr, duk__tvdst, duk__bval); \
79342 		break; \
79343 	}
79344 #endif
79345 
79346 		/* XXX: 12 + 12 bit variant might make sense too, for both reg and
79347 		 * const loads.
79348 		 */
79349 
79350 		/* For LDREG, STREG, LDCONST footprint optimized variants would just
79351 		 * duk_dup() + duk_replace(), but because they're used quite a lot
79352 		 * they're currently intentionally not size optimized.
79353 		 */
79354 		case DUK_OP_LDREG: {
79355 			duk_tval *tv1, *tv2;
79356 
79357 			tv1 = DUK__REGP_A(ins);
79358 			tv2 = DUK__REGP_BC(ins);
79359 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
79360 			break;
79361 		}
79362 
79363 		case DUK_OP_STREG: {
79364 			duk_tval *tv1, *tv2;
79365 
79366 			tv1 = DUK__REGP_A(ins);
79367 			tv2 = DUK__REGP_BC(ins);
79368 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv2, tv1);  /* side effects */
79369 			break;
79370 		}
79371 
79372 		case DUK_OP_LDCONST: {
79373 			duk_tval *tv1, *tv2;
79374 
79375 			tv1 = DUK__REGP_A(ins);
79376 			tv2 = DUK__CONSTP_BC(ins);
79377 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
79378 			break;
79379 		}
79380 
79381 		/* LDINT and LDINTX are intended to load an arbitrary signed
79382 		 * 32-bit value.  Only an LDINT+LDINTX sequence is supported.
79383 		 * This also guarantees all values remain fastints.
79384 		 */
79385 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79386 		case DUK_OP_LDINT: {
79387 			duk_int32_t val;
79388 
79389 			val = (duk_int32_t) DUK_DEC_BC(ins) - (duk_int32_t) DUK_BC_LDINT_BIAS;
79390 			duk_push_int(thr, val);
79391 			DUK__REPLACE_TOP_A_BREAK();
79392 		}
79393 		case DUK_OP_LDINTX: {
79394 			duk_int32_t val;
79395 
79396 			val = (duk_int32_t) duk_get_int(thr, DUK_DEC_A(ins));
79397 			val = (val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins);  /* no bias */
79398 			duk_push_int(thr, val);
79399 			DUK__REPLACE_TOP_A_BREAK();
79400 		}
79401 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79402 		case DUK_OP_LDINT: {
79403 			duk_tval *tv1;
79404 			duk_int32_t val;
79405 
79406 			val = (duk_int32_t) DUK_DEC_BC(ins) - (duk_int32_t) DUK_BC_LDINT_BIAS;
79407 			tv1 = DUK__REGP_A(ins);
79408 			DUK_TVAL_SET_I32_UPDREF(thr, tv1, val);  /* side effects */
79409 			break;
79410 		}
79411 		case DUK_OP_LDINTX: {
79412 			duk_tval *tv1;
79413 			duk_int32_t val;
79414 
79415 			tv1 = DUK__REGP_A(ins);
79416 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
79417 #if defined(DUK_USE_FASTINT)
79418 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
79419 			val = DUK_TVAL_GET_FASTINT_I32(tv1);
79420 #else
79421 			/* XXX: fast double-to-int conversion, we know number is integer in [-0x80000000,0xffffffff]. */
79422 			val = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv1);
79423 #endif
79424 			val = (duk_int32_t) ((duk_uint32_t) val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins);  /* no bias */
79425 			DUK_TVAL_SET_I32_UPDREF(thr, tv1, val);  /* side effects */
79426 			break;
79427 		}
79428 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79429 
79430 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79431 		case DUK_OP_LDTHIS: {
79432 			duk_push_this(thr);
79433 			DUK__REPLACE_TOP_BC_BREAK();
79434 		}
79435 		case DUK_OP_LDUNDEF: {
79436 			duk_to_undefined(thr, (duk_idx_t) DUK_DEC_BC(ins));
79437 			break;
79438 		}
79439 		case DUK_OP_LDNULL: {
79440 			duk_to_null(thr, (duk_idx_t) DUK_DEC_BC(ins));
79441 			break;
79442 		}
79443 		case DUK_OP_LDTRUE: {
79444 			duk_push_true(thr);
79445 			DUK__REPLACE_TOP_BC_BREAK();
79446 		}
79447 		case DUK_OP_LDFALSE: {
79448 			duk_push_false(thr);
79449 			DUK__REPLACE_TOP_BC_BREAK();
79450 		}
79451 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79452 		case DUK_OP_LDTHIS: {
79453 			/* Note: 'this' may be bound to any value, not just an object */
79454 			duk_tval *tv1, *tv2;
79455 
79456 			tv1 = DUK__REGP_BC(ins);
79457 			tv2 = thr->valstack_bottom - 1;  /* 'this binding' is just under bottom */
79458 			DUK_ASSERT(tv2 >= thr->valstack);
79459 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
79460 			break;
79461 		}
79462 		case DUK_OP_LDUNDEF: {
79463 			duk_tval *tv1;
79464 
79465 			tv1 = DUK__REGP_BC(ins);
79466 			DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
79467 			break;
79468 		}
79469 		case DUK_OP_LDNULL: {
79470 			duk_tval *tv1;
79471 
79472 			tv1 = DUK__REGP_BC(ins);
79473 			DUK_TVAL_SET_NULL_UPDREF(thr, tv1);  /* side effects */
79474 			break;
79475 		}
79476 		case DUK_OP_LDTRUE: {
79477 			duk_tval *tv1;
79478 
79479 			tv1 = DUK__REGP_BC(ins);
79480 			DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 1);  /* side effects */
79481 			break;
79482 		}
79483 		case DUK_OP_LDFALSE: {
79484 			duk_tval *tv1;
79485 
79486 			tv1 = DUK__REGP_BC(ins);
79487 			DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 0);  /* side effects */
79488 			break;
79489 		}
79490 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79491 
79492 		case DUK_OP_BNOT: {
79493 			duk__vm_bitwise_not(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins));
79494 			break;
79495 		}
79496 
79497 		case DUK_OP_LNOT: {
79498 			duk__vm_logical_not(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins));
79499 			break;
79500 		}
79501 
79502 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79503 		case DUK_OP_UNM:
79504 		case DUK_OP_UNP: {
79505 			duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), op);
79506 			break;
79507 		}
79508 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79509 		case DUK_OP_UNM: {
79510 			duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), DUK_OP_UNM);
79511 			break;
79512 		}
79513 		case DUK_OP_UNP: {
79514 			duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), DUK_OP_UNP);
79515 			break;
79516 		}
79517 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79518 
79519 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79520 		case DUK_OP_TYPEOF: {
79521 			duk_small_uint_t stridx;
79522 
79523 			stridx = duk_js_typeof_stridx(DUK__REGP_BC(ins));
79524 			DUK_ASSERT_STRIDX_VALID(stridx);
79525 			duk_push_hstring_stridx(thr, stridx);
79526 			DUK__REPLACE_TOP_A_BREAK();
79527 		}
79528 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79529 		case DUK_OP_TYPEOF: {
79530 			duk_tval *tv;
79531 			duk_small_uint_t stridx;
79532 			duk_hstring *h_str;
79533 
79534 			tv = DUK__REGP_BC(ins);
79535 			stridx = duk_js_typeof_stridx(tv);
79536 			DUK_ASSERT_STRIDX_VALID(stridx);
79537 			h_str = DUK_HTHREAD_GET_STRING(thr, stridx);
79538 			tv = DUK__REGP_A(ins);
79539 			DUK_TVAL_SET_STRING_UPDREF(thr, tv, h_str);
79540 			break;
79541 		}
79542 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79543 
79544 		case DUK_OP_TYPEOFID: {
79545 			duk_small_uint_t stridx;
79546 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
79547 			duk_hstring *h_str;
79548 #endif
79549 			duk_activation *act;
79550 			duk_hstring *name;
79551 			duk_tval *tv;
79552 
79553 			/* A -> target register
79554 			 * BC -> constant index of identifier name
79555 			 */
79556 
79557 			tv = DUK__CONSTP_BC(ins);
79558 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv));
79559 			name = DUK_TVAL_GET_STRING(tv);
79560 			tv = NULL;  /* lookup has side effects */
79561 			act = thr->callstack_curr;
79562 			if (duk_js_getvar_activation(thr, act, name, 0 /*throw*/)) {
79563 				/* -> [... val this] */
79564 				tv = DUK_GET_TVAL_NEGIDX(thr, -2);
79565 				stridx = duk_js_typeof_stridx(tv);
79566 				tv = NULL;  /* no longer needed */
79567 				duk_pop_2_unsafe(thr);
79568 			} else {
79569 				/* unresolvable, no stack changes */
79570 				stridx = DUK_STRIDX_LC_UNDEFINED;
79571 			}
79572 			DUK_ASSERT_STRIDX_VALID(stridx);
79573 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79574 			duk_push_hstring_stridx(thr, stridx);
79575 			DUK__REPLACE_TOP_A_BREAK();
79576 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79577 			h_str = DUK_HTHREAD_GET_STRING(thr, stridx);
79578 			tv = DUK__REGP_A(ins);
79579 			DUK_TVAL_SET_STRING_UPDREF(thr, tv, h_str);
79580 			break;
79581 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79582 		}
79583 
79584 		/* Equality: E5 Sections 11.9.1, 11.9.3 */
79585 
79586 #define DUK__EQ_BODY(barg,carg) { \
79587 		duk_bool_t tmp; \
79588 		tmp = duk_js_equals(thr, (barg), (carg)); \
79589 		DUK_ASSERT(tmp == 0 || tmp == 1); \
79590 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
79591 	}
79592 #define DUK__NEQ_BODY(barg,carg) { \
79593 		duk_bool_t tmp; \
79594 		tmp = duk_js_equals(thr, (barg), (carg)); \
79595 		DUK_ASSERT(tmp == 0 || tmp == 1); \
79596 		tmp ^= 1; \
79597 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
79598 	}
79599 #define DUK__SEQ_BODY(barg,carg) { \
79600 		duk_bool_t tmp; \
79601 		tmp = duk_js_strict_equals((barg), (carg)); \
79602 		DUK_ASSERT(tmp == 0 || tmp == 1); \
79603 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
79604 	}
79605 #define DUK__SNEQ_BODY(barg,carg) { \
79606 		duk_bool_t tmp; \
79607 		tmp = duk_js_strict_equals((barg), (carg)); \
79608 		DUK_ASSERT(tmp == 0 || tmp == 1); \
79609 		tmp ^= 1; \
79610 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
79611 	}
79612 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79613 		case DUK_OP_EQ_RR:
79614 		case DUK_OP_EQ_CR:
79615 		case DUK_OP_EQ_RC:
79616 		case DUK_OP_EQ_CC:
79617 			DUK__EQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
79618 		case DUK_OP_NEQ_RR:
79619 		case DUK_OP_NEQ_CR:
79620 		case DUK_OP_NEQ_RC:
79621 		case DUK_OP_NEQ_CC:
79622 			DUK__NEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
79623 		case DUK_OP_SEQ_RR:
79624 		case DUK_OP_SEQ_CR:
79625 		case DUK_OP_SEQ_RC:
79626 		case DUK_OP_SEQ_CC:
79627 			DUK__SEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
79628 		case DUK_OP_SNEQ_RR:
79629 		case DUK_OP_SNEQ_CR:
79630 		case DUK_OP_SNEQ_RC:
79631 		case DUK_OP_SNEQ_CC:
79632 			DUK__SNEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
79633 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79634 		case DUK_OP_EQ_RR:
79635 			DUK__EQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
79636 		case DUK_OP_EQ_CR:
79637 			DUK__EQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
79638 		case DUK_OP_EQ_RC:
79639 			DUK__EQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
79640 		case DUK_OP_EQ_CC:
79641 			DUK__EQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
79642 		case DUK_OP_NEQ_RR:
79643 			DUK__NEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
79644 		case DUK_OP_NEQ_CR:
79645 			DUK__NEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
79646 		case DUK_OP_NEQ_RC:
79647 			DUK__NEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
79648 		case DUK_OP_NEQ_CC:
79649 			DUK__NEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
79650 		case DUK_OP_SEQ_RR:
79651 			DUK__SEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
79652 		case DUK_OP_SEQ_CR:
79653 			DUK__SEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
79654 		case DUK_OP_SEQ_RC:
79655 			DUK__SEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
79656 		case DUK_OP_SEQ_CC:
79657 			DUK__SEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
79658 		case DUK_OP_SNEQ_RR:
79659 			DUK__SNEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
79660 		case DUK_OP_SNEQ_CR:
79661 			DUK__SNEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
79662 		case DUK_OP_SNEQ_RC:
79663 			DUK__SNEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
79664 		case DUK_OP_SNEQ_CC:
79665 			DUK__SNEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
79666 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79667 
79668 #define DUK__COMPARE_BODY(arg1,arg2,flags) { \
79669 		duk_bool_t tmp; \
79670 		tmp = duk_js_compare_helper(thr, (arg1), (arg2), (flags)); \
79671 		DUK_ASSERT(tmp == 0 || tmp == 1); \
79672 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
79673 	}
79674 #define DUK__GT_BODY(barg,carg) DUK__COMPARE_BODY((carg), (barg), 0)
79675 #define DUK__GE_BODY(barg,carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
79676 #define DUK__LT_BODY(barg,carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
79677 #define DUK__LE_BODY(barg,carg) DUK__COMPARE_BODY((carg), (barg), DUK_COMPARE_FLAG_NEGATE)
79678 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79679 		case DUK_OP_GT_RR:
79680 		case DUK_OP_GT_CR:
79681 		case DUK_OP_GT_RC:
79682 		case DUK_OP_GT_CC:
79683 			DUK__GT_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
79684 		case DUK_OP_GE_RR:
79685 		case DUK_OP_GE_CR:
79686 		case DUK_OP_GE_RC:
79687 		case DUK_OP_GE_CC:
79688 			DUK__GE_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
79689 		case DUK_OP_LT_RR:
79690 		case DUK_OP_LT_CR:
79691 		case DUK_OP_LT_RC:
79692 		case DUK_OP_LT_CC:
79693 			DUK__LT_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
79694 		case DUK_OP_LE_RR:
79695 		case DUK_OP_LE_CR:
79696 		case DUK_OP_LE_RC:
79697 		case DUK_OP_LE_CC:
79698 			DUK__LE_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
79699 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79700 		case DUK_OP_GT_RR:
79701 			DUK__GT_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
79702 		case DUK_OP_GT_CR:
79703 			DUK__GT_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
79704 		case DUK_OP_GT_RC:
79705 			DUK__GT_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
79706 		case DUK_OP_GT_CC:
79707 			DUK__GT_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
79708 		case DUK_OP_GE_RR:
79709 			DUK__GE_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
79710 		case DUK_OP_GE_CR:
79711 			DUK__GE_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
79712 		case DUK_OP_GE_RC:
79713 			DUK__GE_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
79714 		case DUK_OP_GE_CC:
79715 			DUK__GE_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
79716 		case DUK_OP_LT_RR:
79717 			DUK__LT_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
79718 		case DUK_OP_LT_CR:
79719 			DUK__LT_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
79720 		case DUK_OP_LT_RC:
79721 			DUK__LT_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
79722 		case DUK_OP_LT_CC:
79723 			DUK__LT_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
79724 		case DUK_OP_LE_RR:
79725 			DUK__LE_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
79726 		case DUK_OP_LE_CR:
79727 			DUK__LE_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
79728 		case DUK_OP_LE_RC:
79729 			DUK__LE_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
79730 		case DUK_OP_LE_CC:
79731 			DUK__LE_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
79732 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79733 
79734 		/* No size optimized variant at present for IF. */
79735 		case DUK_OP_IFTRUE_R: {
79736 			if (duk_js_toboolean(DUK__REGP_BC(ins)) != 0) {
79737 				curr_pc++;
79738 			}
79739 			break;
79740 		}
79741 		case DUK_OP_IFTRUE_C: {
79742 			if (duk_js_toboolean(DUK__CONSTP_BC(ins)) != 0) {
79743 				curr_pc++;
79744 			}
79745 			break;
79746 		}
79747 		case DUK_OP_IFFALSE_R: {
79748 			if (duk_js_toboolean(DUK__REGP_BC(ins)) == 0) {
79749 				curr_pc++;
79750 			}
79751 			break;
79752 		}
79753 		case DUK_OP_IFFALSE_C: {
79754 			if (duk_js_toboolean(DUK__CONSTP_BC(ins)) == 0) {
79755 				curr_pc++;
79756 			}
79757 			break;
79758 		}
79759 
79760 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79761 		case DUK_OP_ADD_RR:
79762 		case DUK_OP_ADD_CR:
79763 		case DUK_OP_ADD_RC:
79764 		case DUK_OP_ADD_CC: {
79765 			/* XXX: could leave value on stack top and goto replace_top_a; */
79766 			duk__vm_arith_add(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins));
79767 			break;
79768 		}
79769 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79770 		case DUK_OP_ADD_RR: {
79771 			duk__vm_arith_add(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins));
79772 			break;
79773 		}
79774 		case DUK_OP_ADD_CR: {
79775 			duk__vm_arith_add(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins));
79776 			break;
79777 		}
79778 		case DUK_OP_ADD_RC: {
79779 			duk__vm_arith_add(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins));
79780 			break;
79781 		}
79782 		case DUK_OP_ADD_CC: {
79783 			duk__vm_arith_add(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins));
79784 			break;
79785 		}
79786 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79787 
79788 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79789 		case DUK_OP_SUB_RR:
79790 		case DUK_OP_SUB_CR:
79791 		case DUK_OP_SUB_RC:
79792 		case DUK_OP_SUB_CC:
79793 		case DUK_OP_MUL_RR:
79794 		case DUK_OP_MUL_CR:
79795 		case DUK_OP_MUL_RC:
79796 		case DUK_OP_MUL_CC:
79797 		case DUK_OP_DIV_RR:
79798 		case DUK_OP_DIV_CR:
79799 		case DUK_OP_DIV_RC:
79800 		case DUK_OP_DIV_CC:
79801 		case DUK_OP_MOD_RR:
79802 		case DUK_OP_MOD_CR:
79803 		case DUK_OP_MOD_RC:
79804 		case DUK_OP_MOD_CC:
79805 #if defined(DUK_USE_ES7_EXP_OPERATOR)
79806 		case DUK_OP_EXP_RR:
79807 		case DUK_OP_EXP_CR:
79808 		case DUK_OP_EXP_RC:
79809 		case DUK_OP_EXP_CC:
79810 #endif  /* DUK_USE_ES7_EXP_OPERATOR */
79811 		{
79812 			/* XXX: could leave value on stack top and goto replace_top_a; */
79813 			duk__vm_arith_binary_op(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins), op);
79814 			break;
79815 		}
79816 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79817 		case DUK_OP_SUB_RR: {
79818 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
79819 			break;
79820 		}
79821 		case DUK_OP_SUB_CR: {
79822 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
79823 			break;
79824 		}
79825 		case DUK_OP_SUB_RC: {
79826 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
79827 			break;
79828 		}
79829 		case DUK_OP_SUB_CC: {
79830 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
79831 			break;
79832 		}
79833 		case DUK_OP_MUL_RR: {
79834 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
79835 			break;
79836 		}
79837 		case DUK_OP_MUL_CR: {
79838 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
79839 			break;
79840 		}
79841 		case DUK_OP_MUL_RC: {
79842 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
79843 			break;
79844 		}
79845 		case DUK_OP_MUL_CC: {
79846 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
79847 			break;
79848 		}
79849 		case DUK_OP_DIV_RR: {
79850 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
79851 			break;
79852 		}
79853 		case DUK_OP_DIV_CR: {
79854 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
79855 			break;
79856 		}
79857 		case DUK_OP_DIV_RC: {
79858 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
79859 			break;
79860 		}
79861 		case DUK_OP_DIV_CC: {
79862 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
79863 			break;
79864 		}
79865 		case DUK_OP_MOD_RR: {
79866 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
79867 			break;
79868 		}
79869 		case DUK_OP_MOD_CR: {
79870 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
79871 			break;
79872 		}
79873 		case DUK_OP_MOD_RC: {
79874 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
79875 			break;
79876 		}
79877 		case DUK_OP_MOD_CC: {
79878 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
79879 			break;
79880 		}
79881 #if defined(DUK_USE_ES7_EXP_OPERATOR)
79882 		case DUK_OP_EXP_RR: {
79883 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
79884 			break;
79885 		}
79886 		case DUK_OP_EXP_CR: {
79887 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
79888 			break;
79889 		}
79890 		case DUK_OP_EXP_RC: {
79891 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
79892 			break;
79893 		}
79894 		case DUK_OP_EXP_CC: {
79895 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
79896 			break;
79897 		}
79898 #endif  /* DUK_USE_ES7_EXP_OPERATOR */
79899 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
79900 
79901 #if defined(DUK_USE_EXEC_PREFER_SIZE)
79902 		case DUK_OP_BAND_RR:
79903 		case DUK_OP_BAND_CR:
79904 		case DUK_OP_BAND_RC:
79905 		case DUK_OP_BAND_CC:
79906 		case DUK_OP_BOR_RR:
79907 		case DUK_OP_BOR_CR:
79908 		case DUK_OP_BOR_RC:
79909 		case DUK_OP_BOR_CC:
79910 		case DUK_OP_BXOR_RR:
79911 		case DUK_OP_BXOR_CR:
79912 		case DUK_OP_BXOR_RC:
79913 		case DUK_OP_BXOR_CC:
79914 		case DUK_OP_BASL_RR:
79915 		case DUK_OP_BASL_CR:
79916 		case DUK_OP_BASL_RC:
79917 		case DUK_OP_BASL_CC:
79918 		case DUK_OP_BLSR_RR:
79919 		case DUK_OP_BLSR_CR:
79920 		case DUK_OP_BLSR_RC:
79921 		case DUK_OP_BLSR_CC:
79922 		case DUK_OP_BASR_RR:
79923 		case DUK_OP_BASR_CR:
79924 		case DUK_OP_BASR_RC:
79925 		case DUK_OP_BASR_CC: {
79926 			/* XXX: could leave value on stack top and goto replace_top_a; */
79927 			duk__vm_bitwise_binary_op(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins), op);
79928 			break;
79929 		}
79930 #else  /* DUK_USE_EXEC_PREFER_SIZE */
79931 		case DUK_OP_BAND_RR: {
79932 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
79933 			break;
79934 		}
79935 		case DUK_OP_BAND_CR: {
79936 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
79937 			break;
79938 		}
79939 		case DUK_OP_BAND_RC: {
79940 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
79941 			break;
79942 		}
79943 		case DUK_OP_BAND_CC: {
79944 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
79945 			break;
79946 		}
79947 		case DUK_OP_BOR_RR: {
79948 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
79949 			break;
79950 		}
79951 		case DUK_OP_BOR_CR: {
79952 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
79953 			break;
79954 		}
79955 		case DUK_OP_BOR_RC: {
79956 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
79957 			break;
79958 		}
79959 		case DUK_OP_BOR_CC: {
79960 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
79961 			break;
79962 		}
79963 		case DUK_OP_BXOR_RR: {
79964 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
79965 			break;
79966 		}
79967 		case DUK_OP_BXOR_CR: {
79968 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
79969 			break;
79970 		}
79971 		case DUK_OP_BXOR_RC: {
79972 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
79973 			break;
79974 		}
79975 		case DUK_OP_BXOR_CC: {
79976 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
79977 			break;
79978 		}
79979 		case DUK_OP_BASL_RR: {
79980 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
79981 			break;
79982 		}
79983 		case DUK_OP_BASL_CR: {
79984 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
79985 			break;
79986 		}
79987 		case DUK_OP_BASL_RC: {
79988 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
79989 			break;
79990 		}
79991 		case DUK_OP_BASL_CC: {
79992 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
79993 			break;
79994 		}
79995 		case DUK_OP_BLSR_RR: {
79996 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
79997 			break;
79998 		}
79999 		case DUK_OP_BLSR_CR: {
80000 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
80001 			break;
80002 		}
80003 		case DUK_OP_BLSR_RC: {
80004 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
80005 			break;
80006 		}
80007 		case DUK_OP_BLSR_CC: {
80008 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
80009 			break;
80010 		}
80011 		case DUK_OP_BASR_RR: {
80012 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
80013 			break;
80014 		}
80015 		case DUK_OP_BASR_CR: {
80016 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
80017 			break;
80018 		}
80019 		case DUK_OP_BASR_RC: {
80020 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
80021 			break;
80022 		}
80023 		case DUK_OP_BASR_CC: {
80024 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
80025 			break;
80026 		}
80027 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
80028 
80029 		/* For INSTOF and IN, B is always a register. */
80030 #define DUK__INSTOF_BODY(barg,carg) { \
80031 		duk_bool_t tmp; \
80032 		tmp = duk_js_instanceof(thr, (barg), (carg)); \
80033 		DUK_ASSERT(tmp == 0 || tmp == 1); \
80034 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
80035 	}
80036 #define DUK__IN_BODY(barg,carg) { \
80037 		duk_bool_t tmp; \
80038 		tmp = duk_js_in(thr, (barg), (carg)); \
80039 		DUK_ASSERT(tmp == 0 || tmp == 1); \
80040 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
80041 	}
80042 #if defined(DUK_USE_EXEC_PREFER_SIZE)
80043 		case DUK_OP_INSTOF_RR:
80044 		case DUK_OP_INSTOF_CR:
80045 		case DUK_OP_INSTOF_RC:
80046 		case DUK_OP_INSTOF_CC:
80047 			DUK__INSTOF_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
80048 		case DUK_OP_IN_RR:
80049 		case DUK_OP_IN_CR:
80050 		case DUK_OP_IN_RC:
80051 		case DUK_OP_IN_CC:
80052 			DUK__IN_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
80053 #else  /* DUK_USE_EXEC_PREFER_SIZE */
80054 		case DUK_OP_INSTOF_RR:
80055 			DUK__INSTOF_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
80056 		case DUK_OP_INSTOF_CR:
80057 			DUK__INSTOF_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
80058 		case DUK_OP_INSTOF_RC:
80059 			DUK__INSTOF_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
80060 		case DUK_OP_INSTOF_CC:
80061 			DUK__INSTOF_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
80062 		case DUK_OP_IN_RR:
80063 			DUK__IN_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
80064 		case DUK_OP_IN_CR:
80065 			DUK__IN_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
80066 		case DUK_OP_IN_RC:
80067 			DUK__IN_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
80068 		case DUK_OP_IN_CC:
80069 			DUK__IN_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
80070 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
80071 
80072 		/* Pre/post inc/dec for register variables, important for loops. */
80073 #if defined(DUK_USE_EXEC_PREFER_SIZE)
80074 		case DUK_OP_PREINCR:
80075 		case DUK_OP_PREDECR:
80076 		case DUK_OP_POSTINCR:
80077 		case DUK_OP_POSTDECR: {
80078 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), op);
80079 			break;
80080 		}
80081 		case DUK_OP_PREINCV:
80082 		case DUK_OP_PREDECV:
80083 		case DUK_OP_POSTINCV:
80084 		case DUK_OP_POSTDECV: {
80085 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), op, DUK__STRICT());
80086 			break;
80087 		}
80088 #else  /* DUK_USE_EXEC_PREFER_SIZE */
80089 		case DUK_OP_PREINCR: {
80090 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_PREINCR);
80091 			break;
80092 		}
80093 		case DUK_OP_PREDECR: {
80094 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_PREDECR);
80095 			break;
80096 		}
80097 		case DUK_OP_POSTINCR: {
80098 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_POSTINCR);
80099 			break;
80100 		}
80101 		case DUK_OP_POSTDECR: {
80102 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_POSTDECR);
80103 			break;
80104 		}
80105 		case DUK_OP_PREINCV: {
80106 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_PREINCV, DUK__STRICT());
80107 			break;
80108 		}
80109 		case DUK_OP_PREDECV: {
80110 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_PREDECV, DUK__STRICT());
80111 			break;
80112 		}
80113 		case DUK_OP_POSTINCV: {
80114 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_POSTINCV, DUK__STRICT());
80115 			break;
80116 		}
80117 		case DUK_OP_POSTDECV: {
80118 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_POSTDECV, DUK__STRICT());
80119 			break;
80120 		}
80121 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
80122 
80123 		/* XXX: Move to separate helper, optimize for perf/size separately. */
80124 		/* Preinc/predec for object properties. */
80125 		case DUK_OP_PREINCP_RR:
80126 		case DUK_OP_PREINCP_CR:
80127 		case DUK_OP_PREINCP_RC:
80128 		case DUK_OP_PREINCP_CC:
80129 		case DUK_OP_PREDECP_RR:
80130 		case DUK_OP_PREDECP_CR:
80131 		case DUK_OP_PREDECP_RC:
80132 		case DUK_OP_PREDECP_CC:
80133 		case DUK_OP_POSTINCP_RR:
80134 		case DUK_OP_POSTINCP_CR:
80135 		case DUK_OP_POSTINCP_RC:
80136 		case DUK_OP_POSTINCP_CC:
80137 		case DUK_OP_POSTDECP_RR:
80138 		case DUK_OP_POSTDECP_CR:
80139 		case DUK_OP_POSTDECP_RC:
80140 		case DUK_OP_POSTDECP_CC: {
80141 			duk_tval *tv_obj;
80142 			duk_tval *tv_key;
80143 			duk_tval *tv_val;
80144 			duk_bool_t rc;
80145 			duk_double_t x, y, z;
80146 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
80147 			duk_tval *tv_dst;
80148 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
80149 
80150 			/* A -> target reg
80151 			 * B -> object reg/const (may be const e.g. in "'foo'[1]")
80152 			 * C -> key reg/const
80153 			 */
80154 
80155 			/* Opcode bits 0-1 are used to distinguish reg/const variants.
80156 			 * Opcode bits 2-3 are used to distinguish inc/dec variants:
80157 			 * Bit 2 = inc(0)/dec(1), bit 3 = pre(0)/post(1).
80158 			 */
80159 			DUK_ASSERT((DUK_OP_PREINCP_RR & 0x0c) == 0x00);
80160 			DUK_ASSERT((DUK_OP_PREDECP_RR & 0x0c) == 0x04);
80161 			DUK_ASSERT((DUK_OP_POSTINCP_RR & 0x0c) == 0x08);
80162 			DUK_ASSERT((DUK_OP_POSTDECP_RR & 0x0c) == 0x0c);
80163 
80164 			tv_obj = DUK__REGCONSTP_B(ins);
80165 			tv_key = DUK__REGCONSTP_C(ins);
80166 			rc = duk_hobject_getprop(thr, tv_obj, tv_key);  /* -> [val] */
80167 			DUK_UNREF(rc);  /* ignore */
80168 			tv_obj = NULL;  /* invalidated */
80169 			tv_key = NULL;  /* invalidated */
80170 
80171 			/* XXX: Fastint fast path would be useful here.  Also fastints
80172 			 * now lose their fastint status in current handling which is
80173 			 * not intuitive.
80174 			 */
80175 
80176 			x = duk_to_number_m1(thr);
80177 			duk_pop_unsafe(thr);
80178 			if (ins & DUK_BC_INCDECP_FLAG_DEC) {
80179 				y = x - 1.0;
80180 			} else {
80181 				y = x + 1.0;
80182 			}
80183 
80184 			duk_push_number(thr, y);
80185 			tv_val = DUK_GET_TVAL_NEGIDX(thr, -1);
80186 			DUK_ASSERT(tv_val != NULL);
80187 			tv_obj = DUK__REGCONSTP_B(ins);
80188 			tv_key = DUK__REGCONSTP_C(ins);
80189 			rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, DUK__STRICT());
80190 			DUK_UNREF(rc);  /* ignore */
80191 			tv_obj = NULL;  /* invalidated */
80192 			tv_key = NULL;  /* invalidated */
80193 			duk_pop_unsafe(thr);
80194 
80195 			z = (ins & DUK_BC_INCDECP_FLAG_POST) ? x : y;
80196 #if defined(DUK_USE_EXEC_PREFER_SIZE)
80197 			duk_push_number(thr, z);
80198 			DUK__REPLACE_TOP_A_BREAK();
80199 #else
80200 			tv_dst = DUK__REGP_A(ins);
80201 			DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_dst, z);
80202 			break;
80203 #endif
80204 		}
80205 
80206 		/* XXX: GETPROP where object is 'this', GETPROPT?
80207 		 * Occurs relatively often in object oriented code.
80208 		 */
80209 
80210 #define DUK__GETPROP_BODY(barg,carg) { \
80211 		/* A -> target reg \
80212 		 * B -> object reg/const (may be const e.g. in "'foo'[1]") \
80213 		 * C -> key reg/const \
80214 		 */ \
80215 		(void) duk_hobject_getprop(thr, (barg), (carg)); \
80216 		DUK__REPLACE_TOP_A_BREAK(); \
80217 	}
80218 #define DUK__GETPROPC_BODY(barg,carg) { \
80219 		/* Same as GETPROP but callability check for property-based calls. */ \
80220 		duk_tval *tv__targ; \
80221 		(void) duk_hobject_getprop(thr, (barg), (carg)); \
80222 		DUK_GC_TORTURE(thr->heap); \
80223 		tv__targ = DUK_GET_TVAL_NEGIDX(thr, -1); \
80224 		if (DUK_UNLIKELY(!duk_is_callable_tval(thr, tv__targ))) { \
80225 			/* Here we intentionally re-evaluate the macro \
80226 			 * arguments to deal with potentially changed \
80227 			 * valstack base pointer! \
80228 			 */ \
80229 			duk_call_setup_propcall_error(thr, (barg), (carg)); \
80230 		} \
80231 		DUK__REPLACE_TOP_A_BREAK(); \
80232 	}
80233 #define DUK__PUTPROP_BODY(aarg,barg,carg) { \
80234 		/* A -> object reg \
80235 		 * B -> key reg/const \
80236 		 * C -> value reg/const \
80237 		 * \
80238 		 * Note: intentional difference to register arrangement \
80239 		 * of e.g. GETPROP; 'A' must contain a register-only value. \
80240 		 */ \
80241 		(void) duk_hobject_putprop(thr, (aarg), (barg), (carg), DUK__STRICT()); \
80242 		break; \
80243 	}
80244 #define DUK__DELPROP_BODY(barg,carg) { \
80245 		/* A -> result reg \
80246 		 * B -> object reg \
80247 		 * C -> key reg/const \
80248 		 */ \
80249 		duk_bool_t rc; \
80250 		rc = duk_hobject_delprop(thr, (barg), (carg), DUK__STRICT()); \
80251 		DUK_ASSERT(rc == 0 || rc == 1); \
80252 		DUK__REPLACE_BOOL_A_BREAK(rc); \
80253 	}
80254 #if defined(DUK_USE_EXEC_PREFER_SIZE)
80255 		case DUK_OP_GETPROP_RR:
80256 		case DUK_OP_GETPROP_CR:
80257 		case DUK_OP_GETPROP_RC:
80258 		case DUK_OP_GETPROP_CC:
80259 			DUK__GETPROP_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
80260 #if defined(DUK_USE_VERBOSE_ERRORS)
80261 		case DUK_OP_GETPROPC_RR:
80262 		case DUK_OP_GETPROPC_CR:
80263 		case DUK_OP_GETPROPC_RC:
80264 		case DUK_OP_GETPROPC_CC:
80265 			DUK__GETPROPC_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
80266 #endif
80267 		case DUK_OP_PUTPROP_RR:
80268 		case DUK_OP_PUTPROP_CR:
80269 		case DUK_OP_PUTPROP_RC:
80270 		case DUK_OP_PUTPROP_CC:
80271 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
80272 		case DUK_OP_DELPROP_RR:
80273 		case DUK_OP_DELPROP_RC:  /* B is always reg */
80274 			DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__REGCONSTP_C(ins));
80275 #else  /* DUK_USE_EXEC_PREFER_SIZE */
80276 		case DUK_OP_GETPROP_RR:
80277 			DUK__GETPROP_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
80278 		case DUK_OP_GETPROP_CR:
80279 			DUK__GETPROP_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
80280 		case DUK_OP_GETPROP_RC:
80281 			DUK__GETPROP_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
80282 		case DUK_OP_GETPROP_CC:
80283 			DUK__GETPROP_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
80284 #if defined(DUK_USE_VERBOSE_ERRORS)
80285 		case DUK_OP_GETPROPC_RR:
80286 			DUK__GETPROPC_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
80287 		case DUK_OP_GETPROPC_CR:
80288 			DUK__GETPROPC_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
80289 		case DUK_OP_GETPROPC_RC:
80290 			DUK__GETPROPC_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
80291 		case DUK_OP_GETPROPC_CC:
80292 			DUK__GETPROPC_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
80293 #endif
80294 		case DUK_OP_PUTPROP_RR:
80295 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGP_B(ins), DUK__REGP_C(ins));
80296 		case DUK_OP_PUTPROP_CR:
80297 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__CONSTP_B(ins), DUK__REGP_C(ins));
80298 		case DUK_OP_PUTPROP_RC:
80299 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGP_B(ins), DUK__CONSTP_C(ins));
80300 		case DUK_OP_PUTPROP_CC:
80301 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
80302 		case DUK_OP_DELPROP_RR:  /* B is always reg */
80303 			DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
80304 		case DUK_OP_DELPROP_RC:
80305 			DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
80306 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
80307 
80308 		/* No fast path for DECLVAR now, it's quite a rare instruction. */
80309 		case DUK_OP_DECLVAR_RR:
80310 		case DUK_OP_DECLVAR_CR:
80311 		case DUK_OP_DECLVAR_RC:
80312 		case DUK_OP_DECLVAR_CC: {
80313 			duk_activation *act;
80314 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
80315 			duk_tval *tv1;
80316 			duk_hstring *name;
80317 			duk_small_uint_t prop_flags;
80318 			duk_bool_t is_func_decl;
80319 
80320 			tv1 = DUK__REGCONSTP_B(ins);
80321 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
80322 			name = DUK_TVAL_GET_STRING(tv1);
80323 			DUK_ASSERT(name != NULL);
80324 
80325 			is_func_decl = ((a & DUK_BC_DECLVAR_FLAG_FUNC_DECL) != 0);
80326 
80327 			/* XXX: declvar takes an duk_tval pointer, which is awkward and
80328 			 * should be reworked.
80329 			 */
80330 
80331 			/* Compiler is responsible for selecting property flags (configurability,
80332 			 * writability, etc).
80333 			 */
80334 			prop_flags = a & DUK_PROPDESC_FLAGS_MASK;
80335 
80336 			if (is_func_decl) {
80337 				duk_push_tval(thr, DUK__REGCONSTP_C(ins));
80338 			} else {
80339 				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */
80340 				thr->valstack_top++;
80341 			}
80342 			tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
80343 
80344 			act = thr->callstack_curr;
80345 			if (duk_js_declvar_activation(thr, act, name, tv1, prop_flags, is_func_decl)) {
80346 				if (is_func_decl) {
80347 					/* Already declared, update value. */
80348 					tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
80349 					duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
80350 				} else {
80351 					/* Already declared but no initializer value
80352 					 * (e.g. 'var xyz;'), no-op.
80353 					 */
80354 				}
80355 			}
80356 
80357 			duk_pop_unsafe(thr);
80358 			break;
80359 		}
80360 
80361 #if defined(DUK_USE_REGEXP_SUPPORT)
80362 		/* The compiler should never emit DUK_OP_REGEXP if there is no
80363 		 * regexp support.
80364 		 */
80365 		case DUK_OP_REGEXP_RR:
80366 		case DUK_OP_REGEXP_CR:
80367 		case DUK_OP_REGEXP_RC:
80368 		case DUK_OP_REGEXP_CC: {
80369 			/* A -> target register
80370 			 * B -> bytecode (also contains flags)
80371 			 * C -> escaped source
80372 			 */
80373 
80374 			duk_push_tval(thr, DUK__REGCONSTP_C(ins));
80375 			duk_push_tval(thr, DUK__REGCONSTP_B(ins));  /* -> [ ... escaped_source bytecode ] */
80376 			duk_regexp_create_instance(thr);   /* -> [ ... regexp_instance ] */
80377 			DUK__REPLACE_TOP_A_BREAK();
80378 		}
80379 #endif  /* DUK_USE_REGEXP_SUPPORT */
80380 
80381 		/* XXX: 'c' is unused, use whole BC, etc. */
80382 		case DUK_OP_CSVAR_RR:
80383 		case DUK_OP_CSVAR_CR:
80384 		case DUK_OP_CSVAR_RC:
80385 		case DUK_OP_CSVAR_CC: {
80386 			/* The speciality of calling through a variable binding is that the
80387 			 * 'this' value may be provided by the variable lookup: E5 Section 6.b.i.
80388 			 *
80389 			 * The only (standard) case where the 'this' binding is non-null is when
80390 			 *   (1) the variable is found in an object environment record, and
80391 			 *   (2) that object environment record is a 'with' block.
80392 			 */
80393 
80394 			duk_activation *act;
80395 			duk_uint_fast_t idx;
80396 			duk_tval *tv1;
80397 			duk_hstring *name;
80398 
80399 			/* A -> target registers (A, A + 1) for call setup
80400 			 * B -> identifier name, usually constant but can be a register due to shuffling
80401 			 */
80402 
80403 			tv1 = DUK__REGCONSTP_B(ins);
80404 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
80405 			name = DUK_TVAL_GET_STRING(tv1);
80406 			DUK_ASSERT(name != NULL);
80407 			act = thr->callstack_curr;
80408 			(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [... val this] */
80409 
80410 			idx = (duk_uint_fast_t) DUK_DEC_A(ins);
80411 
80412 			/* Could add direct value stack handling. */
80413 			duk_replace(thr, (duk_idx_t) (idx + 1));  /* 'this' binding */
80414 			duk_replace(thr, (duk_idx_t) idx);        /* variable value (function, we hope, not checked here) */
80415 			break;
80416 		}
80417 
80418 		case DUK_OP_CLOSURE: {
80419 			duk_activation *act;
80420 			duk_hcompfunc *fun_act;
80421 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
80422 			duk_hobject *fun_temp;
80423 
80424 			/* A -> target reg
80425 			 * BC -> inner function index
80426 			 */
80427 
80428 			DUK_DDD(DUK_DDDPRINT("CLOSURE to target register %ld, fnum %ld (count %ld)",
80429 			                     (long) DUK_DEC_A(ins), (long) DUK_DEC_BC(ins), (long) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, DUK__FUN())));
80430 
80431 			DUK_ASSERT_DISABLE(bc >= 0); /* unsigned */
80432 			DUK_ASSERT((duk_uint_t) bc < (duk_uint_t) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, DUK__FUN()));
80433 
80434 			act = thr->callstack_curr;
80435 			fun_act = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
80436 			fun_temp = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, fun_act)[bc];
80437 			DUK_ASSERT(fun_temp != NULL);
80438 			DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(fun_temp));
80439 
80440 			DUK_DDD(DUK_DDDPRINT("CLOSURE: function template is: %p -> %!O",
80441 			                     (void *) fun_temp, (duk_heaphdr *) fun_temp));
80442 
80443 			if (act->lex_env == NULL) {
80444 				DUK_ASSERT(act->var_env == NULL);
80445 				duk_js_init_activation_environment_records_delayed(thr, act);
80446 				act = thr->callstack_curr;
80447 			}
80448 			DUK_ASSERT(act->lex_env != NULL);
80449 			DUK_ASSERT(act->var_env != NULL);
80450 
80451 			/* functions always have a NEWENV flag, i.e. they get a
80452 			 * new variable declaration environment, so only lex_env
80453 			 * matters here.
80454 			 */
80455 			duk_js_push_closure(thr,
80456 			                    (duk_hcompfunc *) fun_temp,
80457 			                    act->var_env,
80458 			                    act->lex_env,
80459 			                    1 /*add_auto_proto*/);
80460 			DUK__REPLACE_TOP_A_BREAK();
80461 		}
80462 
80463 		case DUK_OP_GETVAR: {
80464 			duk_activation *act;
80465 			duk_tval *tv1;
80466 			duk_hstring *name;
80467 
80468 			tv1 = DUK__CONSTP_BC(ins);
80469 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
80470 			name = DUK_TVAL_GET_STRING(tv1);
80471 			DUK_ASSERT(name != NULL);
80472 			act = thr->callstack_curr;
80473 			DUK_ASSERT(act != NULL);
80474 			(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [... val this] */
80475 			duk_pop_unsafe(thr);  /* 'this' binding is not needed here */
80476 			DUK__REPLACE_TOP_A_BREAK();
80477 		}
80478 
80479 		case DUK_OP_PUTVAR: {
80480 			duk_activation *act;
80481 			duk_tval *tv1;
80482 			duk_hstring *name;
80483 
80484 			tv1 = DUK__CONSTP_BC(ins);
80485 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
80486 			name = DUK_TVAL_GET_STRING(tv1);
80487 			DUK_ASSERT(name != NULL);
80488 
80489 			/* XXX: putvar takes a duk_tval pointer, which is awkward and
80490 			 * should be reworked.
80491 			 */
80492 
80493 			tv1 = DUK__REGP_A(ins);  /* val */
80494 			act = thr->callstack_curr;
80495 			duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
80496 			break;
80497 		}
80498 
80499 		case DUK_OP_DELVAR: {
80500 			duk_activation *act;
80501 			duk_tval *tv1;
80502 			duk_hstring *name;
80503 			duk_bool_t rc;
80504 
80505 			tv1 = DUK__CONSTP_BC(ins);
80506 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
80507 			name = DUK_TVAL_GET_STRING(tv1);
80508 			DUK_ASSERT(name != NULL);
80509 			act = thr->callstack_curr;
80510 			rc = duk_js_delvar_activation(thr, act, name);
80511 			DUK__REPLACE_BOOL_A_BREAK(rc);
80512 		}
80513 
80514 		case DUK_OP_JUMP: {
80515 			/* Note: without explicit cast to signed, MSVC will
80516 			 * apparently generate a large positive jump when the
80517 			 * bias-corrected value would normally be negative.
80518 			 */
80519 			curr_pc += (duk_int_fast_t) DUK_DEC_ABC(ins) - (duk_int_fast_t) DUK_BC_JUMP_BIAS;
80520 			break;
80521 		}
80522 
80523 #define DUK__RETURN_SHARED() do { \
80524 		duk_small_uint_t ret_result; \
80525 		/* duk__handle_return() is guaranteed never to throw, except \
80526 		 * for potential out-of-memory situations which will then \
80527 		 * propagate out of the executor longjmp handler. \
80528 		 */ \
80529 		DUK_ASSERT(thr->ptr_curr_pc == NULL); \
80530 		ret_result = duk__handle_return(thr, entry_act); \
80531 		if (ret_result == DUK__RETHAND_RESTART) { \
80532 			goto restart_execution; \
80533 		} \
80534 		DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED); \
80535 		return; \
80536 	} while (0)
80537 #if defined(DUK_USE_EXEC_PREFER_SIZE)
80538 		case DUK_OP_RETREG:
80539 		case DUK_OP_RETCONST:
80540 		case DUK_OP_RETCONSTN:
80541 		case DUK_OP_RETUNDEF: {
80542 			 /* BC -> return value reg/const */
80543 
80544 			DUK__SYNC_AND_NULL_CURR_PC();
80545 
80546 			if (op == DUK_OP_RETREG) {
80547 				duk_push_tval(thr, DUK__REGP_BC(ins));
80548 			} else if (op == DUK_OP_RETUNDEF) {
80549 				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */
80550 				thr->valstack_top++;
80551 			} else {
80552 				DUK_ASSERT(op == DUK_OP_RETCONST || op == DUK_OP_RETCONSTN);
80553 				duk_push_tval(thr, DUK__CONSTP_BC(ins));
80554 			}
80555 
80556 			DUK__RETURN_SHARED();
80557 		}
80558 #else  /* DUK_USE_EXEC_PREFER_SIZE */
80559 		case DUK_OP_RETREG: {
80560 			duk_tval *tv;
80561 
80562 			DUK__SYNC_AND_NULL_CURR_PC();
80563 			tv = DUK__REGP_BC(ins);
80564 			DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
80565 			DUK_TVAL_INCREF(thr, tv);
80566 			thr->valstack_top++;
80567 			DUK__RETURN_SHARED();
80568 		}
80569 		/* This will be unused without refcounting. */
80570 		case DUK_OP_RETCONST: {
80571 			duk_tval *tv;
80572 
80573 			DUK__SYNC_AND_NULL_CURR_PC();
80574 			tv = DUK__CONSTP_BC(ins);
80575 			DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
80576 			DUK_TVAL_INCREF(thr, tv);
80577 			thr->valstack_top++;
80578 			DUK__RETURN_SHARED();
80579 		}
80580 		case DUK_OP_RETCONSTN: {
80581 			duk_tval *tv;
80582 
80583 			DUK__SYNC_AND_NULL_CURR_PC();
80584 			tv = DUK__CONSTP_BC(ins);
80585 			DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
80586 #if defined(DUK_USE_REFERENCE_COUNTING)
80587 			/* Without refcounting only RETCONSTN is used. */
80588 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv));  /* no INCREF for this constant */
80589 #endif
80590 			thr->valstack_top++;
80591 			DUK__RETURN_SHARED();
80592 		}
80593 		case DUK_OP_RETUNDEF: {
80594 			DUK__SYNC_AND_NULL_CURR_PC();
80595 			thr->valstack_top++;  /* value at valstack top is already undefined by valstack policy */
80596 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
80597 			DUK__RETURN_SHARED();
80598 		}
80599 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
80600 
80601 		case DUK_OP_LABEL: {
80602 			duk_activation *act;
80603 			duk_catcher *cat;
80604 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
80605 
80606 			/* Allocate catcher and populate it (must be atomic). */
80607 
80608 			cat = duk_hthread_catcher_alloc(thr);
80609 			DUK_ASSERT(cat != NULL);
80610 
80611 			cat->flags = (duk_uint32_t) (DUK_CAT_TYPE_LABEL | (bc << DUK_CAT_LABEL_SHIFT));
80612 			cat->pc_base = (duk_instr_t *) curr_pc;  /* pre-incremented, points to first jump slot */
80613 			cat->idx_base = 0;  /* unused for label */
80614 			cat->h_varname = NULL;
80615 
80616 			act = thr->callstack_curr;
80617 			DUK_ASSERT(act != NULL);
80618 			cat->parent = act->cat;
80619 			act->cat = cat;
80620 
80621 			DUK_DDD(DUK_DDDPRINT("LABEL catcher: flags=0x%08lx, pc_base=%ld, "
80622 			                     "idx_base=%ld, h_varname=%!O, label_id=%ld",
80623 			                     (long) cat->flags, (long) cat->pc_base,
80624 			                     (long) cat->idx_base, (duk_heaphdr *) cat->h_varname, (long) DUK_CAT_GET_LABEL(cat)));
80625 
80626 			curr_pc += 2;  /* skip jump slots */
80627 			break;
80628 		}
80629 
80630 		case DUK_OP_ENDLABEL: {
80631 			duk_activation *act;
80632 #if (defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)) || defined(DUK_USE_ASSERTIONS)
80633 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
80634 #endif
80635 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
80636 			DUK_DDD(DUK_DDDPRINT("ENDLABEL %ld", (long) bc));
80637 #endif
80638 
80639 			act = thr->callstack_curr;
80640 			DUK_ASSERT(act->cat != NULL);
80641 			DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_LABEL);
80642 			DUK_ASSERT((duk_uint_fast_t) DUK_CAT_GET_LABEL(act->cat) == bc);
80643 			duk_hthread_catcher_unwind_nolexenv_norz(thr, act);
80644 
80645 			/* no need to unwind callstack */
80646 			break;
80647 		}
80648 
80649 		case DUK_OP_BREAK: {
80650 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
80651 
80652 			DUK__SYNC_AND_NULL_CURR_PC();
80653 			duk__handle_break_or_continue(thr, (duk_uint_t) bc, DUK_LJ_TYPE_BREAK);
80654 			goto restart_execution;
80655 		}
80656 
80657 		case DUK_OP_CONTINUE: {
80658 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
80659 
80660 			DUK__SYNC_AND_NULL_CURR_PC();
80661 			duk__handle_break_or_continue(thr, (duk_uint_t) bc, DUK_LJ_TYPE_CONTINUE);
80662 			goto restart_execution;
80663 		}
80664 
80665 		/* XXX: move to helper, too large to be inline here */
80666 		case DUK_OP_TRYCATCH: {
80667 			duk__handle_op_trycatch(thr, ins, curr_pc);
80668 			curr_pc += 2;  /* skip jump slots */
80669 			break;
80670 		}
80671 
80672 		case DUK_OP_ENDTRY: {
80673 			curr_pc = duk__handle_op_endtry(thr, ins);
80674 			break;
80675 		}
80676 
80677 		case DUK_OP_ENDCATCH: {
80678 			duk__handle_op_endcatch(thr, ins);
80679 			break;
80680 		}
80681 
80682 		case DUK_OP_ENDFIN: {
80683 			/* Sync and NULL early. */
80684 			DUK__SYNC_AND_NULL_CURR_PC();
80685 
80686 			if (duk__handle_op_endfin(thr, ins, entry_act) != 0) {
80687 				return;
80688 			}
80689 
80690 			/* Must restart because we NULLed out curr_pc. */
80691 			goto restart_execution;
80692 		}
80693 
80694 		case DUK_OP_THROW: {
80695 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
80696 
80697 			/* Note: errors are augmented when they are created, not
80698 			 * when they are thrown.  So, don't augment here, it would
80699 			 * break re-throwing for instance.
80700 			 */
80701 
80702 			/* Sync so that augmentation sees up-to-date activations, NULL
80703 			 * thr->ptr_curr_pc so that it's not used if side effects occur
80704 			 * in augmentation or longjmp handling.
80705 			 */
80706 			DUK__SYNC_AND_NULL_CURR_PC();
80707 
80708 			duk_dup(thr, (duk_idx_t) bc);
80709 			DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (before throw augment)",
80710 			                     (duk_tval *) duk_get_tval(thr, -1)));
80711 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
80712 			duk_err_augment_error_throw(thr);
80713 			DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (after throw augment)",
80714 			                     (duk_tval *) duk_get_tval(thr, -1)));
80715 #endif
80716 
80717 			duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, DUK_GET_TVAL_NEGIDX(thr, -1));
80718 #if defined(DUK_USE_DEBUGGER_SUPPORT)
80719 			duk_err_check_debugger_integration(thr);
80720 #endif
80721 
80722 			DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* always in executor */
80723 			duk_err_longjmp(thr);
80724 			DUK_UNREACHABLE();
80725 			break;
80726 		}
80727 
80728 		case DUK_OP_CSREG: {
80729 			/*
80730 			 *  Assuming a register binds to a variable declared within this
80731 			 *  function (a declarative binding), the 'this' for the call
80732 			 *  setup is always 'undefined'.  E5 Section 10.2.1.1.6.
80733 			 */
80734 
80735 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
80736 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
80737 
80738 			/* A -> register containing target function (not type checked here)
80739 			 * BC -> target registers (BC, BC + 1) for call setup
80740 			 */
80741 
80742 #if defined(DUK_USE_PREFER_SIZE)
80743 			duk_dup(thr, (duk_idx_t) a);
80744 			duk_replace(thr, (duk_idx_t) bc);
80745 			duk_to_undefined(thr, (duk_idx_t) (bc + 1));
80746 #else
80747 			duk_tval *tv1;
80748 			duk_tval *tv2;
80749 			duk_tval *tv3;
80750 			duk_tval tv_tmp1;
80751 			duk_tval tv_tmp2;
80752 
80753 			tv1 = DUK__REGP(bc);
80754 			tv2 = tv1 + 1;
80755 			DUK_TVAL_SET_TVAL(&tv_tmp1, tv1);
80756 			DUK_TVAL_SET_TVAL(&tv_tmp2, tv2);
80757 			tv3 = DUK__REGP(a);
80758 			DUK_TVAL_SET_TVAL(tv1, tv3);
80759 			DUK_TVAL_INCREF(thr, tv1);  /* no side effects */
80760 			DUK_TVAL_SET_UNDEFINED(tv2);  /* no need for incref */
80761 			DUK_TVAL_DECREF(thr, &tv_tmp1);
80762 			DUK_TVAL_DECREF(thr, &tv_tmp2);
80763 #endif
80764 			break;
80765 		}
80766 
80767 
80768 		/* XXX: in some cases it's faster NOT to reuse the value
80769 		 * stack but rather copy the arguments on top of the stack
80770 		 * (mainly when the calling value stack is large and the value
80771 		 * stack resize would be large).
80772 		 */
80773 
80774 		case DUK_OP_CALL0:
80775 		case DUK_OP_CALL1:
80776 		case DUK_OP_CALL2:
80777 		case DUK_OP_CALL3:
80778 		case DUK_OP_CALL4:
80779 		case DUK_OP_CALL5:
80780 		case DUK_OP_CALL6:
80781 		case DUK_OP_CALL7: {
80782 			/* Opcode packs 4 flag bits: 1 for indirect, 3 map
80783 			 * 1:1 to three lowest call handling flags.
80784 			 *
80785 			 * A -> nargs or register with nargs (indirect)
80786 			 * BC -> base register for call (base -> func, base+1 -> this, base+2 -> arg1 ... base+2+N-1 -> argN)
80787 			 */
80788 
80789 			duk_idx_t nargs;
80790 			duk_idx_t idx;
80791 			duk_small_uint_t call_flags;
80792 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
80793 			duk_hcompfunc *fun;
80794 #endif
80795 
80796 			DUK_ASSERT((DUK_OP_CALL0 & 0x0fU) == 0);
80797 			DUK_ASSERT((ins & DUK_BC_CALL_FLAG_INDIRECT) == 0);
80798 
80799 			nargs = (duk_idx_t) DUK_DEC_A(ins);
80800 			call_flags = (ins & 0x07U) | DUK_CALL_FLAG_ALLOW_ECMATOECMA;
80801 			idx = (duk_idx_t) DUK_DEC_BC(ins);
80802 
80803 			if (duk__executor_handle_call(thr, idx, nargs, call_flags)) {
80804 				/* curr_pc synced by duk_handle_call_unprotected() */
80805 				DUK_ASSERT(thr->ptr_curr_pc == NULL);
80806 				goto restart_execution;
80807 			}
80808 			DUK_ASSERT(thr->ptr_curr_pc != NULL);
80809 
80810 			/* duk_js_call.c is required to restore the stack reserve
80811 			 * so we only need to reset the top.
80812 			 */
80813 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
80814 			fun = DUK__FUN();
80815 #endif
80816 			duk_set_top_unsafe(thr, (duk_idx_t) fun->nregs);
80817 
80818 			/* No need to reinit setjmp() catchpoint, as call handling
80819 			 * will store and restore our state.
80820 			 *
80821 			 * When debugger is enabled, we need to recheck the activation
80822 			 * status after returning.  This is now handled by call handling
80823 			 * and heap->dbg_force_restart.
80824 			 */
80825 			break;
80826 		}
80827 
80828 		case DUK_OP_CALL8:
80829 		case DUK_OP_CALL9:
80830 		case DUK_OP_CALL10:
80831 		case DUK_OP_CALL11:
80832 		case DUK_OP_CALL12:
80833 		case DUK_OP_CALL13:
80834 		case DUK_OP_CALL14:
80835 		case DUK_OP_CALL15: {
80836 			/* Indirect variant. */
80837 			duk_uint_fast_t nargs;
80838 			duk_idx_t idx;
80839 			duk_small_uint_t call_flags;
80840 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
80841 			duk_hcompfunc *fun;
80842 #endif
80843 
80844 			DUK_ASSERT((DUK_OP_CALL0 & 0x0fU) == 0);
80845 			DUK_ASSERT((ins & DUK_BC_CALL_FLAG_INDIRECT) != 0);
80846 
80847 			nargs = (duk_uint_fast_t) DUK_DEC_A(ins);
80848 			DUK__LOOKUP_INDIRECT(nargs);
80849 			call_flags = (ins & 0x07U) | DUK_CALL_FLAG_ALLOW_ECMATOECMA;
80850 			idx = (duk_idx_t) DUK_DEC_BC(ins);
80851 
80852 			if (duk__executor_handle_call(thr, idx, (duk_idx_t) nargs, call_flags)) {
80853 				DUK_ASSERT(thr->ptr_curr_pc == NULL);
80854 				goto restart_execution;
80855 			}
80856 			DUK_ASSERT(thr->ptr_curr_pc != NULL);
80857 
80858 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
80859 			fun = DUK__FUN();
80860 #endif
80861 			duk_set_top_unsafe(thr, (duk_idx_t) fun->nregs);
80862 			break;
80863 		}
80864 
80865 		case DUK_OP_NEWOBJ: {
80866 			duk_push_object(thr);
80867 #if defined(DUK_USE_ASSERTIONS)
80868 			{
80869 				duk_hobject *h;
80870 				h = duk_require_hobject(thr, -1);
80871 				DUK_ASSERT(DUK_HOBJECT_GET_ESIZE(h) == 0);
80872 				DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(h) == 0);
80873 				DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0);
80874 				DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(h) == 0);
80875 			}
80876 #endif
80877 #if !defined(DUK_USE_PREFER_SIZE)
80878 			/* XXX: could do a direct props realloc, but need hash size */
80879 			duk_hobject_resize_entrypart(thr, duk_known_hobject(thr, -1), DUK_DEC_A(ins));
80880 #endif
80881 			DUK__REPLACE_TOP_BC_BREAK();
80882 		}
80883 
80884 		case DUK_OP_NEWARR: {
80885 			duk_push_array(thr);
80886 #if defined(DUK_USE_ASSERTIONS)
80887 			{
80888 				duk_hobject *h;
80889 				h = duk_require_hobject(thr, -1);
80890 				DUK_ASSERT(DUK_HOBJECT_GET_ESIZE(h) == 0);
80891 				DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(h) == 0);
80892 				DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0);
80893 				DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(h) == 0);
80894 				DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(h));
80895 			}
80896 #endif
80897 #if !defined(DUK_USE_PREFER_SIZE)
80898 			duk_hobject_realloc_props(thr,
80899 			                          duk_known_hobject(thr, -1),
80900 			                          0 /*new_e_size*/,
80901 			                          DUK_DEC_A(ins) /*new_a_size*/,
80902 			                          0 /*new_h_size*/,
80903 			                          0 /*abandon_array*/);
80904 #if 0
80905 			duk_hobject_resize_arraypart(thr, duk_known_hobject(thr, -1), DUK_DEC_A(ins));
80906 #endif
80907 #endif
80908 			DUK__REPLACE_TOP_BC_BREAK();
80909 		}
80910 
80911 		case DUK_OP_MPUTOBJ:
80912 		case DUK_OP_MPUTOBJI: {
80913 			duk_idx_t obj_idx;
80914 			duk_uint_fast_t idx, idx_end;
80915 			duk_small_uint_fast_t count;
80916 
80917 			/* A -> register of target object
80918 			 * B -> first register of key/value pair list
80919 			 *      or register containing first register number if indirect
80920 			 * C -> number of key/value pairs * 2
80921 			 *      (= number of value stack indices used starting from 'B')
80922 			 */
80923 
80924 			obj_idx = DUK_DEC_A(ins);
80925 			DUK_ASSERT(duk_is_object(thr, obj_idx));
80926 
80927 			idx = (duk_uint_fast_t) DUK_DEC_B(ins);
80928 			if (DUK_DEC_OP(ins) == DUK_OP_MPUTOBJI) {
80929 				DUK__LOOKUP_INDIRECT(idx);
80930 			}
80931 
80932 			count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
80933 			DUK_ASSERT(count > 0);  /* compiler guarantees */
80934 			idx_end = idx + count;
80935 
80936 #if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
80937 			if (DUK_UNLIKELY(idx_end > (duk_uint_fast_t) duk_get_top(thr))) {
80938 				/* XXX: use duk_is_valid_index() instead? */
80939 				/* XXX: improve check; check against nregs, not against top */
80940 				DUK__INTERNAL_ERROR("MPUTOBJ out of bounds");
80941 			}
80942 #endif
80943 
80944 			/* Use 'force' flag to duk_def_prop() to ensure that any
80945 			 * inherited properties don't prevent the operation.
80946 			 * With ES2015 duplicate properties are allowed, so that we
80947 			 * must overwrite any previous data or accessor property.
80948 			 *
80949 			 * With ES2015 computed property names the literal keys
80950 			 * may be arbitrary values and need to be ToPropertyKey()
80951 			 * coerced at runtime.
80952 			 */
80953 			do {
80954 				/* XXX: faster initialization (direct access or better primitives) */
80955 				duk_dup(thr, (duk_idx_t) idx);
80956 				duk_dup(thr, (duk_idx_t) (idx + 1));
80957 				duk_def_prop(thr, obj_idx, DUK_DEFPROP_HAVE_VALUE |
80958 				                           DUK_DEFPROP_FORCE |
80959 				                           DUK_DEFPROP_SET_WRITABLE |
80960 				                           DUK_DEFPROP_SET_ENUMERABLE |
80961 				                           DUK_DEFPROP_SET_CONFIGURABLE);
80962 				idx += 2;
80963 			} while (idx < idx_end);
80964 			break;
80965 		}
80966 
80967 		case DUK_OP_INITSET:
80968 		case DUK_OP_INITGET: {
80969 			duk__handle_op_initset_initget(thr, ins);
80970 			break;
80971 		}
80972 
80973 		case DUK_OP_MPUTARR:
80974 		case DUK_OP_MPUTARRI: {
80975 			duk_idx_t obj_idx;
80976 			duk_uint_fast_t idx, idx_end;
80977 			duk_small_uint_fast_t count;
80978 			duk_tval *tv1;
80979 			duk_uint32_t arr_idx;
80980 
80981 			/* A -> register of target object
80982 			 * B -> first register of value data (start_index, value1, value2, ..., valueN)
80983 			 *      or register containing first register number if indirect
80984 			 * C -> number of key/value pairs (N)
80985 			 */
80986 
80987 			obj_idx = DUK_DEC_A(ins);
80988 			DUK_ASSERT(duk_is_object(thr, obj_idx));
80989 
80990 			idx = (duk_uint_fast_t) DUK_DEC_B(ins);
80991 			if (DUK_DEC_OP(ins) == DUK_OP_MPUTARRI) {
80992 				DUK__LOOKUP_INDIRECT(idx);
80993 			}
80994 
80995 			count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
80996 			DUK_ASSERT(count > 0 + 1);  /* compiler guarantees */
80997 			idx_end = idx + count;
80998 
80999 #if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
81000 			if (idx_end > (duk_uint_fast_t) duk_get_top(thr)) {
81001 				/* XXX: use duk_is_valid_index() instead? */
81002 				/* XXX: improve check; check against nregs, not against top */
81003 				DUK__INTERNAL_ERROR("MPUTARR out of bounds");
81004 			}
81005 #endif
81006 
81007 			tv1 = DUK__REGP(idx);
81008 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
81009 #if defined(DUK_USE_FASTINT)
81010 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
81011 			arr_idx = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv1);
81012 #else
81013 			arr_idx = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
81014 #endif
81015 			idx++;
81016 
81017 			do {
81018 				/* duk_xdef_prop() will define an own property without any array
81019 				 * special behaviors.  We'll need to set the array length explicitly
81020 				 * in the end.  For arrays with elisions, the compiler will emit an
81021 				 * explicit SETALEN which will update the length.
81022 				 */
81023 
81024 				/* XXX: because we're dealing with 'own' properties of a fresh array,
81025 				 * the array initializer should just ensure that the array has a large
81026 				 * enough array part and write the values directly into array part,
81027 				 * and finally set 'length' manually in the end (as already happens now).
81028 				 */
81029 
81030 				duk_dup(thr, (duk_idx_t) idx);
81031 				duk_xdef_prop_index_wec(thr, obj_idx, arr_idx);
81032 
81033 				idx++;
81034 				arr_idx++;
81035 			} while (idx < idx_end);
81036 
81037 			/* XXX: E5.1 Section 11.1.4 coerces the final length through
81038 			 * ToUint32() which is odd but happens now as a side effect of
81039 			 * 'arr_idx' type.
81040 			 */
81041 			duk_set_length(thr, obj_idx, (duk_size_t) (duk_uarridx_t) arr_idx);
81042 			break;
81043 		}
81044 
81045 		case DUK_OP_SETALEN: {
81046 			duk_tval *tv1;
81047 			duk_hobject *h;
81048 			duk_uint32_t len;
81049 
81050 			tv1 = DUK__REGP_A(ins);
81051 			DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
81052 			h = DUK_TVAL_GET_OBJECT(tv1);
81053 			DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(h));
81054 
81055 			tv1 = DUK__REGP_BC(ins);
81056 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
81057 #if defined(DUK_USE_FASTINT)
81058 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
81059 			len = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv1);
81060 #else
81061 			len = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
81062 #endif
81063 			((duk_harray *) h)->length = len;
81064 			break;
81065 		}
81066 
81067 		case DUK_OP_INITENUM: {
81068 			duk__handle_op_initenum(thr, ins);
81069 			break;
81070 		}
81071 
81072 		case DUK_OP_NEXTENUM: {
81073 			curr_pc += duk__handle_op_nextenum(thr, ins);
81074 			break;
81075 		}
81076 
81077 		case DUK_OP_INVLHS: {
81078 			DUK_ERROR_REFERENCE(thr, DUK_STR_INVALID_LVALUE);
81079 			DUK_WO_NORETURN(return;);
81080 			break;
81081 		}
81082 
81083 		case DUK_OP_DEBUGGER: {
81084 			/* Opcode only emitted by compiler when debugger
81085 			 * support is enabled.  Ignore it silently without
81086 			 * debugger support, in case it has been loaded
81087 			 * from precompiled bytecode.
81088 			 */
81089 #if defined(DUK_USE_DEBUGGER_SUPPORT)
81090 			if (duk_debug_is_attached(thr->heap)) {
81091 				DUK_D(DUK_DPRINT("DEBUGGER statement encountered, halt execution"));
81092 				DUK__SYNC_AND_NULL_CURR_PC();
81093 				duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
81094 				DUK_D(DUK_DPRINT("DEBUGGER statement finished, resume execution"));
81095 				goto restart_execution;
81096 			} else {
81097 				DUK_D(DUK_DPRINT("DEBUGGER statement ignored, debugger not attached"));
81098 			}
81099 #else
81100 			DUK_D(DUK_DPRINT("DEBUGGER statement ignored, no debugger support"));
81101 #endif
81102 			break;
81103 		}
81104 
81105 		case DUK_OP_NOP: {
81106 			/* Nop, ignored, but ABC fields may carry a value e.g.
81107 			 * for indirect opcode handling.
81108 			 */
81109 			break;
81110 		}
81111 
81112 		case DUK_OP_INVALID: {
81113 			DUK_ERROR_FMT1(thr, DUK_ERR_ERROR, "INVALID opcode (%ld)", (long) DUK_DEC_ABC(ins));
81114 			DUK_WO_NORETURN(return;);
81115 			break;
81116 		}
81117 
81118 #if defined(DUK_USE_ES6)
81119 		case DUK_OP_NEWTARGET: {
81120 			duk_push_new_target(thr);
81121 			DUK__REPLACE_TOP_BC_BREAK();
81122 		}
81123 #endif  /* DUK_USE_ES6 */
81124 
81125 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
81126 #if !defined(DUK_USE_ES7_EXP_OPERATOR)
81127 		case DUK_OP_EXP_RR:
81128 		case DUK_OP_EXP_CR:
81129 		case DUK_OP_EXP_RC:
81130 		case DUK_OP_EXP_CC:
81131 #endif
81132 #if !defined(DUK_USE_ES6)
81133 		case DUK_OP_NEWTARGET:
81134 #endif
81135 #if !defined(DUK_USE_VERBOSE_ERRORS)
81136 		case DUK_OP_GETPROPC_RR:
81137 		case DUK_OP_GETPROPC_CR:
81138 		case DUK_OP_GETPROPC_RC:
81139 		case DUK_OP_GETPROPC_CC:
81140 #endif
81141 		case DUK_OP_UNUSED207:
81142 		case DUK_OP_UNUSED212:
81143 		case DUK_OP_UNUSED213:
81144 		case DUK_OP_UNUSED214:
81145 		case DUK_OP_UNUSED215:
81146 		case DUK_OP_UNUSED216:
81147 		case DUK_OP_UNUSED217:
81148 		case DUK_OP_UNUSED218:
81149 		case DUK_OP_UNUSED219:
81150 		case DUK_OP_UNUSED220:
81151 		case DUK_OP_UNUSED221:
81152 		case DUK_OP_UNUSED222:
81153 		case DUK_OP_UNUSED223:
81154 		case DUK_OP_UNUSED224:
81155 		case DUK_OP_UNUSED225:
81156 		case DUK_OP_UNUSED226:
81157 		case DUK_OP_UNUSED227:
81158 		case DUK_OP_UNUSED228:
81159 		case DUK_OP_UNUSED229:
81160 		case DUK_OP_UNUSED230:
81161 		case DUK_OP_UNUSED231:
81162 		case DUK_OP_UNUSED232:
81163 		case DUK_OP_UNUSED233:
81164 		case DUK_OP_UNUSED234:
81165 		case DUK_OP_UNUSED235:
81166 		case DUK_OP_UNUSED236:
81167 		case DUK_OP_UNUSED237:
81168 		case DUK_OP_UNUSED238:
81169 		case DUK_OP_UNUSED239:
81170 		case DUK_OP_UNUSED240:
81171 		case DUK_OP_UNUSED241:
81172 		case DUK_OP_UNUSED242:
81173 		case DUK_OP_UNUSED243:
81174 		case DUK_OP_UNUSED244:
81175 		case DUK_OP_UNUSED245:
81176 		case DUK_OP_UNUSED246:
81177 		case DUK_OP_UNUSED247:
81178 		case DUK_OP_UNUSED248:
81179 		case DUK_OP_UNUSED249:
81180 		case DUK_OP_UNUSED250:
81181 		case DUK_OP_UNUSED251:
81182 		case DUK_OP_UNUSED252:
81183 		case DUK_OP_UNUSED253:
81184 		case DUK_OP_UNUSED254:
81185 		case DUK_OP_UNUSED255:
81186 		/* Force all case clauses to map to an actual handler
81187 		 * so that the compiler can emit a jump without a bounds
81188 		 * check: the switch argument is a duk_uint8_t so that
81189 		 * the compiler may be able to figure it out.  This is
81190 		 * a small detail and obviously compiler dependent.
81191 		 */
81192 		/* default: clause omitted on purpose */
81193 #else  /* DUK_USE_EXEC_PREFER_SIZE */
81194 		default:
81195 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
81196 		{
81197 			/* Default case catches invalid/unsupported opcodes. */
81198 			DUK_D(DUK_DPRINT("invalid opcode: %ld - %!I", (long) op, ins));
81199 			DUK__INTERNAL_ERROR("invalid opcode");
81200 			break;
81201 		}
81202 
81203 		}  /* end switch */
81204 
81205 		continue;
81206 
81207 		/* Some shared exit paths for opcode handling below.  These
81208 		 * are mostly useful to reduce code footprint when multiple
81209 		 * opcodes have a similar epilogue (like replacing stack top
81210 		 * with index 'a').
81211 		 */
81212 
81213 #if defined(DUK_USE_EXEC_PREFER_SIZE)
81214 	 replace_top_a:
81215 		DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_A(ins));
81216 		continue;
81217 	 replace_top_bc:
81218 		DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_BC(ins));
81219 		continue;
81220 #endif
81221 	}
81222 	DUK_WO_NORETURN(return;);
81223 
81224 #if !defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS)
81225  internal_error:
81226 	DUK_ERROR_INTERNAL(thr);
81227 	DUK_WO_NORETURN(return;);
81228 #endif
81229 }
81230 
81231 /* automatic undefs */
81232 #undef DUK__BYTEOFF_A
81233 #undef DUK__BYTEOFF_B
81234 #undef DUK__BYTEOFF_BC
81235 #undef DUK__BYTEOFF_C
81236 #undef DUK__COMPARE_BODY
81237 #undef DUK__CONST
81238 #undef DUK__CONSTP
81239 #undef DUK__CONSTP_A
81240 #undef DUK__CONSTP_B
81241 #undef DUK__CONSTP_BC
81242 #undef DUK__CONSTP_C
81243 #undef DUK__DELPROP_BODY
81244 #undef DUK__EQ_BODY
81245 #undef DUK__FUN
81246 #undef DUK__GETPROPC_BODY
81247 #undef DUK__GETPROP_BODY
81248 #undef DUK__GE_BODY
81249 #undef DUK__GT_BODY
81250 #undef DUK__INSTOF_BODY
81251 #undef DUK__INTERNAL_ERROR
81252 #undef DUK__INT_NOACTION
81253 #undef DUK__INT_RESTART
81254 #undef DUK__IN_BODY
81255 #undef DUK__LE_BODY
81256 #undef DUK__LONGJMP_RESTART
81257 #undef DUK__LONGJMP_RETHROW
81258 #undef DUK__LOOKUP_INDIRECT
81259 #undef DUK__LT_BODY
81260 #undef DUK__MASK_A
81261 #undef DUK__MASK_B
81262 #undef DUK__MASK_BC
81263 #undef DUK__MASK_C
81264 #undef DUK__NEQ_BODY
81265 #undef DUK__PUTPROP_BODY
81266 #undef DUK__RCBIT_B
81267 #undef DUK__RCBIT_C
81268 #undef DUK__REG
81269 #undef DUK__REGCONSTP_B
81270 #undef DUK__REGCONSTP_C
81271 #undef DUK__REGP
81272 #undef DUK__REGP_A
81273 #undef DUK__REGP_B
81274 #undef DUK__REGP_BC
81275 #undef DUK__REGP_C
81276 #undef DUK__REPLACE_BOOL_A_BREAK
81277 #undef DUK__REPLACE_TOP_A_BREAK
81278 #undef DUK__REPLACE_TOP_BC_BREAK
81279 #undef DUK__REPLACE_TO_TVPTR
81280 #undef DUK__RETHAND_FINISHED
81281 #undef DUK__RETHAND_RESTART
81282 #undef DUK__RETURN_SHARED
81283 #undef DUK__SEQ_BODY
81284 #undef DUK__SHIFT_A
81285 #undef DUK__SHIFT_B
81286 #undef DUK__SHIFT_BC
81287 #undef DUK__SHIFT_C
81288 #undef DUK__SNEQ_BODY
81289 #undef DUK__STRICT
81290 #undef DUK__SYNC_AND_NULL_CURR_PC
81291 #undef DUK__SYNC_CURR_PC
81292 #undef DUK__TVAL_SHIFT
81293 #line 1 "duk_js_ops.c"
81294 /*
81295  *  ECMAScript specification algorithm and conversion helpers.
81296  *
81297  *  These helpers encapsulate the primitive ECMAScript operation semantics,
81298  *  and are used by the bytecode executor and the API (among other places).
81299  *  Some primitives are only implemented as part of the API and have no
81300  *  "internal" helper.  This is the case when an internal helper would not
81301  *  really be useful; e.g. the operation is rare, uses value stack heavily,
81302  *  etc.
81303  *
81304  *  The operation arguments depend on what is required to implement
81305  *  the operation:
81306  *
81307  *    - If an operation is simple and stateless, and has no side
81308  *      effects, it won't take an duk_hthread argument and its
81309  *      arguments may be duk_tval pointers (which are safe as long
81310  *      as no side effects take place).
81311  *
81312  *    - If complex coercions are required (e.g. a "ToNumber" coercion)
81313  *      or errors may be thrown, the operation takes an duk_hthread
81314  *      argument.  This also implies that the operation may have
81315  *      arbitrary side effects, invalidating any duk_tval pointers.
81316  *
81317  *    - For operations with potential side effects, arguments can be
81318  *      taken in several ways:
81319  *
81320  *      a) as duk_tval pointers, which makes sense if the "common case"
81321  *         can be resolved without side effects (e.g. coercion); the
81322  *         arguments are pushed to the valstack for coercion if
81323  *         necessary
81324  *
81325  *      b) as duk_tval values
81326  *
81327  *      c) implicitly on value stack top
81328  *
81329  *      d) as indices to the value stack
81330  *
81331  *  Future work:
81332  *
81333  *     - Argument styles may not be the most sensible in every case now.
81334  *
81335  *     - In-place coercions might be useful for several operations, if
81336  *       in-place coercion is OK for the bytecode executor and the API.
81337  */
81338 
81339 /* #include duk_internal.h -> already included */
81340 
81341 /*
81342  *  ToPrimitive()  (E5 Section 9.1)
81343  *
81344  *  ==> implemented in the API.
81345  */
81346 
81347 /*
81348  *  ToBoolean()  (E5 Section 9.2)
81349  */
81350 
81351 DUK_INTERNAL duk_bool_t duk_js_toboolean(duk_tval *tv) {
81352 	switch (DUK_TVAL_GET_TAG(tv)) {
81353 	case DUK_TAG_UNDEFINED:
81354 	case DUK_TAG_NULL:
81355 		return 0;
81356 	case DUK_TAG_BOOLEAN:
81357 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 || DUK_TVAL_GET_BOOLEAN(tv) == 1);
81358 		return DUK_TVAL_GET_BOOLEAN(tv);
81359 	case DUK_TAG_STRING: {
81360 		/* Symbols ToBoolean() coerce to true, regardless of their
81361 		 * description.  This happens with no explicit check because
81362 		 * of the symbol representation byte prefix.
81363 		 */
81364 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
81365 		DUK_ASSERT(h != NULL);
81366 		return (DUK_HSTRING_GET_BYTELEN(h) > 0 ? 1 : 0);
81367 	}
81368 	case DUK_TAG_OBJECT: {
81369 		return 1;
81370 	}
81371 	case DUK_TAG_BUFFER: {
81372 		/* Mimic Uint8Array semantics: objects coerce true, regardless
81373 		 * of buffer length (zero or not) or context.
81374 		 */
81375 		return 1;
81376 	}
81377 	case DUK_TAG_POINTER: {
81378 		void *p = DUK_TVAL_GET_POINTER(tv);
81379 		return (p != NULL ? 1 : 0);
81380 	}
81381 	case DUK_TAG_LIGHTFUNC: {
81382 		return 1;
81383 	}
81384 #if defined(DUK_USE_FASTINT)
81385 	case DUK_TAG_FASTINT:
81386 		if (DUK_TVAL_GET_FASTINT(tv) != 0) {
81387 			return 1;
81388 		} else {
81389 			return 0;
81390 		}
81391 #endif
81392 	default: {
81393 		/* number */
81394 		duk_double_t d;
81395 #if defined(DUK_USE_PREFER_SIZE)
81396 		int c;
81397 #endif
81398 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
81399 		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
81400 		d = DUK_TVAL_GET_DOUBLE(tv);
81401 #if defined(DUK_USE_PREFER_SIZE)
81402 		c = DUK_FPCLASSIFY((double) d);
81403 		if (c == DUK_FP_ZERO || c == DUK_FP_NAN) {
81404 			return 0;
81405 		} else {
81406 			return 1;
81407 		}
81408 #else
81409 		DUK_ASSERT(duk_double_is_nan_or_zero(d) == 0 || duk_double_is_nan_or_zero(d) == 1);
81410 		return duk_double_is_nan_or_zero(d) ^ 1;
81411 #endif
81412 	}
81413 	}
81414 	DUK_UNREACHABLE();
81415 	DUK_WO_UNREACHABLE(return 0;);
81416 }
81417 
81418 /*
81419  *  ToNumber()  (E5 Section 9.3)
81420  *
81421  *  Value to convert must be on stack top, and is popped before exit.
81422  *
81423  *  See: http://www.cs.indiana.edu/~burger/FP-Printing-PLDI96.pdf
81424  *       http://www.cs.indiana.edu/~burger/fp/index.html
81425  *
81426  *  Notes on the conversion:
81427  *
81428  *    - There are specific requirements on the accuracy of the conversion
81429  *      through a "Mathematical Value" (MV), so this conversion is not
81430  *      trivial.
81431  *
81432  *    - Quick rejects (e.g. based on first char) are difficult because
81433  *      the grammar allows leading and trailing white space.
81434  *
81435  *    - Quick reject based on string length is difficult even after
81436  *      accounting for white space; there may be arbitrarily many
81437  *      decimal digits.
81438  *
81439  *    - Standard grammar allows decimal values ("123"), hex values
81440  *      ("0x123") and infinities
81441  *
81442  *    - Unlike source code literals, ToNumber() coerces empty strings
81443  *      and strings with only whitespace to zero (not NaN).  However,
81444  *      while '' coerces to 0, '+' and '-' coerce to NaN.
81445  */
81446 
81447 /* E5 Section 9.3.1 */
81448 DUK_LOCAL duk_double_t duk__tonumber_string_raw(duk_hthread *thr) {
81449 	duk_small_uint_t s2n_flags;
81450 	duk_double_t d;
81451 
81452 	DUK_ASSERT(duk_is_string(thr, -1));
81453 
81454 	/* Quite lenient, e.g. allow empty as zero, but don't allow trailing
81455 	 * garbage.
81456 	 */
81457 	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
81458 	            DUK_S2N_FLAG_ALLOW_EXP |
81459 	            DUK_S2N_FLAG_ALLOW_PLUS |
81460 	            DUK_S2N_FLAG_ALLOW_MINUS |
81461 	            DUK_S2N_FLAG_ALLOW_INF |
81462 	            DUK_S2N_FLAG_ALLOW_FRAC |
81463 	            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
81464 	            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
81465 	            DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO |
81466 	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
81467 	            DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT |
81468 	            DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT |
81469 	            DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT;
81470 
81471 	duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
81472 
81473 #if defined(DUK_USE_PREFER_SIZE)
81474 	d = duk_get_number(thr, -1);
81475 	duk_pop_unsafe(thr);
81476 #else
81477 	thr->valstack_top--;
81478 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(thr->valstack_top));
81479 	DUK_ASSERT(DUK_TVAL_IS_DOUBLE(thr->valstack_top));  /* no fastint conversion in numconv now */
81480 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(thr->valstack_top));
81481 	d = DUK_TVAL_GET_DOUBLE(thr->valstack_top);  /* assumes not a fastint */
81482 	DUK_TVAL_SET_UNDEFINED(thr->valstack_top);
81483 #endif
81484 
81485 	return d;
81486 }
81487 
81488 DUK_INTERNAL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv) {
81489 	DUK_ASSERT(thr != NULL);
81490 	DUK_ASSERT(tv != NULL);
81491 
81492 	switch (DUK_TVAL_GET_TAG(tv)) {
81493 	case DUK_TAG_UNDEFINED: {
81494 		/* return a specific NaN (although not strictly necessary) */
81495 		duk_double_union du;
81496 		DUK_DBLUNION_SET_NAN(&du);
81497 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
81498 		return du.d;
81499 	}
81500 	case DUK_TAG_NULL: {
81501 		/* +0.0 */
81502 		return 0.0;
81503 	}
81504 	case DUK_TAG_BOOLEAN: {
81505 		if (DUK_TVAL_IS_BOOLEAN_TRUE(tv)) {
81506 			return 1.0;
81507 		}
81508 		return 0.0;
81509 	}
81510 	case DUK_TAG_STRING: {
81511 		/* For Symbols ToNumber() is always a TypeError. */
81512 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
81513 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
81514 			DUK_ERROR_TYPE(thr, DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL);
81515 			DUK_WO_NORETURN(return 0.0;);
81516 		}
81517 		duk_push_hstring(thr, h);
81518 		return duk__tonumber_string_raw(thr);
81519 	}
81520 	case DUK_TAG_BUFFER:  /* plain buffer treated like object */
81521 	case DUK_TAG_OBJECT: {
81522 		duk_double_t d;
81523 		duk_push_tval(thr, tv);
81524 		duk_to_primitive(thr, -1, DUK_HINT_NUMBER);  /* 'tv' becomes invalid */
81525 
81526 		/* recursive call for a primitive value (guaranteed not to cause second
81527 		 * recursion).
81528 		 */
81529 		DUK_ASSERT(duk_get_tval(thr, -1) != NULL);
81530 		d = duk_js_tonumber(thr, duk_get_tval(thr, -1));
81531 
81532 		duk_pop_unsafe(thr);
81533 		return d;
81534 	}
81535 	case DUK_TAG_POINTER: {
81536 		/* Coerce like boolean */
81537 		void *p = DUK_TVAL_GET_POINTER(tv);
81538 		return (p != NULL ? 1.0 : 0.0);
81539 	}
81540 	case DUK_TAG_LIGHTFUNC: {
81541 		/* +(function(){}) -> NaN */
81542 		return DUK_DOUBLE_NAN;
81543 	}
81544 #if defined(DUK_USE_FASTINT)
81545 	case DUK_TAG_FASTINT:
81546 		return (duk_double_t) DUK_TVAL_GET_FASTINT(tv);
81547 #endif
81548 	default: {
81549 		/* number */
81550 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
81551 		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
81552 		return DUK_TVAL_GET_DOUBLE(tv);
81553 	}
81554 	}
81555 
81556 	DUK_UNREACHABLE();
81557 	DUK_WO_UNREACHABLE(return 0.0;);
81558 }
81559 
81560 /*
81561  *  ToInteger()  (E5 Section 9.4)
81562  */
81563 
81564 /* exposed, used by e.g. duk_bi_date.c */
81565 DUK_INTERNAL duk_double_t duk_js_tointeger_number(duk_double_t x) {
81566 #if defined(DUK_USE_PREFER_SIZE)
81567 	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
81568 
81569 	if (DUK_UNLIKELY(c == DUK_FP_NAN)) {
81570 		return 0.0;
81571 	} else if (DUK_UNLIKELY(c == DUK_FP_INFINITE)) {
81572 		return x;
81573 	} else {
81574 		/* Finite, including neg/pos zero.  Neg zero sign must be
81575 		 * preserved.
81576 		 */
81577 		return duk_double_trunc_towards_zero(x);
81578 	}
81579 #else  /* DUK_USE_PREFER_SIZE */
81580 	/* NaN and Infinity have the same exponent so it's a cheap
81581 	 * initial check for the rare path.
81582 	 */
81583 	if (DUK_UNLIKELY(duk_double_is_nan_or_inf(x) != 0U)) {
81584 		if (duk_double_is_nan(x)) {
81585 			return 0.0;
81586 		} else {
81587 			return x;
81588 		}
81589 	} else {
81590 		return duk_double_trunc_towards_zero(x);
81591 	}
81592 #endif  /* DUK_USE_PREFER_SIZE */
81593 }
81594 
81595 DUK_INTERNAL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv) {
81596 	/* XXX: fastint */
81597 	duk_double_t d = duk_js_tonumber(thr, tv);  /* invalidates tv */
81598 	return duk_js_tointeger_number(d);
81599 }
81600 
81601 /*
81602  *  ToInt32(), ToUint32(), ToUint16()  (E5 Sections 9.5, 9.6, 9.7)
81603  */
81604 
81605 /* combined algorithm matching E5 Sections 9.5 and 9.6 */
81606 DUK_LOCAL duk_double_t duk__toint32_touint32_helper(duk_double_t x, duk_bool_t is_toint32) {
81607 #if defined (DUK_USE_PREFER_SIZE)
81608 	duk_small_int_t c;
81609 #endif
81610 
81611 #if defined (DUK_USE_PREFER_SIZE)
81612 	c = (duk_small_int_t) DUK_FPCLASSIFY(x);
81613 	if (c == DUK_FP_NAN || c == DUK_FP_ZERO || c == DUK_FP_INFINITE) {
81614 		return 0.0;
81615 	}
81616 #else
81617 	if (duk_double_is_nan_zero_inf(x)) {
81618 		return 0.0;
81619 	}
81620 #endif
81621 
81622 	/* x = sign(x) * floor(abs(x)), i.e. truncate towards zero, keep sign */
81623 	x = duk_double_trunc_towards_zero(x);
81624 
81625 	/* NOTE: fmod(x) result sign is same as sign of x, which
81626 	 * differs from what Javascript wants (see Section 9.6).
81627 	 */
81628 
81629 	x = DUK_FMOD(x, DUK_DOUBLE_2TO32);    /* -> x in ]-2**32, 2**32[ */
81630 
81631 	if (x < 0.0) {
81632 		x += DUK_DOUBLE_2TO32;
81633 	}
81634 	DUK_ASSERT(x >= 0 && x < DUK_DOUBLE_2TO32);  /* -> x in [0, 2**32[ */
81635 
81636 	if (is_toint32) {
81637 		if (x >= DUK_DOUBLE_2TO31) {
81638 			/* x in [2**31, 2**32[ */
81639 
81640 			x -= DUK_DOUBLE_2TO32;  /* -> x in [-2**31,2**31[ */
81641 		}
81642 	}
81643 
81644 	return x;
81645 }
81646 
81647 DUK_INTERNAL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv) {
81648 	duk_double_t d;
81649 
81650 #if defined(DUK_USE_FASTINT)
81651 	if (DUK_TVAL_IS_FASTINT(tv)) {
81652 		return DUK_TVAL_GET_FASTINT_I32(tv);
81653 	}
81654 #endif
81655 
81656 	d = duk_js_tonumber(thr, tv);  /* invalidates tv */
81657 	d = duk__toint32_touint32_helper(d, 1);
81658 	DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);
81659 	DUK_ASSERT(d >= -2147483648.0 && d <= 2147483647.0);  /* [-0x80000000,0x7fffffff] */
81660 	DUK_ASSERT(duk_double_equals(d, (duk_double_t) ((duk_int32_t) d)));  /* whole, won't clip */
81661 	return (duk_int32_t) d;
81662 }
81663 
81664 
81665 DUK_INTERNAL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv) {
81666 	duk_double_t d;
81667 
81668 #if defined(DUK_USE_FASTINT)
81669 	if (DUK_TVAL_IS_FASTINT(tv)) {
81670 		return DUK_TVAL_GET_FASTINT_U32(tv);
81671 	}
81672 #endif
81673 
81674 	d = duk_js_tonumber(thr, tv);  /* invalidates tv */
81675 	d = duk__toint32_touint32_helper(d, 0);
81676 	DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);
81677 	DUK_ASSERT(d >= 0.0 && d <= 4294967295.0);  /* [0x00000000, 0xffffffff] */
81678 	DUK_ASSERT(duk_double_equals(d, (duk_double_t) ((duk_uint32_t) d)));  /* whole, won't clip */
81679 	return (duk_uint32_t) d;
81680 
81681 }
81682 
81683 DUK_INTERNAL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv) {
81684 	/* should be a safe way to compute this */
81685 	return (duk_uint16_t) (duk_js_touint32(thr, tv) & 0x0000ffffU);
81686 }
81687 
81688 /*
81689  *  ToString()  (E5 Section 9.8)
81690  *  ToObject()  (E5 Section 9.9)
81691  *  CheckObjectCoercible()  (E5 Section 9.10)
81692  *  IsCallable()  (E5 Section 9.11)
81693  *
81694  *  ==> implemented in the API.
81695  */
81696 
81697 /*
81698  *  Loose equality, strict equality, and SameValue (E5 Sections 11.9.1, 11.9.4,
81699  *  9.12).  These have much in common so they can share some helpers.
81700  *
81701  *  Future work notes:
81702  *
81703  *    - Current implementation (and spec definition) has recursion; this should
81704  *      be fixed if possible.
81705  *
81706  *    - String-to-number coercion should be possible without going through the
81707  *      value stack (and be more compact) if a shared helper is invoked.
81708  */
81709 
81710 /* Note that this is the same operation for strict and loose equality:
81711  *  - E5 Section 11.9.3, step 1.c (loose)
81712  *  - E5 Section 11.9.6, step 4 (strict)
81713  */
81714 
81715 DUK_LOCAL duk_bool_t duk__js_equals_number(duk_double_t x, duk_double_t y) {
81716 #if defined(DUK_USE_PARANOID_MATH)
81717 	/* Straightforward algorithm, makes fewer compiler assumptions. */
81718 	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
81719 	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
81720 	if (cx == DUK_FP_NAN || cy == DUK_FP_NAN) {
81721 		return 0;
81722 	}
81723 	if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
81724 		return 1;
81725 	}
81726 	if (x == y) {
81727 		return 1;
81728 	}
81729 	return 0;
81730 #else  /* DUK_USE_PARANOID_MATH */
81731 	/* Better equivalent algorithm.  If the compiler is compliant, C and
81732 	 * ECMAScript semantics are identical for this particular comparison.
81733 	 * In particular, NaNs must never compare equal and zeroes must compare
81734 	 * equal regardless of sign.  Could also use a macro, but this inlines
81735 	 * already nicely (no difference on gcc, for instance).
81736 	 */
81737 	if (duk_double_equals(x, y)) {
81738 		/* IEEE requires that NaNs compare false */
81739 		DUK_ASSERT(DUK_FPCLASSIFY(x) != DUK_FP_NAN);
81740 		DUK_ASSERT(DUK_FPCLASSIFY(y) != DUK_FP_NAN);
81741 		return 1;
81742 	} else {
81743 		/* IEEE requires that zeros compare the same regardless
81744 		 * of their signed, so if both x and y are zeroes, they
81745 		 * are caught above.
81746 		 */
81747 		DUK_ASSERT(!(DUK_FPCLASSIFY(x) == DUK_FP_ZERO && DUK_FPCLASSIFY(y) == DUK_FP_ZERO));
81748 		return 0;
81749 	}
81750 #endif  /* DUK_USE_PARANOID_MATH */
81751 }
81752 
81753 DUK_LOCAL duk_bool_t duk__js_samevalue_number(duk_double_t x, duk_double_t y) {
81754 #if defined(DUK_USE_PARANOID_MATH)
81755 	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
81756 	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
81757 
81758 	if (cx == DUK_FP_NAN && cy == DUK_FP_NAN) {
81759 		/* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
81760 		return 1;
81761 	}
81762 	if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
81763 		/* Note: cannot assume that a non-zero return value of signbit() would
81764 		 * always be the same -- hence cannot (portably) use something like:
81765 		 *
81766 		 *     signbit(x) == signbit(y)
81767 		 */
81768 		duk_small_int_t sx = DUK_SIGNBIT(x) ? 1 : 0;
81769 		duk_small_int_t sy = DUK_SIGNBIT(y) ? 1 : 0;
81770 		return (sx == sy);
81771 	}
81772 
81773 	/* normal comparison; known:
81774 	 *   - both x and y are not NaNs (but one of them can be)
81775 	 *   - both x and y are not zero (but one of them can be)
81776 	 *   - x and y may be denormal or infinite
81777 	 */
81778 
81779 	return (x == y);
81780 #else  /* DUK_USE_PARANOID_MATH */
81781 	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
81782 	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
81783 
81784 	if (duk_double_equals(x, y)) {
81785 		/* IEEE requires that NaNs compare false */
81786 		DUK_ASSERT(DUK_FPCLASSIFY(x) != DUK_FP_NAN);
81787 		DUK_ASSERT(DUK_FPCLASSIFY(y) != DUK_FP_NAN);
81788 
81789 		/* Using classification has smaller footprint than direct comparison. */
81790 		if (DUK_UNLIKELY(cx == DUK_FP_ZERO && cy == DUK_FP_ZERO)) {
81791 			/* Note: cannot assume that a non-zero return value of signbit() would
81792 			 * always be the same -- hence cannot (portably) use something like:
81793 			 *
81794 			 *     signbit(x) == signbit(y)
81795 			 */
81796 			return duk_double_same_sign(x, y);
81797 		}
81798 		return 1;
81799 	} else {
81800 		/* IEEE requires that zeros compare the same regardless
81801 		 * of their sign, so if both x and y are zeroes, they
81802 		 * are caught above.
81803 		 */
81804 		DUK_ASSERT(!(DUK_FPCLASSIFY(x) == DUK_FP_ZERO && DUK_FPCLASSIFY(y) == DUK_FP_ZERO));
81805 
81806 		/* Difference to non-strict/strict comparison is that NaNs compare
81807 		 * equal and signed zero signs matter.
81808 		 */
81809 		if (DUK_UNLIKELY(cx == DUK_FP_NAN && cy == DUK_FP_NAN)) {
81810 			/* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
81811 			return 1;
81812 		}
81813 		return 0;
81814 	}
81815 #endif  /* DUK_USE_PARANOID_MATH */
81816 }
81817 
81818 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) {
81819 	duk_uint_t type_mask_x;
81820 	duk_uint_t type_mask_y;
81821 
81822 	/* If flags != 0 (strict or SameValue), thr can be NULL.  For loose
81823 	 * equals comparison it must be != NULL.
81824 	 */
81825 	DUK_ASSERT(flags != 0 || thr != NULL);
81826 
81827 	/*
81828 	 *  Same type?
81829 	 *
81830 	 *  Note: since number values have no explicit tag in the 8-byte
81831 	 *  representation, need the awkward if + switch.
81832 	 */
81833 
81834 #if defined(DUK_USE_FASTINT)
81835 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
81836 		if (DUK_TVAL_GET_FASTINT(tv_x) == DUK_TVAL_GET_FASTINT(tv_y)) {
81837 			return 1;
81838 		} else {
81839 			return 0;
81840 		}
81841 	}
81842 	else
81843 #endif
81844 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
81845 		duk_double_t d1, d2;
81846 
81847 		/* Catches both doubles and cases where only one argument is
81848 		 * a fastint so can't assume a double.
81849 		 */
81850 		d1 = DUK_TVAL_GET_NUMBER(tv_x);
81851 		d2 = DUK_TVAL_GET_NUMBER(tv_y);
81852 		if (DUK_UNLIKELY((flags & DUK_EQUALS_FLAG_SAMEVALUE) != 0)) {
81853 			/* SameValue */
81854 			return duk__js_samevalue_number(d1, d2);
81855 		} else {
81856 			/* equals and strict equals */
81857 			return duk__js_equals_number(d1, d2);
81858 		}
81859 	} else if (DUK_TVAL_GET_TAG(tv_x) == DUK_TVAL_GET_TAG(tv_y)) {
81860 		switch (DUK_TVAL_GET_TAG(tv_x)) {
81861 		case DUK_TAG_UNDEFINED:
81862 		case DUK_TAG_NULL: {
81863 			return 1;
81864 		}
81865 		case DUK_TAG_BOOLEAN: {
81866 			return DUK_TVAL_GET_BOOLEAN(tv_x) == DUK_TVAL_GET_BOOLEAN(tv_y);
81867 		}
81868 		case DUK_TAG_POINTER: {
81869 			return DUK_TVAL_GET_POINTER(tv_x) == DUK_TVAL_GET_POINTER(tv_y);
81870 		}
81871 		case DUK_TAG_STRING:
81872 		case DUK_TAG_OBJECT: {
81873 			/* Heap pointer comparison suffices for strings and objects.
81874 			 * Symbols compare equal if they have the same internal
81875 			 * representation; again heap pointer comparison suffices.
81876 			 */
81877 			return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
81878 		}
81879 		case DUK_TAG_BUFFER: {
81880 			/* In Duktape 2.x plain buffers mimic Uint8Array objects
81881 			 * so always compare by heap pointer.  In Duktape 1.x
81882 			 * strict comparison would compare heap pointers and
81883 			 * non-strict would compare contents.
81884 			 */
81885 			return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
81886 		}
81887 		case DUK_TAG_LIGHTFUNC: {
81888 			/* At least 'magic' has a significant impact on function
81889 			 * identity.
81890 			 */
81891 			duk_small_uint_t lf_flags_x;
81892 			duk_small_uint_t lf_flags_y;
81893 			duk_c_function func_x;
81894 			duk_c_function func_y;
81895 
81896 			DUK_TVAL_GET_LIGHTFUNC(tv_x, func_x, lf_flags_x);
81897 			DUK_TVAL_GET_LIGHTFUNC(tv_y, func_y, lf_flags_y);
81898 			return ((func_x == func_y) && (lf_flags_x == lf_flags_y)) ? 1 : 0;
81899 		}
81900 #if defined(DUK_USE_FASTINT)
81901 		case DUK_TAG_FASTINT:
81902 #endif
81903 		default: {
81904 			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_x));
81905 			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_y));
81906 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
81907 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_y));
81908 			DUK_UNREACHABLE();
81909 			DUK_WO_UNREACHABLE(return 0;);
81910 		}
81911 		}
81912 	}
81913 
81914 	if ((flags & (DUK_EQUALS_FLAG_STRICT | DUK_EQUALS_FLAG_SAMEVALUE)) != 0) {
81915 		return 0;
81916 	}
81917 
81918 	DUK_ASSERT(flags == 0);  /* non-strict equality from here on */
81919 
81920 	/*
81921 	 *  Types are different; various cases for non-strict comparison
81922 	 *
81923 	 *  Since comparison is symmetric, we use a "swap trick" to reduce
81924 	 *  code size.
81925 	 */
81926 
81927 	type_mask_x = duk_get_type_mask_tval(tv_x);
81928 	type_mask_y = duk_get_type_mask_tval(tv_y);
81929 
81930 	/* Undefined/null are considered equal (e.g. "null == undefined" -> true). */
81931 	if ((type_mask_x & (DUK_TYPE_MASK_UNDEFINED | DUK_TYPE_MASK_NULL)) &&
81932 	    (type_mask_y & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED))) {
81933 		return 1;
81934 	}
81935 
81936 	/* Number/string -> coerce string to number (e.g. "'1.5' == 1.5" -> true). */
81937 	if ((type_mask_x & DUK_TYPE_MASK_NUMBER) && (type_mask_y & DUK_TYPE_MASK_STRING)) {
81938 		if (!DUK_TVAL_STRING_IS_SYMBOL(tv_y)) {
81939 			duk_double_t d1, d2;
81940 			d1 = DUK_TVAL_GET_NUMBER(tv_x);
81941 			d2 = duk_to_number_tval(thr, tv_y);
81942 			return duk__js_equals_number(d1, d2);
81943 		}
81944 	}
81945 	if ((type_mask_x & DUK_TYPE_MASK_STRING) && (type_mask_y & DUK_TYPE_MASK_NUMBER)) {
81946 		if (!DUK_TVAL_STRING_IS_SYMBOL(tv_x)) {
81947 			duk_double_t d1, d2;
81948 			d1 = DUK_TVAL_GET_NUMBER(tv_y);
81949 			d2 = duk_to_number_tval(thr, tv_x);
81950 			return duk__js_equals_number(d1, d2);
81951 		}
81952 	}
81953 
81954 	/* Boolean/any -> coerce boolean to number and try again.  If boolean is
81955 	 * compared to a pointer, the final comparison after coercion now always
81956 	 * yields false (as pointer vs. number compares to false), but this is
81957 	 * not special cased.
81958 	 *
81959 	 * ToNumber(bool) is +1.0 or 0.0.  Tagged boolean value is always 0 or 1.
81960 	 */
81961 	if (type_mask_x & DUK_TYPE_MASK_BOOLEAN) {
81962 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_x) == 0 || DUK_TVAL_GET_BOOLEAN(tv_x) == 1);
81963 		duk_push_uint(thr, DUK_TVAL_GET_BOOLEAN(tv_x));
81964 		duk_push_tval(thr, tv_y);
81965 		goto recursive_call;
81966 	}
81967 	if (type_mask_y & DUK_TYPE_MASK_BOOLEAN) {
81968 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_y) == 0 || DUK_TVAL_GET_BOOLEAN(tv_y) == 1);
81969 		duk_push_tval(thr, tv_x);
81970 		duk_push_uint(thr, DUK_TVAL_GET_BOOLEAN(tv_y));
81971 		goto recursive_call;
81972 	}
81973 
81974 	/* String-number-symbol/object -> coerce object to primitive (apparently without hint), then try again. */
81975 	if ((type_mask_x & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER)) &&
81976 	    (type_mask_y & DUK_TYPE_MASK_OBJECT)) {
81977 		/* No symbol check needed because symbols and strings are accepted. */
81978 		duk_push_tval(thr, tv_x);
81979 		duk_push_tval(thr, tv_y);
81980 		duk_to_primitive(thr, -1, DUK_HINT_NONE);  /* apparently no hint? */
81981 		goto recursive_call;
81982 	}
81983 	if ((type_mask_x & DUK_TYPE_MASK_OBJECT) &&
81984 	    (type_mask_y & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER))) {
81985 		/* No symbol check needed because symbols and strings are accepted. */
81986 		duk_push_tval(thr, tv_x);
81987 		duk_push_tval(thr, tv_y);
81988 		duk_to_primitive(thr, -2, DUK_HINT_NONE);  /* apparently no hint? */
81989 		goto recursive_call;
81990 	}
81991 
81992 	/* Nothing worked -> not equal. */
81993 	return 0;
81994 
81995  recursive_call:
81996 	/* Shared code path to call the helper again with arguments on stack top. */
81997 	{
81998 		duk_bool_t rc;
81999 		rc = duk_js_equals_helper(thr,
82000 		                          DUK_GET_TVAL_NEGIDX(thr, -2),
82001 		                          DUK_GET_TVAL_NEGIDX(thr, -1),
82002 		                          0 /*flags:nonstrict*/);
82003 		duk_pop_2_unsafe(thr);
82004 		return rc;
82005 	}
82006 }
82007 
82008 /*
82009  *  Comparisons (x >= y, x > y, x <= y, x < y)
82010  *
82011  *  E5 Section 11.8.5: implement 'x < y' and then use negate and eval_left_first
82012  *  flags to get the rest.
82013  */
82014 
82015 /* XXX: this should probably just operate on the stack top, because it
82016  * needs to push stuff on the stack anyway...
82017  */
82018 
82019 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) {
82020 	duk_size_t prefix_len;
82021 	duk_small_int_t rc;
82022 
82023 	prefix_len = (len1 <= len2 ? len1 : len2);
82024 
82025 	/* duk_memcmp() is guaranteed to return zero (equal) for zero length
82026 	 * inputs.
82027 	 */
82028 	rc = duk_memcmp_unsafe((const void *) buf1,
82029 	                       (const void *) buf2,
82030 	                       (size_t) prefix_len);
82031 
82032 	if (rc < 0) {
82033 		return -1;
82034 	} else if (rc > 0) {
82035 		return 1;
82036 	}
82037 
82038 	/* prefix matches, lengths matter now */
82039 	if (len1 < len2) {
82040 		/* e.g. "x" < "xx" */
82041 		return -1;
82042 	} else if (len1 > len2) {
82043 		return 1;
82044 	}
82045 
82046 	return 0;
82047 }
82048 
82049 DUK_INTERNAL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2) {
82050 	/*
82051 	 *  String comparison (E5 Section 11.8.5, step 4), which
82052 	 *  needs to compare codepoint by codepoint.
82053 	 *
82054 	 *  However, UTF-8 allows us to use strcmp directly: the shared
82055 	 *  prefix will be encoded identically (UTF-8 has unique encoding)
82056 	 *  and the first differing character can be compared with a simple
82057 	 *  unsigned byte comparison (which strcmp does).
82058 	 *
82059 	 *  This will not work properly for non-xutf-8 strings, but this
82060 	 *  is not an issue for compliance.
82061 	 */
82062 
82063 	DUK_ASSERT(h1 != NULL);
82064 	DUK_ASSERT(h2 != NULL);
82065 
82066 	return duk_js_data_compare((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h1),
82067 	                           (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h2),
82068 	                           (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1),
82069 	                           (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2));
82070 }
82071 
82072 #if 0  /* unused */
82073 DUK_INTERNAL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2) {
82074 	/* Similar to String comparison. */
82075 
82076 	DUK_ASSERT(h1 != NULL);
82077 	DUK_ASSERT(h2 != NULL);
82078 	DUK_UNREF(heap);
82079 
82080 	return duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h1),
82081 	                           (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h2),
82082 	                           (duk_size_t) DUK_HBUFFER_GET_SIZE(h1),
82083 	                           (duk_size_t) DUK_HBUFFER_GET_SIZE(h2));
82084 }
82085 #endif
82086 
82087 #if defined(DUK_USE_FASTINT)
82088 DUK_LOCAL duk_bool_t duk__compare_fastint(duk_bool_t retval, duk_int64_t v1, duk_int64_t v2) {
82089 	DUK_ASSERT(retval == 0 || retval == 1);
82090 	if (v1 < v2) {
82091 		return retval ^ 1;
82092 	} else {
82093 		return retval;
82094 	}
82095 }
82096 #endif
82097 
82098 #if defined(DUK_USE_PARANOID_MATH)
82099 DUK_LOCAL duk_bool_t duk__compare_number(duk_bool_t retval, duk_double_t d1, duk_double_t d2) {
82100 	duk_small_int_t c1, s1, c2, s2;
82101 
82102 	DUK_ASSERT(retval == 0 || retval == 1);
82103 	c1 = (duk_small_int_t) DUK_FPCLASSIFY(d1);
82104 	s1 = (duk_small_int_t) DUK_SIGNBIT(d1);
82105 	c2 = (duk_small_int_t) DUK_FPCLASSIFY(d2);
82106 	s2 = (duk_small_int_t) DUK_SIGNBIT(d2);
82107 
82108 	if (c1 == DUK_FP_NAN || c2 == DUK_FP_NAN) {
82109 		return 0;  /* Always false, regardless of negation. */
82110 	}
82111 
82112 	if (c1 == DUK_FP_ZERO && c2 == DUK_FP_ZERO) {
82113 		/* For all combinations: +0 < +0, +0 < -0, -0 < +0, -0 < -0,
82114 		 * steps e, f, and g.
82115 		 */
82116 		return retval;  /* false */
82117 	}
82118 
82119 	if (d1 == d2) {
82120 		return retval;  /* false */
82121 	}
82122 
82123 	if (c1 == DUK_FP_INFINITE && s1 == 0) {
82124 		/* x == +Infinity */
82125 		return retval;  /* false */
82126 	}
82127 
82128 	if (c2 == DUK_FP_INFINITE && s2 == 0) {
82129 		/* y == +Infinity */
82130 		return retval ^ 1;  /* true */
82131 	}
82132 
82133 	if (c2 == DUK_FP_INFINITE && s2 != 0) {
82134 		/* y == -Infinity */
82135 		return retval;  /* false */
82136 	}
82137 
82138 	if (c1 == DUK_FP_INFINITE && s1 != 0) {
82139 		/* x == -Infinity */
82140 		return retval ^ 1;  /* true */
82141 	}
82142 
82143 	if (d1 < d2) {
82144 		return retval ^ 1;  /* true */
82145 	}
82146 
82147 	return retval;  /* false */
82148 }
82149 #else  /* DUK_USE_PARANOID_MATH */
82150 DUK_LOCAL duk_bool_t duk__compare_number(duk_bool_t retval, duk_double_t d1, duk_double_t d2) {
82151 	/* This comparison tree relies doesn't match the exact steps in
82152 	 * E5 Section 11.8.5 but should produce the same results.  The
82153 	 * steps rely on exact IEEE semantics for NaNs, etc.
82154 	 */
82155 
82156 	DUK_ASSERT(retval == 0 || retval == 1);
82157 	if (d1 < d2) {
82158 		/* In no case should both (d1 < d2) and (d2 < d1) be true.
82159 		 * It's possible that neither is true though, and that's
82160 		 * handled below.
82161 		 */
82162 		DUK_ASSERT(!(d2 < d1));
82163 
82164 		/* - d1 < d2, both d1/d2 are normals (not Infinity, not NaN)
82165 		 * - d2 is +Infinity, d1 != +Infinity and NaN
82166 		 * - d1 is -Infinity, d2 != -Infinity and NaN
82167 		 */
82168 		return retval ^ 1;
82169 	} else {
82170 		if (d2 < d1) {
82171 			/* - !(d1 < d2), both d1/d2 are normals (not Infinity, not NaN)
82172 			 * - d1 is +Infinity, d2 != +Infinity and NaN
82173 			 * - d2 is -Infinity, d1 != -Infinity and NaN
82174 			 */
82175 			return retval;
82176 		} else {
82177 			/* - d1 and/or d2 is NaN
82178 			 * - d1 and d2 are both +/- 0
82179 			 * - d1 == d2 (including infinities)
82180 			 */
82181 			if (duk_double_is_nan(d1) || duk_double_is_nan(d2)) {
82182 				/* Note: undefined from Section 11.8.5 always
82183 				 * results in false return (see e.g. Section
82184 				 * 11.8.3) - hence special treatment here.
82185 				 */
82186 				return 0;  /* zero regardless of negation */
82187 			} else {
82188 				return retval;
82189 			}
82190 		}
82191 	}
82192 }
82193 #endif  /* DUK_USE_PARANOID_MATH */
82194 
82195 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) {
82196 	duk_double_t d1, d2;
82197 	duk_small_int_t rc;
82198 	duk_bool_t retval;
82199 
82200 	DUK_ASSERT(DUK_COMPARE_FLAG_NEGATE == 1);  /* Rely on this flag being lowest. */
82201 	retval = flags & DUK_COMPARE_FLAG_NEGATE;
82202 	DUK_ASSERT(retval == 0 || retval == 1);
82203 
82204 	/* Fast path for fastints */
82205 #if defined(DUK_USE_FASTINT)
82206 	if (DUK_LIKELY(DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y))) {
82207 		return duk__compare_fastint(retval,
82208 		                            DUK_TVAL_GET_FASTINT(tv_x),
82209 		                            DUK_TVAL_GET_FASTINT(tv_y));
82210 	}
82211 #endif  /* DUK_USE_FASTINT */
82212 
82213 	/* Fast path for numbers (one of which may be a fastint) */
82214 #if !defined(DUK_USE_PREFER_SIZE)
82215 	if (DUK_LIKELY(DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y))) {
82216 		return duk__compare_number(retval,
82217 		                           DUK_TVAL_GET_NUMBER(tv_x),
82218 		                           DUK_TVAL_GET_NUMBER(tv_y));
82219 	}
82220 #endif
82221 
82222 	/* Slow path */
82223 
82224 	duk_push_tval(thr, tv_x);
82225 	duk_push_tval(thr, tv_y);
82226 
82227 	if (flags & DUK_COMPARE_FLAG_EVAL_LEFT_FIRST) {
82228 		duk_to_primitive(thr, -2, DUK_HINT_NUMBER);
82229 		duk_to_primitive(thr, -1, DUK_HINT_NUMBER);
82230 	} else {
82231 		duk_to_primitive(thr, -1, DUK_HINT_NUMBER);
82232 		duk_to_primitive(thr, -2, DUK_HINT_NUMBER);
82233 	}
82234 
82235 	/* Note: reuse variables */
82236 	tv_x = DUK_GET_TVAL_NEGIDX(thr, -2);
82237 	tv_y = DUK_GET_TVAL_NEGIDX(thr, -1);
82238 
82239 	if (DUK_TVAL_IS_STRING(tv_x) && DUK_TVAL_IS_STRING(tv_y)) {
82240 		duk_hstring *h1 = DUK_TVAL_GET_STRING(tv_x);
82241 		duk_hstring *h2 = DUK_TVAL_GET_STRING(tv_y);
82242 		DUK_ASSERT(h1 != NULL);
82243 		DUK_ASSERT(h2 != NULL);
82244 
82245 		if (DUK_LIKELY(!DUK_HSTRING_HAS_SYMBOL(h1) && !DUK_HSTRING_HAS_SYMBOL(h2))) {
82246 			rc = duk_js_string_compare(h1, h2);
82247 			duk_pop_2_unsafe(thr);
82248 			if (rc < 0) {
82249 				return retval ^ 1;
82250 			} else {
82251 				return retval;
82252 			}
82253 		}
82254 
82255 		/* One or both are Symbols: fall through to handle in the
82256 		 * generic path.  Concretely, ToNumber() will fail.
82257 		 */
82258 	}
82259 
82260 	/* Ordering should not matter (E5 Section 11.8.5, step 3.a). */
82261 #if 0
82262 	if (flags & DUK_COMPARE_FLAG_EVAL_LEFT_FIRST) {
82263 		d1 = duk_to_number_m2(thr);
82264 		d2 = duk_to_number_m1(thr);
82265 	} else {
82266 		d2 = duk_to_number_m1(thr);
82267 		d1 = duk_to_number_m2(thr);
82268 	}
82269 #endif
82270 	d1 = duk_to_number_m2(thr);
82271 	d2 = duk_to_number_m1(thr);
82272 
82273 	/* We want to duk_pop_2_unsafe(thr); because the values are numbers
82274 	 * no decref check is needed.
82275 	 */
82276 #if defined(DUK_USE_PREFER_SIZE)
82277 	duk_pop_2_nodecref_unsafe(thr);
82278 #else
82279 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk_get_tval(thr, -2)));
82280 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk_get_tval(thr, -1)));
82281 	DUK_ASSERT(duk_get_top(thr) >= 2);
82282 	thr->valstack_top -= 2;
82283 	tv_x = thr->valstack_top;
82284 	tv_y = tv_x + 1;
82285 	DUK_TVAL_SET_UNDEFINED(tv_x);  /* Value stack policy */
82286 	DUK_TVAL_SET_UNDEFINED(tv_y);
82287 #endif
82288 
82289 	return duk__compare_number(retval, d1, d2);
82290 }
82291 
82292 /*
82293  *  instanceof
82294  */
82295 
82296 /*
82297  *  ES2015 Section 7.3.19 describes the OrdinaryHasInstance() algorithm
82298  *  which covers both bound and non-bound functions; in effect the algorithm
82299  *  includes E5 Sections 11.8.6, 15.3.5.3, and 15.3.4.5.3.
82300  *
82301  *  ES2015 Section 12.9.4 describes the instanceof operator which first
82302  *  checks @@hasInstance well-known symbol and falls back to
82303  *  OrdinaryHasInstance().
82304  *
82305  *  Limited Proxy support: don't support 'getPrototypeOf' trap but
82306  *  continue lookup in Proxy target if the value is a Proxy.
82307  */
82308 
82309 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) {
82310 	duk_hobject *func;
82311 	duk_hobject *val;
82312 	duk_hobject *proto;
82313 	duk_tval *tv;
82314 	duk_bool_t skip_first;
82315 	duk_uint_t sanity;
82316 
82317 	/*
82318 	 *  Get the values onto the stack first.  It would be possible to cover
82319 	 *  some normal cases without resorting to the value stack.
82320 	 *
82321 	 *  The right hand side could be a light function (as they generally
82322 	 *  behave like objects).  Light functions never have a 'prototype'
82323 	 *  property so E5.1 Section 15.3.5.3 step 3 always throws a TypeError.
82324 	 *  Using duk_require_hobject() is thus correct (except for error msg).
82325 	 */
82326 
82327 	duk_push_tval(thr, tv_x);
82328 	duk_push_tval(thr, tv_y);
82329 	func = duk_require_hobject(thr, -1);
82330 	DUK_ASSERT(func != NULL);
82331 
82332 #if defined(DUK_USE_SYMBOL_BUILTIN)
82333 	/*
82334 	 *  @@hasInstance check, ES2015 Section 12.9.4, Steps 2-4.
82335 	 */
82336 	if (!skip_sym_check) {
82337 		if (duk_get_method_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)) {
82338 			/* [ ... lhs rhs func ] */
82339 			duk_insert(thr, -3);    /* -> [ ... func lhs rhs ] */
82340 			duk_swap_top(thr, -2);  /* -> [ ... func rhs(this) lhs ] */
82341 			duk_call_method(thr, 1);
82342 			return duk_to_boolean_top_pop(thr);
82343 		}
82344 	}
82345 #else
82346 	DUK_UNREF(skip_sym_check);
82347 #endif
82348 
82349 	/*
82350 	 *  For bound objects, [[HasInstance]] just calls the target function
82351 	 *  [[HasInstance]].  If that is again a bound object, repeat until
82352 	 *  we find a non-bound Function object.
82353 	 *
82354 	 *  The bound function chain is now "collapsed" so there can be only
82355 	 *  one bound function in the chain.
82356 	 */
82357 
82358 	if (!DUK_HOBJECT_IS_CALLABLE(func)) {
82359 		/*
82360 		 *  Note: of native ECMAScript objects, only Function instances
82361 		 *  have a [[HasInstance]] internal property.  Custom objects might
82362 		 *  also have it, but not in current implementation.
82363 		 *
82364 		 *  XXX: add a separate flag, DUK_HOBJECT_FLAG_ALLOW_INSTANCEOF?
82365 		 */
82366 		goto error_invalid_rval;
82367 	}
82368 
82369 	if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
82370 		duk_push_tval(thr, &((duk_hboundfunc *) (void *) func)->target);
82371 		duk_replace(thr, -2);
82372 		func = duk_require_hobject(thr, -1);  /* lightfunc throws */
82373 
82374 		/* Rely on Function.prototype.bind() never creating bound
82375 		 * functions whose target is not proper.
82376 		 */
82377 		DUK_ASSERT(func != NULL);
82378 		DUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(func));
82379 	}
82380 
82381 	/*
82382 	 *  'func' is now a non-bound object which supports [[HasInstance]]
82383 	 *  (which here just means DUK_HOBJECT_FLAG_CALLABLE).  Move on
82384 	 *  to execute E5 Section 15.3.5.3.
82385 	 */
82386 
82387 	DUK_ASSERT(func != NULL);
82388 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
82389 	DUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(func));
82390 
82391 	/* [ ... lval rval(func) ] */
82392 
82393 	/* For lightfuncs, buffers, and pointers start the comparison directly
82394 	 * from the virtual prototype object.
82395 	 */
82396 	skip_first = 0;
82397 	tv = DUK_GET_TVAL_NEGIDX(thr, -2);
82398 	switch (DUK_TVAL_GET_TAG(tv)) {
82399 	case DUK_TAG_LIGHTFUNC:
82400 		val = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
82401 		DUK_ASSERT(val != NULL);
82402 		break;
82403 	case DUK_TAG_BUFFER:
82404 		val = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
82405 		DUK_ASSERT(val != NULL);
82406 		break;
82407 	case DUK_TAG_POINTER:
82408 		val = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
82409 		DUK_ASSERT(val != NULL);
82410 		break;
82411 	case DUK_TAG_OBJECT:
82412 		skip_first = 1;  /* Ignore object itself on first round. */
82413 		val = DUK_TVAL_GET_OBJECT(tv);
82414 		DUK_ASSERT(val != NULL);
82415 		break;
82416 	default:
82417 		goto pop2_and_false;
82418 	}
82419 	DUK_ASSERT(val != NULL);  /* Loop doesn't actually rely on this. */
82420 
82421 	/* Look up .prototype of rval.  Leave it on the value stack in case it
82422 	 * has been virtualized (e.g. getter, Proxy trap).
82423 	 */
82424 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_PROTOTYPE);  /* -> [ ... lval rval rval.prototype ] */
82425 #if defined(DUK_USE_VERBOSE_ERRORS)
82426 	proto = duk_get_hobject(thr, -1);
82427 	if (proto == NULL) {
82428 		goto error_invalid_rval_noproto;
82429 	}
82430 #else
82431 	proto = duk_require_hobject(thr, -1);
82432 #endif
82433 
82434 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
82435 	do {
82436 		/*
82437 		 *  Note: prototype chain is followed BEFORE first comparison.  This
82438 		 *  means that the instanceof lval is never itself compared to the
82439 		 *  rval.prototype property.  This is apparently intentional, see E5
82440 		 *  Section 15.3.5.3, step 4.a.
82441 		 *
82442 		 *  Also note:
82443 		 *
82444 		 *      js> (function() {}) instanceof Function
82445 		 *      true
82446 		 *      js> Function instanceof Function
82447 		 *      true
82448 		 *
82449 		 *  For the latter, h_proto will be Function.prototype, which is the
82450 		 *  built-in Function prototype.  Because Function.[[Prototype]] is
82451 		 *  also the built-in Function prototype, the result is true.
82452 		 */
82453 
82454 		if (!val) {
82455 			goto pop3_and_false;
82456 		}
82457 
82458 		DUK_ASSERT(val != NULL);
82459 #if defined(DUK_USE_ES6_PROXY)
82460 		val = duk_hobject_resolve_proxy_target(val);
82461 #endif
82462 
82463 		if (skip_first) {
82464 			skip_first = 0;
82465 		} else if (val == proto) {
82466 			goto pop3_and_true;
82467 		}
82468 
82469 		DUK_ASSERT(val != NULL);
82470 		val = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, val);
82471 	} while (--sanity > 0);
82472 
82473 	DUK_ASSERT(sanity == 0);
82474 	DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
82475 	DUK_WO_NORETURN(return 0;);
82476 
82477  pop2_and_false:
82478 	duk_pop_2_unsafe(thr);
82479 	return 0;
82480 
82481  pop3_and_false:
82482 	duk_pop_3_unsafe(thr);
82483 	return 0;
82484 
82485  pop3_and_true:
82486 	duk_pop_3_unsafe(thr);
82487 	return 1;
82488 
82489  error_invalid_rval:
82490 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_INSTANCEOF_RVAL);
82491 	DUK_WO_NORETURN(return 0;);
82492 
82493 #if defined(DUK_USE_VERBOSE_ERRORS)
82494  error_invalid_rval_noproto:
82495 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO);
82496 	DUK_WO_NORETURN(return 0;);
82497 #endif
82498 }
82499 
82500 #if defined(DUK_USE_SYMBOL_BUILTIN)
82501 DUK_INTERNAL duk_bool_t duk_js_instanceof_ordinary(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
82502 	return duk__js_instanceof_helper(thr, tv_x, tv_y, 1 /*skip_sym_check*/);
82503 }
82504 #endif
82505 
82506 DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
82507 	return duk__js_instanceof_helper(thr, tv_x, tv_y, 0 /*skip_sym_check*/);
82508 }
82509 
82510 /*
82511  *  in
82512  */
82513 
82514 /*
82515  *  E5 Sections 11.8.7, 8.12.6.
82516  *
82517  *  Basically just a property existence check using [[HasProperty]].
82518  */
82519 
82520 DUK_INTERNAL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
82521 	duk_bool_t retval;
82522 
82523 	/*
82524 	 *  Get the values onto the stack first.  It would be possible to cover
82525 	 *  some normal cases without resorting to the value stack (e.g. if
82526 	 *  lval is already a string).
82527 	 */
82528 
82529 	/* XXX: The ES5/5.1/6 specifications require that the key in 'key in obj'
82530 	 * must be string coerced before the internal HasProperty() algorithm is
82531 	 * invoked.  A fast path skipping coercion could be safely implemented for
82532 	 * numbers (as number-to-string coercion has no side effects).  For ES2015
82533 	 * proxy behavior, the trap 'key' argument must be in a string coerced
82534 	 * form (which is a shame).
82535 	 */
82536 
82537 	/* TypeError if rval is not an object or object like (e.g. lightfunc
82538 	 * or plain buffer).
82539 	 */
82540 	duk_push_tval(thr, tv_x);
82541 	duk_push_tval(thr, tv_y);
82542 	duk_require_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT | DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
82543 
82544 	(void) duk_to_property_key_hstring(thr, -2);
82545 
82546 	retval = duk_hobject_hasprop(thr,
82547 	                             DUK_GET_TVAL_NEGIDX(thr, -1),
82548 	                             DUK_GET_TVAL_NEGIDX(thr, -2));
82549 
82550 	duk_pop_2_unsafe(thr);
82551 	return retval;
82552 }
82553 
82554 /*
82555  *  typeof
82556  *
82557  *  E5 Section 11.4.3.
82558  *
82559  *  Very straightforward.  The only question is what to return for our
82560  *  non-standard tag / object types.
82561  *
82562  *  There is an unfortunate string constant define naming problem with
82563  *  typeof return values for e.g. "Object" and "object"; careful with
82564  *  the built-in string defines.  The LC_XXX defines are used for the
82565  *  lowercase variants now.
82566  */
82567 
82568 DUK_INTERNAL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x) {
82569 	duk_small_uint_t stridx = 0;
82570 
82571 	switch (DUK_TVAL_GET_TAG(tv_x)) {
82572 	case DUK_TAG_UNDEFINED: {
82573 		stridx = DUK_STRIDX_LC_UNDEFINED;
82574 		break;
82575 	}
82576 	case DUK_TAG_NULL: {
82577 		/* Note: not a typo, "object" is returned for a null value. */
82578 		stridx = DUK_STRIDX_LC_OBJECT;
82579 		break;
82580 	}
82581 	case DUK_TAG_BOOLEAN: {
82582 		stridx = DUK_STRIDX_LC_BOOLEAN;
82583 		break;
82584 	}
82585 	case DUK_TAG_POINTER: {
82586 		/* Implementation specific. */
82587 		stridx = DUK_STRIDX_LC_POINTER;
82588 		break;
82589 	}
82590 	case DUK_TAG_STRING: {
82591 		duk_hstring *str;
82592 
82593 		/* All internal keys are identified as Symbols. */
82594 		str = DUK_TVAL_GET_STRING(tv_x);
82595 		DUK_ASSERT(str != NULL);
82596 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(str))) {
82597 			stridx = DUK_STRIDX_LC_SYMBOL;
82598 		} else {
82599 			stridx = DUK_STRIDX_LC_STRING;
82600 		}
82601 		break;
82602 	}
82603 	case DUK_TAG_OBJECT: {
82604 		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_x);
82605 		DUK_ASSERT(obj != NULL);
82606 		if (DUK_HOBJECT_IS_CALLABLE(obj)) {
82607 			stridx = DUK_STRIDX_LC_FUNCTION;
82608 		} else {
82609 			stridx = DUK_STRIDX_LC_OBJECT;
82610 		}
82611 		break;
82612 	}
82613 	case DUK_TAG_BUFFER: {
82614 		/* Implementation specific.  In Duktape 1.x this would be
82615 		 * 'buffer', in Duktape 2.x changed to 'object' because plain
82616 		 * buffers now mimic Uint8Array objects.
82617 		 */
82618 		stridx = DUK_STRIDX_LC_OBJECT;
82619 		break;
82620 	}
82621 	case DUK_TAG_LIGHTFUNC: {
82622 		stridx = DUK_STRIDX_LC_FUNCTION;
82623 		break;
82624 	}
82625 #if defined(DUK_USE_FASTINT)
82626 	case DUK_TAG_FASTINT:
82627 #endif
82628 	default: {
82629 		/* number */
82630 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_x));
82631 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
82632 		stridx = DUK_STRIDX_LC_NUMBER;
82633 		break;
82634 	}
82635 	}
82636 
82637 	DUK_ASSERT_STRIDX_VALID(stridx);
82638 	return stridx;
82639 }
82640 
82641 /*
82642  *  IsArray()
82643  */
82644 
82645 DUK_INTERNAL duk_bool_t duk_js_isarray_hobject(duk_hobject *h) {
82646 	DUK_ASSERT(h != NULL);
82647 #if defined(DUK_USE_ES6_PROXY)
82648 	h = duk_hobject_resolve_proxy_target(h);
82649 #endif
82650 	return (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY ? 1 : 0);
82651 }
82652 
82653 DUK_INTERNAL duk_bool_t duk_js_isarray(duk_tval *tv) {
82654 	DUK_ASSERT(tv != NULL);
82655 	if (DUK_TVAL_IS_OBJECT(tv)) {
82656 		return duk_js_isarray_hobject(DUK_TVAL_GET_OBJECT(tv));
82657 	}
82658 	return 0;
82659 }
82660 
82661 /*
82662  *  Array index and length
82663  *
82664  *  Array index: E5 Section 15.4
82665  *  Array length: E5 Section 15.4.5.1 steps 3.c - 3.d (array length write)
82666  */
82667 
82668 /* Compure array index from string context, or return a "not array index"
82669  * indicator.
82670  */
82671 DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_string(const duk_uint8_t *str, duk_uint32_t blen) {
82672 	duk_uarridx_t res;
82673 
82674 	/* Only strings with byte length 1-10 can be 32-bit array indices.
82675 	 * Leading zeroes (except '0' alone), plus/minus signs are not allowed.
82676 	 * We could do a lot of prechecks here, but since most strings won't
82677 	 * start with any digits, it's simpler to just parse the number and
82678 	 * fail quickly.
82679 	 */
82680 
82681 	res = 0;
82682 	if (blen == 0) {
82683 		goto parse_fail;
82684 	}
82685 	do {
82686 		duk_uarridx_t dig;
82687 		dig = (duk_uarridx_t) (*str++) - DUK_ASC_0;
82688 
82689 		if (dig <= 9U) {
82690 			/* Careful overflow handling.  When multiplying by 10:
82691 			 * - 0x19999998 x 10 = 0xfffffff0: no overflow, and adding
82692 			 *   0...9 is safe.
82693 			 * - 0x19999999 x 10 = 0xfffffffa: no overflow, adding
82694 			 *   0...5 is safe, 6...9 overflows.
82695 			 * - 0x1999999a x 10 = 0x100000004: always overflow.
82696 			 */
82697 			if (DUK_UNLIKELY(res >= 0x19999999UL)) {
82698 				if (res >= 0x1999999aUL) {
82699 					/* Always overflow. */
82700 					goto parse_fail;
82701 				}
82702 				DUK_ASSERT(res == 0x19999999UL);
82703 				if (dig >= 6U) {
82704 					goto parse_fail;
82705 				}
82706 				res = 0xfffffffaUL + dig;
82707 				DUK_ASSERT(res >= 0xfffffffaUL);
82708 				DUK_ASSERT_DISABLE(res <= 0xffffffffUL);  /* range */
82709 			} else {
82710 				res = res * 10U + dig;
82711 				if (DUK_UNLIKELY(res == 0)) {
82712 					/* If 'res' is 0, previous 'res' must
82713 					 * have been 0 and we scanned in a zero.
82714 					 * This is only allowed if blen == 1,
82715 					 * i.e. the exact string '0'.
82716 					 */
82717 					if (blen == (duk_uint32_t) 1) {
82718 						return 0;
82719 					}
82720 					goto parse_fail;
82721 				}
82722 			}
82723 		} else {
82724 			/* Because 'dig' is unsigned, catches both values
82725 			 * above '9' and below '0'.
82726 			 */
82727 			goto parse_fail;
82728 		}
82729 	} while (--blen > 0);
82730 
82731 	return res;
82732 
82733  parse_fail:
82734 	return DUK_HSTRING_NO_ARRAY_INDEX;
82735 }
82736 
82737 #if !defined(DUK_USE_HSTRING_ARRIDX)
82738 /* Get array index for a string which is known to be an array index.  This helper
82739  * is needed when duk_hstring doesn't concretely store the array index, but strings
82740  * are flagged as array indices at intern time.
82741  */
82742 DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_hstring_fast_known(duk_hstring *h) {
82743 	const duk_uint8_t *p;
82744 	duk_uarridx_t res;
82745 	duk_uint8_t t;
82746 
82747 	DUK_ASSERT(h != NULL);
82748 	DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(h));
82749 
82750 	p = DUK_HSTRING_GET_DATA(h);
82751 	res = 0;
82752 	for (;;) {
82753 		t = *p++;
82754 		if (DUK_UNLIKELY(t == 0)) {
82755 			/* Scanning to NUL is always safe for interned strings. */
82756 			break;
82757 		}
82758 		DUK_ASSERT(t >= (duk_uint8_t) DUK_ASC_0 && t <= (duk_uint8_t) DUK_ASC_9);
82759 		res = res * 10U + (duk_uarridx_t) t - (duk_uarridx_t) DUK_ASC_0;
82760 	}
82761 	return res;
82762 }
82763 
82764 DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h) {
82765 	DUK_ASSERT(h != NULL);
82766 	if (!DUK_HSTRING_HAS_ARRIDX(h)) {
82767 		return DUK_HSTRING_NO_ARRAY_INDEX;
82768 	}
82769 	return duk_js_to_arrayindex_hstring_fast_known(h);
82770 }
82771 #endif  /* DUK_USE_HSTRING_ARRIDX */
82772 #line 1 "duk_js_var.c"
82773 /*
82774  *  Identifier access and function closure handling.
82775  *
82776  *  Provides the primitives for slow path identifier accesses: GETVAR,
82777  *  PUTVAR, DELVAR, etc.  The fast path, direct register accesses, should
82778  *  be used for most identifier accesses.  Consequently, these slow path
82779  *  primitives should be optimized for maximum compactness.
82780  *
82781  *  ECMAScript environment records (declarative and object) are represented
82782  *  as internal objects with control keys.  Environment records have a
82783  *  parent record ("outer environment reference") which is represented by
82784  *  the implicit prototype for technical reasons (in other words, it is a
82785  *  convenient field).  The prototype chain is not followed in the ordinary
82786  *  sense for variable lookups.
82787  *
82788  *  See identifier-handling.rst for more details on the identifier algorithms
82789  *  and the internal representation.  See function-objects.rst for details on
82790  *  what function templates and instances are expected to look like.
82791  *
82792  *  Care must be taken to avoid duk_tval pointer invalidation caused by
82793  *  e.g. value stack or object resizing.
82794  *
82795  *  TODO: properties for function instances could be initialized much more
82796  *  efficiently by creating a property allocation for a certain size and
82797  *  filling in keys and values directly (and INCREFing both with "bulk incref"
82798  *  primitives.
82799  *
82800  *  XXX: duk_hobject_getprop() and duk_hobject_putprop() calls are a bit
82801  *  awkward (especially because they follow the prototype chain); rework
82802  *  if "raw" own property helpers are added.
82803  */
82804 
82805 /* #include duk_internal.h -> already included */
82806 
82807 /*
82808  *  Local result type for duk__get_identifier_reference() lookup.
82809  */
82810 
82811 typedef struct {
82812 	duk_hobject *env;
82813 	duk_hobject *holder;      /* for object-bound identifiers */
82814 	duk_tval *value;          /* for register-bound and declarative env identifiers */
82815 	duk_uint_t attrs;         /* property attributes for identifier (relevant if value != NULL) */
82816 	duk_bool_t has_this;      /* for object-bound identifiers: provide 'this' binding */
82817 } duk__id_lookup_result;
82818 
82819 /*
82820  *  Create a new function object based on a "template function" which contains
82821  *  compiled bytecode, constants, etc, but lacks a lexical environment.
82822  *
82823  *  ECMAScript requires that each created closure is a separate object, with
82824  *  its own set of editable properties.  However, structured property values
82825  *  (such as the formal arguments list and the variable map) are shared.
82826  *  Also the bytecode, constants, and inner functions are shared.
82827  *
82828  *  See E5 Section 13.2 for detailed requirements on the function objects;
82829  *  there are no similar requirements for function "templates" which are an
82830  *  implementation dependent internal feature.  Also see function-objects.rst
82831  *  for a discussion on the function instance properties provided by this
82832  *  implementation.
82833  *
82834  *  Notes:
82835  *
82836  *   * Order of internal properties should match frequency of use, since the
82837  *     properties will be linearly scanned on lookup (functions usually don't
82838  *     have enough properties to warrant a hash part).
82839  *
82840  *   * The created closure is independent of its template; they do share the
82841  *     same 'data' buffer object, but the template object itself can be freed
82842  *     even if the closure object remains reachable.
82843  */
82844 
82845 DUK_LOCAL void duk__inc_data_inner_refcounts(duk_hthread *thr, duk_hcompfunc *f) {
82846 	duk_tval *tv, *tv_end;
82847 	duk_hobject **funcs, **funcs_end;
82848 
82849 	DUK_UNREF(thr);
82850 
82851 	/* If function creation fails due to out-of-memory, the data buffer
82852 	 * pointer may be NULL in some cases.  That's actually possible for
82853 	 * GC code, but shouldn't be possible here because the incomplete
82854 	 * function will be unwound from the value stack and never instantiated.
82855 	 */
82856 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, f) != NULL);
82857 
82858 	tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, f);
82859 	tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, f);
82860 	while (tv < tv_end) {
82861 		DUK_TVAL_INCREF(thr, tv);
82862 		tv++;
82863 	}
82864 
82865 	funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, f);
82866 	funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, f);
82867 	while (funcs < funcs_end) {
82868 		DUK_HEAPHDR_INCREF(thr, (duk_heaphdr *) *funcs);
82869 		funcs++;
82870 	}
82871 }
82872 
82873 /* Push a new closure on the stack.
82874  *
82875  * Note: if fun_temp has NEWENV, i.e. a new lexical and variable declaration
82876  * is created when the function is called, only outer_lex_env matters
82877  * (outer_var_env is ignored and may or may not be same as outer_lex_env).
82878  */
82879 
82880 DUK_LOCAL const duk_uint16_t duk__closure_copy_proplist[] = {
82881 	/* order: most frequent to least frequent */
82882 	DUK_STRIDX_INT_VARMAP,
82883 	DUK_STRIDX_INT_FORMALS,
82884 #if defined(DUK_USE_PC2LINE)
82885 	DUK_STRIDX_INT_PC2LINE,
82886 #endif
82887 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
82888 	DUK_STRIDX_FILE_NAME,
82889 #endif
82890 #if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
82891 	DUK_STRIDX_INT_SOURCE
82892 #endif
82893 };
82894 
82895 DUK_INTERNAL
82896 void duk_js_push_closure(duk_hthread *thr,
82897                          duk_hcompfunc *fun_temp,
82898                          duk_hobject *outer_var_env,
82899                          duk_hobject *outer_lex_env,
82900                          duk_bool_t add_auto_proto) {
82901 	duk_hcompfunc *fun_clos;
82902 	duk_harray *formals;
82903 	duk_small_uint_t i;
82904 	duk_uint_t len_value;
82905 
82906 	DUK_ASSERT(fun_temp != NULL);
82907 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_temp) != NULL);
82908 	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_temp) != NULL);
82909 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_temp) != NULL);
82910 	DUK_ASSERT(outer_var_env != NULL);
82911 	DUK_ASSERT(outer_lex_env != NULL);
82912 	DUK_UNREF(len_value);
82913 
82914 	DUK_STATS_INC(thr->heap, stats_envrec_pushclosure);
82915 
82916 	fun_clos = duk_push_hcompfunc(thr);
82917 	DUK_ASSERT(fun_clos != NULL);
82918 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) fun_clos) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
82919 
82920 	duk_push_hobject(thr, &fun_temp->obj);  /* -> [ ... closure template ] */
82921 
82922 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun_clos));
82923 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos) == NULL);
82924 	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_clos) == NULL);
82925 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_clos) == NULL);
82926 
82927 	DUK_HCOMPFUNC_SET_DATA(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_temp));
82928 	DUK_HCOMPFUNC_SET_FUNCS(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_temp));
82929 	DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_temp));
82930 
82931 	/* Note: all references inside 'data' need to get their refcounts
82932 	 * upped too.  This is the case because refcounts are decreased
82933 	 * through every function referencing 'data' independently.
82934 	 */
82935 
82936 	DUK_HBUFFER_INCREF(thr, DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos));
82937 	duk__inc_data_inner_refcounts(thr, fun_temp);
82938 
82939 	fun_clos->nregs = fun_temp->nregs;
82940 	fun_clos->nargs = fun_temp->nargs;
82941 #if defined(DUK_USE_DEBUGGER_SUPPORT)
82942 	fun_clos->start_line = fun_temp->start_line;
82943 	fun_clos->end_line = fun_temp->end_line;
82944 #endif
82945 
82946 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos) != NULL);
82947 	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_clos) != NULL);
82948 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_clos) != NULL);
82949 
82950 	/* XXX: Could also copy from template, but there's no way to have any
82951 	 * other value here now (used code has no access to the template).
82952 	 * Prototype is set by duk_push_hcompfunc().
82953 	 */
82954 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, &fun_clos->obj) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
82955 #if 0
82956 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &fun_clos->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
82957 #endif
82958 
82959 	/* Copy duk_hobject flags as is from the template using a mask.
82960 	 * Leave out duk_heaphdr owned flags just in case (e.g. if there's
82961 	 * some GC flag or similar).  Some flags can then be adjusted
82962 	 * separately if necessary.
82963 	 */
82964 
82965 	/* DUK_HEAPHDR_SET_FLAGS() masks changes to non-duk_heaphdr flags only. */
82966 	DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) fun_clos, DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_temp));
82967 	DUK_DD(DUK_DDPRINT("fun_temp heaphdr flags: 0x%08lx, fun_clos heaphdr flags: 0x%08lx",
82968 	                   (unsigned long) DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_temp),
82969 	                   (unsigned long) DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_clos)));
82970 
82971 	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));
82972 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&fun_clos->obj));
82973 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(&fun_clos->obj));
82974 	DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(&fun_clos->obj));
82975 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(&fun_clos->obj));
82976 	/* DUK_HOBJECT_FLAG_ARRAY_PART: don't care */
82977 	/* DUK_HOBJECT_FLAG_NEWENV: handled below */
82978 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&fun_clos->obj));
82979 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&fun_clos->obj));
82980 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&fun_clos->obj));
82981 
82982 	if (!DUK_HOBJECT_HAS_CONSTRUCTABLE(&fun_clos->obj)) {
82983 		/* If the template is not constructable don't add an automatic
82984 		 * .prototype property.  This is the case for e.g. ES2015 object
82985 		 * literal getters/setters and method definitions.
82986 		 */
82987 		add_auto_proto = 0;
82988 	}
82989 
82990 	/*
82991 	 *  Setup environment record properties based on the template and
82992 	 *  its flags.
82993 	 *
82994 	 *  If DUK_HOBJECT_HAS_NEWENV(fun_temp) is true, the environment
82995 	 *  records represent identifiers "outside" the function; the
82996 	 *  "inner" environment records are created on demand.  Otherwise,
82997 	 *  the environment records are those that will be directly used
82998 	 *  (e.g. for declarations).
82999 	 *
83000 	 *  _Lexenv is always set; _Varenv defaults to _Lexenv if missing,
83001 	 *  so _Varenv is only set if _Lexenv != _Varenv.
83002 	 *
83003 	 *  This is relatively complex, see doc/identifier-handling.rst.
83004 	 */
83005 
83006 	if (DUK_HOBJECT_HAS_NEWENV(&fun_clos->obj)) {
83007 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
83008 		if (DUK_HOBJECT_HAS_NAMEBINDING(&fun_clos->obj)) {
83009 			duk_hobject *proto;
83010 			duk_hdecenv *new_env;
83011 
83012 			/*
83013 			 *  Named function expression, name needs to be bound
83014 			 *  in an intermediate environment record.  The "outer"
83015 			 *  lexical/variable environment will thus be:
83016 			 *
83017 			 *  a) { funcname: <func>, __prototype: outer_lex_env }
83018 			 *  b) { funcname: <func>, __prototype:  <globalenv> }  (if outer_lex_env missing)
83019 			 */
83020 
83021 			if (outer_lex_env) {
83022 				proto = outer_lex_env;
83023 			} else {
83024 				proto = thr->builtins[DUK_BIDX_GLOBAL_ENV];
83025 			}
83026 
83027 			/* -> [ ... closure template env ] */
83028 			new_env = duk_hdecenv_alloc(thr,
83029 			                            DUK_HOBJECT_FLAG_EXTENSIBLE |
83030 			                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
83031 			DUK_ASSERT(new_env != NULL);
83032 			duk_push_hobject(thr, (duk_hobject *) new_env);
83033 
83034 			DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
83035 			DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, proto);
83036 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, proto);
83037 
83038 			DUK_ASSERT(new_env->thread == NULL);  /* Closed. */
83039 			DUK_ASSERT(new_env->varmap == NULL);
83040 
83041 			/* It's important that duk_xdef_prop() is a 'raw define' so that any
83042 			 * properties in an ancestor are never an issue (they should never be
83043 			 * e.g. non-writable, but just in case).
83044 			 *
83045 			 * Because template objects are not visible to user code, the case
83046 			 * where .name is missing shouldn't happen in practice.  It it does,
83047 			 * the name 'undefined' gets bound and maps to the closure (which is
83048 			 * a bit odd, but safe).
83049 			 */
83050 			(void) duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);
83051 			/* -> [ ... closure template env funcname ] */
83052 			duk_dup_m4(thr);                                           /* -> [ ... closure template env funcname closure ] */
83053 			duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_NONE);           /* -> [ ... closure template env ] */
83054 			/* env[funcname] = closure */
83055 
83056 			/* [ ... closure template env ] */
83057 
83058 			DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, (duk_hobject *) new_env);
83059 			DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, (duk_hobject *) new_env);
83060 			DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);
83061 			DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);
83062 			duk_pop_unsafe(thr);
83063 
83064 			/* [ ... closure template ] */
83065 		}
83066 		else
83067 #endif  /* DUK_USE_FUNC_NAME_PROPERTY */
83068 		{
83069 			/*
83070 			 *  Other cases (function declaration, anonymous function expression,
83071 			 *  strict direct eval code).  The "outer" environment will be whatever
83072 			 *  the caller gave us.
83073 			 */
83074 
83075 			DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, outer_lex_env);
83076 			DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, outer_lex_env);
83077 			DUK_HOBJECT_INCREF(thr, outer_lex_env);
83078 			DUK_HOBJECT_INCREF(thr, outer_lex_env);
83079 
83080 			/* [ ... closure template ] */
83081 		}
83082 	} else {
83083 		/*
83084 		 *  Function gets no new environment when called.  This is the
83085 		 *  case for global code, indirect eval code, and non-strict
83086 		 *  direct eval code.  There is no direct correspondence to the
83087 		 *  E5 specification, as global/eval code is not exposed as a
83088 		 *  function.
83089 		 */
83090 
83091 		DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(&fun_temp->obj));
83092 
83093 		DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, outer_lex_env);
83094 		DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, outer_var_env);
83095 		DUK_HOBJECT_INCREF(thr, outer_lex_env);  /* NULLs not allowed; asserted on entry */
83096 		DUK_HOBJECT_INCREF(thr, outer_var_env);
83097 	}
83098 	DUK_DDD(DUK_DDDPRINT("closure varenv -> %!ipO, lexenv -> %!ipO",
83099 	                     (duk_heaphdr *) fun_clos->var_env,
83100 	                     (duk_heaphdr *) fun_clos->lex_env));
83101 
83102 	/* Call handling assumes this for all callable closures. */
83103 	DUK_ASSERT(DUK_HCOMPFUNC_GET_LEXENV(thr->heap, fun_clos) != NULL);
83104 	DUK_ASSERT(DUK_HCOMPFUNC_GET_VARENV(thr->heap, fun_clos) != NULL);
83105 
83106 	/*
83107 	 *  Copy some internal properties directly
83108 	 *
83109 	 *  The properties will be non-writable and non-enumerable, but
83110 	 *  configurable.
83111 	 *
83112 	 *  Function templates are bare objects, so inheritance of internal
83113 	 *  Symbols is not an issue here even when using ordinary property
83114 	 *  reads.  The function instance created is not bare, so internal
83115 	 *  Symbols must be defined without inheritance checks.
83116 	 */
83117 
83118 	/* [ ... closure template ] */
83119 
83120 	DUK_DDD(DUK_DDDPRINT("copying properties: closure=%!iT, template=%!iT",
83121 	                     (duk_tval *) duk_get_tval(thr, -2),
83122 	                     (duk_tval *) duk_get_tval(thr, -1)));
83123 
83124 	for (i = 0; i < (duk_small_uint_t) (sizeof(duk__closure_copy_proplist) / sizeof(duk_uint16_t)); i++) {
83125 		duk_small_int_t stridx = (duk_small_int_t) duk__closure_copy_proplist[i];
83126 		if (duk_xget_owndataprop_stridx_short(thr, -1, stridx)) {
83127 			/* [ ... closure template val ] */
83128 			DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> found", (long) stridx));
83129 			duk_xdef_prop_stridx_short(thr, -3, stridx, DUK_PROPDESC_FLAGS_C);
83130 		} else {
83131 			DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> not found", (long) stridx));
83132 			duk_pop_unsafe(thr);
83133 		}
83134 	}
83135 
83136 	/*
83137 	 *  "length" maps to number of formals (E5 Section 13.2) for function
83138 	 *  declarations/expressions (non-bound functions).  Note that 'nargs'
83139 	 *  is NOT necessarily equal to the number of arguments.  Use length
83140 	 *  of _Formals; if missing, assume nargs matches .length.
83141 	 */
83142 
83143 	/* [ ... closure template ] */
83144 
83145 	formals = duk_hobject_get_formals(thr, (duk_hobject *) fun_temp);
83146 	if (formals) {
83147 		len_value = (duk_uint_t) formals->length;
83148 		DUK_DD(DUK_DDPRINT("closure length from _Formals -> %ld", (long) len_value));
83149 	} else {
83150 		len_value = fun_temp->nargs;
83151 		DUK_DD(DUK_DDPRINT("closure length defaulted from nargs -> %ld", (long) len_value));
83152 	}
83153 
83154 	duk_push_uint(thr, len_value);  /* [ ... closure template len_value ] */
83155 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
83156 
83157 	/*
83158 	 *  "prototype" is, by default, a fresh object with the "constructor"
83159 	 *  property.
83160 	 *
83161 	 *  Note that this creates a circular reference for every function
83162 	 *  instance (closure) which prevents refcount-based collection of
83163 	 *  function instances.
83164 	 *
83165 	 *  XXX: Try to avoid creating the default prototype object, because
83166 	 *  many functions are not used as constructors and the default
83167 	 *  prototype is unnecessary.  Perhaps it could be created on-demand
83168 	 *  when it is first accessed?
83169 	 */
83170 
83171 	/* [ ... closure template ] */
83172 
83173 	if (add_auto_proto) {
83174 		duk_push_object(thr);  /* -> [ ... closure template newobj ] */
83175 		duk_dup_m3(thr);       /* -> [ ... closure template newobj closure ] */
83176 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);  /* -> [ ... closure template newobj ] */
83177 		duk_compact(thr, -1);  /* compact the prototype */
83178 		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);     /* -> [ ... closure template ] */
83179 	}
83180 
83181 	/*
83182 	 *  "arguments" and "caller" must be mapped to throwers for strict
83183 	 *  mode and bound functions (E5 Section 15.3.5).
83184 	 *
83185 	 *  XXX: This is expensive to have for every strict function instance.
83186 	 *  Try to implement as virtual properties or on-demand created properties.
83187 	 */
83188 
83189 	/* [ ... closure template ] */
83190 
83191 	if (DUK_HOBJECT_HAS_STRICT(&fun_clos->obj)) {
83192 		duk_xdef_prop_stridx_thrower(thr, -2, DUK_STRIDX_CALLER);
83193 		duk_xdef_prop_stridx_thrower(thr, -2, DUK_STRIDX_LC_ARGUMENTS);
83194 	} else {
83195 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
83196 		DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property in use, add initial 'null' value"));
83197 		duk_push_null(thr);
83198 		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE);
83199 #else
83200 		DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property not used"));
83201 #endif
83202 	}
83203 
83204 	/*
83205 	 *  "name" used to be non-standard but is now defined by ES2015.
83206 	 *  In ES2015/ES2016 the .name property is configurable.
83207 	 */
83208 
83209 	/* [ ... closure template ] */
83210 
83211 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
83212 	/* XXX: Look for own property only; doesn't matter much because
83213 	 * templates are bare objects.
83214 	 */
83215 	if (duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME)) {
83216 		/* [ ... closure template name ] */
83217 		DUK_ASSERT(duk_is_string(thr, -1));
83218 		DUK_DD(DUK_DDPRINT("setting function instance name to %!T", duk_get_tval(thr, -1)));
83219 		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);  /* -> [ ... closure template ] */
83220 	} else {
83221 		/* Anonymous functions don't have a .name in ES2015, so don't set
83222 		 * it on the instance either.  The instance will then inherit
83223 		 * it from Function.prototype.name.
83224 		 */
83225 		DUK_DD(DUK_DDPRINT("not setting function instance .name"));
83226 		duk_pop_unsafe(thr);
83227 	}
83228 #endif
83229 
83230 	/*
83231 	 *  Compact the closure, in most cases no properties will be added later.
83232 	 *  Also, without this the closures end up having unused property slots
83233 	 *  (e.g. in Duktape 0.9.0, 8 slots would be allocated and only 7 used).
83234 	 *  A better future solution would be to allocate the closure directly
83235 	 *  to correct size (and setup the properties directly without going
83236 	 *  through the API).
83237 	 */
83238 
83239 	duk_compact(thr, -2);
83240 
83241 	/*
83242 	 *  Some assertions (E5 Section 13.2).
83243 	 */
83244 
83245 	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(&fun_clos->obj) == DUK_HOBJECT_CLASS_FUNCTION);
83246 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, &fun_clos->obj) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
83247 	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));
83248 	DUK_ASSERT(duk_has_prop_stridx(thr, -2, DUK_STRIDX_LENGTH) != 0);
83249 	DUK_ASSERT(add_auto_proto == 0 || duk_has_prop_stridx(thr, -2, DUK_STRIDX_PROTOTYPE) != 0);
83250 	/* May be missing .name */
83251 	DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
83252 	           duk_has_prop_stridx(thr, -2, DUK_STRIDX_CALLER) != 0);
83253 	DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
83254 	           duk_has_prop_stridx(thr, -2, DUK_STRIDX_LC_ARGUMENTS) != 0);
83255 
83256 	/*
83257 	 *  Finish
83258 	 */
83259 
83260 	/* [ ... closure template ] */
83261 
83262 	DUK_DDD(DUK_DDDPRINT("created function instance: template=%!iT -> closure=%!iT",
83263 	                     (duk_tval *) duk_get_tval(thr, -1),
83264 	                     (duk_tval *) duk_get_tval(thr, -2)));
83265 
83266 	duk_pop_unsafe(thr);
83267 
83268 	/* [ ... closure ] */
83269 }
83270 
83271 /*
83272  *  Delayed activation environment record initialization (for functions
83273  *  with NEWENV).
83274  *
83275  *  The non-delayed initialization is handled by duk_handle_call().
83276  */
83277 
83278 DUK_LOCAL void duk__preallocate_env_entries(duk_hthread *thr, duk_hobject *varmap, duk_hobject *env) {
83279 	duk_uint_fast32_t i;
83280 
83281 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(varmap); i++) {
83282 		duk_hstring *key;
83283 
83284 		key = DUK_HOBJECT_E_GET_KEY(thr->heap, varmap, i);
83285 		DUK_ASSERT(key != NULL);   /* assume keys are compact in _Varmap */
83286 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i));  /* assume plain values */
83287 
83288 		/* Predefine as 'undefined' to reserve a property slot.
83289 		 * This makes the unwind process (where register values
83290 		 * are copied to the env object) safe against throwing.
83291 		 *
83292 		 * XXX: This could be made much faster by creating the
83293 		 * property table directly.
83294 		 */
83295 		duk_push_undefined(thr);
83296 		DUK_DDD(DUK_DDDPRINT("preallocate env entry for key %!O", key));
83297 		duk_hobject_define_property_internal(thr, env, key, DUK_PROPDESC_FLAGS_WE);
83298 	}
83299 }
83300 
83301 /* shared helper */
83302 DUK_INTERNAL
83303 duk_hobject *duk_create_activation_environment_record(duk_hthread *thr,
83304                                                       duk_hobject *func,
83305                                                       duk_size_t bottom_byteoff) {
83306 	duk_hdecenv *env;
83307 	duk_hobject *parent;
83308 	duk_hcompfunc *f;
83309 
83310 	DUK_ASSERT(thr != NULL);
83311 	DUK_ASSERT(func != NULL);
83312 
83313 	DUK_STATS_INC(thr->heap, stats_envrec_create);
83314 
83315 	f = (duk_hcompfunc *) func;
83316 	parent = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
83317 	if (!parent) {
83318 		parent = thr->builtins[DUK_BIDX_GLOBAL_ENV];
83319 	}
83320 
83321 	env = duk_hdecenv_alloc(thr,
83322 	                        DUK_HOBJECT_FLAG_EXTENSIBLE |
83323 	                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
83324 	DUK_ASSERT(env != NULL);
83325 	duk_push_hobject(thr, (duk_hobject *) env);
83326 
83327 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
83328 	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) env, parent);
83329 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, parent);  /* parent env is the prototype */
83330 
83331 	/* open scope information, for compiled functions only */
83332 
83333 	DUK_ASSERT(env->thread == NULL);
83334 	DUK_ASSERT(env->varmap == NULL);
83335 	DUK_ASSERT(env->regbase_byteoff == 0);
83336 	if (DUK_HOBJECT_IS_COMPFUNC(func)) {
83337 		duk_hobject *varmap;
83338 
83339 		varmap = duk_hobject_get_varmap(thr, func);
83340 		if (varmap != NULL) {
83341 			env->varmap = varmap;
83342 			DUK_HOBJECT_INCREF(thr, varmap);
83343 			env->thread = thr;
83344 			DUK_HTHREAD_INCREF(thr, thr);
83345 			env->regbase_byteoff = bottom_byteoff;
83346 
83347 			/* Preallocate env property table to avoid potential
83348 			 * for out-of-memory on unwind when the env is closed.
83349 			 */
83350 			duk__preallocate_env_entries(thr, varmap, (duk_hobject *) env);
83351 		} else {
83352 			/* If function has no _Varmap, leave the environment closed. */
83353 			DUK_ASSERT(env->thread == NULL);
83354 			DUK_ASSERT(env->varmap == NULL);
83355 			DUK_ASSERT(env->regbase_byteoff == 0);
83356 		}
83357 	}
83358 
83359 	return (duk_hobject *) env;
83360 }
83361 
83362 DUK_INTERNAL
83363 void duk_js_init_activation_environment_records_delayed(duk_hthread *thr,
83364                                                         duk_activation *act) {
83365 	duk_hobject *func;
83366 	duk_hobject *env;
83367 
83368 	DUK_ASSERT(thr != NULL);
83369 	func = DUK_ACT_GET_FUNC(act);
83370 	DUK_ASSERT(func != NULL);
83371 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound functions are never in act 'func' */
83372 
83373 	/*
83374 	 *  Delayed initialization only occurs for 'NEWENV' functions.
83375 	 */
83376 
83377 	DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
83378 	DUK_ASSERT(act->lex_env == NULL);
83379 	DUK_ASSERT(act->var_env == NULL);
83380 
83381 	DUK_STATS_INC(thr->heap, stats_envrec_delayedcreate);
83382 
83383 	env = duk_create_activation_environment_record(thr, func, act->bottom_byteoff);
83384 	DUK_ASSERT(env != NULL);
83385 	/* 'act' is a stable pointer, so still OK. */
83386 
83387 	DUK_DDD(DUK_DDDPRINT("created delayed fresh env: %!ipO", (duk_heaphdr *) env));
83388 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
83389 	{
83390 		duk_hobject *p = env;
83391 		while (p) {
83392 			DUK_DDD(DUK_DDDPRINT("  -> %!ipO", (duk_heaphdr *) p));
83393 			p = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, p);
83394 		}
83395 	}
83396 #endif
83397 
83398 	act->lex_env = env;
83399 	act->var_env = env;
83400 	DUK_HOBJECT_INCREF(thr, env);  /* XXX: incref by count (here 2 times) */
83401 	DUK_HOBJECT_INCREF(thr, env);
83402 
83403 	duk_pop_unsafe(thr);
83404 }
83405 
83406 /*
83407  *  Closing environment records.
83408  *
83409  *  The environment record MUST be closed with the thread where its activation
83410  *  is; i.e. if 'env' is open, 'thr' must match env->thread, and the regbase
83411  *  and varmap must still be valid.  On entry, 'env' must be reachable.
83412  */
83413 
83414 DUK_INTERNAL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env) {
83415 	duk_uint_fast32_t i;
83416 	duk_hobject *varmap;
83417 	duk_hstring *key;
83418 	duk_tval *tv;
83419 	duk_uint_t regnum;
83420 
83421 	DUK_ASSERT(thr != NULL);
83422 	DUK_ASSERT(env != NULL);
83423 
83424 	if (DUK_UNLIKELY(!DUK_HOBJECT_IS_DECENV(env))) {
83425 		DUK_DDD(DUK_DDDPRINT("env not a declarative record: %!iO", (duk_heaphdr *) env));
83426 		return;
83427 	}
83428 
83429 	varmap = ((duk_hdecenv *) env)->varmap;
83430 	if (varmap == NULL) {
83431 		DUK_DDD(DUK_DDDPRINT("env already closed: %!iO", (duk_heaphdr *) env));
83432 
83433 		return;
83434 	}
83435 	DUK_ASSERT(((duk_hdecenv *) env)->thread != NULL);
83436 	DUK_HDECENV_ASSERT_VALID((duk_hdecenv *) env);
83437 
83438 	DUK_DDD(DUK_DDDPRINT("closing env: %!iO", (duk_heaphdr *) env));
83439 	DUK_DDD(DUK_DDDPRINT("varmap: %!O", (duk_heaphdr *) varmap));
83440 
83441 	/* Env must be closed in the same thread as where it runs. */
83442 	DUK_ASSERT(((duk_hdecenv *) env)->thread == thr);
83443 
83444 	/* XXX: additional conditions when to close variables? we don't want to do it
83445 	 * unless the environment may have "escaped" (referenced in a function closure).
83446 	 * With delayed environments, the existence is probably good enough of a check.
83447 	 */
83448 
83449 	/* Note: we rely on the _Varmap having a bunch of nice properties, like:
83450 	 *  - being compacted and unmodified during this process
83451 	 *  - not containing an array part
83452 	 *  - having correct value types
83453 	 */
83454 
83455 	DUK_DDD(DUK_DDDPRINT("copying bound register values, %ld bound regs", (long) DUK_HOBJECT_GET_ENEXT(varmap)));
83456 
83457 	/* Copy over current variable values from value stack to the
83458 	 * environment record.  The scope object is empty but may
83459 	 * inherit from another scope which has conflicting names.
83460 	 */
83461 
83462 	/* XXX: Do this using a once allocated entry area, no side effects.
83463 	 * Hash part would need special treatment however (maybe copy, and
83464 	 * then realloc with hash part if large enough).
83465 	 */
83466 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(varmap); i++) {
83467 		duk_size_t regbase_byteoff;
83468 
83469 		key = DUK_HOBJECT_E_GET_KEY(thr->heap, varmap, i);
83470 		DUK_ASSERT(key != NULL);   /* assume keys are compact in _Varmap */
83471 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i));  /* assume plain values */
83472 
83473 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, varmap, i);
83474 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
83475 		DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (duk_double_t) DUK_UINT32_MAX);  /* limits */
83476 #if defined(DUK_USE_FASTINT)
83477 		DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
83478 		regnum = (duk_uint_t) DUK_TVAL_GET_FASTINT_U32(tv);
83479 #else
83480 		regnum = (duk_uint_t) DUK_TVAL_GET_NUMBER(tv);
83481 #endif
83482 
83483 		regbase_byteoff = ((duk_hdecenv *) env)->regbase_byteoff;
83484 		DUK_ASSERT((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum >= (duk_uint8_t *) thr->valstack);
83485 		DUK_ASSERT((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum < (duk_uint8_t *) thr->valstack_top);
83486 
83487 		/* Write register value into env as named properties.
83488 		 * If property already exists, overwrites silently.
83489 		 * Property is writable, but not deletable (not configurable
83490 		 * in terms of property attributes).
83491 		 *
83492 		 * This property write must not throw because we're unwinding
83493 		 * and unwind code is not allowed to throw at present.  The
83494 		 * call itself has no such guarantees, but we've preallocated
83495 		 * entries for each property when the env was created, so no
83496 		 * out-of-memory error should be possible.  If this guarantee
83497 		 * is not provided, problems like GH-476 may happen.
83498 		 */
83499 		duk_push_tval(thr, (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum));
83500 		DUK_DDD(DUK_DDDPRINT("closing identifier %!O -> reg %ld, value %!T",
83501 		                     (duk_heaphdr *) key,
83502 		                     (long) regnum,
83503 		                     (duk_tval *) duk_get_tval(thr, -1)));
83504 		duk_hobject_define_property_internal(thr, env, key, DUK_PROPDESC_FLAGS_WE);
83505 	}
83506 
83507 	/* NULL atomically to avoid inconsistent state + side effects. */
83508 	DUK_HOBJECT_DECREF_NORZ(thr, ((duk_hdecenv *) env)->thread);
83509 	DUK_HOBJECT_DECREF_NORZ(thr, ((duk_hdecenv *) env)->varmap);
83510 	((duk_hdecenv *) env)->thread = NULL;
83511 	((duk_hdecenv *) env)->varmap = NULL;
83512 
83513 	DUK_DDD(DUK_DDDPRINT("env after closing: %!O", (duk_heaphdr *) env));
83514 }
83515 
83516 /*
83517  *  GETIDREF: a GetIdentifierReference-like helper.
83518  *
83519  *  Provides a parent traversing lookup and a single level lookup
83520  *  (for HasBinding).
83521  *
83522  *  Instead of returning the value, returns a bunch of values allowing
83523  *  the caller to read, write, or delete the binding.  Value pointers
83524  *  are duk_tval pointers which can be mutated directly as long as
83525  *  refcounts are properly updated.  Note that any operation which may
83526  *  reallocate valstacks or compact objects may invalidate the returned
83527  *  duk_tval (but not object) pointers, so caller must be very careful.
83528  *
83529  *  If starting environment record 'env' is given, 'act' is ignored.
83530  *  However, if 'env' is NULL, the caller may identify, in 'act', an
83531  *  activation which hasn't had its declarative environment initialized
83532  *  yet.  The activation registers are then looked up, and its parent
83533  *  traversed normally.
83534  *
83535  *  The 'out' structure values are only valid if the function returns
83536  *  success (non-zero).
83537  */
83538 
83539 /* lookup name from an open declarative record's registers */
83540 DUK_LOCAL
83541 duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,
83542                                          duk_hstring *name,
83543                                          duk_hdecenv *env,
83544                                          duk__id_lookup_result *out) {
83545 	duk_tval *tv;
83546 	duk_size_t reg_rel;
83547 
83548 	DUK_ASSERT(thr != NULL);
83549 	DUK_ASSERT(name != NULL);
83550 	DUK_ASSERT(env != NULL);
83551 	DUK_ASSERT(out != NULL);
83552 
83553 	DUK_ASSERT(DUK_HOBJECT_IS_DECENV((duk_hobject *) env));
83554 	DUK_HDECENV_ASSERT_VALID(env);
83555 
83556 	if (env->thread == NULL) {
83557 		/* already closed */
83558 		return 0;
83559 	}
83560 	DUK_ASSERT(env->varmap != NULL);
83561 
83562 	tv = duk_hobject_find_entry_tval_ptr(thr->heap, env->varmap, name);
83563 	if (DUK_UNLIKELY(tv == NULL)) {
83564 		return 0;
83565 	}
83566 
83567 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
83568 	DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (duk_double_t) DUK_UINT32_MAX);  /* limits */
83569 #if defined(DUK_USE_FASTINT)
83570 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
83571 	reg_rel = (duk_size_t) DUK_TVAL_GET_FASTINT_U32(tv);
83572 #else
83573 	reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
83574 #endif
83575 	DUK_ASSERT_DISABLE(reg_rel >= 0);  /* unsigned */
83576 
83577 	tv = (duk_tval *) (void *) ((duk_uint8_t *) env->thread->valstack + env->regbase_byteoff + sizeof(duk_tval) * reg_rel);
83578 	DUK_ASSERT(tv >= env->thread->valstack && tv < env->thread->valstack_end);  /* XXX: more accurate? */
83579 
83580 	out->value = tv;
83581 	out->attrs = DUK_PROPDESC_FLAGS_W;  /* registers are mutable, non-deletable */
83582 	out->env = (duk_hobject *) env;
83583 	out->holder = NULL;
83584 	out->has_this = 0;
83585 	return 1;
83586 }
83587 
83588 /* lookup name from current activation record's functions' registers */
83589 DUK_LOCAL
83590 duk_bool_t duk__getid_activation_regs(duk_hthread *thr,
83591                                       duk_hstring *name,
83592                                       duk_activation *act,
83593                                       duk__id_lookup_result *out) {
83594 	duk_tval *tv;
83595 	duk_hobject *func;
83596 	duk_hobject *varmap;
83597 	duk_size_t reg_rel;
83598 
83599 	DUK_ASSERT(thr != NULL);
83600 	DUK_ASSERT(name != NULL);
83601 	DUK_ASSERT(act != NULL);
83602 	DUK_ASSERT(out != NULL);
83603 
83604 	func = DUK_ACT_GET_FUNC(act);
83605 	DUK_ASSERT(func != NULL);
83606 	DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
83607 
83608 	if (!DUK_HOBJECT_IS_COMPFUNC(func)) {
83609 		return 0;
83610 	}
83611 
83612 	/* XXX: move varmap to duk_hcompfunc struct field? */
83613 	varmap = duk_hobject_get_varmap(thr, func);
83614 	if (!varmap) {
83615 		return 0;
83616 	}
83617 
83618 	tv = duk_hobject_find_entry_tval_ptr(thr->heap, varmap, name);
83619 	if (!tv) {
83620 		return 0;
83621 	}
83622 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
83623 	reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
83624 	DUK_ASSERT_DISABLE(reg_rel >= 0);
83625 	DUK_ASSERT(reg_rel < ((duk_hcompfunc *) func)->nregs);
83626 
83627 	tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
83628 	tv += reg_rel;
83629 
83630 	out->value = tv;
83631 	out->attrs = DUK_PROPDESC_FLAGS_W;  /* registers are mutable, non-deletable */
83632 	out->env = NULL;
83633 	out->holder = NULL;
83634 	out->has_this = 0;
83635 	return 1;
83636 }
83637 
83638 DUK_LOCAL
83639 duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
83640                                          duk_hobject *env,
83641                                          duk_hstring *name,
83642                                          duk_activation *act,
83643                                          duk_bool_t parents,
83644                                          duk__id_lookup_result *out) {
83645 	duk_tval *tv;
83646 	duk_uint_t sanity;
83647 
83648 	DUK_ASSERT(thr != NULL);
83649 	DUK_ASSERT(env != NULL || act != NULL);
83650 	DUK_ASSERT(name != NULL);
83651 	DUK_ASSERT(out != NULL);
83652 
83653 	DUK_ASSERT(!env || DUK_HOBJECT_IS_ENV(env));
83654 	DUK_ASSERT(!env || !DUK_HOBJECT_HAS_ARRAY_PART(env));
83655 
83656 	/*
83657 	 *  Conceptually, we look for the identifier binding by starting from
83658 	 *  'env' and following to chain of environment records (represented
83659 	 *  by the prototype chain).
83660 	 *
83661 	 *  If 'env' is NULL, the current activation does not yet have an
83662 	 *  allocated declarative environment record; this should be treated
83663 	 *  exactly as if the environment record existed but had no bindings
83664 	 *  other than register bindings.
83665 	 *
83666 	 *  Note: we assume that with the DUK_HOBJECT_FLAG_NEWENV cleared
83667 	 *  the environment will always be initialized immediately; hence
83668 	 *  a NULL 'env' should only happen with the flag set.  This is the
83669 	 *  case for: (1) function calls, and (2) strict, direct eval calls.
83670 	 */
83671 
83672 	if (env == NULL && act != NULL) {
83673 		duk_hobject *func;
83674 		duk_hcompfunc *f;
83675 
83676 		DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference: env is NULL, activation is non-NULL -> "
83677 		                     "delayed env case, look up activation regs first"));
83678 
83679 		/*
83680 		 *  Try registers
83681 		 */
83682 
83683 		if (duk__getid_activation_regs(thr, name, act, out)) {
83684 			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
83685 			                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
83686 			                     "(found from register bindings when env=NULL)",
83687 			                     (duk_heaphdr *) name, (duk_tval *) out->value,
83688 			                     (long) out->attrs, (long) out->has_this,
83689 			                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
83690 			return 1;
83691 		}
83692 
83693 		DUK_DDD(DUK_DDDPRINT("not found in current activation regs"));
83694 
83695 		/*
83696 		 *  Not found in registers, proceed to the parent record.
83697 		 *  Here we need to determine what the parent would be,
83698 		 *  if 'env' was not NULL (i.e. same logic as when initializing
83699 		 *  the record).
83700 		 *
83701 		 *  Note that environment initialization is only deferred when
83702 		 *  DUK_HOBJECT_HAS_NEWENV is set, and this only happens for:
83703 		 *    - Function code
83704 		 *    - Strict eval code
83705 		 *
83706 		 *  We only need to check _Lexenv here; _Varenv exists only if it
83707 		 *  differs from _Lexenv (and thus _Lexenv will also be present).
83708 		 */
83709 
83710 		if (!parents) {
83711 			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
83712 			                     "(not found from register bindings when env=NULL)"));
83713 			goto fail_not_found;
83714 		}
83715 
83716 		func = DUK_ACT_GET_FUNC(act);
83717 		DUK_ASSERT(func != NULL);
83718 		DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
83719 		f = (duk_hcompfunc *) func;
83720 
83721 		env = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
83722 		if (!env) {
83723 			env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
83724 		}
83725 
83726 		DUK_DDD(DUK_DDDPRINT("continue lookup from env: %!iO",
83727 		                     (duk_heaphdr *) env));
83728 	}
83729 
83730 	/*
83731 	 *  Prototype walking starting from 'env'.
83732 	 *
83733 	 *  ('act' is not needed anywhere here.)
83734 	 */
83735 
83736 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
83737 	while (env != NULL) {
83738 		duk_small_uint_t cl;
83739 		duk_uint_t attrs;
83740 
83741 		DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference, name=%!O, considering env=%p -> %!iO",
83742 		                     (duk_heaphdr *) name,
83743 		                     (void *) env,
83744 		                     (duk_heaphdr *) env));
83745 
83746 		DUK_ASSERT(env != NULL);
83747 		DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
83748 		DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(env));
83749 
83750 		cl = DUK_HOBJECT_GET_CLASS_NUMBER(env);
83751 		DUK_ASSERT(cl == DUK_HOBJECT_CLASS_OBJENV || cl == DUK_HOBJECT_CLASS_DECENV);
83752 		if (cl == DUK_HOBJECT_CLASS_DECENV) {
83753 			/*
83754 			 *  Declarative environment record.
83755 			 *
83756 			 *  Identifiers can never be stored in ancestors and are
83757 			 *  always plain values, so we can use an internal helper
83758 			 *  and access the value directly with an duk_tval ptr.
83759 			 *
83760 			 *  A closed environment is only indicated by it missing
83761 			 *  the "book-keeping" properties required for accessing
83762 			 *  register-bound variables.
83763 			 */
83764 
83765 			DUK_HDECENV_ASSERT_VALID((duk_hdecenv *) env);
83766 			if (duk__getid_open_decl_env_regs(thr, name, (duk_hdecenv *) env, out)) {
83767 				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
83768 				                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
83769 				                     "(declarative environment record, scope open, found in regs)",
83770 				                     (duk_heaphdr *) name, (duk_tval *) out->value,
83771 				                     (long) out->attrs, (long) out->has_this,
83772 				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
83773 				return 1;
83774 			}
83775 
83776 			tv = duk_hobject_find_entry_tval_ptr_and_attrs(thr->heap, env, name, &attrs);
83777 			if (tv) {
83778 				out->value = tv;
83779 				out->attrs = attrs;
83780 				out->env = env;
83781 				out->holder = env;
83782 				out->has_this = 0;
83783 
83784 				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
83785 				                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
83786 				                     "(declarative environment record, found in properties)",
83787 				                     (duk_heaphdr *) name, (duk_tval *) out->value,
83788 				                     (long) out->attrs, (long) out->has_this,
83789 				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
83790 				return 1;
83791 			}
83792 		} else {
83793 			/*
83794 			 *  Object environment record.
83795 			 *
83796 			 *  Binding (target) object is an external, uncontrolled object.
83797 			 *  Identifier may be bound in an ancestor property, and may be
83798 			 *  an accessor.  Target can also be a Proxy which we must support
83799 			 *  here.
83800 			 */
83801 
83802 			/* XXX: we could save space by using _Target OR _This.  If _Target, assume
83803 			 * this binding is undefined.  If _This, assumes this binding is _This, and
83804 			 * target is also _This.  One property would then be enough.
83805 			 */
83806 
83807 			duk_hobject *target;
83808 			duk_bool_t found;
83809 
83810 			DUK_ASSERT(cl == DUK_HOBJECT_CLASS_OBJENV);
83811 			DUK_HOBJENV_ASSERT_VALID((duk_hobjenv *) env);
83812 
83813 			target = ((duk_hobjenv *) env)->target;
83814 			DUK_ASSERT(target != NULL);
83815 
83816 			/* Target may be a Proxy or property may be an accessor, so we must
83817 			 * use an actual, Proxy-aware hasprop check here.
83818 			 *
83819 			 * out->holder is NOT set to the actual duk_hobject where the
83820 			 * property is found, but rather the object binding target object.
83821 			 */
83822 
83823 #if defined(DUK_USE_ES6_PROXY)
83824 			if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(target))) {
83825 				duk_tval tv_name;
83826 				duk_tval tv_target_tmp;
83827 
83828 				DUK_ASSERT(name != NULL);
83829 				DUK_TVAL_SET_STRING(&tv_name, name);
83830 				DUK_TVAL_SET_OBJECT(&tv_target_tmp, target);
83831 
83832 				found = duk_hobject_hasprop(thr, &tv_target_tmp, &tv_name);
83833 			} else
83834 #endif  /* DUK_USE_ES6_PROXY */
83835 			{
83836 				/* XXX: duk_hobject_hasprop() would be correct for
83837 				 * non-Proxy objects too, but it is about ~20-25%
83838 				 * slower at present so separate code paths for
83839 				 * Proxy and non-Proxy now.
83840 				 */
83841 				found = duk_hobject_hasprop_raw(thr, target, name);
83842 			}
83843 
83844 			if (found) {
83845 				out->value = NULL;  /* can't get value, may be accessor */
83846 				out->attrs = 0;     /* irrelevant when out->value == NULL */
83847 				out->env = env;
83848 				out->holder = target;
83849 				out->has_this = ((duk_hobjenv *) env)->has_this;
83850 
83851 				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
83852 				                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
83853 				                     "(object environment record)",
83854 				                     (duk_heaphdr *) name, (duk_tval *) out->value,
83855 				                     (long) out->attrs, (long) out->has_this,
83856 				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
83857 				return 1;
83858 			}
83859 		}
83860 
83861 		if (!parents) {
83862 			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
83863 			                     "(not found from first traversed env)"));
83864 			goto fail_not_found;
83865 		}
83866 
83867                 if (DUK_UNLIKELY(sanity-- == 0)) {
83868                         DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
83869 			DUK_WO_NORETURN(return 0;);
83870                 }
83871 		env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);
83872 	}
83873 
83874 	/*
83875 	 *  Not found (even in global object)
83876 	 */
83877 
83878  fail_not_found:
83879 	return 0;
83880 }
83881 
83882 /*
83883  *  HASVAR: check identifier binding from a given environment record
83884  *  without traversing its parents.
83885  *
83886  *  This primitive is not exposed to user code as such, but is used
83887  *  internally for e.g. declaration binding instantiation.
83888  *
83889  *  See E5 Sections:
83890  *    10.2.1.1.1 HasBinding(N)
83891  *    10.2.1.2.1 HasBinding(N)
83892  *
83893  *  Note: strictness has no bearing on this check.  Hence we don't take
83894  *  a 'strict' parameter.
83895  */
83896 
83897 #if 0  /*unused*/
83898 DUK_INTERNAL
83899 duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr,
83900                                 duk_hobject *env,
83901                                 duk_hstring *name) {
83902 	duk__id_lookup_result ref;
83903 	duk_bool_t parents;
83904 
83905 	DUK_DDD(DUK_DDDPRINT("hasvar: thr=%p, env=%p, name=%!O "
83906 	                     "(env -> %!dO)",
83907 	                     (void *) thr, (void *) env, (duk_heaphdr *) name,
83908 	                     (duk_heaphdr *) env));
83909 
83910 	DUK_ASSERT(thr != NULL);
83911 	DUK_ASSERT(env != NULL);
83912 	DUK_ASSERT(name != NULL);
83913 
83914         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
83915         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
83916 
83917 	DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
83918 	DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(env));
83919 
83920 	/* lookup results is ignored */
83921 	parents = 0;
83922 	return duk__get_identifier_reference(thr, env, name, NULL, parents, &ref);
83923 }
83924 #endif
83925 
83926 /*
83927  *  GETVAR
83928  *
83929  *  See E5 Sections:
83930  *    11.1.2 Identifier Reference
83931  *    10.3.1 Identifier Resolution
83932  *    11.13.1 Simple Assignment  [example of where the Reference is GetValue'd]
83933  *    8.7.1 GetValue (V)
83934  *    8.12.1 [[GetOwnProperty]] (P)
83935  *    8.12.2 [[GetProperty]] (P)
83936  *    8.12.3 [[Get]] (P)
83937  *
83938  *  If 'throw' is true, always leaves two values on top of stack: [val this].
83939  *
83940  *  If 'throw' is false, returns 0 if identifier cannot be resolved, and the
83941  *  stack will be unaffected in this case.  If identifier is resolved, returns
83942  *  1 and leaves [val this] on top of stack.
83943  *
83944  *  Note: the 'strict' flag of a reference returned by GetIdentifierReference
83945  *  is ignored by GetValue.  Hence we don't take a 'strict' parameter.
83946  *
83947  *  The 'throw' flag is needed for implementing 'typeof' for an unreferenced
83948  *  identifier.  An unreference identifier in other contexts generates a
83949  *  ReferenceError.
83950  */
83951 
83952 DUK_LOCAL
83953 duk_bool_t duk__getvar_helper(duk_hthread *thr,
83954                               duk_hobject *env,
83955                               duk_activation *act,
83956                               duk_hstring *name,
83957                               duk_bool_t throw_flag) {
83958 	duk__id_lookup_result ref;
83959 	duk_tval tv_tmp_obj;
83960 	duk_tval tv_tmp_key;
83961 	duk_bool_t parents;
83962 
83963 	DUK_DDD(DUK_DDDPRINT("getvar: thr=%p, env=%p, act=%p, name=%!O "
83964 	                     "(env -> %!dO)",
83965 	                     (void *) thr, (void *) env, (void *) act,
83966 	                     (duk_heaphdr *) name, (duk_heaphdr *) env));
83967 
83968 	DUK_ASSERT(thr != NULL);
83969 	DUK_ASSERT(name != NULL);
83970 	/* env and act may be NULL */
83971 
83972 	DUK_STATS_INC(thr->heap, stats_getvar_all);
83973 
83974         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
83975         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
83976 
83977 	parents = 1;     /* follow parent chain */
83978 	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
83979 		if (ref.value) {
83980 			duk_push_tval(thr, ref.value);
83981 			duk_push_undefined(thr);
83982 		} else {
83983 			DUK_ASSERT(ref.holder != NULL);
83984 
83985 			/* ref.holder is safe across the getprop call (even
83986 			 * with side effects) because 'env' is reachable and
83987 			 * ref.holder is a direct heap pointer.
83988 			 */
83989 
83990 			DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
83991 			DUK_TVAL_SET_STRING(&tv_tmp_key, name);
83992 			(void) duk_hobject_getprop(thr, &tv_tmp_obj, &tv_tmp_key);  /* [value] */
83993 
83994 			if (ref.has_this) {
83995 				duk_push_hobject(thr, ref.holder);
83996 			} else {
83997 				duk_push_undefined(thr);
83998 			}
83999 
84000 			/* [value this] */
84001 		}
84002 
84003 		return 1;
84004 	} else {
84005 		if (throw_flag) {
84006 			DUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR,
84007 			               "identifier '%s' undefined",
84008 			               (const char *) DUK_HSTRING_GET_DATA(name));
84009 			DUK_WO_NORETURN(return 0;);
84010 		}
84011 
84012 		return 0;
84013 	}
84014 }
84015 
84016 DUK_INTERNAL
84017 duk_bool_t duk_js_getvar_envrec(duk_hthread *thr,
84018                                 duk_hobject *env,
84019                                 duk_hstring *name,
84020                                 duk_bool_t throw_flag) {
84021 	return duk__getvar_helper(thr, env, NULL, name, throw_flag);
84022 }
84023 
84024 DUK_INTERNAL
84025 duk_bool_t duk_js_getvar_activation(duk_hthread *thr,
84026                                     duk_activation *act,
84027                                     duk_hstring *name,
84028                                     duk_bool_t throw_flag) {
84029 	DUK_ASSERT(act != NULL);
84030 	return duk__getvar_helper(thr, act->lex_env, act, name, throw_flag);
84031 }
84032 
84033 /*
84034  *  PUTVAR
84035  *
84036  *  See E5 Sections:
84037  *    11.1.2 Identifier Reference
84038  *    10.3.1 Identifier Resolution
84039  *    11.13.1 Simple Assignment  [example of where the Reference is PutValue'd]
84040  *    8.7.2 PutValue (V,W)  [see especially step 3.b, undefined -> automatic global in non-strict mode]
84041  *    8.12.4 [[CanPut]] (P)
84042  *    8.12.5 [[Put]] (P)
84043  *
84044  *  Note: may invalidate any valstack (or object) duk_tval pointers because
84045  *  putting a value may reallocate any object or any valstack.  Caller beware.
84046  */
84047 
84048 DUK_LOCAL
84049 void duk__putvar_helper(duk_hthread *thr,
84050                         duk_hobject *env,
84051                         duk_activation *act,
84052                         duk_hstring *name,
84053                         duk_tval *val,
84054                         duk_bool_t strict) {
84055 	duk__id_lookup_result ref;
84056 	duk_tval tv_tmp_val;
84057 	duk_tval tv_tmp_obj;
84058 	duk_tval tv_tmp_key;
84059 	duk_bool_t parents;
84060 
84061 	DUK_STATS_INC(thr->heap, stats_putvar_all);
84062 
84063 	DUK_DDD(DUK_DDDPRINT("putvar: thr=%p, env=%p, act=%p, name=%!O, val=%p, strict=%ld "
84064 	                     "(env -> %!dO, val -> %!T)",
84065 	                     (void *) thr, (void *) env, (void *) act,
84066 	                     (duk_heaphdr *) name, (void *) val, (long) strict,
84067 	                     (duk_heaphdr *) env, (duk_tval *) val));
84068 
84069 	DUK_ASSERT(thr != NULL);
84070 	DUK_ASSERT(name != NULL);
84071 	DUK_ASSERT(val != NULL);
84072 	/* env and act may be NULL */
84073 
84074 	DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
84075 	DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
84076 	DUK_ASSERT_REFCOUNT_NONZERO_TVAL(val);
84077 
84078 	DUK_TVAL_SET_TVAL(&tv_tmp_val, val);  /* Stabilize. */
84079 	val = NULL;
84080 
84081 	/*
84082 	 *  In strict mode E5 protects 'eval' and 'arguments' from being
84083 	 *  assigned to (or even declared anywhere).  Attempt to do so
84084 	 *  should result in a compile time SyntaxError.  See the internal
84085 	 *  design documentation for details.
84086 	 *
84087 	 *  Thus, we should never come here, run-time, for strict code,
84088 	 *  and name 'eval' or 'arguments'.
84089 	 */
84090 
84091 	DUK_ASSERT(!strict ||
84092 	           (name != DUK_HTHREAD_STRING_EVAL(thr) &&
84093 	            name != DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)));
84094 
84095 	/*
84096 	 *  Lookup variable and update in-place if found.
84097 	 */
84098 
84099 	parents = 1;     /* follow parent chain */
84100 
84101 	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
84102 		if (ref.value && (ref.attrs & DUK_PROPDESC_FLAG_WRITABLE)) {
84103 			/* Update duk_tval in-place if pointer provided and the
84104 			 * property is writable.  If the property is not writable
84105 			 * (immutable binding), use duk_hobject_putprop() which
84106 			 * will respect mutability.
84107 			 */
84108 			duk_tval *tv_val;
84109 
84110 			tv_val = ref.value;
84111 			DUK_ASSERT(tv_val != NULL);
84112 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv_val, &tv_tmp_val);  /* side effects */
84113 
84114 			/* ref.value invalidated here */
84115 		} else {
84116 			DUK_ASSERT(ref.holder != NULL);
84117 
84118 			DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
84119 			DUK_TVAL_SET_STRING(&tv_tmp_key, name);
84120 			(void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, &tv_tmp_val, strict);
84121 
84122 			/* ref.value invalidated here */
84123 		}
84124 
84125 		return;
84126 	}
84127 
84128 	/*
84129 	 *  Not found: write to global object (non-strict) or ReferenceError
84130 	 *  (strict); see E5 Section 8.7.2, step 3.
84131 	 */
84132 
84133 	if (strict) {
84134 		DUK_DDD(DUK_DDDPRINT("identifier binding not found, strict => reference error"));
84135 		DUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR,
84136 		               "identifier '%s' undefined",
84137 		               (const char *) DUK_HSTRING_GET_DATA(name));
84138 		DUK_WO_NORETURN(return;);
84139 	}
84140 
84141 	DUK_DDD(DUK_DDDPRINT("identifier binding not found, not strict => set to global"));
84142 
84143 	DUK_TVAL_SET_OBJECT(&tv_tmp_obj, thr->builtins[DUK_BIDX_GLOBAL]);
84144 	DUK_TVAL_SET_STRING(&tv_tmp_key, name);
84145 	(void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, &tv_tmp_val, 0);  /* 0 = no throw */
84146 
84147 	/* NB: 'val' may be invalidated here because put_value may realloc valstack,
84148 	 * caller beware.
84149 	 */
84150 }
84151 
84152 DUK_INTERNAL
84153 void duk_js_putvar_envrec(duk_hthread *thr,
84154                           duk_hobject *env,
84155                           duk_hstring *name,
84156                           duk_tval *val,
84157                           duk_bool_t strict) {
84158 	duk__putvar_helper(thr, env, NULL, name, val, strict);
84159 }
84160 
84161 DUK_INTERNAL
84162 void duk_js_putvar_activation(duk_hthread *thr,
84163                               duk_activation *act,
84164                               duk_hstring *name,
84165                               duk_tval *val,
84166                               duk_bool_t strict) {
84167 	DUK_ASSERT(act != NULL);
84168 	duk__putvar_helper(thr, act->lex_env, act, name, val, strict);
84169 }
84170 
84171 /*
84172  *  DELVAR
84173  *
84174  *  See E5 Sections:
84175  *    11.4.1 The delete operator
84176  *    10.2.1.1.5 DeleteBinding (N)  [declarative environment record]
84177  *    10.2.1.2.5 DeleteBinding (N)  [object environment record]
84178  *
84179  *  Variable bindings established inside eval() are deletable (configurable),
84180  *  other bindings are not, including variables declared in global level.
84181  *  Registers are always non-deletable, and the deletion of other bindings
84182  *  is controlled by the configurable flag.
84183  *
84184  *  For strict mode code, the 'delete' operator should fail with a compile
84185  *  time SyntaxError if applied to identifiers.  Hence, no strict mode
84186  *  run-time deletion of identifiers should ever happen.  This function
84187  *  should never be called from strict mode code!
84188  */
84189 
84190 DUK_LOCAL
84191 duk_bool_t duk__delvar_helper(duk_hthread *thr,
84192                               duk_hobject *env,
84193                               duk_activation *act,
84194                               duk_hstring *name) {
84195 	duk__id_lookup_result ref;
84196 	duk_bool_t parents;
84197 
84198 	DUK_DDD(DUK_DDDPRINT("delvar: thr=%p, env=%p, act=%p, name=%!O "
84199 	                     "(env -> %!dO)",
84200 	                     (void *) thr, (void *) env, (void *) act,
84201 	                     (duk_heaphdr *) name, (duk_heaphdr *) env));
84202 
84203 	DUK_ASSERT(thr != NULL);
84204 	DUK_ASSERT(name != NULL);
84205 	/* env and act may be NULL */
84206 
84207         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
84208 
84209 	parents = 1;     /* follow parent chain */
84210 
84211 	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
84212 		if (ref.value && !(ref.attrs & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
84213 			/* Identifier found in registers (always non-deletable)
84214 			 * or declarative environment record and non-configurable.
84215 			 */
84216 			return 0;
84217 		}
84218 		DUK_ASSERT(ref.holder != NULL);
84219 
84220 		return duk_hobject_delprop_raw(thr, ref.holder, name, 0);
84221 	}
84222 
84223 	/*
84224 	 *  Not found (even in global object).
84225 	 *
84226 	 *  In non-strict mode this is a silent SUCCESS (!), see E5 Section 11.4.1,
84227 	 *  step 3.b.  In strict mode this case is a compile time SyntaxError so
84228 	 *  we should not come here.
84229 	 */
84230 
84231 	DUK_DDD(DUK_DDDPRINT("identifier to be deleted not found: name=%!O "
84232 	                     "(treated as silent success)",
84233 	                     (duk_heaphdr *) name));
84234 	return 1;
84235 }
84236 
84237 #if 0  /*unused*/
84238 DUK_INTERNAL
84239 duk_bool_t duk_js_delvar_envrec(duk_hthread *thr,
84240                                 duk_hobject *env,
84241                                 duk_hstring *name) {
84242 	return duk__delvar_helper(thr, env, NULL, name);
84243 }
84244 #endif
84245 
84246 DUK_INTERNAL
84247 duk_bool_t duk_js_delvar_activation(duk_hthread *thr,
84248                                     duk_activation *act,
84249                                     duk_hstring *name) {
84250 	DUK_ASSERT(act != NULL);
84251 	return duk__delvar_helper(thr, act->lex_env, act, name);
84252 }
84253 
84254 /*
84255  *  DECLVAR
84256  *
84257  *  See E5 Sections:
84258  *    10.4.3 Entering Function Code
84259  *    10.5 Declaration Binding Instantion
84260  *    12.2 Variable Statement
84261  *    11.1.2 Identifier Reference
84262  *    10.3.1 Identifier Resolution
84263  *
84264  *  Variable declaration behavior is mainly discussed in Section 10.5,
84265  *  and is not discussed in the execution semantics (Sections 11-13).
84266  *
84267  *  Conceptually declarations happen when code (global, eval, function)
84268  *  is entered, before any user code is executed.  In practice, register-
84269  *  bound identifiers are 'declared' automatically (by virtue of being
84270  *  allocated to registers with the initial value 'undefined').  Other
84271  *  identifiers are declared in the function prologue with this primitive.
84272  *
84273  *  Since non-register bindings eventually back to an internal object's
84274  *  properties, the 'prop_flags' argument is used to specify binding
84275  *  type:
84276  *
84277  *    - Immutable binding: set DUK_PROPDESC_FLAG_WRITABLE to false
84278  *    - Non-deletable binding: set DUK_PROPDESC_FLAG_CONFIGURABLE to false
84279  *    - The flag DUK_PROPDESC_FLAG_ENUMERABLE should be set, although it
84280  *      doesn't really matter for internal objects
84281  *
84282  *  All bindings are non-deletable mutable bindings except:
84283  *
84284  *    - Declarations in eval code (mutable, deletable)
84285  *    - 'arguments' binding in strict function code (immutable)
84286  *    - Function name binding of a function expression (immutable)
84287  *
84288  *  Declarations may go to declarative environment records (always
84289  *  so for functions), but may also go to object environment records
84290  *  (e.g. global code).  The global object environment has special
84291  *  behavior when re-declaring a function (but not a variable); see
84292  *  E5.1 specification, Section 10.5, step 5.e.
84293  *
84294  *  Declarations always go to the 'top-most' environment record, i.e.
84295  *  we never check the record chain.  It's not an error even if a
84296  *  property (even an immutable or non-deletable one) of the same name
84297  *  already exists.
84298  *
84299  *  If a declared variable already exists, its value needs to be updated
84300  *  (if possible).  Returns 1 if a PUTVAR needs to be done by the caller;
84301  *  otherwise returns 0.
84302  */
84303 
84304 DUK_LOCAL
84305 duk_bool_t duk__declvar_helper(duk_hthread *thr,
84306                                duk_hobject *env,
84307                                duk_hstring *name,
84308                                duk_tval *val,
84309                                duk_small_uint_t prop_flags,
84310                                duk_bool_t is_func_decl) {
84311 	duk_hobject *holder;
84312 	duk_bool_t parents;
84313 	duk__id_lookup_result ref;
84314 	duk_tval *tv;
84315 
84316 	DUK_DDD(DUK_DDDPRINT("declvar: thr=%p, env=%p, name=%!O, val=%!T, prop_flags=0x%08lx, is_func_decl=%ld "
84317 	                     "(env -> %!iO)",
84318 	                     (void *) thr, (void *) env, (duk_heaphdr *) name,
84319 	                     (duk_tval *) val, (unsigned long) prop_flags,
84320 	                     (unsigned int) is_func_decl, (duk_heaphdr *) env));
84321 
84322 	DUK_ASSERT(thr != NULL);
84323 	DUK_ASSERT(env != NULL);
84324 	DUK_ASSERT(name != NULL);
84325 	DUK_ASSERT(val != NULL);
84326 
84327 	/* Note: in strict mode the compiler should reject explicit
84328 	 * declaration of 'eval' or 'arguments'.  However, internal
84329 	 * bytecode may declare 'arguments' in the function prologue.
84330 	 * We don't bother checking (or asserting) for these now.
84331 	 */
84332 
84333 	/* Note: val is a stable duk_tval pointer.  The caller makes
84334 	 * a value copy into its stack frame, so 'tv_val' is not subject
84335 	 * to side effects here.
84336 	 */
84337 
84338 	/*
84339 	 *  Check whether already declared.
84340 	 *
84341 	 *  We need to check whether the binding exists in the environment
84342 	 *  without walking its parents.  However, we still need to check
84343 	 *  register-bound identifiers and the prototype chain of an object
84344 	 *  environment target object.
84345 	 */
84346 
84347 	parents = 0;  /* just check 'env' */
84348 	if (duk__get_identifier_reference(thr, env, name, NULL, parents, &ref)) {
84349 		duk_int_t e_idx;
84350 		duk_int_t h_idx;
84351 		duk_small_uint_t flags;
84352 
84353 		/*
84354 		 *  Variable already declared, ignore re-declaration.
84355 		 *  The only exception is the updated behavior of E5.1 for
84356 		 *  global function declarations, E5.1 Section 10.5, step 5.e.
84357 		 *  This behavior does not apply to global variable declarations.
84358 		 */
84359 
84360 		if (!(is_func_decl && env == thr->builtins[DUK_BIDX_GLOBAL_ENV])) {
84361 			DUK_DDD(DUK_DDDPRINT("re-declare a binding, ignoring"));
84362 			return 1;  /* 1 -> needs a PUTVAR */
84363 		}
84364 
84365 		/*
84366 		 *  Special behavior in E5.1.
84367 		 *
84368 		 *  Note that even though parents == 0, the conflicting property
84369 		 *  may be an inherited property (currently our global object's
84370 		 *  prototype is Object.prototype).  Step 5.e first operates on
84371 		 *  the existing property (which is potentially in an ancestor)
84372 		 *  and then defines a new property in the global object (and
84373 		 *  never modifies the ancestor).
84374 		 *
84375 		 *  Also note that this logic would become even more complicated
84376 		 *  if the conflicting property might be a virtual one.  Object
84377 		 *  prototype has no virtual properties, though.
84378 		 *
84379 		 *  XXX: this is now very awkward, rework.
84380 		 */
84381 
84382 		DUK_DDD(DUK_DDDPRINT("re-declare a function binding in global object, "
84383 		                     "updated E5.1 processing"));
84384 
84385 		DUK_ASSERT(ref.holder != NULL);
84386 		holder = ref.holder;
84387 
84388 		/* holder will be set to the target object, not the actual object
84389 		 * where the property was found (see duk__get_identifier_reference()).
84390 		 */
84391 		DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(holder) == DUK_HOBJECT_CLASS_GLOBAL);
84392 		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(holder));  /* global object doesn't have array part */
84393 
84394 		/* XXX: use a helper for prototype traversal; no loop check here */
84395 		/* must be found: was found earlier, and cannot be inherited */
84396 		for (;;) {
84397 			DUK_ASSERT(holder != NULL);
84398 			if (duk_hobject_find_entry(thr->heap, holder, name, &e_idx, &h_idx)) {
84399 				DUK_ASSERT(e_idx >= 0);
84400 				break;
84401 			}
84402 			/* SCANBUILD: NULL pointer dereference, doesn't actually trigger,
84403 			 * asserted above.
84404 			 */
84405 			holder = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, holder);
84406 		}
84407 		DUK_ASSERT(holder != NULL);
84408 		DUK_ASSERT(e_idx >= 0);
84409 		/* SCANBUILD: scan-build produces a NULL pointer dereference warning
84410 		 * below; it never actually triggers because holder is actually never
84411 		 * NULL.
84412 		 */
84413 
84414 		/* ref.holder is global object, holder is the object with the
84415 		 * conflicting property.
84416 		 */
84417 
84418 		flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, holder, e_idx);
84419 		if (!(flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
84420 			if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
84421 				DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
84422 				                     "accessor -> reject"));
84423 				goto fail_existing_attributes;
84424 			}
84425 			if (!((flags & DUK_PROPDESC_FLAG_WRITABLE) &&
84426 			      (flags & DUK_PROPDESC_FLAG_ENUMERABLE))) {
84427 				DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
84428 				                     "plain property which is not writable and "
84429 				                     "enumerable -> reject"));
84430 				goto fail_existing_attributes;
84431 			}
84432 
84433 			DUK_DDD(DUK_DDDPRINT("existing property is not configurable but "
84434 			                     "is plain, enumerable, and writable -> "
84435 			                     "allow redeclaration"));
84436 		}
84437 
84438 		if (holder == ref.holder) {
84439 			/* XXX: if duk_hobject_define_property_internal() was updated
84440 			 * to handle a pre-existing accessor property, this would be
84441 			 * a simple call (like for the ancestor case).
84442 			 */
84443 			DUK_DDD(DUK_DDDPRINT("redefine, offending property in global object itself"));
84444 
84445 			if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
84446 				duk_hobject *tmp;
84447 
84448 				tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, holder, e_idx);
84449 				DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, holder, e_idx, NULL);
84450 				DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
84451 				DUK_UNREF(tmp);
84452 				tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, holder, e_idx);
84453 				DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, holder, e_idx, NULL);
84454 				DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
84455 				DUK_UNREF(tmp);
84456 			} else {
84457 				tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
84458 				DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);
84459 			}
84460 
84461 			/* Here val would be potentially invalid if we didn't make
84462 			 * a value copy at the caller.
84463 			 */
84464 
84465 			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
84466 			DUK_TVAL_SET_TVAL(tv, val);
84467 			DUK_TVAL_INCREF(thr, tv);
84468 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, holder, e_idx, prop_flags);
84469 
84470 			DUK_DDD(DUK_DDDPRINT("updated global binding, final result: "
84471 			                     "value -> %!T, prop_flags=0x%08lx",
84472 			                     (duk_tval *) DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx),
84473 			                     (unsigned long) prop_flags));
84474 		} else {
84475 			DUK_DDD(DUK_DDDPRINT("redefine, offending property in ancestor"));
84476 
84477 			DUK_ASSERT(ref.holder == thr->builtins[DUK_BIDX_GLOBAL]);
84478 			duk_push_tval(thr, val);
84479 			duk_hobject_define_property_internal(thr, ref.holder, name, prop_flags);
84480 		}
84481 
84482 		return 0;
84483 	}
84484 
84485 	/*
84486 	 *  Not found (in registers or record objects).  Declare
84487 	 *  to current variable environment.
84488 	 */
84489 
84490 	/*
84491 	 *  Get holder object
84492 	 */
84493 
84494 	if (DUK_HOBJECT_IS_DECENV(env)) {
84495 		DUK_HDECENV_ASSERT_VALID((duk_hdecenv *) env);
84496 		holder = env;
84497 	} else {
84498 		DUK_HOBJENV_ASSERT_VALID((duk_hobjenv *) env);
84499 		holder = ((duk_hobjenv *) env)->target;
84500 		DUK_ASSERT(holder != NULL);
84501 	}
84502 
84503 	/*
84504 	 *  Define new property
84505 	 *
84506 	 *  Note: this may fail if the holder is not extensible.
84507 	 */
84508 
84509 	/* XXX: this is awkward as we use an internal method which doesn't handle
84510 	 * extensibility etc correctly.  Basically we'd want to do a [[DefineOwnProperty]]
84511 	 * or Object.defineProperty() here.
84512 	 */
84513 
84514 	if (!DUK_HOBJECT_HAS_EXTENSIBLE(holder)) {
84515 		goto fail_not_extensible;
84516 	}
84517 
84518 	duk_push_hobject(thr, holder);
84519 	duk_push_hstring(thr, name);
84520 	duk_push_tval(thr, val);
84521 	duk_xdef_prop(thr, -3, prop_flags);  /* [holder name val] -> [holder] */
84522 	duk_pop_unsafe(thr);
84523 
84524 	return 0;
84525 
84526  fail_existing_attributes:
84527  fail_not_extensible:
84528 	DUK_ERROR_TYPE(thr, "declaration failed");
84529 	DUK_WO_NORETURN(return 0;);
84530 }
84531 
84532 DUK_INTERNAL
84533 duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
84534                                      duk_activation *act,
84535                                      duk_hstring *name,
84536                                      duk_tval *val,
84537                                      duk_small_uint_t prop_flags,
84538                                      duk_bool_t is_func_decl) {
84539 	duk_hobject *env;
84540 	duk_tval tv_val_copy;
84541 
84542 	DUK_ASSERT(act != NULL);
84543 
84544 	/*
84545 	 *  Make a value copy of the input val.  This ensures that
84546 	 *  side effects cannot invalidate the pointer.
84547 	 */
84548 
84549 	DUK_TVAL_SET_TVAL(&tv_val_copy, val);
84550 	val = &tv_val_copy;
84551 
84552 	/*
84553 	 *  Delayed env creation check
84554 	 */
84555 
84556 	if (!act->var_env) {
84557 		DUK_ASSERT(act->lex_env == NULL);
84558 		duk_js_init_activation_environment_records_delayed(thr, act);
84559 		/* 'act' is a stable pointer, so still OK. */
84560 	}
84561 	DUK_ASSERT(act->lex_env != NULL);
84562 	DUK_ASSERT(act->var_env != NULL);
84563 
84564 	env = act->var_env;
84565 	DUK_ASSERT(env != NULL);
84566 	DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
84567 
84568 	return duk__declvar_helper(thr, env, name, val, prop_flags, is_func_decl);
84569 }
84570 #line 1 "duk_lexer.c"
84571 /*
84572  *  Lexer for source files, ToNumber() string conversions, RegExp expressions,
84573  *  and JSON.
84574  *
84575  *  Provides a stream of ECMAScript tokens from an UTF-8/CESU-8 buffer.  The
84576  *  caller can also rewind the token stream into a certain position which is
84577  *  needed by the compiler part for multi-pass scanning.  Tokens are
84578  *  represented as duk_token structures, and contain line number information.
84579  *  Token types are identified with DUK_TOK_* defines.
84580  *
84581  *  Characters are decoded into a fixed size lookup window consisting of
84582  *  decoded Unicode code points, with window positions past the end of the
84583  *  input filled with an invalid codepoint (-1).  The tokenizer can thus
84584  *  perform multiple character lookups efficiently and with few sanity
84585  *  checks (such as access outside the end of the input), which keeps the
84586  *  tokenization code small at the cost of performance.
84587  *
84588  *  Character data in tokens, such as identifier names and string literals,
84589  *  is encoded into CESU-8 format on-the-fly while parsing the token in
84590  *  question.  The string data is made reachable to garbage collection by
84591  *  placing the token-related values in value stack entries allocated for
84592  *  this purpose by the caller.  The characters exist in Unicode code point
84593  *  form only in the fixed size lookup window, which keeps character data
84594  *  expansion (of especially ASCII data) low.
84595  *
84596  *  Token parsing supports the full range of Unicode characters as described
84597  *  in the E5 specification.  Parsing has been optimized for ASCII characters
84598  *  because ordinary ECMAScript code consists almost entirely of ASCII
84599  *  characters.  Matching of complex Unicode codepoint sets (such as in the
84600  *  IdentifierStart and IdentifierPart productions) is optimized for size,
84601  *  and is done using a linear scan of a bit-packed list of ranges.  This is
84602  *  very slow, but should never be entered unless the source code actually
84603  *  contains Unicode characters.
84604  *
84605  *  ECMAScript tokenization is partially context sensitive.  First,
84606  *  additional future reserved words are recognized in strict mode (see E5
84607  *  Section 7.6.1.2).  Second, a forward slash character ('/') can be
84608  *  recognized either as starting a RegExp literal or as a division operator,
84609  *  depending on context.  The caller must provide necessary context flags
84610  *  when requesting a new token.
84611  *
84612  *  Future work:
84613  *
84614  *    * Make line number tracking optional, as it consumes space.
84615  *
84616  *    * Add a feature flag for disabling UTF-8 decoding of input, as most
84617  *      source code is ASCII.  Because of Unicode escapes written in ASCII,
84618  *      this does not allow Unicode support to be removed from e.g.
84619  *      duk_unicode_is_identifier_start() nor does it allow removal of CESU-8
84620  *      encoding of e.g. string literals.
84621  *
84622  *    * Add a feature flag for disabling Unicode compliance of e.g. identifier
84623  *      names.  This allows for a build more than a kilobyte smaller, because
84624  *      Unicode ranges needed by duk_unicode_is_identifier_start() and
84625  *      duk_unicode_is_identifier_part() can be dropped.  String literals
84626  *      should still be allowed to contain escaped Unicode, so this still does
84627  *      not allow removal of CESU-8 encoding of e.g. string literals.
84628  *
84629  *    * Character lookup tables for codepoints above BMP could be stripped.
84630  *
84631  *    * Strictly speaking, E5 specification requires that source code consists
84632  *      of 16-bit code units, and if not, must be conceptually converted to
84633  *      that format first.  The current lexer processes Unicode code points
84634  *      and allows characters outside the BMP.  These should be converted to
84635  *      surrogate pairs while reading the source characters into the window,
84636  *      not after tokens have been formed (as is done now).  However, the fix
84637  *      is not trivial because two characters are decoded from one codepoint.
84638  *
84639  *    * Optimize for speed as well as size.  Large if-else ladders are (at
84640  *      least potentially) slow.
84641  */
84642 
84643 /* #include duk_internal.h -> already included */
84644 
84645 /*
84646  *  Various defines and file specific helper macros
84647  */
84648 
84649 #define DUK__MAX_RE_DECESC_DIGITS     9
84650 #define DUK__MAX_RE_QUANT_DIGITS      9   /* Does not allow e.g. 2**31-1, but one more would allow overflows of u32. */
84651 
84652 /* whether to use macros or helper function depends on call count */
84653 #define DUK__ISDIGIT(x)          ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_9)
84654 #define DUK__ISHEXDIGIT(x)       duk__is_hex_digit((x))
84655 #define DUK__ISOCTDIGIT(x)       ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_7)
84656 #define DUK__ISDIGIT03(x)        ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_3)
84657 #define DUK__ISDIGIT47(x)        ((x) >= DUK_ASC_4 && (x) <= DUK_ASC_7)
84658 
84659 /* lexer character window helpers */
84660 #define DUK__LOOKUP(lex_ctx,idx)            ((lex_ctx)->window[(idx)].codepoint)
84661 #define DUK__ADVANCECHARS(lex_ctx,count)    duk__advance_chars((lex_ctx), (count))
84662 #define DUK__ADVANCEBYTES(lex_ctx,count)    duk__advance_bytes((lex_ctx), (count))
84663 #define DUK__INITBUFFER(lex_ctx)            duk__initbuffer((lex_ctx))
84664 #define DUK__APPENDBUFFER(lex_ctx,x)        duk__appendbuffer((lex_ctx), (duk_codepoint_t) (x))
84665 #define DUK__APPENDBUFFER_ASCII(lex_ctx,x)  duk__appendbuffer_ascii((lex_ctx), (duk_codepoint_t) (x))
84666 
84667 /* lookup shorthands (note: assume context variable is named 'lex_ctx') */
84668 #define DUK__L0()  DUK__LOOKUP(lex_ctx, 0)
84669 #define DUK__L1()  DUK__LOOKUP(lex_ctx, 1)
84670 #define DUK__L2()  DUK__LOOKUP(lex_ctx, 2)
84671 #define DUK__L3()  DUK__LOOKUP(lex_ctx, 3)
84672 #define DUK__L4()  DUK__LOOKUP(lex_ctx, 4)
84673 #define DUK__L5()  DUK__LOOKUP(lex_ctx, 5)
84674 
84675 /* packed advance/token number macro used by multiple functions */
84676 #define DUK__ADVTOK(advbytes,tok)  ((((advbytes) * sizeof(duk_lexer_codepoint)) << 8) + (tok))
84677 
84678 /*
84679  *  Advance lookup window by N characters, filling in new characters as
84680  *  necessary.  After returning caller is guaranteed a character window of
84681  *  at least DUK_LEXER_WINDOW_SIZE characters.
84682  *
84683  *  The main function duk__advance_bytes() is called at least once per every
84684  *  token so it has a major lexer/compiler performance impact.  There are two
84685  *  variants for the main duk__advance_bytes() algorithm: a sliding window
84686  *  approach which is slightly faster at the cost of larger code footprint,
84687  *  and a simple copying one.
84688  *
84689  *  Decoding directly from the source string would be another lexing option.
84690  *  But the lookup window based approach has the advantage of hiding the
84691  *  source string and its encoding effectively which gives more flexibility
84692  *  going forward to e.g. support chunked streaming of source from flash.
84693  *
84694  *  Decodes UTF-8/CESU-8 leniently with support for code points from U+0000 to
84695  *  U+10FFFF, causing an error if the input is unparseable.  Leniency means:
84696  *
84697  *    * Unicode code point validation is intentionally not performed,
84698  *      except to check that the codepoint does not exceed 0x10ffff.
84699  *
84700  *    * In particular, surrogate pairs are allowed and not combined, which
84701  *      allows source files to represent all SourceCharacters with CESU-8.
84702  *      Broken surrogate pairs are allowed, as ECMAScript does not mandate
84703  *      their validation.
84704  *
84705  *    * Allow non-shortest UTF-8 encodings.
84706  *
84707  *  Leniency here causes few security concerns because all character data is
84708  *  decoded into Unicode codepoints before lexer processing, and is then
84709  *  re-encoded into CESU-8.  The source can be parsed as strict UTF-8 with
84710  *  a compiler option.  However, ECMAScript source characters include -all-
84711  *  16-bit unsigned integer codepoints, so leniency seems to be appropriate.
84712  *
84713  *  Note that codepoints above the BMP are not strictly SourceCharacters,
84714  *  but the lexer still accepts them as such.  Before ending up in a string
84715  *  or an identifier name, codepoints above BMP are converted into surrogate
84716  *  pairs and then CESU-8 encoded, resulting in 16-bit Unicode data as
84717  *  expected by ECMAScript.
84718  *
84719  *  An alternative approach to dealing with invalid or partial sequences
84720  *  would be to skip them and replace them with e.g. the Unicode replacement
84721  *  character U+FFFD.  This has limited utility because a replacement character
84722  *  will most likely cause a parse error, unless it occurs inside a string.
84723  *  Further, ECMAScript source is typically pure ASCII.
84724  *
84725  *  See:
84726  *
84727  *     http://en.wikipedia.org/wiki/UTF-8
84728  *     http://en.wikipedia.org/wiki/CESU-8
84729  *     http://tools.ietf.org/html/rfc3629
84730  *     http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
84731  *
84732  *  Future work:
84733  *
84734  *    * Reject other invalid Unicode sequences (see Wikipedia entry for examples)
84735  *      in strict UTF-8 mode.
84736  *
84737  *    * Size optimize.  An attempt to use a 16-byte lookup table for the first
84738  *      byte resulted in a code increase though.
84739  *
84740  *    * Is checking against maximum 0x10ffff really useful?  4-byte encoding
84741  *      imposes a certain limit anyway.
84742  *
84743  *    * Support chunked streaming of source code.  Can be implemented either
84744  *      by streaming chunks of bytes or chunks of codepoints.
84745  */
84746 
84747 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
84748 DUK_LOCAL void duk__fill_lexer_buffer(duk_lexer_ctx *lex_ctx, duk_small_uint_t start_offset_bytes) {
84749 	duk_lexer_codepoint *cp, *cp_end;
84750 	duk_ucodepoint_t x;
84751 	duk_small_uint_t contlen;
84752 	const duk_uint8_t *p, *p_end;
84753 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
84754 	duk_ucodepoint_t mincp;
84755 #endif
84756 	duk_int_t input_line;
84757 
84758 	/* Use temporaries and update lex_ctx only when finished. */
84759 	input_line = lex_ctx->input_line;
84760 	p = lex_ctx->input + lex_ctx->input_offset;
84761 	p_end = lex_ctx->input + lex_ctx->input_length;
84762 
84763 	cp = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->buffer + start_offset_bytes);
84764 	cp_end = lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE;
84765 
84766 	for (; cp != cp_end; cp++) {
84767 		cp->offset = (duk_size_t) (p - lex_ctx->input);
84768 		cp->line = input_line;
84769 
84770 		/* XXX: potential issue with signed pointers, p_end < p. */
84771 		if (DUK_UNLIKELY(p >= p_end)) {
84772 			/* If input_offset were assigned a negative value, it would
84773 			 * result in a large positive value.  Most likely it would be
84774 			 * larger than input_length and be caught here.  In any case
84775 			 * no memory unsafe behavior would happen.
84776 			 */
84777 			cp->codepoint = -1;
84778 			continue;
84779 		}
84780 
84781 		x = (duk_ucodepoint_t) (*p++);
84782 
84783 		/* Fast path. */
84784 
84785 		if (DUK_LIKELY(x < 0x80UL)) {
84786 			DUK_ASSERT(x != 0x2028UL && x != 0x2029UL);  /* not LS/PS */
84787 			if (DUK_UNLIKELY(x <= 0x000dUL)) {
84788 				if ((x == 0x000aUL) ||
84789 				    ((x == 0x000dUL) && (p >= p_end || *p != 0x000aUL))) {
84790 					/* lookup for 0x000a above assumes shortest encoding now */
84791 
84792 					/* E5 Section 7.3, treat the following as newlines:
84793 					 *   LF
84794 					 *   CR [not followed by LF]
84795 					 *   LS
84796 					 *   PS
84797 					 *
84798 					 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
84799 					 * the line number.
84800 					 */
84801 					input_line++;
84802 				}
84803 			}
84804 
84805 			cp->codepoint = (duk_codepoint_t) x;
84806 			continue;
84807 		}
84808 
84809 		/* Slow path. */
84810 
84811 		if (x < 0xc0UL) {
84812 			/* 10xx xxxx -> invalid */
84813 			goto error_encoding;
84814 		} else if (x < 0xe0UL) {
84815 			/* 110x xxxx   10xx xxxx  */
84816 			contlen = 1;
84817 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
84818 			mincp = 0x80UL;
84819 #endif
84820 			x = x & 0x1fUL;
84821 		} else if (x < 0xf0UL) {
84822 			/* 1110 xxxx   10xx xxxx   10xx xxxx */
84823 			contlen = 2;
84824 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
84825 			mincp = 0x800UL;
84826 #endif
84827 			x = x & 0x0fUL;
84828 		} else if (x < 0xf8UL) {
84829 			/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx */
84830 			contlen = 3;
84831 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
84832 			mincp = 0x10000UL;
84833 #endif
84834 			x = x & 0x07UL;
84835 		} else {
84836 			/* no point in supporting encodings of 5 or more bytes */
84837 			goto error_encoding;
84838 		}
84839 
84840 		DUK_ASSERT(p_end >= p);
84841 		if ((duk_size_t) contlen > (duk_size_t) (p_end - p)) {
84842 			goto error_clipped;
84843 		}
84844 
84845 		while (contlen > 0) {
84846 			duk_small_uint_t y;
84847 			y = *p++;
84848 			if ((y & 0xc0U) != 0x80U) {
84849 				/* check that byte has the form 10xx xxxx */
84850 				goto error_encoding;
84851 			}
84852 			x = x << 6;
84853 			x += y & 0x3fUL;
84854 			contlen--;
84855 		}
84856 
84857 		/* check final character validity */
84858 
84859 		if (x > 0x10ffffUL) {
84860 			goto error_encoding;
84861 		}
84862 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
84863 		if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
84864 			goto error_encoding;
84865 		}
84866 #endif
84867 
84868 		DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
84869 		if ((x == 0x2028UL) || (x == 0x2029UL)) {
84870 			input_line++;
84871 		}
84872 
84873 		cp->codepoint = (duk_codepoint_t) x;
84874 	}
84875 
84876 	lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
84877 	lex_ctx->input_line = input_line;
84878 	return;
84879 
84880  error_clipped:   /* clipped codepoint */
84881  error_encoding:  /* invalid codepoint encoding or codepoint */
84882 	lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
84883 	lex_ctx->input_line = input_line;
84884 
84885 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_SOURCE_DECODE_FAILED);
84886 	DUK_WO_NORETURN(return;);
84887 }
84888 
84889 DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
84890 	duk_small_uint_t used_bytes, avail_bytes;
84891 
84892 	DUK_ASSERT_DISABLE(count_bytes >= 0);  /* unsigned */
84893 	DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));
84894 	DUK_ASSERT(lex_ctx->window >= lex_ctx->buffer);
84895 	DUK_ASSERT(lex_ctx->window < lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE);
84896 	DUK_ASSERT((duk_uint8_t *) lex_ctx->window + count_bytes <= (duk_uint8_t *) lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint));
84897 
84898 	/* Zero 'count' is also allowed to make call sites easier.
84899 	 * Arithmetic in bytes generates better code in GCC.
84900 	 */
84901 
84902 	lex_ctx->window = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->window + count_bytes);  /* avoid multiply */
84903 	used_bytes = (duk_small_uint_t) ((duk_uint8_t *) lex_ctx->window - (duk_uint8_t *) lex_ctx->buffer);
84904 	avail_bytes = DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint) - used_bytes;
84905 	if (avail_bytes < (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint))) {
84906 		/* Not enough data to provide a full window, so "scroll" window to
84907 		 * start of buffer and fill up the rest.
84908 		 */
84909 		duk_memmove((void *) lex_ctx->buffer,
84910 		            (const void *) lex_ctx->window,
84911 		            (size_t) avail_bytes);
84912 		lex_ctx->window = lex_ctx->buffer;
84913 		duk__fill_lexer_buffer(lex_ctx, avail_bytes);
84914 	}
84915 }
84916 
84917 DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {
84918 	lex_ctx->window = lex_ctx->buffer;
84919 	duk__fill_lexer_buffer(lex_ctx, 0);
84920 }
84921 #else  /* DUK_USE_LEXER_SLIDING_WINDOW */
84922 DUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) {
84923 	duk_ucodepoint_t x;
84924 	duk_small_uint_t len;
84925 	duk_small_uint_t i;
84926 	const duk_uint8_t *p;
84927 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
84928 	duk_ucodepoint_t mincp;
84929 #endif
84930 	duk_size_t input_offset;
84931 
84932 	input_offset = lex_ctx->input_offset;
84933 	if (DUK_UNLIKELY(input_offset >= lex_ctx->input_length)) {
84934 		/* If input_offset were assigned a negative value, it would
84935 		 * result in a large positive value.  Most likely it would be
84936 		 * larger than input_length and be caught here.  In any case
84937 		 * no memory unsafe behavior would happen.
84938 		 */
84939 		return -1;
84940 	}
84941 
84942 	p = lex_ctx->input + input_offset;
84943 	x = (duk_ucodepoint_t) (*p);
84944 
84945 	if (DUK_LIKELY(x < 0x80UL)) {
84946 		/* 0xxx xxxx -> fast path */
84947 
84948 		/* input offset tracking */
84949 		lex_ctx->input_offset++;
84950 
84951 		DUK_ASSERT(x != 0x2028UL && x != 0x2029UL);  /* not LS/PS */
84952 		if (DUK_UNLIKELY(x <= 0x000dUL)) {
84953 			if ((x == 0x000aUL) ||
84954 			    ((x == 0x000dUL) && (lex_ctx->input_offset >= lex_ctx->input_length ||
84955 			                         lex_ctx->input[lex_ctx->input_offset] != 0x000aUL))) {
84956 				/* lookup for 0x000a above assumes shortest encoding now */
84957 
84958 				/* E5 Section 7.3, treat the following as newlines:
84959 				 *   LF
84960 				 *   CR [not followed by LF]
84961 				 *   LS
84962 				 *   PS
84963 				 *
84964 				 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
84965 				 * the line number.
84966 				 */
84967 				lex_ctx->input_line++;
84968 			}
84969 		}
84970 
84971 		return (duk_codepoint_t) x;
84972 	}
84973 
84974 	/* Slow path. */
84975 
84976 	if (x < 0xc0UL) {
84977 		/* 10xx xxxx -> invalid */
84978 		goto error_encoding;
84979 	} else if (x < 0xe0UL) {
84980 		/* 110x xxxx   10xx xxxx  */
84981 		len = 2;
84982 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
84983 		mincp = 0x80UL;
84984 #endif
84985 		x = x & 0x1fUL;
84986 	} else if (x < 0xf0UL) {
84987 		/* 1110 xxxx   10xx xxxx   10xx xxxx */
84988 		len = 3;
84989 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
84990 		mincp = 0x800UL;
84991 #endif
84992 		x = x & 0x0fUL;
84993 	} else if (x < 0xf8UL) {
84994 		/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx */
84995 		len = 4;
84996 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
84997 		mincp = 0x10000UL;
84998 #endif
84999 		x = x & 0x07UL;
85000 	} else {
85001 		/* no point in supporting encodings of 5 or more bytes */
85002 		goto error_encoding;
85003 	}
85004 
85005 	DUK_ASSERT(lex_ctx->input_length >= lex_ctx->input_offset);
85006 	if ((duk_size_t) len > (duk_size_t) (lex_ctx->input_length - lex_ctx->input_offset)) {
85007 		goto error_clipped;
85008 	}
85009 
85010 	p++;
85011 	for (i = 1; i < len; i++) {
85012 		duk_small_uint_t y;
85013 		y = *p++;
85014 		if ((y & 0xc0U) != 0x80U) {
85015 			/* check that byte has the form 10xx xxxx */
85016 			goto error_encoding;
85017 		}
85018 		x = x << 6;
85019 		x += y & 0x3fUL;
85020 	}
85021 
85022 	/* check final character validity */
85023 
85024 	if (x > 0x10ffffUL) {
85025 		goto error_encoding;
85026 	}
85027 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
85028 	if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
85029 		goto error_encoding;
85030 	}
85031 #endif
85032 
85033 	/* input offset tracking */
85034 	lex_ctx->input_offset += len;
85035 
85036 	/* line tracking */
85037 	DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
85038 	if ((x == 0x2028UL) || (x == 0x2029UL)) {
85039 		lex_ctx->input_line++;
85040 	}
85041 
85042 	return (duk_codepoint_t) x;
85043 
85044  error_clipped:   /* clipped codepoint */
85045  error_encoding:  /* invalid codepoint encoding or codepoint */
85046 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_SOURCE_DECODE_FAILED);
85047 	DUK_WO_NORETURN(return 0;);
85048 }
85049 
85050 DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
85051 	duk_small_uint_t keep_bytes;
85052 	duk_lexer_codepoint *cp, *cp_end;
85053 
85054 	DUK_ASSERT_DISABLE(count_bytes >= 0);  /* unsigned */
85055 	DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));
85056 
85057 	/* Zero 'count' is also allowed to make call sites easier. */
85058 
85059 	keep_bytes = DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint) - count_bytes;
85060 	duk_memmove((void *) lex_ctx->window,
85061 	            (const void *) ((duk_uint8_t *) lex_ctx->window + count_bytes),
85062 	            (size_t) keep_bytes);
85063 
85064 	cp = (duk_lexer_codepoint *) ((duk_uint8_t *) lex_ctx->window + keep_bytes);
85065 	cp_end = lex_ctx->window + DUK_LEXER_WINDOW_SIZE;
85066 	for (; cp != cp_end; cp++) {
85067 		cp->offset = lex_ctx->input_offset;
85068 		cp->line = lex_ctx->input_line;
85069 		cp->codepoint = duk__read_char(lex_ctx);
85070 	}
85071 }
85072 
85073 DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {
85074 	/* Call with count == DUK_LEXER_WINDOW_SIZE to fill buffer initially. */
85075 	duk__advance_bytes(lex_ctx, DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint));  /* fill window */
85076 }
85077 #endif  /* DUK_USE_LEXER_SLIDING_WINDOW */
85078 
85079 DUK_LOCAL void duk__advance_chars(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_chars) {
85080 	duk__advance_bytes(lex_ctx, count_chars * sizeof(duk_lexer_codepoint));
85081 }
85082 
85083 /*
85084  *  (Re)initialize the temporary byte buffer.  May be called extra times
85085  *  with little impact.
85086  */
85087 
85088 DUK_LOCAL void duk__initbuffer(duk_lexer_ctx *lex_ctx) {
85089 	/* Reuse buffer as is unless buffer has grown large. */
85090 	if (DUK_HBUFFER_DYNAMIC_GET_SIZE(lex_ctx->buf) < DUK_LEXER_TEMP_BUF_LIMIT) {
85091 		/* Keep current size */
85092 	} else {
85093 		duk_hbuffer_resize(lex_ctx->thr, lex_ctx->buf, DUK_LEXER_TEMP_BUF_LIMIT);
85094 	}
85095 
85096 	DUK_BW_INIT_WITHBUF(lex_ctx->thr, &lex_ctx->bw, lex_ctx->buf);
85097 }
85098 
85099 /*
85100  *  Append a Unicode codepoint to the temporary byte buffer.  Performs
85101  *  CESU-8 surrogate pair encoding for codepoints above the BMP.
85102  *  Existing surrogate pairs are allowed and also encoded into CESU-8.
85103  */
85104 
85105 DUK_LOCAL void duk__appendbuffer(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
85106 	/*
85107 	 *  Since character data is only generated by decoding the source or by
85108 	 *  the compiler itself, we rely on the input codepoints being correct
85109 	 *  and avoid a check here.
85110 	 *
85111 	 *  Character data can also come here through decoding of Unicode
85112 	 *  escapes ("\udead\ubeef") so all 16-but unsigned values can be
85113 	 *  present, even when the source file itself is strict UTF-8.
85114 	 */
85115 	DUK_ASSERT(x >= 0 && x <= 0x10ffffL);
85116 
85117 	DUK_BW_WRITE_ENSURE_CESU8(lex_ctx->thr, &lex_ctx->bw, (duk_ucodepoint_t) x);
85118 }
85119 
85120 DUK_LOCAL void duk__appendbuffer_ascii(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
85121 	/* ASCII characters can be emitted as a single byte without encoding
85122 	 * which matters for some fast paths.
85123 	 */
85124 	DUK_ASSERT(x >= 0 && x <= 0x7f);
85125 
85126 	DUK_BW_WRITE_ENSURE_U8(lex_ctx->thr, &lex_ctx->bw, (duk_uint8_t) x);
85127 }
85128 
85129 /*
85130  *  Intern the temporary byte buffer into a valstack slot
85131  *  (in practice, slot1 or slot2).
85132  */
85133 
85134 DUK_LOCAL duk_hstring *duk__internbuffer(duk_lexer_ctx *lex_ctx, duk_idx_t valstack_idx) {
85135 	DUK_ASSERT(valstack_idx == lex_ctx->slot1_idx || valstack_idx == lex_ctx->slot2_idx);
85136 
85137 	DUK_BW_PUSH_AS_STRING(lex_ctx->thr, &lex_ctx->bw);
85138 	duk_replace(lex_ctx->thr, valstack_idx);
85139 	return duk_known_hstring(lex_ctx->thr, valstack_idx);
85140 }
85141 
85142 /*
85143  *  Init lexer context
85144  */
85145 
85146 DUK_INTERNAL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx) {
85147 	DUK_ASSERT(lex_ctx != NULL);
85148 
85149 	duk_memzero(lex_ctx, sizeof(*lex_ctx));
85150 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
85151 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
85152 	lex_ctx->window = NULL;
85153 #endif
85154 	lex_ctx->thr = NULL;
85155 	lex_ctx->input = NULL;
85156 	lex_ctx->buf = NULL;
85157 #endif
85158 }
85159 
85160 /*
85161  *  Set lexer input position and reinitialize lookup window.
85162  */
85163 
85164 DUK_INTERNAL void duk_lexer_getpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {
85165 	pt->offset = lex_ctx->window[0].offset;
85166 	pt->line = lex_ctx->window[0].line;
85167 }
85168 
85169 DUK_INTERNAL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {
85170 	DUK_ASSERT_DISABLE(pt->offset >= 0);  /* unsigned */
85171 	DUK_ASSERT(pt->line >= 1);
85172 	lex_ctx->input_offset = pt->offset;
85173 	lex_ctx->input_line = pt->line;
85174 	duk__init_lexer_window(lex_ctx);
85175 }
85176 
85177 /*
85178  *  Lexing helpers
85179  */
85180 
85181 /* Numeric value of a hex digit (also covers octal and decimal digits) or
85182  * -1 if not a valid hex digit.
85183  */
85184 DUK_LOCAL duk_codepoint_t duk__hexval_validate(duk_codepoint_t x) {
85185 	duk_small_int_t t;
85186 
85187 	/* Here 'x' is a Unicode codepoint */
85188 	if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
85189 		t = duk_hex_dectab[x];
85190 		if (DUK_LIKELY(t >= 0)) {
85191 			return t;
85192 		}
85193 	}
85194 
85195 	return -1;
85196 }
85197 
85198 /* Just a wrapper for call sites where 'x' is known to be valid so
85199  * we assert for it before decoding.
85200  */
85201 DUK_LOCAL duk_codepoint_t duk__hexval(duk_codepoint_t x) {
85202 	duk_codepoint_t ret;
85203 
85204 	DUK_ASSERT((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
85205 	           (x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_F) ||
85206 	           (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_F));
85207 	ret = duk__hexval_validate(x);
85208 	DUK_ASSERT(ret >= 0 && ret <= 15);
85209 	return ret;
85210 }
85211 
85212 /* having this as a separate function provided a size benefit */
85213 DUK_LOCAL duk_bool_t duk__is_hex_digit(duk_codepoint_t x) {
85214 	if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
85215 		return (duk_hex_dectab[x] >= 0);
85216 	}
85217 	return 0;
85218 }
85219 
85220 /* Parse a Unicode escape of the form \xHH, \uHHHH, or \u{H+}.  Shared by
85221  * source and RegExp parsing.
85222  */
85223 DUK_LOCAL duk_codepoint_t duk__lexer_parse_escape(duk_lexer_ctx *lex_ctx, duk_bool_t allow_es6) {
85224 	duk_small_int_t digits;  /* Initial value 2 or 4 for fixed length escapes, 0 for ES2015 \u{H+}. */
85225 	duk_codepoint_t escval;
85226 	duk_codepoint_t x;
85227 	duk_small_uint_t adv;
85228 
85229 	DUK_ASSERT(DUK__L0() == DUK_ASC_BACKSLASH);  /* caller responsibilities */
85230 	DUK_ASSERT(DUK__L1() == DUK_ASC_LC_X || DUK__L1() == DUK_ASC_LC_U);
85231 	DUK_UNREF(allow_es6);
85232 
85233 	adv = 2;
85234 	digits = 2;
85235 	if (DUK__L1() == DUK_ASC_LC_U) {
85236 		digits = 4;
85237 #if defined(DUK_USE_ES6_UNICODE_ESCAPE)
85238 		if (DUK__L2() == DUK_ASC_LCURLY && allow_es6) {
85239 			digits = 0;
85240 			adv = 3;
85241 		}
85242 #endif
85243 	}
85244 	DUK__ADVANCECHARS(lex_ctx, adv);
85245 
85246 	escval = 0;
85247 	for (;;) {
85248 		/* One of the escape forms: \xHH, \uHHHH, \u{H+}.
85249 		 * The 'digits' variable tracks parsing state and is
85250 		 * initialized to:
85251 		 *
85252 		 *   \xHH     2
85253 		 *   \uHH     4
85254 		 *   \u{H+}   0 first time, updated to -1 to indicate
85255 		 *            at least one digit has been parsed
85256 		 *
85257 		 * Octal parsing is handled separately because it can be
85258 		 * done with fixed lookahead and also has validation
85259 		 * rules which depend on the escape length (which is
85260 		 * variable).
85261 		 *
85262 		 * We don't need a specific check for x < 0 (end of
85263 		 * input) or duk_unicode_is_line_terminator(x)
85264 		 * because the 'dig' decode will fail and lead to a
85265 		 * SyntaxError.
85266 		 */
85267 		duk_codepoint_t dig;
85268 
85269 		x = DUK__L0();
85270 		DUK__ADVANCECHARS(lex_ctx, 1);
85271 
85272 		dig = duk__hexval_validate(x);
85273 		if (digits > 0) {
85274 			digits--;
85275 			if (dig < 0) {
85276 				goto fail_escape;
85277 			}
85278 			DUK_ASSERT(dig >= 0x00 && dig <= 0x0f);
85279 			escval = (escval << 4) + dig;
85280 			if (digits == 0) {
85281 				DUK_ASSERT(escval >= 0 && escval <= 0xffffL);
85282 				break;
85283 			}
85284 		} else {
85285 #if defined(DUK_USE_ES6_UNICODE_ESCAPE)
85286 			DUK_ASSERT(digits == 0 /* first time */ || digits == -1 /* others */);
85287 			if (dig >= 0) {
85288 				DUK_ASSERT(dig >= 0x00 && dig <= 0x0f);
85289 				escval = (escval << 4) + dig;
85290 				if (escval > 0x10ffffL) {
85291 					goto fail_escape;
85292 				}
85293 			} else if (x == DUK_ASC_RCURLY) {
85294 				if (digits == 0) {
85295 					/* Empty escape, \u{}. */
85296 					goto fail_escape;
85297 				}
85298 				DUK_ASSERT(escval >= 0 && escval <= 0x10ffffL);
85299 				break;
85300 			} else {
85301 				goto fail_escape;
85302 			}
85303 			digits = -1;  /* Indicate we have at least one digit. */
85304 #else  /* DUK_USE_ES6_UNICODE_ESCAPE */
85305 			DUK_ASSERT(0);  /* Never happens if \u{H+} support disabled. */
85306 #endif  /* DUK_USE_ES6_UNICODE_ESCAPE */
85307 		}
85308 	}
85309 
85310 	return escval;
85311 
85312  fail_escape:
85313 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
85314 	DUK_WO_NORETURN(return 0;);
85315 }
85316 
85317 /* Parse legacy octal escape of the form \N{1,3}, e.g. \0, \5, \0377.  Maximum
85318  * allowed value is \0377 (U+00FF), longest match is used.  Used for both string
85319  * RegExp octal escape parsing.  Window[0] must be the slash '\' and the first
85320  * digit must already be validated to be in [0-9] by the caller.
85321  */
85322 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) {
85323 	duk_codepoint_t cp;
85324 	duk_small_uint_t lookup_idx;
85325 	duk_small_uint_t adv;
85326 	duk_codepoint_t tmp;
85327 
85328 	DUK_ASSERT(out_adv != NULL);
85329 	DUK_ASSERT(DUK__LOOKUP(lex_ctx, 0) == DUK_ASC_BACKSLASH);
85330 	DUK_ASSERT(DUK__LOOKUP(lex_ctx, 1) >= DUK_ASC_0 && DUK__LOOKUP(lex_ctx, 1) <= DUK_ASC_9);
85331 
85332 	cp = 0;
85333 	tmp = 0;
85334 	for (lookup_idx = 1; lookup_idx <= 3; lookup_idx++) {
85335 		DUK_DDD(DUK_DDDPRINT("lookup_idx=%ld, cp=%ld", (long) lookup_idx, (long) cp));
85336 		tmp = DUK__LOOKUP(lex_ctx, lookup_idx);
85337 		if (tmp < DUK_ASC_0 || tmp > DUK_ASC_7) {
85338 			/* No more valid digits. */
85339 			break;
85340 		}
85341 		tmp = (cp << 3) + (tmp - DUK_ASC_0);
85342 		if (tmp > 0xff) {
85343 			/* Three digit octal escapes above \377 (= 0xff)
85344 			 * are not allowed.
85345 			 */
85346 			break;
85347 		}
85348 		cp = tmp;
85349 	}
85350 	DUK_DDD(DUK_DDDPRINT("final lookup_idx=%ld, cp=%ld", (long) lookup_idx, (long) cp));
85351 
85352 	adv = lookup_idx;
85353 	if (lookup_idx == 1) {
85354 		DUK_DDD(DUK_DDDPRINT("\\8 or \\9 -> treat as literal, accept in strict mode too"));
85355 		DUK_ASSERT(tmp == DUK_ASC_8 || tmp == DUK_ASC_9);
85356 		cp = tmp;
85357 		adv++;  /* correction to above, eat offending character */
85358 	} else if (lookup_idx == 2 && cp == 0) {
85359 		/* Note: 'foo\0bar' is OK in strict mode, but 'foo\00bar' is not.
85360 		 * It won't be interpreted as 'foo\u{0}0bar' but as a SyntaxError.
85361 		 */
85362 		DUK_DDD(DUK_DDDPRINT("\\0 -> accept in strict mode too"));
85363 	} else {
85364 		/* This clause also handles non-shortest zero, e.g. \00. */
85365 		if (reject_annex_b) {
85366 			DUK_DDD(DUK_DDDPRINT("non-zero octal literal %ld -> reject in strict-mode", (long) cp));
85367 			cp = -1;
85368 		} else {
85369 			DUK_DDD(DUK_DDDPRINT("non-zero octal literal %ld -> accepted", (long) cp));
85370 			DUK_ASSERT(cp >= 0 && cp <= 0xff);
85371 		}
85372 	}
85373 
85374 	*out_adv = adv;
85375 
85376 	DUK_ASSERT((cp >= 0 && cp <= 0xff) || (cp == -1 && reject_annex_b));
85377 	return cp;
85378 }
85379 
85380 /* XXX: move strict mode to lex_ctx? */
85381 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) {
85382 	duk_small_uint_t adv;
85383 
85384 	for (adv = 1 /* initial quote */ ;;) {
85385 		duk_codepoint_t x;
85386 
85387 		DUK__ADVANCECHARS(lex_ctx, adv);  /* eat opening quote on first loop */
85388 		x = DUK__L0();
85389 
85390 		adv = 1;
85391 		if (x == quote) {
85392 			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat closing quote */
85393 			break;
85394 		} else if (x == '\\') {
85395 			/* DUK__L0        -> '\' char
85396 			 * DUK__L1 ... DUK__L5 -> more lookup
85397 			 */
85398 			duk_small_int_t emitcp = -1;
85399 
85400 			x = DUK__L1();
85401 
85402 			/* How much to advance before next loop. */
85403 			adv = 2;  /* note: long live range */
85404 
85405 			switch (x) {
85406 			case '\'':
85407 				emitcp = 0x0027;
85408 				break;
85409 			case '"':
85410 				emitcp = 0x0022;
85411 				break;
85412 			case '\\':
85413 				emitcp = 0x005c;
85414 				break;
85415 			case 'b':
85416 				emitcp = 0x0008;
85417 				break;
85418 			case 'f':
85419 				emitcp = 0x000c;
85420 				break;
85421 			case 'n':
85422 				emitcp = 0x000a;
85423 				break;
85424 			case 'r':
85425 				emitcp = 0x000d;
85426 				break;
85427 			case 't':
85428 				emitcp = 0x0009;
85429 				break;
85430 			case 'v':
85431 				emitcp = 0x000b;
85432 				break;
85433 			case 'x':
85434 			case 'u': {
85435 				duk_codepoint_t esc_cp;
85436 				esc_cp = duk__lexer_parse_escape(lex_ctx, 1 /*allow_es6*/);
85437 				DUK__APPENDBUFFER(lex_ctx, esc_cp);
85438 				adv = 0;
85439 				break;
85440 			}
85441 			default: {
85442 				if (duk_unicode_is_line_terminator(x)) {
85443 					/* line continuation */
85444 					if (x == 0x000d && DUK__L2() == 0x000a) {
85445 						/* CR LF again a special case */
85446 						adv = 3;  /* line terminator, CR, LF */
85447 					}
85448 				} else if (DUK__ISDIGIT(x)) {
85449 					/*
85450 					 *  Octal escape or zero escape:
85451 					 *    \0                                     (lookahead not OctalDigit)
85452 					 *    \1 ... \7                              (lookahead not OctalDigit)
85453 					 *    \ZeroToThree OctalDigit                (lookahead not OctalDigit)
85454 					 *    \FourToSeven OctalDigit                (no lookahead restrictions)
85455 					 *    \ZeroToThree OctalDigit OctalDigit     (no lookahead restrictions)
85456 					 *
85457 					 *  Zero escape is part of the standard syntax.  Octal escapes are
85458 					 *  defined in E5 Section B.1.2, and are only allowed in non-strict mode.
85459 					 *  Any other productions starting with a decimal digit are invalid
85460 					 *  but are in practice treated like identity escapes.
85461 					 *
85462 					 *  Parse octal (up to 3 digits) from the lookup window.
85463 					 */
85464 
85465 					emitcp = duk__lexer_parse_legacy_octal(lex_ctx, &adv, strict_mode /*reject_annex_b*/);
85466 					if (emitcp < 0) {
85467 						goto fail_escape;
85468 					}
85469 				} else if (x < 0) {
85470 					goto fail_unterminated;
85471 				} else {
85472 					/* escaped NonEscapeCharacter */
85473 					DUK__APPENDBUFFER(lex_ctx, x);
85474 				}
85475 			}  /* end default clause */
85476 			}  /* end switch */
85477 
85478 			/* Shared handling for single codepoint escapes. */
85479 			if (emitcp >= 0) {
85480 				DUK__APPENDBUFFER(lex_ctx, emitcp);
85481 			}
85482 
85483 			/* Track number of escapes; count not really needed but directive
85484 			 * prologues need to detect whether there were any escapes or line
85485 			 * continuations or not.
85486 			 */
85487 			out_token->num_escapes++;
85488 		} else if (x >= 0x20 && x <= 0x7f) {
85489 			/* Fast path for ASCII case, avoids line terminator
85490 			 * check and CESU-8 encoding.
85491 			 */
85492 			DUK_ASSERT(x >= 0);
85493 			DUK_ASSERT(!duk_unicode_is_line_terminator(x));
85494 			DUK_ASSERT(x != quote);
85495 			DUK_ASSERT(x != DUK_ASC_BACKSLASH);
85496 			DUK__APPENDBUFFER_ASCII(lex_ctx, x);
85497 		} else if (x < 0 || duk_unicode_is_line_terminator(x)) {
85498 			goto fail_unterminated;
85499 		} else {
85500 			/* Character which is part of the string but wasn't handled
85501 			 * by the fast path.
85502 			 */
85503 			DUK__APPENDBUFFER(lex_ctx, x);
85504 		}
85505 	} /* string parse loop */
85506 
85507 	return;
85508 
85509  fail_escape:
85510 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
85511 	DUK_WO_NORETURN(return;);
85512 
85513  fail_unterminated:
85514 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_STRING);
85515 	DUK_WO_NORETURN(return;);
85516 }
85517 
85518 /* Skip to end-of-line (or end-of-file), used for single line comments. */
85519 DUK_LOCAL void duk__lexer_skip_to_endofline(duk_lexer_ctx *lex_ctx) {
85520 	for (;;) {
85521 		duk_codepoint_t x;
85522 
85523 		x = DUK__L0();
85524 		if (x < 0 || duk_unicode_is_line_terminator(x)) {
85525 			break;
85526 		}
85527 		DUK__ADVANCECHARS(lex_ctx, 1);
85528 	}
85529 }
85530 
85531 /*
85532  *  Parse ECMAScript source InputElementDiv or InputElementRegExp
85533  *  (E5 Section 7), skipping whitespace, comments, and line terminators.
85534  *
85535  *  Possible results are:
85536  *    (1) a token
85537  *    (2) a line terminator (skipped)
85538  *    (3) a comment (skipped)
85539  *    (4) EOF
85540  *
85541  *  White space is automatically skipped from the current position (but
85542  *  not after the input element).  If input has already ended, returns
85543  *  DUK_TOK_EOF indefinitely.  If a parse error occurs, uses an DUK_ERROR()
85544  *  macro call (and hence a longjmp through current heap longjmp context).
85545  *  Comments and line terminator tokens are automatically skipped.
85546  *
85547  *  The input element being matched is determined by regexp_mode; if set,
85548  *  parses a InputElementRegExp, otherwise a InputElementDiv.  The
85549  *  difference between these are handling of productions starting with a
85550  *  forward slash.
85551  *
85552  *  If strict_mode is set, recognizes additional future reserved words
85553  *  specific to strict mode, and refuses to parse octal literals.
85554  *
85555  *  The matching strategy below is to (currently) use a six character
85556  *  lookup window to quickly determine which production is the -longest-
85557  *  matching one, and then parse that.  The top-level if-else clauses
85558  *  match the first character, and the code blocks for each clause
85559  *  handle -all- alternatives for that first character.  ECMAScript
85560  *  specification uses the "longest match wins" semantics, so the order
85561  *  of the if-clauses matters.
85562  *
85563  *  Misc notes:
85564  *
85565  *    * ECMAScript numeric literals do not accept a sign character.
85566  *      Consequently e.g. "-1.0" is parsed as two tokens: a negative
85567  *      sign and a positive numeric literal.  The compiler performs
85568  *      the negation during compilation, so this has no adverse impact.
85569  *
85570  *    * There is no token for "undefined": it is just a value available
85571  *      from the global object (or simply established by doing a reference
85572  *      to an undefined value).
85573  *
85574  *    * Some contexts want Identifier tokens, which are IdentifierNames
85575  *      excluding reserved words, while some contexts want IdentifierNames
85576  *      directly.  In the latter case e.g. "while" is interpreted as an
85577  *      identifier name, not a DUK_TOK_WHILE token.  The solution here is
85578  *      to provide both token types: DUK_TOK_WHILE goes to 't' while
85579  *      DUK_TOK_IDENTIFIER goes to 't_nores', and 'slot1' always contains
85580  *      the identifier / keyword name.
85581  *
85582  *    * Directive prologue needs to identify string literals such as
85583  *      "use strict" and 'use strict', which are sensitive to line
85584  *      continuations and escape sequences.  For instance, "use\u0020strict"
85585  *      is a valid directive but is distinct from "use strict".  The solution
85586  *      here is to decode escapes while tokenizing, but to keep track of the
85587  *      number of escapes.  Directive detection can then check that the
85588  *      number of escapes is zero.
85589  *
85590  *    * Multi-line comments with one or more internal LineTerminator are
85591  *      treated like a line terminator to comply with automatic semicolon
85592  *      insertion.
85593  */
85594 
85595 DUK_INTERNAL
85596 void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
85597                                       duk_token *out_token,
85598                                       duk_bool_t strict_mode,
85599                                       duk_bool_t regexp_mode) {
85600 	duk_codepoint_t x;           /* temporary, must be signed and 32-bit to hold Unicode code points */
85601 	duk_small_uint_t advtok = 0; /* (advance << 8) + token_type, updated at function end,
85602 	                              * init is unnecessary but suppresses "may be used uninitialized" warnings.
85603 	                              */
85604 	duk_bool_t got_lineterm = 0;  /* got lineterm preceding non-whitespace, non-lineterm token */
85605 
85606 	if (++lex_ctx->token_count >= lex_ctx->token_limit) {
85607 		goto fail_token_limit;
85608 	}
85609 
85610 	out_token->t = DUK_TOK_EOF;
85611 	out_token->t_nores = DUK_TOK_INVALID;  /* marker: copy t if not changed */
85612 #if 0  /* not necessary to init, disabled for faster parsing */
85613 	out_token->num = DUK_DOUBLE_NAN;
85614 	out_token->str1 = NULL;
85615 	out_token->str2 = NULL;
85616 #endif
85617 	out_token->num_escapes = 0;
85618 	/* out_token->lineterm set by caller */
85619 
85620 	/* This would be nice, but parsing is faster without resetting the
85621 	 * value slots.  The only side effect is that references to temporary
85622 	 * string values may linger until lexing is finished; they're then
85623 	 * freed normally.
85624 	 */
85625 #if 0
85626 	duk_to_undefined(lex_ctx->thr, lex_ctx->slot1_idx);
85627 	duk_to_undefined(lex_ctx->thr, lex_ctx->slot2_idx);
85628 #endif
85629 
85630 	/* 'advtok' indicates how much to advance and which token id to assign
85631 	 * at the end.  This shared functionality minimizes code size.  All
85632 	 * code paths are required to set 'advtok' to some value, so no default
85633 	 * init value is used.  Code paths calling DUK_ERROR() never return so
85634 	 * they don't need to set advtok.
85635 	 */
85636 
85637 	/*
85638 	 *  Matching order:
85639 	 *
85640 	 *    Punctuator first chars, also covers comments, regexps
85641 	 *    LineTerminator
85642 	 *    Identifier or reserved word, also covers null/true/false literals
85643 	 *    NumericLiteral
85644 	 *    StringLiteral
85645 	 *    EOF
85646 	 *
85647 	 *  The order does not matter as long as the longest match is
85648 	 *  always correctly identified.  There are order dependencies
85649 	 *  in the clauses, so it's not trivial to convert to a switch.
85650 	 */
85651 
85652  restart_lineupdate:
85653 	out_token->start_line = lex_ctx->window[0].line;
85654 
85655  restart:
85656 	out_token->start_offset = lex_ctx->window[0].offset;
85657 
85658 	x = DUK__L0();
85659 
85660 	switch (x) {
85661 	case DUK_ASC_SPACE:
85662 	case DUK_ASC_HT:  /* fast paths for space and tab */
85663 		DUK__ADVANCECHARS(lex_ctx, 1);
85664 		goto restart;
85665 	case DUK_ASC_LF:  /* LF line terminator; CR LF and Unicode lineterms are handled in slow path */
85666 		DUK__ADVANCECHARS(lex_ctx, 1);
85667 		got_lineterm = 1;
85668 		goto restart_lineupdate;
85669 #if defined(DUK_USE_SHEBANG_COMMENTS)
85670 	case DUK_ASC_HASH:  /* '#' */
85671 		if (DUK__L1() == DUK_ASC_EXCLAMATION && lex_ctx->window[0].offset == 0 &&
85672 		    (lex_ctx->flags & DUK_COMPILE_SHEBANG)) {
85673 			/* "Shebang" comment ('#! ...') on first line. */
85674 			/* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but not necessary */
85675 			duk__lexer_skip_to_endofline(lex_ctx);
85676 			goto restart;  /* line terminator will be handled on next round */
85677 		}
85678 		goto fail_token;
85679 #endif  /* DUK_USE_SHEBANG_COMMENTS */
85680 	case DUK_ASC_SLASH:  /* '/' */
85681 		if (DUK__L1() == DUK_ASC_SLASH) {
85682 			/*
85683 			 *  E5 Section 7.4, allow SourceCharacter (which is any 16-bit
85684 			 *  code point).
85685 			 */
85686 
85687 			/* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but not necessary */
85688 			duk__lexer_skip_to_endofline(lex_ctx);
85689 			goto restart;  /* line terminator will be handled on next round */
85690 		} else if (DUK__L1() == DUK_ASC_STAR) {
85691 			/*
85692 			 *  E5 Section 7.4.  If the multi-line comment contains a newline,
85693 			 *  it is treated like a single line terminator for automatic
85694 			 *  semicolon insertion.
85695 			 */
85696 
85697 			duk_bool_t last_asterisk = 0;
85698 			DUK__ADVANCECHARS(lex_ctx, 2);
85699 			for (;;) {
85700 				x = DUK__L0();
85701 				if (x < 0) {
85702 					goto fail_unterm_comment;
85703 				}
85704 				DUK__ADVANCECHARS(lex_ctx, 1);
85705 				if (last_asterisk && x == DUK_ASC_SLASH) {
85706 					break;
85707 				}
85708 				if (duk_unicode_is_line_terminator(x)) {
85709 					got_lineterm = 1;
85710 				}
85711 				last_asterisk = (x == DUK_ASC_STAR);
85712 			}
85713 			goto restart_lineupdate;
85714 		} else if (regexp_mode) {
85715 #if defined(DUK_USE_REGEXP_SUPPORT)
85716 			/*
85717 			 *  "/" followed by something in regexp mode.  See E5 Section 7.8.5.
85718 			 *
85719 			 *  RegExp parsing is a bit complex.  First, the regexp body is delimited
85720 			 *  by forward slashes, but the body may also contain forward slashes as
85721 			 *  part of an escape sequence or inside a character class (delimited by
85722 			 *  square brackets).  A mini state machine is used to implement these.
85723 			 *
85724 			 *  Further, an early (parse time) error must be thrown if the regexp
85725 			 *  would cause a run-time error when used in the expression new RegExp(...).
85726 			 *  Parsing here simply extracts the (candidate) regexp, and also accepts
85727 			 *  invalid regular expressions (which are delimited properly).  The caller
85728 			 *  (compiler) must perform final validation and regexp compilation.
85729 			 *
85730 			 *  RegExp first char may not be '/' (single line comment) or '*' (multi-
85731 			 *  line comment).  These have already been checked above, so there is no
85732 			 *  need below for special handling of the first regexp character as in
85733 			 *  the E5 productions.
85734 			 *
85735 			 *  About unicode escapes within regexp literals:
85736 			 *
85737 			 *      E5 Section 7.8.5 grammar does NOT accept \uHHHH escapes.
85738 			 *      However, Section 6 states that regexps accept the escapes,
85739 			 *      see paragraph starting with "In string literals...".
85740 			 *      The regexp grammar, which sees the decoded regexp literal
85741 			 *      (after lexical parsing) DOES have a \uHHHH unicode escape.
85742 			 *      So, for instance:
85743 			 *
85744 			 *          /\u1234/
85745 			 *
85746 			 *      should first be parsed by the lexical grammar as:
85747 			 *
85748 			 *          '\' 'u'      RegularExpressionBackslashSequence
85749 			 *          '1'          RegularExpressionNonTerminator
85750 			 *          '2'          RegularExpressionNonTerminator
85751 			 *          '3'          RegularExpressionNonTerminator
85752 			 *          '4'          RegularExpressionNonTerminator
85753 			 *
85754 			 *      and the escape itself is then parsed by the regexp engine.
85755 			 *      This is the current implementation.
85756 			 *
85757 			 *  Minor spec inconsistency:
85758 			 *
85759 			 *      E5 Section 7.8.5 RegularExpressionBackslashSequence is:
85760 			 *
85761 			 *         \ RegularExpressionNonTerminator
85762 			 *
85763 			 *      while Section A.1 RegularExpressionBackslashSequence is:
85764 			 *
85765 			 *         \ NonTerminator
85766 			 *
85767 			 *      The latter is not normative and a typo.
85768 			 *
85769 			 */
85770 
85771 			/* first, parse regexp body roughly */
85772 
85773 			duk_small_int_t state = 0;  /* 0=base, 1=esc, 2=class, 3=class+esc */
85774 
85775 			DUK__INITBUFFER(lex_ctx);
85776 			for (;;) {
85777 				DUK__ADVANCECHARS(lex_ctx, 1);  /* skip opening slash on first loop */
85778 				x = DUK__L0();
85779 				if (x < 0 || duk_unicode_is_line_terminator(x)) {
85780 					goto fail_unterm_regexp;
85781 				}
85782 				x = DUK__L0();  /* re-read to avoid spill / fetch */
85783 				if (state == 0) {
85784 					if (x == DUK_ASC_SLASH) {
85785 						DUK__ADVANCECHARS(lex_ctx, 1);  /* eat closing slash */
85786 						break;
85787 					} else if (x == DUK_ASC_BACKSLASH) {
85788 						state = 1;
85789 					} else if (x == DUK_ASC_LBRACKET) {
85790 						state = 2;
85791 					}
85792 				} else if (state == 1) {
85793 					state = 0;
85794 				} else if (state == 2) {
85795 					if (x == DUK_ASC_RBRACKET) {
85796 						state = 0;
85797 					} else if (x == DUK_ASC_BACKSLASH) {
85798 						state = 3;
85799 					}
85800 				} else { /* state == 3 */
85801 					state = 2;
85802 				}
85803 				DUK__APPENDBUFFER(lex_ctx, x);
85804 			}
85805 			out_token->str1 = duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
85806 
85807 			/* second, parse flags */
85808 
85809 			DUK__INITBUFFER(lex_ctx);
85810 			for (;;) {
85811 				x = DUK__L0();
85812 				if (!duk_unicode_is_identifier_part(x)) {
85813 					break;
85814 				}
85815 				x = DUK__L0();  /* re-read to avoid spill / fetch */
85816 				DUK__APPENDBUFFER(lex_ctx, x);
85817 				DUK__ADVANCECHARS(lex_ctx, 1);
85818 			}
85819 			out_token->str2 = duk__internbuffer(lex_ctx, lex_ctx->slot2_idx);
85820 
85821 			DUK__INITBUFFER(lex_ctx);  /* free some memory */
85822 
85823 			/* validation of the regexp is caller's responsibility */
85824 
85825 			advtok = DUK__ADVTOK(0, DUK_TOK_REGEXP);
85826 #else  /* DUK_USE_REGEXP_SUPPORT */
85827 			goto fail_regexp_support;
85828 #endif  /* DUK_USE_REGEXP_SUPPORT */
85829 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
85830 			/* "/=" and not in regexp mode */
85831 			advtok = DUK__ADVTOK(2, DUK_TOK_DIV_EQ);
85832 		} else {
85833 			/* "/" and not in regexp mode */
85834 			advtok = DUK__ADVTOK(1, DUK_TOK_DIV);
85835 		}
85836 		break;
85837 	case DUK_ASC_LCURLY:  /* '{' */
85838 		advtok = DUK__ADVTOK(1, DUK_TOK_LCURLY);
85839 		break;
85840 	case DUK_ASC_RCURLY:  /* '}' */
85841 		advtok = DUK__ADVTOK(1, DUK_TOK_RCURLY);
85842 		break;
85843 	case DUK_ASC_LPAREN:  /* '(' */
85844 		advtok = DUK__ADVTOK(1, DUK_TOK_LPAREN);
85845 		break;
85846 	case DUK_ASC_RPAREN:  /* ')' */
85847 		advtok = DUK__ADVTOK(1, DUK_TOK_RPAREN);
85848 		break;
85849 	case DUK_ASC_LBRACKET:  /* '[' */
85850 		advtok = DUK__ADVTOK(1, DUK_TOK_LBRACKET);
85851 		break;
85852 	case DUK_ASC_RBRACKET:  /* ']' */
85853 		advtok = DUK__ADVTOK(1, DUK_TOK_RBRACKET);
85854 		break;
85855 	case DUK_ASC_PERIOD:  /* '.' */
85856 		if (DUK__ISDIGIT(DUK__L1())) {
85857 			/* Period followed by a digit can only start DecimalLiteral
85858 			 * (handled in slow path).  We could jump straight into the
85859 			 * DecimalLiteral handling but should avoid goto to inside
85860 			 * a block.
85861 			 */
85862 			goto slow_path;
85863 		}
85864 		advtok = DUK__ADVTOK(1, DUK_TOK_PERIOD);
85865 		break;
85866 	case DUK_ASC_SEMICOLON:  /* ';' */
85867 		advtok = DUK__ADVTOK(1, DUK_TOK_SEMICOLON);
85868 		break;
85869 	case DUK_ASC_COMMA:  /* ',' */
85870 		advtok = DUK__ADVTOK(1, DUK_TOK_COMMA);
85871 		break;
85872 	case DUK_ASC_LANGLE:  /* '<' */
85873 #if defined(DUK_USE_HTML_COMMENTS)
85874 		if (DUK__L1() == DUK_ASC_EXCLAMATION && DUK__L2() == DUK_ASC_MINUS && DUK__L3() == DUK_ASC_MINUS) {
85875 			/*
85876 			 *  ES2015: B.1.3, handle "<!--" SingleLineHTMLOpenComment
85877 			 */
85878 
85879 			/* DUK__ADVANCECHARS(lex_ctx, 4) would be correct here, but not necessary */
85880 			duk__lexer_skip_to_endofline(lex_ctx);
85881 			goto restart;  /* line terminator will be handled on next round */
85882 		}
85883 		else
85884 #endif  /* DUK_USE_HTML_COMMENTS */
85885 		if (DUK__L1() == DUK_ASC_LANGLE && DUK__L2() == DUK_ASC_EQUALS) {
85886 			advtok = DUK__ADVTOK(3, DUK_TOK_ALSHIFT_EQ);
85887 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
85888 			advtok = DUK__ADVTOK(2, DUK_TOK_LE);
85889 		} else if (DUK__L1() == DUK_ASC_LANGLE) {
85890 			advtok = DUK__ADVTOK(2, DUK_TOK_ALSHIFT);
85891 		} else {
85892 			advtok = DUK__ADVTOK(1, DUK_TOK_LT);
85893 		}
85894 		break;
85895 	case DUK_ASC_RANGLE:  /* '>' */
85896 		if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_RANGLE && DUK__L3() == DUK_ASC_EQUALS) {
85897 			advtok = DUK__ADVTOK(4, DUK_TOK_RSHIFT_EQ);
85898 		} else if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_RANGLE) {
85899 			advtok = DUK__ADVTOK(3, DUK_TOK_RSHIFT);
85900 		} else if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_EQUALS) {
85901 			advtok = DUK__ADVTOK(3, DUK_TOK_ARSHIFT_EQ);
85902 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
85903 			advtok = DUK__ADVTOK(2, DUK_TOK_GE);
85904 		} else if (DUK__L1() == DUK_ASC_RANGLE) {
85905 			advtok = DUK__ADVTOK(2, DUK_TOK_ARSHIFT);
85906 		} else {
85907 			advtok = DUK__ADVTOK(1, DUK_TOK_GT);
85908 		}
85909 		break;
85910 	case DUK_ASC_EQUALS:  /* '=' */
85911 		if (DUK__L1() == DUK_ASC_EQUALS && DUK__L2() == DUK_ASC_EQUALS) {
85912 			advtok = DUK__ADVTOK(3, DUK_TOK_SEQ);
85913 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
85914 			advtok = DUK__ADVTOK(2, DUK_TOK_EQ);
85915 		} else {
85916 			advtok = DUK__ADVTOK(1, DUK_TOK_EQUALSIGN);
85917 		}
85918 		break;
85919 	case DUK_ASC_EXCLAMATION:  /* '!' */
85920 		if (DUK__L1() == DUK_ASC_EQUALS && DUK__L2() == DUK_ASC_EQUALS) {
85921 			advtok = DUK__ADVTOK(3, DUK_TOK_SNEQ);
85922 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
85923 			advtok = DUK__ADVTOK(2, DUK_TOK_NEQ);
85924 		} else {
85925 			advtok = DUK__ADVTOK(1, DUK_TOK_LNOT);
85926 		}
85927 		break;
85928 	case DUK_ASC_PLUS:  /* '+' */
85929 		if (DUK__L1() == DUK_ASC_PLUS) {
85930 			advtok = DUK__ADVTOK(2, DUK_TOK_INCREMENT);
85931 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
85932 			advtok = DUK__ADVTOK(2, DUK_TOK_ADD_EQ);
85933 		} else {
85934 			advtok = DUK__ADVTOK(1, DUK_TOK_ADD);
85935 		}
85936 		break;
85937 	case DUK_ASC_MINUS:  /* '-' */
85938 #if defined(DUK_USE_HTML_COMMENTS)
85939 		if (got_lineterm && DUK__L1() == DUK_ASC_MINUS && DUK__L2() == DUK_ASC_RANGLE) {
85940 			/*
85941 			 *  ES2015: B.1.3, handle "-->" SingleLineHTMLCloseComment
85942 			 *  Only allowed:
85943 			 *  - on new line
85944 			 *  - preceded only by whitespace
85945 			 *  - preceded by end of multiline comment and optional whitespace
85946 			 *
85947 			 * Since whitespace generates no tokens, and multiline comments
85948 			 * are treated as a line ending, consulting `got_lineterm` is
85949 			 * sufficient to test for these three options.
85950 			 */
85951 
85952 			/* DUK__ADVANCECHARS(lex_ctx, 3) would be correct here, but not necessary */
85953 			duk__lexer_skip_to_endofline(lex_ctx);
85954 			goto restart;  /* line terminator will be handled on next round */
85955 		} else
85956 #endif  /* DUK_USE_HTML_COMMENTS */
85957 		if (DUK__L1() == DUK_ASC_MINUS) {
85958 			advtok = DUK__ADVTOK(2, DUK_TOK_DECREMENT);
85959 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
85960 			advtok = DUK__ADVTOK(2, DUK_TOK_SUB_EQ);
85961 		} else {
85962 			advtok = DUK__ADVTOK(1, DUK_TOK_SUB);
85963 		}
85964 		break;
85965 	case DUK_ASC_STAR:  /* '*' */
85966 #if defined(DUK_USE_ES7_EXP_OPERATOR)
85967 		if (DUK__L1() == DUK_ASC_STAR && DUK__L2() == DUK_ASC_EQUALS) {
85968 			advtok = DUK__ADVTOK(3, DUK_TOK_EXP_EQ);
85969 		} else if (DUK__L1() == DUK_ASC_STAR) {
85970 			advtok = DUK__ADVTOK(2, DUK_TOK_EXP);
85971 		} else
85972 #endif
85973 		if (DUK__L1() == DUK_ASC_EQUALS) {
85974 			advtok = DUK__ADVTOK(2, DUK_TOK_MUL_EQ);
85975 		} else {
85976 			advtok = DUK__ADVTOK(1, DUK_TOK_MUL);
85977 		}
85978 		break;
85979 	case DUK_ASC_PERCENT:  /* '%' */
85980 		if (DUK__L1() == DUK_ASC_EQUALS) {
85981 			advtok = DUK__ADVTOK(2, DUK_TOK_MOD_EQ);
85982 		} else {
85983 			advtok = DUK__ADVTOK(1, DUK_TOK_MOD);
85984 		}
85985 		break;
85986 	case DUK_ASC_AMP:  /* '&' */
85987 		if (DUK__L1() == DUK_ASC_AMP) {
85988 			advtok = DUK__ADVTOK(2, DUK_TOK_LAND);
85989 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
85990 			advtok = DUK__ADVTOK(2, DUK_TOK_BAND_EQ);
85991 		} else {
85992 			advtok = DUK__ADVTOK(1, DUK_TOK_BAND);
85993 		}
85994 		break;
85995 	case DUK_ASC_PIPE:  /* '|' */
85996 		if (DUK__L1() == DUK_ASC_PIPE) {
85997 			advtok = DUK__ADVTOK(2, DUK_TOK_LOR);
85998 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
85999 			advtok = DUK__ADVTOK(2, DUK_TOK_BOR_EQ);
86000 		} else {
86001 			advtok = DUK__ADVTOK(1, DUK_TOK_BOR);
86002 		}
86003 		break;
86004 	case DUK_ASC_CARET:  /* '^' */
86005 		if (DUK__L1() == DUK_ASC_EQUALS) {
86006 			advtok = DUK__ADVTOK(2, DUK_TOK_BXOR_EQ);
86007 		} else {
86008 			advtok = DUK__ADVTOK(1, DUK_TOK_BXOR);
86009 		}
86010 		break;
86011 	case DUK_ASC_TILDE:  /* '~' */
86012 		advtok = DUK__ADVTOK(1, DUK_TOK_BNOT);
86013 		break;
86014 	case DUK_ASC_QUESTION:  /* '?' */
86015 		advtok = DUK__ADVTOK(1, DUK_TOK_QUESTION);
86016 		break;
86017 	case DUK_ASC_COLON:  /* ':' */
86018 		advtok = DUK__ADVTOK(1, DUK_TOK_COLON);
86019 		break;
86020 	case DUK_ASC_DOUBLEQUOTE:    /* '"' */
86021 	case DUK_ASC_SINGLEQUOTE: {  /* '\'' */
86022 		DUK__INITBUFFER(lex_ctx);
86023 		duk__lexer_parse_string_literal(lex_ctx, out_token, x /*quote*/, strict_mode);
86024 		duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
86025 		out_token->str1 = duk_known_hstring(lex_ctx->thr, lex_ctx->slot1_idx);
86026 
86027 		DUK__INITBUFFER(lex_ctx);  /* free some memory */
86028 
86029 		advtok = DUK__ADVTOK(0, DUK_TOK_STRING);
86030 		break;
86031 	}
86032 	default:
86033 		goto slow_path;
86034 	}  /* switch */
86035 
86036 	goto skip_slow_path;
86037 
86038  slow_path:
86039 	if (duk_unicode_is_line_terminator(x)) {
86040 		if (x == 0x000d && DUK__L1() == 0x000a) {
86041 			/*
86042 			 *  E5 Section 7.3: CR LF is detected as a single line terminator for
86043 			 *  line numbers.  Here we also detect it as a single line terminator
86044 			 *  token.
86045 			 */
86046 			DUK__ADVANCECHARS(lex_ctx, 2);
86047 		} else {
86048 			DUK__ADVANCECHARS(lex_ctx, 1);
86049 		}
86050 		got_lineterm = 1;
86051 		goto restart_lineupdate;
86052 	} else if (duk_unicode_is_identifier_start(x) || x == DUK_ASC_BACKSLASH) {
86053 		/*
86054 		 *  Parse an identifier and then check whether it is:
86055 		 *    - reserved word (keyword or other reserved word)
86056 		 *    - "null"  (NullLiteral)
86057 		 *    - "true"  (BooleanLiteral)
86058 		 *    - "false" (BooleanLiteral)
86059 		 *    - anything else => identifier
86060 		 *
86061 		 *  This does not follow the E5 productions cleanly, but is
86062 		 *  useful and compact.
86063 		 *
86064 		 *  Note that identifiers may contain Unicode escapes,
86065 		 *  see E5 Sections 6 and 7.6.  They must be decoded first,
86066 		 *  and the result checked against allowed characters.
86067 		 *  The above if-clause accepts an identifier start and an
86068 		 *  '\' character -- no other token can begin with a '\'.
86069 		 *
86070 		 *  Note that "get" and "set" are not reserved words in E5
86071 		 *  specification so they are recognized as plain identifiers
86072 		 *  (the tokens DUK_TOK_GET and DUK_TOK_SET are actually not
86073 		 *  used now).  The compiler needs to work around this.
86074 		 *
86075 		 *  Strictly speaking, following ECMAScript longest match
86076 		 *  specification, an invalid escape for the first character
86077 		 *  should cause a syntax error.  However, an invalid escape
86078 		 *  for IdentifierParts should just terminate the identifier
86079 		 *  early (longest match), and let the next tokenization
86080 		 *  fail.  For instance Rhino croaks with 'foo\z' when
86081 		 *  parsing the identifier.  This has little practical impact.
86082 		 */
86083 
86084 		duk_small_uint_t i, i_end;
86085 		duk_bool_t first = 1;
86086 		duk_hstring *str;
86087 
86088 		DUK__INITBUFFER(lex_ctx);
86089 		for (;;) {
86090 			/* re-lookup first char on first loop */
86091 			if (DUK__L0() == DUK_ASC_BACKSLASH) {
86092 				duk_codepoint_t esc_cp;
86093 				if (DUK__L1() != DUK_ASC_LC_U) {
86094 					goto fail_escape;
86095 				}
86096 				esc_cp = duk__lexer_parse_escape(lex_ctx, 1 /*allow_es6*/);
86097 				DUK__APPENDBUFFER(lex_ctx, esc_cp);
86098 
86099 				/* IdentifierStart is stricter than IdentifierPart, so if the first
86100 				 * character is escaped, must have a stricter check here.
86101 				 */
86102 				if (!(first ? duk_unicode_is_identifier_start(esc_cp) : duk_unicode_is_identifier_part(esc_cp))) {
86103 					goto fail_escape;
86104 				}
86105 
86106 				/* Track number of escapes: necessary for proper keyword
86107 				 * detection.
86108 				 */
86109 				out_token->num_escapes++;
86110 			} else {
86111 				/* Note: first character is checked against this.  But because
86112 				 * IdentifierPart includes all IdentifierStart characters, and
86113 				 * the first character (if unescaped) has already been checked
86114 				 * in the if condition, this is OK.
86115 				 */
86116 				if (!duk_unicode_is_identifier_part(DUK__L0())) {
86117 					break;
86118 				}
86119 				DUK__APPENDBUFFER(lex_ctx, DUK__L0());
86120 				DUK__ADVANCECHARS(lex_ctx, 1);
86121 			}
86122 			first = 0;
86123 		}
86124 
86125 		out_token->str1 = duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
86126 		str = out_token->str1;
86127 		out_token->t_nores = DUK_TOK_IDENTIFIER;
86128 
86129 		DUK__INITBUFFER(lex_ctx);  /* free some memory */
86130 
86131 		/*
86132 		 *  Interned identifier is compared against reserved words, which are
86133 		 *  currently interned into the heap context.  See genbuiltins.py.
86134 		 *
86135 		 *  Note that an escape in the identifier disables recognition of
86136 		 *  keywords; e.g. "\u0069f = 1;" is a valid statement (assigns to
86137 		 *  identifier named "if").  This is not necessarily compliant,
86138 		 *  see test-dec-escaped-char-in-keyword.js.
86139 		 *
86140 		 *  Note: "get" and "set" are awkward.  They are not officially
86141 		 *  ReservedWords (and indeed e.g. "var set = 1;" is valid), and
86142 		 *  must come out as DUK_TOK_IDENTIFIER.  The compiler needs to
86143 		 *  work around this a bit.
86144 		 */
86145 
86146 		/* XXX: optimize by adding the token numbers directly into the
86147 		 * always interned duk_hstring objects (there should be enough
86148 		 * flag bits free for that)?
86149 		 */
86150 
86151 		i_end = (strict_mode ? DUK_STRIDX_END_RESERVED : DUK_STRIDX_START_STRICT_RESERVED);
86152 
86153 		advtok = DUK__ADVTOK(0, DUK_TOK_IDENTIFIER);
86154 		if (out_token->num_escapes == 0) {
86155 			for (i = DUK_STRIDX_START_RESERVED; i < i_end; i++) {
86156 				DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
86157 				DUK_ASSERT(i < DUK_HEAP_NUM_STRINGS);
86158 				if (DUK_HTHREAD_GET_STRING(lex_ctx->thr, i) == str) {
86159 					advtok = DUK__ADVTOK(0, DUK_STRIDX_TO_TOK(i));
86160 					break;
86161 				}
86162 			}
86163 		}
86164 	} else if (DUK__ISDIGIT(x) || (x == DUK_ASC_PERIOD)) {
86165 		/* Note: decimal number may start with a period, but must be followed by a digit */
86166 
86167 		/*
86168 		 *  Pre-parsing for decimal, hex, octal (both legacy and ES2015),
86169 		 *  and binary literals, followed by an actual parser step
86170 		 *  provided by numconv.
86171 		 *
86172 		 *  Note: the leading sign character ('+' or '-') is -not- part of
86173 		 *  the production in E5 grammar, and that the a DecimalLiteral
86174 		 *  starting with a '0' must be followed by a non-digit.
86175 		 *
86176 		 *  XXX: the two step parsing process is quite awkward, it would
86177 		 *  be more straightforward to allow numconv to parse the longest
86178 		 *  valid prefix (it already does that, it only needs to indicate
86179 		 *  where the input ended).  However, the lexer decodes characters
86180 		 *  using a limited lookup window, so this is not a trivial change.
86181 		 */
86182 
86183 		/* XXX: because of the final check below (that the literal is not
86184 		 * followed by a digit), this could maybe be simplified, if we bail
86185 		 * out early from a leading zero (and if there are no periods etc).
86186 		 * Maybe too complex.
86187 		 */
86188 
86189 		duk_double_t val;
86190 		duk_bool_t legacy_oct = 0;
86191 		duk_small_int_t state;  /* 0=before period/exp,
86192 		                         * 1=after period, before exp
86193 		                         * 2=after exp, allow '+' or '-'
86194 		                         * 3=after exp and exp sign
86195 		                         */
86196 		duk_small_uint_t s2n_flags;
86197 		duk_codepoint_t y, z;
86198 		duk_small_int_t s2n_radix = 10;
86199 		duk_small_uint_t pre_adv = 0;
86200 
86201 		DUK__INITBUFFER(lex_ctx);
86202 		y = DUK__L1();
86203 
86204 		if (x == DUK_ASC_0) {
86205 			z = DUK_LOWERCASE_CHAR_ASCII(y);
86206 
86207 			pre_adv = 2;  /* default for 0xNNN, 0oNNN, 0bNNN. */
86208 			if (z == DUK_ASC_LC_X) {
86209 				s2n_radix = 16;
86210 			} else if (z == DUK_ASC_LC_O) {
86211 				s2n_radix = 8;
86212 			} else if (z == DUK_ASC_LC_B) {
86213 				s2n_radix = 2;
86214 			} else {
86215 				pre_adv = 0;
86216 				if (DUK__ISDIGIT(y)) {
86217 					if (strict_mode) {
86218 						/* Reject octal like \07 but also octal-lookalike
86219 						 * decimal like \08 in strict mode.
86220 						 */
86221 						goto fail_number_literal;
86222 					} else {
86223 						/* Legacy OctalIntegerLiteral or octal-lookalice
86224 						 * decimal.  Deciding between the two happens below
86225 						 * in digit scanning.
86226 						 */
86227 						DUK__APPENDBUFFER(lex_ctx, x);
86228 						pre_adv = 1;
86229 						legacy_oct = 1;
86230 						s2n_radix = 8;  /* tentative unless conflicting digits found */
86231 					}
86232 				}
86233 			}
86234 		}
86235 
86236 		DUK__ADVANCECHARS(lex_ctx, pre_adv);
86237 
86238 		/* XXX: we could parse integers here directly, and fall back
86239 		 * to numconv only when encountering a fractional expression
86240 		 * or when an octal literal turned out to be decimal (0778 etc).
86241 		 */
86242 		state = 0;
86243 		for (;;) {
86244 			x = DUK__L0();  /* re-lookup curr char on first round */
86245 			if (DUK__ISDIGIT(x)) {
86246 				/* Note: intentionally allow leading zeroes here, as the
86247 				 * actual parser will check for them.
86248 				 */
86249 				if (state == 0 && legacy_oct && (x == DUK_ASC_8 || x == DUK_ASC_9)) {
86250 					/* Started out as an octal-lookalike
86251 					 * but interpreted as decimal, e.g.
86252 					 * '0779' -> 779.  This also means
86253 					 * that fractions are allowed, e.g.
86254 					 * '0779.123' is allowed but '0777.123'
86255 					 * is not!
86256 					 */
86257 					s2n_radix = 10;
86258 				}
86259 				if (state == 2) {
86260 					state = 3;
86261 				}
86262 			} else if (s2n_radix == 16 && DUK__ISHEXDIGIT(x)) {
86263 				/* Note: 'e' and 'E' are also accepted here. */
86264 				;
86265 			} else if (x == DUK_ASC_PERIOD) {
86266 				if (state >= 1 || s2n_radix != 10) {
86267 					break;
86268 				} else {
86269 					state = 1;
86270 				}
86271 			} else if (x == DUK_ASC_LC_E || x == DUK_ASC_UC_E) {
86272 				if (state >= 2 || s2n_radix != 10) {
86273 					break;
86274 				} else {
86275 					state = 2;
86276 				}
86277 			} else if (x == DUK_ASC_MINUS || x == DUK_ASC_PLUS) {
86278 				if (state != 2) {
86279 					break;
86280 				} else {
86281 					state = 3;
86282 				}
86283 			} else {
86284 				break;
86285 			}
86286 			DUK__APPENDBUFFER(lex_ctx, x);
86287 			DUK__ADVANCECHARS(lex_ctx, 1);
86288 		}
86289 
86290 		/* XXX: better coercion */
86291 		(void) duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
86292 
86293 		if (s2n_radix != 10) {
86294 			/* For bases other than 10, integer only. */
86295 			s2n_flags = DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
86296 		} else {
86297 			s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
86298 			            DUK_S2N_FLAG_ALLOW_FRAC |
86299 			            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
86300 			            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
86301 			            DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
86302 		}
86303 
86304 		duk_dup(lex_ctx->thr, lex_ctx->slot1_idx);
86305 		duk_numconv_parse(lex_ctx->thr, s2n_radix, s2n_flags);
86306 		val = duk_to_number_m1(lex_ctx->thr);
86307 		if (DUK_ISNAN(val)) {
86308 			goto fail_number_literal;
86309 		}
86310 		duk_replace(lex_ctx->thr, lex_ctx->slot1_idx);  /* could also just pop? */
86311 
86312 		DUK__INITBUFFER(lex_ctx);  /* free some memory */
86313 
86314 		/* Section 7.8.3 (note): NumericLiteral must be followed by something other than
86315 		 * IdentifierStart or DecimalDigit.
86316 		 */
86317 
86318 		if (DUK__ISDIGIT(DUK__L0()) || duk_unicode_is_identifier_start(DUK__L0())) {
86319 			goto fail_number_literal;
86320 		}
86321 
86322 		out_token->num = val;
86323 		advtok = DUK__ADVTOK(0, DUK_TOK_NUMBER);
86324 	} else if (duk_unicode_is_whitespace(DUK__LOOKUP(lex_ctx, 0))) {
86325 		DUK__ADVANCECHARS(lex_ctx, 1);
86326 		goto restart;
86327 	} else if (x < 0) {
86328 		advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
86329 	} else {
86330 		goto fail_token;
86331 	}
86332  skip_slow_path:
86333 
86334 	/*
86335 	 *  Shared exit path
86336 	 */
86337 
86338 	DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
86339 	out_token->t = advtok & 0xff;
86340 	if (out_token->t_nores == DUK_TOK_INVALID) {
86341 		out_token->t_nores = out_token->t;
86342 	}
86343 	out_token->lineterm = got_lineterm;
86344 
86345 	/* Automatic semicolon insertion is allowed if a token is preceded
86346 	 * by line terminator(s), or terminates a statement list (right curly
86347 	 * or EOF).
86348 	 */
86349 	if (got_lineterm || out_token->t == DUK_TOK_RCURLY || out_token->t == DUK_TOK_EOF) {
86350 		out_token->allow_auto_semi = 1;
86351 	} else {
86352 		out_token->allow_auto_semi = 0;
86353 	}
86354 
86355 	return;
86356 
86357  fail_token_limit:
86358 	DUK_ERROR_RANGE(lex_ctx->thr, DUK_STR_TOKEN_LIMIT);
86359 	DUK_WO_NORETURN(return;);
86360 
86361  fail_token:
86362 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_TOKEN);
86363 	DUK_WO_NORETURN(return;);
86364 
86365  fail_number_literal:
86366 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_NUMBER_LITERAL);
86367 	DUK_WO_NORETURN(return;);
86368 
86369  fail_escape:
86370 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
86371 	DUK_WO_NORETURN(return;);
86372 
86373  fail_unterm_regexp:
86374 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_REGEXP);
86375 	DUK_WO_NORETURN(return;);
86376 
86377  fail_unterm_comment:
86378 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_COMMENT);
86379 	DUK_WO_NORETURN(return;);
86380 
86381 #if !defined(DUK_USE_REGEXP_SUPPORT)
86382  fail_regexp_support:
86383 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_REGEXP_SUPPORT_DISABLED);
86384 	DUK_WO_NORETURN(return;);
86385 #endif
86386 }
86387 
86388 #if defined(DUK_USE_REGEXP_SUPPORT)
86389 
86390 /*
86391  *  Parse a RegExp token.  The grammar is described in E5 Section 15.10.
86392  *  Terminal constructions (such as quantifiers) are parsed directly here.
86393  *
86394  *  0xffffffffU is used as a marker for "infinity" in quantifiers.  Further,
86395  *  DUK__MAX_RE_QUANT_DIGITS limits the maximum number of digits that
86396  *  will be accepted for a quantifier.
86397  */
86398 
86399 DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token) {
86400 	duk_small_uint_t advtok = 0;  /* init is unnecessary but suppresses "may be used uninitialized" warnings */
86401 	duk_codepoint_t x, y;
86402 
86403 	if (++lex_ctx->token_count >= lex_ctx->token_limit) {
86404 		goto fail_token_limit;
86405 	}
86406 
86407 	duk_memzero(out_token, sizeof(*out_token));
86408 
86409 	x = DUK__L0();
86410 	y = DUK__L1();
86411 
86412 	DUK_DDD(DUK_DDDPRINT("parsing regexp token, L0=%ld, L1=%ld", (long) x, (long) y));
86413 
86414 	switch (x) {
86415 	case DUK_ASC_PIPE: {
86416 		advtok = DUK__ADVTOK(1, DUK_RETOK_DISJUNCTION);
86417 		break;
86418 	}
86419 	case DUK_ASC_CARET: {
86420 		advtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_START);
86421 		break;
86422 	}
86423 	case DUK_ASC_DOLLAR: {
86424 		advtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_END);
86425 		break;
86426 	}
86427 	case DUK_ASC_QUESTION: {
86428 		out_token->qmin = 0;
86429 		out_token->qmax = 1;
86430 		if (y == DUK_ASC_QUESTION) {
86431 			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
86432 			out_token->greedy = 0;
86433 		} else {
86434 			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
86435 			out_token->greedy = 1;
86436 		}
86437 		break;
86438 	}
86439 	case DUK_ASC_STAR: {
86440 		out_token->qmin = 0;
86441 		out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
86442 		if (y == DUK_ASC_QUESTION) {
86443 			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
86444 			out_token->greedy = 0;
86445 		} else {
86446 			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
86447 			out_token->greedy = 1;
86448 		}
86449 		break;
86450 	}
86451 	case DUK_ASC_PLUS: {
86452 		out_token->qmin = 1;
86453 		out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
86454 		if (y == DUK_ASC_QUESTION) {
86455 			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
86456 			out_token->greedy = 0;
86457 		} else {
86458 			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
86459 			out_token->greedy = 1;
86460 		}
86461 		break;
86462 	}
86463 	case DUK_ASC_LCURLY: {
86464 		/* Production allows 'DecimalDigits', including leading zeroes */
86465 		duk_uint32_t val1 = 0;
86466 		duk_uint32_t val2 = DUK_RE_QUANTIFIER_INFINITE;
86467 		duk_small_int_t digits = 0;
86468 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
86469 		duk_lexer_point lex_pt;
86470 #endif
86471 
86472 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
86473 		/* Store lexer position, restoring if quantifier is invalid. */
86474 		DUK_LEXER_GETPOINT(lex_ctx, &lex_pt);
86475 #endif
86476 
86477 		for (;;) {
86478 			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat '{' on entry */
86479 			x = DUK__L0();
86480 			if (DUK__ISDIGIT(x)) {
86481 				digits++;
86482 				val1 = val1 * 10 + (duk_uint32_t) duk__hexval(x);
86483 			} else if (x == DUK_ASC_COMMA) {
86484 				if (digits > DUK__MAX_RE_QUANT_DIGITS) {
86485 					goto invalid_quantifier;
86486 				}
86487 				if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
86488 					goto invalid_quantifier;
86489 				}
86490 				if (DUK__L1() == DUK_ASC_RCURLY) {
86491 					/* form: { DecimalDigits , }, val1 = min count */
86492 					if (digits == 0) {
86493 						goto invalid_quantifier;
86494 					}
86495 					out_token->qmin = val1;
86496 					out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
86497 					DUK__ADVANCECHARS(lex_ctx, 2);
86498 					break;
86499 				}
86500 				val2 = val1;
86501 				val1 = 0;
86502 				digits = 0;  /* not strictly necessary because of lookahead '}' above */
86503 			} else if (x == DUK_ASC_RCURLY) {
86504 				if (digits > DUK__MAX_RE_QUANT_DIGITS) {
86505 					goto invalid_quantifier;
86506 				}
86507 				if (digits == 0) {
86508 					goto invalid_quantifier;
86509 				}
86510 				if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
86511 					/* val2 = min count, val1 = max count */
86512 					out_token->qmin = val2;
86513 					out_token->qmax = val1;
86514 				} else {
86515 					/* val1 = count */
86516 					out_token->qmin = val1;
86517 					out_token->qmax = val1;
86518 				}
86519 				DUK__ADVANCECHARS(lex_ctx, 1);
86520 				break;
86521 			} else {
86522 				goto invalid_quantifier;
86523 			}
86524 		}
86525 		if (DUK__L0() == DUK_ASC_QUESTION) {
86526 			out_token->greedy = 0;
86527 			DUK__ADVANCECHARS(lex_ctx, 1);
86528 		} else {
86529 			out_token->greedy = 1;
86530 		}
86531 		advtok = DUK__ADVTOK(0, DUK_RETOK_QUANTIFIER);
86532 		break;
86533  invalid_quantifier:
86534 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
86535 		/* Failed to match the quantifier, restore lexer and parse
86536 		 * opening brace as a literal.
86537 		 */
86538 		DUK_LEXER_SETPOINT(lex_ctx, &lex_pt);
86539 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
86540 		out_token->num = DUK_ASC_LCURLY;
86541 #else
86542 		goto fail_quantifier;
86543 #endif
86544 		break;
86545 	}
86546 	case DUK_ASC_PERIOD: {
86547 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_PERIOD);
86548 		break;
86549 	}
86550 	case DUK_ASC_BACKSLASH: {
86551 		/* The E5.1 specification does not seem to allow IdentifierPart characters
86552 		 * to be used as identity escapes.  Unfortunately this includes '$', which
86553 		 * cannot be escaped as '\$'; it needs to be escaped e.g. as '\u0024'.
86554 		 * Many other implementations (including V8 and Rhino, for instance) do
86555 		 * accept '\$' as a valid identity escape, which is quite pragmatic, and
86556 		 * ES2015 Annex B relaxes the rules to allow these (and other) real world forms.
86557 		 */
86558 
86559 		advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);  /* default: char escape (two chars) */
86560 		if (y == DUK_ASC_LC_B) {
86561 			advtok = DUK__ADVTOK(2, DUK_RETOK_ASSERT_WORD_BOUNDARY);
86562 		} else if (y == DUK_ASC_UC_B) {
86563 			advtok = DUK__ADVTOK(2, DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY);
86564 		} else if (y == DUK_ASC_LC_F) {
86565 			out_token->num = 0x000c;
86566 		} else if (y == DUK_ASC_LC_N) {
86567 			out_token->num = 0x000a;
86568 		} else if (y == DUK_ASC_LC_T) {
86569 			out_token->num = 0x0009;
86570 		} else if (y == DUK_ASC_LC_R) {
86571 			out_token->num = 0x000d;
86572 		} else if (y == DUK_ASC_LC_V) {
86573 			out_token->num = 0x000b;
86574 		} else if (y == DUK_ASC_LC_C) {
86575 			x = DUK__L2();
86576 			if ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) ||
86577 			    (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {
86578 				out_token->num = (duk_uint32_t) (x % 32);
86579 				advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_CHAR);
86580 			} else {
86581 				goto fail_escape;
86582 			}
86583 		} else if (y == DUK_ASC_LC_X || y == DUK_ASC_LC_U) {
86584 			/* The token value is the Unicode codepoint without
86585 			 * it being decode into surrogate pair characters
86586 			 * here.  The \u{H+} is only allowed in Unicode mode
86587 			 * which we don't support yet.
86588 			 */
86589 			out_token->num = (duk_uint32_t) duk__lexer_parse_escape(lex_ctx, 0 /*allow_es6*/);
86590 			advtok = DUK__ADVTOK(0, DUK_RETOK_ATOM_CHAR);
86591 		} else if (y == DUK_ASC_LC_D) {
86592 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_DIGIT);
86593 		} else if (y == DUK_ASC_UC_D) {
86594 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_DIGIT);
86595 		} else if (y == DUK_ASC_LC_S) {
86596 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WHITE);
86597 		} else if (y == DUK_ASC_UC_S) {
86598 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_WHITE);
86599 		} else if (y == DUK_ASC_LC_W) {
86600 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WORD_CHAR);
86601 		} else if (y == DUK_ASC_UC_W) {
86602 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_WORD_CHAR);
86603 		} else if (DUK__ISDIGIT(y)) {
86604 			/* E5 Section 15.10.2.11 */
86605 			if (y == DUK_ASC_0) {
86606 				if (DUK__ISDIGIT(DUK__L2())) {
86607 					goto fail_escape;
86608 				}
86609 				out_token->num = 0x0000;
86610 				advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);
86611 			} else {
86612 				/* XXX: shared parsing? */
86613 				duk_uint32_t val = 0;
86614 				duk_small_int_t i;
86615 				for (i = 0; ; i++) {
86616 					if (i >= DUK__MAX_RE_DECESC_DIGITS) {
86617 						goto fail_escape;
86618 					}
86619 					DUK__ADVANCECHARS(lex_ctx, 1);  /* eat backslash on entry */
86620 					x = DUK__L0();
86621 					if (!DUK__ISDIGIT(x)) {
86622 						break;
86623 					}
86624 					val = val * 10 + (duk_uint32_t) duk__hexval(x);
86625 				}
86626 				/* DUK__L0() cannot be a digit, because the loop doesn't terminate if it is */
86627 				advtok = DUK__ADVTOK(0, DUK_RETOK_ATOM_BACKREFERENCE);
86628 				out_token->num = val;
86629 			}
86630 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
86631 		} else if (y >= 0) {
86632 			/* For ES2015 Annex B, accept any source character as identity
86633 			 * escape except 'c' which is used for control characters.
86634 			 * http://www.ecma-international.org/ecma-262/6.0/#sec-regular-expressions-patterns
86635 			 * Careful not to match end-of-buffer (<0) here.
86636 			 * This is not yet full ES2015 Annex B because cases above
86637 			 * (like hex escape) won't backtrack.
86638 			 */
86639 			DUK_ASSERT(y != DUK_ASC_LC_C);  /* covered above */
86640 #else  /* DUK_USE_ES6_REGEXP_SYNTAX */
86641 		} else if ((y >= 0 && !duk_unicode_is_identifier_part(y)) ||
86642 		           y == DUK_UNICODE_CP_ZWNJ ||
86643 		           y == DUK_UNICODE_CP_ZWJ) {
86644 			/* For ES5.1 identity escapes are not allowed for identifier
86645 			 * parts.  This conflicts with a lot of real world code as this
86646 			 * doesn't e.g. allow escaping a dollar sign as /\$/, see
86647 			 * test-regexp-identity-escape-dollar.js.
86648 			 */
86649 #endif  /* DUK_USE_ES6_REGEXP_SYNTAX */
86650 			out_token->num = (duk_uint32_t) y;
86651 		} else {
86652 			goto fail_escape;
86653 		}
86654 		break;
86655 	}
86656 	case DUK_ASC_LPAREN: {
86657 		/* XXX: naming is inconsistent: ATOM_END_GROUP ends an ASSERT_START_LOOKAHEAD */
86658 
86659 		if (y == DUK_ASC_QUESTION) {
86660 			if (DUK__L2() == DUK_ASC_EQUALS) {
86661 				/* (?= */
86662 				advtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_POS_LOOKAHEAD);
86663 			} else if (DUK__L2() == DUK_ASC_EXCLAMATION) {
86664 				/* (?! */
86665 				advtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD);
86666 			} else if (DUK__L2() == DUK_ASC_COLON) {
86667 				/* (?: */
86668 				advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_START_NONCAPTURE_GROUP);
86669 			} else {
86670 				goto fail_group;
86671 			}
86672 		} else {
86673 			/* ( */
86674 			advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CAPTURE_GROUP);
86675 		}
86676 		break;
86677 	}
86678 	case DUK_ASC_RPAREN: {
86679 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_END_GROUP);
86680 		break;
86681 	}
86682 	case DUK_ASC_LBRACKET: {
86683 		/*
86684 		 *  To avoid creating a heavy intermediate value for the list of ranges,
86685 		 *  only the start token ('[' or '[^') is parsed here.  The regexp
86686 		 *  compiler parses the ranges itself.
86687 		 */
86688 
86689 		/* XXX: with DUK_USE_ES6_REGEXP_SYNTAX we should allow left bracket
86690 		 * literal too, but it's not easy to parse without backtracking.
86691 		 */
86692 
86693 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CHARCLASS);
86694 		if (y == DUK_ASC_CARET) {
86695 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_START_CHARCLASS_INVERTED);
86696 		}
86697 		break;
86698 	}
86699 #if !defined(DUK_USE_ES6_REGEXP_SYNTAX)
86700 	case DUK_ASC_RCURLY:
86701 	case DUK_ASC_RBRACKET: {
86702 		/* Although these could be parsed as PatternCharacters unambiguously (here),
86703 		 * E5 Section 15.10.1 grammar explicitly forbids these as PatternCharacters.
86704 		 */
86705 		goto fail_invalid_char;
86706 		break;
86707 	}
86708 #endif
86709 	case -1: {
86710 		/* EOF */
86711 		advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
86712 		break;
86713 	}
86714 	default: {
86715 		/* PatternCharacter, all excluded characters are matched by cases above */
86716 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
86717 		out_token->num = (duk_uint32_t) x;
86718 		break;
86719 	}
86720 	}
86721 
86722 	/*
86723 	 *  Shared exit path
86724 	 */
86725 
86726 	DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
86727 	out_token->t = advtok & 0xff;
86728 	return;
86729 
86730  fail_token_limit:
86731 	DUK_ERROR_RANGE(lex_ctx->thr, DUK_STR_TOKEN_LIMIT);
86732 	DUK_WO_NORETURN(return;);
86733 
86734  fail_escape:
86735 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_ESCAPE);
86736 	DUK_WO_NORETURN(return;);
86737 
86738  fail_group:
86739 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_GROUP);
86740 	DUK_WO_NORETURN(return;);
86741 
86742 #if !defined(DUK_USE_ES6_REGEXP_SYNTAX)
86743  fail_invalid_char:
86744 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_CHARACTER);
86745 	DUK_WO_NORETURN(return;);
86746 
86747  fail_quantifier:
86748 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_QUANTIFIER);
86749 	DUK_WO_NORETURN(return;);
86750 #endif
86751 }
86752 
86753 /*
86754  *  Special parser for character classes; calls callback for every
86755  *  range parsed and returns the number of ranges present.
86756  */
86757 
86758 /* XXX: this duplicates functionality in duk_regexp.c where a similar loop is
86759  * required anyway.  We could use that BUT we need to update the regexp compiler
86760  * 'nranges' too.  Work this out a bit more cleanly to save space.
86761  */
86762 
86763 /* XXX: the handling of character range detection is a bit convoluted.
86764  * Try to simplify and make smaller.
86765  */
86766 
86767 /* XXX: logic for handling character ranges is now incorrect, it will accept
86768  * e.g. [\d-z] whereas it should croak from it?  SMJS accepts this too, though.
86769  *
86770  * Needs a read through and a lot of additional tests.
86771  */
86772 
86773 DUK_LOCAL
86774 void duk__emit_u16_direct_ranges(duk_lexer_ctx *lex_ctx,
86775                                  duk_re_range_callback gen_range,
86776                                  void *userdata,
86777                                  const duk_uint16_t *ranges,
86778                                  duk_small_int_t num) {
86779 	const duk_uint16_t *ranges_end;
86780 
86781 	DUK_UNREF(lex_ctx);
86782 
86783 	ranges_end = ranges + num;
86784 	while (ranges < ranges_end) {
86785 		/* mark range 'direct', bypass canonicalization (see Wiki) */
86786 		gen_range(userdata, (duk_codepoint_t) ranges[0], (duk_codepoint_t) ranges[1], 1);
86787 		ranges += 2;
86788 	}
86789 }
86790 
86791 DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata) {
86792 	duk_codepoint_t start = -1;
86793 	duk_codepoint_t ch;
86794 	duk_codepoint_t x;
86795 	duk_bool_t dash = 0;
86796 	duk_small_uint_t adv = 0;
86797 
86798 	DUK_DD(DUK_DDPRINT("parsing regexp ranges"));
86799 
86800 	for (;;) {
86801 		DUK__ADVANCECHARS(lex_ctx, adv);
86802 		adv = 1;
86803 
86804 		x = DUK__L0();
86805 
86806 		ch = -1;  /* not strictly necessary, but avoids "uninitialized variable" warnings */
86807 		DUK_UNREF(ch);
86808 
86809 		if (x < 0) {
86810 			goto fail_unterm_charclass;
86811 		} else if (x == DUK_ASC_RBRACKET) {
86812 			if (start >= 0) {
86813 				gen_range(userdata, start, start, 0);
86814 			}
86815 			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat ']' before finishing */
86816 			break;
86817 		} else if (x == DUK_ASC_MINUS) {
86818 			if (start >= 0 && !dash && DUK__L1() != DUK_ASC_RBRACKET) {
86819 				/* '-' as a range indicator */
86820 				dash = 1;
86821 				continue;
86822 			} else {
86823 				/* '-' verbatim */
86824 				ch = x;
86825 			}
86826 		} else if (x == DUK_ASC_BACKSLASH) {
86827 			/*
86828 			 *  The escapes are same as outside a character class, except that \b has a
86829 			 *  different meaning, and \B and backreferences are prohibited (see E5
86830 			 *  Section 15.10.2.19).  However, it's difficult to share code because we
86831 			 *  handle e.g. "\n" very differently: here we generate a single character
86832 			 *  range for it.
86833 			 */
86834 
86835 			/* XXX: ES2015 surrogate pair handling. */
86836 
86837 			x = DUK__L1();
86838 
86839 			adv = 2;
86840 
86841 			if (x == DUK_ASC_LC_B) {
86842 				/* Note: '\b' in char class is different than outside (assertion),
86843 				 * '\B' is not allowed and is caught by the duk_unicode_is_identifier_part()
86844 				 * check below.
86845 				 */
86846 				ch = 0x0008;
86847 			} else if (x == DUK_ASC_LC_F) {
86848 				ch = 0x000c;
86849 			} else if (x == DUK_ASC_LC_N) {
86850 				ch = 0x000a;
86851 			} else if (x == DUK_ASC_LC_T) {
86852 				ch = 0x0009;
86853 			} else if (x == DUK_ASC_LC_R) {
86854 				ch = 0x000d;
86855 			} else if (x == DUK_ASC_LC_V) {
86856 				ch = 0x000b;
86857 			} else if (x == DUK_ASC_LC_C) {
86858 				x = DUK__L2();
86859 				adv = 3;
86860 				if ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) ||
86861 				    (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {
86862 					ch = (x % 32);
86863 				} else {
86864 					goto fail_escape;
86865 				}
86866 			} else if (x == DUK_ASC_LC_X || x == DUK_ASC_LC_U) {
86867 				/* The \u{H+} form is only allowed in Unicode mode which
86868 				 * we don't support yet.
86869 				 */
86870 				ch = duk__lexer_parse_escape(lex_ctx, 0 /*allow_es6*/);
86871 				adv = 0;
86872 			} else if (x == DUK_ASC_LC_D) {
86873 				duk__emit_u16_direct_ranges(lex_ctx,
86874 				                            gen_range,
86875 				                            userdata,
86876 				                            duk_unicode_re_ranges_digit,
86877 				                            sizeof(duk_unicode_re_ranges_digit) / sizeof(duk_uint16_t));
86878 				ch = -1;
86879 			} else if (x == DUK_ASC_UC_D) {
86880 				duk__emit_u16_direct_ranges(lex_ctx,
86881 				                            gen_range,
86882 				                            userdata,
86883 				                            duk_unicode_re_ranges_not_digit,
86884 				                            sizeof(duk_unicode_re_ranges_not_digit) / sizeof(duk_uint16_t));
86885 				ch = -1;
86886 			} else if (x == DUK_ASC_LC_S) {
86887 				duk__emit_u16_direct_ranges(lex_ctx,
86888 				                            gen_range,
86889 				                            userdata,
86890 				                            duk_unicode_re_ranges_white,
86891 				                            sizeof(duk_unicode_re_ranges_white) / sizeof(duk_uint16_t));
86892 				ch = -1;
86893 			} else if (x == DUK_ASC_UC_S) {
86894 				duk__emit_u16_direct_ranges(lex_ctx,
86895 				                            gen_range,
86896 				                            userdata,
86897 				                            duk_unicode_re_ranges_not_white,
86898 				                            sizeof(duk_unicode_re_ranges_not_white) / sizeof(duk_uint16_t));
86899 				ch = -1;
86900 			} else if (x == DUK_ASC_LC_W) {
86901 				duk__emit_u16_direct_ranges(lex_ctx,
86902 				                            gen_range,
86903 				                            userdata,
86904 				                            duk_unicode_re_ranges_wordchar,
86905 				                            sizeof(duk_unicode_re_ranges_wordchar) / sizeof(duk_uint16_t));
86906 				ch = -1;
86907 			} else if (x == DUK_ASC_UC_W) {
86908 				duk__emit_u16_direct_ranges(lex_ctx,
86909 				                            gen_range,
86910 				                            userdata,
86911 				                            duk_unicode_re_ranges_not_wordchar,
86912 				                            sizeof(duk_unicode_re_ranges_not_wordchar) / sizeof(duk_uint16_t));
86913 				ch = -1;
86914 			} else if (DUK__ISDIGIT(x)) {
86915 				/* DecimalEscape, only \0 is allowed, no leading
86916 				 * zeroes are allowed.
86917 				 *
86918 				 * ES2015 Annex B also allows (maximal match) legacy
86919 				 * octal escapes up to \377 and \8 and \9 are
86920 				 * accepted as literal '8' and '9', also in strict mode.
86921 				 */
86922 
86923 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
86924 				ch = duk__lexer_parse_legacy_octal(lex_ctx, &adv, 0 /*reject_annex_b*/);
86925 				DUK_ASSERT(ch >= 0);  /* no rejections */
86926 #else
86927 				if (x == DUK_ASC_0 && !DUK__ISDIGIT(DUK__L2())) {
86928 					ch = 0x0000;
86929 				} else {
86930 					goto fail_escape;
86931 				}
86932 #endif
86933 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
86934 			} else if (x >= 0) {
86935 				/* IdentityEscape: ES2015 Annex B allows almost all
86936 				 * source characters here.  Match anything except
86937 				 * EOF here.
86938 				 */
86939 				ch = x;
86940 #else  /* DUK_USE_ES6_REGEXP_SYNTAX */
86941 			} else if (!duk_unicode_is_identifier_part(x)) {
86942 				/* IdentityEscape: ES5.1 doesn't allow identity escape
86943 				 * for identifier part characters, which conflicts with
86944 				 * some real world code.  For example, it doesn't allow
86945 				 * /[\$]/ which is awkward.
86946 				 */
86947 				ch = x;
86948 #endif  /* DUK_USE_ES6_REGEXP_SYNTAX */
86949 			} else {
86950 				goto fail_escape;
86951 			}
86952 		} else {
86953 			/* character represents itself */
86954 			ch = x;
86955 		}
86956 
86957 		/* ch is a literal character here or -1 if parsed entity was
86958 		 * an escape such as "\s".
86959 		 */
86960 
86961 		if (ch < 0) {
86962 			/* multi-character sets not allowed as part of ranges, see
86963 			 * E5 Section 15.10.2.15, abstract operation CharacterRange.
86964 			 */
86965 			if (start >= 0) {
86966 				if (dash) {
86967 					goto fail_range;
86968 				} else {
86969 					gen_range(userdata, start, start, 0);
86970 					start = -1;
86971 					/* dash is already 0 */
86972 				}
86973 			}
86974 		} else {
86975 			if (start >= 0) {
86976 				if (dash) {
86977 					if (start > ch) {
86978 						goto fail_range;
86979 					}
86980 					gen_range(userdata, start, ch, 0);
86981 					start = -1;
86982 					dash = 0;
86983 				} else {
86984 					gen_range(userdata, start, start, 0);
86985 					start = ch;
86986 					/* dash is already 0 */
86987 				}
86988 			} else {
86989 				start = ch;
86990 			}
86991 		}
86992 	}
86993 
86994 	return;
86995 
86996  fail_escape:
86997 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_ESCAPE);
86998 	DUK_WO_NORETURN(return;);
86999 
87000  fail_range:
87001 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_RANGE);
87002 	DUK_WO_NORETURN(return;);
87003 
87004  fail_unterm_charclass:
87005 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_CHARCLASS);
87006 	DUK_WO_NORETURN(return;);
87007 }
87008 
87009 #endif  /* DUK_USE_REGEXP_SUPPORT */
87010 
87011 /* automatic undefs */
87012 #undef DUK__ADVANCEBYTES
87013 #undef DUK__ADVANCECHARS
87014 #undef DUK__ADVTOK
87015 #undef DUK__APPENDBUFFER
87016 #undef DUK__APPENDBUFFER_ASCII
87017 #undef DUK__INITBUFFER
87018 #undef DUK__ISDIGIT
87019 #undef DUK__ISDIGIT03
87020 #undef DUK__ISDIGIT47
87021 #undef DUK__ISHEXDIGIT
87022 #undef DUK__ISOCTDIGIT
87023 #undef DUK__L0
87024 #undef DUK__L1
87025 #undef DUK__L2
87026 #undef DUK__L3
87027 #undef DUK__L4
87028 #undef DUK__L5
87029 #undef DUK__LOOKUP
87030 #undef DUK__MAX_RE_DECESC_DIGITS
87031 #undef DUK__MAX_RE_QUANT_DIGITS
87032 #line 1 "duk_numconv.c"
87033 /*
87034  *  Number-to-string and string-to-number conversions.
87035  *
87036  *  Slow path number-to-string and string-to-number conversion is based on
87037  *  a Dragon4 variant, with fast paths for small integers.  Big integer
87038  *  arithmetic is needed for guaranteeing that the conversion is correct
87039  *  and uses a minimum number of digits.  The big number arithmetic has a
87040  *  fixed maximum size and does not require dynamic allocations.
87041  *
87042  *  See: doc/number-conversion.rst.
87043  */
87044 
87045 /* #include duk_internal.h -> already included */
87046 
87047 #define DUK__IEEE_DOUBLE_EXP_BIAS  1023
87048 #define DUK__IEEE_DOUBLE_EXP_MIN   (-1022)   /* biased exp == 0 -> denormal, exp -1022 */
87049 
87050 #define DUK__DIGITCHAR(x)  duk_lc_digits[(x)]
87051 
87052 /*
87053  *  Tables generated with util/gennumdigits.py.
87054  *
87055  *  duk__str2num_digits_for_radix indicates, for each radix, how many input
87056  *  digits should be considered significant for string-to-number conversion.
87057  *  The input is also padded to this many digits to give the Dragon4
87058  *  conversion enough (apparent) precision to work with.
87059  *
87060  *  duk__str2num_exp_limits indicates, for each radix, the radix-specific
87061  *  minimum/maximum exponent values (for a Dragon4 integer mantissa)
87062  *  below and above which the number is guaranteed to underflow to zero
87063  *  or overflow to Infinity.  This allows parsing to keep bigint values
87064  *  bounded.
87065  */
87066 
87067 DUK_LOCAL const duk_uint8_t duk__str2num_digits_for_radix[] = {
87068 	69, 44, 35, 30, 27, 25, 23, 22, 20, 20,    /* 2 to 11 */
87069 	20, 19, 19, 18, 18, 17, 17, 17, 16, 16,    /* 12 to 21 */
87070 	16, 16, 16, 15, 15, 15, 15, 15, 15, 14,    /* 22 to 31 */
87071 	14, 14, 14, 14, 14                         /* 31 to 36 */
87072 };
87073 
87074 typedef struct {
87075 	duk_int16_t upper;
87076 	duk_int16_t lower;
87077 } duk__exp_limits;
87078 
87079 DUK_LOCAL const duk__exp_limits duk__str2num_exp_limits[] = {
87080 	{ 957, -1147 }, { 605, -725 },  { 479, -575 },  { 414, -496 },
87081 	{ 372, -446 },  { 342, -411 },  { 321, -384 },  { 304, -364 },
87082 	{ 291, -346 },  { 279, -334 },  { 268, -323 },  { 260, -312 },
87083 	{ 252, -304 },  { 247, -296 },  { 240, -289 },  { 236, -283 },
87084 	{ 231, -278 },  { 227, -273 },  { 223, -267 },  { 220, -263 },
87085 	{ 216, -260 },  { 213, -256 },  { 210, -253 },  { 208, -249 },
87086 	{ 205, -246 },  { 203, -244 },  { 201, -241 },  { 198, -239 },
87087 	{ 196, -237 },  { 195, -234 },  { 193, -232 },  { 191, -230 },
87088 	{ 190, -228 },  { 188, -226 },  { 187, -225 },
87089 };
87090 
87091 /*
87092  *  Limited functionality bigint implementation.
87093  *
87094  *  Restricted to non-negative numbers with less than 32 * DUK__BI_MAX_PARTS bits,
87095  *  with the caller responsible for ensuring this is never exceeded.  No memory
87096  *  allocation (except stack) is needed for bigint computation.  Operations
87097  *  have been tailored for number conversion needs.
87098  *
87099  *  Argument order is "assignment order", i.e. target first, then arguments:
87100  *  x <- y * z  -->  duk__bi_mul(x, y, z);
87101  */
87102 
87103 /* This upper value has been experimentally determined; debug build will check
87104  * bigint size with assertions.
87105  */
87106 #define DUK__BI_MAX_PARTS  37  /* 37x32 = 1184 bits */
87107 
87108 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
87109 #define DUK__BI_PRINT(name,x)  duk__bi_print((name),(x))
87110 #else
87111 #define DUK__BI_PRINT(name,x)
87112 #endif
87113 
87114 /* Current size is about 152 bytes. */
87115 typedef struct {
87116 	duk_small_int_t n;
87117 	duk_uint32_t v[DUK__BI_MAX_PARTS];  /* low to high */
87118 } duk__bigint;
87119 
87120 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
87121 DUK_LOCAL void duk__bi_print(const char *name, duk__bigint *x) {
87122 	/* Overestimate required size; debug code so not critical to be tight. */
87123 	char buf[DUK__BI_MAX_PARTS * 9 + 64];
87124 	char *p = buf;
87125 	duk_small_int_t i;
87126 
87127 	/* No NUL term checks in this debug code. */
87128 	p += DUK_SPRINTF(p, "%p n=%ld", (void *) x, (long) x->n);
87129 	if (x->n == 0) {
87130 		p += DUK_SPRINTF(p, " 0");
87131 	}
87132 	for (i = x->n - 1; i >= 0; i--) {
87133 		p += DUK_SPRINTF(p, " %08lx", (unsigned long) x->v[i]);
87134 	}
87135 
87136 	DUK_DDD(DUK_DDDPRINT("%s: %s", (const char *) name, (const char *) buf));
87137 }
87138 #endif
87139 
87140 #if defined(DUK_USE_ASSERTIONS)
87141 DUK_LOCAL duk_small_int_t duk__bi_is_valid(duk__bigint *x) {
87142 	return (duk_small_int_t)
87143 	       ( ((x->n >= 0) && (x->n <= DUK__BI_MAX_PARTS)) /* is valid size */ &&
87144 	         ((x->n == 0) || (x->v[x->n - 1] != 0)) /* is normalized */ );
87145 }
87146 #endif
87147 
87148 DUK_LOCAL void duk__bi_normalize(duk__bigint *x) {
87149 	duk_small_int_t i;
87150 
87151 	for (i = x->n - 1; i >= 0; i--) {
87152 		if (x->v[i] != 0) {
87153 			break;
87154 		}
87155 	}
87156 
87157 	/* Note: if 'x' is zero, x->n becomes 0 here */
87158 	x->n = i + 1;
87159 	DUK_ASSERT(duk__bi_is_valid(x));
87160 }
87161 
87162 /* x <- y */
87163 DUK_LOCAL void duk__bi_copy(duk__bigint *x, duk__bigint *y) {
87164 	duk_small_int_t n;
87165 
87166 	n = y->n;
87167 	x->n = n;
87168 	/* No need to special case n == 0. */
87169 	duk_memcpy((void *) x->v, (const void *) y->v, (size_t) (sizeof(duk_uint32_t) * (size_t) n));
87170 }
87171 
87172 DUK_LOCAL void duk__bi_set_small(duk__bigint *x, duk_uint32_t v) {
87173 	if (v == 0U) {
87174 		x->n = 0;
87175 	} else {
87176 		x->n = 1;
87177 		x->v[0] = v;
87178 	}
87179 	DUK_ASSERT(duk__bi_is_valid(x));
87180 }
87181 
87182 /* Return value: <0  <=>  x < y
87183  *                0  <=>  x == y
87184  *               >0  <=>  x > y
87185  */
87186 DUK_LOCAL int duk__bi_compare(duk__bigint *x, duk__bigint *y) {
87187 	duk_small_int_t i, nx, ny;
87188 	duk_uint32_t tx, ty;
87189 
87190 	DUK_ASSERT(duk__bi_is_valid(x));
87191 	DUK_ASSERT(duk__bi_is_valid(y));
87192 
87193 	nx = x->n;
87194 	ny = y->n;
87195 	if (nx > ny) {
87196 		goto ret_gt;
87197 	}
87198 	if (nx < ny) {
87199 		goto ret_lt;
87200 	}
87201 	for (i = nx - 1; i >= 0; i--) {
87202 		tx = x->v[i];
87203 		ty = y->v[i];
87204 
87205 		if (tx > ty) {
87206 			goto ret_gt;
87207 		}
87208 		if (tx < ty) {
87209 			goto ret_lt;
87210 		}
87211 	}
87212 
87213 	return 0;
87214 
87215  ret_gt:
87216 	return 1;
87217 
87218  ret_lt:
87219 	return -1;
87220 }
87221 
87222 /* x <- y + z */
87223 #if defined(DUK_USE_64BIT_OPS)
87224 DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
87225 	duk_uint64_t tmp;
87226 	duk_small_int_t i, ny, nz;
87227 
87228 	DUK_ASSERT(duk__bi_is_valid(y));
87229 	DUK_ASSERT(duk__bi_is_valid(z));
87230 
87231 	if (z->n > y->n) {
87232 		duk__bigint *t;
87233 		t = y; y = z; z = t;
87234 	}
87235 	DUK_ASSERT(y->n >= z->n);
87236 
87237 	ny = y->n; nz = z->n;
87238 	tmp = 0U;
87239 	for (i = 0; i < ny; i++) {
87240 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
87241 		tmp += y->v[i];
87242 		if (i < nz) {
87243 			tmp += z->v[i];
87244 		}
87245 		x->v[i] = (duk_uint32_t) (tmp & 0xffffffffUL);
87246 		tmp = tmp >> 32;
87247 	}
87248 	if (tmp != 0U) {
87249 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
87250 		x->v[i++] = (duk_uint32_t) tmp;
87251 	}
87252 	x->n = i;
87253 	DUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);
87254 
87255 	/* no need to normalize */
87256 	DUK_ASSERT(duk__bi_is_valid(x));
87257 }
87258 #else  /* DUK_USE_64BIT_OPS */
87259 DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
87260 	duk_uint32_t carry, tmp1, tmp2;
87261 	duk_small_int_t i, ny, nz;
87262 
87263 	DUK_ASSERT(duk__bi_is_valid(y));
87264 	DUK_ASSERT(duk__bi_is_valid(z));
87265 
87266 	if (z->n > y->n) {
87267 		duk__bigint *t;
87268 		t = y; y = z; z = t;
87269 	}
87270 	DUK_ASSERT(y->n >= z->n);
87271 
87272 	ny = y->n; nz = z->n;
87273 	carry = 0U;
87274 	for (i = 0; i < ny; i++) {
87275 		/* Carry is detected based on wrapping which relies on exact 32-bit
87276 		 * types.
87277 		 */
87278 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
87279 		tmp1 = y->v[i];
87280 		tmp2 = tmp1;
87281 		if (i < nz) {
87282 			tmp2 += z->v[i];
87283 		}
87284 
87285 		/* Careful with carry condition:
87286 		 *  - If carry not added: 0x12345678 + 0 + 0xffffffff = 0x12345677 (< 0x12345678)
87287 		 *  - If carry added:     0x12345678 + 1 + 0xffffffff = 0x12345678 (== 0x12345678)
87288 		 */
87289 		if (carry) {
87290 			tmp2++;
87291 			carry = (tmp2 <= tmp1 ? 1U : 0U);
87292 		} else {
87293 			carry = (tmp2 < tmp1 ? 1U : 0U);
87294 		}
87295 
87296 		x->v[i] = tmp2;
87297 	}
87298 	if (carry) {
87299 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
87300 		DUK_ASSERT(carry == 1U);
87301 		x->v[i++] = carry;
87302 	}
87303 	x->n = i;
87304 	DUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);
87305 
87306 	/* no need to normalize */
87307 	DUK_ASSERT(duk__bi_is_valid(x));
87308 }
87309 #endif  /* DUK_USE_64BIT_OPS */
87310 
87311 /* x <- y + z */
87312 DUK_LOCAL void duk__bi_add_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
87313 	duk__bigint tmp;
87314 
87315 	DUK_ASSERT(duk__bi_is_valid(y));
87316 
87317 	/* XXX: this could be optimized; there is only one call site now though */
87318 	duk__bi_set_small(&tmp, z);
87319 	duk__bi_add(x, y, &tmp);
87320 
87321 	DUK_ASSERT(duk__bi_is_valid(x));
87322 }
87323 
87324 #if 0  /* unused */
87325 /* x <- x + y, use t as temp */
87326 DUK_LOCAL void duk__bi_add_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
87327 	duk__bi_add(t, x, y);
87328 	duk__bi_copy(x, t);
87329 }
87330 #endif
87331 
87332 /* x <- y - z, require x >= y => z >= 0, i.e. y >= z */
87333 #if defined(DUK_USE_64BIT_OPS)
87334 DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
87335 	duk_small_int_t i, ny, nz;
87336 	duk_uint32_t ty, tz;
87337 	duk_int64_t tmp;
87338 
87339 	DUK_ASSERT(duk__bi_is_valid(y));
87340 	DUK_ASSERT(duk__bi_is_valid(z));
87341 	DUK_ASSERT(duk__bi_compare(y, z) >= 0);
87342 	DUK_ASSERT(y->n >= z->n);
87343 
87344 	ny = y->n; nz = z->n;
87345 	tmp = 0;
87346 	for (i = 0; i < ny; i++) {
87347 		ty = y->v[i];
87348 		if (i < nz) {
87349 			tz = z->v[i];
87350 		} else {
87351 			tz = 0;
87352 		}
87353 		tmp = (duk_int64_t) ty - (duk_int64_t) tz + tmp;
87354 		x->v[i] = (duk_uint32_t) ((duk_uint64_t) tmp & 0xffffffffUL);
87355 		tmp = tmp >> 32;  /* 0 or -1 */
87356 	}
87357 	DUK_ASSERT(tmp == 0);
87358 
87359 	x->n = i;
87360 	duk__bi_normalize(x);  /* need to normalize, may even cancel to 0 */
87361 	DUK_ASSERT(duk__bi_is_valid(x));
87362 }
87363 #else
87364 DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
87365 	duk_small_int_t i, ny, nz;
87366 	duk_uint32_t tmp1, tmp2, borrow;
87367 
87368 	DUK_ASSERT(duk__bi_is_valid(y));
87369 	DUK_ASSERT(duk__bi_is_valid(z));
87370 	DUK_ASSERT(duk__bi_compare(y, z) >= 0);
87371 	DUK_ASSERT(y->n >= z->n);
87372 
87373 	ny = y->n; nz = z->n;
87374 	borrow = 0U;
87375 	for (i = 0; i < ny; i++) {
87376 		/* Borrow is detected based on wrapping which relies on exact 32-bit
87377 		 * types.
87378 		 */
87379 		tmp1 = y->v[i];
87380 		tmp2 = tmp1;
87381 		if (i < nz) {
87382 			tmp2 -= z->v[i];
87383 		}
87384 
87385 		/* Careful with borrow condition:
87386 		 *  - If borrow not subtracted: 0x12345678 - 0 - 0xffffffff = 0x12345679 (> 0x12345678)
87387 		 *  - If borrow subtracted:     0x12345678 - 1 - 0xffffffff = 0x12345678 (== 0x12345678)
87388 		 */
87389 		if (borrow) {
87390 			tmp2--;
87391 			borrow = (tmp2 >= tmp1 ? 1U : 0U);
87392 		} else {
87393 			borrow = (tmp2 > tmp1 ? 1U : 0U);
87394 		}
87395 
87396 		x->v[i] = tmp2;
87397 	}
87398 	DUK_ASSERT(borrow == 0U);
87399 
87400 	x->n = i;
87401 	duk__bi_normalize(x);  /* need to normalize, may even cancel to 0 */
87402 	DUK_ASSERT(duk__bi_is_valid(x));
87403 }
87404 #endif
87405 
87406 #if 0  /* unused */
87407 /* x <- y - z */
87408 DUK_LOCAL void duk__bi_sub_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
87409 	duk__bigint tmp;
87410 
87411 	DUK_ASSERT(duk__bi_is_valid(y));
87412 
87413 	/* XXX: this could be optimized */
87414 	duk__bi_set_small(&tmp, z);
87415 	duk__bi_sub(x, y, &tmp);
87416 
87417 	DUK_ASSERT(duk__bi_is_valid(x));
87418 }
87419 #endif
87420 
87421 /* x <- x - y, use t as temp */
87422 DUK_LOCAL void duk__bi_sub_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
87423 	duk__bi_sub(t, x, y);
87424 	duk__bi_copy(x, t);
87425 }
87426 
87427 /* x <- y * z */
87428 DUK_LOCAL void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
87429 	duk_small_int_t i, j, nx, nz;
87430 
87431 	DUK_ASSERT(duk__bi_is_valid(y));
87432 	DUK_ASSERT(duk__bi_is_valid(z));
87433 
87434 	nx = y->n + z->n;  /* max possible */
87435 	DUK_ASSERT(nx <= DUK__BI_MAX_PARTS);
87436 
87437 	if (nx == 0) {
87438 		/* Both inputs are zero; cases where only one is zero can go
87439 		 * through main algorithm.
87440 		 */
87441 		x->n = 0;
87442 		return;
87443 	}
87444 
87445 	duk_memzero((void *) x->v, (size_t) (sizeof(duk_uint32_t) * (size_t) nx));
87446 	x->n = nx;
87447 
87448 	nz = z->n;
87449 	for (i = 0; i < y->n; i++) {
87450 #if defined(DUK_USE_64BIT_OPS)
87451 		duk_uint64_t tmp = 0U;
87452 		for (j = 0; j < nz; j++) {
87453 			tmp += (duk_uint64_t) y->v[i] * (duk_uint64_t) z->v[j] + x->v[i+j];
87454 			x->v[i+j] = (duk_uint32_t) (tmp & 0xffffffffUL);
87455 			tmp = tmp >> 32;
87456 		}
87457 		if (tmp > 0) {
87458 			DUK_ASSERT(i + j < nx);
87459 			DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
87460 			DUK_ASSERT(x->v[i+j] == 0U);
87461 			x->v[i+j] = (duk_uint32_t) tmp;
87462 		}
87463 #else
87464 		/*
87465 		 *  Multiply + add + carry for 32-bit components using only 16x16->32
87466 		 *  multiplies and carry detection based on unsigned overflow.
87467 		 *
87468 		 *    1st mult, 32-bit: (A*2^16 + B)
87469 		 *    2nd mult, 32-bit: (C*2^16 + D)
87470 		 *    3rd add, 32-bit: E
87471 		 *    4th add, 32-bit: F
87472 		 *
87473 		 *      (AC*2^16 + B) * (C*2^16 + D) + E + F
87474 		 *    = AC*2^32 + AD*2^16 + BC*2^16 + BD + E + F
87475 		 *    = AC*2^32 + (AD + BC)*2^16 + (BD + E + F)
87476 		 *    = AC*2^32 + AD*2^16 + BC*2^16 + (BD + E + F)
87477 		 */
87478 		duk_uint32_t a, b, c, d, e, f;
87479 		duk_uint32_t r, s, t;
87480 
87481 		a = y->v[i]; b = a & 0xffffUL; a = a >> 16;
87482 
87483 		f = 0;
87484 		for (j = 0; j < nz; j++) {
87485 			c = z->v[j]; d = c & 0xffffUL; c = c >> 16;
87486 			e = x->v[i+j];
87487 
87488 			/* build result as: (r << 32) + s: start with (BD + E + F) */
87489 			r = 0;
87490 			s = b * d;
87491 
87492 			/* add E */
87493 			t = s + e;
87494 			if (t < s) { r++; }  /* carry */
87495 			s = t;
87496 
87497 			/* add F */
87498 			t = s + f;
87499 			if (t < s) { r++; }  /* carry */
87500 			s = t;
87501 
87502 			/* add BC*2^16 */
87503 			t = b * c;
87504 			r += (t >> 16);
87505 			t = s + ((t & 0xffffUL) << 16);
87506 			if (t < s) { r++; }  /* carry */
87507 			s = t;
87508 
87509 			/* add AD*2^16 */
87510 			t = a * d;
87511 			r += (t >> 16);
87512 			t = s + ((t & 0xffffUL) << 16);
87513 			if (t < s) { r++; }  /* carry */
87514 			s = t;
87515 
87516 			/* add AC*2^32 */
87517 			t = a * c;
87518 			r += t;
87519 
87520 			DUK_DDD(DUK_DDDPRINT("ab=%08lx cd=%08lx ef=%08lx -> rs=%08lx %08lx",
87521 			                     (unsigned long) y->v[i], (unsigned long) z->v[j],
87522 			                     (unsigned long) x->v[i+j], (unsigned long) r,
87523 			                     (unsigned long) s));
87524 
87525 			x->v[i+j] = s;
87526 			f = r;
87527 		}
87528 		if (f > 0U) {
87529 			DUK_ASSERT(i + j < nx);
87530 			DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
87531 			DUK_ASSERT(x->v[i+j] == 0U);
87532 			x->v[i+j] = (duk_uint32_t) f;
87533 		}
87534 #endif  /* DUK_USE_64BIT_OPS */
87535 	}
87536 
87537 	duk__bi_normalize(x);
87538 	DUK_ASSERT(duk__bi_is_valid(x));
87539 }
87540 
87541 /* x <- y * z */
87542 DUK_LOCAL void duk__bi_mul_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
87543 	duk__bigint tmp;
87544 
87545 	DUK_ASSERT(duk__bi_is_valid(y));
87546 
87547 	/* XXX: this could be optimized */
87548 	duk__bi_set_small(&tmp, z);
87549 	duk__bi_mul(x, y, &tmp);
87550 
87551 	DUK_ASSERT(duk__bi_is_valid(x));
87552 }
87553 
87554 /* x <- x * y, use t as temp */
87555 DUK_LOCAL void duk__bi_mul_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
87556 	duk__bi_mul(t, x, y);
87557 	duk__bi_copy(x, t);
87558 }
87559 
87560 /* x <- x * y, use t as temp */
87561 DUK_LOCAL void duk__bi_mul_small_copy(duk__bigint *x, duk_uint32_t y, duk__bigint *t) {
87562 	duk__bi_mul_small(t, x, y);
87563 	duk__bi_copy(x, t);
87564 }
87565 
87566 DUK_LOCAL int duk__bi_is_even(duk__bigint *x) {
87567 	DUK_ASSERT(duk__bi_is_valid(x));
87568 	return (x->n == 0) || ((x->v[0] & 0x01) == 0);
87569 }
87570 
87571 DUK_LOCAL int duk__bi_is_zero(duk__bigint *x) {
87572 	DUK_ASSERT(duk__bi_is_valid(x));
87573 	return (x->n == 0);  /* this is the case for normalized numbers */
87574 }
87575 
87576 /* Bigint is 2^52.  Used to detect normalized IEEE double mantissa values
87577  * which are at the lowest edge (next floating point value downwards has
87578  * a different exponent).  The lowest mantissa has the form:
87579  *
87580  *     1000........000    (52 zeroes; only "hidden bit" is set)
87581  */
87582 DUK_LOCAL duk_small_int_t duk__bi_is_2to52(duk__bigint *x) {
87583 	DUK_ASSERT(duk__bi_is_valid(x));
87584 	return (duk_small_int_t)
87585 	        (x->n == 2) && (x->v[0] == 0U) && (x->v[1] == (1U << (52-32)));
87586 }
87587 
87588 /* x <- (1<<y) */
87589 DUK_LOCAL void duk__bi_twoexp(duk__bigint *x, duk_small_int_t y) {
87590 	duk_small_int_t n, r;
87591 
87592 	n = (y / 32) + 1;
87593 	DUK_ASSERT(n > 0);
87594 	r = y % 32;
87595 	duk_memzero((void *) x->v, sizeof(duk_uint32_t) * (size_t) n);
87596 	x->n = n;
87597 	x->v[n - 1] = (((duk_uint32_t) 1) << r);
87598 }
87599 
87600 /* x <- b^y; use t1 and t2 as temps */
87601 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) {
87602 	/* Fast path the binary case */
87603 
87604 	DUK_ASSERT(x != t1 && x != t2 && t1 != t2);  /* distinct bignums, easy mistake to make */
87605 	DUK_ASSERT(b >= 0);
87606 	DUK_ASSERT(y >= 0);
87607 
87608 	if (b == 2) {
87609 		duk__bi_twoexp(x, y);
87610 		return;
87611 	}
87612 
87613 	/* http://en.wikipedia.org/wiki/Exponentiation_by_squaring */
87614 
87615 	DUK_DDD(DUK_DDDPRINT("exp_small: b=%ld, y=%ld", (long) b, (long) y));
87616 
87617 	duk__bi_set_small(x, 1);
87618 	duk__bi_set_small(t1, (duk_uint32_t) b);
87619 	for (;;) {
87620 		/* Loop structure ensures that we don't compute t1^2 unnecessarily
87621 		 * on the final round, as that might create a bignum exceeding the
87622 		 * current DUK__BI_MAX_PARTS limit.
87623 		 */
87624 		if (y & 0x01) {
87625 			duk__bi_mul_copy(x, t1, t2);
87626 		}
87627 		y = y >> 1;
87628 		if (y == 0) {
87629 			break;
87630 		}
87631 		duk__bi_mul_copy(t1, t1, t2);
87632 	}
87633 
87634 	DUK__BI_PRINT("exp_small result", x);
87635 }
87636 
87637 /*
87638  *  A Dragon4 number-to-string variant, based on:
87639  *
87640  *    Guy L. Steele Jr., Jon L. White: "How to Print Floating-Point Numbers
87641  *    Accurately"
87642  *
87643  *    Robert G. Burger, R. Kent Dybvig: "Printing Floating-Point Numbers
87644  *    Quickly and Accurately"
87645  *
87646  *  The current algorithm is based on Figure 1 of the Burger-Dybvig paper,
87647  *  i.e. the base implementation without logarithm estimation speedups
87648  *  (these would increase code footprint considerably).  Fixed-format output
87649  *  does not follow the suggestions in the paper; instead, we generate an
87650  *  extra digit and round-with-carry.
87651  *
87652  *  The same algorithm is used for number parsing (with b=10 and B=2)
87653  *  by generating one extra digit and doing rounding manually.
87654  *
87655  *  See doc/number-conversion.rst for limitations.
87656  */
87657 
87658 /* Maximum number of digits generated. */
87659 #define DUK__MAX_OUTPUT_DIGITS          1040  /* (Number.MAX_VALUE).toString(2).length == 1024, + slack */
87660 
87661 /* Maximum number of characters in formatted value. */
87662 #define DUK__MAX_FORMATTED_LENGTH       1040  /* (-Number.MAX_VALUE).toString(2).length == 1025, + slack */
87663 
87664 /* Number and (minimum) size of bigints in the nc_ctx structure. */
87665 #define DUK__NUMCONV_CTX_NUM_BIGINTS    7
87666 #define DUK__NUMCONV_CTX_BIGINTS_SIZE   (sizeof(duk__bigint) * DUK__NUMCONV_CTX_NUM_BIGINTS)
87667 
87668 typedef struct {
87669 	/* Currently about 7*152 = 1064 bytes.  The space for these
87670 	 * duk__bigints is used also as a temporary buffer for generating
87671 	 * the final string.  This is a bit awkard; a union would be
87672 	 * more correct.
87673 	 */
87674 	duk__bigint f, r, s, mp, mm, t1, t2;
87675 
87676 	duk_small_int_t is_s2n;        /* if 1, doing a string-to-number; else doing a number-to-string */
87677 	duk_small_int_t is_fixed;      /* if 1, doing a fixed format output (not free format) */
87678 	duk_small_int_t req_digits;    /* requested number of output digits; 0 = free-format */
87679 	duk_small_int_t abs_pos;       /* digit position is absolute, not relative */
87680 	duk_small_int_t e;             /* exponent for 'f' */
87681 	duk_small_int_t b;             /* input radix */
87682 	duk_small_int_t B;             /* output radix */
87683 	duk_small_int_t k;             /* see algorithm */
87684 	duk_small_int_t low_ok;        /* see algorithm */
87685 	duk_small_int_t high_ok;       /* see algorithm */
87686 	duk_small_int_t unequal_gaps;  /* m+ != m- (very rarely) */
87687 
87688 	/* Buffer used for generated digits, values are in the range [0,B-1]. */
87689 	duk_uint8_t digits[DUK__MAX_OUTPUT_DIGITS];
87690 	duk_small_int_t count;  /* digit count */
87691 } duk__numconv_stringify_ctx;
87692 
87693 /* Note: computes with 'idx' in assertions, so caller beware.
87694  * 'idx' is preincremented, i.e. '1' on first call, because it
87695  * is more convenient for the caller.
87696  */
87697 #define DUK__DRAGON4_OUTPUT_PREINC(nc_ctx,preinc_idx,x)  do { \
87698 		DUK_ASSERT((preinc_idx) - 1 >= 0); \
87699 		DUK_ASSERT((preinc_idx) - 1 < DUK__MAX_OUTPUT_DIGITS); \
87700 		((nc_ctx)->digits[(preinc_idx) - 1]) = (duk_uint8_t) (x); \
87701 	} while (0)
87702 
87703 DUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x, duk_small_int_t radix) {
87704 	duk_uint8_t *p;
87705 	duk_size_t len;
87706 	duk_small_int_t dig;
87707 	duk_uint32_t t;
87708 
87709 	DUK_ASSERT(buf != NULL);
87710 	DUK_ASSERT(radix >= 2 && radix <= 36);
87711 
87712 	/* A 32-bit unsigned integer formats to at most 32 digits (the
87713 	 * worst case happens with radix == 2).  Output the digits backwards,
87714 	 * and use a memmove() to get them in the right place.
87715 	 */
87716 
87717 	p = buf + 32;
87718 	for (;;) {
87719 		t = x / (duk_uint32_t) radix;
87720 		dig = (duk_small_int_t) (x - t * (duk_uint32_t) radix);
87721 		x = t;
87722 
87723 		DUK_ASSERT(dig >= 0 && dig < 36);
87724 		*(--p) = DUK__DIGITCHAR(dig);
87725 
87726 		if (x == 0) {
87727 			break;
87728 		}
87729 	}
87730 	len = (duk_size_t) ((buf + 32) - p);
87731 
87732 	duk_memmove((void *) buf, (const void *) p, (size_t) len);
87733 
87734 	return len;
87735 }
87736 
87737 DUK_LOCAL void duk__dragon4_prepare(duk__numconv_stringify_ctx *nc_ctx) {
87738 	duk_small_int_t lowest_mantissa;
87739 
87740 #if 1
87741 	/* Assume IEEE round-to-even, so that shorter encoding can be used
87742 	 * when round-to-even would produce correct result.  By removing
87743 	 * this check (and having low_ok == high_ok == 0) the results would
87744 	 * still be accurate but in some cases longer than necessary.
87745 	 */
87746 	if (duk__bi_is_even(&nc_ctx->f)) {
87747 		DUK_DDD(DUK_DDDPRINT("f is even"));
87748 		nc_ctx->low_ok = 1;
87749 		nc_ctx->high_ok = 1;
87750 	} else {
87751 		DUK_DDD(DUK_DDDPRINT("f is odd"));
87752 		nc_ctx->low_ok = 0;
87753 		nc_ctx->high_ok = 0;
87754 	}
87755 #else
87756 	/* Note: not honoring round-to-even should work but now generates incorrect
87757 	 * results.  For instance, 1e23 serializes to "a000...", i.e. the first digit
87758 	 * equals the radix (10).  Scaling stops one step too early in this case.
87759 	 * Don't know why this is the case, but since this code path is unused, it
87760 	 * doesn't matter.
87761 	 */
87762 	nc_ctx->low_ok = 0;
87763 	nc_ctx->high_ok = 0;
87764 #endif
87765 
87766 	/* For string-to-number, pretend we never have the lowest mantissa as there
87767 	 * is no natural "precision" for inputs.  Having lowest_mantissa == 0, we'll
87768 	 * fall into the base cases for both e >= 0 and e < 0.
87769 	 */
87770 	if (nc_ctx->is_s2n) {
87771 		lowest_mantissa = 0;
87772 	} else {
87773 		lowest_mantissa = duk__bi_is_2to52(&nc_ctx->f);
87774 	}
87775 
87776 	nc_ctx->unequal_gaps = 0;
87777 	if (nc_ctx->e >= 0) {
87778 		/* exponent non-negative (and thus not minimum exponent) */
87779 
87780 		if (lowest_mantissa) {
87781 			/* (>= e 0) AND (= f (expt b (- p 1)))
87782 			 *
87783 			 * be <- (expt b e) == b^e
87784 			 * be1 <- (* be b) == (expt b (+ e 1)) == b^(e+1)
87785 			 * r <- (* f be1 2) == 2 * f * b^(e+1)    [if b==2 -> f * b^(e+2)]
87786 			 * s <- (* b 2)                           [if b==2 -> 4]
87787 			 * m+ <- be1 == b^(e+1)
87788 			 * m- <- be == b^e
87789 			 * k <- 0
87790 			 * B <- B
87791 			 * low_ok <- round
87792 			 * high_ok <- round
87793 			 */
87794 
87795 			DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
87796 			                     "lowest mantissa value for this exponent -> "
87797 			                     "unequal gaps"));
87798 
87799 			duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2);  /* mm <- b^e */
87800 			duk__bi_mul_small(&nc_ctx->mp, &nc_ctx->mm, (duk_uint32_t) nc_ctx->b);           /* mp <- b^(e+1) */
87801 			duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
87802 			duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp);              /* r <- (2 * f) * b^(e+1) */
87803 			duk__bi_set_small(&nc_ctx->s, (duk_uint32_t) (nc_ctx->b * 2));  /* s <- 2 * b */
87804 			nc_ctx->unequal_gaps = 1;
87805 		} else {
87806 			/* (>= e 0) AND (not (= f (expt b (- p 1))))
87807 			 *
87808 			 * be <- (expt b e) == b^e
87809 			 * r <- (* f be 2) == 2 * f * b^e    [if b==2 -> f * b^(e+1)]
87810 			 * s <- 2
87811 			 * m+ <- be == b^e
87812 			 * m- <- be == b^e
87813 			 * k <- 0
87814 			 * B <- B
87815 			 * low_ok <- round
87816 			 * high_ok <- round
87817 			 */
87818 
87819 			DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
87820 			                     "not lowest mantissa for this exponent -> "
87821 			                     "equal gaps"));
87822 
87823 			duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2);  /* mm <- b^e */
87824 			duk__bi_copy(&nc_ctx->mp, &nc_ctx->mm);                /* mp <- b^e */
87825 			duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
87826 			duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp);     /* r <- (2 * f) * b^e */
87827 			duk__bi_set_small(&nc_ctx->s, 2);                      /* s <- 2 */
87828 		}
87829 	} else {
87830 		/* When doing string-to-number, lowest_mantissa is always 0 so
87831 		 * the exponent check, while incorrect, won't matter.
87832 		 */
87833 		if (nc_ctx->e > DUK__IEEE_DOUBLE_EXP_MIN /*not minimum exponent*/ &&
87834 		    lowest_mantissa /* lowest mantissa for this exponent*/) {
87835 			/* r <- (* f b 2)                                [if b==2 -> (* f 4)]
87836 			 * s <- (* (expt b (- 1 e)) 2) == b^(1-e) * 2    [if b==2 -> b^(2-e)]
87837 			 * m+ <- b == 2
87838 			 * m- <- 1
87839 			 * k <- 0
87840 			 * B <- B
87841 			 * low_ok <- round
87842 			 * high_ok <- round
87843 			 */
87844 
87845 			DUK_DDD(DUK_DDDPRINT("negative exponent; not minimum exponent and "
87846 			                     "lowest mantissa for this exponent -> "
87847 			                     "unequal gaps"));
87848 
87849 			duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, (duk_uint32_t) (nc_ctx->b * 2));  /* r <- (2 * b) * f */
87850 			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 */
87851 			duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2);             /* s <- b^(1-e) * 2 */
87852 			duk__bi_set_small(&nc_ctx->mp, 2);
87853 			duk__bi_set_small(&nc_ctx->mm, 1);
87854 			nc_ctx->unequal_gaps = 1;
87855 		} else {
87856 			/* r <- (* f 2)
87857 			 * s <- (* (expt b (- e)) 2) == b^(-e) * 2    [if b==2 -> b^(1-e)]
87858 			 * m+ <- 1
87859 			 * m- <- 1
87860 			 * k <- 0
87861 			 * B <- B
87862 			 * low_ok <- round
87863 			 * high_ok <- round
87864 			 */
87865 
87866 			DUK_DDD(DUK_DDDPRINT("negative exponent; minimum exponent or not "
87867 			                     "lowest mantissa for this exponent -> "
87868 			                     "equal gaps"));
87869 
87870 			duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, 2);            /* r <- 2 * f */
87871 			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 */
87872 			duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2);           /* s <- b^(-e) * 2 */
87873 			duk__bi_set_small(&nc_ctx->mp, 1);
87874 			duk__bi_set_small(&nc_ctx->mm, 1);
87875 		}
87876 	}
87877 }
87878 
87879 DUK_LOCAL void duk__dragon4_scale(duk__numconv_stringify_ctx *nc_ctx) {
87880 	duk_small_int_t k = 0;
87881 
87882 	/* This is essentially the 'scale' algorithm, with recursion removed.
87883 	 * Note that 'k' is either correct immediately, or will move in one
87884 	 * direction in the loop.  There's no need to do the low/high checks
87885 	 * on every round (like the Scheme algorithm does).
87886 	 *
87887 	 * The scheme algorithm finds 'k' and updates 's' simultaneously,
87888 	 * while the logical algorithm finds 'k' with 's' having its initial
87889 	 * value, after which 's' is updated separately (see the Burger-Dybvig
87890 	 * paper, Section 3.1, steps 2 and 3).
87891 	 *
87892 	 * The case where m+ == m- (almost always) is optimized for, because
87893 	 * it reduces the bigint operations considerably and almost always
87894 	 * applies.  The scale loop only needs to work with m+, so this works.
87895 	 */
87896 
87897 	/* XXX: this algorithm could be optimized quite a lot by using e.g.
87898 	 * a logarithm based estimator for 'k' and performing B^n multiplication
87899 	 * using a lookup table or using some bit-representation based exp
87900 	 * algorithm.  Currently we just loop, with significant performance
87901 	 * impact for very large and very small numbers.
87902 	 */
87903 
87904 	DUK_DDD(DUK_DDDPRINT("scale: B=%ld, low_ok=%ld, high_ok=%ld",
87905 	                     (long) nc_ctx->B, (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
87906 	DUK__BI_PRINT("r(init)", &nc_ctx->r);
87907 	DUK__BI_PRINT("s(init)", &nc_ctx->s);
87908 	DUK__BI_PRINT("mp(init)", &nc_ctx->mp);
87909 	DUK__BI_PRINT("mm(init)", &nc_ctx->mm);
87910 
87911 	for (;;) {
87912 		DUK_DDD(DUK_DDDPRINT("scale loop (inc k), k=%ld", (long) k));
87913 		DUK__BI_PRINT("r", &nc_ctx->r);
87914 		DUK__BI_PRINT("s", &nc_ctx->s);
87915 		DUK__BI_PRINT("m+", &nc_ctx->mp);
87916 		DUK__BI_PRINT("m-", &nc_ctx->mm);
87917 
87918 		duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 = (+ r m+) */
87919 		if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1)) {
87920 			DUK_DDD(DUK_DDDPRINT("k is too low"));
87921 			/* r <- r
87922 			 * s <- (* s B)
87923 			 * m+ <- m+
87924 			 * m- <- m-
87925 			 * k <- (+ k 1)
87926 			 */
87927 
87928 			duk__bi_mul_small_copy(&nc_ctx->s, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
87929 			k++;
87930 		} else {
87931 			break;
87932 		}
87933 	}
87934 
87935 	/* k > 0 -> k was too low, and cannot be too high */
87936 	if (k > 0) {
87937 		goto skip_dec_k;
87938 	}
87939 
87940 	for (;;) {
87941 		DUK_DDD(DUK_DDDPRINT("scale loop (dec k), k=%ld", (long) k));
87942 		DUK__BI_PRINT("r", &nc_ctx->r);
87943 		DUK__BI_PRINT("s", &nc_ctx->s);
87944 		DUK__BI_PRINT("m+", &nc_ctx->mp);
87945 		DUK__BI_PRINT("m-", &nc_ctx->mm);
87946 
87947 		duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 = (+ r m+) */
87948 		duk__bi_mul_small(&nc_ctx->t2, &nc_ctx->t1, (duk_uint32_t) nc_ctx->B);   /* t2 = (* (+ r m+) B) */
87949 		if (duk__bi_compare(&nc_ctx->t2, &nc_ctx->s) <= (nc_ctx->high_ok ? -1 : 0)) {
87950 			DUK_DDD(DUK_DDDPRINT("k is too high"));
87951 			/* r <- (* r B)
87952 			 * s <- s
87953 			 * m+ <- (* m+ B)
87954 			 * m- <- (* m- B)
87955 			 * k <- (- k 1)
87956 			 */
87957 			duk__bi_mul_small_copy(&nc_ctx->r, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
87958 			duk__bi_mul_small_copy(&nc_ctx->mp, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
87959 			if (nc_ctx->unequal_gaps) {
87960 				DUK_DDD(DUK_DDDPRINT("m+ != m- -> need to update m- too"));
87961 				duk__bi_mul_small_copy(&nc_ctx->mm, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
87962 			}
87963 			k--;
87964 		} else {
87965 			break;
87966 		}
87967 	}
87968 
87969  skip_dec_k:
87970 
87971 	if (!nc_ctx->unequal_gaps) {
87972 		DUK_DDD(DUK_DDDPRINT("equal gaps, copy m- from m+"));
87973 		duk__bi_copy(&nc_ctx->mm, &nc_ctx->mp);  /* mm <- mp */
87974 	}
87975 	nc_ctx->k = k;
87976 
87977 	DUK_DDD(DUK_DDDPRINT("final k: %ld", (long) k));
87978 	DUK__BI_PRINT("r(final)", &nc_ctx->r);
87979 	DUK__BI_PRINT("s(final)", &nc_ctx->s);
87980 	DUK__BI_PRINT("mp(final)", &nc_ctx->mp);
87981 	DUK__BI_PRINT("mm(final)", &nc_ctx->mm);
87982 }
87983 
87984 DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) {
87985 	duk_small_int_t tc1, tc2;    /* terminating conditions */
87986 	duk_small_int_t d;           /* current digit */
87987 	duk_small_int_t count = 0;   /* digit count */
87988 
87989 	/*
87990 	 *  Digit generation loop.
87991 	 *
87992 	 *  Different termination conditions:
87993 	 *
87994 	 *    1. Free format output.  Terminate when shortest accurate
87995 	 *       representation found.
87996 	 *
87997 	 *    2. Fixed format output, with specific number of digits.
87998 	 *       Ignore termination conditions, terminate when digits
87999 	 *       generated.  Caller requests an extra digit and rounds.
88000 	 *
88001 	 *    3. Fixed format output, with a specific absolute cut-off
88002 	 *       position (e.g. 10 digits after decimal point).  Note
88003 	 *       that we always generate at least one digit, even if
88004 	 *       the digit is below the cut-off point already.
88005 	 */
88006 
88007 	for (;;) {
88008 		DUK_DDD(DUK_DDDPRINT("generate loop, count=%ld, k=%ld, B=%ld, low_ok=%ld, high_ok=%ld",
88009 		                     (long) count, (long) nc_ctx->k, (long) nc_ctx->B,
88010 		                     (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
88011 		DUK__BI_PRINT("r", &nc_ctx->r);
88012 		DUK__BI_PRINT("s", &nc_ctx->s);
88013 		DUK__BI_PRINT("m+", &nc_ctx->mp);
88014 		DUK__BI_PRINT("m-", &nc_ctx->mm);
88015 
88016 		/* (quotient-remainder (* r B) s) using a dummy subtraction loop */
88017 		duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, (duk_uint32_t) nc_ctx->B);       /* t1 <- (* r B) */
88018 		d = 0;
88019 		for (;;) {
88020 			if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {
88021 				break;
88022 			}
88023 			duk__bi_sub_copy(&nc_ctx->t1, &nc_ctx->s, &nc_ctx->t2);  /* t1 <- t1 - s */
88024 			d++;
88025 		}
88026 		duk__bi_copy(&nc_ctx->r, &nc_ctx->t1);  /* r <- (remainder (* r B) s) */
88027 		                                        /* d <- (quotient (* r B) s)   (in range 0...B-1) */
88028 		DUK_DDD(DUK_DDDPRINT("-> d(quot)=%ld", (long) d));
88029 		DUK__BI_PRINT("r(rem)", &nc_ctx->r);
88030 
88031 		duk__bi_mul_small_copy(&nc_ctx->mp, (duk_uint32_t) nc_ctx->B, &nc_ctx->t2); /* m+ <- (* m+ B) */
88032 		duk__bi_mul_small_copy(&nc_ctx->mm, (duk_uint32_t) nc_ctx->B, &nc_ctx->t2); /* m- <- (* m- B) */
88033 		DUK__BI_PRINT("mp(upd)", &nc_ctx->mp);
88034 		DUK__BI_PRINT("mm(upd)", &nc_ctx->mm);
88035 
88036 		/* Terminating conditions.  For fixed width output, we just ignore the
88037 		 * terminating conditions (and pretend that tc1 == tc2 == false).  The
88038 		 * the current shortcut for fixed-format output is to generate a few
88039 		 * extra digits and use rounding (with carry) to finish the output.
88040 		 */
88041 
88042 		if (nc_ctx->is_fixed == 0) {
88043 			/* free-form */
88044 			tc1 = (duk__bi_compare(&nc_ctx->r, &nc_ctx->mm) <= (nc_ctx->low_ok ? 0 : -1));
88045 
88046 			duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 <- (+ r m+) */
88047 			tc2 = (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1));
88048 
88049 			DUK_DDD(DUK_DDDPRINT("tc1=%ld, tc2=%ld", (long) tc1, (long) tc2));
88050 		} else {
88051 			/* fixed-format */
88052 			tc1 = 0;
88053 			tc2 = 0;
88054 		}
88055 
88056 		/* Count is incremented before DUK__DRAGON4_OUTPUT_PREINC() call
88057 		 * on purpose, which is taken into account by the macro.
88058 		 */
88059 		count++;
88060 
88061 		if (tc1) {
88062 			if (tc2) {
88063 				/* tc1 = true, tc2 = true */
88064 				duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, 2);
88065 				if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {  /* (< (* r 2) s) */
88066 					DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r > s: output d --> %ld (k=%ld)",
88067 					                     (long) d, (long) nc_ctx->k));
88068 					DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
88069 				} else {
88070 					DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r <= s: output d+1 --> %ld (k=%ld)",
88071 					                     (long) (d + 1), (long) nc_ctx->k));
88072 					DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
88073 				}
88074 				break;
88075 			} else {
88076 				/* tc1 = true, tc2 = false */
88077 				DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=false: output d --> %ld (k=%ld)",
88078 				                     (long) d, (long) nc_ctx->k));
88079 				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
88080 				break;
88081 			}
88082 		} else {
88083 			if (tc2) {
88084 				/* tc1 = false, tc2 = true */
88085 				DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=true: output d+1 --> %ld (k=%ld)",
88086 				                     (long) (d + 1), (long) nc_ctx->k));
88087 				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
88088 				break;
88089 			} else {
88090 				/* tc1 = false, tc2 = false */
88091 				DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=false: output d --> %ld (k=%ld)",
88092 				                     (long) d, (long) nc_ctx->k));
88093 				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
88094 
88095 				/* r <- r    (updated above: r <- (remainder (* r B) s)
88096 				 * s <- s
88097 				 * m+ <- m+  (updated above: m+ <- (* m+ B)
88098 				 * m- <- m-  (updated above: m- <- (* m- B)
88099 				 * B, low_ok, high_ok are fixed
88100 				 */
88101 
88102 				/* fall through and continue for-loop */
88103 			}
88104 		}
88105 
88106 		/* fixed-format termination conditions */
88107 		if (nc_ctx->is_fixed) {
88108 			if (nc_ctx->abs_pos) {
88109 				int pos = nc_ctx->k - count + 1;  /* count is already incremented, take into account */
88110 				DUK_DDD(DUK_DDDPRINT("fixed format, absolute: abs pos=%ld, k=%ld, count=%ld, req=%ld",
88111 				                     (long) pos, (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
88112 				if (pos <= nc_ctx->req_digits) {
88113 					DUK_DDD(DUK_DDDPRINT("digit position reached req_digits, end generate loop"));
88114 					break;
88115 				}
88116 			} else {
88117 				DUK_DDD(DUK_DDDPRINT("fixed format, relative: k=%ld, count=%ld, req=%ld",
88118 				                     (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
88119 				if (count >= nc_ctx->req_digits) {
88120 					DUK_DDD(DUK_DDDPRINT("digit count reached req_digits, end generate loop"));
88121 					break;
88122 				}
88123 			}
88124 		}
88125 	}  /* for */
88126 
88127 	nc_ctx->count = count;
88128 
88129 	DUK_DDD(DUK_DDDPRINT("generate finished"));
88130 
88131 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
88132 	{
88133 		duk_uint8_t buf[2048];
88134 		duk_small_int_t i, t;
88135 		duk_memzero(buf, sizeof(buf));
88136 		for (i = 0; i < nc_ctx->count; i++) {
88137 			t = nc_ctx->digits[i];
88138 			if (t < 0 || t > 36) {
88139 				buf[i] = (duk_uint8_t) '?';
88140 			} else {
88141 				buf[i] = (duk_uint8_t) DUK__DIGITCHAR(t);
88142 			}
88143 		}
88144 		DUK_DDD(DUK_DDDPRINT("-> generated digits; k=%ld, digits='%s'",
88145 		                     (long) nc_ctx->k, (const char *) buf));
88146 	}
88147 #endif
88148 }
88149 
88150 /* Round up digits to a given position.  If position is out-of-bounds,
88151  * does nothing.  If carry propagates over the first digit, a '1' is
88152  * prepended to digits and 'k' will be updated.  Return value indicates
88153  * whether carry propagated over the first digit.
88154  *
88155  * Note that nc_ctx->count is NOT updated based on the rounding position
88156  * (it is updated only if carry overflows over the first digit and an
88157  * extra digit is prepended).
88158  */
88159 DUK_LOCAL duk_small_int_t duk__dragon4_fixed_format_round(duk__numconv_stringify_ctx *nc_ctx, duk_small_int_t round_idx) {
88160 	duk_small_int_t t;
88161 	duk_uint8_t *p;
88162 	duk_uint8_t roundup_limit;
88163 	duk_small_int_t ret = 0;
88164 
88165 	/*
88166 	 *  round_idx points to the digit which is considered for rounding; the
88167 	 *  digit to its left is the final digit of the rounded value.  If round_idx
88168 	 *  is zero, rounding will be performed; the result will either be an empty
88169 	 *  rounded value or if carry happens a '1' digit is generated.
88170 	 */
88171 
88172 	if (round_idx >= nc_ctx->count) {
88173 		DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld >= %ld (count)) -> no rounding",
88174 		                     (long) round_idx, (long) nc_ctx->count));
88175 		return 0;
88176 	} else if (round_idx < 0) {
88177 		DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld < 0) -> no rounding",
88178 		                     (long) round_idx));
88179 		return 0;
88180 	}
88181 
88182 	/*
88183 	 *  Round-up limit.
88184 	 *
88185 	 *  For even values, divides evenly, e.g. 10 -> roundup_limit=5.
88186 	 *
88187 	 *  For odd values, rounds up, e.g. 3 -> roundup_limit=2.
88188 	 *  If radix is 3, 0/3 -> down, 1/3 -> down, 2/3 -> up.
88189 	 */
88190 	roundup_limit = (duk_uint8_t) ((nc_ctx->B + 1) / 2);
88191 
88192 	p = &nc_ctx->digits[round_idx];
88193 	if (*p >= roundup_limit) {
88194 		DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry required"));
88195 		/* carry */
88196 		for (;;) {
88197 			*p = 0;
88198 			if (p == &nc_ctx->digits[0]) {
88199 				DUK_DDD(DUK_DDDPRINT("carry propagated to first digit -> special case handling"));
88200 				duk_memmove((void *) (&nc_ctx->digits[1]),
88201 				            (const void *) (&nc_ctx->digits[0]),
88202 				            (size_t) (sizeof(char) * (size_t) nc_ctx->count));
88203 				nc_ctx->digits[0] = 1;  /* don't increase 'count' */
88204 				nc_ctx->k++;  /* position of highest digit changed */
88205 				nc_ctx->count++;  /* number of digits changed */
88206 				ret = 1;
88207 				break;
88208 			}
88209 
88210 			DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry: B=%ld, roundup_limit=%ld, p=%p, digits=%p",
88211 			                     (long) nc_ctx->B, (long) roundup_limit, (void *) p, (void *) nc_ctx->digits));
88212 			p--;
88213 			t = *p;
88214 			DUK_DDD(DUK_DDDPRINT("digit before carry: %ld", (long) t));
88215 			if (++t < nc_ctx->B) {
88216 				DUK_DDD(DUK_DDDPRINT("rounding carry terminated"));
88217 				*p = (duk_uint8_t) t;
88218 				break;
88219 			}
88220 
88221 			DUK_DDD(DUK_DDDPRINT("wraps, carry to next digit"));
88222 		}
88223 	}
88224 
88225 	return ret;
88226 }
88227 
88228 #define DUK__NO_EXP  (65536)  /* arbitrary marker, outside valid exp range */
88229 
88230 DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx,
88231                                              duk_hthread *thr,
88232                                              duk_small_int_t radix,
88233                                              duk_small_int_t digits,
88234                                              duk_small_uint_t flags,
88235                                              duk_small_int_t neg) {
88236 	duk_small_int_t k;
88237 	duk_small_int_t pos, pos_end;
88238 	duk_small_int_t expt;
88239 	duk_small_int_t dig;
88240 	duk_uint8_t *q;
88241 	duk_uint8_t *buf;
88242 
88243 	/*
88244 	 *  The string conversion here incorporates all the necessary ECMAScript
88245 	 *  semantics without attempting to be generic.  nc_ctx->digits contains
88246 	 *  nc_ctx->count digits (>= 1), with the topmost digit's 'position'
88247 	 *  indicated by nc_ctx->k as follows:
88248 	 *
88249 	 *    digits="123" count=3 k=0   -->   0.123
88250 	 *    digits="123" count=3 k=1   -->   1.23
88251 	 *    digits="123" count=3 k=5   -->   12300
88252 	 *    digits="123" count=3 k=-1  -->   0.0123
88253 	 *
88254 	 *  Note that the identifier names used for format selection are different
88255 	 *  in Burger-Dybvig paper and ECMAScript specification (quite confusingly
88256 	 *  so, because e.g. 'k' has a totally different meaning in each).  See
88257 	 *  documentation for discussion.
88258 	 *
88259 	 *  ECMAScript doesn't specify any specific behavior for format selection
88260 	 *  (e.g. when to use exponent notation) for non-base-10 numbers.
88261 	 *
88262 	 *  The bigint space in the context is reused for string output, as there
88263 	 *  is more than enough space for that (>1kB at the moment), and we avoid
88264 	 *  allocating even more stack.
88265 	 */
88266 
88267 	DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= DUK__MAX_FORMATTED_LENGTH);
88268 	DUK_ASSERT(nc_ctx->count >= 1);
88269 
88270 	k = nc_ctx->k;
88271 	buf = (duk_uint8_t *) &nc_ctx->f;  /* XXX: union would be more correct */
88272 	q = buf;
88273 
88274 	/* Exponent handling: if exponent format is used, record exponent value and
88275 	 * fake k such that one leading digit is generated (e.g. digits=123 -> "1.23").
88276 	 *
88277 	 * toFixed() prevents exponent use; otherwise apply a set of criteria to
88278 	 * match the other API calls (toString(), toPrecision, etc).
88279 	 */
88280 
88281 	expt = DUK__NO_EXP;
88282 	if (!nc_ctx->abs_pos /* toFixed() */) {
88283 		if ((flags & DUK_N2S_FLAG_FORCE_EXP) ||             /* exponential notation forced */
88284 		    ((flags & DUK_N2S_FLAG_NO_ZERO_PAD) &&          /* fixed precision and zero padding would be required */
88285 	             (k - digits >= 1)) ||                          /* (e.g. k=3, digits=2 -> "12X") */
88286 		    ((k > 21 || k <= -6) && (radix == 10))) {       /* toString() conditions */
88287 			DUK_DDD(DUK_DDDPRINT("use exponential notation: k=%ld -> expt=%ld",
88288 			                     (long) k, (long) (k - 1)));
88289 			expt = k - 1;  /* e.g. 12.3 -> digits="123" k=2 -> 1.23e1 */
88290 			k = 1;  /* generate mantissa with a single leading whole number digit */
88291 		}
88292 	}
88293 
88294 	if (neg) {
88295 		*q++ = '-';
88296 	}
88297 
88298 	/* Start position (inclusive) and end position (exclusive) */
88299 	pos = (k >= 1 ? k : 1);
88300 	if (nc_ctx->is_fixed) {
88301 		if (nc_ctx->abs_pos) {
88302 			/* toFixed() */
88303 			pos_end = -digits;
88304 		} else {
88305 			pos_end = k - digits;
88306 		}
88307 	} else {
88308 		pos_end = k - nc_ctx->count;
88309 	}
88310 	if (pos_end > 0) {
88311 		pos_end = 0;
88312 	}
88313 
88314 	DUK_DDD(DUK_DDDPRINT("expt=%ld, k=%ld, count=%ld, pos=%ld, pos_end=%ld, is_fixed=%ld, "
88315 	                     "digits=%ld, abs_pos=%ld",
88316 	                     (long) expt, (long) k, (long) nc_ctx->count, (long) pos, (long) pos_end,
88317 	                     (long) nc_ctx->is_fixed, (long) digits, (long) nc_ctx->abs_pos));
88318 
88319 	/* Digit generation */
88320 	while (pos > pos_end) {
88321 		DUK_DDD(DUK_DDDPRINT("digit generation: pos=%ld, pos_end=%ld",
88322 		                     (long) pos, (long) pos_end));
88323 		if (pos == 0) {
88324 			*q++ = (duk_uint8_t) '.';
88325 		}
88326 		if (pos > k) {
88327 			*q++ = (duk_uint8_t) '0';
88328 		} else if (pos <= k - nc_ctx->count) {
88329 			*q++ = (duk_uint8_t) '0';
88330 		} else {
88331 			dig = nc_ctx->digits[k - pos];
88332 			DUK_ASSERT(dig >= 0 && dig < nc_ctx->B);
88333 			*q++ = (duk_uint8_t) DUK__DIGITCHAR(dig);
88334 		}
88335 
88336 		pos--;
88337 	}
88338 	DUK_ASSERT(pos <= 1);
88339 
88340 	/* Exponent */
88341 	if (expt != DUK__NO_EXP) {
88342 		/*
88343 		 *  Exponent notation for non-base-10 numbers isn't specified in ECMAScript
88344 		 *  specification, as it never explicitly turns up: non-decimal numbers can
88345 		 *  only be formatted with Number.prototype.toString([radix]) and for that,
88346 		 *  behavior is not explicitly specified.
88347 		 *
88348 		 *  Logical choices include formatting the exponent as decimal (e.g. binary
88349 		 *  100000 as 1e+5) or in current radix (e.g. binary 100000 as 1e+101).
88350 		 *  The Dragon4 algorithm (in the original paper) prints the exponent value
88351 		 *  in the target radix B.  However, for radix values 15 and above, the
88352 		 *  exponent separator 'e' is no longer easily parseable.  Consider, for
88353 		 *  instance, the number "1.faecee+1c".
88354 		 */
88355 
88356 		duk_size_t len;
88357 		char expt_sign;
88358 
88359 		*q++ = 'e';
88360 		if (expt >= 0) {
88361 			expt_sign = '+';
88362 		} else {
88363 			expt_sign = '-';
88364 			expt = -expt;
88365 		}
88366 		*q++ = (duk_uint8_t) expt_sign;
88367 		len = duk__dragon4_format_uint32(q, (duk_uint32_t) expt, radix);
88368 		q += len;
88369 	}
88370 
88371 	duk_push_lstring(thr, (const char *) buf, (size_t) (q - buf));
88372 }
88373 
88374 /*
88375  *  Conversion helpers
88376  */
88377 
88378 DUK_LOCAL void duk__dragon4_double_to_ctx(duk__numconv_stringify_ctx *nc_ctx, duk_double_t x) {
88379 	duk_double_union u;
88380 	duk_uint32_t tmp;
88381 	duk_small_int_t expt;
88382 
88383 	/*
88384 	 *    seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
88385 	 *       A        B        C        D        E        F        G        H
88386 	 *
88387 	 *    s       sign bit
88388 	 *    eee...  exponent field
88389 	 *    fff...  fraction
88390 	 *
88391 	 *    ieee value = 1.ffff... * 2^(e - 1023)  (normal)
88392 	 *               = 0.ffff... * 2^(-1022)     (denormal)
88393 	 *
88394 	 *    algorithm v = f * b^e
88395 	 */
88396 
88397 	DUK_DBLUNION_SET_DOUBLE(&u, x);
88398 
88399 	nc_ctx->f.n = 2;
88400 
88401 	tmp = DUK_DBLUNION_GET_LOW32(&u);
88402 	nc_ctx->f.v[0] = tmp;
88403 	tmp = DUK_DBLUNION_GET_HIGH32(&u);
88404 	nc_ctx->f.v[1] = tmp & 0x000fffffUL;
88405 	expt = (duk_small_int_t) ((tmp >> 20) & 0x07ffUL);
88406 
88407 	if (expt == 0) {
88408 		/* denormal */
88409 		expt = DUK__IEEE_DOUBLE_EXP_MIN - 52;
88410 		duk__bi_normalize(&nc_ctx->f);
88411 	} else {
88412 		/* normal: implicit leading 1-bit */
88413 		nc_ctx->f.v[1] |= 0x00100000UL;
88414 		expt = expt - DUK__IEEE_DOUBLE_EXP_BIAS - 52;
88415 		DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));  /* true, because v[1] has at least one bit set */
88416 	}
88417 
88418 	DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));
88419 
88420 	nc_ctx->e = expt;
88421 }
88422 
88423 DUK_LOCAL void duk__dragon4_ctx_to_double(duk__numconv_stringify_ctx *nc_ctx, duk_double_t *x) {
88424 	duk_double_union u;
88425 	duk_small_int_t expt;
88426 	duk_small_int_t i;
88427 	duk_small_int_t bitstart;
88428 	duk_small_int_t bitround;
88429 	duk_small_int_t bitidx;
88430 	duk_small_int_t skip_round;
88431 	duk_uint32_t t, v;
88432 
88433 	DUK_ASSERT(nc_ctx->count == 53 + 1);
88434 
88435 	/* Sometimes this assert is not true right now; it will be true after
88436 	 * rounding.  See: test-bug-numconv-mantissa-assert.js.
88437 	 */
88438 	DUK_ASSERT_DISABLE(nc_ctx->digits[0] == 1);  /* zero handled by caller */
88439 
88440 	/* Should not be required because the code below always sets both high
88441 	 * and low parts, but at least gcc-4.4.5 fails to deduce this correctly
88442 	 * (perhaps because the low part is set (seemingly) conditionally in a
88443 	 * loop), so this is here to avoid the bogus warning.
88444 	 */
88445 	duk_memzero((void *) &u, sizeof(u));
88446 
88447 	/*
88448 	 *  Figure out how generated digits match up with the mantissa,
88449 	 *  and then perform rounding.  If mantissa overflows, need to
88450 	 *  recompute the exponent (it is bumped and may overflow to
88451 	 *  infinity).
88452 	 *
88453 	 *  For normal numbers the leading '1' is hidden and ignored,
88454 	 *  and the last bit is used for rounding:
88455 	 *
88456 	 *                          rounding pt
88457 	 *       <--------52------->|
88458 	 *     1 x x x x ... x x x x|y  ==>  x x x x ... x x x x
88459 	 *
88460 	 *  For denormals, the leading '1' is included in the number,
88461 	 *  and the rounding point is different:
88462 	 *
88463 	 *                      rounding pt
88464 	 *     <--52 or less--->|
88465 	 *     1 x x x x ... x x|x x y  ==>  0 0 ... 1 x x ... x x
88466 	 *
88467 	 *  The largest denormals will have a mantissa beginning with
88468 	 *  a '1' (the explicit leading bit); smaller denormals will
88469 	 *  have leading zero bits.
88470 	 *
88471 	 *  If the exponent would become too high, the result becomes
88472 	 *  Infinity.  If the exponent is so small that the entire
88473 	 *  mantissa becomes zero, the result becomes zero.
88474 	 *
88475 	 *  Note: the Dragon4 'k' is off-by-one with respect to the IEEE
88476 	 *  exponent.  For instance, k==0 indicates that the leading '1'
88477 	 *  digit is at the first binary fraction position (0.1xxx...);
88478 	 *  the corresponding IEEE exponent would be -1.
88479 	 */
88480 
88481 	skip_round = 0;
88482 
88483  recheck_exp:
88484 
88485 	expt = nc_ctx->k - 1;   /* IEEE exp without bias */
88486 	if (expt > 1023) {
88487 		/* Infinity */
88488 		bitstart = -255;  /* needed for inf: causes mantissa to become zero,
88489 		                   * and rounding to be skipped.
88490 		                   */
88491 		expt = 2047;
88492 	} else if (expt >= -1022) {
88493 		/* normal */
88494 		bitstart = 1;  /* skip leading digit */
88495 		expt += DUK__IEEE_DOUBLE_EXP_BIAS;
88496 		DUK_ASSERT(expt >= 1 && expt <= 2046);
88497 	} else {
88498 		/* denormal or zero */
88499 		bitstart = 1023 + expt;  /* expt==-1023 -> bitstart=0 (leading 1);
88500 		                          * expt==-1024 -> bitstart=-1 (one left of leading 1), etc
88501 		                          */
88502 		expt = 0;
88503 	}
88504 	bitround = bitstart + 52;
88505 
88506 	DUK_DDD(DUK_DDDPRINT("ieee expt=%ld, bitstart=%ld, bitround=%ld",
88507 	                     (long) expt, (long) bitstart, (long) bitround));
88508 
88509 	if (!skip_round) {
88510 		if (duk__dragon4_fixed_format_round(nc_ctx, bitround)) {
88511 			/* Corner case: see test-numconv-parse-mant-carry.js.  We could
88512 			 * just bump the exponent and update bitstart, but it's more robust
88513 			 * to recompute (but avoid rounding twice).
88514 			 */
88515 			DUK_DDD(DUK_DDDPRINT("rounding caused exponent to be bumped, recheck exponent"));
88516 			skip_round = 1;
88517 			goto recheck_exp;
88518 		}
88519 	}
88520 
88521 	/*
88522 	 *  Create mantissa
88523 	 */
88524 
88525 	t = 0;
88526 	for (i = 0; i < 52; i++) {
88527 		bitidx = bitstart + 52 - 1 - i;
88528 		if (bitidx >= nc_ctx->count) {
88529 			v = 0;
88530 		} else if (bitidx < 0) {
88531 			v = 0;
88532 		} else {
88533 			v = nc_ctx->digits[bitidx];
88534 		}
88535 		DUK_ASSERT(v == 0 || v == 1);
88536 		t += v << (i % 32);
88537 		if (i == 31) {
88538 			/* low 32 bits is complete */
88539 			DUK_DBLUNION_SET_LOW32(&u, t);
88540 			t = 0;
88541 		}
88542 	}
88543 	/* t has high mantissa */
88544 
88545 	DUK_DDD(DUK_DDDPRINT("mantissa is complete: %08lx %08lx",
88546 	                     (unsigned long) t,
88547 	                     (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
88548 
88549 	DUK_ASSERT(expt >= 0 && expt <= 0x7ffL);
88550 	t += ((duk_uint32_t) expt) << 20;
88551 #if 0  /* caller handles sign change */
88552 	if (negative) {
88553 		t |= 0x80000000U;
88554 	}
88555 #endif
88556 	DUK_DBLUNION_SET_HIGH32(&u, t);
88557 
88558 	DUK_DDD(DUK_DDDPRINT("number is complete: %08lx %08lx",
88559 	                     (unsigned long) DUK_DBLUNION_GET_HIGH32(&u),
88560 	                     (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
88561 
88562 	*x = DUK_DBLUNION_GET_DOUBLE(&u);
88563 }
88564 
88565 /*
88566  *  Exposed number-to-string API
88567  *
88568  *  Input: [ number ]
88569  *  Output: [ string ]
88570  */
88571 
88572 DUK_LOCAL DUK_NOINLINE void duk__numconv_stringify_raw(duk_hthread *thr, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags) {
88573 	duk_double_t x;
88574 	duk_small_int_t c;
88575 	duk_small_int_t neg;
88576 	duk_uint32_t uval;
88577 	duk__numconv_stringify_ctx nc_ctx_alloc;  /* large context; around 2kB now */
88578 	duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
88579 
88580 	x = (duk_double_t) duk_require_number(thr, -1);
88581 	duk_pop(thr);
88582 
88583 	/*
88584 	 *  Handle special cases (NaN, infinity, zero).
88585 	 */
88586 
88587 	c = (duk_small_int_t) DUK_FPCLASSIFY(x);
88588 	if (DUK_SIGNBIT((double) x)) {
88589 		x = -x;
88590 		neg = 1;
88591 	} else {
88592 		neg = 0;
88593 	}
88594 
88595 	/* NaN sign bit is platform specific with unpacked, un-normalized NaNs */
88596 	DUK_ASSERT(c == DUK_FP_NAN || DUK_SIGNBIT((double) x) == 0);
88597 
88598 	if (c == DUK_FP_NAN) {
88599 		duk_push_hstring_stridx(thr, DUK_STRIDX_NAN);
88600 		return;
88601 	} else if (c == DUK_FP_INFINITE) {
88602 		if (neg) {
88603 			/* -Infinity */
88604 			duk_push_hstring_stridx(thr, DUK_STRIDX_MINUS_INFINITY);
88605 		} else {
88606 			/* Infinity */
88607 			duk_push_hstring_stridx(thr, DUK_STRIDX_INFINITY);
88608 		}
88609 		return;
88610 	} else if (c == DUK_FP_ZERO) {
88611 		/* We can't shortcut zero here if it goes through special formatting
88612 		 * (such as forced exponential notation).
88613 		 */
88614 		;
88615 	}
88616 
88617 	/*
88618 	 *  Handle integers in 32-bit range (that is, [-(2**32-1),2**32-1])
88619 	 *  specially, as they're very likely for embedded programs.  This
88620 	 *  is now done for all radix values.  We must be careful not to use
88621 	 *  the fast path when special formatting (e.g. forced exponential)
88622 	 *  is in force.
88623 	 *
88624 	 *  XXX: could save space by supporting radix 10 only and using
88625 	 *  sprintf "%lu" for the fast path and for exponent formatting.
88626 	 */
88627 
88628 	uval = duk_double_to_uint32_t(x);
88629 	if (duk_double_equals((double) uval, x) &&  /* integer number in range */
88630 	    flags == 0) {                           /* no special formatting */
88631 		/* use bigint area as a temp */
88632 		duk_uint8_t *buf = (duk_uint8_t *) (&nc_ctx->f);
88633 		duk_uint8_t *p = buf;
88634 
88635 		DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= 32 + 1);  /* max size: radix=2 + sign */
88636 		if (neg && uval != 0) {
88637 			/* no negative sign for zero */
88638 			*p++ = (duk_uint8_t) '-';
88639 		}
88640 		p += duk__dragon4_format_uint32(p, uval, radix);
88641 		duk_push_lstring(thr, (const char *) buf, (duk_size_t) (p - buf));
88642 		return;
88643 	}
88644 
88645 	/*
88646 	 *  Dragon4 setup.
88647 	 *
88648 	 *  Convert double from IEEE representation for conversion;
88649 	 *  normal finite values have an implicit leading 1-bit.  The
88650 	 *  slow path algorithm doesn't handle zero, so zero is special
88651 	 *  cased here but still creates a valid nc_ctx, and goes
88652 	 *  through normal formatting in case special formatting has
88653 	 *  been requested (e.g. forced exponential format: 0 -> "0e+0").
88654 	 */
88655 
88656 	/* Would be nice to bulk clear the allocation, but the context
88657 	 * is 1-2 kilobytes and nothing should rely on it being zeroed.
88658 	 */
88659 #if 0
88660 	duk_memzero((void *) nc_ctx, sizeof(*nc_ctx));  /* slow init, do only for slow path cases */
88661 #endif
88662 
88663 	nc_ctx->is_s2n = 0;
88664 	nc_ctx->b = 2;
88665 	nc_ctx->B = radix;
88666 	nc_ctx->abs_pos = 0;
88667 	if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
88668 		nc_ctx->is_fixed = 1;
88669 		if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
88670 			/* absolute req_digits; e.g. digits = 1 -> last digit is 0,
88671 			 * but add an extra digit for rounding.
88672 			 */
88673 			nc_ctx->abs_pos = 1;
88674 			nc_ctx->req_digits = (-digits + 1) - 1;
88675 		} else {
88676 			nc_ctx->req_digits = digits + 1;
88677 		}
88678 	} else {
88679 		nc_ctx->is_fixed = 0;
88680 		nc_ctx->req_digits = 0;
88681 	}
88682 
88683 	if (c == DUK_FP_ZERO) {
88684 		/* Zero special case: fake requested number of zero digits; ensure
88685 		 * no sign bit is printed.  Relative and absolute fixed format
88686 		 * require separate handling.
88687 		 */
88688 		duk_small_int_t count;
88689 		if (nc_ctx->is_fixed) {
88690 			if (nc_ctx->abs_pos) {
88691 				count = digits + 2;  /* lead zero + 'digits' fractions + 1 for rounding */
88692 			} else {
88693 				count = digits + 1;  /* + 1 for rounding */
88694 			}
88695 		} else {
88696 			count = 1;
88697 		}
88698 		DUK_DDD(DUK_DDDPRINT("count=%ld", (long) count));
88699 		DUK_ASSERT(count >= 1);
88700 		duk_memzero((void *) nc_ctx->digits, (size_t) count);
88701 		nc_ctx->count = count;
88702 		nc_ctx->k = 1;  /* 0.000... */
88703 		neg = 0;
88704 		goto zero_skip;
88705 	}
88706 
88707 	duk__dragon4_double_to_ctx(nc_ctx, x);   /* -> sets 'f' and 'e' */
88708 	DUK__BI_PRINT("f", &nc_ctx->f);
88709 	DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
88710 
88711 	/*
88712 	 *  Dragon4 slow path digit generation.
88713 	 */
88714 
88715 	duk__dragon4_prepare(nc_ctx);  /* setup many variables in nc_ctx */
88716 
88717 	DUK_DDD(DUK_DDDPRINT("after prepare:"));
88718 	DUK__BI_PRINT("r", &nc_ctx->r);
88719 	DUK__BI_PRINT("s", &nc_ctx->s);
88720 	DUK__BI_PRINT("mp", &nc_ctx->mp);
88721 	DUK__BI_PRINT("mm", &nc_ctx->mm);
88722 
88723 	duk__dragon4_scale(nc_ctx);
88724 
88725 	DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
88726 	DUK__BI_PRINT("r", &nc_ctx->r);
88727 	DUK__BI_PRINT("s", &nc_ctx->s);
88728 	DUK__BI_PRINT("mp", &nc_ctx->mp);
88729 	DUK__BI_PRINT("mm", &nc_ctx->mm);
88730 
88731 	duk__dragon4_generate(nc_ctx);
88732 
88733 	/*
88734 	 *  Convert and push final string.
88735 	 */
88736 
88737  zero_skip:
88738 
88739 	if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
88740 		/* Perform fixed-format rounding. */
88741 		duk_small_int_t roundpos;
88742 		if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
88743 			/* 'roundpos' is relative to nc_ctx->k and increases to the right
88744 			 * (opposite of how 'k' changes).
88745 			 */
88746 			roundpos = -digits;  /* absolute position for digit considered for rounding */
88747 			roundpos = nc_ctx->k - roundpos;
88748 		} else {
88749 			roundpos = digits;
88750 		}
88751 		DUK_DDD(DUK_DDDPRINT("rounding: k=%ld, count=%ld, digits=%ld, roundpos=%ld",
88752 		                     (long) nc_ctx->k, (long) nc_ctx->count, (long) digits, (long) roundpos));
88753 		(void) duk__dragon4_fixed_format_round(nc_ctx, roundpos);
88754 
88755 		/* Note: 'count' is currently not adjusted by rounding (i.e. the
88756 		 * digits are not "chopped off".  That shouldn't matter because
88757 		 * the digit position (absolute or relative) is passed on to the
88758 		 * convert-and-push function.
88759 		 */
88760 	}
88761 
88762 	duk__dragon4_convert_and_push(nc_ctx, thr, radix, digits, flags, neg);
88763 }
88764 
88765 DUK_INTERNAL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags) {
88766 	duk_native_stack_check(thr);
88767 	duk__numconv_stringify_raw(thr, radix, digits, flags);
88768 }
88769 
88770 /*
88771  *  Exposed string-to-number API
88772  *
88773  *  Input: [ string ]
88774  *  Output: [ number ]
88775  *
88776  *  If number parsing fails, a NaN is pushed as the result.  If number parsing
88777  *  fails due to an internal error, an InternalError is thrown.
88778  */
88779 
88780 DUK_LOCAL DUK_NOINLINE void duk__numconv_parse_raw(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags) {
88781 	duk__numconv_stringify_ctx nc_ctx_alloc;  /* large context; around 2kB now */
88782 	duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
88783 	duk_double_t res;
88784 	duk_hstring *h_str;
88785 	duk_int_t expt;
88786 	duk_bool_t expt_neg;
88787 	duk_small_int_t expt_adj;
88788 	duk_small_int_t neg;
88789 	duk_small_int_t dig;
88790 	duk_small_int_t dig_whole;
88791 	duk_small_int_t dig_lzero;
88792 	duk_small_int_t dig_frac;
88793 	duk_small_int_t dig_expt;
88794 	duk_small_int_t dig_prec;
88795 	const duk__exp_limits *explim;
88796 	const duk_uint8_t *p;
88797 	duk_small_int_t ch;
88798 
88799 	DUK_DDD(DUK_DDDPRINT("parse number: %!T, radix=%ld, flags=0x%08lx",
88800 	                     (duk_tval *) duk_get_tval(thr, -1),
88801 	                     (long) radix, (unsigned long) flags));
88802 
88803 	DUK_ASSERT(radix >= 2 && radix <= 36);
88804 	DUK_ASSERT(radix - 2 < (duk_small_int_t) sizeof(duk__str2num_digits_for_radix));
88805 
88806 	/*
88807 	 *  Preliminaries: trim, sign, Infinity check
88808 	 *
88809 	 *  We rely on the interned string having a NUL terminator, which will
88810 	 *  cause a parse failure wherever it is encountered.  As a result, we
88811 	 *  don't need separate pointer checks.
88812 	 *
88813 	 *  There is no special parsing for 'NaN' in the specification although
88814 	 *  'Infinity' (with an optional sign) is allowed in some contexts.
88815 	 *  Some contexts allow plus/minus sign, while others only allow the
88816 	 *  minus sign (like JSON.parse()).
88817 	 *
88818 	 *  Automatic hex number detection (leading '0x' or '0X') and octal
88819 	 *  number detection (leading '0' followed by at least one octal digit)
88820 	 *  is done here too.
88821 	 *
88822 	 *  Symbols are not explicitly rejected here (that's up to the caller).
88823 	 *  If a symbol were passed here, it should ultimately safely fail
88824 	 *  parsing due to a syntax error.
88825 	 */
88826 
88827 	if (flags & DUK_S2N_FLAG_TRIM_WHITE) {
88828 		/* Leading / trailing whitespace is sometimes accepted and
88829 		 * sometimes not.  After white space trimming, all valid input
88830 		 * characters are pure ASCII.
88831 		 */
88832 		duk_trim(thr, -1);
88833 	}
88834 	h_str = duk_require_hstring(thr, -1);
88835 	DUK_ASSERT(h_str != NULL);
88836 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_str);
88837 
88838 	neg = 0;
88839 	ch = *p;
88840 	if (ch == (duk_small_int_t) '+') {
88841 		if ((flags & DUK_S2N_FLAG_ALLOW_PLUS) == 0) {
88842 			DUK_DDD(DUK_DDDPRINT("parse failed: leading plus sign not allowed"));
88843 			goto parse_fail;
88844 		}
88845 		p++;
88846 	} else if (ch == (duk_small_int_t) '-') {
88847 		if ((flags & DUK_S2N_FLAG_ALLOW_MINUS) == 0) {
88848 			DUK_DDD(DUK_DDDPRINT("parse failed: leading minus sign not allowed"));
88849 			goto parse_fail;
88850 		}
88851 		p++;
88852 		neg = 1;
88853 	}
88854 
88855 	if ((flags & DUK_S2N_FLAG_ALLOW_INF) && DUK_STRNCMP((const char *) p, "Infinity", 8) == 0) {
88856 		/* Don't check for Infinity unless the context allows it.
88857 		 * 'Infinity' is a valid integer literal in e.g. base-36:
88858 		 *
88859 		 *   parseInt('Infinity', 36)
88860 		 *   1461559270678
88861 		 */
88862 
88863 		if ((flags & DUK_S2N_FLAG_ALLOW_GARBAGE) == 0 && p[8] != DUK_ASC_NUL) {
88864 			DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage after matching 'Infinity' not allowed"));
88865 			goto parse_fail;
88866 		} else {
88867 			res = DUK_DOUBLE_INFINITY;
88868 			goto negcheck_and_ret;
88869 		}
88870 	}
88871 	ch = *p;
88872 	if (ch == (duk_small_int_t) '0') {
88873 		duk_small_int_t detect_radix = 0;
88874 		ch = DUK_LOWERCASE_CHAR_ASCII(p[1]);  /* 'x' or 'X' -> 'x' */
88875 		if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT) && ch == DUK_ASC_LC_X) {
88876 			DUK_DDD(DUK_DDDPRINT("detected 0x/0X hex prefix, changing radix and preventing fractions and exponent"));
88877 			detect_radix = 16;
88878 #if 0
88879 		} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT) &&
88880 		           (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9')) {
88881 			DUK_DDD(DUK_DDDPRINT("detected 0n oct prefix, changing radix and preventing fractions and exponent"));
88882 			detect_radix = 8;
88883 
88884 			/* NOTE: if this legacy octal case is added back, it has
88885 			 * different flags and 'p' advance so this needs to be
88886 			 * reworked.
88887 			 */
88888 			flags |= DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO;  /* interpret e.g. '09' as '0', not NaN */
88889 			p += 1;
88890 #endif
88891 		} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT) && ch == DUK_ASC_LC_O) {
88892 			DUK_DDD(DUK_DDDPRINT("detected 0o oct prefix, changing radix and preventing fractions and exponent"));
88893 			detect_radix = 8;
88894 		} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT) && ch == DUK_ASC_LC_B) {
88895 			DUK_DDD(DUK_DDDPRINT("detected 0b bin prefix, changing radix and preventing fractions and exponent"));
88896 			detect_radix = 2;
88897 		}
88898 		if (detect_radix > 0) {
88899 			radix = detect_radix;
88900 			/* Clear empty as zero flag: interpret e.g. '0x' and '0xg' as a NaN (= parse error) */
88901 			flags &= ~(DUK_S2N_FLAG_ALLOW_EXP | DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
88902 			           DUK_S2N_FLAG_ALLOW_FRAC | DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
88903 			           DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO);
88904 			flags |= DUK_S2N_FLAG_ALLOW_LEADING_ZERO;  /* allow e.g. '0x0009' and '0b00010001' */
88905 			p += 2;
88906 		}
88907 	}
88908 
88909 	/*
88910 	 *  Scan number and setup for Dragon4.
88911 	 *
88912 	 *  The fast path case is detected during setup: an integer which
88913 	 *  can be converted without rounding, no net exponent.  The fast
88914 	 *  path could be implemented as a separate scan, but may not really
88915 	 *  be worth it: the multiplications for building 'f' are not
88916 	 *  expensive when 'f' is small.
88917 	 *
88918 	 *  The significand ('f') must contain enough bits of (apparent)
88919 	 *  accuracy, so that Dragon4 will generate enough binary output digits.
88920 	 *  For decimal numbers, this means generating a 20-digit significand,
88921 	 *  which should yield enough practical accuracy to parse IEEE doubles.
88922 	 *  In fact, the ECMAScript specification explicitly allows an
88923 	 *  implementation to treat digits beyond 20 as zeroes (and even
88924 	 *  to round the 20th digit upwards).  For non-decimal numbers, the
88925 	 *  appropriate number of digits has been precomputed for comparable
88926 	 *  accuracy.
88927 	 *
88928 	 *  Digit counts:
88929 	 *
88930 	 *    [ dig_lzero ]
88931 	 *      |
88932 	 *     .+-..---[ dig_prec ]----.
88933 	 *     |  ||                   |
88934 	 *     0000123.456789012345678901234567890e+123456
88935 	 *     |     | |                         |  |    |
88936 	 *     `--+--' `------[ dig_frac ]-------'  `-+--'
88937 	 *        |                                   |
88938 	 *    [ dig_whole ]                       [ dig_expt ]
88939 	 *
88940 	 *    dig_frac and dig_expt are -1 if not present
88941 	 *    dig_lzero is only computed for whole number part
88942 	 *
88943 	 *  Parsing state
88944 	 *
88945 	 *     Parsing whole part      dig_frac < 0 AND dig_expt < 0
88946 	 *     Parsing fraction part   dig_frac >= 0 AND dig_expt < 0
88947 	 *     Parsing exponent part   dig_expt >= 0   (dig_frac may be < 0 or >= 0)
88948 	 *
88949 	 *  Note: in case we hit an implementation limit (like exponent range),
88950 	 *  we should throw an error, NOT return NaN or Infinity.  Even with
88951 	 *  very large exponent (or significand) values the final result may be
88952 	 *  finite, so NaN/Infinity would be incorrect.
88953 	 */
88954 
88955 	duk__bi_set_small(&nc_ctx->f, 0);
88956 	dig_prec = 0;
88957 	dig_lzero = 0;
88958 	dig_whole = 0;
88959 	dig_frac = -1;
88960 	dig_expt = -1;
88961 	expt = 0;
88962 	expt_adj = 0;  /* essentially tracks digit position of lowest 'f' digit */
88963 	expt_neg = 0;
88964 	for (;;) {
88965 		ch = *p++;
88966 
88967 		DUK_DDD(DUK_DDDPRINT("parse digits: p=%p, ch='%c' (%ld), expt=%ld, expt_adj=%ld, "
88968 		                     "dig_whole=%ld, dig_frac=%ld, dig_expt=%ld, dig_lzero=%ld, dig_prec=%ld",
88969 		                     (const void *) p, (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : '?'), (long) ch,
88970 		                     (long) expt, (long) expt_adj, (long) dig_whole, (long) dig_frac,
88971 		                     (long) dig_expt, (long) dig_lzero, (long) dig_prec));
88972 		DUK__BI_PRINT("f", &nc_ctx->f);
88973 
88974 		/* Most common cases first. */
88975 		if (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9') {
88976 			dig = (duk_small_int_t) ch - '0' + 0;
88977 		} else if (ch == (duk_small_int_t) '.') {
88978 			/* A leading digit is not required in some cases, e.g. accept ".123".
88979 			 * In other cases (JSON.parse()) a leading digit is required.  This
88980 			 * is checked for after the loop.
88981 			 */
88982 			if (dig_frac >= 0 || dig_expt >= 0) {
88983 				if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
88984 					DUK_DDD(DUK_DDDPRINT("garbage termination (invalid period)"));
88985 					break;
88986 				} else {
88987 					DUK_DDD(DUK_DDDPRINT("parse failed: period not allowed"));
88988 					goto parse_fail;
88989 				}
88990 			}
88991 
88992 			if ((flags & DUK_S2N_FLAG_ALLOW_FRAC) == 0) {
88993 				/* Some contexts don't allow fractions at all; this can't be a
88994 				 * post-check because the state ('f' and expt) would be incorrect.
88995 				 */
88996 				if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
88997 					DUK_DDD(DUK_DDDPRINT("garbage termination (invalid first period)"));
88998 					break;
88999 				} else {
89000 					DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed"));
89001 				}
89002 			}
89003 
89004 			DUK_DDD(DUK_DDDPRINT("start fraction part"));
89005 			dig_frac = 0;
89006 			continue;
89007 		} else if (ch == (duk_small_int_t) 0) {
89008 			DUK_DDD(DUK_DDDPRINT("NUL termination"));
89009 			break;
89010 		} else if ((flags & DUK_S2N_FLAG_ALLOW_EXP) &&
89011 		           dig_expt < 0 && (ch == (duk_small_int_t) 'e' || ch == (duk_small_int_t) 'E')) {
89012 			/* Note: we don't parse back exponent notation for anything else
89013 			 * than radix 10, so this is not an ambiguous check (e.g. hex
89014 			 * exponent values may have 'e' either as a significand digit
89015 			 * or as an exponent separator).
89016 			 *
89017 			 * If the exponent separator occurs twice, 'e' will be interpreted
89018 			 * as a digit (= 14) and will be rejected as an invalid decimal
89019 			 * digit.
89020 			 */
89021 
89022 			DUK_DDD(DUK_DDDPRINT("start exponent part"));
89023 
89024 			/* Exponent without a sign or with a +/- sign is accepted
89025 			 * by all call sites (even JSON.parse()).
89026 			 */
89027 			ch = *p;
89028 			if (ch == (duk_small_int_t) '-') {
89029 				expt_neg = 1;
89030 				p++;
89031 			} else if (ch == (duk_small_int_t) '+') {
89032 				p++;
89033 			}
89034 			dig_expt = 0;
89035 			continue;
89036 		} else if (ch >= (duk_small_int_t) 'a' && ch <= (duk_small_int_t) 'z') {
89037 			dig = (duk_small_int_t) (ch - (duk_small_int_t) 'a' + 0x0a);
89038 		} else if (ch >= (duk_small_int_t) 'A' && ch <= (duk_small_int_t) 'Z') {
89039 			dig = (duk_small_int_t) (ch - (duk_small_int_t) 'A' + 0x0a);
89040 		} else {
89041 			dig = 255;  /* triggers garbage digit check below */
89042 		}
89043 		DUK_ASSERT((dig >= 0 && dig <= 35) || dig == 255);
89044 
89045 		if (dig >= radix) {
89046 			if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
89047 				DUK_DDD(DUK_DDDPRINT("garbage termination"));
89048 				break;
89049 			} else {
89050 				DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage or invalid digit"));
89051 				goto parse_fail;
89052 			}
89053 		}
89054 
89055 		if (dig_expt < 0) {
89056 			/* whole or fraction digit */
89057 
89058 			if (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
89059 				/* significant from precision perspective */
89060 
89061 				duk_small_int_t f_zero = duk__bi_is_zero(&nc_ctx->f);
89062 				if (f_zero && dig == 0) {
89063 					/* Leading zero is not counted towards precision digits; not
89064 					 * in the integer part, nor in the fraction part.
89065 					 */
89066 					if (dig_frac < 0) {
89067 						dig_lzero++;
89068 					}
89069 				} else {
89070 					/* XXX: join these ops (multiply-accumulate), but only if
89071 					 * code footprint decreases.
89072 					 */
89073 					duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, (duk_uint32_t) radix);
89074 					duk__bi_add_small(&nc_ctx->f, &nc_ctx->t1, (duk_uint32_t) dig);
89075 					dig_prec++;
89076 				}
89077 			} else {
89078 				/* Ignore digits beyond a radix-specific limit, but note them
89079 				 * in expt_adj.
89080 				 */
89081 				expt_adj++;
89082 			}
89083 
89084 			if (dig_frac >= 0) {
89085 				dig_frac++;
89086 				expt_adj--;
89087 			} else {
89088 				dig_whole++;
89089 			}
89090 		} else {
89091 			/* exponent digit */
89092 
89093 			DUK_ASSERT(radix == 10);
89094 			expt = expt * radix + dig;
89095 			if (expt > DUK_S2N_MAX_EXPONENT) {
89096 				/* Impose a reasonable exponent limit, so that exp
89097 				 * doesn't need to get tracked using a bigint.
89098 				 */
89099 				DUK_DDD(DUK_DDDPRINT("parse failed: exponent too large"));
89100 				goto parse_explimit_error;
89101 			}
89102 			dig_expt++;
89103 		}
89104 	}
89105 
89106 	/* Leading zero. */
89107 
89108 	if (dig_lzero > 0 && dig_whole > 1) {
89109 		if ((flags & DUK_S2N_FLAG_ALLOW_LEADING_ZERO) == 0) {
89110 			DUK_DDD(DUK_DDDPRINT("parse failed: leading zeroes not allowed in integer part"));
89111 			goto parse_fail;
89112 		}
89113 	}
89114 
89115 	/* Validity checks for various fraction formats ("0.1", ".1", "1.", "."). */
89116 
89117 	if (dig_whole == 0) {
89118 		if (dig_frac == 0) {
89119 			/* "." is not accepted in any format */
89120 			DUK_DDD(DUK_DDDPRINT("parse failed: plain period without leading or trailing digits"));
89121 			goto parse_fail;
89122 		} else if (dig_frac > 0) {
89123 			/* ".123" */
89124 			if ((flags & DUK_S2N_FLAG_ALLOW_NAKED_FRAC) == 0) {
89125 				DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed without "
89126 				                     "leading integer digit(s)"));
89127 				goto parse_fail;
89128 			}
89129 		} else {
89130 			/* Empty ("") is allowed in some formats (e.g. Number(''), as zero,
89131 			 * but it must not have a leading +/- sign (GH-2019).  Note that
89132 			 * for Number(), h_str is already trimmed so we can check for zero
89133 			 * length and still get Number('  +  ') == NaN.
89134 			 */
89135 			if ((flags & DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO) == 0) {
89136 				DUK_DDD(DUK_DDDPRINT("parse failed: empty string not allowed (as zero)"));
89137 				goto parse_fail;
89138 			} else if (DUK_HSTRING_GET_BYTELEN(h_str) != 0) {
89139 				DUK_DDD(DUK_DDDPRINT("parse failed: no digits, but not empty (had a +/- sign)"));
89140 				goto parse_fail;
89141 			}
89142 		}
89143 	} else {
89144 		if (dig_frac == 0) {
89145 			/* "123." is allowed in some formats */
89146 			if ((flags & DUK_S2N_FLAG_ALLOW_EMPTY_FRAC) == 0) {
89147 				DUK_DDD(DUK_DDDPRINT("parse failed: empty fractions"));
89148 				goto parse_fail;
89149 			}
89150 		} else if (dig_frac > 0) {
89151 			/* "123.456" */
89152 			;
89153 		} else {
89154 			/* "123" */
89155 			;
89156 		}
89157 	}
89158 
89159 	/* Exponent without digits (e.g. "1e" or "1e+").  If trailing garbage is
89160 	 * allowed, ignore exponent part as garbage (= parse as "1", i.e. exp 0).
89161 	 */
89162 
89163 	if (dig_expt == 0) {
89164 		if ((flags & DUK_S2N_FLAG_ALLOW_GARBAGE) == 0) {
89165 			DUK_DDD(DUK_DDDPRINT("parse failed: empty exponent"));
89166 			goto parse_fail;
89167 		}
89168 		DUK_ASSERT(expt == 0);
89169 	}
89170 
89171 	if (expt_neg) {
89172 		expt = -expt;
89173 	}
89174 	DUK_DDD(DUK_DDDPRINT("expt=%ld, expt_adj=%ld, net exponent -> %ld",
89175 	                     (long) expt, (long) expt_adj, (long) (expt + expt_adj)));
89176 	expt += expt_adj;
89177 
89178 	/* Fast path check. */
89179 
89180 	if (nc_ctx->f.n <= 1 &&   /* 32-bit value */
89181 	    expt == 0    /* no net exponent */) {
89182 		/* Fast path is triggered for no exponent and also for balanced exponent
89183 		 * and fraction parts, e.g. for "1.23e2" == "123".  Remember to respect
89184 		 * zero sign.
89185 		 */
89186 
89187 		/* XXX: could accept numbers larger than 32 bits, e.g. up to 53 bits? */
89188 		DUK_DDD(DUK_DDDPRINT("fast path number parse"));
89189 		if (nc_ctx->f.n == 1) {
89190 			res = (double) nc_ctx->f.v[0];
89191 		} else {
89192 			res = 0.0;
89193 		}
89194 		goto negcheck_and_ret;
89195 	}
89196 
89197 	/* Significand ('f') padding. */
89198 
89199 	while (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
89200 		/* Pad significand with "virtual" zero digits so that Dragon4 will
89201 		 * have enough (apparent) precision to work with.
89202 		 */
89203 		DUK_DDD(DUK_DDDPRINT("dig_prec=%ld, pad significand with zero", (long) dig_prec));
89204 		duk__bi_mul_small_copy(&nc_ctx->f, (duk_uint32_t) radix, &nc_ctx->t1);
89205 		DUK__BI_PRINT("f", &nc_ctx->f);
89206 		expt--;
89207 		dig_prec++;
89208 	}
89209 
89210 	DUK_DDD(DUK_DDDPRINT("final exponent: %ld", (long) expt));
89211 
89212 	/* Detect zero special case. */
89213 
89214 	if (nc_ctx->f.n == 0) {
89215 		/* This may happen even after the fast path check, if exponent is
89216 		 * not balanced (e.g. "0e1").  Remember to respect zero sign.
89217 		 */
89218 		DUK_DDD(DUK_DDDPRINT("significand is zero"));
89219 		res = 0.0;
89220 		goto negcheck_and_ret;
89221 	}
89222 
89223 
89224 	/* Quick reject of too large or too small exponents.  This check
89225 	 * would be incorrect for zero (e.g. "0e1000" is zero, not Infinity)
89226 	 * so zero check must be above.
89227 	 */
89228 
89229 	explim = &duk__str2num_exp_limits[radix - 2];
89230 	if (expt > explim->upper) {
89231 		DUK_DDD(DUK_DDDPRINT("exponent too large -> infinite"));
89232 		res = (duk_double_t) DUK_DOUBLE_INFINITY;
89233 		goto negcheck_and_ret;
89234 	} else if (expt < explim->lower) {
89235 		DUK_DDD(DUK_DDDPRINT("exponent too small -> zero"));
89236 		res = (duk_double_t) 0.0;
89237 		goto negcheck_and_ret;
89238 	}
89239 
89240 	nc_ctx->is_s2n = 1;
89241 	nc_ctx->e = expt;
89242 	nc_ctx->b = radix;
89243 	nc_ctx->B = 2;
89244 	nc_ctx->is_fixed = 1;
89245 	nc_ctx->abs_pos = 0;
89246 	nc_ctx->req_digits = 53 + 1;
89247 
89248 	DUK__BI_PRINT("f", &nc_ctx->f);
89249 	DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
89250 
89251 	/*
89252 	 *  Dragon4 slow path (binary) digit generation.
89253 	 *  An extra digit is generated for rounding.
89254 	 */
89255 
89256 	duk__dragon4_prepare(nc_ctx);  /* setup many variables in nc_ctx */
89257 
89258 	DUK_DDD(DUK_DDDPRINT("after prepare:"));
89259 	DUK__BI_PRINT("r", &nc_ctx->r);
89260 	DUK__BI_PRINT("s", &nc_ctx->s);
89261 	DUK__BI_PRINT("mp", &nc_ctx->mp);
89262 	DUK__BI_PRINT("mm", &nc_ctx->mm);
89263 
89264 	duk__dragon4_scale(nc_ctx);
89265 
89266 	DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
89267 	DUK__BI_PRINT("r", &nc_ctx->r);
89268 	DUK__BI_PRINT("s", &nc_ctx->s);
89269 	DUK__BI_PRINT("mp", &nc_ctx->mp);
89270 	DUK__BI_PRINT("mm", &nc_ctx->mm);
89271 
89272 	duk__dragon4_generate(nc_ctx);
89273 
89274 	DUK_ASSERT(nc_ctx->count == 53 + 1);
89275 
89276 	/*
89277 	 *  Convert binary digits into an IEEE double.  Need to handle
89278 	 *  denormals and rounding correctly.
89279 	 *
89280 	 *  Some call sites currently assume the result is always a
89281 	 *  non-fastint double.  If this is changed, check all call
89282 	 *  sites.
89283 	 */
89284 
89285 	duk__dragon4_ctx_to_double(nc_ctx, &res);
89286 	goto negcheck_and_ret;
89287 
89288  negcheck_and_ret:
89289 	if (neg) {
89290 		res = -res;
89291 	}
89292 	duk_pop(thr);
89293 	duk_push_number(thr, (double) res);
89294 	DUK_DDD(DUK_DDDPRINT("result: %!T", (duk_tval *) duk_get_tval(thr, -1)));
89295 	return;
89296 
89297  parse_fail:
89298 	DUK_DDD(DUK_DDDPRINT("parse failed"));
89299 	duk_pop(thr);
89300 	duk_push_nan(thr);
89301 	return;
89302 
89303  parse_explimit_error:
89304 	DUK_DDD(DUK_DDDPRINT("parse failed, internal error, can't return a value"));
89305 	DUK_ERROR_RANGE(thr, "exponent too large");
89306 	DUK_WO_NORETURN(return;);
89307 }
89308 
89309 DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags) {
89310 	duk_native_stack_check(thr);
89311 	duk__numconv_parse_raw(thr, radix, flags);
89312 }
89313 
89314 /* automatic undefs */
89315 #undef DUK__BI_MAX_PARTS
89316 #undef DUK__BI_PRINT
89317 #undef DUK__DIGITCHAR
89318 #undef DUK__DRAGON4_OUTPUT_PREINC
89319 #undef DUK__IEEE_DOUBLE_EXP_BIAS
89320 #undef DUK__IEEE_DOUBLE_EXP_MIN
89321 #undef DUK__MAX_FORMATTED_LENGTH
89322 #undef DUK__MAX_OUTPUT_DIGITS
89323 #undef DUK__NO_EXP
89324 #undef DUK__NUMCONV_CTX_BIGINTS_SIZE
89325 #undef DUK__NUMCONV_CTX_NUM_BIGINTS
89326 #line 1 "duk_regexp_compiler.c"
89327 /*
89328  *  Regexp compilation.
89329  *
89330  *  See doc/regexp.rst for a discussion of the compilation approach and
89331  *  current limitations.
89332  *
89333  *  Regexp bytecode assumes jumps can be expressed with signed 32-bit
89334  *  integers.  Consequently the bytecode size must not exceed 0x7fffffffL.
89335  *  The implementation casts duk_size_t (buffer size) to duk_(u)int32_t
89336  *  in many places.  Although this could be changed, the bytecode format
89337  *  limit would still prevent regexps exceeding the signed 32-bit limit
89338  *  from working.
89339  *
89340  *  XXX: The implementation does not prevent bytecode from exceeding the
89341  *  maximum supported size.  This could be done by limiting the maximum
89342  *  input string size (assuming an upper bound can be computed for number
89343  *  of bytecode bytes emitted per input byte) or checking buffer maximum
89344  *  size when emitting bytecode (slower).
89345  */
89346 
89347 /* #include duk_internal.h -> already included */
89348 
89349 #if defined(DUK_USE_REGEXP_SUPPORT)
89350 
89351 /*
89352  *  Helper macros
89353  */
89354 
89355 #define DUK__RE_INITIAL_BUFSIZE 64
89356 
89357 #define DUK__RE_BUFLEN(re_ctx) \
89358 	DUK_BW_GET_SIZE(re_ctx->thr, &re_ctx->bw)
89359 
89360 /*
89361  *  Disjunction struct: result of parsing a disjunction
89362  */
89363 
89364 typedef struct {
89365 	/* Number of characters that the atom matches (e.g. 3 for 'abc'),
89366 	 * -1 if atom is complex and number of matched characters either
89367 	 * varies or is not known.
89368 	 */
89369 	duk_int32_t charlen;
89370 
89371 #if 0
89372 	/* These are not needed to implement quantifier capture handling,
89373 	 * but might be needed at some point.
89374 	 */
89375 
89376 	/* re_ctx->captures at start and end of atom parsing.
89377 	 * Since 'captures' indicates highest capture number emitted
89378 	 * so far in a DUK_REOP_SAVE, the captures numbers saved by
89379 	 * the atom are: ]start_captures,end_captures].
89380 	 */
89381 	duk_uint32_t start_captures;
89382 	duk_uint32_t end_captures;
89383 #endif
89384 } duk__re_disjunction_info;
89385 
89386 /*
89387  *  Encoding helpers
89388  *
89389  *  Some of the typing is bytecode based, e.g. slice sizes are unsigned 32-bit
89390  *  even though the buffer operations will use duk_size_t.
89391  */
89392 
89393 /* XXX: the insert helpers should ensure that the bytecode result is not
89394  * larger than expected (or at least assert for it).  Many things in the
89395  * bytecode, like skip offsets, won't work correctly if the bytecode is
89396  * larger than say 2G.
89397  */
89398 
89399 DUK_LOCAL duk_uint32_t duk__encode_i32(duk_int32_t x) {
89400 	if (x < 0) {
89401 		return ((duk_uint32_t) (-x)) * 2 + 1;
89402 	} else {
89403 		return ((duk_uint32_t) x) * 2;
89404 	}
89405 }
89406 
89407 /* XXX: return type should probably be duk_size_t, or explicit checks are needed for
89408  * maximum size.
89409  */
89410 DUK_LOCAL duk_uint32_t duk__insert_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t x) {
89411 	duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
89412 	duk_small_int_t len;
89413 
89414 	len = duk_unicode_encode_xutf8((duk_ucodepoint_t) x, buf);
89415 	DUK_ASSERT(len >= 0);
89416 	DUK_BW_INSERT_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, offset, buf, (duk_size_t) len);
89417 	return (duk_uint32_t) len;
89418 }
89419 
89420 DUK_LOCAL void duk__append_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
89421 	DUK_BW_WRITE_ENSURE_XUTF8(re_ctx->thr, &re_ctx->bw, x);
89422 }
89423 
89424 DUK_LOCAL void duk__append_7bit(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
89425 #if defined(DUK_USE_PREFER_SIZE)
89426 	duk__append_u32(re_ctx, x);
89427 #else
89428 	DUK_ASSERT(x <= 0x7fU);
89429 	DUK_BW_WRITE_ENSURE_U8(re_ctx->thr, &re_ctx->bw, (duk_uint8_t) x);
89430 #endif
89431 }
89432 
89433 #if 0
89434 DUK_LOCAL void duk__append_2bytes(duk_re_compiler_ctx *re_ctx, duk_uint8_t x, duk_uint8_t y) {
89435 	DUK_BW_WRITE_ENSURE_U8_2(re_ctx->thr, &re_ctx->bw, x, y);
89436 }
89437 #endif
89438 
89439 DUK_LOCAL duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x) {
89440 	return duk__insert_u32(re_ctx, offset, duk__encode_i32(x));
89441 }
89442 
89443 DUK_LOCAL void duk__append_reop(duk_re_compiler_ctx *re_ctx, duk_uint32_t reop) {
89444 	DUK_ASSERT(reop <= 0x7fU);
89445 	(void) duk__append_7bit(re_ctx, reop);
89446 }
89447 
89448 #if 0  /* unused */
89449 DUK_LOCAL void duk__append_i32(duk_re_compiler_ctx *re_ctx, duk_int32_t x) {
89450 	duk__append_u32(re_ctx, duk__encode_i32(x));
89451 }
89452 #endif
89453 
89454 /* special helper for emitting u16 lists (used for character ranges for built-in char classes) */
89455 DUK_LOCAL void duk__append_u16_list(duk_re_compiler_ctx *re_ctx, const duk_uint16_t *values, duk_uint32_t count) {
89456 	/* Call sites don't need the result length so it's not accumulated. */
89457 	while (count-- > 0) {
89458 		duk__append_u32(re_ctx, (duk_uint32_t) (*values++));
89459 	}
89460 }
89461 
89462 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) {
89463 	DUK_BW_INSERT_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, offset, data_offset, data_length);
89464 }
89465 
89466 DUK_LOCAL void duk__append_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
89467 	DUK_BW_WRITE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
89468 }
89469 
89470 DUK_LOCAL void duk__remove_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
89471 	DUK_BW_REMOVE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
89472 }
89473 
89474 /*
89475  *  Insert a jump offset at 'offset' to complete an instruction
89476  *  (the jump offset is always the last component of an instruction).
89477  *  The 'skip' argument must be computed relative to 'offset',
89478  *  -without- taking into account the skip field being inserted.
89479  *
89480  *       ... A B C ins X Y Z ...   (ins may be a JUMP, SPLIT1/SPLIT2, etc)
89481  *   =>  ... A B C ins SKIP X Y Z
89482  *
89483  *  Computing the final (adjusted) skip value, which is relative to the
89484  *  first byte of the next instruction, is a bit tricky because of the
89485  *  variable length UTF-8 encoding.  See doc/regexp.rst for discussion.
89486  */
89487 DUK_LOCAL duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t skip) {
89488 #if 0
89489 	/* Iterative solution. */
89490 	if (skip < 0) {
89491 		duk_small_int_t len;
89492 		/* two encoding attempts suffices */
89493 		len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip));
89494 		len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip - (duk_int32_t) len));
89495 		DUK_ASSERT(duk_unicode_get_xutf8_length(duk__encode_i32(skip - (duk_int32_t) len)) == len);  /* no change */
89496 		skip -= (duk_int32_t) len;
89497 	}
89498 #endif
89499 
89500 #if defined(DUK_USE_PREFER_SIZE)
89501 	/* Closed form solution, this produces smallest code.
89502 	 * See re_neg_jump_offset (closed2).
89503 	 */
89504 	if (skip < 0) {
89505 		skip--;
89506 		if (skip < -0x3fL) {
89507 			skip--;
89508 		}
89509 		if (skip < -0x3ffL) {
89510 			skip--;
89511 		}
89512 		if (skip < -0x7fffL) {
89513 			skip--;
89514 		}
89515 		if (skip < -0xfffffL) {
89516 			skip--;
89517 		}
89518 		if (skip < -0x1ffffffL) {
89519 			skip--;
89520 		}
89521 		if (skip < -0x3fffffffL) {
89522 			skip--;
89523 		}
89524 	}
89525 #else  /* DUK_USE_PREFER_SIZE */
89526 	/* Closed form solution, this produces fastest code.
89527 	 * See re_neg_jump_offset (closed1).
89528 	 */
89529 	if (skip < 0) {
89530 		if (skip >= -0x3eL) {
89531 			skip -= 1;
89532 		} else if (skip >= -0x3fdL) {
89533 			skip -= 2;
89534 		} else if (skip >= -0x7ffcL) {
89535 			skip -= 3;
89536 		} else if (skip >= -0xffffbL) {
89537 			skip -= 4;
89538 		} else if (skip >= -0x1fffffaL) {
89539 			skip -= 5;
89540 		} else if (skip >= -0x3ffffff9L) {
89541 			skip -= 6;
89542 		} else {
89543 			skip -= 7;
89544 		}
89545 	}
89546 #endif  /* DUK_USE_PREFER_SIZE */
89547 
89548 	return duk__insert_i32(re_ctx, offset, skip);
89549 }
89550 
89551 DUK_LOCAL duk_uint32_t duk__append_jump_offset(duk_re_compiler_ctx *re_ctx, duk_int32_t skip) {
89552 	return (duk_uint32_t) duk__insert_jump_offset(re_ctx, (duk_uint32_t) DUK__RE_BUFLEN(re_ctx), skip);
89553 }
89554 
89555 /*
89556  *  duk_re_range_callback for generating character class ranges.
89557  *
89558  *  When ignoreCase is false, the range is simply emitted as is.  We don't,
89559  *  for instance, eliminate duplicates or overlapping ranges in a character
89560  *  class.
89561  *
89562  *  When ignoreCase is true but the 'direct' flag is set, the caller knows
89563  *  that the range canonicalizes to itself for case insensitive matching,
89564  *  so the range is emitted as is.  This is mainly useful for built-in ranges
89565  *  like \W.
89566  *
89567  *  Otherwise, when ignoreCase is true, the range needs to be normalized
89568  *  through canonicalization.  Unfortunately a canonicalized version of a
89569  *  continuous range is not necessarily continuous (e.g. [x-{] is continuous
89570  *  but [X-{] is not).  As a result, a single input range may expand to a lot
89571  *  of output ranges.  The current algorithm creates the canonicalized ranges
89572  *  footprint efficiently at the cost of compile time execution time; see
89573  *  doc/regexp.rst for discussion, and some more details below.
89574  *
89575  *  Note that the ctx->nranges is a context-wide temporary value.  This is OK
89576  *  because there cannot be multiple character classes being parsed
89577  *  simultaneously.
89578  *
89579  *  More detail on canonicalization:
89580  *
89581  *  Conceptually, a range is canonicalized by scanning the entire range,
89582  *  normalizing each codepoint by converting it to uppercase, and generating
89583  *  a set of result ranges.
89584  *
89585  *  Ideally a minimal set of output ranges would be emitted by merging all
89586  *  possible ranges even if they're emitted out of sequence.  Because the
89587  *  input string is also case normalized during matching, some codepoints
89588  *  never occur at runtime; these "don't care" codepoints can be included or
89589  *  excluded from ranges when merging/optimizing ranges.
89590  *
89591  *  The current algorithm does not do optimal range merging.  Rather, output
89592  *  codepoints are generated in sequence, and when the output codepoints are
89593  *  continuous (CP, CP+1, CP+2, ...), they are merged locally into as large a
89594  *  range as possible.  A small canonicalization bitmap is used to reduce
89595  *  actual codepoint canonicalizations which are quite slow at present.  The
89596  *  bitmap provides a "codepoint block is continuous with respect to
89597  *  canonicalization" for N-codepoint blocks.  This allows blocks to be
89598  *  skipped quickly.
89599  *
89600  *  There are a number of shortcomings and future work here:
89601  *
89602  *    - Individual codepoint normalizations are slow because they involve
89603  *      walking bit-packed rules without a lookup index.
89604  *
89605  *    - The conceptual algorithm needs to canonicalize every codepoint in the
89606  *      input range to figure out the output range(s).  Even with the small
89607  *      canonicalization bitmap the algorithm runs quite slowly for worst case
89608  *      inputs.  There are many data structure alternatives to improve this.
89609  *
89610  *    - While the current algorithm generates maximal output ranges when the
89611  *      output codepoints are emitted linearly, output ranges are not sorted or
89612  *      merged otherwise.  In the worst case a lot of ranges are emitted when
89613  *      most of the ranges could be merged.  In this process one could take
89614  *      advantage of "don't care" codepoints, which are never matched against at
89615  *      runtime due to canonicalization of input codepoints before comparison,
89616  *      to merge otherwise discontinuous output ranges.
89617  *
89618  *    - The runtime data structure is just a linear list of ranges to match
89619  *      against.  This can be quite slow if there are a lot of output ranges.
89620  *      There are various ways to make matching against the ranges faster,
89621  *      e.g. sorting the ranges and using a binary search; skip lists; tree
89622  *      based representations; full or approximate codepoint bitmaps, etc.
89623  *
89624  *    - Only BMP is supported, codepoints above BMP are assumed to canonicalize
89625  *      to themselves.  For now this is one place where we don't want to
89626  *      support chars outside the BMP, because the exhaustive search would be
89627  *      massively larger.  It would be possible to support non-BMP with a
89628  *      different algorithm, or perhaps doing case normalization only at match
89629  *      time.
89630  */
89631 
89632 DUK_LOCAL void duk__regexp_emit_range(duk_re_compiler_ctx *re_ctx, duk_codepoint_t r1, duk_codepoint_t r2) {
89633 	DUK_ASSERT(r2 >= r1);
89634 	duk__append_u32(re_ctx, (duk_uint32_t) r1);
89635 	duk__append_u32(re_ctx, (duk_uint32_t) r2);
89636 	re_ctx->nranges++;
89637 }
89638 
89639 #if defined(DUK_USE_REGEXP_CANON_BITMAP)
89640 /* Find next canonicalization discontinuity (conservative estimate) starting
89641  * from 'start', not exceeding 'end'.  If continuity is fine up to 'end'
89642  * inclusive, returns end.  Minimum possible return value is start.
89643  */
89644 DUK_LOCAL duk_codepoint_t duk__re_canon_next_discontinuity(duk_codepoint_t start, duk_codepoint_t end) {
89645 	duk_uint_t start_blk;
89646 	duk_uint_t end_blk;
89647 	duk_uint_t blk;
89648 	duk_uint_t offset;
89649 	duk_uint8_t mask;
89650 
89651 	/* Inclusive block range. */
89652 	DUK_ASSERT(start >= 0);
89653 	DUK_ASSERT(end >= 0);
89654 	DUK_ASSERT(end >= start);
89655 	start_blk = (duk_uint_t) (start >> DUK_CANON_BITMAP_BLKSHIFT);
89656 	end_blk = (duk_uint_t) (end >> DUK_CANON_BITMAP_BLKSHIFT);
89657 
89658 	for (blk = start_blk; blk <= end_blk; blk++) {
89659 		offset = blk >> 3;
89660 		mask = 1U << (blk & 0x07);
89661 		if (offset >= sizeof(duk_unicode_re_canon_bitmap)) {
89662 			/* Reached non-BMP range which is assumed continuous. */
89663 			return end;
89664 		}
89665 		DUK_ASSERT(offset < sizeof(duk_unicode_re_canon_bitmap));
89666 		if ((duk_unicode_re_canon_bitmap[offset] & mask) == 0) {
89667 			/* Block is discontinuous, continuity is guaranteed
89668 			 * only up to end of previous block (+1 for exclusive
89669 			 * return value => start of current block).  Start
89670 			 * block requires special handling.
89671 			 */
89672 			if (blk > start_blk) {
89673 				return (duk_codepoint_t) (blk << DUK_CANON_BITMAP_BLKSHIFT);
89674 			} else {
89675 				return start;
89676 			}
89677 		}
89678 	}
89679 	DUK_ASSERT(blk == end_blk + 1);  /* Reached end block which is continuous. */
89680 	return end;
89681 }
89682 #else  /* DUK_USE_REGEXP_CANON_BITMAP */
89683 DUK_LOCAL duk_codepoint_t duk__re_canon_next_discontinuity(duk_codepoint_t start, duk_codepoint_t end) {
89684 	DUK_ASSERT(start >= 0);
89685 	DUK_ASSERT(end >= 0);
89686 	DUK_ASSERT(end >= start);
89687 	if (start >= 0x10000) {
89688 		/* Even without the bitmap, treat non-BMP as continuous. */
89689 		return end;
89690 	}
89691 	return start;
89692 }
89693 #endif  /* DUK_USE_REGEXP_CANON_BITMAP */
89694 
89695 DUK_LOCAL void duk__regexp_generate_ranges(void *userdata, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct) {
89696 	duk_re_compiler_ctx *re_ctx = (duk_re_compiler_ctx *) userdata;
89697 	duk_codepoint_t r_start;
89698 	duk_codepoint_t r_end;
89699 	duk_codepoint_t i;
89700 	duk_codepoint_t t;
89701 	duk_codepoint_t r_disc;
89702 
89703 	DUK_DD(DUK_DDPRINT("duk__regexp_generate_ranges(): re_ctx=%p, range=[%ld,%ld] direct=%ld",
89704 	                   (void *) re_ctx, (long) r1, (long) r2, (long) direct));
89705 
89706 	DUK_ASSERT(r2 >= r1);  /* SyntaxError for out of order range. */
89707 
89708 	if (direct || (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) == 0) {
89709 		DUK_DD(DUK_DDPRINT("direct or not case sensitive, emit range: [%ld,%ld]", (long) r1, (long) r2));
89710 		duk__regexp_emit_range(re_ctx, r1, r2);
89711 		return;
89712 	}
89713 
89714 	DUK_DD(DUK_DDPRINT("case sensitive, process range: [%ld,%ld]", (long) r1, (long) r2));
89715 
89716 	r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
89717 	r_end = r_start;
89718 
89719 	for (i = r1 + 1; i <= r2;) {
89720 		/* Input codepoint space processed up to i-1, and
89721 		 * current range in r_{start,end} is up-to-date
89722 		 * (inclusive) and may either break or continue.
89723 		 */
89724 		r_disc = duk__re_canon_next_discontinuity(i, r2);
89725 		DUK_ASSERT(r_disc >= i);
89726 		DUK_ASSERT(r_disc <= r2);
89727 
89728 		r_end += r_disc - i;  /* May be zero. */
89729 		t = duk_unicode_re_canonicalize_char(re_ctx->thr, r_disc);
89730 		if (t == r_end + 1) {
89731 			/* Not actually a discontinuity, continue range
89732 			 * to r_disc and recheck.
89733 			 */
89734 			r_end = t;
89735 		} else {
89736 			duk__regexp_emit_range(re_ctx, r_start, r_end);
89737 			r_start = t;
89738 			r_end = t;
89739 		}
89740 		i = r_disc + 1;  /* Guarantees progress. */
89741 	}
89742 	duk__regexp_emit_range(re_ctx, r_start, r_end);
89743 
89744 #if 0  /* Exhaustive search, very slow. */
89745 	r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
89746 	r_end = r_start;
89747 	for (i = r1 + 1; i <= r2; i++) {
89748 		t = duk_unicode_re_canonicalize_char(re_ctx->thr, i);
89749 		if (t == r_end + 1) {
89750 			r_end = t;
89751 		} else {
89752 			DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
89753 			duk__append_u32(re_ctx, (duk_uint32_t) r_start);
89754 			duk__append_u32(re_ctx, (duk_uint32_t) r_end);
89755 			re_ctx->nranges++;
89756 			r_start = t;
89757 			r_end = t;
89758 		}
89759 	}
89760 	DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
89761 	duk__append_u32(re_ctx, (duk_uint32_t) r_start);
89762 	duk__append_u32(re_ctx, (duk_uint32_t) r_end);
89763 	re_ctx->nranges++;
89764 #endif
89765 }
89766 
89767 /*
89768  *  Parse regexp Disjunction.  Most of regexp compilation happens here.
89769  *
89770  *  Handles Disjunction, Alternative, and Term productions directly without
89771  *  recursion.  The only constructs requiring recursion are positive/negative
89772  *  lookaheads, capturing parentheses, and non-capturing parentheses.
89773  *
89774  *  The function determines whether the entire disjunction is a 'simple atom'
89775  *  (see doc/regexp.rst discussion on 'simple quantifiers') and if so,
89776  *  returns the atom character length which is needed by the caller to keep
89777  *  track of its own atom character length.  A disjunction with more than one
89778  *  alternative is never considered a simple atom (although in some cases
89779  *  that might be the case).
89780  *
89781  *  Return value: simple atom character length or < 0 if not a simple atom.
89782  *  Appends the bytecode for the disjunction matcher to the end of the temp
89783  *  buffer.
89784  *
89785  *  Regexp top level structure is:
89786  *
89787  *    Disjunction = Term*
89788  *                | Term* | Disjunction
89789  *
89790  *    Term = Assertion
89791  *         | Atom
89792  *         | Atom Quantifier
89793  *
89794  *  An empty Term sequence is a valid disjunction alternative (e.g. /|||c||/).
89795  *
89796  *  Notes:
89797  *
89798  *    * Tracking of the 'simple-ness' of the current atom vs. the entire
89799  *      disjunction are separate matters.  For instance, the disjunction
89800  *      may be complex, but individual atoms may be simple.  Furthermore,
89801  *      simple quantifiers are used whenever possible, even if the
89802  *      disjunction as a whole is complex.
89803  *
89804  *    * The estimate of whether an atom is simple is conservative now,
89805  *      and it would be possible to expand it.  For instance, captures
89806  *      cause the disjunction to be marked complex, even though captures
89807  *      -can- be handled by simple quantifiers with some minor modifications.
89808  *
89809  *    * Disjunction 'tainting' as 'complex' is handled at the end of the
89810  *      main for loop collectively for atoms.  Assertions, quantifiers,
89811  *      and '|' tokens need to taint the result manually if necessary.
89812  *      Assertions cannot add to result char length, only atoms (and
89813  *      quantifiers) can; currently quantifiers will taint the result
89814  *      as complex though.
89815  */
89816 
89817 DUK_LOCAL const duk_uint16_t * const duk__re_range_lookup1[3] = {
89818 	duk_unicode_re_ranges_digit,
89819 	duk_unicode_re_ranges_white,
89820 	duk_unicode_re_ranges_wordchar
89821 };
89822 DUK_LOCAL const duk_uint8_t duk__re_range_lookup2[3] = {
89823 	sizeof(duk_unicode_re_ranges_digit) / (2 * sizeof(duk_uint16_t)),
89824 	sizeof(duk_unicode_re_ranges_white) / (2 * sizeof(duk_uint16_t)),
89825 	sizeof(duk_unicode_re_ranges_wordchar) / (2 * sizeof(duk_uint16_t))
89826 };
89827 
89828 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) {
89829 #if 0
89830 	DUK_ASSERT(re_op <= 0x7fUL);
89831 	DUK_ASSERT(count <= 0x7fUL);
89832 	duk__append_2bytes(re_ctx, (duk_uint8_t) re_op, (duk_uint8_t) count);
89833 #endif
89834 	duk__append_reop(re_ctx, re_op);
89835 	duk__append_7bit(re_ctx, count);
89836 	duk__append_u16_list(re_ctx, ranges, count * 2);
89837 }
89838 
89839 DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t expect_eof, duk__re_disjunction_info *out_atom_info) {
89840 	duk_int32_t atom_start_offset = -1;                   /* negative -> no atom matched on previous round */
89841 	duk_int32_t atom_char_length = 0;                     /* negative -> complex atom */
89842 	duk_uint32_t atom_start_captures = re_ctx->captures;  /* value of re_ctx->captures at start of atom */
89843 	duk_int32_t unpatched_disjunction_split = -1;
89844 	duk_int32_t unpatched_disjunction_jump = -1;
89845 	duk_uint32_t entry_offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
89846 	duk_int32_t res_charlen = 0;  /* -1 if disjunction is complex, char length if simple */
89847 	duk__re_disjunction_info tmp_disj;
89848 
89849 	DUK_ASSERT(out_atom_info != NULL);
89850 
89851 	duk_native_stack_check(re_ctx->thr);
89852 	if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
89853 		DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT);
89854 		DUK_WO_NORETURN(return;);
89855 	}
89856 	re_ctx->recursion_depth++;
89857 
89858 #if 0
89859 	out_atom_info->start_captures = re_ctx->captures;
89860 #endif
89861 
89862 	for (;;) {
89863 		/* atom_char_length, atom_start_offset, atom_start_offset reflect the
89864 		 * atom matched on the previous loop.  If a quantifier is encountered
89865 		 * on this loop, these are needed to handle the quantifier correctly.
89866 		 * new_atom_char_length etc are for the atom parsed on this round;
89867 		 * they're written to atom_char_length etc at the end of the round.
89868 		 */
89869 		duk_int32_t new_atom_char_length;   /* char length of the atom parsed in this loop */
89870 		duk_int32_t new_atom_start_offset;  /* bytecode start offset of the atom parsed in this loop
89871 		                                     * (allows quantifiers to copy the atom bytecode)
89872 		                                     */
89873 		duk_uint32_t new_atom_start_captures;  /* re_ctx->captures at the start of the atom parsed in this loop */
89874 
89875 		duk_lexer_parse_re_token(&re_ctx->lex, &re_ctx->curr_token);
89876 
89877 		DUK_DD(DUK_DDPRINT("re token: %ld (num=%ld, char=%c)",
89878 		                   (long) re_ctx->curr_token.t,
89879 		                   (long) re_ctx->curr_token.num,
89880 		                   (re_ctx->curr_token.num >= 0x20 && re_ctx->curr_token.num <= 0x7e) ?
89881 		                   (int) re_ctx->curr_token.num : (int) '?'));
89882 
89883 		/* set by atom case clauses */
89884 		new_atom_start_offset = -1;
89885 		new_atom_char_length = -1;
89886 		new_atom_start_captures = re_ctx->captures;
89887 
89888 		switch (re_ctx->curr_token.t) {
89889 		case DUK_RETOK_DISJUNCTION: {
89890 			/*
89891 			 *  The handling here is a bit tricky.  If a previous '|' has been processed,
89892 			 *  we have a pending split1 and a pending jump (for a previous match).  These
89893 			 *  need to be back-patched carefully.  See docs for a detailed example.
89894 			 */
89895 
89896 			/* patch pending jump and split */
89897 			if (unpatched_disjunction_jump >= 0) {
89898 				duk_uint32_t offset;
89899 
89900 				DUK_ASSERT(unpatched_disjunction_split >= 0);
89901 				offset = (duk_uint32_t) unpatched_disjunction_jump;
89902 				offset += duk__insert_jump_offset(re_ctx,
89903 				                                  offset,
89904 				                                  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
89905 				/* offset is now target of the pending split (right after jump) */
89906 				duk__insert_jump_offset(re_ctx,
89907 				                        (duk_uint32_t) unpatched_disjunction_split,
89908 				                        (duk_int32_t) offset - unpatched_disjunction_split);
89909 			}
89910 
89911 			/* add a new pending split to the beginning of the entire disjunction */
89912 			(void) duk__insert_u32(re_ctx,
89913 			                       entry_offset,
89914 			                       DUK_REOP_SPLIT1);   /* prefer direct execution */
89915 			unpatched_disjunction_split = (duk_int32_t) (entry_offset + 1);   /* +1 for opcode */
89916 
89917 			/* add a new pending match jump for latest finished alternative */
89918 			duk__append_reop(re_ctx, DUK_REOP_JUMP);
89919 			unpatched_disjunction_jump = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
89920 
89921 			/* 'taint' result as complex */
89922 			res_charlen = -1;
89923 			break;
89924 		}
89925 		case DUK_RETOK_QUANTIFIER: {
89926 			if (atom_start_offset < 0) {
89927 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_NO_ATOM);
89928 				DUK_WO_NORETURN(return;);
89929 			}
89930 			if (re_ctx->curr_token.qmin > re_ctx->curr_token.qmax) {
89931 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_VALUES);
89932 				DUK_WO_NORETURN(return;);
89933 			}
89934 			if (atom_char_length >= 0) {
89935 				/*
89936 				 *  Simple atom
89937 				 *
89938 				 *  If atom_char_length is zero, we'll have unbounded execution time for e.g.
89939 				 *  /()*x/.exec('x').  We can't just skip the match because it might have some
89940 				 *  side effects (for instance, if we allowed captures in simple atoms, the
89941 				 *  capture needs to happen).  The simple solution below is to force the
89942 				 *  quantifier to match at most once, since the additional matches have no effect.
89943 				 *
89944 				 *  With a simple atom there can be no capture groups, so no captures need
89945 				 *  to be reset.
89946 				 */
89947 				duk_int32_t atom_code_length;
89948 				duk_uint32_t offset;
89949 				duk_uint32_t qmin, qmax;
89950 
89951 				qmin = re_ctx->curr_token.qmin;
89952 				qmax = re_ctx->curr_token.qmax;
89953 				if (atom_char_length == 0) {
89954 					/* qmin and qmax will be 0 or 1 */
89955 					if (qmin > 1) {
89956 						qmin = 1;
89957 					}
89958 					if (qmax > 1) {
89959 						qmax = 1;
89960 					}
89961 				}
89962 
89963 				duk__append_reop(re_ctx, DUK_REOP_MATCH);   /* complete 'sub atom' */
89964 				atom_code_length = (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (duk_size_t) atom_start_offset);
89965 
89966 				offset = (duk_uint32_t) atom_start_offset;
89967 				if (re_ctx->curr_token.greedy) {
89968 					offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQGREEDY);
89969 					offset += duk__insert_u32(re_ctx, offset, qmin);
89970 					offset += duk__insert_u32(re_ctx, offset, qmax);
89971 					offset += duk__insert_u32(re_ctx, offset, (duk_uint32_t) atom_char_length);
89972 					offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
89973 				} else {
89974 					offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQMINIMAL);
89975 					offset += duk__insert_u32(re_ctx, offset, qmin);
89976 					offset += duk__insert_u32(re_ctx, offset, qmax);
89977 					offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
89978 				}
89979 				DUK_UNREF(offset);  /* silence scan-build warning */
89980 			} else {
89981 				/*
89982 				 *  Complex atom
89983 				 *
89984 				 *  The original code is used as a template, and removed at the end
89985 				 *  (this differs from the handling of simple quantifiers).
89986 				 *
89987 				 *  NOTE: there is no current solution for empty atoms in complex
89988 				 *  quantifiers.  This would need some sort of a 'progress' instruction.
89989 				 *
89990 				 *  XXX: impose limit on maximum result size, i.e. atom_code_len * atom_copies?
89991 				 */
89992 				duk_int32_t atom_code_length;
89993 				duk_uint32_t atom_copies;
89994 				duk_uint32_t tmp_qmin, tmp_qmax;
89995 
89996 				/* pre-check how many atom copies we're willing to make (atom_copies not needed below) */
89997 				atom_copies = (re_ctx->curr_token.qmax == DUK_RE_QUANTIFIER_INFINITE) ?
89998 				              re_ctx->curr_token.qmin : re_ctx->curr_token.qmax;
89999 				if (atom_copies > DUK_RE_MAX_ATOM_COPIES) {
90000 					DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_QUANTIFIER_TOO_MANY_COPIES);
90001 					DUK_WO_NORETURN(return;);
90002 				}
90003 
90004 				/* wipe the capture range made by the atom (if any) */
90005 				DUK_ASSERT(atom_start_captures <= re_ctx->captures);
90006 				if (atom_start_captures != re_ctx->captures) {
90007 					DUK_ASSERT(atom_start_captures < re_ctx->captures);
90008 					DUK_DDD(DUK_DDDPRINT("must wipe ]atom_start_captures,re_ctx->captures]: ]%ld,%ld]",
90009 					                     (long) atom_start_captures, (long) re_ctx->captures));
90010 
90011 					/* insert (DUK_REOP_WIPERANGE, start, count) in reverse order so the order ends up right */
90012 					duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, (re_ctx->captures - atom_start_captures) * 2U);
90013 					duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, (atom_start_captures + 1) * 2);
90014 					duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, DUK_REOP_WIPERANGE);
90015 				} else {
90016 					DUK_DDD(DUK_DDDPRINT("no need to wipe captures: atom_start_captures == re_ctx->captures == %ld",
90017 					                     (long) atom_start_captures));
90018 				}
90019 
90020 				atom_code_length = (duk_int32_t) DUK__RE_BUFLEN(re_ctx) - atom_start_offset;
90021 
90022 				/* insert the required matches (qmin) by copying the atom */
90023 				tmp_qmin = re_ctx->curr_token.qmin;
90024 				tmp_qmax = re_ctx->curr_token.qmax;
90025 				while (tmp_qmin > 0) {
90026 					duk__append_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
90027 					tmp_qmin--;
90028 					if (tmp_qmax != DUK_RE_QUANTIFIER_INFINITE) {
90029 						tmp_qmax--;
90030 					}
90031 				}
90032 				DUK_ASSERT(tmp_qmin == 0);
90033 
90034 				/* insert code for matching the remainder - infinite or finite */
90035 				if (tmp_qmax == DUK_RE_QUANTIFIER_INFINITE) {
90036 					/* reuse last emitted atom for remaining 'infinite' quantifier */
90037 
90038 					if (re_ctx->curr_token.qmin == 0) {
90039 						/* Special case: original qmin was zero so there is nothing
90040 						 * to repeat.  Emit an atom copy but jump over it here.
90041 						 */
90042 						duk__append_reop(re_ctx, DUK_REOP_JUMP);
90043 						duk__append_jump_offset(re_ctx, atom_code_length);
90044 						duk__append_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
90045 					}
90046 					if (re_ctx->curr_token.greedy) {
90047 						duk__append_reop(re_ctx, DUK_REOP_SPLIT2);   /* prefer jump */
90048 					} else {
90049 						duk__append_reop(re_ctx, DUK_REOP_SPLIT1);   /* prefer direct */
90050 					}
90051 					duk__append_jump_offset(re_ctx, -atom_code_length - 1);  /* -1 for opcode */
90052 				} else {
90053 					/*
90054 					 *  The remaining matches are emitted as sequence of SPLITs and atom
90055 					 *  copies; the SPLITs skip the remaining copies and match the sequel.
90056 					 *  This sequence needs to be emitted starting from the last copy
90057 					 *  because the SPLITs are variable length due to the variable length
90058 					 *  skip offset.  This causes a lot of memory copying now.
90059 					 *
90060 					 *  Example structure (greedy, match maximum # atoms):
90061 					 *
90062 					 *      SPLIT1 LSEQ
90063 					 *      (atom)
90064 					 *      SPLIT1 LSEQ    ; <- the byte length of this instruction is needed
90065 					 *      (atom)         ; to encode the above SPLIT1 correctly
90066 					 *      ...
90067 					 *   LSEQ:
90068 					 */
90069 					duk_uint32_t offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
90070 					while (tmp_qmax > 0) {
90071 						duk__insert_slice(re_ctx, offset, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
90072 						if (re_ctx->curr_token.greedy) {
90073 							duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT1);   /* prefer direct */
90074 						} else {
90075 							duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT2);   /* prefer jump */
90076 						}
90077 						duk__insert_jump_offset(re_ctx,
90078 						                        offset + 1,   /* +1 for opcode */
90079 						                        (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
90080 						tmp_qmax--;
90081 					}
90082 				}
90083 
90084 				/* remove the original 'template' atom */
90085 				duk__remove_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
90086 			}
90087 
90088 			/* 'taint' result as complex */
90089 			res_charlen = -1;
90090 			break;
90091 		}
90092 		case DUK_RETOK_ASSERT_START: {
90093 			duk__append_reop(re_ctx, DUK_REOP_ASSERT_START);
90094 			break;
90095 		}
90096 		case DUK_RETOK_ASSERT_END: {
90097 			duk__append_reop(re_ctx, DUK_REOP_ASSERT_END);
90098 			break;
90099 		}
90100 		case DUK_RETOK_ASSERT_WORD_BOUNDARY: {
90101 			duk__append_reop(re_ctx, DUK_REOP_ASSERT_WORD_BOUNDARY);
90102 			break;
90103 		}
90104 		case DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY: {
90105 			duk__append_reop(re_ctx, DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);
90106 			break;
90107 		}
90108 		case DUK_RETOK_ASSERT_START_POS_LOOKAHEAD:
90109 		case DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD: {
90110 			duk_uint32_t offset;
90111 			duk_uint32_t opcode = (re_ctx->curr_token.t == DUK_RETOK_ASSERT_START_POS_LOOKAHEAD) ?
90112 			                      DUK_REOP_LOOKPOS : DUK_REOP_LOOKNEG;
90113 
90114 			offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
90115 			duk__parse_disjunction(re_ctx, 0, &tmp_disj);
90116 			duk__append_reop(re_ctx, DUK_REOP_MATCH);
90117 
90118 			(void) duk__insert_u32(re_ctx, offset, opcode);
90119 			(void) duk__insert_jump_offset(re_ctx,
90120 			                               offset + 1,   /* +1 for opcode */
90121 			                               (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
90122 
90123 			/* 'taint' result as complex -- this is conservative,
90124 			 * as lookaheads do not backtrack.
90125 			 */
90126 			res_charlen = -1;
90127 			break;
90128 		}
90129 		case DUK_RETOK_ATOM_PERIOD: {
90130 			new_atom_char_length = 1;
90131 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
90132 			duk__append_reop(re_ctx, DUK_REOP_PERIOD);
90133 			break;
90134 		}
90135 		case DUK_RETOK_ATOM_CHAR: {
90136 			/* Note: successive characters could be joined into string matches
90137 			 * but this is not trivial (consider e.g. '/xyz+/); see docs for
90138 			 * more discussion.
90139 			 *
90140 			 * No support for \u{H+} yet.  While only BMP Unicode escapes are
90141 			 * supported for RegExps at present, 'ch' may still be a non-BMP
90142 			 * codepoint if it is decoded straight from source text UTF-8.
90143 			 * There's no non-BMP support yet so this is handled simply by
90144 			 * matching the non-BMP character (which is custom behavior).
90145 			 */
90146 			duk_uint32_t ch;
90147 
90148 			new_atom_char_length = 1;
90149 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
90150 			duk__append_reop(re_ctx, DUK_REOP_CHAR);
90151 			ch = re_ctx->curr_token.num;
90152 			if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
90153 				ch = (duk_uint32_t) duk_unicode_re_canonicalize_char(re_ctx->thr, (duk_codepoint_t) ch);
90154 			}
90155 			duk__append_u32(re_ctx, ch);
90156 			break;
90157 		}
90158 		case DUK_RETOK_ATOM_DIGIT:
90159 		case DUK_RETOK_ATOM_NOT_DIGIT:
90160 		case DUK_RETOK_ATOM_WHITE:
90161 		case DUK_RETOK_ATOM_NOT_WHITE:
90162 		case DUK_RETOK_ATOM_WORD_CHAR:
90163 		case DUK_RETOK_ATOM_NOT_WORD_CHAR: {
90164 			duk_small_uint_t re_op;
90165 			duk_small_uint_t idx;
90166 
90167 			new_atom_char_length = 1;
90168 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
90169 
90170 			DUK_ASSERT((DUK_RETOK_ATOM_DIGIT & 0x01) != 0);
90171 			DUK_ASSERT((DUK_RETOK_ATOM_WHITE & 0x01) != 0);
90172 			DUK_ASSERT((DUK_RETOK_ATOM_WORD_CHAR & 0x01) != 0);
90173 			DUK_ASSERT((DUK_RETOK_ATOM_NOT_DIGIT & 0x01) == 0);
90174 			DUK_ASSERT((DUK_RETOK_ATOM_NOT_WHITE & 0x01) == 0);
90175 			DUK_ASSERT((DUK_RETOK_ATOM_NOT_WORD_CHAR & 0x01) == 0);
90176 			re_op = (re_ctx->curr_token.t & 0x01) ? DUK_REOP_RANGES : DUK_REOP_INVRANGES;
90177 
90178 			DUK_ASSERT(DUK_RETOK_ATOM_WHITE == DUK_RETOK_ATOM_DIGIT + 2);
90179 			DUK_ASSERT(DUK_RETOK_ATOM_WORD_CHAR == DUK_RETOK_ATOM_DIGIT + 4);
90180 			idx = (duk_small_uint_t) ((re_ctx->curr_token.t - DUK_RETOK_ATOM_DIGIT) >> 1U);
90181 			DUK_ASSERT(idx <= 2U);  /* Assume continuous token numbers; also checks negative underflow. */
90182 
90183 			duk__append_range_atom_matcher(re_ctx, re_op, duk__re_range_lookup1[idx], duk__re_range_lookup2[idx]);
90184 			break;
90185 		}
90186 		case DUK_RETOK_ATOM_BACKREFERENCE: {
90187 			duk_uint32_t backref = (duk_uint32_t) re_ctx->curr_token.num;
90188 			if (backref > re_ctx->highest_backref) {
90189 				re_ctx->highest_backref = backref;
90190 			}
90191 			new_atom_char_length = -1;   /* mark as complex */
90192 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
90193 			duk__append_reop(re_ctx, DUK_REOP_BACKREFERENCE);
90194 			duk__append_u32(re_ctx, backref);
90195 			break;
90196 		}
90197 		case DUK_RETOK_ATOM_START_CAPTURE_GROUP: {
90198 			duk_uint32_t cap;
90199 
90200 			new_atom_char_length = -1;   /* mark as complex (capture handling) */
90201 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
90202 			cap = ++re_ctx->captures;
90203 			duk__append_reop(re_ctx, DUK_REOP_SAVE);
90204 			duk__append_u32(re_ctx, cap * 2);
90205 			duk__parse_disjunction(re_ctx, 0, &tmp_disj);  /* retval (sub-atom char length) unused, tainted as complex above */
90206 			duk__append_reop(re_ctx, DUK_REOP_SAVE);
90207 			duk__append_u32(re_ctx, cap * 2 + 1);
90208 			break;
90209 		}
90210 		case DUK_RETOK_ATOM_START_NONCAPTURE_GROUP: {
90211 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
90212 			duk__parse_disjunction(re_ctx, 0, &tmp_disj);
90213 			new_atom_char_length = tmp_disj.charlen;
90214 			break;
90215 		}
90216 		case DUK_RETOK_ATOM_START_CHARCLASS:
90217 		case DUK_RETOK_ATOM_START_CHARCLASS_INVERTED: {
90218 			/*
90219 			 *  Range parsing is done with a special lexer function which calls
90220 			 *  us for every range parsed.  This is different from how rest of
90221 			 *  the parsing works, but avoids a heavy, arbitrary size intermediate
90222 			 *  value type to hold the ranges.
90223 			 *
90224 			 *  Another complication is the handling of character ranges when
90225 			 *  case insensitive matching is used (see docs for discussion).
90226 			 *  The range handler callback given to the lexer takes care of this
90227 			 *  as well.
90228 			 *
90229 			 *  Note that duplicate ranges are not eliminated when parsing character
90230 			 *  classes, so that canonicalization of
90231 			 *
90232 			 *    [0-9a-fA-Fx-{]
90233 			 *
90234 			 *  creates the result (note the duplicate ranges):
90235 			 *
90236 			 *    [0-9A-FA-FX-Z{-{]
90237 			 *
90238 			 *  where [x-{] is split as a result of canonicalization.  The duplicate
90239 			 *  ranges are not a semantics issue: they work correctly.
90240 			 */
90241 
90242 			duk_uint32_t offset;
90243 
90244 			DUK_DD(DUK_DDPRINT("character class"));
90245 
90246 			/* insert ranges instruction, range count patched in later */
90247 			new_atom_char_length = 1;
90248 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
90249 			duk__append_reop(re_ctx,
90250 			                 (re_ctx->curr_token.t == DUK_RETOK_ATOM_START_CHARCLASS) ?
90251 			                 DUK_REOP_RANGES : DUK_REOP_INVRANGES);
90252 			offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);    /* patch in range count later */
90253 
90254 			/* parse ranges until character class ends */
90255 			re_ctx->nranges = 0;    /* note: ctx-wide temporary */
90256 			duk_lexer_parse_re_ranges(&re_ctx->lex, duk__regexp_generate_ranges, (void *) re_ctx);
90257 
90258 			/* insert range count */
90259 			duk__insert_u32(re_ctx, offset, re_ctx->nranges);
90260 			break;
90261 		}
90262 		case DUK_RETOK_ATOM_END_GROUP: {
90263 			if (expect_eof) {
90264 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_CLOSING_PAREN);
90265 				DUK_WO_NORETURN(return;);
90266 			}
90267 			goto done;
90268 		}
90269 		case DUK_RETOK_EOF: {
90270 			if (!expect_eof) {
90271 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_END_OF_PATTERN);
90272 				DUK_WO_NORETURN(return;);
90273 			}
90274 			goto done;
90275 		}
90276 		default: {
90277 			DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_REGEXP_TOKEN);
90278 			DUK_WO_NORETURN(return;);
90279 		}
90280 		}
90281 
90282 		/* a complex (new) atom taints the result */
90283 		if (new_atom_start_offset >= 0) {
90284 			if (new_atom_char_length < 0) {
90285 				res_charlen = -1;
90286 			} else if (res_charlen >= 0) {
90287 				/* only advance if not tainted */
90288 				res_charlen += new_atom_char_length;
90289 			}
90290 		}
90291 
90292 		/* record previous atom info in case next token is a quantifier */
90293 		atom_start_offset = new_atom_start_offset;
90294 		atom_char_length = new_atom_char_length;
90295 		atom_start_captures = new_atom_start_captures;
90296 	}
90297 
90298  done:
90299 
90300 	/* finish up pending jump and split for last alternative */
90301 	if (unpatched_disjunction_jump >= 0) {
90302 		duk_uint32_t offset;
90303 
90304 		DUK_ASSERT(unpatched_disjunction_split >= 0);
90305 		offset = (duk_uint32_t) unpatched_disjunction_jump;
90306 		offset += duk__insert_jump_offset(re_ctx,
90307 		                                  offset,
90308 		                                  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
90309 		/* offset is now target of the pending split (right after jump) */
90310 		duk__insert_jump_offset(re_ctx,
90311 		                        (duk_uint32_t) unpatched_disjunction_split,
90312 		                        (duk_int32_t) offset - unpatched_disjunction_split);
90313 	}
90314 
90315 #if 0
90316 	out_atom_info->end_captures = re_ctx->captures;
90317 #endif
90318 	out_atom_info->charlen = res_charlen;
90319 	DUK_DDD(DUK_DDDPRINT("parse disjunction finished: charlen=%ld",
90320 	                     (long) out_atom_info->charlen));
90321 
90322 	re_ctx->recursion_depth--;
90323 }
90324 
90325 /*
90326  *  Flags parsing (see E5 Section 15.10.4.1).
90327  */
90328 
90329 DUK_LOCAL duk_uint32_t duk__parse_regexp_flags(duk_hthread *thr, duk_hstring *h) {
90330 	const duk_uint8_t *p;
90331 	const duk_uint8_t *p_end;
90332 	duk_uint32_t flags = 0;
90333 
90334 	p = DUK_HSTRING_GET_DATA(h);
90335 	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
90336 
90337 	/* Note: can be safely scanned as bytes (undecoded) */
90338 
90339 	while (p < p_end) {
90340 		duk_uint8_t c = *p++;
90341 		switch (c) {
90342 		case (duk_uint8_t) 'g': {
90343 			if (flags & DUK_RE_FLAG_GLOBAL) {
90344 				goto flags_error;
90345 			}
90346 			flags |= DUK_RE_FLAG_GLOBAL;
90347 			break;
90348 		}
90349 		case (duk_uint8_t) 'i': {
90350 			if (flags & DUK_RE_FLAG_IGNORE_CASE) {
90351 				goto flags_error;
90352 			}
90353 			flags |= DUK_RE_FLAG_IGNORE_CASE;
90354 			break;
90355 		}
90356 		case (duk_uint8_t) 'm': {
90357 			if (flags & DUK_RE_FLAG_MULTILINE) {
90358 				goto flags_error;
90359 			}
90360 			flags |= DUK_RE_FLAG_MULTILINE;
90361 			break;
90362 		}
90363 		default: {
90364 			goto flags_error;
90365 		}
90366 		}
90367 	}
90368 
90369 	return flags;
90370 
90371  flags_error:
90372 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_REGEXP_FLAGS);
90373 	DUK_WO_NORETURN(return 0U;);
90374 }
90375 
90376 /*
90377  *  Create escaped RegExp source (E5 Section 15.10.3).
90378  *
90379  *  The current approach is to special case the empty RegExp
90380  *  ('' -> '(?:)') and otherwise replace unescaped '/' characters
90381  *  with '\/' regardless of where they occur in the regexp.
90382  *
90383  *  Note that normalization does not seem to be necessary for
90384  *  RegExp literals (e.g. '/foo/') because to be acceptable as
90385  *  a RegExp literal, the text between forward slashes must
90386  *  already match the escaping requirements (e.g. must not contain
90387  *  unescaped forward slashes or be empty).  Escaping IS needed
90388  *  for expressions like 'new Regexp("...", "")' however.
90389  *  Currently, we re-escape in either case.
90390  *
90391  *  Also note that we process the source here in UTF-8 encoded
90392  *  form.  This is correct, because any non-ASCII characters are
90393  *  passed through without change.
90394  */
90395 
90396 DUK_LOCAL void duk__create_escaped_source(duk_hthread *thr, int idx_pattern) {
90397 	duk_hstring *h;
90398 	const duk_uint8_t *p;
90399 	duk_bufwriter_ctx bw_alloc;
90400 	duk_bufwriter_ctx *bw;
90401 	duk_uint8_t *q;
90402 	duk_size_t i, n;
90403 	duk_uint_fast8_t c_prev, c;
90404 
90405 	h = duk_known_hstring(thr, idx_pattern);
90406 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
90407 	n = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
90408 
90409 	if (n == 0) {
90410 		duk_push_literal(thr, "(?:)");
90411 		return;
90412 	}
90413 
90414 	bw = &bw_alloc;
90415 	DUK_BW_INIT_PUSHBUF(thr, bw, n);
90416 	q = DUK_BW_GET_PTR(thr, bw);
90417 
90418 	c_prev = (duk_uint_fast8_t) 0;
90419 
90420 	for (i = 0; i < n; i++) {
90421 		c = p[i];
90422 
90423 		q = DUK_BW_ENSURE_RAW(thr, bw, 2, q);
90424 
90425 		if (c == (duk_uint_fast8_t) '/' && c_prev != (duk_uint_fast8_t) '\\') {
90426 			/* Unescaped '/' ANYWHERE in the regexp (in disjunction,
90427 			 * inside a character class, ...) => same escape works.
90428 			 */
90429 			*q++ = DUK_ASC_BACKSLASH;
90430 		}
90431 		*q++ = (duk_uint8_t) c;
90432 
90433 		c_prev = c;
90434 	}
90435 
90436 	DUK_BW_SETPTR_AND_COMPACT(thr, bw, q);
90437 	(void) duk_buffer_to_string(thr, -1);  /* Safe if input is safe. */
90438 
90439 	/* [ ... escaped_source ] */
90440 }
90441 
90442 /*
90443  *  Exposed regexp compilation primitive.
90444  *
90445  *  Sets up a regexp compilation context, and calls duk__parse_disjunction() to do the
90446  *  actual parsing.  Handles generation of the compiled regexp header and the
90447  *  "boilerplate" capture of the matching substring (save 0 and 1).  Also does some
90448  *  global level regexp checks after recursive compilation has finished.
90449  *
90450  *  An escaped version of the regexp source, suitable for use as a RegExp instance
90451  *  'source' property (see E5 Section 15.10.3), is also left on the stack.
90452  *
90453  *  Input stack:  [ pattern flags ]
90454  *  Output stack: [ bytecode escaped_source ]  (both as strings)
90455  */
90456 
90457 DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) {
90458 	duk_re_compiler_ctx re_ctx;
90459 	duk_lexer_point lex_point;
90460 	duk_hstring *h_pattern;
90461 	duk_hstring *h_flags;
90462 	duk__re_disjunction_info ign_disj;
90463 
90464 	DUK_ASSERT(thr != NULL);
90465 
90466 	/*
90467 	 *  Args validation
90468 	 */
90469 
90470 	/* TypeError if fails */
90471 	h_pattern = duk_require_hstring_notsymbol(thr, -2);
90472 	h_flags = duk_require_hstring_notsymbol(thr, -1);
90473 
90474 	/*
90475 	 *  Create normalized 'source' property (E5 Section 15.10.3).
90476 	 */
90477 
90478 	/* [ ... pattern flags ] */
90479 
90480 	duk__create_escaped_source(thr, -2);
90481 
90482 	/* [ ... pattern flags escaped_source ] */
90483 
90484 	/*
90485 	 *  Init compilation context
90486 	 */
90487 
90488 	/* [ ... pattern flags escaped_source buffer ] */
90489 
90490 	duk_memzero(&re_ctx, sizeof(re_ctx));
90491 	DUK_LEXER_INITCTX(&re_ctx.lex);  /* duplicate zeroing, expect for (possible) NULL inits */
90492 	re_ctx.thr = thr;
90493 	re_ctx.lex.thr = thr;
90494 	re_ctx.lex.input = DUK_HSTRING_GET_DATA(h_pattern);
90495 	re_ctx.lex.input_length = DUK_HSTRING_GET_BYTELEN(h_pattern);
90496 	re_ctx.lex.token_limit = DUK_RE_COMPILE_TOKEN_LIMIT;
90497 	re_ctx.recursion_limit = DUK_USE_REGEXP_COMPILER_RECLIMIT;
90498 	re_ctx.re_flags = duk__parse_regexp_flags(thr, h_flags);
90499 
90500 	DUK_BW_INIT_PUSHBUF(thr, &re_ctx.bw, DUK__RE_INITIAL_BUFSIZE);
90501 
90502 	DUK_DD(DUK_DDPRINT("regexp compiler ctx initialized, flags=0x%08lx, recursion_limit=%ld",
90503 	                   (unsigned long) re_ctx.re_flags, (long) re_ctx.recursion_limit));
90504 
90505 	/*
90506 	 *  Init lexer
90507 	 */
90508 
90509 	lex_point.offset = 0;  /* expensive init, just want to fill window */
90510 	lex_point.line = 1;
90511 	DUK_LEXER_SETPOINT(&re_ctx.lex, &lex_point);
90512 
90513 	/*
90514 	 *  Compilation
90515 	 */
90516 
90517 	DUK_DD(DUK_DDPRINT("starting regexp compilation"));
90518 
90519 	duk__append_reop(&re_ctx, DUK_REOP_SAVE);
90520 	duk__append_7bit(&re_ctx, 0);
90521 	duk__parse_disjunction(&re_ctx, 1 /*expect_eof*/, &ign_disj);
90522 	duk__append_reop(&re_ctx, DUK_REOP_SAVE);
90523 	duk__append_7bit(&re_ctx, 1);
90524 	duk__append_reop(&re_ctx, DUK_REOP_MATCH);
90525 
90526 	/*
90527 	 *  Check for invalid backreferences; note that it is NOT an error
90528 	 *  to back-reference a capture group which has not yet been introduced
90529 	 *  in the pattern (as in /\1(foo)/); in fact, the backreference will
90530 	 *  always match!  It IS an error to back-reference a capture group
90531 	 *  which will never be introduced in the pattern.  Thus, we can check
90532 	 *  for such references only after parsing is complete.
90533 	 */
90534 
90535 	if (re_ctx.highest_backref > re_ctx.captures) {
90536 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BACKREFS);
90537 		DUK_WO_NORETURN(return;);
90538 	}
90539 
90540 	/*
90541 	 *  Emit compiled regexp header: flags, ncaptures
90542 	 *  (insertion order inverted on purpose)
90543 	 */
90544 
90545 	duk__insert_u32(&re_ctx, 0, (re_ctx.captures + 1) * 2);
90546 	duk__insert_u32(&re_ctx, 0, re_ctx.re_flags);
90547 
90548 	/* [ ... pattern flags escaped_source buffer ] */
90549 
90550 	DUK_BW_COMPACT(thr, &re_ctx.bw);
90551 	(void) duk_buffer_to_string(thr, -1);  /* Safe because flags is at most 7 bit. */
90552 
90553 	/* [ ... pattern flags escaped_source bytecode ] */
90554 
90555 	/*
90556 	 *  Finalize stack
90557 	 */
90558 
90559 	duk_remove(thr, -4);     /* -> [ ... flags escaped_source bytecode ] */
90560 	duk_remove(thr, -3);     /* -> [ ... escaped_source bytecode ] */
90561 
90562 	DUK_DD(DUK_DDPRINT("regexp compilation successful, bytecode: %!T, escaped source: %!T",
90563 	                   (duk_tval *) duk_get_tval(thr, -1), (duk_tval *) duk_get_tval(thr, -2)));
90564 }
90565 
90566 /*
90567  *  Create a RegExp instance (E5 Section 15.10.7).
90568  *
90569  *  Note: the output stack left by duk_regexp_compile() is directly compatible
90570  *  with the input here.
90571  *
90572  *  Input stack:  [ escaped_source bytecode ]  (both as strings)
90573  *  Output stack: [ RegExp ]
90574  */
90575 
90576 DUK_INTERNAL void duk_regexp_create_instance(duk_hthread *thr) {
90577 	duk_hobject *h;
90578 
90579 	/* [ ... escaped_source bytecode ] */
90580 
90581 	duk_push_object(thr);
90582 	h = duk_known_hobject(thr, -1);
90583 	duk_insert(thr, -3);
90584 
90585 	/* [ ... regexp_object escaped_source bytecode ] */
90586 
90587 	DUK_HOBJECT_SET_CLASS_NUMBER(h, DUK_HOBJECT_CLASS_REGEXP);
90588 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]);
90589 
90590 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_BYTECODE, DUK_PROPDESC_FLAGS_NONE);
90591 
90592 	/* [ ... regexp_object escaped_source ] */
90593 
90594 	/* In ES2015 .source, and the .global, .multiline, etc flags are
90595 	 * inherited getters.  Store the escaped source as an internal
90596 	 * property for the getter.
90597 	 */
90598 
90599 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE);
90600 
90601 	/* [ ... regexp_object ] */
90602 
90603 	duk_push_int(thr, 0);
90604 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LAST_INDEX, DUK_PROPDESC_FLAGS_W);
90605 
90606 	/* [ ... regexp_object ] */
90607 }
90608 
90609 #else  /* DUK_USE_REGEXP_SUPPORT */
90610 
90611 /* regexp support disabled */
90612 
90613 #endif  /* DUK_USE_REGEXP_SUPPORT */
90614 
90615 /* automatic undefs */
90616 #undef DUK__RE_BUFLEN
90617 #undef DUK__RE_INITIAL_BUFSIZE
90618 #line 1 "duk_regexp_executor.c"
90619 /*
90620  *  Regexp executor.
90621  *
90622  *  Safety: the ECMAScript executor should prevent user from reading and
90623  *  replacing regexp bytecode.  Even so, the executor must validate all
90624  *  memory accesses etc.  When an invalid access is detected (e.g. a 'save'
90625  *  opcode to invalid, unallocated index) it should fail with an internal
90626  *  error but not cause a segmentation fault.
90627  *
90628  *  Notes:
90629  *
90630  *    - Backtrack counts are limited to unsigned 32 bits but should
90631  *      technically be duk_size_t for strings longer than 4G chars.
90632  *      This also requires a regexp bytecode change.
90633  */
90634 
90635 /* #include duk_internal.h -> already included */
90636 
90637 #if defined(DUK_USE_REGEXP_SUPPORT)
90638 
90639 /*
90640  *  Helpers for UTF-8 handling
90641  *
90642  *  For bytecode readers the duk_uint32_t and duk_int32_t types are correct
90643  *  because they're used for more than just codepoints.
90644  */
90645 
90646 DUK_LOCAL duk_uint32_t duk__bc_get_u32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
90647 	return (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
90648 }
90649 
90650 DUK_LOCAL duk_int32_t duk__bc_get_i32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
90651 	duk_uint32_t t;
90652 
90653 	/* signed integer encoding needed to work with UTF-8 */
90654 	t = (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
90655 	if (t & 1) {
90656 		return -((duk_int32_t) (t >> 1));
90657 	} else {
90658 		return (duk_int32_t) (t >> 1);
90659 	}
90660 }
90661 
90662 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) {
90663 	const duk_uint8_t *p;
90664 
90665 	/* Note: allow backtracking from p == ptr_end */
90666 	p = *ptr;
90667 	if (p < ptr_start || p > ptr_end) {
90668 		goto fail;
90669 	}
90670 
90671 	while (count > 0) {
90672 		for (;;) {
90673 			p--;
90674 			if (p < ptr_start) {
90675 				goto fail;
90676 			}
90677 			if ((*p & 0xc0) != 0x80) {
90678 				/* utf-8 continuation bytes have the form 10xx xxxx */
90679 				break;
90680 			}
90681 		}
90682 		count--;
90683 	}
90684 	*ptr = p;
90685 	return p;
90686 
90687  fail:
90688 	DUK_ERROR_INTERNAL(thr);
90689 	DUK_WO_NORETURN(return NULL;);
90690 }
90691 
90692 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) {
90693 	const duk_uint8_t *p;
90694 
90695 	p = *ptr;
90696 	if (p < ptr_start || p >= ptr_end) {
90697 		goto fail;
90698 	}
90699 
90700 	while (count > 0) {
90701 		for (;;) {
90702 			p++;
90703 
90704 			/* Note: if encoding ends by hitting end of input, we don't check that
90705 			 * the encoding is valid, we just assume it is.
90706 			 */
90707 			if (p >= ptr_end || ((*p & 0xc0) != 0x80)) {
90708 				/* utf-8 continuation bytes have the form 10xx xxxx */
90709 				break;
90710 			}
90711 		}
90712 		count--;
90713 	}
90714 
90715 	*ptr = p;
90716 	return p;
90717 
90718  fail:
90719 	DUK_ERROR_INTERNAL(thr);
90720 	DUK_WO_NORETURN(return NULL;);
90721 }
90722 
90723 /*
90724  *  Helpers for dealing with the input string
90725  */
90726 
90727 /* Get a (possibly canonicalized) input character from current sp.  The input
90728  * itself is never modified, and captures always record non-canonicalized
90729  * characters even in case-insensitive matching.  Return <0 if out of input.
90730  */
90731 DUK_LOCAL duk_codepoint_t duk__inp_get_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp) {
90732 	duk_codepoint_t res;
90733 
90734 	if (*sp >= re_ctx->input_end) {
90735 		return -1;
90736 	}
90737 	res = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end);
90738 	if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
90739 		res = duk_unicode_re_canonicalize_char(re_ctx->thr, res);
90740 	}
90741 	return res;
90742 }
90743 
90744 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) {
90745 	return duk__utf8_backtrack(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end, count);
90746 }
90747 
90748 /* Backtrack utf-8 input and return a (possibly canonicalized) input character. */
90749 DUK_LOCAL duk_codepoint_t duk__inp_get_prev_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *sp) {
90750 	/* note: caller 'sp' is intentionally not updated here */
90751 	(void) duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) 1);
90752 	return duk__inp_get_cp(re_ctx, &sp);
90753 }
90754 
90755 /*
90756  *  Regexp recursive matching function.
90757  *
90758  *  Returns 'sp' on successful match (points to character after last matched one),
90759  *  NULL otherwise.
90760  *
90761  *  The C recursion depth limit check is only performed in this function, this
90762  *  suffices because the function is present in all true recursion required by
90763  *  regexp execution.
90764  */
90765 
90766 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) {
90767 	duk_native_stack_check(re_ctx->thr);
90768 	if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
90769 		DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT);
90770 		DUK_WO_NORETURN(return NULL;);
90771 	}
90772 	re_ctx->recursion_depth++;
90773 
90774 	for (;;) {
90775 		duk_small_int_t op;
90776 
90777 		if (re_ctx->steps_count >= re_ctx->steps_limit) {
90778 			DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT);
90779 			DUK_WO_NORETURN(return NULL;);
90780 		}
90781 		re_ctx->steps_count++;
90782 
90783 		/* Opcodes are at most 7 bits now so they encode to one byte.  If this
90784 		 * were not the case or 'pc' is invalid here (due to a bug etc) we'll
90785 		 * still fail safely through the switch default case.
90786 		 */
90787 		DUK_ASSERT(pc[0] <= 0x7fU);
90788 #if 0
90789 		op = (duk_small_int_t) duk__bc_get_u32(re_ctx, &pc);
90790 #endif
90791 		op = *pc++;
90792 
90793 		DUK_DDD(DUK_DDDPRINT("match: rec=%ld, steps=%ld, pc (after op)=%ld, sp=%ld, op=%ld",
90794 		                     (long) re_ctx->recursion_depth,
90795 		                     (long) re_ctx->steps_count,
90796 		                     (long) (pc - re_ctx->bytecode),
90797 		                     (long) (sp - re_ctx->input),
90798 		                     (long) op));
90799 
90800 		switch (op) {
90801 		case DUK_REOP_MATCH: {
90802 			goto match;
90803 		}
90804 		case DUK_REOP_CHAR: {
90805 			/*
90806 			 *  Byte-based matching would be possible for case-sensitive
90807 			 *  matching but not for case-insensitive matching.  So, we
90808 			 *  match by decoding the input and bytecode character normally.
90809 			 *
90810 			 *  Bytecode characters are assumed to be already canonicalized.
90811 			 *  Input characters are canonicalized automatically by
90812 			 *  duk__inp_get_cp() if necessary.
90813 			 *
90814 			 *  There is no opcode for matching multiple characters.  The
90815 			 *  regexp compiler has trouble joining strings efficiently
90816 			 *  during compilation.  See doc/regexp.rst for more discussion.
90817 			 */
90818 			duk_codepoint_t c1, c2;
90819 
90820 			c1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
90821 			DUK_ASSERT(!(re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) ||
90822 			           c1 == duk_unicode_re_canonicalize_char(re_ctx->thr, c1));  /* canonicalized by compiler */
90823 			c2 = duk__inp_get_cp(re_ctx, &sp);
90824 			/* No need to check for c2 < 0 (end of input): because c1 >= 0, it
90825 			 * will fail the match below automatically and cause goto fail.
90826 			 */
90827 #if 0
90828 			if (c2 < 0) {
90829 				goto fail;
90830 			}
90831 #endif
90832 			DUK_ASSERT(c1 >= 0);
90833 
90834 			DUK_DDD(DUK_DDDPRINT("char match, c1=%ld, c2=%ld", (long) c1, (long) c2));
90835 			if (c1 != c2) {
90836 				goto fail;
90837 			}
90838 			break;
90839 		}
90840 		case DUK_REOP_PERIOD: {
90841 			duk_codepoint_t c;
90842 
90843 			c = duk__inp_get_cp(re_ctx, &sp);
90844 			if (c < 0 || duk_unicode_is_line_terminator(c)) {
90845 				/* E5 Sections 15.10.2.8, 7.3 */
90846 				goto fail;
90847 			}
90848 			break;
90849 		}
90850 		case DUK_REOP_RANGES:
90851 		case DUK_REOP_INVRANGES: {
90852 			duk_uint32_t n;
90853 			duk_codepoint_t c;
90854 			duk_small_int_t match;
90855 
90856 			n = duk__bc_get_u32(re_ctx, &pc);
90857 			c = duk__inp_get_cp(re_ctx, &sp);
90858 			if (c < 0) {
90859 				goto fail;
90860 			}
90861 
90862 			match = 0;
90863 			while (n) {
90864 				duk_codepoint_t r1, r2;
90865 				r1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
90866 				r2 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
90867 				DUK_DDD(DUK_DDDPRINT("matching ranges/invranges, n=%ld, r1=%ld, r2=%ld, c=%ld",
90868 				                     (long) n, (long) r1, (long) r2, (long) c));
90869 				if (c >= r1 && c <= r2) {
90870 					/* Note: don't bail out early, we must read all the ranges from
90871 					 * bytecode.  Another option is to skip them efficiently after
90872 					 * breaking out of here.  Prefer smallest code.
90873 					 */
90874 					match = 1;
90875 				}
90876 				n--;
90877 			}
90878 
90879 			if (op == DUK_REOP_RANGES) {
90880 				if (!match) {
90881 					goto fail;
90882 				}
90883 			} else {
90884 				DUK_ASSERT(op == DUK_REOP_INVRANGES);
90885 				if (match) {
90886 					goto fail;
90887 				}
90888 			}
90889 			break;
90890 		}
90891 		case DUK_REOP_ASSERT_START: {
90892 			duk_codepoint_t c;
90893 
90894 			if (sp <= re_ctx->input) {
90895 				break;
90896 			}
90897 			if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
90898 				goto fail;
90899 			}
90900 			c = duk__inp_get_prev_cp(re_ctx, sp);
90901 			if (duk_unicode_is_line_terminator(c)) {
90902 				/* E5 Sections 15.10.2.8, 7.3 */
90903 				break;
90904 			}
90905 			goto fail;
90906 		}
90907 		case DUK_REOP_ASSERT_END: {
90908 			duk_codepoint_t c;
90909 			const duk_uint8_t *tmp_sp;
90910 
90911 			tmp_sp = sp;
90912 			c = duk__inp_get_cp(re_ctx, &tmp_sp);
90913 			if (c < 0) {
90914 				break;
90915 			}
90916 			if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
90917 				goto fail;
90918 			}
90919 			if (duk_unicode_is_line_terminator(c)) {
90920 				/* E5 Sections 15.10.2.8, 7.3 */
90921 				break;
90922 			}
90923 			goto fail;
90924 		}
90925 		case DUK_REOP_ASSERT_WORD_BOUNDARY:
90926 		case DUK_REOP_ASSERT_NOT_WORD_BOUNDARY: {
90927 			/*
90928 			 *  E5 Section 15.10.2.6.  The previous and current character
90929 			 *  should -not- be canonicalized as they are now.  However,
90930 			 *  canonicalization does not affect the result of IsWordChar()
90931 			 *  (which depends on Unicode characters never canonicalizing
90932 			 *  into ASCII characters) so this does not matter.
90933 			 */
90934 			duk_small_int_t w1, w2;
90935 
90936 			if (sp <= re_ctx->input) {
90937 				w1 = 0;  /* not a wordchar */
90938 			} else {
90939 				duk_codepoint_t c;
90940 				c = duk__inp_get_prev_cp(re_ctx, sp);
90941 				w1 = duk_unicode_re_is_wordchar(c);
90942 			}
90943 			if (sp >= re_ctx->input_end) {
90944 				w2 = 0;  /* not a wordchar */
90945 			} else {
90946 				const duk_uint8_t *tmp_sp = sp;  /* dummy so sp won't get updated */
90947 				duk_codepoint_t c;
90948 				c = duk__inp_get_cp(re_ctx, &tmp_sp);
90949 				w2 = duk_unicode_re_is_wordchar(c);
90950 			}
90951 
90952 			if (op == DUK_REOP_ASSERT_WORD_BOUNDARY) {
90953 				if (w1 == w2) {
90954 					goto fail;
90955 				}
90956 			} else {
90957 				DUK_ASSERT(op == DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);
90958 				if (w1 != w2) {
90959 					goto fail;
90960 				}
90961 			}
90962 			break;
90963 		}
90964 		case DUK_REOP_JUMP: {
90965 			duk_int32_t skip;
90966 
90967 			skip = duk__bc_get_i32(re_ctx, &pc);
90968 			pc += skip;
90969 			break;
90970 		}
90971 		case DUK_REOP_SPLIT1: {
90972 			/* split1: prefer direct execution (no jump) */
90973 			const duk_uint8_t *sub_sp;
90974 			duk_int32_t skip;
90975 
90976 			skip = duk__bc_get_i32(re_ctx, &pc);
90977 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
90978 			if (sub_sp) {
90979 				sp = sub_sp;
90980 				goto match;
90981 			}
90982 			pc += skip;
90983 			break;
90984 		}
90985 		case DUK_REOP_SPLIT2: {
90986 			/* split2: prefer jump execution (not direct) */
90987 			const duk_uint8_t *sub_sp;
90988 			duk_int32_t skip;
90989 
90990 			skip = duk__bc_get_i32(re_ctx, &pc);
90991 			sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
90992 			if (sub_sp) {
90993 				sp = sub_sp;
90994 				goto match;
90995 			}
90996 			break;
90997 		}
90998 		case DUK_REOP_SQMINIMAL: {
90999 			duk_uint32_t q, qmin, qmax;
91000 			duk_int32_t skip;
91001 			const duk_uint8_t *sub_sp;
91002 
91003 			qmin = duk__bc_get_u32(re_ctx, &pc);
91004 			qmax = duk__bc_get_u32(re_ctx, &pc);
91005 			skip = duk__bc_get_i32(re_ctx, &pc);
91006 			DUK_DDD(DUK_DDDPRINT("minimal quantifier, qmin=%lu, qmax=%lu, skip=%ld",
91007 			                     (unsigned long) qmin, (unsigned long) qmax, (long) skip));
91008 
91009 			q = 0;
91010 			while (q <= qmax) {
91011 				if (q >= qmin) {
91012 					sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
91013 					if (sub_sp) {
91014 						sp = sub_sp;
91015 						goto match;
91016 					}
91017 				}
91018 				sub_sp = duk__match_regexp(re_ctx, pc, sp);
91019 				if (!sub_sp) {
91020 					break;
91021 				}
91022 				sp = sub_sp;
91023 				q++;
91024 			}
91025 			goto fail;
91026 		}
91027 		case DUK_REOP_SQGREEDY: {
91028 			duk_uint32_t q, qmin, qmax, atomlen;
91029 			duk_int32_t skip;
91030 			const duk_uint8_t *sub_sp;
91031 
91032 			qmin = duk__bc_get_u32(re_ctx, &pc);
91033 			qmax = duk__bc_get_u32(re_ctx, &pc);
91034 			atomlen = duk__bc_get_u32(re_ctx, &pc);
91035 			skip = duk__bc_get_i32(re_ctx, &pc);
91036 			DUK_DDD(DUK_DDDPRINT("greedy quantifier, qmin=%lu, qmax=%lu, atomlen=%lu, skip=%ld",
91037 			                     (unsigned long) qmin, (unsigned long) qmax, (unsigned long) atomlen, (long) skip));
91038 
91039 			q = 0;
91040 			while (q < qmax) {
91041 				sub_sp = duk__match_regexp(re_ctx, pc, sp);
91042 				if (!sub_sp) {
91043 					break;
91044 				}
91045 				sp = sub_sp;
91046 				q++;
91047 			}
91048 			while (q >= qmin) {
91049 				sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
91050 				if (sub_sp) {
91051 					sp = sub_sp;
91052 					goto match;
91053 				}
91054 				if (q == qmin) {
91055 					break;
91056 				}
91057 
91058 				/* Note: if atom were to contain e.g. captures, we would need to
91059 				 * re-match the atom to get correct captures.  Simply quantifiers
91060 				 * do not allow captures in their atom now, so this is not an issue.
91061 				 */
91062 
91063 				DUK_DDD(DUK_DDDPRINT("greedy quantifier, backtrack %ld characters (atomlen)",
91064 				                     (long) atomlen));
91065 				sp = duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) atomlen);
91066 				q--;
91067 			}
91068 			goto fail;
91069 		}
91070 		case DUK_REOP_SAVE: {
91071 			duk_uint32_t idx;
91072 			const duk_uint8_t *old;
91073 			const duk_uint8_t *sub_sp;
91074 
91075 			idx = duk__bc_get_u32(re_ctx, &pc);
91076 			if (idx >= re_ctx->nsaved) {
91077 				/* idx is unsigned, < 0 check is not necessary */
91078 				DUK_D(DUK_DPRINT("internal error, regexp save index insane: idx=%ld", (long) idx));
91079 				goto internal_error;
91080 			}
91081 			old = re_ctx->saved[idx];
91082 			re_ctx->saved[idx] = sp;
91083 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
91084 			if (sub_sp) {
91085 				sp = sub_sp;
91086 				goto match;
91087 			}
91088 			re_ctx->saved[idx] = old;
91089 			goto fail;
91090 		}
91091 		case DUK_REOP_WIPERANGE: {
91092 			/* Wipe capture range and save old values for backtracking.
91093 			 *
91094 			 * XXX: this typically happens with a relatively small idx_count.
91095 			 * It might be useful to handle cases where the count is small
91096 			 * (say <= 8) by saving the values in stack instead.  This would
91097 			 * reduce memory churn and improve performance, at the cost of a
91098 			 * slightly higher code footprint.
91099 			 */
91100 			duk_uint32_t idx_start, idx_count;
91101 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
91102 			duk_uint32_t idx_end, idx;
91103 #endif
91104 			duk_uint8_t **range_save;
91105 			const duk_uint8_t *sub_sp;
91106 
91107 			idx_start = duk__bc_get_u32(re_ctx, &pc);
91108 			idx_count = duk__bc_get_u32(re_ctx, &pc);
91109 			DUK_DDD(DUK_DDDPRINT("wipe saved range: start=%ld, count=%ld -> [%ld,%ld] (captures [%ld,%ld])",
91110 			                     (long) idx_start, (long) idx_count,
91111 			                     (long) idx_start, (long) (idx_start + idx_count - 1),
91112 			                     (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
91113 			if (idx_start + idx_count > re_ctx->nsaved || idx_count == 0) {
91114 				/* idx is unsigned, < 0 check is not necessary */
91115 				DUK_D(DUK_DPRINT("internal error, regexp wipe indices insane: idx_start=%ld, idx_count=%ld",
91116 				                 (long) idx_start, (long) idx_count));
91117 				goto internal_error;
91118 			}
91119 			DUK_ASSERT(idx_count > 0);
91120 
91121 			duk_require_stack(re_ctx->thr, 1);
91122 			range_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr,
91123 			                                                           sizeof(duk_uint8_t *) * idx_count);
91124 			DUK_ASSERT(range_save != NULL);
91125 			duk_memcpy(range_save, re_ctx->saved + idx_start, sizeof(duk_uint8_t *) * idx_count);
91126 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
91127 			idx_end = idx_start + idx_count;
91128 			for (idx = idx_start; idx < idx_end; idx++) {
91129 				re_ctx->saved[idx] = NULL;
91130 			}
91131 #else
91132 			duk_memzero((void *) (re_ctx->saved + idx_start), sizeof(duk_uint8_t *) * idx_count);
91133 #endif
91134 
91135 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
91136 			if (sub_sp) {
91137 				/* match: keep wiped/resaved values */
91138 				DUK_DDD(DUK_DDDPRINT("match: keep wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
91139 				                     (long) idx_start, (long) (idx_start + idx_count - 1),
91140 			                             (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
91141 				duk_pop_unsafe(re_ctx->thr);
91142 				sp = sub_sp;
91143 				goto match;
91144 			}
91145 
91146 			/* fail: restore saves */
91147 			DUK_DDD(DUK_DDDPRINT("fail: restore wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
91148 			                     (long) idx_start, (long) (idx_start + idx_count - 1),
91149 			                     (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
91150 			duk_memcpy((void *) (re_ctx->saved + idx_start),
91151 			           (const void *) range_save,
91152 			           sizeof(duk_uint8_t *) * idx_count);
91153 			duk_pop_unsafe(re_ctx->thr);
91154 			goto fail;
91155 		}
91156 		case DUK_REOP_LOOKPOS:
91157 		case DUK_REOP_LOOKNEG: {
91158 			/*
91159 			 *  Needs a save of multiple saved[] entries depending on what range
91160 			 *  may be overwritten.  Because the regexp parser does no such analysis,
91161 			 *  we currently save the entire saved array here.  Lookaheads are thus
91162 			 *  a bit expensive.  Note that the saved array is not needed for just
91163 			 *  the lookahead sub-match, but for the matching of the entire sequel.
91164 			 *
91165 			 *  The temporary save buffer is pushed on to the valstack to handle
91166 			 *  errors correctly.  Each lookahead causes a C recursion and pushes
91167 			 *  more stuff on the value stack.  If the C recursion limit is less
91168 			 *  than the value stack slack, there is no need to check the stack.
91169 			 *  We do so regardless, just in case.
91170 			 */
91171 
91172 			duk_int32_t skip;
91173 			duk_uint8_t **full_save;
91174 			const duk_uint8_t *sub_sp;
91175 
91176 			DUK_ASSERT(re_ctx->nsaved > 0);
91177 
91178 			duk_require_stack(re_ctx->thr, 1);
91179 			full_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr,
91180 			                                                          sizeof(duk_uint8_t *) * re_ctx->nsaved);
91181 			DUK_ASSERT(full_save != NULL);
91182 			duk_memcpy(full_save, re_ctx->saved, sizeof(duk_uint8_t *) * re_ctx->nsaved);
91183 
91184 			skip = duk__bc_get_i32(re_ctx, &pc);
91185 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
91186 			if (op == DUK_REOP_LOOKPOS) {
91187 				if (!sub_sp) {
91188 					goto lookahead_fail;
91189 				}
91190 			} else {
91191 				if (sub_sp) {
91192 					goto lookahead_fail;
91193 				}
91194 			}
91195 			sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
91196 			if (sub_sp) {
91197 				/* match: keep saves */
91198 				duk_pop_unsafe(re_ctx->thr);
91199 				sp = sub_sp;
91200 				goto match;
91201 			}
91202 
91203 			/* fall through */
91204 
91205 		 lookahead_fail:
91206 			/* fail: restore saves */
91207 			duk_memcpy((void *) re_ctx->saved,
91208 			           (const void *) full_save,
91209 			           sizeof(duk_uint8_t *) * re_ctx->nsaved);
91210 			duk_pop_unsafe(re_ctx->thr);
91211 			goto fail;
91212 		}
91213 		case DUK_REOP_BACKREFERENCE: {
91214 			/*
91215 			 *  Byte matching for back-references would be OK in case-
91216 			 *  sensitive matching.  In case-insensitive matching we need
91217 			 *  to canonicalize characters, so back-reference matching needs
91218 			 *  to be done with codepoints instead.  So, we just decode
91219 			 *  everything normally here, too.
91220 			 *
91221 			 *  Note: back-reference index which is 0 or higher than
91222 			 *  NCapturingParens (= number of capturing parens in the
91223 			 *  -entire- regexp) is a compile time error.  However, a
91224 			 *  backreference referring to a valid capture which has
91225 			 *  not matched anything always succeeds!  See E5 Section
91226 			 *  15.10.2.9, step 5, sub-step 3.
91227 			 */
91228 			duk_uint32_t idx;
91229 			const duk_uint8_t *p;
91230 
91231 			idx = duk__bc_get_u32(re_ctx, &pc);
91232 			idx = idx << 1;  /* backref n -> saved indices [n*2, n*2+1] */
91233 			if (idx < 2 || idx + 1 >= re_ctx->nsaved) {
91234 				/* regexp compiler should catch these */
91235 				DUK_D(DUK_DPRINT("internal error, backreference index insane"));
91236 				goto internal_error;
91237 			}
91238 			if (!re_ctx->saved[idx] || !re_ctx->saved[idx+1]) {
91239 				/* capture is 'undefined', always matches! */
91240 				DUK_DDD(DUK_DDDPRINT("backreference: saved[%ld,%ld] not complete, always match",
91241 				                     (long) idx, (long) (idx + 1)));
91242 				break;
91243 			}
91244 			DUK_DDD(DUK_DDDPRINT("backreference: match saved[%ld,%ld]", (long) idx, (long) (idx + 1)));
91245 
91246 			p = re_ctx->saved[idx];
91247 			while (p < re_ctx->saved[idx+1]) {
91248 				duk_codepoint_t c1, c2;
91249 
91250 				/* Note: not necessary to check p against re_ctx->input_end:
91251 				 * the memory access is checked by duk__inp_get_cp(), while
91252 				 * valid compiled regexps cannot write a saved[] entry
91253 				 * which points to outside the string.
91254 				 */
91255 				c1 = duk__inp_get_cp(re_ctx, &p);
91256 				DUK_ASSERT(c1 >= 0);
91257 				c2 = duk__inp_get_cp(re_ctx, &sp);
91258 				/* No need for an explicit c2 < 0 check: because c1 >= 0,
91259 				 * the comparison will always fail if c2 < 0.
91260 				 */
91261 #if 0
91262 				if (c2 < 0) {
91263 					goto fail;
91264 				}
91265 #endif
91266 				if (c1 != c2) {
91267 					goto fail;
91268 				}
91269 			}
91270 			break;
91271 		}
91272 		default: {
91273 			DUK_D(DUK_DPRINT("internal error, regexp opcode error: %ld", (long) op));
91274 			goto internal_error;
91275 		}
91276 		}
91277 	}
91278 
91279  match:
91280 	re_ctx->recursion_depth--;
91281 	return sp;
91282 
91283  fail:
91284 	re_ctx->recursion_depth--;
91285 	return NULL;
91286 
91287  internal_error:
91288 	DUK_ERROR_INTERNAL(re_ctx->thr);
91289 	DUK_WO_NORETURN(return NULL;);
91290 }
91291 
91292 /*
91293  *  Exposed matcher function which provides the semantics of RegExp.prototype.exec().
91294  *
91295  *  RegExp.prototype.test() has the same semantics as exec() but does not return the
91296  *  result object (which contains the matching string and capture groups).  Currently
91297  *  there is no separate test() helper, so a temporary result object is created and
91298  *  discarded if test() is needed.  This is intentional, to save code space.
91299  *
91300  *  Input stack:  [ ... re_obj input ]
91301  *  Output stack: [ ... result ]
91302  */
91303 
91304 DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_global) {
91305 	duk_re_matcher_ctx re_ctx;
91306 	duk_hobject *h_regexp;
91307 	duk_hstring *h_bytecode;
91308 	duk_hstring *h_input;
91309 	duk_uint8_t *p_buf;
91310 	const duk_uint8_t *pc;
91311 	const duk_uint8_t *sp;
91312 	duk_small_int_t match = 0;
91313 	duk_small_int_t global;
91314 	duk_uint_fast32_t i;
91315 	double d;
91316 	duk_uint32_t char_offset;
91317 
91318 	DUK_ASSERT(thr != NULL);
91319 
91320 	DUK_DD(DUK_DDPRINT("regexp match: regexp=%!T, input=%!T",
91321 	                   (duk_tval *) duk_get_tval(thr, -2),
91322 	                   (duk_tval *) duk_get_tval(thr, -1)));
91323 
91324 	/*
91325 	 *  Regexp instance check, bytecode check, input coercion.
91326 	 *
91327 	 *  See E5 Section 15.10.6.
91328 	 */
91329 
91330 	/* TypeError if wrong; class check, see E5 Section 15.10.6 */
91331 	h_regexp = duk_require_hobject_with_class(thr, -2, DUK_HOBJECT_CLASS_REGEXP);
91332 	DUK_ASSERT(h_regexp != NULL);
91333 	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_regexp) == DUK_HOBJECT_CLASS_REGEXP);
91334 	DUK_UNREF(h_regexp);
91335 
91336 	h_input = duk_to_hstring(thr, -1);
91337 	DUK_ASSERT(h_input != NULL);
91338 
91339 	duk_xget_owndataprop_stridx_short(thr, -2, DUK_STRIDX_INT_BYTECODE);  /* [ ... re_obj input ] -> [ ... re_obj input bc ] */
91340 	h_bytecode = duk_require_hstring(thr, -1);  /* no regexp instance should exist without a non-configurable bytecode property */
91341 	DUK_ASSERT(h_bytecode != NULL);
91342 
91343 	/*
91344 	 *  Basic context initialization.
91345 	 *
91346 	 *  Some init values are read from the bytecode header
91347 	 *  whose format is (UTF-8 codepoints):
91348 	 *
91349 	 *    uint   flags
91350 	 *    uint   nsaved (even, 2n+2 where n = num captures)
91351 	 */
91352 
91353 	/* [ ... re_obj input bc ] */
91354 
91355 	duk_memzero(&re_ctx, sizeof(re_ctx));
91356 
91357 	re_ctx.thr = thr;
91358 	re_ctx.input = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
91359 	re_ctx.input_end = re_ctx.input + DUK_HSTRING_GET_BYTELEN(h_input);
91360 	re_ctx.bytecode = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_bytecode);
91361 	re_ctx.bytecode_end = re_ctx.bytecode + DUK_HSTRING_GET_BYTELEN(h_bytecode);
91362 	re_ctx.saved = NULL;
91363 	re_ctx.recursion_limit = DUK_USE_REGEXP_EXECUTOR_RECLIMIT;
91364 	re_ctx.steps_limit = DUK_RE_EXECUTE_STEPS_LIMIT;
91365 
91366 	/* read header */
91367 	pc = re_ctx.bytecode;
91368 	re_ctx.re_flags = duk__bc_get_u32(&re_ctx, &pc);
91369 	re_ctx.nsaved = duk__bc_get_u32(&re_ctx, &pc);
91370 	re_ctx.bytecode = pc;
91371 
91372 	DUK_ASSERT(DUK_RE_FLAG_GLOBAL < 0x10000UL);  /* must fit into duk_small_int_t */
91373 	global = (duk_small_int_t) (force_global | (duk_small_int_t) (re_ctx.re_flags & DUK_RE_FLAG_GLOBAL));
91374 
91375 	DUK_ASSERT(re_ctx.nsaved >= 2);
91376 	DUK_ASSERT((re_ctx.nsaved % 2) == 0);
91377 
91378 	p_buf = (duk_uint8_t *) duk_push_fixed_buffer(thr, sizeof(duk_uint8_t *) * re_ctx.nsaved);  /* rely on zeroing */
91379 	DUK_UNREF(p_buf);
91380 	re_ctx.saved = (const duk_uint8_t **) duk_get_buffer(thr, -1, NULL);
91381 	DUK_ASSERT(re_ctx.saved != NULL);
91382 
91383 	/* [ ... re_obj input bc saved_buf ] */
91384 
91385 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
91386 	for (i = 0; i < re_ctx.nsaved; i++) {
91387 		re_ctx.saved[i] = (duk_uint8_t *) NULL;
91388 	}
91389 #elif defined(DUK_USE_ZERO_BUFFER_DATA)
91390 	/* buffer is automatically zeroed */
91391 #else
91392 	duk_memzero((void *) p_buf, sizeof(duk_uint8_t *) * re_ctx.nsaved);
91393 #endif
91394 
91395 	DUK_DDD(DUK_DDDPRINT("regexp ctx initialized, flags=0x%08lx, nsaved=%ld, recursion_limit=%ld, steps_limit=%ld",
91396 	                     (unsigned long) re_ctx.re_flags, (long) re_ctx.nsaved, (long) re_ctx.recursion_limit,
91397 	                     (long) re_ctx.steps_limit));
91398 
91399 	/*
91400 	 *  Get starting character offset for match, and initialize 'sp' based on it.
91401 	 *
91402 	 *  Note: lastIndex is non-configurable so it must be present (we check the
91403 	 *  internal class of the object above, so we know it is).  User code can set
91404 	 *  its value to an arbitrary (garbage) value though; E5 requires that lastIndex
91405 	 *  be coerced to a number before using.  The code below works even if the
91406 	 *  property is missing: the value will then be coerced to zero.
91407 	 *
91408 	 *  Note: lastIndex may be outside Uint32 range even after ToInteger() coercion.
91409 	 *  For instance, ToInteger(+Infinity) = +Infinity.  We track the match offset
91410 	 *  as an integer, but pre-check it to be inside the 32-bit range before the loop.
91411 	 *  If not, the check in E5 Section 15.10.6.2, step 9.a applies.
91412 	 */
91413 
91414 	/* XXX: lastIndex handling produces a lot of asm */
91415 
91416 	/* [ ... re_obj input bc saved_buf ] */
91417 
91418 	duk_get_prop_stridx_short(thr, -4, DUK_STRIDX_LAST_INDEX);  /* -> [ ... re_obj input bc saved_buf lastIndex ] */
91419 	(void) duk_to_int(thr, -1);  /* ToInteger(lastIndex) */
91420 	d = duk_get_number(thr, -1);  /* integer, but may be +/- Infinite, +/- zero (not NaN, though) */
91421 	duk_pop_nodecref_unsafe(thr);
91422 
91423 	if (global) {
91424 		if (d < 0.0 || d > (double) DUK_HSTRING_GET_CHARLEN(h_input)) {
91425 			/* match fail */
91426 			char_offset = 0;   /* not really necessary */
91427 			DUK_ASSERT(match == 0);
91428 			goto match_over;
91429 		}
91430 		char_offset = (duk_uint32_t) d;
91431 	} else {
91432 		/* lastIndex must be ignored for non-global regexps, but get the
91433 		 * value for (theoretical) side effects.  No side effects can
91434 		 * really occur, because lastIndex is a normal property and is
91435 		 * always non-configurable for RegExp instances.
91436 		 */
91437 		char_offset = (duk_uint32_t) 0;
91438 	}
91439 
91440 	DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));
91441 	sp = re_ctx.input + duk_heap_strcache_offset_char2byte(thr, h_input, char_offset);
91442 
91443 	/*
91444 	 *  Match loop.
91445 	 *
91446 	 *  Try matching at different offsets until match found or input exhausted.
91447 	 */
91448 
91449 	/* [ ... re_obj input bc saved_buf ] */
91450 
91451 	DUK_ASSERT(match == 0);
91452 
91453 	for (;;) {
91454 		/* char offset in [0, h_input->clen] (both ends inclusive), checked before entry */
91455 		DUK_ASSERT_DISABLE(char_offset >= 0);
91456 		DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));
91457 
91458 		/* Note: re_ctx.steps is intentionally not reset, it applies to the entire unanchored match */
91459 		DUK_ASSERT(re_ctx.recursion_depth == 0);
91460 
91461 		DUK_DDD(DUK_DDDPRINT("attempt match at char offset %ld; %p [%p,%p]",
91462 		                     (long) char_offset, (const void *) sp,
91463 		                     (const void *) re_ctx.input, (const void *) re_ctx.input_end));
91464 
91465 		/*
91466 		 *  Note:
91467 		 *
91468 		 *    - duk__match_regexp() is required not to longjmp() in ordinary "non-match"
91469 		 *      conditions; a longjmp() will terminate the entire matching process.
91470 		 *
91471 		 *    - Clearing saved[] is not necessary because backtracking does it
91472 		 *
91473 		 *    - Backtracking also rewinds re_ctx.recursion back to zero, unless an
91474 		 *      internal/limit error occurs (which causes a longjmp())
91475 		 *
91476 		 *    - If we supported anchored matches, we would break out here
91477 		 *      unconditionally; however, ECMAScript regexps don't have anchored
91478 		 *      matches.  It might make sense to implement a fast bail-out if
91479 		 *      the regexp begins with '^' and sp is not 0: currently we'll just
91480 		 *      run through the entire input string, trivially failing the match
91481 		 *      at every non-zero offset.
91482 		 */
91483 
91484 		if (duk__match_regexp(&re_ctx, re_ctx.bytecode, sp) != NULL) {
91485 			DUK_DDD(DUK_DDDPRINT("match at offset %ld", (long) char_offset));
91486 			match = 1;
91487 			break;
91488 		}
91489 
91490 		/* advance by one character (code point) and one char_offset */
91491 		char_offset++;
91492 		if (char_offset > DUK_HSTRING_GET_CHARLEN(h_input)) {
91493 			/*
91494 			 *  Note:
91495 			 *
91496 			 *    - Intentionally attempt (empty) match at char_offset == k_input->clen
91497 			 *
91498 			 *    - Negative char_offsets have been eliminated and char_offset is duk_uint32_t
91499 			 *      -> no need or use for a negative check
91500 			 */
91501 
91502 			DUK_DDD(DUK_DDDPRINT("no match after trying all sp offsets"));
91503 			break;
91504 		}
91505 
91506 		/* avoid calling at end of input, will DUK_ERROR (above check suffices to avoid this) */
91507 		(void) duk__utf8_advance(thr, &sp, re_ctx.input, re_ctx.input_end, (duk_uint_fast32_t) 1);
91508 	}
91509 
91510  match_over:
91511 
91512 	/*
91513 	 *  Matching complete, create result array or return a 'null'.  Update lastIndex
91514 	 *  if necessary.  See E5 Section 15.10.6.2.
91515 	 *
91516 	 *  Because lastIndex is a character (not byte) offset, we need the character
91517 	 *  length of the match which we conveniently get as a side effect of interning
91518 	 *  the matching substring (0th index of result array).
91519 	 *
91520 	 *  saved[0]         start pointer (~ byte offset) of current match
91521 	 *  saved[1]         end pointer (~ byte offset) of current match (exclusive)
91522 	 *  char_offset      start character offset of current match (-> .index of result)
91523 	 *  char_end_offset  end character offset (computed below)
91524 	 */
91525 
91526 	/* [ ... re_obj input bc saved_buf ] */
91527 
91528 	if (match) {
91529 #if defined(DUK_USE_ASSERTIONS)
91530 		duk_hobject *h_res;
91531 #endif
91532 		duk_uint32_t char_end_offset = 0;
91533 
91534 		DUK_DDD(DUK_DDDPRINT("regexp matches at char_offset %ld", (long) char_offset));
91535 
91536 		DUK_ASSERT(re_ctx.nsaved >= 2);        /* must have start and end */
91537 		DUK_ASSERT((re_ctx.nsaved % 2) == 0);  /* and even number */
91538 
91539 		/* XXX: Array size is known before and (2 * re_ctx.nsaved) but not taken
91540 		 * advantage of now.  The array is not compacted either, as regexp match
91541 		 * objects are usually short lived.
91542 		 */
91543 
91544 		duk_push_array(thr);
91545 
91546 #if defined(DUK_USE_ASSERTIONS)
91547 		h_res = duk_require_hobject(thr, -1);
91548 		DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_res));
91549 		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h_res));
91550 		DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_res) == DUK_HOBJECT_CLASS_ARRAY);
91551 #endif
91552 
91553 		/* [ ... re_obj input bc saved_buf res_obj ] */
91554 
91555 		duk_push_u32(thr, char_offset);
91556 		duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INDEX);
91557 
91558 		duk_dup_m4(thr);
91559 		duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INPUT);
91560 
91561 		for (i = 0; i < re_ctx.nsaved; i += 2) {
91562 			/* Captures which are undefined have NULL pointers and are returned
91563 			 * as 'undefined'.  The same is done when saved[] pointers are insane
91564 			 * (this should, of course, never happen in practice).
91565 			 */
91566 			duk_push_uarridx(thr, (duk_uarridx_t) (i / 2));
91567 
91568 			if (re_ctx.saved[i] && re_ctx.saved[i + 1] && re_ctx.saved[i + 1] >= re_ctx.saved[i]) {
91569 				duk_push_lstring(thr,
91570 				                 (const char *) re_ctx.saved[i],
91571 				                 (duk_size_t) (re_ctx.saved[i + 1] - re_ctx.saved[i]));
91572 				if (i == 0) {
91573 					/* Assumes that saved[0] and saved[1] are always
91574 					 * set by regexp bytecode (if not, char_end_offset
91575 					 * will be zero).  Also assumes clen reflects the
91576 					 * correct char length.
91577 					 */
91578 					char_end_offset = char_offset + (duk_uint32_t) duk_get_length(thr, -1);  /* add charlen */
91579 				}
91580 			} else {
91581 				duk_push_undefined(thr);
91582 			}
91583 
91584 			/* [ ... re_obj input bc saved_buf res_obj idx val ] */
91585 			duk_def_prop(thr, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_SET_WEC);
91586 		}
91587 
91588 		/* [ ... re_obj input bc saved_buf res_obj ] */
91589 
91590 		/* NB: 'length' property is automatically updated by the array setup loop */
91591 
91592 		if (global) {
91593 			/* global regexp: lastIndex updated on match */
91594 			duk_push_u32(thr, char_end_offset);
91595 			duk_put_prop_stridx_short(thr, -6, DUK_STRIDX_LAST_INDEX);
91596 		} else {
91597 			/* non-global regexp: lastIndex never updated on match */
91598 			;
91599 		}
91600 	} else {
91601 		/*
91602 		 *  No match, E5 Section 15.10.6.2, step 9.a.i - 9.a.ii apply, regardless
91603 		 *  of 'global' flag of the RegExp.  In particular, if lastIndex is invalid
91604 		 *  initially, it is reset to zero.
91605 		 */
91606 
91607 		DUK_DDD(DUK_DDDPRINT("regexp does not match"));
91608 
91609 		duk_push_null(thr);
91610 
91611 		/* [ ... re_obj input bc saved_buf res_obj ] */
91612 
91613 		duk_push_int(thr, 0);
91614 		duk_put_prop_stridx_short(thr, -6, DUK_STRIDX_LAST_INDEX);
91615 	}
91616 
91617 	/* [ ... re_obj input bc saved_buf res_obj ] */
91618 
91619 	duk_insert(thr, -5);
91620 
91621 	/* [ ... res_obj re_obj input bc saved_buf ] */
91622 
91623 	duk_pop_n_unsafe(thr, 4);
91624 
91625 	/* [ ... res_obj ] */
91626 
91627 	/* XXX: these last tricks are unnecessary if the function is made
91628 	 * a genuine native function.
91629 	 */
91630 }
91631 
91632 DUK_INTERNAL void duk_regexp_match(duk_hthread *thr) {
91633 	duk__regexp_match_helper(thr, 0 /*force_global*/);
91634 }
91635 
91636 /* This variant is needed by String.prototype.split(); it needs to perform
91637  * global-style matching on a cloned RegExp which is potentially non-global.
91638  */
91639 DUK_INTERNAL void duk_regexp_match_force_global(duk_hthread *thr) {
91640 	duk__regexp_match_helper(thr, 1 /*force_global*/);
91641 }
91642 
91643 #else  /* DUK_USE_REGEXP_SUPPORT */
91644 
91645 /* regexp support disabled */
91646 
91647 #endif  /* DUK_USE_REGEXP_SUPPORT */
91648 #line 1 "duk_selftest.c"
91649 /*
91650  *  Self tests to ensure execution environment is sane.  Intended to catch
91651  *  compiler/platform problems which cannot be detected at compile time.
91652  */
91653 
91654 /* #include duk_internal.h -> already included */
91655 
91656 #if defined(DUK_USE_SELF_TESTS)
91657 
91658 /*
91659  *  Unions and structs for self tests
91660  */
91661 
91662 typedef union {
91663 	double d;
91664 	duk_uint8_t x[8];
91665 } duk__test_double_union;
91666 
91667 /* Self test failed.  Expects a local variable 'error_count' to exist. */
91668 #define DUK__FAILED(msg)  do { \
91669 		DUK_D(DUK_DPRINT("self test failed: " #msg " at " DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO))); \
91670 		error_count++; \
91671 	} while (0)
91672 
91673 #define DUK__DBLUNION_CMP_TRUE(a,b)  do { \
91674 		if (duk_memcmp((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) != 0) { \
91675 			DUK__FAILED("double union compares false (expected true)"); \
91676 		} \
91677 	} while (0)
91678 
91679 #define DUK__DBLUNION_CMP_FALSE(a,b)  do { \
91680 		if (duk_memcmp((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) == 0) { \
91681 			DUK__FAILED("double union compares true (expected false)"); \
91682 		} \
91683 	} while (0)
91684 
91685 typedef union {
91686 	duk_uint32_t i;
91687 	duk_uint8_t x[8];
91688 } duk__test_u32_union;
91689 
91690 #if defined(DUK_USE_INTEGER_LE)
91691 #define DUK__U32_INIT(u, a, b, c, d) do { \
91692 		(u)->x[0] = (d); (u)->x[1] = (c); (u)->x[2] = (b); (u)->x[3] = (a); \
91693 	} while (0)
91694 #elif defined(DUK_USE_INTEGER_ME)
91695 #error integer mixed endian not supported now
91696 #elif defined(DUK_USE_INTEGER_BE)
91697 #define DUK__U32_INIT(u, a, b, c, d) do { \
91698 		(u)->x[0] = (a); (u)->x[1] = (b); (u)->x[2] = (c); (u)->x[3] = (d); \
91699 	} while (0)
91700 #else
91701 #error unknown integer endianness
91702 #endif
91703 
91704 #if defined(DUK_USE_DOUBLE_LE)
91705 #define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
91706 		(u)->x[0] = (h); (u)->x[1] = (g); (u)->x[2] = (f); (u)->x[3] = (e); \
91707 		(u)->x[4] = (d); (u)->x[5] = (c); (u)->x[6] = (b); (u)->x[7] = (a); \
91708 	} while (0)
91709 #define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
91710 	((u)->x[0] == (h) && (u)->x[1] == (g) && (u)->x[2] == (f) && (u)->x[3] == (e) && \
91711 	 (u)->x[4] == (d) && (u)->x[5] == (c) && (u)->x[6] == (b) && (u)->x[7] == (a))
91712 #elif defined(DUK_USE_DOUBLE_ME)
91713 #define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
91714 		(u)->x[0] = (d); (u)->x[1] = (c); (u)->x[2] = (b); (u)->x[3] = (a); \
91715 		(u)->x[4] = (h); (u)->x[5] = (g); (u)->x[6] = (f); (u)->x[7] = (e); \
91716 	} while (0)
91717 #define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
91718 	((u)->x[0] == (d) && (u)->x[1] == (c) && (u)->x[2] == (b) && (u)->x[3] == (a) && \
91719 	 (u)->x[4] == (h) && (u)->x[5] == (g) && (u)->x[6] == (f) && (u)->x[7] == (e))
91720 #elif defined(DUK_USE_DOUBLE_BE)
91721 #define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
91722 		(u)->x[0] = (a); (u)->x[1] = (b); (u)->x[2] = (c); (u)->x[3] = (d); \
91723 		(u)->x[4] = (e); (u)->x[5] = (f); (u)->x[6] = (g); (u)->x[7] = (h); \
91724 	} while (0)
91725 #define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
91726 	((u)->x[0] == (a) && (u)->x[1] == (b) && (u)->x[2] == (c) && (u)->x[3] == (d) && \
91727 	 (u)->x[4] == (e) && (u)->x[5] == (f) && (u)->x[6] == (g) && (u)->x[7] == (h))
91728 #else
91729 #error unknown double endianness
91730 #endif
91731 
91732 /*
91733  *  Various sanity checks for typing
91734  */
91735 
91736 DUK_LOCAL duk_uint_t duk__selftest_types(void) {
91737 	duk_uint_t error_count = 0;
91738 
91739 	if (!(sizeof(duk_int8_t) == 1 &&
91740 	      sizeof(duk_uint8_t) == 1 &&
91741 	      sizeof(duk_int16_t) == 2 &&
91742 	      sizeof(duk_uint16_t) == 2 &&
91743 	      sizeof(duk_int32_t) == 4 &&
91744 	      sizeof(duk_uint32_t) == 4)) {
91745 		DUK__FAILED("duk_(u)int{8,16,32}_t size");
91746 	}
91747 #if defined(DUK_USE_64BIT_OPS)
91748 	if (!(sizeof(duk_int64_t) == 8 &&
91749 	      sizeof(duk_uint64_t) == 8)) {
91750 		DUK__FAILED("duk_(u)int64_t size");
91751 	}
91752 #endif
91753 
91754 	if (!(sizeof(duk_size_t) >= sizeof(duk_uint_t))) {
91755 		/* Some internal code now assumes that all duk_uint_t values
91756 		 * can be expressed with a duk_size_t.
91757 		 */
91758 		DUK__FAILED("duk_size_t is smaller than duk_uint_t");
91759 	}
91760 	if (!(sizeof(duk_int_t) >= 4)) {
91761 		DUK__FAILED("duk_int_t is not 32 bits");
91762 	}
91763 
91764 	return error_count;
91765 }
91766 
91767 /*
91768  *  Packed tval sanity
91769  */
91770 
91771 DUK_LOCAL duk_uint_t duk__selftest_packed_tval(void) {
91772 	duk_uint_t error_count = 0;
91773 
91774 #if defined(DUK_USE_PACKED_TVAL)
91775 	if (sizeof(void *) > 4) {
91776 		DUK__FAILED("packed duk_tval in use but sizeof(void *) > 4");
91777 	}
91778 #endif
91779 
91780 	return error_count;
91781 }
91782 
91783 /*
91784  *  Two's complement arithmetic.
91785  */
91786 
91787 DUK_LOCAL duk_uint_t duk__selftest_twos_complement(void) {
91788 	duk_uint_t error_count = 0;
91789 	volatile int test;
91790 	test = -1;
91791 
91792 	/* Note that byte order doesn't affect this test: all bytes in
91793 	 * 'test' will be 0xFF for two's complement.
91794 	 */
91795 	if (((volatile duk_uint8_t *) &test)[0] != (duk_uint8_t) 0xff) {
91796 		DUK__FAILED("two's complement arithmetic");
91797 	}
91798 
91799 	return error_count;
91800 }
91801 
91802 /*
91803  *  Byte order.  Important to self check, because on some exotic platforms
91804  *  there is no actual detection but rather assumption based on platform
91805  *  defines.
91806  */
91807 
91808 DUK_LOCAL duk_uint_t duk__selftest_byte_order(void) {
91809 	duk_uint_t error_count = 0;
91810 	duk__test_u32_union u1;
91811 	duk__test_double_union u2;
91812 
91813 	/*
91814 	 *  >>> struct.pack('>d', 102030405060).encode('hex')
91815 	 *  '4237c17c6dc40000'
91816 	 */
91817 
91818 	DUK__U32_INIT(&u1, 0xde, 0xad, 0xbe, 0xef);
91819 	DUK__DOUBLE_INIT(&u2, 0x42, 0x37, 0xc1, 0x7c, 0x6d, 0xc4, 0x00, 0x00);
91820 
91821 	if (u1.i != (duk_uint32_t) 0xdeadbeefUL) {
91822 		DUK__FAILED("duk_uint32_t byte order");
91823 	}
91824 
91825 	if (!duk_double_equals(u2.d, 102030405060.0)) {
91826 		DUK__FAILED("double byte order");
91827 	}
91828 
91829 	return error_count;
91830 }
91831 
91832 /*
91833  *  DUK_BSWAP macros
91834  */
91835 
91836 DUK_LOCAL duk_uint_t duk__selftest_bswap_macros(void) {
91837 	duk_uint_t error_count = 0;
91838 	volatile duk_uint32_t x32_input, x32_output;
91839 	duk_uint32_t x32;
91840 	volatile duk_uint16_t x16_input, x16_output;
91841 	duk_uint16_t x16;
91842 	duk_double_union du;
91843 	duk_double_t du_diff;
91844 #if defined(DUK_BSWAP64)
91845 	volatile duk_uint64_t x64_input, x64_output;
91846 	duk_uint64_t x64;
91847 #endif
91848 
91849 	/* Cover both compile time and runtime bswap operations, as these
91850 	 * may have different bugs.
91851 	 */
91852 
91853 	x16_input = 0xbeefUL;
91854 	x16 = x16_input;
91855 	x16 = DUK_BSWAP16(x16);
91856 	x16_output = x16;
91857 	if (x16_output != (duk_uint16_t) 0xefbeUL) {
91858 		DUK__FAILED("DUK_BSWAP16");
91859 	}
91860 
91861 	x16 = 0xbeefUL;
91862 	x16 = DUK_BSWAP16(x16);
91863 	if (x16 != (duk_uint16_t) 0xefbeUL) {
91864 		DUK__FAILED("DUK_BSWAP16");
91865 	}
91866 
91867 	x32_input = 0xdeadbeefUL;
91868 	x32 = x32_input;
91869 	x32 = DUK_BSWAP32(x32);
91870 	x32_output = x32;
91871 	if (x32_output != (duk_uint32_t) 0xefbeaddeUL) {
91872 		DUK__FAILED("DUK_BSWAP32");
91873 	}
91874 
91875 	x32 = 0xdeadbeefUL;
91876 	x32 = DUK_BSWAP32(x32);
91877 	if (x32 != (duk_uint32_t) 0xefbeaddeUL) {
91878 		DUK__FAILED("DUK_BSWAP32");
91879 	}
91880 
91881 #if defined(DUK_BSWAP64)
91882 	x64_input = DUK_U64_CONSTANT(0x8899aabbccddeeff);
91883 	x64 = x64_input;
91884 	x64 = DUK_BSWAP64(x64);
91885 	x64_output = x64;
91886 	if (x64_output != (duk_uint64_t) DUK_U64_CONSTANT(0xffeeddccbbaa9988)) {
91887 		DUK__FAILED("DUK_BSWAP64");
91888 	}
91889 
91890 	x64 = DUK_U64_CONSTANT(0x8899aabbccddeeff);
91891 	x64 = DUK_BSWAP64(x64);
91892 	if (x64 != (duk_uint64_t) DUK_U64_CONSTANT(0xffeeddccbbaa9988)) {
91893 		DUK__FAILED("DUK_BSWAP64");
91894 	}
91895 #endif
91896 
91897 	/* >>> struct.unpack('>d', '4000112233445566'.decode('hex'))
91898 	 * (2.008366013071895,)
91899 	 */
91900 
91901 	du.uc[0] = 0x40; du.uc[1] = 0x00; du.uc[2] = 0x11; du.uc[3] = 0x22;
91902 	du.uc[4] = 0x33; du.uc[5] = 0x44; du.uc[6] = 0x55; du.uc[7] = 0x66;
91903 	DUK_DBLUNION_DOUBLE_NTOH(&du);
91904 	du_diff = du.d - 2.008366013071895;
91905 #if 0
91906 	DUK_D(DUK_DPRINT("du_diff: %lg\n", (double) du_diff));
91907 #endif
91908 	if (du_diff > 1e-15) {
91909 		/* Allow very small lenience because some compilers won't parse
91910 		 * exact IEEE double constants (happened in matrix testing with
91911 		 * Linux gcc-4.8 -m32 at least).
91912 		 */
91913 #if 0
91914 		DUK_D(DUK_DPRINT("Result of DUK_DBLUNION_DOUBLE_NTOH: %02x %02x %02x %02x %02x %02x %02x %02x\n",
91915 		            (unsigned int) du.uc[0], (unsigned int) du.uc[1],
91916 		            (unsigned int) du.uc[2], (unsigned int) du.uc[3],
91917 		            (unsigned int) du.uc[4], (unsigned int) du.uc[5],
91918 		            (unsigned int) du.uc[6], (unsigned int) du.uc[7]));
91919 #endif
91920 		DUK__FAILED("DUK_DBLUNION_DOUBLE_NTOH");
91921 	}
91922 
91923 	return error_count;
91924 }
91925 
91926 /*
91927  *  Basic double / byte union memory layout.
91928  */
91929 
91930 DUK_LOCAL duk_uint_t duk__selftest_double_union_size(void) {
91931 	duk_uint_t error_count = 0;
91932 
91933 	if (sizeof(duk__test_double_union) != 8) {
91934 		DUK__FAILED("invalid union size");
91935 	}
91936 
91937 	return error_count;
91938 }
91939 
91940 /*
91941  *  Union aliasing, see misc/clang_aliasing.c.
91942  */
91943 
91944 DUK_LOCAL duk_uint_t duk__selftest_double_aliasing(void) {
91945 	/* This testcase fails when Emscripten-generated code runs on Firefox.
91946 	 * It's not an issue because the failure should only affect packed
91947 	 * duk_tval representation, which is not used with Emscripten.
91948 	 */
91949 #if defined(DUK_USE_PACKED_TVAL)
91950 	duk_uint_t error_count = 0;
91951 	duk__test_double_union a, b;
91952 
91953 	/* Test signaling NaN and alias assignment in all endianness combinations.
91954 	 */
91955 
91956 	/* little endian */
91957 	a.x[0] = 0x11; a.x[1] = 0x22; a.x[2] = 0x33; a.x[3] = 0x44;
91958 	a.x[4] = 0x00; a.x[5] = 0x00; a.x[6] = 0xf1; a.x[7] = 0xff;
91959 	b = a;
91960 	DUK__DBLUNION_CMP_TRUE(&a, &b);
91961 
91962 	/* big endian */
91963 	a.x[0] = 0xff; a.x[1] = 0xf1; a.x[2] = 0x00; a.x[3] = 0x00;
91964 	a.x[4] = 0x44; a.x[5] = 0x33; a.x[6] = 0x22; a.x[7] = 0x11;
91965 	b = a;
91966 	DUK__DBLUNION_CMP_TRUE(&a, &b);
91967 
91968 	/* mixed endian */
91969 	a.x[0] = 0x00; a.x[1] = 0x00; a.x[2] = 0xf1; a.x[3] = 0xff;
91970 	a.x[4] = 0x11; a.x[5] = 0x22; a.x[6] = 0x33; a.x[7] = 0x44;
91971 	b = a;
91972 	DUK__DBLUNION_CMP_TRUE(&a, &b);
91973 
91974 	return error_count;
91975 #else
91976 	DUK_D(DUK_DPRINT("skip double aliasing self test when duk_tval is not packed"));
91977 	return 0;
91978 #endif
91979 }
91980 
91981 /*
91982  *  Zero sign, see misc/tcc_zerosign2.c.
91983  */
91984 
91985 DUK_LOCAL duk_uint_t duk__selftest_double_zero_sign(void) {
91986 	duk_uint_t error_count = 0;
91987 	duk__test_double_union a, b;
91988 
91989 	a.d = 0.0;
91990 	b.d = -a.d;
91991 	DUK__DBLUNION_CMP_FALSE(&a, &b);
91992 
91993 	return error_count;
91994 }
91995 
91996 /*
91997  *  Rounding mode: Duktape assumes round-to-nearest, check that this is true.
91998  *  If we had C99 fenv.h we could check that fegetround() == FE_TONEAREST,
91999  *  but we don't want to rely on that header; and even if we did, it's good
92000  *  to ensure the rounding actually works.
92001  */
92002 
92003 DUK_LOCAL duk_uint_t duk__selftest_double_rounding(void) {
92004 	duk_uint_t error_count = 0;
92005 	duk__test_double_union a, b, c;
92006 
92007 #if 0
92008 	/* Include <fenv.h> and test manually; these trigger failures: */
92009 	fesetround(FE_UPWARD);
92010 	fesetround(FE_DOWNWARD);
92011 	fesetround(FE_TOWARDZERO);
92012 
92013 	/* This is the default and passes. */
92014 	fesetround(FE_TONEAREST);
92015 #endif
92016 
92017 	/* Rounding tests check that none of the other modes (round to
92018 	 * +Inf, round to -Inf, round to zero) can be active:
92019 	 * http://www.gnu.org/software/libc/manual/html_node/Rounding.html
92020 	 */
92021 
92022 	/* 1.0 + 2^(-53): result is midway between 1.0 and 1.0 + ulp.
92023 	 * Round to nearest: 1.0
92024 	 * Round to +Inf:    1.0 + ulp
92025 	 * Round to -Inf:    1.0
92026 	 * Round to zero:    1.0
92027 	 * => Correct result eliminates round to +Inf.
92028 	 */
92029 	DUK__DOUBLE_INIT(&a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
92030 	DUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
92031 	duk_memset((void *) &c, 0, sizeof(c));
92032 	c.d = a.d + b.d;
92033 	if (!DUK__DOUBLE_COMPARE(&c, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)) {
92034 		DUK_D(DUK_DPRINT("broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x",
92035 		                 (unsigned int) c.x[0], (unsigned int) c.x[1],
92036 		                 (unsigned int) c.x[2], (unsigned int) c.x[3],
92037 		                 (unsigned int) c.x[4], (unsigned int) c.x[5],
92038 		                 (unsigned int) c.x[6], (unsigned int) c.x[7]));
92039 		DUK__FAILED("invalid result from 1.0 + 0.5ulp");
92040 	}
92041 
92042 	/* (1.0 + ulp) + 2^(-53): result is midway between 1.0 + ulp and 1.0 + 2*ulp.
92043 	 * Round to nearest: 1.0 + 2*ulp (round to even mantissa)
92044 	 * Round to +Inf:    1.0 + 2*ulp
92045 	 * Round to -Inf:    1.0 + ulp
92046 	 * Round to zero:    1.0 + ulp
92047 	 * => Correct result eliminates round to -Inf and round to zero.
92048 	 */
92049 	DUK__DOUBLE_INIT(&a, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
92050 	DUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
92051 	duk_memset((void *) &c, 0, sizeof(c));
92052 	c.d = a.d + b.d;
92053 	if (!DUK__DOUBLE_COMPARE(&c, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02)) {
92054 		DUK_D(DUK_DPRINT("broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x",
92055 		                 (unsigned int) c.x[0], (unsigned int) c.x[1],
92056 		                 (unsigned int) c.x[2], (unsigned int) c.x[3],
92057 		                 (unsigned int) c.x[4], (unsigned int) c.x[5],
92058 		                 (unsigned int) c.x[6], (unsigned int) c.x[7]));
92059 		DUK__FAILED("invalid result from (1.0 + ulp) + 0.5ulp");
92060 	}
92061 
92062 	/* Could do negative number testing too, but the tests above should
92063 	 * differentiate between IEEE 754 rounding modes.
92064 	 */
92065 	return error_count;
92066 }
92067 
92068 /*
92069  *  fmod(): often a portability issue in embedded or bare platform targets.
92070  *  Check for at least minimally correct behavior.  Unlike some other math
92071  *  functions (like cos()) Duktape relies on fmod() internally too.
92072  */
92073 
92074 DUK_LOCAL duk_uint_t duk__selftest_fmod(void) {
92075 	duk_uint_t error_count = 0;
92076 	duk__test_double_union u1, u2;
92077 	volatile duk_double_t t1, t2, t3;
92078 
92079 	/* fmod() with integer argument and exponent 2^32 is used by e.g.
92080 	 * ToUint32() and some Duktape internals.
92081 	 */
92082 	u1.d = DUK_FMOD(10.0, 4294967296.0);
92083 	u2.d = 10.0;
92084 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
92085 
92086 	u1.d = DUK_FMOD(4294967306.0, 4294967296.0);
92087 	u2.d = 10.0;
92088 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
92089 
92090 	u1.d = DUK_FMOD(73014444042.0, 4294967296.0);
92091 	u2.d = 10.0;
92092 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
92093 
92094 	/* 52-bit integer split into two parts:
92095 	 * >>> 0x1fedcba9876543
92096 	 * 8987183256397123
92097 	 * >>> float(0x1fedcba9876543) / float(2**53)
92098 	 * 0.9977777777777778
92099 	 */
92100 	u1.d = DUK_FMOD(8987183256397123.0, 4294967296.0);
92101 	u2.d = (duk_double_t) 0xa9876543UL;
92102 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
92103 	t1 = 8987183256397123.0;
92104 	t2 = 4294967296.0;
92105 	t3 = t1 / t2;
92106 	u1.d = DUK_FLOOR(t3);
92107 	u2.d = (duk_double_t) 0x1fedcbUL;
92108 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
92109 
92110 	/* C99 behavior is for fmod() result sign to mathc argument sign. */
92111 	u1.d = DUK_FMOD(-10.0, 4294967296.0);
92112 	u2.d = -10.0;
92113 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
92114 
92115 	u1.d = DUK_FMOD(-4294967306.0, 4294967296.0);
92116 	u2.d = -10.0;
92117 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
92118 
92119 	u1.d = DUK_FMOD(-73014444042.0, 4294967296.0);
92120 	u2.d = -10.0;
92121 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
92122 
92123 	return error_count;
92124 }
92125 
92126 /*
92127  *  Struct size/alignment if platform requires it
92128  *
92129  *  There are some compiler specific struct padding pragmas etc in use, this
92130  *  selftest ensures they're correctly detected and used.
92131  */
92132 
92133 DUK_LOCAL duk_uint_t duk__selftest_struct_align(void) {
92134 	duk_uint_t error_count = 0;
92135 
92136 #if (DUK_USE_ALIGN_BY == 4)
92137 	if ((sizeof(duk_hbuffer_fixed) % 4) != 0) {
92138 		DUK__FAILED("sizeof(duk_hbuffer_fixed) not aligned to 4");
92139 	}
92140 #elif (DUK_USE_ALIGN_BY == 8)
92141 	if ((sizeof(duk_hbuffer_fixed) % 8) != 0) {
92142 		DUK__FAILED("sizeof(duk_hbuffer_fixed) not aligned to 8");
92143 	}
92144 #elif (DUK_USE_ALIGN_BY == 1)
92145 	/* no check */
92146 #else
92147 #error invalid DUK_USE_ALIGN_BY
92148 #endif
92149 	return error_count;
92150 }
92151 
92152 /*
92153  *  64-bit arithmetic
92154  *
92155  *  There are some platforms/compilers where 64-bit types are available
92156  *  but don't work correctly.  Test for known cases.
92157  */
92158 
92159 DUK_LOCAL duk_uint_t duk__selftest_64bit_arithmetic(void) {
92160 	duk_uint_t error_count = 0;
92161 #if defined(DUK_USE_64BIT_OPS)
92162 	volatile duk_int64_t i;
92163 	volatile duk_double_t d;
92164 
92165 	/* Catch a double-to-int64 cast issue encountered in practice. */
92166 	d = 2147483648.0;
92167 	i = (duk_int64_t) d;
92168 	if (i != DUK_I64_CONSTANT(0x80000000)) {
92169 		DUK__FAILED("casting 2147483648.0 to duk_int64_t failed");
92170 	}
92171 #else
92172 	/* nop */
92173 #endif
92174 	return error_count;
92175 }
92176 
92177 /*
92178  *  Casting
92179  */
92180 
92181 DUK_LOCAL duk_uint_t duk__selftest_cast_double_to_small_uint(void) {
92182 	/*
92183 	 *  https://github.com/svaarala/duktape/issues/127#issuecomment-77863473
92184 	 */
92185 
92186 	duk_uint_t error_count = 0;
92187 
92188 	duk_double_t d1, d2;
92189 	duk_small_uint_t u;
92190 
92191 	duk_double_t d1v, d2v;
92192 	duk_small_uint_t uv;
92193 
92194 	/* Test without volatiles */
92195 
92196 	d1 = 1.0;
92197 	u = (duk_small_uint_t) d1;
92198 	d2 = (duk_double_t) u;
92199 
92200 	if (!(duk_double_equals(d1, 1.0) && u == 1 && duk_double_equals(d2, 1.0) && duk_double_equals(d1, d2))) {
92201 		DUK__FAILED("double to duk_small_uint_t cast failed");
92202 	}
92203 
92204 	/* Same test with volatiles */
92205 
92206 	d1v = 1.0;
92207 	uv = (duk_small_uint_t) d1v;
92208 	d2v = (duk_double_t) uv;
92209 
92210 	if (!(duk_double_equals(d1v, 1.0) && uv == 1 && duk_double_equals(d2v, 1.0) && duk_double_equals(d1v, d2v))) {
92211 		DUK__FAILED("double to duk_small_uint_t cast failed");
92212 	}
92213 
92214 	return error_count;
92215 }
92216 
92217 DUK_LOCAL duk_uint_t duk__selftest_cast_double_to_uint32(void) {
92218 	/*
92219 	 *  This test fails on an exotic ARM target; double-to-uint
92220 	 *  cast is incorrectly clamped to -signed- int highest value.
92221 	 *
92222 	 *  https://github.com/svaarala/duktape/issues/336
92223 	 */
92224 
92225 	duk_uint_t error_count = 0;
92226 	duk_double_t dv;
92227 	duk_uint32_t uv;
92228 
92229 	dv = 3735928559.0;  /* 0xdeadbeef in decimal */
92230 	uv = (duk_uint32_t) dv;
92231 
92232 	if (uv != 0xdeadbeefUL) {
92233 		DUK__FAILED("double to duk_uint32_t cast failed");
92234 	}
92235 
92236 	return error_count;
92237 }
92238 
92239 /*
92240  *  Minimal test of user supplied allocation functions
92241  *
92242  *    - Basic alloc + realloc + free cycle
92243  *
92244  *    - Realloc to significantly larger size to (hopefully) trigger a
92245  *      relocation and check that relocation copying works
92246  */
92247 
92248 DUK_LOCAL duk_uint_t duk__selftest_alloc_funcs(duk_alloc_function alloc_func,
92249                                                duk_realloc_function realloc_func,
92250                                                duk_free_function free_func,
92251                                                void *udata) {
92252 	duk_uint_t error_count = 0;
92253 	void *ptr;
92254 	void *new_ptr;
92255 	duk_small_int_t i, j;
92256 	unsigned char x;
92257 
92258 	if (alloc_func == NULL || realloc_func == NULL || free_func == NULL) {
92259 		return 0;
92260 	}
92261 
92262 	for (i = 1; i <= 256; i++) {
92263 		ptr = alloc_func(udata, (duk_size_t) i);
92264 		if (ptr == NULL) {
92265 			DUK_D(DUK_DPRINT("alloc failed, ignore"));
92266 			continue;  /* alloc failed, ignore */
92267 		}
92268 		for (j = 0; j < i; j++) {
92269 			((unsigned char *) ptr)[j] = (unsigned char) (0x80 + j);
92270 		}
92271 		new_ptr = realloc_func(udata, ptr, 1024);
92272 		if (new_ptr == NULL) {
92273 			DUK_D(DUK_DPRINT("realloc failed, ignore"));
92274 			free_func(udata, ptr);
92275 			continue;  /* realloc failed, ignore */
92276 		}
92277 		ptr = new_ptr;
92278 		for (j = 0; j < i; j++) {
92279 			x = ((unsigned char *) ptr)[j];
92280 			if (x != (unsigned char) (0x80 + j)) {
92281 				DUK_D(DUK_DPRINT("byte at index %ld doesn't match after realloc: %02lx",
92282 				                 (long) j, (unsigned long) x));
92283 				DUK__FAILED("byte compare after realloc");
92284 				break;
92285 			}
92286 		}
92287 		free_func(udata, ptr);
92288 	}
92289 
92290 	return error_count;
92291 }
92292 
92293 /*
92294  *  Self test main
92295  */
92296 
92297 DUK_INTERNAL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_func,
92298                                                duk_realloc_function realloc_func,
92299                                                duk_free_function free_func,
92300                                                void *udata) {
92301 	duk_uint_t error_count = 0;
92302 
92303 	DUK_D(DUK_DPRINT("self test starting"));
92304 
92305 	error_count += duk__selftest_types();
92306 	error_count += duk__selftest_packed_tval();
92307 	error_count += duk__selftest_twos_complement();
92308 	error_count += duk__selftest_byte_order();
92309 	error_count += duk__selftest_bswap_macros();
92310 	error_count += duk__selftest_double_union_size();
92311 	error_count += duk__selftest_double_aliasing();
92312 	error_count += duk__selftest_double_zero_sign();
92313 	error_count += duk__selftest_double_rounding();
92314 	error_count += duk__selftest_fmod();
92315 	error_count += duk__selftest_struct_align();
92316 	error_count += duk__selftest_64bit_arithmetic();
92317 	error_count += duk__selftest_cast_double_to_small_uint();
92318 	error_count += duk__selftest_cast_double_to_uint32();
92319 	error_count += duk__selftest_alloc_funcs(alloc_func, realloc_func, free_func, udata);
92320 
92321 	DUK_D(DUK_DPRINT("self test complete, total error count: %ld", (long) error_count));
92322 
92323 	return error_count;
92324 }
92325 
92326 #endif  /* DUK_USE_SELF_TESTS */
92327 
92328 /* automatic undefs */
92329 #undef DUK__DBLUNION_CMP_FALSE
92330 #undef DUK__DBLUNION_CMP_TRUE
92331 #undef DUK__DOUBLE_COMPARE
92332 #undef DUK__DOUBLE_INIT
92333 #undef DUK__FAILED
92334 #undef DUK__U32_INIT
92335 /* #include duk_internal.h -> already included */
92336 #line 2 "duk_tval.c"
92337 
92338 #if defined(DUK_USE_FASTINT)
92339 
92340 /*
92341  *  Manually optimized double-to-fastint downgrade check.
92342  *
92343  *  This check has a large impact on performance, especially for fastint
92344  *  slow paths, so must be changed carefully.  The code should probably be
92345  *  optimized for the case where the result does not fit into a fastint,
92346  *  to minimize the penalty for "slow path code" dealing with fractions etc.
92347  *
92348  *  At least on one tested soft float ARM platform double-to-int64 coercion
92349  *  is very slow (and sometimes produces incorrect results, see self tests).
92350  *  This algorithm combines a fastint compatibility check and extracting the
92351  *  integer value from an IEEE double for setting the tagged fastint.  For
92352  *  other platforms a more naive approach might be better.
92353  *
92354  *  See doc/fastint.rst for details.
92355  */
92356 
92357 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x) {
92358 	duk_double_union du;
92359 	duk_int64_t i;
92360 	duk_small_int_t expt;
92361 	duk_small_int_t shift;
92362 
92363 	/* XXX: optimize for packed duk_tval directly? */
92364 
92365 	du.d = x;
92366 	i = (duk_int64_t) DUK_DBLUNION_GET_INT64(&du);
92367 	expt = (duk_small_int_t) ((i >> 52) & 0x07ff);
92368 	shift = expt - 1023;
92369 
92370 	if (shift >= 0 && shift <= 46) {  /* exponents 1023 to 1069 */
92371 		duk_int64_t t;
92372 
92373 		if (((DUK_I64_CONSTANT(0x000fffffffffffff) >> shift) & i) == 0) {
92374 			t = i | DUK_I64_CONSTANT(0x0010000000000000);  /* implicit leading one */
92375 			t = t & DUK_I64_CONSTANT(0x001fffffffffffff);
92376 			t = t >> (52 - shift);
92377 			if (i < 0) {
92378 				t = -t;
92379 			}
92380 			DUK_TVAL_SET_FASTINT(tv, t);
92381 			return;
92382 		}
92383 	} else if (shift == -1023) {  /* exponent 0 */
92384 		if (i >= 0 && (i & DUK_I64_CONSTANT(0x000fffffffffffff)) == 0) {
92385 			/* Note: reject negative zero. */
92386 			DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) 0);
92387 			return;
92388 		}
92389 	} else if (shift == 47) {  /* exponent 1070 */
92390 		if (i < 0 && (i & DUK_I64_CONSTANT(0x000fffffffffffff)) == 0) {
92391 			DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) DUK_FASTINT_MIN);
92392 			return;
92393 		}
92394 	}
92395 
92396 	DUK_TVAL_SET_DOUBLE(tv, x);
92397 	return;
92398 }
92399 
92400 DUK_INTERNAL DUK_NOINLINE void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x) {
92401 	duk_tval_set_number_chkfast_fast(tv, x);
92402 }
92403 
92404 /*
92405  *  Manually optimized number-to-double conversion
92406  */
92407 
92408 #if defined(DUK_USE_FASTINT) && defined(DUK_USE_PACKED_TVAL)
92409 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_packed(duk_tval *tv) {
92410 	duk_double_union du;
92411 	duk_uint64_t t;
92412 
92413 	t = (duk_uint64_t) DUK_DBLUNION_GET_UINT64(tv);
92414 	if ((t >> 48) != DUK_TAG_FASTINT) {
92415 		return tv->d;
92416 	} else if (t & DUK_U64_CONSTANT(0x0000800000000000)) {
92417 		t = (duk_uint64_t) (-((duk_int64_t) t));  /* avoid unary minus on unsigned */
92418 		t = t & DUK_U64_CONSTANT(0x0000ffffffffffff);  /* negative */
92419 		t |= DUK_U64_CONSTANT(0xc330000000000000);
92420 		DUK_DBLUNION_SET_UINT64(&du, t);
92421 		return du.d + 4503599627370496.0;  /* 1 << 52 */
92422 	} else if (t != 0) {
92423 		t &= DUK_U64_CONSTANT(0x0000ffffffffffff);  /* positive */
92424 		t |= DUK_U64_CONSTANT(0x4330000000000000);
92425 		DUK_DBLUNION_SET_UINT64(&du, t);
92426 		return du.d - 4503599627370496.0;  /* 1 << 52 */
92427 	} else {
92428 		return 0.0;  /* zero */
92429 	}
92430 }
92431 #endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
92432 
92433 #if 0  /* unused */
92434 #if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
92435 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked(duk_tval *tv) {
92436 	duk_double_union du;
92437 	duk_uint64_t t;
92438 
92439 	DUK_ASSERT(tv->t == DUK_TAG_NUMBER || tv->t == DUK_TAG_FASTINT);
92440 
92441 	if (tv->t == DUK_TAG_FASTINT) {
92442 		if (tv->v.fi >= 0) {
92443 			t = DUK_U64_CONSTANT(0x4330000000000000) | (duk_uint64_t) tv->v.fi;
92444 			DUK_DBLUNION_SET_UINT64(&du, t);
92445 			return du.d - 4503599627370496.0;  /* 1 << 52 */
92446 		} else {
92447 			t = DUK_U64_CONSTANT(0xc330000000000000) | (duk_uint64_t) (-tv->v.fi);
92448 			DUK_DBLUNION_SET_UINT64(&du, t);
92449 			return du.d + 4503599627370496.0;  /* 1 << 52 */
92450 		}
92451 	} else {
92452 		return tv->v.d;
92453 	}
92454 }
92455 #endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
92456 #endif  /* 0 */
92457 
92458 #if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
92459 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv) {
92460 	duk_double_union du;
92461 	duk_uint64_t t;
92462 
92463 	DUK_ASSERT(tv->t == DUK_TAG_FASTINT);
92464 
92465 	if (tv->v.fi >= 0) {
92466 		t = DUK_U64_CONSTANT(0x4330000000000000) | (duk_uint64_t) tv->v.fi;
92467 		DUK_DBLUNION_SET_UINT64(&du, t);
92468 		return du.d - 4503599627370496.0;  /* 1 << 52 */
92469 	} else {
92470 		t = DUK_U64_CONSTANT(0xc330000000000000) | (duk_uint64_t) (-tv->v.fi);
92471 		DUK_DBLUNION_SET_UINT64(&du, t);
92472 		return du.d + 4503599627370496.0;  /* 1 << 52 */
92473 	}
92474 }
92475 #endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
92476 
92477 #endif  /* DUK_USE_FASTINT */
92478 
92479 /*
92480  *  Assertion helpers.
92481  */
92482 
92483 #if defined(DUK_USE_ASSERTIONS)
92484 DUK_INTERNAL void duk_tval_assert_valid(duk_tval *tv) {
92485 	DUK_ASSERT(tv != NULL);
92486 }
92487 #endif
92488 #line 1 "duk_unicode_tables.c"
92489 /*
92490  *  Unicode support tables automatically generated during build.
92491  */
92492 
92493 /* #include duk_internal.h -> already included */
92494 
92495 /*
92496  *  Unicode tables containing ranges of Unicode characters in a
92497  *  packed format.  These tables are used to match non-ASCII
92498  *  characters of complex productions by resorting to a linear
92499  *  range-by-range comparison.  This is very slow, but is expected
92500  *  to be very rare in practical ECMAScript source code, and thus
92501  *  compactness is most important.
92502  *
92503  *  The tables are matched using uni_range_match() and the format
92504  *  is described in tools/extract_chars.py.
92505  */
92506 
92507 #if defined(DUK_USE_SOURCE_NONBMP)
92508 /* IdentifierStart production with ASCII excluded */
92509 /* duk_unicode_ids_noa[] */
92510 /*
92511  *  Automatically generated by extract_chars.py, do not edit!
92512  */
92513 
92514 const duk_uint8_t duk_unicode_ids_noa[1116] = {
92515 249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34,
92516 2,240,66,244,50,247,185,249,98,241,99,7,241,159,57,240,181,63,31,241,191,
92517 21,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
92518 101,10,4,15,9,240,152,175,39,240,82,127,56,242,100,15,4,8,159,1,240,5,115,
92519 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,
92520 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,
92521 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,
92522 12,38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,
92523 6,41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,2,66,240,130,
92524 2,146,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,2,85,52,4,
92525 24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,35,63,17,35,
92526 54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,227,240,18,240,
92527 166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,15,53,244,
92528 152,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,175,40,240,122,
92529 242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,79,27,43,241,67,
92530 136,241,179,47,27,50,82,20,6,251,15,50,255,224,8,53,63,22,53,55,32,32,32,
92531 47,15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,32,
92532 68,112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,87,
92533 52,29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,254,
92534 12,146,240,184,132,52,95,70,114,47,74,35,111,27,47,78,240,63,11,242,127,0,
92535 255,224,244,255,240,0,138,143,60,255,240,4,14,47,2,255,227,127,243,95,30,
92536 63,253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,37,52,242,42,
92537 34,35,47,7,240,255,36,240,15,34,243,5,64,33,207,12,191,7,240,191,13,143,31,
92538 240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,48,32,
92539 240,162,58,130,213,53,53,166,38,47,27,43,159,99,240,255,255,0,26,150,223,7,
92540 95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,18,245,
92541 207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,127,10,
92542 207,73,69,53,53,50,241,91,47,10,47,3,33,46,61,241,79,107,243,127,37,255,
92543 223,13,79,33,242,31,16,239,14,111,22,191,14,63,20,87,36,241,207,142,240,79,
92544 20,95,20,95,24,159,36,248,239,254,2,154,240,107,127,138,83,2,241,194,20,3,
92545 240,123,240,122,240,255,51,240,50,27,240,107,240,175,56,242,135,31,50,15,1,
92546 50,34,240,223,28,240,212,240,223,21,114,240,207,13,242,107,240,107,240,62,
92547 240,47,96,243,159,41,242,62,242,62,241,79,254,13,15,13,176,159,6,248,207,7,
92548 223,37,243,223,29,241,47,9,240,207,20,240,240,207,19,64,223,32,240,3,240,
92549 112,32,241,95,2,47,9,244,102,32,35,46,41,143,31,241,135,49,63,6,38,33,36,
92550 64,240,64,212,249,15,37,240,67,240,96,241,47,32,240,97,32,250,175,31,241,
92551 179,241,111,32,240,96,242,223,27,224,243,159,11,253,127,28,246,111,48,241,
92552 16,249,39,63,23,240,32,32,240,224,191,24,128,240,112,207,30,240,80,241,79,
92553 41,255,152,47,21,240,48,242,63,14,246,38,33,47,22,240,112,240,181,33,47,16,
92554 240,0,255,224,59,240,63,254,0,31,254,40,207,88,245,255,3,251,79,254,155,15,
92555 254,50,31,254,236,95,254,19,159,255,0,16,173,255,225,43,143,15,246,63,14,
92556 240,79,32,240,35,241,31,5,111,3,255,225,164,243,15,114,243,182,15,52,207,
92557 50,18,15,14,255,240,0,110,169,255,225,229,255,240,1,64,31,254,1,31,35,47,3,
92558 57,255,224,126,255,231,248,245,182,196,136,159,255,0,6,90,244,82,243,114,
92559 19,3,19,50,178,2,98,243,18,51,114,98,240,194,50,66,4,98,255,224,70,63,9,47,
92560 9,47,15,47,9,47,15,47,9,47,15,47,9,47,15,47,9,39,255,232,40,241,219,111,2,
92561 15,254,6,95,28,255,228,8,251,95,45,243,72,15,254,58,131,47,11,33,32,48,41,
92562 35,32,32,112,80,32,32,34,33,32,48,32,32,32,32,33,32,51,38,35,35,32,41,47,1,
92563 98,36,47,1,255,240,0,3,143,255,0,149,201,241,191,254,242,124,252,227,255,
92564 240,0,87,79,0,255,240,0,194,63,254,177,63,254,17,0,
92565 };
92566 #else
92567 /* IdentifierStart production with ASCII and non-BMP excluded */
92568 /* duk_unicode_ids_noabmp[] */
92569 /*
92570  *  Automatically generated by extract_chars.py, do not edit!
92571  */
92572 
92573 const duk_uint8_t duk_unicode_ids_noabmp[625] = {
92574 249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34,
92575 2,240,66,244,50,247,185,249,98,241,99,7,241,159,57,240,181,63,31,241,191,
92576 21,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
92577 101,10,4,15,9,240,152,175,39,240,82,127,56,242,100,15,4,8,159,1,240,5,115,
92578 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,
92579 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,
92580 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,
92581 12,38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,
92582 6,41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,2,66,240,130,
92583 2,146,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,2,85,52,4,
92584 24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,35,63,17,35,
92585 54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,227,240,18,240,
92586 166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,15,53,244,
92587 152,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,175,40,240,122,
92588 242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,79,27,43,241,67,
92589 136,241,179,47,27,50,82,20,6,251,15,50,255,224,8,53,63,22,53,55,32,32,32,
92590 47,15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,32,
92591 68,112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,87,
92592 52,29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,254,
92593 12,146,240,184,132,52,95,70,114,47,74,35,111,27,47,78,240,63,11,242,127,0,
92594 255,224,244,255,240,0,138,143,60,255,240,4,14,47,2,255,227,127,243,95,30,
92595 63,253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,37,52,242,42,
92596 34,35,47,7,240,255,36,240,15,34,243,5,64,33,207,12,191,7,240,191,13,143,31,
92597 240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,48,32,
92598 240,162,58,130,213,53,53,166,38,47,27,43,159,99,240,255,255,0,26,150,223,7,
92599 95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,18,245,
92600 207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,127,10,
92601 207,73,69,53,53,50,0,
92602 };
92603 #endif
92604 
92605 #if defined(DUK_USE_SOURCE_NONBMP)
92606 /* IdentifierStart production with Letter and ASCII excluded */
92607 /* duk_unicode_ids_m_let_noa[] */
92608 /*
92609  *  Automatically generated by extract_chars.py, do not edit!
92610  */
92611 
92612 const duk_uint8_t duk_unicode_ids_m_let_noa[42] = {
92613 255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
92614 249,255,240,4,148,79,37,255,224,192,9,15,120,79,255,0,15,30,245,240,
92615 };
92616 #else
92617 /* IdentifierStart production with Letter, ASCII, and non-BMP excluded */
92618 /* duk_unicode_ids_m_let_noabmp[] */
92619 /*
92620  *  Automatically generated by extract_chars.py, do not edit!
92621  */
92622 
92623 const duk_uint8_t duk_unicode_ids_m_let_noabmp[24] = {
92624 255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
92625 249,0,
92626 };
92627 #endif
92628 
92629 #if defined(DUK_USE_SOURCE_NONBMP)
92630 /* IdentifierPart production with IdentifierStart and ASCII excluded */
92631 /* duk_unicode_idp_m_ids_noa[] */
92632 /*
92633  *  Automatically generated by extract_chars.py, do not edit!
92634  */
92635 
92636 const duk_uint8_t duk_unicode_idp_m_ids_noa[576] = {
92637 255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
92638 245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,160,240,163,40,
92639 34,36,241,210,246,158,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,
92640 160,177,57,240,0,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,
92641 240,97,57,181,34,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,
92642 9,240,36,242,182,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,
92643 35,242,145,38,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,
92644 215,41,244,144,56,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,
92645 245,111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,
92646 241,241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,
92647 242,244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,
92648 57,241,237,242,47,4,153,121,246,130,47,5,80,112,50,251,143,42,36,255,225,0,
92649 31,35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,
92650 31,255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,
92651 242,79,2,185,127,2,234,240,231,240,188,241,227,242,29,240,25,192,185,242,
92652 29,208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,
92653 225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,15,254,27,16,253,64,
92654 248,116,255,224,25,159,254,68,178,33,99,241,162,80,249,113,255,225,49,57,
92655 159,254,16,10,250,18,242,126,241,25,240,19,241,250,242,121,114,241,109,41,
92656 97,241,224,210,242,45,147,73,244,75,112,249,43,105,115,242,145,38,49,50,
92657 160,177,54,68,251,47,2,169,80,244,63,4,217,252,118,56,240,209,244,79,1,240,
92658 25,244,60,153,244,94,89,254,78,249,121,253,150,54,64,240,233,241,166,35,
92659 144,170,242,15,0,255,224,137,114,127,2,159,42,240,98,223,108,84,2,18,98,9,
92660 159,34,66,18,73,159,254,3,211,255,240,3,165,217,247,132,242,214,240,185,
92661 255,226,233,2,242,120,63,255,0,59,254,31,255,0,3,186,68,89,115,111,16,63,
92662 134,47,254,71,223,34,255,224,244,242,117,242,41,15,0,15,8,66,239,254,68,70,
92663 47,1,54,33,36,255,118,169,255,224,150,223,254,76,166,245,246,105,255,240,
92664 192,105,175,224,0,
92665 };
92666 #else
92667 /* IdentifierPart production with IdentifierStart, ASCII, and non-BMP excluded */
92668 /* duk_unicode_idp_m_ids_noabmp[] */
92669 /*
92670  *  Automatically generated by extract_chars.py, do not edit!
92671  */
92672 
92673 const duk_uint8_t duk_unicode_idp_m_ids_noabmp[358] = {
92674 255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
92675 245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,160,240,163,40,
92676 34,36,241,210,246,158,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,
92677 160,177,57,240,0,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,
92678 240,97,57,181,34,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,
92679 9,240,36,242,182,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,
92680 35,242,145,38,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,
92681 215,41,244,144,56,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,
92682 245,111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,
92683 241,241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,
92684 242,244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,
92685 57,241,237,242,47,4,153,121,246,130,47,5,80,112,50,251,143,42,36,255,225,0,
92686 31,35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,
92687 31,255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,
92688 242,79,2,185,127,2,234,240,231,240,188,241,227,242,29,240,25,192,185,242,
92689 29,208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,
92690 225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,0,
92691 };
92692 #endif
92693 
92694 /*
92695  *  Case conversion tables generated using tools/extract_caseconv.py.
92696  */
92697 
92698 /* duk_unicode_caseconv_uc[] */
92699 /* duk_unicode_caseconv_lc[] */
92700 
92701 /*
92702  *  Automatically generated by extract_caseconv.py, do not edit!
92703  */
92704 
92705 const duk_uint8_t duk_unicode_caseconv_uc[1411] = {
92706 152,3,128,3,0,184,7,192,6,192,112,35,242,199,224,64,74,192,49,32,128,162,
92707 128,108,65,1,189,129,254,131,3,173,3,136,6,7,98,7,34,68,15,12,14,140,72,30,
92708 104,28,112,32,67,0,65,4,0,138,0,128,4,1,88,65,76,83,8,104,14,72,43,16,253,
92709 28,189,6,39,240,39,224,24,114,12,16,132,16,248,0,248,64,129,241,1,241,128,
92710 195,228,3,229,2,7,204,7,206,4,15,160,15,164,6,31,96,31,104,16,62,224,63,
92711 116,8,125,200,127,32,32,251,176,254,208,33,247,129,255,128,67,239,67,253,
92712 64,135,223,7,254,129,15,216,15,220,2,31,208,31,216,4,63,192,63,208,8,133,
92713 192,133,128,129,38,129,37,177,162,195,2,192,5,229,160,2,20,9,170,220,4,232,
92714 40,127,160,255,144,154,136,4,4,4,0,192,9,152,9,144,48,19,160,19,145,0,41,
92715 96,41,69,192,94,128,94,65,128,193,128,193,2,1,161,1,160,6,3,104,3,102,8,7,
92716 56,7,52,64,14,248,14,240,144,31,144,31,130,128,68,96,68,66,64,145,192,145,
92717 130,129,184,129,184,2,3,217,3,216,24,8,194,8,192,68,18,44,18,40,216,38,16,
92718 38,8,112,77,16,77,6,3,192,35,192,18,199,168,71,168,24,15,168,143,172,132,
92719 44,104,44,103,6,89,2,89,0,200,179,176,179,172,21,50,13,50,1,122,104,26,104,
92720 1,212,228,116,228,65,233,204,233,204,143,211,189,83,188,130,167,127,167,
92721 126,11,79,35,79,32,10,158,94,158,88,85,61,173,61,160,97,192,107,64,107,1,0,
92722 226,128,226,3,1,198,1,196,6,3,228,3,226,8,10,0,6,152,16,31,192,31,184,34,
92723 199,50,199,32,65,128,196,0,195,130,1,185,1,184,4,4,205,79,84,8,0,192,143,0,
92724 142,193,1,52,128,203,2,45,39,16,199,5,253,0,11,80,57,192,15,240,23,128,19,
92725 16,4,144,23,240,5,48,24,0,36,48,25,32,25,16,25,80,31,96,25,144,25,128,25,
92726 160,35,208,25,224,34,0,26,128,26,112,27,240,31,112,29,208,24,224,31,48,31,
92727 16,37,2,198,240,37,18,198,208,37,34,199,0,37,48,24,16,37,64,24,96,37,144,
92728 24,240,37,176,25,0,37,202,122,176,38,0,25,48,38,26,122,192,38,48,25,64,38,
92729 90,120,208,38,128,25,112,38,178,198,32,38,202,122,208,39,18,198,224,39,32,
92730 25,208,39,80,25,240,39,210,198,64,40,42,124,80,40,122,123,16,40,128,26,224,
92731 40,144,36,64,40,192,36,80,41,32,27,112,41,218,123,32,41,234,123,0,52,80,57,
92732 144,55,112,55,96,58,192,56,96,60,32,58,48,60,192,56,192,61,0,57,32,61,16,
92733 57,128,61,80,58,96,61,96,58,0,61,112,60,240,63,0,57,160,63,16,58,16,63,32,
92734 63,144,63,48,55,240,63,80,57,80,76,240,76,1,200,0,65,33,200,16,65,65,200,
92735 32,65,225,200,80,66,33,200,96,66,161,200,112,70,33,200,138,100,161,215,154,
92736 119,209,215,210,198,49,216,234,124,97,233,177,230,1,251,224,57,145,254,81,
92737 254,194,20,226,19,34,24,66,24,50,198,18,198,2,198,80,35,162,198,96,35,226,
92738 207,50,207,42,120,202,120,186,121,74,124,74,124,58,124,42,181,58,123,60,
92739 192,27,240,2,152,2,152,10,76,5,120,0,156,3,225,0,37,1,134,1,200,96,115,32,
92740 97,0,96,32,118,24,29,40,24,64,24,8,44,60,10,106,10,164,61,45,0,36,1,152,
92741 143,75,192,10,128,97,3,211,16,2,184,24,80,244,204,0,178,6,20,61,53,0,32,
92742 129,95,15,168,64,116,160,98,99,234,88,29,40,24,152,24,0,250,166,7,74,6,38,
92743 6,2,62,173,129,210,129,137,129,161,15,192,67,225,0,115,35,240,48,248,72,28,
92744 200,252,20,62,20,7,50,63,7,15,133,129,204,143,194,67,225,128,115,35,240,
92745 176,248,104,28,200,252,52,62,28,7,50,63,15,15,135,129,204,143,196,67,225,0,
92746 115,35,241,48,248,72,28,200,252,84,62,20,7,50,63,23,15,133,129,204,143,198,
92747 67,225,128,115,35,241,176,248,104,28,200,252,116,62,28,7,50,63,31,15,135,
92748 129,204,143,200,67,229,0,115,35,242,48,249,72,28,200,252,148,62,84,7,50,63,
92749 39,15,149,129,204,143,202,67,229,128,115,35,242,176,249,104,28,200,252,180,
92750 62,92,7,50,63,47,15,151,129,204,143,204,67,229,0,115,35,243,48,249,72,28,
92751 200,252,212,62,84,7,50,63,55,15,149,129,204,143,206,67,229,128,115,35,243,
92752 176,249,104,28,200,252,244,62,92,7,50,63,63,15,151,129,204,143,208,67,237,
92753 0,115,35,244,48,251,72,28,200,253,20,62,212,7,50,63,71,15,181,129,204,143,
92754 210,67,237,128,115,35,244,176,251,104,28,200,253,52,62,220,7,50,63,79,15,
92755 183,129,204,143,212,67,237,0,115,35,245,48,251,72,28,200,253,84,62,212,7,
92756 50,63,87,15,181,129,204,143,214,67,237,128,115,35,245,176,251,104,28,200,
92757 253,116,62,220,7,50,63,95,15,183,129,204,143,217,67,247,64,115,35,246,112,
92758 28,136,28,200,253,164,7,12,7,50,63,109,1,200,129,161,15,219,224,114,32,104,
92759 64,115,35,247,144,28,136,28,200,254,20,63,148,7,50,63,135,1,203,129,204,
92760 143,226,64,113,32,115,35,248,208,28,184,26,16,254,62,7,46,6,132,7,50,63,
92761 153,1,203,129,204,143,233,96,115,32,97,0,96,3,250,120,28,200,24,64,24,8,
92762 254,180,7,50,6,132,63,175,129,204,129,132,1,161,15,241,96,116,160,97,0,96,
92763 3,252,120,29,40,24,64,24,8,255,36,7,66,6,38,63,205,1,210,129,161,15,243,
92764 224,116,160,97,0,104,67,254,80,255,208,28,200,255,156,7,82,7,50,63,233,1,
92765 199,129,204,143,251,64,117,32,104,67,254,248,29,72,26,16,28,200,255,228,7,
92766 82,7,51,246,1,0,35,0,35,125,128,192,8,192,9,63,96,80,2,48,2,103,216,30,0,
92767 140,0,140,0,147,246,9,128,35,0,35,0,38,125,130,192,10,96,10,159,96,208,2,
92768 152,2,167,216,156,10,136,10,141,246,41,2,162,2,154,253,138,192,168,128,167,
92769 127,98,208,42,112,42,55,216,188,10,136,10,122,
92770 };
92771 const duk_uint8_t duk_unicode_caseconv_lc[706] = {
92772 160,3,0,3,128,184,6,192,7,192,112,24,144,37,96,64,54,32,81,64,128,226,0,
92773 235,65,129,199,1,230,130,3,145,3,177,34,7,70,7,134,36,15,244,13,236,24,32,
92774 0,34,129,0,65,0,67,4,0,166,32,172,41,132,40,11,64,19,9,208,85,184,80,19,
92775 240,19,248,12,57,32,33,160,172,114,244,67,244,24,248,64,248,0,129,241,129,
92776 241,0,195,229,3,228,2,7,206,7,204,4,15,164,15,160,6,31,104,31,96,16,63,16,
92777 63,0,32,126,96,126,64,64,253,64,253,0,129,251,129,251,0,67,247,67,238,0,
92778 135,242,7,220,130,15,236,15,232,2,31,218,31,118,4,63,208,63,192,8,127,168,
92779 125,232,16,255,192,251,192,33,255,161,247,192,68,44,4,46,4,9,45,137,52,13,
92780 22,0,22,24,47,44,126,2,63,5,254,67,254,130,106,48,16,0,16,19,0,38,64,38,96,
92781 192,78,64,78,132,0,165,0,165,151,1,121,1,122,6,3,4,3,6,8,6,128,6,132,24,13,
92782 152,13,160,32,28,176,28,193,32,59,192,59,226,64,124,128,124,193,0,252,0,
92783 252,148,2,34,2,35,18,4,140,4,142,20,13,192,13,196,16,30,192,30,200,192,70,
92784 0,70,18,32,145,64,145,102,193,48,65,48,131,130,104,2,104,176,30,0,30,1,150,
92785 61,64,61,66,192,125,100,125,68,33,99,57,99,64,50,200,2,200,22,69,157,101,
92786 157,128,169,144,41,144,75,211,64,83,64,142,167,34,167,35,15,78,101,78,102,
92787 126,157,230,157,232,21,59,245,59,248,90,121,10,121,16,84,242,212,242,226,
92788 169,237,41,237,67,12,3,76,5,0,8,6,176,6,180,16,14,32,14,48,48,28,80,28,96,
92789 64,126,224,127,0,139,28,139,28,193,6,3,14,3,16,8,6,224,6,228,21,61,80,19,
92790 48,32,3,1,150,2,105,4,4,118,4,120,8,67,28,180,156,23,240,192,94,0,63,192,
92791 96,64,148,192,97,128,149,0,99,128,119,64,99,192,150,64,100,0,150,192,100,
92792 64,100,128,100,192,152,0,101,0,152,192,101,192,154,0,102,0,102,64,103,64,
92793 156,128,103,192,157,64,105,192,106,0,107,128,162,0,109,192,164,128,124,64,
92794 124,192,125,128,101,64,125,192,111,192,136,0,103,128,142,139,25,64,143,64,
92795 102,128,143,139,25,128,144,192,96,0,145,0,162,64,145,64,163,0,221,128,221,
92796 192,223,192,252,192,225,128,235,0,227,0,243,0,243,192,245,192,253,0,238,0,
92797 254,64,252,129,48,1,51,199,167,128,55,199,239,7,236,199,243,7,240,199,251,
92798 7,249,71,255,7,252,200,73,128,242,72,74,128,26,200,74,192,57,72,76,136,83,
92799 136,96,200,97,11,24,11,24,75,24,128,154,203,24,199,95,75,25,0,159,75,27,64,
92800 148,75,27,128,156,75,27,192,148,11,28,0,148,139,60,139,60,233,223,71,94,
92801 105,226,233,227,41,227,64,153,105,234,192,151,41,235,0,152,105,235,64,155,
92802 41,236,0,167,169,236,64,161,233,236,128,167,105,236,234,212,233,240,169,
92803 240,233,241,41,229,41,241,64,160,169,241,135,99,128,128,152,64,13,32,96,
92804 224,
92805 };
92806 
92807 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
92808 /*
92809  *  Automatically generated by extract_caseconv.py, do not edit!
92810  */
92811 
92812 const duk_uint16_t duk_unicode_re_canon_lookup[65536] = {
92813 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,
92814 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,
92815 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,
92816 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,
92817 71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,123,124,125,
92818 126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
92819 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
92820 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
92821 180,924,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
92822 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
92823 216,217,218,219,220,221,222,223,192,193,194,195,196,197,198,199,200,201,
92824 202,203,204,205,206,207,208,209,210,211,212,213,214,247,216,217,218,219,
92825 220,221,222,376,256,256,258,258,260,260,262,262,264,264,266,266,268,268,
92826 270,270,272,272,274,274,276,276,278,278,280,280,282,282,284,284,286,286,
92827 288,288,290,290,292,292,294,294,296,296,298,298,300,300,302,302,304,305,
92828 306,306,308,308,310,310,312,313,313,315,315,317,317,319,319,321,321,323,
92829 323,325,325,327,327,329,330,330,332,332,334,334,336,336,338,338,340,340,
92830 342,342,344,344,346,346,348,348,350,350,352,352,354,354,356,356,358,358,
92831 360,360,362,362,364,364,366,366,368,368,370,370,372,372,374,374,376,377,
92832 377,379,379,381,381,383,579,385,386,386,388,388,390,391,391,393,394,395,
92833 395,397,398,399,400,401,401,403,404,502,406,407,408,408,573,411,412,413,
92834 544,415,416,416,418,418,420,420,422,423,423,425,426,427,428,428,430,431,
92835 431,433,434,435,435,437,437,439,440,440,442,443,444,444,446,503,448,449,
92836 450,451,452,452,452,455,455,455,458,458,458,461,461,463,463,465,465,467,
92837 467,469,469,471,471,473,473,475,475,398,478,478,480,480,482,482,484,484,
92838 486,486,488,488,490,490,492,492,494,494,496,497,497,497,500,500,502,503,
92839 504,504,506,506,508,508,510,510,512,512,514,514,516,516,518,518,520,520,
92840 522,522,524,524,526,526,528,528,530,530,532,532,534,534,536,536,538,538,
92841 540,540,542,542,544,545,546,546,548,548,550,550,552,552,554,554,556,556,
92842 558,558,560,560,562,562,564,565,566,567,568,569,570,571,571,573,574,11390,
92843 11391,577,577,579,580,581,582,582,584,584,586,586,588,588,590,590,11375,
92844 11373,11376,385,390,597,393,394,600,399,602,400,42923L,605,606,607,403,
92845 42924L,610,404,612,42893L,42922L,615,407,406,42926L,11362,42925L,621,622,
92846 412,624,11374,413,627,628,415,630,631,632,633,634,635,636,11364,638,639,
92847 422,641,42949L,425,644,645,646,42929L,430,580,433,434,581,653,654,655,656,
92848 657,439,659,660,661,662,663,664,665,666,667,668,42930L,42928L,671,672,673,
92849 674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,
92850 692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,
92851 710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,
92852 728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,
92853 746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,
92854 764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,
92855 782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,
92856 800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,
92857 818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,
92858 836,921,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,
92859 854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,
92860 872,873,874,875,876,877,878,879,880,880,882,882,884,885,886,886,888,889,
92861 890,1021,1022,1023,894,895,896,897,898,899,900,901,902,903,904,905,906,907,
92862 908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,
92863 926,927,928,929,930,931,932,933,934,935,936,937,938,939,902,904,905,906,
92864 944,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,
92865 931,931,932,933,934,935,936,937,938,939,908,910,911,975,914,920,978,979,
92866 980,934,928,975,984,984,986,986,988,988,990,990,992,992,994,994,996,996,
92867 998,998,1000,1000,1002,1002,1004,1004,1006,1006,922,929,1017,895,1012,917,
92868 1014,1015,1015,1017,1018,1018,1020,1021,1022,1023,1024,1025,1026,1027,1028,
92869 1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,
92870 1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,
92871 1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1040,1041,
92872 1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,
92873 1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,
92874 1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,
92875 1039,1120,1120,1122,1122,1124,1124,1126,1126,1128,1128,1130,1130,1132,1132,
92876 1134,1134,1136,1136,1138,1138,1140,1140,1142,1142,1144,1144,1146,1146,1148,
92877 1148,1150,1150,1152,1152,1154,1155,1156,1157,1158,1159,1160,1161,1162,1162,
92878 1164,1164,1166,1166,1168,1168,1170,1170,1172,1172,1174,1174,1176,1176,1178,
92879 1178,1180,1180,1182,1182,1184,1184,1186,1186,1188,1188,1190,1190,1192,1192,
92880 1194,1194,1196,1196,1198,1198,1200,1200,1202,1202,1204,1204,1206,1206,1208,
92881 1208,1210,1210,1212,1212,1214,1214,1216,1217,1217,1219,1219,1221,1221,1223,
92882 1223,1225,1225,1227,1227,1229,1229,1216,1232,1232,1234,1234,1236,1236,1238,
92883 1238,1240,1240,1242,1242,1244,1244,1246,1246,1248,1248,1250,1250,1252,1252,
92884 1254,1254,1256,1256,1258,1258,1260,1260,1262,1262,1264,1264,1266,1266,1268,
92885 1268,1270,1270,1272,1272,1274,1274,1276,1276,1278,1278,1280,1280,1282,1282,
92886 1284,1284,1286,1286,1288,1288,1290,1290,1292,1292,1294,1294,1296,1296,1298,
92887 1298,1300,1300,1302,1302,1304,1304,1306,1306,1308,1308,1310,1310,1312,1312,
92888 1314,1314,1316,1316,1318,1318,1320,1320,1322,1322,1324,1324,1326,1326,1328,
92889 1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,
92890 1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,
92891 1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,
92892 1374,1375,1376,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,
92893 1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,
92894 1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1415,1416,1417,1418,
92895 1419,1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,
92896 1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,
92897 1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,
92898 1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,
92899 1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,
92900 1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,
92901 1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,
92902 1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,
92903 1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,
92904 1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,
92905 1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,
92906 1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,
92907 1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,
92908 1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,
92909 1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,
92910 1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,
92911 1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,
92912 1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,
92913 1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,
92914 1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,
92915 1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,
92916 1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,
92917 1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,
92918 1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,
92919 1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,
92920 1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,
92921 1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,
92922 1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,
92923 1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,
92924 1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,
92925 1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,
92926 1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,
92927 1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,
92928 1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,
92929 1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,
92930 1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,
92931 1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,
92932 1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,
92933 1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,
92934 2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,
92935 2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,
92936 2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,
92937 2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,
92938 2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,
92939 2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,
92940 2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,
92941 2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,
92942 2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,
92943 2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,
92944 2154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,
92945 2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,
92946 2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,
92947 2199,2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,
92948 2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,
92949 2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,
92950 2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,
92951 2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,
92952 2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,
92953 2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,
92954 2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,
92955 2319,2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,
92956 2334,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,
92957 2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,
92958 2364,2365,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,
92959 2379,2380,2381,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,
92960 2394,2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,
92961 2409,2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,
92962 2424,2425,2426,2427,2428,2429,2430,2431,2432,2433,2434,2435,2436,2437,2438,
92963 2439,2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,
92964 2454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,
92965 2469,2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2480,2481,2482,2483,
92966 2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,
92967 2499,2500,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,
92968 2514,2515,2516,2517,2518,2519,2520,2521,2522,2523,2524,2525,2526,2527,2528,
92969 2529,2530,2531,2532,2533,2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,
92970 2544,2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,
92971 2559,2560,2561,2562,2563,2564,2565,2566,2567,2568,2569,2570,2571,2572,2573,
92972 2574,2575,2576,2577,2578,2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,
92973 2589,2590,2591,2592,2593,2594,2595,2596,2597,2598,2599,2600,2601,2602,2603,
92974 2604,2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,
92975 2619,2620,2621,2622,2623,2624,2625,2626,2627,2628,2629,2630,2631,2632,2633,
92976 2634,2635,2636,2637,2638,2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,
92977 2649,2650,2651,2652,2653,2654,2655,2656,2657,2658,2659,2660,2661,2662,2663,
92978 2664,2665,2666,2667,2668,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,
92979 2679,2680,2681,2682,2683,2684,2685,2686,2687,2688,2689,2690,2691,2692,2693,
92980 2694,2695,2696,2697,2698,2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,
92981 2709,2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,
92982 2724,2725,2726,2727,2728,2729,2730,2731,2732,2733,2734,2735,2736,2737,2738,
92983 2739,2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,2751,2752,2753,
92984 2754,2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,
92985 2769,2770,2771,2772,2773,2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,
92986 2784,2785,2786,2787,2788,2789,2790,2791,2792,2793,2794,2795,2796,2797,2798,
92987 2799,2800,2801,2802,2803,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,
92988 2814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,
92989 2829,2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840,2841,2842,2843,
92990 2844,2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,
92991 2859,2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,
92992 2874,2875,2876,2877,2878,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,
92993 2889,2890,2891,2892,2893,2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,
92994 2904,2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,
92995 2919,2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,2931,2932,2933,
92996 2934,2935,2936,2937,2938,2939,2940,2941,2942,2943,2944,2945,2946,2947,2948,
92997 2949,2950,2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961,2962,2963,
92998 2964,2965,2966,2967,2968,2969,2970,2971,2972,2973,2974,2975,2976,2977,2978,
92999 2979,2980,2981,2982,2983,2984,2985,2986,2987,2988,2989,2990,2991,2992,2993,
93000 2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3005,3006,3007,3008,
93001 3009,3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,
93002 3024,3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037,3038,
93003 3039,3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,
93004 3054,3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066,3067,3068,
93005 3069,3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,
93006 3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,
93007 3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3113,
93008 3114,3115,3116,3117,3118,3119,3120,3121,3122,3123,3124,3125,3126,3127,3128,
93009 3129,3130,3131,3132,3133,3134,3135,3136,3137,3138,3139,3140,3141,3142,3143,
93010 3144,3145,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,
93011 3159,3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,
93012 3174,3175,3176,3177,3178,3179,3180,3181,3182,3183,3184,3185,3186,3187,3188,
93013 3189,3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,3200,3201,3202,3203,
93014 3204,3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3217,3218,
93015 3219,3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,
93016 3234,3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,
93017 3249,3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,
93018 3264,3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,3278,
93019 3279,3280,3281,3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,
93020 3294,3295,3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,
93021 3309,3310,3311,3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,
93022 3324,3325,3326,3327,3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,
93023 3339,3340,3341,3342,3343,3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,
93024 3354,3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,
93025 3369,3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,
93026 3384,3385,3386,3387,3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,
93027 3399,3400,3401,3402,3403,3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,
93028 3414,3415,3416,3417,3418,3419,3420,3421,3422,3423,3424,3425,3426,3427,3428,
93029 3429,3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,
93030 3444,3445,3446,3447,3448,3449,3450,3451,3452,3453,3454,3455,3456,3457,3458,
93031 3459,3460,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,
93032 3474,3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,
93033 3489,3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,
93034 3504,3505,3506,3507,3508,3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,
93035 3519,3520,3521,3522,3523,3524,3525,3526,3527,3528,3529,3530,3531,3532,3533,
93036 3534,3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,
93037 3549,3550,3551,3552,3553,3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,
93038 3564,3565,3566,3567,3568,3569,3570,3571,3572,3573,3574,3575,3576,3577,3578,
93039 3579,3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3590,3591,3592,3593,
93040 3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,
93041 3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,
93042 3624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,
93043 3639,3640,3641,3642,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,
93044 3654,3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,
93045 3669,3670,3671,3672,3673,3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,
93046 3684,3685,3686,3687,3688,3689,3690,3691,3692,3693,3694,3695,3696,3697,3698,
93047 3699,3700,3701,3702,3703,3704,3705,3706,3707,3708,3709,3710,3711,3712,3713,
93048 3714,3715,3716,3717,3718,3719,3720,3721,3722,3723,3724,3725,3726,3727,3728,
93049 3729,3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,
93050 3744,3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,
93051 3759,3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,
93052 3774,3775,3776,3777,3778,3779,3780,3781,3782,3783,3784,3785,3786,3787,3788,
93053 3789,3790,3791,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3802,3803,
93054 3804,3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815,3816,3817,3818,
93055 3819,3820,3821,3822,3823,3824,3825,3826,3827,3828,3829,3830,3831,3832,3833,
93056 3834,3835,3836,3837,3838,3839,3840,3841,3842,3843,3844,3845,3846,3847,3848,
93057 3849,3850,3851,3852,3853,3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,
93058 3864,3865,3866,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,
93059 3879,3880,3881,3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,3892,3893,
93060 3894,3895,3896,3897,3898,3899,3900,3901,3902,3903,3904,3905,3906,3907,3908,
93061 3909,3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,
93062 3924,3925,3926,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,
93063 3939,3940,3941,3942,3943,3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,
93064 3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,
93065 3969,3970,3971,3972,3973,3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,
93066 3984,3985,3986,3987,3988,3989,3990,3991,3992,3993,3994,3995,3996,3997,3998,
93067 3999,4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,
93068 4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,
93069 4029,4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,
93070 4044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,
93071 4059,4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,
93072 4074,4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,
93073 4089,4090,4091,4092,4093,4094,4095,4096,4097,4098,4099,4100,4101,4102,4103,
93074 4104,4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,
93075 4119,4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,
93076 4134,4135,4136,4137,4138,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,
93077 4149,4150,4151,4152,4153,4154,4155,4156,4157,4158,4159,4160,4161,4162,4163,
93078 4164,4165,4166,4167,4168,4169,4170,4171,4172,4173,4174,4175,4176,4177,4178,
93079 4179,4180,4181,4182,4183,4184,4185,4186,4187,4188,4189,4190,4191,4192,4193,
93080 4194,4195,4196,4197,4198,4199,4200,4201,4202,4203,4204,4205,4206,4207,4208,
93081 4209,4210,4211,4212,4213,4214,4215,4216,4217,4218,4219,4220,4221,4222,4223,
93082 4224,4225,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4238,
93083 4239,4240,4241,4242,4243,4244,4245,4246,4247,4248,4249,4250,4251,4252,4253,
93084 4254,4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,
93085 4269,4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,
93086 4284,4285,4286,4287,4288,4289,4290,4291,4292,4293,4294,4295,4296,4297,4298,
93087 4299,4300,4301,4302,4303,7312,7313,7314,7315,7316,7317,7318,7319,7320,7321,
93088 7322,7323,7324,7325,7326,7327,7328,7329,7330,7331,7332,7333,7334,7335,7336,
93089 7337,7338,7339,7340,7341,7342,7343,7344,7345,7346,7347,7348,7349,7350,7351,
93090 7352,7353,7354,4347,4348,7357,7358,7359,4352,4353,4354,4355,4356,4357,4358,
93091 4359,4360,4361,4362,4363,4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,
93092 4374,4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,
93093 4389,4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401,4402,4403,
93094 4404,4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416,4417,4418,
93095 4419,4420,4421,4422,4423,4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,
93096 4434,4435,4436,4437,4438,4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,
93097 4449,4450,4451,4452,4453,4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,
93098 4464,4465,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,
93099 4479,4480,4481,4482,4483,4484,4485,4486,4487,4488,4489,4490,4491,4492,4493,
93100 4494,4495,4496,4497,4498,4499,4500,4501,4502,4503,4504,4505,4506,4507,4508,
93101 4509,4510,4511,4512,4513,4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,
93102 4524,4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,
93103 4539,4540,4541,4542,4543,4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,
93104 4554,4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,
93105 4569,4570,4571,4572,4573,4574,4575,4576,4577,4578,4579,4580,4581,4582,4583,
93106 4584,4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,
93107 4599,4600,4601,4602,4603,4604,4605,4606,4607,4608,4609,4610,4611,4612,4613,
93108 4614,4615,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,
93109 4629,4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,
93110 4644,4645,4646,4647,4648,4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,
93111 4659,4660,4661,4662,4663,4664,4665,4666,4667,4668,4669,4670,4671,4672,4673,
93112 4674,4675,4676,4677,4678,4679,4680,4681,4682,4683,4684,4685,4686,4687,4688,
93113 4689,4690,4691,4692,4693,4694,4695,4696,4697,4698,4699,4700,4701,4702,4703,
93114 4704,4705,4706,4707,4708,4709,4710,4711,4712,4713,4714,4715,4716,4717,4718,
93115 4719,4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,
93116 4734,4735,4736,4737,4738,4739,4740,4741,4742,4743,4744,4745,4746,4747,4748,
93117 4749,4750,4751,4752,4753,4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,
93118 4764,4765,4766,4767,4768,4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,
93119 4779,4780,4781,4782,4783,4784,4785,4786,4787,4788,4789,4790,4791,4792,4793,
93120 4794,4795,4796,4797,4798,4799,4800,4801,4802,4803,4804,4805,4806,4807,4808,
93121 4809,4810,4811,4812,4813,4814,4815,4816,4817,4818,4819,4820,4821,4822,4823,
93122 4824,4825,4826,4827,4828,4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,
93123 4839,4840,4841,4842,4843,4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,
93124 4854,4855,4856,4857,4858,4859,4860,4861,4862,4863,4864,4865,4866,4867,4868,
93125 4869,4870,4871,4872,4873,4874,4875,4876,4877,4878,4879,4880,4881,4882,4883,
93126 4884,4885,4886,4887,4888,4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,
93127 4899,4900,4901,4902,4903,4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,
93128 4914,4915,4916,4917,4918,4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,
93129 4929,4930,4931,4932,4933,4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,
93130 4944,4945,4946,4947,4948,4949,4950,4951,4952,4953,4954,4955,4956,4957,4958,
93131 4959,4960,4961,4962,4963,4964,4965,4966,4967,4968,4969,4970,4971,4972,4973,
93132 4974,4975,4976,4977,4978,4979,4980,4981,4982,4983,4984,4985,4986,4987,4988,
93133 4989,4990,4991,4992,4993,4994,4995,4996,4997,4998,4999,5000,5001,5002,5003,
93134 5004,5005,5006,5007,5008,5009,5010,5011,5012,5013,5014,5015,5016,5017,5018,
93135 5019,5020,5021,5022,5023,5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,
93136 5034,5035,5036,5037,5038,5039,5040,5041,5042,5043,5044,5045,5046,5047,5048,
93137 5049,5050,5051,5052,5053,5054,5055,5056,5057,5058,5059,5060,5061,5062,5063,
93138 5064,5065,5066,5067,5068,5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,
93139 5079,5080,5081,5082,5083,5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,
93140 5094,5095,5096,5097,5098,5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,
93141 5109,5110,5111,5104,5105,5106,5107,5108,5109,5118,5119,5120,5121,5122,5123,
93142 5124,5125,5126,5127,5128,5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,
93143 5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,
93144 5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,
93145 5169,5170,5171,5172,5173,5174,5175,5176,5177,5178,5179,5180,5181,5182,5183,
93146 5184,5185,5186,5187,5188,5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,
93147 5199,5200,5201,5202,5203,5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,
93148 5214,5215,5216,5217,5218,5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,
93149 5229,5230,5231,5232,5233,5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,
93150 5244,5245,5246,5247,5248,5249,5250,5251,5252,5253,5254,5255,5256,5257,5258,
93151 5259,5260,5261,5262,5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,
93152 5274,5275,5276,5277,5278,5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,
93153 5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,
93154 5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,
93155 5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,
93156 5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,
93157 5349,5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,
93158 5364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,
93159 5379,5380,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,
93160 5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,
93161 5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,
93162 5424,5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,
93163 5439,5440,5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,
93164 5454,5455,5456,5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,
93165 5469,5470,5471,5472,5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,
93166 5484,5485,5486,5487,5488,5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,
93167 5499,5500,5501,5502,5503,5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,
93168 5514,5515,5516,5517,5518,5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,
93169 5529,5530,5531,5532,5533,5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,
93170 5544,5545,5546,5547,5548,5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,
93171 5559,5560,5561,5562,5563,5564,5565,5566,5567,5568,5569,5570,5571,5572,5573,
93172 5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584,5585,5586,5587,5588,
93173 5589,5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600,5601,5602,5603,
93174 5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616,5617,5618,
93175 5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632,5633,
93176 5634,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648,
93177 5649,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,
93178 5664,5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,
93179 5679,5680,5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,
93180 5694,5695,5696,5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,
93181 5709,5710,5711,5712,5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,
93182 5724,5725,5726,5727,5728,5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,
93183 5739,5740,5741,5742,5743,5744,5745,5746,5747,5748,5749,5750,5751,5752,5753,
93184 5754,5755,5756,5757,5758,5759,5760,5761,5762,5763,5764,5765,5766,5767,5768,
93185 5769,5770,5771,5772,5773,5774,5775,5776,5777,5778,5779,5780,5781,5782,5783,
93186 5784,5785,5786,5787,5788,5789,5790,5791,5792,5793,5794,5795,5796,5797,5798,
93187 5799,5800,5801,5802,5803,5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,
93188 5814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824,5825,5826,5827,5828,
93189 5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,
93190 5844,5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,
93191 5859,5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872,5873,
93192 5874,5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888,
93193 5889,5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,
93194 5904,5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,
93195 5919,5920,5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,
93196 5934,5935,5936,5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,
93197 5949,5950,5951,5952,5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,
93198 5964,5965,5966,5967,5968,5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,
93199 5979,5980,5981,5982,5983,5984,5985,5986,5987,5988,5989,5990,5991,5992,5993,
93200 5994,5995,5996,5997,5998,5999,6000,6001,6002,6003,6004,6005,6006,6007,6008,
93201 6009,6010,6011,6012,6013,6014,6015,6016,6017,6018,6019,6020,6021,6022,6023,
93202 6024,6025,6026,6027,6028,6029,6030,6031,6032,6033,6034,6035,6036,6037,6038,
93203 6039,6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,
93204 6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6068,
93205 6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,
93206 6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,
93207 6099,6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,
93208 6114,6115,6116,6117,6118,6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,
93209 6129,6130,6131,6132,6133,6134,6135,6136,6137,6138,6139,6140,6141,6142,6143,
93210 6144,6145,6146,6147,6148,6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,
93211 6159,6160,6161,6162,6163,6164,6165,6166,6167,6168,6169,6170,6171,6172,6173,
93212 6174,6175,6176,6177,6178,6179,6180,6181,6182,6183,6184,6185,6186,6187,6188,
93213 6189,6190,6191,6192,6193,6194,6195,6196,6197,6198,6199,6200,6201,6202,6203,
93214 6204,6205,6206,6207,6208,6209,6210,6211,6212,6213,6214,6215,6216,6217,6218,
93215 6219,6220,6221,6222,6223,6224,6225,6226,6227,6228,6229,6230,6231,6232,6233,
93216 6234,6235,6236,6237,6238,6239,6240,6241,6242,6243,6244,6245,6246,6247,6248,
93217 6249,6250,6251,6252,6253,6254,6255,6256,6257,6258,6259,6260,6261,6262,6263,
93218 6264,6265,6266,6267,6268,6269,6270,6271,6272,6273,6274,6275,6276,6277,6278,
93219 6279,6280,6281,6282,6283,6284,6285,6286,6287,6288,6289,6290,6291,6292,6293,
93220 6294,6295,6296,6297,6298,6299,6300,6301,6302,6303,6304,6305,6306,6307,6308,
93221 6309,6310,6311,6312,6313,6314,6315,6316,6317,6318,6319,6320,6321,6322,6323,
93222 6324,6325,6326,6327,6328,6329,6330,6331,6332,6333,6334,6335,6336,6337,6338,
93223 6339,6340,6341,6342,6343,6344,6345,6346,6347,6348,6349,6350,6351,6352,6353,
93224 6354,6355,6356,6357,6358,6359,6360,6361,6362,6363,6364,6365,6366,6367,6368,
93225 6369,6370,6371,6372,6373,6374,6375,6376,6377,6378,6379,6380,6381,6382,6383,
93226 6384,6385,6386,6387,6388,6389,6390,6391,6392,6393,6394,6395,6396,6397,6398,
93227 6399,6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,6411,6412,6413,
93228 6414,6415,6416,6417,6418,6419,6420,6421,6422,6423,6424,6425,6426,6427,6428,
93229 6429,6430,6431,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443,
93230 6444,6445,6446,6447,6448,6449,6450,6451,6452,6453,6454,6455,6456,6457,6458,
93231 6459,6460,6461,6462,6463,6464,6465,6466,6467,6468,6469,6470,6471,6472,6473,
93232 6474,6475,6476,6477,6478,6479,6480,6481,6482,6483,6484,6485,6486,6487,6488,
93233 6489,6490,6491,6492,6493,6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,
93234 6504,6505,6506,6507,6508,6509,6510,6511,6512,6513,6514,6515,6516,6517,6518,
93235 6519,6520,6521,6522,6523,6524,6525,6526,6527,6528,6529,6530,6531,6532,6533,
93236 6534,6535,6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,
93237 6549,6550,6551,6552,6553,6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,
93238 6564,6565,6566,6567,6568,6569,6570,6571,6572,6573,6574,6575,6576,6577,6578,
93239 6579,6580,6581,6582,6583,6584,6585,6586,6587,6588,6589,6590,6591,6592,6593,
93240 6594,6595,6596,6597,6598,6599,6600,6601,6602,6603,6604,6605,6606,6607,6608,
93241 6609,6610,6611,6612,6613,6614,6615,6616,6617,6618,6619,6620,6621,6622,6623,
93242 6624,6625,6626,6627,6628,6629,6630,6631,6632,6633,6634,6635,6636,6637,6638,
93243 6639,6640,6641,6642,6643,6644,6645,6646,6647,6648,6649,6650,6651,6652,6653,
93244 6654,6655,6656,6657,6658,6659,6660,6661,6662,6663,6664,6665,6666,6667,6668,
93245 6669,6670,6671,6672,6673,6674,6675,6676,6677,6678,6679,6680,6681,6682,6683,
93246 6684,6685,6686,6687,6688,6689,6690,6691,6692,6693,6694,6695,6696,6697,6698,
93247 6699,6700,6701,6702,6703,6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,
93248 6714,6715,6716,6717,6718,6719,6720,6721,6722,6723,6724,6725,6726,6727,6728,
93249 6729,6730,6731,6732,6733,6734,6735,6736,6737,6738,6739,6740,6741,6742,6743,
93250 6744,6745,6746,6747,6748,6749,6750,6751,6752,6753,6754,6755,6756,6757,6758,
93251 6759,6760,6761,6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,
93252 6774,6775,6776,6777,6778,6779,6780,6781,6782,6783,6784,6785,6786,6787,6788,
93253 6789,6790,6791,6792,6793,6794,6795,6796,6797,6798,6799,6800,6801,6802,6803,
93254 6804,6805,6806,6807,6808,6809,6810,6811,6812,6813,6814,6815,6816,6817,6818,
93255 6819,6820,6821,6822,6823,6824,6825,6826,6827,6828,6829,6830,6831,6832,6833,
93256 6834,6835,6836,6837,6838,6839,6840,6841,6842,6843,6844,6845,6846,6847,6848,
93257 6849,6850,6851,6852,6853,6854,6855,6856,6857,6858,6859,6860,6861,6862,6863,
93258 6864,6865,6866,6867,6868,6869,6870,6871,6872,6873,6874,6875,6876,6877,6878,
93259 6879,6880,6881,6882,6883,6884,6885,6886,6887,6888,6889,6890,6891,6892,6893,
93260 6894,6895,6896,6897,6898,6899,6900,6901,6902,6903,6904,6905,6906,6907,6908,
93261 6909,6910,6911,6912,6913,6914,6915,6916,6917,6918,6919,6920,6921,6922,6923,
93262 6924,6925,6926,6927,6928,6929,6930,6931,6932,6933,6934,6935,6936,6937,6938,
93263 6939,6940,6941,6942,6943,6944,6945,6946,6947,6948,6949,6950,6951,6952,6953,
93264 6954,6955,6956,6957,6958,6959,6960,6961,6962,6963,6964,6965,6966,6967,6968,
93265 6969,6970,6971,6972,6973,6974,6975,6976,6977,6978,6979,6980,6981,6982,6983,
93266 6984,6985,6986,6987,6988,6989,6990,6991,6992,6993,6994,6995,6996,6997,6998,
93267 6999,7000,7001,7002,7003,7004,7005,7006,7007,7008,7009,7010,7011,7012,7013,
93268 7014,7015,7016,7017,7018,7019,7020,7021,7022,7023,7024,7025,7026,7027,7028,
93269 7029,7030,7031,7032,7033,7034,7035,7036,7037,7038,7039,7040,7041,7042,7043,
93270 7044,7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,
93271 7059,7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,7071,7072,7073,
93272 7074,7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7086,7087,7088,
93273 7089,7090,7091,7092,7093,7094,7095,7096,7097,7098,7099,7100,7101,7102,7103,
93274 7104,7105,7106,7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,
93275 7119,7120,7121,7122,7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,
93276 7134,7135,7136,7137,7138,7139,7140,7141,7142,7143,7144,7145,7146,7147,7148,
93277 7149,7150,7151,7152,7153,7154,7155,7156,7157,7158,7159,7160,7161,7162,7163,
93278 7164,7165,7166,7167,7168,7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,
93279 7179,7180,7181,7182,7183,7184,7185,7186,7187,7188,7189,7190,7191,7192,7193,
93280 7194,7195,7196,7197,7198,7199,7200,7201,7202,7203,7204,7205,7206,7207,7208,
93281 7209,7210,7211,7212,7213,7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,
93282 7224,7225,7226,7227,7228,7229,7230,7231,7232,7233,7234,7235,7236,7237,7238,
93283 7239,7240,7241,7242,7243,7244,7245,7246,7247,7248,7249,7250,7251,7252,7253,
93284 7254,7255,7256,7257,7258,7259,7260,7261,7262,7263,7264,7265,7266,7267,7268,
93285 7269,7270,7271,7272,7273,7274,7275,7276,7277,7278,7279,7280,7281,7282,7283,
93286 7284,7285,7286,7287,7288,7289,7290,7291,7292,7293,7294,7295,1042,1044,1054,
93287 1057,1058,1058,1066,1122,42570L,7305,7306,7307,7308,7309,7310,7311,7312,
93288 7313,7314,7315,7316,7317,7318,7319,7320,7321,7322,7323,7324,7325,7326,7327,
93289 7328,7329,7330,7331,7332,7333,7334,7335,7336,7337,7338,7339,7340,7341,7342,
93290 7343,7344,7345,7346,7347,7348,7349,7350,7351,7352,7353,7354,7355,7356,7357,
93291 7358,7359,7360,7361,7362,7363,7364,7365,7366,7367,7368,7369,7370,7371,7372,
93292 7373,7374,7375,7376,7377,7378,7379,7380,7381,7382,7383,7384,7385,7386,7387,
93293 7388,7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400,7401,7402,
93294 7403,7404,7405,7406,7407,7408,7409,7410,7411,7412,7413,7414,7415,7416,7417,
93295 7418,7419,7420,7421,7422,7423,7424,7425,7426,7427,7428,7429,7430,7431,7432,
93296 7433,7434,7435,7436,7437,7438,7439,7440,7441,7442,7443,7444,7445,7446,7447,
93297 7448,7449,7450,7451,7452,7453,7454,7455,7456,7457,7458,7459,7460,7461,7462,
93298 7463,7464,7465,7466,7467,7468,7469,7470,7471,7472,7473,7474,7475,7476,7477,
93299 7478,7479,7480,7481,7482,7483,7484,7485,7486,7487,7488,7489,7490,7491,7492,
93300 7493,7494,7495,7496,7497,7498,7499,7500,7501,7502,7503,7504,7505,7506,7507,
93301 7508,7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519,7520,7521,7522,
93302 7523,7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535,7536,7537,
93303 7538,7539,7540,7541,7542,7543,7544,42877L,7546,7547,7548,11363,7550,7551,
93304 7552,7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,
93305 42950L,7567,7568,7569,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,
93306 7580,7581,7582,7583,7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,
93307 7595,7596,7597,7598,7599,7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,
93308 7610,7611,7612,7613,7614,7615,7616,7617,7618,7619,7620,7621,7622,7623,7624,
93309 7625,7626,7627,7628,7629,7630,7631,7632,7633,7634,7635,7636,7637,7638,7639,
93310 7640,7641,7642,7643,7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,
93311 7655,7656,7657,7658,7659,7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,
93312 7670,7671,7672,7673,7674,7675,7676,7677,7678,7679,7680,7680,7682,7682,7684,
93313 7684,7686,7686,7688,7688,7690,7690,7692,7692,7694,7694,7696,7696,7698,7698,
93314 7700,7700,7702,7702,7704,7704,7706,7706,7708,7708,7710,7710,7712,7712,7714,
93315 7714,7716,7716,7718,7718,7720,7720,7722,7722,7724,7724,7726,7726,7728,7728,
93316 7730,7730,7732,7732,7734,7734,7736,7736,7738,7738,7740,7740,7742,7742,7744,
93317 7744,7746,7746,7748,7748,7750,7750,7752,7752,7754,7754,7756,7756,7758,7758,
93318 7760,7760,7762,7762,7764,7764,7766,7766,7768,7768,7770,7770,7772,7772,7774,
93319 7774,7776,7776,7778,7778,7780,7780,7782,7782,7784,7784,7786,7786,7788,7788,
93320 7790,7790,7792,7792,7794,7794,7796,7796,7798,7798,7800,7800,7802,7802,7804,
93321 7804,7806,7806,7808,7808,7810,7810,7812,7812,7814,7814,7816,7816,7818,7818,
93322 7820,7820,7822,7822,7824,7824,7826,7826,7828,7828,7830,7831,7832,7833,7834,
93323 7776,7836,7837,7838,7839,7840,7840,7842,7842,7844,7844,7846,7846,7848,7848,
93324 7850,7850,7852,7852,7854,7854,7856,7856,7858,7858,7860,7860,7862,7862,7864,
93325 7864,7866,7866,7868,7868,7870,7870,7872,7872,7874,7874,7876,7876,7878,7878,
93326 7880,7880,7882,7882,7884,7884,7886,7886,7888,7888,7890,7890,7892,7892,7894,
93327 7894,7896,7896,7898,7898,7900,7900,7902,7902,7904,7904,7906,7906,7908,7908,
93328 7910,7910,7912,7912,7914,7914,7916,7916,7918,7918,7920,7920,7922,7922,7924,
93329 7924,7926,7926,7928,7928,7930,7930,7932,7932,7934,7934,7944,7945,7946,7947,
93330 7948,7949,7950,7951,7944,7945,7946,7947,7948,7949,7950,7951,7960,7961,7962,
93331 7963,7964,7965,7958,7959,7960,7961,7962,7963,7964,7965,7966,7967,7976,7977,
93332 7978,7979,7980,7981,7982,7983,7976,7977,7978,7979,7980,7981,7982,7983,7992,
93333 7993,7994,7995,7996,7997,7998,7999,7992,7993,7994,7995,7996,7997,7998,7999,
93334 8008,8009,8010,8011,8012,8013,8006,8007,8008,8009,8010,8011,8012,8013,8014,
93335 8015,8016,8025,8018,8027,8020,8029,8022,8031,8024,8025,8026,8027,8028,8029,
93336 8030,8031,8040,8041,8042,8043,8044,8045,8046,8047,8040,8041,8042,8043,8044,
93337 8045,8046,8047,8122,8123,8136,8137,8138,8139,8154,8155,8184,8185,8170,8171,
93338 8186,8187,8062,8063,8064,8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,
93339 8075,8076,8077,8078,8079,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,
93340 8090,8091,8092,8093,8094,8095,8096,8097,8098,8099,8100,8101,8102,8103,8104,
93341 8105,8106,8107,8108,8109,8110,8111,8120,8121,8114,8115,8116,8117,8118,8119,
93342 8120,8121,8122,8123,8124,8125,921,8127,8128,8129,8130,8131,8132,8133,8134,
93343 8135,8136,8137,8138,8139,8140,8141,8142,8143,8152,8153,8146,8147,8148,8149,
93344 8150,8151,8152,8153,8154,8155,8156,8157,8158,8159,8168,8169,8162,8163,8164,
93345 8172,8166,8167,8168,8169,8170,8171,8172,8173,8174,8175,8176,8177,8178,8179,
93346 8180,8181,8182,8183,8184,8185,8186,8187,8188,8189,8190,8191,8192,8193,8194,
93347 8195,8196,8197,8198,8199,8200,8201,8202,8203,8204,8205,8206,8207,8208,8209,
93348 8210,8211,8212,8213,8214,8215,8216,8217,8218,8219,8220,8221,8222,8223,8224,
93349 8225,8226,8227,8228,8229,8230,8231,8232,8233,8234,8235,8236,8237,8238,8239,
93350 8240,8241,8242,8243,8244,8245,8246,8247,8248,8249,8250,8251,8252,8253,8254,
93351 8255,8256,8257,8258,8259,8260,8261,8262,8263,8264,8265,8266,8267,8268,8269,
93352 8270,8271,8272,8273,8274,8275,8276,8277,8278,8279,8280,8281,8282,8283,8284,
93353 8285,8286,8287,8288,8289,8290,8291,8292,8293,8294,8295,8296,8297,8298,8299,
93354 8300,8301,8302,8303,8304,8305,8306,8307,8308,8309,8310,8311,8312,8313,8314,
93355 8315,8316,8317,8318,8319,8320,8321,8322,8323,8324,8325,8326,8327,8328,8329,
93356 8330,8331,8332,8333,8334,8335,8336,8337,8338,8339,8340,8341,8342,8343,8344,
93357 8345,8346,8347,8348,8349,8350,8351,8352,8353,8354,8355,8356,8357,8358,8359,
93358 8360,8361,8362,8363,8364,8365,8366,8367,8368,8369,8370,8371,8372,8373,8374,
93359 8375,8376,8377,8378,8379,8380,8381,8382,8383,8384,8385,8386,8387,8388,8389,
93360 8390,8391,8392,8393,8394,8395,8396,8397,8398,8399,8400,8401,8402,8403,8404,
93361 8405,8406,8407,8408,8409,8410,8411,8412,8413,8414,8415,8416,8417,8418,8419,
93362 8420,8421,8422,8423,8424,8425,8426,8427,8428,8429,8430,8431,8432,8433,8434,
93363 8435,8436,8437,8438,8439,8440,8441,8442,8443,8444,8445,8446,8447,8448,8449,
93364 8450,8451,8452,8453,8454,8455,8456,8457,8458,8459,8460,8461,8462,8463,8464,
93365 8465,8466,8467,8468,8469,8470,8471,8472,8473,8474,8475,8476,8477,8478,8479,
93366 8480,8481,8482,8483,8484,8485,8486,8487,8488,8489,8490,8491,8492,8493,8494,
93367 8495,8496,8497,8498,8499,8500,8501,8502,8503,8504,8505,8506,8507,8508,8509,
93368 8510,8511,8512,8513,8514,8515,8516,8517,8518,8519,8520,8521,8522,8523,8524,
93369 8525,8498,8527,8528,8529,8530,8531,8532,8533,8534,8535,8536,8537,8538,8539,
93370 8540,8541,8542,8543,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,
93371 8555,8556,8557,8558,8559,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,
93372 8554,8555,8556,8557,8558,8559,8576,8577,8578,8579,8579,8581,8582,8583,8584,
93373 8585,8586,8587,8588,8589,8590,8591,8592,8593,8594,8595,8596,8597,8598,8599,
93374 8600,8601,8602,8603,8604,8605,8606,8607,8608,8609,8610,8611,8612,8613,8614,
93375 8615,8616,8617,8618,8619,8620,8621,8622,8623,8624,8625,8626,8627,8628,8629,
93376 8630,8631,8632,8633,8634,8635,8636,8637,8638,8639,8640,8641,8642,8643,8644,
93377 8645,8646,8647,8648,8649,8650,8651,8652,8653,8654,8655,8656,8657,8658,8659,
93378 8660,8661,8662,8663,8664,8665,8666,8667,8668,8669,8670,8671,8672,8673,8674,
93379 8675,8676,8677,8678,8679,8680,8681,8682,8683,8684,8685,8686,8687,8688,8689,
93380 8690,8691,8692,8693,8694,8695,8696,8697,8698,8699,8700,8701,8702,8703,8704,
93381 8705,8706,8707,8708,8709,8710,8711,8712,8713,8714,8715,8716,8717,8718,8719,
93382 8720,8721,8722,8723,8724,8725,8726,8727,8728,8729,8730,8731,8732,8733,8734,
93383 8735,8736,8737,8738,8739,8740,8741,8742,8743,8744,8745,8746,8747,8748,8749,
93384 8750,8751,8752,8753,8754,8755,8756,8757,8758,8759,8760,8761,8762,8763,8764,
93385 8765,8766,8767,8768,8769,8770,8771,8772,8773,8774,8775,8776,8777,8778,8779,
93386 8780,8781,8782,8783,8784,8785,8786,8787,8788,8789,8790,8791,8792,8793,8794,
93387 8795,8796,8797,8798,8799,8800,8801,8802,8803,8804,8805,8806,8807,8808,8809,
93388 8810,8811,8812,8813,8814,8815,8816,8817,8818,8819,8820,8821,8822,8823,8824,
93389 8825,8826,8827,8828,8829,8830,8831,8832,8833,8834,8835,8836,8837,8838,8839,
93390 8840,8841,8842,8843,8844,8845,8846,8847,8848,8849,8850,8851,8852,8853,8854,
93391 8855,8856,8857,8858,8859,8860,8861,8862,8863,8864,8865,8866,8867,8868,8869,
93392 8870,8871,8872,8873,8874,8875,8876,8877,8878,8879,8880,8881,8882,8883,8884,
93393 8885,8886,8887,8888,8889,8890,8891,8892,8893,8894,8895,8896,8897,8898,8899,
93394 8900,8901,8902,8903,8904,8905,8906,8907,8908,8909,8910,8911,8912,8913,8914,
93395 8915,8916,8917,8918,8919,8920,8921,8922,8923,8924,8925,8926,8927,8928,8929,
93396 8930,8931,8932,8933,8934,8935,8936,8937,8938,8939,8940,8941,8942,8943,8944,
93397 8945,8946,8947,8948,8949,8950,8951,8952,8953,8954,8955,8956,8957,8958,8959,
93398 8960,8961,8962,8963,8964,8965,8966,8967,8968,8969,8970,8971,8972,8973,8974,
93399 8975,8976,8977,8978,8979,8980,8981,8982,8983,8984,8985,8986,8987,8988,8989,
93400 8990,8991,8992,8993,8994,8995,8996,8997,8998,8999,9000,9001,9002,9003,9004,
93401 9005,9006,9007,9008,9009,9010,9011,9012,9013,9014,9015,9016,9017,9018,9019,
93402 9020,9021,9022,9023,9024,9025,9026,9027,9028,9029,9030,9031,9032,9033,9034,
93403 9035,9036,9037,9038,9039,9040,9041,9042,9043,9044,9045,9046,9047,9048,9049,
93404 9050,9051,9052,9053,9054,9055,9056,9057,9058,9059,9060,9061,9062,9063,9064,
93405 9065,9066,9067,9068,9069,9070,9071,9072,9073,9074,9075,9076,9077,9078,9079,
93406 9080,9081,9082,9083,9084,9085,9086,9087,9088,9089,9090,9091,9092,9093,9094,
93407 9095,9096,9097,9098,9099,9100,9101,9102,9103,9104,9105,9106,9107,9108,9109,
93408 9110,9111,9112,9113,9114,9115,9116,9117,9118,9119,9120,9121,9122,9123,9124,
93409 9125,9126,9127,9128,9129,9130,9131,9132,9133,9134,9135,9136,9137,9138,9139,
93410 9140,9141,9142,9143,9144,9145,9146,9147,9148,9149,9150,9151,9152,9153,9154,
93411 9155,9156,9157,9158,9159,9160,9161,9162,9163,9164,9165,9166,9167,9168,9169,
93412 9170,9171,9172,9173,9174,9175,9176,9177,9178,9179,9180,9181,9182,9183,9184,
93413 9185,9186,9187,9188,9189,9190,9191,9192,9193,9194,9195,9196,9197,9198,9199,
93414 9200,9201,9202,9203,9204,9205,9206,9207,9208,9209,9210,9211,9212,9213,9214,
93415 9215,9216,9217,9218,9219,9220,9221,9222,9223,9224,9225,9226,9227,9228,9229,
93416 9230,9231,9232,9233,9234,9235,9236,9237,9238,9239,9240,9241,9242,9243,9244,
93417 9245,9246,9247,9248,9249,9250,9251,9252,9253,9254,9255,9256,9257,9258,9259,
93418 9260,9261,9262,9263,9264,9265,9266,9267,9268,9269,9270,9271,9272,9273,9274,
93419 9275,9276,9277,9278,9279,9280,9281,9282,9283,9284,9285,9286,9287,9288,9289,
93420 9290,9291,9292,9293,9294,9295,9296,9297,9298,9299,9300,9301,9302,9303,9304,
93421 9305,9306,9307,9308,9309,9310,9311,9312,9313,9314,9315,9316,9317,9318,9319,
93422 9320,9321,9322,9323,9324,9325,9326,9327,9328,9329,9330,9331,9332,9333,9334,
93423 9335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345,9346,9347,9348,9349,
93424 9350,9351,9352,9353,9354,9355,9356,9357,9358,9359,9360,9361,9362,9363,9364,
93425 9365,9366,9367,9368,9369,9370,9371,9372,9373,9374,9375,9376,9377,9378,9379,
93426 9380,9381,9382,9383,9384,9385,9386,9387,9388,9389,9390,9391,9392,9393,9394,
93427 9395,9396,9397,9398,9399,9400,9401,9402,9403,9404,9405,9406,9407,9408,9409,
93428 9410,9411,9412,9413,9414,9415,9416,9417,9418,9419,9420,9421,9422,9423,9398,
93429 9399,9400,9401,9402,9403,9404,9405,9406,9407,9408,9409,9410,9411,9412,9413,
93430 9414,9415,9416,9417,9418,9419,9420,9421,9422,9423,9450,9451,9452,9453,9454,
93431 9455,9456,9457,9458,9459,9460,9461,9462,9463,9464,9465,9466,9467,9468,9469,
93432 9470,9471,9472,9473,9474,9475,9476,9477,9478,9479,9480,9481,9482,9483,9484,
93433 9485,9486,9487,9488,9489,9490,9491,9492,9493,9494,9495,9496,9497,9498,9499,
93434 9500,9501,9502,9503,9504,9505,9506,9507,9508,9509,9510,9511,9512,9513,9514,
93435 9515,9516,9517,9518,9519,9520,9521,9522,9523,9524,9525,9526,9527,9528,9529,
93436 9530,9531,9532,9533,9534,9535,9536,9537,9538,9539,9540,9541,9542,9543,9544,
93437 9545,9546,9547,9548,9549,9550,9551,9552,9553,9554,9555,9556,9557,9558,9559,
93438 9560,9561,9562,9563,9564,9565,9566,9567,9568,9569,9570,9571,9572,9573,9574,
93439 9575,9576,9577,9578,9579,9580,9581,9582,9583,9584,9585,9586,9587,9588,9589,
93440 9590,9591,9592,9593,9594,9595,9596,9597,9598,9599,9600,9601,9602,9603,9604,
93441 9605,9606,9607,9608,9609,9610,9611,9612,9613,9614,9615,9616,9617,9618,9619,
93442 9620,9621,9622,9623,9624,9625,9626,9627,9628,9629,9630,9631,9632,9633,9634,
93443 9635,9636,9637,9638,9639,9640,9641,9642,9643,9644,9645,9646,9647,9648,9649,
93444 9650,9651,9652,9653,9654,9655,9656,9657,9658,9659,9660,9661,9662,9663,9664,
93445 9665,9666,9667,9668,9669,9670,9671,9672,9673,9674,9675,9676,9677,9678,9679,
93446 9680,9681,9682,9683,9684,9685,9686,9687,9688,9689,9690,9691,9692,9693,9694,
93447 9695,9696,9697,9698,9699,9700,9701,9702,9703,9704,9705,9706,9707,9708,9709,
93448 9710,9711,9712,9713,9714,9715,9716,9717,9718,9719,9720,9721,9722,9723,9724,
93449 9725,9726,9727,9728,9729,9730,9731,9732,9733,9734,9735,9736,9737,9738,9739,
93450 9740,9741,9742,9743,9744,9745,9746,9747,9748,9749,9750,9751,9752,9753,9754,
93451 9755,9756,9757,9758,9759,9760,9761,9762,9763,9764,9765,9766,9767,9768,9769,
93452 9770,9771,9772,9773,9774,9775,9776,9777,9778,9779,9780,9781,9782,9783,9784,
93453 9785,9786,9787,9788,9789,9790,9791,9792,9793,9794,9795,9796,9797,9798,9799,
93454 9800,9801,9802,9803,9804,9805,9806,9807,9808,9809,9810,9811,9812,9813,9814,
93455 9815,9816,9817,9818,9819,9820,9821,9822,9823,9824,9825,9826,9827,9828,9829,
93456 9830,9831,9832,9833,9834,9835,9836,9837,9838,9839,9840,9841,9842,9843,9844,
93457 9845,9846,9847,9848,9849,9850,9851,9852,9853,9854,9855,9856,9857,9858,9859,
93458 9860,9861,9862,9863,9864,9865,9866,9867,9868,9869,9870,9871,9872,9873,9874,
93459 9875,9876,9877,9878,9879,9880,9881,9882,9883,9884,9885,9886,9887,9888,9889,
93460 9890,9891,9892,9893,9894,9895,9896,9897,9898,9899,9900,9901,9902,9903,9904,
93461 9905,9906,9907,9908,9909,9910,9911,9912,9913,9914,9915,9916,9917,9918,9919,
93462 9920,9921,9922,9923,9924,9925,9926,9927,9928,9929,9930,9931,9932,9933,9934,
93463 9935,9936,9937,9938,9939,9940,9941,9942,9943,9944,9945,9946,9947,9948,9949,
93464 9950,9951,9952,9953,9954,9955,9956,9957,9958,9959,9960,9961,9962,9963,9964,
93465 9965,9966,9967,9968,9969,9970,9971,9972,9973,9974,9975,9976,9977,9978,9979,
93466 9980,9981,9982,9983,9984,9985,9986,9987,9988,9989,9990,9991,9992,9993,9994,
93467 9995,9996,9997,9998,9999,10000,10001,10002,10003,10004,10005,10006,10007,
93468 10008,10009,10010,10011,10012,10013,10014,10015,10016,10017,10018,10019,
93469 10020,10021,10022,10023,10024,10025,10026,10027,10028,10029,10030,10031,
93470 10032,10033,10034,10035,10036,10037,10038,10039,10040,10041,10042,10043,
93471 10044,10045,10046,10047,10048,10049,10050,10051,10052,10053,10054,10055,
93472 10056,10057,10058,10059,10060,10061,10062,10063,10064,10065,10066,10067,
93473 10068,10069,10070,10071,10072,10073,10074,10075,10076,10077,10078,10079,
93474 10080,10081,10082,10083,10084,10085,10086,10087,10088,10089,10090,10091,
93475 10092,10093,10094,10095,10096,10097,10098,10099,10100,10101,10102,10103,
93476 10104,10105,10106,10107,10108,10109,10110,10111,10112,10113,10114,10115,
93477 10116,10117,10118,10119,10120,10121,10122,10123,10124,10125,10126,10127,
93478 10128,10129,10130,10131,10132,10133,10134,10135,10136,10137,10138,10139,
93479 10140,10141,10142,10143,10144,10145,10146,10147,10148,10149,10150,10151,
93480 10152,10153,10154,10155,10156,10157,10158,10159,10160,10161,10162,10163,
93481 10164,10165,10166,10167,10168,10169,10170,10171,10172,10173,10174,10175,
93482 10176,10177,10178,10179,10180,10181,10182,10183,10184,10185,10186,10187,
93483 10188,10189,10190,10191,10192,10193,10194,10195,10196,10197,10198,10199,
93484 10200,10201,10202,10203,10204,10205,10206,10207,10208,10209,10210,10211,
93485 10212,10213,10214,10215,10216,10217,10218,10219,10220,10221,10222,10223,
93486 10224,10225,10226,10227,10228,10229,10230,10231,10232,10233,10234,10235,
93487 10236,10237,10238,10239,10240,10241,10242,10243,10244,10245,10246,10247,
93488 10248,10249,10250,10251,10252,10253,10254,10255,10256,10257,10258,10259,
93489 10260,10261,10262,10263,10264,10265,10266,10267,10268,10269,10270,10271,
93490 10272,10273,10274,10275,10276,10277,10278,10279,10280,10281,10282,10283,
93491 10284,10285,10286,10287,10288,10289,10290,10291,10292,10293,10294,10295,
93492 10296,10297,10298,10299,10300,10301,10302,10303,10304,10305,10306,10307,
93493 10308,10309,10310,10311,10312,10313,10314,10315,10316,10317,10318,10319,
93494 10320,10321,10322,10323,10324,10325,10326,10327,10328,10329,10330,10331,
93495 10332,10333,10334,10335,10336,10337,10338,10339,10340,10341,10342,10343,
93496 10344,10345,10346,10347,10348,10349,10350,10351,10352,10353,10354,10355,
93497 10356,10357,10358,10359,10360,10361,10362,10363,10364,10365,10366,10367,
93498 10368,10369,10370,10371,10372,10373,10374,10375,10376,10377,10378,10379,
93499 10380,10381,10382,10383,10384,10385,10386,10387,10388,10389,10390,10391,
93500 10392,10393,10394,10395,10396,10397,10398,10399,10400,10401,10402,10403,
93501 10404,10405,10406,10407,10408,10409,10410,10411,10412,10413,10414,10415,
93502 10416,10417,10418,10419,10420,10421,10422,10423,10424,10425,10426,10427,
93503 10428,10429,10430,10431,10432,10433,10434,10435,10436,10437,10438,10439,
93504 10440,10441,10442,10443,10444,10445,10446,10447,10448,10449,10450,10451,
93505 10452,10453,10454,10455,10456,10457,10458,10459,10460,10461,10462,10463,
93506 10464,10465,10466,10467,10468,10469,10470,10471,10472,10473,10474,10475,
93507 10476,10477,10478,10479,10480,10481,10482,10483,10484,10485,10486,10487,
93508 10488,10489,10490,10491,10492,10493,10494,10495,10496,10497,10498,10499,
93509 10500,10501,10502,10503,10504,10505,10506,10507,10508,10509,10510,10511,
93510 10512,10513,10514,10515,10516,10517,10518,10519,10520,10521,10522,10523,
93511 10524,10525,10526,10527,10528,10529,10530,10531,10532,10533,10534,10535,
93512 10536,10537,10538,10539,10540,10541,10542,10543,10544,10545,10546,10547,
93513 10548,10549,10550,10551,10552,10553,10554,10555,10556,10557,10558,10559,
93514 10560,10561,10562,10563,10564,10565,10566,10567,10568,10569,10570,10571,
93515 10572,10573,10574,10575,10576,10577,10578,10579,10580,10581,10582,10583,
93516 10584,10585,10586,10587,10588,10589,10590,10591,10592,10593,10594,10595,
93517 10596,10597,10598,10599,10600,10601,10602,10603,10604,10605,10606,10607,
93518 10608,10609,10610,10611,10612,10613,10614,10615,10616,10617,10618,10619,
93519 10620,10621,10622,10623,10624,10625,10626,10627,10628,10629,10630,10631,
93520 10632,10633,10634,10635,10636,10637,10638,10639,10640,10641,10642,10643,
93521 10644,10645,10646,10647,10648,10649,10650,10651,10652,10653,10654,10655,
93522 10656,10657,10658,10659,10660,10661,10662,10663,10664,10665,10666,10667,
93523 10668,10669,10670,10671,10672,10673,10674,10675,10676,10677,10678,10679,
93524 10680,10681,10682,10683,10684,10685,10686,10687,10688,10689,10690,10691,
93525 10692,10693,10694,10695,10696,10697,10698,10699,10700,10701,10702,10703,
93526 10704,10705,10706,10707,10708,10709,10710,10711,10712,10713,10714,10715,
93527 10716,10717,10718,10719,10720,10721,10722,10723,10724,10725,10726,10727,
93528 10728,10729,10730,10731,10732,10733,10734,10735,10736,10737,10738,10739,
93529 10740,10741,10742,10743,10744,10745,10746,10747,10748,10749,10750,10751,
93530 10752,10753,10754,10755,10756,10757,10758,10759,10760,10761,10762,10763,
93531 10764,10765,10766,10767,10768,10769,10770,10771,10772,10773,10774,10775,
93532 10776,10777,10778,10779,10780,10781,10782,10783,10784,10785,10786,10787,
93533 10788,10789,10790,10791,10792,10793,10794,10795,10796,10797,10798,10799,
93534 10800,10801,10802,10803,10804,10805,10806,10807,10808,10809,10810,10811,
93535 10812,10813,10814,10815,10816,10817,10818,10819,10820,10821,10822,10823,
93536 10824,10825,10826,10827,10828,10829,10830,10831,10832,10833,10834,10835,
93537 10836,10837,10838,10839,10840,10841,10842,10843,10844,10845,10846,10847,
93538 10848,10849,10850,10851,10852,10853,10854,10855,10856,10857,10858,10859,
93539 10860,10861,10862,10863,10864,10865,10866,10867,10868,10869,10870,10871,
93540 10872,10873,10874,10875,10876,10877,10878,10879,10880,10881,10882,10883,
93541 10884,10885,10886,10887,10888,10889,10890,10891,10892,10893,10894,10895,
93542 10896,10897,10898,10899,10900,10901,10902,10903,10904,10905,10906,10907,
93543 10908,10909,10910,10911,10912,10913,10914,10915,10916,10917,10918,10919,
93544 10920,10921,10922,10923,10924,10925,10926,10927,10928,10929,10930,10931,
93545 10932,10933,10934,10935,10936,10937,10938,10939,10940,10941,10942,10943,
93546 10944,10945,10946,10947,10948,10949,10950,10951,10952,10953,10954,10955,
93547 10956,10957,10958,10959,10960,10961,10962,10963,10964,10965,10966,10967,
93548 10968,10969,10970,10971,10972,10973,10974,10975,10976,10977,10978,10979,
93549 10980,10981,10982,10983,10984,10985,10986,10987,10988,10989,10990,10991,
93550 10992,10993,10994,10995,10996,10997,10998,10999,11000,11001,11002,11003,
93551 11004,11005,11006,11007,11008,11009,11010,11011,11012,11013,11014,11015,
93552 11016,11017,11018,11019,11020,11021,11022,11023,11024,11025,11026,11027,
93553 11028,11029,11030,11031,11032,11033,11034,11035,11036,11037,11038,11039,
93554 11040,11041,11042,11043,11044,11045,11046,11047,11048,11049,11050,11051,
93555 11052,11053,11054,11055,11056,11057,11058,11059,11060,11061,11062,11063,
93556 11064,11065,11066,11067,11068,11069,11070,11071,11072,11073,11074,11075,
93557 11076,11077,11078,11079,11080,11081,11082,11083,11084,11085,11086,11087,
93558 11088,11089,11090,11091,11092,11093,11094,11095,11096,11097,11098,11099,
93559 11100,11101,11102,11103,11104,11105,11106,11107,11108,11109,11110,11111,
93560 11112,11113,11114,11115,11116,11117,11118,11119,11120,11121,11122,11123,
93561 11124,11125,11126,11127,11128,11129,11130,11131,11132,11133,11134,11135,
93562 11136,11137,11138,11139,11140,11141,11142,11143,11144,11145,11146,11147,
93563 11148,11149,11150,11151,11152,11153,11154,11155,11156,11157,11158,11159,
93564 11160,11161,11162,11163,11164,11165,11166,11167,11168,11169,11170,11171,
93565 11172,11173,11174,11175,11176,11177,11178,11179,11180,11181,11182,11183,
93566 11184,11185,11186,11187,11188,11189,11190,11191,11192,11193,11194,11195,
93567 11196,11197,11198,11199,11200,11201,11202,11203,11204,11205,11206,11207,
93568 11208,11209,11210,11211,11212,11213,11214,11215,11216,11217,11218,11219,
93569 11220,11221,11222,11223,11224,11225,11226,11227,11228,11229,11230,11231,
93570 11232,11233,11234,11235,11236,11237,11238,11239,11240,11241,11242,11243,
93571 11244,11245,11246,11247,11248,11249,11250,11251,11252,11253,11254,11255,
93572 11256,11257,11258,11259,11260,11261,11262,11263,11264,11265,11266,11267,
93573 11268,11269,11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,
93574 11280,11281,11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,
93575 11292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,
93576 11304,11305,11306,11307,11308,11309,11310,11311,11264,11265,11266,11267,
93577 11268,11269,11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,
93578 11280,11281,11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,
93579 11292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,
93580 11304,11305,11306,11307,11308,11309,11310,11359,11360,11360,11362,11363,
93581 11364,570,574,11367,11367,11369,11369,11371,11371,11373,11374,11375,11376,
93582 11377,11378,11378,11380,11381,11381,11383,11384,11385,11386,11387,11388,
93583 11389,11390,11391,11392,11392,11394,11394,11396,11396,11398,11398,11400,
93584 11400,11402,11402,11404,11404,11406,11406,11408,11408,11410,11410,11412,
93585 11412,11414,11414,11416,11416,11418,11418,11420,11420,11422,11422,11424,
93586 11424,11426,11426,11428,11428,11430,11430,11432,11432,11434,11434,11436,
93587 11436,11438,11438,11440,11440,11442,11442,11444,11444,11446,11446,11448,
93588 11448,11450,11450,11452,11452,11454,11454,11456,11456,11458,11458,11460,
93589 11460,11462,11462,11464,11464,11466,11466,11468,11468,11470,11470,11472,
93590 11472,11474,11474,11476,11476,11478,11478,11480,11480,11482,11482,11484,
93591 11484,11486,11486,11488,11488,11490,11490,11492,11493,11494,11495,11496,
93592 11497,11498,11499,11499,11501,11501,11503,11504,11505,11506,11506,11508,
93593 11509,11510,11511,11512,11513,11514,11515,11516,11517,11518,11519,4256,
93594 4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,
93595 4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,
93596 4287,4288,4289,4290,4291,4292,4293,11558,4295,11560,11561,11562,11563,
93597 11564,4301,11566,11567,11568,11569,11570,11571,11572,11573,11574,11575,
93598 11576,11577,11578,11579,11580,11581,11582,11583,11584,11585,11586,11587,
93599 11588,11589,11590,11591,11592,11593,11594,11595,11596,11597,11598,11599,
93600 11600,11601,11602,11603,11604,11605,11606,11607,11608,11609,11610,11611,
93601 11612,11613,11614,11615,11616,11617,11618,11619,11620,11621,11622,11623,
93602 11624,11625,11626,11627,11628,11629,11630,11631,11632,11633,11634,11635,
93603 11636,11637,11638,11639,11640,11641,11642,11643,11644,11645,11646,11647,
93604 11648,11649,11650,11651,11652,11653,11654,11655,11656,11657,11658,11659,
93605 11660,11661,11662,11663,11664,11665,11666,11667,11668,11669,11670,11671,
93606 11672,11673,11674,11675,11676,11677,11678,11679,11680,11681,11682,11683,
93607 11684,11685,11686,11687,11688,11689,11690,11691,11692,11693,11694,11695,
93608 11696,11697,11698,11699,11700,11701,11702,11703,11704,11705,11706,11707,
93609 11708,11709,11710,11711,11712,11713,11714,11715,11716,11717,11718,11719,
93610 11720,11721,11722,11723,11724,11725,11726,11727,11728,11729,11730,11731,
93611 11732,11733,11734,11735,11736,11737,11738,11739,11740,11741,11742,11743,
93612 11744,11745,11746,11747,11748,11749,11750,11751,11752,11753,11754,11755,
93613 11756,11757,11758,11759,11760,11761,11762,11763,11764,11765,11766,11767,
93614 11768,11769,11770,11771,11772,11773,11774,11775,11776,11777,11778,11779,
93615 11780,11781,11782,11783,11784,11785,11786,11787,11788,11789,11790,11791,
93616 11792,11793,11794,11795,11796,11797,11798,11799,11800,11801,11802,11803,
93617 11804,11805,11806,11807,11808,11809,11810,11811,11812,11813,11814,11815,
93618 11816,11817,11818,11819,11820,11821,11822,11823,11824,11825,11826,11827,
93619 11828,11829,11830,11831,11832,11833,11834,11835,11836,11837,11838,11839,
93620 11840,11841,11842,11843,11844,11845,11846,11847,11848,11849,11850,11851,
93621 11852,11853,11854,11855,11856,11857,11858,11859,11860,11861,11862,11863,
93622 11864,11865,11866,11867,11868,11869,11870,11871,11872,11873,11874,11875,
93623 11876,11877,11878,11879,11880,11881,11882,11883,11884,11885,11886,11887,
93624 11888,11889,11890,11891,11892,11893,11894,11895,11896,11897,11898,11899,
93625 11900,11901,11902,11903,11904,11905,11906,11907,11908,11909,11910,11911,
93626 11912,11913,11914,11915,11916,11917,11918,11919,11920,11921,11922,11923,
93627 11924,11925,11926,11927,11928,11929,11930,11931,11932,11933,11934,11935,
93628 11936,11937,11938,11939,11940,11941,11942,11943,11944,11945,11946,11947,
93629 11948,11949,11950,11951,11952,11953,11954,11955,11956,11957,11958,11959,
93630 11960,11961,11962,11963,11964,11965,11966,11967,11968,11969,11970,11971,
93631 11972,11973,11974,11975,11976,11977,11978,11979,11980,11981,11982,11983,
93632 11984,11985,11986,11987,11988,11989,11990,11991,11992,11993,11994,11995,
93633 11996,11997,11998,11999,12000,12001,12002,12003,12004,12005,12006,12007,
93634 12008,12009,12010,12011,12012,12013,12014,12015,12016,12017,12018,12019,
93635 12020,12021,12022,12023,12024,12025,12026,12027,12028,12029,12030,12031,
93636 12032,12033,12034,12035,12036,12037,12038,12039,12040,12041,12042,12043,
93637 12044,12045,12046,12047,12048,12049,12050,12051,12052,12053,12054,12055,
93638 12056,12057,12058,12059,12060,12061,12062,12063,12064,12065,12066,12067,
93639 12068,12069,12070,12071,12072,12073,12074,12075,12076,12077,12078,12079,
93640 12080,12081,12082,12083,12084,12085,12086,12087,12088,12089,12090,12091,
93641 12092,12093,12094,12095,12096,12097,12098,12099,12100,12101,12102,12103,
93642 12104,12105,12106,12107,12108,12109,12110,12111,12112,12113,12114,12115,
93643 12116,12117,12118,12119,12120,12121,12122,12123,12124,12125,12126,12127,
93644 12128,12129,12130,12131,12132,12133,12134,12135,12136,12137,12138,12139,
93645 12140,12141,12142,12143,12144,12145,12146,12147,12148,12149,12150,12151,
93646 12152,12153,12154,12155,12156,12157,12158,12159,12160,12161,12162,12163,
93647 12164,12165,12166,12167,12168,12169,12170,12171,12172,12173,12174,12175,
93648 12176,12177,12178,12179,12180,12181,12182,12183,12184,12185,12186,12187,
93649 12188,12189,12190,12191,12192,12193,12194,12195,12196,12197,12198,12199,
93650 12200,12201,12202,12203,12204,12205,12206,12207,12208,12209,12210,12211,
93651 12212,12213,12214,12215,12216,12217,12218,12219,12220,12221,12222,12223,
93652 12224,12225,12226,12227,12228,12229,12230,12231,12232,12233,12234,12235,
93653 12236,12237,12238,12239,12240,12241,12242,12243,12244,12245,12246,12247,
93654 12248,12249,12250,12251,12252,12253,12254,12255,12256,12257,12258,12259,
93655 12260,12261,12262,12263,12264,12265,12266,12267,12268,12269,12270,12271,
93656 12272,12273,12274,12275,12276,12277,12278,12279,12280,12281,12282,12283,
93657 12284,12285,12286,12287,12288,12289,12290,12291,12292,12293,12294,12295,
93658 12296,12297,12298,12299,12300,12301,12302,12303,12304,12305,12306,12307,
93659 12308,12309,12310,12311,12312,12313,12314,12315,12316,12317,12318,12319,
93660 12320,12321,12322,12323,12324,12325,12326,12327,12328,12329,12330,12331,
93661 12332,12333,12334,12335,12336,12337,12338,12339,12340,12341,12342,12343,
93662 12344,12345,12346,12347,12348,12349,12350,12351,12352,12353,12354,12355,
93663 12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,
93664 12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,
93665 12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,
93666 12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,
93667 12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,
93668 12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,
93669 12428,12429,12430,12431,12432,12433,12434,12435,12436,12437,12438,12439,
93670 12440,12441,12442,12443,12444,12445,12446,12447,12448,12449,12450,12451,
93671 12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,
93672 12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,
93673 12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,
93674 12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,
93675 12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,
93676 12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,
93677 12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,12535,
93678 12536,12537,12538,12539,12540,12541,12542,12543,12544,12545,12546,12547,
93679 12548,12549,12550,12551,12552,12553,12554,12555,12556,12557,12558,12559,
93680 12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570,12571,
93681 12572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,12583,
93682 12584,12585,12586,12587,12588,12589,12590,12591,12592,12593,12594,12595,
93683 12596,12597,12598,12599,12600,12601,12602,12603,12604,12605,12606,12607,
93684 12608,12609,12610,12611,12612,12613,12614,12615,12616,12617,12618,12619,
93685 12620,12621,12622,12623,12624,12625,12626,12627,12628,12629,12630,12631,
93686 12632,12633,12634,12635,12636,12637,12638,12639,12640,12641,12642,12643,
93687 12644,12645,12646,12647,12648,12649,12650,12651,12652,12653,12654,12655,
93688 12656,12657,12658,12659,12660,12661,12662,12663,12664,12665,12666,12667,
93689 12668,12669,12670,12671,12672,12673,12674,12675,12676,12677,12678,12679,
93690 12680,12681,12682,12683,12684,12685,12686,12687,12688,12689,12690,12691,
93691 12692,12693,12694,12695,12696,12697,12698,12699,12700,12701,12702,12703,
93692 12704,12705,12706,12707,12708,12709,12710,12711,12712,12713,12714,12715,
93693 12716,12717,12718,12719,12720,12721,12722,12723,12724,12725,12726,12727,
93694 12728,12729,12730,12731,12732,12733,12734,12735,12736,12737,12738,12739,
93695 12740,12741,12742,12743,12744,12745,12746,12747,12748,12749,12750,12751,
93696 12752,12753,12754,12755,12756,12757,12758,12759,12760,12761,12762,12763,
93697 12764,12765,12766,12767,12768,12769,12770,12771,12772,12773,12774,12775,
93698 12776,12777,12778,12779,12780,12781,12782,12783,12784,12785,12786,12787,
93699 12788,12789,12790,12791,12792,12793,12794,12795,12796,12797,12798,12799,
93700 12800,12801,12802,12803,12804,12805,12806,12807,12808,12809,12810,12811,
93701 12812,12813,12814,12815,12816,12817,12818,12819,12820,12821,12822,12823,
93702 12824,12825,12826,12827,12828,12829,12830,12831,12832,12833,12834,12835,
93703 12836,12837,12838,12839,12840,12841,12842,12843,12844,12845,12846,12847,
93704 12848,12849,12850,12851,12852,12853,12854,12855,12856,12857,12858,12859,
93705 12860,12861,12862,12863,12864,12865,12866,12867,12868,12869,12870,12871,
93706 12872,12873,12874,12875,12876,12877,12878,12879,12880,12881,12882,12883,
93707 12884,12885,12886,12887,12888,12889,12890,12891,12892,12893,12894,12895,
93708 12896,12897,12898,12899,12900,12901,12902,12903,12904,12905,12906,12907,
93709 12908,12909,12910,12911,12912,12913,12914,12915,12916,12917,12918,12919,
93710 12920,12921,12922,12923,12924,12925,12926,12927,12928,12929,12930,12931,
93711 12932,12933,12934,12935,12936,12937,12938,12939,12940,12941,12942,12943,
93712 12944,12945,12946,12947,12948,12949,12950,12951,12952,12953,12954,12955,
93713 12956,12957,12958,12959,12960,12961,12962,12963,12964,12965,12966,12967,
93714 12968,12969,12970,12971,12972,12973,12974,12975,12976,12977,12978,12979,
93715 12980,12981,12982,12983,12984,12985,12986,12987,12988,12989,12990,12991,
93716 12992,12993,12994,12995,12996,12997,12998,12999,13000,13001,13002,13003,
93717 13004,13005,13006,13007,13008,13009,13010,13011,13012,13013,13014,13015,
93718 13016,13017,13018,13019,13020,13021,13022,13023,13024,13025,13026,13027,
93719 13028,13029,13030,13031,13032,13033,13034,13035,13036,13037,13038,13039,
93720 13040,13041,13042,13043,13044,13045,13046,13047,13048,13049,13050,13051,
93721 13052,13053,13054,13055,13056,13057,13058,13059,13060,13061,13062,13063,
93722 13064,13065,13066,13067,13068,13069,13070,13071,13072,13073,13074,13075,
93723 13076,13077,13078,13079,13080,13081,13082,13083,13084,13085,13086,13087,
93724 13088,13089,13090,13091,13092,13093,13094,13095,13096,13097,13098,13099,
93725 13100,13101,13102,13103,13104,13105,13106,13107,13108,13109,13110,13111,
93726 13112,13113,13114,13115,13116,13117,13118,13119,13120,13121,13122,13123,
93727 13124,13125,13126,13127,13128,13129,13130,13131,13132,13133,13134,13135,
93728 13136,13137,13138,13139,13140,13141,13142,13143,13144,13145,13146,13147,
93729 13148,13149,13150,13151,13152,13153,13154,13155,13156,13157,13158,13159,
93730 13160,13161,13162,13163,13164,13165,13166,13167,13168,13169,13170,13171,
93731 13172,13173,13174,13175,13176,13177,13178,13179,13180,13181,13182,13183,
93732 13184,13185,13186,13187,13188,13189,13190,13191,13192,13193,13194,13195,
93733 13196,13197,13198,13199,13200,13201,13202,13203,13204,13205,13206,13207,
93734 13208,13209,13210,13211,13212,13213,13214,13215,13216,13217,13218,13219,
93735 13220,13221,13222,13223,13224,13225,13226,13227,13228,13229,13230,13231,
93736 13232,13233,13234,13235,13236,13237,13238,13239,13240,13241,13242,13243,
93737 13244,13245,13246,13247,13248,13249,13250,13251,13252,13253,13254,13255,
93738 13256,13257,13258,13259,13260,13261,13262,13263,13264,13265,13266,13267,
93739 13268,13269,13270,13271,13272,13273,13274,13275,13276,13277,13278,13279,
93740 13280,13281,13282,13283,13284,13285,13286,13287,13288,13289,13290,13291,
93741 13292,13293,13294,13295,13296,13297,13298,13299,13300,13301,13302,13303,
93742 13304,13305,13306,13307,13308,13309,13310,13311,13312,13313,13314,13315,
93743 13316,13317,13318,13319,13320,13321,13322,13323,13324,13325,13326,13327,
93744 13328,13329,13330,13331,13332,13333,13334,13335,13336,13337,13338,13339,
93745 13340,13341,13342,13343,13344,13345,13346,13347,13348,13349,13350,13351,
93746 13352,13353,13354,13355,13356,13357,13358,13359,13360,13361,13362,13363,
93747 13364,13365,13366,13367,13368,13369,13370,13371,13372,13373,13374,13375,
93748 13376,13377,13378,13379,13380,13381,13382,13383,13384,13385,13386,13387,
93749 13388,13389,13390,13391,13392,13393,13394,13395,13396,13397,13398,13399,
93750 13400,13401,13402,13403,13404,13405,13406,13407,13408,13409,13410,13411,
93751 13412,13413,13414,13415,13416,13417,13418,13419,13420,13421,13422,13423,
93752 13424,13425,13426,13427,13428,13429,13430,13431,13432,13433,13434,13435,
93753 13436,13437,13438,13439,13440,13441,13442,13443,13444,13445,13446,13447,
93754 13448,13449,13450,13451,13452,13453,13454,13455,13456,13457,13458,13459,
93755 13460,13461,13462,13463,13464,13465,13466,13467,13468,13469,13470,13471,
93756 13472,13473,13474,13475,13476,13477,13478,13479,13480,13481,13482,13483,
93757 13484,13485,13486,13487,13488,13489,13490,13491,13492,13493,13494,13495,
93758 13496,13497,13498,13499,13500,13501,13502,13503,13504,13505,13506,13507,
93759 13508,13509,13510,13511,13512,13513,13514,13515,13516,13517,13518,13519,
93760 13520,13521,13522,13523,13524,13525,13526,13527,13528,13529,13530,13531,
93761 13532,13533,13534,13535,13536,13537,13538,13539,13540,13541,13542,13543,
93762 13544,13545,13546,13547,13548,13549,13550,13551,13552,13553,13554,13555,
93763 13556,13557,13558,13559,13560,13561,13562,13563,13564,13565,13566,13567,
93764 13568,13569,13570,13571,13572,13573,13574,13575,13576,13577,13578,13579,
93765 13580,13581,13582,13583,13584,13585,13586,13587,13588,13589,13590,13591,
93766 13592,13593,13594,13595,13596,13597,13598,13599,13600,13601,13602,13603,
93767 13604,13605,13606,13607,13608,13609,13610,13611,13612,13613,13614,13615,
93768 13616,13617,13618,13619,13620,13621,13622,13623,13624,13625,13626,13627,
93769 13628,13629,13630,13631,13632,13633,13634,13635,13636,13637,13638,13639,
93770 13640,13641,13642,13643,13644,13645,13646,13647,13648,13649,13650,13651,
93771 13652,13653,13654,13655,13656,13657,13658,13659,13660,13661,13662,13663,
93772 13664,13665,13666,13667,13668,13669,13670,13671,13672,13673,13674,13675,
93773 13676,13677,13678,13679,13680,13681,13682,13683,13684,13685,13686,13687,
93774 13688,13689,13690,13691,13692,13693,13694,13695,13696,13697,13698,13699,
93775 13700,13701,13702,13703,13704,13705,13706,13707,13708,13709,13710,13711,
93776 13712,13713,13714,13715,13716,13717,13718,13719,13720,13721,13722,13723,
93777 13724,13725,13726,13727,13728,13729,13730,13731,13732,13733,13734,13735,
93778 13736,13737,13738,13739,13740,13741,13742,13743,13744,13745,13746,13747,
93779 13748,13749,13750,13751,13752,13753,13754,13755,13756,13757,13758,13759,
93780 13760,13761,13762,13763,13764,13765,13766,13767,13768,13769,13770,13771,
93781 13772,13773,13774,13775,13776,13777,13778,13779,13780,13781,13782,13783,
93782 13784,13785,13786,13787,13788,13789,13790,13791,13792,13793,13794,13795,
93783 13796,13797,13798,13799,13800,13801,13802,13803,13804,13805,13806,13807,
93784 13808,13809,13810,13811,13812,13813,13814,13815,13816,13817,13818,13819,
93785 13820,13821,13822,13823,13824,13825,13826,13827,13828,13829,13830,13831,
93786 13832,13833,13834,13835,13836,13837,13838,13839,13840,13841,13842,13843,
93787 13844,13845,13846,13847,13848,13849,13850,13851,13852,13853,13854,13855,
93788 13856,13857,13858,13859,13860,13861,13862,13863,13864,13865,13866,13867,
93789 13868,13869,13870,13871,13872,13873,13874,13875,13876,13877,13878,13879,
93790 13880,13881,13882,13883,13884,13885,13886,13887,13888,13889,13890,13891,
93791 13892,13893,13894,13895,13896,13897,13898,13899,13900,13901,13902,13903,
93792 13904,13905,13906,13907,13908,13909,13910,13911,13912,13913,13914,13915,
93793 13916,13917,13918,13919,13920,13921,13922,13923,13924,13925,13926,13927,
93794 13928,13929,13930,13931,13932,13933,13934,13935,13936,13937,13938,13939,
93795 13940,13941,13942,13943,13944,13945,13946,13947,13948,13949,13950,13951,
93796 13952,13953,13954,13955,13956,13957,13958,13959,13960,13961,13962,13963,
93797 13964,13965,13966,13967,13968,13969,13970,13971,13972,13973,13974,13975,
93798 13976,13977,13978,13979,13980,13981,13982,13983,13984,13985,13986,13987,
93799 13988,13989,13990,13991,13992,13993,13994,13995,13996,13997,13998,13999,
93800 14000,14001,14002,14003,14004,14005,14006,14007,14008,14009,14010,14011,
93801 14012,14013,14014,14015,14016,14017,14018,14019,14020,14021,14022,14023,
93802 14024,14025,14026,14027,14028,14029,14030,14031,14032,14033,14034,14035,
93803 14036,14037,14038,14039,14040,14041,14042,14043,14044,14045,14046,14047,
93804 14048,14049,14050,14051,14052,14053,14054,14055,14056,14057,14058,14059,
93805 14060,14061,14062,14063,14064,14065,14066,14067,14068,14069,14070,14071,
93806 14072,14073,14074,14075,14076,14077,14078,14079,14080,14081,14082,14083,
93807 14084,14085,14086,14087,14088,14089,14090,14091,14092,14093,14094,14095,
93808 14096,14097,14098,14099,14100,14101,14102,14103,14104,14105,14106,14107,
93809 14108,14109,14110,14111,14112,14113,14114,14115,14116,14117,14118,14119,
93810 14120,14121,14122,14123,14124,14125,14126,14127,14128,14129,14130,14131,
93811 14132,14133,14134,14135,14136,14137,14138,14139,14140,14141,14142,14143,
93812 14144,14145,14146,14147,14148,14149,14150,14151,14152,14153,14154,14155,
93813 14156,14157,14158,14159,14160,14161,14162,14163,14164,14165,14166,14167,
93814 14168,14169,14170,14171,14172,14173,14174,14175,14176,14177,14178,14179,
93815 14180,14181,14182,14183,14184,14185,14186,14187,14188,14189,14190,14191,
93816 14192,14193,14194,14195,14196,14197,14198,14199,14200,14201,14202,14203,
93817 14204,14205,14206,14207,14208,14209,14210,14211,14212,14213,14214,14215,
93818 14216,14217,14218,14219,14220,14221,14222,14223,14224,14225,14226,14227,
93819 14228,14229,14230,14231,14232,14233,14234,14235,14236,14237,14238,14239,
93820 14240,14241,14242,14243,14244,14245,14246,14247,14248,14249,14250,14251,
93821 14252,14253,14254,14255,14256,14257,14258,14259,14260,14261,14262,14263,
93822 14264,14265,14266,14267,14268,14269,14270,14271,14272,14273,14274,14275,
93823 14276,14277,14278,14279,14280,14281,14282,14283,14284,14285,14286,14287,
93824 14288,14289,14290,14291,14292,14293,14294,14295,14296,14297,14298,14299,
93825 14300,14301,14302,14303,14304,14305,14306,14307,14308,14309,14310,14311,
93826 14312,14313,14314,14315,14316,14317,14318,14319,14320,14321,14322,14323,
93827 14324,14325,14326,14327,14328,14329,14330,14331,14332,14333,14334,14335,
93828 14336,14337,14338,14339,14340,14341,14342,14343,14344,14345,14346,14347,
93829 14348,14349,14350,14351,14352,14353,14354,14355,14356,14357,14358,14359,
93830 14360,14361,14362,14363,14364,14365,14366,14367,14368,14369,14370,14371,
93831 14372,14373,14374,14375,14376,14377,14378,14379,14380,14381,14382,14383,
93832 14384,14385,14386,14387,14388,14389,14390,14391,14392,14393,14394,14395,
93833 14396,14397,14398,14399,14400,14401,14402,14403,14404,14405,14406,14407,
93834 14408,14409,14410,14411,14412,14413,14414,14415,14416,14417,14418,14419,
93835 14420,14421,14422,14423,14424,14425,14426,14427,14428,14429,14430,14431,
93836 14432,14433,14434,14435,14436,14437,14438,14439,14440,14441,14442,14443,
93837 14444,14445,14446,14447,14448,14449,14450,14451,14452,14453,14454,14455,
93838 14456,14457,14458,14459,14460,14461,14462,14463,14464,14465,14466,14467,
93839 14468,14469,14470,14471,14472,14473,14474,14475,14476,14477,14478,14479,
93840 14480,14481,14482,14483,14484,14485,14486,14487,14488,14489,14490,14491,
93841 14492,14493,14494,14495,14496,14497,14498,14499,14500,14501,14502,14503,
93842 14504,14505,14506,14507,14508,14509,14510,14511,14512,14513,14514,14515,
93843 14516,14517,14518,14519,14520,14521,14522,14523,14524,14525,14526,14527,
93844 14528,14529,14530,14531,14532,14533,14534,14535,14536,14537,14538,14539,
93845 14540,14541,14542,14543,14544,14545,14546,14547,14548,14549,14550,14551,
93846 14552,14553,14554,14555,14556,14557,14558,14559,14560,14561,14562,14563,
93847 14564,14565,14566,14567,14568,14569,14570,14571,14572,14573,14574,14575,
93848 14576,14577,14578,14579,14580,14581,14582,14583,14584,14585,14586,14587,
93849 14588,14589,14590,14591,14592,14593,14594,14595,14596,14597,14598,14599,
93850 14600,14601,14602,14603,14604,14605,14606,14607,14608,14609,14610,14611,
93851 14612,14613,14614,14615,14616,14617,14618,14619,14620,14621,14622,14623,
93852 14624,14625,14626,14627,14628,14629,14630,14631,14632,14633,14634,14635,
93853 14636,14637,14638,14639,14640,14641,14642,14643,14644,14645,14646,14647,
93854 14648,14649,14650,14651,14652,14653,14654,14655,14656,14657,14658,14659,
93855 14660,14661,14662,14663,14664,14665,14666,14667,14668,14669,14670,14671,
93856 14672,14673,14674,14675,14676,14677,14678,14679,14680,14681,14682,14683,
93857 14684,14685,14686,14687,14688,14689,14690,14691,14692,14693,14694,14695,
93858 14696,14697,14698,14699,14700,14701,14702,14703,14704,14705,14706,14707,
93859 14708,14709,14710,14711,14712,14713,14714,14715,14716,14717,14718,14719,
93860 14720,14721,14722,14723,14724,14725,14726,14727,14728,14729,14730,14731,
93861 14732,14733,14734,14735,14736,14737,14738,14739,14740,14741,14742,14743,
93862 14744,14745,14746,14747,14748,14749,14750,14751,14752,14753,14754,14755,
93863 14756,14757,14758,14759,14760,14761,14762,14763,14764,14765,14766,14767,
93864 14768,14769,14770,14771,14772,14773,14774,14775,14776,14777,14778,14779,
93865 14780,14781,14782,14783,14784,14785,14786,14787,14788,14789,14790,14791,
93866 14792,14793,14794,14795,14796,14797,14798,14799,14800,14801,14802,14803,
93867 14804,14805,14806,14807,14808,14809,14810,14811,14812,14813,14814,14815,
93868 14816,14817,14818,14819,14820,14821,14822,14823,14824,14825,14826,14827,
93869 14828,14829,14830,14831,14832,14833,14834,14835,14836,14837,14838,14839,
93870 14840,14841,14842,14843,14844,14845,14846,14847,14848,14849,14850,14851,
93871 14852,14853,14854,14855,14856,14857,14858,14859,14860,14861,14862,14863,
93872 14864,14865,14866,14867,14868,14869,14870,14871,14872,14873,14874,14875,
93873 14876,14877,14878,14879,14880,14881,14882,14883,14884,14885,14886,14887,
93874 14888,14889,14890,14891,14892,14893,14894,14895,14896,14897,14898,14899,
93875 14900,14901,14902,14903,14904,14905,14906,14907,14908,14909,14910,14911,
93876 14912,14913,14914,14915,14916,14917,14918,14919,14920,14921,14922,14923,
93877 14924,14925,14926,14927,14928,14929,14930,14931,14932,14933,14934,14935,
93878 14936,14937,14938,14939,14940,14941,14942,14943,14944,14945,14946,14947,
93879 14948,14949,14950,14951,14952,14953,14954,14955,14956,14957,14958,14959,
93880 14960,14961,14962,14963,14964,14965,14966,14967,14968,14969,14970,14971,
93881 14972,14973,14974,14975,14976,14977,14978,14979,14980,14981,14982,14983,
93882 14984,14985,14986,14987,14988,14989,14990,14991,14992,14993,14994,14995,
93883 14996,14997,14998,14999,15000,15001,15002,15003,15004,15005,15006,15007,
93884 15008,15009,15010,15011,15012,15013,15014,15015,15016,15017,15018,15019,
93885 15020,15021,15022,15023,15024,15025,15026,15027,15028,15029,15030,15031,
93886 15032,15033,15034,15035,15036,15037,15038,15039,15040,15041,15042,15043,
93887 15044,15045,15046,15047,15048,15049,15050,15051,15052,15053,15054,15055,
93888 15056,15057,15058,15059,15060,15061,15062,15063,15064,15065,15066,15067,
93889 15068,15069,15070,15071,15072,15073,15074,15075,15076,15077,15078,15079,
93890 15080,15081,15082,15083,15084,15085,15086,15087,15088,15089,15090,15091,
93891 15092,15093,15094,15095,15096,15097,15098,15099,15100,15101,15102,15103,
93892 15104,15105,15106,15107,15108,15109,15110,15111,15112,15113,15114,15115,
93893 15116,15117,15118,15119,15120,15121,15122,15123,15124,15125,15126,15127,
93894 15128,15129,15130,15131,15132,15133,15134,15135,15136,15137,15138,15139,
93895 15140,15141,15142,15143,15144,15145,15146,15147,15148,15149,15150,15151,
93896 15152,15153,15154,15155,15156,15157,15158,15159,15160,15161,15162,15163,
93897 15164,15165,15166,15167,15168,15169,15170,15171,15172,15173,15174,15175,
93898 15176,15177,15178,15179,15180,15181,15182,15183,15184,15185,15186,15187,
93899 15188,15189,15190,15191,15192,15193,15194,15195,15196,15197,15198,15199,
93900 15200,15201,15202,15203,15204,15205,15206,15207,15208,15209,15210,15211,
93901 15212,15213,15214,15215,15216,15217,15218,15219,15220,15221,15222,15223,
93902 15224,15225,15226,15227,15228,15229,15230,15231,15232,15233,15234,15235,
93903 15236,15237,15238,15239,15240,15241,15242,15243,15244,15245,15246,15247,
93904 15248,15249,15250,15251,15252,15253,15254,15255,15256,15257,15258,15259,
93905 15260,15261,15262,15263,15264,15265,15266,15267,15268,15269,15270,15271,
93906 15272,15273,15274,15275,15276,15277,15278,15279,15280,15281,15282,15283,
93907 15284,15285,15286,15287,15288,15289,15290,15291,15292,15293,15294,15295,
93908 15296,15297,15298,15299,15300,15301,15302,15303,15304,15305,15306,15307,
93909 15308,15309,15310,15311,15312,15313,15314,15315,15316,15317,15318,15319,
93910 15320,15321,15322,15323,15324,15325,15326,15327,15328,15329,15330,15331,
93911 15332,15333,15334,15335,15336,15337,15338,15339,15340,15341,15342,15343,
93912 15344,15345,15346,15347,15348,15349,15350,15351,15352,15353,15354,15355,
93913 15356,15357,15358,15359,15360,15361,15362,15363,15364,15365,15366,15367,
93914 15368,15369,15370,15371,15372,15373,15374,15375,15376,15377,15378,15379,
93915 15380,15381,15382,15383,15384,15385,15386,15387,15388,15389,15390,15391,
93916 15392,15393,15394,15395,15396,15397,15398,15399,15400,15401,15402,15403,
93917 15404,15405,15406,15407,15408,15409,15410,15411,15412,15413,15414,15415,
93918 15416,15417,15418,15419,15420,15421,15422,15423,15424,15425,15426,15427,
93919 15428,15429,15430,15431,15432,15433,15434,15435,15436,15437,15438,15439,
93920 15440,15441,15442,15443,15444,15445,15446,15447,15448,15449,15450,15451,
93921 15452,15453,15454,15455,15456,15457,15458,15459,15460,15461,15462,15463,
93922 15464,15465,15466,15467,15468,15469,15470,15471,15472,15473,15474,15475,
93923 15476,15477,15478,15479,15480,15481,15482,15483,15484,15485,15486,15487,
93924 15488,15489,15490,15491,15492,15493,15494,15495,15496,15497,15498,15499,
93925 15500,15501,15502,15503,15504,15505,15506,15507,15508,15509,15510,15511,
93926 15512,15513,15514,15515,15516,15517,15518,15519,15520,15521,15522,15523,
93927 15524,15525,15526,15527,15528,15529,15530,15531,15532,15533,15534,15535,
93928 15536,15537,15538,15539,15540,15541,15542,15543,15544,15545,15546,15547,
93929 15548,15549,15550,15551,15552,15553,15554,15555,15556,15557,15558,15559,
93930 15560,15561,15562,15563,15564,15565,15566,15567,15568,15569,15570,15571,
93931 15572,15573,15574,15575,15576,15577,15578,15579,15580,15581,15582,15583,
93932 15584,15585,15586,15587,15588,15589,15590,15591,15592,15593,15594,15595,
93933 15596,15597,15598,15599,15600,15601,15602,15603,15604,15605,15606,15607,
93934 15608,15609,15610,15611,15612,15613,15614,15615,15616,15617,15618,15619,
93935 15620,15621,15622,15623,15624,15625,15626,15627,15628,15629,15630,15631,
93936 15632,15633,15634,15635,15636,15637,15638,15639,15640,15641,15642,15643,
93937 15644,15645,15646,15647,15648,15649,15650,15651,15652,15653,15654,15655,
93938 15656,15657,15658,15659,15660,15661,15662,15663,15664,15665,15666,15667,
93939 15668,15669,15670,15671,15672,15673,15674,15675,15676,15677,15678,15679,
93940 15680,15681,15682,15683,15684,15685,15686,15687,15688,15689,15690,15691,
93941 15692,15693,15694,15695,15696,15697,15698,15699,15700,15701,15702,15703,
93942 15704,15705,15706,15707,15708,15709,15710,15711,15712,15713,15714,15715,
93943 15716,15717,15718,15719,15720,15721,15722,15723,15724,15725,15726,15727,
93944 15728,15729,15730,15731,15732,15733,15734,15735,15736,15737,15738,15739,
93945 15740,15741,15742,15743,15744,15745,15746,15747,15748,15749,15750,15751,
93946 15752,15753,15754,15755,15756,15757,15758,15759,15760,15761,15762,15763,
93947 15764,15765,15766,15767,15768,15769,15770,15771,15772,15773,15774,15775,
93948 15776,15777,15778,15779,15780,15781,15782,15783,15784,15785,15786,15787,
93949 15788,15789,15790,15791,15792,15793,15794,15795,15796,15797,15798,15799,
93950 15800,15801,15802,15803,15804,15805,15806,15807,15808,15809,15810,15811,
93951 15812,15813,15814,15815,15816,15817,15818,15819,15820,15821,15822,15823,
93952 15824,15825,15826,15827,15828,15829,15830,15831,15832,15833,15834,15835,
93953 15836,15837,15838,15839,15840,15841,15842,15843,15844,15845,15846,15847,
93954 15848,15849,15850,15851,15852,15853,15854,15855,15856,15857,15858,15859,
93955 15860,15861,15862,15863,15864,15865,15866,15867,15868,15869,15870,15871,
93956 15872,15873,15874,15875,15876,15877,15878,15879,15880,15881,15882,15883,
93957 15884,15885,15886,15887,15888,15889,15890,15891,15892,15893,15894,15895,
93958 15896,15897,15898,15899,15900,15901,15902,15903,15904,15905,15906,15907,
93959 15908,15909,15910,15911,15912,15913,15914,15915,15916,15917,15918,15919,
93960 15920,15921,15922,15923,15924,15925,15926,15927,15928,15929,15930,15931,
93961 15932,15933,15934,15935,15936,15937,15938,15939,15940,15941,15942,15943,
93962 15944,15945,15946,15947,15948,15949,15950,15951,15952,15953,15954,15955,
93963 15956,15957,15958,15959,15960,15961,15962,15963,15964,15965,15966,15967,
93964 15968,15969,15970,15971,15972,15973,15974,15975,15976,15977,15978,15979,
93965 15980,15981,15982,15983,15984,15985,15986,15987,15988,15989,15990,15991,
93966 15992,15993,15994,15995,15996,15997,15998,15999,16000,16001,16002,16003,
93967 16004,16005,16006,16007,16008,16009,16010,16011,16012,16013,16014,16015,
93968 16016,16017,16018,16019,16020,16021,16022,16023,16024,16025,16026,16027,
93969 16028,16029,16030,16031,16032,16033,16034,16035,16036,16037,16038,16039,
93970 16040,16041,16042,16043,16044,16045,16046,16047,16048,16049,16050,16051,
93971 16052,16053,16054,16055,16056,16057,16058,16059,16060,16061,16062,16063,
93972 16064,16065,16066,16067,16068,16069,16070,16071,16072,16073,16074,16075,
93973 16076,16077,16078,16079,16080,16081,16082,16083,16084,16085,16086,16087,
93974 16088,16089,16090,16091,16092,16093,16094,16095,16096,16097,16098,16099,
93975 16100,16101,16102,16103,16104,16105,16106,16107,16108,16109,16110,16111,
93976 16112,16113,16114,16115,16116,16117,16118,16119,16120,16121,16122,16123,
93977 16124,16125,16126,16127,16128,16129,16130,16131,16132,16133,16134,16135,
93978 16136,16137,16138,16139,16140,16141,16142,16143,16144,16145,16146,16147,
93979 16148,16149,16150,16151,16152,16153,16154,16155,16156,16157,16158,16159,
93980 16160,16161,16162,16163,16164,16165,16166,16167,16168,16169,16170,16171,
93981 16172,16173,16174,16175,16176,16177,16178,16179,16180,16181,16182,16183,
93982 16184,16185,16186,16187,16188,16189,16190,16191,16192,16193,16194,16195,
93983 16196,16197,16198,16199,16200,16201,16202,16203,16204,16205,16206,16207,
93984 16208,16209,16210,16211,16212,16213,16214,16215,16216,16217,16218,16219,
93985 16220,16221,16222,16223,16224,16225,16226,16227,16228,16229,16230,16231,
93986 16232,16233,16234,16235,16236,16237,16238,16239,16240,16241,16242,16243,
93987 16244,16245,16246,16247,16248,16249,16250,16251,16252,16253,16254,16255,
93988 16256,16257,16258,16259,16260,16261,16262,16263,16264,16265,16266,16267,
93989 16268,16269,16270,16271,16272,16273,16274,16275,16276,16277,16278,16279,
93990 16280,16281,16282,16283,16284,16285,16286,16287,16288,16289,16290,16291,
93991 16292,16293,16294,16295,16296,16297,16298,16299,16300,16301,16302,16303,
93992 16304,16305,16306,16307,16308,16309,16310,16311,16312,16313,16314,16315,
93993 16316,16317,16318,16319,16320,16321,16322,16323,16324,16325,16326,16327,
93994 16328,16329,16330,16331,16332,16333,16334,16335,16336,16337,16338,16339,
93995 16340,16341,16342,16343,16344,16345,16346,16347,16348,16349,16350,16351,
93996 16352,16353,16354,16355,16356,16357,16358,16359,16360,16361,16362,16363,
93997 16364,16365,16366,16367,16368,16369,16370,16371,16372,16373,16374,16375,
93998 16376,16377,16378,16379,16380,16381,16382,16383,16384,16385,16386,16387,
93999 16388,16389,16390,16391,16392,16393,16394,16395,16396,16397,16398,16399,
94000 16400,16401,16402,16403,16404,16405,16406,16407,16408,16409,16410,16411,
94001 16412,16413,16414,16415,16416,16417,16418,16419,16420,16421,16422,16423,
94002 16424,16425,16426,16427,16428,16429,16430,16431,16432,16433,16434,16435,
94003 16436,16437,16438,16439,16440,16441,16442,16443,16444,16445,16446,16447,
94004 16448,16449,16450,16451,16452,16453,16454,16455,16456,16457,16458,16459,
94005 16460,16461,16462,16463,16464,16465,16466,16467,16468,16469,16470,16471,
94006 16472,16473,16474,16475,16476,16477,16478,16479,16480,16481,16482,16483,
94007 16484,16485,16486,16487,16488,16489,16490,16491,16492,16493,16494,16495,
94008 16496,16497,16498,16499,16500,16501,16502,16503,16504,16505,16506,16507,
94009 16508,16509,16510,16511,16512,16513,16514,16515,16516,16517,16518,16519,
94010 16520,16521,16522,16523,16524,16525,16526,16527,16528,16529,16530,16531,
94011 16532,16533,16534,16535,16536,16537,16538,16539,16540,16541,16542,16543,
94012 16544,16545,16546,16547,16548,16549,16550,16551,16552,16553,16554,16555,
94013 16556,16557,16558,16559,16560,16561,16562,16563,16564,16565,16566,16567,
94014 16568,16569,16570,16571,16572,16573,16574,16575,16576,16577,16578,16579,
94015 16580,16581,16582,16583,16584,16585,16586,16587,16588,16589,16590,16591,
94016 16592,16593,16594,16595,16596,16597,16598,16599,16600,16601,16602,16603,
94017 16604,16605,16606,16607,16608,16609,16610,16611,16612,16613,16614,16615,
94018 16616,16617,16618,16619,16620,16621,16622,16623,16624,16625,16626,16627,
94019 16628,16629,16630,16631,16632,16633,16634,16635,16636,16637,16638,16639,
94020 16640,16641,16642,16643,16644,16645,16646,16647,16648,16649,16650,16651,
94021 16652,16653,16654,16655,16656,16657,16658,16659,16660,16661,16662,16663,
94022 16664,16665,16666,16667,16668,16669,16670,16671,16672,16673,16674,16675,
94023 16676,16677,16678,16679,16680,16681,16682,16683,16684,16685,16686,16687,
94024 16688,16689,16690,16691,16692,16693,16694,16695,16696,16697,16698,16699,
94025 16700,16701,16702,16703,16704,16705,16706,16707,16708,16709,16710,16711,
94026 16712,16713,16714,16715,16716,16717,16718,16719,16720,16721,16722,16723,
94027 16724,16725,16726,16727,16728,16729,16730,16731,16732,16733,16734,16735,
94028 16736,16737,16738,16739,16740,16741,16742,16743,16744,16745,16746,16747,
94029 16748,16749,16750,16751,16752,16753,16754,16755,16756,16757,16758,16759,
94030 16760,16761,16762,16763,16764,16765,16766,16767,16768,16769,16770,16771,
94031 16772,16773,16774,16775,16776,16777,16778,16779,16780,16781,16782,16783,
94032 16784,16785,16786,16787,16788,16789,16790,16791,16792,16793,16794,16795,
94033 16796,16797,16798,16799,16800,16801,16802,16803,16804,16805,16806,16807,
94034 16808,16809,16810,16811,16812,16813,16814,16815,16816,16817,16818,16819,
94035 16820,16821,16822,16823,16824,16825,16826,16827,16828,16829,16830,16831,
94036 16832,16833,16834,16835,16836,16837,16838,16839,16840,16841,16842,16843,
94037 16844,16845,16846,16847,16848,16849,16850,16851,16852,16853,16854,16855,
94038 16856,16857,16858,16859,16860,16861,16862,16863,16864,16865,16866,16867,
94039 16868,16869,16870,16871,16872,16873,16874,16875,16876,16877,16878,16879,
94040 16880,16881,16882,16883,16884,16885,16886,16887,16888,16889,16890,16891,
94041 16892,16893,16894,16895,16896,16897,16898,16899,16900,16901,16902,16903,
94042 16904,16905,16906,16907,16908,16909,16910,16911,16912,16913,16914,16915,
94043 16916,16917,16918,16919,16920,16921,16922,16923,16924,16925,16926,16927,
94044 16928,16929,16930,16931,16932,16933,16934,16935,16936,16937,16938,16939,
94045 16940,16941,16942,16943,16944,16945,16946,16947,16948,16949,16950,16951,
94046 16952,16953,16954,16955,16956,16957,16958,16959,16960,16961,16962,16963,
94047 16964,16965,16966,16967,16968,16969,16970,16971,16972,16973,16974,16975,
94048 16976,16977,16978,16979,16980,16981,16982,16983,16984,16985,16986,16987,
94049 16988,16989,16990,16991,16992,16993,16994,16995,16996,16997,16998,16999,
94050 17000,17001,17002,17003,17004,17005,17006,17007,17008,17009,17010,17011,
94051 17012,17013,17014,17015,17016,17017,17018,17019,17020,17021,17022,17023,
94052 17024,17025,17026,17027,17028,17029,17030,17031,17032,17033,17034,17035,
94053 17036,17037,17038,17039,17040,17041,17042,17043,17044,17045,17046,17047,
94054 17048,17049,17050,17051,17052,17053,17054,17055,17056,17057,17058,17059,
94055 17060,17061,17062,17063,17064,17065,17066,17067,17068,17069,17070,17071,
94056 17072,17073,17074,17075,17076,17077,17078,17079,17080,17081,17082,17083,
94057 17084,17085,17086,17087,17088,17089,17090,17091,17092,17093,17094,17095,
94058 17096,17097,17098,17099,17100,17101,17102,17103,17104,17105,17106,17107,
94059 17108,17109,17110,17111,17112,17113,17114,17115,17116,17117,17118,17119,
94060 17120,17121,17122,17123,17124,17125,17126,17127,17128,17129,17130,17131,
94061 17132,17133,17134,17135,17136,17137,17138,17139,17140,17141,17142,17143,
94062 17144,17145,17146,17147,17148,17149,17150,17151,17152,17153,17154,17155,
94063 17156,17157,17158,17159,17160,17161,17162,17163,17164,17165,17166,17167,
94064 17168,17169,17170,17171,17172,17173,17174,17175,17176,17177,17178,17179,
94065 17180,17181,17182,17183,17184,17185,17186,17187,17188,17189,17190,17191,
94066 17192,17193,17194,17195,17196,17197,17198,17199,17200,17201,17202,17203,
94067 17204,17205,17206,17207,17208,17209,17210,17211,17212,17213,17214,17215,
94068 17216,17217,17218,17219,17220,17221,17222,17223,17224,17225,17226,17227,
94069 17228,17229,17230,17231,17232,17233,17234,17235,17236,17237,17238,17239,
94070 17240,17241,17242,17243,17244,17245,17246,17247,17248,17249,17250,17251,
94071 17252,17253,17254,17255,17256,17257,17258,17259,17260,17261,17262,17263,
94072 17264,17265,17266,17267,17268,17269,17270,17271,17272,17273,17274,17275,
94073 17276,17277,17278,17279,17280,17281,17282,17283,17284,17285,17286,17287,
94074 17288,17289,17290,17291,17292,17293,17294,17295,17296,17297,17298,17299,
94075 17300,17301,17302,17303,17304,17305,17306,17307,17308,17309,17310,17311,
94076 17312,17313,17314,17315,17316,17317,17318,17319,17320,17321,17322,17323,
94077 17324,17325,17326,17327,17328,17329,17330,17331,17332,17333,17334,17335,
94078 17336,17337,17338,17339,17340,17341,17342,17343,17344,17345,17346,17347,
94079 17348,17349,17350,17351,17352,17353,17354,17355,17356,17357,17358,17359,
94080 17360,17361,17362,17363,17364,17365,17366,17367,17368,17369,17370,17371,
94081 17372,17373,17374,17375,17376,17377,17378,17379,17380,17381,17382,17383,
94082 17384,17385,17386,17387,17388,17389,17390,17391,17392,17393,17394,17395,
94083 17396,17397,17398,17399,17400,17401,17402,17403,17404,17405,17406,17407,
94084 17408,17409,17410,17411,17412,17413,17414,17415,17416,17417,17418,17419,
94085 17420,17421,17422,17423,17424,17425,17426,17427,17428,17429,17430,17431,
94086 17432,17433,17434,17435,17436,17437,17438,17439,17440,17441,17442,17443,
94087 17444,17445,17446,17447,17448,17449,17450,17451,17452,17453,17454,17455,
94088 17456,17457,17458,17459,17460,17461,17462,17463,17464,17465,17466,17467,
94089 17468,17469,17470,17471,17472,17473,17474,17475,17476,17477,17478,17479,
94090 17480,17481,17482,17483,17484,17485,17486,17487,17488,17489,17490,17491,
94091 17492,17493,17494,17495,17496,17497,17498,17499,17500,17501,17502,17503,
94092 17504,17505,17506,17507,17508,17509,17510,17511,17512,17513,17514,17515,
94093 17516,17517,17518,17519,17520,17521,17522,17523,17524,17525,17526,17527,
94094 17528,17529,17530,17531,17532,17533,17534,17535,17536,17537,17538,17539,
94095 17540,17541,17542,17543,17544,17545,17546,17547,17548,17549,17550,17551,
94096 17552,17553,17554,17555,17556,17557,17558,17559,17560,17561,17562,17563,
94097 17564,17565,17566,17567,17568,17569,17570,17571,17572,17573,17574,17575,
94098 17576,17577,17578,17579,17580,17581,17582,17583,17584,17585,17586,17587,
94099 17588,17589,17590,17591,17592,17593,17594,17595,17596,17597,17598,17599,
94100 17600,17601,17602,17603,17604,17605,17606,17607,17608,17609,17610,17611,
94101 17612,17613,17614,17615,17616,17617,17618,17619,17620,17621,17622,17623,
94102 17624,17625,17626,17627,17628,17629,17630,17631,17632,17633,17634,17635,
94103 17636,17637,17638,17639,17640,17641,17642,17643,17644,17645,17646,17647,
94104 17648,17649,17650,17651,17652,17653,17654,17655,17656,17657,17658,17659,
94105 17660,17661,17662,17663,17664,17665,17666,17667,17668,17669,17670,17671,
94106 17672,17673,17674,17675,17676,17677,17678,17679,17680,17681,17682,17683,
94107 17684,17685,17686,17687,17688,17689,17690,17691,17692,17693,17694,17695,
94108 17696,17697,17698,17699,17700,17701,17702,17703,17704,17705,17706,17707,
94109 17708,17709,17710,17711,17712,17713,17714,17715,17716,17717,17718,17719,
94110 17720,17721,17722,17723,17724,17725,17726,17727,17728,17729,17730,17731,
94111 17732,17733,17734,17735,17736,17737,17738,17739,17740,17741,17742,17743,
94112 17744,17745,17746,17747,17748,17749,17750,17751,17752,17753,17754,17755,
94113 17756,17757,17758,17759,17760,17761,17762,17763,17764,17765,17766,17767,
94114 17768,17769,17770,17771,17772,17773,17774,17775,17776,17777,17778,17779,
94115 17780,17781,17782,17783,17784,17785,17786,17787,17788,17789,17790,17791,
94116 17792,17793,17794,17795,17796,17797,17798,17799,17800,17801,17802,17803,
94117 17804,17805,17806,17807,17808,17809,17810,17811,17812,17813,17814,17815,
94118 17816,17817,17818,17819,17820,17821,17822,17823,17824,17825,17826,17827,
94119 17828,17829,17830,17831,17832,17833,17834,17835,17836,17837,17838,17839,
94120 17840,17841,17842,17843,17844,17845,17846,17847,17848,17849,17850,17851,
94121 17852,17853,17854,17855,17856,17857,17858,17859,17860,17861,17862,17863,
94122 17864,17865,17866,17867,17868,17869,17870,17871,17872,17873,17874,17875,
94123 17876,17877,17878,17879,17880,17881,17882,17883,17884,17885,17886,17887,
94124 17888,17889,17890,17891,17892,17893,17894,17895,17896,17897,17898,17899,
94125 17900,17901,17902,17903,17904,17905,17906,17907,17908,17909,17910,17911,
94126 17912,17913,17914,17915,17916,17917,17918,17919,17920,17921,17922,17923,
94127 17924,17925,17926,17927,17928,17929,17930,17931,17932,17933,17934,17935,
94128 17936,17937,17938,17939,17940,17941,17942,17943,17944,17945,17946,17947,
94129 17948,17949,17950,17951,17952,17953,17954,17955,17956,17957,17958,17959,
94130 17960,17961,17962,17963,17964,17965,17966,17967,17968,17969,17970,17971,
94131 17972,17973,17974,17975,17976,17977,17978,17979,17980,17981,17982,17983,
94132 17984,17985,17986,17987,17988,17989,17990,17991,17992,17993,17994,17995,
94133 17996,17997,17998,17999,18000,18001,18002,18003,18004,18005,18006,18007,
94134 18008,18009,18010,18011,18012,18013,18014,18015,18016,18017,18018,18019,
94135 18020,18021,18022,18023,18024,18025,18026,18027,18028,18029,18030,18031,
94136 18032,18033,18034,18035,18036,18037,18038,18039,18040,18041,18042,18043,
94137 18044,18045,18046,18047,18048,18049,18050,18051,18052,18053,18054,18055,
94138 18056,18057,18058,18059,18060,18061,18062,18063,18064,18065,18066,18067,
94139 18068,18069,18070,18071,18072,18073,18074,18075,18076,18077,18078,18079,
94140 18080,18081,18082,18083,18084,18085,18086,18087,18088,18089,18090,18091,
94141 18092,18093,18094,18095,18096,18097,18098,18099,18100,18101,18102,18103,
94142 18104,18105,18106,18107,18108,18109,18110,18111,18112,18113,18114,18115,
94143 18116,18117,18118,18119,18120,18121,18122,18123,18124,18125,18126,18127,
94144 18128,18129,18130,18131,18132,18133,18134,18135,18136,18137,18138,18139,
94145 18140,18141,18142,18143,18144,18145,18146,18147,18148,18149,18150,18151,
94146 18152,18153,18154,18155,18156,18157,18158,18159,18160,18161,18162,18163,
94147 18164,18165,18166,18167,18168,18169,18170,18171,18172,18173,18174,18175,
94148 18176,18177,18178,18179,18180,18181,18182,18183,18184,18185,18186,18187,
94149 18188,18189,18190,18191,18192,18193,18194,18195,18196,18197,18198,18199,
94150 18200,18201,18202,18203,18204,18205,18206,18207,18208,18209,18210,18211,
94151 18212,18213,18214,18215,18216,18217,18218,18219,18220,18221,18222,18223,
94152 18224,18225,18226,18227,18228,18229,18230,18231,18232,18233,18234,18235,
94153 18236,18237,18238,18239,18240,18241,18242,18243,18244,18245,18246,18247,
94154 18248,18249,18250,18251,18252,18253,18254,18255,18256,18257,18258,18259,
94155 18260,18261,18262,18263,18264,18265,18266,18267,18268,18269,18270,18271,
94156 18272,18273,18274,18275,18276,18277,18278,18279,18280,18281,18282,18283,
94157 18284,18285,18286,18287,18288,18289,18290,18291,18292,18293,18294,18295,
94158 18296,18297,18298,18299,18300,18301,18302,18303,18304,18305,18306,18307,
94159 18308,18309,18310,18311,18312,18313,18314,18315,18316,18317,18318,18319,
94160 18320,18321,18322,18323,18324,18325,18326,18327,18328,18329,18330,18331,
94161 18332,18333,18334,18335,18336,18337,18338,18339,18340,18341,18342,18343,
94162 18344,18345,18346,18347,18348,18349,18350,18351,18352,18353,18354,18355,
94163 18356,18357,18358,18359,18360,18361,18362,18363,18364,18365,18366,18367,
94164 18368,18369,18370,18371,18372,18373,18374,18375,18376,18377,18378,18379,
94165 18380,18381,18382,18383,18384,18385,18386,18387,18388,18389,18390,18391,
94166 18392,18393,18394,18395,18396,18397,18398,18399,18400,18401,18402,18403,
94167 18404,18405,18406,18407,18408,18409,18410,18411,18412,18413,18414,18415,
94168 18416,18417,18418,18419,18420,18421,18422,18423,18424,18425,18426,18427,
94169 18428,18429,18430,18431,18432,18433,18434,18435,18436,18437,18438,18439,
94170 18440,18441,18442,18443,18444,18445,18446,18447,18448,18449,18450,18451,
94171 18452,18453,18454,18455,18456,18457,18458,18459,18460,18461,18462,18463,
94172 18464,18465,18466,18467,18468,18469,18470,18471,18472,18473,18474,18475,
94173 18476,18477,18478,18479,18480,18481,18482,18483,18484,18485,18486,18487,
94174 18488,18489,18490,18491,18492,18493,18494,18495,18496,18497,18498,18499,
94175 18500,18501,18502,18503,18504,18505,18506,18507,18508,18509,18510,18511,
94176 18512,18513,18514,18515,18516,18517,18518,18519,18520,18521,18522,18523,
94177 18524,18525,18526,18527,18528,18529,18530,18531,18532,18533,18534,18535,
94178 18536,18537,18538,18539,18540,18541,18542,18543,18544,18545,18546,18547,
94179 18548,18549,18550,18551,18552,18553,18554,18555,18556,18557,18558,18559,
94180 18560,18561,18562,18563,18564,18565,18566,18567,18568,18569,18570,18571,
94181 18572,18573,18574,18575,18576,18577,18578,18579,18580,18581,18582,18583,
94182 18584,18585,18586,18587,18588,18589,18590,18591,18592,18593,18594,18595,
94183 18596,18597,18598,18599,18600,18601,18602,18603,18604,18605,18606,18607,
94184 18608,18609,18610,18611,18612,18613,18614,18615,18616,18617,18618,18619,
94185 18620,18621,18622,18623,18624,18625,18626,18627,18628,18629,18630,18631,
94186 18632,18633,18634,18635,18636,18637,18638,18639,18640,18641,18642,18643,
94187 18644,18645,18646,18647,18648,18649,18650,18651,18652,18653,18654,18655,
94188 18656,18657,18658,18659,18660,18661,18662,18663,18664,18665,18666,18667,
94189 18668,18669,18670,18671,18672,18673,18674,18675,18676,18677,18678,18679,
94190 18680,18681,18682,18683,18684,18685,18686,18687,18688,18689,18690,18691,
94191 18692,18693,18694,18695,18696,18697,18698,18699,18700,18701,18702,18703,
94192 18704,18705,18706,18707,18708,18709,18710,18711,18712,18713,18714,18715,
94193 18716,18717,18718,18719,18720,18721,18722,18723,18724,18725,18726,18727,
94194 18728,18729,18730,18731,18732,18733,18734,18735,18736,18737,18738,18739,
94195 18740,18741,18742,18743,18744,18745,18746,18747,18748,18749,18750,18751,
94196 18752,18753,18754,18755,18756,18757,18758,18759,18760,18761,18762,18763,
94197 18764,18765,18766,18767,18768,18769,18770,18771,18772,18773,18774,18775,
94198 18776,18777,18778,18779,18780,18781,18782,18783,18784,18785,18786,18787,
94199 18788,18789,18790,18791,18792,18793,18794,18795,18796,18797,18798,18799,
94200 18800,18801,18802,18803,18804,18805,18806,18807,18808,18809,18810,18811,
94201 18812,18813,18814,18815,18816,18817,18818,18819,18820,18821,18822,18823,
94202 18824,18825,18826,18827,18828,18829,18830,18831,18832,18833,18834,18835,
94203 18836,18837,18838,18839,18840,18841,18842,18843,18844,18845,18846,18847,
94204 18848,18849,18850,18851,18852,18853,18854,18855,18856,18857,18858,18859,
94205 18860,18861,18862,18863,18864,18865,18866,18867,18868,18869,18870,18871,
94206 18872,18873,18874,18875,18876,18877,18878,18879,18880,18881,18882,18883,
94207 18884,18885,18886,18887,18888,18889,18890,18891,18892,18893,18894,18895,
94208 18896,18897,18898,18899,18900,18901,18902,18903,18904,18905,18906,18907,
94209 18908,18909,18910,18911,18912,18913,18914,18915,18916,18917,18918,18919,
94210 18920,18921,18922,18923,18924,18925,18926,18927,18928,18929,18930,18931,
94211 18932,18933,18934,18935,18936,18937,18938,18939,18940,18941,18942,18943,
94212 18944,18945,18946,18947,18948,18949,18950,18951,18952,18953,18954,18955,
94213 18956,18957,18958,18959,18960,18961,18962,18963,18964,18965,18966,18967,
94214 18968,18969,18970,18971,18972,18973,18974,18975,18976,18977,18978,18979,
94215 18980,18981,18982,18983,18984,18985,18986,18987,18988,18989,18990,18991,
94216 18992,18993,18994,18995,18996,18997,18998,18999,19000,19001,19002,19003,
94217 19004,19005,19006,19007,19008,19009,19010,19011,19012,19013,19014,19015,
94218 19016,19017,19018,19019,19020,19021,19022,19023,19024,19025,19026,19027,
94219 19028,19029,19030,19031,19032,19033,19034,19035,19036,19037,19038,19039,
94220 19040,19041,19042,19043,19044,19045,19046,19047,19048,19049,19050,19051,
94221 19052,19053,19054,19055,19056,19057,19058,19059,19060,19061,19062,19063,
94222 19064,19065,19066,19067,19068,19069,19070,19071,19072,19073,19074,19075,
94223 19076,19077,19078,19079,19080,19081,19082,19083,19084,19085,19086,19087,
94224 19088,19089,19090,19091,19092,19093,19094,19095,19096,19097,19098,19099,
94225 19100,19101,19102,19103,19104,19105,19106,19107,19108,19109,19110,19111,
94226 19112,19113,19114,19115,19116,19117,19118,19119,19120,19121,19122,19123,
94227 19124,19125,19126,19127,19128,19129,19130,19131,19132,19133,19134,19135,
94228 19136,19137,19138,19139,19140,19141,19142,19143,19144,19145,19146,19147,
94229 19148,19149,19150,19151,19152,19153,19154,19155,19156,19157,19158,19159,
94230 19160,19161,19162,19163,19164,19165,19166,19167,19168,19169,19170,19171,
94231 19172,19173,19174,19175,19176,19177,19178,19179,19180,19181,19182,19183,
94232 19184,19185,19186,19187,19188,19189,19190,19191,19192,19193,19194,19195,
94233 19196,19197,19198,19199,19200,19201,19202,19203,19204,19205,19206,19207,
94234 19208,19209,19210,19211,19212,19213,19214,19215,19216,19217,19218,19219,
94235 19220,19221,19222,19223,19224,19225,19226,19227,19228,19229,19230,19231,
94236 19232,19233,19234,19235,19236,19237,19238,19239,19240,19241,19242,19243,
94237 19244,19245,19246,19247,19248,19249,19250,19251,19252,19253,19254,19255,
94238 19256,19257,19258,19259,19260,19261,19262,19263,19264,19265,19266,19267,
94239 19268,19269,19270,19271,19272,19273,19274,19275,19276,19277,19278,19279,
94240 19280,19281,19282,19283,19284,19285,19286,19287,19288,19289,19290,19291,
94241 19292,19293,19294,19295,19296,19297,19298,19299,19300,19301,19302,19303,
94242 19304,19305,19306,19307,19308,19309,19310,19311,19312,19313,19314,19315,
94243 19316,19317,19318,19319,19320,19321,19322,19323,19324,19325,19326,19327,
94244 19328,19329,19330,19331,19332,19333,19334,19335,19336,19337,19338,19339,
94245 19340,19341,19342,19343,19344,19345,19346,19347,19348,19349,19350,19351,
94246 19352,19353,19354,19355,19356,19357,19358,19359,19360,19361,19362,19363,
94247 19364,19365,19366,19367,19368,19369,19370,19371,19372,19373,19374,19375,
94248 19376,19377,19378,19379,19380,19381,19382,19383,19384,19385,19386,19387,
94249 19388,19389,19390,19391,19392,19393,19394,19395,19396,19397,19398,19399,
94250 19400,19401,19402,19403,19404,19405,19406,19407,19408,19409,19410,19411,
94251 19412,19413,19414,19415,19416,19417,19418,19419,19420,19421,19422,19423,
94252 19424,19425,19426,19427,19428,19429,19430,19431,19432,19433,19434,19435,
94253 19436,19437,19438,19439,19440,19441,19442,19443,19444,19445,19446,19447,
94254 19448,19449,19450,19451,19452,19453,19454,19455,19456,19457,19458,19459,
94255 19460,19461,19462,19463,19464,19465,19466,19467,19468,19469,19470,19471,
94256 19472,19473,19474,19475,19476,19477,19478,19479,19480,19481,19482,19483,
94257 19484,19485,19486,19487,19488,19489,19490,19491,19492,19493,19494,19495,
94258 19496,19497,19498,19499,19500,19501,19502,19503,19504,19505,19506,19507,
94259 19508,19509,19510,19511,19512,19513,19514,19515,19516,19517,19518,19519,
94260 19520,19521,19522,19523,19524,19525,19526,19527,19528,19529,19530,19531,
94261 19532,19533,19534,19535,19536,19537,19538,19539,19540,19541,19542,19543,
94262 19544,19545,19546,19547,19548,19549,19550,19551,19552,19553,19554,19555,
94263 19556,19557,19558,19559,19560,19561,19562,19563,19564,19565,19566,19567,
94264 19568,19569,19570,19571,19572,19573,19574,19575,19576,19577,19578,19579,
94265 19580,19581,19582,19583,19584,19585,19586,19587,19588,19589,19590,19591,
94266 19592,19593,19594,19595,19596,19597,19598,19599,19600,19601,19602,19603,
94267 19604,19605,19606,19607,19608,19609,19610,19611,19612,19613,19614,19615,
94268 19616,19617,19618,19619,19620,19621,19622,19623,19624,19625,19626,19627,
94269 19628,19629,19630,19631,19632,19633,19634,19635,19636,19637,19638,19639,
94270 19640,19641,19642,19643,19644,19645,19646,19647,19648,19649,19650,19651,
94271 19652,19653,19654,19655,19656,19657,19658,19659,19660,19661,19662,19663,
94272 19664,19665,19666,19667,19668,19669,19670,19671,19672,19673,19674,19675,
94273 19676,19677,19678,19679,19680,19681,19682,19683,19684,19685,19686,19687,
94274 19688,19689,19690,19691,19692,19693,19694,19695,19696,19697,19698,19699,
94275 19700,19701,19702,19703,19704,19705,19706,19707,19708,19709,19710,19711,
94276 19712,19713,19714,19715,19716,19717,19718,19719,19720,19721,19722,19723,
94277 19724,19725,19726,19727,19728,19729,19730,19731,19732,19733,19734,19735,
94278 19736,19737,19738,19739,19740,19741,19742,19743,19744,19745,19746,19747,
94279 19748,19749,19750,19751,19752,19753,19754,19755,19756,19757,19758,19759,
94280 19760,19761,19762,19763,19764,19765,19766,19767,19768,19769,19770,19771,
94281 19772,19773,19774,19775,19776,19777,19778,19779,19780,19781,19782,19783,
94282 19784,19785,19786,19787,19788,19789,19790,19791,19792,19793,19794,19795,
94283 19796,19797,19798,19799,19800,19801,19802,19803,19804,19805,19806,19807,
94284 19808,19809,19810,19811,19812,19813,19814,19815,19816,19817,19818,19819,
94285 19820,19821,19822,19823,19824,19825,19826,19827,19828,19829,19830,19831,
94286 19832,19833,19834,19835,19836,19837,19838,19839,19840,19841,19842,19843,
94287 19844,19845,19846,19847,19848,19849,19850,19851,19852,19853,19854,19855,
94288 19856,19857,19858,19859,19860,19861,19862,19863,19864,19865,19866,19867,
94289 19868,19869,19870,19871,19872,19873,19874,19875,19876,19877,19878,19879,
94290 19880,19881,19882,19883,19884,19885,19886,19887,19888,19889,19890,19891,
94291 19892,19893,19894,19895,19896,19897,19898,19899,19900,19901,19902,19903,
94292 19904,19905,19906,19907,19908,19909,19910,19911,19912,19913,19914,19915,
94293 19916,19917,19918,19919,19920,19921,19922,19923,19924,19925,19926,19927,
94294 19928,19929,19930,19931,19932,19933,19934,19935,19936,19937,19938,19939,
94295 19940,19941,19942,19943,19944,19945,19946,19947,19948,19949,19950,19951,
94296 19952,19953,19954,19955,19956,19957,19958,19959,19960,19961,19962,19963,
94297 19964,19965,19966,19967,19968,19969,19970,19971,19972,19973,19974,19975,
94298 19976,19977,19978,19979,19980,19981,19982,19983,19984,19985,19986,19987,
94299 19988,19989,19990,19991,19992,19993,19994,19995,19996,19997,19998,19999,
94300 20000,20001,20002,20003,20004,20005,20006,20007,20008,20009,20010,20011,
94301 20012,20013,20014,20015,20016,20017,20018,20019,20020,20021,20022,20023,
94302 20024,20025,20026,20027,20028,20029,20030,20031,20032,20033,20034,20035,
94303 20036,20037,20038,20039,20040,20041,20042,20043,20044,20045,20046,20047,
94304 20048,20049,20050,20051,20052,20053,20054,20055,20056,20057,20058,20059,
94305 20060,20061,20062,20063,20064,20065,20066,20067,20068,20069,20070,20071,
94306 20072,20073,20074,20075,20076,20077,20078,20079,20080,20081,20082,20083,
94307 20084,20085,20086,20087,20088,20089,20090,20091,20092,20093,20094,20095,
94308 20096,20097,20098,20099,20100,20101,20102,20103,20104,20105,20106,20107,
94309 20108,20109,20110,20111,20112,20113,20114,20115,20116,20117,20118,20119,
94310 20120,20121,20122,20123,20124,20125,20126,20127,20128,20129,20130,20131,
94311 20132,20133,20134,20135,20136,20137,20138,20139,20140,20141,20142,20143,
94312 20144,20145,20146,20147,20148,20149,20150,20151,20152,20153,20154,20155,
94313 20156,20157,20158,20159,20160,20161,20162,20163,20164,20165,20166,20167,
94314 20168,20169,20170,20171,20172,20173,20174,20175,20176,20177,20178,20179,
94315 20180,20181,20182,20183,20184,20185,20186,20187,20188,20189,20190,20191,
94316 20192,20193,20194,20195,20196,20197,20198,20199,20200,20201,20202,20203,
94317 20204,20205,20206,20207,20208,20209,20210,20211,20212,20213,20214,20215,
94318 20216,20217,20218,20219,20220,20221,20222,20223,20224,20225,20226,20227,
94319 20228,20229,20230,20231,20232,20233,20234,20235,20236,20237,20238,20239,
94320 20240,20241,20242,20243,20244,20245,20246,20247,20248,20249,20250,20251,
94321 20252,20253,20254,20255,20256,20257,20258,20259,20260,20261,20262,20263,
94322 20264,20265,20266,20267,20268,20269,20270,20271,20272,20273,20274,20275,
94323 20276,20277,20278,20279,20280,20281,20282,20283,20284,20285,20286,20287,
94324 20288,20289,20290,20291,20292,20293,20294,20295,20296,20297,20298,20299,
94325 20300,20301,20302,20303,20304,20305,20306,20307,20308,20309,20310,20311,
94326 20312,20313,20314,20315,20316,20317,20318,20319,20320,20321,20322,20323,
94327 20324,20325,20326,20327,20328,20329,20330,20331,20332,20333,20334,20335,
94328 20336,20337,20338,20339,20340,20341,20342,20343,20344,20345,20346,20347,
94329 20348,20349,20350,20351,20352,20353,20354,20355,20356,20357,20358,20359,
94330 20360,20361,20362,20363,20364,20365,20366,20367,20368,20369,20370,20371,
94331 20372,20373,20374,20375,20376,20377,20378,20379,20380,20381,20382,20383,
94332 20384,20385,20386,20387,20388,20389,20390,20391,20392,20393,20394,20395,
94333 20396,20397,20398,20399,20400,20401,20402,20403,20404,20405,20406,20407,
94334 20408,20409,20410,20411,20412,20413,20414,20415,20416,20417,20418,20419,
94335 20420,20421,20422,20423,20424,20425,20426,20427,20428,20429,20430,20431,
94336 20432,20433,20434,20435,20436,20437,20438,20439,20440,20441,20442,20443,
94337 20444,20445,20446,20447,20448,20449,20450,20451,20452,20453,20454,20455,
94338 20456,20457,20458,20459,20460,20461,20462,20463,20464,20465,20466,20467,
94339 20468,20469,20470,20471,20472,20473,20474,20475,20476,20477,20478,20479,
94340 20480,20481,20482,20483,20484,20485,20486,20487,20488,20489,20490,20491,
94341 20492,20493,20494,20495,20496,20497,20498,20499,20500,20501,20502,20503,
94342 20504,20505,20506,20507,20508,20509,20510,20511,20512,20513,20514,20515,
94343 20516,20517,20518,20519,20520,20521,20522,20523,20524,20525,20526,20527,
94344 20528,20529,20530,20531,20532,20533,20534,20535,20536,20537,20538,20539,
94345 20540,20541,20542,20543,20544,20545,20546,20547,20548,20549,20550,20551,
94346 20552,20553,20554,20555,20556,20557,20558,20559,20560,20561,20562,20563,
94347 20564,20565,20566,20567,20568,20569,20570,20571,20572,20573,20574,20575,
94348 20576,20577,20578,20579,20580,20581,20582,20583,20584,20585,20586,20587,
94349 20588,20589,20590,20591,20592,20593,20594,20595,20596,20597,20598,20599,
94350 20600,20601,20602,20603,20604,20605,20606,20607,20608,20609,20610,20611,
94351 20612,20613,20614,20615,20616,20617,20618,20619,20620,20621,20622,20623,
94352 20624,20625,20626,20627,20628,20629,20630,20631,20632,20633,20634,20635,
94353 20636,20637,20638,20639,20640,20641,20642,20643,20644,20645,20646,20647,
94354 20648,20649,20650,20651,20652,20653,20654,20655,20656,20657,20658,20659,
94355 20660,20661,20662,20663,20664,20665,20666,20667,20668,20669,20670,20671,
94356 20672,20673,20674,20675,20676,20677,20678,20679,20680,20681,20682,20683,
94357 20684,20685,20686,20687,20688,20689,20690,20691,20692,20693,20694,20695,
94358 20696,20697,20698,20699,20700,20701,20702,20703,20704,20705,20706,20707,
94359 20708,20709,20710,20711,20712,20713,20714,20715,20716,20717,20718,20719,
94360 20720,20721,20722,20723,20724,20725,20726,20727,20728,20729,20730,20731,
94361 20732,20733,20734,20735,20736,20737,20738,20739,20740,20741,20742,20743,
94362 20744,20745,20746,20747,20748,20749,20750,20751,20752,20753,20754,20755,
94363 20756,20757,20758,20759,20760,20761,20762,20763,20764,20765,20766,20767,
94364 20768,20769,20770,20771,20772,20773,20774,20775,20776,20777,20778,20779,
94365 20780,20781,20782,20783,20784,20785,20786,20787,20788,20789,20790,20791,
94366 20792,20793,20794,20795,20796,20797,20798,20799,20800,20801,20802,20803,
94367 20804,20805,20806,20807,20808,20809,20810,20811,20812,20813,20814,20815,
94368 20816,20817,20818,20819,20820,20821,20822,20823,20824,20825,20826,20827,
94369 20828,20829,20830,20831,20832,20833,20834,20835,20836,20837,20838,20839,
94370 20840,20841,20842,20843,20844,20845,20846,20847,20848,20849,20850,20851,
94371 20852,20853,20854,20855,20856,20857,20858,20859,20860,20861,20862,20863,
94372 20864,20865,20866,20867,20868,20869,20870,20871,20872,20873,20874,20875,
94373 20876,20877,20878,20879,20880,20881,20882,20883,20884,20885,20886,20887,
94374 20888,20889,20890,20891,20892,20893,20894,20895,20896,20897,20898,20899,
94375 20900,20901,20902,20903,20904,20905,20906,20907,20908,20909,20910,20911,
94376 20912,20913,20914,20915,20916,20917,20918,20919,20920,20921,20922,20923,
94377 20924,20925,20926,20927,20928,20929,20930,20931,20932,20933,20934,20935,
94378 20936,20937,20938,20939,20940,20941,20942,20943,20944,20945,20946,20947,
94379 20948,20949,20950,20951,20952,20953,20954,20955,20956,20957,20958,20959,
94380 20960,20961,20962,20963,20964,20965,20966,20967,20968,20969,20970,20971,
94381 20972,20973,20974,20975,20976,20977,20978,20979,20980,20981,20982,20983,
94382 20984,20985,20986,20987,20988,20989,20990,20991,20992,20993,20994,20995,
94383 20996,20997,20998,20999,21000,21001,21002,21003,21004,21005,21006,21007,
94384 21008,21009,21010,21011,21012,21013,21014,21015,21016,21017,21018,21019,
94385 21020,21021,21022,21023,21024,21025,21026,21027,21028,21029,21030,21031,
94386 21032,21033,21034,21035,21036,21037,21038,21039,21040,21041,21042,21043,
94387 21044,21045,21046,21047,21048,21049,21050,21051,21052,21053,21054,21055,
94388 21056,21057,21058,21059,21060,21061,21062,21063,21064,21065,21066,21067,
94389 21068,21069,21070,21071,21072,21073,21074,21075,21076,21077,21078,21079,
94390 21080,21081,21082,21083,21084,21085,21086,21087,21088,21089,21090,21091,
94391 21092,21093,21094,21095,21096,21097,21098,21099,21100,21101,21102,21103,
94392 21104,21105,21106,21107,21108,21109,21110,21111,21112,21113,21114,21115,
94393 21116,21117,21118,21119,21120,21121,21122,21123,21124,21125,21126,21127,
94394 21128,21129,21130,21131,21132,21133,21134,21135,21136,21137,21138,21139,
94395 21140,21141,21142,21143,21144,21145,21146,21147,21148,21149,21150,21151,
94396 21152,21153,21154,21155,21156,21157,21158,21159,21160,21161,21162,21163,
94397 21164,21165,21166,21167,21168,21169,21170,21171,21172,21173,21174,21175,
94398 21176,21177,21178,21179,21180,21181,21182,21183,21184,21185,21186,21187,
94399 21188,21189,21190,21191,21192,21193,21194,21195,21196,21197,21198,21199,
94400 21200,21201,21202,21203,21204,21205,21206,21207,21208,21209,21210,21211,
94401 21212,21213,21214,21215,21216,21217,21218,21219,21220,21221,21222,21223,
94402 21224,21225,21226,21227,21228,21229,21230,21231,21232,21233,21234,21235,
94403 21236,21237,21238,21239,21240,21241,21242,21243,21244,21245,21246,21247,
94404 21248,21249,21250,21251,21252,21253,21254,21255,21256,21257,21258,21259,
94405 21260,21261,21262,21263,21264,21265,21266,21267,21268,21269,21270,21271,
94406 21272,21273,21274,21275,21276,21277,21278,21279,21280,21281,21282,21283,
94407 21284,21285,21286,21287,21288,21289,21290,21291,21292,21293,21294,21295,
94408 21296,21297,21298,21299,21300,21301,21302,21303,21304,21305,21306,21307,
94409 21308,21309,21310,21311,21312,21313,21314,21315,21316,21317,21318,21319,
94410 21320,21321,21322,21323,21324,21325,21326,21327,21328,21329,21330,21331,
94411 21332,21333,21334,21335,21336,21337,21338,21339,21340,21341,21342,21343,
94412 21344,21345,21346,21347,21348,21349,21350,21351,21352,21353,21354,21355,
94413 21356,21357,21358,21359,21360,21361,21362,21363,21364,21365,21366,21367,
94414 21368,21369,21370,21371,21372,21373,21374,21375,21376,21377,21378,21379,
94415 21380,21381,21382,21383,21384,21385,21386,21387,21388,21389,21390,21391,
94416 21392,21393,21394,21395,21396,21397,21398,21399,21400,21401,21402,21403,
94417 21404,21405,21406,21407,21408,21409,21410,21411,21412,21413,21414,21415,
94418 21416,21417,21418,21419,21420,21421,21422,21423,21424,21425,21426,21427,
94419 21428,21429,21430,21431,21432,21433,21434,21435,21436,21437,21438,21439,
94420 21440,21441,21442,21443,21444,21445,21446,21447,21448,21449,21450,21451,
94421 21452,21453,21454,21455,21456,21457,21458,21459,21460,21461,21462,21463,
94422 21464,21465,21466,21467,21468,21469,21470,21471,21472,21473,21474,21475,
94423 21476,21477,21478,21479,21480,21481,21482,21483,21484,21485,21486,21487,
94424 21488,21489,21490,21491,21492,21493,21494,21495,21496,21497,21498,21499,
94425 21500,21501,21502,21503,21504,21505,21506,21507,21508,21509,21510,21511,
94426 21512,21513,21514,21515,21516,21517,21518,21519,21520,21521,21522,21523,
94427 21524,21525,21526,21527,21528,21529,21530,21531,21532,21533,21534,21535,
94428 21536,21537,21538,21539,21540,21541,21542,21543,21544,21545,21546,21547,
94429 21548,21549,21550,21551,21552,21553,21554,21555,21556,21557,21558,21559,
94430 21560,21561,21562,21563,21564,21565,21566,21567,21568,21569,21570,21571,
94431 21572,21573,21574,21575,21576,21577,21578,21579,21580,21581,21582,21583,
94432 21584,21585,21586,21587,21588,21589,21590,21591,21592,21593,21594,21595,
94433 21596,21597,21598,21599,21600,21601,21602,21603,21604,21605,21606,21607,
94434 21608,21609,21610,21611,21612,21613,21614,21615,21616,21617,21618,21619,
94435 21620,21621,21622,21623,21624,21625,21626,21627,21628,21629,21630,21631,
94436 21632,21633,21634,21635,21636,21637,21638,21639,21640,21641,21642,21643,
94437 21644,21645,21646,21647,21648,21649,21650,21651,21652,21653,21654,21655,
94438 21656,21657,21658,21659,21660,21661,21662,21663,21664,21665,21666,21667,
94439 21668,21669,21670,21671,21672,21673,21674,21675,21676,21677,21678,21679,
94440 21680,21681,21682,21683,21684,21685,21686,21687,21688,21689,21690,21691,
94441 21692,21693,21694,21695,21696,21697,21698,21699,21700,21701,21702,21703,
94442 21704,21705,21706,21707,21708,21709,21710,21711,21712,21713,21714,21715,
94443 21716,21717,21718,21719,21720,21721,21722,21723,21724,21725,21726,21727,
94444 21728,21729,21730,21731,21732,21733,21734,21735,21736,21737,21738,21739,
94445 21740,21741,21742,21743,21744,21745,21746,21747,21748,21749,21750,21751,
94446 21752,21753,21754,21755,21756,21757,21758,21759,21760,21761,21762,21763,
94447 21764,21765,21766,21767,21768,21769,21770,21771,21772,21773,21774,21775,
94448 21776,21777,21778,21779,21780,21781,21782,21783,21784,21785,21786,21787,
94449 21788,21789,21790,21791,21792,21793,21794,21795,21796,21797,21798,21799,
94450 21800,21801,21802,21803,21804,21805,21806,21807,21808,21809,21810,21811,
94451 21812,21813,21814,21815,21816,21817,21818,21819,21820,21821,21822,21823,
94452 21824,21825,21826,21827,21828,21829,21830,21831,21832,21833,21834,21835,
94453 21836,21837,21838,21839,21840,21841,21842,21843,21844,21845,21846,21847,
94454 21848,21849,21850,21851,21852,21853,21854,21855,21856,21857,21858,21859,
94455 21860,21861,21862,21863,21864,21865,21866,21867,21868,21869,21870,21871,
94456 21872,21873,21874,21875,21876,21877,21878,21879,21880,21881,21882,21883,
94457 21884,21885,21886,21887,21888,21889,21890,21891,21892,21893,21894,21895,
94458 21896,21897,21898,21899,21900,21901,21902,21903,21904,21905,21906,21907,
94459 21908,21909,21910,21911,21912,21913,21914,21915,21916,21917,21918,21919,
94460 21920,21921,21922,21923,21924,21925,21926,21927,21928,21929,21930,21931,
94461 21932,21933,21934,21935,21936,21937,21938,21939,21940,21941,21942,21943,
94462 21944,21945,21946,21947,21948,21949,21950,21951,21952,21953,21954,21955,
94463 21956,21957,21958,21959,21960,21961,21962,21963,21964,21965,21966,21967,
94464 21968,21969,21970,21971,21972,21973,21974,21975,21976,21977,21978,21979,
94465 21980,21981,21982,21983,21984,21985,21986,21987,21988,21989,21990,21991,
94466 21992,21993,21994,21995,21996,21997,21998,21999,22000,22001,22002,22003,
94467 22004,22005,22006,22007,22008,22009,22010,22011,22012,22013,22014,22015,
94468 22016,22017,22018,22019,22020,22021,22022,22023,22024,22025,22026,22027,
94469 22028,22029,22030,22031,22032,22033,22034,22035,22036,22037,22038,22039,
94470 22040,22041,22042,22043,22044,22045,22046,22047,22048,22049,22050,22051,
94471 22052,22053,22054,22055,22056,22057,22058,22059,22060,22061,22062,22063,
94472 22064,22065,22066,22067,22068,22069,22070,22071,22072,22073,22074,22075,
94473 22076,22077,22078,22079,22080,22081,22082,22083,22084,22085,22086,22087,
94474 22088,22089,22090,22091,22092,22093,22094,22095,22096,22097,22098,22099,
94475 22100,22101,22102,22103,22104,22105,22106,22107,22108,22109,22110,22111,
94476 22112,22113,22114,22115,22116,22117,22118,22119,22120,22121,22122,22123,
94477 22124,22125,22126,22127,22128,22129,22130,22131,22132,22133,22134,22135,
94478 22136,22137,22138,22139,22140,22141,22142,22143,22144,22145,22146,22147,
94479 22148,22149,22150,22151,22152,22153,22154,22155,22156,22157,22158,22159,
94480 22160,22161,22162,22163,22164,22165,22166,22167,22168,22169,22170,22171,
94481 22172,22173,22174,22175,22176,22177,22178,22179,22180,22181,22182,22183,
94482 22184,22185,22186,22187,22188,22189,22190,22191,22192,22193,22194,22195,
94483 22196,22197,22198,22199,22200,22201,22202,22203,22204,22205,22206,22207,
94484 22208,22209,22210,22211,22212,22213,22214,22215,22216,22217,22218,22219,
94485 22220,22221,22222,22223,22224,22225,22226,22227,22228,22229,22230,22231,
94486 22232,22233,22234,22235,22236,22237,22238,22239,22240,22241,22242,22243,
94487 22244,22245,22246,22247,22248,22249,22250,22251,22252,22253,22254,22255,
94488 22256,22257,22258,22259,22260,22261,22262,22263,22264,22265,22266,22267,
94489 22268,22269,22270,22271,22272,22273,22274,22275,22276,22277,22278,22279,
94490 22280,22281,22282,22283,22284,22285,22286,22287,22288,22289,22290,22291,
94491 22292,22293,22294,22295,22296,22297,22298,22299,22300,22301,22302,22303,
94492 22304,22305,22306,22307,22308,22309,22310,22311,22312,22313,22314,22315,
94493 22316,22317,22318,22319,22320,22321,22322,22323,22324,22325,22326,22327,
94494 22328,22329,22330,22331,22332,22333,22334,22335,22336,22337,22338,22339,
94495 22340,22341,22342,22343,22344,22345,22346,22347,22348,22349,22350,22351,
94496 22352,22353,22354,22355,22356,22357,22358,22359,22360,22361,22362,22363,
94497 22364,22365,22366,22367,22368,22369,22370,22371,22372,22373,22374,22375,
94498 22376,22377,22378,22379,22380,22381,22382,22383,22384,22385,22386,22387,
94499 22388,22389,22390,22391,22392,22393,22394,22395,22396,22397,22398,22399,
94500 22400,22401,22402,22403,22404,22405,22406,22407,22408,22409,22410,22411,
94501 22412,22413,22414,22415,22416,22417,22418,22419,22420,22421,22422,22423,
94502 22424,22425,22426,22427,22428,22429,22430,22431,22432,22433,22434,22435,
94503 22436,22437,22438,22439,22440,22441,22442,22443,22444,22445,22446,22447,
94504 22448,22449,22450,22451,22452,22453,22454,22455,22456,22457,22458,22459,
94505 22460,22461,22462,22463,22464,22465,22466,22467,22468,22469,22470,22471,
94506 22472,22473,22474,22475,22476,22477,22478,22479,22480,22481,22482,22483,
94507 22484,22485,22486,22487,22488,22489,22490,22491,22492,22493,22494,22495,
94508 22496,22497,22498,22499,22500,22501,22502,22503,22504,22505,22506,22507,
94509 22508,22509,22510,22511,22512,22513,22514,22515,22516,22517,22518,22519,
94510 22520,22521,22522,22523,22524,22525,22526,22527,22528,22529,22530,22531,
94511 22532,22533,22534,22535,22536,22537,22538,22539,22540,22541,22542,22543,
94512 22544,22545,22546,22547,22548,22549,22550,22551,22552,22553,22554,22555,
94513 22556,22557,22558,22559,22560,22561,22562,22563,22564,22565,22566,22567,
94514 22568,22569,22570,22571,22572,22573,22574,22575,22576,22577,22578,22579,
94515 22580,22581,22582,22583,22584,22585,22586,22587,22588,22589,22590,22591,
94516 22592,22593,22594,22595,22596,22597,22598,22599,22600,22601,22602,22603,
94517 22604,22605,22606,22607,22608,22609,22610,22611,22612,22613,22614,22615,
94518 22616,22617,22618,22619,22620,22621,22622,22623,22624,22625,22626,22627,
94519 22628,22629,22630,22631,22632,22633,22634,22635,22636,22637,22638,22639,
94520 22640,22641,22642,22643,22644,22645,22646,22647,22648,22649,22650,22651,
94521 22652,22653,22654,22655,22656,22657,22658,22659,22660,22661,22662,22663,
94522 22664,22665,22666,22667,22668,22669,22670,22671,22672,22673,22674,22675,
94523 22676,22677,22678,22679,22680,22681,22682,22683,22684,22685,22686,22687,
94524 22688,22689,22690,22691,22692,22693,22694,22695,22696,22697,22698,22699,
94525 22700,22701,22702,22703,22704,22705,22706,22707,22708,22709,22710,22711,
94526 22712,22713,22714,22715,22716,22717,22718,22719,22720,22721,22722,22723,
94527 22724,22725,22726,22727,22728,22729,22730,22731,22732,22733,22734,22735,
94528 22736,22737,22738,22739,22740,22741,22742,22743,22744,22745,22746,22747,
94529 22748,22749,22750,22751,22752,22753,22754,22755,22756,22757,22758,22759,
94530 22760,22761,22762,22763,22764,22765,22766,22767,22768,22769,22770,22771,
94531 22772,22773,22774,22775,22776,22777,22778,22779,22780,22781,22782,22783,
94532 22784,22785,22786,22787,22788,22789,22790,22791,22792,22793,22794,22795,
94533 22796,22797,22798,22799,22800,22801,22802,22803,22804,22805,22806,22807,
94534 22808,22809,22810,22811,22812,22813,22814,22815,22816,22817,22818,22819,
94535 22820,22821,22822,22823,22824,22825,22826,22827,22828,22829,22830,22831,
94536 22832,22833,22834,22835,22836,22837,22838,22839,22840,22841,22842,22843,
94537 22844,22845,22846,22847,22848,22849,22850,22851,22852,22853,22854,22855,
94538 22856,22857,22858,22859,22860,22861,22862,22863,22864,22865,22866,22867,
94539 22868,22869,22870,22871,22872,22873,22874,22875,22876,22877,22878,22879,
94540 22880,22881,22882,22883,22884,22885,22886,22887,22888,22889,22890,22891,
94541 22892,22893,22894,22895,22896,22897,22898,22899,22900,22901,22902,22903,
94542 22904,22905,22906,22907,22908,22909,22910,22911,22912,22913,22914,22915,
94543 22916,22917,22918,22919,22920,22921,22922,22923,22924,22925,22926,22927,
94544 22928,22929,22930,22931,22932,22933,22934,22935,22936,22937,22938,22939,
94545 22940,22941,22942,22943,22944,22945,22946,22947,22948,22949,22950,22951,
94546 22952,22953,22954,22955,22956,22957,22958,22959,22960,22961,22962,22963,
94547 22964,22965,22966,22967,22968,22969,22970,22971,22972,22973,22974,22975,
94548 22976,22977,22978,22979,22980,22981,22982,22983,22984,22985,22986,22987,
94549 22988,22989,22990,22991,22992,22993,22994,22995,22996,22997,22998,22999,
94550 23000,23001,23002,23003,23004,23005,23006,23007,23008,23009,23010,23011,
94551 23012,23013,23014,23015,23016,23017,23018,23019,23020,23021,23022,23023,
94552 23024,23025,23026,23027,23028,23029,23030,23031,23032,23033,23034,23035,
94553 23036,23037,23038,23039,23040,23041,23042,23043,23044,23045,23046,23047,
94554 23048,23049,23050,23051,23052,23053,23054,23055,23056,23057,23058,23059,
94555 23060,23061,23062,23063,23064,23065,23066,23067,23068,23069,23070,23071,
94556 23072,23073,23074,23075,23076,23077,23078,23079,23080,23081,23082,23083,
94557 23084,23085,23086,23087,23088,23089,23090,23091,23092,23093,23094,23095,
94558 23096,23097,23098,23099,23100,23101,23102,23103,23104,23105,23106,23107,
94559 23108,23109,23110,23111,23112,23113,23114,23115,23116,23117,23118,23119,
94560 23120,23121,23122,23123,23124,23125,23126,23127,23128,23129,23130,23131,
94561 23132,23133,23134,23135,23136,23137,23138,23139,23140,23141,23142,23143,
94562 23144,23145,23146,23147,23148,23149,23150,23151,23152,23153,23154,23155,
94563 23156,23157,23158,23159,23160,23161,23162,23163,23164,23165,23166,23167,
94564 23168,23169,23170,23171,23172,23173,23174,23175,23176,23177,23178,23179,
94565 23180,23181,23182,23183,23184,23185,23186,23187,23188,23189,23190,23191,
94566 23192,23193,23194,23195,23196,23197,23198,23199,23200,23201,23202,23203,
94567 23204,23205,23206,23207,23208,23209,23210,23211,23212,23213,23214,23215,
94568 23216,23217,23218,23219,23220,23221,23222,23223,23224,23225,23226,23227,
94569 23228,23229,23230,23231,23232,23233,23234,23235,23236,23237,23238,23239,
94570 23240,23241,23242,23243,23244,23245,23246,23247,23248,23249,23250,23251,
94571 23252,23253,23254,23255,23256,23257,23258,23259,23260,23261,23262,23263,
94572 23264,23265,23266,23267,23268,23269,23270,23271,23272,23273,23274,23275,
94573 23276,23277,23278,23279,23280,23281,23282,23283,23284,23285,23286,23287,
94574 23288,23289,23290,23291,23292,23293,23294,23295,23296,23297,23298,23299,
94575 23300,23301,23302,23303,23304,23305,23306,23307,23308,23309,23310,23311,
94576 23312,23313,23314,23315,23316,23317,23318,23319,23320,23321,23322,23323,
94577 23324,23325,23326,23327,23328,23329,23330,23331,23332,23333,23334,23335,
94578 23336,23337,23338,23339,23340,23341,23342,23343,23344,23345,23346,23347,
94579 23348,23349,23350,23351,23352,23353,23354,23355,23356,23357,23358,23359,
94580 23360,23361,23362,23363,23364,23365,23366,23367,23368,23369,23370,23371,
94581 23372,23373,23374,23375,23376,23377,23378,23379,23380,23381,23382,23383,
94582 23384,23385,23386,23387,23388,23389,23390,23391,23392,23393,23394,23395,
94583 23396,23397,23398,23399,23400,23401,23402,23403,23404,23405,23406,23407,
94584 23408,23409,23410,23411,23412,23413,23414,23415,23416,23417,23418,23419,
94585 23420,23421,23422,23423,23424,23425,23426,23427,23428,23429,23430,23431,
94586 23432,23433,23434,23435,23436,23437,23438,23439,23440,23441,23442,23443,
94587 23444,23445,23446,23447,23448,23449,23450,23451,23452,23453,23454,23455,
94588 23456,23457,23458,23459,23460,23461,23462,23463,23464,23465,23466,23467,
94589 23468,23469,23470,23471,23472,23473,23474,23475,23476,23477,23478,23479,
94590 23480,23481,23482,23483,23484,23485,23486,23487,23488,23489,23490,23491,
94591 23492,23493,23494,23495,23496,23497,23498,23499,23500,23501,23502,23503,
94592 23504,23505,23506,23507,23508,23509,23510,23511,23512,23513,23514,23515,
94593 23516,23517,23518,23519,23520,23521,23522,23523,23524,23525,23526,23527,
94594 23528,23529,23530,23531,23532,23533,23534,23535,23536,23537,23538,23539,
94595 23540,23541,23542,23543,23544,23545,23546,23547,23548,23549,23550,23551,
94596 23552,23553,23554,23555,23556,23557,23558,23559,23560,23561,23562,23563,
94597 23564,23565,23566,23567,23568,23569,23570,23571,23572,23573,23574,23575,
94598 23576,23577,23578,23579,23580,23581,23582,23583,23584,23585,23586,23587,
94599 23588,23589,23590,23591,23592,23593,23594,23595,23596,23597,23598,23599,
94600 23600,23601,23602,23603,23604,23605,23606,23607,23608,23609,23610,23611,
94601 23612,23613,23614,23615,23616,23617,23618,23619,23620,23621,23622,23623,
94602 23624,23625,23626,23627,23628,23629,23630,23631,23632,23633,23634,23635,
94603 23636,23637,23638,23639,23640,23641,23642,23643,23644,23645,23646,23647,
94604 23648,23649,23650,23651,23652,23653,23654,23655,23656,23657,23658,23659,
94605 23660,23661,23662,23663,23664,23665,23666,23667,23668,23669,23670,23671,
94606 23672,23673,23674,23675,23676,23677,23678,23679,23680,23681,23682,23683,
94607 23684,23685,23686,23687,23688,23689,23690,23691,23692,23693,23694,23695,
94608 23696,23697,23698,23699,23700,23701,23702,23703,23704,23705,23706,23707,
94609 23708,23709,23710,23711,23712,23713,23714,23715,23716,23717,23718,23719,
94610 23720,23721,23722,23723,23724,23725,23726,23727,23728,23729,23730,23731,
94611 23732,23733,23734,23735,23736,23737,23738,23739,23740,23741,23742,23743,
94612 23744,23745,23746,23747,23748,23749,23750,23751,23752,23753,23754,23755,
94613 23756,23757,23758,23759,23760,23761,23762,23763,23764,23765,23766,23767,
94614 23768,23769,23770,23771,23772,23773,23774,23775,23776,23777,23778,23779,
94615 23780,23781,23782,23783,23784,23785,23786,23787,23788,23789,23790,23791,
94616 23792,23793,23794,23795,23796,23797,23798,23799,23800,23801,23802,23803,
94617 23804,23805,23806,23807,23808,23809,23810,23811,23812,23813,23814,23815,
94618 23816,23817,23818,23819,23820,23821,23822,23823,23824,23825,23826,23827,
94619 23828,23829,23830,23831,23832,23833,23834,23835,23836,23837,23838,23839,
94620 23840,23841,23842,23843,23844,23845,23846,23847,23848,23849,23850,23851,
94621 23852,23853,23854,23855,23856,23857,23858,23859,23860,23861,23862,23863,
94622 23864,23865,23866,23867,23868,23869,23870,23871,23872,23873,23874,23875,
94623 23876,23877,23878,23879,23880,23881,23882,23883,23884,23885,23886,23887,
94624 23888,23889,23890,23891,23892,23893,23894,23895,23896,23897,23898,23899,
94625 23900,23901,23902,23903,23904,23905,23906,23907,23908,23909,23910,23911,
94626 23912,23913,23914,23915,23916,23917,23918,23919,23920,23921,23922,23923,
94627 23924,23925,23926,23927,23928,23929,23930,23931,23932,23933,23934,23935,
94628 23936,23937,23938,23939,23940,23941,23942,23943,23944,23945,23946,23947,
94629 23948,23949,23950,23951,23952,23953,23954,23955,23956,23957,23958,23959,
94630 23960,23961,23962,23963,23964,23965,23966,23967,23968,23969,23970,23971,
94631 23972,23973,23974,23975,23976,23977,23978,23979,23980,23981,23982,23983,
94632 23984,23985,23986,23987,23988,23989,23990,23991,23992,23993,23994,23995,
94633 23996,23997,23998,23999,24000,24001,24002,24003,24004,24005,24006,24007,
94634 24008,24009,24010,24011,24012,24013,24014,24015,24016,24017,24018,24019,
94635 24020,24021,24022,24023,24024,24025,24026,24027,24028,24029,24030,24031,
94636 24032,24033,24034,24035,24036,24037,24038,24039,24040,24041,24042,24043,
94637 24044,24045,24046,24047,24048,24049,24050,24051,24052,24053,24054,24055,
94638 24056,24057,24058,24059,24060,24061,24062,24063,24064,24065,24066,24067,
94639 24068,24069,24070,24071,24072,24073,24074,24075,24076,24077,24078,24079,
94640 24080,24081,24082,24083,24084,24085,24086,24087,24088,24089,24090,24091,
94641 24092,24093,24094,24095,24096,24097,24098,24099,24100,24101,24102,24103,
94642 24104,24105,24106,24107,24108,24109,24110,24111,24112,24113,24114,24115,
94643 24116,24117,24118,24119,24120,24121,24122,24123,24124,24125,24126,24127,
94644 24128,24129,24130,24131,24132,24133,24134,24135,24136,24137,24138,24139,
94645 24140,24141,24142,24143,24144,24145,24146,24147,24148,24149,24150,24151,
94646 24152,24153,24154,24155,24156,24157,24158,24159,24160,24161,24162,24163,
94647 24164,24165,24166,24167,24168,24169,24170,24171,24172,24173,24174,24175,
94648 24176,24177,24178,24179,24180,24181,24182,24183,24184,24185,24186,24187,
94649 24188,24189,24190,24191,24192,24193,24194,24195,24196,24197,24198,24199,
94650 24200,24201,24202,24203,24204,24205,24206,24207,24208,24209,24210,24211,
94651 24212,24213,24214,24215,24216,24217,24218,24219,24220,24221,24222,24223,
94652 24224,24225,24226,24227,24228,24229,24230,24231,24232,24233,24234,24235,
94653 24236,24237,24238,24239,24240,24241,24242,24243,24244,24245,24246,24247,
94654 24248,24249,24250,24251,24252,24253,24254,24255,24256,24257,24258,24259,
94655 24260,24261,24262,24263,24264,24265,24266,24267,24268,24269,24270,24271,
94656 24272,24273,24274,24275,24276,24277,24278,24279,24280,24281,24282,24283,
94657 24284,24285,24286,24287,24288,24289,24290,24291,24292,24293,24294,24295,
94658 24296,24297,24298,24299,24300,24301,24302,24303,24304,24305,24306,24307,
94659 24308,24309,24310,24311,24312,24313,24314,24315,24316,24317,24318,24319,
94660 24320,24321,24322,24323,24324,24325,24326,24327,24328,24329,24330,24331,
94661 24332,24333,24334,24335,24336,24337,24338,24339,24340,24341,24342,24343,
94662 24344,24345,24346,24347,24348,24349,24350,24351,24352,24353,24354,24355,
94663 24356,24357,24358,24359,24360,24361,24362,24363,24364,24365,24366,24367,
94664 24368,24369,24370,24371,24372,24373,24374,24375,24376,24377,24378,24379,
94665 24380,24381,24382,24383,24384,24385,24386,24387,24388,24389,24390,24391,
94666 24392,24393,24394,24395,24396,24397,24398,24399,24400,24401,24402,24403,
94667 24404,24405,24406,24407,24408,24409,24410,24411,24412,24413,24414,24415,
94668 24416,24417,24418,24419,24420,24421,24422,24423,24424,24425,24426,24427,
94669 24428,24429,24430,24431,24432,24433,24434,24435,24436,24437,24438,24439,
94670 24440,24441,24442,24443,24444,24445,24446,24447,24448,24449,24450,24451,
94671 24452,24453,24454,24455,24456,24457,24458,24459,24460,24461,24462,24463,
94672 24464,24465,24466,24467,24468,24469,24470,24471,24472,24473,24474,24475,
94673 24476,24477,24478,24479,24480,24481,24482,24483,24484,24485,24486,24487,
94674 24488,24489,24490,24491,24492,24493,24494,24495,24496,24497,24498,24499,
94675 24500,24501,24502,24503,24504,24505,24506,24507,24508,24509,24510,24511,
94676 24512,24513,24514,24515,24516,24517,24518,24519,24520,24521,24522,24523,
94677 24524,24525,24526,24527,24528,24529,24530,24531,24532,24533,24534,24535,
94678 24536,24537,24538,24539,24540,24541,24542,24543,24544,24545,24546,24547,
94679 24548,24549,24550,24551,24552,24553,24554,24555,24556,24557,24558,24559,
94680 24560,24561,24562,24563,24564,24565,24566,24567,24568,24569,24570,24571,
94681 24572,24573,24574,24575,24576,24577,24578,24579,24580,24581,24582,24583,
94682 24584,24585,24586,24587,24588,24589,24590,24591,24592,24593,24594,24595,
94683 24596,24597,24598,24599,24600,24601,24602,24603,24604,24605,24606,24607,
94684 24608,24609,24610,24611,24612,24613,24614,24615,24616,24617,24618,24619,
94685 24620,24621,24622,24623,24624,24625,24626,24627,24628,24629,24630,24631,
94686 24632,24633,24634,24635,24636,24637,24638,24639,24640,24641,24642,24643,
94687 24644,24645,24646,24647,24648,24649,24650,24651,24652,24653,24654,24655,
94688 24656,24657,24658,24659,24660,24661,24662,24663,24664,24665,24666,24667,
94689 24668,24669,24670,24671,24672,24673,24674,24675,24676,24677,24678,24679,
94690 24680,24681,24682,24683,24684,24685,24686,24687,24688,24689,24690,24691,
94691 24692,24693,24694,24695,24696,24697,24698,24699,24700,24701,24702,24703,
94692 24704,24705,24706,24707,24708,24709,24710,24711,24712,24713,24714,24715,
94693 24716,24717,24718,24719,24720,24721,24722,24723,24724,24725,24726,24727,
94694 24728,24729,24730,24731,24732,24733,24734,24735,24736,24737,24738,24739,
94695 24740,24741,24742,24743,24744,24745,24746,24747,24748,24749,24750,24751,
94696 24752,24753,24754,24755,24756,24757,24758,24759,24760,24761,24762,24763,
94697 24764,24765,24766,24767,24768,24769,24770,24771,24772,24773,24774,24775,
94698 24776,24777,24778,24779,24780,24781,24782,24783,24784,24785,24786,24787,
94699 24788,24789,24790,24791,24792,24793,24794,24795,24796,24797,24798,24799,
94700 24800,24801,24802,24803,24804,24805,24806,24807,24808,24809,24810,24811,
94701 24812,24813,24814,24815,24816,24817,24818,24819,24820,24821,24822,24823,
94702 24824,24825,24826,24827,24828,24829,24830,24831,24832,24833,24834,24835,
94703 24836,24837,24838,24839,24840,24841,24842,24843,24844,24845,24846,24847,
94704 24848,24849,24850,24851,24852,24853,24854,24855,24856,24857,24858,24859,
94705 24860,24861,24862,24863,24864,24865,24866,24867,24868,24869,24870,24871,
94706 24872,24873,24874,24875,24876,24877,24878,24879,24880,24881,24882,24883,
94707 24884,24885,24886,24887,24888,24889,24890,24891,24892,24893,24894,24895,
94708 24896,24897,24898,24899,24900,24901,24902,24903,24904,24905,24906,24907,
94709 24908,24909,24910,24911,24912,24913,24914,24915,24916,24917,24918,24919,
94710 24920,24921,24922,24923,24924,24925,24926,24927,24928,24929,24930,24931,
94711 24932,24933,24934,24935,24936,24937,24938,24939,24940,24941,24942,24943,
94712 24944,24945,24946,24947,24948,24949,24950,24951,24952,24953,24954,24955,
94713 24956,24957,24958,24959,24960,24961,24962,24963,24964,24965,24966,24967,
94714 24968,24969,24970,24971,24972,24973,24974,24975,24976,24977,24978,24979,
94715 24980,24981,24982,24983,24984,24985,24986,24987,24988,24989,24990,24991,
94716 24992,24993,24994,24995,24996,24997,24998,24999,25000,25001,25002,25003,
94717 25004,25005,25006,25007,25008,25009,25010,25011,25012,25013,25014,25015,
94718 25016,25017,25018,25019,25020,25021,25022,25023,25024,25025,25026,25027,
94719 25028,25029,25030,25031,25032,25033,25034,25035,25036,25037,25038,25039,
94720 25040,25041,25042,25043,25044,25045,25046,25047,25048,25049,25050,25051,
94721 25052,25053,25054,25055,25056,25057,25058,25059,25060,25061,25062,25063,
94722 25064,25065,25066,25067,25068,25069,25070,25071,25072,25073,25074,25075,
94723 25076,25077,25078,25079,25080,25081,25082,25083,25084,25085,25086,25087,
94724 25088,25089,25090,25091,25092,25093,25094,25095,25096,25097,25098,25099,
94725 25100,25101,25102,25103,25104,25105,25106,25107,25108,25109,25110,25111,
94726 25112,25113,25114,25115,25116,25117,25118,25119,25120,25121,25122,25123,
94727 25124,25125,25126,25127,25128,25129,25130,25131,25132,25133,25134,25135,
94728 25136,25137,25138,25139,25140,25141,25142,25143,25144,25145,25146,25147,
94729 25148,25149,25150,25151,25152,25153,25154,25155,25156,25157,25158,25159,
94730 25160,25161,25162,25163,25164,25165,25166,25167,25168,25169,25170,25171,
94731 25172,25173,25174,25175,25176,25177,25178,25179,25180,25181,25182,25183,
94732 25184,25185,25186,25187,25188,25189,25190,25191,25192,25193,25194,25195,
94733 25196,25197,25198,25199,25200,25201,25202,25203,25204,25205,25206,25207,
94734 25208,25209,25210,25211,25212,25213,25214,25215,25216,25217,25218,25219,
94735 25220,25221,25222,25223,25224,25225,25226,25227,25228,25229,25230,25231,
94736 25232,25233,25234,25235,25236,25237,25238,25239,25240,25241,25242,25243,
94737 25244,25245,25246,25247,25248,25249,25250,25251,25252,25253,25254,25255,
94738 25256,25257,25258,25259,25260,25261,25262,25263,25264,25265,25266,25267,
94739 25268,25269,25270,25271,25272,25273,25274,25275,25276,25277,25278,25279,
94740 25280,25281,25282,25283,25284,25285,25286,25287,25288,25289,25290,25291,
94741 25292,25293,25294,25295,25296,25297,25298,25299,25300,25301,25302,25303,
94742 25304,25305,25306,25307,25308,25309,25310,25311,25312,25313,25314,25315,
94743 25316,25317,25318,25319,25320,25321,25322,25323,25324,25325,25326,25327,
94744 25328,25329,25330,25331,25332,25333,25334,25335,25336,25337,25338,25339,
94745 25340,25341,25342,25343,25344,25345,25346,25347,25348,25349,25350,25351,
94746 25352,25353,25354,25355,25356,25357,25358,25359,25360,25361,25362,25363,
94747 25364,25365,25366,25367,25368,25369,25370,25371,25372,25373,25374,25375,
94748 25376,25377,25378,25379,25380,25381,25382,25383,25384,25385,25386,25387,
94749 25388,25389,25390,25391,25392,25393,25394,25395,25396,25397,25398,25399,
94750 25400,25401,25402,25403,25404,25405,25406,25407,25408,25409,25410,25411,
94751 25412,25413,25414,25415,25416,25417,25418,25419,25420,25421,25422,25423,
94752 25424,25425,25426,25427,25428,25429,25430,25431,25432,25433,25434,25435,
94753 25436,25437,25438,25439,25440,25441,25442,25443,25444,25445,25446,25447,
94754 25448,25449,25450,25451,25452,25453,25454,25455,25456,25457,25458,25459,
94755 25460,25461,25462,25463,25464,25465,25466,25467,25468,25469,25470,25471,
94756 25472,25473,25474,25475,25476,25477,25478,25479,25480,25481,25482,25483,
94757 25484,25485,25486,25487,25488,25489,25490,25491,25492,25493,25494,25495,
94758 25496,25497,25498,25499,25500,25501,25502,25503,25504,25505,25506,25507,
94759 25508,25509,25510,25511,25512,25513,25514,25515,25516,25517,25518,25519,
94760 25520,25521,25522,25523,25524,25525,25526,25527,25528,25529,25530,25531,
94761 25532,25533,25534,25535,25536,25537,25538,25539,25540,25541,25542,25543,
94762 25544,25545,25546,25547,25548,25549,25550,25551,25552,25553,25554,25555,
94763 25556,25557,25558,25559,25560,25561,25562,25563,25564,25565,25566,25567,
94764 25568,25569,25570,25571,25572,25573,25574,25575,25576,25577,25578,25579,
94765 25580,25581,25582,25583,25584,25585,25586,25587,25588,25589,25590,25591,
94766 25592,25593,25594,25595,25596,25597,25598,25599,25600,25601,25602,25603,
94767 25604,25605,25606,25607,25608,25609,25610,25611,25612,25613,25614,25615,
94768 25616,25617,25618,25619,25620,25621,25622,25623,25624,25625,25626,25627,
94769 25628,25629,25630,25631,25632,25633,25634,25635,25636,25637,25638,25639,
94770 25640,25641,25642,25643,25644,25645,25646,25647,25648,25649,25650,25651,
94771 25652,25653,25654,25655,25656,25657,25658,25659,25660,25661,25662,25663,
94772 25664,25665,25666,25667,25668,25669,25670,25671,25672,25673,25674,25675,
94773 25676,25677,25678,25679,25680,25681,25682,25683,25684,25685,25686,25687,
94774 25688,25689,25690,25691,25692,25693,25694,25695,25696,25697,25698,25699,
94775 25700,25701,25702,25703,25704,25705,25706,25707,25708,25709,25710,25711,
94776 25712,25713,25714,25715,25716,25717,25718,25719,25720,25721,25722,25723,
94777 25724,25725,25726,25727,25728,25729,25730,25731,25732,25733,25734,25735,
94778 25736,25737,25738,25739,25740,25741,25742,25743,25744,25745,25746,25747,
94779 25748,25749,25750,25751,25752,25753,25754,25755,25756,25757,25758,25759,
94780 25760,25761,25762,25763,25764,25765,25766,25767,25768,25769,25770,25771,
94781 25772,25773,25774,25775,25776,25777,25778,25779,25780,25781,25782,25783,
94782 25784,25785,25786,25787,25788,25789,25790,25791,25792,25793,25794,25795,
94783 25796,25797,25798,25799,25800,25801,25802,25803,25804,25805,25806,25807,
94784 25808,25809,25810,25811,25812,25813,25814,25815,25816,25817,25818,25819,
94785 25820,25821,25822,25823,25824,25825,25826,25827,25828,25829,25830,25831,
94786 25832,25833,25834,25835,25836,25837,25838,25839,25840,25841,25842,25843,
94787 25844,25845,25846,25847,25848,25849,25850,25851,25852,25853,25854,25855,
94788 25856,25857,25858,25859,25860,25861,25862,25863,25864,25865,25866,25867,
94789 25868,25869,25870,25871,25872,25873,25874,25875,25876,25877,25878,25879,
94790 25880,25881,25882,25883,25884,25885,25886,25887,25888,25889,25890,25891,
94791 25892,25893,25894,25895,25896,25897,25898,25899,25900,25901,25902,25903,
94792 25904,25905,25906,25907,25908,25909,25910,25911,25912,25913,25914,25915,
94793 25916,25917,25918,25919,25920,25921,25922,25923,25924,25925,25926,25927,
94794 25928,25929,25930,25931,25932,25933,25934,25935,25936,25937,25938,25939,
94795 25940,25941,25942,25943,25944,25945,25946,25947,25948,25949,25950,25951,
94796 25952,25953,25954,25955,25956,25957,25958,25959,25960,25961,25962,25963,
94797 25964,25965,25966,25967,25968,25969,25970,25971,25972,25973,25974,25975,
94798 25976,25977,25978,25979,25980,25981,25982,25983,25984,25985,25986,25987,
94799 25988,25989,25990,25991,25992,25993,25994,25995,25996,25997,25998,25999,
94800 26000,26001,26002,26003,26004,26005,26006,26007,26008,26009,26010,26011,
94801 26012,26013,26014,26015,26016,26017,26018,26019,26020,26021,26022,26023,
94802 26024,26025,26026,26027,26028,26029,26030,26031,26032,26033,26034,26035,
94803 26036,26037,26038,26039,26040,26041,26042,26043,26044,26045,26046,26047,
94804 26048,26049,26050,26051,26052,26053,26054,26055,26056,26057,26058,26059,
94805 26060,26061,26062,26063,26064,26065,26066,26067,26068,26069,26070,26071,
94806 26072,26073,26074,26075,26076,26077,26078,26079,26080,26081,26082,26083,
94807 26084,26085,26086,26087,26088,26089,26090,26091,26092,26093,26094,26095,
94808 26096,26097,26098,26099,26100,26101,26102,26103,26104,26105,26106,26107,
94809 26108,26109,26110,26111,26112,26113,26114,26115,26116,26117,26118,26119,
94810 26120,26121,26122,26123,26124,26125,26126,26127,26128,26129,26130,26131,
94811 26132,26133,26134,26135,26136,26137,26138,26139,26140,26141,26142,26143,
94812 26144,26145,26146,26147,26148,26149,26150,26151,26152,26153,26154,26155,
94813 26156,26157,26158,26159,26160,26161,26162,26163,26164,26165,26166,26167,
94814 26168,26169,26170,26171,26172,26173,26174,26175,26176,26177,26178,26179,
94815 26180,26181,26182,26183,26184,26185,26186,26187,26188,26189,26190,26191,
94816 26192,26193,26194,26195,26196,26197,26198,26199,26200,26201,26202,26203,
94817 26204,26205,26206,26207,26208,26209,26210,26211,26212,26213,26214,26215,
94818 26216,26217,26218,26219,26220,26221,26222,26223,26224,26225,26226,26227,
94819 26228,26229,26230,26231,26232,26233,26234,26235,26236,26237,26238,26239,
94820 26240,26241,26242,26243,26244,26245,26246,26247,26248,26249,26250,26251,
94821 26252,26253,26254,26255,26256,26257,26258,26259,26260,26261,26262,26263,
94822 26264,26265,26266,26267,26268,26269,26270,26271,26272,26273,26274,26275,
94823 26276,26277,26278,26279,26280,26281,26282,26283,26284,26285,26286,26287,
94824 26288,26289,26290,26291,26292,26293,26294,26295,26296,26297,26298,26299,
94825 26300,26301,26302,26303,26304,26305,26306,26307,26308,26309,26310,26311,
94826 26312,26313,26314,26315,26316,26317,26318,26319,26320,26321,26322,26323,
94827 26324,26325,26326,26327,26328,26329,26330,26331,26332,26333,26334,26335,
94828 26336,26337,26338,26339,26340,26341,26342,26343,26344,26345,26346,26347,
94829 26348,26349,26350,26351,26352,26353,26354,26355,26356,26357,26358,26359,
94830 26360,26361,26362,26363,26364,26365,26366,26367,26368,26369,26370,26371,
94831 26372,26373,26374,26375,26376,26377,26378,26379,26380,26381,26382,26383,
94832 26384,26385,26386,26387,26388,26389,26390,26391,26392,26393,26394,26395,
94833 26396,26397,26398,26399,26400,26401,26402,26403,26404,26405,26406,26407,
94834 26408,26409,26410,26411,26412,26413,26414,26415,26416,26417,26418,26419,
94835 26420,26421,26422,26423,26424,26425,26426,26427,26428,26429,26430,26431,
94836 26432,26433,26434,26435,26436,26437,26438,26439,26440,26441,26442,26443,
94837 26444,26445,26446,26447,26448,26449,26450,26451,26452,26453,26454,26455,
94838 26456,26457,26458,26459,26460,26461,26462,26463,26464,26465,26466,26467,
94839 26468,26469,26470,26471,26472,26473,26474,26475,26476,26477,26478,26479,
94840 26480,26481,26482,26483,26484,26485,26486,26487,26488,26489,26490,26491,
94841 26492,26493,26494,26495,26496,26497,26498,26499,26500,26501,26502,26503,
94842 26504,26505,26506,26507,26508,26509,26510,26511,26512,26513,26514,26515,
94843 26516,26517,26518,26519,26520,26521,26522,26523,26524,26525,26526,26527,
94844 26528,26529,26530,26531,26532,26533,26534,26535,26536,26537,26538,26539,
94845 26540,26541,26542,26543,26544,26545,26546,26547,26548,26549,26550,26551,
94846 26552,26553,26554,26555,26556,26557,26558,26559,26560,26561,26562,26563,
94847 26564,26565,26566,26567,26568,26569,26570,26571,26572,26573,26574,26575,
94848 26576,26577,26578,26579,26580,26581,26582,26583,26584,26585,26586,26587,
94849 26588,26589,26590,26591,26592,26593,26594,26595,26596,26597,26598,26599,
94850 26600,26601,26602,26603,26604,26605,26606,26607,26608,26609,26610,26611,
94851 26612,26613,26614,26615,26616,26617,26618,26619,26620,26621,26622,26623,
94852 26624,26625,26626,26627,26628,26629,26630,26631,26632,26633,26634,26635,
94853 26636,26637,26638,26639,26640,26641,26642,26643,26644,26645,26646,26647,
94854 26648,26649,26650,26651,26652,26653,26654,26655,26656,26657,26658,26659,
94855 26660,26661,26662,26663,26664,26665,26666,26667,26668,26669,26670,26671,
94856 26672,26673,26674,26675,26676,26677,26678,26679,26680,26681,26682,26683,
94857 26684,26685,26686,26687,26688,26689,26690,26691,26692,26693,26694,26695,
94858 26696,26697,26698,26699,26700,26701,26702,26703,26704,26705,26706,26707,
94859 26708,26709,26710,26711,26712,26713,26714,26715,26716,26717,26718,26719,
94860 26720,26721,26722,26723,26724,26725,26726,26727,26728,26729,26730,26731,
94861 26732,26733,26734,26735,26736,26737,26738,26739,26740,26741,26742,26743,
94862 26744,26745,26746,26747,26748,26749,26750,26751,26752,26753,26754,26755,
94863 26756,26757,26758,26759,26760,26761,26762,26763,26764,26765,26766,26767,
94864 26768,26769,26770,26771,26772,26773,26774,26775,26776,26777,26778,26779,
94865 26780,26781,26782,26783,26784,26785,26786,26787,26788,26789,26790,26791,
94866 26792,26793,26794,26795,26796,26797,26798,26799,26800,26801,26802,26803,
94867 26804,26805,26806,26807,26808,26809,26810,26811,26812,26813,26814,26815,
94868 26816,26817,26818,26819,26820,26821,26822,26823,26824,26825,26826,26827,
94869 26828,26829,26830,26831,26832,26833,26834,26835,26836,26837,26838,26839,
94870 26840,26841,26842,26843,26844,26845,26846,26847,26848,26849,26850,26851,
94871 26852,26853,26854,26855,26856,26857,26858,26859,26860,26861,26862,26863,
94872 26864,26865,26866,26867,26868,26869,26870,26871,26872,26873,26874,26875,
94873 26876,26877,26878,26879,26880,26881,26882,26883,26884,26885,26886,26887,
94874 26888,26889,26890,26891,26892,26893,26894,26895,26896,26897,26898,26899,
94875 26900,26901,26902,26903,26904,26905,26906,26907,26908,26909,26910,26911,
94876 26912,26913,26914,26915,26916,26917,26918,26919,26920,26921,26922,26923,
94877 26924,26925,26926,26927,26928,26929,26930,26931,26932,26933,26934,26935,
94878 26936,26937,26938,26939,26940,26941,26942,26943,26944,26945,26946,26947,
94879 26948,26949,26950,26951,26952,26953,26954,26955,26956,26957,26958,26959,
94880 26960,26961,26962,26963,26964,26965,26966,26967,26968,26969,26970,26971,
94881 26972,26973,26974,26975,26976,26977,26978,26979,26980,26981,26982,26983,
94882 26984,26985,26986,26987,26988,26989,26990,26991,26992,26993,26994,26995,
94883 26996,26997,26998,26999,27000,27001,27002,27003,27004,27005,27006,27007,
94884 27008,27009,27010,27011,27012,27013,27014,27015,27016,27017,27018,27019,
94885 27020,27021,27022,27023,27024,27025,27026,27027,27028,27029,27030,27031,
94886 27032,27033,27034,27035,27036,27037,27038,27039,27040,27041,27042,27043,
94887 27044,27045,27046,27047,27048,27049,27050,27051,27052,27053,27054,27055,
94888 27056,27057,27058,27059,27060,27061,27062,27063,27064,27065,27066,27067,
94889 27068,27069,27070,27071,27072,27073,27074,27075,27076,27077,27078,27079,
94890 27080,27081,27082,27083,27084,27085,27086,27087,27088,27089,27090,27091,
94891 27092,27093,27094,27095,27096,27097,27098,27099,27100,27101,27102,27103,
94892 27104,27105,27106,27107,27108,27109,27110,27111,27112,27113,27114,27115,
94893 27116,27117,27118,27119,27120,27121,27122,27123,27124,27125,27126,27127,
94894 27128,27129,27130,27131,27132,27133,27134,27135,27136,27137,27138,27139,
94895 27140,27141,27142,27143,27144,27145,27146,27147,27148,27149,27150,27151,
94896 27152,27153,27154,27155,27156,27157,27158,27159,27160,27161,27162,27163,
94897 27164,27165,27166,27167,27168,27169,27170,27171,27172,27173,27174,27175,
94898 27176,27177,27178,27179,27180,27181,27182,27183,27184,27185,27186,27187,
94899 27188,27189,27190,27191,27192,27193,27194,27195,27196,27197,27198,27199,
94900 27200,27201,27202,27203,27204,27205,27206,27207,27208,27209,27210,27211,
94901 27212,27213,27214,27215,27216,27217,27218,27219,27220,27221,27222,27223,
94902 27224,27225,27226,27227,27228,27229,27230,27231,27232,27233,27234,27235,
94903 27236,27237,27238,27239,27240,27241,27242,27243,27244,27245,27246,27247,
94904 27248,27249,27250,27251,27252,27253,27254,27255,27256,27257,27258,27259,
94905 27260,27261,27262,27263,27264,27265,27266,27267,27268,27269,27270,27271,
94906 27272,27273,27274,27275,27276,27277,27278,27279,27280,27281,27282,27283,
94907 27284,27285,27286,27287,27288,27289,27290,27291,27292,27293,27294,27295,
94908 27296,27297,27298,27299,27300,27301,27302,27303,27304,27305,27306,27307,
94909 27308,27309,27310,27311,27312,27313,27314,27315,27316,27317,27318,27319,
94910 27320,27321,27322,27323,27324,27325,27326,27327,27328,27329,27330,27331,
94911 27332,27333,27334,27335,27336,27337,27338,27339,27340,27341,27342,27343,
94912 27344,27345,27346,27347,27348,27349,27350,27351,27352,27353,27354,27355,
94913 27356,27357,27358,27359,27360,27361,27362,27363,27364,27365,27366,27367,
94914 27368,27369,27370,27371,27372,27373,27374,27375,27376,27377,27378,27379,
94915 27380,27381,27382,27383,27384,27385,27386,27387,27388,27389,27390,27391,
94916 27392,27393,27394,27395,27396,27397,27398,27399,27400,27401,27402,27403,
94917 27404,27405,27406,27407,27408,27409,27410,27411,27412,27413,27414,27415,
94918 27416,27417,27418,27419,27420,27421,27422,27423,27424,27425,27426,27427,
94919 27428,27429,27430,27431,27432,27433,27434,27435,27436,27437,27438,27439,
94920 27440,27441,27442,27443,27444,27445,27446,27447,27448,27449,27450,27451,
94921 27452,27453,27454,27455,27456,27457,27458,27459,27460,27461,27462,27463,
94922 27464,27465,27466,27467,27468,27469,27470,27471,27472,27473,27474,27475,
94923 27476,27477,27478,27479,27480,27481,27482,27483,27484,27485,27486,27487,
94924 27488,27489,27490,27491,27492,27493,27494,27495,27496,27497,27498,27499,
94925 27500,27501,27502,27503,27504,27505,27506,27507,27508,27509,27510,27511,
94926 27512,27513,27514,27515,27516,27517,27518,27519,27520,27521,27522,27523,
94927 27524,27525,27526,27527,27528,27529,27530,27531,27532,27533,27534,27535,
94928 27536,27537,27538,27539,27540,27541,27542,27543,27544,27545,27546,27547,
94929 27548,27549,27550,27551,27552,27553,27554,27555,27556,27557,27558,27559,
94930 27560,27561,27562,27563,27564,27565,27566,27567,27568,27569,27570,27571,
94931 27572,27573,27574,27575,27576,27577,27578,27579,27580,27581,27582,27583,
94932 27584,27585,27586,27587,27588,27589,27590,27591,27592,27593,27594,27595,
94933 27596,27597,27598,27599,27600,27601,27602,27603,27604,27605,27606,27607,
94934 27608,27609,27610,27611,27612,27613,27614,27615,27616,27617,27618,27619,
94935 27620,27621,27622,27623,27624,27625,27626,27627,27628,27629,27630,27631,
94936 27632,27633,27634,27635,27636,27637,27638,27639,27640,27641,27642,27643,
94937 27644,27645,27646,27647,27648,27649,27650,27651,27652,27653,27654,27655,
94938 27656,27657,27658,27659,27660,27661,27662,27663,27664,27665,27666,27667,
94939 27668,27669,27670,27671,27672,27673,27674,27675,27676,27677,27678,27679,
94940 27680,27681,27682,27683,27684,27685,27686,27687,27688,27689,27690,27691,
94941 27692,27693,27694,27695,27696,27697,27698,27699,27700,27701,27702,27703,
94942 27704,27705,27706,27707,27708,27709,27710,27711,27712,27713,27714,27715,
94943 27716,27717,27718,27719,27720,27721,27722,27723,27724,27725,27726,27727,
94944 27728,27729,27730,27731,27732,27733,27734,27735,27736,27737,27738,27739,
94945 27740,27741,27742,27743,27744,27745,27746,27747,27748,27749,27750,27751,
94946 27752,27753,27754,27755,27756,27757,27758,27759,27760,27761,27762,27763,
94947 27764,27765,27766,27767,27768,27769,27770,27771,27772,27773,27774,27775,
94948 27776,27777,27778,27779,27780,27781,27782,27783,27784,27785,27786,27787,
94949 27788,27789,27790,27791,27792,27793,27794,27795,27796,27797,27798,27799,
94950 27800,27801,27802,27803,27804,27805,27806,27807,27808,27809,27810,27811,
94951 27812,27813,27814,27815,27816,27817,27818,27819,27820,27821,27822,27823,
94952 27824,27825,27826,27827,27828,27829,27830,27831,27832,27833,27834,27835,
94953 27836,27837,27838,27839,27840,27841,27842,27843,27844,27845,27846,27847,
94954 27848,27849,27850,27851,27852,27853,27854,27855,27856,27857,27858,27859,
94955 27860,27861,27862,27863,27864,27865,27866,27867,27868,27869,27870,27871,
94956 27872,27873,27874,27875,27876,27877,27878,27879,27880,27881,27882,27883,
94957 27884,27885,27886,27887,27888,27889,27890,27891,27892,27893,27894,27895,
94958 27896,27897,27898,27899,27900,27901,27902,27903,27904,27905,27906,27907,
94959 27908,27909,27910,27911,27912,27913,27914,27915,27916,27917,27918,27919,
94960 27920,27921,27922,27923,27924,27925,27926,27927,27928,27929,27930,27931,
94961 27932,27933,27934,27935,27936,27937,27938,27939,27940,27941,27942,27943,
94962 27944,27945,27946,27947,27948,27949,27950,27951,27952,27953,27954,27955,
94963 27956,27957,27958,27959,27960,27961,27962,27963,27964,27965,27966,27967,
94964 27968,27969,27970,27971,27972,27973,27974,27975,27976,27977,27978,27979,
94965 27980,27981,27982,27983,27984,27985,27986,27987,27988,27989,27990,27991,
94966 27992,27993,27994,27995,27996,27997,27998,27999,28000,28001,28002,28003,
94967 28004,28005,28006,28007,28008,28009,28010,28011,28012,28013,28014,28015,
94968 28016,28017,28018,28019,28020,28021,28022,28023,28024,28025,28026,28027,
94969 28028,28029,28030,28031,28032,28033,28034,28035,28036,28037,28038,28039,
94970 28040,28041,28042,28043,28044,28045,28046,28047,28048,28049,28050,28051,
94971 28052,28053,28054,28055,28056,28057,28058,28059,28060,28061,28062,28063,
94972 28064,28065,28066,28067,28068,28069,28070,28071,28072,28073,28074,28075,
94973 28076,28077,28078,28079,28080,28081,28082,28083,28084,28085,28086,28087,
94974 28088,28089,28090,28091,28092,28093,28094,28095,28096,28097,28098,28099,
94975 28100,28101,28102,28103,28104,28105,28106,28107,28108,28109,28110,28111,
94976 28112,28113,28114,28115,28116,28117,28118,28119,28120,28121,28122,28123,
94977 28124,28125,28126,28127,28128,28129,28130,28131,28132,28133,28134,28135,
94978 28136,28137,28138,28139,28140,28141,28142,28143,28144,28145,28146,28147,
94979 28148,28149,28150,28151,28152,28153,28154,28155,28156,28157,28158,28159,
94980 28160,28161,28162,28163,28164,28165,28166,28167,28168,28169,28170,28171,
94981 28172,28173,28174,28175,28176,28177,28178,28179,28180,28181,28182,28183,
94982 28184,28185,28186,28187,28188,28189,28190,28191,28192,28193,28194,28195,
94983 28196,28197,28198,28199,28200,28201,28202,28203,28204,28205,28206,28207,
94984 28208,28209,28210,28211,28212,28213,28214,28215,28216,28217,28218,28219,
94985 28220,28221,28222,28223,28224,28225,28226,28227,28228,28229,28230,28231,
94986 28232,28233,28234,28235,28236,28237,28238,28239,28240,28241,28242,28243,
94987 28244,28245,28246,28247,28248,28249,28250,28251,28252,28253,28254,28255,
94988 28256,28257,28258,28259,28260,28261,28262,28263,28264,28265,28266,28267,
94989 28268,28269,28270,28271,28272,28273,28274,28275,28276,28277,28278,28279,
94990 28280,28281,28282,28283,28284,28285,28286,28287,28288,28289,28290,28291,
94991 28292,28293,28294,28295,28296,28297,28298,28299,28300,28301,28302,28303,
94992 28304,28305,28306,28307,28308,28309,28310,28311,28312,28313,28314,28315,
94993 28316,28317,28318,28319,28320,28321,28322,28323,28324,28325,28326,28327,
94994 28328,28329,28330,28331,28332,28333,28334,28335,28336,28337,28338,28339,
94995 28340,28341,28342,28343,28344,28345,28346,28347,28348,28349,28350,28351,
94996 28352,28353,28354,28355,28356,28357,28358,28359,28360,28361,28362,28363,
94997 28364,28365,28366,28367,28368,28369,28370,28371,28372,28373,28374,28375,
94998 28376,28377,28378,28379,28380,28381,28382,28383,28384,28385,28386,28387,
94999 28388,28389,28390,28391,28392,28393,28394,28395,28396,28397,28398,28399,
95000 28400,28401,28402,28403,28404,28405,28406,28407,28408,28409,28410,28411,
95001 28412,28413,28414,28415,28416,28417,28418,28419,28420,28421,28422,28423,
95002 28424,28425,28426,28427,28428,28429,28430,28431,28432,28433,28434,28435,
95003 28436,28437,28438,28439,28440,28441,28442,28443,28444,28445,28446,28447,
95004 28448,28449,28450,28451,28452,28453,28454,28455,28456,28457,28458,28459,
95005 28460,28461,28462,28463,28464,28465,28466,28467,28468,28469,28470,28471,
95006 28472,28473,28474,28475,28476,28477,28478,28479,28480,28481,28482,28483,
95007 28484,28485,28486,28487,28488,28489,28490,28491,28492,28493,28494,28495,
95008 28496,28497,28498,28499,28500,28501,28502,28503,28504,28505,28506,28507,
95009 28508,28509,28510,28511,28512,28513,28514,28515,28516,28517,28518,28519,
95010 28520,28521,28522,28523,28524,28525,28526,28527,28528,28529,28530,28531,
95011 28532,28533,28534,28535,28536,28537,28538,28539,28540,28541,28542,28543,
95012 28544,28545,28546,28547,28548,28549,28550,28551,28552,28553,28554,28555,
95013 28556,28557,28558,28559,28560,28561,28562,28563,28564,28565,28566,28567,
95014 28568,28569,28570,28571,28572,28573,28574,28575,28576,28577,28578,28579,
95015 28580,28581,28582,28583,28584,28585,28586,28587,28588,28589,28590,28591,
95016 28592,28593,28594,28595,28596,28597,28598,28599,28600,28601,28602,28603,
95017 28604,28605,28606,28607,28608,28609,28610,28611,28612,28613,28614,28615,
95018 28616,28617,28618,28619,28620,28621,28622,28623,28624,28625,28626,28627,
95019 28628,28629,28630,28631,28632,28633,28634,28635,28636,28637,28638,28639,
95020 28640,28641,28642,28643,28644,28645,28646,28647,28648,28649,28650,28651,
95021 28652,28653,28654,28655,28656,28657,28658,28659,28660,28661,28662,28663,
95022 28664,28665,28666,28667,28668,28669,28670,28671,28672,28673,28674,28675,
95023 28676,28677,28678,28679,28680,28681,28682,28683,28684,28685,28686,28687,
95024 28688,28689,28690,28691,28692,28693,28694,28695,28696,28697,28698,28699,
95025 28700,28701,28702,28703,28704,28705,28706,28707,28708,28709,28710,28711,
95026 28712,28713,28714,28715,28716,28717,28718,28719,28720,28721,28722,28723,
95027 28724,28725,28726,28727,28728,28729,28730,28731,28732,28733,28734,28735,
95028 28736,28737,28738,28739,28740,28741,28742,28743,28744,28745,28746,28747,
95029 28748,28749,28750,28751,28752,28753,28754,28755,28756,28757,28758,28759,
95030 28760,28761,28762,28763,28764,28765,28766,28767,28768,28769,28770,28771,
95031 28772,28773,28774,28775,28776,28777,28778,28779,28780,28781,28782,28783,
95032 28784,28785,28786,28787,28788,28789,28790,28791,28792,28793,28794,28795,
95033 28796,28797,28798,28799,28800,28801,28802,28803,28804,28805,28806,28807,
95034 28808,28809,28810,28811,28812,28813,28814,28815,28816,28817,28818,28819,
95035 28820,28821,28822,28823,28824,28825,28826,28827,28828,28829,28830,28831,
95036 28832,28833,28834,28835,28836,28837,28838,28839,28840,28841,28842,28843,
95037 28844,28845,28846,28847,28848,28849,28850,28851,28852,28853,28854,28855,
95038 28856,28857,28858,28859,28860,28861,28862,28863,28864,28865,28866,28867,
95039 28868,28869,28870,28871,28872,28873,28874,28875,28876,28877,28878,28879,
95040 28880,28881,28882,28883,28884,28885,28886,28887,28888,28889,28890,28891,
95041 28892,28893,28894,28895,28896,28897,28898,28899,28900,28901,28902,28903,
95042 28904,28905,28906,28907,28908,28909,28910,28911,28912,28913,28914,28915,
95043 28916,28917,28918,28919,28920,28921,28922,28923,28924,28925,28926,28927,
95044 28928,28929,28930,28931,28932,28933,28934,28935,28936,28937,28938,28939,
95045 28940,28941,28942,28943,28944,28945,28946,28947,28948,28949,28950,28951,
95046 28952,28953,28954,28955,28956,28957,28958,28959,28960,28961,28962,28963,
95047 28964,28965,28966,28967,28968,28969,28970,28971,28972,28973,28974,28975,
95048 28976,28977,28978,28979,28980,28981,28982,28983,28984,28985,28986,28987,
95049 28988,28989,28990,28991,28992,28993,28994,28995,28996,28997,28998,28999,
95050 29000,29001,29002,29003,29004,29005,29006,29007,29008,29009,29010,29011,
95051 29012,29013,29014,29015,29016,29017,29018,29019,29020,29021,29022,29023,
95052 29024,29025,29026,29027,29028,29029,29030,29031,29032,29033,29034,29035,
95053 29036,29037,29038,29039,29040,29041,29042,29043,29044,29045,29046,29047,
95054 29048,29049,29050,29051,29052,29053,29054,29055,29056,29057,29058,29059,
95055 29060,29061,29062,29063,29064,29065,29066,29067,29068,29069,29070,29071,
95056 29072,29073,29074,29075,29076,29077,29078,29079,29080,29081,29082,29083,
95057 29084,29085,29086,29087,29088,29089,29090,29091,29092,29093,29094,29095,
95058 29096,29097,29098,29099,29100,29101,29102,29103,29104,29105,29106,29107,
95059 29108,29109,29110,29111,29112,29113,29114,29115,29116,29117,29118,29119,
95060 29120,29121,29122,29123,29124,29125,29126,29127,29128,29129,29130,29131,
95061 29132,29133,29134,29135,29136,29137,29138,29139,29140,29141,29142,29143,
95062 29144,29145,29146,29147,29148,29149,29150,29151,29152,29153,29154,29155,
95063 29156,29157,29158,29159,29160,29161,29162,29163,29164,29165,29166,29167,
95064 29168,29169,29170,29171,29172,29173,29174,29175,29176,29177,29178,29179,
95065 29180,29181,29182,29183,29184,29185,29186,29187,29188,29189,29190,29191,
95066 29192,29193,29194,29195,29196,29197,29198,29199,29200,29201,29202,29203,
95067 29204,29205,29206,29207,29208,29209,29210,29211,29212,29213,29214,29215,
95068 29216,29217,29218,29219,29220,29221,29222,29223,29224,29225,29226,29227,
95069 29228,29229,29230,29231,29232,29233,29234,29235,29236,29237,29238,29239,
95070 29240,29241,29242,29243,29244,29245,29246,29247,29248,29249,29250,29251,
95071 29252,29253,29254,29255,29256,29257,29258,29259,29260,29261,29262,29263,
95072 29264,29265,29266,29267,29268,29269,29270,29271,29272,29273,29274,29275,
95073 29276,29277,29278,29279,29280,29281,29282,29283,29284,29285,29286,29287,
95074 29288,29289,29290,29291,29292,29293,29294,29295,29296,29297,29298,29299,
95075 29300,29301,29302,29303,29304,29305,29306,29307,29308,29309,29310,29311,
95076 29312,29313,29314,29315,29316,29317,29318,29319,29320,29321,29322,29323,
95077 29324,29325,29326,29327,29328,29329,29330,29331,29332,29333,29334,29335,
95078 29336,29337,29338,29339,29340,29341,29342,29343,29344,29345,29346,29347,
95079 29348,29349,29350,29351,29352,29353,29354,29355,29356,29357,29358,29359,
95080 29360,29361,29362,29363,29364,29365,29366,29367,29368,29369,29370,29371,
95081 29372,29373,29374,29375,29376,29377,29378,29379,29380,29381,29382,29383,
95082 29384,29385,29386,29387,29388,29389,29390,29391,29392,29393,29394,29395,
95083 29396,29397,29398,29399,29400,29401,29402,29403,29404,29405,29406,29407,
95084 29408,29409,29410,29411,29412,29413,29414,29415,29416,29417,29418,29419,
95085 29420,29421,29422,29423,29424,29425,29426,29427,29428,29429,29430,29431,
95086 29432,29433,29434,29435,29436,29437,29438,29439,29440,29441,29442,29443,
95087 29444,29445,29446,29447,29448,29449,29450,29451,29452,29453,29454,29455,
95088 29456,29457,29458,29459,29460,29461,29462,29463,29464,29465,29466,29467,
95089 29468,29469,29470,29471,29472,29473,29474,29475,29476,29477,29478,29479,
95090 29480,29481,29482,29483,29484,29485,29486,29487,29488,29489,29490,29491,
95091 29492,29493,29494,29495,29496,29497,29498,29499,29500,29501,29502,29503,
95092 29504,29505,29506,29507,29508,29509,29510,29511,29512,29513,29514,29515,
95093 29516,29517,29518,29519,29520,29521,29522,29523,29524,29525,29526,29527,
95094 29528,29529,29530,29531,29532,29533,29534,29535,29536,29537,29538,29539,
95095 29540,29541,29542,29543,29544,29545,29546,29547,29548,29549,29550,29551,
95096 29552,29553,29554,29555,29556,29557,29558,29559,29560,29561,29562,29563,
95097 29564,29565,29566,29567,29568,29569,29570,29571,29572,29573,29574,29575,
95098 29576,29577,29578,29579,29580,29581,29582,29583,29584,29585,29586,29587,
95099 29588,29589,29590,29591,29592,29593,29594,29595,29596,29597,29598,29599,
95100 29600,29601,29602,29603,29604,29605,29606,29607,29608,29609,29610,29611,
95101 29612,29613,29614,29615,29616,29617,29618,29619,29620,29621,29622,29623,
95102 29624,29625,29626,29627,29628,29629,29630,29631,29632,29633,29634,29635,
95103 29636,29637,29638,29639,29640,29641,29642,29643,29644,29645,29646,29647,
95104 29648,29649,29650,29651,29652,29653,29654,29655,29656,29657,29658,29659,
95105 29660,29661,29662,29663,29664,29665,29666,29667,29668,29669,29670,29671,
95106 29672,29673,29674,29675,29676,29677,29678,29679,29680,29681,29682,29683,
95107 29684,29685,29686,29687,29688,29689,29690,29691,29692,29693,29694,29695,
95108 29696,29697,29698,29699,29700,29701,29702,29703,29704,29705,29706,29707,
95109 29708,29709,29710,29711,29712,29713,29714,29715,29716,29717,29718,29719,
95110 29720,29721,29722,29723,29724,29725,29726,29727,29728,29729,29730,29731,
95111 29732,29733,29734,29735,29736,29737,29738,29739,29740,29741,29742,29743,
95112 29744,29745,29746,29747,29748,29749,29750,29751,29752,29753,29754,29755,
95113 29756,29757,29758,29759,29760,29761,29762,29763,29764,29765,29766,29767,
95114 29768,29769,29770,29771,29772,29773,29774,29775,29776,29777,29778,29779,
95115 29780,29781,29782,29783,29784,29785,29786,29787,29788,29789,29790,29791,
95116 29792,29793,29794,29795,29796,29797,29798,29799,29800,29801,29802,29803,
95117 29804,29805,29806,29807,29808,29809,29810,29811,29812,29813,29814,29815,
95118 29816,29817,29818,29819,29820,29821,29822,29823,29824,29825,29826,29827,
95119 29828,29829,29830,29831,29832,29833,29834,29835,29836,29837,29838,29839,
95120 29840,29841,29842,29843,29844,29845,29846,29847,29848,29849,29850,29851,
95121 29852,29853,29854,29855,29856,29857,29858,29859,29860,29861,29862,29863,
95122 29864,29865,29866,29867,29868,29869,29870,29871,29872,29873,29874,29875,
95123 29876,29877,29878,29879,29880,29881,29882,29883,29884,29885,29886,29887,
95124 29888,29889,29890,29891,29892,29893,29894,29895,29896,29897,29898,29899,
95125 29900,29901,29902,29903,29904,29905,29906,29907,29908,29909,29910,29911,
95126 29912,29913,29914,29915,29916,29917,29918,29919,29920,29921,29922,29923,
95127 29924,29925,29926,29927,29928,29929,29930,29931,29932,29933,29934,29935,
95128 29936,29937,29938,29939,29940,29941,29942,29943,29944,29945,29946,29947,
95129 29948,29949,29950,29951,29952,29953,29954,29955,29956,29957,29958,29959,
95130 29960,29961,29962,29963,29964,29965,29966,29967,29968,29969,29970,29971,
95131 29972,29973,29974,29975,29976,29977,29978,29979,29980,29981,29982,29983,
95132 29984,29985,29986,29987,29988,29989,29990,29991,29992,29993,29994,29995,
95133 29996,29997,29998,29999,30000,30001,30002,30003,30004,30005,30006,30007,
95134 30008,30009,30010,30011,30012,30013,30014,30015,30016,30017,30018,30019,
95135 30020,30021,30022,30023,30024,30025,30026,30027,30028,30029,30030,30031,
95136 30032,30033,30034,30035,30036,30037,30038,30039,30040,30041,30042,30043,
95137 30044,30045,30046,30047,30048,30049,30050,30051,30052,30053,30054,30055,
95138 30056,30057,30058,30059,30060,30061,30062,30063,30064,30065,30066,30067,
95139 30068,30069,30070,30071,30072,30073,30074,30075,30076,30077,30078,30079,
95140 30080,30081,30082,30083,30084,30085,30086,30087,30088,30089,30090,30091,
95141 30092,30093,30094,30095,30096,30097,30098,30099,30100,30101,30102,30103,
95142 30104,30105,30106,30107,30108,30109,30110,30111,30112,30113,30114,30115,
95143 30116,30117,30118,30119,30120,30121,30122,30123,30124,30125,30126,30127,
95144 30128,30129,30130,30131,30132,30133,30134,30135,30136,30137,30138,30139,
95145 30140,30141,30142,30143,30144,30145,30146,30147,30148,30149,30150,30151,
95146 30152,30153,30154,30155,30156,30157,30158,30159,30160,30161,30162,30163,
95147 30164,30165,30166,30167,30168,30169,30170,30171,30172,30173,30174,30175,
95148 30176,30177,30178,30179,30180,30181,30182,30183,30184,30185,30186,30187,
95149 30188,30189,30190,30191,30192,30193,30194,30195,30196,30197,30198,30199,
95150 30200,30201,30202,30203,30204,30205,30206,30207,30208,30209,30210,30211,
95151 30212,30213,30214,30215,30216,30217,30218,30219,30220,30221,30222,30223,
95152 30224,30225,30226,30227,30228,30229,30230,30231,30232,30233,30234,30235,
95153 30236,30237,30238,30239,30240,30241,30242,30243,30244,30245,30246,30247,
95154 30248,30249,30250,30251,30252,30253,30254,30255,30256,30257,30258,30259,
95155 30260,30261,30262,30263,30264,30265,30266,30267,30268,30269,30270,30271,
95156 30272,30273,30274,30275,30276,30277,30278,30279,30280,30281,30282,30283,
95157 30284,30285,30286,30287,30288,30289,30290,30291,30292,30293,30294,30295,
95158 30296,30297,30298,30299,30300,30301,30302,30303,30304,30305,30306,30307,
95159 30308,30309,30310,30311,30312,30313,30314,30315,30316,30317,30318,30319,
95160 30320,30321,30322,30323,30324,30325,30326,30327,30328,30329,30330,30331,
95161 30332,30333,30334,30335,30336,30337,30338,30339,30340,30341,30342,30343,
95162 30344,30345,30346,30347,30348,30349,30350,30351,30352,30353,30354,30355,
95163 30356,30357,30358,30359,30360,30361,30362,30363,30364,30365,30366,30367,
95164 30368,30369,30370,30371,30372,30373,30374,30375,30376,30377,30378,30379,
95165 30380,30381,30382,30383,30384,30385,30386,30387,30388,30389,30390,30391,
95166 30392,30393,30394,30395,30396,30397,30398,30399,30400,30401,30402,30403,
95167 30404,30405,30406,30407,30408,30409,30410,30411,30412,30413,30414,30415,
95168 30416,30417,30418,30419,30420,30421,30422,30423,30424,30425,30426,30427,
95169 30428,30429,30430,30431,30432,30433,30434,30435,30436,30437,30438,30439,
95170 30440,30441,30442,30443,30444,30445,30446,30447,30448,30449,30450,30451,
95171 30452,30453,30454,30455,30456,30457,30458,30459,30460,30461,30462,30463,
95172 30464,30465,30466,30467,30468,30469,30470,30471,30472,30473,30474,30475,
95173 30476,30477,30478,30479,30480,30481,30482,30483,30484,30485,30486,30487,
95174 30488,30489,30490,30491,30492,30493,30494,30495,30496,30497,30498,30499,
95175 30500,30501,30502,30503,30504,30505,30506,30507,30508,30509,30510,30511,
95176 30512,30513,30514,30515,30516,30517,30518,30519,30520,30521,30522,30523,
95177 30524,30525,30526,30527,30528,30529,30530,30531,30532,30533,30534,30535,
95178 30536,30537,30538,30539,30540,30541,30542,30543,30544,30545,30546,30547,
95179 30548,30549,30550,30551,30552,30553,30554,30555,30556,30557,30558,30559,
95180 30560,30561,30562,30563,30564,30565,30566,30567,30568,30569,30570,30571,
95181 30572,30573,30574,30575,30576,30577,30578,30579,30580,30581,30582,30583,
95182 30584,30585,30586,30587,30588,30589,30590,30591,30592,30593,30594,30595,
95183 30596,30597,30598,30599,30600,30601,30602,30603,30604,30605,30606,30607,
95184 30608,30609,30610,30611,30612,30613,30614,30615,30616,30617,30618,30619,
95185 30620,30621,30622,30623,30624,30625,30626,30627,30628,30629,30630,30631,
95186 30632,30633,30634,30635,30636,30637,30638,30639,30640,30641,30642,30643,
95187 30644,30645,30646,30647,30648,30649,30650,30651,30652,30653,30654,30655,
95188 30656,30657,30658,30659,30660,30661,30662,30663,30664,30665,30666,30667,
95189 30668,30669,30670,30671,30672,30673,30674,30675,30676,30677,30678,30679,
95190 30680,30681,30682,30683,30684,30685,30686,30687,30688,30689,30690,30691,
95191 30692,30693,30694,30695,30696,30697,30698,30699,30700,30701,30702,30703,
95192 30704,30705,30706,30707,30708,30709,30710,30711,30712,30713,30714,30715,
95193 30716,30717,30718,30719,30720,30721,30722,30723,30724,30725,30726,30727,
95194 30728,30729,30730,30731,30732,30733,30734,30735,30736,30737,30738,30739,
95195 30740,30741,30742,30743,30744,30745,30746,30747,30748,30749,30750,30751,
95196 30752,30753,30754,30755,30756,30757,30758,30759,30760,30761,30762,30763,
95197 30764,30765,30766,30767,30768,30769,30770,30771,30772,30773,30774,30775,
95198 30776,30777,30778,30779,30780,30781,30782,30783,30784,30785,30786,30787,
95199 30788,30789,30790,30791,30792,30793,30794,30795,30796,30797,30798,30799,
95200 30800,30801,30802,30803,30804,30805,30806,30807,30808,30809,30810,30811,
95201 30812,30813,30814,30815,30816,30817,30818,30819,30820,30821,30822,30823,
95202 30824,30825,30826,30827,30828,30829,30830,30831,30832,30833,30834,30835,
95203 30836,30837,30838,30839,30840,30841,30842,30843,30844,30845,30846,30847,
95204 30848,30849,30850,30851,30852,30853,30854,30855,30856,30857,30858,30859,
95205 30860,30861,30862,30863,30864,30865,30866,30867,30868,30869,30870,30871,
95206 30872,30873,30874,30875,30876,30877,30878,30879,30880,30881,30882,30883,
95207 30884,30885,30886,30887,30888,30889,30890,30891,30892,30893,30894,30895,
95208 30896,30897,30898,30899,30900,30901,30902,30903,30904,30905,30906,30907,
95209 30908,30909,30910,30911,30912,30913,30914,30915,30916,30917,30918,30919,
95210 30920,30921,30922,30923,30924,30925,30926,30927,30928,30929,30930,30931,
95211 30932,30933,30934,30935,30936,30937,30938,30939,30940,30941,30942,30943,
95212 30944,30945,30946,30947,30948,30949,30950,30951,30952,30953,30954,30955,
95213 30956,30957,30958,30959,30960,30961,30962,30963,30964,30965,30966,30967,
95214 30968,30969,30970,30971,30972,30973,30974,30975,30976,30977,30978,30979,
95215 30980,30981,30982,30983,30984,30985,30986,30987,30988,30989,30990,30991,
95216 30992,30993,30994,30995,30996,30997,30998,30999,31000,31001,31002,31003,
95217 31004,31005,31006,31007,31008,31009,31010,31011,31012,31013,31014,31015,
95218 31016,31017,31018,31019,31020,31021,31022,31023,31024,31025,31026,31027,
95219 31028,31029,31030,31031,31032,31033,31034,31035,31036,31037,31038,31039,
95220 31040,31041,31042,31043,31044,31045,31046,31047,31048,31049,31050,31051,
95221 31052,31053,31054,31055,31056,31057,31058,31059,31060,31061,31062,31063,
95222 31064,31065,31066,31067,31068,31069,31070,31071,31072,31073,31074,31075,
95223 31076,31077,31078,31079,31080,31081,31082,31083,31084,31085,31086,31087,
95224 31088,31089,31090,31091,31092,31093,31094,31095,31096,31097,31098,31099,
95225 31100,31101,31102,31103,31104,31105,31106,31107,31108,31109,31110,31111,
95226 31112,31113,31114,31115,31116,31117,31118,31119,31120,31121,31122,31123,
95227 31124,31125,31126,31127,31128,31129,31130,31131,31132,31133,31134,31135,
95228 31136,31137,31138,31139,31140,31141,31142,31143,31144,31145,31146,31147,
95229 31148,31149,31150,31151,31152,31153,31154,31155,31156,31157,31158,31159,
95230 31160,31161,31162,31163,31164,31165,31166,31167,31168,31169,31170,31171,
95231 31172,31173,31174,31175,31176,31177,31178,31179,31180,31181,31182,31183,
95232 31184,31185,31186,31187,31188,31189,31190,31191,31192,31193,31194,31195,
95233 31196,31197,31198,31199,31200,31201,31202,31203,31204,31205,31206,31207,
95234 31208,31209,31210,31211,31212,31213,31214,31215,31216,31217,31218,31219,
95235 31220,31221,31222,31223,31224,31225,31226,31227,31228,31229,31230,31231,
95236 31232,31233,31234,31235,31236,31237,31238,31239,31240,31241,31242,31243,
95237 31244,31245,31246,31247,31248,31249,31250,31251,31252,31253,31254,31255,
95238 31256,31257,31258,31259,31260,31261,31262,31263,31264,31265,31266,31267,
95239 31268,31269,31270,31271,31272,31273,31274,31275,31276,31277,31278,31279,
95240 31280,31281,31282,31283,31284,31285,31286,31287,31288,31289,31290,31291,
95241 31292,31293,31294,31295,31296,31297,31298,31299,31300,31301,31302,31303,
95242 31304,31305,31306,31307,31308,31309,31310,31311,31312,31313,31314,31315,
95243 31316,31317,31318,31319,31320,31321,31322,31323,31324,31325,31326,31327,
95244 31328,31329,31330,31331,31332,31333,31334,31335,31336,31337,31338,31339,
95245 31340,31341,31342,31343,31344,31345,31346,31347,31348,31349,31350,31351,
95246 31352,31353,31354,31355,31356,31357,31358,31359,31360,31361,31362,31363,
95247 31364,31365,31366,31367,31368,31369,31370,31371,31372,31373,31374,31375,
95248 31376,31377,31378,31379,31380,31381,31382,31383,31384,31385,31386,31387,
95249 31388,31389,31390,31391,31392,31393,31394,31395,31396,31397,31398,31399,
95250 31400,31401,31402,31403,31404,31405,31406,31407,31408,31409,31410,31411,
95251 31412,31413,31414,31415,31416,31417,31418,31419,31420,31421,31422,31423,
95252 31424,31425,31426,31427,31428,31429,31430,31431,31432,31433,31434,31435,
95253 31436,31437,31438,31439,31440,31441,31442,31443,31444,31445,31446,31447,
95254 31448,31449,31450,31451,31452,31453,31454,31455,31456,31457,31458,31459,
95255 31460,31461,31462,31463,31464,31465,31466,31467,31468,31469,31470,31471,
95256 31472,31473,31474,31475,31476,31477,31478,31479,31480,31481,31482,31483,
95257 31484,31485,31486,31487,31488,31489,31490,31491,31492,31493,31494,31495,
95258 31496,31497,31498,31499,31500,31501,31502,31503,31504,31505,31506,31507,
95259 31508,31509,31510,31511,31512,31513,31514,31515,31516,31517,31518,31519,
95260 31520,31521,31522,31523,31524,31525,31526,31527,31528,31529,31530,31531,
95261 31532,31533,31534,31535,31536,31537,31538,31539,31540,31541,31542,31543,
95262 31544,31545,31546,31547,31548,31549,31550,31551,31552,31553,31554,31555,
95263 31556,31557,31558,31559,31560,31561,31562,31563,31564,31565,31566,31567,
95264 31568,31569,31570,31571,31572,31573,31574,31575,31576,31577,31578,31579,
95265 31580,31581,31582,31583,31584,31585,31586,31587,31588,31589,31590,31591,
95266 31592,31593,31594,31595,31596,31597,31598,31599,31600,31601,31602,31603,
95267 31604,31605,31606,31607,31608,31609,31610,31611,31612,31613,31614,31615,
95268 31616,31617,31618,31619,31620,31621,31622,31623,31624,31625,31626,31627,
95269 31628,31629,31630,31631,31632,31633,31634,31635,31636,31637,31638,31639,
95270 31640,31641,31642,31643,31644,31645,31646,31647,31648,31649,31650,31651,
95271 31652,31653,31654,31655,31656,31657,31658,31659,31660,31661,31662,31663,
95272 31664,31665,31666,31667,31668,31669,31670,31671,31672,31673,31674,31675,
95273 31676,31677,31678,31679,31680,31681,31682,31683,31684,31685,31686,31687,
95274 31688,31689,31690,31691,31692,31693,31694,31695,31696,31697,31698,31699,
95275 31700,31701,31702,31703,31704,31705,31706,31707,31708,31709,31710,31711,
95276 31712,31713,31714,31715,31716,31717,31718,31719,31720,31721,31722,31723,
95277 31724,31725,31726,31727,31728,31729,31730,31731,31732,31733,31734,31735,
95278 31736,31737,31738,31739,31740,31741,31742,31743,31744,31745,31746,31747,
95279 31748,31749,31750,31751,31752,31753,31754,31755,31756,31757,31758,31759,
95280 31760,31761,31762,31763,31764,31765,31766,31767,31768,31769,31770,31771,
95281 31772,31773,31774,31775,31776,31777,31778,31779,31780,31781,31782,31783,
95282 31784,31785,31786,31787,31788,31789,31790,31791,31792,31793,31794,31795,
95283 31796,31797,31798,31799,31800,31801,31802,31803,31804,31805,31806,31807,
95284 31808,31809,31810,31811,31812,31813,31814,31815,31816,31817,31818,31819,
95285 31820,31821,31822,31823,31824,31825,31826,31827,31828,31829,31830,31831,
95286 31832,31833,31834,31835,31836,31837,31838,31839,31840,31841,31842,31843,
95287 31844,31845,31846,31847,31848,31849,31850,31851,31852,31853,31854,31855,
95288 31856,31857,31858,31859,31860,31861,31862,31863,31864,31865,31866,31867,
95289 31868,31869,31870,31871,31872,31873,31874,31875,31876,31877,31878,31879,
95290 31880,31881,31882,31883,31884,31885,31886,31887,31888,31889,31890,31891,
95291 31892,31893,31894,31895,31896,31897,31898,31899,31900,31901,31902,31903,
95292 31904,31905,31906,31907,31908,31909,31910,31911,31912,31913,31914,31915,
95293 31916,31917,31918,31919,31920,31921,31922,31923,31924,31925,31926,31927,
95294 31928,31929,31930,31931,31932,31933,31934,31935,31936,31937,31938,31939,
95295 31940,31941,31942,31943,31944,31945,31946,31947,31948,31949,31950,31951,
95296 31952,31953,31954,31955,31956,31957,31958,31959,31960,31961,31962,31963,
95297 31964,31965,31966,31967,31968,31969,31970,31971,31972,31973,31974,31975,
95298 31976,31977,31978,31979,31980,31981,31982,31983,31984,31985,31986,31987,
95299 31988,31989,31990,31991,31992,31993,31994,31995,31996,31997,31998,31999,
95300 32000,32001,32002,32003,32004,32005,32006,32007,32008,32009,32010,32011,
95301 32012,32013,32014,32015,32016,32017,32018,32019,32020,32021,32022,32023,
95302 32024,32025,32026,32027,32028,32029,32030,32031,32032,32033,32034,32035,
95303 32036,32037,32038,32039,32040,32041,32042,32043,32044,32045,32046,32047,
95304 32048,32049,32050,32051,32052,32053,32054,32055,32056,32057,32058,32059,
95305 32060,32061,32062,32063,32064,32065,32066,32067,32068,32069,32070,32071,
95306 32072,32073,32074,32075,32076,32077,32078,32079,32080,32081,32082,32083,
95307 32084,32085,32086,32087,32088,32089,32090,32091,32092,32093,32094,32095,
95308 32096,32097,32098,32099,32100,32101,32102,32103,32104,32105,32106,32107,
95309 32108,32109,32110,32111,32112,32113,32114,32115,32116,32117,32118,32119,
95310 32120,32121,32122,32123,32124,32125,32126,32127,32128,32129,32130,32131,
95311 32132,32133,32134,32135,32136,32137,32138,32139,32140,32141,32142,32143,
95312 32144,32145,32146,32147,32148,32149,32150,32151,32152,32153,32154,32155,
95313 32156,32157,32158,32159,32160,32161,32162,32163,32164,32165,32166,32167,
95314 32168,32169,32170,32171,32172,32173,32174,32175,32176,32177,32178,32179,
95315 32180,32181,32182,32183,32184,32185,32186,32187,32188,32189,32190,32191,
95316 32192,32193,32194,32195,32196,32197,32198,32199,32200,32201,32202,32203,
95317 32204,32205,32206,32207,32208,32209,32210,32211,32212,32213,32214,32215,
95318 32216,32217,32218,32219,32220,32221,32222,32223,32224,32225,32226,32227,
95319 32228,32229,32230,32231,32232,32233,32234,32235,32236,32237,32238,32239,
95320 32240,32241,32242,32243,32244,32245,32246,32247,32248,32249,32250,32251,
95321 32252,32253,32254,32255,32256,32257,32258,32259,32260,32261,32262,32263,
95322 32264,32265,32266,32267,32268,32269,32270,32271,32272,32273,32274,32275,
95323 32276,32277,32278,32279,32280,32281,32282,32283,32284,32285,32286,32287,
95324 32288,32289,32290,32291,32292,32293,32294,32295,32296,32297,32298,32299,
95325 32300,32301,32302,32303,32304,32305,32306,32307,32308,32309,32310,32311,
95326 32312,32313,32314,32315,32316,32317,32318,32319,32320,32321,32322,32323,
95327 32324,32325,32326,32327,32328,32329,32330,32331,32332,32333,32334,32335,
95328 32336,32337,32338,32339,32340,32341,32342,32343,32344,32345,32346,32347,
95329 32348,32349,32350,32351,32352,32353,32354,32355,32356,32357,32358,32359,
95330 32360,32361,32362,32363,32364,32365,32366,32367,32368,32369,32370,32371,
95331 32372,32373,32374,32375,32376,32377,32378,32379,32380,32381,32382,32383,
95332 32384,32385,32386,32387,32388,32389,32390,32391,32392,32393,32394,32395,
95333 32396,32397,32398,32399,32400,32401,32402,32403,32404,32405,32406,32407,
95334 32408,32409,32410,32411,32412,32413,32414,32415,32416,32417,32418,32419,
95335 32420,32421,32422,32423,32424,32425,32426,32427,32428,32429,32430,32431,
95336 32432,32433,32434,32435,32436,32437,32438,32439,32440,32441,32442,32443,
95337 32444,32445,32446,32447,32448,32449,32450,32451,32452,32453,32454,32455,
95338 32456,32457,32458,32459,32460,32461,32462,32463,32464,32465,32466,32467,
95339 32468,32469,32470,32471,32472,32473,32474,32475,32476,32477,32478,32479,
95340 32480,32481,32482,32483,32484,32485,32486,32487,32488,32489,32490,32491,
95341 32492,32493,32494,32495,32496,32497,32498,32499,32500,32501,32502,32503,
95342 32504,32505,32506,32507,32508,32509,32510,32511,32512,32513,32514,32515,
95343 32516,32517,32518,32519,32520,32521,32522,32523,32524,32525,32526,32527,
95344 32528,32529,32530,32531,32532,32533,32534,32535,32536,32537,32538,32539,
95345 32540,32541,32542,32543,32544,32545,32546,32547,32548,32549,32550,32551,
95346 32552,32553,32554,32555,32556,32557,32558,32559,32560,32561,32562,32563,
95347 32564,32565,32566,32567,32568,32569,32570,32571,32572,32573,32574,32575,
95348 32576,32577,32578,32579,32580,32581,32582,32583,32584,32585,32586,32587,
95349 32588,32589,32590,32591,32592,32593,32594,32595,32596,32597,32598,32599,
95350 32600,32601,32602,32603,32604,32605,32606,32607,32608,32609,32610,32611,
95351 32612,32613,32614,32615,32616,32617,32618,32619,32620,32621,32622,32623,
95352 32624,32625,32626,32627,32628,32629,32630,32631,32632,32633,32634,32635,
95353 32636,32637,32638,32639,32640,32641,32642,32643,32644,32645,32646,32647,
95354 32648,32649,32650,32651,32652,32653,32654,32655,32656,32657,32658,32659,
95355 32660,32661,32662,32663,32664,32665,32666,32667,32668,32669,32670,32671,
95356 32672,32673,32674,32675,32676,32677,32678,32679,32680,32681,32682,32683,
95357 32684,32685,32686,32687,32688,32689,32690,32691,32692,32693,32694,32695,
95358 32696,32697,32698,32699,32700,32701,32702,32703,32704,32705,32706,32707,
95359 32708,32709,32710,32711,32712,32713,32714,32715,32716,32717,32718,32719,
95360 32720,32721,32722,32723,32724,32725,32726,32727,32728,32729,32730,32731,
95361 32732,32733,32734,32735,32736,32737,32738,32739,32740,32741,32742,32743,
95362 32744,32745,32746,32747,32748,32749,32750,32751,32752,32753,32754,32755,
95363 32756,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,
95364 32768L,32769L,32770L,32771L,32772L,32773L,32774L,32775L,32776L,32777L,
95365 32778L,32779L,32780L,32781L,32782L,32783L,32784L,32785L,32786L,32787L,
95366 32788L,32789L,32790L,32791L,32792L,32793L,32794L,32795L,32796L,32797L,
95367 32798L,32799L,32800L,32801L,32802L,32803L,32804L,32805L,32806L,32807L,
95368 32808L,32809L,32810L,32811L,32812L,32813L,32814L,32815L,32816L,32817L,
95369 32818L,32819L,32820L,32821L,32822L,32823L,32824L,32825L,32826L,32827L,
95370 32828L,32829L,32830L,32831L,32832L,32833L,32834L,32835L,32836L,32837L,
95371 32838L,32839L,32840L,32841L,32842L,32843L,32844L,32845L,32846L,32847L,
95372 32848L,32849L,32850L,32851L,32852L,32853L,32854L,32855L,32856L,32857L,
95373 32858L,32859L,32860L,32861L,32862L,32863L,32864L,32865L,32866L,32867L,
95374 32868L,32869L,32870L,32871L,32872L,32873L,32874L,32875L,32876L,32877L,
95375 32878L,32879L,32880L,32881L,32882L,32883L,32884L,32885L,32886L,32887L,
95376 32888L,32889L,32890L,32891L,32892L,32893L,32894L,32895L,32896L,32897L,
95377 32898L,32899L,32900L,32901L,32902L,32903L,32904L,32905L,32906L,32907L,
95378 32908L,32909L,32910L,32911L,32912L,32913L,32914L,32915L,32916L,32917L,
95379 32918L,32919L,32920L,32921L,32922L,32923L,32924L,32925L,32926L,32927L,
95380 32928L,32929L,32930L,32931L,32932L,32933L,32934L,32935L,32936L,32937L,
95381 32938L,32939L,32940L,32941L,32942L,32943L,32944L,32945L,32946L,32947L,
95382 32948L,32949L,32950L,32951L,32952L,32953L,32954L,32955L,32956L,32957L,
95383 32958L,32959L,32960L,32961L,32962L,32963L,32964L,32965L,32966L,32967L,
95384 32968L,32969L,32970L,32971L,32972L,32973L,32974L,32975L,32976L,32977L,
95385 32978L,32979L,32980L,32981L,32982L,32983L,32984L,32985L,32986L,32987L,
95386 32988L,32989L,32990L,32991L,32992L,32993L,32994L,32995L,32996L,32997L,
95387 32998L,32999L,33000L,33001L,33002L,33003L,33004L,33005L,33006L,33007L,
95388 33008L,33009L,33010L,33011L,33012L,33013L,33014L,33015L,33016L,33017L,
95389 33018L,33019L,33020L,33021L,33022L,33023L,33024L,33025L,33026L,33027L,
95390 33028L,33029L,33030L,33031L,33032L,33033L,33034L,33035L,33036L,33037L,
95391 33038L,33039L,33040L,33041L,33042L,33043L,33044L,33045L,33046L,33047L,
95392 33048L,33049L,33050L,33051L,33052L,33053L,33054L,33055L,33056L,33057L,
95393 33058L,33059L,33060L,33061L,33062L,33063L,33064L,33065L,33066L,33067L,
95394 33068L,33069L,33070L,33071L,33072L,33073L,33074L,33075L,33076L,33077L,
95395 33078L,33079L,33080L,33081L,33082L,33083L,33084L,33085L,33086L,33087L,
95396 33088L,33089L,33090L,33091L,33092L,33093L,33094L,33095L,33096L,33097L,
95397 33098L,33099L,33100L,33101L,33102L,33103L,33104L,33105L,33106L,33107L,
95398 33108L,33109L,33110L,33111L,33112L,33113L,33114L,33115L,33116L,33117L,
95399 33118L,33119L,33120L,33121L,33122L,33123L,33124L,33125L,33126L,33127L,
95400 33128L,33129L,33130L,33131L,33132L,33133L,33134L,33135L,33136L,33137L,
95401 33138L,33139L,33140L,33141L,33142L,33143L,33144L,33145L,33146L,33147L,
95402 33148L,33149L,33150L,33151L,33152L,33153L,33154L,33155L,33156L,33157L,
95403 33158L,33159L,33160L,33161L,33162L,33163L,33164L,33165L,33166L,33167L,
95404 33168L,33169L,33170L,33171L,33172L,33173L,33174L,33175L,33176L,33177L,
95405 33178L,33179L,33180L,33181L,33182L,33183L,33184L,33185L,33186L,33187L,
95406 33188L,33189L,33190L,33191L,33192L,33193L,33194L,33195L,33196L,33197L,
95407 33198L,33199L,33200L,33201L,33202L,33203L,33204L,33205L,33206L,33207L,
95408 33208L,33209L,33210L,33211L,33212L,33213L,33214L,33215L,33216L,33217L,
95409 33218L,33219L,33220L,33221L,33222L,33223L,33224L,33225L,33226L,33227L,
95410 33228L,33229L,33230L,33231L,33232L,33233L,33234L,33235L,33236L,33237L,
95411 33238L,33239L,33240L,33241L,33242L,33243L,33244L,33245L,33246L,33247L,
95412 33248L,33249L,33250L,33251L,33252L,33253L,33254L,33255L,33256L,33257L,
95413 33258L,33259L,33260L,33261L,33262L,33263L,33264L,33265L,33266L,33267L,
95414 33268L,33269L,33270L,33271L,33272L,33273L,33274L,33275L,33276L,33277L,
95415 33278L,33279L,33280L,33281L,33282L,33283L,33284L,33285L,33286L,33287L,
95416 33288L,33289L,33290L,33291L,33292L,33293L,33294L,33295L,33296L,33297L,
95417 33298L,33299L,33300L,33301L,33302L,33303L,33304L,33305L,33306L,33307L,
95418 33308L,33309L,33310L,33311L,33312L,33313L,33314L,33315L,33316L,33317L,
95419 33318L,33319L,33320L,33321L,33322L,33323L,33324L,33325L,33326L,33327L,
95420 33328L,33329L,33330L,33331L,33332L,33333L,33334L,33335L,33336L,33337L,
95421 33338L,33339L,33340L,33341L,33342L,33343L,33344L,33345L,33346L,33347L,
95422 33348L,33349L,33350L,33351L,33352L,33353L,33354L,33355L,33356L,33357L,
95423 33358L,33359L,33360L,33361L,33362L,33363L,33364L,33365L,33366L,33367L,
95424 33368L,33369L,33370L,33371L,33372L,33373L,33374L,33375L,33376L,33377L,
95425 33378L,33379L,33380L,33381L,33382L,33383L,33384L,33385L,33386L,33387L,
95426 33388L,33389L,33390L,33391L,33392L,33393L,33394L,33395L,33396L,33397L,
95427 33398L,33399L,33400L,33401L,33402L,33403L,33404L,33405L,33406L,33407L,
95428 33408L,33409L,33410L,33411L,33412L,33413L,33414L,33415L,33416L,33417L,
95429 33418L,33419L,33420L,33421L,33422L,33423L,33424L,33425L,33426L,33427L,
95430 33428L,33429L,33430L,33431L,33432L,33433L,33434L,33435L,33436L,33437L,
95431 33438L,33439L,33440L,33441L,33442L,33443L,33444L,33445L,33446L,33447L,
95432 33448L,33449L,33450L,33451L,33452L,33453L,33454L,33455L,33456L,33457L,
95433 33458L,33459L,33460L,33461L,33462L,33463L,33464L,33465L,33466L,33467L,
95434 33468L,33469L,33470L,33471L,33472L,33473L,33474L,33475L,33476L,33477L,
95435 33478L,33479L,33480L,33481L,33482L,33483L,33484L,33485L,33486L,33487L,
95436 33488L,33489L,33490L,33491L,33492L,33493L,33494L,33495L,33496L,33497L,
95437 33498L,33499L,33500L,33501L,33502L,33503L,33504L,33505L,33506L,33507L,
95438 33508L,33509L,33510L,33511L,33512L,33513L,33514L,33515L,33516L,33517L,
95439 33518L,33519L,33520L,33521L,33522L,33523L,33524L,33525L,33526L,33527L,
95440 33528L,33529L,33530L,33531L,33532L,33533L,33534L,33535L,33536L,33537L,
95441 33538L,33539L,33540L,33541L,33542L,33543L,33544L,33545L,33546L,33547L,
95442 33548L,33549L,33550L,33551L,33552L,33553L,33554L,33555L,33556L,33557L,
95443 33558L,33559L,33560L,33561L,33562L,33563L,33564L,33565L,33566L,33567L,
95444 33568L,33569L,33570L,33571L,33572L,33573L,33574L,33575L,33576L,33577L,
95445 33578L,33579L,33580L,33581L,33582L,33583L,33584L,33585L,33586L,33587L,
95446 33588L,33589L,33590L,33591L,33592L,33593L,33594L,33595L,33596L,33597L,
95447 33598L,33599L,33600L,33601L,33602L,33603L,33604L,33605L,33606L,33607L,
95448 33608L,33609L,33610L,33611L,33612L,33613L,33614L,33615L,33616L,33617L,
95449 33618L,33619L,33620L,33621L,33622L,33623L,33624L,33625L,33626L,33627L,
95450 33628L,33629L,33630L,33631L,33632L,33633L,33634L,33635L,33636L,33637L,
95451 33638L,33639L,33640L,33641L,33642L,33643L,33644L,33645L,33646L,33647L,
95452 33648L,33649L,33650L,33651L,33652L,33653L,33654L,33655L,33656L,33657L,
95453 33658L,33659L,33660L,33661L,33662L,33663L,33664L,33665L,33666L,33667L,
95454 33668L,33669L,33670L,33671L,33672L,33673L,33674L,33675L,33676L,33677L,
95455 33678L,33679L,33680L,33681L,33682L,33683L,33684L,33685L,33686L,33687L,
95456 33688L,33689L,33690L,33691L,33692L,33693L,33694L,33695L,33696L,33697L,
95457 33698L,33699L,33700L,33701L,33702L,33703L,33704L,33705L,33706L,33707L,
95458 33708L,33709L,33710L,33711L,33712L,33713L,33714L,33715L,33716L,33717L,
95459 33718L,33719L,33720L,33721L,33722L,33723L,33724L,33725L,33726L,33727L,
95460 33728L,33729L,33730L,33731L,33732L,33733L,33734L,33735L,33736L,33737L,
95461 33738L,33739L,33740L,33741L,33742L,33743L,33744L,33745L,33746L,33747L,
95462 33748L,33749L,33750L,33751L,33752L,33753L,33754L,33755L,33756L,33757L,
95463 33758L,33759L,33760L,33761L,33762L,33763L,33764L,33765L,33766L,33767L,
95464 33768L,33769L,33770L,33771L,33772L,33773L,33774L,33775L,33776L,33777L,
95465 33778L,33779L,33780L,33781L,33782L,33783L,33784L,33785L,33786L,33787L,
95466 33788L,33789L,33790L,33791L,33792L,33793L,33794L,33795L,33796L,33797L,
95467 33798L,33799L,33800L,33801L,33802L,33803L,33804L,33805L,33806L,33807L,
95468 33808L,33809L,33810L,33811L,33812L,33813L,33814L,33815L,33816L,33817L,
95469 33818L,33819L,33820L,33821L,33822L,33823L,33824L,33825L,33826L,33827L,
95470 33828L,33829L,33830L,33831L,33832L,33833L,33834L,33835L,33836L,33837L,
95471 33838L,33839L,33840L,33841L,33842L,33843L,33844L,33845L,33846L,33847L,
95472 33848L,33849L,33850L,33851L,33852L,33853L,33854L,33855L,33856L,33857L,
95473 33858L,33859L,33860L,33861L,33862L,33863L,33864L,33865L,33866L,33867L,
95474 33868L,33869L,33870L,33871L,33872L,33873L,33874L,33875L,33876L,33877L,
95475 33878L,33879L,33880L,33881L,33882L,33883L,33884L,33885L,33886L,33887L,
95476 33888L,33889L,33890L,33891L,33892L,33893L,33894L,33895L,33896L,33897L,
95477 33898L,33899L,33900L,33901L,33902L,33903L,33904L,33905L,33906L,33907L,
95478 33908L,33909L,33910L,33911L,33912L,33913L,33914L,33915L,33916L,33917L,
95479 33918L,33919L,33920L,33921L,33922L,33923L,33924L,33925L,33926L,33927L,
95480 33928L,33929L,33930L,33931L,33932L,33933L,33934L,33935L,33936L,33937L,
95481 33938L,33939L,33940L,33941L,33942L,33943L,33944L,33945L,33946L,33947L,
95482 33948L,33949L,33950L,33951L,33952L,33953L,33954L,33955L,33956L,33957L,
95483 33958L,33959L,33960L,33961L,33962L,33963L,33964L,33965L,33966L,33967L,
95484 33968L,33969L,33970L,33971L,33972L,33973L,33974L,33975L,33976L,33977L,
95485 33978L,33979L,33980L,33981L,33982L,33983L,33984L,33985L,33986L,33987L,
95486 33988L,33989L,33990L,33991L,33992L,33993L,33994L,33995L,33996L,33997L,
95487 33998L,33999L,34000L,34001L,34002L,34003L,34004L,34005L,34006L,34007L,
95488 34008L,34009L,34010L,34011L,34012L,34013L,34014L,34015L,34016L,34017L,
95489 34018L,34019L,34020L,34021L,34022L,34023L,34024L,34025L,34026L,34027L,
95490 34028L,34029L,34030L,34031L,34032L,34033L,34034L,34035L,34036L,34037L,
95491 34038L,34039L,34040L,34041L,34042L,34043L,34044L,34045L,34046L,34047L,
95492 34048L,34049L,34050L,34051L,34052L,34053L,34054L,34055L,34056L,34057L,
95493 34058L,34059L,34060L,34061L,34062L,34063L,34064L,34065L,34066L,34067L,
95494 34068L,34069L,34070L,34071L,34072L,34073L,34074L,34075L,34076L,34077L,
95495 34078L,34079L,34080L,34081L,34082L,34083L,34084L,34085L,34086L,34087L,
95496 34088L,34089L,34090L,34091L,34092L,34093L,34094L,34095L,34096L,34097L,
95497 34098L,34099L,34100L,34101L,34102L,34103L,34104L,34105L,34106L,34107L,
95498 34108L,34109L,34110L,34111L,34112L,34113L,34114L,34115L,34116L,34117L,
95499 34118L,34119L,34120L,34121L,34122L,34123L,34124L,34125L,34126L,34127L,
95500 34128L,34129L,34130L,34131L,34132L,34133L,34134L,34135L,34136L,34137L,
95501 34138L,34139L,34140L,34141L,34142L,34143L,34144L,34145L,34146L,34147L,
95502 34148L,34149L,34150L,34151L,34152L,34153L,34154L,34155L,34156L,34157L,
95503 34158L,34159L,34160L,34161L,34162L,34163L,34164L,34165L,34166L,34167L,
95504 34168L,34169L,34170L,34171L,34172L,34173L,34174L,34175L,34176L,34177L,
95505 34178L,34179L,34180L,34181L,34182L,34183L,34184L,34185L,34186L,34187L,
95506 34188L,34189L,34190L,34191L,34192L,34193L,34194L,34195L,34196L,34197L,
95507 34198L,34199L,34200L,34201L,34202L,34203L,34204L,34205L,34206L,34207L,
95508 34208L,34209L,34210L,34211L,34212L,34213L,34214L,34215L,34216L,34217L,
95509 34218L,34219L,34220L,34221L,34222L,34223L,34224L,34225L,34226L,34227L,
95510 34228L,34229L,34230L,34231L,34232L,34233L,34234L,34235L,34236L,34237L,
95511 34238L,34239L,34240L,34241L,34242L,34243L,34244L,34245L,34246L,34247L,
95512 34248L,34249L,34250L,34251L,34252L,34253L,34254L,34255L,34256L,34257L,
95513 34258L,34259L,34260L,34261L,34262L,34263L,34264L,34265L,34266L,34267L,
95514 34268L,34269L,34270L,34271L,34272L,34273L,34274L,34275L,34276L,34277L,
95515 34278L,34279L,34280L,34281L,34282L,34283L,34284L,34285L,34286L,34287L,
95516 34288L,34289L,34290L,34291L,34292L,34293L,34294L,34295L,34296L,34297L,
95517 34298L,34299L,34300L,34301L,34302L,34303L,34304L,34305L,34306L,34307L,
95518 34308L,34309L,34310L,34311L,34312L,34313L,34314L,34315L,34316L,34317L,
95519 34318L,34319L,34320L,34321L,34322L,34323L,34324L,34325L,34326L,34327L,
95520 34328L,34329L,34330L,34331L,34332L,34333L,34334L,34335L,34336L,34337L,
95521 34338L,34339L,34340L,34341L,34342L,34343L,34344L,34345L,34346L,34347L,
95522 34348L,34349L,34350L,34351L,34352L,34353L,34354L,34355L,34356L,34357L,
95523 34358L,34359L,34360L,34361L,34362L,34363L,34364L,34365L,34366L,34367L,
95524 34368L,34369L,34370L,34371L,34372L,34373L,34374L,34375L,34376L,34377L,
95525 34378L,34379L,34380L,34381L,34382L,34383L,34384L,34385L,34386L,34387L,
95526 34388L,34389L,34390L,34391L,34392L,34393L,34394L,34395L,34396L,34397L,
95527 34398L,34399L,34400L,34401L,34402L,34403L,34404L,34405L,34406L,34407L,
95528 34408L,34409L,34410L,34411L,34412L,34413L,34414L,34415L,34416L,34417L,
95529 34418L,34419L,34420L,34421L,34422L,34423L,34424L,34425L,34426L,34427L,
95530 34428L,34429L,34430L,34431L,34432L,34433L,34434L,34435L,34436L,34437L,
95531 34438L,34439L,34440L,34441L,34442L,34443L,34444L,34445L,34446L,34447L,
95532 34448L,34449L,34450L,34451L,34452L,34453L,34454L,34455L,34456L,34457L,
95533 34458L,34459L,34460L,34461L,34462L,34463L,34464L,34465L,34466L,34467L,
95534 34468L,34469L,34470L,34471L,34472L,34473L,34474L,34475L,34476L,34477L,
95535 34478L,34479L,34480L,34481L,34482L,34483L,34484L,34485L,34486L,34487L,
95536 34488L,34489L,34490L,34491L,34492L,34493L,34494L,34495L,34496L,34497L,
95537 34498L,34499L,34500L,34501L,34502L,34503L,34504L,34505L,34506L,34507L,
95538 34508L,34509L,34510L,34511L,34512L,34513L,34514L,34515L,34516L,34517L,
95539 34518L,34519L,34520L,34521L,34522L,34523L,34524L,34525L,34526L,34527L,
95540 34528L,34529L,34530L,34531L,34532L,34533L,34534L,34535L,34536L,34537L,
95541 34538L,34539L,34540L,34541L,34542L,34543L,34544L,34545L,34546L,34547L,
95542 34548L,34549L,34550L,34551L,34552L,34553L,34554L,34555L,34556L,34557L,
95543 34558L,34559L,34560L,34561L,34562L,34563L,34564L,34565L,34566L,34567L,
95544 34568L,34569L,34570L,34571L,34572L,34573L,34574L,34575L,34576L,34577L,
95545 34578L,34579L,34580L,34581L,34582L,34583L,34584L,34585L,34586L,34587L,
95546 34588L,34589L,34590L,34591L,34592L,34593L,34594L,34595L,34596L,34597L,
95547 34598L,34599L,34600L,34601L,34602L,34603L,34604L,34605L,34606L,34607L,
95548 34608L,34609L,34610L,34611L,34612L,34613L,34614L,34615L,34616L,34617L,
95549 34618L,34619L,34620L,34621L,34622L,34623L,34624L,34625L,34626L,34627L,
95550 34628L,34629L,34630L,34631L,34632L,34633L,34634L,34635L,34636L,34637L,
95551 34638L,34639L,34640L,34641L,34642L,34643L,34644L,34645L,34646L,34647L,
95552 34648L,34649L,34650L,34651L,34652L,34653L,34654L,34655L,34656L,34657L,
95553 34658L,34659L,34660L,34661L,34662L,34663L,34664L,34665L,34666L,34667L,
95554 34668L,34669L,34670L,34671L,34672L,34673L,34674L,34675L,34676L,34677L,
95555 34678L,34679L,34680L,34681L,34682L,34683L,34684L,34685L,34686L,34687L,
95556 34688L,34689L,34690L,34691L,34692L,34693L,34694L,34695L,34696L,34697L,
95557 34698L,34699L,34700L,34701L,34702L,34703L,34704L,34705L,34706L,34707L,
95558 34708L,34709L,34710L,34711L,34712L,34713L,34714L,34715L,34716L,34717L,
95559 34718L,34719L,34720L,34721L,34722L,34723L,34724L,34725L,34726L,34727L,
95560 34728L,34729L,34730L,34731L,34732L,34733L,34734L,34735L,34736L,34737L,
95561 34738L,34739L,34740L,34741L,34742L,34743L,34744L,34745L,34746L,34747L,
95562 34748L,34749L,34750L,34751L,34752L,34753L,34754L,34755L,34756L,34757L,
95563 34758L,34759L,34760L,34761L,34762L,34763L,34764L,34765L,34766L,34767L,
95564 34768L,34769L,34770L,34771L,34772L,34773L,34774L,34775L,34776L,34777L,
95565 34778L,34779L,34780L,34781L,34782L,34783L,34784L,34785L,34786L,34787L,
95566 34788L,34789L,34790L,34791L,34792L,34793L,34794L,34795L,34796L,34797L,
95567 34798L,34799L,34800L,34801L,34802L,34803L,34804L,34805L,34806L,34807L,
95568 34808L,34809L,34810L,34811L,34812L,34813L,34814L,34815L,34816L,34817L,
95569 34818L,34819L,34820L,34821L,34822L,34823L,34824L,34825L,34826L,34827L,
95570 34828L,34829L,34830L,34831L,34832L,34833L,34834L,34835L,34836L,34837L,
95571 34838L,34839L,34840L,34841L,34842L,34843L,34844L,34845L,34846L,34847L,
95572 34848L,34849L,34850L,34851L,34852L,34853L,34854L,34855L,34856L,34857L,
95573 34858L,34859L,34860L,34861L,34862L,34863L,34864L,34865L,34866L,34867L,
95574 34868L,34869L,34870L,34871L,34872L,34873L,34874L,34875L,34876L,34877L,
95575 34878L,34879L,34880L,34881L,34882L,34883L,34884L,34885L,34886L,34887L,
95576 34888L,34889L,34890L,34891L,34892L,34893L,34894L,34895L,34896L,34897L,
95577 34898L,34899L,34900L,34901L,34902L,34903L,34904L,34905L,34906L,34907L,
95578 34908L,34909L,34910L,34911L,34912L,34913L,34914L,34915L,34916L,34917L,
95579 34918L,34919L,34920L,34921L,34922L,34923L,34924L,34925L,34926L,34927L,
95580 34928L,34929L,34930L,34931L,34932L,34933L,34934L,34935L,34936L,34937L,
95581 34938L,34939L,34940L,34941L,34942L,34943L,34944L,34945L,34946L,34947L,
95582 34948L,34949L,34950L,34951L,34952L,34953L,34954L,34955L,34956L,34957L,
95583 34958L,34959L,34960L,34961L,34962L,34963L,34964L,34965L,34966L,34967L,
95584 34968L,34969L,34970L,34971L,34972L,34973L,34974L,34975L,34976L,34977L,
95585 34978L,34979L,34980L,34981L,34982L,34983L,34984L,34985L,34986L,34987L,
95586 34988L,34989L,34990L,34991L,34992L,34993L,34994L,34995L,34996L,34997L,
95587 34998L,34999L,35000L,35001L,35002L,35003L,35004L,35005L,35006L,35007L,
95588 35008L,35009L,35010L,35011L,35012L,35013L,35014L,35015L,35016L,35017L,
95589 35018L,35019L,35020L,35021L,35022L,35023L,35024L,35025L,35026L,35027L,
95590 35028L,35029L,35030L,35031L,35032L,35033L,35034L,35035L,35036L,35037L,
95591 35038L,35039L,35040L,35041L,35042L,35043L,35044L,35045L,35046L,35047L,
95592 35048L,35049L,35050L,35051L,35052L,35053L,35054L,35055L,35056L,35057L,
95593 35058L,35059L,35060L,35061L,35062L,35063L,35064L,35065L,35066L,35067L,
95594 35068L,35069L,35070L,35071L,35072L,35073L,35074L,35075L,35076L,35077L,
95595 35078L,35079L,35080L,35081L,35082L,35083L,35084L,35085L,35086L,35087L,
95596 35088L,35089L,35090L,35091L,35092L,35093L,35094L,35095L,35096L,35097L,
95597 35098L,35099L,35100L,35101L,35102L,35103L,35104L,35105L,35106L,35107L,
95598 35108L,35109L,35110L,35111L,35112L,35113L,35114L,35115L,35116L,35117L,
95599 35118L,35119L,35120L,35121L,35122L,35123L,35124L,35125L,35126L,35127L,
95600 35128L,35129L,35130L,35131L,35132L,35133L,35134L,35135L,35136L,35137L,
95601 35138L,35139L,35140L,35141L,35142L,35143L,35144L,35145L,35146L,35147L,
95602 35148L,35149L,35150L,35151L,35152L,35153L,35154L,35155L,35156L,35157L,
95603 35158L,35159L,35160L,35161L,35162L,35163L,35164L,35165L,35166L,35167L,
95604 35168L,35169L,35170L,35171L,35172L,35173L,35174L,35175L,35176L,35177L,
95605 35178L,35179L,35180L,35181L,35182L,35183L,35184L,35185L,35186L,35187L,
95606 35188L,35189L,35190L,35191L,35192L,35193L,35194L,35195L,35196L,35197L,
95607 35198L,35199L,35200L,35201L,35202L,35203L,35204L,35205L,35206L,35207L,
95608 35208L,35209L,35210L,35211L,35212L,35213L,35214L,35215L,35216L,35217L,
95609 35218L,35219L,35220L,35221L,35222L,35223L,35224L,35225L,35226L,35227L,
95610 35228L,35229L,35230L,35231L,35232L,35233L,35234L,35235L,35236L,35237L,
95611 35238L,35239L,35240L,35241L,35242L,35243L,35244L,35245L,35246L,35247L,
95612 35248L,35249L,35250L,35251L,35252L,35253L,35254L,35255L,35256L,35257L,
95613 35258L,35259L,35260L,35261L,35262L,35263L,35264L,35265L,35266L,35267L,
95614 35268L,35269L,35270L,35271L,35272L,35273L,35274L,35275L,35276L,35277L,
95615 35278L,35279L,35280L,35281L,35282L,35283L,35284L,35285L,35286L,35287L,
95616 35288L,35289L,35290L,35291L,35292L,35293L,35294L,35295L,35296L,35297L,
95617 35298L,35299L,35300L,35301L,35302L,35303L,35304L,35305L,35306L,35307L,
95618 35308L,35309L,35310L,35311L,35312L,35313L,35314L,35315L,35316L,35317L,
95619 35318L,35319L,35320L,35321L,35322L,35323L,35324L,35325L,35326L,35327L,
95620 35328L,35329L,35330L,35331L,35332L,35333L,35334L,35335L,35336L,35337L,
95621 35338L,35339L,35340L,35341L,35342L,35343L,35344L,35345L,35346L,35347L,
95622 35348L,35349L,35350L,35351L,35352L,35353L,35354L,35355L,35356L,35357L,
95623 35358L,35359L,35360L,35361L,35362L,35363L,35364L,35365L,35366L,35367L,
95624 35368L,35369L,35370L,35371L,35372L,35373L,35374L,35375L,35376L,35377L,
95625 35378L,35379L,35380L,35381L,35382L,35383L,35384L,35385L,35386L,35387L,
95626 35388L,35389L,35390L,35391L,35392L,35393L,35394L,35395L,35396L,35397L,
95627 35398L,35399L,35400L,35401L,35402L,35403L,35404L,35405L,35406L,35407L,
95628 35408L,35409L,35410L,35411L,35412L,35413L,35414L,35415L,35416L,35417L,
95629 35418L,35419L,35420L,35421L,35422L,35423L,35424L,35425L,35426L,35427L,
95630 35428L,35429L,35430L,35431L,35432L,35433L,35434L,35435L,35436L,35437L,
95631 35438L,35439L,35440L,35441L,35442L,35443L,35444L,35445L,35446L,35447L,
95632 35448L,35449L,35450L,35451L,35452L,35453L,35454L,35455L,35456L,35457L,
95633 35458L,35459L,35460L,35461L,35462L,35463L,35464L,35465L,35466L,35467L,
95634 35468L,35469L,35470L,35471L,35472L,35473L,35474L,35475L,35476L,35477L,
95635 35478L,35479L,35480L,35481L,35482L,35483L,35484L,35485L,35486L,35487L,
95636 35488L,35489L,35490L,35491L,35492L,35493L,35494L,35495L,35496L,35497L,
95637 35498L,35499L,35500L,35501L,35502L,35503L,35504L,35505L,35506L,35507L,
95638 35508L,35509L,35510L,35511L,35512L,35513L,35514L,35515L,35516L,35517L,
95639 35518L,35519L,35520L,35521L,35522L,35523L,35524L,35525L,35526L,35527L,
95640 35528L,35529L,35530L,35531L,35532L,35533L,35534L,35535L,35536L,35537L,
95641 35538L,35539L,35540L,35541L,35542L,35543L,35544L,35545L,35546L,35547L,
95642 35548L,35549L,35550L,35551L,35552L,35553L,35554L,35555L,35556L,35557L,
95643 35558L,35559L,35560L,35561L,35562L,35563L,35564L,35565L,35566L,35567L,
95644 35568L,35569L,35570L,35571L,35572L,35573L,35574L,35575L,35576L,35577L,
95645 35578L,35579L,35580L,35581L,35582L,35583L,35584L,35585L,35586L,35587L,
95646 35588L,35589L,35590L,35591L,35592L,35593L,35594L,35595L,35596L,35597L,
95647 35598L,35599L,35600L,35601L,35602L,35603L,35604L,35605L,35606L,35607L,
95648 35608L,35609L,35610L,35611L,35612L,35613L,35614L,35615L,35616L,35617L,
95649 35618L,35619L,35620L,35621L,35622L,35623L,35624L,35625L,35626L,35627L,
95650 35628L,35629L,35630L,35631L,35632L,35633L,35634L,35635L,35636L,35637L,
95651 35638L,35639L,35640L,35641L,35642L,35643L,35644L,35645L,35646L,35647L,
95652 35648L,35649L,35650L,35651L,35652L,35653L,35654L,35655L,35656L,35657L,
95653 35658L,35659L,35660L,35661L,35662L,35663L,35664L,35665L,35666L,35667L,
95654 35668L,35669L,35670L,35671L,35672L,35673L,35674L,35675L,35676L,35677L,
95655 35678L,35679L,35680L,35681L,35682L,35683L,35684L,35685L,35686L,35687L,
95656 35688L,35689L,35690L,35691L,35692L,35693L,35694L,35695L,35696L,35697L,
95657 35698L,35699L,35700L,35701L,35702L,35703L,35704L,35705L,35706L,35707L,
95658 35708L,35709L,35710L,35711L,35712L,35713L,35714L,35715L,35716L,35717L,
95659 35718L,35719L,35720L,35721L,35722L,35723L,35724L,35725L,35726L,35727L,
95660 35728L,35729L,35730L,35731L,35732L,35733L,35734L,35735L,35736L,35737L,
95661 35738L,35739L,35740L,35741L,35742L,35743L,35744L,35745L,35746L,35747L,
95662 35748L,35749L,35750L,35751L,35752L,35753L,35754L,35755L,35756L,35757L,
95663 35758L,35759L,35760L,35761L,35762L,35763L,35764L,35765L,35766L,35767L,
95664 35768L,35769L,35770L,35771L,35772L,35773L,35774L,35775L,35776L,35777L,
95665 35778L,35779L,35780L,35781L,35782L,35783L,35784L,35785L,35786L,35787L,
95666 35788L,35789L,35790L,35791L,35792L,35793L,35794L,35795L,35796L,35797L,
95667 35798L,35799L,35800L,35801L,35802L,35803L,35804L,35805L,35806L,35807L,
95668 35808L,35809L,35810L,35811L,35812L,35813L,35814L,35815L,35816L,35817L,
95669 35818L,35819L,35820L,35821L,35822L,35823L,35824L,35825L,35826L,35827L,
95670 35828L,35829L,35830L,35831L,35832L,35833L,35834L,35835L,35836L,35837L,
95671 35838L,35839L,35840L,35841L,35842L,35843L,35844L,35845L,35846L,35847L,
95672 35848L,35849L,35850L,35851L,35852L,35853L,35854L,35855L,35856L,35857L,
95673 35858L,35859L,35860L,35861L,35862L,35863L,35864L,35865L,35866L,35867L,
95674 35868L,35869L,35870L,35871L,35872L,35873L,35874L,35875L,35876L,35877L,
95675 35878L,35879L,35880L,35881L,35882L,35883L,35884L,35885L,35886L,35887L,
95676 35888L,35889L,35890L,35891L,35892L,35893L,35894L,35895L,35896L,35897L,
95677 35898L,35899L,35900L,35901L,35902L,35903L,35904L,35905L,35906L,35907L,
95678 35908L,35909L,35910L,35911L,35912L,35913L,35914L,35915L,35916L,35917L,
95679 35918L,35919L,35920L,35921L,35922L,35923L,35924L,35925L,35926L,35927L,
95680 35928L,35929L,35930L,35931L,35932L,35933L,35934L,35935L,35936L,35937L,
95681 35938L,35939L,35940L,35941L,35942L,35943L,35944L,35945L,35946L,35947L,
95682 35948L,35949L,35950L,35951L,35952L,35953L,35954L,35955L,35956L,35957L,
95683 35958L,35959L,35960L,35961L,35962L,35963L,35964L,35965L,35966L,35967L,
95684 35968L,35969L,35970L,35971L,35972L,35973L,35974L,35975L,35976L,35977L,
95685 35978L,35979L,35980L,35981L,35982L,35983L,35984L,35985L,35986L,35987L,
95686 35988L,35989L,35990L,35991L,35992L,35993L,35994L,35995L,35996L,35997L,
95687 35998L,35999L,36000L,36001L,36002L,36003L,36004L,36005L,36006L,36007L,
95688 36008L,36009L,36010L,36011L,36012L,36013L,36014L,36015L,36016L,36017L,
95689 36018L,36019L,36020L,36021L,36022L,36023L,36024L,36025L,36026L,36027L,
95690 36028L,36029L,36030L,36031L,36032L,36033L,36034L,36035L,36036L,36037L,
95691 36038L,36039L,36040L,36041L,36042L,36043L,36044L,36045L,36046L,36047L,
95692 36048L,36049L,36050L,36051L,36052L,36053L,36054L,36055L,36056L,36057L,
95693 36058L,36059L,36060L,36061L,36062L,36063L,36064L,36065L,36066L,36067L,
95694 36068L,36069L,36070L,36071L,36072L,36073L,36074L,36075L,36076L,36077L,
95695 36078L,36079L,36080L,36081L,36082L,36083L,36084L,36085L,36086L,36087L,
95696 36088L,36089L,36090L,36091L,36092L,36093L,36094L,36095L,36096L,36097L,
95697 36098L,36099L,36100L,36101L,36102L,36103L,36104L,36105L,36106L,36107L,
95698 36108L,36109L,36110L,36111L,36112L,36113L,36114L,36115L,36116L,36117L,
95699 36118L,36119L,36120L,36121L,36122L,36123L,36124L,36125L,36126L,36127L,
95700 36128L,36129L,36130L,36131L,36132L,36133L,36134L,36135L,36136L,36137L,
95701 36138L,36139L,36140L,36141L,36142L,36143L,36144L,36145L,36146L,36147L,
95702 36148L,36149L,36150L,36151L,36152L,36153L,36154L,36155L,36156L,36157L,
95703 36158L,36159L,36160L,36161L,36162L,36163L,36164L,36165L,36166L,36167L,
95704 36168L,36169L,36170L,36171L,36172L,36173L,36174L,36175L,36176L,36177L,
95705 36178L,36179L,36180L,36181L,36182L,36183L,36184L,36185L,36186L,36187L,
95706 36188L,36189L,36190L,36191L,36192L,36193L,36194L,36195L,36196L,36197L,
95707 36198L,36199L,36200L,36201L,36202L,36203L,36204L,36205L,36206L,36207L,
95708 36208L,36209L,36210L,36211L,36212L,36213L,36214L,36215L,36216L,36217L,
95709 36218L,36219L,36220L,36221L,36222L,36223L,36224L,36225L,36226L,36227L,
95710 36228L,36229L,36230L,36231L,36232L,36233L,36234L,36235L,36236L,36237L,
95711 36238L,36239L,36240L,36241L,36242L,36243L,36244L,36245L,36246L,36247L,
95712 36248L,36249L,36250L,36251L,36252L,36253L,36254L,36255L,36256L,36257L,
95713 36258L,36259L,36260L,36261L,36262L,36263L,36264L,36265L,36266L,36267L,
95714 36268L,36269L,36270L,36271L,36272L,36273L,36274L,36275L,36276L,36277L,
95715 36278L,36279L,36280L,36281L,36282L,36283L,36284L,36285L,36286L,36287L,
95716 36288L,36289L,36290L,36291L,36292L,36293L,36294L,36295L,36296L,36297L,
95717 36298L,36299L,36300L,36301L,36302L,36303L,36304L,36305L,36306L,36307L,
95718 36308L,36309L,36310L,36311L,36312L,36313L,36314L,36315L,36316L,36317L,
95719 36318L,36319L,36320L,36321L,36322L,36323L,36324L,36325L,36326L,36327L,
95720 36328L,36329L,36330L,36331L,36332L,36333L,36334L,36335L,36336L,36337L,
95721 36338L,36339L,36340L,36341L,36342L,36343L,36344L,36345L,36346L,36347L,
95722 36348L,36349L,36350L,36351L,36352L,36353L,36354L,36355L,36356L,36357L,
95723 36358L,36359L,36360L,36361L,36362L,36363L,36364L,36365L,36366L,36367L,
95724 36368L,36369L,36370L,36371L,36372L,36373L,36374L,36375L,36376L,36377L,
95725 36378L,36379L,36380L,36381L,36382L,36383L,36384L,36385L,36386L,36387L,
95726 36388L,36389L,36390L,36391L,36392L,36393L,36394L,36395L,36396L,36397L,
95727 36398L,36399L,36400L,36401L,36402L,36403L,36404L,36405L,36406L,36407L,
95728 36408L,36409L,36410L,36411L,36412L,36413L,36414L,36415L,36416L,36417L,
95729 36418L,36419L,36420L,36421L,36422L,36423L,36424L,36425L,36426L,36427L,
95730 36428L,36429L,36430L,36431L,36432L,36433L,36434L,36435L,36436L,36437L,
95731 36438L,36439L,36440L,36441L,36442L,36443L,36444L,36445L,36446L,36447L,
95732 36448L,36449L,36450L,36451L,36452L,36453L,36454L,36455L,36456L,36457L,
95733 36458L,36459L,36460L,36461L,36462L,36463L,36464L,36465L,36466L,36467L,
95734 36468L,36469L,36470L,36471L,36472L,36473L,36474L,36475L,36476L,36477L,
95735 36478L,36479L,36480L,36481L,36482L,36483L,36484L,36485L,36486L,36487L,
95736 36488L,36489L,36490L,36491L,36492L,36493L,36494L,36495L,36496L,36497L,
95737 36498L,36499L,36500L,36501L,36502L,36503L,36504L,36505L,36506L,36507L,
95738 36508L,36509L,36510L,36511L,36512L,36513L,36514L,36515L,36516L,36517L,
95739 36518L,36519L,36520L,36521L,36522L,36523L,36524L,36525L,36526L,36527L,
95740 36528L,36529L,36530L,36531L,36532L,36533L,36534L,36535L,36536L,36537L,
95741 36538L,36539L,36540L,36541L,36542L,36543L,36544L,36545L,36546L,36547L,
95742 36548L,36549L,36550L,36551L,36552L,36553L,36554L,36555L,36556L,36557L,
95743 36558L,36559L,36560L,36561L,36562L,36563L,36564L,36565L,36566L,36567L,
95744 36568L,36569L,36570L,36571L,36572L,36573L,36574L,36575L,36576L,36577L,
95745 36578L,36579L,36580L,36581L,36582L,36583L,36584L,36585L,36586L,36587L,
95746 36588L,36589L,36590L,36591L,36592L,36593L,36594L,36595L,36596L,36597L,
95747 36598L,36599L,36600L,36601L,36602L,36603L,36604L,36605L,36606L,36607L,
95748 36608L,36609L,36610L,36611L,36612L,36613L,36614L,36615L,36616L,36617L,
95749 36618L,36619L,36620L,36621L,36622L,36623L,36624L,36625L,36626L,36627L,
95750 36628L,36629L,36630L,36631L,36632L,36633L,36634L,36635L,36636L,36637L,
95751 36638L,36639L,36640L,36641L,36642L,36643L,36644L,36645L,36646L,36647L,
95752 36648L,36649L,36650L,36651L,36652L,36653L,36654L,36655L,36656L,36657L,
95753 36658L,36659L,36660L,36661L,36662L,36663L,36664L,36665L,36666L,36667L,
95754 36668L,36669L,36670L,36671L,36672L,36673L,36674L,36675L,36676L,36677L,
95755 36678L,36679L,36680L,36681L,36682L,36683L,36684L,36685L,36686L,36687L,
95756 36688L,36689L,36690L,36691L,36692L,36693L,36694L,36695L,36696L,36697L,
95757 36698L,36699L,36700L,36701L,36702L,36703L,36704L,36705L,36706L,36707L,
95758 36708L,36709L,36710L,36711L,36712L,36713L,36714L,36715L,36716L,36717L,
95759 36718L,36719L,36720L,36721L,36722L,36723L,36724L,36725L,36726L,36727L,
95760 36728L,36729L,36730L,36731L,36732L,36733L,36734L,36735L,36736L,36737L,
95761 36738L,36739L,36740L,36741L,36742L,36743L,36744L,36745L,36746L,36747L,
95762 36748L,36749L,36750L,36751L,36752L,36753L,36754L,36755L,36756L,36757L,
95763 36758L,36759L,36760L,36761L,36762L,36763L,36764L,36765L,36766L,36767L,
95764 36768L,36769L,36770L,36771L,36772L,36773L,36774L,36775L,36776L,36777L,
95765 36778L,36779L,36780L,36781L,36782L,36783L,36784L,36785L,36786L,36787L,
95766 36788L,36789L,36790L,36791L,36792L,36793L,36794L,36795L,36796L,36797L,
95767 36798L,36799L,36800L,36801L,36802L,36803L,36804L,36805L,36806L,36807L,
95768 36808L,36809L,36810L,36811L,36812L,36813L,36814L,36815L,36816L,36817L,
95769 36818L,36819L,36820L,36821L,36822L,36823L,36824L,36825L,36826L,36827L,
95770 36828L,36829L,36830L,36831L,36832L,36833L,36834L,36835L,36836L,36837L,
95771 36838L,36839L,36840L,36841L,36842L,36843L,36844L,36845L,36846L,36847L,
95772 36848L,36849L,36850L,36851L,36852L,36853L,36854L,36855L,36856L,36857L,
95773 36858L,36859L,36860L,36861L,36862L,36863L,36864L,36865L,36866L,36867L,
95774 36868L,36869L,36870L,36871L,36872L,36873L,36874L,36875L,36876L,36877L,
95775 36878L,36879L,36880L,36881L,36882L,36883L,36884L,36885L,36886L,36887L,
95776 36888L,36889L,36890L,36891L,36892L,36893L,36894L,36895L,36896L,36897L,
95777 36898L,36899L,36900L,36901L,36902L,36903L,36904L,36905L,36906L,36907L,
95778 36908L,36909L,36910L,36911L,36912L,36913L,36914L,36915L,36916L,36917L,
95779 36918L,36919L,36920L,36921L,36922L,36923L,36924L,36925L,36926L,36927L,
95780 36928L,36929L,36930L,36931L,36932L,36933L,36934L,36935L,36936L,36937L,
95781 36938L,36939L,36940L,36941L,36942L,36943L,36944L,36945L,36946L,36947L,
95782 36948L,36949L,36950L,36951L,36952L,36953L,36954L,36955L,36956L,36957L,
95783 36958L,36959L,36960L,36961L,36962L,36963L,36964L,36965L,36966L,36967L,
95784 36968L,36969L,36970L,36971L,36972L,36973L,36974L,36975L,36976L,36977L,
95785 36978L,36979L,36980L,36981L,36982L,36983L,36984L,36985L,36986L,36987L,
95786 36988L,36989L,36990L,36991L,36992L,36993L,36994L,36995L,36996L,36997L,
95787 36998L,36999L,37000L,37001L,37002L,37003L,37004L,37005L,37006L,37007L,
95788 37008L,37009L,37010L,37011L,37012L,37013L,37014L,37015L,37016L,37017L,
95789 37018L,37019L,37020L,37021L,37022L,37023L,37024L,37025L,37026L,37027L,
95790 37028L,37029L,37030L,37031L,37032L,37033L,37034L,37035L,37036L,37037L,
95791 37038L,37039L,37040L,37041L,37042L,37043L,37044L,37045L,37046L,37047L,
95792 37048L,37049L,37050L,37051L,37052L,37053L,37054L,37055L,37056L,37057L,
95793 37058L,37059L,37060L,37061L,37062L,37063L,37064L,37065L,37066L,37067L,
95794 37068L,37069L,37070L,37071L,37072L,37073L,37074L,37075L,37076L,37077L,
95795 37078L,37079L,37080L,37081L,37082L,37083L,37084L,37085L,37086L,37087L,
95796 37088L,37089L,37090L,37091L,37092L,37093L,37094L,37095L,37096L,37097L,
95797 37098L,37099L,37100L,37101L,37102L,37103L,37104L,37105L,37106L,37107L,
95798 37108L,37109L,37110L,37111L,37112L,37113L,37114L,37115L,37116L,37117L,
95799 37118L,37119L,37120L,37121L,37122L,37123L,37124L,37125L,37126L,37127L,
95800 37128L,37129L,37130L,37131L,37132L,37133L,37134L,37135L,37136L,37137L,
95801 37138L,37139L,37140L,37141L,37142L,37143L,37144L,37145L,37146L,37147L,
95802 37148L,37149L,37150L,37151L,37152L,37153L,37154L,37155L,37156L,37157L,
95803 37158L,37159L,37160L,37161L,37162L,37163L,37164L,37165L,37166L,37167L,
95804 37168L,37169L,37170L,37171L,37172L,37173L,37174L,37175L,37176L,37177L,
95805 37178L,37179L,37180L,37181L,37182L,37183L,37184L,37185L,37186L,37187L,
95806 37188L,37189L,37190L,37191L,37192L,37193L,37194L,37195L,37196L,37197L,
95807 37198L,37199L,37200L,37201L,37202L,37203L,37204L,37205L,37206L,37207L,
95808 37208L,37209L,37210L,37211L,37212L,37213L,37214L,37215L,37216L,37217L,
95809 37218L,37219L,37220L,37221L,37222L,37223L,37224L,37225L,37226L,37227L,
95810 37228L,37229L,37230L,37231L,37232L,37233L,37234L,37235L,37236L,37237L,
95811 37238L,37239L,37240L,37241L,37242L,37243L,37244L,37245L,37246L,37247L,
95812 37248L,37249L,37250L,37251L,37252L,37253L,37254L,37255L,37256L,37257L,
95813 37258L,37259L,37260L,37261L,37262L,37263L,37264L,37265L,37266L,37267L,
95814 37268L,37269L,37270L,37271L,37272L,37273L,37274L,37275L,37276L,37277L,
95815 37278L,37279L,37280L,37281L,37282L,37283L,37284L,37285L,37286L,37287L,
95816 37288L,37289L,37290L,37291L,37292L,37293L,37294L,37295L,37296L,37297L,
95817 37298L,37299L,37300L,37301L,37302L,37303L,37304L,37305L,37306L,37307L,
95818 37308L,37309L,37310L,37311L,37312L,37313L,37314L,37315L,37316L,37317L,
95819 37318L,37319L,37320L,37321L,37322L,37323L,37324L,37325L,37326L,37327L,
95820 37328L,37329L,37330L,37331L,37332L,37333L,37334L,37335L,37336L,37337L,
95821 37338L,37339L,37340L,37341L,37342L,37343L,37344L,37345L,37346L,37347L,
95822 37348L,37349L,37350L,37351L,37352L,37353L,37354L,37355L,37356L,37357L,
95823 37358L,37359L,37360L,37361L,37362L,37363L,37364L,37365L,37366L,37367L,
95824 37368L,37369L,37370L,37371L,37372L,37373L,37374L,37375L,37376L,37377L,
95825 37378L,37379L,37380L,37381L,37382L,37383L,37384L,37385L,37386L,37387L,
95826 37388L,37389L,37390L,37391L,37392L,37393L,37394L,37395L,37396L,37397L,
95827 37398L,37399L,37400L,37401L,37402L,37403L,37404L,37405L,37406L,37407L,
95828 37408L,37409L,37410L,37411L,37412L,37413L,37414L,37415L,37416L,37417L,
95829 37418L,37419L,37420L,37421L,37422L,37423L,37424L,37425L,37426L,37427L,
95830 37428L,37429L,37430L,37431L,37432L,37433L,37434L,37435L,37436L,37437L,
95831 37438L,37439L,37440L,37441L,37442L,37443L,37444L,37445L,37446L,37447L,
95832 37448L,37449L,37450L,37451L,37452L,37453L,37454L,37455L,37456L,37457L,
95833 37458L,37459L,37460L,37461L,37462L,37463L,37464L,37465L,37466L,37467L,
95834 37468L,37469L,37470L,37471L,37472L,37473L,37474L,37475L,37476L,37477L,
95835 37478L,37479L,37480L,37481L,37482L,37483L,37484L,37485L,37486L,37487L,
95836 37488L,37489L,37490L,37491L,37492L,37493L,37494L,37495L,37496L,37497L,
95837 37498L,37499L,37500L,37501L,37502L,37503L,37504L,37505L,37506L,37507L,
95838 37508L,37509L,37510L,37511L,37512L,37513L,37514L,37515L,37516L,37517L,
95839 37518L,37519L,37520L,37521L,37522L,37523L,37524L,37525L,37526L,37527L,
95840 37528L,37529L,37530L,37531L,37532L,37533L,37534L,37535L,37536L,37537L,
95841 37538L,37539L,37540L,37541L,37542L,37543L,37544L,37545L,37546L,37547L,
95842 37548L,37549L,37550L,37551L,37552L,37553L,37554L,37555L,37556L,37557L,
95843 37558L,37559L,37560L,37561L,37562L,37563L,37564L,37565L,37566L,37567L,
95844 37568L,37569L,37570L,37571L,37572L,37573L,37574L,37575L,37576L,37577L,
95845 37578L,37579L,37580L,37581L,37582L,37583L,37584L,37585L,37586L,37587L,
95846 37588L,37589L,37590L,37591L,37592L,37593L,37594L,37595L,37596L,37597L,
95847 37598L,37599L,37600L,37601L,37602L,37603L,37604L,37605L,37606L,37607L,
95848 37608L,37609L,37610L,37611L,37612L,37613L,37614L,37615L,37616L,37617L,
95849 37618L,37619L,37620L,37621L,37622L,37623L,37624L,37625L,37626L,37627L,
95850 37628L,37629L,37630L,37631L,37632L,37633L,37634L,37635L,37636L,37637L,
95851 37638L,37639L,37640L,37641L,37642L,37643L,37644L,37645L,37646L,37647L,
95852 37648L,37649L,37650L,37651L,37652L,37653L,37654L,37655L,37656L,37657L,
95853 37658L,37659L,37660L,37661L,37662L,37663L,37664L,37665L,37666L,37667L,
95854 37668L,37669L,37670L,37671L,37672L,37673L,37674L,37675L,37676L,37677L,
95855 37678L,37679L,37680L,37681L,37682L,37683L,37684L,37685L,37686L,37687L,
95856 37688L,37689L,37690L,37691L,37692L,37693L,37694L,37695L,37696L,37697L,
95857 37698L,37699L,37700L,37701L,37702L,37703L,37704L,37705L,37706L,37707L,
95858 37708L,37709L,37710L,37711L,37712L,37713L,37714L,37715L,37716L,37717L,
95859 37718L,37719L,37720L,37721L,37722L,37723L,37724L,37725L,37726L,37727L,
95860 37728L,37729L,37730L,37731L,37732L,37733L,37734L,37735L,37736L,37737L,
95861 37738L,37739L,37740L,37741L,37742L,37743L,37744L,37745L,37746L,37747L,
95862 37748L,37749L,37750L,37751L,37752L,37753L,37754L,37755L,37756L,37757L,
95863 37758L,37759L,37760L,37761L,37762L,37763L,37764L,37765L,37766L,37767L,
95864 37768L,37769L,37770L,37771L,37772L,37773L,37774L,37775L,37776L,37777L,
95865 37778L,37779L,37780L,37781L,37782L,37783L,37784L,37785L,37786L,37787L,
95866 37788L,37789L,37790L,37791L,37792L,37793L,37794L,37795L,37796L,37797L,
95867 37798L,37799L,37800L,37801L,37802L,37803L,37804L,37805L,37806L,37807L,
95868 37808L,37809L,37810L,37811L,37812L,37813L,37814L,37815L,37816L,37817L,
95869 37818L,37819L,37820L,37821L,37822L,37823L,37824L,37825L,37826L,37827L,
95870 37828L,37829L,37830L,37831L,37832L,37833L,37834L,37835L,37836L,37837L,
95871 37838L,37839L,37840L,37841L,37842L,37843L,37844L,37845L,37846L,37847L,
95872 37848L,37849L,37850L,37851L,37852L,37853L,37854L,37855L,37856L,37857L,
95873 37858L,37859L,37860L,37861L,37862L,37863L,37864L,37865L,37866L,37867L,
95874 37868L,37869L,37870L,37871L,37872L,37873L,37874L,37875L,37876L,37877L,
95875 37878L,37879L,37880L,37881L,37882L,37883L,37884L,37885L,37886L,37887L,
95876 37888L,37889L,37890L,37891L,37892L,37893L,37894L,37895L,37896L,37897L,
95877 37898L,37899L,37900L,37901L,37902L,37903L,37904L,37905L,37906L,37907L,
95878 37908L,37909L,37910L,37911L,37912L,37913L,37914L,37915L,37916L,37917L,
95879 37918L,37919L,37920L,37921L,37922L,37923L,37924L,37925L,37926L,37927L,
95880 37928L,37929L,37930L,37931L,37932L,37933L,37934L,37935L,37936L,37937L,
95881 37938L,37939L,37940L,37941L,37942L,37943L,37944L,37945L,37946L,37947L,
95882 37948L,37949L,37950L,37951L,37952L,37953L,37954L,37955L,37956L,37957L,
95883 37958L,37959L,37960L,37961L,37962L,37963L,37964L,37965L,37966L,37967L,
95884 37968L,37969L,37970L,37971L,37972L,37973L,37974L,37975L,37976L,37977L,
95885 37978L,37979L,37980L,37981L,37982L,37983L,37984L,37985L,37986L,37987L,
95886 37988L,37989L,37990L,37991L,37992L,37993L,37994L,37995L,37996L,37997L,
95887 37998L,37999L,38000L,38001L,38002L,38003L,38004L,38005L,38006L,38007L,
95888 38008L,38009L,38010L,38011L,38012L,38013L,38014L,38015L,38016L,38017L,
95889 38018L,38019L,38020L,38021L,38022L,38023L,38024L,38025L,38026L,38027L,
95890 38028L,38029L,38030L,38031L,38032L,38033L,38034L,38035L,38036L,38037L,
95891 38038L,38039L,38040L,38041L,38042L,38043L,38044L,38045L,38046L,38047L,
95892 38048L,38049L,38050L,38051L,38052L,38053L,38054L,38055L,38056L,38057L,
95893 38058L,38059L,38060L,38061L,38062L,38063L,38064L,38065L,38066L,38067L,
95894 38068L,38069L,38070L,38071L,38072L,38073L,38074L,38075L,38076L,38077L,
95895 38078L,38079L,38080L,38081L,38082L,38083L,38084L,38085L,38086L,38087L,
95896 38088L,38089L,38090L,38091L,38092L,38093L,38094L,38095L,38096L,38097L,
95897 38098L,38099L,38100L,38101L,38102L,38103L,38104L,38105L,38106L,38107L,
95898 38108L,38109L,38110L,38111L,38112L,38113L,38114L,38115L,38116L,38117L,
95899 38118L,38119L,38120L,38121L,38122L,38123L,38124L,38125L,38126L,38127L,
95900 38128L,38129L,38130L,38131L,38132L,38133L,38134L,38135L,38136L,38137L,
95901 38138L,38139L,38140L,38141L,38142L,38143L,38144L,38145L,38146L,38147L,
95902 38148L,38149L,38150L,38151L,38152L,38153L,38154L,38155L,38156L,38157L,
95903 38158L,38159L,38160L,38161L,38162L,38163L,38164L,38165L,38166L,38167L,
95904 38168L,38169L,38170L,38171L,38172L,38173L,38174L,38175L,38176L,38177L,
95905 38178L,38179L,38180L,38181L,38182L,38183L,38184L,38185L,38186L,38187L,
95906 38188L,38189L,38190L,38191L,38192L,38193L,38194L,38195L,38196L,38197L,
95907 38198L,38199L,38200L,38201L,38202L,38203L,38204L,38205L,38206L,38207L,
95908 38208L,38209L,38210L,38211L,38212L,38213L,38214L,38215L,38216L,38217L,
95909 38218L,38219L,38220L,38221L,38222L,38223L,38224L,38225L,38226L,38227L,
95910 38228L,38229L,38230L,38231L,38232L,38233L,38234L,38235L,38236L,38237L,
95911 38238L,38239L,38240L,38241L,38242L,38243L,38244L,38245L,38246L,38247L,
95912 38248L,38249L,38250L,38251L,38252L,38253L,38254L,38255L,38256L,38257L,
95913 38258L,38259L,38260L,38261L,38262L,38263L,38264L,38265L,38266L,38267L,
95914 38268L,38269L,38270L,38271L,38272L,38273L,38274L,38275L,38276L,38277L,
95915 38278L,38279L,38280L,38281L,38282L,38283L,38284L,38285L,38286L,38287L,
95916 38288L,38289L,38290L,38291L,38292L,38293L,38294L,38295L,38296L,38297L,
95917 38298L,38299L,38300L,38301L,38302L,38303L,38304L,38305L,38306L,38307L,
95918 38308L,38309L,38310L,38311L,38312L,38313L,38314L,38315L,38316L,38317L,
95919 38318L,38319L,38320L,38321L,38322L,38323L,38324L,38325L,38326L,38327L,
95920 38328L,38329L,38330L,38331L,38332L,38333L,38334L,38335L,38336L,38337L,
95921 38338L,38339L,38340L,38341L,38342L,38343L,38344L,38345L,38346L,38347L,
95922 38348L,38349L,38350L,38351L,38352L,38353L,38354L,38355L,38356L,38357L,
95923 38358L,38359L,38360L,38361L,38362L,38363L,38364L,38365L,38366L,38367L,
95924 38368L,38369L,38370L,38371L,38372L,38373L,38374L,38375L,38376L,38377L,
95925 38378L,38379L,38380L,38381L,38382L,38383L,38384L,38385L,38386L,38387L,
95926 38388L,38389L,38390L,38391L,38392L,38393L,38394L,38395L,38396L,38397L,
95927 38398L,38399L,38400L,38401L,38402L,38403L,38404L,38405L,38406L,38407L,
95928 38408L,38409L,38410L,38411L,38412L,38413L,38414L,38415L,38416L,38417L,
95929 38418L,38419L,38420L,38421L,38422L,38423L,38424L,38425L,38426L,38427L,
95930 38428L,38429L,38430L,38431L,38432L,38433L,38434L,38435L,38436L,38437L,
95931 38438L,38439L,38440L,38441L,38442L,38443L,38444L,38445L,38446L,38447L,
95932 38448L,38449L,38450L,38451L,38452L,38453L,38454L,38455L,38456L,38457L,
95933 38458L,38459L,38460L,38461L,38462L,38463L,38464L,38465L,38466L,38467L,
95934 38468L,38469L,38470L,38471L,38472L,38473L,38474L,38475L,38476L,38477L,
95935 38478L,38479L,38480L,38481L,38482L,38483L,38484L,38485L,38486L,38487L,
95936 38488L,38489L,38490L,38491L,38492L,38493L,38494L,38495L,38496L,38497L,
95937 38498L,38499L,38500L,38501L,38502L,38503L,38504L,38505L,38506L,38507L,
95938 38508L,38509L,38510L,38511L,38512L,38513L,38514L,38515L,38516L,38517L,
95939 38518L,38519L,38520L,38521L,38522L,38523L,38524L,38525L,38526L,38527L,
95940 38528L,38529L,38530L,38531L,38532L,38533L,38534L,38535L,38536L,38537L,
95941 38538L,38539L,38540L,38541L,38542L,38543L,38544L,38545L,38546L,38547L,
95942 38548L,38549L,38550L,38551L,38552L,38553L,38554L,38555L,38556L,38557L,
95943 38558L,38559L,38560L,38561L,38562L,38563L,38564L,38565L,38566L,38567L,
95944 38568L,38569L,38570L,38571L,38572L,38573L,38574L,38575L,38576L,38577L,
95945 38578L,38579L,38580L,38581L,38582L,38583L,38584L,38585L,38586L,38587L,
95946 38588L,38589L,38590L,38591L,38592L,38593L,38594L,38595L,38596L,38597L,
95947 38598L,38599L,38600L,38601L,38602L,38603L,38604L,38605L,38606L,38607L,
95948 38608L,38609L,38610L,38611L,38612L,38613L,38614L,38615L,38616L,38617L,
95949 38618L,38619L,38620L,38621L,38622L,38623L,38624L,38625L,38626L,38627L,
95950 38628L,38629L,38630L,38631L,38632L,38633L,38634L,38635L,38636L,38637L,
95951 38638L,38639L,38640L,38641L,38642L,38643L,38644L,38645L,38646L,38647L,
95952 38648L,38649L,38650L,38651L,38652L,38653L,38654L,38655L,38656L,38657L,
95953 38658L,38659L,38660L,38661L,38662L,38663L,38664L,38665L,38666L,38667L,
95954 38668L,38669L,38670L,38671L,38672L,38673L,38674L,38675L,38676L,38677L,
95955 38678L,38679L,38680L,38681L,38682L,38683L,38684L,38685L,38686L,38687L,
95956 38688L,38689L,38690L,38691L,38692L,38693L,38694L,38695L,38696L,38697L,
95957 38698L,38699L,38700L,38701L,38702L,38703L,38704L,38705L,38706L,38707L,
95958 38708L,38709L,38710L,38711L,38712L,38713L,38714L,38715L,38716L,38717L,
95959 38718L,38719L,38720L,38721L,38722L,38723L,38724L,38725L,38726L,38727L,
95960 38728L,38729L,38730L,38731L,38732L,38733L,38734L,38735L,38736L,38737L,
95961 38738L,38739L,38740L,38741L,38742L,38743L,38744L,38745L,38746L,38747L,
95962 38748L,38749L,38750L,38751L,38752L,38753L,38754L,38755L,38756L,38757L,
95963 38758L,38759L,38760L,38761L,38762L,38763L,38764L,38765L,38766L,38767L,
95964 38768L,38769L,38770L,38771L,38772L,38773L,38774L,38775L,38776L,38777L,
95965 38778L,38779L,38780L,38781L,38782L,38783L,38784L,38785L,38786L,38787L,
95966 38788L,38789L,38790L,38791L,38792L,38793L,38794L,38795L,38796L,38797L,
95967 38798L,38799L,38800L,38801L,38802L,38803L,38804L,38805L,38806L,38807L,
95968 38808L,38809L,38810L,38811L,38812L,38813L,38814L,38815L,38816L,38817L,
95969 38818L,38819L,38820L,38821L,38822L,38823L,38824L,38825L,38826L,38827L,
95970 38828L,38829L,38830L,38831L,38832L,38833L,38834L,38835L,38836L,38837L,
95971 38838L,38839L,38840L,38841L,38842L,38843L,38844L,38845L,38846L,38847L,
95972 38848L,38849L,38850L,38851L,38852L,38853L,38854L,38855L,38856L,38857L,
95973 38858L,38859L,38860L,38861L,38862L,38863L,38864L,38865L,38866L,38867L,
95974 38868L,38869L,38870L,38871L,38872L,38873L,38874L,38875L,38876L,38877L,
95975 38878L,38879L,38880L,38881L,38882L,38883L,38884L,38885L,38886L,38887L,
95976 38888L,38889L,38890L,38891L,38892L,38893L,38894L,38895L,38896L,38897L,
95977 38898L,38899L,38900L,38901L,38902L,38903L,38904L,38905L,38906L,38907L,
95978 38908L,38909L,38910L,38911L,38912L,38913L,38914L,38915L,38916L,38917L,
95979 38918L,38919L,38920L,38921L,38922L,38923L,38924L,38925L,38926L,38927L,
95980 38928L,38929L,38930L,38931L,38932L,38933L,38934L,38935L,38936L,38937L,
95981 38938L,38939L,38940L,38941L,38942L,38943L,38944L,38945L,38946L,38947L,
95982 38948L,38949L,38950L,38951L,38952L,38953L,38954L,38955L,38956L,38957L,
95983 38958L,38959L,38960L,38961L,38962L,38963L,38964L,38965L,38966L,38967L,
95984 38968L,38969L,38970L,38971L,38972L,38973L,38974L,38975L,38976L,38977L,
95985 38978L,38979L,38980L,38981L,38982L,38983L,38984L,38985L,38986L,38987L,
95986 38988L,38989L,38990L,38991L,38992L,38993L,38994L,38995L,38996L,38997L,
95987 38998L,38999L,39000L,39001L,39002L,39003L,39004L,39005L,39006L,39007L,
95988 39008L,39009L,39010L,39011L,39012L,39013L,39014L,39015L,39016L,39017L,
95989 39018L,39019L,39020L,39021L,39022L,39023L,39024L,39025L,39026L,39027L,
95990 39028L,39029L,39030L,39031L,39032L,39033L,39034L,39035L,39036L,39037L,
95991 39038L,39039L,39040L,39041L,39042L,39043L,39044L,39045L,39046L,39047L,
95992 39048L,39049L,39050L,39051L,39052L,39053L,39054L,39055L,39056L,39057L,
95993 39058L,39059L,39060L,39061L,39062L,39063L,39064L,39065L,39066L,39067L,
95994 39068L,39069L,39070L,39071L,39072L,39073L,39074L,39075L,39076L,39077L,
95995 39078L,39079L,39080L,39081L,39082L,39083L,39084L,39085L,39086L,39087L,
95996 39088L,39089L,39090L,39091L,39092L,39093L,39094L,39095L,39096L,39097L,
95997 39098L,39099L,39100L,39101L,39102L,39103L,39104L,39105L,39106L,39107L,
95998 39108L,39109L,39110L,39111L,39112L,39113L,39114L,39115L,39116L,39117L,
95999 39118L,39119L,39120L,39121L,39122L,39123L,39124L,39125L,39126L,39127L,
96000 39128L,39129L,39130L,39131L,39132L,39133L,39134L,39135L,39136L,39137L,
96001 39138L,39139L,39140L,39141L,39142L,39143L,39144L,39145L,39146L,39147L,
96002 39148L,39149L,39150L,39151L,39152L,39153L,39154L,39155L,39156L,39157L,
96003 39158L,39159L,39160L,39161L,39162L,39163L,39164L,39165L,39166L,39167L,
96004 39168L,39169L,39170L,39171L,39172L,39173L,39174L,39175L,39176L,39177L,
96005 39178L,39179L,39180L,39181L,39182L,39183L,39184L,39185L,39186L,39187L,
96006 39188L,39189L,39190L,39191L,39192L,39193L,39194L,39195L,39196L,39197L,
96007 39198L,39199L,39200L,39201L,39202L,39203L,39204L,39205L,39206L,39207L,
96008 39208L,39209L,39210L,39211L,39212L,39213L,39214L,39215L,39216L,39217L,
96009 39218L,39219L,39220L,39221L,39222L,39223L,39224L,39225L,39226L,39227L,
96010 39228L,39229L,39230L,39231L,39232L,39233L,39234L,39235L,39236L,39237L,
96011 39238L,39239L,39240L,39241L,39242L,39243L,39244L,39245L,39246L,39247L,
96012 39248L,39249L,39250L,39251L,39252L,39253L,39254L,39255L,39256L,39257L,
96013 39258L,39259L,39260L,39261L,39262L,39263L,39264L,39265L,39266L,39267L,
96014 39268L,39269L,39270L,39271L,39272L,39273L,39274L,39275L,39276L,39277L,
96015 39278L,39279L,39280L,39281L,39282L,39283L,39284L,39285L,39286L,39287L,
96016 39288L,39289L,39290L,39291L,39292L,39293L,39294L,39295L,39296L,39297L,
96017 39298L,39299L,39300L,39301L,39302L,39303L,39304L,39305L,39306L,39307L,
96018 39308L,39309L,39310L,39311L,39312L,39313L,39314L,39315L,39316L,39317L,
96019 39318L,39319L,39320L,39321L,39322L,39323L,39324L,39325L,39326L,39327L,
96020 39328L,39329L,39330L,39331L,39332L,39333L,39334L,39335L,39336L,39337L,
96021 39338L,39339L,39340L,39341L,39342L,39343L,39344L,39345L,39346L,39347L,
96022 39348L,39349L,39350L,39351L,39352L,39353L,39354L,39355L,39356L,39357L,
96023 39358L,39359L,39360L,39361L,39362L,39363L,39364L,39365L,39366L,39367L,
96024 39368L,39369L,39370L,39371L,39372L,39373L,39374L,39375L,39376L,39377L,
96025 39378L,39379L,39380L,39381L,39382L,39383L,39384L,39385L,39386L,39387L,
96026 39388L,39389L,39390L,39391L,39392L,39393L,39394L,39395L,39396L,39397L,
96027 39398L,39399L,39400L,39401L,39402L,39403L,39404L,39405L,39406L,39407L,
96028 39408L,39409L,39410L,39411L,39412L,39413L,39414L,39415L,39416L,39417L,
96029 39418L,39419L,39420L,39421L,39422L,39423L,39424L,39425L,39426L,39427L,
96030 39428L,39429L,39430L,39431L,39432L,39433L,39434L,39435L,39436L,39437L,
96031 39438L,39439L,39440L,39441L,39442L,39443L,39444L,39445L,39446L,39447L,
96032 39448L,39449L,39450L,39451L,39452L,39453L,39454L,39455L,39456L,39457L,
96033 39458L,39459L,39460L,39461L,39462L,39463L,39464L,39465L,39466L,39467L,
96034 39468L,39469L,39470L,39471L,39472L,39473L,39474L,39475L,39476L,39477L,
96035 39478L,39479L,39480L,39481L,39482L,39483L,39484L,39485L,39486L,39487L,
96036 39488L,39489L,39490L,39491L,39492L,39493L,39494L,39495L,39496L,39497L,
96037 39498L,39499L,39500L,39501L,39502L,39503L,39504L,39505L,39506L,39507L,
96038 39508L,39509L,39510L,39511L,39512L,39513L,39514L,39515L,39516L,39517L,
96039 39518L,39519L,39520L,39521L,39522L,39523L,39524L,39525L,39526L,39527L,
96040 39528L,39529L,39530L,39531L,39532L,39533L,39534L,39535L,39536L,39537L,
96041 39538L,39539L,39540L,39541L,39542L,39543L,39544L,39545L,39546L,39547L,
96042 39548L,39549L,39550L,39551L,39552L,39553L,39554L,39555L,39556L,39557L,
96043 39558L,39559L,39560L,39561L,39562L,39563L,39564L,39565L,39566L,39567L,
96044 39568L,39569L,39570L,39571L,39572L,39573L,39574L,39575L,39576L,39577L,
96045 39578L,39579L,39580L,39581L,39582L,39583L,39584L,39585L,39586L,39587L,
96046 39588L,39589L,39590L,39591L,39592L,39593L,39594L,39595L,39596L,39597L,
96047 39598L,39599L,39600L,39601L,39602L,39603L,39604L,39605L,39606L,39607L,
96048 39608L,39609L,39610L,39611L,39612L,39613L,39614L,39615L,39616L,39617L,
96049 39618L,39619L,39620L,39621L,39622L,39623L,39624L,39625L,39626L,39627L,
96050 39628L,39629L,39630L,39631L,39632L,39633L,39634L,39635L,39636L,39637L,
96051 39638L,39639L,39640L,39641L,39642L,39643L,39644L,39645L,39646L,39647L,
96052 39648L,39649L,39650L,39651L,39652L,39653L,39654L,39655L,39656L,39657L,
96053 39658L,39659L,39660L,39661L,39662L,39663L,39664L,39665L,39666L,39667L,
96054 39668L,39669L,39670L,39671L,39672L,39673L,39674L,39675L,39676L,39677L,
96055 39678L,39679L,39680L,39681L,39682L,39683L,39684L,39685L,39686L,39687L,
96056 39688L,39689L,39690L,39691L,39692L,39693L,39694L,39695L,39696L,39697L,
96057 39698L,39699L,39700L,39701L,39702L,39703L,39704L,39705L,39706L,39707L,
96058 39708L,39709L,39710L,39711L,39712L,39713L,39714L,39715L,39716L,39717L,
96059 39718L,39719L,39720L,39721L,39722L,39723L,39724L,39725L,39726L,39727L,
96060 39728L,39729L,39730L,39731L,39732L,39733L,39734L,39735L,39736L,39737L,
96061 39738L,39739L,39740L,39741L,39742L,39743L,39744L,39745L,39746L,39747L,
96062 39748L,39749L,39750L,39751L,39752L,39753L,39754L,39755L,39756L,39757L,
96063 39758L,39759L,39760L,39761L,39762L,39763L,39764L,39765L,39766L,39767L,
96064 39768L,39769L,39770L,39771L,39772L,39773L,39774L,39775L,39776L,39777L,
96065 39778L,39779L,39780L,39781L,39782L,39783L,39784L,39785L,39786L,39787L,
96066 39788L,39789L,39790L,39791L,39792L,39793L,39794L,39795L,39796L,39797L,
96067 39798L,39799L,39800L,39801L,39802L,39803L,39804L,39805L,39806L,39807L,
96068 39808L,39809L,39810L,39811L,39812L,39813L,39814L,39815L,39816L,39817L,
96069 39818L,39819L,39820L,39821L,39822L,39823L,39824L,39825L,39826L,39827L,
96070 39828L,39829L,39830L,39831L,39832L,39833L,39834L,39835L,39836L,39837L,
96071 39838L,39839L,39840L,39841L,39842L,39843L,39844L,39845L,39846L,39847L,
96072 39848L,39849L,39850L,39851L,39852L,39853L,39854L,39855L,39856L,39857L,
96073 39858L,39859L,39860L,39861L,39862L,39863L,39864L,39865L,39866L,39867L,
96074 39868L,39869L,39870L,39871L,39872L,39873L,39874L,39875L,39876L,39877L,
96075 39878L,39879L,39880L,39881L,39882L,39883L,39884L,39885L,39886L,39887L,
96076 39888L,39889L,39890L,39891L,39892L,39893L,39894L,39895L,39896L,39897L,
96077 39898L,39899L,39900L,39901L,39902L,39903L,39904L,39905L,39906L,39907L,
96078 39908L,39909L,39910L,39911L,39912L,39913L,39914L,39915L,39916L,39917L,
96079 39918L,39919L,39920L,39921L,39922L,39923L,39924L,39925L,39926L,39927L,
96080 39928L,39929L,39930L,39931L,39932L,39933L,39934L,39935L,39936L,39937L,
96081 39938L,39939L,39940L,39941L,39942L,39943L,39944L,39945L,39946L,39947L,
96082 39948L,39949L,39950L,39951L,39952L,39953L,39954L,39955L,39956L,39957L,
96083 39958L,39959L,39960L,39961L,39962L,39963L,39964L,39965L,39966L,39967L,
96084 39968L,39969L,39970L,39971L,39972L,39973L,39974L,39975L,39976L,39977L,
96085 39978L,39979L,39980L,39981L,39982L,39983L,39984L,39985L,39986L,39987L,
96086 39988L,39989L,39990L,39991L,39992L,39993L,39994L,39995L,39996L,39997L,
96087 39998L,39999L,40000L,40001L,40002L,40003L,40004L,40005L,40006L,40007L,
96088 40008L,40009L,40010L,40011L,40012L,40013L,40014L,40015L,40016L,40017L,
96089 40018L,40019L,40020L,40021L,40022L,40023L,40024L,40025L,40026L,40027L,
96090 40028L,40029L,40030L,40031L,40032L,40033L,40034L,40035L,40036L,40037L,
96091 40038L,40039L,40040L,40041L,40042L,40043L,40044L,40045L,40046L,40047L,
96092 40048L,40049L,40050L,40051L,40052L,40053L,40054L,40055L,40056L,40057L,
96093 40058L,40059L,40060L,40061L,40062L,40063L,40064L,40065L,40066L,40067L,
96094 40068L,40069L,40070L,40071L,40072L,40073L,40074L,40075L,40076L,40077L,
96095 40078L,40079L,40080L,40081L,40082L,40083L,40084L,40085L,40086L,40087L,
96096 40088L,40089L,40090L,40091L,40092L,40093L,40094L,40095L,40096L,40097L,
96097 40098L,40099L,40100L,40101L,40102L,40103L,40104L,40105L,40106L,40107L,
96098 40108L,40109L,40110L,40111L,40112L,40113L,40114L,40115L,40116L,40117L,
96099 40118L,40119L,40120L,40121L,40122L,40123L,40124L,40125L,40126L,40127L,
96100 40128L,40129L,40130L,40131L,40132L,40133L,40134L,40135L,40136L,40137L,
96101 40138L,40139L,40140L,40141L,40142L,40143L,40144L,40145L,40146L,40147L,
96102 40148L,40149L,40150L,40151L,40152L,40153L,40154L,40155L,40156L,40157L,
96103 40158L,40159L,40160L,40161L,40162L,40163L,40164L,40165L,40166L,40167L,
96104 40168L,40169L,40170L,40171L,40172L,40173L,40174L,40175L,40176L,40177L,
96105 40178L,40179L,40180L,40181L,40182L,40183L,40184L,40185L,40186L,40187L,
96106 40188L,40189L,40190L,40191L,40192L,40193L,40194L,40195L,40196L,40197L,
96107 40198L,40199L,40200L,40201L,40202L,40203L,40204L,40205L,40206L,40207L,
96108 40208L,40209L,40210L,40211L,40212L,40213L,40214L,40215L,40216L,40217L,
96109 40218L,40219L,40220L,40221L,40222L,40223L,40224L,40225L,40226L,40227L,
96110 40228L,40229L,40230L,40231L,40232L,40233L,40234L,40235L,40236L,40237L,
96111 40238L,40239L,40240L,40241L,40242L,40243L,40244L,40245L,40246L,40247L,
96112 40248L,40249L,40250L,40251L,40252L,40253L,40254L,40255L,40256L,40257L,
96113 40258L,40259L,40260L,40261L,40262L,40263L,40264L,40265L,40266L,40267L,
96114 40268L,40269L,40270L,40271L,40272L,40273L,40274L,40275L,40276L,40277L,
96115 40278L,40279L,40280L,40281L,40282L,40283L,40284L,40285L,40286L,40287L,
96116 40288L,40289L,40290L,40291L,40292L,40293L,40294L,40295L,40296L,40297L,
96117 40298L,40299L,40300L,40301L,40302L,40303L,40304L,40305L,40306L,40307L,
96118 40308L,40309L,40310L,40311L,40312L,40313L,40314L,40315L,40316L,40317L,
96119 40318L,40319L,40320L,40321L,40322L,40323L,40324L,40325L,40326L,40327L,
96120 40328L,40329L,40330L,40331L,40332L,40333L,40334L,40335L,40336L,40337L,
96121 40338L,40339L,40340L,40341L,40342L,40343L,40344L,40345L,40346L,40347L,
96122 40348L,40349L,40350L,40351L,40352L,40353L,40354L,40355L,40356L,40357L,
96123 40358L,40359L,40360L,40361L,40362L,40363L,40364L,40365L,40366L,40367L,
96124 40368L,40369L,40370L,40371L,40372L,40373L,40374L,40375L,40376L,40377L,
96125 40378L,40379L,40380L,40381L,40382L,40383L,40384L,40385L,40386L,40387L,
96126 40388L,40389L,40390L,40391L,40392L,40393L,40394L,40395L,40396L,40397L,
96127 40398L,40399L,40400L,40401L,40402L,40403L,40404L,40405L,40406L,40407L,
96128 40408L,40409L,40410L,40411L,40412L,40413L,40414L,40415L,40416L,40417L,
96129 40418L,40419L,40420L,40421L,40422L,40423L,40424L,40425L,40426L,40427L,
96130 40428L,40429L,40430L,40431L,40432L,40433L,40434L,40435L,40436L,40437L,
96131 40438L,40439L,40440L,40441L,40442L,40443L,40444L,40445L,40446L,40447L,
96132 40448L,40449L,40450L,40451L,40452L,40453L,40454L,40455L,40456L,40457L,
96133 40458L,40459L,40460L,40461L,40462L,40463L,40464L,40465L,40466L,40467L,
96134 40468L,40469L,40470L,40471L,40472L,40473L,40474L,40475L,40476L,40477L,
96135 40478L,40479L,40480L,40481L,40482L,40483L,40484L,40485L,40486L,40487L,
96136 40488L,40489L,40490L,40491L,40492L,40493L,40494L,40495L,40496L,40497L,
96137 40498L,40499L,40500L,40501L,40502L,40503L,40504L,40505L,40506L,40507L,
96138 40508L,40509L,40510L,40511L,40512L,40513L,40514L,40515L,40516L,40517L,
96139 40518L,40519L,40520L,40521L,40522L,40523L,40524L,40525L,40526L,40527L,
96140 40528L,40529L,40530L,40531L,40532L,40533L,40534L,40535L,40536L,40537L,
96141 40538L,40539L,40540L,40541L,40542L,40543L,40544L,40545L,40546L,40547L,
96142 40548L,40549L,40550L,40551L,40552L,40553L,40554L,40555L,40556L,40557L,
96143 40558L,40559L,40560L,40561L,40562L,40563L,40564L,40565L,40566L,40567L,
96144 40568L,40569L,40570L,40571L,40572L,40573L,40574L,40575L,40576L,40577L,
96145 40578L,40579L,40580L,40581L,40582L,40583L,40584L,40585L,40586L,40587L,
96146 40588L,40589L,40590L,40591L,40592L,40593L,40594L,40595L,40596L,40597L,
96147 40598L,40599L,40600L,40601L,40602L,40603L,40604L,40605L,40606L,40607L,
96148 40608L,40609L,40610L,40611L,40612L,40613L,40614L,40615L,40616L,40617L,
96149 40618L,40619L,40620L,40621L,40622L,40623L,40624L,40625L,40626L,40627L,
96150 40628L,40629L,40630L,40631L,40632L,40633L,40634L,40635L,40636L,40637L,
96151 40638L,40639L,40640L,40641L,40642L,40643L,40644L,40645L,40646L,40647L,
96152 40648L,40649L,40650L,40651L,40652L,40653L,40654L,40655L,40656L,40657L,
96153 40658L,40659L,40660L,40661L,40662L,40663L,40664L,40665L,40666L,40667L,
96154 40668L,40669L,40670L,40671L,40672L,40673L,40674L,40675L,40676L,40677L,
96155 40678L,40679L,40680L,40681L,40682L,40683L,40684L,40685L,40686L,40687L,
96156 40688L,40689L,40690L,40691L,40692L,40693L,40694L,40695L,40696L,40697L,
96157 40698L,40699L,40700L,40701L,40702L,40703L,40704L,40705L,40706L,40707L,
96158 40708L,40709L,40710L,40711L,40712L,40713L,40714L,40715L,40716L,40717L,
96159 40718L,40719L,40720L,40721L,40722L,40723L,40724L,40725L,40726L,40727L,
96160 40728L,40729L,40730L,40731L,40732L,40733L,40734L,40735L,40736L,40737L,
96161 40738L,40739L,40740L,40741L,40742L,40743L,40744L,40745L,40746L,40747L,
96162 40748L,40749L,40750L,40751L,40752L,40753L,40754L,40755L,40756L,40757L,
96163 40758L,40759L,40760L,40761L,40762L,40763L,40764L,40765L,40766L,40767L,
96164 40768L,40769L,40770L,40771L,40772L,40773L,40774L,40775L,40776L,40777L,
96165 40778L,40779L,40780L,40781L,40782L,40783L,40784L,40785L,40786L,40787L,
96166 40788L,40789L,40790L,40791L,40792L,40793L,40794L,40795L,40796L,40797L,
96167 40798L,40799L,40800L,40801L,40802L,40803L,40804L,40805L,40806L,40807L,
96168 40808L,40809L,40810L,40811L,40812L,40813L,40814L,40815L,40816L,40817L,
96169 40818L,40819L,40820L,40821L,40822L,40823L,40824L,40825L,40826L,40827L,
96170 40828L,40829L,40830L,40831L,40832L,40833L,40834L,40835L,40836L,40837L,
96171 40838L,40839L,40840L,40841L,40842L,40843L,40844L,40845L,40846L,40847L,
96172 40848L,40849L,40850L,40851L,40852L,40853L,40854L,40855L,40856L,40857L,
96173 40858L,40859L,40860L,40861L,40862L,40863L,40864L,40865L,40866L,40867L,
96174 40868L,40869L,40870L,40871L,40872L,40873L,40874L,40875L,40876L,40877L,
96175 40878L,40879L,40880L,40881L,40882L,40883L,40884L,40885L,40886L,40887L,
96176 40888L,40889L,40890L,40891L,40892L,40893L,40894L,40895L,40896L,40897L,
96177 40898L,40899L,40900L,40901L,40902L,40903L,40904L,40905L,40906L,40907L,
96178 40908L,40909L,40910L,40911L,40912L,40913L,40914L,40915L,40916L,40917L,
96179 40918L,40919L,40920L,40921L,40922L,40923L,40924L,40925L,40926L,40927L,
96180 40928L,40929L,40930L,40931L,40932L,40933L,40934L,40935L,40936L,40937L,
96181 40938L,40939L,40940L,40941L,40942L,40943L,40944L,40945L,40946L,40947L,
96182 40948L,40949L,40950L,40951L,40952L,40953L,40954L,40955L,40956L,40957L,
96183 40958L,40959L,40960L,40961L,40962L,40963L,40964L,40965L,40966L,40967L,
96184 40968L,40969L,40970L,40971L,40972L,40973L,40974L,40975L,40976L,40977L,
96185 40978L,40979L,40980L,40981L,40982L,40983L,40984L,40985L,40986L,40987L,
96186 40988L,40989L,40990L,40991L,40992L,40993L,40994L,40995L,40996L,40997L,
96187 40998L,40999L,41000L,41001L,41002L,41003L,41004L,41005L,41006L,41007L,
96188 41008L,41009L,41010L,41011L,41012L,41013L,41014L,41015L,41016L,41017L,
96189 41018L,41019L,41020L,41021L,41022L,41023L,41024L,41025L,41026L,41027L,
96190 41028L,41029L,41030L,41031L,41032L,41033L,41034L,41035L,41036L,41037L,
96191 41038L,41039L,41040L,41041L,41042L,41043L,41044L,41045L,41046L,41047L,
96192 41048L,41049L,41050L,41051L,41052L,41053L,41054L,41055L,41056L,41057L,
96193 41058L,41059L,41060L,41061L,41062L,41063L,41064L,41065L,41066L,41067L,
96194 41068L,41069L,41070L,41071L,41072L,41073L,41074L,41075L,41076L,41077L,
96195 41078L,41079L,41080L,41081L,41082L,41083L,41084L,41085L,41086L,41087L,
96196 41088L,41089L,41090L,41091L,41092L,41093L,41094L,41095L,41096L,41097L,
96197 41098L,41099L,41100L,41101L,41102L,41103L,41104L,41105L,41106L,41107L,
96198 41108L,41109L,41110L,41111L,41112L,41113L,41114L,41115L,41116L,41117L,
96199 41118L,41119L,41120L,41121L,41122L,41123L,41124L,41125L,41126L,41127L,
96200 41128L,41129L,41130L,41131L,41132L,41133L,41134L,41135L,41136L,41137L,
96201 41138L,41139L,41140L,41141L,41142L,41143L,41144L,41145L,41146L,41147L,
96202 41148L,41149L,41150L,41151L,41152L,41153L,41154L,41155L,41156L,41157L,
96203 41158L,41159L,41160L,41161L,41162L,41163L,41164L,41165L,41166L,41167L,
96204 41168L,41169L,41170L,41171L,41172L,41173L,41174L,41175L,41176L,41177L,
96205 41178L,41179L,41180L,41181L,41182L,41183L,41184L,41185L,41186L,41187L,
96206 41188L,41189L,41190L,41191L,41192L,41193L,41194L,41195L,41196L,41197L,
96207 41198L,41199L,41200L,41201L,41202L,41203L,41204L,41205L,41206L,41207L,
96208 41208L,41209L,41210L,41211L,41212L,41213L,41214L,41215L,41216L,41217L,
96209 41218L,41219L,41220L,41221L,41222L,41223L,41224L,41225L,41226L,41227L,
96210 41228L,41229L,41230L,41231L,41232L,41233L,41234L,41235L,41236L,41237L,
96211 41238L,41239L,41240L,41241L,41242L,41243L,41244L,41245L,41246L,41247L,
96212 41248L,41249L,41250L,41251L,41252L,41253L,41254L,41255L,41256L,41257L,
96213 41258L,41259L,41260L,41261L,41262L,41263L,41264L,41265L,41266L,41267L,
96214 41268L,41269L,41270L,41271L,41272L,41273L,41274L,41275L,41276L,41277L,
96215 41278L,41279L,41280L,41281L,41282L,41283L,41284L,41285L,41286L,41287L,
96216 41288L,41289L,41290L,41291L,41292L,41293L,41294L,41295L,41296L,41297L,
96217 41298L,41299L,41300L,41301L,41302L,41303L,41304L,41305L,41306L,41307L,
96218 41308L,41309L,41310L,41311L,41312L,41313L,41314L,41315L,41316L,41317L,
96219 41318L,41319L,41320L,41321L,41322L,41323L,41324L,41325L,41326L,41327L,
96220 41328L,41329L,41330L,41331L,41332L,41333L,41334L,41335L,41336L,41337L,
96221 41338L,41339L,41340L,41341L,41342L,41343L,41344L,41345L,41346L,41347L,
96222 41348L,41349L,41350L,41351L,41352L,41353L,41354L,41355L,41356L,41357L,
96223 41358L,41359L,41360L,41361L,41362L,41363L,41364L,41365L,41366L,41367L,
96224 41368L,41369L,41370L,41371L,41372L,41373L,41374L,41375L,41376L,41377L,
96225 41378L,41379L,41380L,41381L,41382L,41383L,41384L,41385L,41386L,41387L,
96226 41388L,41389L,41390L,41391L,41392L,41393L,41394L,41395L,41396L,41397L,
96227 41398L,41399L,41400L,41401L,41402L,41403L,41404L,41405L,41406L,41407L,
96228 41408L,41409L,41410L,41411L,41412L,41413L,41414L,41415L,41416L,41417L,
96229 41418L,41419L,41420L,41421L,41422L,41423L,41424L,41425L,41426L,41427L,
96230 41428L,41429L,41430L,41431L,41432L,41433L,41434L,41435L,41436L,41437L,
96231 41438L,41439L,41440L,41441L,41442L,41443L,41444L,41445L,41446L,41447L,
96232 41448L,41449L,41450L,41451L,41452L,41453L,41454L,41455L,41456L,41457L,
96233 41458L,41459L,41460L,41461L,41462L,41463L,41464L,41465L,41466L,41467L,
96234 41468L,41469L,41470L,41471L,41472L,41473L,41474L,41475L,41476L,41477L,
96235 41478L,41479L,41480L,41481L,41482L,41483L,41484L,41485L,41486L,41487L,
96236 41488L,41489L,41490L,41491L,41492L,41493L,41494L,41495L,41496L,41497L,
96237 41498L,41499L,41500L,41501L,41502L,41503L,41504L,41505L,41506L,41507L,
96238 41508L,41509L,41510L,41511L,41512L,41513L,41514L,41515L,41516L,41517L,
96239 41518L,41519L,41520L,41521L,41522L,41523L,41524L,41525L,41526L,41527L,
96240 41528L,41529L,41530L,41531L,41532L,41533L,41534L,41535L,41536L,41537L,
96241 41538L,41539L,41540L,41541L,41542L,41543L,41544L,41545L,41546L,41547L,
96242 41548L,41549L,41550L,41551L,41552L,41553L,41554L,41555L,41556L,41557L,
96243 41558L,41559L,41560L,41561L,41562L,41563L,41564L,41565L,41566L,41567L,
96244 41568L,41569L,41570L,41571L,41572L,41573L,41574L,41575L,41576L,41577L,
96245 41578L,41579L,41580L,41581L,41582L,41583L,41584L,41585L,41586L,41587L,
96246 41588L,41589L,41590L,41591L,41592L,41593L,41594L,41595L,41596L,41597L,
96247 41598L,41599L,41600L,41601L,41602L,41603L,41604L,41605L,41606L,41607L,
96248 41608L,41609L,41610L,41611L,41612L,41613L,41614L,41615L,41616L,41617L,
96249 41618L,41619L,41620L,41621L,41622L,41623L,41624L,41625L,41626L,41627L,
96250 41628L,41629L,41630L,41631L,41632L,41633L,41634L,41635L,41636L,41637L,
96251 41638L,41639L,41640L,41641L,41642L,41643L,41644L,41645L,41646L,41647L,
96252 41648L,41649L,41650L,41651L,41652L,41653L,41654L,41655L,41656L,41657L,
96253 41658L,41659L,41660L,41661L,41662L,41663L,41664L,41665L,41666L,41667L,
96254 41668L,41669L,41670L,41671L,41672L,41673L,41674L,41675L,41676L,41677L,
96255 41678L,41679L,41680L,41681L,41682L,41683L,41684L,41685L,41686L,41687L,
96256 41688L,41689L,41690L,41691L,41692L,41693L,41694L,41695L,41696L,41697L,
96257 41698L,41699L,41700L,41701L,41702L,41703L,41704L,41705L,41706L,41707L,
96258 41708L,41709L,41710L,41711L,41712L,41713L,41714L,41715L,41716L,41717L,
96259 41718L,41719L,41720L,41721L,41722L,41723L,41724L,41725L,41726L,41727L,
96260 41728L,41729L,41730L,41731L,41732L,41733L,41734L,41735L,41736L,41737L,
96261 41738L,41739L,41740L,41741L,41742L,41743L,41744L,41745L,41746L,41747L,
96262 41748L,41749L,41750L,41751L,41752L,41753L,41754L,41755L,41756L,41757L,
96263 41758L,41759L,41760L,41761L,41762L,41763L,41764L,41765L,41766L,41767L,
96264 41768L,41769L,41770L,41771L,41772L,41773L,41774L,41775L,41776L,41777L,
96265 41778L,41779L,41780L,41781L,41782L,41783L,41784L,41785L,41786L,41787L,
96266 41788L,41789L,41790L,41791L,41792L,41793L,41794L,41795L,41796L,41797L,
96267 41798L,41799L,41800L,41801L,41802L,41803L,41804L,41805L,41806L,41807L,
96268 41808L,41809L,41810L,41811L,41812L,41813L,41814L,41815L,41816L,41817L,
96269 41818L,41819L,41820L,41821L,41822L,41823L,41824L,41825L,41826L,41827L,
96270 41828L,41829L,41830L,41831L,41832L,41833L,41834L,41835L,41836L,41837L,
96271 41838L,41839L,41840L,41841L,41842L,41843L,41844L,41845L,41846L,41847L,
96272 41848L,41849L,41850L,41851L,41852L,41853L,41854L,41855L,41856L,41857L,
96273 41858L,41859L,41860L,41861L,41862L,41863L,41864L,41865L,41866L,41867L,
96274 41868L,41869L,41870L,41871L,41872L,41873L,41874L,41875L,41876L,41877L,
96275 41878L,41879L,41880L,41881L,41882L,41883L,41884L,41885L,41886L,41887L,
96276 41888L,41889L,41890L,41891L,41892L,41893L,41894L,41895L,41896L,41897L,
96277 41898L,41899L,41900L,41901L,41902L,41903L,41904L,41905L,41906L,41907L,
96278 41908L,41909L,41910L,41911L,41912L,41913L,41914L,41915L,41916L,41917L,
96279 41918L,41919L,41920L,41921L,41922L,41923L,41924L,41925L,41926L,41927L,
96280 41928L,41929L,41930L,41931L,41932L,41933L,41934L,41935L,41936L,41937L,
96281 41938L,41939L,41940L,41941L,41942L,41943L,41944L,41945L,41946L,41947L,
96282 41948L,41949L,41950L,41951L,41952L,41953L,41954L,41955L,41956L,41957L,
96283 41958L,41959L,41960L,41961L,41962L,41963L,41964L,41965L,41966L,41967L,
96284 41968L,41969L,41970L,41971L,41972L,41973L,41974L,41975L,41976L,41977L,
96285 41978L,41979L,41980L,41981L,41982L,41983L,41984L,41985L,41986L,41987L,
96286 41988L,41989L,41990L,41991L,41992L,41993L,41994L,41995L,41996L,41997L,
96287 41998L,41999L,42000L,42001L,42002L,42003L,42004L,42005L,42006L,42007L,
96288 42008L,42009L,42010L,42011L,42012L,42013L,42014L,42015L,42016L,42017L,
96289 42018L,42019L,42020L,42021L,42022L,42023L,42024L,42025L,42026L,42027L,
96290 42028L,42029L,42030L,42031L,42032L,42033L,42034L,42035L,42036L,42037L,
96291 42038L,42039L,42040L,42041L,42042L,42043L,42044L,42045L,42046L,42047L,
96292 42048L,42049L,42050L,42051L,42052L,42053L,42054L,42055L,42056L,42057L,
96293 42058L,42059L,42060L,42061L,42062L,42063L,42064L,42065L,42066L,42067L,
96294 42068L,42069L,42070L,42071L,42072L,42073L,42074L,42075L,42076L,42077L,
96295 42078L,42079L,42080L,42081L,42082L,42083L,42084L,42085L,42086L,42087L,
96296 42088L,42089L,42090L,42091L,42092L,42093L,42094L,42095L,42096L,42097L,
96297 42098L,42099L,42100L,42101L,42102L,42103L,42104L,42105L,42106L,42107L,
96298 42108L,42109L,42110L,42111L,42112L,42113L,42114L,42115L,42116L,42117L,
96299 42118L,42119L,42120L,42121L,42122L,42123L,42124L,42125L,42126L,42127L,
96300 42128L,42129L,42130L,42131L,42132L,42133L,42134L,42135L,42136L,42137L,
96301 42138L,42139L,42140L,42141L,42142L,42143L,42144L,42145L,42146L,42147L,
96302 42148L,42149L,42150L,42151L,42152L,42153L,42154L,42155L,42156L,42157L,
96303 42158L,42159L,42160L,42161L,42162L,42163L,42164L,42165L,42166L,42167L,
96304 42168L,42169L,42170L,42171L,42172L,42173L,42174L,42175L,42176L,42177L,
96305 42178L,42179L,42180L,42181L,42182L,42183L,42184L,42185L,42186L,42187L,
96306 42188L,42189L,42190L,42191L,42192L,42193L,42194L,42195L,42196L,42197L,
96307 42198L,42199L,42200L,42201L,42202L,42203L,42204L,42205L,42206L,42207L,
96308 42208L,42209L,42210L,42211L,42212L,42213L,42214L,42215L,42216L,42217L,
96309 42218L,42219L,42220L,42221L,42222L,42223L,42224L,42225L,42226L,42227L,
96310 42228L,42229L,42230L,42231L,42232L,42233L,42234L,42235L,42236L,42237L,
96311 42238L,42239L,42240L,42241L,42242L,42243L,42244L,42245L,42246L,42247L,
96312 42248L,42249L,42250L,42251L,42252L,42253L,42254L,42255L,42256L,42257L,
96313 42258L,42259L,42260L,42261L,42262L,42263L,42264L,42265L,42266L,42267L,
96314 42268L,42269L,42270L,42271L,42272L,42273L,42274L,42275L,42276L,42277L,
96315 42278L,42279L,42280L,42281L,42282L,42283L,42284L,42285L,42286L,42287L,
96316 42288L,42289L,42290L,42291L,42292L,42293L,42294L,42295L,42296L,42297L,
96317 42298L,42299L,42300L,42301L,42302L,42303L,42304L,42305L,42306L,42307L,
96318 42308L,42309L,42310L,42311L,42312L,42313L,42314L,42315L,42316L,42317L,
96319 42318L,42319L,42320L,42321L,42322L,42323L,42324L,42325L,42326L,42327L,
96320 42328L,42329L,42330L,42331L,42332L,42333L,42334L,42335L,42336L,42337L,
96321 42338L,42339L,42340L,42341L,42342L,42343L,42344L,42345L,42346L,42347L,
96322 42348L,42349L,42350L,42351L,42352L,42353L,42354L,42355L,42356L,42357L,
96323 42358L,42359L,42360L,42361L,42362L,42363L,42364L,42365L,42366L,42367L,
96324 42368L,42369L,42370L,42371L,42372L,42373L,42374L,42375L,42376L,42377L,
96325 42378L,42379L,42380L,42381L,42382L,42383L,42384L,42385L,42386L,42387L,
96326 42388L,42389L,42390L,42391L,42392L,42393L,42394L,42395L,42396L,42397L,
96327 42398L,42399L,42400L,42401L,42402L,42403L,42404L,42405L,42406L,42407L,
96328 42408L,42409L,42410L,42411L,42412L,42413L,42414L,42415L,42416L,42417L,
96329 42418L,42419L,42420L,42421L,42422L,42423L,42424L,42425L,42426L,42427L,
96330 42428L,42429L,42430L,42431L,42432L,42433L,42434L,42435L,42436L,42437L,
96331 42438L,42439L,42440L,42441L,42442L,42443L,42444L,42445L,42446L,42447L,
96332 42448L,42449L,42450L,42451L,42452L,42453L,42454L,42455L,42456L,42457L,
96333 42458L,42459L,42460L,42461L,42462L,42463L,42464L,42465L,42466L,42467L,
96334 42468L,42469L,42470L,42471L,42472L,42473L,42474L,42475L,42476L,42477L,
96335 42478L,42479L,42480L,42481L,42482L,42483L,42484L,42485L,42486L,42487L,
96336 42488L,42489L,42490L,42491L,42492L,42493L,42494L,42495L,42496L,42497L,
96337 42498L,42499L,42500L,42501L,42502L,42503L,42504L,42505L,42506L,42507L,
96338 42508L,42509L,42510L,42511L,42512L,42513L,42514L,42515L,42516L,42517L,
96339 42518L,42519L,42520L,42521L,42522L,42523L,42524L,42525L,42526L,42527L,
96340 42528L,42529L,42530L,42531L,42532L,42533L,42534L,42535L,42536L,42537L,
96341 42538L,42539L,42540L,42541L,42542L,42543L,42544L,42545L,42546L,42547L,
96342 42548L,42549L,42550L,42551L,42552L,42553L,42554L,42555L,42556L,42557L,
96343 42558L,42559L,42560L,42560L,42562L,42562L,42564L,42564L,42566L,42566L,
96344 42568L,42568L,42570L,42570L,42572L,42572L,42574L,42574L,42576L,42576L,
96345 42578L,42578L,42580L,42580L,42582L,42582L,42584L,42584L,42586L,42586L,
96346 42588L,42588L,42590L,42590L,42592L,42592L,42594L,42594L,42596L,42596L,
96347 42598L,42598L,42600L,42600L,42602L,42602L,42604L,42604L,42606L,42607L,
96348 42608L,42609L,42610L,42611L,42612L,42613L,42614L,42615L,42616L,42617L,
96349 42618L,42619L,42620L,42621L,42622L,42623L,42624L,42624L,42626L,42626L,
96350 42628L,42628L,42630L,42630L,42632L,42632L,42634L,42634L,42636L,42636L,
96351 42638L,42638L,42640L,42640L,42642L,42642L,42644L,42644L,42646L,42646L,
96352 42648L,42648L,42650L,42650L,42652L,42653L,42654L,42655L,42656L,42657L,
96353 42658L,42659L,42660L,42661L,42662L,42663L,42664L,42665L,42666L,42667L,
96354 42668L,42669L,42670L,42671L,42672L,42673L,42674L,42675L,42676L,42677L,
96355 42678L,42679L,42680L,42681L,42682L,42683L,42684L,42685L,42686L,42687L,
96356 42688L,42689L,42690L,42691L,42692L,42693L,42694L,42695L,42696L,42697L,
96357 42698L,42699L,42700L,42701L,42702L,42703L,42704L,42705L,42706L,42707L,
96358 42708L,42709L,42710L,42711L,42712L,42713L,42714L,42715L,42716L,42717L,
96359 42718L,42719L,42720L,42721L,42722L,42723L,42724L,42725L,42726L,42727L,
96360 42728L,42729L,42730L,42731L,42732L,42733L,42734L,42735L,42736L,42737L,
96361 42738L,42739L,42740L,42741L,42742L,42743L,42744L,42745L,42746L,42747L,
96362 42748L,42749L,42750L,42751L,42752L,42753L,42754L,42755L,42756L,42757L,
96363 42758L,42759L,42760L,42761L,42762L,42763L,42764L,42765L,42766L,42767L,
96364 42768L,42769L,42770L,42771L,42772L,42773L,42774L,42775L,42776L,42777L,
96365 42778L,42779L,42780L,42781L,42782L,42783L,42784L,42785L,42786L,42786L,
96366 42788L,42788L,42790L,42790L,42792L,42792L,42794L,42794L,42796L,42796L,
96367 42798L,42798L,42800L,42801L,42802L,42802L,42804L,42804L,42806L,42806L,
96368 42808L,42808L,42810L,42810L,42812L,42812L,42814L,42814L,42816L,42816L,
96369 42818L,42818L,42820L,42820L,42822L,42822L,42824L,42824L,42826L,42826L,
96370 42828L,42828L,42830L,42830L,42832L,42832L,42834L,42834L,42836L,42836L,
96371 42838L,42838L,42840L,42840L,42842L,42842L,42844L,42844L,42846L,42846L,
96372 42848L,42848L,42850L,42850L,42852L,42852L,42854L,42854L,42856L,42856L,
96373 42858L,42858L,42860L,42860L,42862L,42862L,42864L,42865L,42866L,42867L,
96374 42868L,42869L,42870L,42871L,42872L,42873L,42873L,42875L,42875L,42877L,
96375 42878L,42878L,42880L,42880L,42882L,42882L,42884L,42884L,42886L,42886L,
96376 42888L,42889L,42890L,42891L,42891L,42893L,42894L,42895L,42896L,42896L,
96377 42898L,42898L,42948L,42901L,42902L,42902L,42904L,42904L,42906L,42906L,
96378 42908L,42908L,42910L,42910L,42912L,42912L,42914L,42914L,42916L,42916L,
96379 42918L,42918L,42920L,42920L,42922L,42923L,42924L,42925L,42926L,42927L,
96380 42928L,42929L,42930L,42931L,42932L,42932L,42934L,42934L,42936L,42936L,
96381 42938L,42938L,42940L,42940L,42942L,42942L,42944L,42945L,42946L,42946L,
96382 42948L,42949L,42950L,42951L,42952L,42953L,42954L,42955L,42956L,42957L,
96383 42958L,42959L,42960L,42961L,42962L,42963L,42964L,42965L,42966L,42967L,
96384 42968L,42969L,42970L,42971L,42972L,42973L,42974L,42975L,42976L,42977L,
96385 42978L,42979L,42980L,42981L,42982L,42983L,42984L,42985L,42986L,42987L,
96386 42988L,42989L,42990L,42991L,42992L,42993L,42994L,42995L,42996L,42997L,
96387 42998L,42999L,43000L,43001L,43002L,43003L,43004L,43005L,43006L,43007L,
96388 43008L,43009L,43010L,43011L,43012L,43013L,43014L,43015L,43016L,43017L,
96389 43018L,43019L,43020L,43021L,43022L,43023L,43024L,43025L,43026L,43027L,
96390 43028L,43029L,43030L,43031L,43032L,43033L,43034L,43035L,43036L,43037L,
96391 43038L,43039L,43040L,43041L,43042L,43043L,43044L,43045L,43046L,43047L,
96392 43048L,43049L,43050L,43051L,43052L,43053L,43054L,43055L,43056L,43057L,
96393 43058L,43059L,43060L,43061L,43062L,43063L,43064L,43065L,43066L,43067L,
96394 43068L,43069L,43070L,43071L,43072L,43073L,43074L,43075L,43076L,43077L,
96395 43078L,43079L,43080L,43081L,43082L,43083L,43084L,43085L,43086L,43087L,
96396 43088L,43089L,43090L,43091L,43092L,43093L,43094L,43095L,43096L,43097L,
96397 43098L,43099L,43100L,43101L,43102L,43103L,43104L,43105L,43106L,43107L,
96398 43108L,43109L,43110L,43111L,43112L,43113L,43114L,43115L,43116L,43117L,
96399 43118L,43119L,43120L,43121L,43122L,43123L,43124L,43125L,43126L,43127L,
96400 43128L,43129L,43130L,43131L,43132L,43133L,43134L,43135L,43136L,43137L,
96401 43138L,43139L,43140L,43141L,43142L,43143L,43144L,43145L,43146L,43147L,
96402 43148L,43149L,43150L,43151L,43152L,43153L,43154L,43155L,43156L,43157L,
96403 43158L,43159L,43160L,43161L,43162L,43163L,43164L,43165L,43166L,43167L,
96404 43168L,43169L,43170L,43171L,43172L,43173L,43174L,43175L,43176L,43177L,
96405 43178L,43179L,43180L,43181L,43182L,43183L,43184L,43185L,43186L,43187L,
96406 43188L,43189L,43190L,43191L,43192L,43193L,43194L,43195L,43196L,43197L,
96407 43198L,43199L,43200L,43201L,43202L,43203L,43204L,43205L,43206L,43207L,
96408 43208L,43209L,43210L,43211L,43212L,43213L,43214L,43215L,43216L,43217L,
96409 43218L,43219L,43220L,43221L,43222L,43223L,43224L,43225L,43226L,43227L,
96410 43228L,43229L,43230L,43231L,43232L,43233L,43234L,43235L,43236L,43237L,
96411 43238L,43239L,43240L,43241L,43242L,43243L,43244L,43245L,43246L,43247L,
96412 43248L,43249L,43250L,43251L,43252L,43253L,43254L,43255L,43256L,43257L,
96413 43258L,43259L,43260L,43261L,43262L,43263L,43264L,43265L,43266L,43267L,
96414 43268L,43269L,43270L,43271L,43272L,43273L,43274L,43275L,43276L,43277L,
96415 43278L,43279L,43280L,43281L,43282L,43283L,43284L,43285L,43286L,43287L,
96416 43288L,43289L,43290L,43291L,43292L,43293L,43294L,43295L,43296L,43297L,
96417 43298L,43299L,43300L,43301L,43302L,43303L,43304L,43305L,43306L,43307L,
96418 43308L,43309L,43310L,43311L,43312L,43313L,43314L,43315L,43316L,43317L,
96419 43318L,43319L,43320L,43321L,43322L,43323L,43324L,43325L,43326L,43327L,
96420 43328L,43329L,43330L,43331L,43332L,43333L,43334L,43335L,43336L,43337L,
96421 43338L,43339L,43340L,43341L,43342L,43343L,43344L,43345L,43346L,43347L,
96422 43348L,43349L,43350L,43351L,43352L,43353L,43354L,43355L,43356L,43357L,
96423 43358L,43359L,43360L,43361L,43362L,43363L,43364L,43365L,43366L,43367L,
96424 43368L,43369L,43370L,43371L,43372L,43373L,43374L,43375L,43376L,43377L,
96425 43378L,43379L,43380L,43381L,43382L,43383L,43384L,43385L,43386L,43387L,
96426 43388L,43389L,43390L,43391L,43392L,43393L,43394L,43395L,43396L,43397L,
96427 43398L,43399L,43400L,43401L,43402L,43403L,43404L,43405L,43406L,43407L,
96428 43408L,43409L,43410L,43411L,43412L,43413L,43414L,43415L,43416L,43417L,
96429 43418L,43419L,43420L,43421L,43422L,43423L,43424L,43425L,43426L,43427L,
96430 43428L,43429L,43430L,43431L,43432L,43433L,43434L,43435L,43436L,43437L,
96431 43438L,43439L,43440L,43441L,43442L,43443L,43444L,43445L,43446L,43447L,
96432 43448L,43449L,43450L,43451L,43452L,43453L,43454L,43455L,43456L,43457L,
96433 43458L,43459L,43460L,43461L,43462L,43463L,43464L,43465L,43466L,43467L,
96434 43468L,43469L,43470L,43471L,43472L,43473L,43474L,43475L,43476L,43477L,
96435 43478L,43479L,43480L,43481L,43482L,43483L,43484L,43485L,43486L,43487L,
96436 43488L,43489L,43490L,43491L,43492L,43493L,43494L,43495L,43496L,43497L,
96437 43498L,43499L,43500L,43501L,43502L,43503L,43504L,43505L,43506L,43507L,
96438 43508L,43509L,43510L,43511L,43512L,43513L,43514L,43515L,43516L,43517L,
96439 43518L,43519L,43520L,43521L,43522L,43523L,43524L,43525L,43526L,43527L,
96440 43528L,43529L,43530L,43531L,43532L,43533L,43534L,43535L,43536L,43537L,
96441 43538L,43539L,43540L,43541L,43542L,43543L,43544L,43545L,43546L,43547L,
96442 43548L,43549L,43550L,43551L,43552L,43553L,43554L,43555L,43556L,43557L,
96443 43558L,43559L,43560L,43561L,43562L,43563L,43564L,43565L,43566L,43567L,
96444 43568L,43569L,43570L,43571L,43572L,43573L,43574L,43575L,43576L,43577L,
96445 43578L,43579L,43580L,43581L,43582L,43583L,43584L,43585L,43586L,43587L,
96446 43588L,43589L,43590L,43591L,43592L,43593L,43594L,43595L,43596L,43597L,
96447 43598L,43599L,43600L,43601L,43602L,43603L,43604L,43605L,43606L,43607L,
96448 43608L,43609L,43610L,43611L,43612L,43613L,43614L,43615L,43616L,43617L,
96449 43618L,43619L,43620L,43621L,43622L,43623L,43624L,43625L,43626L,43627L,
96450 43628L,43629L,43630L,43631L,43632L,43633L,43634L,43635L,43636L,43637L,
96451 43638L,43639L,43640L,43641L,43642L,43643L,43644L,43645L,43646L,43647L,
96452 43648L,43649L,43650L,43651L,43652L,43653L,43654L,43655L,43656L,43657L,
96453 43658L,43659L,43660L,43661L,43662L,43663L,43664L,43665L,43666L,43667L,
96454 43668L,43669L,43670L,43671L,43672L,43673L,43674L,43675L,43676L,43677L,
96455 43678L,43679L,43680L,43681L,43682L,43683L,43684L,43685L,43686L,43687L,
96456 43688L,43689L,43690L,43691L,43692L,43693L,43694L,43695L,43696L,43697L,
96457 43698L,43699L,43700L,43701L,43702L,43703L,43704L,43705L,43706L,43707L,
96458 43708L,43709L,43710L,43711L,43712L,43713L,43714L,43715L,43716L,43717L,
96459 43718L,43719L,43720L,43721L,43722L,43723L,43724L,43725L,43726L,43727L,
96460 43728L,43729L,43730L,43731L,43732L,43733L,43734L,43735L,43736L,43737L,
96461 43738L,43739L,43740L,43741L,43742L,43743L,43744L,43745L,43746L,43747L,
96462 43748L,43749L,43750L,43751L,43752L,43753L,43754L,43755L,43756L,43757L,
96463 43758L,43759L,43760L,43761L,43762L,43763L,43764L,43765L,43766L,43767L,
96464 43768L,43769L,43770L,43771L,43772L,43773L,43774L,43775L,43776L,43777L,
96465 43778L,43779L,43780L,43781L,43782L,43783L,43784L,43785L,43786L,43787L,
96466 43788L,43789L,43790L,43791L,43792L,43793L,43794L,43795L,43796L,43797L,
96467 43798L,43799L,43800L,43801L,43802L,43803L,43804L,43805L,43806L,43807L,
96468 43808L,43809L,43810L,43811L,43812L,43813L,43814L,43815L,43816L,43817L,
96469 43818L,43819L,43820L,43821L,43822L,43823L,43824L,43825L,43826L,43827L,
96470 43828L,43829L,43830L,43831L,43832L,43833L,43834L,43835L,43836L,43837L,
96471 43838L,43839L,43840L,43841L,43842L,43843L,43844L,43845L,43846L,43847L,
96472 43848L,43849L,43850L,43851L,43852L,43853L,43854L,43855L,43856L,43857L,
96473 43858L,42931L,43860L,43861L,43862L,43863L,43864L,43865L,43866L,43867L,
96474 43868L,43869L,43870L,43871L,43872L,43873L,43874L,43875L,43876L,43877L,
96475 43878L,43879L,43880L,43881L,43882L,43883L,43884L,43885L,43886L,43887L,5024,
96476 5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,
96477 5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,5054,
96478 5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,
96479 5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,5084,
96480 5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,
96481 5100,5101,5102,5103,43968L,43969L,43970L,43971L,43972L,43973L,43974L,
96482 43975L,43976L,43977L,43978L,43979L,43980L,43981L,43982L,43983L,43984L,
96483 43985L,43986L,43987L,43988L,43989L,43990L,43991L,43992L,43993L,43994L,
96484 43995L,43996L,43997L,43998L,43999L,44000L,44001L,44002L,44003L,44004L,
96485 44005L,44006L,44007L,44008L,44009L,44010L,44011L,44012L,44013L,44014L,
96486 44015L,44016L,44017L,44018L,44019L,44020L,44021L,44022L,44023L,44024L,
96487 44025L,44026L,44027L,44028L,44029L,44030L,44031L,44032L,44033L,44034L,
96488 44035L,44036L,44037L,44038L,44039L,44040L,44041L,44042L,44043L,44044L,
96489 44045L,44046L,44047L,44048L,44049L,44050L,44051L,44052L,44053L,44054L,
96490 44055L,44056L,44057L,44058L,44059L,44060L,44061L,44062L,44063L,44064L,
96491 44065L,44066L,44067L,44068L,44069L,44070L,44071L,44072L,44073L,44074L,
96492 44075L,44076L,44077L,44078L,44079L,44080L,44081L,44082L,44083L,44084L,
96493 44085L,44086L,44087L,44088L,44089L,44090L,44091L,44092L,44093L,44094L,
96494 44095L,44096L,44097L,44098L,44099L,44100L,44101L,44102L,44103L,44104L,
96495 44105L,44106L,44107L,44108L,44109L,44110L,44111L,44112L,44113L,44114L,
96496 44115L,44116L,44117L,44118L,44119L,44120L,44121L,44122L,44123L,44124L,
96497 44125L,44126L,44127L,44128L,44129L,44130L,44131L,44132L,44133L,44134L,
96498 44135L,44136L,44137L,44138L,44139L,44140L,44141L,44142L,44143L,44144L,
96499 44145L,44146L,44147L,44148L,44149L,44150L,44151L,44152L,44153L,44154L,
96500 44155L,44156L,44157L,44158L,44159L,44160L,44161L,44162L,44163L,44164L,
96501 44165L,44166L,44167L,44168L,44169L,44170L,44171L,44172L,44173L,44174L,
96502 44175L,44176L,44177L,44178L,44179L,44180L,44181L,44182L,44183L,44184L,
96503 44185L,44186L,44187L,44188L,44189L,44190L,44191L,44192L,44193L,44194L,
96504 44195L,44196L,44197L,44198L,44199L,44200L,44201L,44202L,44203L,44204L,
96505 44205L,44206L,44207L,44208L,44209L,44210L,44211L,44212L,44213L,44214L,
96506 44215L,44216L,44217L,44218L,44219L,44220L,44221L,44222L,44223L,44224L,
96507 44225L,44226L,44227L,44228L,44229L,44230L,44231L,44232L,44233L,44234L,
96508 44235L,44236L,44237L,44238L,44239L,44240L,44241L,44242L,44243L,44244L,
96509 44245L,44246L,44247L,44248L,44249L,44250L,44251L,44252L,44253L,44254L,
96510 44255L,44256L,44257L,44258L,44259L,44260L,44261L,44262L,44263L,44264L,
96511 44265L,44266L,44267L,44268L,44269L,44270L,44271L,44272L,44273L,44274L,
96512 44275L,44276L,44277L,44278L,44279L,44280L,44281L,44282L,44283L,44284L,
96513 44285L,44286L,44287L,44288L,44289L,44290L,44291L,44292L,44293L,44294L,
96514 44295L,44296L,44297L,44298L,44299L,44300L,44301L,44302L,44303L,44304L,
96515 44305L,44306L,44307L,44308L,44309L,44310L,44311L,44312L,44313L,44314L,
96516 44315L,44316L,44317L,44318L,44319L,44320L,44321L,44322L,44323L,44324L,
96517 44325L,44326L,44327L,44328L,44329L,44330L,44331L,44332L,44333L,44334L,
96518 44335L,44336L,44337L,44338L,44339L,44340L,44341L,44342L,44343L,44344L,
96519 44345L,44346L,44347L,44348L,44349L,44350L,44351L,44352L,44353L,44354L,
96520 44355L,44356L,44357L,44358L,44359L,44360L,44361L,44362L,44363L,44364L,
96521 44365L,44366L,44367L,44368L,44369L,44370L,44371L,44372L,44373L,44374L,
96522 44375L,44376L,44377L,44378L,44379L,44380L,44381L,44382L,44383L,44384L,
96523 44385L,44386L,44387L,44388L,44389L,44390L,44391L,44392L,44393L,44394L,
96524 44395L,44396L,44397L,44398L,44399L,44400L,44401L,44402L,44403L,44404L,
96525 44405L,44406L,44407L,44408L,44409L,44410L,44411L,44412L,44413L,44414L,
96526 44415L,44416L,44417L,44418L,44419L,44420L,44421L,44422L,44423L,44424L,
96527 44425L,44426L,44427L,44428L,44429L,44430L,44431L,44432L,44433L,44434L,
96528 44435L,44436L,44437L,44438L,44439L,44440L,44441L,44442L,44443L,44444L,
96529 44445L,44446L,44447L,44448L,44449L,44450L,44451L,44452L,44453L,44454L,
96530 44455L,44456L,44457L,44458L,44459L,44460L,44461L,44462L,44463L,44464L,
96531 44465L,44466L,44467L,44468L,44469L,44470L,44471L,44472L,44473L,44474L,
96532 44475L,44476L,44477L,44478L,44479L,44480L,44481L,44482L,44483L,44484L,
96533 44485L,44486L,44487L,44488L,44489L,44490L,44491L,44492L,44493L,44494L,
96534 44495L,44496L,44497L,44498L,44499L,44500L,44501L,44502L,44503L,44504L,
96535 44505L,44506L,44507L,44508L,44509L,44510L,44511L,44512L,44513L,44514L,
96536 44515L,44516L,44517L,44518L,44519L,44520L,44521L,44522L,44523L,44524L,
96537 44525L,44526L,44527L,44528L,44529L,44530L,44531L,44532L,44533L,44534L,
96538 44535L,44536L,44537L,44538L,44539L,44540L,44541L,44542L,44543L,44544L,
96539 44545L,44546L,44547L,44548L,44549L,44550L,44551L,44552L,44553L,44554L,
96540 44555L,44556L,44557L,44558L,44559L,44560L,44561L,44562L,44563L,44564L,
96541 44565L,44566L,44567L,44568L,44569L,44570L,44571L,44572L,44573L,44574L,
96542 44575L,44576L,44577L,44578L,44579L,44580L,44581L,44582L,44583L,44584L,
96543 44585L,44586L,44587L,44588L,44589L,44590L,44591L,44592L,44593L,44594L,
96544 44595L,44596L,44597L,44598L,44599L,44600L,44601L,44602L,44603L,44604L,
96545 44605L,44606L,44607L,44608L,44609L,44610L,44611L,44612L,44613L,44614L,
96546 44615L,44616L,44617L,44618L,44619L,44620L,44621L,44622L,44623L,44624L,
96547 44625L,44626L,44627L,44628L,44629L,44630L,44631L,44632L,44633L,44634L,
96548 44635L,44636L,44637L,44638L,44639L,44640L,44641L,44642L,44643L,44644L,
96549 44645L,44646L,44647L,44648L,44649L,44650L,44651L,44652L,44653L,44654L,
96550 44655L,44656L,44657L,44658L,44659L,44660L,44661L,44662L,44663L,44664L,
96551 44665L,44666L,44667L,44668L,44669L,44670L,44671L,44672L,44673L,44674L,
96552 44675L,44676L,44677L,44678L,44679L,44680L,44681L,44682L,44683L,44684L,
96553 44685L,44686L,44687L,44688L,44689L,44690L,44691L,44692L,44693L,44694L,
96554 44695L,44696L,44697L,44698L,44699L,44700L,44701L,44702L,44703L,44704L,
96555 44705L,44706L,44707L,44708L,44709L,44710L,44711L,44712L,44713L,44714L,
96556 44715L,44716L,44717L,44718L,44719L,44720L,44721L,44722L,44723L,44724L,
96557 44725L,44726L,44727L,44728L,44729L,44730L,44731L,44732L,44733L,44734L,
96558 44735L,44736L,44737L,44738L,44739L,44740L,44741L,44742L,44743L,44744L,
96559 44745L,44746L,44747L,44748L,44749L,44750L,44751L,44752L,44753L,44754L,
96560 44755L,44756L,44757L,44758L,44759L,44760L,44761L,44762L,44763L,44764L,
96561 44765L,44766L,44767L,44768L,44769L,44770L,44771L,44772L,44773L,44774L,
96562 44775L,44776L,44777L,44778L,44779L,44780L,44781L,44782L,44783L,44784L,
96563 44785L,44786L,44787L,44788L,44789L,44790L,44791L,44792L,44793L,44794L,
96564 44795L,44796L,44797L,44798L,44799L,44800L,44801L,44802L,44803L,44804L,
96565 44805L,44806L,44807L,44808L,44809L,44810L,44811L,44812L,44813L,44814L,
96566 44815L,44816L,44817L,44818L,44819L,44820L,44821L,44822L,44823L,44824L,
96567 44825L,44826L,44827L,44828L,44829L,44830L,44831L,44832L,44833L,44834L,
96568 44835L,44836L,44837L,44838L,44839L,44840L,44841L,44842L,44843L,44844L,
96569 44845L,44846L,44847L,44848L,44849L,44850L,44851L,44852L,44853L,44854L,
96570 44855L,44856L,44857L,44858L,44859L,44860L,44861L,44862L,44863L,44864L,
96571 44865L,44866L,44867L,44868L,44869L,44870L,44871L,44872L,44873L,44874L,
96572 44875L,44876L,44877L,44878L,44879L,44880L,44881L,44882L,44883L,44884L,
96573 44885L,44886L,44887L,44888L,44889L,44890L,44891L,44892L,44893L,44894L,
96574 44895L,44896L,44897L,44898L,44899L,44900L,44901L,44902L,44903L,44904L,
96575 44905L,44906L,44907L,44908L,44909L,44910L,44911L,44912L,44913L,44914L,
96576 44915L,44916L,44917L,44918L,44919L,44920L,44921L,44922L,44923L,44924L,
96577 44925L,44926L,44927L,44928L,44929L,44930L,44931L,44932L,44933L,44934L,
96578 44935L,44936L,44937L,44938L,44939L,44940L,44941L,44942L,44943L,44944L,
96579 44945L,44946L,44947L,44948L,44949L,44950L,44951L,44952L,44953L,44954L,
96580 44955L,44956L,44957L,44958L,44959L,44960L,44961L,44962L,44963L,44964L,
96581 44965L,44966L,44967L,44968L,44969L,44970L,44971L,44972L,44973L,44974L,
96582 44975L,44976L,44977L,44978L,44979L,44980L,44981L,44982L,44983L,44984L,
96583 44985L,44986L,44987L,44988L,44989L,44990L,44991L,44992L,44993L,44994L,
96584 44995L,44996L,44997L,44998L,44999L,45000L,45001L,45002L,45003L,45004L,
96585 45005L,45006L,45007L,45008L,45009L,45010L,45011L,45012L,45013L,45014L,
96586 45015L,45016L,45017L,45018L,45019L,45020L,45021L,45022L,45023L,45024L,
96587 45025L,45026L,45027L,45028L,45029L,45030L,45031L,45032L,45033L,45034L,
96588 45035L,45036L,45037L,45038L,45039L,45040L,45041L,45042L,45043L,45044L,
96589 45045L,45046L,45047L,45048L,45049L,45050L,45051L,45052L,45053L,45054L,
96590 45055L,45056L,45057L,45058L,45059L,45060L,45061L,45062L,45063L,45064L,
96591 45065L,45066L,45067L,45068L,45069L,45070L,45071L,45072L,45073L,45074L,
96592 45075L,45076L,45077L,45078L,45079L,45080L,45081L,45082L,45083L,45084L,
96593 45085L,45086L,45087L,45088L,45089L,45090L,45091L,45092L,45093L,45094L,
96594 45095L,45096L,45097L,45098L,45099L,45100L,45101L,45102L,45103L,45104L,
96595 45105L,45106L,45107L,45108L,45109L,45110L,45111L,45112L,45113L,45114L,
96596 45115L,45116L,45117L,45118L,45119L,45120L,45121L,45122L,45123L,45124L,
96597 45125L,45126L,45127L,45128L,45129L,45130L,45131L,45132L,45133L,45134L,
96598 45135L,45136L,45137L,45138L,45139L,45140L,45141L,45142L,45143L,45144L,
96599 45145L,45146L,45147L,45148L,45149L,45150L,45151L,45152L,45153L,45154L,
96600 45155L,45156L,45157L,45158L,45159L,45160L,45161L,45162L,45163L,45164L,
96601 45165L,45166L,45167L,45168L,45169L,45170L,45171L,45172L,45173L,45174L,
96602 45175L,45176L,45177L,45178L,45179L,45180L,45181L,45182L,45183L,45184L,
96603 45185L,45186L,45187L,45188L,45189L,45190L,45191L,45192L,45193L,45194L,
96604 45195L,45196L,45197L,45198L,45199L,45200L,45201L,45202L,45203L,45204L,
96605 45205L,45206L,45207L,45208L,45209L,45210L,45211L,45212L,45213L,45214L,
96606 45215L,45216L,45217L,45218L,45219L,45220L,45221L,45222L,45223L,45224L,
96607 45225L,45226L,45227L,45228L,45229L,45230L,45231L,45232L,45233L,45234L,
96608 45235L,45236L,45237L,45238L,45239L,45240L,45241L,45242L,45243L,45244L,
96609 45245L,45246L,45247L,45248L,45249L,45250L,45251L,45252L,45253L,45254L,
96610 45255L,45256L,45257L,45258L,45259L,45260L,45261L,45262L,45263L,45264L,
96611 45265L,45266L,45267L,45268L,45269L,45270L,45271L,45272L,45273L,45274L,
96612 45275L,45276L,45277L,45278L,45279L,45280L,45281L,45282L,45283L,45284L,
96613 45285L,45286L,45287L,45288L,45289L,45290L,45291L,45292L,45293L,45294L,
96614 45295L,45296L,45297L,45298L,45299L,45300L,45301L,45302L,45303L,45304L,
96615 45305L,45306L,45307L,45308L,45309L,45310L,45311L,45312L,45313L,45314L,
96616 45315L,45316L,45317L,45318L,45319L,45320L,45321L,45322L,45323L,45324L,
96617 45325L,45326L,45327L,45328L,45329L,45330L,45331L,45332L,45333L,45334L,
96618 45335L,45336L,45337L,45338L,45339L,45340L,45341L,45342L,45343L,45344L,
96619 45345L,45346L,45347L,45348L,45349L,45350L,45351L,45352L,45353L,45354L,
96620 45355L,45356L,45357L,45358L,45359L,45360L,45361L,45362L,45363L,45364L,
96621 45365L,45366L,45367L,45368L,45369L,45370L,45371L,45372L,45373L,45374L,
96622 45375L,45376L,45377L,45378L,45379L,45380L,45381L,45382L,45383L,45384L,
96623 45385L,45386L,45387L,45388L,45389L,45390L,45391L,45392L,45393L,45394L,
96624 45395L,45396L,45397L,45398L,45399L,45400L,45401L,45402L,45403L,45404L,
96625 45405L,45406L,45407L,45408L,45409L,45410L,45411L,45412L,45413L,45414L,
96626 45415L,45416L,45417L,45418L,45419L,45420L,45421L,45422L,45423L,45424L,
96627 45425L,45426L,45427L,45428L,45429L,45430L,45431L,45432L,45433L,45434L,
96628 45435L,45436L,45437L,45438L,45439L,45440L,45441L,45442L,45443L,45444L,
96629 45445L,45446L,45447L,45448L,45449L,45450L,45451L,45452L,45453L,45454L,
96630 45455L,45456L,45457L,45458L,45459L,45460L,45461L,45462L,45463L,45464L,
96631 45465L,45466L,45467L,45468L,45469L,45470L,45471L,45472L,45473L,45474L,
96632 45475L,45476L,45477L,45478L,45479L,45480L,45481L,45482L,45483L,45484L,
96633 45485L,45486L,45487L,45488L,45489L,45490L,45491L,45492L,45493L,45494L,
96634 45495L,45496L,45497L,45498L,45499L,45500L,45501L,45502L,45503L,45504L,
96635 45505L,45506L,45507L,45508L,45509L,45510L,45511L,45512L,45513L,45514L,
96636 45515L,45516L,45517L,45518L,45519L,45520L,45521L,45522L,45523L,45524L,
96637 45525L,45526L,45527L,45528L,45529L,45530L,45531L,45532L,45533L,45534L,
96638 45535L,45536L,45537L,45538L,45539L,45540L,45541L,45542L,45543L,45544L,
96639 45545L,45546L,45547L,45548L,45549L,45550L,45551L,45552L,45553L,45554L,
96640 45555L,45556L,45557L,45558L,45559L,45560L,45561L,45562L,45563L,45564L,
96641 45565L,45566L,45567L,45568L,45569L,45570L,45571L,45572L,45573L,45574L,
96642 45575L,45576L,45577L,45578L,45579L,45580L,45581L,45582L,45583L,45584L,
96643 45585L,45586L,45587L,45588L,45589L,45590L,45591L,45592L,45593L,45594L,
96644 45595L,45596L,45597L,45598L,45599L,45600L,45601L,45602L,45603L,45604L,
96645 45605L,45606L,45607L,45608L,45609L,45610L,45611L,45612L,45613L,45614L,
96646 45615L,45616L,45617L,45618L,45619L,45620L,45621L,45622L,45623L,45624L,
96647 45625L,45626L,45627L,45628L,45629L,45630L,45631L,45632L,45633L,45634L,
96648 45635L,45636L,45637L,45638L,45639L,45640L,45641L,45642L,45643L,45644L,
96649 45645L,45646L,45647L,45648L,45649L,45650L,45651L,45652L,45653L,45654L,
96650 45655L,45656L,45657L,45658L,45659L,45660L,45661L,45662L,45663L,45664L,
96651 45665L,45666L,45667L,45668L,45669L,45670L,45671L,45672L,45673L,45674L,
96652 45675L,45676L,45677L,45678L,45679L,45680L,45681L,45682L,45683L,45684L,
96653 45685L,45686L,45687L,45688L,45689L,45690L,45691L,45692L,45693L,45694L,
96654 45695L,45696L,45697L,45698L,45699L,45700L,45701L,45702L,45703L,45704L,
96655 45705L,45706L,45707L,45708L,45709L,45710L,45711L,45712L,45713L,45714L,
96656 45715L,45716L,45717L,45718L,45719L,45720L,45721L,45722L,45723L,45724L,
96657 45725L,45726L,45727L,45728L,45729L,45730L,45731L,45732L,45733L,45734L,
96658 45735L,45736L,45737L,45738L,45739L,45740L,45741L,45742L,45743L,45744L,
96659 45745L,45746L,45747L,45748L,45749L,45750L,45751L,45752L,45753L,45754L,
96660 45755L,45756L,45757L,45758L,45759L,45760L,45761L,45762L,45763L,45764L,
96661 45765L,45766L,45767L,45768L,45769L,45770L,45771L,45772L,45773L,45774L,
96662 45775L,45776L,45777L,45778L,45779L,45780L,45781L,45782L,45783L,45784L,
96663 45785L,45786L,45787L,45788L,45789L,45790L,45791L,45792L,45793L,45794L,
96664 45795L,45796L,45797L,45798L,45799L,45800L,45801L,45802L,45803L,45804L,
96665 45805L,45806L,45807L,45808L,45809L,45810L,45811L,45812L,45813L,45814L,
96666 45815L,45816L,45817L,45818L,45819L,45820L,45821L,45822L,45823L,45824L,
96667 45825L,45826L,45827L,45828L,45829L,45830L,45831L,45832L,45833L,45834L,
96668 45835L,45836L,45837L,45838L,45839L,45840L,45841L,45842L,45843L,45844L,
96669 45845L,45846L,45847L,45848L,45849L,45850L,45851L,45852L,45853L,45854L,
96670 45855L,45856L,45857L,45858L,45859L,45860L,45861L,45862L,45863L,45864L,
96671 45865L,45866L,45867L,45868L,45869L,45870L,45871L,45872L,45873L,45874L,
96672 45875L,45876L,45877L,45878L,45879L,45880L,45881L,45882L,45883L,45884L,
96673 45885L,45886L,45887L,45888L,45889L,45890L,45891L,45892L,45893L,45894L,
96674 45895L,45896L,45897L,45898L,45899L,45900L,45901L,45902L,45903L,45904L,
96675 45905L,45906L,45907L,45908L,45909L,45910L,45911L,45912L,45913L,45914L,
96676 45915L,45916L,45917L,45918L,45919L,45920L,45921L,45922L,45923L,45924L,
96677 45925L,45926L,45927L,45928L,45929L,45930L,45931L,45932L,45933L,45934L,
96678 45935L,45936L,45937L,45938L,45939L,45940L,45941L,45942L,45943L,45944L,
96679 45945L,45946L,45947L,45948L,45949L,45950L,45951L,45952L,45953L,45954L,
96680 45955L,45956L,45957L,45958L,45959L,45960L,45961L,45962L,45963L,45964L,
96681 45965L,45966L,45967L,45968L,45969L,45970L,45971L,45972L,45973L,45974L,
96682 45975L,45976L,45977L,45978L,45979L,45980L,45981L,45982L,45983L,45984L,
96683 45985L,45986L,45987L,45988L,45989L,45990L,45991L,45992L,45993L,45994L,
96684 45995L,45996L,45997L,45998L,45999L,46000L,46001L,46002L,46003L,46004L,
96685 46005L,46006L,46007L,46008L,46009L,46010L,46011L,46012L,46013L,46014L,
96686 46015L,46016L,46017L,46018L,46019L,46020L,46021L,46022L,46023L,46024L,
96687 46025L,46026L,46027L,46028L,46029L,46030L,46031L,46032L,46033L,46034L,
96688 46035L,46036L,46037L,46038L,46039L,46040L,46041L,46042L,46043L,46044L,
96689 46045L,46046L,46047L,46048L,46049L,46050L,46051L,46052L,46053L,46054L,
96690 46055L,46056L,46057L,46058L,46059L,46060L,46061L,46062L,46063L,46064L,
96691 46065L,46066L,46067L,46068L,46069L,46070L,46071L,46072L,46073L,46074L,
96692 46075L,46076L,46077L,46078L,46079L,46080L,46081L,46082L,46083L,46084L,
96693 46085L,46086L,46087L,46088L,46089L,46090L,46091L,46092L,46093L,46094L,
96694 46095L,46096L,46097L,46098L,46099L,46100L,46101L,46102L,46103L,46104L,
96695 46105L,46106L,46107L,46108L,46109L,46110L,46111L,46112L,46113L,46114L,
96696 46115L,46116L,46117L,46118L,46119L,46120L,46121L,46122L,46123L,46124L,
96697 46125L,46126L,46127L,46128L,46129L,46130L,46131L,46132L,46133L,46134L,
96698 46135L,46136L,46137L,46138L,46139L,46140L,46141L,46142L,46143L,46144L,
96699 46145L,46146L,46147L,46148L,46149L,46150L,46151L,46152L,46153L,46154L,
96700 46155L,46156L,46157L,46158L,46159L,46160L,46161L,46162L,46163L,46164L,
96701 46165L,46166L,46167L,46168L,46169L,46170L,46171L,46172L,46173L,46174L,
96702 46175L,46176L,46177L,46178L,46179L,46180L,46181L,46182L,46183L,46184L,
96703 46185L,46186L,46187L,46188L,46189L,46190L,46191L,46192L,46193L,46194L,
96704 46195L,46196L,46197L,46198L,46199L,46200L,46201L,46202L,46203L,46204L,
96705 46205L,46206L,46207L,46208L,46209L,46210L,46211L,46212L,46213L,46214L,
96706 46215L,46216L,46217L,46218L,46219L,46220L,46221L,46222L,46223L,46224L,
96707 46225L,46226L,46227L,46228L,46229L,46230L,46231L,46232L,46233L,46234L,
96708 46235L,46236L,46237L,46238L,46239L,46240L,46241L,46242L,46243L,46244L,
96709 46245L,46246L,46247L,46248L,46249L,46250L,46251L,46252L,46253L,46254L,
96710 46255L,46256L,46257L,46258L,46259L,46260L,46261L,46262L,46263L,46264L,
96711 46265L,46266L,46267L,46268L,46269L,46270L,46271L,46272L,46273L,46274L,
96712 46275L,46276L,46277L,46278L,46279L,46280L,46281L,46282L,46283L,46284L,
96713 46285L,46286L,46287L,46288L,46289L,46290L,46291L,46292L,46293L,46294L,
96714 46295L,46296L,46297L,46298L,46299L,46300L,46301L,46302L,46303L,46304L,
96715 46305L,46306L,46307L,46308L,46309L,46310L,46311L,46312L,46313L,46314L,
96716 46315L,46316L,46317L,46318L,46319L,46320L,46321L,46322L,46323L,46324L,
96717 46325L,46326L,46327L,46328L,46329L,46330L,46331L,46332L,46333L,46334L,
96718 46335L,46336L,46337L,46338L,46339L,46340L,46341L,46342L,46343L,46344L,
96719 46345L,46346L,46347L,46348L,46349L,46350L,46351L,46352L,46353L,46354L,
96720 46355L,46356L,46357L,46358L,46359L,46360L,46361L,46362L,46363L,46364L,
96721 46365L,46366L,46367L,46368L,46369L,46370L,46371L,46372L,46373L,46374L,
96722 46375L,46376L,46377L,46378L,46379L,46380L,46381L,46382L,46383L,46384L,
96723 46385L,46386L,46387L,46388L,46389L,46390L,46391L,46392L,46393L,46394L,
96724 46395L,46396L,46397L,46398L,46399L,46400L,46401L,46402L,46403L,46404L,
96725 46405L,46406L,46407L,46408L,46409L,46410L,46411L,46412L,46413L,46414L,
96726 46415L,46416L,46417L,46418L,46419L,46420L,46421L,46422L,46423L,46424L,
96727 46425L,46426L,46427L,46428L,46429L,46430L,46431L,46432L,46433L,46434L,
96728 46435L,46436L,46437L,46438L,46439L,46440L,46441L,46442L,46443L,46444L,
96729 46445L,46446L,46447L,46448L,46449L,46450L,46451L,46452L,46453L,46454L,
96730 46455L,46456L,46457L,46458L,46459L,46460L,46461L,46462L,46463L,46464L,
96731 46465L,46466L,46467L,46468L,46469L,46470L,46471L,46472L,46473L,46474L,
96732 46475L,46476L,46477L,46478L,46479L,46480L,46481L,46482L,46483L,46484L,
96733 46485L,46486L,46487L,46488L,46489L,46490L,46491L,46492L,46493L,46494L,
96734 46495L,46496L,46497L,46498L,46499L,46500L,46501L,46502L,46503L,46504L,
96735 46505L,46506L,46507L,46508L,46509L,46510L,46511L,46512L,46513L,46514L,
96736 46515L,46516L,46517L,46518L,46519L,46520L,46521L,46522L,46523L,46524L,
96737 46525L,46526L,46527L,46528L,46529L,46530L,46531L,46532L,46533L,46534L,
96738 46535L,46536L,46537L,46538L,46539L,46540L,46541L,46542L,46543L,46544L,
96739 46545L,46546L,46547L,46548L,46549L,46550L,46551L,46552L,46553L,46554L,
96740 46555L,46556L,46557L,46558L,46559L,46560L,46561L,46562L,46563L,46564L,
96741 46565L,46566L,46567L,46568L,46569L,46570L,46571L,46572L,46573L,46574L,
96742 46575L,46576L,46577L,46578L,46579L,46580L,46581L,46582L,46583L,46584L,
96743 46585L,46586L,46587L,46588L,46589L,46590L,46591L,46592L,46593L,46594L,
96744 46595L,46596L,46597L,46598L,46599L,46600L,46601L,46602L,46603L,46604L,
96745 46605L,46606L,46607L,46608L,46609L,46610L,46611L,46612L,46613L,46614L,
96746 46615L,46616L,46617L,46618L,46619L,46620L,46621L,46622L,46623L,46624L,
96747 46625L,46626L,46627L,46628L,46629L,46630L,46631L,46632L,46633L,46634L,
96748 46635L,46636L,46637L,46638L,46639L,46640L,46641L,46642L,46643L,46644L,
96749 46645L,46646L,46647L,46648L,46649L,46650L,46651L,46652L,46653L,46654L,
96750 46655L,46656L,46657L,46658L,46659L,46660L,46661L,46662L,46663L,46664L,
96751 46665L,46666L,46667L,46668L,46669L,46670L,46671L,46672L,46673L,46674L,
96752 46675L,46676L,46677L,46678L,46679L,46680L,46681L,46682L,46683L,46684L,
96753 46685L,46686L,46687L,46688L,46689L,46690L,46691L,46692L,46693L,46694L,
96754 46695L,46696L,46697L,46698L,46699L,46700L,46701L,46702L,46703L,46704L,
96755 46705L,46706L,46707L,46708L,46709L,46710L,46711L,46712L,46713L,46714L,
96756 46715L,46716L,46717L,46718L,46719L,46720L,46721L,46722L,46723L,46724L,
96757 46725L,46726L,46727L,46728L,46729L,46730L,46731L,46732L,46733L,46734L,
96758 46735L,46736L,46737L,46738L,46739L,46740L,46741L,46742L,46743L,46744L,
96759 46745L,46746L,46747L,46748L,46749L,46750L,46751L,46752L,46753L,46754L,
96760 46755L,46756L,46757L,46758L,46759L,46760L,46761L,46762L,46763L,46764L,
96761 46765L,46766L,46767L,46768L,46769L,46770L,46771L,46772L,46773L,46774L,
96762 46775L,46776L,46777L,46778L,46779L,46780L,46781L,46782L,46783L,46784L,
96763 46785L,46786L,46787L,46788L,46789L,46790L,46791L,46792L,46793L,46794L,
96764 46795L,46796L,46797L,46798L,46799L,46800L,46801L,46802L,46803L,46804L,
96765 46805L,46806L,46807L,46808L,46809L,46810L,46811L,46812L,46813L,46814L,
96766 46815L,46816L,46817L,46818L,46819L,46820L,46821L,46822L,46823L,46824L,
96767 46825L,46826L,46827L,46828L,46829L,46830L,46831L,46832L,46833L,46834L,
96768 46835L,46836L,46837L,46838L,46839L,46840L,46841L,46842L,46843L,46844L,
96769 46845L,46846L,46847L,46848L,46849L,46850L,46851L,46852L,46853L,46854L,
96770 46855L,46856L,46857L,46858L,46859L,46860L,46861L,46862L,46863L,46864L,
96771 46865L,46866L,46867L,46868L,46869L,46870L,46871L,46872L,46873L,46874L,
96772 46875L,46876L,46877L,46878L,46879L,46880L,46881L,46882L,46883L,46884L,
96773 46885L,46886L,46887L,46888L,46889L,46890L,46891L,46892L,46893L,46894L,
96774 46895L,46896L,46897L,46898L,46899L,46900L,46901L,46902L,46903L,46904L,
96775 46905L,46906L,46907L,46908L,46909L,46910L,46911L,46912L,46913L,46914L,
96776 46915L,46916L,46917L,46918L,46919L,46920L,46921L,46922L,46923L,46924L,
96777 46925L,46926L,46927L,46928L,46929L,46930L,46931L,46932L,46933L,46934L,
96778 46935L,46936L,46937L,46938L,46939L,46940L,46941L,46942L,46943L,46944L,
96779 46945L,46946L,46947L,46948L,46949L,46950L,46951L,46952L,46953L,46954L,
96780 46955L,46956L,46957L,46958L,46959L,46960L,46961L,46962L,46963L,46964L,
96781 46965L,46966L,46967L,46968L,46969L,46970L,46971L,46972L,46973L,46974L,
96782 46975L,46976L,46977L,46978L,46979L,46980L,46981L,46982L,46983L,46984L,
96783 46985L,46986L,46987L,46988L,46989L,46990L,46991L,46992L,46993L,46994L,
96784 46995L,46996L,46997L,46998L,46999L,47000L,47001L,47002L,47003L,47004L,
96785 47005L,47006L,47007L,47008L,47009L,47010L,47011L,47012L,47013L,47014L,
96786 47015L,47016L,47017L,47018L,47019L,47020L,47021L,47022L,47023L,47024L,
96787 47025L,47026L,47027L,47028L,47029L,47030L,47031L,47032L,47033L,47034L,
96788 47035L,47036L,47037L,47038L,47039L,47040L,47041L,47042L,47043L,47044L,
96789 47045L,47046L,47047L,47048L,47049L,47050L,47051L,47052L,47053L,47054L,
96790 47055L,47056L,47057L,47058L,47059L,47060L,47061L,47062L,47063L,47064L,
96791 47065L,47066L,47067L,47068L,47069L,47070L,47071L,47072L,47073L,47074L,
96792 47075L,47076L,47077L,47078L,47079L,47080L,47081L,47082L,47083L,47084L,
96793 47085L,47086L,47087L,47088L,47089L,47090L,47091L,47092L,47093L,47094L,
96794 47095L,47096L,47097L,47098L,47099L,47100L,47101L,47102L,47103L,47104L,
96795 47105L,47106L,47107L,47108L,47109L,47110L,47111L,47112L,47113L,47114L,
96796 47115L,47116L,47117L,47118L,47119L,47120L,47121L,47122L,47123L,47124L,
96797 47125L,47126L,47127L,47128L,47129L,47130L,47131L,47132L,47133L,47134L,
96798 47135L,47136L,47137L,47138L,47139L,47140L,47141L,47142L,47143L,47144L,
96799 47145L,47146L,47147L,47148L,47149L,47150L,47151L,47152L,47153L,47154L,
96800 47155L,47156L,47157L,47158L,47159L,47160L,47161L,47162L,47163L,47164L,
96801 47165L,47166L,47167L,47168L,47169L,47170L,47171L,47172L,47173L,47174L,
96802 47175L,47176L,47177L,47178L,47179L,47180L,47181L,47182L,47183L,47184L,
96803 47185L,47186L,47187L,47188L,47189L,47190L,47191L,47192L,47193L,47194L,
96804 47195L,47196L,47197L,47198L,47199L,47200L,47201L,47202L,47203L,47204L,
96805 47205L,47206L,47207L,47208L,47209L,47210L,47211L,47212L,47213L,47214L,
96806 47215L,47216L,47217L,47218L,47219L,47220L,47221L,47222L,47223L,47224L,
96807 47225L,47226L,47227L,47228L,47229L,47230L,47231L,47232L,47233L,47234L,
96808 47235L,47236L,47237L,47238L,47239L,47240L,47241L,47242L,47243L,47244L,
96809 47245L,47246L,47247L,47248L,47249L,47250L,47251L,47252L,47253L,47254L,
96810 47255L,47256L,47257L,47258L,47259L,47260L,47261L,47262L,47263L,47264L,
96811 47265L,47266L,47267L,47268L,47269L,47270L,47271L,47272L,47273L,47274L,
96812 47275L,47276L,47277L,47278L,47279L,47280L,47281L,47282L,47283L,47284L,
96813 47285L,47286L,47287L,47288L,47289L,47290L,47291L,47292L,47293L,47294L,
96814 47295L,47296L,47297L,47298L,47299L,47300L,47301L,47302L,47303L,47304L,
96815 47305L,47306L,47307L,47308L,47309L,47310L,47311L,47312L,47313L,47314L,
96816 47315L,47316L,47317L,47318L,47319L,47320L,47321L,47322L,47323L,47324L,
96817 47325L,47326L,47327L,47328L,47329L,47330L,47331L,47332L,47333L,47334L,
96818 47335L,47336L,47337L,47338L,47339L,47340L,47341L,47342L,47343L,47344L,
96819 47345L,47346L,47347L,47348L,47349L,47350L,47351L,47352L,47353L,47354L,
96820 47355L,47356L,47357L,47358L,47359L,47360L,47361L,47362L,47363L,47364L,
96821 47365L,47366L,47367L,47368L,47369L,47370L,47371L,47372L,47373L,47374L,
96822 47375L,47376L,47377L,47378L,47379L,47380L,47381L,47382L,47383L,47384L,
96823 47385L,47386L,47387L,47388L,47389L,47390L,47391L,47392L,47393L,47394L,
96824 47395L,47396L,47397L,47398L,47399L,47400L,47401L,47402L,47403L,47404L,
96825 47405L,47406L,47407L,47408L,47409L,47410L,47411L,47412L,47413L,47414L,
96826 47415L,47416L,47417L,47418L,47419L,47420L,47421L,47422L,47423L,47424L,
96827 47425L,47426L,47427L,47428L,47429L,47430L,47431L,47432L,47433L,47434L,
96828 47435L,47436L,47437L,47438L,47439L,47440L,47441L,47442L,47443L,47444L,
96829 47445L,47446L,47447L,47448L,47449L,47450L,47451L,47452L,47453L,47454L,
96830 47455L,47456L,47457L,47458L,47459L,47460L,47461L,47462L,47463L,47464L,
96831 47465L,47466L,47467L,47468L,47469L,47470L,47471L,47472L,47473L,47474L,
96832 47475L,47476L,47477L,47478L,47479L,47480L,47481L,47482L,47483L,47484L,
96833 47485L,47486L,47487L,47488L,47489L,47490L,47491L,47492L,47493L,47494L,
96834 47495L,47496L,47497L,47498L,47499L,47500L,47501L,47502L,47503L,47504L,
96835 47505L,47506L,47507L,47508L,47509L,47510L,47511L,47512L,47513L,47514L,
96836 47515L,47516L,47517L,47518L,47519L,47520L,47521L,47522L,47523L,47524L,
96837 47525L,47526L,47527L,47528L,47529L,47530L,47531L,47532L,47533L,47534L,
96838 47535L,47536L,47537L,47538L,47539L,47540L,47541L,47542L,47543L,47544L,
96839 47545L,47546L,47547L,47548L,47549L,47550L,47551L,47552L,47553L,47554L,
96840 47555L,47556L,47557L,47558L,47559L,47560L,47561L,47562L,47563L,47564L,
96841 47565L,47566L,47567L,47568L,47569L,47570L,47571L,47572L,47573L,47574L,
96842 47575L,47576L,47577L,47578L,47579L,47580L,47581L,47582L,47583L,47584L,
96843 47585L,47586L,47587L,47588L,47589L,47590L,47591L,47592L,47593L,47594L,
96844 47595L,47596L,47597L,47598L,47599L,47600L,47601L,47602L,47603L,47604L,
96845 47605L,47606L,47607L,47608L,47609L,47610L,47611L,47612L,47613L,47614L,
96846 47615L,47616L,47617L,47618L,47619L,47620L,47621L,47622L,47623L,47624L,
96847 47625L,47626L,47627L,47628L,47629L,47630L,47631L,47632L,47633L,47634L,
96848 47635L,47636L,47637L,47638L,47639L,47640L,47641L,47642L,47643L,47644L,
96849 47645L,47646L,47647L,47648L,47649L,47650L,47651L,47652L,47653L,47654L,
96850 47655L,47656L,47657L,47658L,47659L,47660L,47661L,47662L,47663L,47664L,
96851 47665L,47666L,47667L,47668L,47669L,47670L,47671L,47672L,47673L,47674L,
96852 47675L,47676L,47677L,47678L,47679L,47680L,47681L,47682L,47683L,47684L,
96853 47685L,47686L,47687L,47688L,47689L,47690L,47691L,47692L,47693L,47694L,
96854 47695L,47696L,47697L,47698L,47699L,47700L,47701L,47702L,47703L,47704L,
96855 47705L,47706L,47707L,47708L,47709L,47710L,47711L,47712L,47713L,47714L,
96856 47715L,47716L,47717L,47718L,47719L,47720L,47721L,47722L,47723L,47724L,
96857 47725L,47726L,47727L,47728L,47729L,47730L,47731L,47732L,47733L,47734L,
96858 47735L,47736L,47737L,47738L,47739L,47740L,47741L,47742L,47743L,47744L,
96859 47745L,47746L,47747L,47748L,47749L,47750L,47751L,47752L,47753L,47754L,
96860 47755L,47756L,47757L,47758L,47759L,47760L,47761L,47762L,47763L,47764L,
96861 47765L,47766L,47767L,47768L,47769L,47770L,47771L,47772L,47773L,47774L,
96862 47775L,47776L,47777L,47778L,47779L,47780L,47781L,47782L,47783L,47784L,
96863 47785L,47786L,47787L,47788L,47789L,47790L,47791L,47792L,47793L,47794L,
96864 47795L,47796L,47797L,47798L,47799L,47800L,47801L,47802L,47803L,47804L,
96865 47805L,47806L,47807L,47808L,47809L,47810L,47811L,47812L,47813L,47814L,
96866 47815L,47816L,47817L,47818L,47819L,47820L,47821L,47822L,47823L,47824L,
96867 47825L,47826L,47827L,47828L,47829L,47830L,47831L,47832L,47833L,47834L,
96868 47835L,47836L,47837L,47838L,47839L,47840L,47841L,47842L,47843L,47844L,
96869 47845L,47846L,47847L,47848L,47849L,47850L,47851L,47852L,47853L,47854L,
96870 47855L,47856L,47857L,47858L,47859L,47860L,47861L,47862L,47863L,47864L,
96871 47865L,47866L,47867L,47868L,47869L,47870L,47871L,47872L,47873L,47874L,
96872 47875L,47876L,47877L,47878L,47879L,47880L,47881L,47882L,47883L,47884L,
96873 47885L,47886L,47887L,47888L,47889L,47890L,47891L,47892L,47893L,47894L,
96874 47895L,47896L,47897L,47898L,47899L,47900L,47901L,47902L,47903L,47904L,
96875 47905L,47906L,47907L,47908L,47909L,47910L,47911L,47912L,47913L,47914L,
96876 47915L,47916L,47917L,47918L,47919L,47920L,47921L,47922L,47923L,47924L,
96877 47925L,47926L,47927L,47928L,47929L,47930L,47931L,47932L,47933L,47934L,
96878 47935L,47936L,47937L,47938L,47939L,47940L,47941L,47942L,47943L,47944L,
96879 47945L,47946L,47947L,47948L,47949L,47950L,47951L,47952L,47953L,47954L,
96880 47955L,47956L,47957L,47958L,47959L,47960L,47961L,47962L,47963L,47964L,
96881 47965L,47966L,47967L,47968L,47969L,47970L,47971L,47972L,47973L,47974L,
96882 47975L,47976L,47977L,47978L,47979L,47980L,47981L,47982L,47983L,47984L,
96883 47985L,47986L,47987L,47988L,47989L,47990L,47991L,47992L,47993L,47994L,
96884 47995L,47996L,47997L,47998L,47999L,48000L,48001L,48002L,48003L,48004L,
96885 48005L,48006L,48007L,48008L,48009L,48010L,48011L,48012L,48013L,48014L,
96886 48015L,48016L,48017L,48018L,48019L,48020L,48021L,48022L,48023L,48024L,
96887 48025L,48026L,48027L,48028L,48029L,48030L,48031L,48032L,48033L,48034L,
96888 48035L,48036L,48037L,48038L,48039L,48040L,48041L,48042L,48043L,48044L,
96889 48045L,48046L,48047L,48048L,48049L,48050L,48051L,48052L,48053L,48054L,
96890 48055L,48056L,48057L,48058L,48059L,48060L,48061L,48062L,48063L,48064L,
96891 48065L,48066L,48067L,48068L,48069L,48070L,48071L,48072L,48073L,48074L,
96892 48075L,48076L,48077L,48078L,48079L,48080L,48081L,48082L,48083L,48084L,
96893 48085L,48086L,48087L,48088L,48089L,48090L,48091L,48092L,48093L,48094L,
96894 48095L,48096L,48097L,48098L,48099L,48100L,48101L,48102L,48103L,48104L,
96895 48105L,48106L,48107L,48108L,48109L,48110L,48111L,48112L,48113L,48114L,
96896 48115L,48116L,48117L,48118L,48119L,48120L,48121L,48122L,48123L,48124L,
96897 48125L,48126L,48127L,48128L,48129L,48130L,48131L,48132L,48133L,48134L,
96898 48135L,48136L,48137L,48138L,48139L,48140L,48141L,48142L,48143L,48144L,
96899 48145L,48146L,48147L,48148L,48149L,48150L,48151L,48152L,48153L,48154L,
96900 48155L,48156L,48157L,48158L,48159L,48160L,48161L,48162L,48163L,48164L,
96901 48165L,48166L,48167L,48168L,48169L,48170L,48171L,48172L,48173L,48174L,
96902 48175L,48176L,48177L,48178L,48179L,48180L,48181L,48182L,48183L,48184L,
96903 48185L,48186L,48187L,48188L,48189L,48190L,48191L,48192L,48193L,48194L,
96904 48195L,48196L,48197L,48198L,48199L,48200L,48201L,48202L,48203L,48204L,
96905 48205L,48206L,48207L,48208L,48209L,48210L,48211L,48212L,48213L,48214L,
96906 48215L,48216L,48217L,48218L,48219L,48220L,48221L,48222L,48223L,48224L,
96907 48225L,48226L,48227L,48228L,48229L,48230L,48231L,48232L,48233L,48234L,
96908 48235L,48236L,48237L,48238L,48239L,48240L,48241L,48242L,48243L,48244L,
96909 48245L,48246L,48247L,48248L,48249L,48250L,48251L,48252L,48253L,48254L,
96910 48255L,48256L,48257L,48258L,48259L,48260L,48261L,48262L,48263L,48264L,
96911 48265L,48266L,48267L,48268L,48269L,48270L,48271L,48272L,48273L,48274L,
96912 48275L,48276L,48277L,48278L,48279L,48280L,48281L,48282L,48283L,48284L,
96913 48285L,48286L,48287L,48288L,48289L,48290L,48291L,48292L,48293L,48294L,
96914 48295L,48296L,48297L,48298L,48299L,48300L,48301L,48302L,48303L,48304L,
96915 48305L,48306L,48307L,48308L,48309L,48310L,48311L,48312L,48313L,48314L,
96916 48315L,48316L,48317L,48318L,48319L,48320L,48321L,48322L,48323L,48324L,
96917 48325L,48326L,48327L,48328L,48329L,48330L,48331L,48332L,48333L,48334L,
96918 48335L,48336L,48337L,48338L,48339L,48340L,48341L,48342L,48343L,48344L,
96919 48345L,48346L,48347L,48348L,48349L,48350L,48351L,48352L,48353L,48354L,
96920 48355L,48356L,48357L,48358L,48359L,48360L,48361L,48362L,48363L,48364L,
96921 48365L,48366L,48367L,48368L,48369L,48370L,48371L,48372L,48373L,48374L,
96922 48375L,48376L,48377L,48378L,48379L,48380L,48381L,48382L,48383L,48384L,
96923 48385L,48386L,48387L,48388L,48389L,48390L,48391L,48392L,48393L,48394L,
96924 48395L,48396L,48397L,48398L,48399L,48400L,48401L,48402L,48403L,48404L,
96925 48405L,48406L,48407L,48408L,48409L,48410L,48411L,48412L,48413L,48414L,
96926 48415L,48416L,48417L,48418L,48419L,48420L,48421L,48422L,48423L,48424L,
96927 48425L,48426L,48427L,48428L,48429L,48430L,48431L,48432L,48433L,48434L,
96928 48435L,48436L,48437L,48438L,48439L,48440L,48441L,48442L,48443L,48444L,
96929 48445L,48446L,48447L,48448L,48449L,48450L,48451L,48452L,48453L,48454L,
96930 48455L,48456L,48457L,48458L,48459L,48460L,48461L,48462L,48463L,48464L,
96931 48465L,48466L,48467L,48468L,48469L,48470L,48471L,48472L,48473L,48474L,
96932 48475L,48476L,48477L,48478L,48479L,48480L,48481L,48482L,48483L,48484L,
96933 48485L,48486L,48487L,48488L,48489L,48490L,48491L,48492L,48493L,48494L,
96934 48495L,48496L,48497L,48498L,48499L,48500L,48501L,48502L,48503L,48504L,
96935 48505L,48506L,48507L,48508L,48509L,48510L,48511L,48512L,48513L,48514L,
96936 48515L,48516L,48517L,48518L,48519L,48520L,48521L,48522L,48523L,48524L,
96937 48525L,48526L,48527L,48528L,48529L,48530L,48531L,48532L,48533L,48534L,
96938 48535L,48536L,48537L,48538L,48539L,48540L,48541L,48542L,48543L,48544L,
96939 48545L,48546L,48547L,48548L,48549L,48550L,48551L,48552L,48553L,48554L,
96940 48555L,48556L,48557L,48558L,48559L,48560L,48561L,48562L,48563L,48564L,
96941 48565L,48566L,48567L,48568L,48569L,48570L,48571L,48572L,48573L,48574L,
96942 48575L,48576L,48577L,48578L,48579L,48580L,48581L,48582L,48583L,48584L,
96943 48585L,48586L,48587L,48588L,48589L,48590L,48591L,48592L,48593L,48594L,
96944 48595L,48596L,48597L,48598L,48599L,48600L,48601L,48602L,48603L,48604L,
96945 48605L,48606L,48607L,48608L,48609L,48610L,48611L,48612L,48613L,48614L,
96946 48615L,48616L,48617L,48618L,48619L,48620L,48621L,48622L,48623L,48624L,
96947 48625L,48626L,48627L,48628L,48629L,48630L,48631L,48632L,48633L,48634L,
96948 48635L,48636L,48637L,48638L,48639L,48640L,48641L,48642L,48643L,48644L,
96949 48645L,48646L,48647L,48648L,48649L,48650L,48651L,48652L,48653L,48654L,
96950 48655L,48656L,48657L,48658L,48659L,48660L,48661L,48662L,48663L,48664L,
96951 48665L,48666L,48667L,48668L,48669L,48670L,48671L,48672L,48673L,48674L,
96952 48675L,48676L,48677L,48678L,48679L,48680L,48681L,48682L,48683L,48684L,
96953 48685L,48686L,48687L,48688L,48689L,48690L,48691L,48692L,48693L,48694L,
96954 48695L,48696L,48697L,48698L,48699L,48700L,48701L,48702L,48703L,48704L,
96955 48705L,48706L,48707L,48708L,48709L,48710L,48711L,48712L,48713L,48714L,
96956 48715L,48716L,48717L,48718L,48719L,48720L,48721L,48722L,48723L,48724L,
96957 48725L,48726L,48727L,48728L,48729L,48730L,48731L,48732L,48733L,48734L,
96958 48735L,48736L,48737L,48738L,48739L,48740L,48741L,48742L,48743L,48744L,
96959 48745L,48746L,48747L,48748L,48749L,48750L,48751L,48752L,48753L,48754L,
96960 48755L,48756L,48757L,48758L,48759L,48760L,48761L,48762L,48763L,48764L,
96961 48765L,48766L,48767L,48768L,48769L,48770L,48771L,48772L,48773L,48774L,
96962 48775L,48776L,48777L,48778L,48779L,48780L,48781L,48782L,48783L,48784L,
96963 48785L,48786L,48787L,48788L,48789L,48790L,48791L,48792L,48793L,48794L,
96964 48795L,48796L,48797L,48798L,48799L,48800L,48801L,48802L,48803L,48804L,
96965 48805L,48806L,48807L,48808L,48809L,48810L,48811L,48812L,48813L,48814L,
96966 48815L,48816L,48817L,48818L,48819L,48820L,48821L,48822L,48823L,48824L,
96967 48825L,48826L,48827L,48828L,48829L,48830L,48831L,48832L,48833L,48834L,
96968 48835L,48836L,48837L,48838L,48839L,48840L,48841L,48842L,48843L,48844L,
96969 48845L,48846L,48847L,48848L,48849L,48850L,48851L,48852L,48853L,48854L,
96970 48855L,48856L,48857L,48858L,48859L,48860L,48861L,48862L,48863L,48864L,
96971 48865L,48866L,48867L,48868L,48869L,48870L,48871L,48872L,48873L,48874L,
96972 48875L,48876L,48877L,48878L,48879L,48880L,48881L,48882L,48883L,48884L,
96973 48885L,48886L,48887L,48888L,48889L,48890L,48891L,48892L,48893L,48894L,
96974 48895L,48896L,48897L,48898L,48899L,48900L,48901L,48902L,48903L,48904L,
96975 48905L,48906L,48907L,48908L,48909L,48910L,48911L,48912L,48913L,48914L,
96976 48915L,48916L,48917L,48918L,48919L,48920L,48921L,48922L,48923L,48924L,
96977 48925L,48926L,48927L,48928L,48929L,48930L,48931L,48932L,48933L,48934L,
96978 48935L,48936L,48937L,48938L,48939L,48940L,48941L,48942L,48943L,48944L,
96979 48945L,48946L,48947L,48948L,48949L,48950L,48951L,48952L,48953L,48954L,
96980 48955L,48956L,48957L,48958L,48959L,48960L,48961L,48962L,48963L,48964L,
96981 48965L,48966L,48967L,48968L,48969L,48970L,48971L,48972L,48973L,48974L,
96982 48975L,48976L,48977L,48978L,48979L,48980L,48981L,48982L,48983L,48984L,
96983 48985L,48986L,48987L,48988L,48989L,48990L,48991L,48992L,48993L,48994L,
96984 48995L,48996L,48997L,48998L,48999L,49000L,49001L,49002L,49003L,49004L,
96985 49005L,49006L,49007L,49008L,49009L,49010L,49011L,49012L,49013L,49014L,
96986 49015L,49016L,49017L,49018L,49019L,49020L,49021L,49022L,49023L,49024L,
96987 49025L,49026L,49027L,49028L,49029L,49030L,49031L,49032L,49033L,49034L,
96988 49035L,49036L,49037L,49038L,49039L,49040L,49041L,49042L,49043L,49044L,
96989 49045L,49046L,49047L,49048L,49049L,49050L,49051L,49052L,49053L,49054L,
96990 49055L,49056L,49057L,49058L,49059L,49060L,49061L,49062L,49063L,49064L,
96991 49065L,49066L,49067L,49068L,49069L,49070L,49071L,49072L,49073L,49074L,
96992 49075L,49076L,49077L,49078L,49079L,49080L,49081L,49082L,49083L,49084L,
96993 49085L,49086L,49087L,49088L,49089L,49090L,49091L,49092L,49093L,49094L,
96994 49095L,49096L,49097L,49098L,49099L,49100L,49101L,49102L,49103L,49104L,
96995 49105L,49106L,49107L,49108L,49109L,49110L,49111L,49112L,49113L,49114L,
96996 49115L,49116L,49117L,49118L,49119L,49120L,49121L,49122L,49123L,49124L,
96997 49125L,49126L,49127L,49128L,49129L,49130L,49131L,49132L,49133L,49134L,
96998 49135L,49136L,49137L,49138L,49139L,49140L,49141L,49142L,49143L,49144L,
96999 49145L,49146L,49147L,49148L,49149L,49150L,49151L,49152L,49153L,49154L,
97000 49155L,49156L,49157L,49158L,49159L,49160L,49161L,49162L,49163L,49164L,
97001 49165L,49166L,49167L,49168L,49169L,49170L,49171L,49172L,49173L,49174L,
97002 49175L,49176L,49177L,49178L,49179L,49180L,49181L,49182L,49183L,49184L,
97003 49185L,49186L,49187L,49188L,49189L,49190L,49191L,49192L,49193L,49194L,
97004 49195L,49196L,49197L,49198L,49199L,49200L,49201L,49202L,49203L,49204L,
97005 49205L,49206L,49207L,49208L,49209L,49210L,49211L,49212L,49213L,49214L,
97006 49215L,49216L,49217L,49218L,49219L,49220L,49221L,49222L,49223L,49224L,
97007 49225L,49226L,49227L,49228L,49229L,49230L,49231L,49232L,49233L,49234L,
97008 49235L,49236L,49237L,49238L,49239L,49240L,49241L,49242L,49243L,49244L,
97009 49245L,49246L,49247L,49248L,49249L,49250L,49251L,49252L,49253L,49254L,
97010 49255L,49256L,49257L,49258L,49259L,49260L,49261L,49262L,49263L,49264L,
97011 49265L,49266L,49267L,49268L,49269L,49270L,49271L,49272L,49273L,49274L,
97012 49275L,49276L,49277L,49278L,49279L,49280L,49281L,49282L,49283L,49284L,
97013 49285L,49286L,49287L,49288L,49289L,49290L,49291L,49292L,49293L,49294L,
97014 49295L,49296L,49297L,49298L,49299L,49300L,49301L,49302L,49303L,49304L,
97015 49305L,49306L,49307L,49308L,49309L,49310L,49311L,49312L,49313L,49314L,
97016 49315L,49316L,49317L,49318L,49319L,49320L,49321L,49322L,49323L,49324L,
97017 49325L,49326L,49327L,49328L,49329L,49330L,49331L,49332L,49333L,49334L,
97018 49335L,49336L,49337L,49338L,49339L,49340L,49341L,49342L,49343L,49344L,
97019 49345L,49346L,49347L,49348L,49349L,49350L,49351L,49352L,49353L,49354L,
97020 49355L,49356L,49357L,49358L,49359L,49360L,49361L,49362L,49363L,49364L,
97021 49365L,49366L,49367L,49368L,49369L,49370L,49371L,49372L,49373L,49374L,
97022 49375L,49376L,49377L,49378L,49379L,49380L,49381L,49382L,49383L,49384L,
97023 49385L,49386L,49387L,49388L,49389L,49390L,49391L,49392L,49393L,49394L,
97024 49395L,49396L,49397L,49398L,49399L,49400L,49401L,49402L,49403L,49404L,
97025 49405L,49406L,49407L,49408L,49409L,49410L,49411L,49412L,49413L,49414L,
97026 49415L,49416L,49417L,49418L,49419L,49420L,49421L,49422L,49423L,49424L,
97027 49425L,49426L,49427L,49428L,49429L,49430L,49431L,49432L,49433L,49434L,
97028 49435L,49436L,49437L,49438L,49439L,49440L,49441L,49442L,49443L,49444L,
97029 49445L,49446L,49447L,49448L,49449L,49450L,49451L,49452L,49453L,49454L,
97030 49455L,49456L,49457L,49458L,49459L,49460L,49461L,49462L,49463L,49464L,
97031 49465L,49466L,49467L,49468L,49469L,49470L,49471L,49472L,49473L,49474L,
97032 49475L,49476L,49477L,49478L,49479L,49480L,49481L,49482L,49483L,49484L,
97033 49485L,49486L,49487L,49488L,49489L,49490L,49491L,49492L,49493L,49494L,
97034 49495L,49496L,49497L,49498L,49499L,49500L,49501L,49502L,49503L,49504L,
97035 49505L,49506L,49507L,49508L,49509L,49510L,49511L,49512L,49513L,49514L,
97036 49515L,49516L,49517L,49518L,49519L,49520L,49521L,49522L,49523L,49524L,
97037 49525L,49526L,49527L,49528L,49529L,49530L,49531L,49532L,49533L,49534L,
97038 49535L,49536L,49537L,49538L,49539L,49540L,49541L,49542L,49543L,49544L,
97039 49545L,49546L,49547L,49548L,49549L,49550L,49551L,49552L,49553L,49554L,
97040 49555L,49556L,49557L,49558L,49559L,49560L,49561L,49562L,49563L,49564L,
97041 49565L,49566L,49567L,49568L,49569L,49570L,49571L,49572L,49573L,49574L,
97042 49575L,49576L,49577L,49578L,49579L,49580L,49581L,49582L,49583L,49584L,
97043 49585L,49586L,49587L,49588L,49589L,49590L,49591L,49592L,49593L,49594L,
97044 49595L,49596L,49597L,49598L,49599L,49600L,49601L,49602L,49603L,49604L,
97045 49605L,49606L,49607L,49608L,49609L,49610L,49611L,49612L,49613L,49614L,
97046 49615L,49616L,49617L,49618L,49619L,49620L,49621L,49622L,49623L,49624L,
97047 49625L,49626L,49627L,49628L,49629L,49630L,49631L,49632L,49633L,49634L,
97048 49635L,49636L,49637L,49638L,49639L,49640L,49641L,49642L,49643L,49644L,
97049 49645L,49646L,49647L,49648L,49649L,49650L,49651L,49652L,49653L,49654L,
97050 49655L,49656L,49657L,49658L,49659L,49660L,49661L,49662L,49663L,49664L,
97051 49665L,49666L,49667L,49668L,49669L,49670L,49671L,49672L,49673L,49674L,
97052 49675L,49676L,49677L,49678L,49679L,49680L,49681L,49682L,49683L,49684L,
97053 49685L,49686L,49687L,49688L,49689L,49690L,49691L,49692L,49693L,49694L,
97054 49695L,49696L,49697L,49698L,49699L,49700L,49701L,49702L,49703L,49704L,
97055 49705L,49706L,49707L,49708L,49709L,49710L,49711L,49712L,49713L,49714L,
97056 49715L,49716L,49717L,49718L,49719L,49720L,49721L,49722L,49723L,49724L,
97057 49725L,49726L,49727L,49728L,49729L,49730L,49731L,49732L,49733L,49734L,
97058 49735L,49736L,49737L,49738L,49739L,49740L,49741L,49742L,49743L,49744L,
97059 49745L,49746L,49747L,49748L,49749L,49750L,49751L,49752L,49753L,49754L,
97060 49755L,49756L,49757L,49758L,49759L,49760L,49761L,49762L,49763L,49764L,
97061 49765L,49766L,49767L,49768L,49769L,49770L,49771L,49772L,49773L,49774L,
97062 49775L,49776L,49777L,49778L,49779L,49780L,49781L,49782L,49783L,49784L,
97063 49785L,49786L,49787L,49788L,49789L,49790L,49791L,49792L,49793L,49794L,
97064 49795L,49796L,49797L,49798L,49799L,49800L,49801L,49802L,49803L,49804L,
97065 49805L,49806L,49807L,49808L,49809L,49810L,49811L,49812L,49813L,49814L,
97066 49815L,49816L,49817L,49818L,49819L,49820L,49821L,49822L,49823L,49824L,
97067 49825L,49826L,49827L,49828L,49829L,49830L,49831L,49832L,49833L,49834L,
97068 49835L,49836L,49837L,49838L,49839L,49840L,49841L,49842L,49843L,49844L,
97069 49845L,49846L,49847L,49848L,49849L,49850L,49851L,49852L,49853L,49854L,
97070 49855L,49856L,49857L,49858L,49859L,49860L,49861L,49862L,49863L,49864L,
97071 49865L,49866L,49867L,49868L,49869L,49870L,49871L,49872L,49873L,49874L,
97072 49875L,49876L,49877L,49878L,49879L,49880L,49881L,49882L,49883L,49884L,
97073 49885L,49886L,49887L,49888L,49889L,49890L,49891L,49892L,49893L,49894L,
97074 49895L,49896L,49897L,49898L,49899L,49900L,49901L,49902L,49903L,49904L,
97075 49905L,49906L,49907L,49908L,49909L,49910L,49911L,49912L,49913L,49914L,
97076 49915L,49916L,49917L,49918L,49919L,49920L,49921L,49922L,49923L,49924L,
97077 49925L,49926L,49927L,49928L,49929L,49930L,49931L,49932L,49933L,49934L,
97078 49935L,49936L,49937L,49938L,49939L,49940L,49941L,49942L,49943L,49944L,
97079 49945L,49946L,49947L,49948L,49949L,49950L,49951L,49952L,49953L,49954L,
97080 49955L,49956L,49957L,49958L,49959L,49960L,49961L,49962L,49963L,49964L,
97081 49965L,49966L,49967L,49968L,49969L,49970L,49971L,49972L,49973L,49974L,
97082 49975L,49976L,49977L,49978L,49979L,49980L,49981L,49982L,49983L,49984L,
97083 49985L,49986L,49987L,49988L,49989L,49990L,49991L,49992L,49993L,49994L,
97084 49995L,49996L,49997L,49998L,49999L,50000L,50001L,50002L,50003L,50004L,
97085 50005L,50006L,50007L,50008L,50009L,50010L,50011L,50012L,50013L,50014L,
97086 50015L,50016L,50017L,50018L,50019L,50020L,50021L,50022L,50023L,50024L,
97087 50025L,50026L,50027L,50028L,50029L,50030L,50031L,50032L,50033L,50034L,
97088 50035L,50036L,50037L,50038L,50039L,50040L,50041L,50042L,50043L,50044L,
97089 50045L,50046L,50047L,50048L,50049L,50050L,50051L,50052L,50053L,50054L,
97090 50055L,50056L,50057L,50058L,50059L,50060L,50061L,50062L,50063L,50064L,
97091 50065L,50066L,50067L,50068L,50069L,50070L,50071L,50072L,50073L,50074L,
97092 50075L,50076L,50077L,50078L,50079L,50080L,50081L,50082L,50083L,50084L,
97093 50085L,50086L,50087L,50088L,50089L,50090L,50091L,50092L,50093L,50094L,
97094 50095L,50096L,50097L,50098L,50099L,50100L,50101L,50102L,50103L,50104L,
97095 50105L,50106L,50107L,50108L,50109L,50110L,50111L,50112L,50113L,50114L,
97096 50115L,50116L,50117L,50118L,50119L,50120L,50121L,50122L,50123L,50124L,
97097 50125L,50126L,50127L,50128L,50129L,50130L,50131L,50132L,50133L,50134L,
97098 50135L,50136L,50137L,50138L,50139L,50140L,50141L,50142L,50143L,50144L,
97099 50145L,50146L,50147L,50148L,50149L,50150L,50151L,50152L,50153L,50154L,
97100 50155L,50156L,50157L,50158L,50159L,50160L,50161L,50162L,50163L,50164L,
97101 50165L,50166L,50167L,50168L,50169L,50170L,50171L,50172L,50173L,50174L,
97102 50175L,50176L,50177L,50178L,50179L,50180L,50181L,50182L,50183L,50184L,
97103 50185L,50186L,50187L,50188L,50189L,50190L,50191L,50192L,50193L,50194L,
97104 50195L,50196L,50197L,50198L,50199L,50200L,50201L,50202L,50203L,50204L,
97105 50205L,50206L,50207L,50208L,50209L,50210L,50211L,50212L,50213L,50214L,
97106 50215L,50216L,50217L,50218L,50219L,50220L,50221L,50222L,50223L,50224L,
97107 50225L,50226L,50227L,50228L,50229L,50230L,50231L,50232L,50233L,50234L,
97108 50235L,50236L,50237L,50238L,50239L,50240L,50241L,50242L,50243L,50244L,
97109 50245L,50246L,50247L,50248L,50249L,50250L,50251L,50252L,50253L,50254L,
97110 50255L,50256L,50257L,50258L,50259L,50260L,50261L,50262L,50263L,50264L,
97111 50265L,50266L,50267L,50268L,50269L,50270L,50271L,50272L,50273L,50274L,
97112 50275L,50276L,50277L,50278L,50279L,50280L,50281L,50282L,50283L,50284L,
97113 50285L,50286L,50287L,50288L,50289L,50290L,50291L,50292L,50293L,50294L,
97114 50295L,50296L,50297L,50298L,50299L,50300L,50301L,50302L,50303L,50304L,
97115 50305L,50306L,50307L,50308L,50309L,50310L,50311L,50312L,50313L,50314L,
97116 50315L,50316L,50317L,50318L,50319L,50320L,50321L,50322L,50323L,50324L,
97117 50325L,50326L,50327L,50328L,50329L,50330L,50331L,50332L,50333L,50334L,
97118 50335L,50336L,50337L,50338L,50339L,50340L,50341L,50342L,50343L,50344L,
97119 50345L,50346L,50347L,50348L,50349L,50350L,50351L,50352L,50353L,50354L,
97120 50355L,50356L,50357L,50358L,50359L,50360L,50361L,50362L,50363L,50364L,
97121 50365L,50366L,50367L,50368L,50369L,50370L,50371L,50372L,50373L,50374L,
97122 50375L,50376L,50377L,50378L,50379L,50380L,50381L,50382L,50383L,50384L,
97123 50385L,50386L,50387L,50388L,50389L,50390L,50391L,50392L,50393L,50394L,
97124 50395L,50396L,50397L,50398L,50399L,50400L,50401L,50402L,50403L,50404L,
97125 50405L,50406L,50407L,50408L,50409L,50410L,50411L,50412L,50413L,50414L,
97126 50415L,50416L,50417L,50418L,50419L,50420L,50421L,50422L,50423L,50424L,
97127 50425L,50426L,50427L,50428L,50429L,50430L,50431L,50432L,50433L,50434L,
97128 50435L,50436L,50437L,50438L,50439L,50440L,50441L,50442L,50443L,50444L,
97129 50445L,50446L,50447L,50448L,50449L,50450L,50451L,50452L,50453L,50454L,
97130 50455L,50456L,50457L,50458L,50459L,50460L,50461L,50462L,50463L,50464L,
97131 50465L,50466L,50467L,50468L,50469L,50470L,50471L,50472L,50473L,50474L,
97132 50475L,50476L,50477L,50478L,50479L,50480L,50481L,50482L,50483L,50484L,
97133 50485L,50486L,50487L,50488L,50489L,50490L,50491L,50492L,50493L,50494L,
97134 50495L,50496L,50497L,50498L,50499L,50500L,50501L,50502L,50503L,50504L,
97135 50505L,50506L,50507L,50508L,50509L,50510L,50511L,50512L,50513L,50514L,
97136 50515L,50516L,50517L,50518L,50519L,50520L,50521L,50522L,50523L,50524L,
97137 50525L,50526L,50527L,50528L,50529L,50530L,50531L,50532L,50533L,50534L,
97138 50535L,50536L,50537L,50538L,50539L,50540L,50541L,50542L,50543L,50544L,
97139 50545L,50546L,50547L,50548L,50549L,50550L,50551L,50552L,50553L,50554L,
97140 50555L,50556L,50557L,50558L,50559L,50560L,50561L,50562L,50563L,50564L,
97141 50565L,50566L,50567L,50568L,50569L,50570L,50571L,50572L,50573L,50574L,
97142 50575L,50576L,50577L,50578L,50579L,50580L,50581L,50582L,50583L,50584L,
97143 50585L,50586L,50587L,50588L,50589L,50590L,50591L,50592L,50593L,50594L,
97144 50595L,50596L,50597L,50598L,50599L,50600L,50601L,50602L,50603L,50604L,
97145 50605L,50606L,50607L,50608L,50609L,50610L,50611L,50612L,50613L,50614L,
97146 50615L,50616L,50617L,50618L,50619L,50620L,50621L,50622L,50623L,50624L,
97147 50625L,50626L,50627L,50628L,50629L,50630L,50631L,50632L,50633L,50634L,
97148 50635L,50636L,50637L,50638L,50639L,50640L,50641L,50642L,50643L,50644L,
97149 50645L,50646L,50647L,50648L,50649L,50650L,50651L,50652L,50653L,50654L,
97150 50655L,50656L,50657L,50658L,50659L,50660L,50661L,50662L,50663L,50664L,
97151 50665L,50666L,50667L,50668L,50669L,50670L,50671L,50672L,50673L,50674L,
97152 50675L,50676L,50677L,50678L,50679L,50680L,50681L,50682L,50683L,50684L,
97153 50685L,50686L,50687L,50688L,50689L,50690L,50691L,50692L,50693L,50694L,
97154 50695L,50696L,50697L,50698L,50699L,50700L,50701L,50702L,50703L,50704L,
97155 50705L,50706L,50707L,50708L,50709L,50710L,50711L,50712L,50713L,50714L,
97156 50715L,50716L,50717L,50718L,50719L,50720L,50721L,50722L,50723L,50724L,
97157 50725L,50726L,50727L,50728L,50729L,50730L,50731L,50732L,50733L,50734L,
97158 50735L,50736L,50737L,50738L,50739L,50740L,50741L,50742L,50743L,50744L,
97159 50745L,50746L,50747L,50748L,50749L,50750L,50751L,50752L,50753L,50754L,
97160 50755L,50756L,50757L,50758L,50759L,50760L,50761L,50762L,50763L,50764L,
97161 50765L,50766L,50767L,50768L,50769L,50770L,50771L,50772L,50773L,50774L,
97162 50775L,50776L,50777L,50778L,50779L,50780L,50781L,50782L,50783L,50784L,
97163 50785L,50786L,50787L,50788L,50789L,50790L,50791L,50792L,50793L,50794L,
97164 50795L,50796L,50797L,50798L,50799L,50800L,50801L,50802L,50803L,50804L,
97165 50805L,50806L,50807L,50808L,50809L,50810L,50811L,50812L,50813L,50814L,
97166 50815L,50816L,50817L,50818L,50819L,50820L,50821L,50822L,50823L,50824L,
97167 50825L,50826L,50827L,50828L,50829L,50830L,50831L,50832L,50833L,50834L,
97168 50835L,50836L,50837L,50838L,50839L,50840L,50841L,50842L,50843L,50844L,
97169 50845L,50846L,50847L,50848L,50849L,50850L,50851L,50852L,50853L,50854L,
97170 50855L,50856L,50857L,50858L,50859L,50860L,50861L,50862L,50863L,50864L,
97171 50865L,50866L,50867L,50868L,50869L,50870L,50871L,50872L,50873L,50874L,
97172 50875L,50876L,50877L,50878L,50879L,50880L,50881L,50882L,50883L,50884L,
97173 50885L,50886L,50887L,50888L,50889L,50890L,50891L,50892L,50893L,50894L,
97174 50895L,50896L,50897L,50898L,50899L,50900L,50901L,50902L,50903L,50904L,
97175 50905L,50906L,50907L,50908L,50909L,50910L,50911L,50912L,50913L,50914L,
97176 50915L,50916L,50917L,50918L,50919L,50920L,50921L,50922L,50923L,50924L,
97177 50925L,50926L,50927L,50928L,50929L,50930L,50931L,50932L,50933L,50934L,
97178 50935L,50936L,50937L,50938L,50939L,50940L,50941L,50942L,50943L,50944L,
97179 50945L,50946L,50947L,50948L,50949L,50950L,50951L,50952L,50953L,50954L,
97180 50955L,50956L,50957L,50958L,50959L,50960L,50961L,50962L,50963L,50964L,
97181 50965L,50966L,50967L,50968L,50969L,50970L,50971L,50972L,50973L,50974L,
97182 50975L,50976L,50977L,50978L,50979L,50980L,50981L,50982L,50983L,50984L,
97183 50985L,50986L,50987L,50988L,50989L,50990L,50991L,50992L,50993L,50994L,
97184 50995L,50996L,50997L,50998L,50999L,51000L,51001L,51002L,51003L,51004L,
97185 51005L,51006L,51007L,51008L,51009L,51010L,51011L,51012L,51013L,51014L,
97186 51015L,51016L,51017L,51018L,51019L,51020L,51021L,51022L,51023L,51024L,
97187 51025L,51026L,51027L,51028L,51029L,51030L,51031L,51032L,51033L,51034L,
97188 51035L,51036L,51037L,51038L,51039L,51040L,51041L,51042L,51043L,51044L,
97189 51045L,51046L,51047L,51048L,51049L,51050L,51051L,51052L,51053L,51054L,
97190 51055L,51056L,51057L,51058L,51059L,51060L,51061L,51062L,51063L,51064L,
97191 51065L,51066L,51067L,51068L,51069L,51070L,51071L,51072L,51073L,51074L,
97192 51075L,51076L,51077L,51078L,51079L,51080L,51081L,51082L,51083L,51084L,
97193 51085L,51086L,51087L,51088L,51089L,51090L,51091L,51092L,51093L,51094L,
97194 51095L,51096L,51097L,51098L,51099L,51100L,51101L,51102L,51103L,51104L,
97195 51105L,51106L,51107L,51108L,51109L,51110L,51111L,51112L,51113L,51114L,
97196 51115L,51116L,51117L,51118L,51119L,51120L,51121L,51122L,51123L,51124L,
97197 51125L,51126L,51127L,51128L,51129L,51130L,51131L,51132L,51133L,51134L,
97198 51135L,51136L,51137L,51138L,51139L,51140L,51141L,51142L,51143L,51144L,
97199 51145L,51146L,51147L,51148L,51149L,51150L,51151L,51152L,51153L,51154L,
97200 51155L,51156L,51157L,51158L,51159L,51160L,51161L,51162L,51163L,51164L,
97201 51165L,51166L,51167L,51168L,51169L,51170L,51171L,51172L,51173L,51174L,
97202 51175L,51176L,51177L,51178L,51179L,51180L,51181L,51182L,51183L,51184L,
97203 51185L,51186L,51187L,51188L,51189L,51190L,51191L,51192L,51193L,51194L,
97204 51195L,51196L,51197L,51198L,51199L,51200L,51201L,51202L,51203L,51204L,
97205 51205L,51206L,51207L,51208L,51209L,51210L,51211L,51212L,51213L,51214L,
97206 51215L,51216L,51217L,51218L,51219L,51220L,51221L,51222L,51223L,51224L,
97207 51225L,51226L,51227L,51228L,51229L,51230L,51231L,51232L,51233L,51234L,
97208 51235L,51236L,51237L,51238L,51239L,51240L,51241L,51242L,51243L,51244L,
97209 51245L,51246L,51247L,51248L,51249L,51250L,51251L,51252L,51253L,51254L,
97210 51255L,51256L,51257L,51258L,51259L,51260L,51261L,51262L,51263L,51264L,
97211 51265L,51266L,51267L,51268L,51269L,51270L,51271L,51272L,51273L,51274L,
97212 51275L,51276L,51277L,51278L,51279L,51280L,51281L,51282L,51283L,51284L,
97213 51285L,51286L,51287L,51288L,51289L,51290L,51291L,51292L,51293L,51294L,
97214 51295L,51296L,51297L,51298L,51299L,51300L,51301L,51302L,51303L,51304L,
97215 51305L,51306L,51307L,51308L,51309L,51310L,51311L,51312L,51313L,51314L,
97216 51315L,51316L,51317L,51318L,51319L,51320L,51321L,51322L,51323L,51324L,
97217 51325L,51326L,51327L,51328L,51329L,51330L,51331L,51332L,51333L,51334L,
97218 51335L,51336L,51337L,51338L,51339L,51340L,51341L,51342L,51343L,51344L,
97219 51345L,51346L,51347L,51348L,51349L,51350L,51351L,51352L,51353L,51354L,
97220 51355L,51356L,51357L,51358L,51359L,51360L,51361L,51362L,51363L,51364L,
97221 51365L,51366L,51367L,51368L,51369L,51370L,51371L,51372L,51373L,51374L,
97222 51375L,51376L,51377L,51378L,51379L,51380L,51381L,51382L,51383L,51384L,
97223 51385L,51386L,51387L,51388L,51389L,51390L,51391L,51392L,51393L,51394L,
97224 51395L,51396L,51397L,51398L,51399L,51400L,51401L,51402L,51403L,51404L,
97225 51405L,51406L,51407L,51408L,51409L,51410L,51411L,51412L,51413L,51414L,
97226 51415L,51416L,51417L,51418L,51419L,51420L,51421L,51422L,51423L,51424L,
97227 51425L,51426L,51427L,51428L,51429L,51430L,51431L,51432L,51433L,51434L,
97228 51435L,51436L,51437L,51438L,51439L,51440L,51441L,51442L,51443L,51444L,
97229 51445L,51446L,51447L,51448L,51449L,51450L,51451L,51452L,51453L,51454L,
97230 51455L,51456L,51457L,51458L,51459L,51460L,51461L,51462L,51463L,51464L,
97231 51465L,51466L,51467L,51468L,51469L,51470L,51471L,51472L,51473L,51474L,
97232 51475L,51476L,51477L,51478L,51479L,51480L,51481L,51482L,51483L,51484L,
97233 51485L,51486L,51487L,51488L,51489L,51490L,51491L,51492L,51493L,51494L,
97234 51495L,51496L,51497L,51498L,51499L,51500L,51501L,51502L,51503L,51504L,
97235 51505L,51506L,51507L,51508L,51509L,51510L,51511L,51512L,51513L,51514L,
97236 51515L,51516L,51517L,51518L,51519L,51520L,51521L,51522L,51523L,51524L,
97237 51525L,51526L,51527L,51528L,51529L,51530L,51531L,51532L,51533L,51534L,
97238 51535L,51536L,51537L,51538L,51539L,51540L,51541L,51542L,51543L,51544L,
97239 51545L,51546L,51547L,51548L,51549L,51550L,51551L,51552L,51553L,51554L,
97240 51555L,51556L,51557L,51558L,51559L,51560L,51561L,51562L,51563L,51564L,
97241 51565L,51566L,51567L,51568L,51569L,51570L,51571L,51572L,51573L,51574L,
97242 51575L,51576L,51577L,51578L,51579L,51580L,51581L,51582L,51583L,51584L,
97243 51585L,51586L,51587L,51588L,51589L,51590L,51591L,51592L,51593L,51594L,
97244 51595L,51596L,51597L,51598L,51599L,51600L,51601L,51602L,51603L,51604L,
97245 51605L,51606L,51607L,51608L,51609L,51610L,51611L,51612L,51613L,51614L,
97246 51615L,51616L,51617L,51618L,51619L,51620L,51621L,51622L,51623L,51624L,
97247 51625L,51626L,51627L,51628L,51629L,51630L,51631L,51632L,51633L,51634L,
97248 51635L,51636L,51637L,51638L,51639L,51640L,51641L,51642L,51643L,51644L,
97249 51645L,51646L,51647L,51648L,51649L,51650L,51651L,51652L,51653L,51654L,
97250 51655L,51656L,51657L,51658L,51659L,51660L,51661L,51662L,51663L,51664L,
97251 51665L,51666L,51667L,51668L,51669L,51670L,51671L,51672L,51673L,51674L,
97252 51675L,51676L,51677L,51678L,51679L,51680L,51681L,51682L,51683L,51684L,
97253 51685L,51686L,51687L,51688L,51689L,51690L,51691L,51692L,51693L,51694L,
97254 51695L,51696L,51697L,51698L,51699L,51700L,51701L,51702L,51703L,51704L,
97255 51705L,51706L,51707L,51708L,51709L,51710L,51711L,51712L,51713L,51714L,
97256 51715L,51716L,51717L,51718L,51719L,51720L,51721L,51722L,51723L,51724L,
97257 51725L,51726L,51727L,51728L,51729L,51730L,51731L,51732L,51733L,51734L,
97258 51735L,51736L,51737L,51738L,51739L,51740L,51741L,51742L,51743L,51744L,
97259 51745L,51746L,51747L,51748L,51749L,51750L,51751L,51752L,51753L,51754L,
97260 51755L,51756L,51757L,51758L,51759L,51760L,51761L,51762L,51763L,51764L,
97261 51765L,51766L,51767L,51768L,51769L,51770L,51771L,51772L,51773L,51774L,
97262 51775L,51776L,51777L,51778L,51779L,51780L,51781L,51782L,51783L,51784L,
97263 51785L,51786L,51787L,51788L,51789L,51790L,51791L,51792L,51793L,51794L,
97264 51795L,51796L,51797L,51798L,51799L,51800L,51801L,51802L,51803L,51804L,
97265 51805L,51806L,51807L,51808L,51809L,51810L,51811L,51812L,51813L,51814L,
97266 51815L,51816L,51817L,51818L,51819L,51820L,51821L,51822L,51823L,51824L,
97267 51825L,51826L,51827L,51828L,51829L,51830L,51831L,51832L,51833L,51834L,
97268 51835L,51836L,51837L,51838L,51839L,51840L,51841L,51842L,51843L,51844L,
97269 51845L,51846L,51847L,51848L,51849L,51850L,51851L,51852L,51853L,51854L,
97270 51855L,51856L,51857L,51858L,51859L,51860L,51861L,51862L,51863L,51864L,
97271 51865L,51866L,51867L,51868L,51869L,51870L,51871L,51872L,51873L,51874L,
97272 51875L,51876L,51877L,51878L,51879L,51880L,51881L,51882L,51883L,51884L,
97273 51885L,51886L,51887L,51888L,51889L,51890L,51891L,51892L,51893L,51894L,
97274 51895L,51896L,51897L,51898L,51899L,51900L,51901L,51902L,51903L,51904L,
97275 51905L,51906L,51907L,51908L,51909L,51910L,51911L,51912L,51913L,51914L,
97276 51915L,51916L,51917L,51918L,51919L,51920L,51921L,51922L,51923L,51924L,
97277 51925L,51926L,51927L,51928L,51929L,51930L,51931L,51932L,51933L,51934L,
97278 51935L,51936L,51937L,51938L,51939L,51940L,51941L,51942L,51943L,51944L,
97279 51945L,51946L,51947L,51948L,51949L,51950L,51951L,51952L,51953L,51954L,
97280 51955L,51956L,51957L,51958L,51959L,51960L,51961L,51962L,51963L,51964L,
97281 51965L,51966L,51967L,51968L,51969L,51970L,51971L,51972L,51973L,51974L,
97282 51975L,51976L,51977L,51978L,51979L,51980L,51981L,51982L,51983L,51984L,
97283 51985L,51986L,51987L,51988L,51989L,51990L,51991L,51992L,51993L,51994L,
97284 51995L,51996L,51997L,51998L,51999L,52000L,52001L,52002L,52003L,52004L,
97285 52005L,52006L,52007L,52008L,52009L,52010L,52011L,52012L,52013L,52014L,
97286 52015L,52016L,52017L,52018L,52019L,52020L,52021L,52022L,52023L,52024L,
97287 52025L,52026L,52027L,52028L,52029L,52030L,52031L,52032L,52033L,52034L,
97288 52035L,52036L,52037L,52038L,52039L,52040L,52041L,52042L,52043L,52044L,
97289 52045L,52046L,52047L,52048L,52049L,52050L,52051L,52052L,52053L,52054L,
97290 52055L,52056L,52057L,52058L,52059L,52060L,52061L,52062L,52063L,52064L,
97291 52065L,52066L,52067L,52068L,52069L,52070L,52071L,52072L,52073L,52074L,
97292 52075L,52076L,52077L,52078L,52079L,52080L,52081L,52082L,52083L,52084L,
97293 52085L,52086L,52087L,52088L,52089L,52090L,52091L,52092L,52093L,52094L,
97294 52095L,52096L,52097L,52098L,52099L,52100L,52101L,52102L,52103L,52104L,
97295 52105L,52106L,52107L,52108L,52109L,52110L,52111L,52112L,52113L,52114L,
97296 52115L,52116L,52117L,52118L,52119L,52120L,52121L,52122L,52123L,52124L,
97297 52125L,52126L,52127L,52128L,52129L,52130L,52131L,52132L,52133L,52134L,
97298 52135L,52136L,52137L,52138L,52139L,52140L,52141L,52142L,52143L,52144L,
97299 52145L,52146L,52147L,52148L,52149L,52150L,52151L,52152L,52153L,52154L,
97300 52155L,52156L,52157L,52158L,52159L,52160L,52161L,52162L,52163L,52164L,
97301 52165L,52166L,52167L,52168L,52169L,52170L,52171L,52172L,52173L,52174L,
97302 52175L,52176L,52177L,52178L,52179L,52180L,52181L,52182L,52183L,52184L,
97303 52185L,52186L,52187L,52188L,52189L,52190L,52191L,52192L,52193L,52194L,
97304 52195L,52196L,52197L,52198L,52199L,52200L,52201L,52202L,52203L,52204L,
97305 52205L,52206L,52207L,52208L,52209L,52210L,52211L,52212L,52213L,52214L,
97306 52215L,52216L,52217L,52218L,52219L,52220L,52221L,52222L,52223L,52224L,
97307 52225L,52226L,52227L,52228L,52229L,52230L,52231L,52232L,52233L,52234L,
97308 52235L,52236L,52237L,52238L,52239L,52240L,52241L,52242L,52243L,52244L,
97309 52245L,52246L,52247L,52248L,52249L,52250L,52251L,52252L,52253L,52254L,
97310 52255L,52256L,52257L,52258L,52259L,52260L,52261L,52262L,52263L,52264L,
97311 52265L,52266L,52267L,52268L,52269L,52270L,52271L,52272L,52273L,52274L,
97312 52275L,52276L,52277L,52278L,52279L,52280L,52281L,52282L,52283L,52284L,
97313 52285L,52286L,52287L,52288L,52289L,52290L,52291L,52292L,52293L,52294L,
97314 52295L,52296L,52297L,52298L,52299L,52300L,52301L,52302L,52303L,52304L,
97315 52305L,52306L,52307L,52308L,52309L,52310L,52311L,52312L,52313L,52314L,
97316 52315L,52316L,52317L,52318L,52319L,52320L,52321L,52322L,52323L,52324L,
97317 52325L,52326L,52327L,52328L,52329L,52330L,52331L,52332L,52333L,52334L,
97318 52335L,52336L,52337L,52338L,52339L,52340L,52341L,52342L,52343L,52344L,
97319 52345L,52346L,52347L,52348L,52349L,52350L,52351L,52352L,52353L,52354L,
97320 52355L,52356L,52357L,52358L,52359L,52360L,52361L,52362L,52363L,52364L,
97321 52365L,52366L,52367L,52368L,52369L,52370L,52371L,52372L,52373L,52374L,
97322 52375L,52376L,52377L,52378L,52379L,52380L,52381L,52382L,52383L,52384L,
97323 52385L,52386L,52387L,52388L,52389L,52390L,52391L,52392L,52393L,52394L,
97324 52395L,52396L,52397L,52398L,52399L,52400L,52401L,52402L,52403L,52404L,
97325 52405L,52406L,52407L,52408L,52409L,52410L,52411L,52412L,52413L,52414L,
97326 52415L,52416L,52417L,52418L,52419L,52420L,52421L,52422L,52423L,52424L,
97327 52425L,52426L,52427L,52428L,52429L,52430L,52431L,52432L,52433L,52434L,
97328 52435L,52436L,52437L,52438L,52439L,52440L,52441L,52442L,52443L,52444L,
97329 52445L,52446L,52447L,52448L,52449L,52450L,52451L,52452L,52453L,52454L,
97330 52455L,52456L,52457L,52458L,52459L,52460L,52461L,52462L,52463L,52464L,
97331 52465L,52466L,52467L,52468L,52469L,52470L,52471L,52472L,52473L,52474L,
97332 52475L,52476L,52477L,52478L,52479L,52480L,52481L,52482L,52483L,52484L,
97333 52485L,52486L,52487L,52488L,52489L,52490L,52491L,52492L,52493L,52494L,
97334 52495L,52496L,52497L,52498L,52499L,52500L,52501L,52502L,52503L,52504L,
97335 52505L,52506L,52507L,52508L,52509L,52510L,52511L,52512L,52513L,52514L,
97336 52515L,52516L,52517L,52518L,52519L,52520L,52521L,52522L,52523L,52524L,
97337 52525L,52526L,52527L,52528L,52529L,52530L,52531L,52532L,52533L,52534L,
97338 52535L,52536L,52537L,52538L,52539L,52540L,52541L,52542L,52543L,52544L,
97339 52545L,52546L,52547L,52548L,52549L,52550L,52551L,52552L,52553L,52554L,
97340 52555L,52556L,52557L,52558L,52559L,52560L,52561L,52562L,52563L,52564L,
97341 52565L,52566L,52567L,52568L,52569L,52570L,52571L,52572L,52573L,52574L,
97342 52575L,52576L,52577L,52578L,52579L,52580L,52581L,52582L,52583L,52584L,
97343 52585L,52586L,52587L,52588L,52589L,52590L,52591L,52592L,52593L,52594L,
97344 52595L,52596L,52597L,52598L,52599L,52600L,52601L,52602L,52603L,52604L,
97345 52605L,52606L,52607L,52608L,52609L,52610L,52611L,52612L,52613L,52614L,
97346 52615L,52616L,52617L,52618L,52619L,52620L,52621L,52622L,52623L,52624L,
97347 52625L,52626L,52627L,52628L,52629L,52630L,52631L,52632L,52633L,52634L,
97348 52635L,52636L,52637L,52638L,52639L,52640L,52641L,52642L,52643L,52644L,
97349 52645L,52646L,52647L,52648L,52649L,52650L,52651L,52652L,52653L,52654L,
97350 52655L,52656L,52657L,52658L,52659L,52660L,52661L,52662L,52663L,52664L,
97351 52665L,52666L,52667L,52668L,52669L,52670L,52671L,52672L,52673L,52674L,
97352 52675L,52676L,52677L,52678L,52679L,52680L,52681L,52682L,52683L,52684L,
97353 52685L,52686L,52687L,52688L,52689L,52690L,52691L,52692L,52693L,52694L,
97354 52695L,52696L,52697L,52698L,52699L,52700L,52701L,52702L,52703L,52704L,
97355 52705L,52706L,52707L,52708L,52709L,52710L,52711L,52712L,52713L,52714L,
97356 52715L,52716L,52717L,52718L,52719L,52720L,52721L,52722L,52723L,52724L,
97357 52725L,52726L,52727L,52728L,52729L,52730L,52731L,52732L,52733L,52734L,
97358 52735L,52736L,52737L,52738L,52739L,52740L,52741L,52742L,52743L,52744L,
97359 52745L,52746L,52747L,52748L,52749L,52750L,52751L,52752L,52753L,52754L,
97360 52755L,52756L,52757L,52758L,52759L,52760L,52761L,52762L,52763L,52764L,
97361 52765L,52766L,52767L,52768L,52769L,52770L,52771L,52772L,52773L,52774L,
97362 52775L,52776L,52777L,52778L,52779L,52780L,52781L,52782L,52783L,52784L,
97363 52785L,52786L,52787L,52788L,52789L,52790L,52791L,52792L,52793L,52794L,
97364 52795L,52796L,52797L,52798L,52799L,52800L,52801L,52802L,52803L,52804L,
97365 52805L,52806L,52807L,52808L,52809L,52810L,52811L,52812L,52813L,52814L,
97366 52815L,52816L,52817L,52818L,52819L,52820L,52821L,52822L,52823L,52824L,
97367 52825L,52826L,52827L,52828L,52829L,52830L,52831L,52832L,52833L,52834L,
97368 52835L,52836L,52837L,52838L,52839L,52840L,52841L,52842L,52843L,52844L,
97369 52845L,52846L,52847L,52848L,52849L,52850L,52851L,52852L,52853L,52854L,
97370 52855L,52856L,52857L,52858L,52859L,52860L,52861L,52862L,52863L,52864L,
97371 52865L,52866L,52867L,52868L,52869L,52870L,52871L,52872L,52873L,52874L,
97372 52875L,52876L,52877L,52878L,52879L,52880L,52881L,52882L,52883L,52884L,
97373 52885L,52886L,52887L,52888L,52889L,52890L,52891L,52892L,52893L,52894L,
97374 52895L,52896L,52897L,52898L,52899L,52900L,52901L,52902L,52903L,52904L,
97375 52905L,52906L,52907L,52908L,52909L,52910L,52911L,52912L,52913L,52914L,
97376 52915L,52916L,52917L,52918L,52919L,52920L,52921L,52922L,52923L,52924L,
97377 52925L,52926L,52927L,52928L,52929L,52930L,52931L,52932L,52933L,52934L,
97378 52935L,52936L,52937L,52938L,52939L,52940L,52941L,52942L,52943L,52944L,
97379 52945L,52946L,52947L,52948L,52949L,52950L,52951L,52952L,52953L,52954L,
97380 52955L,52956L,52957L,52958L,52959L,52960L,52961L,52962L,52963L,52964L,
97381 52965L,52966L,52967L,52968L,52969L,52970L,52971L,52972L,52973L,52974L,
97382 52975L,52976L,52977L,52978L,52979L,52980L,52981L,52982L,52983L,52984L,
97383 52985L,52986L,52987L,52988L,52989L,52990L,52991L,52992L,52993L,52994L,
97384 52995L,52996L,52997L,52998L,52999L,53000L,53001L,53002L,53003L,53004L,
97385 53005L,53006L,53007L,53008L,53009L,53010L,53011L,53012L,53013L,53014L,
97386 53015L,53016L,53017L,53018L,53019L,53020L,53021L,53022L,53023L,53024L,
97387 53025L,53026L,53027L,53028L,53029L,53030L,53031L,53032L,53033L,53034L,
97388 53035L,53036L,53037L,53038L,53039L,53040L,53041L,53042L,53043L,53044L,
97389 53045L,53046L,53047L,53048L,53049L,53050L,53051L,53052L,53053L,53054L,
97390 53055L,53056L,53057L,53058L,53059L,53060L,53061L,53062L,53063L,53064L,
97391 53065L,53066L,53067L,53068L,53069L,53070L,53071L,53072L,53073L,53074L,
97392 53075L,53076L,53077L,53078L,53079L,53080L,53081L,53082L,53083L,53084L,
97393 53085L,53086L,53087L,53088L,53089L,53090L,53091L,53092L,53093L,53094L,
97394 53095L,53096L,53097L,53098L,53099L,53100L,53101L,53102L,53103L,53104L,
97395 53105L,53106L,53107L,53108L,53109L,53110L,53111L,53112L,53113L,53114L,
97396 53115L,53116L,53117L,53118L,53119L,53120L,53121L,53122L,53123L,53124L,
97397 53125L,53126L,53127L,53128L,53129L,53130L,53131L,53132L,53133L,53134L,
97398 53135L,53136L,53137L,53138L,53139L,53140L,53141L,53142L,53143L,53144L,
97399 53145L,53146L,53147L,53148L,53149L,53150L,53151L,53152L,53153L,53154L,
97400 53155L,53156L,53157L,53158L,53159L,53160L,53161L,53162L,53163L,53164L,
97401 53165L,53166L,53167L,53168L,53169L,53170L,53171L,53172L,53173L,53174L,
97402 53175L,53176L,53177L,53178L,53179L,53180L,53181L,53182L,53183L,53184L,
97403 53185L,53186L,53187L,53188L,53189L,53190L,53191L,53192L,53193L,53194L,
97404 53195L,53196L,53197L,53198L,53199L,53200L,53201L,53202L,53203L,53204L,
97405 53205L,53206L,53207L,53208L,53209L,53210L,53211L,53212L,53213L,53214L,
97406 53215L,53216L,53217L,53218L,53219L,53220L,53221L,53222L,53223L,53224L,
97407 53225L,53226L,53227L,53228L,53229L,53230L,53231L,53232L,53233L,53234L,
97408 53235L,53236L,53237L,53238L,53239L,53240L,53241L,53242L,53243L,53244L,
97409 53245L,53246L,53247L,53248L,53249L,53250L,53251L,53252L,53253L,53254L,
97410 53255L,53256L,53257L,53258L,53259L,53260L,53261L,53262L,53263L,53264L,
97411 53265L,53266L,53267L,53268L,53269L,53270L,53271L,53272L,53273L,53274L,
97412 53275L,53276L,53277L,53278L,53279L,53280L,53281L,53282L,53283L,53284L,
97413 53285L,53286L,53287L,53288L,53289L,53290L,53291L,53292L,53293L,53294L,
97414 53295L,53296L,53297L,53298L,53299L,53300L,53301L,53302L,53303L,53304L,
97415 53305L,53306L,53307L,53308L,53309L,53310L,53311L,53312L,53313L,53314L,
97416 53315L,53316L,53317L,53318L,53319L,53320L,53321L,53322L,53323L,53324L,
97417 53325L,53326L,53327L,53328L,53329L,53330L,53331L,53332L,53333L,53334L,
97418 53335L,53336L,53337L,53338L,53339L,53340L,53341L,53342L,53343L,53344L,
97419 53345L,53346L,53347L,53348L,53349L,53350L,53351L,53352L,53353L,53354L,
97420 53355L,53356L,53357L,53358L,53359L,53360L,53361L,53362L,53363L,53364L,
97421 53365L,53366L,53367L,53368L,53369L,53370L,53371L,53372L,53373L,53374L,
97422 53375L,53376L,53377L,53378L,53379L,53380L,53381L,53382L,53383L,53384L,
97423 53385L,53386L,53387L,53388L,53389L,53390L,53391L,53392L,53393L,53394L,
97424 53395L,53396L,53397L,53398L,53399L,53400L,53401L,53402L,53403L,53404L,
97425 53405L,53406L,53407L,53408L,53409L,53410L,53411L,53412L,53413L,53414L,
97426 53415L,53416L,53417L,53418L,53419L,53420L,53421L,53422L,53423L,53424L,
97427 53425L,53426L,53427L,53428L,53429L,53430L,53431L,53432L,53433L,53434L,
97428 53435L,53436L,53437L,53438L,53439L,53440L,53441L,53442L,53443L,53444L,
97429 53445L,53446L,53447L,53448L,53449L,53450L,53451L,53452L,53453L,53454L,
97430 53455L,53456L,53457L,53458L,53459L,53460L,53461L,53462L,53463L,53464L,
97431 53465L,53466L,53467L,53468L,53469L,53470L,53471L,53472L,53473L,53474L,
97432 53475L,53476L,53477L,53478L,53479L,53480L,53481L,53482L,53483L,53484L,
97433 53485L,53486L,53487L,53488L,53489L,53490L,53491L,53492L,53493L,53494L,
97434 53495L,53496L,53497L,53498L,53499L,53500L,53501L,53502L,53503L,53504L,
97435 53505L,53506L,53507L,53508L,53509L,53510L,53511L,53512L,53513L,53514L,
97436 53515L,53516L,53517L,53518L,53519L,53520L,53521L,53522L,53523L,53524L,
97437 53525L,53526L,53527L,53528L,53529L,53530L,53531L,53532L,53533L,53534L,
97438 53535L,53536L,53537L,53538L,53539L,53540L,53541L,53542L,53543L,53544L,
97439 53545L,53546L,53547L,53548L,53549L,53550L,53551L,53552L,53553L,53554L,
97440 53555L,53556L,53557L,53558L,53559L,53560L,53561L,53562L,53563L,53564L,
97441 53565L,53566L,53567L,53568L,53569L,53570L,53571L,53572L,53573L,53574L,
97442 53575L,53576L,53577L,53578L,53579L,53580L,53581L,53582L,53583L,53584L,
97443 53585L,53586L,53587L,53588L,53589L,53590L,53591L,53592L,53593L,53594L,
97444 53595L,53596L,53597L,53598L,53599L,53600L,53601L,53602L,53603L,53604L,
97445 53605L,53606L,53607L,53608L,53609L,53610L,53611L,53612L,53613L,53614L,
97446 53615L,53616L,53617L,53618L,53619L,53620L,53621L,53622L,53623L,53624L,
97447 53625L,53626L,53627L,53628L,53629L,53630L,53631L,53632L,53633L,53634L,
97448 53635L,53636L,53637L,53638L,53639L,53640L,53641L,53642L,53643L,53644L,
97449 53645L,53646L,53647L,53648L,53649L,53650L,53651L,53652L,53653L,53654L,
97450 53655L,53656L,53657L,53658L,53659L,53660L,53661L,53662L,53663L,53664L,
97451 53665L,53666L,53667L,53668L,53669L,53670L,53671L,53672L,53673L,53674L,
97452 53675L,53676L,53677L,53678L,53679L,53680L,53681L,53682L,53683L,53684L,
97453 53685L,53686L,53687L,53688L,53689L,53690L,53691L,53692L,53693L,53694L,
97454 53695L,53696L,53697L,53698L,53699L,53700L,53701L,53702L,53703L,53704L,
97455 53705L,53706L,53707L,53708L,53709L,53710L,53711L,53712L,53713L,53714L,
97456 53715L,53716L,53717L,53718L,53719L,53720L,53721L,53722L,53723L,53724L,
97457 53725L,53726L,53727L,53728L,53729L,53730L,53731L,53732L,53733L,53734L,
97458 53735L,53736L,53737L,53738L,53739L,53740L,53741L,53742L,53743L,53744L,
97459 53745L,53746L,53747L,53748L,53749L,53750L,53751L,53752L,53753L,53754L,
97460 53755L,53756L,53757L,53758L,53759L,53760L,53761L,53762L,53763L,53764L,
97461 53765L,53766L,53767L,53768L,53769L,53770L,53771L,53772L,53773L,53774L,
97462 53775L,53776L,53777L,53778L,53779L,53780L,53781L,53782L,53783L,53784L,
97463 53785L,53786L,53787L,53788L,53789L,53790L,53791L,53792L,53793L,53794L,
97464 53795L,53796L,53797L,53798L,53799L,53800L,53801L,53802L,53803L,53804L,
97465 53805L,53806L,53807L,53808L,53809L,53810L,53811L,53812L,53813L,53814L,
97466 53815L,53816L,53817L,53818L,53819L,53820L,53821L,53822L,53823L,53824L,
97467 53825L,53826L,53827L,53828L,53829L,53830L,53831L,53832L,53833L,53834L,
97468 53835L,53836L,53837L,53838L,53839L,53840L,53841L,53842L,53843L,53844L,
97469 53845L,53846L,53847L,53848L,53849L,53850L,53851L,53852L,53853L,53854L,
97470 53855L,53856L,53857L,53858L,53859L,53860L,53861L,53862L,53863L,53864L,
97471 53865L,53866L,53867L,53868L,53869L,53870L,53871L,53872L,53873L,53874L,
97472 53875L,53876L,53877L,53878L,53879L,53880L,53881L,53882L,53883L,53884L,
97473 53885L,53886L,53887L,53888L,53889L,53890L,53891L,53892L,53893L,53894L,
97474 53895L,53896L,53897L,53898L,53899L,53900L,53901L,53902L,53903L,53904L,
97475 53905L,53906L,53907L,53908L,53909L,53910L,53911L,53912L,53913L,53914L,
97476 53915L,53916L,53917L,53918L,53919L,53920L,53921L,53922L,53923L,53924L,
97477 53925L,53926L,53927L,53928L,53929L,53930L,53931L,53932L,53933L,53934L,
97478 53935L,53936L,53937L,53938L,53939L,53940L,53941L,53942L,53943L,53944L,
97479 53945L,53946L,53947L,53948L,53949L,53950L,53951L,53952L,53953L,53954L,
97480 53955L,53956L,53957L,53958L,53959L,53960L,53961L,53962L,53963L,53964L,
97481 53965L,53966L,53967L,53968L,53969L,53970L,53971L,53972L,53973L,53974L,
97482 53975L,53976L,53977L,53978L,53979L,53980L,53981L,53982L,53983L,53984L,
97483 53985L,53986L,53987L,53988L,53989L,53990L,53991L,53992L,53993L,53994L,
97484 53995L,53996L,53997L,53998L,53999L,54000L,54001L,54002L,54003L,54004L,
97485 54005L,54006L,54007L,54008L,54009L,54010L,54011L,54012L,54013L,54014L,
97486 54015L,54016L,54017L,54018L,54019L,54020L,54021L,54022L,54023L,54024L,
97487 54025L,54026L,54027L,54028L,54029L,54030L,54031L,54032L,54033L,54034L,
97488 54035L,54036L,54037L,54038L,54039L,54040L,54041L,54042L,54043L,54044L,
97489 54045L,54046L,54047L,54048L,54049L,54050L,54051L,54052L,54053L,54054L,
97490 54055L,54056L,54057L,54058L,54059L,54060L,54061L,54062L,54063L,54064L,
97491 54065L,54066L,54067L,54068L,54069L,54070L,54071L,54072L,54073L,54074L,
97492 54075L,54076L,54077L,54078L,54079L,54080L,54081L,54082L,54083L,54084L,
97493 54085L,54086L,54087L,54088L,54089L,54090L,54091L,54092L,54093L,54094L,
97494 54095L,54096L,54097L,54098L,54099L,54100L,54101L,54102L,54103L,54104L,
97495 54105L,54106L,54107L,54108L,54109L,54110L,54111L,54112L,54113L,54114L,
97496 54115L,54116L,54117L,54118L,54119L,54120L,54121L,54122L,54123L,54124L,
97497 54125L,54126L,54127L,54128L,54129L,54130L,54131L,54132L,54133L,54134L,
97498 54135L,54136L,54137L,54138L,54139L,54140L,54141L,54142L,54143L,54144L,
97499 54145L,54146L,54147L,54148L,54149L,54150L,54151L,54152L,54153L,54154L,
97500 54155L,54156L,54157L,54158L,54159L,54160L,54161L,54162L,54163L,54164L,
97501 54165L,54166L,54167L,54168L,54169L,54170L,54171L,54172L,54173L,54174L,
97502 54175L,54176L,54177L,54178L,54179L,54180L,54181L,54182L,54183L,54184L,
97503 54185L,54186L,54187L,54188L,54189L,54190L,54191L,54192L,54193L,54194L,
97504 54195L,54196L,54197L,54198L,54199L,54200L,54201L,54202L,54203L,54204L,
97505 54205L,54206L,54207L,54208L,54209L,54210L,54211L,54212L,54213L,54214L,
97506 54215L,54216L,54217L,54218L,54219L,54220L,54221L,54222L,54223L,54224L,
97507 54225L,54226L,54227L,54228L,54229L,54230L,54231L,54232L,54233L,54234L,
97508 54235L,54236L,54237L,54238L,54239L,54240L,54241L,54242L,54243L,54244L,
97509 54245L,54246L,54247L,54248L,54249L,54250L,54251L,54252L,54253L,54254L,
97510 54255L,54256L,54257L,54258L,54259L,54260L,54261L,54262L,54263L,54264L,
97511 54265L,54266L,54267L,54268L,54269L,54270L,54271L,54272L,54273L,54274L,
97512 54275L,54276L,54277L,54278L,54279L,54280L,54281L,54282L,54283L,54284L,
97513 54285L,54286L,54287L,54288L,54289L,54290L,54291L,54292L,54293L,54294L,
97514 54295L,54296L,54297L,54298L,54299L,54300L,54301L,54302L,54303L,54304L,
97515 54305L,54306L,54307L,54308L,54309L,54310L,54311L,54312L,54313L,54314L,
97516 54315L,54316L,54317L,54318L,54319L,54320L,54321L,54322L,54323L,54324L,
97517 54325L,54326L,54327L,54328L,54329L,54330L,54331L,54332L,54333L,54334L,
97518 54335L,54336L,54337L,54338L,54339L,54340L,54341L,54342L,54343L,54344L,
97519 54345L,54346L,54347L,54348L,54349L,54350L,54351L,54352L,54353L,54354L,
97520 54355L,54356L,54357L,54358L,54359L,54360L,54361L,54362L,54363L,54364L,
97521 54365L,54366L,54367L,54368L,54369L,54370L,54371L,54372L,54373L,54374L,
97522 54375L,54376L,54377L,54378L,54379L,54380L,54381L,54382L,54383L,54384L,
97523 54385L,54386L,54387L,54388L,54389L,54390L,54391L,54392L,54393L,54394L,
97524 54395L,54396L,54397L,54398L,54399L,54400L,54401L,54402L,54403L,54404L,
97525 54405L,54406L,54407L,54408L,54409L,54410L,54411L,54412L,54413L,54414L,
97526 54415L,54416L,54417L,54418L,54419L,54420L,54421L,54422L,54423L,54424L,
97527 54425L,54426L,54427L,54428L,54429L,54430L,54431L,54432L,54433L,54434L,
97528 54435L,54436L,54437L,54438L,54439L,54440L,54441L,54442L,54443L,54444L,
97529 54445L,54446L,54447L,54448L,54449L,54450L,54451L,54452L,54453L,54454L,
97530 54455L,54456L,54457L,54458L,54459L,54460L,54461L,54462L,54463L,54464L,
97531 54465L,54466L,54467L,54468L,54469L,54470L,54471L,54472L,54473L,54474L,
97532 54475L,54476L,54477L,54478L,54479L,54480L,54481L,54482L,54483L,54484L,
97533 54485L,54486L,54487L,54488L,54489L,54490L,54491L,54492L,54493L,54494L,
97534 54495L,54496L,54497L,54498L,54499L,54500L,54501L,54502L,54503L,54504L,
97535 54505L,54506L,54507L,54508L,54509L,54510L,54511L,54512L,54513L,54514L,
97536 54515L,54516L,54517L,54518L,54519L,54520L,54521L,54522L,54523L,54524L,
97537 54525L,54526L,54527L,54528L,54529L,54530L,54531L,54532L,54533L,54534L,
97538 54535L,54536L,54537L,54538L,54539L,54540L,54541L,54542L,54543L,54544L,
97539 54545L,54546L,54547L,54548L,54549L,54550L,54551L,54552L,54553L,54554L,
97540 54555L,54556L,54557L,54558L,54559L,54560L,54561L,54562L,54563L,54564L,
97541 54565L,54566L,54567L,54568L,54569L,54570L,54571L,54572L,54573L,54574L,
97542 54575L,54576L,54577L,54578L,54579L,54580L,54581L,54582L,54583L,54584L,
97543 54585L,54586L,54587L,54588L,54589L,54590L,54591L,54592L,54593L,54594L,
97544 54595L,54596L,54597L,54598L,54599L,54600L,54601L,54602L,54603L,54604L,
97545 54605L,54606L,54607L,54608L,54609L,54610L,54611L,54612L,54613L,54614L,
97546 54615L,54616L,54617L,54618L,54619L,54620L,54621L,54622L,54623L,54624L,
97547 54625L,54626L,54627L,54628L,54629L,54630L,54631L,54632L,54633L,54634L,
97548 54635L,54636L,54637L,54638L,54639L,54640L,54641L,54642L,54643L,54644L,
97549 54645L,54646L,54647L,54648L,54649L,54650L,54651L,54652L,54653L,54654L,
97550 54655L,54656L,54657L,54658L,54659L,54660L,54661L,54662L,54663L,54664L,
97551 54665L,54666L,54667L,54668L,54669L,54670L,54671L,54672L,54673L,54674L,
97552 54675L,54676L,54677L,54678L,54679L,54680L,54681L,54682L,54683L,54684L,
97553 54685L,54686L,54687L,54688L,54689L,54690L,54691L,54692L,54693L,54694L,
97554 54695L,54696L,54697L,54698L,54699L,54700L,54701L,54702L,54703L,54704L,
97555 54705L,54706L,54707L,54708L,54709L,54710L,54711L,54712L,54713L,54714L,
97556 54715L,54716L,54717L,54718L,54719L,54720L,54721L,54722L,54723L,54724L,
97557 54725L,54726L,54727L,54728L,54729L,54730L,54731L,54732L,54733L,54734L,
97558 54735L,54736L,54737L,54738L,54739L,54740L,54741L,54742L,54743L,54744L,
97559 54745L,54746L,54747L,54748L,54749L,54750L,54751L,54752L,54753L,54754L,
97560 54755L,54756L,54757L,54758L,54759L,54760L,54761L,54762L,54763L,54764L,
97561 54765L,54766L,54767L,54768L,54769L,54770L,54771L,54772L,54773L,54774L,
97562 54775L,54776L,54777L,54778L,54779L,54780L,54781L,54782L,54783L,54784L,
97563 54785L,54786L,54787L,54788L,54789L,54790L,54791L,54792L,54793L,54794L,
97564 54795L,54796L,54797L,54798L,54799L,54800L,54801L,54802L,54803L,54804L,
97565 54805L,54806L,54807L,54808L,54809L,54810L,54811L,54812L,54813L,54814L,
97566 54815L,54816L,54817L,54818L,54819L,54820L,54821L,54822L,54823L,54824L,
97567 54825L,54826L,54827L,54828L,54829L,54830L,54831L,54832L,54833L,54834L,
97568 54835L,54836L,54837L,54838L,54839L,54840L,54841L,54842L,54843L,54844L,
97569 54845L,54846L,54847L,54848L,54849L,54850L,54851L,54852L,54853L,54854L,
97570 54855L,54856L,54857L,54858L,54859L,54860L,54861L,54862L,54863L,54864L,
97571 54865L,54866L,54867L,54868L,54869L,54870L,54871L,54872L,54873L,54874L,
97572 54875L,54876L,54877L,54878L,54879L,54880L,54881L,54882L,54883L,54884L,
97573 54885L,54886L,54887L,54888L,54889L,54890L,54891L,54892L,54893L,54894L,
97574 54895L,54896L,54897L,54898L,54899L,54900L,54901L,54902L,54903L,54904L,
97575 54905L,54906L,54907L,54908L,54909L,54910L,54911L,54912L,54913L,54914L,
97576 54915L,54916L,54917L,54918L,54919L,54920L,54921L,54922L,54923L,54924L,
97577 54925L,54926L,54927L,54928L,54929L,54930L,54931L,54932L,54933L,54934L,
97578 54935L,54936L,54937L,54938L,54939L,54940L,54941L,54942L,54943L,54944L,
97579 54945L,54946L,54947L,54948L,54949L,54950L,54951L,54952L,54953L,54954L,
97580 54955L,54956L,54957L,54958L,54959L,54960L,54961L,54962L,54963L,54964L,
97581 54965L,54966L,54967L,54968L,54969L,54970L,54971L,54972L,54973L,54974L,
97582 54975L,54976L,54977L,54978L,54979L,54980L,54981L,54982L,54983L,54984L,
97583 54985L,54986L,54987L,54988L,54989L,54990L,54991L,54992L,54993L,54994L,
97584 54995L,54996L,54997L,54998L,54999L,55000L,55001L,55002L,55003L,55004L,
97585 55005L,55006L,55007L,55008L,55009L,55010L,55011L,55012L,55013L,55014L,
97586 55015L,55016L,55017L,55018L,55019L,55020L,55021L,55022L,55023L,55024L,
97587 55025L,55026L,55027L,55028L,55029L,55030L,55031L,55032L,55033L,55034L,
97588 55035L,55036L,55037L,55038L,55039L,55040L,55041L,55042L,55043L,55044L,
97589 55045L,55046L,55047L,55048L,55049L,55050L,55051L,55052L,55053L,55054L,
97590 55055L,55056L,55057L,55058L,55059L,55060L,55061L,55062L,55063L,55064L,
97591 55065L,55066L,55067L,55068L,55069L,55070L,55071L,55072L,55073L,55074L,
97592 55075L,55076L,55077L,55078L,55079L,55080L,55081L,55082L,55083L,55084L,
97593 55085L,55086L,55087L,55088L,55089L,55090L,55091L,55092L,55093L,55094L,
97594 55095L,55096L,55097L,55098L,55099L,55100L,55101L,55102L,55103L,55104L,
97595 55105L,55106L,55107L,55108L,55109L,55110L,55111L,55112L,55113L,55114L,
97596 55115L,55116L,55117L,55118L,55119L,55120L,55121L,55122L,55123L,55124L,
97597 55125L,55126L,55127L,55128L,55129L,55130L,55131L,55132L,55133L,55134L,
97598 55135L,55136L,55137L,55138L,55139L,55140L,55141L,55142L,55143L,55144L,
97599 55145L,55146L,55147L,55148L,55149L,55150L,55151L,55152L,55153L,55154L,
97600 55155L,55156L,55157L,55158L,55159L,55160L,55161L,55162L,55163L,55164L,
97601 55165L,55166L,55167L,55168L,55169L,55170L,55171L,55172L,55173L,55174L,
97602 55175L,55176L,55177L,55178L,55179L,55180L,55181L,55182L,55183L,55184L,
97603 55185L,55186L,55187L,55188L,55189L,55190L,55191L,55192L,55193L,55194L,
97604 55195L,55196L,55197L,55198L,55199L,55200L,55201L,55202L,55203L,55204L,
97605 55205L,55206L,55207L,55208L,55209L,55210L,55211L,55212L,55213L,55214L,
97606 55215L,55216L,55217L,55218L,55219L,55220L,55221L,55222L,55223L,55224L,
97607 55225L,55226L,55227L,55228L,55229L,55230L,55231L,55232L,55233L,55234L,
97608 55235L,55236L,55237L,55238L,55239L,55240L,55241L,55242L,55243L,55244L,
97609 55245L,55246L,55247L,55248L,55249L,55250L,55251L,55252L,55253L,55254L,
97610 55255L,55256L,55257L,55258L,55259L,55260L,55261L,55262L,55263L,55264L,
97611 55265L,55266L,55267L,55268L,55269L,55270L,55271L,55272L,55273L,55274L,
97612 55275L,55276L,55277L,55278L,55279L,55280L,55281L,55282L,55283L,55284L,
97613 55285L,55286L,55287L,55288L,55289L,55290L,55291L,55292L,55293L,55294L,
97614 55295L,55296L,55297L,55298L,55299L,55300L,55301L,55302L,55303L,55304L,
97615 55305L,55306L,55307L,55308L,55309L,55310L,55311L,55312L,55313L,55314L,
97616 55315L,55316L,55317L,55318L,55319L,55320L,55321L,55322L,55323L,55324L,
97617 55325L,55326L,55327L,55328L,55329L,55330L,55331L,55332L,55333L,55334L,
97618 55335L,55336L,55337L,55338L,55339L,55340L,55341L,55342L,55343L,55344L,
97619 55345L,55346L,55347L,55348L,55349L,55350L,55351L,55352L,55353L,55354L,
97620 55355L,55356L,55357L,55358L,55359L,55360L,55361L,55362L,55363L,55364L,
97621 55365L,55366L,55367L,55368L,55369L,55370L,55371L,55372L,55373L,55374L,
97622 55375L,55376L,55377L,55378L,55379L,55380L,55381L,55382L,55383L,55384L,
97623 55385L,55386L,55387L,55388L,55389L,55390L,55391L,55392L,55393L,55394L,
97624 55395L,55396L,55397L,55398L,55399L,55400L,55401L,55402L,55403L,55404L,
97625 55405L,55406L,55407L,55408L,55409L,55410L,55411L,55412L,55413L,55414L,
97626 55415L,55416L,55417L,55418L,55419L,55420L,55421L,55422L,55423L,55424L,
97627 55425L,55426L,55427L,55428L,55429L,55430L,55431L,55432L,55433L,55434L,
97628 55435L,55436L,55437L,55438L,55439L,55440L,55441L,55442L,55443L,55444L,
97629 55445L,55446L,55447L,55448L,55449L,55450L,55451L,55452L,55453L,55454L,
97630 55455L,55456L,55457L,55458L,55459L,55460L,55461L,55462L,55463L,55464L,
97631 55465L,55466L,55467L,55468L,55469L,55470L,55471L,55472L,55473L,55474L,
97632 55475L,55476L,55477L,55478L,55479L,55480L,55481L,55482L,55483L,55484L,
97633 55485L,55486L,55487L,55488L,55489L,55490L,55491L,55492L,55493L,55494L,
97634 55495L,55496L,55497L,55498L,55499L,55500L,55501L,55502L,55503L,55504L,
97635 55505L,55506L,55507L,55508L,55509L,55510L,55511L,55512L,55513L,55514L,
97636 55515L,55516L,55517L,55518L,55519L,55520L,55521L,55522L,55523L,55524L,
97637 55525L,55526L,55527L,55528L,55529L,55530L,55531L,55532L,55533L,55534L,
97638 55535L,55536L,55537L,55538L,55539L,55540L,55541L,55542L,55543L,55544L,
97639 55545L,55546L,55547L,55548L,55549L,55550L,55551L,55552L,55553L,55554L,
97640 55555L,55556L,55557L,55558L,55559L,55560L,55561L,55562L,55563L,55564L,
97641 55565L,55566L,55567L,55568L,55569L,55570L,55571L,55572L,55573L,55574L,
97642 55575L,55576L,55577L,55578L,55579L,55580L,55581L,55582L,55583L,55584L,
97643 55585L,55586L,55587L,55588L,55589L,55590L,55591L,55592L,55593L,55594L,
97644 55595L,55596L,55597L,55598L,55599L,55600L,55601L,55602L,55603L,55604L,
97645 55605L,55606L,55607L,55608L,55609L,55610L,55611L,55612L,55613L,55614L,
97646 55615L,55616L,55617L,55618L,55619L,55620L,55621L,55622L,55623L,55624L,
97647 55625L,55626L,55627L,55628L,55629L,55630L,55631L,55632L,55633L,55634L,
97648 55635L,55636L,55637L,55638L,55639L,55640L,55641L,55642L,55643L,55644L,
97649 55645L,55646L,55647L,55648L,55649L,55650L,55651L,55652L,55653L,55654L,
97650 55655L,55656L,55657L,55658L,55659L,55660L,55661L,55662L,55663L,55664L,
97651 55665L,55666L,55667L,55668L,55669L,55670L,55671L,55672L,55673L,55674L,
97652 55675L,55676L,55677L,55678L,55679L,55680L,55681L,55682L,55683L,55684L,
97653 55685L,55686L,55687L,55688L,55689L,55690L,55691L,55692L,55693L,55694L,
97654 55695L,55696L,55697L,55698L,55699L,55700L,55701L,55702L,55703L,55704L,
97655 55705L,55706L,55707L,55708L,55709L,55710L,55711L,55712L,55713L,55714L,
97656 55715L,55716L,55717L,55718L,55719L,55720L,55721L,55722L,55723L,55724L,
97657 55725L,55726L,55727L,55728L,55729L,55730L,55731L,55732L,55733L,55734L,
97658 55735L,55736L,55737L,55738L,55739L,55740L,55741L,55742L,55743L,55744L,
97659 55745L,55746L,55747L,55748L,55749L,55750L,55751L,55752L,55753L,55754L,
97660 55755L,55756L,55757L,55758L,55759L,55760L,55761L,55762L,55763L,55764L,
97661 55765L,55766L,55767L,55768L,55769L,55770L,55771L,55772L,55773L,55774L,
97662 55775L,55776L,55777L,55778L,55779L,55780L,55781L,55782L,55783L,55784L,
97663 55785L,55786L,55787L,55788L,55789L,55790L,55791L,55792L,55793L,55794L,
97664 55795L,55796L,55797L,55798L,55799L,55800L,55801L,55802L,55803L,55804L,
97665 55805L,55806L,55807L,55808L,55809L,55810L,55811L,55812L,55813L,55814L,
97666 55815L,55816L,55817L,55818L,55819L,55820L,55821L,55822L,55823L,55824L,
97667 55825L,55826L,55827L,55828L,55829L,55830L,55831L,55832L,55833L,55834L,
97668 55835L,55836L,55837L,55838L,55839L,55840L,55841L,55842L,55843L,55844L,
97669 55845L,55846L,55847L,55848L,55849L,55850L,55851L,55852L,55853L,55854L,
97670 55855L,55856L,55857L,55858L,55859L,55860L,55861L,55862L,55863L,55864L,
97671 55865L,55866L,55867L,55868L,55869L,55870L,55871L,55872L,55873L,55874L,
97672 55875L,55876L,55877L,55878L,55879L,55880L,55881L,55882L,55883L,55884L,
97673 55885L,55886L,55887L,55888L,55889L,55890L,55891L,55892L,55893L,55894L,
97674 55895L,55896L,55897L,55898L,55899L,55900L,55901L,55902L,55903L,55904L,
97675 55905L,55906L,55907L,55908L,55909L,55910L,55911L,55912L,55913L,55914L,
97676 55915L,55916L,55917L,55918L,55919L,55920L,55921L,55922L,55923L,55924L,
97677 55925L,55926L,55927L,55928L,55929L,55930L,55931L,55932L,55933L,55934L,
97678 55935L,55936L,55937L,55938L,55939L,55940L,55941L,55942L,55943L,55944L,
97679 55945L,55946L,55947L,55948L,55949L,55950L,55951L,55952L,55953L,55954L,
97680 55955L,55956L,55957L,55958L,55959L,55960L,55961L,55962L,55963L,55964L,
97681 55965L,55966L,55967L,55968L,55969L,55970L,55971L,55972L,55973L,55974L,
97682 55975L,55976L,55977L,55978L,55979L,55980L,55981L,55982L,55983L,55984L,
97683 55985L,55986L,55987L,55988L,55989L,55990L,55991L,55992L,55993L,55994L,
97684 55995L,55996L,55997L,55998L,55999L,56000L,56001L,56002L,56003L,56004L,
97685 56005L,56006L,56007L,56008L,56009L,56010L,56011L,56012L,56013L,56014L,
97686 56015L,56016L,56017L,56018L,56019L,56020L,56021L,56022L,56023L,56024L,
97687 56025L,56026L,56027L,56028L,56029L,56030L,56031L,56032L,56033L,56034L,
97688 56035L,56036L,56037L,56038L,56039L,56040L,56041L,56042L,56043L,56044L,
97689 56045L,56046L,56047L,56048L,56049L,56050L,56051L,56052L,56053L,56054L,
97690 56055L,56056L,56057L,56058L,56059L,56060L,56061L,56062L,56063L,56064L,
97691 56065L,56066L,56067L,56068L,56069L,56070L,56071L,56072L,56073L,56074L,
97692 56075L,56076L,56077L,56078L,56079L,56080L,56081L,56082L,56083L,56084L,
97693 56085L,56086L,56087L,56088L,56089L,56090L,56091L,56092L,56093L,56094L,
97694 56095L,56096L,56097L,56098L,56099L,56100L,56101L,56102L,56103L,56104L,
97695 56105L,56106L,56107L,56108L,56109L,56110L,56111L,56112L,56113L,56114L,
97696 56115L,56116L,56117L,56118L,56119L,56120L,56121L,56122L,56123L,56124L,
97697 56125L,56126L,56127L,56128L,56129L,56130L,56131L,56132L,56133L,56134L,
97698 56135L,56136L,56137L,56138L,56139L,56140L,56141L,56142L,56143L,56144L,
97699 56145L,56146L,56147L,56148L,56149L,56150L,56151L,56152L,56153L,56154L,
97700 56155L,56156L,56157L,56158L,56159L,56160L,56161L,56162L,56163L,56164L,
97701 56165L,56166L,56167L,56168L,56169L,56170L,56171L,56172L,56173L,56174L,
97702 56175L,56176L,56177L,56178L,56179L,56180L,56181L,56182L,56183L,56184L,
97703 56185L,56186L,56187L,56188L,56189L,56190L,56191L,56192L,56193L,56194L,
97704 56195L,56196L,56197L,56198L,56199L,56200L,56201L,56202L,56203L,56204L,
97705 56205L,56206L,56207L,56208L,56209L,56210L,56211L,56212L,56213L,56214L,
97706 56215L,56216L,56217L,56218L,56219L,56220L,56221L,56222L,56223L,56224L,
97707 56225L,56226L,56227L,56228L,56229L,56230L,56231L,56232L,56233L,56234L,
97708 56235L,56236L,56237L,56238L,56239L,56240L,56241L,56242L,56243L,56244L,
97709 56245L,56246L,56247L,56248L,56249L,56250L,56251L,56252L,56253L,56254L,
97710 56255L,56256L,56257L,56258L,56259L,56260L,56261L,56262L,56263L,56264L,
97711 56265L,56266L,56267L,56268L,56269L,56270L,56271L,56272L,56273L,56274L,
97712 56275L,56276L,56277L,56278L,56279L,56280L,56281L,56282L,56283L,56284L,
97713 56285L,56286L,56287L,56288L,56289L,56290L,56291L,56292L,56293L,56294L,
97714 56295L,56296L,56297L,56298L,56299L,56300L,56301L,56302L,56303L,56304L,
97715 56305L,56306L,56307L,56308L,56309L,56310L,56311L,56312L,56313L,56314L,
97716 56315L,56316L,56317L,56318L,56319L,56320L,56321L,56322L,56323L,56324L,
97717 56325L,56326L,56327L,56328L,56329L,56330L,56331L,56332L,56333L,56334L,
97718 56335L,56336L,56337L,56338L,56339L,56340L,56341L,56342L,56343L,56344L,
97719 56345L,56346L,56347L,56348L,56349L,56350L,56351L,56352L,56353L,56354L,
97720 56355L,56356L,56357L,56358L,56359L,56360L,56361L,56362L,56363L,56364L,
97721 56365L,56366L,56367L,56368L,56369L,56370L,56371L,56372L,56373L,56374L,
97722 56375L,56376L,56377L,56378L,56379L,56380L,56381L,56382L,56383L,56384L,
97723 56385L,56386L,56387L,56388L,56389L,56390L,56391L,56392L,56393L,56394L,
97724 56395L,56396L,56397L,56398L,56399L,56400L,56401L,56402L,56403L,56404L,
97725 56405L,56406L,56407L,56408L,56409L,56410L,56411L,56412L,56413L,56414L,
97726 56415L,56416L,56417L,56418L,56419L,56420L,56421L,56422L,56423L,56424L,
97727 56425L,56426L,56427L,56428L,56429L,56430L,56431L,56432L,56433L,56434L,
97728 56435L,56436L,56437L,56438L,56439L,56440L,56441L,56442L,56443L,56444L,
97729 56445L,56446L,56447L,56448L,56449L,56450L,56451L,56452L,56453L,56454L,
97730 56455L,56456L,56457L,56458L,56459L,56460L,56461L,56462L,56463L,56464L,
97731 56465L,56466L,56467L,56468L,56469L,56470L,56471L,56472L,56473L,56474L,
97732 56475L,56476L,56477L,56478L,56479L,56480L,56481L,56482L,56483L,56484L,
97733 56485L,56486L,56487L,56488L,56489L,56490L,56491L,56492L,56493L,56494L,
97734 56495L,56496L,56497L,56498L,56499L,56500L,56501L,56502L,56503L,56504L,
97735 56505L,56506L,56507L,56508L,56509L,56510L,56511L,56512L,56513L,56514L,
97736 56515L,56516L,56517L,56518L,56519L,56520L,56521L,56522L,56523L,56524L,
97737 56525L,56526L,56527L,56528L,56529L,56530L,56531L,56532L,56533L,56534L,
97738 56535L,56536L,56537L,56538L,56539L,56540L,56541L,56542L,56543L,56544L,
97739 56545L,56546L,56547L,56548L,56549L,56550L,56551L,56552L,56553L,56554L,
97740 56555L,56556L,56557L,56558L,56559L,56560L,56561L,56562L,56563L,56564L,
97741 56565L,56566L,56567L,56568L,56569L,56570L,56571L,56572L,56573L,56574L,
97742 56575L,56576L,56577L,56578L,56579L,56580L,56581L,56582L,56583L,56584L,
97743 56585L,56586L,56587L,56588L,56589L,56590L,56591L,56592L,56593L,56594L,
97744 56595L,56596L,56597L,56598L,56599L,56600L,56601L,56602L,56603L,56604L,
97745 56605L,56606L,56607L,56608L,56609L,56610L,56611L,56612L,56613L,56614L,
97746 56615L,56616L,56617L,56618L,56619L,56620L,56621L,56622L,56623L,56624L,
97747 56625L,56626L,56627L,56628L,56629L,56630L,56631L,56632L,56633L,56634L,
97748 56635L,56636L,56637L,56638L,56639L,56640L,56641L,56642L,56643L,56644L,
97749 56645L,56646L,56647L,56648L,56649L,56650L,56651L,56652L,56653L,56654L,
97750 56655L,56656L,56657L,56658L,56659L,56660L,56661L,56662L,56663L,56664L,
97751 56665L,56666L,56667L,56668L,56669L,56670L,56671L,56672L,56673L,56674L,
97752 56675L,56676L,56677L,56678L,56679L,56680L,56681L,56682L,56683L,56684L,
97753 56685L,56686L,56687L,56688L,56689L,56690L,56691L,56692L,56693L,56694L,
97754 56695L,56696L,56697L,56698L,56699L,56700L,56701L,56702L,56703L,56704L,
97755 56705L,56706L,56707L,56708L,56709L,56710L,56711L,56712L,56713L,56714L,
97756 56715L,56716L,56717L,56718L,56719L,56720L,56721L,56722L,56723L,56724L,
97757 56725L,56726L,56727L,56728L,56729L,56730L,56731L,56732L,56733L,56734L,
97758 56735L,56736L,56737L,56738L,56739L,56740L,56741L,56742L,56743L,56744L,
97759 56745L,56746L,56747L,56748L,56749L,56750L,56751L,56752L,56753L,56754L,
97760 56755L,56756L,56757L,56758L,56759L,56760L,56761L,56762L,56763L,56764L,
97761 56765L,56766L,56767L,56768L,56769L,56770L,56771L,56772L,56773L,56774L,
97762 56775L,56776L,56777L,56778L,56779L,56780L,56781L,56782L,56783L,56784L,
97763 56785L,56786L,56787L,56788L,56789L,56790L,56791L,56792L,56793L,56794L,
97764 56795L,56796L,56797L,56798L,56799L,56800L,56801L,56802L,56803L,56804L,
97765 56805L,56806L,56807L,56808L,56809L,56810L,56811L,56812L,56813L,56814L,
97766 56815L,56816L,56817L,56818L,56819L,56820L,56821L,56822L,56823L,56824L,
97767 56825L,56826L,56827L,56828L,56829L,56830L,56831L,56832L,56833L,56834L,
97768 56835L,56836L,56837L,56838L,56839L,56840L,56841L,56842L,56843L,56844L,
97769 56845L,56846L,56847L,56848L,56849L,56850L,56851L,56852L,56853L,56854L,
97770 56855L,56856L,56857L,56858L,56859L,56860L,56861L,56862L,56863L,56864L,
97771 56865L,56866L,56867L,56868L,56869L,56870L,56871L,56872L,56873L,56874L,
97772 56875L,56876L,56877L,56878L,56879L,56880L,56881L,56882L,56883L,56884L,
97773 56885L,56886L,56887L,56888L,56889L,56890L,56891L,56892L,56893L,56894L,
97774 56895L,56896L,56897L,56898L,56899L,56900L,56901L,56902L,56903L,56904L,
97775 56905L,56906L,56907L,56908L,56909L,56910L,56911L,56912L,56913L,56914L,
97776 56915L,56916L,56917L,56918L,56919L,56920L,56921L,56922L,56923L,56924L,
97777 56925L,56926L,56927L,56928L,56929L,56930L,56931L,56932L,56933L,56934L,
97778 56935L,56936L,56937L,56938L,56939L,56940L,56941L,56942L,56943L,56944L,
97779 56945L,56946L,56947L,56948L,56949L,56950L,56951L,56952L,56953L,56954L,
97780 56955L,56956L,56957L,56958L,56959L,56960L,56961L,56962L,56963L,56964L,
97781 56965L,56966L,56967L,56968L,56969L,56970L,56971L,56972L,56973L,56974L,
97782 56975L,56976L,56977L,56978L,56979L,56980L,56981L,56982L,56983L,56984L,
97783 56985L,56986L,56987L,56988L,56989L,56990L,56991L,56992L,56993L,56994L,
97784 56995L,56996L,56997L,56998L,56999L,57000L,57001L,57002L,57003L,57004L,
97785 57005L,57006L,57007L,57008L,57009L,57010L,57011L,57012L,57013L,57014L,
97786 57015L,57016L,57017L,57018L,57019L,57020L,57021L,57022L,57023L,57024L,
97787 57025L,57026L,57027L,57028L,57029L,57030L,57031L,57032L,57033L,57034L,
97788 57035L,57036L,57037L,57038L,57039L,57040L,57041L,57042L,57043L,57044L,
97789 57045L,57046L,57047L,57048L,57049L,57050L,57051L,57052L,57053L,57054L,
97790 57055L,57056L,57057L,57058L,57059L,57060L,57061L,57062L,57063L,57064L,
97791 57065L,57066L,57067L,57068L,57069L,57070L,57071L,57072L,57073L,57074L,
97792 57075L,57076L,57077L,57078L,57079L,57080L,57081L,57082L,57083L,57084L,
97793 57085L,57086L,57087L,57088L,57089L,57090L,57091L,57092L,57093L,57094L,
97794 57095L,57096L,57097L,57098L,57099L,57100L,57101L,57102L,57103L,57104L,
97795 57105L,57106L,57107L,57108L,57109L,57110L,57111L,57112L,57113L,57114L,
97796 57115L,57116L,57117L,57118L,57119L,57120L,57121L,57122L,57123L,57124L,
97797 57125L,57126L,57127L,57128L,57129L,57130L,57131L,57132L,57133L,57134L,
97798 57135L,57136L,57137L,57138L,57139L,57140L,57141L,57142L,57143L,57144L,
97799 57145L,57146L,57147L,57148L,57149L,57150L,57151L,57152L,57153L,57154L,
97800 57155L,57156L,57157L,57158L,57159L,57160L,57161L,57162L,57163L,57164L,
97801 57165L,57166L,57167L,57168L,57169L,57170L,57171L,57172L,57173L,57174L,
97802 57175L,57176L,57177L,57178L,57179L,57180L,57181L,57182L,57183L,57184L,
97803 57185L,57186L,57187L,57188L,57189L,57190L,57191L,57192L,57193L,57194L,
97804 57195L,57196L,57197L,57198L,57199L,57200L,57201L,57202L,57203L,57204L,
97805 57205L,57206L,57207L,57208L,57209L,57210L,57211L,57212L,57213L,57214L,
97806 57215L,57216L,57217L,57218L,57219L,57220L,57221L,57222L,57223L,57224L,
97807 57225L,57226L,57227L,57228L,57229L,57230L,57231L,57232L,57233L,57234L,
97808 57235L,57236L,57237L,57238L,57239L,57240L,57241L,57242L,57243L,57244L,
97809 57245L,57246L,57247L,57248L,57249L,57250L,57251L,57252L,57253L,57254L,
97810 57255L,57256L,57257L,57258L,57259L,57260L,57261L,57262L,57263L,57264L,
97811 57265L,57266L,57267L,57268L,57269L,57270L,57271L,57272L,57273L,57274L,
97812 57275L,57276L,57277L,57278L,57279L,57280L,57281L,57282L,57283L,57284L,
97813 57285L,57286L,57287L,57288L,57289L,57290L,57291L,57292L,57293L,57294L,
97814 57295L,57296L,57297L,57298L,57299L,57300L,57301L,57302L,57303L,57304L,
97815 57305L,57306L,57307L,57308L,57309L,57310L,57311L,57312L,57313L,57314L,
97816 57315L,57316L,57317L,57318L,57319L,57320L,57321L,57322L,57323L,57324L,
97817 57325L,57326L,57327L,57328L,57329L,57330L,57331L,57332L,57333L,57334L,
97818 57335L,57336L,57337L,57338L,57339L,57340L,57341L,57342L,57343L,57344L,
97819 57345L,57346L,57347L,57348L,57349L,57350L,57351L,57352L,57353L,57354L,
97820 57355L,57356L,57357L,57358L,57359L,57360L,57361L,57362L,57363L,57364L,
97821 57365L,57366L,57367L,57368L,57369L,57370L,57371L,57372L,57373L,57374L,
97822 57375L,57376L,57377L,57378L,57379L,57380L,57381L,57382L,57383L,57384L,
97823 57385L,57386L,57387L,57388L,57389L,57390L,57391L,57392L,57393L,57394L,
97824 57395L,57396L,57397L,57398L,57399L,57400L,57401L,57402L,57403L,57404L,
97825 57405L,57406L,57407L,57408L,57409L,57410L,57411L,57412L,57413L,57414L,
97826 57415L,57416L,57417L,57418L,57419L,57420L,57421L,57422L,57423L,57424L,
97827 57425L,57426L,57427L,57428L,57429L,57430L,57431L,57432L,57433L,57434L,
97828 57435L,57436L,57437L,57438L,57439L,57440L,57441L,57442L,57443L,57444L,
97829 57445L,57446L,57447L,57448L,57449L,57450L,57451L,57452L,57453L,57454L,
97830 57455L,57456L,57457L,57458L,57459L,57460L,57461L,57462L,57463L,57464L,
97831 57465L,57466L,57467L,57468L,57469L,57470L,57471L,57472L,57473L,57474L,
97832 57475L,57476L,57477L,57478L,57479L,57480L,57481L,57482L,57483L,57484L,
97833 57485L,57486L,57487L,57488L,57489L,57490L,57491L,57492L,57493L,57494L,
97834 57495L,57496L,57497L,57498L,57499L,57500L,57501L,57502L,57503L,57504L,
97835 57505L,57506L,57507L,57508L,57509L,57510L,57511L,57512L,57513L,57514L,
97836 57515L,57516L,57517L,57518L,57519L,57520L,57521L,57522L,57523L,57524L,
97837 57525L,57526L,57527L,57528L,57529L,57530L,57531L,57532L,57533L,57534L,
97838 57535L,57536L,57537L,57538L,57539L,57540L,57541L,57542L,57543L,57544L,
97839 57545L,57546L,57547L,57548L,57549L,57550L,57551L,57552L,57553L,57554L,
97840 57555L,57556L,57557L,57558L,57559L,57560L,57561L,57562L,57563L,57564L,
97841 57565L,57566L,57567L,57568L,57569L,57570L,57571L,57572L,57573L,57574L,
97842 57575L,57576L,57577L,57578L,57579L,57580L,57581L,57582L,57583L,57584L,
97843 57585L,57586L,57587L,57588L,57589L,57590L,57591L,57592L,57593L,57594L,
97844 57595L,57596L,57597L,57598L,57599L,57600L,57601L,57602L,57603L,57604L,
97845 57605L,57606L,57607L,57608L,57609L,57610L,57611L,57612L,57613L,57614L,
97846 57615L,57616L,57617L,57618L,57619L,57620L,57621L,57622L,57623L,57624L,
97847 57625L,57626L,57627L,57628L,57629L,57630L,57631L,57632L,57633L,57634L,
97848 57635L,57636L,57637L,57638L,57639L,57640L,57641L,57642L,57643L,57644L,
97849 57645L,57646L,57647L,57648L,57649L,57650L,57651L,57652L,57653L,57654L,
97850 57655L,57656L,57657L,57658L,57659L,57660L,57661L,57662L,57663L,57664L,
97851 57665L,57666L,57667L,57668L,57669L,57670L,57671L,57672L,57673L,57674L,
97852 57675L,57676L,57677L,57678L,57679L,57680L,57681L,57682L,57683L,57684L,
97853 57685L,57686L,57687L,57688L,57689L,57690L,57691L,57692L,57693L,57694L,
97854 57695L,57696L,57697L,57698L,57699L,57700L,57701L,57702L,57703L,57704L,
97855 57705L,57706L,57707L,57708L,57709L,57710L,57711L,57712L,57713L,57714L,
97856 57715L,57716L,57717L,57718L,57719L,57720L,57721L,57722L,57723L,57724L,
97857 57725L,57726L,57727L,57728L,57729L,57730L,57731L,57732L,57733L,57734L,
97858 57735L,57736L,57737L,57738L,57739L,57740L,57741L,57742L,57743L,57744L,
97859 57745L,57746L,57747L,57748L,57749L,57750L,57751L,57752L,57753L,57754L,
97860 57755L,57756L,57757L,57758L,57759L,57760L,57761L,57762L,57763L,57764L,
97861 57765L,57766L,57767L,57768L,57769L,57770L,57771L,57772L,57773L,57774L,
97862 57775L,57776L,57777L,57778L,57779L,57780L,57781L,57782L,57783L,57784L,
97863 57785L,57786L,57787L,57788L,57789L,57790L,57791L,57792L,57793L,57794L,
97864 57795L,57796L,57797L,57798L,57799L,57800L,57801L,57802L,57803L,57804L,
97865 57805L,57806L,57807L,57808L,57809L,57810L,57811L,57812L,57813L,57814L,
97866 57815L,57816L,57817L,57818L,57819L,57820L,57821L,57822L,57823L,57824L,
97867 57825L,57826L,57827L,57828L,57829L,57830L,57831L,57832L,57833L,57834L,
97868 57835L,57836L,57837L,57838L,57839L,57840L,57841L,57842L,57843L,57844L,
97869 57845L,57846L,57847L,57848L,57849L,57850L,57851L,57852L,57853L,57854L,
97870 57855L,57856L,57857L,57858L,57859L,57860L,57861L,57862L,57863L,57864L,
97871 57865L,57866L,57867L,57868L,57869L,57870L,57871L,57872L,57873L,57874L,
97872 57875L,57876L,57877L,57878L,57879L,57880L,57881L,57882L,57883L,57884L,
97873 57885L,57886L,57887L,57888L,57889L,57890L,57891L,57892L,57893L,57894L,
97874 57895L,57896L,57897L,57898L,57899L,57900L,57901L,57902L,57903L,57904L,
97875 57905L,57906L,57907L,57908L,57909L,57910L,57911L,57912L,57913L,57914L,
97876 57915L,57916L,57917L,57918L,57919L,57920L,57921L,57922L,57923L,57924L,
97877 57925L,57926L,57927L,57928L,57929L,57930L,57931L,57932L,57933L,57934L,
97878 57935L,57936L,57937L,57938L,57939L,57940L,57941L,57942L,57943L,57944L,
97879 57945L,57946L,57947L,57948L,57949L,57950L,57951L,57952L,57953L,57954L,
97880 57955L,57956L,57957L,57958L,57959L,57960L,57961L,57962L,57963L,57964L,
97881 57965L,57966L,57967L,57968L,57969L,57970L,57971L,57972L,57973L,57974L,
97882 57975L,57976L,57977L,57978L,57979L,57980L,57981L,57982L,57983L,57984L,
97883 57985L,57986L,57987L,57988L,57989L,57990L,57991L,57992L,57993L,57994L,
97884 57995L,57996L,57997L,57998L,57999L,58000L,58001L,58002L,58003L,58004L,
97885 58005L,58006L,58007L,58008L,58009L,58010L,58011L,58012L,58013L,58014L,
97886 58015L,58016L,58017L,58018L,58019L,58020L,58021L,58022L,58023L,58024L,
97887 58025L,58026L,58027L,58028L,58029L,58030L,58031L,58032L,58033L,58034L,
97888 58035L,58036L,58037L,58038L,58039L,58040L,58041L,58042L,58043L,58044L,
97889 58045L,58046L,58047L,58048L,58049L,58050L,58051L,58052L,58053L,58054L,
97890 58055L,58056L,58057L,58058L,58059L,58060L,58061L,58062L,58063L,58064L,
97891 58065L,58066L,58067L,58068L,58069L,58070L,58071L,58072L,58073L,58074L,
97892 58075L,58076L,58077L,58078L,58079L,58080L,58081L,58082L,58083L,58084L,
97893 58085L,58086L,58087L,58088L,58089L,58090L,58091L,58092L,58093L,58094L,
97894 58095L,58096L,58097L,58098L,58099L,58100L,58101L,58102L,58103L,58104L,
97895 58105L,58106L,58107L,58108L,58109L,58110L,58111L,58112L,58113L,58114L,
97896 58115L,58116L,58117L,58118L,58119L,58120L,58121L,58122L,58123L,58124L,
97897 58125L,58126L,58127L,58128L,58129L,58130L,58131L,58132L,58133L,58134L,
97898 58135L,58136L,58137L,58138L,58139L,58140L,58141L,58142L,58143L,58144L,
97899 58145L,58146L,58147L,58148L,58149L,58150L,58151L,58152L,58153L,58154L,
97900 58155L,58156L,58157L,58158L,58159L,58160L,58161L,58162L,58163L,58164L,
97901 58165L,58166L,58167L,58168L,58169L,58170L,58171L,58172L,58173L,58174L,
97902 58175L,58176L,58177L,58178L,58179L,58180L,58181L,58182L,58183L,58184L,
97903 58185L,58186L,58187L,58188L,58189L,58190L,58191L,58192L,58193L,58194L,
97904 58195L,58196L,58197L,58198L,58199L,58200L,58201L,58202L,58203L,58204L,
97905 58205L,58206L,58207L,58208L,58209L,58210L,58211L,58212L,58213L,58214L,
97906 58215L,58216L,58217L,58218L,58219L,58220L,58221L,58222L,58223L,58224L,
97907 58225L,58226L,58227L,58228L,58229L,58230L,58231L,58232L,58233L,58234L,
97908 58235L,58236L,58237L,58238L,58239L,58240L,58241L,58242L,58243L,58244L,
97909 58245L,58246L,58247L,58248L,58249L,58250L,58251L,58252L,58253L,58254L,
97910 58255L,58256L,58257L,58258L,58259L,58260L,58261L,58262L,58263L,58264L,
97911 58265L,58266L,58267L,58268L,58269L,58270L,58271L,58272L,58273L,58274L,
97912 58275L,58276L,58277L,58278L,58279L,58280L,58281L,58282L,58283L,58284L,
97913 58285L,58286L,58287L,58288L,58289L,58290L,58291L,58292L,58293L,58294L,
97914 58295L,58296L,58297L,58298L,58299L,58300L,58301L,58302L,58303L,58304L,
97915 58305L,58306L,58307L,58308L,58309L,58310L,58311L,58312L,58313L,58314L,
97916 58315L,58316L,58317L,58318L,58319L,58320L,58321L,58322L,58323L,58324L,
97917 58325L,58326L,58327L,58328L,58329L,58330L,58331L,58332L,58333L,58334L,
97918 58335L,58336L,58337L,58338L,58339L,58340L,58341L,58342L,58343L,58344L,
97919 58345L,58346L,58347L,58348L,58349L,58350L,58351L,58352L,58353L,58354L,
97920 58355L,58356L,58357L,58358L,58359L,58360L,58361L,58362L,58363L,58364L,
97921 58365L,58366L,58367L,58368L,58369L,58370L,58371L,58372L,58373L,58374L,
97922 58375L,58376L,58377L,58378L,58379L,58380L,58381L,58382L,58383L,58384L,
97923 58385L,58386L,58387L,58388L,58389L,58390L,58391L,58392L,58393L,58394L,
97924 58395L,58396L,58397L,58398L,58399L,58400L,58401L,58402L,58403L,58404L,
97925 58405L,58406L,58407L,58408L,58409L,58410L,58411L,58412L,58413L,58414L,
97926 58415L,58416L,58417L,58418L,58419L,58420L,58421L,58422L,58423L,58424L,
97927 58425L,58426L,58427L,58428L,58429L,58430L,58431L,58432L,58433L,58434L,
97928 58435L,58436L,58437L,58438L,58439L,58440L,58441L,58442L,58443L,58444L,
97929 58445L,58446L,58447L,58448L,58449L,58450L,58451L,58452L,58453L,58454L,
97930 58455L,58456L,58457L,58458L,58459L,58460L,58461L,58462L,58463L,58464L,
97931 58465L,58466L,58467L,58468L,58469L,58470L,58471L,58472L,58473L,58474L,
97932 58475L,58476L,58477L,58478L,58479L,58480L,58481L,58482L,58483L,58484L,
97933 58485L,58486L,58487L,58488L,58489L,58490L,58491L,58492L,58493L,58494L,
97934 58495L,58496L,58497L,58498L,58499L,58500L,58501L,58502L,58503L,58504L,
97935 58505L,58506L,58507L,58508L,58509L,58510L,58511L,58512L,58513L,58514L,
97936 58515L,58516L,58517L,58518L,58519L,58520L,58521L,58522L,58523L,58524L,
97937 58525L,58526L,58527L,58528L,58529L,58530L,58531L,58532L,58533L,58534L,
97938 58535L,58536L,58537L,58538L,58539L,58540L,58541L,58542L,58543L,58544L,
97939 58545L,58546L,58547L,58548L,58549L,58550L,58551L,58552L,58553L,58554L,
97940 58555L,58556L,58557L,58558L,58559L,58560L,58561L,58562L,58563L,58564L,
97941 58565L,58566L,58567L,58568L,58569L,58570L,58571L,58572L,58573L,58574L,
97942 58575L,58576L,58577L,58578L,58579L,58580L,58581L,58582L,58583L,58584L,
97943 58585L,58586L,58587L,58588L,58589L,58590L,58591L,58592L,58593L,58594L,
97944 58595L,58596L,58597L,58598L,58599L,58600L,58601L,58602L,58603L,58604L,
97945 58605L,58606L,58607L,58608L,58609L,58610L,58611L,58612L,58613L,58614L,
97946 58615L,58616L,58617L,58618L,58619L,58620L,58621L,58622L,58623L,58624L,
97947 58625L,58626L,58627L,58628L,58629L,58630L,58631L,58632L,58633L,58634L,
97948 58635L,58636L,58637L,58638L,58639L,58640L,58641L,58642L,58643L,58644L,
97949 58645L,58646L,58647L,58648L,58649L,58650L,58651L,58652L,58653L,58654L,
97950 58655L,58656L,58657L,58658L,58659L,58660L,58661L,58662L,58663L,58664L,
97951 58665L,58666L,58667L,58668L,58669L,58670L,58671L,58672L,58673L,58674L,
97952 58675L,58676L,58677L,58678L,58679L,58680L,58681L,58682L,58683L,58684L,
97953 58685L,58686L,58687L,58688L,58689L,58690L,58691L,58692L,58693L,58694L,
97954 58695L,58696L,58697L,58698L,58699L,58700L,58701L,58702L,58703L,58704L,
97955 58705L,58706L,58707L,58708L,58709L,58710L,58711L,58712L,58713L,58714L,
97956 58715L,58716L,58717L,58718L,58719L,58720L,58721L,58722L,58723L,58724L,
97957 58725L,58726L,58727L,58728L,58729L,58730L,58731L,58732L,58733L,58734L,
97958 58735L,58736L,58737L,58738L,58739L,58740L,58741L,58742L,58743L,58744L,
97959 58745L,58746L,58747L,58748L,58749L,58750L,58751L,58752L,58753L,58754L,
97960 58755L,58756L,58757L,58758L,58759L,58760L,58761L,58762L,58763L,58764L,
97961 58765L,58766L,58767L,58768L,58769L,58770L,58771L,58772L,58773L,58774L,
97962 58775L,58776L,58777L,58778L,58779L,58780L,58781L,58782L,58783L,58784L,
97963 58785L,58786L,58787L,58788L,58789L,58790L,58791L,58792L,58793L,58794L,
97964 58795L,58796L,58797L,58798L,58799L,58800L,58801L,58802L,58803L,58804L,
97965 58805L,58806L,58807L,58808L,58809L,58810L,58811L,58812L,58813L,58814L,
97966 58815L,58816L,58817L,58818L,58819L,58820L,58821L,58822L,58823L,58824L,
97967 58825L,58826L,58827L,58828L,58829L,58830L,58831L,58832L,58833L,58834L,
97968 58835L,58836L,58837L,58838L,58839L,58840L,58841L,58842L,58843L,58844L,
97969 58845L,58846L,58847L,58848L,58849L,58850L,58851L,58852L,58853L,58854L,
97970 58855L,58856L,58857L,58858L,58859L,58860L,58861L,58862L,58863L,58864L,
97971 58865L,58866L,58867L,58868L,58869L,58870L,58871L,58872L,58873L,58874L,
97972 58875L,58876L,58877L,58878L,58879L,58880L,58881L,58882L,58883L,58884L,
97973 58885L,58886L,58887L,58888L,58889L,58890L,58891L,58892L,58893L,58894L,
97974 58895L,58896L,58897L,58898L,58899L,58900L,58901L,58902L,58903L,58904L,
97975 58905L,58906L,58907L,58908L,58909L,58910L,58911L,58912L,58913L,58914L,
97976 58915L,58916L,58917L,58918L,58919L,58920L,58921L,58922L,58923L,58924L,
97977 58925L,58926L,58927L,58928L,58929L,58930L,58931L,58932L,58933L,58934L,
97978 58935L,58936L,58937L,58938L,58939L,58940L,58941L,58942L,58943L,58944L,
97979 58945L,58946L,58947L,58948L,58949L,58950L,58951L,58952L,58953L,58954L,
97980 58955L,58956L,58957L,58958L,58959L,58960L,58961L,58962L,58963L,58964L,
97981 58965L,58966L,58967L,58968L,58969L,58970L,58971L,58972L,58973L,58974L,
97982 58975L,58976L,58977L,58978L,58979L,58980L,58981L,58982L,58983L,58984L,
97983 58985L,58986L,58987L,58988L,58989L,58990L,58991L,58992L,58993L,58994L,
97984 58995L,58996L,58997L,58998L,58999L,59000L,59001L,59002L,59003L,59004L,
97985 59005L,59006L,59007L,59008L,59009L,59010L,59011L,59012L,59013L,59014L,
97986 59015L,59016L,59017L,59018L,59019L,59020L,59021L,59022L,59023L,59024L,
97987 59025L,59026L,59027L,59028L,59029L,59030L,59031L,59032L,59033L,59034L,
97988 59035L,59036L,59037L,59038L,59039L,59040L,59041L,59042L,59043L,59044L,
97989 59045L,59046L,59047L,59048L,59049L,59050L,59051L,59052L,59053L,59054L,
97990 59055L,59056L,59057L,59058L,59059L,59060L,59061L,59062L,59063L,59064L,
97991 59065L,59066L,59067L,59068L,59069L,59070L,59071L,59072L,59073L,59074L,
97992 59075L,59076L,59077L,59078L,59079L,59080L,59081L,59082L,59083L,59084L,
97993 59085L,59086L,59087L,59088L,59089L,59090L,59091L,59092L,59093L,59094L,
97994 59095L,59096L,59097L,59098L,59099L,59100L,59101L,59102L,59103L,59104L,
97995 59105L,59106L,59107L,59108L,59109L,59110L,59111L,59112L,59113L,59114L,
97996 59115L,59116L,59117L,59118L,59119L,59120L,59121L,59122L,59123L,59124L,
97997 59125L,59126L,59127L,59128L,59129L,59130L,59131L,59132L,59133L,59134L,
97998 59135L,59136L,59137L,59138L,59139L,59140L,59141L,59142L,59143L,59144L,
97999 59145L,59146L,59147L,59148L,59149L,59150L,59151L,59152L,59153L,59154L,
98000 59155L,59156L,59157L,59158L,59159L,59160L,59161L,59162L,59163L,59164L,
98001 59165L,59166L,59167L,59168L,59169L,59170L,59171L,59172L,59173L,59174L,
98002 59175L,59176L,59177L,59178L,59179L,59180L,59181L,59182L,59183L,59184L,
98003 59185L,59186L,59187L,59188L,59189L,59190L,59191L,59192L,59193L,59194L,
98004 59195L,59196L,59197L,59198L,59199L,59200L,59201L,59202L,59203L,59204L,
98005 59205L,59206L,59207L,59208L,59209L,59210L,59211L,59212L,59213L,59214L,
98006 59215L,59216L,59217L,59218L,59219L,59220L,59221L,59222L,59223L,59224L,
98007 59225L,59226L,59227L,59228L,59229L,59230L,59231L,59232L,59233L,59234L,
98008 59235L,59236L,59237L,59238L,59239L,59240L,59241L,59242L,59243L,59244L,
98009 59245L,59246L,59247L,59248L,59249L,59250L,59251L,59252L,59253L,59254L,
98010 59255L,59256L,59257L,59258L,59259L,59260L,59261L,59262L,59263L,59264L,
98011 59265L,59266L,59267L,59268L,59269L,59270L,59271L,59272L,59273L,59274L,
98012 59275L,59276L,59277L,59278L,59279L,59280L,59281L,59282L,59283L,59284L,
98013 59285L,59286L,59287L,59288L,59289L,59290L,59291L,59292L,59293L,59294L,
98014 59295L,59296L,59297L,59298L,59299L,59300L,59301L,59302L,59303L,59304L,
98015 59305L,59306L,59307L,59308L,59309L,59310L,59311L,59312L,59313L,59314L,
98016 59315L,59316L,59317L,59318L,59319L,59320L,59321L,59322L,59323L,59324L,
98017 59325L,59326L,59327L,59328L,59329L,59330L,59331L,59332L,59333L,59334L,
98018 59335L,59336L,59337L,59338L,59339L,59340L,59341L,59342L,59343L,59344L,
98019 59345L,59346L,59347L,59348L,59349L,59350L,59351L,59352L,59353L,59354L,
98020 59355L,59356L,59357L,59358L,59359L,59360L,59361L,59362L,59363L,59364L,
98021 59365L,59366L,59367L,59368L,59369L,59370L,59371L,59372L,59373L,59374L,
98022 59375L,59376L,59377L,59378L,59379L,59380L,59381L,59382L,59383L,59384L,
98023 59385L,59386L,59387L,59388L,59389L,59390L,59391L,59392L,59393L,59394L,
98024 59395L,59396L,59397L,59398L,59399L,59400L,59401L,59402L,59403L,59404L,
98025 59405L,59406L,59407L,59408L,59409L,59410L,59411L,59412L,59413L,59414L,
98026 59415L,59416L,59417L,59418L,59419L,59420L,59421L,59422L,59423L,59424L,
98027 59425L,59426L,59427L,59428L,59429L,59430L,59431L,59432L,59433L,59434L,
98028 59435L,59436L,59437L,59438L,59439L,59440L,59441L,59442L,59443L,59444L,
98029 59445L,59446L,59447L,59448L,59449L,59450L,59451L,59452L,59453L,59454L,
98030 59455L,59456L,59457L,59458L,59459L,59460L,59461L,59462L,59463L,59464L,
98031 59465L,59466L,59467L,59468L,59469L,59470L,59471L,59472L,59473L,59474L,
98032 59475L,59476L,59477L,59478L,59479L,59480L,59481L,59482L,59483L,59484L,
98033 59485L,59486L,59487L,59488L,59489L,59490L,59491L,59492L,59493L,59494L,
98034 59495L,59496L,59497L,59498L,59499L,59500L,59501L,59502L,59503L,59504L,
98035 59505L,59506L,59507L,59508L,59509L,59510L,59511L,59512L,59513L,59514L,
98036 59515L,59516L,59517L,59518L,59519L,59520L,59521L,59522L,59523L,59524L,
98037 59525L,59526L,59527L,59528L,59529L,59530L,59531L,59532L,59533L,59534L,
98038 59535L,59536L,59537L,59538L,59539L,59540L,59541L,59542L,59543L,59544L,
98039 59545L,59546L,59547L,59548L,59549L,59550L,59551L,59552L,59553L,59554L,
98040 59555L,59556L,59557L,59558L,59559L,59560L,59561L,59562L,59563L,59564L,
98041 59565L,59566L,59567L,59568L,59569L,59570L,59571L,59572L,59573L,59574L,
98042 59575L,59576L,59577L,59578L,59579L,59580L,59581L,59582L,59583L,59584L,
98043 59585L,59586L,59587L,59588L,59589L,59590L,59591L,59592L,59593L,59594L,
98044 59595L,59596L,59597L,59598L,59599L,59600L,59601L,59602L,59603L,59604L,
98045 59605L,59606L,59607L,59608L,59609L,59610L,59611L,59612L,59613L,59614L,
98046 59615L,59616L,59617L,59618L,59619L,59620L,59621L,59622L,59623L,59624L,
98047 59625L,59626L,59627L,59628L,59629L,59630L,59631L,59632L,59633L,59634L,
98048 59635L,59636L,59637L,59638L,59639L,59640L,59641L,59642L,59643L,59644L,
98049 59645L,59646L,59647L,59648L,59649L,59650L,59651L,59652L,59653L,59654L,
98050 59655L,59656L,59657L,59658L,59659L,59660L,59661L,59662L,59663L,59664L,
98051 59665L,59666L,59667L,59668L,59669L,59670L,59671L,59672L,59673L,59674L,
98052 59675L,59676L,59677L,59678L,59679L,59680L,59681L,59682L,59683L,59684L,
98053 59685L,59686L,59687L,59688L,59689L,59690L,59691L,59692L,59693L,59694L,
98054 59695L,59696L,59697L,59698L,59699L,59700L,59701L,59702L,59703L,59704L,
98055 59705L,59706L,59707L,59708L,59709L,59710L,59711L,59712L,59713L,59714L,
98056 59715L,59716L,59717L,59718L,59719L,59720L,59721L,59722L,59723L,59724L,
98057 59725L,59726L,59727L,59728L,59729L,59730L,59731L,59732L,59733L,59734L,
98058 59735L,59736L,59737L,59738L,59739L,59740L,59741L,59742L,59743L,59744L,
98059 59745L,59746L,59747L,59748L,59749L,59750L,59751L,59752L,59753L,59754L,
98060 59755L,59756L,59757L,59758L,59759L,59760L,59761L,59762L,59763L,59764L,
98061 59765L,59766L,59767L,59768L,59769L,59770L,59771L,59772L,59773L,59774L,
98062 59775L,59776L,59777L,59778L,59779L,59780L,59781L,59782L,59783L,59784L,
98063 59785L,59786L,59787L,59788L,59789L,59790L,59791L,59792L,59793L,59794L,
98064 59795L,59796L,59797L,59798L,59799L,59800L,59801L,59802L,59803L,59804L,
98065 59805L,59806L,59807L,59808L,59809L,59810L,59811L,59812L,59813L,59814L,
98066 59815L,59816L,59817L,59818L,59819L,59820L,59821L,59822L,59823L,59824L,
98067 59825L,59826L,59827L,59828L,59829L,59830L,59831L,59832L,59833L,59834L,
98068 59835L,59836L,59837L,59838L,59839L,59840L,59841L,59842L,59843L,59844L,
98069 59845L,59846L,59847L,59848L,59849L,59850L,59851L,59852L,59853L,59854L,
98070 59855L,59856L,59857L,59858L,59859L,59860L,59861L,59862L,59863L,59864L,
98071 59865L,59866L,59867L,59868L,59869L,59870L,59871L,59872L,59873L,59874L,
98072 59875L,59876L,59877L,59878L,59879L,59880L,59881L,59882L,59883L,59884L,
98073 59885L,59886L,59887L,59888L,59889L,59890L,59891L,59892L,59893L,59894L,
98074 59895L,59896L,59897L,59898L,59899L,59900L,59901L,59902L,59903L,59904L,
98075 59905L,59906L,59907L,59908L,59909L,59910L,59911L,59912L,59913L,59914L,
98076 59915L,59916L,59917L,59918L,59919L,59920L,59921L,59922L,59923L,59924L,
98077 59925L,59926L,59927L,59928L,59929L,59930L,59931L,59932L,59933L,59934L,
98078 59935L,59936L,59937L,59938L,59939L,59940L,59941L,59942L,59943L,59944L,
98079 59945L,59946L,59947L,59948L,59949L,59950L,59951L,59952L,59953L,59954L,
98080 59955L,59956L,59957L,59958L,59959L,59960L,59961L,59962L,59963L,59964L,
98081 59965L,59966L,59967L,59968L,59969L,59970L,59971L,59972L,59973L,59974L,
98082 59975L,59976L,59977L,59978L,59979L,59980L,59981L,59982L,59983L,59984L,
98083 59985L,59986L,59987L,59988L,59989L,59990L,59991L,59992L,59993L,59994L,
98084 59995L,59996L,59997L,59998L,59999L,60000L,60001L,60002L,60003L,60004L,
98085 60005L,60006L,60007L,60008L,60009L,60010L,60011L,60012L,60013L,60014L,
98086 60015L,60016L,60017L,60018L,60019L,60020L,60021L,60022L,60023L,60024L,
98087 60025L,60026L,60027L,60028L,60029L,60030L,60031L,60032L,60033L,60034L,
98088 60035L,60036L,60037L,60038L,60039L,60040L,60041L,60042L,60043L,60044L,
98089 60045L,60046L,60047L,60048L,60049L,60050L,60051L,60052L,60053L,60054L,
98090 60055L,60056L,60057L,60058L,60059L,60060L,60061L,60062L,60063L,60064L,
98091 60065L,60066L,60067L,60068L,60069L,60070L,60071L,60072L,60073L,60074L,
98092 60075L,60076L,60077L,60078L,60079L,60080L,60081L,60082L,60083L,60084L,
98093 60085L,60086L,60087L,60088L,60089L,60090L,60091L,60092L,60093L,60094L,
98094 60095L,60096L,60097L,60098L,60099L,60100L,60101L,60102L,60103L,60104L,
98095 60105L,60106L,60107L,60108L,60109L,60110L,60111L,60112L,60113L,60114L,
98096 60115L,60116L,60117L,60118L,60119L,60120L,60121L,60122L,60123L,60124L,
98097 60125L,60126L,60127L,60128L,60129L,60130L,60131L,60132L,60133L,60134L,
98098 60135L,60136L,60137L,60138L,60139L,60140L,60141L,60142L,60143L,60144L,
98099 60145L,60146L,60147L,60148L,60149L,60150L,60151L,60152L,60153L,60154L,
98100 60155L,60156L,60157L,60158L,60159L,60160L,60161L,60162L,60163L,60164L,
98101 60165L,60166L,60167L,60168L,60169L,60170L,60171L,60172L,60173L,60174L,
98102 60175L,60176L,60177L,60178L,60179L,60180L,60181L,60182L,60183L,60184L,
98103 60185L,60186L,60187L,60188L,60189L,60190L,60191L,60192L,60193L,60194L,
98104 60195L,60196L,60197L,60198L,60199L,60200L,60201L,60202L,60203L,60204L,
98105 60205L,60206L,60207L,60208L,60209L,60210L,60211L,60212L,60213L,60214L,
98106 60215L,60216L,60217L,60218L,60219L,60220L,60221L,60222L,60223L,60224L,
98107 60225L,60226L,60227L,60228L,60229L,60230L,60231L,60232L,60233L,60234L,
98108 60235L,60236L,60237L,60238L,60239L,60240L,60241L,60242L,60243L,60244L,
98109 60245L,60246L,60247L,60248L,60249L,60250L,60251L,60252L,60253L,60254L,
98110 60255L,60256L,60257L,60258L,60259L,60260L,60261L,60262L,60263L,60264L,
98111 60265L,60266L,60267L,60268L,60269L,60270L,60271L,60272L,60273L,60274L,
98112 60275L,60276L,60277L,60278L,60279L,60280L,60281L,60282L,60283L,60284L,
98113 60285L,60286L,60287L,60288L,60289L,60290L,60291L,60292L,60293L,60294L,
98114 60295L,60296L,60297L,60298L,60299L,60300L,60301L,60302L,60303L,60304L,
98115 60305L,60306L,60307L,60308L,60309L,60310L,60311L,60312L,60313L,60314L,
98116 60315L,60316L,60317L,60318L,60319L,60320L,60321L,60322L,60323L,60324L,
98117 60325L,60326L,60327L,60328L,60329L,60330L,60331L,60332L,60333L,60334L,
98118 60335L,60336L,60337L,60338L,60339L,60340L,60341L,60342L,60343L,60344L,
98119 60345L,60346L,60347L,60348L,60349L,60350L,60351L,60352L,60353L,60354L,
98120 60355L,60356L,60357L,60358L,60359L,60360L,60361L,60362L,60363L,60364L,
98121 60365L,60366L,60367L,60368L,60369L,60370L,60371L,60372L,60373L,60374L,
98122 60375L,60376L,60377L,60378L,60379L,60380L,60381L,60382L,60383L,60384L,
98123 60385L,60386L,60387L,60388L,60389L,60390L,60391L,60392L,60393L,60394L,
98124 60395L,60396L,60397L,60398L,60399L,60400L,60401L,60402L,60403L,60404L,
98125 60405L,60406L,60407L,60408L,60409L,60410L,60411L,60412L,60413L,60414L,
98126 60415L,60416L,60417L,60418L,60419L,60420L,60421L,60422L,60423L,60424L,
98127 60425L,60426L,60427L,60428L,60429L,60430L,60431L,60432L,60433L,60434L,
98128 60435L,60436L,60437L,60438L,60439L,60440L,60441L,60442L,60443L,60444L,
98129 60445L,60446L,60447L,60448L,60449L,60450L,60451L,60452L,60453L,60454L,
98130 60455L,60456L,60457L,60458L,60459L,60460L,60461L,60462L,60463L,60464L,
98131 60465L,60466L,60467L,60468L,60469L,60470L,60471L,60472L,60473L,60474L,
98132 60475L,60476L,60477L,60478L,60479L,60480L,60481L,60482L,60483L,60484L,
98133 60485L,60486L,60487L,60488L,60489L,60490L,60491L,60492L,60493L,60494L,
98134 60495L,60496L,60497L,60498L,60499L,60500L,60501L,60502L,60503L,60504L,
98135 60505L,60506L,60507L,60508L,60509L,60510L,60511L,60512L,60513L,60514L,
98136 60515L,60516L,60517L,60518L,60519L,60520L,60521L,60522L,60523L,60524L,
98137 60525L,60526L,60527L,60528L,60529L,60530L,60531L,60532L,60533L,60534L,
98138 60535L,60536L,60537L,60538L,60539L,60540L,60541L,60542L,60543L,60544L,
98139 60545L,60546L,60547L,60548L,60549L,60550L,60551L,60552L,60553L,60554L,
98140 60555L,60556L,60557L,60558L,60559L,60560L,60561L,60562L,60563L,60564L,
98141 60565L,60566L,60567L,60568L,60569L,60570L,60571L,60572L,60573L,60574L,
98142 60575L,60576L,60577L,60578L,60579L,60580L,60581L,60582L,60583L,60584L,
98143 60585L,60586L,60587L,60588L,60589L,60590L,60591L,60592L,60593L,60594L,
98144 60595L,60596L,60597L,60598L,60599L,60600L,60601L,60602L,60603L,60604L,
98145 60605L,60606L,60607L,60608L,60609L,60610L,60611L,60612L,60613L,60614L,
98146 60615L,60616L,60617L,60618L,60619L,60620L,60621L,60622L,60623L,60624L,
98147 60625L,60626L,60627L,60628L,60629L,60630L,60631L,60632L,60633L,60634L,
98148 60635L,60636L,60637L,60638L,60639L,60640L,60641L,60642L,60643L,60644L,
98149 60645L,60646L,60647L,60648L,60649L,60650L,60651L,60652L,60653L,60654L,
98150 60655L,60656L,60657L,60658L,60659L,60660L,60661L,60662L,60663L,60664L,
98151 60665L,60666L,60667L,60668L,60669L,60670L,60671L,60672L,60673L,60674L,
98152 60675L,60676L,60677L,60678L,60679L,60680L,60681L,60682L,60683L,60684L,
98153 60685L,60686L,60687L,60688L,60689L,60690L,60691L,60692L,60693L,60694L,
98154 60695L,60696L,60697L,60698L,60699L,60700L,60701L,60702L,60703L,60704L,
98155 60705L,60706L,60707L,60708L,60709L,60710L,60711L,60712L,60713L,60714L,
98156 60715L,60716L,60717L,60718L,60719L,60720L,60721L,60722L,60723L,60724L,
98157 60725L,60726L,60727L,60728L,60729L,60730L,60731L,60732L,60733L,60734L,
98158 60735L,60736L,60737L,60738L,60739L,60740L,60741L,60742L,60743L,60744L,
98159 60745L,60746L,60747L,60748L,60749L,60750L,60751L,60752L,60753L,60754L,
98160 60755L,60756L,60757L,60758L,60759L,60760L,60761L,60762L,60763L,60764L,
98161 60765L,60766L,60767L,60768L,60769L,60770L,60771L,60772L,60773L,60774L,
98162 60775L,60776L,60777L,60778L,60779L,60780L,60781L,60782L,60783L,60784L,
98163 60785L,60786L,60787L,60788L,60789L,60790L,60791L,60792L,60793L,60794L,
98164 60795L,60796L,60797L,60798L,60799L,60800L,60801L,60802L,60803L,60804L,
98165 60805L,60806L,60807L,60808L,60809L,60810L,60811L,60812L,60813L,60814L,
98166 60815L,60816L,60817L,60818L,60819L,60820L,60821L,60822L,60823L,60824L,
98167 60825L,60826L,60827L,60828L,60829L,60830L,60831L,60832L,60833L,60834L,
98168 60835L,60836L,60837L,60838L,60839L,60840L,60841L,60842L,60843L,60844L,
98169 60845L,60846L,60847L,60848L,60849L,60850L,60851L,60852L,60853L,60854L,
98170 60855L,60856L,60857L,60858L,60859L,60860L,60861L,60862L,60863L,60864L,
98171 60865L,60866L,60867L,60868L,60869L,60870L,60871L,60872L,60873L,60874L,
98172 60875L,60876L,60877L,60878L,60879L,60880L,60881L,60882L,60883L,60884L,
98173 60885L,60886L,60887L,60888L,60889L,60890L,60891L,60892L,60893L,60894L,
98174 60895L,60896L,60897L,60898L,60899L,60900L,60901L,60902L,60903L,60904L,
98175 60905L,60906L,60907L,60908L,60909L,60910L,60911L,60912L,60913L,60914L,
98176 60915L,60916L,60917L,60918L,60919L,60920L,60921L,60922L,60923L,60924L,
98177 60925L,60926L,60927L,60928L,60929L,60930L,60931L,60932L,60933L,60934L,
98178 60935L,60936L,60937L,60938L,60939L,60940L,60941L,60942L,60943L,60944L,
98179 60945L,60946L,60947L,60948L,60949L,60950L,60951L,60952L,60953L,60954L,
98180 60955L,60956L,60957L,60958L,60959L,60960L,60961L,60962L,60963L,60964L,
98181 60965L,60966L,60967L,60968L,60969L,60970L,60971L,60972L,60973L,60974L,
98182 60975L,60976L,60977L,60978L,60979L,60980L,60981L,60982L,60983L,60984L,
98183 60985L,60986L,60987L,60988L,60989L,60990L,60991L,60992L,60993L,60994L,
98184 60995L,60996L,60997L,60998L,60999L,61000L,61001L,61002L,61003L,61004L,
98185 61005L,61006L,61007L,61008L,61009L,61010L,61011L,61012L,61013L,61014L,
98186 61015L,61016L,61017L,61018L,61019L,61020L,61021L,61022L,61023L,61024L,
98187 61025L,61026L,61027L,61028L,61029L,61030L,61031L,61032L,61033L,61034L,
98188 61035L,61036L,61037L,61038L,61039L,61040L,61041L,61042L,61043L,61044L,
98189 61045L,61046L,61047L,61048L,61049L,61050L,61051L,61052L,61053L,61054L,
98190 61055L,61056L,61057L,61058L,61059L,61060L,61061L,61062L,61063L,61064L,
98191 61065L,61066L,61067L,61068L,61069L,61070L,61071L,61072L,61073L,61074L,
98192 61075L,61076L,61077L,61078L,61079L,61080L,61081L,61082L,61083L,61084L,
98193 61085L,61086L,61087L,61088L,61089L,61090L,61091L,61092L,61093L,61094L,
98194 61095L,61096L,61097L,61098L,61099L,61100L,61101L,61102L,61103L,61104L,
98195 61105L,61106L,61107L,61108L,61109L,61110L,61111L,61112L,61113L,61114L,
98196 61115L,61116L,61117L,61118L,61119L,61120L,61121L,61122L,61123L,61124L,
98197 61125L,61126L,61127L,61128L,61129L,61130L,61131L,61132L,61133L,61134L,
98198 61135L,61136L,61137L,61138L,61139L,61140L,61141L,61142L,61143L,61144L,
98199 61145L,61146L,61147L,61148L,61149L,61150L,61151L,61152L,61153L,61154L,
98200 61155L,61156L,61157L,61158L,61159L,61160L,61161L,61162L,61163L,61164L,
98201 61165L,61166L,61167L,61168L,61169L,61170L,61171L,61172L,61173L,61174L,
98202 61175L,61176L,61177L,61178L,61179L,61180L,61181L,61182L,61183L,61184L,
98203 61185L,61186L,61187L,61188L,61189L,61190L,61191L,61192L,61193L,61194L,
98204 61195L,61196L,61197L,61198L,61199L,61200L,61201L,61202L,61203L,61204L,
98205 61205L,61206L,61207L,61208L,61209L,61210L,61211L,61212L,61213L,61214L,
98206 61215L,61216L,61217L,61218L,61219L,61220L,61221L,61222L,61223L,61224L,
98207 61225L,61226L,61227L,61228L,61229L,61230L,61231L,61232L,61233L,61234L,
98208 61235L,61236L,61237L,61238L,61239L,61240L,61241L,61242L,61243L,61244L,
98209 61245L,61246L,61247L,61248L,61249L,61250L,61251L,61252L,61253L,61254L,
98210 61255L,61256L,61257L,61258L,61259L,61260L,61261L,61262L,61263L,61264L,
98211 61265L,61266L,61267L,61268L,61269L,61270L,61271L,61272L,61273L,61274L,
98212 61275L,61276L,61277L,61278L,61279L,61280L,61281L,61282L,61283L,61284L,
98213 61285L,61286L,61287L,61288L,61289L,61290L,61291L,61292L,61293L,61294L,
98214 61295L,61296L,61297L,61298L,61299L,61300L,61301L,61302L,61303L,61304L,
98215 61305L,61306L,61307L,61308L,61309L,61310L,61311L,61312L,61313L,61314L,
98216 61315L,61316L,61317L,61318L,61319L,61320L,61321L,61322L,61323L,61324L,
98217 61325L,61326L,61327L,61328L,61329L,61330L,61331L,61332L,61333L,61334L,
98218 61335L,61336L,61337L,61338L,61339L,61340L,61341L,61342L,61343L,61344L,
98219 61345L,61346L,61347L,61348L,61349L,61350L,61351L,61352L,61353L,61354L,
98220 61355L,61356L,61357L,61358L,61359L,61360L,61361L,61362L,61363L,61364L,
98221 61365L,61366L,61367L,61368L,61369L,61370L,61371L,61372L,61373L,61374L,
98222 61375L,61376L,61377L,61378L,61379L,61380L,61381L,61382L,61383L,61384L,
98223 61385L,61386L,61387L,61388L,61389L,61390L,61391L,61392L,61393L,61394L,
98224 61395L,61396L,61397L,61398L,61399L,61400L,61401L,61402L,61403L,61404L,
98225 61405L,61406L,61407L,61408L,61409L,61410L,61411L,61412L,61413L,61414L,
98226 61415L,61416L,61417L,61418L,61419L,61420L,61421L,61422L,61423L,61424L,
98227 61425L,61426L,61427L,61428L,61429L,61430L,61431L,61432L,61433L,61434L,
98228 61435L,61436L,61437L,61438L,61439L,61440L,61441L,61442L,61443L,61444L,
98229 61445L,61446L,61447L,61448L,61449L,61450L,61451L,61452L,61453L,61454L,
98230 61455L,61456L,61457L,61458L,61459L,61460L,61461L,61462L,61463L,61464L,
98231 61465L,61466L,61467L,61468L,61469L,61470L,61471L,61472L,61473L,61474L,
98232 61475L,61476L,61477L,61478L,61479L,61480L,61481L,61482L,61483L,61484L,
98233 61485L,61486L,61487L,61488L,61489L,61490L,61491L,61492L,61493L,61494L,
98234 61495L,61496L,61497L,61498L,61499L,61500L,61501L,61502L,61503L,61504L,
98235 61505L,61506L,61507L,61508L,61509L,61510L,61511L,61512L,61513L,61514L,
98236 61515L,61516L,61517L,61518L,61519L,61520L,61521L,61522L,61523L,61524L,
98237 61525L,61526L,61527L,61528L,61529L,61530L,61531L,61532L,61533L,61534L,
98238 61535L,61536L,61537L,61538L,61539L,61540L,61541L,61542L,61543L,61544L,
98239 61545L,61546L,61547L,61548L,61549L,61550L,61551L,61552L,61553L,61554L,
98240 61555L,61556L,61557L,61558L,61559L,61560L,61561L,61562L,61563L,61564L,
98241 61565L,61566L,61567L,61568L,61569L,61570L,61571L,61572L,61573L,61574L,
98242 61575L,61576L,61577L,61578L,61579L,61580L,61581L,61582L,61583L,61584L,
98243 61585L,61586L,61587L,61588L,61589L,61590L,61591L,61592L,61593L,61594L,
98244 61595L,61596L,61597L,61598L,61599L,61600L,61601L,61602L,61603L,61604L,
98245 61605L,61606L,61607L,61608L,61609L,61610L,61611L,61612L,61613L,61614L,
98246 61615L,61616L,61617L,61618L,61619L,61620L,61621L,61622L,61623L,61624L,
98247 61625L,61626L,61627L,61628L,61629L,61630L,61631L,61632L,61633L,61634L,
98248 61635L,61636L,61637L,61638L,61639L,61640L,61641L,61642L,61643L,61644L,
98249 61645L,61646L,61647L,61648L,61649L,61650L,61651L,61652L,61653L,61654L,
98250 61655L,61656L,61657L,61658L,61659L,61660L,61661L,61662L,61663L,61664L,
98251 61665L,61666L,61667L,61668L,61669L,61670L,61671L,61672L,61673L,61674L,
98252 61675L,61676L,61677L,61678L,61679L,61680L,61681L,61682L,61683L,61684L,
98253 61685L,61686L,61687L,61688L,61689L,61690L,61691L,61692L,61693L,61694L,
98254 61695L,61696L,61697L,61698L,61699L,61700L,61701L,61702L,61703L,61704L,
98255 61705L,61706L,61707L,61708L,61709L,61710L,61711L,61712L,61713L,61714L,
98256 61715L,61716L,61717L,61718L,61719L,61720L,61721L,61722L,61723L,61724L,
98257 61725L,61726L,61727L,61728L,61729L,61730L,61731L,61732L,61733L,61734L,
98258 61735L,61736L,61737L,61738L,61739L,61740L,61741L,61742L,61743L,61744L,
98259 61745L,61746L,61747L,61748L,61749L,61750L,61751L,61752L,61753L,61754L,
98260 61755L,61756L,61757L,61758L,61759L,61760L,61761L,61762L,61763L,61764L,
98261 61765L,61766L,61767L,61768L,61769L,61770L,61771L,61772L,61773L,61774L,
98262 61775L,61776L,61777L,61778L,61779L,61780L,61781L,61782L,61783L,61784L,
98263 61785L,61786L,61787L,61788L,61789L,61790L,61791L,61792L,61793L,61794L,
98264 61795L,61796L,61797L,61798L,61799L,61800L,61801L,61802L,61803L,61804L,
98265 61805L,61806L,61807L,61808L,61809L,61810L,61811L,61812L,61813L,61814L,
98266 61815L,61816L,61817L,61818L,61819L,61820L,61821L,61822L,61823L,61824L,
98267 61825L,61826L,61827L,61828L,61829L,61830L,61831L,61832L,61833L,61834L,
98268 61835L,61836L,61837L,61838L,61839L,61840L,61841L,61842L,61843L,61844L,
98269 61845L,61846L,61847L,61848L,61849L,61850L,61851L,61852L,61853L,61854L,
98270 61855L,61856L,61857L,61858L,61859L,61860L,61861L,61862L,61863L,61864L,
98271 61865L,61866L,61867L,61868L,61869L,61870L,61871L,61872L,61873L,61874L,
98272 61875L,61876L,61877L,61878L,61879L,61880L,61881L,61882L,61883L,61884L,
98273 61885L,61886L,61887L,61888L,61889L,61890L,61891L,61892L,61893L,61894L,
98274 61895L,61896L,61897L,61898L,61899L,61900L,61901L,61902L,61903L,61904L,
98275 61905L,61906L,61907L,61908L,61909L,61910L,61911L,61912L,61913L,61914L,
98276 61915L,61916L,61917L,61918L,61919L,61920L,61921L,61922L,61923L,61924L,
98277 61925L,61926L,61927L,61928L,61929L,61930L,61931L,61932L,61933L,61934L,
98278 61935L,61936L,61937L,61938L,61939L,61940L,61941L,61942L,61943L,61944L,
98279 61945L,61946L,61947L,61948L,61949L,61950L,61951L,61952L,61953L,61954L,
98280 61955L,61956L,61957L,61958L,61959L,61960L,61961L,61962L,61963L,61964L,
98281 61965L,61966L,61967L,61968L,61969L,61970L,61971L,61972L,61973L,61974L,
98282 61975L,61976L,61977L,61978L,61979L,61980L,61981L,61982L,61983L,61984L,
98283 61985L,61986L,61987L,61988L,61989L,61990L,61991L,61992L,61993L,61994L,
98284 61995L,61996L,61997L,61998L,61999L,62000L,62001L,62002L,62003L,62004L,
98285 62005L,62006L,62007L,62008L,62009L,62010L,62011L,62012L,62013L,62014L,
98286 62015L,62016L,62017L,62018L,62019L,62020L,62021L,62022L,62023L,62024L,
98287 62025L,62026L,62027L,62028L,62029L,62030L,62031L,62032L,62033L,62034L,
98288 62035L,62036L,62037L,62038L,62039L,62040L,62041L,62042L,62043L,62044L,
98289 62045L,62046L,62047L,62048L,62049L,62050L,62051L,62052L,62053L,62054L,
98290 62055L,62056L,62057L,62058L,62059L,62060L,62061L,62062L,62063L,62064L,
98291 62065L,62066L,62067L,62068L,62069L,62070L,62071L,62072L,62073L,62074L,
98292 62075L,62076L,62077L,62078L,62079L,62080L,62081L,62082L,62083L,62084L,
98293 62085L,62086L,62087L,62088L,62089L,62090L,62091L,62092L,62093L,62094L,
98294 62095L,62096L,62097L,62098L,62099L,62100L,62101L,62102L,62103L,62104L,
98295 62105L,62106L,62107L,62108L,62109L,62110L,62111L,62112L,62113L,62114L,
98296 62115L,62116L,62117L,62118L,62119L,62120L,62121L,62122L,62123L,62124L,
98297 62125L,62126L,62127L,62128L,62129L,62130L,62131L,62132L,62133L,62134L,
98298 62135L,62136L,62137L,62138L,62139L,62140L,62141L,62142L,62143L,62144L,
98299 62145L,62146L,62147L,62148L,62149L,62150L,62151L,62152L,62153L,62154L,
98300 62155L,62156L,62157L,62158L,62159L,62160L,62161L,62162L,62163L,62164L,
98301 62165L,62166L,62167L,62168L,62169L,62170L,62171L,62172L,62173L,62174L,
98302 62175L,62176L,62177L,62178L,62179L,62180L,62181L,62182L,62183L,62184L,
98303 62185L,62186L,62187L,62188L,62189L,62190L,62191L,62192L,62193L,62194L,
98304 62195L,62196L,62197L,62198L,62199L,62200L,62201L,62202L,62203L,62204L,
98305 62205L,62206L,62207L,62208L,62209L,62210L,62211L,62212L,62213L,62214L,
98306 62215L,62216L,62217L,62218L,62219L,62220L,62221L,62222L,62223L,62224L,
98307 62225L,62226L,62227L,62228L,62229L,62230L,62231L,62232L,62233L,62234L,
98308 62235L,62236L,62237L,62238L,62239L,62240L,62241L,62242L,62243L,62244L,
98309 62245L,62246L,62247L,62248L,62249L,62250L,62251L,62252L,62253L,62254L,
98310 62255L,62256L,62257L,62258L,62259L,62260L,62261L,62262L,62263L,62264L,
98311 62265L,62266L,62267L,62268L,62269L,62270L,62271L,62272L,62273L,62274L,
98312 62275L,62276L,62277L,62278L,62279L,62280L,62281L,62282L,62283L,62284L,
98313 62285L,62286L,62287L,62288L,62289L,62290L,62291L,62292L,62293L,62294L,
98314 62295L,62296L,62297L,62298L,62299L,62300L,62301L,62302L,62303L,62304L,
98315 62305L,62306L,62307L,62308L,62309L,62310L,62311L,62312L,62313L,62314L,
98316 62315L,62316L,62317L,62318L,62319L,62320L,62321L,62322L,62323L,62324L,
98317 62325L,62326L,62327L,62328L,62329L,62330L,62331L,62332L,62333L,62334L,
98318 62335L,62336L,62337L,62338L,62339L,62340L,62341L,62342L,62343L,62344L,
98319 62345L,62346L,62347L,62348L,62349L,62350L,62351L,62352L,62353L,62354L,
98320 62355L,62356L,62357L,62358L,62359L,62360L,62361L,62362L,62363L,62364L,
98321 62365L,62366L,62367L,62368L,62369L,62370L,62371L,62372L,62373L,62374L,
98322 62375L,62376L,62377L,62378L,62379L,62380L,62381L,62382L,62383L,62384L,
98323 62385L,62386L,62387L,62388L,62389L,62390L,62391L,62392L,62393L,62394L,
98324 62395L,62396L,62397L,62398L,62399L,62400L,62401L,62402L,62403L,62404L,
98325 62405L,62406L,62407L,62408L,62409L,62410L,62411L,62412L,62413L,62414L,
98326 62415L,62416L,62417L,62418L,62419L,62420L,62421L,62422L,62423L,62424L,
98327 62425L,62426L,62427L,62428L,62429L,62430L,62431L,62432L,62433L,62434L,
98328 62435L,62436L,62437L,62438L,62439L,62440L,62441L,62442L,62443L,62444L,
98329 62445L,62446L,62447L,62448L,62449L,62450L,62451L,62452L,62453L,62454L,
98330 62455L,62456L,62457L,62458L,62459L,62460L,62461L,62462L,62463L,62464L,
98331 62465L,62466L,62467L,62468L,62469L,62470L,62471L,62472L,62473L,62474L,
98332 62475L,62476L,62477L,62478L,62479L,62480L,62481L,62482L,62483L,62484L,
98333 62485L,62486L,62487L,62488L,62489L,62490L,62491L,62492L,62493L,62494L,
98334 62495L,62496L,62497L,62498L,62499L,62500L,62501L,62502L,62503L,62504L,
98335 62505L,62506L,62507L,62508L,62509L,62510L,62511L,62512L,62513L,62514L,
98336 62515L,62516L,62517L,62518L,62519L,62520L,62521L,62522L,62523L,62524L,
98337 62525L,62526L,62527L,62528L,62529L,62530L,62531L,62532L,62533L,62534L,
98338 62535L,62536L,62537L,62538L,62539L,62540L,62541L,62542L,62543L,62544L,
98339 62545L,62546L,62547L,62548L,62549L,62550L,62551L,62552L,62553L,62554L,
98340 62555L,62556L,62557L,62558L,62559L,62560L,62561L,62562L,62563L,62564L,
98341 62565L,62566L,62567L,62568L,62569L,62570L,62571L,62572L,62573L,62574L,
98342 62575L,62576L,62577L,62578L,62579L,62580L,62581L,62582L,62583L,62584L,
98343 62585L,62586L,62587L,62588L,62589L,62590L,62591L,62592L,62593L,62594L,
98344 62595L,62596L,62597L,62598L,62599L,62600L,62601L,62602L,62603L,62604L,
98345 62605L,62606L,62607L,62608L,62609L,62610L,62611L,62612L,62613L,62614L,
98346 62615L,62616L,62617L,62618L,62619L,62620L,62621L,62622L,62623L,62624L,
98347 62625L,62626L,62627L,62628L,62629L,62630L,62631L,62632L,62633L,62634L,
98348 62635L,62636L,62637L,62638L,62639L,62640L,62641L,62642L,62643L,62644L,
98349 62645L,62646L,62647L,62648L,62649L,62650L,62651L,62652L,62653L,62654L,
98350 62655L,62656L,62657L,62658L,62659L,62660L,62661L,62662L,62663L,62664L,
98351 62665L,62666L,62667L,62668L,62669L,62670L,62671L,62672L,62673L,62674L,
98352 62675L,62676L,62677L,62678L,62679L,62680L,62681L,62682L,62683L,62684L,
98353 62685L,62686L,62687L,62688L,62689L,62690L,62691L,62692L,62693L,62694L,
98354 62695L,62696L,62697L,62698L,62699L,62700L,62701L,62702L,62703L,62704L,
98355 62705L,62706L,62707L,62708L,62709L,62710L,62711L,62712L,62713L,62714L,
98356 62715L,62716L,62717L,62718L,62719L,62720L,62721L,62722L,62723L,62724L,
98357 62725L,62726L,62727L,62728L,62729L,62730L,62731L,62732L,62733L,62734L,
98358 62735L,62736L,62737L,62738L,62739L,62740L,62741L,62742L,62743L,62744L,
98359 62745L,62746L,62747L,62748L,62749L,62750L,62751L,62752L,62753L,62754L,
98360 62755L,62756L,62757L,62758L,62759L,62760L,62761L,62762L,62763L,62764L,
98361 62765L,62766L,62767L,62768L,62769L,62770L,62771L,62772L,62773L,62774L,
98362 62775L,62776L,62777L,62778L,62779L,62780L,62781L,62782L,62783L,62784L,
98363 62785L,62786L,62787L,62788L,62789L,62790L,62791L,62792L,62793L,62794L,
98364 62795L,62796L,62797L,62798L,62799L,62800L,62801L,62802L,62803L,62804L,
98365 62805L,62806L,62807L,62808L,62809L,62810L,62811L,62812L,62813L,62814L,
98366 62815L,62816L,62817L,62818L,62819L,62820L,62821L,62822L,62823L,62824L,
98367 62825L,62826L,62827L,62828L,62829L,62830L,62831L,62832L,62833L,62834L,
98368 62835L,62836L,62837L,62838L,62839L,62840L,62841L,62842L,62843L,62844L,
98369 62845L,62846L,62847L,62848L,62849L,62850L,62851L,62852L,62853L,62854L,
98370 62855L,62856L,62857L,62858L,62859L,62860L,62861L,62862L,62863L,62864L,
98371 62865L,62866L,62867L,62868L,62869L,62870L,62871L,62872L,62873L,62874L,
98372 62875L,62876L,62877L,62878L,62879L,62880L,62881L,62882L,62883L,62884L,
98373 62885L,62886L,62887L,62888L,62889L,62890L,62891L,62892L,62893L,62894L,
98374 62895L,62896L,62897L,62898L,62899L,62900L,62901L,62902L,62903L,62904L,
98375 62905L,62906L,62907L,62908L,62909L,62910L,62911L,62912L,62913L,62914L,
98376 62915L,62916L,62917L,62918L,62919L,62920L,62921L,62922L,62923L,62924L,
98377 62925L,62926L,62927L,62928L,62929L,62930L,62931L,62932L,62933L,62934L,
98378 62935L,62936L,62937L,62938L,62939L,62940L,62941L,62942L,62943L,62944L,
98379 62945L,62946L,62947L,62948L,62949L,62950L,62951L,62952L,62953L,62954L,
98380 62955L,62956L,62957L,62958L,62959L,62960L,62961L,62962L,62963L,62964L,
98381 62965L,62966L,62967L,62968L,62969L,62970L,62971L,62972L,62973L,62974L,
98382 62975L,62976L,62977L,62978L,62979L,62980L,62981L,62982L,62983L,62984L,
98383 62985L,62986L,62987L,62988L,62989L,62990L,62991L,62992L,62993L,62994L,
98384 62995L,62996L,62997L,62998L,62999L,63000L,63001L,63002L,63003L,63004L,
98385 63005L,63006L,63007L,63008L,63009L,63010L,63011L,63012L,63013L,63014L,
98386 63015L,63016L,63017L,63018L,63019L,63020L,63021L,63022L,63023L,63024L,
98387 63025L,63026L,63027L,63028L,63029L,63030L,63031L,63032L,63033L,63034L,
98388 63035L,63036L,63037L,63038L,63039L,63040L,63041L,63042L,63043L,63044L,
98389 63045L,63046L,63047L,63048L,63049L,63050L,63051L,63052L,63053L,63054L,
98390 63055L,63056L,63057L,63058L,63059L,63060L,63061L,63062L,63063L,63064L,
98391 63065L,63066L,63067L,63068L,63069L,63070L,63071L,63072L,63073L,63074L,
98392 63075L,63076L,63077L,63078L,63079L,63080L,63081L,63082L,63083L,63084L,
98393 63085L,63086L,63087L,63088L,63089L,63090L,63091L,63092L,63093L,63094L,
98394 63095L,63096L,63097L,63098L,63099L,63100L,63101L,63102L,63103L,63104L,
98395 63105L,63106L,63107L,63108L,63109L,63110L,63111L,63112L,63113L,63114L,
98396 63115L,63116L,63117L,63118L,63119L,63120L,63121L,63122L,63123L,63124L,
98397 63125L,63126L,63127L,63128L,63129L,63130L,63131L,63132L,63133L,63134L,
98398 63135L,63136L,63137L,63138L,63139L,63140L,63141L,63142L,63143L,63144L,
98399 63145L,63146L,63147L,63148L,63149L,63150L,63151L,63152L,63153L,63154L,
98400 63155L,63156L,63157L,63158L,63159L,63160L,63161L,63162L,63163L,63164L,
98401 63165L,63166L,63167L,63168L,63169L,63170L,63171L,63172L,63173L,63174L,
98402 63175L,63176L,63177L,63178L,63179L,63180L,63181L,63182L,63183L,63184L,
98403 63185L,63186L,63187L,63188L,63189L,63190L,63191L,63192L,63193L,63194L,
98404 63195L,63196L,63197L,63198L,63199L,63200L,63201L,63202L,63203L,63204L,
98405 63205L,63206L,63207L,63208L,63209L,63210L,63211L,63212L,63213L,63214L,
98406 63215L,63216L,63217L,63218L,63219L,63220L,63221L,63222L,63223L,63224L,
98407 63225L,63226L,63227L,63228L,63229L,63230L,63231L,63232L,63233L,63234L,
98408 63235L,63236L,63237L,63238L,63239L,63240L,63241L,63242L,63243L,63244L,
98409 63245L,63246L,63247L,63248L,63249L,63250L,63251L,63252L,63253L,63254L,
98410 63255L,63256L,63257L,63258L,63259L,63260L,63261L,63262L,63263L,63264L,
98411 63265L,63266L,63267L,63268L,63269L,63270L,63271L,63272L,63273L,63274L,
98412 63275L,63276L,63277L,63278L,63279L,63280L,63281L,63282L,63283L,63284L,
98413 63285L,63286L,63287L,63288L,63289L,63290L,63291L,63292L,63293L,63294L,
98414 63295L,63296L,63297L,63298L,63299L,63300L,63301L,63302L,63303L,63304L,
98415 63305L,63306L,63307L,63308L,63309L,63310L,63311L,63312L,63313L,63314L,
98416 63315L,63316L,63317L,63318L,63319L,63320L,63321L,63322L,63323L,63324L,
98417 63325L,63326L,63327L,63328L,63329L,63330L,63331L,63332L,63333L,63334L,
98418 63335L,63336L,63337L,63338L,63339L,63340L,63341L,63342L,63343L,63344L,
98419 63345L,63346L,63347L,63348L,63349L,63350L,63351L,63352L,63353L,63354L,
98420 63355L,63356L,63357L,63358L,63359L,63360L,63361L,63362L,63363L,63364L,
98421 63365L,63366L,63367L,63368L,63369L,63370L,63371L,63372L,63373L,63374L,
98422 63375L,63376L,63377L,63378L,63379L,63380L,63381L,63382L,63383L,63384L,
98423 63385L,63386L,63387L,63388L,63389L,63390L,63391L,63392L,63393L,63394L,
98424 63395L,63396L,63397L,63398L,63399L,63400L,63401L,63402L,63403L,63404L,
98425 63405L,63406L,63407L,63408L,63409L,63410L,63411L,63412L,63413L,63414L,
98426 63415L,63416L,63417L,63418L,63419L,63420L,63421L,63422L,63423L,63424L,
98427 63425L,63426L,63427L,63428L,63429L,63430L,63431L,63432L,63433L,63434L,
98428 63435L,63436L,63437L,63438L,63439L,63440L,63441L,63442L,63443L,63444L,
98429 63445L,63446L,63447L,63448L,63449L,63450L,63451L,63452L,63453L,63454L,
98430 63455L,63456L,63457L,63458L,63459L,63460L,63461L,63462L,63463L,63464L,
98431 63465L,63466L,63467L,63468L,63469L,63470L,63471L,63472L,63473L,63474L,
98432 63475L,63476L,63477L,63478L,63479L,63480L,63481L,63482L,63483L,63484L,
98433 63485L,63486L,63487L,63488L,63489L,63490L,63491L,63492L,63493L,63494L,
98434 63495L,63496L,63497L,63498L,63499L,63500L,63501L,63502L,63503L,63504L,
98435 63505L,63506L,63507L,63508L,63509L,63510L,63511L,63512L,63513L,63514L,
98436 63515L,63516L,63517L,63518L,63519L,63520L,63521L,63522L,63523L,63524L,
98437 63525L,63526L,63527L,63528L,63529L,63530L,63531L,63532L,63533L,63534L,
98438 63535L,63536L,63537L,63538L,63539L,63540L,63541L,63542L,63543L,63544L,
98439 63545L,63546L,63547L,63548L,63549L,63550L,63551L,63552L,63553L,63554L,
98440 63555L,63556L,63557L,63558L,63559L,63560L,63561L,63562L,63563L,63564L,
98441 63565L,63566L,63567L,63568L,63569L,63570L,63571L,63572L,63573L,63574L,
98442 63575L,63576L,63577L,63578L,63579L,63580L,63581L,63582L,63583L,63584L,
98443 63585L,63586L,63587L,63588L,63589L,63590L,63591L,63592L,63593L,63594L,
98444 63595L,63596L,63597L,63598L,63599L,63600L,63601L,63602L,63603L,63604L,
98445 63605L,63606L,63607L,63608L,63609L,63610L,63611L,63612L,63613L,63614L,
98446 63615L,63616L,63617L,63618L,63619L,63620L,63621L,63622L,63623L,63624L,
98447 63625L,63626L,63627L,63628L,63629L,63630L,63631L,63632L,63633L,63634L,
98448 63635L,63636L,63637L,63638L,63639L,63640L,63641L,63642L,63643L,63644L,
98449 63645L,63646L,63647L,63648L,63649L,63650L,63651L,63652L,63653L,63654L,
98450 63655L,63656L,63657L,63658L,63659L,63660L,63661L,63662L,63663L,63664L,
98451 63665L,63666L,63667L,63668L,63669L,63670L,63671L,63672L,63673L,63674L,
98452 63675L,63676L,63677L,63678L,63679L,63680L,63681L,63682L,63683L,63684L,
98453 63685L,63686L,63687L,63688L,63689L,63690L,63691L,63692L,63693L,63694L,
98454 63695L,63696L,63697L,63698L,63699L,63700L,63701L,63702L,63703L,63704L,
98455 63705L,63706L,63707L,63708L,63709L,63710L,63711L,63712L,63713L,63714L,
98456 63715L,63716L,63717L,63718L,63719L,63720L,63721L,63722L,63723L,63724L,
98457 63725L,63726L,63727L,63728L,63729L,63730L,63731L,63732L,63733L,63734L,
98458 63735L,63736L,63737L,63738L,63739L,63740L,63741L,63742L,63743L,63744L,
98459 63745L,63746L,63747L,63748L,63749L,63750L,63751L,63752L,63753L,63754L,
98460 63755L,63756L,63757L,63758L,63759L,63760L,63761L,63762L,63763L,63764L,
98461 63765L,63766L,63767L,63768L,63769L,63770L,63771L,63772L,63773L,63774L,
98462 63775L,63776L,63777L,63778L,63779L,63780L,63781L,63782L,63783L,63784L,
98463 63785L,63786L,63787L,63788L,63789L,63790L,63791L,63792L,63793L,63794L,
98464 63795L,63796L,63797L,63798L,63799L,63800L,63801L,63802L,63803L,63804L,
98465 63805L,63806L,63807L,63808L,63809L,63810L,63811L,63812L,63813L,63814L,
98466 63815L,63816L,63817L,63818L,63819L,63820L,63821L,63822L,63823L,63824L,
98467 63825L,63826L,63827L,63828L,63829L,63830L,63831L,63832L,63833L,63834L,
98468 63835L,63836L,63837L,63838L,63839L,63840L,63841L,63842L,63843L,63844L,
98469 63845L,63846L,63847L,63848L,63849L,63850L,63851L,63852L,63853L,63854L,
98470 63855L,63856L,63857L,63858L,63859L,63860L,63861L,63862L,63863L,63864L,
98471 63865L,63866L,63867L,63868L,63869L,63870L,63871L,63872L,63873L,63874L,
98472 63875L,63876L,63877L,63878L,63879L,63880L,63881L,63882L,63883L,63884L,
98473 63885L,63886L,63887L,63888L,63889L,63890L,63891L,63892L,63893L,63894L,
98474 63895L,63896L,63897L,63898L,63899L,63900L,63901L,63902L,63903L,63904L,
98475 63905L,63906L,63907L,63908L,63909L,63910L,63911L,63912L,63913L,63914L,
98476 63915L,63916L,63917L,63918L,63919L,63920L,63921L,63922L,63923L,63924L,
98477 63925L,63926L,63927L,63928L,63929L,63930L,63931L,63932L,63933L,63934L,
98478 63935L,63936L,63937L,63938L,63939L,63940L,63941L,63942L,63943L,63944L,
98479 63945L,63946L,63947L,63948L,63949L,63950L,63951L,63952L,63953L,63954L,
98480 63955L,63956L,63957L,63958L,63959L,63960L,63961L,63962L,63963L,63964L,
98481 63965L,63966L,63967L,63968L,63969L,63970L,63971L,63972L,63973L,63974L,
98482 63975L,63976L,63977L,63978L,63979L,63980L,63981L,63982L,63983L,63984L,
98483 63985L,63986L,63987L,63988L,63989L,63990L,63991L,63992L,63993L,63994L,
98484 63995L,63996L,63997L,63998L,63999L,64000L,64001L,64002L,64003L,64004L,
98485 64005L,64006L,64007L,64008L,64009L,64010L,64011L,64012L,64013L,64014L,
98486 64015L,64016L,64017L,64018L,64019L,64020L,64021L,64022L,64023L,64024L,
98487 64025L,64026L,64027L,64028L,64029L,64030L,64031L,64032L,64033L,64034L,
98488 64035L,64036L,64037L,64038L,64039L,64040L,64041L,64042L,64043L,64044L,
98489 64045L,64046L,64047L,64048L,64049L,64050L,64051L,64052L,64053L,64054L,
98490 64055L,64056L,64057L,64058L,64059L,64060L,64061L,64062L,64063L,64064L,
98491 64065L,64066L,64067L,64068L,64069L,64070L,64071L,64072L,64073L,64074L,
98492 64075L,64076L,64077L,64078L,64079L,64080L,64081L,64082L,64083L,64084L,
98493 64085L,64086L,64087L,64088L,64089L,64090L,64091L,64092L,64093L,64094L,
98494 64095L,64096L,64097L,64098L,64099L,64100L,64101L,64102L,64103L,64104L,
98495 64105L,64106L,64107L,64108L,64109L,64110L,64111L,64112L,64113L,64114L,
98496 64115L,64116L,64117L,64118L,64119L,64120L,64121L,64122L,64123L,64124L,
98497 64125L,64126L,64127L,64128L,64129L,64130L,64131L,64132L,64133L,64134L,
98498 64135L,64136L,64137L,64138L,64139L,64140L,64141L,64142L,64143L,64144L,
98499 64145L,64146L,64147L,64148L,64149L,64150L,64151L,64152L,64153L,64154L,
98500 64155L,64156L,64157L,64158L,64159L,64160L,64161L,64162L,64163L,64164L,
98501 64165L,64166L,64167L,64168L,64169L,64170L,64171L,64172L,64173L,64174L,
98502 64175L,64176L,64177L,64178L,64179L,64180L,64181L,64182L,64183L,64184L,
98503 64185L,64186L,64187L,64188L,64189L,64190L,64191L,64192L,64193L,64194L,
98504 64195L,64196L,64197L,64198L,64199L,64200L,64201L,64202L,64203L,64204L,
98505 64205L,64206L,64207L,64208L,64209L,64210L,64211L,64212L,64213L,64214L,
98506 64215L,64216L,64217L,64218L,64219L,64220L,64221L,64222L,64223L,64224L,
98507 64225L,64226L,64227L,64228L,64229L,64230L,64231L,64232L,64233L,64234L,
98508 64235L,64236L,64237L,64238L,64239L,64240L,64241L,64242L,64243L,64244L,
98509 64245L,64246L,64247L,64248L,64249L,64250L,64251L,64252L,64253L,64254L,
98510 64255L,64256L,64257L,64258L,64259L,64260L,64261L,64262L,64263L,64264L,
98511 64265L,64266L,64267L,64268L,64269L,64270L,64271L,64272L,64273L,64274L,
98512 64275L,64276L,64277L,64278L,64279L,64280L,64281L,64282L,64283L,64284L,
98513 64285L,64286L,64287L,64288L,64289L,64290L,64291L,64292L,64293L,64294L,
98514 64295L,64296L,64297L,64298L,64299L,64300L,64301L,64302L,64303L,64304L,
98515 64305L,64306L,64307L,64308L,64309L,64310L,64311L,64312L,64313L,64314L,
98516 64315L,64316L,64317L,64318L,64319L,64320L,64321L,64322L,64323L,64324L,
98517 64325L,64326L,64327L,64328L,64329L,64330L,64331L,64332L,64333L,64334L,
98518 64335L,64336L,64337L,64338L,64339L,64340L,64341L,64342L,64343L,64344L,
98519 64345L,64346L,64347L,64348L,64349L,64350L,64351L,64352L,64353L,64354L,
98520 64355L,64356L,64357L,64358L,64359L,64360L,64361L,64362L,64363L,64364L,
98521 64365L,64366L,64367L,64368L,64369L,64370L,64371L,64372L,64373L,64374L,
98522 64375L,64376L,64377L,64378L,64379L,64380L,64381L,64382L,64383L,64384L,
98523 64385L,64386L,64387L,64388L,64389L,64390L,64391L,64392L,64393L,64394L,
98524 64395L,64396L,64397L,64398L,64399L,64400L,64401L,64402L,64403L,64404L,
98525 64405L,64406L,64407L,64408L,64409L,64410L,64411L,64412L,64413L,64414L,
98526 64415L,64416L,64417L,64418L,64419L,64420L,64421L,64422L,64423L,64424L,
98527 64425L,64426L,64427L,64428L,64429L,64430L,64431L,64432L,64433L,64434L,
98528 64435L,64436L,64437L,64438L,64439L,64440L,64441L,64442L,64443L,64444L,
98529 64445L,64446L,64447L,64448L,64449L,64450L,64451L,64452L,64453L,64454L,
98530 64455L,64456L,64457L,64458L,64459L,64460L,64461L,64462L,64463L,64464L,
98531 64465L,64466L,64467L,64468L,64469L,64470L,64471L,64472L,64473L,64474L,
98532 64475L,64476L,64477L,64478L,64479L,64480L,64481L,64482L,64483L,64484L,
98533 64485L,64486L,64487L,64488L,64489L,64490L,64491L,64492L,64493L,64494L,
98534 64495L,64496L,64497L,64498L,64499L,64500L,64501L,64502L,64503L,64504L,
98535 64505L,64506L,64507L,64508L,64509L,64510L,64511L,64512L,64513L,64514L,
98536 64515L,64516L,64517L,64518L,64519L,64520L,64521L,64522L,64523L,64524L,
98537 64525L,64526L,64527L,64528L,64529L,64530L,64531L,64532L,64533L,64534L,
98538 64535L,64536L,64537L,64538L,64539L,64540L,64541L,64542L,64543L,64544L,
98539 64545L,64546L,64547L,64548L,64549L,64550L,64551L,64552L,64553L,64554L,
98540 64555L,64556L,64557L,64558L,64559L,64560L,64561L,64562L,64563L,64564L,
98541 64565L,64566L,64567L,64568L,64569L,64570L,64571L,64572L,64573L,64574L,
98542 64575L,64576L,64577L,64578L,64579L,64580L,64581L,64582L,64583L,64584L,
98543 64585L,64586L,64587L,64588L,64589L,64590L,64591L,64592L,64593L,64594L,
98544 64595L,64596L,64597L,64598L,64599L,64600L,64601L,64602L,64603L,64604L,
98545 64605L,64606L,64607L,64608L,64609L,64610L,64611L,64612L,64613L,64614L,
98546 64615L,64616L,64617L,64618L,64619L,64620L,64621L,64622L,64623L,64624L,
98547 64625L,64626L,64627L,64628L,64629L,64630L,64631L,64632L,64633L,64634L,
98548 64635L,64636L,64637L,64638L,64639L,64640L,64641L,64642L,64643L,64644L,
98549 64645L,64646L,64647L,64648L,64649L,64650L,64651L,64652L,64653L,64654L,
98550 64655L,64656L,64657L,64658L,64659L,64660L,64661L,64662L,64663L,64664L,
98551 64665L,64666L,64667L,64668L,64669L,64670L,64671L,64672L,64673L,64674L,
98552 64675L,64676L,64677L,64678L,64679L,64680L,64681L,64682L,64683L,64684L,
98553 64685L,64686L,64687L,64688L,64689L,64690L,64691L,64692L,64693L,64694L,
98554 64695L,64696L,64697L,64698L,64699L,64700L,64701L,64702L,64703L,64704L,
98555 64705L,64706L,64707L,64708L,64709L,64710L,64711L,64712L,64713L,64714L,
98556 64715L,64716L,64717L,64718L,64719L,64720L,64721L,64722L,64723L,64724L,
98557 64725L,64726L,64727L,64728L,64729L,64730L,64731L,64732L,64733L,64734L,
98558 64735L,64736L,64737L,64738L,64739L,64740L,64741L,64742L,64743L,64744L,
98559 64745L,64746L,64747L,64748L,64749L,64750L,64751L,64752L,64753L,64754L,
98560 64755L,64756L,64757L,64758L,64759L,64760L,64761L,64762L,64763L,64764L,
98561 64765L,64766L,64767L,64768L,64769L,64770L,64771L,64772L,64773L,64774L,
98562 64775L,64776L,64777L,64778L,64779L,64780L,64781L,64782L,64783L,64784L,
98563 64785L,64786L,64787L,64788L,64789L,64790L,64791L,64792L,64793L,64794L,
98564 64795L,64796L,64797L,64798L,64799L,64800L,64801L,64802L,64803L,64804L,
98565 64805L,64806L,64807L,64808L,64809L,64810L,64811L,64812L,64813L,64814L,
98566 64815L,64816L,64817L,64818L,64819L,64820L,64821L,64822L,64823L,64824L,
98567 64825L,64826L,64827L,64828L,64829L,64830L,64831L,64832L,64833L,64834L,
98568 64835L,64836L,64837L,64838L,64839L,64840L,64841L,64842L,64843L,64844L,
98569 64845L,64846L,64847L,64848L,64849L,64850L,64851L,64852L,64853L,64854L,
98570 64855L,64856L,64857L,64858L,64859L,64860L,64861L,64862L,64863L,64864L,
98571 64865L,64866L,64867L,64868L,64869L,64870L,64871L,64872L,64873L,64874L,
98572 64875L,64876L,64877L,64878L,64879L,64880L,64881L,64882L,64883L,64884L,
98573 64885L,64886L,64887L,64888L,64889L,64890L,64891L,64892L,64893L,64894L,
98574 64895L,64896L,64897L,64898L,64899L,64900L,64901L,64902L,64903L,64904L,
98575 64905L,64906L,64907L,64908L,64909L,64910L,64911L,64912L,64913L,64914L,
98576 64915L,64916L,64917L,64918L,64919L,64920L,64921L,64922L,64923L,64924L,
98577 64925L,64926L,64927L,64928L,64929L,64930L,64931L,64932L,64933L,64934L,
98578 64935L,64936L,64937L,64938L,64939L,64940L,64941L,64942L,64943L,64944L,
98579 64945L,64946L,64947L,64948L,64949L,64950L,64951L,64952L,64953L,64954L,
98580 64955L,64956L,64957L,64958L,64959L,64960L,64961L,64962L,64963L,64964L,
98581 64965L,64966L,64967L,64968L,64969L,64970L,64971L,64972L,64973L,64974L,
98582 64975L,64976L,64977L,64978L,64979L,64980L,64981L,64982L,64983L,64984L,
98583 64985L,64986L,64987L,64988L,64989L,64990L,64991L,64992L,64993L,64994L,
98584 64995L,64996L,64997L,64998L,64999L,65000L,65001L,65002L,65003L,65004L,
98585 65005L,65006L,65007L,65008L,65009L,65010L,65011L,65012L,65013L,65014L,
98586 65015L,65016L,65017L,65018L,65019L,65020L,65021L,65022L,65023L,65024L,
98587 65025L,65026L,65027L,65028L,65029L,65030L,65031L,65032L,65033L,65034L,
98588 65035L,65036L,65037L,65038L,65039L,65040L,65041L,65042L,65043L,65044L,
98589 65045L,65046L,65047L,65048L,65049L,65050L,65051L,65052L,65053L,65054L,
98590 65055L,65056L,65057L,65058L,65059L,65060L,65061L,65062L,65063L,65064L,
98591 65065L,65066L,65067L,65068L,65069L,65070L,65071L,65072L,65073L,65074L,
98592 65075L,65076L,65077L,65078L,65079L,65080L,65081L,65082L,65083L,65084L,
98593 65085L,65086L,65087L,65088L,65089L,65090L,65091L,65092L,65093L,65094L,
98594 65095L,65096L,65097L,65098L,65099L,65100L,65101L,65102L,65103L,65104L,
98595 65105L,65106L,65107L,65108L,65109L,65110L,65111L,65112L,65113L,65114L,
98596 65115L,65116L,65117L,65118L,65119L,65120L,65121L,65122L,65123L,65124L,
98597 65125L,65126L,65127L,65128L,65129L,65130L,65131L,65132L,65133L,65134L,
98598 65135L,65136L,65137L,65138L,65139L,65140L,65141L,65142L,65143L,65144L,
98599 65145L,65146L,65147L,65148L,65149L,65150L,65151L,65152L,65153L,65154L,
98600 65155L,65156L,65157L,65158L,65159L,65160L,65161L,65162L,65163L,65164L,
98601 65165L,65166L,65167L,65168L,65169L,65170L,65171L,65172L,65173L,65174L,
98602 65175L,65176L,65177L,65178L,65179L,65180L,65181L,65182L,65183L,65184L,
98603 65185L,65186L,65187L,65188L,65189L,65190L,65191L,65192L,65193L,65194L,
98604 65195L,65196L,65197L,65198L,65199L,65200L,65201L,65202L,65203L,65204L,
98605 65205L,65206L,65207L,65208L,65209L,65210L,65211L,65212L,65213L,65214L,
98606 65215L,65216L,65217L,65218L,65219L,65220L,65221L,65222L,65223L,65224L,
98607 65225L,65226L,65227L,65228L,65229L,65230L,65231L,65232L,65233L,65234L,
98608 65235L,65236L,65237L,65238L,65239L,65240L,65241L,65242L,65243L,65244L,
98609 65245L,65246L,65247L,65248L,65249L,65250L,65251L,65252L,65253L,65254L,
98610 65255L,65256L,65257L,65258L,65259L,65260L,65261L,65262L,65263L,65264L,
98611 65265L,65266L,65267L,65268L,65269L,65270L,65271L,65272L,65273L,65274L,
98612 65275L,65276L,65277L,65278L,65279L,65280L,65281L,65282L,65283L,65284L,
98613 65285L,65286L,65287L,65288L,65289L,65290L,65291L,65292L,65293L,65294L,
98614 65295L,65296L,65297L,65298L,65299L,65300L,65301L,65302L,65303L,65304L,
98615 65305L,65306L,65307L,65308L,65309L,65310L,65311L,65312L,65313L,65314L,
98616 65315L,65316L,65317L,65318L,65319L,65320L,65321L,65322L,65323L,65324L,
98617 65325L,65326L,65327L,65328L,65329L,65330L,65331L,65332L,65333L,65334L,
98618 65335L,65336L,65337L,65338L,65339L,65340L,65341L,65342L,65343L,65344L,
98619 65313L,65314L,65315L,65316L,65317L,65318L,65319L,65320L,65321L,65322L,
98620 65323L,65324L,65325L,65326L,65327L,65328L,65329L,65330L,65331L,65332L,
98621 65333L,65334L,65335L,65336L,65337L,65338L,65371L,65372L,65373L,65374L,
98622 65375L,65376L,65377L,65378L,65379L,65380L,65381L,65382L,65383L,65384L,
98623 65385L,65386L,65387L,65388L,65389L,65390L,65391L,65392L,65393L,65394L,
98624 65395L,65396L,65397L,65398L,65399L,65400L,65401L,65402L,65403L,65404L,
98625 65405L,65406L,65407L,65408L,65409L,65410L,65411L,65412L,65413L,65414L,
98626 65415L,65416L,65417L,65418L,65419L,65420L,65421L,65422L,65423L,65424L,
98627 65425L,65426L,65427L,65428L,65429L,65430L,65431L,65432L,65433L,65434L,
98628 65435L,65436L,65437L,65438L,65439L,65440L,65441L,65442L,65443L,65444L,
98629 65445L,65446L,65447L,65448L,65449L,65450L,65451L,65452L,65453L,65454L,
98630 65455L,65456L,65457L,65458L,65459L,65460L,65461L,65462L,65463L,65464L,
98631 65465L,65466L,65467L,65468L,65469L,65470L,65471L,65472L,65473L,65474L,
98632 65475L,65476L,65477L,65478L,65479L,65480L,65481L,65482L,65483L,65484L,
98633 65485L,65486L,65487L,65488L,65489L,65490L,65491L,65492L,65493L,65494L,
98634 65495L,65496L,65497L,65498L,65499L,65500L,65501L,65502L,65503L,65504L,
98635 65505L,65506L,65507L,65508L,65509L,65510L,65511L,65512L,65513L,65514L,
98636 65515L,65516L,65517L,65518L,65519L,65520L,65521L,65522L,65523L,65524L,
98637 65525L,65526L,65527L,65528L,65529L,65530L,65531L,65532L,65533L,65534L,
98638 65535L,
98639 };
98640 #endif
98641 
98642 #if defined(DUK_USE_REGEXP_CANON_BITMAP)
98643 /*
98644  *  Automatically generated by extract_caseconv.py, do not edit!
98645  */
98646 
98647 const duk_uint8_t duk_unicode_re_canon_bitmap[256] = {
98648 23,0,224,19,1,228,255,255,255,255,255,255,255,255,255,255,63,254,255,127,
98649 255,255,255,255,255,255,255,255,231,231,0,16,255,227,255,255,63,255,255,
98650 255,255,255,255,255,1,252,255,255,255,255,255,255,255,255,255,255,255,255,
98651 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
98652 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
98653 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
98654 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
98655 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
98656 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
98657 227,129,255,255,255,147,255,255,255,255,255,255,255,255,255,255,255,255,
98658 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
98659 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
98660 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
98661 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,251,
98662 };
98663 #endif
98664 #line 1 "duk_util_bitdecoder.c"
98665 /*
98666  *  Bitstream decoder.
98667  */
98668 
98669 /* #include duk_internal.h -> already included */
98670 
98671 /* Decode 'bits' bits from the input stream (bits must be 1...24).
98672  * When reading past bitstream end, zeroes are shifted in.  The result
98673  * is signed to match duk_bd_decode_flagged.
98674  */
98675 DUK_INTERNAL duk_uint32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits) {
98676 	duk_small_int_t shift;
98677 	duk_uint32_t mask;
98678 	duk_uint32_t tmp;
98679 
98680 	/* Note: cannot read more than 24 bits without possibly shifting top bits out.
98681 	 * Fixable, but adds complexity.
98682 	 */
98683 	DUK_ASSERT(bits >= 1 && bits <= 24);
98684 
98685 	while (ctx->currbits < bits) {
98686 #if 0
98687 		DUK_DDD(DUK_DDDPRINT("decode_bits: shift more data (bits=%ld, currbits=%ld)",
98688 		                     (long) bits, (long) ctx->currbits));
98689 #endif
98690 		ctx->currval <<= 8;
98691 		if (ctx->offset < ctx->length) {
98692 			/* If ctx->offset >= ctx->length, we "shift zeroes in"
98693 			 * instead of croaking.
98694 			 */
98695 			ctx->currval |= ctx->data[ctx->offset++];
98696 		}
98697 		ctx->currbits += 8;
98698 	}
98699 #if 0
98700 	DUK_DDD(DUK_DDDPRINT("decode_bits: bits=%ld, currbits=%ld, currval=0x%08lx",
98701 	                     (long) bits, (long) ctx->currbits, (unsigned long) ctx->currval));
98702 #endif
98703 
98704 	/* Extract 'top' bits of currval; note that the extracted bits do not need
98705 	 * to be cleared, we just ignore them on next round.
98706 	 */
98707 	shift = ctx->currbits - bits;
98708 	mask = (((duk_uint32_t) 1U) << bits) - 1U;
98709 	tmp = (ctx->currval >> shift) & mask;
98710 	ctx->currbits = shift;  /* remaining */
98711 
98712 #if 0
98713 	DUK_DDD(DUK_DDDPRINT("decode_bits: %ld bits -> 0x%08lx (%ld), currbits=%ld, currval=0x%08lx",
98714 	                     (long) bits, (unsigned long) tmp, (long) tmp, (long) ctx->currbits, (unsigned long) ctx->currval));
98715 #endif
98716 
98717 	return tmp;
98718 }
98719 
98720 DUK_INTERNAL duk_small_uint_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx) {
98721 	return (duk_small_uint_t) duk_bd_decode(ctx, 1);
98722 }
98723 
98724 /* Decode a one-bit flag, and if set, decode a value of 'bits', otherwise return
98725  * default value.
98726  */
98727 DUK_INTERNAL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value) {
98728 	if (duk_bd_decode_flag(ctx)) {
98729 		return duk_bd_decode(ctx, bits);
98730 	} else {
98731 		return def_value;
98732 	}
98733 }
98734 
98735 /* Signed variant, allows negative marker value. */
98736 DUK_INTERNAL duk_int32_t duk_bd_decode_flagged_signed(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value) {
98737 	return (duk_int32_t) duk_bd_decode_flagged(ctx, bits, (duk_uint32_t) def_value);
98738 }
98739 
98740 /* Shared varint encoding.  Match dukutil.py BitEncode.varuint(). */
98741 DUK_INTERNAL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx) {
98742 	duk_small_uint_t t;
98743 
98744 	/* The bit encoding choices here are based on manual testing against
98745 	 * the actual varuints generated by genbuiltins.py.
98746 	 */
98747 	switch (duk_bd_decode(ctx, 2)) {
98748 	case 0:
98749 		return 0;  /* [0,0] */
98750 	case 1:
98751 		return duk_bd_decode(ctx, 2) + 1;  /* [1,4] */
98752 	case 2:
98753 		return duk_bd_decode(ctx, 5) + 5;  /* [5,36] */
98754 	default:
98755 		t = duk_bd_decode(ctx, 7);
98756 		if (t == 0) {
98757 			return duk_bd_decode(ctx, 20);
98758 		}
98759 		return (t - 1) + 37;  /* [37,163] */
98760 	}
98761 }
98762 
98763 /* Decode a bit packed string from a custom format used by genbuiltins.py.
98764  * This function is here because it's used for both heap and thread inits.
98765  * Caller must supply the output buffer whose size is NOT checked!
98766  */
98767 
98768 #define DUK__BITPACK_LETTER_LIMIT  26
98769 #define DUK__BITPACK_LOOKUP1       26
98770 #define DUK__BITPACK_LOOKUP2       27
98771 #define DUK__BITPACK_SWITCH1       28
98772 #define DUK__BITPACK_SWITCH        29
98773 #define DUK__BITPACK_UNUSED1       30
98774 #define DUK__BITPACK_EIGHTBIT      31
98775 
98776 DUK_LOCAL const duk_uint8_t duk__bitpacked_lookup[16] = {
98777 	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
98778 	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
98779 	DUK_ASC_8, DUK_ASC_9, DUK_ASC_UNDERSCORE, DUK_ASC_SPACE,
98780 	0x82, 0x80, DUK_ASC_DOUBLEQUOTE, DUK_ASC_LCURLY
98781 };
98782 
98783 DUK_INTERNAL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx *bd, duk_uint8_t *out) {
98784 	duk_small_uint_t len;
98785 	duk_small_uint_t mode;
98786 	duk_small_uint_t t;
98787 	duk_small_uint_t i;
98788 
98789 	len = duk_bd_decode(bd, 5);
98790 	if (len == 31) {
98791 		len = duk_bd_decode(bd, 8);  /* Support up to 256 bytes; rare. */
98792 	}
98793 
98794 	mode = 32;  /* 0 = uppercase, 32 = lowercase (= 'a' - 'A') */
98795 	for (i = 0; i < len; i++) {
98796 		t = duk_bd_decode(bd, 5);
98797 		if (t < DUK__BITPACK_LETTER_LIMIT) {
98798 			t = t + DUK_ASC_UC_A + mode;
98799 		} else if (t == DUK__BITPACK_LOOKUP1) {
98800 			t = duk__bitpacked_lookup[duk_bd_decode(bd, 3)];
98801 		} else if (t == DUK__BITPACK_LOOKUP2) {
98802 			t = duk__bitpacked_lookup[8 + duk_bd_decode(bd, 3)];
98803 		} else if (t == DUK__BITPACK_SWITCH1) {
98804 			t = duk_bd_decode(bd, 5);
98805 			DUK_ASSERT_DISABLE(t >= 0);  /* unsigned */
98806 			DUK_ASSERT(t <= 25);
98807 			t = t + DUK_ASC_UC_A + (mode ^ 32);
98808 		} else if (t == DUK__BITPACK_SWITCH) {
98809 			mode = mode ^ 32;
98810 			t = duk_bd_decode(bd, 5);
98811 			DUK_ASSERT_DISABLE(t >= 0);
98812 			DUK_ASSERT(t <= 25);
98813 			t = t + DUK_ASC_UC_A + mode;
98814 		} else if (t == DUK__BITPACK_EIGHTBIT) {
98815 			t = duk_bd_decode(bd, 8);
98816 		}
98817 		out[i] = (duk_uint8_t) t;
98818 	}
98819 
98820 	return len;
98821 }
98822 
98823 /* automatic undefs */
98824 #undef DUK__BITPACK_EIGHTBIT
98825 #undef DUK__BITPACK_LETTER_LIMIT
98826 #undef DUK__BITPACK_LOOKUP1
98827 #undef DUK__BITPACK_LOOKUP2
98828 #undef DUK__BITPACK_SWITCH
98829 #undef DUK__BITPACK_SWITCH1
98830 #undef DUK__BITPACK_UNUSED1
98831 #line 1 "duk_util_bitencoder.c"
98832 /*
98833  *  Bitstream encoder.
98834  */
98835 
98836 /* #include duk_internal.h -> already included */
98837 
98838 DUK_INTERNAL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits) {
98839 	duk_uint8_t tmp;
98840 
98841 	DUK_ASSERT(ctx != NULL);
98842 	DUK_ASSERT(ctx->currbits < 8);
98843 
98844 	/* This limitation would be fixable but adds unnecessary complexity. */
98845 	DUK_ASSERT(bits >= 1 && bits <= 24);
98846 
98847 	ctx->currval = (ctx->currval << bits) | data;
98848 	ctx->currbits += bits;
98849 
98850 	while (ctx->currbits >= 8) {
98851 		if (ctx->offset < ctx->length) {
98852 			tmp = (duk_uint8_t) ((ctx->currval >> (ctx->currbits - 8)) & 0xff);
98853 			ctx->data[ctx->offset++] = tmp;
98854 		} else {
98855 			/* If buffer has been exhausted, truncate bitstream */
98856 			ctx->truncated = 1;
98857 		}
98858 
98859 		ctx->currbits -= 8;
98860 	}
98861 }
98862 
98863 DUK_INTERNAL void duk_be_finish(duk_bitencoder_ctx *ctx) {
98864 	duk_small_int_t npad;
98865 
98866 	DUK_ASSERT(ctx != NULL);
98867 	DUK_ASSERT(ctx->currbits < 8);
98868 
98869 	npad = (duk_small_int_t) (8 - ctx->currbits);
98870 	if (npad > 0) {
98871 		duk_be_encode(ctx, 0, npad);
98872 	}
98873 	DUK_ASSERT(ctx->currbits == 0);
98874 }
98875 #line 1 "duk_util_bufwriter.c"
98876 /*
98877  *  Fast buffer writer with slack management.
98878  */
98879 
98880 /* #include duk_internal.h -> already included */
98881 
98882 /* XXX: Avoid duk_{memcmp,memmove}_unsafe() by imposing a minimum length of
98883  * >0 for the underlying dynamic buffer.
98884  */
98885 
98886 /*
98887  *  Macro support functions (use only macros in calling code)
98888  */
98889 
98890 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) {
98891 	duk_uint8_t *p;
98892 
98893 	DUK_ASSERT(thr != NULL);
98894 	DUK_ASSERT(bw_ctx != NULL);
98895 	DUK_UNREF(thr);
98896 
98897 	/* 'p' might be NULL when the underlying buffer is zero size.  If so,
98898 	 * the resulting pointers are not used unsafely.
98899 	 */
98900 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, bw_ctx->buf);
98901 	DUK_ASSERT(p != NULL || (DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0 && curr_offset == 0 && new_length == 0));
98902 	bw_ctx->p = p + curr_offset;
98903 	bw_ctx->p_base = p;
98904 	bw_ctx->p_limit = p + new_length;
98905 }
98906 
98907 DUK_INTERNAL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf) {
98908 	DUK_ASSERT(thr != NULL);
98909 	DUK_ASSERT(bw_ctx != NULL);
98910 	DUK_ASSERT(h_buf != NULL);
98911 
98912 	bw_ctx->buf = h_buf;
98913 	duk__bw_update_ptrs(thr, bw_ctx, 0, DUK_HBUFFER_DYNAMIC_GET_SIZE(h_buf));
98914 }
98915 
98916 DUK_INTERNAL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size) {
98917 	DUK_ASSERT(thr != NULL);
98918 	DUK_ASSERT(bw_ctx != NULL);
98919 
98920 	(void) duk_push_dynamic_buffer(thr, buf_size);
98921 	bw_ctx->buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, -1);
98922 	DUK_ASSERT(bw_ctx->buf != NULL);
98923 	duk__bw_update_ptrs(thr, bw_ctx, 0, buf_size);
98924 }
98925 
98926 /* Resize target buffer for requested size.  Called by the macro only when the
98927  * fast path test (= there is space) fails.
98928  */
98929 DUK_INTERNAL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz) {
98930 	duk_size_t curr_off;
98931 	duk_size_t add_sz;
98932 	duk_size_t new_sz;
98933 
98934 	DUK_ASSERT(thr != NULL);
98935 	DUK_ASSERT(bw_ctx != NULL);
98936 
98937 	/* We could do this operation without caller updating bw_ctx->ptr,
98938 	 * but by writing it back here we can share code better.
98939 	 */
98940 
98941 	curr_off = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
98942 	add_sz = (curr_off >> DUK_BW_SLACK_SHIFT) + DUK_BW_SLACK_ADD;
98943 	new_sz = curr_off + sz + add_sz;
98944 	if (DUK_UNLIKELY(new_sz < curr_off)) {
98945 		/* overflow */
98946 		DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);
98947 		DUK_WO_NORETURN(return NULL;);
98948 	}
98949 #if 0  /* for manual torture testing: tight allocation, useful with valgrind */
98950 	new_sz = curr_off + sz;
98951 #endif
98952 
98953 	/* This is important to ensure dynamic buffer data pointer is not
98954 	 * NULL (which is possible if buffer size is zero), which in turn
98955 	 * causes portability issues with e.g. memmove() and memcpy().
98956 	 */
98957 	DUK_ASSERT(new_sz >= 1);
98958 
98959 	DUK_DD(DUK_DDPRINT("resize bufferwriter from %ld to %ld (add_sz=%ld)", (long) curr_off, (long) new_sz, (long) add_sz));
98960 
98961 	duk_hbuffer_resize(thr, bw_ctx->buf, new_sz);
98962 	duk__bw_update_ptrs(thr, bw_ctx, curr_off, new_sz);
98963 	return bw_ctx->p;
98964 }
98965 
98966 /* Make buffer compact, matching current written size. */
98967 DUK_INTERNAL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx) {
98968 	duk_size_t len;
98969 
98970 	DUK_ASSERT(thr != NULL);
98971 	DUK_ASSERT(bw_ctx != NULL);
98972 	DUK_UNREF(thr);
98973 
98974 	len = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
98975 	duk_hbuffer_resize(thr, bw_ctx->buf, len);
98976 	duk__bw_update_ptrs(thr, bw_ctx, len, len);
98977 }
98978 
98979 DUK_INTERNAL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) {
98980 	duk_uint8_t *p_base;
98981 
98982 	DUK_ASSERT(thr != NULL);
98983 	DUK_ASSERT(bw != NULL);
98984 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
98985 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
98986 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
98987 	DUK_UNREF(thr);
98988 
98989 	p_base = bw->p_base;
98990 	duk_memcpy_unsafe((void *) bw->p,
98991 	                  (const void *) (p_base + src_off),
98992 	                  (size_t) len);
98993 	bw->p += len;
98994 }
98995 
98996 DUK_INTERNAL void duk_bw_write_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) {
98997 	DUK_ASSERT(thr != NULL);
98998 	DUK_ASSERT(bw != NULL);
98999 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
99000 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
99001 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
99002 
99003 	DUK_BW_ENSURE(thr, bw, len);
99004 	duk_bw_write_raw_slice(thr, bw, src_off, len);
99005 }
99006 
99007 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) {
99008 	duk_uint8_t *p_base;
99009 	duk_size_t buf_sz, move_sz;
99010 
99011 	DUK_ASSERT(thr != NULL);
99012 	DUK_ASSERT(bw != NULL);
99013 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
99014 	DUK_ASSERT(buf != NULL);
99015 	DUK_UNREF(thr);
99016 
99017 	p_base = bw->p_base;
99018 	buf_sz = (duk_size_t) (bw->p - p_base);  /* constrained by maximum buffer size */
99019 	move_sz = buf_sz - dst_off;
99020 
99021 	DUK_ASSERT(p_base != NULL);  /* buffer size is >= 1 */
99022 	duk_memmove_unsafe((void *) (p_base + dst_off + len),
99023 	                   (const void *) (p_base + dst_off),
99024 	                   (size_t) move_sz);
99025 	duk_memcpy_unsafe((void *) (p_base + dst_off),
99026 	                  (const void *) buf,
99027 	                  (size_t) len);
99028 	bw->p += len;
99029 }
99030 
99031 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) {
99032 	DUK_ASSERT(thr != NULL);
99033 	DUK_ASSERT(bw != NULL);
99034 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
99035 	DUK_ASSERT(buf != NULL);
99036 
99037 	DUK_BW_ENSURE(thr, bw, len);
99038 	duk_bw_insert_raw_bytes(thr, bw, dst_off, buf, len);
99039 }
99040 
99041 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) {
99042 	duk_uint8_t *p_base;
99043 	duk_size_t buf_sz, move_sz;
99044 
99045 	DUK_ASSERT(thr != NULL);
99046 	DUK_ASSERT(bw != NULL);
99047 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
99048 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
99049 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
99050 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
99051 	DUK_UNREF(thr);
99052 
99053 	p_base = bw->p_base;
99054 
99055 	/* Don't support "straddled" source now. */
99056 	DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
99057 
99058 	if (dst_off <= src_off) {
99059 		/* Target is before source.  Source offset is expressed as
99060 		 * a "before change" offset.  Account for the memmove.
99061 		 */
99062 		src_off += len;
99063 	}
99064 
99065 	buf_sz = (duk_size_t) (bw->p - p_base);
99066 	move_sz = buf_sz - dst_off;
99067 
99068 	DUK_ASSERT(p_base != NULL);  /* buffer size is >= 1 */
99069 	duk_memmove_unsafe((void *) (p_base + dst_off + len),
99070 	                   (const void *) (p_base + dst_off),
99071 	                   (size_t) move_sz);
99072 	duk_memcpy_unsafe((void *) (p_base + dst_off),
99073 	                  (const void *) (p_base + src_off),
99074 	                  (size_t) len);
99075 	bw->p += len;
99076 }
99077 
99078 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) {
99079 	DUK_ASSERT(thr != NULL);
99080 	DUK_ASSERT(bw != NULL);
99081 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
99082 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
99083 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
99084 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
99085 
99086 	/* Don't support "straddled" source now. */
99087 	DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
99088 
99089 	DUK_BW_ENSURE(thr, bw, len);
99090 	duk_bw_insert_raw_slice(thr, bw, dst_off, src_off, len);
99091 }
99092 
99093 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) {
99094 	duk_uint8_t *p_base, *p_dst, *p_src;
99095 	duk_size_t buf_sz, move_sz;
99096 
99097 	DUK_ASSERT(thr != NULL);
99098 	DUK_ASSERT(bw != NULL);
99099 	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
99100 	DUK_UNREF(thr);
99101 
99102 	p_base = bw->p_base;
99103 	buf_sz = (duk_size_t) (bw->p - p_base);
99104 	move_sz = buf_sz - off;
99105 	p_dst = p_base + off + len;
99106 	p_src = p_base + off;
99107 	duk_memmove_unsafe((void *) p_dst, (const void *) p_src, (size_t) move_sz);
99108 	return p_src;  /* point to start of 'reserved area' */
99109 }
99110 
99111 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) {
99112 	DUK_ASSERT(thr != NULL);
99113 	DUK_ASSERT(bw != NULL);
99114 	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
99115 
99116 	DUK_BW_ENSURE(thr, bw, len);
99117 	return duk_bw_insert_raw_area(thr, bw, off, len);
99118 }
99119 
99120 DUK_INTERNAL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) {
99121 	duk_size_t move_sz;
99122 
99123 	duk_uint8_t *p_base;
99124 	duk_uint8_t *p_src;
99125 	duk_uint8_t *p_dst;
99126 
99127 	DUK_ASSERT(thr != NULL);
99128 	DUK_ASSERT(bw != NULL);
99129 	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
99130 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
99131 	DUK_ASSERT(off + len <= DUK_BW_GET_SIZE(thr, bw));
99132 	DUK_UNREF(thr);
99133 
99134 	p_base = bw->p_base;
99135 	p_dst = p_base + off;
99136 	p_src = p_dst + len;
99137 	move_sz = (duk_size_t) (bw->p - p_src);
99138 	duk_memmove_unsafe((void *) p_dst,
99139 	                   (const void *) p_src,
99140 	                   (size_t) move_sz);
99141 	bw->p -= len;
99142 }
99143 
99144 /*
99145  *  Assertion helpers
99146  */
99147 
99148 #if defined(DUK_USE_ASSERTIONS)
99149 DUK_INTERNAL void duk_bw_assert_valid(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx) {
99150 	DUK_UNREF(thr);
99151 	DUK_ASSERT(bw_ctx != NULL);
99152 	DUK_ASSERT(bw_ctx->buf != NULL);
99153 	DUK_ASSERT((DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0) ||
99154 	           (bw_ctx->p != NULL &&
99155 	            bw_ctx->p_base != NULL &&
99156 	            bw_ctx->p_limit != NULL &&
99157 	            bw_ctx->p_limit >= bw_ctx->p_base &&
99158 	            bw_ctx->p >= bw_ctx->p_base &&
99159 	            bw_ctx->p <= bw_ctx->p_limit));
99160 }
99161 #endif
99162 #line 1 "duk_util_cast.c"
99163 /*
99164  *  Cast helpers.
99165  *
99166  *  C99+ coercion is challenging portability-wise because out-of-range casts
99167  *  may invoke implementation defined or even undefined behavior.  See e.g.
99168  *  http://blog.frama-c.com/index.php?post/2013/10/09/Overflow-float-integer.
99169  *
99170  *  Provide explicit cast helpers which try to avoid implementation defined
99171  *  or undefined behavior.  These helpers can then be simplified in the vast
99172  *  majority of cases where the implementation defined or undefined behavior
99173  *  is not problematic.
99174  */
99175 
99176 /* #include duk_internal.h -> already included */
99177 
99178 /* Portable double-to-integer cast which avoids undefined behavior and avoids
99179  * relying on fmin(), fmax(), or other intrinsics.  Out-of-range results are
99180  * not assumed by caller, but here value is clamped, NaN converts to minval.
99181  */
99182 #define DUK__DOUBLE_INT_CAST1(tname,minval,maxval)  do { \
99183 		if (DUK_LIKELY(x >= (duk_double_t) (minval))) { \
99184 			DUK_ASSERT(!DUK_ISNAN(x)); \
99185 			if (DUK_LIKELY(x <= (duk_double_t) (maxval))) { \
99186 				return (tname) x; \
99187 			} else { \
99188 				return (tname) (maxval); \
99189 			} \
99190 		} else { \
99191 			/* NaN or below minval.  Since we don't care about the result \
99192 			 * for out-of-range values, just return the minimum value for \
99193 			 * both. \
99194 			 */ \
99195 			return (tname) (minval); \
99196 		} \
99197 	} while (0)
99198 
99199 /* Rely on specific NaN behavior for duk_double_{fmin,fmax}(): if either
99200  * argument is a NaN, return the second argument.  This avoids a
99201  * NaN-to-integer cast which is undefined behavior.
99202  */
99203 #define DUK__DOUBLE_INT_CAST2(tname,minval,maxval)  do { \
99204 		return (tname) duk_double_fmin(duk_double_fmax(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
99205 	} while (0)
99206 
99207 /* Another solution which doesn't need C99+ behavior for fmin() and fmax(). */
99208 #define DUK__DOUBLE_INT_CAST3(tname,minval,maxval)  do { \
99209 		if (DUK_ISNAN(x)) { \
99210 			/* 0 or any other value is fine. */ \
99211 			return (tname) 0; \
99212 		} else \
99213 			return (tname) DUK_FMIN(DUK_FMAX(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
99214 		} \
99215 	} while (0)
99216 
99217 /* C99+ solution: relies on specific fmin() and fmax() behavior in C99: if
99218  * one argument is NaN but the other isn't, the non-NaN argument is returned.
99219  * Because the limits are non-NaN values, explicit NaN check is not needed.
99220  * This may not work on all legacy platforms, and also doesn't seem to inline
99221  * the fmin() and fmax() calls (unless one uses -ffast-math which we don't
99222  * support).
99223  */
99224 #define DUK__DOUBLE_INT_CAST4(tname,minval,maxval)  do { \
99225 		return (tname) DUK_FMIN(DUK_FMAX(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
99226 	} while (0)
99227 
99228 DUK_INTERNAL duk_int_t duk_double_to_int_t(duk_double_t x) {
99229 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
99230 	/* Real world solution: almost any practical platform will provide
99231 	 * an integer value without any guarantees what it is (which is fine).
99232 	 */
99233 	return (duk_int_t) x;
99234 #else
99235 	DUK__DOUBLE_INT_CAST1(duk_int_t, DUK_INT_MIN, DUK_INT_MAX);
99236 #endif
99237 }
99238 
99239 DUK_INTERNAL duk_uint_t duk_double_to_uint_t(duk_double_t x) {
99240 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
99241 	return (duk_uint_t) x;
99242 #else
99243 	DUK__DOUBLE_INT_CAST1(duk_uint_t, DUK_UINT_MIN, DUK_UINT_MAX);
99244 #endif
99245 }
99246 
99247 DUK_INTERNAL duk_int32_t duk_double_to_int32_t(duk_double_t x) {
99248 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
99249 	return (duk_int32_t) x;
99250 #else
99251 	DUK__DOUBLE_INT_CAST1(duk_int32_t, DUK_INT32_MIN, DUK_INT32_MAX);
99252 #endif
99253 }
99254 
99255 DUK_INTERNAL duk_uint32_t duk_double_to_uint32_t(duk_double_t x) {
99256 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
99257 	return (duk_uint32_t) x;
99258 #else
99259 	DUK__DOUBLE_INT_CAST1(duk_uint32_t, DUK_UINT32_MIN, DUK_UINT32_MAX);
99260 #endif
99261 }
99262 
99263 /* Largest IEEE double that doesn't round to infinity in the default rounding
99264  * mode.  The exact midpoint between (1 - 2^(-24)) * 2^128 and 2^128 rounds to
99265  * infinity, at least on x64.  This number is one double unit below that
99266  * midpoint.  See misc/float_cast.c.
99267  */
99268 #define DUK__FLOAT_ROUND_LIMIT      340282356779733623858607532500980858880.0
99269 
99270 /* Maximum IEEE float.  Double-to-float conversion above this would be out of
99271  * range and thus technically undefined behavior.
99272  */
99273 #define DUK__FLOAT_MAX              340282346638528859811704183484516925440.0
99274 
99275 DUK_INTERNAL duk_float_t duk_double_to_float_t(duk_double_t x) {
99276 	/* Even a double-to-float cast is technically undefined behavior if
99277 	 * the double is out-of-range.  C99 Section 6.3.1.5:
99278 	 *
99279 	 *   If the value being converted is in the range of values that can
99280 	 *   be represented but cannot be represented exactly, the result is
99281 	 *   either the nearest higher or nearest lower representable value,
99282 	 *   chosen in an implementation-defined manner.  If the value being
99283 	 *   converted is outside the range of values that can be represented,
99284 	 *   the behavior is undefined.
99285 	 */
99286 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
99287 	return (duk_float_t) x;
99288 #else
99289 	duk_double_t t;
99290 
99291 	t = DUK_FABS(x);
99292 	DUK_ASSERT((DUK_ISNAN(x) && DUK_ISNAN(t)) ||
99293 	           (!DUK_ISNAN(x) && !DUK_ISNAN(t)));
99294 
99295 	if (DUK_LIKELY(t <= DUK__FLOAT_MAX)) {
99296 		/* Standard in-range case, try to get here with a minimum
99297 		 * number of checks and branches.
99298 		 */
99299 		DUK_ASSERT(!DUK_ISNAN(x));
99300 		return (duk_float_t) x;
99301 	} else if (t <= DUK__FLOAT_ROUND_LIMIT) {
99302 		/* Out-of-range, but rounds to min/max float. */
99303 		DUK_ASSERT(!DUK_ISNAN(x));
99304 		if (x < 0.0) {
99305 			return (duk_float_t) -DUK__FLOAT_MAX;
99306 		} else {
99307 			return (duk_float_t) DUK__FLOAT_MAX;
99308 		}
99309 	} else if (DUK_ISNAN(x)) {
99310 		/* Assumes double NaN -> float NaN considered "in range". */
99311 		DUK_ASSERT(DUK_ISNAN(x));
99312 		return (duk_float_t) x;
99313 	} else {
99314 		/* Out-of-range, rounds to +/- Infinity. */
99315 		if (x < 0.0) {
99316 			return (duk_float_t) -DUK_DOUBLE_INFINITY;
99317 		} else {
99318 			return (duk_float_t) DUK_DOUBLE_INFINITY;
99319 		}
99320 	}
99321 #endif
99322 }
99323 
99324 /* automatic undefs */
99325 #undef DUK__DOUBLE_INT_CAST1
99326 #undef DUK__DOUBLE_INT_CAST2
99327 #undef DUK__DOUBLE_INT_CAST3
99328 #undef DUK__DOUBLE_INT_CAST4
99329 #undef DUK__FLOAT_MAX
99330 #undef DUK__FLOAT_ROUND_LIMIT
99331 #line 1 "duk_util_double.c"
99332 /*
99333  *  IEEE double helpers.
99334  */
99335 
99336 /* #include duk_internal.h -> already included */
99337 
99338 DUK_INTERNAL duk_bool_t duk_double_is_anyinf(duk_double_t x) {
99339 	duk_double_union du;
99340 	du.d = x;
99341 	return DUK_DBLUNION_IS_ANYINF(&du);
99342 }
99343 
99344 DUK_INTERNAL duk_bool_t duk_double_is_posinf(duk_double_t x) {
99345 	duk_double_union du;
99346 	du.d = x;
99347 	return DUK_DBLUNION_IS_POSINF(&du);
99348 }
99349 
99350 DUK_INTERNAL duk_bool_t duk_double_is_neginf(duk_double_t x) {
99351 	duk_double_union du;
99352 	du.d = x;
99353 	return DUK_DBLUNION_IS_NEGINF(&du);
99354 }
99355 
99356 DUK_INTERNAL duk_bool_t duk_double_is_nan(duk_double_t x) {
99357 	duk_double_union du;
99358 	du.d = x;
99359 	/* Assumes we're dealing with a Duktape internal NaN which is
99360 	 * NaN normalized if duk_tval requires it.
99361 	 */
99362 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
99363 	return DUK_DBLUNION_IS_NAN(&du);
99364 }
99365 
99366 DUK_INTERNAL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x) {
99367 	duk_double_union du;
99368 	du.d = x;
99369 	/* Assumes we're dealing with a Duktape internal NaN which is
99370 	 * NaN normalized if duk_tval requires it.
99371 	 */
99372 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
99373 	return DUK_DBLUNION_IS_NAN(&du) || DUK_DBLUNION_IS_ANYZERO(&du);
99374 }
99375 
99376 DUK_INTERNAL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x) {
99377 	duk_double_union du;
99378 	du.d = x;
99379 	/* If exponent is 0x7FF the argument is either a NaN or an
99380 	 * infinity.  We don't need to check any other fields.
99381 	 */
99382 #if defined(DUK_USE_64BIT_OPS)
99383 #if defined(DUK_USE_DOUBLE_ME)
99384 	return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000);
99385 #else
99386 	return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000);
99387 #endif
99388 #else
99389 	return (du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL;
99390 #endif
99391 }
99392 
99393 DUK_INTERNAL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x) {
99394 	duk_double_union du;
99395 #if defined(DUK_USE_64BIT_OPS)
99396 	duk_uint64_t t;
99397 #else
99398 	duk_uint32_t t;
99399 #endif
99400 	du.d = x;
99401 #if defined(DUK_USE_64BIT_OPS)
99402 #if defined(DUK_USE_DOUBLE_ME)
99403 	t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000);
99404 	if (t == DUK_U64_CONSTANT(0x0000000000000000)) {
99405 		t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x0000000080000000);
99406 		return t == 0;
99407 	}
99408 	if (t == DUK_U64_CONSTANT(0x000000007ff00000)) {
99409 		return 1;
99410 	}
99411 #else
99412 	t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000);
99413 	if (t == DUK_U64_CONSTANT(0x0000000000000000)) {
99414 		t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x8000000000000000);
99415 		return t == 0;
99416 	}
99417 	if (t == DUK_U64_CONSTANT(0x7ff0000000000000)) {
99418 		return 1;
99419 	}
99420 #endif
99421 #else
99422 	t = du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL;
99423 	if (t == 0x00000000UL) {
99424 		return DUK_DBLUNION_IS_ANYZERO(&du);
99425 	}
99426 	if (t == 0x7ff00000UL) {
99427 		return 1;
99428 	}
99429 #endif
99430 	return 0;
99431 }
99432 
99433 DUK_INTERNAL duk_small_uint_t duk_double_signbit(duk_double_t x) {
99434 	duk_double_union du;
99435 	du.d = x;
99436 	return (duk_small_uint_t) DUK_DBLUNION_GET_SIGNBIT(&du);
99437 }
99438 
99439 DUK_INTERNAL duk_double_t duk_double_trunc_towards_zero(duk_double_t x) {
99440 	/* XXX: optimize */
99441 	duk_small_uint_t s = duk_double_signbit(x);
99442 	x = DUK_FLOOR(DUK_FABS(x));  /* truncate towards zero */
99443 	if (s) {
99444 		x = -x;
99445 	}
99446 	return x;
99447 }
99448 
99449 DUK_INTERNAL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y) {
99450 	duk_double_union du1;
99451 	duk_double_union du2;
99452 	du1.d = x;
99453 	du2.d = y;
99454 
99455 	return (((du1.ui[DUK_DBL_IDX_UI0] ^ du2.ui[DUK_DBL_IDX_UI0]) & 0x80000000UL) == 0);
99456 }
99457 
99458 DUK_INTERNAL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y) {
99459 	/* Doesn't replicate fmin() behavior exactly: for fmin() if one
99460 	 * argument is a NaN, the other argument should be returned.
99461 	 * Duktape doesn't rely on this behavior so the replacement can
99462 	 * be simplified.
99463 	 */
99464 	return (x < y ? x : y);
99465 }
99466 
99467 DUK_INTERNAL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y) {
99468 	/* Doesn't replicate fmax() behavior exactly: for fmax() if one
99469 	 * argument is a NaN, the other argument should be returned.
99470 	 * Duktape doesn't rely on this behavior so the replacement can
99471 	 * be simplified.
99472 	 */
99473 	return (x > y ? x : y);
99474 }
99475 
99476 DUK_INTERNAL duk_bool_t duk_double_is_finite(duk_double_t x) {
99477 	return !duk_double_is_nan_or_inf(x);
99478 }
99479 
99480 DUK_INTERNAL duk_bool_t duk_double_is_integer(duk_double_t x) {
99481 	if (duk_double_is_nan_or_inf(x)) {
99482 		return 0;
99483 	} else {
99484 		return duk_double_equals(duk_js_tointeger_number(x), x);
99485 	}
99486 }
99487 
99488 DUK_INTERNAL duk_bool_t duk_double_is_safe_integer(duk_double_t x) {
99489 	/* >>> 2**53-1
99490 	 * 9007199254740991
99491 	 */
99492 	return duk_double_is_integer(x) && DUK_FABS(x) <= 9007199254740991.0;
99493 }
99494 
99495 /* Check whether a duk_double_t is a whole number in the 32-bit range (reject
99496  * negative zero), and if so, return a duk_int32_t.
99497  * For compiler use: don't allow negative zero as it will cause trouble with
99498  * LDINT+LDINTX, positive zero is OK.
99499  */
99500 DUK_INTERNAL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival) {
99501 	duk_int32_t t;
99502 
99503 	t = duk_double_to_int32_t(x);
99504 	if (!duk_double_equals((duk_double_t) t, x)) {
99505 		return 0;
99506 	}
99507 	if (t == 0) {
99508 		duk_double_union du;
99509 		du.d = x;
99510 		if (DUK_DBLUNION_HAS_SIGNBIT(&du)) {
99511 			return 0;
99512 		}
99513 	}
99514 	*ival = t;
99515 	return 1;
99516 }
99517 
99518 /* Check whether a duk_double_t is a whole number in the 32-bit range, and if
99519  * so, return a duk_int32_t.
99520  */
99521 DUK_INTERNAL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival) {
99522 	duk_int32_t t;
99523 
99524 	t = duk_double_to_int32_t(x);
99525 	if (!duk_double_equals((duk_double_t) t, x)) {
99526 		return 0;
99527 	}
99528 	*ival = t;
99529 	return 1;
99530 }
99531 
99532 /* Division: division by zero is undefined behavior (and may in fact trap)
99533  * so it needs special handling for portability.
99534  */
99535 
99536 DUK_INTERNAL DUK_INLINE duk_double_t duk_double_div(duk_double_t x, duk_double_t y) {
99537 #if !defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
99538 	if (DUK_UNLIKELY(duk_double_equals(y, 0.0) != 0)) {
99539 		/* In C99+ division by zero is undefined behavior so
99540 		 * avoid it entirely.  Hopefully the compiler is
99541 		 * smart enough to avoid emitting any actual code
99542 		 * because almost all practical platforms behave as
99543 		 * expected.
99544 		 */
99545 		if (x > 0.0) {
99546 			if (DUK_SIGNBIT(y)) {
99547 				return -DUK_DOUBLE_INFINITY;
99548 			} else {
99549 				return DUK_DOUBLE_INFINITY;
99550 			}
99551 		} else if (x < 0.0) {
99552 			if (DUK_SIGNBIT(y)) {
99553 				return DUK_DOUBLE_INFINITY;
99554 			} else {
99555 				return -DUK_DOUBLE_INFINITY;
99556 			}
99557 		} else {
99558 			/* +/- 0, NaN */
99559 			return DUK_DOUBLE_NAN;
99560 		}
99561 	}
99562 #endif
99563 
99564 	return x / y;
99565 }
99566 
99567 /* Double and float byteorder changes. */
99568 
99569 DUK_INTERNAL DUK_INLINE void duk_dblunion_host_to_little(duk_double_union *u) {
99570 #if defined(DUK_USE_DOUBLE_LE)
99571 	/* HGFEDCBA -> HGFEDCBA */
99572 	DUK_UNREF(u);
99573 #elif defined(DUK_USE_DOUBLE_ME)
99574 	duk_uint32_t a, b;
99575 
99576 	/* DCBAHGFE -> HGFEDCBA */
99577 	a = u->ui[0];
99578 	b = u->ui[1];
99579 	u->ui[0] = b;
99580 	u->ui[1] = a;
99581 #elif defined(DUK_USE_DOUBLE_BE)
99582 	/* ABCDEFGH -> HGFEDCBA */
99583 #if defined(DUK_USE_64BIT_OPS)
99584 	u->ull[0] = DUK_BSWAP64(u->ull[0]);
99585 #else
99586 	duk_uint32_t a, b;
99587 
99588 	a = u->ui[0];
99589 	b = u->ui[1];
99590 	u->ui[0] = DUK_BSWAP32(b);
99591 	u->ui[1] = DUK_BSWAP32(a);
99592 #endif
99593 #else
99594 #error internal error
99595 #endif
99596 }
99597 
99598 DUK_INTERNAL DUK_INLINE void duk_dblunion_little_to_host(duk_double_union *u) {
99599 	duk_dblunion_host_to_little(u);
99600 }
99601 
99602 DUK_INTERNAL DUK_INLINE void duk_dblunion_host_to_big(duk_double_union *u) {
99603 #if defined(DUK_USE_DOUBLE_LE)
99604 	/* HGFEDCBA -> ABCDEFGH */
99605 #if defined(DUK_USE_64BIT_OPS)
99606 	u->ull[0] = DUK_BSWAP64(u->ull[0]);
99607 #else
99608 	duk_uint32_t a, b;
99609 
99610 	a = u->ui[0];
99611 	b = u->ui[1];
99612 	u->ui[0] = DUK_BSWAP32(b);
99613 	u->ui[1] = DUK_BSWAP32(a);
99614 #endif
99615 #elif defined(DUK_USE_DOUBLE_ME)
99616 	duk_uint32_t a, b;
99617 
99618 	/* DCBAHGFE -> ABCDEFGH */
99619 	a = u->ui[0];
99620 	b = u->ui[1];
99621 	u->ui[0] = DUK_BSWAP32(a);
99622 	u->ui[1] = DUK_BSWAP32(b);
99623 #elif defined(DUK_USE_DOUBLE_BE)
99624 	/* ABCDEFGH -> ABCDEFGH */
99625 	DUK_UNREF(u);
99626 #else
99627 #error internal error
99628 #endif
99629 }
99630 
99631 DUK_INTERNAL DUK_INLINE void duk_dblunion_big_to_host(duk_double_union *u) {
99632 	duk_dblunion_host_to_big(u);
99633 }
99634 
99635 DUK_INTERNAL DUK_INLINE void duk_fltunion_host_to_big(duk_float_union *u) {
99636 #if defined(DUK_USE_DOUBLE_LE) || defined(DUK_USE_DOUBLE_ME)
99637 	/* DCBA -> ABCD */
99638 	u->ui[0] = DUK_BSWAP32(u->ui[0]);
99639 #elif defined(DUK_USE_DOUBLE_BE)
99640 	/* ABCD -> ABCD */
99641 	DUK_UNREF(u);
99642 #else
99643 #error internal error
99644 #endif
99645 }
99646 
99647 DUK_INTERNAL DUK_INLINE void duk_fltunion_big_to_host(duk_float_union *u) {
99648 	duk_fltunion_host_to_big(u);
99649 }
99650 
99651 /* Comparison: ensures comparison operates on exactly correct types, avoiding
99652  * some floating point comparison pitfalls (e.g. atan2() assertions failed on
99653  * -m32 with direct comparison, even with explicit casts).
99654  */
99655 #if defined(DUK_USE_GCC_PRAGMAS)
99656 #pragma GCC diagnostic push
99657 #pragma GCC diagnostic ignored "-Wfloat-equal"
99658 #elif defined(DUK_USE_CLANG_PRAGMAS)
99659 #pragma clang diagnostic push
99660 #pragma clang diagnostic ignored "-Wfloat-equal"
99661 #endif
99662 
99663 DUK_INTERNAL DUK_ALWAYS_INLINE duk_bool_t duk_double_equals(duk_double_t x, duk_double_t y) {
99664 	return x == y;
99665 }
99666 
99667 DUK_INTERNAL DUK_ALWAYS_INLINE duk_bool_t duk_float_equals(duk_float_t x, duk_float_t y) {
99668 	return x == y;
99669 }
99670 #if defined(DUK_USE_GCC_PRAGMAS)
99671 #pragma GCC diagnostic pop
99672 #elif defined(DUK_USE_CLANG_PRAGMAS)
99673 #pragma clang diagnostic pop
99674 #endif
99675 #line 1 "duk_util_hashbytes.c"
99676 /*
99677  *  Hash function duk_util_hashbytes().
99678  *
99679  *  Currently, 32-bit MurmurHash2.
99680  *
99681  *  Don't rely on specific hash values; hash function may be endianness
99682  *  dependent, for instance.
99683  */
99684 
99685 /* #include duk_internal.h -> already included */
99686 
99687 #if defined(DUK_USE_STRHASH_DENSE)
99688 /* 'magic' constants for Murmurhash2 */
99689 #define DUK__MAGIC_M  ((duk_uint32_t) 0x5bd1e995UL)
99690 #define DUK__MAGIC_R  24
99691 
99692 DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed) {
99693 	duk_uint32_t h = seed ^ ((duk_uint32_t) len);
99694 
99695 	while (len >= 4) {
99696 		/* Portability workaround is required for platforms without
99697 		 * unaligned access.  The replacement code emulates little
99698 		 * endian access even on big endian architectures, which is
99699 		 * OK as long as it is consistent for a build.
99700 		 */
99701 #if defined(DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS)
99702 		duk_uint32_t k = *((const duk_uint32_t *) (const void *) data);
99703 #else
99704 		duk_uint32_t k = ((duk_uint32_t) data[0]) |
99705 		                 (((duk_uint32_t) data[1]) << 8) |
99706 		                 (((duk_uint32_t) data[2]) << 16) |
99707 		                 (((duk_uint32_t) data[3]) << 24);
99708 #endif
99709 
99710 		k *= DUK__MAGIC_M;
99711 		k ^= k >> DUK__MAGIC_R;
99712 		k *= DUK__MAGIC_M;
99713 		h *= DUK__MAGIC_M;
99714 		h ^= k;
99715 		data += 4;
99716 		len -= 4;
99717 	}
99718 
99719 	switch (len) {
99720 	case 3: h ^= data[2] << 16;
99721 	case 2: h ^= data[1] << 8;
99722 	case 1: h ^= data[0];
99723 	        h *= DUK__MAGIC_M;
99724         }
99725 
99726 	h ^= h >> 13;
99727 	h *= DUK__MAGIC_M;
99728 	h ^= h >> 15;
99729 
99730 	return h;
99731 }
99732 #endif  /* DUK_USE_STRHASH_DENSE */
99733 
99734 /* automatic undefs */
99735 #undef DUK__MAGIC_M
99736 #undef DUK__MAGIC_R
99737 #line 1 "duk_util_memory.c"
99738 /*
99739  *  Memory utils.
99740  */
99741 
99742 /* #include duk_internal.h -> already included */
99743 
99744 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
99745 DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len) {
99746 	DUK_ASSERT(s1 != NULL || len == 0U);
99747 	DUK_ASSERT(s2 != NULL || len == 0U);
99748 	return DUK_MEMCMP(s1, s2, (size_t) len);
99749 }
99750 
99751 DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len) {
99752 	DUK_ASSERT(s1 != NULL);
99753 	DUK_ASSERT(s2 != NULL);
99754 	return DUK_MEMCMP(s1, s2, (size_t) len);
99755 }
99756 #else  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
99757 DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len) {
99758 	DUK_ASSERT(s1 != NULL || len == 0U);
99759 	DUK_ASSERT(s2 != NULL || len == 0U);
99760 	if (DUK_UNLIKELY(len == 0U)) {
99761 		return 0;
99762 	}
99763 	DUK_ASSERT(s1 != NULL);
99764 	DUK_ASSERT(s2 != NULL);
99765 	return duk_memcmp(s1, s2, len);
99766 }
99767 
99768 DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len) {
99769 	DUK_ASSERT(s1 != NULL);
99770 	DUK_ASSERT(s2 != NULL);
99771 	return DUK_MEMCMP(s1, s2, (size_t) len);
99772 }
99773 #endif  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
99774 #line 1 "duk_util_tinyrandom.c"
99775 /*
99776  *  A tiny random number generator used for Math.random() and other internals.
99777  *
99778  *  Default algorithm is xoroshiro128+: http://xoroshiro.di.unimi.it/xoroshiro128plus.c
99779  *  with SplitMix64 seed preparation: http://xorshift.di.unimi.it/splitmix64.c.
99780  *
99781  *  Low memory targets and targets without 64-bit types use a slightly smaller
99782  *  (but slower) algorithm by Adi Shamir:
99783  *  http://www.woodmann.com/forum/archive/index.php/t-3100.html.
99784  *
99785  */
99786 
99787 /* #include duk_internal.h -> already included */
99788 
99789 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
99790 
99791 #if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
99792 #define DUK__RANDOM_SHAMIR3OP
99793 #else
99794 #define DUK__RANDOM_XOROSHIRO128PLUS
99795 #endif
99796 
99797 #if defined(DUK__RANDOM_SHAMIR3OP)
99798 #define DUK__UPDATE_RND(rnd) do { \
99799 		(rnd) += ((rnd) * (rnd)) | 0x05UL; \
99800 		(rnd) = ((rnd) & 0xffffffffUL);       /* if duk_uint32_t is exactly 32 bits, this is a NOP */ \
99801 	} while (0)
99802 
99803 #define DUK__RND_BIT(rnd)  ((rnd) >> 31)  /* only use the highest bit */
99804 
99805 DUK_INTERNAL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr) {
99806 	DUK_UNREF(thr);  /* Nothing now. */
99807 }
99808 
99809 DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
99810 	duk_double_t t;
99811 	duk_small_int_t n;
99812 	duk_uint32_t rnd;
99813 
99814 	rnd = thr->heap->rnd_state;
99815 
99816 	n = 53;  /* enough to cover the whole mantissa */
99817 	t = 0.0;
99818 
99819 	do {
99820 		DUK__UPDATE_RND(rnd);
99821 		t += DUK__RND_BIT(rnd);
99822 		t /= 2.0;
99823 	} while (--n);
99824 
99825 	thr->heap->rnd_state = rnd;
99826 
99827 	DUK_ASSERT(t >= (duk_double_t) 0.0);
99828 	DUK_ASSERT(t < (duk_double_t) 1.0);
99829 
99830 	return t;
99831 }
99832 #endif  /* DUK__RANDOM_SHAMIR3OP */
99833 
99834 #if defined(DUK__RANDOM_XOROSHIRO128PLUS)
99835 DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__rnd_splitmix64(duk_uint64_t *x) {
99836 	duk_uint64_t z;
99837 	z = (*x += DUK_U64_CONSTANT(0x9E3779B97F4A7C15));
99838 	z = (z ^ (z >> 30U)) * DUK_U64_CONSTANT(0xBF58476D1CE4E5B9);
99839 	z = (z ^ (z >> 27U)) * DUK_U64_CONSTANT(0x94D049BB133111EB);
99840 	return z ^ (z >> 31U);
99841 }
99842 
99843 DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__rnd_rotl(const duk_uint64_t x, duk_small_uint_t k) {
99844 	return (x << k) | (x >> (64U - k));
99845 }
99846 
99847 DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__xoroshiro128plus(duk_uint64_t *s) {
99848 	duk_uint64_t s0;
99849 	duk_uint64_t s1;
99850 	duk_uint64_t res;
99851 
99852 	s0 = s[0];
99853 	s1 = s[1];
99854 	res = s0 + s1;
99855 	s1 ^= s0;
99856 	s[0] = duk__rnd_rotl(s0, 55) ^ s1 ^ (s1 << 14U);
99857 	s[1] = duk__rnd_rotl(s1, 36);
99858 
99859 	return res;
99860 }
99861 
99862 DUK_INTERNAL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr) {
99863 	duk_small_uint_t i;
99864 	duk_uint64_t x;
99865 
99866 	/* Mix both halves of the initial seed with SplitMix64.  The intent
99867 	 * is to ensure that very similar raw seeds (which is usually the case
99868 	 * because current seed is Date.now()) result in different xoroshiro128+
99869 	 * seeds.
99870 	 */
99871 	x = thr->heap->rnd_state[0];  /* Only [0] is used as input here. */
99872 	for (i = 0; i < 64; i++) {
99873 		thr->heap->rnd_state[i & 0x01] = duk__rnd_splitmix64(&x);  /* Keep last 2 values. */
99874 	}
99875 }
99876 
99877 DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
99878 	duk_uint64_t v;
99879 	duk_double_union du;
99880 
99881 	/* For big and little endian the integer and IEEE double byte order
99882 	 * is the same so a direct assignment works.  For mixed endian the
99883 	 * 32-bit parts must be swapped.
99884 	 */
99885 	v = (DUK_U64_CONSTANT(0x3ff) << 52U) | (duk__xoroshiro128plus((duk_uint64_t *) thr->heap->rnd_state) >> 12U);
99886 	du.ull[0] = v;
99887 #if defined(DUK_USE_DOUBLE_ME)
99888 	do {
99889 		duk_uint32_t tmp;
99890 		tmp = du.ui[0];
99891 		du.ui[0] = du.ui[1];
99892 		du.ui[1] = tmp;
99893 	} while (0);
99894 #endif
99895 	return du.d - 1.0;
99896 }
99897 #endif  /* DUK__RANDOM_XOROSHIRO128PLUS */
99898 
99899 #endif  /* !DUK_USE_GET_RANDOM_DOUBLE */
99900 
99901 /* automatic undefs */
99902 #undef DUK__RANDOM_SHAMIR3OP
99903 #undef DUK__RANDOM_XOROSHIRO128PLUS
99904 #undef DUK__RND_BIT
99905 #undef DUK__UPDATE_RND
99906