1 /*
2  *  Single source autogenerated distributable for Duktape 2.3.0.
3  *
4  *  Git commit d7fdb67f18561a50e06bafd196c6b423af9ad6fe (v2.3.0).
5  *  Git branch master.
6  *
7  *  See Duktape AUTHORS.rst and LICENSE.txt for copyright and
8  *  licensing information.
9  */
10 
11 /* LICENSE.txt */
12 /*
13 *  ===============
14 *  Duktape license
15 *  ===============
16 *
17 *  (http://opensource.org/licenses/MIT)
18 *
19 *  Copyright (c) 2013-2018 by Duktape authors (see AUTHORS.rst)
20 *
21 *  Permission is hereby granted, free of charge, to any person obtaining a copy
22 *  of this software and associated documentation files (the "Software"), to deal
23 *  in the Software without restriction, including without limitation the rights
24 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25 *  copies of the Software, and to permit persons to whom the Software is
26 *  furnished to do so, subject to the following conditions:
27 *
28 *  The above copyright notice and this permission notice shall be included in
29 *  all copies or substantial portions of the Software.
30 *
31 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37 *  THE SOFTWARE.
38 */
39 
40 /* AUTHORS.rst */
41 /*
42 *  ===============
43 *  Duktape authors
44 *  ===============
45 *
46 *  Copyright
47 *  =========
48 *
49 *  Duktape copyrights are held by its authors.  Each author has a copyright
50 *  to their contribution, and agrees to irrevocably license the contribution
51 *  under the Duktape ``LICENSE.txt``.
52 *
53 *  Authors
54 *  =======
55 *
56 *  Please include an e-mail address, a link to your GitHub profile, or something
57 *  similar to allow your contribution to be identified accurately.
58 *
59 *  The following people have contributed code, website contents, or Wiki contents,
60 *  and agreed to irrevocably license their contributions under the Duktape
61 *  ``LICENSE.txt`` (in order of appearance):
62 *
63 *  * Sami Vaarala <sami.vaarala@iki.fi>
64 *  * Niki Dobrev
65 *  * Andreas \u00d6man <andreas@lonelycoder.com>
66 *  * L\u00e1szl\u00f3 Lang\u00f3 <llango.u-szeged@partner.samsung.com>
67 *  * Legimet <legimet.calc@gmail.com>
68 *  * Karl Skomski <karl@skomski.com>
69 *  * Bruce Pascoe <fatcerberus1@gmail.com>
70 *  * Ren\u00e9 Hollander <rene@rene8888.at>
71 *  * Julien Hamaide (https://github.com/crazyjul)
72 *  * Sebastian G\u00f6tte (https://github.com/jaseg)
73 *  * Tomasz Magulski (https://github.com/magul)
74 *  * \D. Bohdan (https://github.com/dbohdan)
75 *  * Ond\u0159ej Jirman (https://github.com/megous)
76 *  * Sa\u00fal Ibarra Corretg\u00e9 <saghul@gmail.com>
77 *  * Jeremy HU <huxingyi@msn.com>
78 *  * Ole Andr\u00e9 Vadla Ravn\u00e5s (https://github.com/oleavr)
79 *  * Harold Brenes (https://github.com/harold-b)
80 *  * Oliver Crow (https://github.com/ocrow)
81 *  * Jakub Ch\u0142api\u0144ski (https://github.com/jchlapinski)
82 *  * Brett Vickers (https://github.com/beevik)
83 *  * Dominik Okwieka (https://github.com/okitec)
84 *  * Remko Tron\u00e7on (https://el-tramo.be)
85 *  * Romero Malaquias (rbsm@ic.ufal.br)
86 *  * Michael Drake <michael.drake@codethink.co.uk>
87 *  * Steven Don (https://github.com/shdon)
88 *  * Simon Stone (https://github.com/sstone1)
89 *  * \J. McC. (https://github.com/jmhmccr)
90 *  * Jakub Nowakowski (https://github.com/jimvonmoon)
91 *  * Tommy Nguyen (https://github.com/tn0502)
92 *  * Fabrice Fontaine (https://github.com/ffontaine)
93 *  * Christopher Hiller (https://github.com/boneskull)
94 *  * Gonzalo Diethelm (https://github.com/gonzus)
95 *  * Michal Kasperek (https://github.com/michalkas)
96 *  * Andrew Janke (https://github.com/apjanke)
97 *  * Steve Fan (https://github.com/stevefan1999)
98 *
99 *  Other contributions
100 *  ===================
101 *
102 *  The following people have contributed something other than code (e.g. reported
103 *  bugs, provided ideas, etc; roughly in order of appearance):
104 *
105 *  * Greg Burns
106 *  * Anthony Rabine
107 *  * Carlos Costa
108 *  * Aur\u00e9lien Bouilland
109 *  * Preet Desai (Pris Matic)
110 *  * judofyr (http://www.reddit.com/user/judofyr)
111 *  * Jason Woofenden
112 *  * Micha\u0142 Przyby\u015b
113 *  * Anthony Howe
114 *  * Conrad Pankoff
115 *  * Jim Schimpf
116 *  * Rajaran Gaunker (https://github.com/zimbabao)
117 *  * Andreas \u00d6man
118 *  * Doug Sanden
119 *  * Josh Engebretson (https://github.com/JoshEngebretson)
120 *  * Remo Eichenberger (https://github.com/remoe)
121 *  * Mamod Mehyar (https://github.com/mamod)
122 *  * David Demelier (https://github.com/markand)
123 *  * Tim Caswell (https://github.com/creationix)
124 *  * Mitchell Blank Jr (https://github.com/mitchblank)
125 *  * https://github.com/yushli
126 *  * Seo Sanghyeon (https://github.com/sanxiyn)
127 *  * Han ChoongWoo (https://github.com/tunz)
128 *  * Joshua Peek (https://github.com/josh)
129 *  * Bruce E. Pascoe (https://github.com/fatcerberus)
130 *  * https://github.com/Kelledin
131 *  * https://github.com/sstruchtrup
132 *  * Michael Drake (https://github.com/tlsa)
133 *  * https://github.com/chris-y
134 *  * Laurent Zubiaur (https://github.com/lzubiaur)
135 *  * Neil Kolban (https://github.com/nkolban)
136 *  * Wilhelm Wanecek (https://github.com/wanecek)
137 *  * Andrew Janke (https://github.com/apjanke)
138 *
139 *  If you are accidentally missing from this list, send me an e-mail
140 *  (``sami.vaarala@iki.fi``) and I'll fix the omission.
141 */
142 
143 #line 1 "duk_replacements.c"
144 /*
145  *  Replacements for missing platform functions.
146  *
147  *  Unlike the originals, fpclassify() and signbit() replacements don't
148  *  work on any floating point types, only doubles.  The C typing here
149  *  mimics the standard prototypes.
150  */
151 
152 /* #include duk_internal.h */
153 #line 1 "duk_internal.h"
154 /*
155  *  Top-level include file to be used for all (internal) source files.
156  *
157  *  Source files should not include individual header files, as they
158  *  have not been designed to be individually included.
159  */
160 
161 #if !defined(DUK_INTERNAL_H_INCLUDED)
162 #define DUK_INTERNAL_H_INCLUDED
163 
164 /*
165  *  The 'duktape.h' header provides the public API, but also handles all
166  *  compiler and platform specific feature detection, Duktape feature
167  *  resolution, inclusion of system headers, etc.  These have been merged
168  *  because the public API is also dependent on e.g. detecting appropriate
169  *  C types which is quite platform/compiler specific especially for a non-C99
170  *  build.  The public API is also dependent on the resolved feature set.
171  *
172  *  Some actions taken by the merged header (such as including system headers)
173  *  are not appropriate for building a user application.  The define
174  *  DUK_COMPILING_DUKTAPE allows the merged header to skip/include some
175  *  sections depending on what is being built.
176  */
177 
178 #define DUK_COMPILING_DUKTAPE
179 
180 #ifdef OF_JS_DEBUG
181 #include "duk_trans_socket_windows.cpp"
182 #endif
183 
184 #include "duktape.h"
185 
186 /*
187  *  User declarations, e.g. prototypes for user functions used by Duktape
188  *  macros.
189  */
190 
191 DUK_USE_USER_DECLARE()
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/cross endian (e.g. ARM)   DUK_USE_DOUBLE_ME
233  *
234  *  ARM is a special case: ARM double values are in mixed/cross endian
235  *  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  *
240  *  Indexes of various types (8-bit, 16-bit, 32-bit) in memory relative to
241  *  the logical (big endian) order:
242  *
243  *  byte order      duk_uint8_t    duk_uint16_t     duk_uint32_t
244  *    BE             01234567         0123               01
245  *    LE             76543210         3210               10
246  *    ME (ARM)       32107654         1032               01
247  *
248  *  Some processors may alter NaN values in a floating point load+store.
249  *  For instance, on X86 a FLD + FSTP may convert a signaling NaN to a
250  *  quiet one.  This is catastrophic when NaN space is used in packed
251  *  duk_tval values.  See: misc/clang_aliasing.c.
252  */
253 
254 #if !defined(DUK_DBLUNION_H_INCLUDED)
255 #define DUK_DBLUNION_H_INCLUDED
256 
257 /*
258  *  Union for accessing double parts, also serves as packed duk_tval
259  */
260 
261 union duk_double_union {
262 	double d;
263 	float f[2];
264 #if defined(DUK_USE_64BIT_OPS)
265 	duk_uint64_t ull[1];
266 #endif
267 	duk_uint32_t ui[2];
268 	duk_uint16_t us[4];
269 	duk_uint8_t uc[8];
270 #if defined(DUK_USE_PACKED_TVAL)
271 	void *vp[2];  /* used by packed duk_tval, assumes sizeof(void *) == 4 */
272 #endif
273 };
274 
275 typedef union duk_double_union duk_double_union;
276 
277 /*
278  *  Indexes of various types with respect to big endian (logical) layout
279  */
280 
281 #if defined(DUK_USE_DOUBLE_LE)
282 #if defined(DUK_USE_64BIT_OPS)
283 #define DUK_DBL_IDX_ULL0   0
284 #endif
285 #define DUK_DBL_IDX_UI0    1
286 #define DUK_DBL_IDX_UI1    0
287 #define DUK_DBL_IDX_US0    3
288 #define DUK_DBL_IDX_US1    2
289 #define DUK_DBL_IDX_US2    1
290 #define DUK_DBL_IDX_US3    0
291 #define DUK_DBL_IDX_UC0    7
292 #define DUK_DBL_IDX_UC1    6
293 #define DUK_DBL_IDX_UC2    5
294 #define DUK_DBL_IDX_UC3    4
295 #define DUK_DBL_IDX_UC4    3
296 #define DUK_DBL_IDX_UC5    2
297 #define DUK_DBL_IDX_UC6    1
298 #define DUK_DBL_IDX_UC7    0
299 #define DUK_DBL_IDX_VP0    DUK_DBL_IDX_UI0  /* packed tval */
300 #define DUK_DBL_IDX_VP1    DUK_DBL_IDX_UI1  /* packed tval */
301 #elif defined(DUK_USE_DOUBLE_BE)
302 #if defined(DUK_USE_64BIT_OPS)
303 #define DUK_DBL_IDX_ULL0   0
304 #endif
305 #define DUK_DBL_IDX_UI0    0
306 #define DUK_DBL_IDX_UI1    1
307 #define DUK_DBL_IDX_US0    0
308 #define DUK_DBL_IDX_US1    1
309 #define DUK_DBL_IDX_US2    2
310 #define DUK_DBL_IDX_US3    3
311 #define DUK_DBL_IDX_UC0    0
312 #define DUK_DBL_IDX_UC1    1
313 #define DUK_DBL_IDX_UC2    2
314 #define DUK_DBL_IDX_UC3    3
315 #define DUK_DBL_IDX_UC4    4
316 #define DUK_DBL_IDX_UC5    5
317 #define DUK_DBL_IDX_UC6    6
318 #define DUK_DBL_IDX_UC7    7
319 #define DUK_DBL_IDX_VP0    DUK_DBL_IDX_UI0  /* packed tval */
320 #define DUK_DBL_IDX_VP1    DUK_DBL_IDX_UI1  /* packed tval */
321 #elif defined(DUK_USE_DOUBLE_ME)
322 #if defined(DUK_USE_64BIT_OPS)
323 #define DUK_DBL_IDX_ULL0   0  /* not directly applicable, byte order differs from a double */
324 #endif
325 #define DUK_DBL_IDX_UI0    0
326 #define DUK_DBL_IDX_UI1    1
327 #define DUK_DBL_IDX_US0    1
328 #define DUK_DBL_IDX_US1    0
329 #define DUK_DBL_IDX_US2    3
330 #define DUK_DBL_IDX_US3    2
331 #define DUK_DBL_IDX_UC0    3
332 #define DUK_DBL_IDX_UC1    2
333 #define DUK_DBL_IDX_UC2    1
334 #define DUK_DBL_IDX_UC3    0
335 #define DUK_DBL_IDX_UC4    7
336 #define DUK_DBL_IDX_UC5    6
337 #define DUK_DBL_IDX_UC6    5
338 #define DUK_DBL_IDX_UC7    4
339 #define DUK_DBL_IDX_VP0    DUK_DBL_IDX_UI0  /* packed tval */
340 #define DUK_DBL_IDX_VP1    DUK_DBL_IDX_UI1  /* packed tval */
341 #else
342 #error internal error
343 #endif
344 
345 /*
346  *  Helper macros for reading/writing memory representation parts, used
347  *  by duk_numconv.c and duk_tval.h.
348  */
349 
350 #define DUK_DBLUNION_SET_DOUBLE(u,v)  do {  \
351 		(u)->d = (v); \
352 	} while (0)
353 
354 #define DUK_DBLUNION_SET_HIGH32(u,v)  do {  \
355 		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) (v); \
356 	} while (0)
357 
358 #if defined(DUK_USE_64BIT_OPS)
359 #if defined(DUK_USE_DOUBLE_ME)
360 #define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v)  do { \
361 		(u)->ull[DUK_DBL_IDX_ULL0] = (duk_uint64_t) (v); \
362 	} while (0)
363 #else
364 #define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v)  do { \
365 		(u)->ull[DUK_DBL_IDX_ULL0] = ((duk_uint64_t) (v)) << 32; \
366 	} while (0)
367 #endif
368 #else  /* DUK_USE_64BIT_OPS */
369 #define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v)  do { \
370 		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) (v); \
371 		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) 0; \
372 	} while (0)
373 #endif  /* DUK_USE_64BIT_OPS */
374 
375 #define DUK_DBLUNION_SET_LOW32(u,v)  do {  \
376 		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (v); \
377 	} while (0)
378 
379 #define DUK_DBLUNION_GET_DOUBLE(u)  ((u)->d)
380 #define DUK_DBLUNION_GET_HIGH32(u)  ((u)->ui[DUK_DBL_IDX_UI0])
381 #define DUK_DBLUNION_GET_LOW32(u)   ((u)->ui[DUK_DBL_IDX_UI1])
382 
383 #if defined(DUK_USE_64BIT_OPS)
384 #if defined(DUK_USE_DOUBLE_ME)
385 #define DUK_DBLUNION_SET_UINT64(u,v)  do { \
386 		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) ((v) >> 32); \
387 		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (v); \
388 	} while (0)
389 #define DUK_DBLUNION_GET_UINT64(u) \
390 	((((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI0]) << 32) | \
391 	 ((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI1]))
392 #else
393 #define DUK_DBLUNION_SET_UINT64(u,v)  do { \
394 		(u)->ull[DUK_DBL_IDX_ULL0] = (duk_uint64_t) (v); \
395 	} while (0)
396 #define DUK_DBLUNION_GET_UINT64(u)  ((u)->ull[DUK_DBL_IDX_ULL0])
397 #endif
398 #define DUK_DBLUNION_SET_INT64(u,v) DUK_DBLUNION_SET_UINT64((u), (duk_uint64_t) (v))
399 #define DUK_DBLUNION_GET_INT64(u)   ((duk_int64_t) DUK_DBLUNION_GET_UINT64((u)))
400 #endif  /* DUK_USE_64BIT_OPS */
401 
402 /*
403  *  Double NaN manipulation macros related to NaN normalization needed when
404  *  using the packed duk_tval representation.  NaN normalization is necessary
405  *  to keep double values compatible with the duk_tval format.
406  *
407  *  When packed duk_tval is used, the NaN space is used to store pointers
408  *  and other tagged values in addition to NaNs.  Actual NaNs are normalized
409  *  to a specific quiet NaN.  The macros below are used by the implementation
410  *  to check and normalize NaN values when they might be created.  The macros
411  *  are essentially NOPs when the non-packed duk_tval representation is used.
412  *
413  *  A FULL check is exact and checks all bits.  A NOTFULL check is used by
414  *  the packed duk_tval and works correctly for all NaNs except those that
415  *  begin with 0x7ff0.  Since the 'normalized NaN' values used with packed
416  *  duk_tval begin with 0x7ff8, the partial check is reliable when packed
417  *  duk_tval is used.  The 0x7ff8 prefix means the normalized NaN will be a
418  *  quiet NaN regardless of its remaining lower bits.
419  *
420  *  The ME variant below is specifically for ARM byte order, which has the
421  *  feature that while doubles have a mixed byte order (32107654), unsigned
422  *  long long values has a little endian byte order (76543210).  When writing
423  *  a logical double value through a ULL pointer, the 32-bit words need to be
424  *  swapped; hence the #if defined()s below for ULL writes with DUK_USE_DOUBLE_ME.
425  *  This is not full ARM support but suffices for some environments.
426  */
427 
428 #if defined(DUK_USE_64BIT_OPS)
429 #if defined(DUK_USE_DOUBLE_ME)
430 /* Macros for 64-bit ops + mixed endian doubles. */
431 #define DUK__DBLUNION_SET_NAN_FULL(u)  do { \
432 		(u)->ull[DUK_DBL_IDX_ULL0] = DUK_U64_CONSTANT(0x000000007ff80000); \
433 	} while (0)
434 #define DUK__DBLUNION_IS_NAN_FULL(u) \
435 	((((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000)) && \
436 	 ((((u)->ull[DUK_DBL_IDX_ULL0]) & DUK_U64_CONSTANT(0xffffffff000fffff)) != 0))
437 #define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \
438 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x000000007ff80000))
439 #define DUK__DBLUNION_IS_ANYINF(u) \
440 	(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0xffffffff7fffffff)) == DUK_U64_CONSTANT(0x000000007ff00000))
441 #define DUK__DBLUNION_IS_POSINF(u) \
442 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x000000007ff00000))
443 #define DUK__DBLUNION_IS_NEGINF(u) \
444 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x00000000fff00000))
445 #define DUK__DBLUNION_IS_ANYZERO(u) \
446 	(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0xffffffff7fffffff)) == DUK_U64_CONSTANT(0x0000000000000000))
447 #define DUK__DBLUNION_IS_POSZERO(u) \
448 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000000000000))
449 #define DUK__DBLUNION_IS_NEGZERO(u) \
450 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000080000000))
451 #else
452 /* Macros for 64-bit ops + big/little endian doubles. */
453 #define DUK__DBLUNION_SET_NAN_FULL(u)  do { \
454 		(u)->ull[DUK_DBL_IDX_ULL0] = DUK_U64_CONSTANT(0x7ff8000000000000); \
455 	} while (0)
456 #define DUK__DBLUNION_IS_NAN_FULL(u) \
457 	((((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000)) && \
458 	 ((((u)->ull[DUK_DBL_IDX_ULL0]) & DUK_U64_CONSTANT(0x000fffffffffffff)) != 0))
459 #define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \
460 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x7ff8000000000000))
461 #define DUK__DBLUNION_IS_ANYINF(u) \
462 	(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7fffffffffffffff)) == DUK_U64_CONSTANT(0x7ff0000000000000))
463 #define DUK__DBLUNION_IS_POSINF(u) \
464 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x7ff0000000000000))
465 #define DUK__DBLUNION_IS_NEGINF(u) \
466 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0xfff0000000000000))
467 #define DUK__DBLUNION_IS_ANYZERO(u) \
468 	(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7fffffffffffffff)) == DUK_U64_CONSTANT(0x0000000000000000))
469 #define DUK__DBLUNION_IS_POSZERO(u) \
470 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000000000000))
471 #define DUK__DBLUNION_IS_NEGZERO(u) \
472 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x8000000000000000))
473 #endif
474 #else  /* DUK_USE_64BIT_OPS */
475 /* Macros for no 64-bit ops, any endianness. */
476 #define DUK__DBLUNION_SET_NAN_FULL(u)  do { \
477 		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) 0x7ff80000UL; \
478 		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) 0x00000000UL; \
479 	} while (0)
480 #define DUK__DBLUNION_IS_NAN_FULL(u) \
481 	((((u)->ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL) && \
482 	 (((u)->ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) != 0 || \
483           (u)->ui[DUK_DBL_IDX_UI1] != 0))
484 #define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \
485 	(((u)->ui[DUK_DBL_IDX_UI0] == 0x7ff80000UL) && \
486 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
487 #define DUK__DBLUNION_IS_ANYINF(u) \
488 	((((u)->ui[DUK_DBL_IDX_UI0] & 0x7fffffffUL) == 0x7ff00000UL) && \
489 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
490 #define DUK__DBLUNION_IS_POSINF(u) \
491 	(((u)->ui[DUK_DBL_IDX_UI0] == 0x7ff00000UL) && \
492 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
493 #define DUK__DBLUNION_IS_NEGINF(u) \
494 	(((u)->ui[DUK_DBL_IDX_UI0] == 0xfff00000UL) && \
495 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
496 #define DUK__DBLUNION_IS_ANYZERO(u) \
497 	((((u)->ui[DUK_DBL_IDX_UI0] & 0x7fffffffUL) == 0x00000000UL) && \
498 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
499 #define DUK__DBLUNION_IS_POSZERO(u) \
500 	(((u)->ui[DUK_DBL_IDX_UI0] == 0x00000000UL) && \
501 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
502 #define DUK__DBLUNION_IS_NEGZERO(u) \
503 	(((u)->ui[DUK_DBL_IDX_UI0] == 0x80000000UL) && \
504 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
505 #endif  /* DUK_USE_64BIT_OPS */
506 
507 #define DUK__DBLUNION_SET_NAN_NOTFULL(u)  do { \
508 		(u)->us[DUK_DBL_IDX_US0] = 0x7ff8UL; \
509 	} while (0)
510 
511 #define DUK__DBLUNION_IS_NAN_NOTFULL(u) \
512 	/* E == 0x7ff, topmost four bits of F != 0 => assume NaN */ \
513 	((((u)->us[DUK_DBL_IDX_US0] & 0x7ff0UL) == 0x7ff0UL) && \
514 	 (((u)->us[DUK_DBL_IDX_US0] & 0x000fUL) != 0x0000UL))
515 
516 #define DUK__DBLUNION_IS_NORMALIZED_NAN_NOTFULL(u) \
517 	/* E == 0x7ff, F == 8 => normalized NaN */ \
518 	((u)->us[DUK_DBL_IDX_US0] == 0x7ff8UL)
519 
520 #define DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL(u)  do { \
521 		if (DUK__DBLUNION_IS_NAN_FULL((u))) { \
522 			DUK__DBLUNION_SET_NAN_FULL((u)); \
523 		} \
524 	} while (0)
525 
526 #define DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL(u)  do { \
527 		if (DUK__DBLUNION_IS_NAN_NOTFULL((u))) { \
528 			DUK__DBLUNION_SET_NAN_NOTFULL((u)); \
529 		} \
530 	} while (0)
531 
532 /* Concrete macros for NaN handling used by the implementation internals.
533  * Chosen so that they match the duk_tval representation: with a packed
534  * duk_tval, ensure NaNs are properly normalized; with a non-packed duk_tval
535  * these are essentially NOPs.
536  */
537 
538 #if defined(DUK_USE_PACKED_TVAL)
539 #if defined(DUK_USE_FULL_TVAL)
540 #define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)  DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL((u))
541 #define DUK_DBLUNION_IS_NAN(u)               DUK__DBLUNION_IS_NAN_FULL((u))
542 #define DUK_DBLUNION_IS_NORMALIZED_NAN(u)    DUK__DBLUNION_IS_NORMALIZED_NAN_FULL((u))
543 #define DUK_DBLUNION_SET_NAN(d)              DUK__DBLUNION_SET_NAN_FULL((d))
544 #else
545 #define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)  DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL((u))
546 #define DUK_DBLUNION_IS_NAN(u)               DUK__DBLUNION_IS_NAN_NOTFULL((u))
547 #define DUK_DBLUNION_IS_NORMALIZED_NAN(u)    DUK__DBLUNION_IS_NORMALIZED_NAN_NOTFULL((u))
548 #define DUK_DBLUNION_SET_NAN(d)              DUK__DBLUNION_SET_NAN_NOTFULL((d))
549 #endif
550 #define DUK_DBLUNION_IS_NORMALIZED(u) \
551 	(!DUK_DBLUNION_IS_NAN((u)) ||  /* either not a NaN */ \
552 	 DUK_DBLUNION_IS_NORMALIZED_NAN((u)))  /* or is a normalized NaN */
553 #else  /* DUK_USE_PACKED_TVAL */
554 #define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)  /* nop: no need to normalize */
555 #define DUK_DBLUNION_IS_NAN(u)               DUK__DBLUNION_IS_NAN_FULL((u))  /* (DUK_ISNAN((u)->d)) */
556 #define DUK_DBLUNION_IS_NORMALIZED_NAN(u)    DUK__DBLUNION_IS_NAN_FULL((u))  /* (DUK_ISNAN((u)->d)) */
557 #define DUK_DBLUNION_IS_NORMALIZED(u)        1  /* all doubles are considered normalized */
558 #define DUK_DBLUNION_SET_NAN(u)  do { \
559 		/* in non-packed representation we don't care about which NaN is used */ \
560 		(u)->d = DUK_DOUBLE_NAN; \
561 	} while (0)
562 #endif  /* DUK_USE_PACKED_TVAL */
563 
564 #define DUK_DBLUNION_IS_ANYINF(u) DUK__DBLUNION_IS_ANYINF((u))
565 #define DUK_DBLUNION_IS_POSINF(u) DUK__DBLUNION_IS_POSINF((u))
566 #define DUK_DBLUNION_IS_NEGINF(u) DUK__DBLUNION_IS_NEGINF((u))
567 
568 #define DUK_DBLUNION_IS_ANYZERO(u) DUK__DBLUNION_IS_ANYZERO((u))
569 #define DUK_DBLUNION_IS_POSZERO(u) DUK__DBLUNION_IS_POSZERO((u))
570 #define DUK_DBLUNION_IS_NEGZERO(u) DUK__DBLUNION_IS_NEGZERO((u))
571 
572 /* XXX: native 64-bit byteswaps when available */
573 
574 /* 64-bit byteswap, same operation independent of target endianness. */
575 #define DUK_DBLUNION_BSWAP64(u) do { \
576 		duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
577 		duk__bswaptmp1 = (u)->ui[0]; \
578 		duk__bswaptmp2 = (u)->ui[1]; \
579 		duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
580 		duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
581 		(u)->ui[0] = duk__bswaptmp2; \
582 		(u)->ui[1] = duk__bswaptmp1; \
583 	} while (0)
584 
585 /* Byteswap an IEEE double in the duk_double_union from host to network
586  * order.  For a big endian target this is a no-op.
587  */
588 #if defined(DUK_USE_DOUBLE_LE)
589 #define DUK_DBLUNION_DOUBLE_HTON(u) do { \
590 		duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
591 		duk__bswaptmp1 = (u)->ui[0]; \
592 		duk__bswaptmp2 = (u)->ui[1]; \
593 		duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
594 		duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
595 		(u)->ui[0] = duk__bswaptmp2; \
596 		(u)->ui[1] = duk__bswaptmp1; \
597 	} while (0)
598 #elif defined(DUK_USE_DOUBLE_ME)
599 #define DUK_DBLUNION_DOUBLE_HTON(u) do { \
600 		duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
601 		duk__bswaptmp1 = (u)->ui[0]; \
602 		duk__bswaptmp2 = (u)->ui[1]; \
603 		duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
604 		duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
605 		(u)->ui[0] = duk__bswaptmp1; \
606 		(u)->ui[1] = duk__bswaptmp2; \
607 	} while (0)
608 #elif defined(DUK_USE_DOUBLE_BE)
609 #define DUK_DBLUNION_DOUBLE_HTON(u) do { } while (0)
610 #else
611 #error internal error, double endianness insane
612 #endif
613 
614 /* Reverse operation is the same. */
615 #define DUK_DBLUNION_DOUBLE_NTOH(u) DUK_DBLUNION_DOUBLE_HTON((u))
616 
617 /* Some sign bit helpers. */
618 #if defined(DUK_USE_64BIT_OPS)
619 #define DUK_DBLUNION_HAS_SIGNBIT(u) (((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x8000000000000000)) != 0)
620 #define DUK_DBLUNION_GET_SIGNBIT(u) (((u)->ull[DUK_DBL_IDX_ULL0] >> 63U))
621 #else
622 #define DUK_DBLUNION_HAS_SIGNBIT(u) (((u)->ui[DUK_DBL_IDX_UI0] & 0x80000000UL) != 0)
623 #define DUK_DBLUNION_GET_SIGNBIT(u) (((u)->ui[DUK_DBL_IDX_UI0] >> 31U))
624 #endif
625 
626 #endif  /* DUK_DBLUNION_H_INCLUDED */
627 /* #include duk_replacements.h */
628 #line 1 "duk_replacements.h"
629 #if !defined(DUK_REPLACEMENTS_H_INCLUDED)
630 #define DUK_REPLACEMENTS_H_INCLUDED
631 
632 #if !defined(DUK_SINGLE_FILE)
633 #if defined(DUK_USE_COMPUTED_INFINITY)
634 DUK_INTERNAL_DECL double duk_computed_infinity;
635 #endif
636 #if defined(DUK_USE_COMPUTED_NAN)
637 DUK_INTERNAL_DECL double duk_computed_nan;
638 #endif
639 #endif  /* !DUK_SINGLE_FILE */
640 
641 #if defined(DUK_USE_REPL_FPCLASSIFY)
642 DUK_INTERNAL_DECL int duk_repl_fpclassify(double x);
643 #endif
644 #if defined(DUK_USE_REPL_SIGNBIT)
645 DUK_INTERNAL_DECL int duk_repl_signbit(double x);
646 #endif
647 #if defined(DUK_USE_REPL_ISFINITE)
648 DUK_INTERNAL_DECL int duk_repl_isfinite(double x);
649 #endif
650 #if defined(DUK_USE_REPL_ISNAN)
651 DUK_INTERNAL_DECL int duk_repl_isnan(double x);
652 #endif
653 #if defined(DUK_USE_REPL_ISINF)
654 DUK_INTERNAL_DECL int duk_repl_isinf(double x);
655 #endif
656 
657 #endif  /* DUK_REPLACEMENTS_H_INCLUDED */
658 /* #include duk_jmpbuf.h */
659 #line 1 "duk_jmpbuf.h"
660 /*
661  *  Wrapper for jmp_buf.
662  *
663  *  This is used because jmp_buf is an array type for backward compatibility.
664  *  Wrapping jmp_buf in a struct makes pointer references, sizeof, etc,
665  *  behave more intuitively.
666  *
667  *  http://en.wikipedia.org/wiki/Setjmp.h#Member_types
668  */
669 
670 #if !defined(DUK_JMPBUF_H_INCLUDED)
671 #define DUK_JMPBUF_H_INCLUDED
672 
673 #if defined(DUK_USE_CPP_EXCEPTIONS)
674 struct duk_jmpbuf {
675 	duk_small_int_t dummy;  /* unused */
676 };
677 #else
678 struct duk_jmpbuf {
679 	DUK_JMPBUF_TYPE jb;
680 };
681 #endif
682 
683 #endif  /* DUK_JMPBUF_H_INCLUDED */
684 /* #include duk_exception.h */
685 #line 1 "duk_exception.h"
686 /*
687  *  Exceptions for Duktape internal throws when C++ exceptions are used
688  *  for long control transfers.
689  */
690 
691 #if !defined(DUK_EXCEPTION_H_INCLUDED)
692 #define DUK_EXCEPTION_H_INCLUDED
693 
694 #if defined(DUK_USE_CPP_EXCEPTIONS)
695 /* Internal exception used as a setjmp-longjmp replacement.  User code should
696  * NEVER see or catch this exception, so it doesn't inherit from any base
697  * class which should minimize the chance of user code accidentally catching
698  * the exception.
699  */
700 class duk_internal_exception {
701 	/* intentionally empty */
702 };
703 
704 /* Fatal error, thrown as a specific C++ exception with C++ exceptions
705  * enabled.  It is unsafe to continue; doing so may cause crashes or memory
706  * leaks.  This is intended to be either uncaught, or caught by user code
707  * aware of the "unsafe to continue" semantics.
708  */
709 class duk_fatal_exception : public virtual std::runtime_error {
710  public:
duk_fatal_exception(const char * message)711 	duk_fatal_exception(const char *message) : std::runtime_error(message) {}
712 };
713 #endif
714 
715 #endif  /* DUK_EXCEPTION_H_INCLUDED */
716 /* #include duk_forwdecl.h */
717 #line 1 "duk_forwdecl.h"
718 /*
719  *  Forward declarations for all Duktape structures.
720  */
721 
722 #if !defined(DUK_FORWDECL_H_INCLUDED)
723 #define DUK_FORWDECL_H_INCLUDED
724 
725 /*
726  *  Forward declarations
727  */
728 
729 #if defined(DUK_USE_CPP_EXCEPTIONS)
730 class duk_internal_exception;
731 #else
732 struct duk_jmpbuf;
733 #endif
734 
735 /* duk_tval intentionally skipped */
736 struct duk_heaphdr;
737 struct duk_heaphdr_string;
738 struct duk_harray;
739 struct duk_hstring;
740 struct duk_hstring_external;
741 struct duk_hobject;
742 struct duk_hcompfunc;
743 struct duk_hnatfunc;
744 struct duk_hboundfunc;
745 struct duk_hthread;
746 struct duk_hbufobj;
747 struct duk_hdecenv;
748 struct duk_hobjenv;
749 struct duk_hproxy;
750 struct duk_hbuffer;
751 struct duk_hbuffer_fixed;
752 struct duk_hbuffer_dynamic;
753 struct duk_hbuffer_external;
754 
755 struct duk_propaccessor;
756 union duk_propvalue;
757 struct duk_propdesc;
758 
759 struct duk_heap;
760 struct duk_breakpoint;
761 
762 struct duk_activation;
763 struct duk_catcher;
764 struct duk_ljstate;
765 struct duk_strcache_entry;
766 struct duk_litcache_entry;
767 struct duk_strtab_entry;
768 
769 #if defined(DUK_USE_DEBUG)
770 struct duk_fixedbuffer;
771 #endif
772 
773 struct duk_bitdecoder_ctx;
774 struct duk_bitencoder_ctx;
775 struct duk_bufwriter_ctx;
776 
777 struct duk_token;
778 struct duk_re_token;
779 struct duk_lexer_point;
780 struct duk_lexer_ctx;
781 struct duk_lexer_codepoint;
782 
783 struct duk_compiler_instr;
784 struct duk_compiler_func;
785 struct duk_compiler_ctx;
786 
787 struct duk_re_matcher_ctx;
788 struct duk_re_compiler_ctx;
789 
790 #if defined(DUK_USE_CPP_EXCEPTIONS)
791 /* no typedef */
792 #else
793 typedef struct duk_jmpbuf duk_jmpbuf;
794 #endif
795 
796 /* duk_tval intentionally skipped */
797 typedef struct duk_heaphdr duk_heaphdr;
798 typedef struct duk_heaphdr_string duk_heaphdr_string;
799 typedef struct duk_harray duk_harray;
800 typedef struct duk_hstring duk_hstring;
801 typedef struct duk_hstring_external duk_hstring_external;
802 typedef struct duk_hobject duk_hobject;
803 typedef struct duk_hcompfunc duk_hcompfunc;
804 typedef struct duk_hnatfunc duk_hnatfunc;
805 typedef struct duk_hboundfunc duk_hboundfunc;
806 typedef struct duk_hthread duk_hthread;
807 typedef struct duk_hbufobj duk_hbufobj;
808 typedef struct duk_hdecenv duk_hdecenv;
809 typedef struct duk_hobjenv duk_hobjenv;
810 typedef struct duk_hproxy duk_hproxy;
811 typedef struct duk_hbuffer duk_hbuffer;
812 typedef struct duk_hbuffer_fixed duk_hbuffer_fixed;
813 typedef struct duk_hbuffer_dynamic duk_hbuffer_dynamic;
814 typedef struct duk_hbuffer_external duk_hbuffer_external;
815 
816 typedef struct duk_propaccessor duk_propaccessor;
817 typedef union duk_propvalue duk_propvalue;
818 typedef struct duk_propdesc duk_propdesc;
819 
820 typedef struct duk_heap duk_heap;
821 typedef struct duk_breakpoint duk_breakpoint;
822 
823 typedef struct duk_activation duk_activation;
824 typedef struct duk_catcher duk_catcher;
825 typedef struct duk_ljstate duk_ljstate;
826 typedef struct duk_strcache_entry duk_strcache_entry;
827 typedef struct duk_litcache_entry duk_litcache_entry;
828 typedef struct duk_strtab_entry duk_strtab_entry;
829 
830 #if defined(DUK_USE_DEBUG)
831 typedef struct duk_fixedbuffer duk_fixedbuffer;
832 #endif
833 
834 typedef struct duk_bitdecoder_ctx duk_bitdecoder_ctx;
835 typedef struct duk_bitencoder_ctx duk_bitencoder_ctx;
836 typedef struct duk_bufwriter_ctx duk_bufwriter_ctx;
837 
838 typedef struct duk_token duk_token;
839 typedef struct duk_re_token duk_re_token;
840 typedef struct duk_lexer_point duk_lexer_point;
841 typedef struct duk_lexer_ctx duk_lexer_ctx;
842 typedef struct duk_lexer_codepoint duk_lexer_codepoint;
843 
844 typedef struct duk_compiler_instr duk_compiler_instr;
845 typedef struct duk_compiler_func duk_compiler_func;
846 typedef struct duk_compiler_ctx duk_compiler_ctx;
847 
848 typedef struct duk_re_matcher_ctx duk_re_matcher_ctx;
849 typedef struct duk_re_compiler_ctx duk_re_compiler_ctx;
850 
851 #endif  /* DUK_FORWDECL_H_INCLUDED */
852 /* #include duk_tval.h */
853 #line 1 "duk_tval.h"
854 /*
855  *  Tagged type definition (duk_tval) and accessor macros.
856  *
857  *  Access all fields through the accessor macros, as the representation
858  *  is quite tricky.
859  *
860  *  There are two packed type alternatives: an 8-byte representation
861  *  based on an IEEE double (preferred for compactness), and a 12-byte
862  *  representation (portability).  The latter is needed also in e.g.
863  *  64-bit environments (it usually pads to 16 bytes per value).
864  *
865  *  Selecting the tagged type format involves many trade-offs (memory
866  *  use, size and performance of generated code, portability, etc).
867  *
868  *  NB: because macro arguments are often expressions, macros should
869  *  avoid evaluating their argument more than once.
870  */
871 
872 #if !defined(DUK_TVAL_H_INCLUDED)
873 #define DUK_TVAL_H_INCLUDED
874 
875 /* sanity */
876 #if !defined(DUK_USE_DOUBLE_LE) && !defined(DUK_USE_DOUBLE_ME) && !defined(DUK_USE_DOUBLE_BE)
877 #error unsupported: cannot determine byte order variant
878 #endif
879 
880 #if defined(DUK_USE_PACKED_TVAL)
881 /* ======================================================================== */
882 
883 /*
884  *  Packed 8-byte representation
885  */
886 
887 /* use duk_double_union as duk_tval directly */
888 typedef union duk_double_union duk_tval;
889 typedef struct {
890 	duk_uint16_t a;
891 	duk_uint16_t b;
892 	duk_uint16_t c;
893 	duk_uint16_t d;
894 } duk_tval_unused;
895 
896 /* tags */
897 #define DUK_TAG_NORMALIZED_NAN    0x7ff8UL   /* the NaN variant we use */
898 /* avoid tag 0xfff0, no risk of confusion with negative infinity */
899 #define DUK_TAG_MIN               0xfff1UL
900 #if defined(DUK_USE_FASTINT)
901 #define DUK_TAG_FASTINT           0xfff1UL   /* embed: integer value */
902 #endif
903 #define DUK_TAG_UNUSED            0xfff2UL   /* marker; not actual tagged value */
904 #define DUK_TAG_UNDEFINED         0xfff3UL   /* embed: nothing */
905 #define DUK_TAG_NULL              0xfff4UL   /* embed: nothing */
906 #define DUK_TAG_BOOLEAN           0xfff5UL   /* embed: 0 or 1 (false or true) */
907 /* DUK_TAG_NUMBER would logically go here, but it has multiple 'tags' */
908 #define DUK_TAG_POINTER           0xfff6UL   /* embed: void ptr */
909 #define DUK_TAG_LIGHTFUNC         0xfff7UL   /* embed: func ptr */
910 #define DUK_TAG_STRING            0xfff8UL   /* embed: duk_hstring ptr */
911 #define DUK_TAG_OBJECT            0xfff9UL   /* embed: duk_hobject ptr */
912 #define DUK_TAG_BUFFER            0xfffaUL   /* embed: duk_hbuffer ptr */
913 #define DUK_TAG_MAX               0xfffaUL
914 
915 /* for convenience */
916 #define DUK_XTAG_BOOLEAN_FALSE    0xfff50000UL
917 #define DUK_XTAG_BOOLEAN_TRUE     0xfff50001UL
918 
919 #define DUK_TVAL_IS_VALID_TAG(tv) \
920 	(DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)
921 
922 /* DUK_TVAL_UNUSED initializer for duk_tval_unused, works for any endianness. */
923 #define DUK_TVAL_UNUSED_INITIALIZER() \
924 	{ DUK_TAG_UNUSED, DUK_TAG_UNUSED, DUK_TAG_UNUSED, DUK_TAG_UNUSED }
925 
926 /* two casts to avoid gcc warning: "warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]" */
927 #if defined(DUK_USE_64BIT_OPS)
928 #if defined(DUK_USE_DOUBLE_ME)
929 #define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \
930 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 16) | (((duk_uint64_t) (duk_uint32_t) (h)) << 32); \
931 	} while (0)
932 #else
933 #define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \
934 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 48) | ((duk_uint64_t) (duk_uint32_t) (h)); \
935 	} while (0)
936 #endif
937 #else  /* DUK_USE_64BIT_OPS */
938 #define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \
939 		duk_tval *duk__tv; \
940 		duk__tv = (tv); \
941 		duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) (tag)) << 16; \
942 		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (h); \
943 	} while (0)
944 #endif  /* DUK_USE_64BIT_OPS */
945 
946 #if defined(DUK_USE_64BIT_OPS)
947 /* Double casting for pointer to avoid gcc warning (cast from pointer to integer of different size) */
948 #if defined(DUK_USE_DOUBLE_ME)
949 #define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
950 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 16) | \
951 		                              ((duk_uint64_t) (flags)) | \
952 		                              (((duk_uint64_t) (duk_uint32_t) (fp)) << 32); \
953 	} while (0)
954 #else
955 #define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
956 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 48) | \
957 		                              (((duk_uint64_t) (flags)) << 32) | \
958 		                              ((duk_uint64_t) (duk_uint32_t) (fp)); \
959 	} while (0)
960 #endif
961 #else  /* DUK_USE_64BIT_OPS */
962 #define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
963 		duk_tval *duk__tv; \
964 		duk__tv = (tv); \
965 		duk__tv->ui[DUK_DBL_IDX_UI0] = (((duk_uint32_t) DUK_TAG_LIGHTFUNC) << 16) | ((duk_uint32_t) (flags)); \
966 		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (fp); \
967 	} while (0)
968 #endif  /* DUK_USE_64BIT_OPS */
969 
970 #if defined(DUK_USE_FASTINT)
971 /* Note: masking is done for 'i' to deal with negative numbers correctly */
972 #if defined(DUK_USE_DOUBLE_ME)
973 #define DUK__TVAL_SET_I48(tv,i)  do { \
974 		duk_tval *duk__tv; \
975 		duk__tv = (tv); \
976 		duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16 | (((duk_uint32_t) ((i) >> 32)) & 0x0000ffffUL); \
977 		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
978 	} while (0)
979 #define DUK__TVAL_SET_U32(tv,i)  do { \
980 		duk_tval *duk__tv; \
981 		duk__tv = (tv); \
982 		duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16; \
983 		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
984 	} while (0)
985 #else
986 #define DUK__TVAL_SET_I48(tv,i)  do { \
987 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (((duk_uint64_t) (i)) & DUK_U64_CONSTANT(0x0000ffffffffffff)); \
988 	} while (0)
989 #define DUK__TVAL_SET_U32(tv,i)  do { \
990 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (duk_uint64_t) (i); \
991 	} while (0)
992 #endif
993 
994 /* This needs to go through a cast because sign extension is needed. */
995 #define DUK__TVAL_SET_I32(tv,i)  do { \
996 		duk_int64_t duk__tmp = (duk_int64_t) (i); \
997 		DUK_TVAL_SET_I48((tv), duk__tmp); \
998 	} while (0)
999 
1000 /* XXX: Clumsy sign extend and masking of 16 topmost bits. */
1001 #if defined(DUK_USE_DOUBLE_ME)
1002 #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)
1003 #else
1004 #define DUK__TVAL_GET_FASTINT(tv)      ((((duk_int64_t) (tv)->ull[DUK_DBL_IDX_ULL0]) << 16) >> 16)
1005 #endif
1006 #define DUK__TVAL_GET_FASTINT_U32(tv)  ((tv)->ui[DUK_DBL_IDX_UI1])
1007 #define DUK__TVAL_GET_FASTINT_I32(tv)  ((duk_int32_t) (tv)->ui[DUK_DBL_IDX_UI1])
1008 #endif  /* DUK_USE_FASTINT */
1009 
1010 #define DUK_TVAL_SET_UNDEFINED(tv)  do { \
1011 		(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNDEFINED; \
1012 	} while (0)
1013 #define DUK_TVAL_SET_UNUSED(tv)  do { \
1014 		(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNUSED; \
1015 	} while (0)
1016 #define DUK_TVAL_SET_NULL(tv)  do { \
1017 		(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_NULL; \
1018 	} while (0)
1019 
1020 #define DUK_TVAL_SET_BOOLEAN(tv,val)         DUK_DBLUNION_SET_HIGH32((tv), (((duk_uint32_t) DUK_TAG_BOOLEAN) << 16) | ((duk_uint32_t) (val)))
1021 
1022 #define DUK_TVAL_SET_NAN(tv)                 DUK_DBLUNION_SET_NAN_FULL((tv))
1023 
1024 /* Assumes that caller has normalized NaNs, otherwise trouble ahead. */
1025 #if defined(DUK_USE_FASTINT)
1026 #define DUK_TVAL_SET_DOUBLE(tv,d)  do { \
1027 		duk_double_t duk__dblval; \
1028 		duk__dblval = (d); \
1029 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
1030 		DUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \
1031 	} while (0)
1032 #define DUK_TVAL_SET_I48(tv,i)               DUK__TVAL_SET_I48((tv), (i))
1033 #define DUK_TVAL_SET_I32(tv,i)               DUK__TVAL_SET_I32((tv), (i))
1034 #define DUK_TVAL_SET_U32(tv,i)               DUK__TVAL_SET_U32((tv), (i))
1035 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d)  duk_tval_set_number_chkfast_fast((tv), (d))
1036 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d)  duk_tval_set_number_chkfast_slow((tv), (d))
1037 #define DUK_TVAL_SET_NUMBER(tv,d)            DUK_TVAL_SET_DOUBLE((tv), (d))
1038 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { \
1039 		duk_tval *duk__tv; \
1040 		duk_double_t duk__d; \
1041 		duk__tv = (tv); \
1042 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1043 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1044 			DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \
1045 		} \
1046 	} while (0)
1047 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { \
1048 		duk_tval *duk__tv; \
1049 		duk_double_t duk__d; \
1050 		duk__tv = (tv); \
1051 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1052 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1053 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \
1054 		} \
1055 	} while (0)
1056 #else  /* DUK_USE_FASTINT */
1057 #define DUK_TVAL_SET_DOUBLE(tv,d)  do { \
1058 		duk_double_t duk__dblval; \
1059 		duk__dblval = (d); \
1060 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
1061 		DUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \
1062 	} while (0)
1063 #define DUK_TVAL_SET_I48(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))  /* XXX: fast int-to-double */
1064 #define DUK_TVAL_SET_I32(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
1065 #define DUK_TVAL_SET_U32(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
1066 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d)    DUK_TVAL_SET_DOUBLE((tv), (d))
1067 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d)    DUK_TVAL_SET_DOUBLE((tv), (d))
1068 #define DUK_TVAL_SET_NUMBER(tv,d)            DUK_TVAL_SET_DOUBLE((tv), (d))
1069 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { } while (0)
1070 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { } while (0)
1071 #endif  /* DUK_USE_FASTINT */
1072 
1073 #define DUK_TVAL_SET_FASTINT(tv,i)           DUK_TVAL_SET_I48((tv), (i))  /* alias */
1074 
1075 #define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags)  DUK__TVAL_SET_LIGHTFUNC((tv), (fp), (flags))
1076 #define DUK_TVAL_SET_STRING(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_STRING)
1077 #define DUK_TVAL_SET_OBJECT(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_OBJECT)
1078 #define DUK_TVAL_SET_BUFFER(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_BUFFER)
1079 #define DUK_TVAL_SET_POINTER(tv,p)           DUK__TVAL_SET_TAGGEDPOINTER((tv), (p), DUK_TAG_POINTER)
1080 
1081 #define DUK_TVAL_SET_TVAL(tv,x)              do { *(tv) = *(x); } while (0)
1082 
1083 /* getters */
1084 #define DUK_TVAL_GET_BOOLEAN(tv)             ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US1])
1085 #if defined(DUK_USE_FASTINT)
1086 #define DUK_TVAL_GET_DOUBLE(tv)              ((tv)->d)
1087 #define DUK_TVAL_GET_FASTINT(tv)             DUK__TVAL_GET_FASTINT((tv))
1088 #define DUK_TVAL_GET_FASTINT_U32(tv)         DUK__TVAL_GET_FASTINT_U32((tv))
1089 #define DUK_TVAL_GET_FASTINT_I32(tv)         DUK__TVAL_GET_FASTINT_I32((tv))
1090 #define DUK_TVAL_GET_NUMBER(tv)              duk_tval_get_number_packed((tv))
1091 #else
1092 #define DUK_TVAL_GET_NUMBER(tv)              ((tv)->d)
1093 #define DUK_TVAL_GET_DOUBLE(tv)              ((tv)->d)
1094 #endif
1095 #define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags)  do { \
1096 		(out_flags) = (tv)->ui[DUK_DBL_IDX_UI0] & 0xffffUL; \
1097 		(out_fp) = (duk_c_function) (tv)->ui[DUK_DBL_IDX_UI1]; \
1098 	} while (0)
1099 #define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv)   ((duk_c_function) ((tv)->ui[DUK_DBL_IDX_UI1]))
1100 #define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv)     (((duk_small_uint_t) (tv)->ui[DUK_DBL_IDX_UI0]) & 0xffffUL)
1101 #define DUK_TVAL_GET_STRING(tv)              ((duk_hstring *) (tv)->vp[DUK_DBL_IDX_VP1])
1102 #define DUK_TVAL_GET_OBJECT(tv)              ((duk_hobject *) (tv)->vp[DUK_DBL_IDX_VP1])
1103 #define DUK_TVAL_GET_BUFFER(tv)              ((duk_hbuffer *) (tv)->vp[DUK_DBL_IDX_VP1])
1104 #define DUK_TVAL_GET_POINTER(tv)             ((void *) (tv)->vp[DUK_DBL_IDX_VP1])
1105 #define DUK_TVAL_GET_HEAPHDR(tv)             ((duk_heaphdr *) (tv)->vp[DUK_DBL_IDX_VP1])
1106 
1107 /* decoding */
1108 #define DUK_TVAL_GET_TAG(tv)                 ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US0])
1109 
1110 #define DUK_TVAL_IS_UNDEFINED(tv)            (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNDEFINED)
1111 #define DUK_TVAL_IS_UNUSED(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNUSED)
1112 #define DUK_TVAL_IS_NULL(tv)                 (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_NULL)
1113 #define DUK_TVAL_IS_BOOLEAN(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BOOLEAN)
1114 #define DUK_TVAL_IS_BOOLEAN_TRUE(tv)         ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_TRUE)
1115 #define DUK_TVAL_IS_BOOLEAN_FALSE(tv)        ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_FALSE)
1116 #define DUK_TVAL_IS_LIGHTFUNC(tv)            (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_LIGHTFUNC)
1117 #define DUK_TVAL_IS_STRING(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_STRING)
1118 #define DUK_TVAL_IS_OBJECT(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_OBJECT)
1119 #define DUK_TVAL_IS_BUFFER(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BUFFER)
1120 #define DUK_TVAL_IS_POINTER(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_POINTER)
1121 #if defined(DUK_USE_FASTINT)
1122 /* 0xfff0 is -Infinity */
1123 #define DUK_TVAL_IS_DOUBLE(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)
1124 #define DUK_TVAL_IS_FASTINT(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_FASTINT)
1125 #define DUK_TVAL_IS_NUMBER(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff1UL)
1126 #else
1127 #define DUK_TVAL_IS_NUMBER(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)
1128 #define DUK_TVAL_IS_DOUBLE(tv)               DUK_TVAL_IS_NUMBER((tv))
1129 #endif
1130 
1131 /* This is performance critical because it appears in every DECREF. */
1132 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv)       (DUK_TVAL_GET_TAG((tv)) >= DUK_TAG_STRING)
1133 
1134 #if defined(DUK_USE_FASTINT)
1135 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_packed(duk_tval *tv);
1136 #endif
1137 
1138 #else  /* DUK_USE_PACKED_TVAL */
1139 /* ======================================================================== */
1140 
1141 /*
1142  *  Portable 12-byte representation
1143  */
1144 
1145 /* Note: not initializing all bytes is normally not an issue: Duktape won't
1146  * read or use the uninitialized bytes so valgrind won't issue warnings.
1147  * In some special cases a harmless valgrind warning may be issued though.
1148  * For example, the DumpHeap debugger command writes out a compiled function's
1149  * 'data' area as is, including any uninitialized bytes, which causes a
1150  * valgrind warning.
1151  */
1152 
1153 typedef struct duk_tval_struct duk_tval;
1154 
1155 struct duk_tval_struct {
1156 	duk_small_uint_t t;
1157 	duk_small_uint_t v_extra;
1158 	union {
1159 		duk_double_t d;
1160 		duk_small_int_t i;
1161 #if defined(DUK_USE_FASTINT)
1162 		duk_int64_t fi;  /* if present, forces 16-byte duk_tval */
1163 #endif
1164 		void *voidptr;
1165 		duk_hstring *hstring;
1166 		duk_hobject *hobject;
1167 		duk_hcompfunc *hcompfunc;
1168 		duk_hnatfunc *hnatfunc;
1169 		duk_hthread *hthread;
1170 		duk_hbuffer *hbuffer;
1171 		duk_heaphdr *heaphdr;
1172 		duk_c_function lightfunc;
1173 	} v;
1174 };
1175 
1176 typedef struct {
1177 	duk_small_uint_t t;
1178 	duk_small_uint_t v_extra;
1179 	/* The rest of the fields don't matter except for debug dumps and such
1180 	 * for which a partial initializer may trigger out-ot-bounds memory
1181 	 * reads.  Include a double field which is usually as large or larger
1182 	 * than pointers (not always however).
1183 	 */
1184 	duk_double_t d;
1185 } duk_tval_unused;
1186 
1187 #define DUK_TVAL_UNUSED_INITIALIZER() \
1188 	{ DUK_TAG_UNUSED, 0, 0.0 }
1189 
1190 #define DUK_TAG_MIN                   0
1191 #define DUK_TAG_NUMBER                0  /* DUK_TAG_NUMBER only defined for non-packed duk_tval */
1192 #if defined(DUK_USE_FASTINT)
1193 #define DUK_TAG_FASTINT               1
1194 #endif
1195 #define DUK_TAG_UNDEFINED             2
1196 #define DUK_TAG_NULL                  3
1197 #define DUK_TAG_BOOLEAN               4
1198 #define DUK_TAG_POINTER               5
1199 #define DUK_TAG_LIGHTFUNC             6
1200 #define DUK_TAG_UNUSED                7  /* marker; not actual tagged type */
1201 #define DUK_TAG_STRING                8  /* first heap allocated, match bit boundary */
1202 #define DUK_TAG_OBJECT                9
1203 #define DUK_TAG_BUFFER                10
1204 #define DUK_TAG_MAX                   10
1205 
1206 #define DUK_TVAL_IS_VALID_TAG(tv) \
1207 	(DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)
1208 
1209 /* DUK_TAG_NUMBER is intentionally first, as it is the default clause in code
1210  * to support the 8-byte representation.  Further, it is a non-heap-allocated
1211  * type so it should come before DUK_TAG_STRING.  Finally, it should not break
1212  * the tag value ranges covered by case-clauses in a switch-case.
1213  */
1214 
1215 /* setters */
1216 #define DUK_TVAL_SET_UNDEFINED(tv)  do { \
1217 		duk_tval *duk__tv; \
1218 		duk__tv = (tv); \
1219 		duk__tv->t = DUK_TAG_UNDEFINED; \
1220 	} while (0)
1221 
1222 #define DUK_TVAL_SET_UNUSED(tv)  do { \
1223 		duk_tval *duk__tv; \
1224 		duk__tv = (tv); \
1225 		duk__tv->t = DUK_TAG_UNUSED; \
1226 	} while (0)
1227 
1228 #define DUK_TVAL_SET_NULL(tv)  do { \
1229 		duk_tval *duk__tv; \
1230 		duk__tv = (tv); \
1231 		duk__tv->t = DUK_TAG_NULL; \
1232 	} while (0)
1233 
1234 #define DUK_TVAL_SET_BOOLEAN(tv,val)  do { \
1235 		duk_tval *duk__tv; \
1236 		duk__tv = (tv); \
1237 		duk__tv->t = DUK_TAG_BOOLEAN; \
1238 		duk__tv->v.i = (duk_small_int_t) (val); \
1239 	} while (0)
1240 
1241 #if defined(DUK_USE_FASTINT)
1242 #define DUK_TVAL_SET_DOUBLE(tv,val)  do { \
1243 		duk_tval *duk__tv; \
1244 		duk_double_t duk__dblval; \
1245 		duk__dblval = (val); \
1246 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); /* nop for unpacked duk_tval */ \
1247 		duk__tv = (tv); \
1248 		duk__tv->t = DUK_TAG_NUMBER; \
1249 		duk__tv->v.d = duk__dblval; \
1250 	} while (0)
1251 #define DUK_TVAL_SET_I48(tv,val)  do { \
1252 		duk_tval *duk__tv; \
1253 		duk__tv = (tv); \
1254 		duk__tv->t = DUK_TAG_FASTINT; \
1255 		duk__tv->v.fi = (val); \
1256 	} while (0)
1257 #define DUK_TVAL_SET_U32(tv,val)  do { \
1258 		duk_tval *duk__tv; \
1259 		duk__tv = (tv); \
1260 		duk__tv->t = DUK_TAG_FASTINT; \
1261 		duk__tv->v.fi = (duk_int64_t) (val); \
1262 	} while (0)
1263 #define DUK_TVAL_SET_I32(tv,val)  do { \
1264 		duk_tval *duk__tv; \
1265 		duk__tv = (tv); \
1266 		duk__tv->t = DUK_TAG_FASTINT; \
1267 		duk__tv->v.fi = (duk_int64_t) (val); \
1268 	} while (0)
1269 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \
1270 	duk_tval_set_number_chkfast_fast((tv), (d))
1271 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \
1272 	duk_tval_set_number_chkfast_slow((tv), (d))
1273 #define DUK_TVAL_SET_NUMBER(tv,val) \
1274 	DUK_TVAL_SET_DOUBLE((tv), (val))
1275 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { \
1276 		duk_tval *duk__tv; \
1277 		duk_double_t duk__d; \
1278 		duk__tv = (tv); \
1279 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1280 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1281 			DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \
1282 		} \
1283 	} while (0)
1284 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { \
1285 		duk_tval *duk__tv; \
1286 		duk_double_t duk__d; \
1287 		duk__tv = (tv); \
1288 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1289 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1290 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \
1291 		} \
1292 	} while (0)
1293 #else  /* DUK_USE_FASTINT */
1294 #define DUK_TVAL_SET_DOUBLE(tv,d) \
1295 	DUK_TVAL_SET_NUMBER((tv), (d))
1296 #define DUK_TVAL_SET_I48(tv,val) \
1297 	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))  /* XXX: fast int-to-double */
1298 #define DUK_TVAL_SET_U32(tv,val) \
1299 	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
1300 #define DUK_TVAL_SET_I32(tv,val) \
1301 	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
1302 #define DUK_TVAL_SET_NUMBER(tv,val)  do { \
1303 		duk_tval *duk__tv; \
1304 		duk_double_t duk__dblval; \
1305 		duk__dblval = (val); \
1306 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); /* nop for unpacked duk_tval */ \
1307 		duk__tv = (tv); \
1308 		duk__tv->t = DUK_TAG_NUMBER; \
1309 		duk__tv->v.d = duk__dblval; \
1310 	} while (0)
1311 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \
1312 	DUK_TVAL_SET_NUMBER((tv), (d))
1313 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \
1314 	DUK_TVAL_SET_NUMBER((tv), (d))
1315 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { } while (0)
1316 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { } while (0)
1317 #endif  /* DUK_USE_FASTINT */
1318 
1319 #define DUK_TVAL_SET_FASTINT(tv,i) \
1320 	DUK_TVAL_SET_I48((tv), (i))  /* alias */
1321 
1322 #define DUK_TVAL_SET_POINTER(tv,hptr)  do { \
1323 		duk_tval *duk__tv; \
1324 		duk__tv = (tv); \
1325 		duk__tv->t = DUK_TAG_POINTER; \
1326 		duk__tv->v.voidptr = (hptr); \
1327 	} while (0)
1328 
1329 #define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
1330 		duk_tval *duk__tv; \
1331 		duk__tv = (tv); \
1332 		duk__tv->t = DUK_TAG_LIGHTFUNC; \
1333 		duk__tv->v_extra = (flags); \
1334 		duk__tv->v.lightfunc = (duk_c_function) (fp); \
1335 	} while (0)
1336 
1337 #define DUK_TVAL_SET_STRING(tv,hptr)  do { \
1338 		duk_tval *duk__tv; \
1339 		duk__tv = (tv); \
1340 		duk__tv->t = DUK_TAG_STRING; \
1341 		duk__tv->v.hstring = (hptr); \
1342 	} while (0)
1343 
1344 #define DUK_TVAL_SET_OBJECT(tv,hptr)  do { \
1345 		duk_tval *duk__tv; \
1346 		duk__tv = (tv); \
1347 		duk__tv->t = DUK_TAG_OBJECT; \
1348 		duk__tv->v.hobject = (hptr); \
1349 	} while (0)
1350 
1351 #define DUK_TVAL_SET_BUFFER(tv,hptr)  do { \
1352 		duk_tval *duk__tv; \
1353 		duk__tv = (tv); \
1354 		duk__tv->t = DUK_TAG_BUFFER; \
1355 		duk__tv->v.hbuffer = (hptr); \
1356 	} while (0)
1357 
1358 #define DUK_TVAL_SET_NAN(tv)  do { \
1359 		/* in non-packed representation we don't care about which NaN is used */ \
1360 		duk_tval *duk__tv; \
1361 		duk__tv = (tv); \
1362 		duk__tv->t = DUK_TAG_NUMBER; \
1363 		duk__tv->v.d = DUK_DOUBLE_NAN; \
1364 	} while (0)
1365 
1366 #define DUK_TVAL_SET_TVAL(tv,x)            do { *(tv) = *(x); } while (0)
1367 
1368 /* getters */
1369 #define DUK_TVAL_GET_BOOLEAN(tv)           ((duk_small_uint_t) (tv)->v.i)
1370 #if defined(DUK_USE_FASTINT)
1371 #define DUK_TVAL_GET_DOUBLE(tv)            ((tv)->v.d)
1372 #define DUK_TVAL_GET_FASTINT(tv)           ((tv)->v.fi)
1373 #define DUK_TVAL_GET_FASTINT_U32(tv)       ((duk_uint32_t) ((tv)->v.fi))
1374 #define DUK_TVAL_GET_FASTINT_I32(tv)       ((duk_int32_t) ((tv)->v.fi))
1375 #if 0
1376 #define DUK_TVAL_GET_NUMBER(tv)            (DUK_TVAL_IS_FASTINT((tv)) ? \
1377                                                (duk_double_t) DUK_TVAL_GET_FASTINT((tv)) : \
1378                                                DUK_TVAL_GET_DOUBLE((tv)))
1379 #define DUK_TVAL_GET_NUMBER(tv)            duk_tval_get_number_unpacked((tv))
1380 #else
1381 /* This seems reasonable overall. */
1382 #define DUK_TVAL_GET_NUMBER(tv)            (DUK_TVAL_IS_FASTINT((tv)) ? \
1383                                                duk_tval_get_number_unpacked_fastint((tv)) : \
1384                                                DUK_TVAL_GET_DOUBLE((tv)))
1385 #endif
1386 #else
1387 #define DUK_TVAL_GET_NUMBER(tv)            ((tv)->v.d)
1388 #define DUK_TVAL_GET_DOUBLE(tv)            ((tv)->v.d)
1389 #endif  /* DUK_USE_FASTINT */
1390 #define DUK_TVAL_GET_POINTER(tv)           ((tv)->v.voidptr)
1391 #define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags)  do { \
1392 		(out_flags) = (duk_uint32_t) (tv)->v_extra; \
1393 		(out_fp) = (tv)->v.lightfunc; \
1394 	} while (0)
1395 #define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((tv)->v.lightfunc)
1396 #define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv)   ((duk_small_uint_t) ((tv)->v_extra))
1397 #define DUK_TVAL_GET_STRING(tv)            ((tv)->v.hstring)
1398 #define DUK_TVAL_GET_OBJECT(tv)            ((tv)->v.hobject)
1399 #define DUK_TVAL_GET_BUFFER(tv)            ((tv)->v.hbuffer)
1400 #define DUK_TVAL_GET_HEAPHDR(tv)           ((tv)->v.heaphdr)
1401 
1402 /* decoding */
1403 #define DUK_TVAL_GET_TAG(tv)               ((tv)->t)
1404 #define DUK_TVAL_IS_UNDEFINED(tv)          ((tv)->t == DUK_TAG_UNDEFINED)
1405 #define DUK_TVAL_IS_UNUSED(tv)             ((tv)->t == DUK_TAG_UNUSED)
1406 #define DUK_TVAL_IS_NULL(tv)               ((tv)->t == DUK_TAG_NULL)
1407 #define DUK_TVAL_IS_BOOLEAN(tv)            ((tv)->t == DUK_TAG_BOOLEAN)
1408 #define DUK_TVAL_IS_BOOLEAN_TRUE(tv)       (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i != 0))
1409 #define DUK_TVAL_IS_BOOLEAN_FALSE(tv)      (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i == 0))
1410 #if defined(DUK_USE_FASTINT)
1411 #define DUK_TVAL_IS_DOUBLE(tv)             ((tv)->t == DUK_TAG_NUMBER)
1412 #define DUK_TVAL_IS_FASTINT(tv)            ((tv)->t == DUK_TAG_FASTINT)
1413 #define DUK_TVAL_IS_NUMBER(tv)             ((tv)->t == DUK_TAG_NUMBER || \
1414                                             (tv)->t == DUK_TAG_FASTINT)
1415 #else
1416 #define DUK_TVAL_IS_NUMBER(tv)             ((tv)->t == DUK_TAG_NUMBER)
1417 #define DUK_TVAL_IS_DOUBLE(tv)             DUK_TVAL_IS_NUMBER((tv))
1418 #endif  /* DUK_USE_FASTINT */
1419 #define DUK_TVAL_IS_POINTER(tv)            ((tv)->t == DUK_TAG_POINTER)
1420 #define DUK_TVAL_IS_LIGHTFUNC(tv)          ((tv)->t == DUK_TAG_LIGHTFUNC)
1421 #define DUK_TVAL_IS_STRING(tv)             ((tv)->t == DUK_TAG_STRING)
1422 #define DUK_TVAL_IS_OBJECT(tv)             ((tv)->t == DUK_TAG_OBJECT)
1423 #define DUK_TVAL_IS_BUFFER(tv)             ((tv)->t == DUK_TAG_BUFFER)
1424 
1425 /* This is performance critical because it's needed for every DECREF.
1426  * Take advantage of the fact that the first heap allocated tag is 8,
1427  * so that bit 3 is set for all heap allocated tags (and never set for
1428  * non-heap-allocated tags).
1429  */
1430 #if 0
1431 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv)     ((tv)->t >= DUK_TAG_STRING)
1432 #endif
1433 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv)     ((tv)->t & 0x08)
1434 
1435 #if defined(DUK_USE_FASTINT)
1436 #if 0
1437 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked(duk_tval *tv);
1438 #endif
1439 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv);
1440 #endif
1441 
1442 #endif  /* DUK_USE_PACKED_TVAL */
1443 
1444 /*
1445  *  Convenience (independent of representation)
1446  */
1447 
1448 #define DUK_TVAL_SET_BOOLEAN_TRUE(tv)        DUK_TVAL_SET_BOOLEAN((tv), 1)
1449 #define DUK_TVAL_SET_BOOLEAN_FALSE(tv)       DUK_TVAL_SET_BOOLEAN((tv), 0)
1450 
1451 #define DUK_TVAL_STRING_IS_SYMBOL(tv) \
1452 	DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING((tv)))
1453 
1454 /* Lightfunc flags packing and unpacking. */
1455 /* Sign extend: 0x0000##00 -> 0x##000000 -> sign extend to 0xssssss##.
1456  * Avoid signed shifts due to portability limitations.
1457  */
1458 #define DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags) \
1459 	((duk_int32_t) (duk_int8_t) (((duk_uint16_t) (lf_flags)) >> 8))
1460 #define DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags) \
1461 	(((lf_flags) >> 4) & 0x0fU)
1462 #define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags) \
1463 	((lf_flags) & 0x0fU)
1464 #define DUK_LFUNC_FLAGS_PACK(magic,length,nargs) \
1465 	((((duk_small_uint_t) (magic)) & 0xffU) << 8) | ((length) << 4) | (nargs)
1466 
1467 #define DUK_LFUNC_NARGS_VARARGS             0x0f   /* varargs marker */
1468 #define DUK_LFUNC_NARGS_MIN                 0x00
1469 #define DUK_LFUNC_NARGS_MAX                 0x0e   /* max, excl. varargs marker */
1470 #define DUK_LFUNC_LENGTH_MIN                0x00
1471 #define DUK_LFUNC_LENGTH_MAX                0x0f
1472 #define DUK_LFUNC_MAGIC_MIN                 (-0x80)
1473 #define DUK_LFUNC_MAGIC_MAX                 0x7f
1474 
1475 /* fastint constants etc */
1476 #if defined(DUK_USE_FASTINT)
1477 #define DUK_FASTINT_MIN           (DUK_I64_CONSTANT(-0x800000000000))
1478 #define DUK_FASTINT_MAX           (DUK_I64_CONSTANT(0x7fffffffffff))
1479 #define DUK_FASTINT_BITS          48
1480 
1481 DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x);
1482 DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x);
1483 #endif
1484 
1485 #endif  /* DUK_TVAL_H_INCLUDED */
1486 /* #include duk_builtins.h */
1487 #line 1 "duk_builtins.h"
1488 /*
1489  *  Automatically generated by genbuiltins.py, do not edit!
1490  */
1491 
1492 #if !defined(DUK_BUILTINS_H_INCLUDED)
1493 #define DUK_BUILTINS_H_INCLUDED
1494 
1495 #if defined(DUK_USE_ROM_STRINGS)
1496 #error ROM support not enabled, rerun configure.py with --rom-support
1497 #else  /* DUK_USE_ROM_STRINGS */
1498 #define DUK_STRIDX_UC_UNDEFINED                                       0                              /* 'Undefined' */
1499 #define DUK_HEAP_STRING_UC_UNDEFINED(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_UNDEFINED)
1500 #define DUK_HTHREAD_STRING_UC_UNDEFINED(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_UNDEFINED)
1501 #define DUK_STRIDX_UC_NULL                                            1                              /* 'Null' */
1502 #define DUK_HEAP_STRING_UC_NULL(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NULL)
1503 #define DUK_HTHREAD_STRING_UC_NULL(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NULL)
1504 #define DUK_STRIDX_UC_SYMBOL                                          2                              /* 'Symbol' */
1505 #define DUK_HEAP_STRING_UC_SYMBOL(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_SYMBOL)
1506 #define DUK_HTHREAD_STRING_UC_SYMBOL(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_SYMBOL)
1507 #define DUK_STRIDX_UC_ARGUMENTS                                       3                              /* 'Arguments' */
1508 #define DUK_HEAP_STRING_UC_ARGUMENTS(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ARGUMENTS)
1509 #define DUK_HTHREAD_STRING_UC_ARGUMENTS(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ARGUMENTS)
1510 #define DUK_STRIDX_UC_OBJECT                                          4                              /* 'Object' */
1511 #define DUK_HEAP_STRING_UC_OBJECT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_OBJECT)
1512 #define DUK_HTHREAD_STRING_UC_OBJECT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_OBJECT)
1513 #define DUK_STRIDX_UC_FUNCTION                                        5                              /* 'Function' */
1514 #define DUK_HEAP_STRING_UC_FUNCTION(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_FUNCTION)
1515 #define DUK_HTHREAD_STRING_UC_FUNCTION(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_FUNCTION)
1516 #define DUK_STRIDX_ARRAY                                              6                              /* 'Array' */
1517 #define DUK_HEAP_STRING_ARRAY(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY)
1518 #define DUK_HTHREAD_STRING_ARRAY(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY)
1519 #define DUK_STRIDX_UC_STRING                                          7                              /* 'String' */
1520 #define DUK_HEAP_STRING_UC_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_STRING)
1521 #define DUK_HTHREAD_STRING_UC_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_STRING)
1522 #define DUK_STRIDX_UC_BOOLEAN                                         8                              /* 'Boolean' */
1523 #define DUK_HEAP_STRING_UC_BOOLEAN(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BOOLEAN)
1524 #define DUK_HTHREAD_STRING_UC_BOOLEAN(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BOOLEAN)
1525 #define DUK_STRIDX_UC_NUMBER                                          9                              /* 'Number' */
1526 #define DUK_HEAP_STRING_UC_NUMBER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NUMBER)
1527 #define DUK_HTHREAD_STRING_UC_NUMBER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NUMBER)
1528 #define DUK_STRIDX_DATE                                               10                             /* 'Date' */
1529 #define DUK_HEAP_STRING_DATE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATE)
1530 #define DUK_HTHREAD_STRING_DATE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATE)
1531 #define DUK_STRIDX_REG_EXP                                            11                             /* 'RegExp' */
1532 #define DUK_HEAP_STRING_REG_EXP(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REG_EXP)
1533 #define DUK_HTHREAD_STRING_REG_EXP(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_REG_EXP)
1534 #define DUK_STRIDX_UC_ERROR                                           12                             /* 'Error' */
1535 #define DUK_HEAP_STRING_UC_ERROR(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ERROR)
1536 #define DUK_HTHREAD_STRING_UC_ERROR(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ERROR)
1537 #define DUK_STRIDX_MATH                                               13                             /* 'Math' */
1538 #define DUK_HEAP_STRING_MATH(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MATH)
1539 #define DUK_HTHREAD_STRING_MATH(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MATH)
1540 #define DUK_STRIDX_JSON                                               14                             /* 'JSON' */
1541 #define DUK_HEAP_STRING_JSON(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON)
1542 #define DUK_HTHREAD_STRING_JSON(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON)
1543 #define DUK_STRIDX_EMPTY_STRING                                       15                             /* '' */
1544 #define DUK_HEAP_STRING_EMPTY_STRING(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EMPTY_STRING)
1545 #define DUK_HTHREAD_STRING_EMPTY_STRING(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EMPTY_STRING)
1546 #define DUK_STRIDX_ARRAY_BUFFER                                       16                             /* 'ArrayBuffer' */
1547 #define DUK_HEAP_STRING_ARRAY_BUFFER(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY_BUFFER)
1548 #define DUK_HTHREAD_STRING_ARRAY_BUFFER(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY_BUFFER)
1549 #define DUK_STRIDX_DATA_VIEW                                          17                             /* 'DataView' */
1550 #define DUK_HEAP_STRING_DATA_VIEW(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA_VIEW)
1551 #define DUK_HTHREAD_STRING_DATA_VIEW(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA_VIEW)
1552 #define DUK_STRIDX_INT8_ARRAY                                         18                             /* 'Int8Array' */
1553 #define DUK_HEAP_STRING_INT8_ARRAY(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT8_ARRAY)
1554 #define DUK_HTHREAD_STRING_INT8_ARRAY(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT8_ARRAY)
1555 #define DUK_STRIDX_UINT8_ARRAY                                        19                             /* 'Uint8Array' */
1556 #define DUK_HEAP_STRING_UINT8_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_ARRAY)
1557 #define DUK_HTHREAD_STRING_UINT8_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_ARRAY)
1558 #define DUK_STRIDX_UINT8_CLAMPED_ARRAY                                20                             /* 'Uint8ClampedArray' */
1559 #define DUK_HEAP_STRING_UINT8_CLAMPED_ARRAY(heap)                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
1560 #define DUK_HTHREAD_STRING_UINT8_CLAMPED_ARRAY(thr)                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
1561 #define DUK_STRIDX_INT16_ARRAY                                        21                             /* 'Int16Array' */
1562 #define DUK_HEAP_STRING_INT16_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT16_ARRAY)
1563 #define DUK_HTHREAD_STRING_INT16_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT16_ARRAY)
1564 #define DUK_STRIDX_UINT16_ARRAY                                       22                             /* 'Uint16Array' */
1565 #define DUK_HEAP_STRING_UINT16_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT16_ARRAY)
1566 #define DUK_HTHREAD_STRING_UINT16_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT16_ARRAY)
1567 #define DUK_STRIDX_INT32_ARRAY                                        23                             /* 'Int32Array' */
1568 #define DUK_HEAP_STRING_INT32_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT32_ARRAY)
1569 #define DUK_HTHREAD_STRING_INT32_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT32_ARRAY)
1570 #define DUK_STRIDX_UINT32_ARRAY                                       24                             /* 'Uint32Array' */
1571 #define DUK_HEAP_STRING_UINT32_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT32_ARRAY)
1572 #define DUK_HTHREAD_STRING_UINT32_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT32_ARRAY)
1573 #define DUK_STRIDX_FLOAT32_ARRAY                                      25                             /* 'Float32Array' */
1574 #define DUK_HEAP_STRING_FLOAT32_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT32_ARRAY)
1575 #define DUK_HTHREAD_STRING_FLOAT32_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT32_ARRAY)
1576 #define DUK_STRIDX_FLOAT64_ARRAY                                      26                             /* 'Float64Array' */
1577 #define DUK_HEAP_STRING_FLOAT64_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT64_ARRAY)
1578 #define DUK_HTHREAD_STRING_FLOAT64_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT64_ARRAY)
1579 #define DUK_STRIDX_GLOBAL                                             27                             /* 'global' */
1580 #define DUK_HEAP_STRING_GLOBAL(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GLOBAL)
1581 #define DUK_HTHREAD_STRING_GLOBAL(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GLOBAL)
1582 #define DUK_STRIDX_OBJ_ENV                                            28                             /* 'ObjEnv' */
1583 #define DUK_HEAP_STRING_OBJ_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OBJ_ENV)
1584 #define DUK_HTHREAD_STRING_OBJ_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OBJ_ENV)
1585 #define DUK_STRIDX_DEC_ENV                                            29                             /* 'DecEnv' */
1586 #define DUK_HEAP_STRING_DEC_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEC_ENV)
1587 #define DUK_HTHREAD_STRING_DEC_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEC_ENV)
1588 #define DUK_STRIDX_UC_BUFFER                                          30                             /* 'Buffer' */
1589 #define DUK_HEAP_STRING_UC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER)
1590 #define DUK_HTHREAD_STRING_UC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER)
1591 #define DUK_STRIDX_UC_POINTER                                         31                             /* 'Pointer' */
1592 #define DUK_HEAP_STRING_UC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_POINTER)
1593 #define DUK_HTHREAD_STRING_UC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_POINTER)
1594 #define DUK_STRIDX_UC_THREAD                                          32                             /* 'Thread' */
1595 #define DUK_HEAP_STRING_UC_THREAD(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_THREAD)
1596 #define DUK_HTHREAD_STRING_UC_THREAD(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_THREAD)
1597 #define DUK_STRIDX_EVAL                                               33                             /* 'eval' */
1598 #define DUK_HEAP_STRING_EVAL(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EVAL)
1599 #define DUK_HTHREAD_STRING_EVAL(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EVAL)
1600 #define DUK_STRIDX_VALUE                                              34                             /* 'value' */
1601 #define DUK_HEAP_STRING_VALUE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE)
1602 #define DUK_HTHREAD_STRING_VALUE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE)
1603 #define DUK_STRIDX_WRITABLE                                           35                             /* 'writable' */
1604 #define DUK_HEAP_STRING_WRITABLE(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITABLE)
1605 #define DUK_HTHREAD_STRING_WRITABLE(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITABLE)
1606 #define DUK_STRIDX_CONFIGURABLE                                       36                             /* 'configurable' */
1607 #define DUK_HEAP_STRING_CONFIGURABLE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONFIGURABLE)
1608 #define DUK_HTHREAD_STRING_CONFIGURABLE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONFIGURABLE)
1609 #define DUK_STRIDX_ENUMERABLE                                         37                             /* 'enumerable' */
1610 #define DUK_HEAP_STRING_ENUMERABLE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUMERABLE)
1611 #define DUK_HTHREAD_STRING_ENUMERABLE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUMERABLE)
1612 #define DUK_STRIDX_JOIN                                               38                             /* 'join' */
1613 #define DUK_HEAP_STRING_JOIN(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JOIN)
1614 #define DUK_HTHREAD_STRING_JOIN(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JOIN)
1615 #define DUK_STRIDX_TO_LOCALE_STRING                                   39                             /* 'toLocaleString' */
1616 #define DUK_HEAP_STRING_TO_LOCALE_STRING(heap)                        DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_LOCALE_STRING)
1617 #define DUK_HTHREAD_STRING_TO_LOCALE_STRING(thr)                      DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_LOCALE_STRING)
1618 #define DUK_STRIDX_VALUE_OF                                           40                             /* 'valueOf' */
1619 #define DUK_HEAP_STRING_VALUE_OF(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE_OF)
1620 #define DUK_HTHREAD_STRING_VALUE_OF(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE_OF)
1621 #define DUK_STRIDX_TO_UTC_STRING                                      41                             /* 'toUTCString' */
1622 #define DUK_HEAP_STRING_TO_UTC_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_UTC_STRING)
1623 #define DUK_HTHREAD_STRING_TO_UTC_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_UTC_STRING)
1624 #define DUK_STRIDX_TO_ISO_STRING                                      42                             /* 'toISOString' */
1625 #define DUK_HEAP_STRING_TO_ISO_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_ISO_STRING)
1626 #define DUK_HTHREAD_STRING_TO_ISO_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_ISO_STRING)
1627 #define DUK_STRIDX_TO_GMT_STRING                                      43                             /* 'toGMTString' */
1628 #define DUK_HEAP_STRING_TO_GMT_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_GMT_STRING)
1629 #define DUK_HTHREAD_STRING_TO_GMT_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_GMT_STRING)
1630 #define DUK_STRIDX_SOURCE                                             44                             /* 'source' */
1631 #define DUK_HEAP_STRING_SOURCE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SOURCE)
1632 #define DUK_HTHREAD_STRING_SOURCE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SOURCE)
1633 #define DUK_STRIDX_IGNORE_CASE                                        45                             /* 'ignoreCase' */
1634 #define DUK_HEAP_STRING_IGNORE_CASE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IGNORE_CASE)
1635 #define DUK_HTHREAD_STRING_IGNORE_CASE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IGNORE_CASE)
1636 #define DUK_STRIDX_MULTILINE                                          46                             /* 'multiline' */
1637 #define DUK_HEAP_STRING_MULTILINE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MULTILINE)
1638 #define DUK_HTHREAD_STRING_MULTILINE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MULTILINE)
1639 #define DUK_STRIDX_LAST_INDEX                                         47                             /* 'lastIndex' */
1640 #define DUK_HEAP_STRING_LAST_INDEX(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LAST_INDEX)
1641 #define DUK_HTHREAD_STRING_LAST_INDEX(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LAST_INDEX)
1642 #define DUK_STRIDX_FLAGS                                              48                             /* 'flags' */
1643 #define DUK_HEAP_STRING_FLAGS(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLAGS)
1644 #define DUK_HTHREAD_STRING_FLAGS(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLAGS)
1645 #define DUK_STRIDX_INDEX                                              49                             /* 'index' */
1646 #define DUK_HEAP_STRING_INDEX(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INDEX)
1647 #define DUK_HTHREAD_STRING_INDEX(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INDEX)
1648 #define DUK_STRIDX_PROTOTYPE                                          50                             /* 'prototype' */
1649 #define DUK_HEAP_STRING_PROTOTYPE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTOTYPE)
1650 #define DUK_HTHREAD_STRING_PROTOTYPE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTOTYPE)
1651 #define DUK_STRIDX_CONSTRUCTOR                                        51                             /* 'constructor' */
1652 #define DUK_HEAP_STRING_CONSTRUCTOR(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCTOR)
1653 #define DUK_HTHREAD_STRING_CONSTRUCTOR(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCTOR)
1654 #define DUK_STRIDX_MESSAGE                                            52                             /* 'message' */
1655 #define DUK_HEAP_STRING_MESSAGE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MESSAGE)
1656 #define DUK_HTHREAD_STRING_MESSAGE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MESSAGE)
1657 #define DUK_STRIDX_LC_BOOLEAN                                         53                             /* 'boolean' */
1658 #define DUK_HEAP_STRING_LC_BOOLEAN(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BOOLEAN)
1659 #define DUK_HTHREAD_STRING_LC_BOOLEAN(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BOOLEAN)
1660 #define DUK_STRIDX_LC_NUMBER                                          54                             /* 'number' */
1661 #define DUK_HEAP_STRING_LC_NUMBER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NUMBER)
1662 #define DUK_HTHREAD_STRING_LC_NUMBER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NUMBER)
1663 #define DUK_STRIDX_LC_STRING                                          55                             /* 'string' */
1664 #define DUK_HEAP_STRING_LC_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_STRING)
1665 #define DUK_HTHREAD_STRING_LC_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_STRING)
1666 #define DUK_STRIDX_LC_SYMBOL                                          56                             /* 'symbol' */
1667 #define DUK_HEAP_STRING_LC_SYMBOL(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_SYMBOL)
1668 #define DUK_HTHREAD_STRING_LC_SYMBOL(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_SYMBOL)
1669 #define DUK_STRIDX_LC_OBJECT                                          57                             /* 'object' */
1670 #define DUK_HEAP_STRING_LC_OBJECT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_OBJECT)
1671 #define DUK_HTHREAD_STRING_LC_OBJECT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_OBJECT)
1672 #define DUK_STRIDX_LC_UNDEFINED                                       58                             /* 'undefined' */
1673 #define DUK_HEAP_STRING_LC_UNDEFINED(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_UNDEFINED)
1674 #define DUK_HTHREAD_STRING_LC_UNDEFINED(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_UNDEFINED)
1675 #define DUK_STRIDX_NAN                                                59                             /* 'NaN' */
1676 #define DUK_HEAP_STRING_NAN(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAN)
1677 #define DUK_HTHREAD_STRING_NAN(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAN)
1678 #define DUK_STRIDX_INFINITY                                           60                             /* 'Infinity' */
1679 #define DUK_HEAP_STRING_INFINITY(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INFINITY)
1680 #define DUK_HTHREAD_STRING_INFINITY(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INFINITY)
1681 #define DUK_STRIDX_MINUS_INFINITY                                     61                             /* '-Infinity' */
1682 #define DUK_HEAP_STRING_MINUS_INFINITY(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_INFINITY)
1683 #define DUK_HTHREAD_STRING_MINUS_INFINITY(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_INFINITY)
1684 #define DUK_STRIDX_MINUS_ZERO                                         62                             /* '-0' */
1685 #define DUK_HEAP_STRING_MINUS_ZERO(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_ZERO)
1686 #define DUK_HTHREAD_STRING_MINUS_ZERO(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_ZERO)
1687 #define DUK_STRIDX_COMMA                                              63                             /* ',' */
1688 #define DUK_HEAP_STRING_COMMA(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMMA)
1689 #define DUK_HTHREAD_STRING_COMMA(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMMA)
1690 #define DUK_STRIDX_NEWLINE_4SPACE                                     64                             /* '\n    ' */
1691 #define DUK_HEAP_STRING_NEWLINE_4SPACE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEWLINE_4SPACE)
1692 #define DUK_HTHREAD_STRING_NEWLINE_4SPACE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEWLINE_4SPACE)
1693 #define DUK_STRIDX_BRACKETED_ELLIPSIS                                 65                             /* '[...]' */
1694 #define DUK_HEAP_STRING_BRACKETED_ELLIPSIS(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BRACKETED_ELLIPSIS)
1695 #define DUK_HTHREAD_STRING_BRACKETED_ELLIPSIS(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BRACKETED_ELLIPSIS)
1696 #define DUK_STRIDX_INVALID_DATE                                       66                             /* 'Invalid Date' */
1697 #define DUK_HEAP_STRING_INVALID_DATE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INVALID_DATE)
1698 #define DUK_HTHREAD_STRING_INVALID_DATE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INVALID_DATE)
1699 #define DUK_STRIDX_LC_ARGUMENTS                                       67                             /* 'arguments' */
1700 #define DUK_HEAP_STRING_LC_ARGUMENTS(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_ARGUMENTS)
1701 #define DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_ARGUMENTS)
1702 #define DUK_STRIDX_CALLEE                                             68                             /* 'callee' */
1703 #define DUK_HEAP_STRING_CALLEE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLEE)
1704 #define DUK_HTHREAD_STRING_CALLEE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLEE)
1705 #define DUK_STRIDX_CALLER                                             69                             /* 'caller' */
1706 #define DUK_HEAP_STRING_CALLER(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLER)
1707 #define DUK_HTHREAD_STRING_CALLER(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLER)
1708 #define DUK_STRIDX_APPLY                                              70                             /* 'apply' */
1709 #define DUK_HEAP_STRING_APPLY(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_APPLY)
1710 #define DUK_HTHREAD_STRING_APPLY(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_APPLY)
1711 #define DUK_STRIDX_CONSTRUCT                                          71                             /* 'construct' */
1712 #define DUK_HEAP_STRING_CONSTRUCT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCT)
1713 #define DUK_HTHREAD_STRING_CONSTRUCT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCT)
1714 #define DUK_STRIDX_DELETE_PROPERTY                                    72                             /* 'deleteProperty' */
1715 #define DUK_HEAP_STRING_DELETE_PROPERTY(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE_PROPERTY)
1716 #define DUK_HTHREAD_STRING_DELETE_PROPERTY(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE_PROPERTY)
1717 #define DUK_STRIDX_GET                                                73                             /* 'get' */
1718 #define DUK_HEAP_STRING_GET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET)
1719 #define DUK_HTHREAD_STRING_GET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET)
1720 #define DUK_STRIDX_HAS                                                74                             /* 'has' */
1721 #define DUK_HEAP_STRING_HAS(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HAS)
1722 #define DUK_HTHREAD_STRING_HAS(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HAS)
1723 #define DUK_STRIDX_OWN_KEYS                                           75                             /* 'ownKeys' */
1724 #define DUK_HEAP_STRING_OWN_KEYS(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OWN_KEYS)
1725 #define DUK_HTHREAD_STRING_OWN_KEYS(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OWN_KEYS)
1726 #define DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE                      76                             /* '\x81Symbol.toPrimitive\xff' */
1727 #define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_TO_PRIMITIVE(heap)           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)
1728 #define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_TO_PRIMITIVE(thr)         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)
1729 #define DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE                      77                             /* '\x81Symbol.hasInstance\xff' */
1730 #define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_HAS_INSTANCE(heap)           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)
1731 #define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_HAS_INSTANCE(thr)         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)
1732 #define DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG                     78                             /* '\x81Symbol.toStringTag\xff' */
1733 #define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_TO_STRING_TAG(heap)          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG)
1734 #define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_TO_STRING_TAG(thr)        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG)
1735 #define DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE              79                             /* '\x81Symbol.isConcatSpreadable\xff' */
1736 #define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE(heap)   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE)
1737 #define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE(thr)  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE)
1738 #define DUK_STRIDX_SET_PROTOTYPE_OF                                   80                             /* 'setPrototypeOf' */
1739 #define DUK_HEAP_STRING_SET_PROTOTYPE_OF(heap)                        DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_PROTOTYPE_OF)
1740 #define DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr)                      DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_PROTOTYPE_OF)
1741 #define DUK_STRIDX___PROTO__                                          81                             /* '__proto__' */
1742 #define DUK_HEAP_STRING___PROTO__(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX___PROTO__)
1743 #define DUK_HTHREAD_STRING___PROTO__(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX___PROTO__)
1744 #define DUK_STRIDX_TO_STRING                                          82                             /* 'toString' */
1745 #define DUK_HEAP_STRING_TO_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_STRING)
1746 #define DUK_HTHREAD_STRING_TO_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_STRING)
1747 #define DUK_STRIDX_TO_JSON                                            83                             /* 'toJSON' */
1748 #define DUK_HEAP_STRING_TO_JSON(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_JSON)
1749 #define DUK_HTHREAD_STRING_TO_JSON(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_JSON)
1750 #define DUK_STRIDX_TYPE                                               84                             /* 'type' */
1751 #define DUK_HEAP_STRING_TYPE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPE)
1752 #define DUK_HTHREAD_STRING_TYPE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPE)
1753 #define DUK_STRIDX_DATA                                               85                             /* 'data' */
1754 #define DUK_HEAP_STRING_DATA(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA)
1755 #define DUK_HTHREAD_STRING_DATA(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA)
1756 #define DUK_STRIDX_LENGTH                                             86                             /* 'length' */
1757 #define DUK_HEAP_STRING_LENGTH(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LENGTH)
1758 #define DUK_HTHREAD_STRING_LENGTH(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LENGTH)
1759 #define DUK_STRIDX_SET                                                87                             /* 'set' */
1760 #define DUK_HEAP_STRING_SET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET)
1761 #define DUK_HTHREAD_STRING_SET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET)
1762 #define DUK_STRIDX_STACK                                              88                             /* 'stack' */
1763 #define DUK_HEAP_STRING_STACK(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STACK)
1764 #define DUK_HTHREAD_STRING_STACK(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STACK)
1765 #define DUK_STRIDX_PC                                                 89                             /* 'pc' */
1766 #define DUK_HEAP_STRING_PC(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PC)
1767 #define DUK_HTHREAD_STRING_PC(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PC)
1768 #define DUK_STRIDX_LINE_NUMBER                                        90                             /* 'lineNumber' */
1769 #define DUK_HEAP_STRING_LINE_NUMBER(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER)
1770 #define DUK_HTHREAD_STRING_LINE_NUMBER(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LINE_NUMBER)
1771 #define DUK_STRIDX_INT_TRACEDATA                                      91                             /* '\x82Tracedata' */
1772 #define DUK_HEAP_STRING_INT_TRACEDATA(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA)
1773 #define DUK_HTHREAD_STRING_INT_TRACEDATA(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA)
1774 #define DUK_STRIDX_NAME                                               92                             /* 'name' */
1775 #define DUK_HEAP_STRING_NAME(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAME)
1776 #define DUK_HTHREAD_STRING_NAME(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAME)
1777 #define DUK_STRIDX_FILE_NAME                                          93                             /* 'fileName' */
1778 #define DUK_HEAP_STRING_FILE_NAME(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILE_NAME)
1779 #define DUK_HTHREAD_STRING_FILE_NAME(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILE_NAME)
1780 #define DUK_STRIDX_LC_POINTER                                         94                             /* 'pointer' */
1781 #define DUK_HEAP_STRING_LC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER)
1782 #define DUK_HTHREAD_STRING_LC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER)
1783 #define DUK_STRIDX_INT_TARGET                                         95                             /* '\x82Target' */
1784 #define DUK_HEAP_STRING_INT_TARGET(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TARGET)
1785 #define DUK_HTHREAD_STRING_INT_TARGET(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TARGET)
1786 #define DUK_STRIDX_INT_NEXT                                           96                             /* '\x82Next' */
1787 #define DUK_HEAP_STRING_INT_NEXT(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_NEXT)
1788 #define DUK_HTHREAD_STRING_INT_NEXT(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_NEXT)
1789 #define DUK_STRIDX_INT_BYTECODE                                       97                             /* '\x82Bytecode' */
1790 #define DUK_HEAP_STRING_INT_BYTECODE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_BYTECODE)
1791 #define DUK_HTHREAD_STRING_INT_BYTECODE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_BYTECODE)
1792 #define DUK_STRIDX_INT_FORMALS                                        98                             /* '\x82Formals' */
1793 #define DUK_HEAP_STRING_INT_FORMALS(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FORMALS)
1794 #define DUK_HTHREAD_STRING_INT_FORMALS(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FORMALS)
1795 #define DUK_STRIDX_INT_VARMAP                                         99                             /* '\x82Varmap' */
1796 #define DUK_HEAP_STRING_INT_VARMAP(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARMAP)
1797 #define DUK_HTHREAD_STRING_INT_VARMAP(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARMAP)
1798 #define DUK_STRIDX_INT_SOURCE                                         100                            /* '\x82Source' */
1799 #define DUK_HEAP_STRING_INT_SOURCE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_SOURCE)
1800 #define DUK_HTHREAD_STRING_INT_SOURCE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_SOURCE)
1801 #define DUK_STRIDX_INT_PC2LINE                                        101                            /* '\x82Pc2line' */
1802 #define DUK_HEAP_STRING_INT_PC2LINE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_PC2LINE)
1803 #define DUK_HTHREAD_STRING_INT_PC2LINE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_PC2LINE)
1804 #define DUK_STRIDX_INT_MAP                                            102                            /* '\x82Map' */
1805 #define DUK_HEAP_STRING_INT_MAP(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_MAP)
1806 #define DUK_HTHREAD_STRING_INT_MAP(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_MAP)
1807 #define DUK_STRIDX_INT_VARENV                                         103                            /* '\x82Varenv' */
1808 #define DUK_HEAP_STRING_INT_VARENV(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARENV)
1809 #define DUK_HTHREAD_STRING_INT_VARENV(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARENV)
1810 #define DUK_STRIDX_INT_FINALIZER                                      104                            /* '\x82Finalizer' */
1811 #define DUK_HEAP_STRING_INT_FINALIZER(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FINALIZER)
1812 #define DUK_HTHREAD_STRING_INT_FINALIZER(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FINALIZER)
1813 #define DUK_STRIDX_INT_VALUE                                          105                            /* '\x82Value' */
1814 #define DUK_HEAP_STRING_INT_VALUE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VALUE)
1815 #define DUK_HTHREAD_STRING_INT_VALUE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE)
1816 #define DUK_STRIDX_COMPILE                                            106                            /* 'compile' */
1817 #define DUK_HEAP_STRING_COMPILE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPILE)
1818 #define DUK_HTHREAD_STRING_COMPILE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPILE)
1819 #define DUK_STRIDX_INPUT                                              107                            /* 'input' */
1820 #define DUK_HEAP_STRING_INPUT(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INPUT)
1821 #define DUK_HTHREAD_STRING_INPUT(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INPUT)
1822 #define DUK_STRIDX_ERR_CREATE                                         108                            /* 'errCreate' */
1823 #define DUK_HEAP_STRING_ERR_CREATE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_CREATE)
1824 #define DUK_HTHREAD_STRING_ERR_CREATE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_CREATE)
1825 #define DUK_STRIDX_ERR_THROW                                          109                            /* 'errThrow' */
1826 #define DUK_HEAP_STRING_ERR_THROW(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_THROW)
1827 #define DUK_HTHREAD_STRING_ERR_THROW(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_THROW)
1828 #define DUK_STRIDX_ENV                                                110                            /* 'env' */
1829 #define DUK_HEAP_STRING_ENV(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENV)
1830 #define DUK_HTHREAD_STRING_ENV(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENV)
1831 #define DUK_STRIDX_HEX                                                111                            /* 'hex' */
1832 #define DUK_HEAP_STRING_HEX(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HEX)
1833 #define DUK_HTHREAD_STRING_HEX(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HEX)
1834 #define DUK_STRIDX_BASE64                                             112                            /* 'base64' */
1835 #define DUK_HEAP_STRING_BASE64(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BASE64)
1836 #define DUK_HTHREAD_STRING_BASE64(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BASE64)
1837 #define DUK_STRIDX_JX                                                 113                            /* 'jx' */
1838 #define DUK_HEAP_STRING_JX(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JX)
1839 #define DUK_HTHREAD_STRING_JX(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JX)
1840 #define DUK_STRIDX_JC                                                 114                            /* 'jc' */
1841 #define DUK_HEAP_STRING_JC(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JC)
1842 #define DUK_HTHREAD_STRING_JC(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JC)
1843 #define DUK_STRIDX_JSON_EXT_UNDEFINED                                 115                            /* '{"_undef":true}' */
1844 #define DUK_HEAP_STRING_JSON_EXT_UNDEFINED(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_UNDEFINED)
1845 #define DUK_HTHREAD_STRING_JSON_EXT_UNDEFINED(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_UNDEFINED)
1846 #define DUK_STRIDX_JSON_EXT_NAN                                       116                            /* '{"_nan":true}' */
1847 #define DUK_HEAP_STRING_JSON_EXT_NAN(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NAN)
1848 #define DUK_HTHREAD_STRING_JSON_EXT_NAN(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NAN)
1849 #define DUK_STRIDX_JSON_EXT_POSINF                                    117                            /* '{"_inf":true}' */
1850 #define DUK_HEAP_STRING_JSON_EXT_POSINF(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_POSINF)
1851 #define DUK_HTHREAD_STRING_JSON_EXT_POSINF(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_POSINF)
1852 #define DUK_STRIDX_JSON_EXT_NEGINF                                    118                            /* '{"_ninf":true}' */
1853 #define DUK_HEAP_STRING_JSON_EXT_NEGINF(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NEGINF)
1854 #define DUK_HTHREAD_STRING_JSON_EXT_NEGINF(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NEGINF)
1855 #define DUK_STRIDX_JSON_EXT_FUNCTION1                                 119                            /* '{"_func":true}' */
1856 #define DUK_HEAP_STRING_JSON_EXT_FUNCTION1(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION1)
1857 #define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION1(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION1)
1858 #define DUK_STRIDX_JSON_EXT_FUNCTION2                                 120                            /* '{_func:true}' */
1859 #define DUK_HEAP_STRING_JSON_EXT_FUNCTION2(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION2)
1860 #define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION2(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION2)
1861 #define DUK_STRIDX_BREAK                                              121                            /* 'break' */
1862 #define DUK_HEAP_STRING_BREAK(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BREAK)
1863 #define DUK_HTHREAD_STRING_BREAK(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BREAK)
1864 #define DUK_STRIDX_CASE                                               122                            /* 'case' */
1865 #define DUK_HEAP_STRING_CASE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CASE)
1866 #define DUK_HTHREAD_STRING_CASE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CASE)
1867 #define DUK_STRIDX_CATCH                                              123                            /* 'catch' */
1868 #define DUK_HEAP_STRING_CATCH(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CATCH)
1869 #define DUK_HTHREAD_STRING_CATCH(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CATCH)
1870 #define DUK_STRIDX_CONTINUE                                           124                            /* 'continue' */
1871 #define DUK_HEAP_STRING_CONTINUE(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONTINUE)
1872 #define DUK_HTHREAD_STRING_CONTINUE(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONTINUE)
1873 #define DUK_STRIDX_DEBUGGER                                           125                            /* 'debugger' */
1874 #define DUK_HEAP_STRING_DEBUGGER(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEBUGGER)
1875 #define DUK_HTHREAD_STRING_DEBUGGER(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEBUGGER)
1876 #define DUK_STRIDX_DEFAULT                                            126                            /* 'default' */
1877 #define DUK_HEAP_STRING_DEFAULT(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEFAULT)
1878 #define DUK_HTHREAD_STRING_DEFAULT(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEFAULT)
1879 #define DUK_STRIDX_DELETE                                             127                            /* 'delete' */
1880 #define DUK_HEAP_STRING_DELETE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE)
1881 #define DUK_HTHREAD_STRING_DELETE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE)
1882 #define DUK_STRIDX_DO                                                 128                            /* 'do' */
1883 #define DUK_HEAP_STRING_DO(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DO)
1884 #define DUK_HTHREAD_STRING_DO(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DO)
1885 #define DUK_STRIDX_ELSE                                               129                            /* 'else' */
1886 #define DUK_HEAP_STRING_ELSE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ELSE)
1887 #define DUK_HTHREAD_STRING_ELSE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ELSE)
1888 #define DUK_STRIDX_FINALLY                                            130                            /* 'finally' */
1889 #define DUK_HEAP_STRING_FINALLY(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FINALLY)
1890 #define DUK_HTHREAD_STRING_FINALLY(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FINALLY)
1891 #define DUK_STRIDX_FOR                                                131                            /* 'for' */
1892 #define DUK_HEAP_STRING_FOR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FOR)
1893 #define DUK_HTHREAD_STRING_FOR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FOR)
1894 #define DUK_STRIDX_LC_FUNCTION                                        132                            /* 'function' */
1895 #define DUK_HEAP_STRING_LC_FUNCTION(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_FUNCTION)
1896 #define DUK_HTHREAD_STRING_LC_FUNCTION(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_FUNCTION)
1897 #define DUK_STRIDX_IF                                                 133                            /* 'if' */
1898 #define DUK_HEAP_STRING_IF(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IF)
1899 #define DUK_HTHREAD_STRING_IF(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IF)
1900 #define DUK_STRIDX_IN                                                 134                            /* 'in' */
1901 #define DUK_HEAP_STRING_IN(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IN)
1902 #define DUK_HTHREAD_STRING_IN(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IN)
1903 #define DUK_STRIDX_INSTANCEOF                                         135                            /* 'instanceof' */
1904 #define DUK_HEAP_STRING_INSTANCEOF(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INSTANCEOF)
1905 #define DUK_HTHREAD_STRING_INSTANCEOF(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INSTANCEOF)
1906 #define DUK_STRIDX_NEW                                                136                            /* 'new' */
1907 #define DUK_HEAP_STRING_NEW(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEW)
1908 #define DUK_HTHREAD_STRING_NEW(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEW)
1909 #define DUK_STRIDX_RETURN                                             137                            /* 'return' */
1910 #define DUK_HEAP_STRING_RETURN(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RETURN)
1911 #define DUK_HTHREAD_STRING_RETURN(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RETURN)
1912 #define DUK_STRIDX_SWITCH                                             138                            /* 'switch' */
1913 #define DUK_HEAP_STRING_SWITCH(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SWITCH)
1914 #define DUK_HTHREAD_STRING_SWITCH(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SWITCH)
1915 #define DUK_STRIDX_THIS                                               139                            /* 'this' */
1916 #define DUK_HEAP_STRING_THIS(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THIS)
1917 #define DUK_HTHREAD_STRING_THIS(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THIS)
1918 #define DUK_STRIDX_THROW                                              140                            /* 'throw' */
1919 #define DUK_HEAP_STRING_THROW(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THROW)
1920 #define DUK_HTHREAD_STRING_THROW(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW)
1921 #define DUK_STRIDX_TRY                                                141                            /* 'try' */
1922 #define DUK_HEAP_STRING_TRY(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRY)
1923 #define DUK_HTHREAD_STRING_TRY(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRY)
1924 #define DUK_STRIDX_TYPEOF                                             142                            /* 'typeof' */
1925 #define DUK_HEAP_STRING_TYPEOF(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPEOF)
1926 #define DUK_HTHREAD_STRING_TYPEOF(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF)
1927 #define DUK_STRIDX_VAR                                                143                            /* 'var' */
1928 #define DUK_HEAP_STRING_VAR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VAR)
1929 #define DUK_HTHREAD_STRING_VAR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VAR)
1930 #define DUK_STRIDX_CONST                                              144                            /* 'const' */
1931 #define DUK_HEAP_STRING_CONST(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST)
1932 #define DUK_HTHREAD_STRING_CONST(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST)
1933 #define DUK_STRIDX_VOID                                               145                            /* 'void' */
1934 #define DUK_HEAP_STRING_VOID(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VOID)
1935 #define DUK_HTHREAD_STRING_VOID(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VOID)
1936 #define DUK_STRIDX_WHILE                                              146                            /* 'while' */
1937 #define DUK_HEAP_STRING_WHILE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE)
1938 #define DUK_HTHREAD_STRING_WHILE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WHILE)
1939 #define DUK_STRIDX_WITH                                               147                            /* 'with' */
1940 #define DUK_HEAP_STRING_WITH(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WITH)
1941 #define DUK_HTHREAD_STRING_WITH(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH)
1942 #define DUK_STRIDX_CLASS                                              148                            /* 'class' */
1943 #define DUK_HEAP_STRING_CLASS(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLASS)
1944 #define DUK_HTHREAD_STRING_CLASS(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLASS)
1945 #define DUK_STRIDX_ENUM                                               149                            /* 'enum' */
1946 #define DUK_HEAP_STRING_ENUM(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUM)
1947 #define DUK_HTHREAD_STRING_ENUM(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUM)
1948 #define DUK_STRIDX_EXPORT                                             150                            /* 'export' */
1949 #define DUK_HEAP_STRING_EXPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT)
1950 #define DUK_HTHREAD_STRING_EXPORT(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORT)
1951 #define DUK_STRIDX_EXTENDS                                            151                            /* 'extends' */
1952 #define DUK_HEAP_STRING_EXTENDS(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXTENDS)
1953 #define DUK_HTHREAD_STRING_EXTENDS(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXTENDS)
1954 #define DUK_STRIDX_IMPORT                                             152                            /* 'import' */
1955 #define DUK_HEAP_STRING_IMPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPORT)
1956 #define DUK_HTHREAD_STRING_IMPORT(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPORT)
1957 #define DUK_STRIDX_SUPER                                              153                            /* 'super' */
1958 #define DUK_HEAP_STRING_SUPER(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUPER)
1959 #define DUK_HTHREAD_STRING_SUPER(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUPER)
1960 #define DUK_STRIDX_LC_NULL                                            154                            /* 'null' */
1961 #define DUK_HEAP_STRING_LC_NULL(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NULL)
1962 #define DUK_HTHREAD_STRING_LC_NULL(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NULL)
1963 #define DUK_STRIDX_TRUE                                               155                            /* 'true' */
1964 #define DUK_HEAP_STRING_TRUE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRUE)
1965 #define DUK_HTHREAD_STRING_TRUE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRUE)
1966 #define DUK_STRIDX_FALSE                                              156                            /* 'false' */
1967 #define DUK_HEAP_STRING_FALSE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FALSE)
1968 #define DUK_HTHREAD_STRING_FALSE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FALSE)
1969 #define DUK_STRIDX_IMPLEMENTS                                         157                            /* 'implements' */
1970 #define DUK_HEAP_STRING_IMPLEMENTS(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPLEMENTS)
1971 #define DUK_HTHREAD_STRING_IMPLEMENTS(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPLEMENTS)
1972 #define DUK_STRIDX_INTERFACE                                          158                            /* 'interface' */
1973 #define DUK_HEAP_STRING_INTERFACE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INTERFACE)
1974 #define DUK_HTHREAD_STRING_INTERFACE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INTERFACE)
1975 #define DUK_STRIDX_LET                                                159                            /* 'let' */
1976 #define DUK_HEAP_STRING_LET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LET)
1977 #define DUK_HTHREAD_STRING_LET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LET)
1978 #define DUK_STRIDX_PACKAGE                                            160                            /* 'package' */
1979 #define DUK_HEAP_STRING_PACKAGE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PACKAGE)
1980 #define DUK_HTHREAD_STRING_PACKAGE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PACKAGE)
1981 #define DUK_STRIDX_PRIVATE                                            161                            /* 'private' */
1982 #define DUK_HEAP_STRING_PRIVATE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PRIVATE)
1983 #define DUK_HTHREAD_STRING_PRIVATE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PRIVATE)
1984 #define DUK_STRIDX_PROTECTED                                          162                            /* 'protected' */
1985 #define DUK_HEAP_STRING_PROTECTED(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTECTED)
1986 #define DUK_HTHREAD_STRING_PROTECTED(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTECTED)
1987 #define DUK_STRIDX_PUBLIC                                             163                            /* 'public' */
1988 #define DUK_HEAP_STRING_PUBLIC(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PUBLIC)
1989 #define DUK_HTHREAD_STRING_PUBLIC(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PUBLIC)
1990 #define DUK_STRIDX_STATIC                                             164                            /* 'static' */
1991 #define DUK_HEAP_STRING_STATIC(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STATIC)
1992 #define DUK_HTHREAD_STRING_STATIC(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STATIC)
1993 #define DUK_STRIDX_YIELD                                              165                            /* 'yield' */
1994 #define DUK_HEAP_STRING_YIELD(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD)
1995 #define DUK_HTHREAD_STRING_YIELD(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD)
1996 
1997 #define DUK_HEAP_NUM_STRINGS                                          166
1998 #define DUK_STRIDX_START_RESERVED                                     121
1999 #define DUK_STRIDX_START_STRICT_RESERVED                              157
2000 #define DUK_STRIDX_END_RESERVED                                       166                            /* exclusive endpoint */
2001 
2002 /* To convert a heap stridx to a token number, subtract
2003  * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
2004  */
2005 #if !defined(DUK_SINGLE_FILE)
2006 DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[967];
2007 #endif  /* !DUK_SINGLE_FILE */
2008 #define DUK_STRDATA_MAX_STRLEN                                        27
2009 #define DUK_STRDATA_DATA_LENGTH                                       967
2010 #endif  /* DUK_USE_ROM_STRINGS */
2011 
2012 #if defined(DUK_USE_ROM_OBJECTS)
2013 #error RAM support not enabled, rerun configure.py with --ram-support
2014 #else  /* DUK_USE_ROM_OBJECTS */
2015 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor(duk_context *ctx);
2016 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_constructor(duk_context *ctx);
2017 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_context *ctx);
2018 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor(duk_context *ctx);
2019 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor(duk_context *ctx);
2020 DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx);
2021 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_constructor(duk_context *ctx);
2022 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor(duk_context *ctx);
2023 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx);
2024 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx);
2025 DUK_INTERNAL_DECL duk_ret_t duk_bi_type_error_thrower(duk_context *ctx);
2026 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx);
2027 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx);
2028 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_constructor(duk_context *ctx);
2029 DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_constructor(duk_context *ctx);
2030 DUK_INTERNAL_DECL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx);
2031 DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx);
2032 DUK_INTERNAL_DECL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx);
2033 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx);
2034 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx);
2035 DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_constructor(duk_context *ctx);
2036 DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_constructor(duk_context *ctx);
2037 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_eval(duk_context *ctx);
2038 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx);
2039 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx);
2040 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx);
2041 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx);
2042 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx);
2043 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx);
2044 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_escape(duk_context *ctx);
2045 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx);
2046 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx);
2047 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx);
2048 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_context *ctx);
2049 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx);
2050 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_assign(duk_context *ctx);
2051 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_create(duk_context *ctx);
2052 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_property(duk_context *ctx);
2053 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx);
2054 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx);
2055 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx);
2056 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_context *ctx);
2057 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx);
2058 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is(duk_context *ctx);
2059 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx);
2060 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_context *ctx);
2061 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx);
2062 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_has_own_property(duk_context *ctx);
2063 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_context *ctx);
2064 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx);
2065 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_defineaccessor(duk_context *ctx);
2066 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_lookupaccessor(duk_context *ctx);
2067 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx);
2068 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx);
2069 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx);
2070 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx);
2071 DUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_length(duk_context *ctx);
2072 DUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_name(duk_context *ctx);
2073 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx);
2074 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx);
2075 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx);
2076 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx);
2077 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx);
2078 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_push(duk_context *ctx);
2079 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reverse(duk_context *ctx);
2080 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx);
2081 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx);
2082 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx);
2083 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx);
2084 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx);
2085 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx);
2086 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx);
2087 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx);
2088 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx);
2089 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_code_point(duk_context *ctx);
2090 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_to_string(duk_context *ctx);
2091 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_at(duk_context *ctx);
2092 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_code_at(duk_context *ctx);
2093 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_concat(duk_context *ctx);
2094 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_context *ctx);
2095 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_locale_compare(duk_context *ctx);
2096 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_match(duk_context *ctx);
2097 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx);
2098 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx);
2099 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_slice(duk_context *ctx);
2100 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_split(duk_context *ctx);
2101 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substring(duk_context *ctx);
2102 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_context *ctx);
2103 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_trim(duk_context *ctx);
2104 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_repeat(duk_context *ctx);
2105 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_context *ctx);
2106 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_includes(duk_context *ctx);
2107 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx);
2108 DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx);
2109 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_check_shared(duk_context *ctx);
2110 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx);
2111 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx);
2112 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx);
2113 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_fixed(duk_context *ctx);
2114 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx);
2115 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_precision(duk_context *ctx);
2116 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx);
2117 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx);
2118 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_now(duk_context *ctx);
2119 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_context *ctx);
2120 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx);
2121 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx);
2122 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx);
2123 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx);
2124 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx);
2125 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx);
2126 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx);
2127 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx);
2128 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_tostring(duk_context *ctx);
2129 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_flags(duk_context *ctx);
2130 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_context *ctx);
2131 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx);
2132 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_setter(duk_context *ctx);
2133 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx);
2134 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_setter(duk_context *ctx);
2135 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx);
2136 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_context *ctx);
2137 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx);
2138 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx);
2139 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx);
2140 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_clz32(duk_context *ctx);
2141 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_hypot(duk_context *ctx);
2142 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_imul(duk_context *ctx);
2143 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_max(duk_context *ctx);
2144 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_min(duk_context *ctx);
2145 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_random(duk_context *ctx);
2146 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_sign(duk_context *ctx);
2147 DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_parse(duk_context *ctx);
2148 DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_stringify(duk_context *ctx);
2149 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx);
2150 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_act(duk_context *ctx);
2151 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx);
2152 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx);
2153 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx);
2154 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx);
2155 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx);
2156 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_yield(duk_context *ctx);
2157 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_resume(duk_context *ctx);
2158 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_current(duk_context *ctx);
2159 DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_context *ctx);
2160 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_apply(duk_context *ctx);
2161 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_construct(duk_context *ctx);
2162 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_delete_property(duk_context *ctx);
2163 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_get(duk_context *ctx);
2164 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_has(duk_context *ctx);
2165 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_set(duk_context *ctx);
2166 DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx);
2167 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_context *ctx);
2168 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx);
2169 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_context *ctx);
2170 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_buffer_getter(duk_context *ctx);
2171 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx);
2172 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx);
2173 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_set(duk_context *ctx);
2174 DUK_INTERNAL_DECL duk_ret_t duk_bi_uint8array_allocplain(duk_context *ctx);
2175 DUK_INTERNAL_DECL duk_ret_t duk_bi_uint8array_plainof(duk_context *ctx);
2176 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx);
2177 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx);
2178 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx);
2179 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx);
2180 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx);
2181 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx);
2182 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx);
2183 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx);
2184 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx);
2185 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx);
2186 DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_context *ctx);
2187 DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encode(duk_context *ctx);
2188 DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_context *ctx);
2189 DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_context *ctx);
2190 DUK_INTERNAL_DECL duk_ret_t duk_bi_performance_now(duk_context *ctx);
2191 #if !defined(DUK_SINGLE_FILE)
2192 DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[177];
2193 #endif  /* !DUK_SINGLE_FILE */
2194 #define DUK_BIDX_GLOBAL                                               0
2195 #define DUK_BIDX_GLOBAL_ENV                                           1
2196 #define DUK_BIDX_OBJECT_CONSTRUCTOR                                   2
2197 #define DUK_BIDX_OBJECT_PROTOTYPE                                     3
2198 #define DUK_BIDX_FUNCTION_CONSTRUCTOR                                 4
2199 #define DUK_BIDX_FUNCTION_PROTOTYPE                                   5
2200 #define DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE                            6
2201 #define DUK_BIDX_ARRAY_CONSTRUCTOR                                    7
2202 #define DUK_BIDX_ARRAY_PROTOTYPE                                      8
2203 #define DUK_BIDX_STRING_CONSTRUCTOR                                   9
2204 #define DUK_BIDX_STRING_PROTOTYPE                                     10
2205 #define DUK_BIDX_BOOLEAN_CONSTRUCTOR                                  11
2206 #define DUK_BIDX_BOOLEAN_PROTOTYPE                                    12
2207 #define DUK_BIDX_NUMBER_CONSTRUCTOR                                   13
2208 #define DUK_BIDX_NUMBER_PROTOTYPE                                     14
2209 #define DUK_BIDX_DATE_CONSTRUCTOR                                     15
2210 #define DUK_BIDX_DATE_PROTOTYPE                                       16
2211 #define DUK_BIDX_REGEXP_CONSTRUCTOR                                   17
2212 #define DUK_BIDX_REGEXP_PROTOTYPE                                     18
2213 #define DUK_BIDX_ERROR_CONSTRUCTOR                                    19
2214 #define DUK_BIDX_ERROR_PROTOTYPE                                      20
2215 #define DUK_BIDX_EVAL_ERROR_CONSTRUCTOR                               21
2216 #define DUK_BIDX_EVAL_ERROR_PROTOTYPE                                 22
2217 #define DUK_BIDX_RANGE_ERROR_CONSTRUCTOR                              23
2218 #define DUK_BIDX_RANGE_ERROR_PROTOTYPE                                24
2219 #define DUK_BIDX_REFERENCE_ERROR_CONSTRUCTOR                          25
2220 #define DUK_BIDX_REFERENCE_ERROR_PROTOTYPE                            26
2221 #define DUK_BIDX_SYNTAX_ERROR_CONSTRUCTOR                             27
2222 #define DUK_BIDX_SYNTAX_ERROR_PROTOTYPE                               28
2223 #define DUK_BIDX_TYPE_ERROR_CONSTRUCTOR                               29
2224 #define DUK_BIDX_TYPE_ERROR_PROTOTYPE                                 30
2225 #define DUK_BIDX_URI_ERROR_CONSTRUCTOR                                31
2226 #define DUK_BIDX_URI_ERROR_PROTOTYPE                                  32
2227 #define DUK_BIDX_TYPE_ERROR_THROWER                                   33
2228 #define DUK_BIDX_DUKTAPE                                              34
2229 #define DUK_BIDX_THREAD_PROTOTYPE                                     35
2230 #define DUK_BIDX_POINTER_PROTOTYPE                                    36
2231 #define DUK_BIDX_DOUBLE_ERROR                                         37
2232 #define DUK_BIDX_SYMBOL_PROTOTYPE                                     38
2233 #define DUK_BIDX_ARRAYBUFFER_PROTOTYPE                                39
2234 #define DUK_BIDX_DATAVIEW_PROTOTYPE                                   40
2235 #define DUK_BIDX_INT8ARRAY_PROTOTYPE                                  41
2236 #define DUK_BIDX_UINT8ARRAY_PROTOTYPE                                 42
2237 #define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE                          43
2238 #define DUK_BIDX_INT16ARRAY_PROTOTYPE                                 44
2239 #define DUK_BIDX_UINT16ARRAY_PROTOTYPE                                45
2240 #define DUK_BIDX_INT32ARRAY_PROTOTYPE                                 46
2241 #define DUK_BIDX_UINT32ARRAY_PROTOTYPE                                47
2242 #define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE                               48
2243 #define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE                               49
2244 #define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE                              50
2245 #define DUK_NUM_BUILTINS                                              51
2246 #define DUK_NUM_BIDX_BUILTINS                                         51
2247 #define DUK_NUM_ALL_BUILTINS                                          78
2248 #if defined(DUK_USE_DOUBLE_LE)
2249 #if !defined(DUK_SINGLE_FILE)
2250 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4116];
2251 #endif  /* !DUK_SINGLE_FILE */
2252 #define DUK_BUILTINS_DATA_LENGTH                                      4116
2253 #elif defined(DUK_USE_DOUBLE_BE)
2254 #if !defined(DUK_SINGLE_FILE)
2255 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4116];
2256 #endif  /* !DUK_SINGLE_FILE */
2257 #define DUK_BUILTINS_DATA_LENGTH                                      4116
2258 #elif defined(DUK_USE_DOUBLE_ME)
2259 #if !defined(DUK_SINGLE_FILE)
2260 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4116];
2261 #endif  /* !DUK_SINGLE_FILE */
2262 #define DUK_BUILTINS_DATA_LENGTH                                      4116
2263 #else
2264 #error invalid endianness defines
2265 #endif
2266 #endif  /* DUK_USE_ROM_OBJECTS */
2267 #endif  /* DUK_BUILTINS_H_INCLUDED */
2268 #line 51 "duk_internal.h"
2269 
2270 /* #include duk_util.h */
2271 #line 1 "duk_util.h"
2272 /*
2273  *  Utilities
2274  */
2275 
2276 #if !defined(DUK_UTIL_H_INCLUDED)
2277 #define DUK_UTIL_H_INCLUDED
2278 
2279 #if defined(DUK_USE_GET_RANDOM_DOUBLE)
2280 #define DUK_UTIL_GET_RANDOM_DOUBLE(thr) DUK_USE_GET_RANDOM_DOUBLE((thr)->heap_udata)
2281 #else
2282 #define DUK_UTIL_GET_RANDOM_DOUBLE(thr) duk_util_tinyrandom_get_double(thr)
2283 #endif
2284 
2285 /*
2286  *  Some useful constants
2287  */
2288 
2289 #define DUK_DOUBLE_2TO32     4294967296.0
2290 #define DUK_DOUBLE_2TO31     2147483648.0
2291 #define DUK_DOUBLE_LOG2E     1.4426950408889634
2292 #define DUK_DOUBLE_LOG10E    0.4342944819032518
2293 
2294 /*
2295  *  Endian conversion
2296  */
2297 
2298 #if defined(DUK_USE_INTEGER_LE)
2299 #define DUK_HTON32(x) DUK_BSWAP32((x))
2300 #define DUK_NTOH32(x) DUK_BSWAP32((x))
2301 #define DUK_HTON16(x) DUK_BSWAP16((x))
2302 #define DUK_NTOH16(x) DUK_BSWAP16((x))
2303 #elif defined(DUK_USE_INTEGER_BE)
2304 #define DUK_HTON32(x) (x)
2305 #define DUK_NTOH32(x) (x)
2306 #define DUK_HTON16(x) (x)
2307 #define DUK_NTOH16(x) (x)
2308 #else
2309 #error internal error, endianness defines broken
2310 #endif
2311 
2312 /*
2313  *  Bitstream decoder
2314  */
2315 
2316 struct duk_bitdecoder_ctx {
2317 	const duk_uint8_t *data;
2318 	duk_size_t offset;
2319 	duk_size_t length;
2320 	duk_uint32_t currval;
2321 	duk_small_int_t currbits;
2322 };
2323 
2324 #define DUK_BD_BITPACKED_STRING_MAXLEN 256
2325 
2326 /*
2327  *  Bitstream encoder
2328  */
2329 
2330 struct duk_bitencoder_ctx {
2331 	duk_uint8_t *data;
2332 	duk_size_t offset;
2333 	duk_size_t length;
2334 	duk_uint32_t currval;
2335 	duk_small_int_t currbits;
2336 	duk_small_int_t truncated;
2337 };
2338 
2339 /*
2340  *  Raw write/read macros for big endian, unaligned basic values.
2341  *  Caller ensures there's enough space.  The macros update the pointer
2342  *  argument automatically on resizes.  The idiom seems a bit odd, but
2343  *  leads to compact code.
2344  */
2345 
2346 #define DUK_RAW_WRITE_U8(ptr,val)  do { \
2347 		*(ptr)++ = (duk_uint8_t) (val); \
2348 	} while (0)
2349 #define DUK_RAW_WRITE_U16_BE(ptr,val) duk_raw_write_u16_be(&(ptr), (duk_uint16_t) (val))
2350 #define DUK_RAW_WRITE_U32_BE(ptr,val) duk_raw_write_u32_be(&(ptr), (duk_uint32_t) (val))
2351 #define DUK_RAW_WRITE_DOUBLE_BE(ptr,val) duk_raw_write_double_be(&(ptr), (duk_double_t) (val))
2352 #define DUK_RAW_WRITE_XUTF8(ptr,val)  do { \
2353 		/* 'ptr' is evaluated both as LHS and RHS. */ \
2354 		duk_uint8_t *duk__ptr; \
2355 		duk_small_int_t duk__len; \
2356 		duk__ptr = (duk_uint8_t *) (ptr); \
2357 		duk__len = duk_unicode_encode_xutf8((duk_ucodepoint_t) (val), duk__ptr); \
2358 		duk__ptr += duk__len; \
2359 		(ptr) = duk__ptr; \
2360 	} while (0)
2361 #define DUK_RAW_WRITE_CESU8(ptr,val)  do { \
2362 		/* 'ptr' is evaluated both as LHS and RHS. */ \
2363 		duk_uint8_t *duk__ptr; \
2364 		duk_small_int_t duk__len; \
2365 		duk__ptr = (duk_uint8_t *) (ptr); \
2366 		duk__len = duk_unicode_encode_cesu8((duk_ucodepoint_t) (val), duk__ptr); \
2367 		duk__ptr += duk__len; \
2368 		(ptr) = duk__ptr; \
2369 	} while (0)
2370 
2371 #define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)++))
2372 #define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be(&(ptr));
2373 #define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be(&(ptr));
2374 #define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be(&(ptr));
2375 
2376 /*
2377  *  Buffer writer (dynamic buffer only)
2378  *
2379  *  Helper for writing to a dynamic buffer with a concept of a "slack" area
2380  *  to reduce resizes.  You can ensure there is enough space beforehand and
2381  *  then write for a while without further checks, relying on a stable data
2382  *  pointer.  Slack handling is automatic so call sites only indicate how
2383  *  much data they need right now.
2384  *
2385  *  There are several ways to write using bufwriter.  The best approach
2386  *  depends mainly on how much performance matters over code footprint.
2387  *  The key issues are (1) ensuring there is space and (2) keeping the
2388  *  pointers consistent.  Fast code should ensure space for multiple writes
2389  *  with one ensure call.  Fastest inner loop code can temporarily borrow
2390  *  the 'p' pointer but must write it back eventually.
2391  *
2392  *  Be careful to ensure all macro arguments (other than static pointers like
2393  *  'thr' and 'bw_ctx') are evaluated exactly once, using temporaries if
2394  *  necessary (if that's not possible, there should be a note near the macro).
2395  *  Buffer write arguments often contain arithmetic etc so this is
2396  *  particularly important here.
2397  */
2398 
2399 /* XXX: Migrate bufwriter and other read/write helpers to its own header? */
2400 
2401 struct duk_bufwriter_ctx {
2402 	duk_uint8_t *p;
2403 	duk_uint8_t *p_base;
2404 	duk_uint8_t *p_limit;
2405 	duk_hbuffer_dynamic *buf;
2406 };
2407 
2408 #if defined(DUK_USE_PREFER_SIZE)
2409 #define DUK_BW_SLACK_ADD           64
2410 #define DUK_BW_SLACK_SHIFT         4    /* 2^4 -> 1/16 = 6.25% slack */
2411 #else
2412 #define DUK_BW_SLACK_ADD           64
2413 #define DUK_BW_SLACK_SHIFT         2    /* 2^2 -> 1/4 = 25% slack */
2414 #endif
2415 
2416 /* Initialization and finalization (compaction), converting to other types. */
2417 
2418 #define DUK_BW_INIT_PUSHBUF(thr,bw_ctx,sz) do { \
2419 		duk_bw_init_pushbuf((thr), (bw_ctx), (sz)); \
2420 	} while (0)
2421 #define DUK_BW_INIT_WITHBUF(thr,bw_ctx,buf) do { \
2422 		duk_bw_init((thr), (bw_ctx), (buf)); \
2423 	} while (0)
2424 #define DUK_BW_COMPACT(thr,bw_ctx) do { \
2425 		/* Make underlying buffer compact to match DUK_BW_GET_SIZE(). */ \
2426 		duk_bw_compact((thr), (bw_ctx)); \
2427 	} while (0)
2428 #define DUK_BW_PUSH_AS_STRING(thr,bw_ctx) do { \
2429 		duk_push_lstring((thr), \
2430 		                 (const char *) (bw_ctx)->p_base, \
2431 		                 (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
2432 	} while (0)
2433 /* Pointers may be NULL for a while when 'buf' size is zero and before any
2434  * ENSURE calls have been made.  Once an ENSURE has been made, the pointers
2435  * are required to be non-NULL so that it's always valid to use memcpy() and
2436  * memmove(), even for zero size.
2437  */
2438 #define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx) \
2439 	DUK_ASSERT_EXPR((bw_ctx) != NULL && \
2440 	                (bw_ctx)->buf != NULL && \
2441 			((DUK_HBUFFER_DYNAMIC_GET_SIZE((bw_ctx)->buf) == 0) || \
2442 				((bw_ctx)->p != NULL && \
2443 		                 (bw_ctx)->p_base != NULL && \
2444 		                 (bw_ctx)->p_limit != NULL && \
2445 		                 (bw_ctx)->p_limit >= (bw_ctx)->p_base && \
2446 		                 (bw_ctx)->p >= (bw_ctx)->p_base && \
2447 		                 (bw_ctx)->p <= (bw_ctx)->p_limit)))
2448 #define DUK_BW_ASSERT_VALID(thr,bw_ctx) do { \
2449 		DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)); \
2450 	} while (0)
2451 
2452 /* Working with the pointer and current size. */
2453 
2454 #define DUK_BW_GET_PTR(thr,bw_ctx) \
2455 	((bw_ctx)->p)
2456 #define DUK_BW_SET_PTR(thr,bw_ctx,ptr) do { \
2457 		(bw_ctx)->p = (ptr); \
2458 	} while (0)
2459 #define DUK_BW_ADD_PTR(thr,bw_ctx,delta) do { \
2460 		(bw_ctx)->p += (delta); \
2461 	} while (0)
2462 #define DUK_BW_GET_BASEPTR(thr,bw_ctx) \
2463 	((bw_ctx)->p_base)
2464 #define DUK_BW_GET_LIMITPTR(thr,bw_ctx) \
2465 	((bw_ctx)->p_limit)
2466 #define DUK_BW_GET_SIZE(thr,bw_ctx) \
2467 	((duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base))
2468 #define DUK_BW_SET_SIZE(thr,bw_ctx,sz) do { \
2469 		DUK_ASSERT((duk_size_t) (sz) <= (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
2470 		(bw_ctx)->p = (bw_ctx)->p_base + (sz); \
2471 	} while (0)
2472 #define DUK_BW_RESET_SIZE(thr,bw_ctx) do { \
2473 		/* Reset to zero size, keep current limit. */ \
2474 		(bw_ctx)->p = (bw_ctx)->p_base; \
2475 	} while (0)
2476 #define DUK_BW_GET_BUFFER(thr,bw_ctx) \
2477 	((bw_ctx)->buf)
2478 
2479 /* Ensuring (reserving) space. */
2480 
2481 #define DUK_BW_ENSURE(thr,bw_ctx,sz) do { \
2482 		duk_size_t duk__sz, duk__space; \
2483 		DUK_BW_ASSERT_VALID((thr), (bw_ctx)); \
2484 		duk__sz = (sz); \
2485 		duk__space = (duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p); \
2486 		if (duk__space < duk__sz) { \
2487 			(void) duk_bw_resize((thr), (bw_ctx), duk__sz); \
2488 		} \
2489 	} while (0)
2490 /* NOTE: Multiple evaluation of 'ptr' in this macro. */
2491 /* XXX: Rework to use an always-inline function? */
2492 #define DUK_BW_ENSURE_RAW(thr,bw_ctx,sz,ptr) \
2493 	(((duk_size_t) ((bw_ctx)->p_limit - (ptr)) >= (sz)) ? \
2494 	 (ptr) : \
2495 	 ((bw_ctx)->p = (ptr), duk_bw_resize((thr),(bw_ctx),(sz))))
2496 #define DUK_BW_ENSURE_GETPTR(thr,bw_ctx,sz) \
2497 	DUK_BW_ENSURE_RAW((thr), (bw_ctx), (sz), (bw_ctx)->p)
2498 #define DUK_BW_ASSERT_SPACE_EXPR(thr,bw_ctx,sz) \
2499 	(DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)), \
2500 	 DUK_ASSERT_EXPR((duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p) >= (duk_size_t) (sz)))
2501 #define DUK_BW_ASSERT_SPACE(thr,bw_ctx,sz) do { \
2502 		DUK_BW_ASSERT_SPACE_EXPR((thr), (bw_ctx), (sz)); \
2503 	} while (0)
2504 
2505 /* Miscellaneous. */
2506 
2507 #define DUK_BW_SETPTR_AND_COMPACT(thr,bw_ctx,ptr) do { \
2508 		(bw_ctx)->p = (ptr); \
2509 		duk_bw_compact((thr), (bw_ctx)); \
2510 	} while (0)
2511 
2512 /* Fast write calls which assume you control the slack beforehand.
2513  * Multibyte write variants exist and use a temporary write pointer
2514  * because byte writes alias with anything: with a stored pointer
2515  * explicit pointer load/stores get generated (e.g. gcc -Os).
2516  */
2517 
2518 #define DUK_BW_WRITE_RAW_U8(thr,bw_ctx,val) do { \
2519 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 1); \
2520 		*(bw_ctx)->p++ = (duk_uint8_t) (val); \
2521 	} while (0)
2522 #define DUK_BW_WRITE_RAW_U8_2(thr,bw_ctx,val1,val2) do { \
2523 		duk_uint8_t *duk__p; \
2524 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 2); \
2525 		duk__p = (bw_ctx)->p; \
2526 		*duk__p++ = (duk_uint8_t) (val1); \
2527 		*duk__p++ = (duk_uint8_t) (val2); \
2528 		(bw_ctx)->p = duk__p; \
2529 	} while (0)
2530 #define DUK_BW_WRITE_RAW_U8_3(thr,bw_ctx,val1,val2,val3) do { \
2531 		duk_uint8_t *duk__p; \
2532 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 3); \
2533 		duk__p = (bw_ctx)->p; \
2534 		*duk__p++ = (duk_uint8_t) (val1); \
2535 		*duk__p++ = (duk_uint8_t) (val2); \
2536 		*duk__p++ = (duk_uint8_t) (val3); \
2537 		(bw_ctx)->p = duk__p; \
2538 	} while (0)
2539 #define DUK_BW_WRITE_RAW_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
2540 		duk_uint8_t *duk__p; \
2541 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 4); \
2542 		duk__p = (bw_ctx)->p; \
2543 		*duk__p++ = (duk_uint8_t) (val1); \
2544 		*duk__p++ = (duk_uint8_t) (val2); \
2545 		*duk__p++ = (duk_uint8_t) (val3); \
2546 		*duk__p++ = (duk_uint8_t) (val4); \
2547 		(bw_ctx)->p = duk__p; \
2548 	} while (0)
2549 #define DUK_BW_WRITE_RAW_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
2550 		duk_uint8_t *duk__p; \
2551 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 5); \
2552 		duk__p = (bw_ctx)->p; \
2553 		*duk__p++ = (duk_uint8_t) (val1); \
2554 		*duk__p++ = (duk_uint8_t) (val2); \
2555 		*duk__p++ = (duk_uint8_t) (val3); \
2556 		*duk__p++ = (duk_uint8_t) (val4); \
2557 		*duk__p++ = (duk_uint8_t) (val5); \
2558 		(bw_ctx)->p = duk__p; \
2559 	} while (0)
2560 #define DUK_BW_WRITE_RAW_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
2561 		duk_uint8_t *duk__p; \
2562 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 6); \
2563 		duk__p = (bw_ctx)->p; \
2564 		*duk__p++ = (duk_uint8_t) (val1); \
2565 		*duk__p++ = (duk_uint8_t) (val2); \
2566 		*duk__p++ = (duk_uint8_t) (val3); \
2567 		*duk__p++ = (duk_uint8_t) (val4); \
2568 		*duk__p++ = (duk_uint8_t) (val5); \
2569 		*duk__p++ = (duk_uint8_t) (val6); \
2570 		(bw_ctx)->p = duk__p; \
2571 	} while (0)
2572 #define DUK_BW_WRITE_RAW_XUTF8(thr,bw_ctx,cp) do { \
2573 		duk_ucodepoint_t duk__cp; \
2574 		duk_small_int_t duk__enc_len; \
2575 		duk__cp = (duk_ucodepoint_t) (cp); \
2576 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_xutf8_length(duk__cp)); \
2577 		duk__enc_len = duk_unicode_encode_xutf8(duk__cp, (bw_ctx)->p); \
2578 		(bw_ctx)->p += duk__enc_len; \
2579 	} while (0)
2580 #define DUK_BW_WRITE_RAW_CESU8(thr,bw_ctx,cp) do { \
2581 		duk_ucodepoint_t duk__cp; \
2582 		duk_small_int_t duk__enc_len; \
2583 		duk__cp = (duk_ucodepoint_t) (cp); \
2584 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_cesu8_length(duk__cp)); \
2585 		duk__enc_len = duk_unicode_encode_cesu8(duk__cp, (bw_ctx)->p); \
2586 		(bw_ctx)->p += duk__enc_len; \
2587 	} while (0)
2588 /* XXX: add temporary duk__p pointer here too; sharing */
2589 /* XXX: avoid unsafe variants */
2590 #define DUK_BW_WRITE_RAW_BYTES(thr,bw_ctx,valptr,valsz) do { \
2591 		const void *duk__valptr; \
2592 		duk_size_t duk__valsz; \
2593 		duk__valptr = (const void *) (valptr); \
2594 		duk__valsz = (duk_size_t) (valsz); \
2595 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
2596 		(bw_ctx)->p += duk__valsz; \
2597 	} while (0)
2598 #define DUK_BW_WRITE_RAW_CSTRING(thr,bw_ctx,val) do { \
2599 		const duk_uint8_t *duk__val; \
2600 		duk_size_t duk__val_len; \
2601 		duk__val = (const duk_uint8_t *) (val); \
2602 		duk__val_len = DUK_STRLEN((const char *) duk__val); \
2603 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
2604 		(bw_ctx)->p += duk__val_len; \
2605 	} while (0)
2606 #define DUK_BW_WRITE_RAW_HSTRING(thr,bw_ctx,val) do { \
2607 		duk_size_t duk__val_len; \
2608 		duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
2609 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
2610 		(bw_ctx)->p += duk__val_len; \
2611 	} while (0)
2612 #define DUK_BW_WRITE_RAW_HBUFFER(thr,bw_ctx,val) do { \
2613 		duk_size_t duk__val_len; \
2614 		duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
2615 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2616 		(bw_ctx)->p += duk__val_len; \
2617 	} while (0)
2618 #define DUK_BW_WRITE_RAW_HBUFFER_FIXED(thr,bw_ctx,val) do { \
2619 		duk_size_t duk__val_len; \
2620 		duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
2621 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2622 		(bw_ctx)->p += duk__val_len; \
2623 	} while (0)
2624 #define DUK_BW_WRITE_RAW_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
2625 		duk_size_t duk__val_len; \
2626 		duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
2627 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2628 		(bw_ctx)->p += duk__val_len; \
2629 	} while (0)
2630 
2631 /* Append bytes from a slice already in the buffer. */
2632 #define DUK_BW_WRITE_RAW_SLICE(thr,bw,dst_off,dst_len) \
2633 	duk_bw_write_raw_slice((thr), (bw), (dst_off), (dst_len))
2634 
2635 /* Insert bytes in the middle of the buffer from an external buffer. */
2636 #define DUK_BW_INSERT_RAW_BYTES(thr,bw,dst_off,buf,len) \
2637 	duk_bw_insert_raw_bytes((thr), (bw), (dst_off), (buf), (len))
2638 
2639 /* Insert bytes in the middle of the buffer from a slice already
2640  * in the buffer.  Source offset is interpreted "before" the operation.
2641  */
2642 #define DUK_BW_INSERT_RAW_SLICE(thr,bw,dst_off,src_off,len) \
2643 	duk_bw_insert_raw_slice((thr), (bw), (dst_off), (src_off), (len))
2644 
2645 /* Insert a reserved area somewhere in the buffer; caller fills it.
2646  * Evaluates to a (duk_uint_t *) pointing to the start of the reserved
2647  * area for convenience.
2648  */
2649 #define DUK_BW_INSERT_RAW_AREA(thr,bw,off,len) \
2650 	duk_bw_insert_raw_area((thr), (bw), (off), (len))
2651 
2652 /* Remove a slice from inside buffer. */
2653 #define DUK_BW_REMOVE_RAW_SLICE(thr,bw,off,len) \
2654 	duk_bw_remove_raw_slice((thr), (bw), (off), (len))
2655 
2656 /* Safe write calls which will ensure space first. */
2657 
2658 #define DUK_BW_WRITE_ENSURE_U8(thr,bw_ctx,val) do { \
2659 		DUK_BW_ENSURE((thr), (bw_ctx), 1); \
2660 		DUK_BW_WRITE_RAW_U8((thr), (bw_ctx), (val)); \
2661 	} while (0)
2662 #define DUK_BW_WRITE_ENSURE_U8_2(thr,bw_ctx,val1,val2) do { \
2663 		DUK_BW_ENSURE((thr), (bw_ctx), 2); \
2664 		DUK_BW_WRITE_RAW_U8_2((thr), (bw_ctx), (val1), (val2)); \
2665 	} while (0)
2666 #define DUK_BW_WRITE_ENSURE_U8_3(thr,bw_ctx,val1,val2,val3) do { \
2667 		DUK_BW_ENSURE((thr), (bw_ctx), 3); \
2668 		DUK_BW_WRITE_RAW_U8_3((thr), (bw_ctx), (val1), (val2), (val3)); \
2669 	} while (0)
2670 #define DUK_BW_WRITE_ENSURE_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
2671 		DUK_BW_ENSURE((thr), (bw_ctx), 4); \
2672 		DUK_BW_WRITE_RAW_U8_4((thr), (bw_ctx), (val1), (val2), (val3), (val4)); \
2673 	} while (0)
2674 #define DUK_BW_WRITE_ENSURE_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
2675 		DUK_BW_ENSURE((thr), (bw_ctx), 5); \
2676 		DUK_BW_WRITE_RAW_U8_5((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5)); \
2677 	} while (0)
2678 #define DUK_BW_WRITE_ENSURE_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
2679 		DUK_BW_ENSURE((thr), (bw_ctx), 6); \
2680 		DUK_BW_WRITE_RAW_U8_6((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5), (val6)); \
2681 	} while (0)
2682 #define DUK_BW_WRITE_ENSURE_XUTF8(thr,bw_ctx,cp) do { \
2683 		DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_XUTF8_LENGTH); \
2684 		DUK_BW_WRITE_RAW_XUTF8((thr), (bw_ctx), (cp)); \
2685 	} while (0)
2686 #define DUK_BW_WRITE_ENSURE_CESU8(thr,bw_ctx,cp) do { \
2687 		DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_CESU8_LENGTH); \
2688 		DUK_BW_WRITE_RAW_CESU8((thr), (bw_ctx), (cp)); \
2689 	} while (0)
2690 /* XXX: add temporary duk__p pointer here too; sharing */
2691 /* XXX: avoid unsafe */
2692 #define DUK_BW_WRITE_ENSURE_BYTES(thr,bw_ctx,valptr,valsz) do { \
2693 		const void *duk__valptr; \
2694 		duk_size_t duk__valsz; \
2695 		duk__valptr = (const void *) (valptr); \
2696 		duk__valsz = (duk_size_t) (valsz); \
2697 		DUK_BW_ENSURE((thr), (bw_ctx), duk__valsz); \
2698 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
2699 		(bw_ctx)->p += duk__valsz; \
2700 	} while (0)
2701 #define DUK_BW_WRITE_ENSURE_CSTRING(thr,bw_ctx,val) do { \
2702 		const duk_uint8_t *duk__val; \
2703 		duk_size_t duk__val_len; \
2704 		duk__val = (const duk_uint8_t *) (val); \
2705 		duk__val_len = DUK_STRLEN((const char *) duk__val); \
2706 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2707 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
2708 		(bw_ctx)->p += duk__val_len; \
2709 	} while (0)
2710 #define DUK_BW_WRITE_ENSURE_HSTRING(thr,bw_ctx,val) do { \
2711 		duk_size_t duk__val_len; \
2712 		duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
2713 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2714 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
2715 		(bw_ctx)->p += duk__val_len; \
2716 	} while (0)
2717 #define DUK_BW_WRITE_ENSURE_HBUFFER(thr,bw_ctx,val) do { \
2718 		duk_size_t duk__val_len; \
2719 		duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
2720 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2721 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2722 		(bw_ctx)->p += duk__val_len; \
2723 	} while (0)
2724 #define DUK_BW_WRITE_ENSURE_HBUFFER_FIXED(thr,bw_ctx,val) do { \
2725 		duk_size_t duk__val_len; \
2726 		duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
2727 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2728 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2729 		(bw_ctx)->p += duk__val_len; \
2730 	} while (0)
2731 #define DUK_BW_WRITE_ENSURE_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
2732 		duk_size_t duk__val_len; \
2733 		duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
2734 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2735 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2736 		(bw_ctx)->p += duk__val_len; \
2737 	} while (0)
2738 
2739 #define DUK_BW_WRITE_ENSURE_SLICE(thr,bw,dst_off,dst_len) \
2740 	duk_bw_write_ensure_slice((thr), (bw), (dst_off), (dst_len))
2741 #define DUK_BW_INSERT_ENSURE_BYTES(thr,bw,dst_off,buf,len) \
2742 	duk_bw_insert_ensure_bytes((thr), (bw), (dst_off), (buf), (len))
2743 #define DUK_BW_INSERT_ENSURE_SLICE(thr,bw,dst_off,src_off,len) \
2744 	duk_bw_insert_ensure_slice((thr), (bw), (dst_off), (src_off), (len))
2745 #define DUK_BW_INSERT_ENSURE_AREA(thr,bw,off,len) \
2746 	/* Evaluates to (duk_uint8_t *) pointing to start of area. */ \
2747 	duk_bw_insert_ensure_area((thr), (bw), (off), (len))
2748 #define DUK_BW_REMOVE_ENSURE_SLICE(thr,bw,off,len) \
2749 	/* No difference between raw/ensure because the buffer shrinks. */ \
2750 	DUK_BW_REMOVE_RAW_SLICE((thr), (bw), (off), (len))
2751 
2752 /*
2753  *  Externs and prototypes
2754  */
2755 
2756 #if !defined(DUK_SINGLE_FILE)
2757 DUK_INTERNAL_DECL const duk_uint8_t duk_lc_digits[36];
2758 DUK_INTERNAL_DECL const duk_uint8_t duk_uc_nybbles[16];
2759 DUK_INTERNAL_DECL const duk_int8_t duk_hex_dectab[256];
2760 #if defined(DUK_USE_HEX_FASTPATH)
2761 DUK_INTERNAL_DECL const duk_int16_t duk_hex_dectab_shift4[256];
2762 DUK_INTERNAL_DECL const duk_uint16_t duk_hex_enctab[256];
2763 #endif
2764 #endif  /* !DUK_SINGLE_FILE */
2765 
2766 /* Note: assumes that duk_util_probe_steps size is 32 */
2767 #if defined(DUK_USE_HOBJECT_HASH_PART)
2768 #if !defined(DUK_SINGLE_FILE)
2769 DUK_INTERNAL_DECL duk_uint8_t duk_util_probe_steps[32];
2770 #endif  /* !DUK_SINGLE_FILE */
2771 #endif
2772 
2773 #if defined(DUK_USE_STRHASH_DENSE)
2774 DUK_INTERNAL_DECL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed);
2775 #endif
2776 
2777 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits);
2778 DUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx);
2779 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value);
2780 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);
2781 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx);
2782 DUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx *bd, duk_uint8_t *out);
2783 
2784 DUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits);
2785 DUK_INTERNAL_DECL void duk_be_finish(duk_bitencoder_ctx *ctx);
2786 
2787 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
2788 DUK_INTERNAL_DECL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr);
2789 DUK_INTERNAL_DECL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr);
2790 #endif
2791 
2792 DUK_INTERNAL_DECL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf);
2793 DUK_INTERNAL_DECL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size);
2794 DUK_INTERNAL_DECL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz);
2795 DUK_INTERNAL_DECL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx);
2796 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);
2797 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);
2798 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);
2799 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);
2800 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);
2801 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);
2802 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);
2803 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);
2804 DUK_INTERNAL_DECL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);
2805 /* No duk_bw_remove_ensure_slice(), functionality would be identical. */
2806 
2807 DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p);
2808 DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p);
2809 DUK_INTERNAL_DECL duk_double_t duk_raw_read_double_be(duk_uint8_t **p);
2810 DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val);
2811 DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val);
2812 DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val);
2813 
2814 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* For now only needed by the debugger. */
2815 DUK_INTERNAL_DECL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len);
2816 #endif
2817 
2818 /* memcpy(), memmove() etc wrappers.  The plain variants like duk_memcpy()
2819  * assume C99+ and 'src' and 'dst' pointers must be non-NULL even when the
2820  * operation size is zero.  The unsafe variants like duk_memcpy_safe() deal
2821  * with the zero size case explicitly, and allow NULL pointers in that case
2822  * (which is undefined behavior in C99+).  For the majority of actual targets
2823  * a NULL pointer with a zero length is fine in practice.  These wrappers are
2824  * macros to force inlining; because there are hundreds of call sites, even a
2825  * few extra bytes per call site adds up to ~1kB footprint.
2826  */
2827 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
2828 #define duk_memcpy(dst,src,len)  do { \
2829 		void *duk__dst = (dst); \
2830 		const void *duk__src = (src); \
2831 		duk_size_t duk__len = (len); \
2832 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2833 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2834 		(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
2835 	} while (0)
2836 #define duk_memcpy_unsafe(dst,src,len)  duk_memcpy((dst), (src), (len))
2837 #define duk_memmove(dst,src,len)  do { \
2838 		void *duk__dst = (dst); \
2839 		const void *duk__src = (src); \
2840 		duk_size_t duk__len = (len); \
2841 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2842 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2843 		(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
2844 	} while (0)
2845 #define duk_memmove_unsafe(dst,src,len)  duk_memmove((dst), (src), (len))
2846 #define duk_memset(dst,val,len)  do { \
2847 		void *duk__dst = (dst); \
2848 		duk_small_int_t duk__val = (val); \
2849 		duk_size_t duk__len = (len); \
2850 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2851 		(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
2852 	} while (0)
2853 #define duk_memset_unsafe(dst,val,len)  duk_memset((dst), (val), (len))
2854 #define duk_memzero(dst,len)  do { \
2855 		void *duk__dst = (dst); \
2856 		duk_size_t duk__len = (len); \
2857 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2858 		(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
2859 	} while (0)
2860 #define duk_memzero_unsafe(dst,len)  duk_memzero((dst), (len))
2861 #else  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
2862 #define duk_memcpy(dst,src,len)  do { \
2863 		void *duk__dst = (dst); \
2864 		const void *duk__src = (src); \
2865 		duk_size_t duk__len = (len); \
2866 		DUK_ASSERT(duk__dst != NULL); \
2867 		DUK_ASSERT(duk__src != NULL); \
2868 		(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
2869 	} while (0)
2870 #define duk_memcpy_unsafe(dst,src,len)  do { \
2871 		void *duk__dst = (dst); \
2872 		const void *duk__src = (src); \
2873 		duk_size_t duk__len = (len); \
2874 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2875 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2876 		if (DUK_LIKELY(duk__len > 0U)) { \
2877 			DUK_ASSERT(duk__dst != NULL); \
2878 			DUK_ASSERT(duk__src != NULL); \
2879 			(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
2880 		} \
2881 	} while (0)
2882 #define duk_memmove(dst,src,len)  do { \
2883 		void *duk__dst = (dst); \
2884 		const void *duk__src = (src); \
2885 		duk_size_t duk__len = (len); \
2886 		DUK_ASSERT(duk__dst != NULL); \
2887 		DUK_ASSERT(duk__src != NULL); \
2888 		(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
2889 	} while (0)
2890 #define duk_memmove_unsafe(dst,src,len)  do { \
2891 		void *duk__dst = (dst); \
2892 		const void *duk__src = (src); \
2893 		duk_size_t duk__len = (len); \
2894 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2895 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2896 		if (DUK_LIKELY(duk__len > 0U)) { \
2897 			DUK_ASSERT(duk__dst != NULL); \
2898 			DUK_ASSERT(duk__src != NULL); \
2899 			(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
2900 		} \
2901 	} while (0)
2902 #define duk_memset(dst,val,len)  do { \
2903 		void *duk__dst = (dst); \
2904 		duk_small_int_t duk__val = (val); \
2905 		duk_size_t duk__len = (len); \
2906 		DUK_ASSERT(duk__dst != NULL); \
2907 		(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
2908 	} while (0)
2909 #define duk_memset_unsafe(dst,val,len)  do { \
2910 		void *duk__dst = (dst); \
2911 		duk_small_int_t duk__val = (val); \
2912 		duk_size_t duk__len = (len); \
2913 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2914 		if (DUK_LIKELY(duk__len > 0U)) { \
2915 			DUK_ASSERT(duk__dst != NULL); \
2916 			(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
2917 		} \
2918 	} while (0)
2919 #define duk_memzero(dst,len)  do { \
2920 		void *duk__dst = (dst); \
2921 		duk_size_t duk__len = (len); \
2922 		DUK_ASSERT(duk__dst != NULL); \
2923 		(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
2924 	} while (0)
2925 #define duk_memzero_unsafe(dst,len)  do { \
2926 		void *duk__dst = (dst); \
2927 		duk_size_t duk__len = (len); \
2928 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2929 		if (DUK_LIKELY(duk__len > 0U)) { \
2930 			DUK_ASSERT(duk__dst != NULL); \
2931 			(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
2932 		} \
2933 	} while (0)
2934 #endif  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
2935 
2936 DUK_INTERNAL_DECL duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len);
2937 DUK_INTERNAL_DECL duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len);
2938 
2939 DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival);
2940 DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival);
2941 DUK_INTERNAL_DECL duk_bool_t duk_double_is_anyinf(duk_double_t x);
2942 DUK_INTERNAL_DECL duk_bool_t duk_double_is_posinf(duk_double_t x);
2943 DUK_INTERNAL_DECL duk_bool_t duk_double_is_neginf(duk_double_t x);
2944 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan(duk_double_t x);
2945 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x);
2946 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x);
2947 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x);
2948 DUK_INTERNAL_DECL duk_small_uint_t duk_double_signbit(duk_double_t x);
2949 DUK_INTERNAL_DECL duk_double_t duk_double_trunc_towards_zero(duk_double_t x);
2950 DUK_INTERNAL_DECL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y);
2951 DUK_INTERNAL_DECL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y);
2952 DUK_INTERNAL_DECL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y);
2953 DUK_INTERNAL_DECL duk_bool_t duk_double_is_finite(duk_double_t x);
2954 DUK_INTERNAL_DECL duk_bool_t duk_double_is_integer(duk_double_t x);
2955 DUK_INTERNAL_DECL duk_bool_t duk_double_is_safe_integer(duk_double_t x);
2956 
2957 DUK_INTERNAL_DECL duk_double_t duk_double_div(duk_double_t x, duk_double_t y);
2958 DUK_INTERNAL_DECL duk_int_t duk_double_to_int_t(duk_double_t x);
2959 DUK_INTERNAL_DECL duk_uint_t duk_double_to_uint_t(duk_double_t x);
2960 DUK_INTERNAL_DECL duk_int32_t duk_double_to_int32_t(duk_double_t x);
2961 DUK_INTERNAL_DECL duk_uint32_t duk_double_to_uint32_t(duk_double_t x);
2962 DUK_INTERNAL_DECL duk_float_t duk_double_to_float_t(duk_double_t x);
2963 
2964 /*
2965  *  Miscellaneous
2966  */
2967 
2968 /* Example: x     = 0x10 = 0b00010000
2969  *          x - 1 = 0x0f = 0b00001111
2970  *          x & (x - 1) == 0
2971  *
2972  *          x     = 0x07 = 0b00000111
2973  *          x - 1 = 0x06 = 0b00000110
2974  *          x & (x - 1) != 0
2975  *
2976  * However, incorrectly true for x == 0 so check for that explicitly.
2977  */
2978 #define DUK_IS_POWER_OF_TWO(x) \
2979 	((x) != 0U && ((x) & ((x) - 1U)) == 0U)
2980 
2981 #endif  /* DUK_UTIL_H_INCLUDED */
2982 /* #include duk_strings.h */
2983 #line 1 "duk_strings.h"
2984 /*
2985  *  Shared string macros.
2986  *
2987  *  Using shared macros helps minimize strings data size because it's easy
2988  *  to check if an existing string could be used.  String constants don't
2989  *  need to be all defined here; defining a string here makes sense if there's
2990  *  a high chance the string could be reused.  Also, using macros allows
2991  *  a call site express the exact string needed, but the macro may map to an
2992  *  approximate string to reduce unique string count.  Macros can also be
2993  *  more easily tuned for low memory targets than #if defined()s throughout
2994  *  the code base.
2995  *
2996  *  Because format strings behave differently in the call site (they need to
2997  *  be followed by format arguments), they use a special prefix DUK_STR_FMT_.
2998  *
2999  *  On some compilers using explicit shared strings is preferable; on others
3000  *  it may be better to use straight literals because the compiler will combine
3001  *  them anyway, and such strings won't end up unnecessarily in a symbol table.
3002  */
3003 
3004 #if !defined(DUK_ERRMSG_H_INCLUDED)
3005 #define DUK_ERRMSG_H_INCLUDED
3006 
3007 /* Mostly API and built-in method related */
3008 #define DUK_STR_INTERNAL_ERROR                   "internal error"
3009 #define DUK_STR_UNSUPPORTED                      "unsupported"
3010 #define DUK_STR_INVALID_COUNT                    "invalid count"
3011 #define DUK_STR_INVALID_ARGS                     "invalid args"
3012 #define DUK_STR_INVALID_STATE                    "invalid state"
3013 #define DUK_STR_INVALID_INPUT                    "invalid input"
3014 #define DUK_STR_INVALID_LENGTH                   "invalid length"
3015 #define DUK_STR_NOT_CONSTRUCTABLE                "not constructable"
3016 #define DUK_STR_CONSTRUCT_ONLY                   "constructor requires 'new'"
3017 #define DUK_STR_NOT_CALLABLE                     "not callable"
3018 #define DUK_STR_NOT_EXTENSIBLE                   "not extensible"
3019 #define DUK_STR_NOT_WRITABLE                     "not writable"
3020 #define DUK_STR_NOT_CONFIGURABLE                 "not configurable"
3021 #define DUK_STR_INVALID_CONTEXT                  "invalid context"
3022 #define DUK_STR_INVALID_INDEX                    "invalid args"
3023 #define DUK_STR_PUSH_BEYOND_ALLOC_STACK          "cannot push beyond allocated stack"
3024 #define DUK_STR_NOT_UNDEFINED                    "unexpected type"
3025 #define DUK_STR_NOT_NULL                         "unexpected type"
3026 #define DUK_STR_NOT_BOOLEAN                      "unexpected type"
3027 #define DUK_STR_NOT_NUMBER                       "unexpected type"
3028 #define DUK_STR_NOT_STRING                       "unexpected type"
3029 #define DUK_STR_NOT_OBJECT                       "unexpected type"
3030 #define DUK_STR_NOT_POINTER                      "unexpected type"
3031 #define DUK_STR_NOT_BUFFER                       "not buffer"  /* still in use with verbose messages */
3032 #define DUK_STR_UNEXPECTED_TYPE                  "unexpected type"
3033 #define DUK_STR_NOT_THREAD                       "unexpected type"
3034 #define DUK_STR_NOT_COMPFUNC                     "unexpected type"
3035 #define DUK_STR_NOT_NATFUNC                      "unexpected type"
3036 #define DUK_STR_NOT_C_FUNCTION                   "unexpected type"
3037 #define DUK_STR_NOT_FUNCTION                     "unexpected type"
3038 #define DUK_STR_NOT_REGEXP                       "unexpected type"
3039 #define DUK_STR_TOPRIMITIVE_FAILED               "coercion to primitive failed"
3040 #define DUK_STR_NUMBER_OUTSIDE_RANGE             "number outside range"
3041 #define DUK_STR_NOT_OBJECT_COERCIBLE             "not object coercible"
3042 #define DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL      "cannot number coerce Symbol"
3043 #define DUK_STR_CANNOT_STRING_COERCE_SYMBOL      "cannot string coerce Symbol"
3044 #define DUK_STR_STRING_TOO_LONG                  "string too long"
3045 #define DUK_STR_BUFFER_TOO_LONG                  "buffer too long"
3046 #define DUK_STR_ALLOC_FAILED                     "alloc failed"
3047 #define DUK_STR_WRONG_BUFFER_TYPE                "wrong buffer type"
3048 #define DUK_STR_BASE64_ENCODE_FAILED             "base64 encode failed"
3049 #define DUK_STR_SOURCE_DECODE_FAILED             "source decode failed"
3050 #define DUK_STR_UTF8_DECODE_FAILED               "utf-8 decode failed"
3051 #define DUK_STR_BASE64_DECODE_FAILED             "base64 decode failed"
3052 #define DUK_STR_HEX_DECODE_FAILED                "hex decode failed"
3053 #define DUK_STR_INVALID_BYTECODE                 "invalid bytecode"
3054 #define DUK_STR_NO_SOURCECODE                    "no sourcecode"
3055 #define DUK_STR_RESULT_TOO_LONG                  "result too long"
3056 #define DUK_STR_INVALID_CFUNC_RC                 "invalid C function rc"
3057 #define DUK_STR_INVALID_INSTANCEOF_RVAL          "invalid instanceof rval"
3058 #define DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO  "instanceof rval has no .prototype"
3059 
3060 /* JSON */
3061 #define DUK_STR_FMT_PTR                          "%p"
3062 #define DUK_STR_FMT_INVALID_JSON                 "invalid json (at offset %ld)"
3063 #define DUK_STR_JSONDEC_RECLIMIT                 "json decode recursion limit"
3064 #define DUK_STR_JSONENC_RECLIMIT                 "json encode recursion limit"
3065 #define DUK_STR_CYCLIC_INPUT                     "cyclic input"
3066 
3067 /* Object property access */
3068 #define DUK_STR_INVALID_BASE                     "invalid base value"
3069 #define DUK_STR_STRICT_CALLER_READ               "cannot read strict 'caller'"
3070 #define DUK_STR_PROXY_REJECTED                   "proxy rejected"
3071 #define DUK_STR_INVALID_ARRAY_LENGTH             "invalid array length"
3072 #define DUK_STR_SETTER_UNDEFINED                 "setter undefined"
3073 #define DUK_STR_INVALID_DESCRIPTOR               "invalid descriptor"
3074 
3075 /* Proxy */
3076 #define DUK_STR_PROXY_REVOKED                    "proxy revoked"
3077 #define DUK_STR_INVALID_TRAP_RESULT              "invalid trap result"
3078 
3079 /* Variables */
3080 
3081 /* Lexer */
3082 #define DUK_STR_INVALID_ESCAPE                   "invalid escape"
3083 #define DUK_STR_UNTERMINATED_STRING              "unterminated string"
3084 #define DUK_STR_UNTERMINATED_COMMENT             "unterminated comment"
3085 #define DUK_STR_UNTERMINATED_REGEXP              "unterminated regexp"
3086 #define DUK_STR_TOKEN_LIMIT                      "token limit"
3087 #define DUK_STR_REGEXP_SUPPORT_DISABLED          "regexp support disabled"
3088 #define DUK_STR_INVALID_NUMBER_LITERAL           "invalid number literal"
3089 #define DUK_STR_INVALID_TOKEN                    "invalid token"
3090 
3091 /* Compiler */
3092 #define DUK_STR_PARSE_ERROR                      "parse error"
3093 #define DUK_STR_DUPLICATE_LABEL                  "duplicate label"
3094 #define DUK_STR_INVALID_LABEL                    "invalid label"
3095 #define DUK_STR_INVALID_ARRAY_LITERAL            "invalid array literal"
3096 #define DUK_STR_INVALID_OBJECT_LITERAL           "invalid object literal"
3097 #define DUK_STR_INVALID_VAR_DECLARATION          "invalid variable declaration"
3098 #define DUK_STR_CANNOT_DELETE_IDENTIFIER         "cannot delete identifier"
3099 #define DUK_STR_INVALID_EXPRESSION               "invalid expression"
3100 #define DUK_STR_INVALID_LVALUE                   "invalid lvalue"
3101 #define DUK_STR_INVALID_NEWTARGET                "invalid new.target"
3102 #define DUK_STR_EXPECTED_IDENTIFIER              "expected identifier"
3103 #define DUK_STR_EMPTY_EXPR_NOT_ALLOWED           "empty expression not allowed"
3104 #define DUK_STR_INVALID_FOR                      "invalid for statement"
3105 #define DUK_STR_INVALID_SWITCH                   "invalid switch statement"
3106 #define DUK_STR_INVALID_BREAK_CONT_LABEL         "invalid break/continue label"
3107 #define DUK_STR_INVALID_RETURN                   "invalid return"
3108 #define DUK_STR_INVALID_TRY                      "invalid try"
3109 #define DUK_STR_INVALID_THROW                    "invalid throw"
3110 #define DUK_STR_WITH_IN_STRICT_MODE              "with in strict mode"
3111 #define DUK_STR_FUNC_STMT_NOT_ALLOWED            "function statement not allowed"
3112 #define DUK_STR_UNTERMINATED_STMT                "unterminated statement"
3113 #define DUK_STR_INVALID_ARG_NAME                 "invalid argument name"
3114 #define DUK_STR_INVALID_FUNC_NAME                "invalid function name"
3115 #define DUK_STR_INVALID_GETSET_NAME              "invalid getter/setter name"
3116 #define DUK_STR_FUNC_NAME_REQUIRED               "function name required"
3117 
3118 /* RegExp */
3119 #define DUK_STR_INVALID_QUANTIFIER               "invalid regexp quantifier"
3120 #define DUK_STR_INVALID_QUANTIFIER_NO_ATOM       "quantifier without preceding atom"
3121 #define DUK_STR_INVALID_QUANTIFIER_VALUES        "quantifier values invalid (qmin > qmax)"
3122 #define DUK_STR_QUANTIFIER_TOO_MANY_COPIES       "quantifier requires too many atom copies"
3123 #define DUK_STR_UNEXPECTED_CLOSING_PAREN         "unexpected closing parenthesis"
3124 #define DUK_STR_UNEXPECTED_END_OF_PATTERN        "unexpected end of pattern"
3125 #define DUK_STR_UNEXPECTED_REGEXP_TOKEN          "unexpected token in regexp"
3126 #define DUK_STR_INVALID_REGEXP_FLAGS             "invalid regexp flags"
3127 #define DUK_STR_INVALID_REGEXP_ESCAPE            "invalid regexp escape"
3128 #define DUK_STR_INVALID_BACKREFS                 "invalid backreference(s)"
3129 #define DUK_STR_INVALID_REGEXP_CHARACTER         "invalid regexp character"
3130 #define DUK_STR_INVALID_REGEXP_GROUP             "invalid regexp group"
3131 #define DUK_STR_UNTERMINATED_CHARCLASS           "unterminated character class"
3132 #define DUK_STR_INVALID_RANGE                    "invalid range"
3133 
3134 /* Limits */
3135 #define DUK_STR_VALSTACK_LIMIT                   "valstack limit"
3136 #define DUK_STR_CALLSTACK_LIMIT                  "callstack limit"
3137 #define DUK_STR_PROTOTYPE_CHAIN_LIMIT            "prototype chain limit"
3138 #define DUK_STR_BOUND_CHAIN_LIMIT                "function call bound chain limit"
3139 #define DUK_STR_C_CALLSTACK_LIMIT                "C call stack depth limit"
3140 #define DUK_STR_COMPILER_RECURSION_LIMIT         "compiler recursion limit"
3141 #define DUK_STR_BYTECODE_LIMIT                   "bytecode limit"
3142 #define DUK_STR_REG_LIMIT                        "register limit"
3143 #define DUK_STR_TEMP_LIMIT                       "temp limit"
3144 #define DUK_STR_CONST_LIMIT                      "const limit"
3145 #define DUK_STR_FUNC_LIMIT                       "function limit"
3146 #define DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT  "regexp compiler recursion limit"
3147 #define DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT  "regexp executor recursion limit"
3148 #define DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT       "regexp step limit"
3149 
3150 #endif  /* DUK_ERRMSG_H_INCLUDED */
3151 /* #include duk_js_bytecode.h */
3152 #line 1 "duk_js_bytecode.h"
3153 /*
3154  *  ECMAScript bytecode
3155  */
3156 
3157 #if !defined(DUK_JS_BYTECODE_H_INCLUDED)
3158 #define DUK_JS_BYTECODE_H_INCLUDED
3159 
3160 /*
3161  *  Bytecode instruction layout
3162  *  ===========================
3163  *
3164  *  Instructions are unsigned 32-bit integers divided as follows:
3165  *
3166  *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
3167  *  !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!
3168  *  +-----------------------------------------------+---------------+
3169  *  !       C       !       B       !       A       !       OP      !
3170  *  +-----------------------------------------------+---------------+
3171  *
3172  *  OP (8 bits):  opcode (DUK_OP_*), access should be fastest
3173  *                consecutive opcodes allocated when opcode needs flags
3174  *   A (8 bits):  typically a target register number
3175  *   B (8 bits):  typically first source register/constant number
3176  *   C (8 bits):  typically second source register/constant number
3177  *
3178  *  Some instructions combine BC or ABC together for larger parameter values.
3179  *  Signed integers (e.g. jump offsets) are encoded as unsigned, with an
3180  *  opcode specific bias.
3181  *
3182  *  Some opcodes have flags which are handled by allocating consecutive
3183  *  opcodes to make space for 1-N flags.  Flags can also be e.g. in the 'A'
3184  *  field when there's room for the specific opcode.
3185  *
3186  *  For example, if three flags were needed, they could be allocated from
3187  *  the opcode field as follows:
3188  *
3189  *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
3190  *  !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!
3191  *  +-----------------------------------------------+---------------+
3192  *  !       C       !       B       !       A       !    OP   !Z!Y!X!
3193  *  +-----------------------------------------------+---------------+
3194  *
3195  *  Some opcodes accept a reg/const argument which is handled by allocating
3196  *  flags in the OP field, see DUK_BC_ISREG() and DUK_BC_ISCONST().  The
3197  *  following convention is shared by most opcodes, so that the compiler
3198  *  can handle reg/const flagging without opcode specific code paths:
3199  *
3200  *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
3201  *  !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!
3202  *  +-----------------------------------------------+---------------+
3203  *  !       C       !       B       !       A       !     OP    !Y!X!
3204  *  +-----------------------------------------------+---------------+
3205  *
3206  *    X  1=B is const, 0=B is reg
3207  *    Y  1=C is const, 0=C is reg
3208  *
3209  *    In effect OP, OP + 1, OP + 2, and OP + 3 are allocated from the
3210  *    8-bit opcode space for a single logical opcode.  The base opcode
3211  *    number should be divisible by 4.  If the opcode is called 'FOO'
3212  *    the following opcode constants would be defined:
3213  *
3214  *      DUK_OP_FOO     100       // base opcode number
3215  *      DUK_OP_FOO_RR  100       // FOO, B=reg, C=reg
3216  *      DUK_OP_FOO_CR  101       // FOO, B=const, C=reg
3217  *      DUK_OP_FOO_RC  102       // FOO, B=reg, C=const
3218  *      DUK_OP_FOO_CC  103       // FOO, B=const, C=const
3219  *
3220  *  If only B or C is a reg/const, the unused opcode combinations can be
3221  *  used for other opcodes (which take no reg/const argument).  However,
3222  *  such opcode values are initially reserved, at least while opcode space
3223  *  is available.  For example, if 'BAR' uses B for a register field and
3224  *  C is a reg/const:
3225  *
3226  *      DUK_OP_BAR            116    // base opcode number
3227  *      DUK_OP_BAR_RR         116    // BAR, B=reg, C=reg
3228  *      DUK_OP_BAR_CR_UNUSED  117    // unused, could be repurposed
3229  *      DUK_OP_BAR_RC         118    // BAR, B=reg, C=const
3230  *      DUK_OP_BAR_CC_UNUSED  119    // unused, could be repurposed
3231  *
3232  *  Macro naming is a bit misleading, e.g. "ABC" in macro name but the
3233  *  field layout is concretely "CBA" in the register.
3234  */
3235 
3236 typedef duk_uint32_t duk_instr_t;
3237 
3238 #define DUK_BC_SHIFT_OP             0
3239 #define DUK_BC_SHIFT_A              8
3240 #define DUK_BC_SHIFT_B              16
3241 #define DUK_BC_SHIFT_C              24
3242 #define DUK_BC_SHIFT_BC             DUK_BC_SHIFT_B
3243 #define DUK_BC_SHIFT_ABC            DUK_BC_SHIFT_A
3244 
3245 #define DUK_BC_UNSHIFTED_MASK_OP    0xffUL
3246 #define DUK_BC_UNSHIFTED_MASK_A     0xffUL
3247 #define DUK_BC_UNSHIFTED_MASK_B     0xffUL
3248 #define DUK_BC_UNSHIFTED_MASK_C     0xffUL
3249 #define DUK_BC_UNSHIFTED_MASK_BC    0xffffUL
3250 #define DUK_BC_UNSHIFTED_MASK_ABC   0xffffffUL
3251 
3252 #define DUK_BC_SHIFTED_MASK_OP      (DUK_BC_UNSHIFTED_MASK_OP << DUK_BC_SHIFT_OP)
3253 #define DUK_BC_SHIFTED_MASK_A       (DUK_BC_UNSHIFTED_MASK_A << DUK_BC_SHIFT_A)
3254 #define DUK_BC_SHIFTED_MASK_B       (DUK_BC_UNSHIFTED_MASK_B << DUK_BC_SHIFT_B)
3255 #define DUK_BC_SHIFTED_MASK_C       (DUK_BC_UNSHIFTED_MASK_C << DUK_BC_SHIFT_C)
3256 #define DUK_BC_SHIFTED_MASK_BC      (DUK_BC_UNSHIFTED_MASK_BC << DUK_BC_SHIFT_BC)
3257 #define DUK_BC_SHIFTED_MASK_ABC     (DUK_BC_UNSHIFTED_MASK_ABC << DUK_BC_SHIFT_ABC)
3258 
3259 #define DUK_DEC_OP(x)               ((x) & 0xffUL)
3260 #define DUK_DEC_A(x)                (((x) >> 8) & 0xffUL)
3261 #define DUK_DEC_B(x)                (((x) >> 16) & 0xffUL)
3262 #define DUK_DEC_C(x)                (((x) >> 24) & 0xffUL)
3263 #define DUK_DEC_BC(x)               (((x) >> 16) & 0xffffUL)
3264 #define DUK_DEC_ABC(x)              (((x) >> 8) & 0xffffffUL)
3265 
3266 #define DUK_ENC_OP(op)              ((duk_instr_t) (op))
3267 #define DUK_ENC_OP_ABC(op,abc)      ((duk_instr_t) ( \
3268                                         (((duk_instr_t) (abc)) << 8) | \
3269                                         ((duk_instr_t) (op)) \
3270                                     ))
3271 #define DUK_ENC_OP_A_BC(op,a,bc)    ((duk_instr_t) ( \
3272                                         (((duk_instr_t) (bc)) << 16) | \
3273                                         (((duk_instr_t) (a)) << 8) | \
3274                                         ((duk_instr_t) (op)) \
3275                                     ))
3276 #define DUK_ENC_OP_A_B_C(op,a,b,c)  ((duk_instr_t) ( \
3277                                         (((duk_instr_t) (c)) << 24) | \
3278                                         (((duk_instr_t) (b)) << 16) | \
3279                                         (((duk_instr_t) (a)) << 8) | \
3280                                         ((duk_instr_t) (op)) \
3281                                     ))
3282 #define DUK_ENC_OP_A_B(op,a,b)      DUK_ENC_OP_A_B_C((op),(a),(b),0)
3283 #define DUK_ENC_OP_A(op,a)          DUK_ENC_OP_A_B_C((op),(a),0,0)
3284 #define DUK_ENC_OP_BC(op,bc)        DUK_ENC_OP_A_BC((op),0,(bc))
3285 
3286 /* Get opcode base value with B/C reg/const flags cleared. */
3287 #define DUK_BC_NOREGCONST_OP(op)    ((op) & 0xfc)
3288 
3289 /* Constants should be signed so that signed arithmetic involving them
3290  * won't cause values to be coerced accidentally to unsigned.
3291  */
3292 #define DUK_BC_OP_MIN               0
3293 #define DUK_BC_OP_MAX               0xffL
3294 #define DUK_BC_A_MIN                0
3295 #define DUK_BC_A_MAX                0xffL
3296 #define DUK_BC_B_MIN                0
3297 #define DUK_BC_B_MAX                0xffL
3298 #define DUK_BC_C_MIN                0
3299 #define DUK_BC_C_MAX                0xffL
3300 #define DUK_BC_BC_MIN               0
3301 #define DUK_BC_BC_MAX               0xffffL
3302 #define DUK_BC_ABC_MIN              0
3303 #define DUK_BC_ABC_MAX              0xffffffL
3304 
3305 /* Masks for B/C reg/const indicator in opcode field. */
3306 #define DUK_BC_REGCONST_B           (0x01UL)
3307 #define DUK_BC_REGCONST_C           (0x02UL)
3308 
3309 /* Misc. masks for opcode field. */
3310 #define DUK_BC_INCDECP_FLAG_DEC     (0x04UL)
3311 #define DUK_BC_INCDECP_FLAG_POST    (0x08UL)
3312 
3313 /* Opcodes. */
3314 #define DUK_OP_LDREG                0
3315 #define DUK_OP_STREG                1
3316 #define DUK_OP_JUMP                 2
3317 #define DUK_OP_LDCONST              3
3318 #define DUK_OP_LDINT                4
3319 #define DUK_OP_LDINTX               5
3320 #define DUK_OP_LDTHIS               6
3321 #define DUK_OP_LDUNDEF              7
3322 #define DUK_OP_LDNULL               8
3323 #define DUK_OP_LDTRUE               9
3324 #define DUK_OP_LDFALSE              10
3325 #define DUK_OP_GETVAR               11
3326 #define DUK_OP_BNOT                 12
3327 #define DUK_OP_LNOT                 13
3328 #define DUK_OP_UNM                  14
3329 #define DUK_OP_UNP                  15
3330 #define DUK_OP_EQ                   16
3331 #define DUK_OP_EQ_RR                16
3332 #define DUK_OP_EQ_CR                17
3333 #define DUK_OP_EQ_RC                18
3334 #define DUK_OP_EQ_CC                19
3335 #define DUK_OP_NEQ                  20
3336 #define DUK_OP_NEQ_RR               20
3337 #define DUK_OP_NEQ_CR               21
3338 #define DUK_OP_NEQ_RC               22
3339 #define DUK_OP_NEQ_CC               23
3340 #define DUK_OP_SEQ                  24
3341 #define DUK_OP_SEQ_RR               24
3342 #define DUK_OP_SEQ_CR               25
3343 #define DUK_OP_SEQ_RC               26
3344 #define DUK_OP_SEQ_CC               27
3345 #define DUK_OP_SNEQ                 28
3346 #define DUK_OP_SNEQ_RR              28
3347 #define DUK_OP_SNEQ_CR              29
3348 #define DUK_OP_SNEQ_RC              30
3349 #define DUK_OP_SNEQ_CC              31
3350 #define DUK_OP_GT                   32
3351 #define DUK_OP_GT_RR                32
3352 #define DUK_OP_GT_CR                33
3353 #define DUK_OP_GT_RC                34
3354 #define DUK_OP_GT_CC                35
3355 #define DUK_OP_GE                   36
3356 #define DUK_OP_GE_RR                36
3357 #define DUK_OP_GE_CR                37
3358 #define DUK_OP_GE_RC                38
3359 #define DUK_OP_GE_CC                39
3360 #define DUK_OP_LT                   40
3361 #define DUK_OP_LT_RR                40
3362 #define DUK_OP_LT_CR                41
3363 #define DUK_OP_LT_RC                42
3364 #define DUK_OP_LT_CC                43
3365 #define DUK_OP_LE                   44
3366 #define DUK_OP_LE_RR                44
3367 #define DUK_OP_LE_CR                45
3368 #define DUK_OP_LE_RC                46
3369 #define DUK_OP_LE_CC                47
3370 #define DUK_OP_IFTRUE               48
3371 #define DUK_OP_IFTRUE_R             48
3372 #define DUK_OP_IFTRUE_C             49
3373 #define DUK_OP_IFFALSE              50
3374 #define DUK_OP_IFFALSE_R            50
3375 #define DUK_OP_IFFALSE_C            51
3376 #define DUK_OP_ADD                  52
3377 #define DUK_OP_ADD_RR               52
3378 #define DUK_OP_ADD_CR               53
3379 #define DUK_OP_ADD_RC               54
3380 #define DUK_OP_ADD_CC               55
3381 #define DUK_OP_SUB                  56
3382 #define DUK_OP_SUB_RR               56
3383 #define DUK_OP_SUB_CR               57
3384 #define DUK_OP_SUB_RC               58
3385 #define DUK_OP_SUB_CC               59
3386 #define DUK_OP_MUL                  60
3387 #define DUK_OP_MUL_RR               60
3388 #define DUK_OP_MUL_CR               61
3389 #define DUK_OP_MUL_RC               62
3390 #define DUK_OP_MUL_CC               63
3391 #define DUK_OP_DIV                  64
3392 #define DUK_OP_DIV_RR               64
3393 #define DUK_OP_DIV_CR               65
3394 #define DUK_OP_DIV_RC               66
3395 #define DUK_OP_DIV_CC               67
3396 #define DUK_OP_MOD                  68
3397 #define DUK_OP_MOD_RR               68
3398 #define DUK_OP_MOD_CR               69
3399 #define DUK_OP_MOD_RC               70
3400 #define DUK_OP_MOD_CC               71
3401 #define DUK_OP_EXP                  72
3402 #define DUK_OP_EXP_RR               72
3403 #define DUK_OP_EXP_CR               73
3404 #define DUK_OP_EXP_RC               74
3405 #define DUK_OP_EXP_CC               75
3406 #define DUK_OP_BAND                 76
3407 #define DUK_OP_BAND_RR              76
3408 #define DUK_OP_BAND_CR              77
3409 #define DUK_OP_BAND_RC              78
3410 #define DUK_OP_BAND_CC              79
3411 #define DUK_OP_BOR                  80
3412 #define DUK_OP_BOR_RR               80
3413 #define DUK_OP_BOR_CR               81
3414 #define DUK_OP_BOR_RC               82
3415 #define DUK_OP_BOR_CC               83
3416 #define DUK_OP_BXOR                 84
3417 #define DUK_OP_BXOR_RR              84
3418 #define DUK_OP_BXOR_CR              85
3419 #define DUK_OP_BXOR_RC              86
3420 #define DUK_OP_BXOR_CC              87
3421 #define DUK_OP_BASL                 88
3422 #define DUK_OP_BASL_RR              88
3423 #define DUK_OP_BASL_CR              89
3424 #define DUK_OP_BASL_RC              90
3425 #define DUK_OP_BASL_CC              91
3426 #define DUK_OP_BLSR                 92
3427 #define DUK_OP_BLSR_RR              92
3428 #define DUK_OP_BLSR_CR              93
3429 #define DUK_OP_BLSR_RC              94
3430 #define DUK_OP_BLSR_CC              95
3431 #define DUK_OP_BASR                 96
3432 #define DUK_OP_BASR_RR              96
3433 #define DUK_OP_BASR_CR              97
3434 #define DUK_OP_BASR_RC              98
3435 #define DUK_OP_BASR_CC              99
3436 #define DUK_OP_INSTOF               100
3437 #define DUK_OP_INSTOF_RR            100
3438 #define DUK_OP_INSTOF_CR            101
3439 #define DUK_OP_INSTOF_RC            102
3440 #define DUK_OP_INSTOF_CC            103
3441 #define DUK_OP_IN                   104
3442 #define DUK_OP_IN_RR                104
3443 #define DUK_OP_IN_CR                105
3444 #define DUK_OP_IN_RC                106
3445 #define DUK_OP_IN_CC                107
3446 #define DUK_OP_GETPROP              108
3447 #define DUK_OP_GETPROP_RR           108
3448 #define DUK_OP_GETPROP_CR           109
3449 #define DUK_OP_GETPROP_RC           110
3450 #define DUK_OP_GETPROP_CC           111
3451 #define DUK_OP_PUTPROP              112
3452 #define DUK_OP_PUTPROP_RR           112
3453 #define DUK_OP_PUTPROP_CR           113
3454 #define DUK_OP_PUTPROP_RC           114
3455 #define DUK_OP_PUTPROP_CC           115
3456 #define DUK_OP_DELPROP              116
3457 #define DUK_OP_DELPROP_RR           116
3458 #define DUK_OP_DELPROP_CR_UNUSED    117  /* unused now */
3459 #define DUK_OP_DELPROP_RC           118
3460 #define DUK_OP_DELPROP_CC_UNUSED    119  /* unused now */
3461 #define DUK_OP_PREINCR              120  /* pre/post opcode values have constraints, */
3462 #define DUK_OP_PREDECR              121  /* see duk_js_executor.c and duk_js_compiler.c. */
3463 #define DUK_OP_POSTINCR             122
3464 #define DUK_OP_POSTDECR             123
3465 #define DUK_OP_PREINCV              124
3466 #define DUK_OP_PREDECV              125
3467 #define DUK_OP_POSTINCV             126
3468 #define DUK_OP_POSTDECV             127
3469 #define DUK_OP_PREINCP              128  /* pre/post inc/dec prop opcodes have constraints */
3470 #define DUK_OP_PREINCP_RR           128
3471 #define DUK_OP_PREINCP_CR           129
3472 #define DUK_OP_PREINCP_RC           130
3473 #define DUK_OP_PREINCP_CC           131
3474 #define DUK_OP_PREDECP              132
3475 #define DUK_OP_PREDECP_RR           132
3476 #define DUK_OP_PREDECP_CR           133
3477 #define DUK_OP_PREDECP_RC           134
3478 #define DUK_OP_PREDECP_CC           135
3479 #define DUK_OP_POSTINCP             136
3480 #define DUK_OP_POSTINCP_RR          136
3481 #define DUK_OP_POSTINCP_CR          137
3482 #define DUK_OP_POSTINCP_RC          138
3483 #define DUK_OP_POSTINCP_CC          139
3484 #define DUK_OP_POSTDECP             140
3485 #define DUK_OP_POSTDECP_RR          140
3486 #define DUK_OP_POSTDECP_CR          141
3487 #define DUK_OP_POSTDECP_RC          142
3488 #define DUK_OP_POSTDECP_CC          143
3489 #define DUK_OP_DECLVAR              144
3490 #define DUK_OP_DECLVAR_RR           144
3491 #define DUK_OP_DECLVAR_CR           145
3492 #define DUK_OP_DECLVAR_RC           146
3493 #define DUK_OP_DECLVAR_CC           147
3494 #define DUK_OP_REGEXP               148
3495 #define DUK_OP_REGEXP_RR            148
3496 #define DUK_OP_REGEXP_CR            149
3497 #define DUK_OP_REGEXP_RC            150
3498 #define DUK_OP_REGEXP_CC            151
3499 #define DUK_OP_CLOSURE              152
3500 #define DUK_OP_TYPEOF               153
3501 #define DUK_OP_TYPEOFID             154
3502 #define DUK_OP_PUTVAR               155
3503 #define DUK_OP_DELVAR               156
3504 #define DUK_OP_RETREG               157
3505 #define DUK_OP_RETUNDEF             158
3506 #define DUK_OP_RETCONST             159
3507 #define DUK_OP_RETCONSTN            160  /* return const without incref (e.g. number) */
3508 #define DUK_OP_LABEL                161
3509 #define DUK_OP_ENDLABEL             162
3510 #define DUK_OP_BREAK                163
3511 #define DUK_OP_CONTINUE             164
3512 #define DUK_OP_TRYCATCH             165
3513 #define DUK_OP_ENDTRY               166
3514 #define DUK_OP_ENDCATCH             167
3515 #define DUK_OP_ENDFIN               168
3516 #define DUK_OP_THROW                169
3517 #define DUK_OP_INVLHS               170
3518 #define DUK_OP_CSREG                171
3519 #define DUK_OP_CSVAR                172
3520 #define DUK_OP_CSVAR_RR             172
3521 #define DUK_OP_CSVAR_CR             173
3522 #define DUK_OP_CSVAR_RC             174
3523 #define DUK_OP_CSVAR_CC             175
3524 #define DUK_OP_CALL0                176  /* DUK_OP_CALL0 & 0x0F must be zero. */
3525 #define DUK_OP_CALL1                177
3526 #define DUK_OP_CALL2                178
3527 #define DUK_OP_CALL3                179
3528 #define DUK_OP_CALL4                180
3529 #define DUK_OP_CALL5                181
3530 #define DUK_OP_CALL6                182
3531 #define DUK_OP_CALL7                183
3532 #define DUK_OP_CALL8                184
3533 #define DUK_OP_CALL9                185
3534 #define DUK_OP_CALL10               186
3535 #define DUK_OP_CALL11               187
3536 #define DUK_OP_CALL12               188
3537 #define DUK_OP_CALL13               189
3538 #define DUK_OP_CALL14               190
3539 #define DUK_OP_CALL15               191
3540 #define DUK_OP_NEWOBJ               192
3541 #define DUK_OP_NEWARR               193
3542 #define DUK_OP_MPUTOBJ              194
3543 #define DUK_OP_MPUTOBJI             195
3544 #define DUK_OP_INITSET              196
3545 #define DUK_OP_INITGET              197
3546 #define DUK_OP_MPUTARR              198
3547 #define DUK_OP_MPUTARRI             199
3548 #define DUK_OP_SETALEN              200
3549 #define DUK_OP_INITENUM             201
3550 #define DUK_OP_NEXTENUM             202
3551 #define DUK_OP_NEWTARGET            203
3552 #define DUK_OP_DEBUGGER             204
3553 #define DUK_OP_NOP                  205
3554 #define DUK_OP_INVALID              206
3555 #define DUK_OP_UNUSED207            207
3556 #define DUK_OP_GETPROPC             208
3557 #define DUK_OP_GETPROPC_RR          208
3558 #define DUK_OP_GETPROPC_CR          209
3559 #define DUK_OP_GETPROPC_RC          210
3560 #define DUK_OP_GETPROPC_CC          211
3561 #define DUK_OP_UNUSED212            212
3562 #define DUK_OP_UNUSED213            213
3563 #define DUK_OP_UNUSED214            214
3564 #define DUK_OP_UNUSED215            215
3565 #define DUK_OP_UNUSED216            216
3566 #define DUK_OP_UNUSED217            217
3567 #define DUK_OP_UNUSED218            218
3568 #define DUK_OP_UNUSED219            219
3569 #define DUK_OP_UNUSED220            220
3570 #define DUK_OP_UNUSED221            221
3571 #define DUK_OP_UNUSED222            222
3572 #define DUK_OP_UNUSED223            223
3573 #define DUK_OP_UNUSED224            224
3574 #define DUK_OP_UNUSED225            225
3575 #define DUK_OP_UNUSED226            226
3576 #define DUK_OP_UNUSED227            227
3577 #define DUK_OP_UNUSED228            228
3578 #define DUK_OP_UNUSED229            229
3579 #define DUK_OP_UNUSED230            230
3580 #define DUK_OP_UNUSED231            231
3581 #define DUK_OP_UNUSED232            232
3582 #define DUK_OP_UNUSED233            233
3583 #define DUK_OP_UNUSED234            234
3584 #define DUK_OP_UNUSED235            235
3585 #define DUK_OP_UNUSED236            236
3586 #define DUK_OP_UNUSED237            237
3587 #define DUK_OP_UNUSED238            238
3588 #define DUK_OP_UNUSED239            239
3589 #define DUK_OP_UNUSED240            240
3590 #define DUK_OP_UNUSED241            241
3591 #define DUK_OP_UNUSED242            242
3592 #define DUK_OP_UNUSED243            243
3593 #define DUK_OP_UNUSED244            244
3594 #define DUK_OP_UNUSED245            245
3595 #define DUK_OP_UNUSED246            246
3596 #define DUK_OP_UNUSED247            247
3597 #define DUK_OP_UNUSED248            248
3598 #define DUK_OP_UNUSED249            249
3599 #define DUK_OP_UNUSED250            250
3600 #define DUK_OP_UNUSED251            251
3601 #define DUK_OP_UNUSED252            252
3602 #define DUK_OP_UNUSED253            253
3603 #define DUK_OP_UNUSED254            254
3604 #define DUK_OP_UNUSED255            255
3605 #define DUK_OP_NONE                 256  /* dummy value used as marker (doesn't fit in 8-bit field) */
3606 
3607 /* XXX: Allocate flags from opcode field?  Would take 16 opcode slots
3608  * but avoids shuffling in more cases.  Maybe not worth it.
3609  */
3610 /* DUK_OP_TRYCATCH flags in A. */
3611 #define DUK_BC_TRYCATCH_FLAG_HAVE_CATCH     (1U << 0)
3612 #define DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY   (1U << 1)
3613 #define DUK_BC_TRYCATCH_FLAG_CATCH_BINDING  (1U << 2)
3614 #define DUK_BC_TRYCATCH_FLAG_WITH_BINDING   (1U << 3)
3615 
3616 /* DUK_OP_DECLVAR flags in A; bottom bits are reserved for propdesc flags
3617  * (DUK_PROPDESC_FLAG_XXX).
3618  */
3619 #define DUK_BC_DECLVAR_FLAG_FUNC_DECL       (1U << 4)  /* function declaration */
3620 
3621 /* DUK_OP_CALLn flags, part of opcode field.  Three lowest bits must match
3622  * DUK_CALL_FLAG_xxx directly.
3623  */
3624 #define DUK_BC_CALL_FLAG_TAILCALL           (1U << 0)
3625 #define DUK_BC_CALL_FLAG_CONSTRUCT          (1U << 1)
3626 #define DUK_BC_CALL_FLAG_CALLED_AS_EVAL     (1U << 2)
3627 #define DUK_BC_CALL_FLAG_INDIRECT           (1U << 3)
3628 
3629 /* Misc constants and helper macros. */
3630 #define DUK_BC_LDINT_BIAS           (1L << 15)
3631 #define DUK_BC_LDINTX_SHIFT         16
3632 #define DUK_BC_JUMP_BIAS            (1L << 23)
3633 
3634 #endif  /* DUK_JS_BYTECODE_H_INCLUDED */
3635 /* #include duk_lexer.h */
3636 #line 1 "duk_lexer.h"
3637 /*
3638  *  Lexer defines.
3639  */
3640 
3641 #if !defined(DUK_LEXER_H_INCLUDED)
3642 #define DUK_LEXER_H_INCLUDED
3643 
3644 typedef void (*duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct);
3645 
3646 /*
3647  *  A token is interpreted as any possible production of InputElementDiv
3648  *  and InputElementRegExp, see E5 Section 7 in its entirety.  Note that
3649  *  the E5 "Token" production does not cover all actual tokens of the
3650  *  language (which is explicitly stated in the specification, Section 7.5).
3651  *  Null and boolean literals are defined as part of both ReservedWord
3652  *  (E5 Section 7.6.1) and Literal (E5 Section 7.8) productions.  Here,
3653  *  null and boolean values have literal tokens, and are not reserved
3654  *  words.
3655  *
3656  *  Decimal literal negative/positive sign is -not- part of DUK_TOK_NUMBER.
3657  *  The number tokens always have a non-negative value.  The unary minus
3658  *  operator in "-1.0" is optimized during compilation to yield a single
3659  *  negative constant.
3660  *
3661  *  Token numbering is free except that reserved words are required to be
3662  *  in a continuous range and in a particular order.  See genstrings.py.
3663  */
3664 
3665 #define DUK_LEXER_INITCTX(ctx)        duk_lexer_initctx((ctx))
3666 
3667 #define DUK_LEXER_SETPOINT(ctx,pt)    duk_lexer_setpoint((ctx), (pt))
3668 
3669 #define DUK_LEXER_GETPOINT(ctx,pt)    duk_lexer_getpoint((ctx), (pt))
3670 
3671 /* Currently 6 characters of lookup are actually needed (duk_lexer.c). */
3672 #define DUK_LEXER_WINDOW_SIZE                     6
3673 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
3674 #define DUK_LEXER_BUFFER_SIZE                     64
3675 #endif
3676 
3677 #define DUK_TOK_MINVAL                            0
3678 
3679 /* returned after EOF (infinite amount) */
3680 #define DUK_TOK_EOF                               0
3681 
3682 /* identifier names (E5 Section 7.6) */
3683 #define DUK_TOK_IDENTIFIER                        1
3684 
3685 /* reserved words: keywords */
3686 #define DUK_TOK_START_RESERVED                    2
3687 #define DUK_TOK_BREAK                             2
3688 #define DUK_TOK_CASE                              3
3689 #define DUK_TOK_CATCH                             4
3690 #define DUK_TOK_CONTINUE                          5
3691 #define DUK_TOK_DEBUGGER                          6
3692 #define DUK_TOK_DEFAULT                           7
3693 #define DUK_TOK_DELETE                            8
3694 #define DUK_TOK_DO                                9
3695 #define DUK_TOK_ELSE                              10
3696 #define DUK_TOK_FINALLY                           11
3697 #define DUK_TOK_FOR                               12
3698 #define DUK_TOK_FUNCTION                          13
3699 #define DUK_TOK_IF                                14
3700 #define DUK_TOK_IN                                15
3701 #define DUK_TOK_INSTANCEOF                        16
3702 #define DUK_TOK_NEW                               17
3703 #define DUK_TOK_RETURN                            18
3704 #define DUK_TOK_SWITCH                            19
3705 #define DUK_TOK_THIS                              20
3706 #define DUK_TOK_THROW                             21
3707 #define DUK_TOK_TRY                               22
3708 #define DUK_TOK_TYPEOF                            23
3709 #define DUK_TOK_VAR                               24
3710 #define DUK_TOK_CONST                             25
3711 #define DUK_TOK_VOID                              26
3712 #define DUK_TOK_WHILE                             27
3713 #define DUK_TOK_WITH                              28
3714 
3715 /* reserved words: future reserved words */
3716 #define DUK_TOK_CLASS                             29
3717 #define DUK_TOK_ENUM                              30
3718 #define DUK_TOK_EXPORT                            31
3719 #define DUK_TOK_EXTENDS                           32
3720 #define DUK_TOK_IMPORT                            33
3721 #define DUK_TOK_SUPER                             34
3722 
3723 /* "null", "true", and "false" are always reserved words.
3724  * Note that "get" and "set" are not!
3725  */
3726 #define DUK_TOK_NULL                              35
3727 #define DUK_TOK_TRUE                              36
3728 #define DUK_TOK_FALSE                             37
3729 
3730 /* reserved words: additional future reserved words in strict mode */
3731 #define DUK_TOK_START_STRICT_RESERVED             38  /* inclusive */
3732 #define DUK_TOK_IMPLEMENTS                        38
3733 #define DUK_TOK_INTERFACE                         39
3734 #define DUK_TOK_LET                               40
3735 #define DUK_TOK_PACKAGE                           41
3736 #define DUK_TOK_PRIVATE                           42
3737 #define DUK_TOK_PROTECTED                         43
3738 #define DUK_TOK_PUBLIC                            44
3739 #define DUK_TOK_STATIC                            45
3740 #define DUK_TOK_YIELD                             46
3741 
3742 #define DUK_TOK_END_RESERVED                      47  /* exclusive */
3743 
3744 /* "get" and "set" are tokens but NOT ReservedWords.  They are currently
3745  * parsed and identifiers and these defines are actually now unused.
3746  */
3747 #define DUK_TOK_GET                               47
3748 #define DUK_TOK_SET                               48
3749 
3750 /* punctuators (unlike the spec, also includes "/" and "/=") */
3751 #define DUK_TOK_LCURLY                            49
3752 #define DUK_TOK_RCURLY                            50
3753 #define DUK_TOK_LBRACKET                          51
3754 #define DUK_TOK_RBRACKET                          52
3755 #define DUK_TOK_LPAREN                            53
3756 #define DUK_TOK_RPAREN                            54
3757 #define DUK_TOK_PERIOD                            55
3758 #define DUK_TOK_SEMICOLON                         56
3759 #define DUK_TOK_COMMA                             57
3760 #define DUK_TOK_LT                                58
3761 #define DUK_TOK_GT                                59
3762 #define DUK_TOK_LE                                60
3763 #define DUK_TOK_GE                                61
3764 #define DUK_TOK_EQ                                62
3765 #define DUK_TOK_NEQ                               63
3766 #define DUK_TOK_SEQ                               64
3767 #define DUK_TOK_SNEQ                              65
3768 #define DUK_TOK_ADD                               66
3769 #define DUK_TOK_SUB                               67
3770 #define DUK_TOK_MUL                               68
3771 #define DUK_TOK_DIV                               69
3772 #define DUK_TOK_MOD                               70
3773 #define DUK_TOK_EXP                               71
3774 #define DUK_TOK_INCREMENT                         72
3775 #define DUK_TOK_DECREMENT                         73
3776 #define DUK_TOK_ALSHIFT                           74   /* named "arithmetic" because result is signed */
3777 #define DUK_TOK_ARSHIFT                           75
3778 #define DUK_TOK_RSHIFT                            76
3779 #define DUK_TOK_BAND                              77
3780 #define DUK_TOK_BOR                               78
3781 #define DUK_TOK_BXOR                              79
3782 #define DUK_TOK_LNOT                              80
3783 #define DUK_TOK_BNOT                              81
3784 #define DUK_TOK_LAND                              82
3785 #define DUK_TOK_LOR                               83
3786 #define DUK_TOK_QUESTION                          84
3787 #define DUK_TOK_COLON                             85
3788 #define DUK_TOK_EQUALSIGN                         86
3789 #define DUK_TOK_ADD_EQ                            87
3790 #define DUK_TOK_SUB_EQ                            88
3791 #define DUK_TOK_MUL_EQ                            89
3792 #define DUK_TOK_DIV_EQ                            90
3793 #define DUK_TOK_MOD_EQ                            91
3794 #define DUK_TOK_EXP_EQ                            92
3795 #define DUK_TOK_ALSHIFT_EQ                        93
3796 #define DUK_TOK_ARSHIFT_EQ                        94
3797 #define DUK_TOK_RSHIFT_EQ                         95
3798 #define DUK_TOK_BAND_EQ                           96
3799 #define DUK_TOK_BOR_EQ                            97
3800 #define DUK_TOK_BXOR_EQ                           98
3801 
3802 /* literals (E5 Section 7.8), except null, true, false, which are treated
3803  * like reserved words (above).
3804  */
3805 #define DUK_TOK_NUMBER                            99
3806 #define DUK_TOK_STRING                            100
3807 #define DUK_TOK_REGEXP                            101
3808 
3809 #define DUK_TOK_MAXVAL                            101  /* inclusive */
3810 
3811 #define DUK_TOK_INVALID                           DUK_SMALL_UINT_MAX
3812 
3813 /* Convert heap string index to a token (reserved words) */
3814 #define DUK_STRIDX_TO_TOK(x)                        ((x) - DUK_STRIDX_START_RESERVED + DUK_TOK_START_RESERVED)
3815 
3816 /* Sanity check */
3817 #if (DUK_TOK_MAXVAL > 255)
3818 #error DUK_TOK_MAXVAL too large, code assumes it fits into 8 bits
3819 #endif
3820 
3821 /* Sanity checks for string and token defines */
3822 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_BREAK) != DUK_TOK_BREAK)
3823 #error mismatch in token defines
3824 #endif
3825 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CASE) != DUK_TOK_CASE)
3826 #error mismatch in token defines
3827 #endif
3828 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CATCH) != DUK_TOK_CATCH)
3829 #error mismatch in token defines
3830 #endif
3831 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONTINUE) != DUK_TOK_CONTINUE)
3832 #error mismatch in token defines
3833 #endif
3834 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEBUGGER) != DUK_TOK_DEBUGGER)
3835 #error mismatch in token defines
3836 #endif
3837 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEFAULT) != DUK_TOK_DEFAULT)
3838 #error mismatch in token defines
3839 #endif
3840 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DELETE) != DUK_TOK_DELETE)
3841 #error mismatch in token defines
3842 #endif
3843 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DO) != DUK_TOK_DO)
3844 #error mismatch in token defines
3845 #endif
3846 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ELSE) != DUK_TOK_ELSE)
3847 #error mismatch in token defines
3848 #endif
3849 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FINALLY) != DUK_TOK_FINALLY)
3850 #error mismatch in token defines
3851 #endif
3852 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FOR) != DUK_TOK_FOR)
3853 #error mismatch in token defines
3854 #endif
3855 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_FUNCTION) != DUK_TOK_FUNCTION)
3856 #error mismatch in token defines
3857 #endif
3858 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IF) != DUK_TOK_IF)
3859 #error mismatch in token defines
3860 #endif
3861 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IN) != DUK_TOK_IN)
3862 #error mismatch in token defines
3863 #endif
3864 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INSTANCEOF) != DUK_TOK_INSTANCEOF)
3865 #error mismatch in token defines
3866 #endif
3867 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_NEW) != DUK_TOK_NEW)
3868 #error mismatch in token defines
3869 #endif
3870 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_RETURN) != DUK_TOK_RETURN)
3871 #error mismatch in token defines
3872 #endif
3873 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SWITCH) != DUK_TOK_SWITCH)
3874 #error mismatch in token defines
3875 #endif
3876 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THIS) != DUK_TOK_THIS)
3877 #error mismatch in token defines
3878 #endif
3879 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THROW) != DUK_TOK_THROW)
3880 #error mismatch in token defines
3881 #endif
3882 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRY) != DUK_TOK_TRY)
3883 #error mismatch in token defines
3884 #endif
3885 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TYPEOF) != DUK_TOK_TYPEOF)
3886 #error mismatch in token defines
3887 #endif
3888 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VAR) != DUK_TOK_VAR)
3889 #error mismatch in token defines
3890 #endif
3891 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VOID) != DUK_TOK_VOID)
3892 #error mismatch in token defines
3893 #endif
3894 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WHILE) != DUK_TOK_WHILE)
3895 #error mismatch in token defines
3896 #endif
3897 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WITH) != DUK_TOK_WITH)
3898 #error mismatch in token defines
3899 #endif
3900 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CLASS) != DUK_TOK_CLASS)
3901 #error mismatch in token defines
3902 #endif
3903 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONST) != DUK_TOK_CONST)
3904 #error mismatch in token defines
3905 #endif
3906 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ENUM) != DUK_TOK_ENUM)
3907 #error mismatch in token defines
3908 #endif
3909 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXPORT) != DUK_TOK_EXPORT)
3910 #error mismatch in token defines
3911 #endif
3912 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXTENDS) != DUK_TOK_EXTENDS)
3913 #error mismatch in token defines
3914 #endif
3915 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPORT) != DUK_TOK_IMPORT)
3916 #error mismatch in token defines
3917 #endif
3918 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SUPER) != DUK_TOK_SUPER)
3919 #error mismatch in token defines
3920 #endif
3921 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_NULL) != DUK_TOK_NULL)
3922 #error mismatch in token defines
3923 #endif
3924 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRUE) != DUK_TOK_TRUE)
3925 #error mismatch in token defines
3926 #endif
3927 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FALSE) != DUK_TOK_FALSE)
3928 #error mismatch in token defines
3929 #endif
3930 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPLEMENTS) != DUK_TOK_IMPLEMENTS)
3931 #error mismatch in token defines
3932 #endif
3933 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INTERFACE) != DUK_TOK_INTERFACE)
3934 #error mismatch in token defines
3935 #endif
3936 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LET) != DUK_TOK_LET)
3937 #error mismatch in token defines
3938 #endif
3939 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PACKAGE) != DUK_TOK_PACKAGE)
3940 #error mismatch in token defines
3941 #endif
3942 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PRIVATE) != DUK_TOK_PRIVATE)
3943 #error mismatch in token defines
3944 #endif
3945 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PROTECTED) != DUK_TOK_PROTECTED)
3946 #error mismatch in token defines
3947 #endif
3948 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PUBLIC) != DUK_TOK_PUBLIC)
3949 #error mismatch in token defines
3950 #endif
3951 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_STATIC) != DUK_TOK_STATIC)
3952 #error mismatch in token defines
3953 #endif
3954 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_YIELD) != DUK_TOK_YIELD)
3955 #error mismatch in token defines
3956 #endif
3957 
3958 /* Regexp tokens */
3959 #define DUK_RETOK_EOF                              0
3960 #define DUK_RETOK_DISJUNCTION                      1
3961 #define DUK_RETOK_QUANTIFIER                       2
3962 #define DUK_RETOK_ASSERT_START                     3
3963 #define DUK_RETOK_ASSERT_END                       4
3964 #define DUK_RETOK_ASSERT_WORD_BOUNDARY             5
3965 #define DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY         6
3966 #define DUK_RETOK_ASSERT_START_POS_LOOKAHEAD       7
3967 #define DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD       8
3968 #define DUK_RETOK_ATOM_PERIOD                      9
3969 #define DUK_RETOK_ATOM_CHAR                        10
3970 #define DUK_RETOK_ATOM_DIGIT                       11  /* assumptions in regexp compiler */
3971 #define DUK_RETOK_ATOM_NOT_DIGIT                   12  /* -""- */
3972 #define DUK_RETOK_ATOM_WHITE                       13  /* -""- */
3973 #define DUK_RETOK_ATOM_NOT_WHITE                   14  /* -""- */
3974 #define DUK_RETOK_ATOM_WORD_CHAR                   15  /* -""- */
3975 #define DUK_RETOK_ATOM_NOT_WORD_CHAR               16  /* -""- */
3976 #define DUK_RETOK_ATOM_BACKREFERENCE               17
3977 #define DUK_RETOK_ATOM_START_CAPTURE_GROUP         18
3978 #define DUK_RETOK_ATOM_START_NONCAPTURE_GROUP      19
3979 #define DUK_RETOK_ATOM_START_CHARCLASS             20
3980 #define DUK_RETOK_ATOM_START_CHARCLASS_INVERTED    21
3981 #define DUK_RETOK_ATOM_END_GROUP                   22
3982 
3983 /* Constants for duk_lexer_ctx.buf. */
3984 #define DUK_LEXER_TEMP_BUF_LIMIT                   256
3985 
3986 /* A token value.  Can be memcpy()'d, but note that slot1/slot2 values are on the valstack.
3987  * Some fields (like num, str1, str2) are only valid for specific token types and may have
3988  * stale values otherwise.
3989  */
3990 struct duk_token {
3991 	duk_small_uint_t t;           /* token type (with reserved word identification) */
3992 	duk_small_uint_t t_nores;     /* token type (with reserved words as DUK_TOK_IDENTIFER) */
3993 	duk_double_t num;             /* numeric value of token */
3994 	duk_hstring *str1;            /* string 1 of token (borrowed, stored to ctx->slot1_idx) */
3995 	duk_hstring *str2;            /* string 2 of token (borrowed, stored to ctx->slot2_idx) */
3996 	duk_size_t start_offset;      /* start byte offset of token in lexer input */
3997 	duk_int_t start_line;         /* start line of token (first char) */
3998 	duk_int_t num_escapes;        /* number of escapes and line continuations (for directive prologue) */
3999 	duk_bool_t lineterm;          /* token was preceded by a lineterm */
4000 	duk_bool_t allow_auto_semi;   /* token allows automatic semicolon insertion (eof or preceded by newline) */
4001 };
4002 
4003 #define DUK_RE_QUANTIFIER_INFINITE         ((duk_uint32_t) 0xffffffffUL)
4004 
4005 /* A regexp token value. */
4006 struct duk_re_token {
4007 	duk_small_uint_t t;          /* token type */
4008 	duk_small_uint_t greedy;
4009 	duk_uint32_t num;            /* numeric value (character, count) */
4010 	duk_uint32_t qmin;
4011 	duk_uint32_t qmax;
4012 };
4013 
4014 /* A structure for 'snapshotting' a point for rewinding */
4015 struct duk_lexer_point {
4016 	duk_size_t offset;
4017 	duk_int_t line;
4018 };
4019 
4020 /* Lexer codepoint with additional info like offset/line number */
4021 struct duk_lexer_codepoint {
4022 	duk_codepoint_t codepoint;
4023 	duk_size_t offset;
4024 	duk_int_t line;
4025 };
4026 
4027 /* Lexer context.  Same context is used for ECMAScript and Regexp parsing. */
4028 struct duk_lexer_ctx {
4029 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
4030 	duk_lexer_codepoint *window; /* unicode code points, window[0] is always next, points to 'buffer' */
4031 	duk_lexer_codepoint buffer[DUK_LEXER_BUFFER_SIZE];
4032 #else
4033 	duk_lexer_codepoint window[DUK_LEXER_WINDOW_SIZE]; /* unicode code points, window[0] is always next */
4034 #endif
4035 
4036 	duk_hthread *thr;                              /* thread; minimizes argument passing */
4037 
4038 	const duk_uint8_t *input;                      /* input string (may be a user pointer) */
4039 	duk_size_t input_length;                       /* input byte length */
4040 	duk_size_t input_offset;                       /* input offset for window leading edge (not window[0]) */
4041 	duk_int_t input_line;                          /* input linenumber at input_offset (not window[0]), init to 1 */
4042 
4043 	duk_idx_t slot1_idx;                           /* valstack slot for 1st token value */
4044 	duk_idx_t slot2_idx;                           /* valstack slot for 2nd token value */
4045 	duk_idx_t buf_idx;                             /* valstack slot for temp buffer */
4046 	duk_hbuffer_dynamic *buf;                      /* temp accumulation buffer */
4047 	duk_bufwriter_ctx bw;                          /* bufwriter for temp accumulation */
4048 
4049 	duk_int_t token_count;                         /* number of tokens parsed */
4050 	duk_int_t token_limit;                         /* maximum token count before error (sanity backstop) */
4051 
4052 	duk_small_uint_t flags;                        /* lexer flags, use compiler flag defines for now */
4053 };
4054 
4055 /*
4056  *  Prototypes
4057  */
4058 
4059 DUK_INTERNAL_DECL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx);
4060 
4061 DUK_INTERNAL_DECL void duk_lexer_getpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt);
4062 DUK_INTERNAL_DECL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt);
4063 
4064 DUK_INTERNAL_DECL
4065 void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
4066                                       duk_token *out_token,
4067                                       duk_bool_t strict_mode,
4068                                       duk_bool_t regexp_mode);
4069 #if defined(DUK_USE_REGEXP_SUPPORT)
4070 DUK_INTERNAL_DECL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token);
4071 DUK_INTERNAL_DECL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata);
4072 #endif  /* DUK_USE_REGEXP_SUPPORT */
4073 
4074 #endif  /* DUK_LEXER_H_INCLUDED */
4075 /* #include duk_js_compiler.h */
4076 #line 1 "duk_js_compiler.h"
4077 /*
4078  *  ECMAScript compiler.
4079  */
4080 
4081 #if !defined(DUK_JS_COMPILER_H_INCLUDED)
4082 #define DUK_JS_COMPILER_H_INCLUDED
4083 
4084 /* ECMAScript compiler limits */
4085 #define DUK_COMPILER_TOKEN_LIMIT           100000000L  /* 1e8: protects against deeply nested inner functions */
4086 
4087 /* maximum loopcount for peephole optimization */
4088 #define DUK_COMPILER_PEEPHOLE_MAXITER      3
4089 
4090 /* maximum bytecode length in instructions */
4091 #define DUK_COMPILER_MAX_BYTECODE_LENGTH   (256L * 1024L * 1024L)  /* 1 GB */
4092 
4093 /*
4094  *  Compiler intermediate values
4095  *
4096  *  Intermediate values describe either plain values (e.g. strings or
4097  *  numbers) or binary operations which have not yet been coerced into
4098  *  either a left-hand-side or right-hand-side role (e.g. object property).
4099  */
4100 
4101 #define DUK_IVAL_NONE          0   /* no value */
4102 #define DUK_IVAL_PLAIN         1   /* register, constant, or value */
4103 #define DUK_IVAL_ARITH         2   /* binary arithmetic; DUK_OP_ADD, DUK_OP_EQ, other binary ops */
4104 #define DUK_IVAL_PROP          3   /* property access */
4105 #define DUK_IVAL_VAR           4   /* variable access */
4106 
4107 #define DUK_ISPEC_NONE         0   /* no value */
4108 #define DUK_ISPEC_VALUE        1   /* value resides in 'valstack_idx' */
4109 #define DUK_ISPEC_REGCONST     2   /* value resides in a register or constant */
4110 
4111 /* Bit mask which indicates that a regconst is a constant instead of a register.
4112  * Chosen so that when a regconst is cast to duk_int32_t, all consts are
4113  * negative values.
4114  */
4115 #define DUK_REGCONST_CONST_MARKER    DUK_INT32_MIN  /* = -0x80000000 */
4116 
4117 /* Type to represent a reg/const reference during compilation, with <0
4118  * indicating a constant.  Some call sites also use -1 to indicate 'none'.
4119  */
4120 typedef duk_int32_t duk_regconst_t;
4121 
4122 typedef struct {
4123 	duk_small_uint_t t;          /* DUK_ISPEC_XXX */
4124 	duk_regconst_t regconst;
4125 	duk_idx_t valstack_idx;      /* always set; points to a reserved valstack slot */
4126 } duk_ispec;
4127 
4128 typedef struct {
4129 	/*
4130 	 *  PLAIN: x1
4131 	 *  ARITH: x1 <op> x2
4132 	 *  PROP: x1.x2
4133 	 *  VAR: x1 (name)
4134 	 */
4135 
4136 	/* XXX: can be optimized for smaller footprint esp. on 32-bit environments */
4137 	duk_small_uint_t t;          /* DUK_IVAL_XXX */
4138 	duk_small_uint_t op;         /* bytecode opcode for binary ops */
4139 	duk_ispec x1;
4140 	duk_ispec x2;
4141 } duk_ivalue;
4142 
4143 /*
4144  *  Bytecode instruction representation during compilation
4145  *
4146  *  Contains the actual instruction and (optionally) debug info.
4147  */
4148 
4149 struct duk_compiler_instr {
4150 	duk_instr_t ins;
4151 #if defined(DUK_USE_PC2LINE)
4152 	duk_uint32_t line;
4153 #endif
4154 };
4155 
4156 /*
4157  *  Compiler state
4158  */
4159 
4160 #define DUK_LABEL_FLAG_ALLOW_BREAK       (1U << 0)
4161 #define DUK_LABEL_FLAG_ALLOW_CONTINUE    (1U << 1)
4162 
4163 #define DUK_DECL_TYPE_VAR                0
4164 #define DUK_DECL_TYPE_FUNC               1
4165 
4166 /* XXX: optimize to 16 bytes */
4167 typedef struct {
4168 	duk_small_uint_t flags;
4169 	duk_int_t label_id;          /* numeric label_id (-1 reserved as marker) */
4170 	duk_hstring *h_label;        /* borrowed label name */
4171 	duk_int_t catch_depth;       /* catch depth at point of definition */
4172 	duk_int_t pc_label;          /* pc of label statement:
4173 	                              * pc+1: break jump site
4174 	                              * pc+2: continue jump site
4175 	                              */
4176 
4177 	/* Fast jumps (which avoid longjmp) jump directly to the jump sites
4178 	 * which are always known even while the iteration/switch statement
4179 	 * is still being parsed.  A final peephole pass "straightens out"
4180 	 * the jumps.
4181 	 */
4182 } duk_labelinfo;
4183 
4184 /* Compiling state of one function, eventually converted to duk_hcompfunc */
4185 struct duk_compiler_func {
4186 	/* These pointers are at the start of the struct so that they pack
4187 	 * nicely.  Mixing pointers and integer values is bad on some
4188 	 * platforms (e.g. if int is 32 bits and pointers are 64 bits).
4189 	 */
4190 
4191 	duk_bufwriter_ctx bw_code;          /* bufwriter for code */
4192 
4193 	duk_hstring *h_name;                /* function name (borrowed reference), ends up in _name */
4194 	/* h_code: held in bw_code */
4195 	duk_hobject *h_consts;              /* array */
4196 	duk_hobject *h_funcs;               /* array of function templates: [func1, offset1, line1, func2, offset2, line2]
4197 	                                     * offset/line points to closing brace to allow skipping on pass 2
4198 	                                     */
4199 	duk_hobject *h_decls;               /* array of declarations: [ name1, val1, name2, val2, ... ]
4200 	                                     * valN = (typeN) | (fnum << 8), where fnum is inner func number (0 for vars)
4201 	                                     * record function and variable declarations in pass 1
4202 	                                     */
4203 	duk_hobject *h_labelnames;          /* array of active label names */
4204 	duk_hbuffer_dynamic *h_labelinfos;  /* C array of duk_labelinfo */
4205 	duk_hobject *h_argnames;            /* array of formal argument names (-> _Formals) */
4206 	duk_hobject *h_varmap;              /* variable map for pass 2 (identifier -> register number or null (unmapped)) */
4207 
4208 	/* Value stack indices for tracking objects. */
4209 	/* code_idx: not needed */
4210 	duk_idx_t consts_idx;
4211 	duk_idx_t funcs_idx;
4212 	duk_idx_t decls_idx;
4213 	duk_idx_t labelnames_idx;
4214 	duk_idx_t labelinfos_idx;
4215 	duk_idx_t argnames_idx;
4216 	duk_idx_t varmap_idx;
4217 
4218 	/* Temp reg handling. */
4219 	duk_regconst_t temp_first;           /* first register that is a temporary (below: variables) */
4220 	duk_regconst_t temp_next;            /* next temporary register to allocate */
4221 	duk_regconst_t temp_max;             /* highest value of temp_reg (temp_max - 1 is highest used reg) */
4222 
4223 	/* Shuffle registers if large number of regs/consts. */
4224 	duk_regconst_t shuffle1;
4225 	duk_regconst_t shuffle2;
4226 	duk_regconst_t shuffle3;
4227 
4228 	/* Stats for current expression being parsed. */
4229 	duk_int_t nud_count;
4230 	duk_int_t led_count;
4231 	duk_int_t paren_level;              /* parenthesis count, 0 = top level */
4232 	duk_bool_t expr_lhs;                /* expression is left-hand-side compatible */
4233 	duk_bool_t allow_in;                /* current paren level allows 'in' token */
4234 
4235 	/* Misc. */
4236 	duk_int_t stmt_next;                /* statement id allocation (running counter) */
4237 	duk_int_t label_next;               /* label id allocation (running counter) */
4238 	duk_int_t catch_depth;              /* catch stack depth */
4239 	duk_int_t with_depth;               /* with stack depth (affects identifier lookups) */
4240 	duk_int_t fnum_next;                /* inner function numbering */
4241 	duk_int_t num_formals;              /* number of formal arguments */
4242 	duk_regconst_t reg_stmt_value;      /* register for writing value of 'non-empty' statements (global or eval code), -1 is marker */
4243 #if defined(DUK_USE_DEBUGGER_SUPPORT)
4244 	duk_int_t min_line;                 /* XXX: typing (duk_hcompfunc has duk_uint32_t) */
4245 	duk_int_t max_line;
4246 #endif
4247 
4248 	/* Status booleans. */
4249 	duk_uint8_t is_function;             /* is an actual function (not global/eval code) */
4250 	duk_uint8_t is_eval;                 /* is eval code */
4251 	duk_uint8_t is_global;               /* is global code */
4252 	duk_uint8_t is_namebinding;          /* needs a name binding */
4253 	duk_uint8_t is_constructable;        /* result is constructable */
4254 	duk_uint8_t is_setget;               /* is a setter/getter */
4255 	duk_uint8_t is_strict;               /* function is strict */
4256 	duk_uint8_t is_notail;               /* function must not be tail called */
4257 	duk_uint8_t in_directive_prologue;   /* parsing in "directive prologue", recognize directives */
4258 	duk_uint8_t in_scanning;             /* parsing in "scanning" phase (first pass) */
4259 	duk_uint8_t may_direct_eval;         /* function may call direct eval */
4260 	duk_uint8_t id_access_arguments;     /* function refers to 'arguments' identifier */
4261 	duk_uint8_t id_access_slow;          /* function makes one or more slow path accesses that won't match own static variables */
4262 	duk_uint8_t id_access_slow_own;      /* function makes one or more slow path accesses that may match own static variables */
4263 	duk_uint8_t is_arguments_shadowed;   /* argument/function declaration shadows 'arguments' */
4264 	duk_uint8_t needs_shuffle;           /* function needs shuffle registers */
4265 	duk_uint8_t reject_regexp_in_adv;    /* reject RegExp literal on next advance() call; needed for handling IdentifierName productions */
4266 	duk_uint8_t allow_regexp_in_adv;     /* allow RegExp literal on next advance() call */
4267 };
4268 
4269 struct duk_compiler_ctx {
4270 	duk_hthread *thr;
4271 
4272 	/* filename being compiled (ends up in functions' '_filename' property) */
4273 	duk_hstring *h_filename;            /* borrowed reference */
4274 
4275 	/* lexing (tokenization) state (contains two valstack slot indices) */
4276 	duk_lexer_ctx lex;
4277 
4278 	/* current and previous token for parsing */
4279 	duk_token prev_token;
4280 	duk_token curr_token;
4281 	duk_idx_t tok11_idx;                /* curr_token slot1 (matches 'lex' slot1_idx) */
4282 	duk_idx_t tok12_idx;                /* curr_token slot2 (matches 'lex' slot2_idx) */
4283 	duk_idx_t tok21_idx;                /* prev_token slot1 */
4284 	duk_idx_t tok22_idx;                /* prev_token slot2 */
4285 
4286 	/* recursion limit */
4287 	duk_int_t recursion_depth;
4288 	duk_int_t recursion_limit;
4289 
4290 	/* code emission temporary */
4291 	duk_int_t emit_jumpslot_pc;
4292 
4293 	/* current function being compiled (embedded instead of pointer for more compact access) */
4294 	duk_compiler_func curr_func;
4295 };
4296 
4297 /*
4298  *  Prototypes
4299  */
4300 
4301 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);
4302 
4303 #endif  /* DUK_JS_COMPILER_H_INCLUDED */
4304 /* #include duk_regexp.h */
4305 #line 1 "duk_regexp.h"
4306 /*
4307  *  Regular expression structs, constants, and bytecode defines.
4308  */
4309 
4310 #if !defined(DUK_REGEXP_H_INCLUDED)
4311 #define DUK_REGEXP_H_INCLUDED
4312 
4313 /* maximum bytecode copies for {n,m} quantifiers */
4314 #define DUK_RE_MAX_ATOM_COPIES             1000
4315 
4316 /* regexp compilation limits */
4317 #define DUK_RE_COMPILE_TOKEN_LIMIT         100000000L   /* 1e8 */
4318 
4319 /* regexp execution limits */
4320 #define DUK_RE_EXECUTE_STEPS_LIMIT         1000000000L  /* 1e9 */
4321 
4322 /* regexp opcodes */
4323 #define DUK_REOP_MATCH                     1
4324 #define DUK_REOP_CHAR                      2
4325 #define DUK_REOP_PERIOD                    3
4326 #define DUK_REOP_RANGES                    4
4327 #define DUK_REOP_INVRANGES                 5
4328 #define DUK_REOP_JUMP                      6
4329 #define DUK_REOP_SPLIT1                    7
4330 #define DUK_REOP_SPLIT2                    8
4331 #define DUK_REOP_SQMINIMAL                 9
4332 #define DUK_REOP_SQGREEDY                  10
4333 #define DUK_REOP_SAVE                      11
4334 #define DUK_REOP_WIPERANGE                 12
4335 #define DUK_REOP_LOOKPOS                   13
4336 #define DUK_REOP_LOOKNEG                   14
4337 #define DUK_REOP_BACKREFERENCE             15
4338 #define DUK_REOP_ASSERT_START              16
4339 #define DUK_REOP_ASSERT_END                17
4340 #define DUK_REOP_ASSERT_WORD_BOUNDARY      18
4341 #define DUK_REOP_ASSERT_NOT_WORD_BOUNDARY  19
4342 
4343 /* flags */
4344 #define DUK_RE_FLAG_GLOBAL                 (1U << 0)
4345 #define DUK_RE_FLAG_IGNORE_CASE            (1U << 1)
4346 #define DUK_RE_FLAG_MULTILINE              (1U << 2)
4347 
4348 struct duk_re_matcher_ctx {
4349 	duk_hthread *thr;
4350 
4351 	duk_uint32_t re_flags;
4352 	const duk_uint8_t *input;
4353 	const duk_uint8_t *input_end;
4354 	const duk_uint8_t *bytecode;
4355 	const duk_uint8_t *bytecode_end;
4356 	const duk_uint8_t **saved;  /* allocated from valstack (fixed buffer) */
4357 	duk_uint32_t nsaved;
4358 	duk_uint32_t recursion_depth;
4359 	duk_uint32_t recursion_limit;
4360 	duk_uint32_t steps_count;
4361 	duk_uint32_t steps_limit;
4362 };
4363 
4364 struct duk_re_compiler_ctx {
4365 	duk_hthread *thr;
4366 
4367 	duk_uint32_t re_flags;
4368 	duk_lexer_ctx lex;
4369 	duk_re_token curr_token;
4370 	duk_bufwriter_ctx bw;
4371 	duk_uint32_t captures;  /* highest capture number emitted so far (used as: ++captures) */
4372 	duk_uint32_t highest_backref;
4373 	duk_uint32_t recursion_depth;
4374 	duk_uint32_t recursion_limit;
4375 	duk_uint32_t nranges;  /* internal temporary value, used for char classes */
4376 };
4377 
4378 /*
4379  *  Prototypes
4380  */
4381 
4382 #if defined(DUK_USE_REGEXP_SUPPORT)
4383 DUK_INTERNAL_DECL void duk_regexp_compile(duk_hthread *thr);
4384 DUK_INTERNAL_DECL void duk_regexp_create_instance(duk_hthread *thr);
4385 DUK_INTERNAL_DECL void duk_regexp_match(duk_hthread *thr);
4386 DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr);  /* hacky helper for String.prototype.split() */
4387 #endif
4388 
4389 #endif  /* DUK_REGEXP_H_INCLUDED */
4390 /* #include duk_heaphdr.h */
4391 #line 1 "duk_heaphdr.h"
4392 /*
4393  *  Heap header definition and assorted macros, including ref counting.
4394  *  Access all fields through the accessor macros.
4395  */
4396 
4397 #if !defined(DUK_HEAPHDR_H_INCLUDED)
4398 #define DUK_HEAPHDR_H_INCLUDED
4399 
4400 /*
4401  *  Common heap header
4402  *
4403  *  All heap objects share the same flags and refcount fields.  Objects other
4404  *  than strings also need to have a single or double linked list pointers
4405  *  for insertion into the "heap allocated" list.  Strings have single linked
4406  *  list pointers for string table chaining.
4407  *
4408  *  Technically, 'h_refcount' must be wide enough to guarantee that it cannot
4409  *  wrap; otherwise objects might be freed incorrectly after wrapping.  The
4410  *  default refcount field is 32 bits even on 64-bit systems: while that's in
4411  *  theory incorrect, the Duktape heap needs to be larger than 64GB for the
4412  *  count to actually wrap (assuming 16-byte duk_tvals).  This is very unlikely
4413  *  to ever be an issue, but if it is, disabling DUK_USE_REFCOUNT32 causes
4414  *  Duktape to use size_t for refcounts which should always be safe.
4415  *
4416  *  Heap header size on 32-bit platforms: 8 bytes without reference counting,
4417  *  16 bytes with reference counting.
4418  *
4419  *  Note that 'raw' macros such as DUK_HEAPHDR_GET_REFCOUNT() are not
4420  *  defined without DUK_USE_REFERENCE_COUNTING, so caller must #if defined()
4421  *  around them.
4422  */
4423 
4424 /* XXX: macro for shared header fields (avoids some padding issues) */
4425 
4426 struct duk_heaphdr {
4427 	duk_uint32_t h_flags;
4428 
4429 #if defined(DUK_USE_REFERENCE_COUNTING)
4430 #if defined(DUK_USE_ASSERTIONS)
4431 	/* When assertions enabled, used by mark-and-sweep for refcount
4432 	 * validation.  Largest reasonable type; also detects overflows.
4433 	 */
4434 	duk_size_t h_assert_refcount;
4435 #endif
4436 #if defined(DUK_USE_REFCOUNT16)
4437 	duk_uint16_t h_refcount;
4438 #elif defined(DUK_USE_REFCOUNT32)
4439 	duk_uint32_t h_refcount;
4440 #else
4441 	duk_size_t h_refcount;
4442 #endif
4443 #endif  /* DUK_USE_REFERENCE_COUNTING */
4444 
4445 #if defined(DUK_USE_HEAPPTR16)
4446 	duk_uint16_t h_next16;
4447 #else
4448 	duk_heaphdr *h_next;
4449 #endif
4450 
4451 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
4452 	/* refcounting requires direct heap frees, which in turn requires a dual linked heap */
4453 #if defined(DUK_USE_HEAPPTR16)
4454 	duk_uint16_t h_prev16;
4455 #else
4456 	duk_heaphdr *h_prev;
4457 #endif
4458 #endif
4459 
4460 	/* When DUK_USE_HEAPPTR16 (and DUK_USE_REFCOUNT16) is in use, the
4461 	 * struct won't align nicely to 4 bytes.  This 16-bit extra field
4462 	 * is added to make the alignment clean; the field can be used by
4463 	 * heap objects when 16-bit packing is used.  This field is now
4464 	 * conditional to DUK_USE_HEAPPTR16 only, but it is intended to be
4465 	 * used with DUK_USE_REFCOUNT16 and DUK_USE_DOUBLE_LINKED_HEAP;
4466 	 * this only matter to low memory environments anyway.
4467 	 */
4468 #if defined(DUK_USE_HEAPPTR16)
4469 	duk_uint16_t h_extra16;
4470 #endif
4471 };
4472 
4473 struct duk_heaphdr_string {
4474 	/* 16 bits would be enough for shared heaphdr flags and duk_hstring
4475 	 * flags.  The initial parts of duk_heaphdr_string and duk_heaphdr
4476 	 * must match so changing the flags field size here would be quite
4477 	 * awkward.  However, to minimize struct size, we can pack at least
4478 	 * 16 bits of duk_hstring data into the flags field.
4479 	 */
4480 	duk_uint32_t h_flags;
4481 
4482 #if defined(DUK_USE_REFERENCE_COUNTING)
4483 #if defined(DUK_USE_ASSERTIONS)
4484 	/* When assertions enabled, used by mark-and-sweep for refcount
4485 	 * validation.  Largest reasonable type; also detects overflows.
4486 	 */
4487 	duk_size_t h_assert_refcount;
4488 #endif
4489 #if defined(DUK_USE_REFCOUNT16)
4490 	duk_uint16_t h_refcount;
4491 	duk_uint16_t h_strextra16;  /* round out to 8 bytes */
4492 #elif defined(DUK_USE_REFCOUNT32)
4493 	duk_uint32_t h_refcount;
4494 #else
4495 	duk_size_t h_refcount;
4496 #endif
4497 #else
4498 	duk_uint16_t h_strextra16;
4499 #endif  /* DUK_USE_REFERENCE_COUNTING */
4500 
4501 	duk_hstring *h_next;
4502 	/* No 'h_prev' pointer for strings. */
4503 };
4504 
4505 #define DUK_HEAPHDR_FLAGS_TYPE_MASK      0x00000003UL
4506 #define DUK_HEAPHDR_FLAGS_FLAG_MASK      (~DUK_HEAPHDR_FLAGS_TYPE_MASK)
4507 
4508                                              /* 2 bits for heap type */
4509 #define DUK_HEAPHDR_FLAGS_HEAP_START     2   /* 5 heap flags */
4510 #define DUK_HEAPHDR_FLAGS_USER_START     7   /* 25 user flags */
4511 
4512 #define DUK_HEAPHDR_HEAP_FLAG_NUMBER(n)  (DUK_HEAPHDR_FLAGS_HEAP_START + (n))
4513 #define DUK_HEAPHDR_USER_FLAG_NUMBER(n)  (DUK_HEAPHDR_FLAGS_USER_START + (n))
4514 #define DUK_HEAPHDR_HEAP_FLAG(n)         (1UL << (DUK_HEAPHDR_FLAGS_HEAP_START + (n)))
4515 #define DUK_HEAPHDR_USER_FLAG(n)         (1UL << (DUK_HEAPHDR_FLAGS_USER_START + (n)))
4516 
4517 #define DUK_HEAPHDR_FLAG_REACHABLE       DUK_HEAPHDR_HEAP_FLAG(0)  /* mark-and-sweep: reachable */
4518 #define DUK_HEAPHDR_FLAG_TEMPROOT        DUK_HEAPHDR_HEAP_FLAG(1)  /* mark-and-sweep: children not processed */
4519 #define DUK_HEAPHDR_FLAG_FINALIZABLE     DUK_HEAPHDR_HEAP_FLAG(2)  /* mark-and-sweep: finalizable (on current pass) */
4520 #define DUK_HEAPHDR_FLAG_FINALIZED       DUK_HEAPHDR_HEAP_FLAG(3)  /* mark-and-sweep: finalized (on previous pass) */
4521 #define DUK_HEAPHDR_FLAG_READONLY        DUK_HEAPHDR_HEAP_FLAG(4)  /* read-only object, in code section */
4522 
4523 #define DUK_HTYPE_MIN                    0
4524 #define DUK_HTYPE_STRING                 0
4525 #define DUK_HTYPE_OBJECT                 1
4526 #define DUK_HTYPE_BUFFER                 2
4527 #define DUK_HTYPE_MAX                    2
4528 
4529 #if defined(DUK_USE_HEAPPTR16)
4530 #define DUK_HEAPHDR_GET_NEXT(heap,h) \
4531 	((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_next16))
4532 #define DUK_HEAPHDR_SET_NEXT(heap,h,val)   do { \
4533 		(h)->h_next16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) val); \
4534 	} while (0)
4535 #else
4536 #define DUK_HEAPHDR_GET_NEXT(heap,h)  ((h)->h_next)
4537 #define DUK_HEAPHDR_SET_NEXT(heap,h,val)   do { \
4538 		(h)->h_next = (val); \
4539 	} while (0)
4540 #endif
4541 
4542 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
4543 #if defined(DUK_USE_HEAPPTR16)
4544 #define DUK_HEAPHDR_GET_PREV(heap,h) \
4545 	((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_prev16))
4546 #define DUK_HEAPHDR_SET_PREV(heap,h,val)   do { \
4547 		(h)->h_prev16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (val)); \
4548 	} while (0)
4549 #else
4550 #define DUK_HEAPHDR_GET_PREV(heap,h)       ((h)->h_prev)
4551 #define DUK_HEAPHDR_SET_PREV(heap,h,val)   do { \
4552 		(h)->h_prev = (val); \
4553 	} while (0)
4554 #endif
4555 #endif
4556 
4557 #if defined(DUK_USE_REFERENCE_COUNTING)
4558 #define DUK_HEAPHDR_GET_REFCOUNT(h)   ((h)->h_refcount)
4559 #define DUK_HEAPHDR_SET_REFCOUNT(h,val)  do { \
4560 		(h)->h_refcount = (val); \
4561 		DUK_ASSERT((h)->h_refcount == (val));  /* No truncation. */ \
4562 	} while (0)
4563 #define DUK_HEAPHDR_PREINC_REFCOUNT(h)  (++(h)->h_refcount)  /* result: updated refcount */
4564 #define DUK_HEAPHDR_PREDEC_REFCOUNT(h)  (--(h)->h_refcount)  /* result: updated refcount */
4565 #else
4566 /* refcount macros not defined without refcounting, caller must #if defined() now */
4567 #endif  /* DUK_USE_REFERENCE_COUNTING */
4568 
4569 /*
4570  *  Note: type is treated as a field separate from flags, so some masking is
4571  *  involved in the macros below.
4572  */
4573 
4574 #define DUK_HEAPHDR_GET_FLAGS_RAW(h)  ((h)->h_flags)
4575 #define DUK_HEAPHDR_SET_FLAGS_RAW(h,val)  do { \
4576 		(h)->h_flags = (val); } \
4577 	}
4578 #define DUK_HEAPHDR_GET_FLAGS(h)      ((h)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK)
4579 #define DUK_HEAPHDR_SET_FLAGS(h,val)  do { \
4580 		(h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) | (val); \
4581 	} while (0)
4582 #define DUK_HEAPHDR_GET_TYPE(h)       ((h)->h_flags & DUK_HEAPHDR_FLAGS_TYPE_MASK)
4583 #define DUK_HEAPHDR_SET_TYPE(h,val)   do { \
4584 		(h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_TYPE_MASK)) | (val); \
4585 	} while (0)
4586 
4587 /* Comparison for type >= DUK_HTYPE_MIN skipped; because DUK_HTYPE_MIN is zero
4588  * and the comparison is unsigned, it's always true and generates warnings.
4589  */
4590 #define DUK_HEAPHDR_HTYPE_VALID(h)    ( \
4591 	DUK_HEAPHDR_GET_TYPE((h)) <= DUK_HTYPE_MAX \
4592 	)
4593 
4594 #define DUK_HEAPHDR_SET_TYPE_AND_FLAGS(h,tval,fval)  do { \
4595 		(h)->h_flags = ((tval) & DUK_HEAPHDR_FLAGS_TYPE_MASK) | \
4596 		               ((fval) & DUK_HEAPHDR_FLAGS_FLAG_MASK); \
4597 	} while (0)
4598 
4599 #define DUK_HEAPHDR_SET_FLAG_BITS(h,bits)  do { \
4600 		DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
4601 		(h)->h_flags |= (bits); \
4602 	} while (0)
4603 
4604 #define DUK_HEAPHDR_CLEAR_FLAG_BITS(h,bits)  do { \
4605 		DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
4606 		(h)->h_flags &= ~((bits)); \
4607 	} while (0)
4608 
4609 #define DUK_HEAPHDR_CHECK_FLAG_BITS(h,bits)  (((h)->h_flags & (bits)) != 0)
4610 
4611 #define DUK_HEAPHDR_SET_REACHABLE(h)      DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
4612 #define DUK_HEAPHDR_CLEAR_REACHABLE(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
4613 #define DUK_HEAPHDR_HAS_REACHABLE(h)      DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
4614 
4615 #define DUK_HEAPHDR_SET_TEMPROOT(h)       DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
4616 #define DUK_HEAPHDR_CLEAR_TEMPROOT(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
4617 #define DUK_HEAPHDR_HAS_TEMPROOT(h)       DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
4618 
4619 #define DUK_HEAPHDR_SET_FINALIZABLE(h)    DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
4620 #define DUK_HEAPHDR_CLEAR_FINALIZABLE(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
4621 #define DUK_HEAPHDR_HAS_FINALIZABLE(h)    DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
4622 
4623 #define DUK_HEAPHDR_SET_FINALIZED(h)      DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
4624 #define DUK_HEAPHDR_CLEAR_FINALIZED(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
4625 #define DUK_HEAPHDR_HAS_FINALIZED(h)      DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
4626 
4627 #define DUK_HEAPHDR_SET_READONLY(h)       DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
4628 #define DUK_HEAPHDR_CLEAR_READONLY(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
4629 #define DUK_HEAPHDR_HAS_READONLY(h)       DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
4630 
4631 /* get or set a range of flags; m=first bit number, n=number of bits */
4632 #define DUK_HEAPHDR_GET_FLAG_RANGE(h,m,n)  (((h)->h_flags >> (m)) & ((1UL << (n)) - 1UL))
4633 
4634 #define DUK_HEAPHDR_SET_FLAG_RANGE(h,m,n,v)  do { \
4635 		(h)->h_flags = \
4636 			((h)->h_flags & (~(((1UL << (n)) - 1UL) << (m)))) \
4637 			| ((v) << (m)); \
4638 	} while (0)
4639 
4640 /* init pointer fields to null */
4641 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
4642 #define DUK_HEAPHDR_INIT_NULLS(h)       do { \
4643 		DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
4644 		DUK_HEAPHDR_SET_PREV((h), (void *) NULL); \
4645 	} while (0)
4646 #else
4647 #define DUK_HEAPHDR_INIT_NULLS(h)       do { \
4648 		DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
4649 	} while (0)
4650 #endif
4651 
4652 #define DUK_HEAPHDR_STRING_INIT_NULLS(h)  do { \
4653 		(h)->h_next = NULL; \
4654 	} while (0)
4655 
4656 /*
4657  *  Type tests
4658  */
4659 
4660 /* Take advantage of the fact that for DUK_HTYPE_xxx numbers the lowest bit
4661  * is only set for DUK_HTYPE_OBJECT (= 1).
4662  */
4663 #if 0
4664 #define DUK_HEAPHDR_IS_OBJECT(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_OBJECT)
4665 #endif
4666 #define DUK_HEAPHDR_IS_OBJECT(h) ((h)->h_flags & 0x01UL)
4667 #define DUK_HEAPHDR_IS_STRING(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_STRING)
4668 #define DUK_HEAPHDR_IS_BUFFER(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_BUFFER)
4669 
4670 /*
4671  *  Assert helpers
4672  */
4673 
4674 /* Check that prev/next links are consistent: if e.g. h->prev is != NULL,
4675  * h->prev->next should point back to h.
4676  */
4677 #if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_ASSERTIONS)
4678 #define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do { \
4679 		if ((h) != NULL) { \
4680 			duk_heaphdr *h__prev, *h__next; \
4681 			h__prev = DUK_HEAPHDR_GET_PREV((heap), (h)); \
4682 			h__next = DUK_HEAPHDR_GET_NEXT((heap), (h)); \
4683 			DUK_ASSERT(h__prev == NULL || (DUK_HEAPHDR_GET_NEXT((heap), h__prev) == (h))); \
4684 			DUK_ASSERT(h__next == NULL || (DUK_HEAPHDR_GET_PREV((heap), h__next) == (h))); \
4685 		} \
4686 	} while (0)
4687 #else
4688 #define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do {} while (0)
4689 #endif
4690 
4691 #define DUK_ASSERT_HEAPHDR_VALID(h) do { \
4692 		DUK_ASSERT((h) != NULL); \
4693 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID((h))); \
4694 	} while (0)
4695 
4696 #endif  /* DUK_HEAPHDR_H_INCLUDED */
4697 /* #include duk_refcount.h */
4698 #line 1 "duk_refcount.h"
4699 /*
4700  *  Reference counting helper macros.  The macros take a thread argument
4701  *  and must thus always be executed in a specific thread context.  The
4702  *  thread argument is not really needed anymore: DECREF can operate with
4703  *  a heap pointer only, and INCREF needs neither.
4704  */
4705 
4706 #if !defined(DUK_REFCOUNT_H_INCLUDED)
4707 #define DUK_REFCOUNT_H_INCLUDED
4708 
4709 #if defined(DUK_USE_REFERENCE_COUNTING)
4710 
4711 #if defined(DUK_USE_ROM_OBJECTS)
4712 /* With ROM objects "needs refcount update" is true when the value is
4713  * heap allocated and is not a ROM object.
4714  */
4715 /* XXX: double evaluation for 'tv' argument. */
4716 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) \
4717 	(DUK_TVAL_IS_HEAP_ALLOCATED((tv)) && !DUK_HEAPHDR_HAS_READONLY(DUK_TVAL_GET_HEAPHDR((tv))))
4718 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)  (!DUK_HEAPHDR_HAS_READONLY((h)))
4719 #else  /* DUK_USE_ROM_OBJECTS */
4720 /* Without ROM objects "needs refcount update" == is heap allocated. */
4721 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)    DUK_TVAL_IS_HEAP_ALLOCATED((tv))
4722 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)  1
4723 #endif  /* DUK_USE_ROM_OBJECTS */
4724 
4725 /* Fast variants, inline refcount operations except for refzero handling.
4726  * Can be used explicitly when speed is always more important than size.
4727  * For a good compiler and a single file build, these are basically the
4728  * same as a forced inline.
4729  */
4730 #define DUK_TVAL_INCREF_FAST(thr,tv) do { \
4731 		duk_tval *duk__tv = (tv); \
4732 		DUK_ASSERT(duk__tv != NULL); \
4733 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
4734 			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
4735 			DUK_ASSERT(duk__h != NULL); \
4736 			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4737 			DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
4738 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0);  /* No wrapping. */ \
4739 		} \
4740 	} while (0)
4741 #define DUK_TVAL_DECREF_FAST(thr,tv) do { \
4742 		duk_tval *duk__tv = (tv); \
4743 		DUK_ASSERT(duk__tv != NULL); \
4744 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
4745 			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
4746 			DUK_ASSERT(duk__h != NULL); \
4747 			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4748 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4749 			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4750 				duk_heaphdr_refzero((thr), duk__h); \
4751 			} \
4752 		} \
4753 	} while (0)
4754 #define DUK_TVAL_DECREF_NORZ_FAST(thr,tv) do { \
4755 		duk_tval *duk__tv = (tv); \
4756 		DUK_ASSERT(duk__tv != NULL); \
4757 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
4758 			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
4759 			DUK_ASSERT(duk__h != NULL); \
4760 			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4761 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4762 			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4763 				duk_heaphdr_refzero_norz((thr), duk__h); \
4764 			} \
4765 		} \
4766 	} while (0)
4767 #define DUK_HEAPHDR_INCREF_FAST(thr,h) do { \
4768 		duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
4769 		DUK_ASSERT(duk__h != NULL); \
4770 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4771 		if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
4772 			DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
4773 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0);  /* No wrapping. */ \
4774 		} \
4775 	} while (0)
4776 #define DUK_HEAPHDR_DECREF_FAST_RAW(thr,h,rzcall,rzcast) do { \
4777 		duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
4778 		DUK_ASSERT(duk__h != NULL); \
4779 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4780 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4781 		if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
4782 			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4783 				(rzcall)((thr), (rzcast) duk__h); \
4784 			} \
4785 		} \
4786 	} while (0)
4787 #define DUK_HEAPHDR_DECREF_FAST(thr,h) \
4788 	DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero,duk_heaphdr *)
4789 #define DUK_HEAPHDR_DECREF_NORZ_FAST(thr,h) \
4790 	DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero_norz,duk_heaphdr *)
4791 
4792 /* Slow variants, call to a helper to reduce code size.
4793  * Can be used explicitly when size is always more important than speed.
4794  */
4795 #define DUK_TVAL_INCREF_SLOW(thr,tv)         do { duk_tval_incref((tv)); } while (0)
4796 #define DUK_TVAL_DECREF_SLOW(thr,tv)         do { duk_tval_decref((thr), (tv)); } while (0)
4797 #define DUK_TVAL_DECREF_NORZ_SLOW(thr,tv)    do { duk_tval_decref_norz((thr), (tv)); } while (0)
4798 #define DUK_HEAPHDR_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4799 #define DUK_HEAPHDR_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4800 #define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4801 #define DUK_HSTRING_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4802 #define DUK_HSTRING_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4803 #define DUK_HSTRING_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4804 #define DUK_HBUFFER_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4805 #define DUK_HBUFFER_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4806 #define DUK_HBUFFER_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4807 #define DUK_HOBJECT_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4808 #define DUK_HOBJECT_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4809 #define DUK_HOBJECT_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4810 
4811 /* Default variants.  Selection depends on speed/size preference.
4812  * Concretely: with gcc 4.8.1 -Os x64 the difference in final binary
4813  * is about +1kB for _FAST variants.
4814  */
4815 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
4816 /* XXX: It would be nice to specialize for specific duk_hobject subtypes
4817  * but current refzero queue handling prevents that.
4818  */
4819 #define DUK_TVAL_INCREF(thr,tv)                DUK_TVAL_INCREF_FAST((thr),(tv))
4820 #define DUK_TVAL_DECREF(thr,tv)                DUK_TVAL_DECREF_FAST((thr),(tv))
4821 #define DUK_TVAL_DECREF_NORZ(thr,tv)           DUK_TVAL_DECREF_NORZ_FAST((thr),(tv))
4822 #define DUK_HEAPHDR_INCREF(thr,h)              DUK_HEAPHDR_INCREF_FAST((thr),(h))
4823 #define DUK_HEAPHDR_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero,duk_heaphdr *)
4824 #define DUK_HEAPHDR_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero_norz,duk_heaphdr *)
4825 #define DUK_HSTRING_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4826 #define DUK_HSTRING_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hstring_refzero,duk_hstring *)
4827 #define DUK_HSTRING_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hstring_refzero,duk_hstring *)  /* no 'norz' variant */
4828 #define DUK_HOBJECT_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4829 #define DUK_HOBJECT_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4830 #define DUK_HOBJECT_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4831 #define DUK_HBUFFER_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4832 #define DUK_HBUFFER_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hbuffer_refzero,duk_hbuffer *)
4833 #define DUK_HBUFFER_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hbuffer_refzero,duk_hbuffer *)  /* no 'norz' variant */
4834 #define DUK_HCOMPFUNC_INCREF(thr,h)            DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4835 #define DUK_HCOMPFUNC_DECREF(thr,h)            DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4836 #define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4837 #define DUK_HNATFUNC_INCREF(thr,h)             DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4838 #define DUK_HNATFUNC_DECREF(thr,h)             DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4839 #define DUK_HNATFUNC_DECREF_NORZ(thr,h)        DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4840 #define DUK_HBUFOBJ_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4841 #define DUK_HBUFOBJ_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4842 #define DUK_HBUFOBJ_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4843 #define DUK_HTHREAD_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4844 #define DUK_HTHREAD_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4845 #define DUK_HTHREAD_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4846 #else
4847 #define DUK_TVAL_INCREF(thr,tv)                DUK_TVAL_INCREF_SLOW((thr),(tv))
4848 #define DUK_TVAL_DECREF(thr,tv)                DUK_TVAL_DECREF_SLOW((thr),(tv))
4849 #define DUK_TVAL_DECREF_NORZ(thr,tv)           DUK_TVAL_DECREF_NORZ_SLOW((thr),(tv))
4850 #define DUK_HEAPHDR_INCREF(thr,h)              DUK_HEAPHDR_INCREF_SLOW((thr),(h))
4851 #define DUK_HEAPHDR_DECREF(thr,h)              DUK_HEAPHDR_DECREF_SLOW((thr),(h))
4852 #define DUK_HEAPHDR_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_NORZ_SLOW((thr),(h))
4853 #define DUK_HSTRING_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4854 #define DUK_HSTRING_DECREF(thr,h)              DUK_HSTRING_DECREF_SLOW((thr),(h))
4855 #define DUK_HSTRING_DECREF_NORZ(thr,h)         DUK_HSTRING_DECREF_NORZ_SLOW((thr),(h))
4856 #define DUK_HOBJECT_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4857 #define DUK_HOBJECT_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(h))
4858 #define DUK_HOBJECT_DECREF_NORZ(thr,h)         DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(h))
4859 #define DUK_HBUFFER_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4860 #define DUK_HBUFFER_DECREF(thr,h)              DUK_HBUFFER_DECREF_SLOW((thr),(h))
4861 #define DUK_HBUFFER_DECREF_NORZ(thr,h)         DUK_HBUFFER_DECREF_NORZ_SLOW((thr),(h))
4862 #define DUK_HCOMPFUNC_INCREF(thr,h)            DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4863 #define DUK_HCOMPFUNC_DECREF(thr,h)            DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4864 #define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4865 #define DUK_HNATFUNC_INCREF(thr,h)             DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4866 #define DUK_HNATFUNC_DECREF(thr,h)             DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4867 #define DUK_HNATFUNC_DECREF_NORZ(thr,h)        DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4868 #define DUK_HBUFOBJ_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4869 #define DUK_HBUFOBJ_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4870 #define DUK_HBUFOB_DECREF_NORZ(thr,h)          DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4871 #define DUK_HTHREAD_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4872 #define DUK_HTHREAD_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4873 #define DUK_HTHREAD_DECREF_NORZ(thr,h)         DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4874 #endif
4875 
4876 /* Convenience for some situations; the above macros don't allow NULLs
4877  * for performance reasons.  Macros cover only actually needed cases.
4878  */
4879 #define DUK_HEAPHDR_INCREF_ALLOWNULL(thr,h) do { \
4880 		if ((h) != NULL) { \
4881 			DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h)); \
4882 		} \
4883 	} while (0)
4884 #define DUK_HEAPHDR_DECREF_ALLOWNULL(thr,h) do { \
4885 		if ((h) != NULL) { \
4886 			DUK_HEAPHDR_DECREF((thr), (duk_heaphdr *) (h)); \
4887 		} \
4888 	} while (0)
4889 #define DUK_HEAPHDR_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4890 		if ((h) != NULL) { \
4891 			DUK_HEAPHDR_DECREF_NORZ((thr), (duk_heaphdr *) (h)); \
4892 		} \
4893 	} while (0)
4894 #define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do { \
4895 		if ((h) != NULL) { \
4896 			DUK_HOBJECT_INCREF((thr), (h)); \
4897 		} \
4898 	} while (0)
4899 #define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do { \
4900 		if ((h) != NULL) { \
4901 			DUK_HOBJECT_DECREF((thr), (h)); \
4902 		} \
4903 	} while (0)
4904 #define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4905 		if ((h) != NULL) { \
4906 			DUK_HOBJECT_DECREF_NORZ((thr), (h)); \
4907 		} \
4908 	} while (0)
4909 #define DUK_HBUFFER_INCREF_ALLOWNULL(thr,h) do { \
4910 		if ((h) != NULL) { \
4911 			DUK_HBUFFER_INCREF((thr), (h)); \
4912 		} \
4913 	} while (0)
4914 #define DUK_HBUFFER_DECREF_ALLOWNULL(thr,h) do { \
4915 		if ((h) != NULL) { \
4916 			DUK_HBUFFER_DECREF((thr), (h)); \
4917 		} \
4918 	} while (0)
4919 #define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4920 		if ((h) != NULL) { \
4921 			DUK_HBUFFER_DECREF_NORZ((thr), (h)); \
4922 		} \
4923 	} while (0)
4924 #define DUK_HTHREAD_INCREF_ALLOWNULL(thr,h) do { \
4925 		if ((h) != NULL) { \
4926 			DUK_HTHREAD_INCREF((thr), (h)); \
4927 		} \
4928 	} while (0)
4929 #define DUK_HTHREAD_DECREF_ALLOWNULL(thr,h) do { \
4930 		if ((h) != NULL) { \
4931 			DUK_HTHREAD_DECREF((thr), (h)); \
4932 		} \
4933 	} while (0)
4934 #define DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4935 		if ((h) != NULL) { \
4936 			DUK_HTHREAD_DECREF_NORZ((thr), (h)); \
4937 		} \
4938 	} while (0)
4939 
4940 /* Called after one or more DECREF NORZ calls to handle pending side effects.
4941  * At present DECREF NORZ does freeing inline but doesn't execute finalizers,
4942  * so these macros check for pending finalizers and execute them.  The FAST
4943  * variant is performance critical.
4944  */
4945 #if defined(DUK_USE_FINALIZER_SUPPORT)
4946 #define DUK_REFZERO_CHECK_FAST(thr) do { \
4947 		duk_refzero_check_fast((thr)); \
4948 	} while (0)
4949 #define DUK_REFZERO_CHECK_SLOW(thr) do { \
4950 		duk_refzero_check_slow((thr)); \
4951 	} while (0)
4952 #else  /* DUK_USE_FINALIZER_SUPPORT */
4953 #define DUK_REFZERO_CHECK_FAST(thr) do { } while (0)
4954 #define DUK_REFZERO_CHECK_SLOW(thr) do { } while (0)
4955 #endif  /* DUK_USE_FINALIZER_SUPPORT */
4956 
4957 /*
4958  *  Macros to set a duk_tval and update refcount of the target (decref the
4959  *  old value and incref the new value if necessary).  This is both performance
4960  *  and footprint critical; any changes made should be measured for size/speed.
4961  */
4962 
4963 #define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
4964 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4965 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4966 		DUK_TVAL_SET_UNDEFINED(tv__dst); \
4967 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
4968 	} while (0)
4969 
4970 #define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0(thr,tvptr_dst) do { \
4971 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4972 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4973 		DUK_TVAL_SET_UNDEFINED(tv__dst); \
4974 		DUK_TVAL_DECREF_NORZ((thr), &tv__tmp); \
4975 	} while (0)
4976 
4977 #define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
4978 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4979 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4980 		DUK_TVAL_SET_UNUSED(tv__dst); \
4981 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
4982 	} while (0)
4983 
4984 #define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
4985 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4986 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4987 		DUK_TVAL_SET_NULL(tv__dst); \
4988 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
4989 	} while (0)
4990 
4991 #define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4992 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4993 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4994 		DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
4995 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
4996 	} while (0)
4997 
4998 #define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4999 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5000 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5001 		DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
5002 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5003 	} while (0)
5004 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5005 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5006 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5007 		DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \
5008 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5009 	} while (0)
5010 #define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5011 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5012 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5013 		DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
5014 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5015 	} while (0)
5016 #define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
5017 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5018 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5019 		DUK_TVAL_SET_NAN(tv__dst); \
5020 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5021 	} while (0)
5022 #if defined(DUK_USE_FASTINT)
5023 #define DUK_TVAL_SET_I48_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5024 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5025 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5026 		DUK_TVAL_SET_I48(tv__dst, (newval)); \
5027 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5028 	} while (0)
5029 #define DUK_TVAL_SET_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5030 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5031 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5032 		DUK_TVAL_SET_I32(tv__dst, (newval)); \
5033 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5034 	} while (0)
5035 #define DUK_TVAL_SET_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5036 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5037 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5038 		DUK_TVAL_SET_U32(tv__dst, (newval)); \
5039 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5040 	} while (0)
5041 #else
5042 #define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
5043 	DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
5044 #endif  /* DUK_USE_FASTINT */
5045 
5046 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
5047 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5048 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5049 		DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
5050 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5051 	} while (0)
5052 
5053 #define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5054 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5055 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5056 		DUK_TVAL_SET_STRING(tv__dst, (newval)); \
5057 		DUK_HSTRING_INCREF((thr), (newval)); \
5058 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5059 	} while (0)
5060 
5061 #define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5062 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5063 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5064 		DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
5065 		DUK_HOBJECT_INCREF((thr), (newval)); \
5066 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5067 	} while (0)
5068 
5069 #define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5070 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5071 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5072 		DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
5073 		DUK_HBUFFER_INCREF((thr), (newval)); \
5074 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5075 	} while (0)
5076 
5077 #define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5078 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5079 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5080 		DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
5081 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5082 	} while (0)
5083 
5084 /* DUK_TVAL_SET_TVAL_UPDREF() is used a lot in executor, property lookups,
5085  * etc, so it's very important for performance.  Measure when changing.
5086  *
5087  * NOTE: the source and destination duk_tval pointers may be the same, and
5088  * the macros MUST deal with that correctly.
5089  */
5090 
5091 /* Original idiom used, minimal code size. */
5092 #define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
5093 		duk_tval *tv__dst, *tv__src; duk_tval tv__tmp; \
5094 		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
5095 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5096 		DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5097 		DUK_TVAL_INCREF((thr), tv__src); \
5098 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5099 	} while (0)
5100 
5101 /* Faster alternative: avoid making a temporary copy of tvptr_dst and use
5102  * fast incref/decref macros.
5103  */
5104 #define DUK_TVAL_SET_TVAL_UPDREF_ALT1(thr,tvptr_dst,tvptr_src) do { \
5105 		duk_tval *tv__dst, *tv__src; duk_heaphdr *h__obj; \
5106 		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
5107 		DUK_TVAL_INCREF_FAST((thr), tv__src); \
5108 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv__dst)) { \
5109 			h__obj = DUK_TVAL_GET_HEAPHDR(tv__dst); \
5110 			DUK_ASSERT(h__obj != NULL); \
5111 			DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5112 			DUK_HEAPHDR_DECREF_FAST((thr), h__obj);  /* side effects */ \
5113 		} else { \
5114 			DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5115 		} \
5116 	} while (0)
5117 
5118 /* XXX: no optimized variants yet */
5119 #define DUK_TVAL_SET_UNDEFINED_UPDREF         DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
5120 #define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ    DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0
5121 #define DUK_TVAL_SET_UNUSED_UPDREF            DUK_TVAL_SET_UNUSED_UPDREF_ALT0
5122 #define DUK_TVAL_SET_NULL_UPDREF              DUK_TVAL_SET_NULL_UPDREF_ALT0
5123 #define DUK_TVAL_SET_BOOLEAN_UPDREF           DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
5124 #define DUK_TVAL_SET_NUMBER_UPDREF            DUK_TVAL_SET_NUMBER_UPDREF_ALT0
5125 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF    DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
5126 #define DUK_TVAL_SET_DOUBLE_UPDREF            DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
5127 #define DUK_TVAL_SET_NAN_UPDREF               DUK_TVAL_SET_NAN_UPDREF_ALT0
5128 #if defined(DUK_USE_FASTINT)
5129 #define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_I48_UPDREF_ALT0
5130 #define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_I32_UPDREF_ALT0
5131 #define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_U32_UPDREF_ALT0
5132 #else
5133 #define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF  /* XXX: fast int-to-double */
5134 #define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5135 #define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5136 #endif  /* DUK_USE_FASTINT */
5137 #define DUK_TVAL_SET_FASTINT_UPDREF           DUK_TVAL_SET_I48_UPDREF  /* convenience */
5138 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF         DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
5139 #define DUK_TVAL_SET_STRING_UPDREF            DUK_TVAL_SET_STRING_UPDREF_ALT0
5140 #define DUK_TVAL_SET_OBJECT_UPDREF            DUK_TVAL_SET_OBJECT_UPDREF_ALT0
5141 #define DUK_TVAL_SET_BUFFER_UPDREF            DUK_TVAL_SET_BUFFER_UPDREF_ALT0
5142 #define DUK_TVAL_SET_POINTER_UPDREF           DUK_TVAL_SET_POINTER_UPDREF_ALT0
5143 
5144 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
5145 /* Optimized for speed. */
5146 #define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT1
5147 #define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT1
5148 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5149 #else
5150 /* Optimized for size. */
5151 #define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT0
5152 #define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5153 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5154 #endif
5155 
5156 #else  /* DUK_USE_REFERENCE_COUNTING */
5157 
5158 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)     0
5159 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)   0
5160 
5161 #define DUK_TVAL_INCREF_FAST(thr,v)            do {} while (0) /* nop */
5162 #define DUK_TVAL_DECREF_FAST(thr,v)            do {} while (0) /* nop */
5163 #define DUK_TVAL_DECREF_NORZ_FAST(thr,v)       do {} while (0) /* nop */
5164 #define DUK_TVAL_INCREF_SLOW(thr,v)            do {} while (0) /* nop */
5165 #define DUK_TVAL_DECREF_SLOW(thr,v)            do {} while (0) /* nop */
5166 #define DUK_TVAL_DECREF_NORZ_SLOW(thr,v)       do {} while (0) /* nop */
5167 #define DUK_TVAL_INCREF(thr,v)                 do {} while (0) /* nop */
5168 #define DUK_TVAL_DECREF(thr,v)                 do {} while (0) /* nop */
5169 #define DUK_TVAL_DECREF_NORZ(thr,v)            do {} while (0) /* nop */
5170 #define DUK_HEAPHDR_INCREF_FAST(thr,h)         do {} while (0) /* nop */
5171 #define DUK_HEAPHDR_DECREF_FAST(thr,h)         do {} while (0) /* nop */
5172 #define DUK_HEAPHDR_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
5173 #define DUK_HEAPHDR_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
5174 #define DUK_HEAPHDR_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
5175 #define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
5176 #define DUK_HEAPHDR_INCREF(thr,h)              do {} while (0) /* nop */
5177 #define DUK_HEAPHDR_DECREF(thr,h)              do {} while (0) /* nop */
5178 #define DUK_HEAPHDR_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5179 #define DUK_HSTRING_INCREF_FAST(thr,h)         do {} while (0) /* nop */
5180 #define DUK_HSTRING_DECREF_FAST(thr,h)         do {} while (0) /* nop */
5181 #define DUK_HSTRING_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
5182 #define DUK_HSTRING_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
5183 #define DUK_HSTRING_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
5184 #define DUK_HSTRING_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
5185 #define DUK_HSTRING_INCREF(thr,h)              do {} while (0) /* nop */
5186 #define DUK_HSTRING_DECREF(thr,h)              do {} while (0) /* nop */
5187 #define DUK_HSTRING_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5188 #define DUK_HOBJECT_INCREF_FAST(thr,h)         do {} while (0) /* nop */
5189 #define DUK_HOBJECT_DECREF_FAST(thr,h)         do {} while (0) /* nop */
5190 #define DUK_HOBJECT_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
5191 #define DUK_HOBJECT_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
5192 #define DUK_HOBJECT_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
5193 #define DUK_HOBJECT_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
5194 #define DUK_HOBJECT_INCREF(thr,h)              do {} while (0) /* nop */
5195 #define DUK_HOBJECT_DECREF(thr,h)              do {} while (0) /* nop */
5196 #define DUK_HOBJECT_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5197 #define DUK_HBUFFER_INCREF_FAST(thr,h)         do {} while (0) /* nop */
5198 #define DUK_HBUFFER_DECREF_FAST(thr,h)         do {} while (0) /* nop */
5199 #define DUK_HBUFFER_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
5200 #define DUK_HBUFFER_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
5201 #define DUK_HBUFFER_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
5202 #define DUK_HBUFFER_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
5203 #define DUK_HBUFFER_INCREF(thr,h)              do {} while (0) /* nop */
5204 #define DUK_HBUFFER_DECREF(thr,h)              do {} while (0) /* nop */
5205 #define DUK_HBUFFER_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5206 
5207 #define DUK_HCOMPFUNC_INCREF(thr,h)            do {} while (0) /* nop */
5208 #define DUK_HCOMPFUNC_DECREF(thr,h)            do {} while (0) /* nop */
5209 #define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       do {} while (0) /* nop */
5210 #define DUK_HNATFUNC_INCREF(thr,h)             do {} while (0) /* nop */
5211 #define DUK_HNATFUNC_DECREF(thr,h)             do {} while (0) /* nop */
5212 #define DUK_HNATFUNC_DECREF_NORZ(thr,h)        do {} while (0) /* nop */
5213 #define DUK_HBUFOBJ_INCREF(thr,h)              do {} while (0) /* nop */
5214 #define DUK_HBUFOBJ_DECREF(thr,h)              do {} while (0) /* nop */
5215 #define DUK_HBUFOBJ_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5216 #define DUK_HTHREAD_INCREF(thr,h)              do {} while (0) /* nop */
5217 #define DUK_HTHREAD_DECREF(thr,h)              do {} while (0) /* nop */
5218 #define DUK_HTHREAD_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5219 #define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
5220 #define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
5221 #define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr,h)  do {} while (0) /* nop */
5222 #define DUK_HBUFFER_INCREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
5223 #define DUK_HBUFFER_DECREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
5224 #define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr,h)  do {} while (0) /* nop */
5225 
5226 #define DUK_REFZERO_CHECK_FAST(thr)            do {} while (0) /* nop */
5227 #define DUK_REFZERO_CHECK_SLOW(thr)            do {} while (0) /* nop */
5228 
5229 #define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
5230 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5231 		DUK_TVAL_SET_UNDEFINED(tv__dst); \
5232 		DUK_UNREF((thr)); \
5233 	} while (0)
5234 
5235 #define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
5236 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5237 		DUK_TVAL_SET_UNUSED(tv__dst); \
5238 		DUK_UNREF((thr)); \
5239 	} while (0)
5240 
5241 #define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
5242 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5243 		DUK_TVAL_SET_NULL(tv__dst); \
5244 		DUK_UNREF((thr)); \
5245 	} while (0)
5246 
5247 #define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5248 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5249 		DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
5250 		DUK_UNREF((thr)); \
5251 	} while (0)
5252 
5253 #define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5254 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5255 		DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
5256 		DUK_UNREF((thr)); \
5257 	} while (0)
5258 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5259 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5260 		DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \
5261 		DUK_UNREF((thr)); \
5262 	} while (0)
5263 #define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5264 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5265 		DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
5266 		DUK_UNREF((thr)); \
5267 	} while (0)
5268 #define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
5269 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5270 		DUK_TVAL_SET_NAN(tv__dst); \
5271 		DUK_UNREF((thr)); \
5272 	} while (0)
5273 #if defined(DUK_USE_FASTINT)
5274 #define DUK_TVAL_SET_I48_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5275 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5276 		DUK_TVAL_SET_I48(tv__dst, (newval)); \
5277 		DUK_UNREF((thr)); \
5278 	} while (0)
5279 #define DUK_TVAL_SET_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5280 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5281 		DUK_TVAL_SET_I32(tv__dst, (newval)); \
5282 		DUK_UNREF((thr)); \
5283 	} while (0)
5284 #define DUK_TVAL_SET_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5285 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5286 		DUK_TVAL_SET_U32(tv__dst, (newval)); \
5287 		DUK_UNREF((thr)); \
5288 	} while (0)
5289 #else
5290 #define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
5291 	DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
5292 #endif  /* DUK_USE_FASTINT */
5293 
5294 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
5295 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5296 		DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
5297 		DUK_UNREF((thr)); \
5298 	} while (0)
5299 
5300 #define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5301 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5302 		DUK_TVAL_SET_STRING(tv__dst, (newval)); \
5303 		DUK_UNREF((thr)); \
5304 	} while (0)
5305 
5306 #define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5307 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5308 		DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
5309 		DUK_UNREF((thr)); \
5310 	} while (0)
5311 
5312 #define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5313 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5314 		DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
5315 		DUK_UNREF((thr)); \
5316 	} while (0)
5317 
5318 #define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5319 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5320 		DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
5321 		DUK_UNREF((thr)); \
5322 	} while (0)
5323 
5324 #define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
5325 		duk_tval *tv__dst, *tv__src; \
5326 		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
5327 		DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5328 		DUK_UNREF((thr)); \
5329 	} while (0)
5330 
5331 #define DUK_TVAL_SET_UNDEFINED_UPDREF         DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
5332 #define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ    DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
5333 #define DUK_TVAL_SET_UNUSED_UPDREF            DUK_TVAL_SET_UNUSED_UPDREF_ALT0
5334 #define DUK_TVAL_SET_NULL_UPDREF              DUK_TVAL_SET_NULL_UPDREF_ALT0
5335 #define DUK_TVAL_SET_BOOLEAN_UPDREF           DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
5336 #define DUK_TVAL_SET_NUMBER_UPDREF            DUK_TVAL_SET_NUMBER_UPDREF_ALT0
5337 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF    DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
5338 #define DUK_TVAL_SET_DOUBLE_UPDREF            DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
5339 #define DUK_TVAL_SET_NAN_UPDREF               DUK_TVAL_SET_NAN_UPDREF_ALT0
5340 #if defined(DUK_USE_FASTINT)
5341 #define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_I48_UPDREF_ALT0
5342 #define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_I32_UPDREF_ALT0
5343 #define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_U32_UPDREF_ALT0
5344 #else
5345 #define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF  /* XXX: fast-int-to-double */
5346 #define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5347 #define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5348 #endif  /* DUK_USE_FASTINT */
5349 #define DUK_TVAL_SET_FASTINT_UPDREF           DUK_TVAL_SET_I48_UPDREF  /* convenience */
5350 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF         DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
5351 #define DUK_TVAL_SET_STRING_UPDREF            DUK_TVAL_SET_STRING_UPDREF_ALT0
5352 #define DUK_TVAL_SET_OBJECT_UPDREF            DUK_TVAL_SET_OBJECT_UPDREF_ALT0
5353 #define DUK_TVAL_SET_BUFFER_UPDREF            DUK_TVAL_SET_BUFFER_UPDREF_ALT0
5354 #define DUK_TVAL_SET_POINTER_UPDREF           DUK_TVAL_SET_POINTER_UPDREF_ALT0
5355 
5356 #define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT0
5357 #define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5358 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5359 
5360 #endif  /* DUK_USE_REFERENCE_COUNTING */
5361 
5362 /*
5363  *  Some convenience macros that don't have optimized implementations now.
5364  */
5365 
5366 #define DUK_TVAL_SET_TVAL_UPDREF_NORZ(thr,tv_dst,tv_src) do { \
5367 		duk_hthread *duk__thr = (thr); \
5368 		duk_tval *duk__dst = (tv_dst); \
5369 		duk_tval *duk__src = (tv_src); \
5370 		DUK_UNREF(duk__thr); \
5371 		DUK_TVAL_DECREF_NORZ(thr, duk__dst); \
5372 		DUK_TVAL_SET_TVAL(duk__dst, duk__src); \
5373 		DUK_TVAL_INCREF(thr, duk__dst); \
5374 	} while (0)
5375 
5376 #define DUK_TVAL_SET_U32_UPDREF_NORZ(thr,tv_dst,val) do { \
5377 		duk_hthread *duk__thr = (thr); \
5378 		duk_tval *duk__dst = (tv_dst); \
5379 		duk_uint32_t duk__val = (duk_uint32_t) (val); \
5380 		DUK_UNREF(duk__thr); \
5381 		DUK_TVAL_DECREF_NORZ(thr, duk__dst); \
5382 		DUK_TVAL_SET_U32(duk__dst, duk__val); \
5383 	} while (0)
5384 
5385 /*
5386  *  Prototypes
5387  */
5388 
5389 #if defined(DUK_USE_REFERENCE_COUNTING)
5390 #if defined(DUK_USE_FINALIZER_SUPPORT)
5391 DUK_INTERNAL_DECL void duk_refzero_check_slow(duk_hthread *thr);
5392 DUK_INTERNAL_DECL void duk_refzero_check_fast(duk_hthread *thr);
5393 #endif
5394 DUK_INTERNAL_DECL void duk_heaphdr_refcount_finalize_norz(duk_heap *heap, duk_heaphdr *hdr);
5395 DUK_INTERNAL_DECL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject *h);
5396 #if 0  /* Not needed: fast path handles inline; slow path uses duk_heaphdr_decref() which is needed anyway. */
5397 DUK_INTERNAL_DECL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h);
5398 DUK_INTERNAL_DECL void duk_hstring_decref_norz(duk_hthread *thr, duk_hstring *h);
5399 DUK_INTERNAL_DECL void duk_hbuffer_decref(duk_hthread *thr, duk_hbuffer *h);
5400 DUK_INTERNAL_DECL void duk_hbuffer_decref_norz(duk_hthread *thr, duk_hbuffer *h);
5401 DUK_INTERNAL_DECL void duk_hobject_decref(duk_hthread *thr, duk_hobject *h);
5402 DUK_INTERNAL_DECL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h);
5403 #endif
5404 DUK_INTERNAL_DECL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h);
5405 DUK_INTERNAL_DECL void duk_heaphdr_refzero_norz(duk_hthread *thr, duk_heaphdr *h);
5406 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
5407 DUK_INTERNAL_DECL void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h);  /* no 'norz' variant */
5408 DUK_INTERNAL_DECL void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h);  /* no 'norz' variant */
5409 DUK_INTERNAL_DECL void duk_hobject_refzero(duk_hthread *thr, duk_hobject *h);
5410 DUK_INTERNAL_DECL void duk_hobject_refzero_norz(duk_hthread *thr, duk_hobject *h);
5411 #else
5412 DUK_INTERNAL_DECL void duk_tval_incref(duk_tval *tv);
5413 DUK_INTERNAL_DECL void duk_tval_decref(duk_hthread *thr, duk_tval *tv);
5414 DUK_INTERNAL_DECL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv);
5415 DUK_INTERNAL_DECL void duk_heaphdr_incref(duk_heaphdr *h);
5416 DUK_INTERNAL_DECL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h);
5417 DUK_INTERNAL_DECL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h);
5418 #endif
5419 #else  /* DUK_USE_REFERENCE_COUNTING */
5420 /* no refcounting */
5421 #endif  /* DUK_USE_REFERENCE_COUNTING */
5422 
5423 #endif  /* DUK_REFCOUNT_H_INCLUDED */
5424 /* #include duk_api_internal.h */
5425 #line 1 "duk_api_internal.h"
5426 /*
5427  *  Internal API calls which have (stack and other) semantics similar
5428  *  to the public API.
5429  */
5430 
5431 #if !defined(DUK_API_INTERNAL_H_INCLUDED)
5432 #define DUK_API_INTERNAL_H_INCLUDED
5433 
5434 #define DUK_INTERNAL_SYMBOL(x)     ("\x82" x)
5435 
5436 /* duk_push_sprintf constants */
5437 #define DUK_PUSH_SPRINTF_INITIAL_SIZE  256L
5438 #define DUK_PUSH_SPRINTF_SANITY_LIMIT  (1L * 1024L * 1024L * 1024L)
5439 
5440 /* Flag ORed to err_code to indicate __FILE__ / __LINE__ is not
5441  * blamed as source of error for error fileName / lineNumber.
5442  */
5443 #define DUK_ERRCODE_FLAG_NOBLAME_FILELINE  (1L << 24)
5444 
5445 /* Current convention is to use duk_size_t for value stack sizes and global indices,
5446  * and duk_idx_t for local frame indices.
5447  */
5448 DUK_INTERNAL_DECL void duk_valstack_grow_check_throw(duk_hthread *thr, duk_size_t min_bytes);
5449 DUK_INTERNAL_DECL duk_bool_t duk_valstack_grow_check_nothrow(duk_hthread *thr, duk_size_t min_bytes);
5450 DUK_INTERNAL_DECL void duk_valstack_shrink_check_nothrow(duk_hthread *thr, duk_bool_t snug);
5451 
5452 DUK_INTERNAL_DECL void duk_copy_tvals_incref(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_size_t count);
5453 
5454 DUK_INTERNAL_DECL duk_tval *duk_reserve_gap(duk_hthread *thr, duk_idx_t idx_base, duk_idx_t count);
5455 
5456 DUK_INTERNAL_DECL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx);
5457 DUK_INTERNAL_DECL void duk_set_top_and_wipe(duk_hthread *thr, duk_idx_t top, duk_idx_t idx_wipe_start);
5458 
5459 DUK_INTERNAL_DECL void duk_dup_0(duk_hthread *thr);
5460 DUK_INTERNAL_DECL void duk_dup_1(duk_hthread *thr);
5461 DUK_INTERNAL_DECL void duk_dup_2(duk_hthread *thr);
5462 /* duk_dup_m1() would be same as duk_dup_top() */
5463 DUK_INTERNAL_DECL void duk_dup_m2(duk_hthread *thr);
5464 DUK_INTERNAL_DECL void duk_dup_m3(duk_hthread *thr);
5465 DUK_INTERNAL_DECL void duk_dup_m4(duk_hthread *thr);
5466 
5467 DUK_INTERNAL_DECL void duk_remove_unsafe(duk_hthread *thr, duk_idx_t idx);
5468 DUK_INTERNAL_DECL void duk_remove_m2(duk_hthread *thr);
5469 DUK_INTERNAL_DECL void duk_remove_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);
5470 DUK_INTERNAL_DECL void duk_remove_n_unsafe(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);
5471 
5472 DUK_INTERNAL_DECL duk_int_t duk_get_type_tval(duk_tval *tv);
5473 DUK_INTERNAL_DECL duk_uint_t duk_get_type_mask_tval(duk_tval *tv);
5474 
5475 #if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
5476 DUK_INTERNAL_DECL const char *duk_get_type_name(duk_hthread *thr, duk_idx_t idx);
5477 #endif
5478 DUK_INTERNAL_DECL duk_small_uint_t duk_get_class_number(duk_hthread *thr, duk_idx_t idx);
5479 
5480 DUK_INTERNAL_DECL duk_tval *duk_get_tval(duk_hthread *thr, duk_idx_t idx);
5481 DUK_INTERNAL_DECL duk_tval *duk_get_tval_or_unused(duk_hthread *thr, duk_idx_t idx);
5482 DUK_INTERNAL_DECL duk_tval *duk_require_tval(duk_hthread *thr, duk_idx_t idx);
5483 DUK_INTERNAL_DECL void duk_push_tval(duk_hthread *thr, duk_tval *tv);
5484 
5485 /* Push the current 'this' binding; throw TypeError if binding is not object
5486  * coercible (CheckObjectCoercible).
5487  */
5488 DUK_INTERNAL_DECL void duk_push_this_check_object_coercible(duk_hthread *thr);
5489 
5490 /* duk_push_this() + CheckObjectCoercible() + duk_to_object() */
5491 DUK_INTERNAL_DECL duk_hobject *duk_push_this_coercible_to_object(duk_hthread *thr);
5492 
5493 /* duk_push_this() + CheckObjectCoercible() + duk_to_string() */
5494 DUK_INTERNAL_DECL duk_hstring *duk_push_this_coercible_to_string(duk_hthread *thr);
5495 
5496 DUK_INTERNAL_DECL duk_hstring *duk_push_uint_to_hstring(duk_hthread *thr, duk_uint_t i);
5497 
5498 /* Get a borrowed duk_tval pointer to the current 'this' binding.  Caller must
5499  * make sure there's an active callstack entry.  Note that the returned pointer
5500  * is unstable with regards to side effects.
5501  */
5502 DUK_INTERNAL_DECL duk_tval *duk_get_borrowed_this_tval(duk_hthread *thr);
5503 
5504 /* XXX: add fastint support? */
5505 #define duk_push_u64(thr,val) \
5506 	duk_push_number((thr), (duk_double_t) (val))
5507 #define duk_push_i64(thr,val) \
5508 	duk_push_number((thr), (duk_double_t) (val))
5509 
5510 /* duk_push_(u)int() is guaranteed to support at least (un)signed 32-bit range */
5511 #define duk_push_u32(thr,val) \
5512 	duk_push_uint((thr), (duk_uint_t) (val))
5513 #define duk_push_i32(thr,val) \
5514 	duk_push_int((thr), (duk_int_t) (val))
5515 
5516 /* sometimes stack and array indices need to go on the stack */
5517 #define duk_push_idx(thr,val) \
5518 	duk_push_int((thr), (duk_int_t) (val))
5519 #define duk_push_uarridx(thr,val) \
5520 	duk_push_uint((thr), (duk_uint_t) (val))
5521 #define duk_push_size_t(thr,val) \
5522 	duk_push_uint((thr), (duk_uint_t) (val))  /* XXX: assumed to fit for now */
5523 
5524 DUK_INTERNAL_DECL duk_bool_t duk_is_string_notsymbol(duk_hthread *thr, duk_idx_t idx);
5525 
5526 DUK_INTERNAL_DECL duk_bool_t duk_is_callable_tval(duk_hthread *thr, duk_tval *tv);
5527 
5528 DUK_INTERNAL_DECL duk_hstring *duk_get_hstring(duk_hthread *thr, duk_idx_t idx);
5529 DUK_INTERNAL_DECL duk_hstring *duk_get_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx);
5530 DUK_INTERNAL_DECL const char *duk_get_string_notsymbol(duk_hthread *thr, duk_idx_t idx);
5531 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject(duk_hthread *thr, duk_idx_t idx);
5532 DUK_INTERNAL_DECL duk_hbuffer *duk_get_hbuffer(duk_hthread *thr, duk_idx_t idx);
5533 DUK_INTERNAL_DECL duk_hthread *duk_get_hthread(duk_hthread *thr, duk_idx_t idx);
5534 DUK_INTERNAL_DECL duk_hcompfunc *duk_get_hcompfunc(duk_hthread *thr, duk_idx_t idx);
5535 DUK_INTERNAL_DECL duk_hnatfunc *duk_get_hnatfunc(duk_hthread *thr, duk_idx_t idx);
5536 
5537 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);
5538 
5539 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum);
5540 
5541 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
5542 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
5543 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_accept_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
5544 #define duk_require_hobject_promote_lfunc(thr,idx) \
5545 	duk_require_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC)
5546 #define duk_get_hobject_promote_lfunc(thr,idx) \
5547 	duk_get_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC)
5548 
5549 #if 0  /*unused*/
5550 DUK_INTERNAL_DECL void *duk_get_voidptr(duk_hthread *thr, duk_idx_t idx);
5551 #endif
5552 
5553 DUK_INTERNAL_DECL duk_hstring *duk_known_hstring(duk_hthread *thr, duk_idx_t idx);
5554 DUK_INTERNAL_DECL duk_hobject *duk_known_hobject(duk_hthread *thr, duk_idx_t idx);
5555 DUK_INTERNAL_DECL duk_hbuffer *duk_known_hbuffer(duk_hthread *thr, duk_idx_t idx);
5556 DUK_INTERNAL_DECL duk_hcompfunc *duk_known_hcompfunc(duk_hthread *thr, duk_idx_t idx);
5557 DUK_INTERNAL_DECL duk_hnatfunc *duk_known_hnatfunc(duk_hthread *thr, duk_idx_t idx);
5558 
5559 DUK_INTERNAL_DECL duk_double_t duk_to_number_tval(duk_hthread *thr, duk_tval *tv);
5560 
5561 DUK_INTERNAL_DECL duk_hstring *duk_to_hstring(duk_hthread *thr, duk_idx_t idx);
5562 DUK_INTERNAL_DECL duk_hstring *duk_to_hstring_m1(duk_hthread *thr);
5563 DUK_INTERNAL_DECL duk_hstring *duk_to_hstring_acceptsymbol(duk_hthread *thr, duk_idx_t idx);
5564 
5565 DUK_INTERNAL_DECL duk_hobject *duk_to_hobject(duk_hthread *thr, duk_idx_t idx);
5566 
5567 DUK_INTERNAL_DECL duk_double_t duk_to_number_m1(duk_hthread *thr);
5568 DUK_INTERNAL_DECL duk_double_t duk_to_number_m2(duk_hthread *thr);
5569 
5570 DUK_INTERNAL_DECL duk_bool_t duk_to_boolean_top_pop(duk_hthread *thr);
5571 
5572 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* only needed by debugger for now */
5573 DUK_INTERNAL_DECL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx);
5574 #endif
5575 DUK_INTERNAL_DECL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects);
5576 
5577 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 */
5578 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);
5579 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);
5580 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
5581 DUK_INTERNAL_DECL duk_uint8_t duk_to_uint8clamped(duk_hthread *thr, duk_idx_t idx);
5582 #endif
5583 DUK_INTERNAL_DECL duk_hstring *duk_to_property_key_hstring(duk_hthread *thr, duk_idx_t idx);
5584 
5585 DUK_INTERNAL_DECL duk_hstring *duk_require_hstring(duk_hthread *thr, duk_idx_t idx);
5586 DUK_INTERNAL_DECL duk_hstring *duk_require_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx);
5587 DUK_INTERNAL_DECL const char *duk_require_lstring_notsymbol(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len);
5588 DUK_INTERNAL_DECL const char *duk_require_string_notsymbol(duk_hthread *thr, duk_idx_t idx);
5589 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject(duk_hthread *thr, duk_idx_t idx);
5590 DUK_INTERNAL_DECL duk_hbuffer *duk_require_hbuffer(duk_hthread *thr, duk_idx_t idx);
5591 DUK_INTERNAL_DECL duk_hthread *duk_require_hthread(duk_hthread *thr, duk_idx_t idx);
5592 DUK_INTERNAL_DECL duk_hcompfunc *duk_require_hcompfunc(duk_hthread *thr, duk_idx_t idx);
5593 DUK_INTERNAL_DECL duk_hnatfunc *duk_require_hnatfunc(duk_hthread *thr, duk_idx_t idx);
5594 
5595 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum);
5596 
5597 DUK_INTERNAL_DECL void duk_push_hstring(duk_hthread *thr, duk_hstring *h);
5598 DUK_INTERNAL_DECL void duk_push_hstring_stridx(duk_hthread *thr, duk_small_uint_t stridx);
5599 DUK_INTERNAL_DECL void duk_push_hstring_empty(duk_hthread *thr);
5600 DUK_INTERNAL_DECL void duk_push_hobject(duk_hthread *thr, duk_hobject *h);
5601 DUK_INTERNAL_DECL void duk_push_hbuffer(duk_hthread *thr, duk_hbuffer *h);
5602 #define duk_push_hthread(thr,h) \
5603 	duk_push_hobject((thr), (duk_hobject *) (h))
5604 #define duk_push_hnatfunc(thr,h) \
5605 	duk_push_hobject((thr), (duk_hobject *) (h))
5606 DUK_INTERNAL_DECL void duk_push_hobject_bidx(duk_hthread *thr, duk_small_int_t builtin_idx);
5607 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);
5608 DUK_INTERNAL_DECL duk_hobject *duk_push_object_helper_proto(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_hobject *proto);
5609 DUK_INTERNAL_DECL duk_hcompfunc *duk_push_hcompfunc(duk_hthread *thr);
5610 DUK_INTERNAL_DECL duk_hboundfunc *duk_push_hboundfunc(duk_hthread *thr);
5611 DUK_INTERNAL_DECL void duk_push_c_function_builtin(duk_hthread *thr, duk_c_function func, duk_int_t nargs);
5612 DUK_INTERNAL_DECL void duk_push_c_function_builtin_noconstruct(duk_hthread *thr, duk_c_function func, duk_int_t nargs);
5613 
5614 /* XXX: duk_push_harray() and duk_push_hcompfunc() are inconsistent with
5615  * duk_push_hobject() etc which don't create a new value.
5616  */
5617 DUK_INTERNAL_DECL duk_harray *duk_push_harray(duk_hthread *thr);
5618 DUK_INTERNAL_DECL duk_harray *duk_push_harray_with_size(duk_hthread *thr, duk_uint32_t size);
5619 DUK_INTERNAL_DECL duk_tval *duk_push_harray_with_size_outptr(duk_hthread *thr, duk_uint32_t size);
5620 
5621 DUK_INTERNAL_DECL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, duk_size_t sz);
5622 DUK_INTERNAL_DECL void duk_push_lightfunc_name_raw(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags);
5623 DUK_INTERNAL_DECL void duk_push_lightfunc_name(duk_hthread *thr, duk_tval *tv);
5624 DUK_INTERNAL_DECL void duk_push_lightfunc_tostring(duk_hthread *thr, duk_tval *tv);
5625 #if 0  /* not used yet */
5626 DUK_INTERNAL_DECL void duk_push_hnatfunc_name(duk_hthread *thr, duk_hnatfunc *h);
5627 #endif
5628 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
5629 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);
5630 #endif
5631 
5632 DUK_INTERNAL_DECL void *duk_push_fixed_buffer_nozero(duk_hthread *thr, duk_size_t len);
5633 DUK_INTERNAL_DECL void *duk_push_fixed_buffer_zero(duk_hthread *thr, duk_size_t len);
5634 
5635 DUK_INTERNAL_DECL const char *duk_push_string_readable(duk_hthread *thr, duk_idx_t idx);
5636 DUK_INTERNAL_DECL const char *duk_push_string_tval_readable(duk_hthread *thr, duk_tval *tv);
5637 DUK_INTERNAL_DECL const char *duk_push_string_tval_readable_error(duk_hthread *thr, duk_tval *tv);
5638 
5639 /* The duk_xxx_prop_stridx_short() variants expect their arguments to be short
5640  * enough to be packed into a single 32-bit integer argument.  Argument limits
5641  * vary per call; typically 16 bits are assigned to the signed value stack index
5642  * and the stridx.  In practice these work well for footprint with constant
5643  * arguments and such call sites are also easiest to verify to be correct.
5644  */
5645 
5646 DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [val] */
5647 DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5648 #define duk_get_prop_stridx_short(thr,obj_idx,stridx) \
5649 	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
5650 	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
5651 	 duk_get_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5652 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);  /* [] -> [] */
5653 
5654 DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [val] -> [] */
5655 DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5656 #define duk_put_prop_stridx_short(thr,obj_idx,stridx) \
5657 	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
5658 	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
5659 	 duk_put_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5660 
5661 DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [] */
5662 #if 0  /* Too few call sites to be useful. */
5663 DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5664 #define duk_del_prop_stridx_short(thr,obj_idx,stridx) \
5665 	(DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \
5666 	 DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \
5667 	 duk_del_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5668 #endif
5669 #define duk_del_prop_stridx_short(thr,obj_idx,stridx) \
5670 	duk_del_prop_stridx((thr), (obj_idx), (stridx))
5671 
5672 DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [] */
5673 #if 0  /* Too few call sites to be useful. */
5674 DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5675 #define duk_has_prop_stridx_short(thr,obj_idx,stridx) \
5676 	(DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \
5677 	 DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \
5678 	 duk_has_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5679 #endif
5680 #define duk_has_prop_stridx_short(thr,obj_idx,stridx) \
5681 	duk_has_prop_stridx((thr), (obj_idx), (stridx))
5682 
5683 DUK_INTERNAL_DECL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t desc_flags);  /* [key val] -> [] */
5684 
5685 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] -> [] */
5686 
5687 /* XXX: Because stridx and desc_flags have a limited range, this call could
5688  * always pack stridx and desc_flags into a single argument.
5689  */
5690 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] -> [] */
5691 DUK_INTERNAL_DECL void duk_xdef_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5692 #define duk_xdef_prop_stridx_short(thr,obj_idx,stridx,desc_flags) \
5693 	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x80L && (duk_int_t) (obj_idx) <= 0x7fL), \
5694 	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
5695 	 DUK_ASSERT_EXPR((duk_int_t) (desc_flags) >= 0 && (duk_int_t) (desc_flags) <= 0xffL), \
5696 	 duk_xdef_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 24) + (((duk_uint_t) (stridx)) << 8) + (duk_uint_t) (desc_flags)))
5697 
5698 #define duk_xdef_prop_wec(thr,obj_idx) \
5699 	duk_xdef_prop((thr), (obj_idx), DUK_PROPDESC_FLAGS_WEC)
5700 #define duk_xdef_prop_index_wec(thr,obj_idx,arr_idx) \
5701 	duk_xdef_prop_index((thr), (obj_idx), (arr_idx), DUK_PROPDESC_FLAGS_WEC)
5702 #define duk_xdef_prop_stridx_wec(thr,obj_idx,stridx) \
5703 	duk_xdef_prop_stridx((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)
5704 #define duk_xdef_prop_stridx_short_wec(thr,obj_idx,stridx) \
5705 	duk_xdef_prop_stridx_short((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)
5706 
5707 #if 0  /*unused*/
5708 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);  /* [] -> [] */
5709 #endif
5710 
5711 DUK_INTERNAL_DECL void duk_xdef_prop_stridx_thrower(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);  /* [] -> [] */
5712 
5713 DUK_INTERNAL_DECL duk_bool_t duk_get_method_stridx(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t stridx);
5714 
5715 DUK_INTERNAL_DECL void duk_pack(duk_hthread *thr, duk_idx_t count);
5716 DUK_INTERNAL_DECL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx);
5717 #if 0
5718 DUK_INTERNAL_DECL void duk_unpack(duk_hthread *thr);
5719 #endif
5720 
5721 DUK_INTERNAL_DECL void duk_require_constructor_call(duk_hthread *thr);
5722 DUK_INTERNAL_DECL void duk_require_constructable(duk_hthread *thr, duk_idx_t idx);
5723 DUK_INTERNAL_DECL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstring *h);
5724 
5725 DUK_INTERNAL_DECL void duk_resolve_nonbound_function(duk_hthread *thr);
5726 
5727 DUK_INTERNAL_DECL duk_idx_t duk_get_top_require_min(duk_hthread *thr, duk_idx_t min_top);
5728 DUK_INTERNAL_DECL duk_idx_t duk_get_top_index_unsafe(duk_hthread *thr);
5729 
5730 DUK_INTERNAL_DECL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count);
5731 DUK_INTERNAL_DECL void duk_pop_unsafe(duk_hthread *thr);
5732 DUK_INTERNAL_DECL void duk_pop_2_unsafe(duk_hthread *thr);
5733 DUK_INTERNAL_DECL void duk_pop_3_unsafe(duk_hthread *thr);
5734 DUK_INTERNAL_DECL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count);
5735 DUK_INTERNAL_DECL void duk_pop_nodecref_unsafe(duk_hthread *thr);
5736 DUK_INTERNAL_DECL void duk_pop_2_nodecref_unsafe(duk_hthread *thr);
5737 DUK_INTERNAL_DECL void duk_pop_3_nodecref_unsafe(duk_hthread *thr);
5738 DUK_INTERNAL_DECL void duk_pop_undefined(duk_hthread *thr);
5739 
5740 DUK_INTERNAL_DECL void duk_compact_m1(duk_hthread *thr);
5741 
5742 DUK_INTERNAL_DECL void duk_seal_freeze_raw(duk_hthread *thr, duk_idx_t obj_idx, duk_bool_t is_freeze);
5743 
5744 DUK_INTERNAL_DECL void duk_insert_undefined(duk_hthread *thr, duk_idx_t idx);
5745 DUK_INTERNAL_DECL void duk_insert_undefined_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);
5746 
5747 DUK_INTERNAL_DECL void duk_concat_2(duk_hthread *thr);
5748 
5749 DUK_INTERNAL_DECL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags);
5750 
5751 #if defined(DUK_USE_SYMBOL_BUILTIN)
5752 DUK_INTERNAL_DECL void duk_to_primitive_ordinary(duk_hthread *thr, duk_idx_t idx, duk_int_t hint);
5753 #endif
5754 
5755 /* Raw internal valstack access macros: access is unsafe so call site
5756  * must have a guarantee that the index is valid.  When that is the case,
5757  * using these macro results in faster and smaller code than duk_get_tval().
5758  * Both 'ctx' and 'idx' are evaluted multiple times, but only for asserts.
5759  */
5760 #define DUK_ASSERT_VALID_NEGIDX(thr,idx) \
5761 	(DUK_ASSERT_EXPR((duk_int_t) (idx) < 0), DUK_ASSERT_EXPR(duk_is_valid_index((thr), (idx))))
5762 #define DUK_ASSERT_VALID_POSIDX(thr,idx) \
5763 	(DUK_ASSERT_EXPR((duk_int_t) (idx) >= 0), DUK_ASSERT_EXPR(duk_is_valid_index((thr), (idx))))
5764 #define DUK_GET_TVAL_NEGIDX(thr,idx) \
5765 	(DUK_ASSERT_VALID_NEGIDX((thr),(idx)), ((duk_hthread *) (thr))->valstack_top + (idx))
5766 #define DUK_GET_TVAL_POSIDX(thr,idx) \
5767 	(DUK_ASSERT_VALID_POSIDX((thr),(idx)), ((duk_hthread *) (thr))->valstack_bottom + (idx))
5768 #define DUK_GET_HOBJECT_NEGIDX(thr,idx) \
5769 	(DUK_ASSERT_VALID_NEGIDX((thr),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_top + (idx)))
5770 #define DUK_GET_HOBJECT_POSIDX(thr,idx) \
5771 	(DUK_ASSERT_VALID_POSIDX((thr),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_bottom + (idx)))
5772 
5773 #define DUK_GET_THIS_TVAL_PTR(thr) \
5774 	(DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \
5775 	 (thr)->valstack_bottom - 1)
5776 
5777 DUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr);
5778 DUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time_nofrac(duk_hthread *thr);
5779 DUK_INTERNAL_DECL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr);
5780 
5781 #endif  /* DUK_API_INTERNAL_H_INCLUDED */
5782 /* #include duk_hstring.h */
5783 #line 1 "duk_hstring.h"
5784 /*
5785  *  Heap string representation.
5786  *
5787  *  Strings are byte sequences ordinarily stored in extended UTF-8 format,
5788  *  allowing values larger than the official UTF-8 range (used internally)
5789  *  and also allowing UTF-8 encoding of surrogate pairs (CESU-8 format).
5790  *  Strings may also be invalid UTF-8 altogether which is the case e.g. with
5791  *  strings used as internal property names and raw buffers converted to
5792  *  strings.  In such cases the 'clen' field contains an inaccurate value.
5793  *
5794  *  ECMAScript requires support for 32-bit long strings.  However, since each
5795  *  16-bit codepoint can take 3 bytes in CESU-8, this representation can only
5796  *  support about 1.4G codepoint long strings in extreme cases.  This is not
5797  *  really a practical issue.
5798  */
5799 
5800 #if !defined(DUK_HSTRING_H_INCLUDED)
5801 #define DUK_HSTRING_H_INCLUDED
5802 
5803 /* Impose a maximum string length for now.  Restricted artificially to
5804  * ensure adding a heap header length won't overflow size_t.  The limit
5805  * should be synchronized with DUK_HBUFFER_MAX_BYTELEN.
5806  *
5807  * E5.1 makes provisions to support strings longer than 4G characters.
5808  * This limit should be eliminated on 64-bit platforms (and increased
5809  * closer to maximum support on 32-bit platforms).
5810  */
5811 
5812 #if defined(DUK_USE_STRLEN16)
5813 #define DUK_HSTRING_MAX_BYTELEN                     (0x0000ffffUL)
5814 #else
5815 #define DUK_HSTRING_MAX_BYTELEN                     (0x7fffffffUL)
5816 #endif
5817 
5818 /* XXX: could add flags for "is valid CESU-8" (ECMAScript compatible strings),
5819  * "is valid UTF-8", "is valid extended UTF-8" (internal strings are not,
5820  * regexp bytecode is), and "contains non-BMP characters".  These are not
5821  * needed right now.
5822  */
5823 
5824 /* With lowmem builds the high 16 bits of duk_heaphdr are used for other
5825  * purposes, so this leaves 7 duk_heaphdr flags and 9 duk_hstring flags.
5826  */
5827 #define DUK_HSTRING_FLAG_ASCII                      DUK_HEAPHDR_USER_FLAG(0)  /* string is ASCII, clen == blen */
5828 #define DUK_HSTRING_FLAG_ARRIDX                     DUK_HEAPHDR_USER_FLAG(1)  /* string is a valid array index */
5829 #define DUK_HSTRING_FLAG_SYMBOL                     DUK_HEAPHDR_USER_FLAG(2)  /* string is a symbol (invalid utf-8) */
5830 #define DUK_HSTRING_FLAG_HIDDEN                     DUK_HEAPHDR_USER_FLAG(3)  /* string is a hidden symbol (implies symbol, Duktape 1.x internal string) */
5831 #define DUK_HSTRING_FLAG_RESERVED_WORD              DUK_HEAPHDR_USER_FLAG(4)  /* string is a reserved word (non-strict) */
5832 #define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD       DUK_HEAPHDR_USER_FLAG(5)  /* string is a reserved word (strict) */
5833 #define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS          DUK_HEAPHDR_USER_FLAG(6)  /* string is 'eval' or 'arguments' */
5834 #define DUK_HSTRING_FLAG_EXTDATA                    DUK_HEAPHDR_USER_FLAG(7)  /* string data is external (duk_hstring_external) */
5835 #define DUK_HSTRING_FLAG_PINNED_LITERAL             DUK_HEAPHDR_USER_FLAG(8)  /* string is a literal, and pinned */
5836 
5837 #define DUK_HSTRING_HAS_ASCII(x)                    DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
5838 #define DUK_HSTRING_HAS_ARRIDX(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
5839 #define DUK_HSTRING_HAS_SYMBOL(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
5840 #define DUK_HSTRING_HAS_HIDDEN(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
5841 #define DUK_HSTRING_HAS_RESERVED_WORD(x)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
5842 #define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
5843 #define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
5844 #define DUK_HSTRING_HAS_EXTDATA(x)                  DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
5845 #define DUK_HSTRING_HAS_PINNED_LITERAL(x)           DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
5846 
5847 #define DUK_HSTRING_SET_ASCII(x)                    DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
5848 #define DUK_HSTRING_SET_ARRIDX(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
5849 #define DUK_HSTRING_SET_SYMBOL(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
5850 #define DUK_HSTRING_SET_HIDDEN(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
5851 #define DUK_HSTRING_SET_RESERVED_WORD(x)            DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
5852 #define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x)     DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
5853 #define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x)        DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
5854 #define DUK_HSTRING_SET_EXTDATA(x)                  DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
5855 #define DUK_HSTRING_SET_PINNED_LITERAL(x)           DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
5856 
5857 #define DUK_HSTRING_CLEAR_ASCII(x)                  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
5858 #define DUK_HSTRING_CLEAR_ARRIDX(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
5859 #define DUK_HSTRING_CLEAR_SYMBOL(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
5860 #define DUK_HSTRING_CLEAR_HIDDEN(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
5861 #define DUK_HSTRING_CLEAR_RESERVED_WORD(x)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
5862 #define DUK_HSTRING_CLEAR_STRICT_RESERVED_WORD(x)   DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
5863 #define DUK_HSTRING_CLEAR_EVAL_OR_ARGUMENTS(x)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
5864 #define DUK_HSTRING_CLEAR_EXTDATA(x)                DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
5865 #define DUK_HSTRING_CLEAR_PINNED_LITERAL(x)         DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
5866 
5867 #if 0  /* Slightly smaller code without explicit flag, but explicit flag
5868         * is very useful when 'clen' is dropped.
5869         */
5870 #define DUK_HSTRING_IS_ASCII(x)                     (DUK_HSTRING_GET_BYTELEN((x)) == DUK_HSTRING_GET_CHARLEN((x)))
5871 #endif
5872 #define DUK_HSTRING_IS_ASCII(x)                     DUK_HSTRING_HAS_ASCII((x))  /* lazily set! */
5873 #define DUK_HSTRING_IS_EMPTY(x)                     (DUK_HSTRING_GET_BYTELEN((x)) == 0)
5874 
5875 #if defined(DUK_USE_STRHASH16)
5876 #define DUK_HSTRING_GET_HASH(x)                     ((x)->hdr.h_flags >> 16)
5877 #define DUK_HSTRING_SET_HASH(x,v) do { \
5878 		(x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | ((v) << 16); \
5879 	} while (0)
5880 #else
5881 #define DUK_HSTRING_GET_HASH(x)                     ((x)->hash)
5882 #define DUK_HSTRING_SET_HASH(x,v) do { \
5883 		(x)->hash = (v); \
5884 	} while (0)
5885 #endif
5886 
5887 #if defined(DUK_USE_STRLEN16)
5888 #define DUK_HSTRING_GET_BYTELEN(x)                  ((x)->hdr.h_strextra16)
5889 #define DUK_HSTRING_SET_BYTELEN(x,v) do { \
5890 		(x)->hdr.h_strextra16 = (v); \
5891 	} while (0)
5892 #if defined(DUK_USE_HSTRING_CLEN)
5893 #define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))
5894 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
5895 		(x)->clen16 = (v); \
5896 	} while (0)
5897 #else
5898 #define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))
5899 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
5900 		DUK_ASSERT(0);  /* should never be called */ \
5901 	} while (0)
5902 #endif
5903 #else
5904 #define DUK_HSTRING_GET_BYTELEN(x)                  ((x)->blen)
5905 #define DUK_HSTRING_SET_BYTELEN(x,v) do { \
5906 		(x)->blen = (v); \
5907 	} while (0)
5908 #define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))
5909 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
5910 		(x)->clen = (v); \
5911 	} while (0)
5912 #endif
5913 
5914 #if defined(DUK_USE_HSTRING_EXTDATA)
5915 #define DUK_HSTRING_GET_EXTDATA(x) \
5916 	((x)->extdata)
5917 #define DUK_HSTRING_GET_DATA(x) \
5918 	(DUK_HSTRING_HAS_EXTDATA((x)) ? \
5919 		DUK_HSTRING_GET_EXTDATA((const duk_hstring_external *) (x)) : ((const duk_uint8_t *) ((x) + 1)))
5920 #else
5921 #define DUK_HSTRING_GET_DATA(x) \
5922 	((const duk_uint8_t *) ((x) + 1))
5923 #endif
5924 
5925 #define DUK_HSTRING_GET_DATA_END(x) \
5926 	(DUK_HSTRING_GET_DATA((x)) + (x)->blen)
5927 
5928 /* Marker value; in E5 2^32-1 is not a valid array index (2^32-2 is highest
5929  * valid).
5930  */
5931 #define DUK_HSTRING_NO_ARRAY_INDEX  (0xffffffffUL)
5932 
5933 #if defined(DUK_USE_HSTRING_ARRIDX)
5934 #define DUK_HSTRING_GET_ARRIDX_FAST(h)  ((h)->arridx)
5935 #define DUK_HSTRING_GET_ARRIDX_SLOW(h)  ((h)->arridx)
5936 #else
5937 /* Get array index related to string (or return DUK_HSTRING_NO_ARRAY_INDEX);
5938  * avoids helper call if string has no array index value.
5939  */
5940 #define DUK_HSTRING_GET_ARRIDX_FAST(h)  \
5941 	(DUK_HSTRING_HAS_ARRIDX((h)) ? duk_js_to_arrayindex_hstring_fast_known((h)) : DUK_HSTRING_NO_ARRAY_INDEX)
5942 
5943 /* Slower but more compact variant. */
5944 #define DUK_HSTRING_GET_ARRIDX_SLOW(h)  \
5945 	(duk_js_to_arrayindex_hstring_fast((h)))
5946 #endif
5947 
5948 /* XXX: these actually fit into duk_hstring */
5949 #define DUK_SYMBOL_TYPE_HIDDEN 0
5950 #define DUK_SYMBOL_TYPE_GLOBAL 1
5951 #define DUK_SYMBOL_TYPE_LOCAL 2
5952 #define DUK_SYMBOL_TYPE_WELLKNOWN 3
5953 
5954 /*
5955  *  Misc
5956  */
5957 
5958 struct duk_hstring {
5959 	/* Smaller heaphdr than for other objects, because strings are held
5960 	 * in string intern table which requires no link pointers.  Much of
5961 	 * the 32-bit flags field is unused by flags, so we can stuff a 16-bit
5962 	 * field in there.
5963 	 */
5964 	duk_heaphdr_string hdr;
5965 
5966 	/* String hash. */
5967 #if defined(DUK_USE_STRHASH16)
5968 	/* If 16-bit hash is in use, stuff it into duk_heaphdr_string flags. */
5969 #else
5970 	duk_uint32_t hash;
5971 #endif
5972 
5973 	/* Precomputed array index (or DUK_HSTRING_NO_ARRAY_INDEX). */
5974 #if defined(DUK_USE_HSTRING_ARRIDX)
5975 	duk_uarridx_t arridx;
5976 #endif
5977 
5978 	/* Length in bytes (not counting NUL term). */
5979 #if defined(DUK_USE_STRLEN16)
5980 	/* placed in duk_heaphdr_string */
5981 #else
5982 	duk_uint32_t blen;
5983 #endif
5984 
5985 	/* Length in codepoints (must be E5 compatible). */
5986 #if defined(DUK_USE_STRLEN16)
5987 #if defined(DUK_USE_HSTRING_CLEN)
5988 	duk_uint16_t clen16;
5989 #else
5990 	/* computed live */
5991 #endif
5992 #else
5993 	duk_uint32_t clen;
5994 #endif
5995 
5996 	/*
5997 	 *  String data of 'blen+1' bytes follows (+1 for NUL termination
5998 	 *  convenience for C API).  No alignment needs to be guaranteed
5999 	 *  for strings, but fields above should guarantee alignment-by-4
6000 	 *  (but not alignment-by-8).
6001 	 */
6002 };
6003 
6004 /* The external string struct is defined even when the feature is inactive. */
6005 struct duk_hstring_external {
6006 	duk_hstring str;
6007 
6008 	/*
6009 	 *  For an external string, the NUL-terminated string data is stored
6010 	 *  externally.  The user must guarantee that data behind this pointer
6011 	 *  doesn't change while it's used.
6012 	 */
6013 
6014 	const duk_uint8_t *extdata;
6015 };
6016 
6017 /*
6018  *  Prototypes
6019  */
6020 
6021 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);
6022 DUK_INTERNAL_DECL duk_bool_t duk_hstring_equals_ascii_cstring(duk_hstring *h, const char *cstr);
6023 DUK_INTERNAL_DECL duk_size_t duk_hstring_get_charlen(duk_hstring *h);
6024 #if !defined(DUK_USE_HSTRING_LAZY_CLEN)
6025 DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h);
6026 #endif
6027 
6028 #endif  /* DUK_HSTRING_H_INCLUDED */
6029 /* #include duk_hobject.h */
6030 #line 1 "duk_hobject.h"
6031 /*
6032  *  Heap object representation.
6033  *
6034  *  Heap objects are used for ECMAScript objects, arrays, and functions,
6035  *  but also for internal control like declarative and object environment
6036  *  records.  Compiled functions, native functions, and threads are also
6037  *  objects but with an extended C struct.
6038  *
6039  *  Objects provide the required ECMAScript semantics and exotic behaviors
6040  *  especially for property access.
6041  *
6042  *  Properties are stored in three conceptual parts:
6043  *
6044  *    1. A linear 'entry part' contains ordered key-value-attributes triples
6045  *       and is the main method of string properties.
6046  *
6047  *    2. An optional linear 'array part' is used for array objects to store a
6048  *       (dense) range of [0,N[ array indexed entries with default attributes
6049  *       (writable, enumerable, configurable).  If the array part would become
6050  *       sparse or non-default attributes are required, the array part is
6051  *       abandoned and moved to the 'entry part'.
6052  *
6053  *    3. An optional 'hash part' is used to optimize lookups of the entry
6054  *       part; it is used only for objects with sufficiently many properties
6055  *       and can be abandoned without loss of information.
6056  *
6057  *  These three conceptual parts are stored in a single memory allocated area.
6058  *  This minimizes memory allocation overhead but also means that all three
6059  *  parts are resized together, and makes property access a bit complicated.
6060  */
6061 
6062 #if !defined(DUK_HOBJECT_H_INCLUDED)
6063 #define DUK_HOBJECT_H_INCLUDED
6064 
6065 /* Object flags.  Make sure this stays in sync with debugger object
6066  * inspection code.
6067  */
6068 
6069 /* XXX: some flags are object subtype specific (e.g. common to all function
6070  * subtypes, duk_harray, etc) and could be reused for different subtypes.
6071  */
6072 #define DUK_HOBJECT_FLAG_EXTENSIBLE            DUK_HEAPHDR_USER_FLAG(0)   /* object is extensible */
6073 #define DUK_HOBJECT_FLAG_CONSTRUCTABLE         DUK_HEAPHDR_USER_FLAG(1)   /* object is constructable */
6074 #define DUK_HOBJECT_FLAG_CALLABLE              DUK_HEAPHDR_USER_FLAG(2)   /* object is callable */
6075 #define DUK_HOBJECT_FLAG_BOUNDFUNC             DUK_HEAPHDR_USER_FLAG(3)   /* object established using Function.prototype.bind() */
6076 #define DUK_HOBJECT_FLAG_COMPFUNC              DUK_HEAPHDR_USER_FLAG(4)   /* object is a compiled function (duk_hcompfunc) */
6077 #define DUK_HOBJECT_FLAG_NATFUNC               DUK_HEAPHDR_USER_FLAG(5)   /* object is a native function (duk_hnatfunc) */
6078 #define DUK_HOBJECT_FLAG_BUFOBJ                DUK_HEAPHDR_USER_FLAG(6)   /* object is a buffer object (duk_hbufobj) (always exotic) */
6079 #define DUK_HOBJECT_FLAG_FASTREFS              DUK_HEAPHDR_USER_FLAG(7)   /* object has no fields needing DECREF/marking beyond base duk_hobject header */
6080 #define DUK_HOBJECT_FLAG_ARRAY_PART            DUK_HEAPHDR_USER_FLAG(8)   /* object has an array part (a_size may still be 0) */
6081 #define DUK_HOBJECT_FLAG_STRICT                DUK_HEAPHDR_USER_FLAG(9)   /* function: function object is strict */
6082 #define DUK_HOBJECT_FLAG_NOTAIL                DUK_HEAPHDR_USER_FLAG(10)  /* function: function must not be tail called */
6083 #define DUK_HOBJECT_FLAG_NEWENV                DUK_HEAPHDR_USER_FLAG(11)  /* function: create new environment when called (see duk_hcompfunc) */
6084 #define DUK_HOBJECT_FLAG_NAMEBINDING           DUK_HEAPHDR_USER_FLAG(12)  /* function: create binding for func name (function templates only, used for named function expressions) */
6085 #define DUK_HOBJECT_FLAG_CREATEARGS            DUK_HEAPHDR_USER_FLAG(13)  /* function: create an arguments object on function call */
6086 #define DUK_HOBJECT_FLAG_HAVE_FINALIZER        DUK_HEAPHDR_USER_FLAG(14)  /* object has a callable (own) finalizer property */
6087 #define DUK_HOBJECT_FLAG_EXOTIC_ARRAY          DUK_HEAPHDR_USER_FLAG(15)  /* 'Array' object, array length and index exotic behavior */
6088 #define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ      DUK_HEAPHDR_USER_FLAG(16)  /* 'String' object, array index exotic behavior */
6089 #define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS      DUK_HEAPHDR_USER_FLAG(17)  /* 'Arguments' object and has arguments exotic behavior (non-strict callee) */
6090 #define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ       DUK_HEAPHDR_USER_FLAG(18)  /* 'Proxy' object */
6091 #define DUK_HOBJECT_FLAG_SPECIAL_CALL          DUK_HEAPHDR_USER_FLAG(19)  /* special casing in call behavior, for .call(), .apply(), etc. */
6092 
6093 #define DUK_HOBJECT_FLAG_CLASS_BASE            DUK_HEAPHDR_USER_FLAG_NUMBER(20)
6094 #define DUK_HOBJECT_FLAG_CLASS_BITS            5
6095 
6096 #define DUK_HOBJECT_GET_CLASS_NUMBER(h)        \
6097 	DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS)
6098 #define DUK_HOBJECT_SET_CLASS_NUMBER(h,v)      \
6099 	DUK_HEAPHDR_SET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS, (v))
6100 
6101 #define DUK_HOBJECT_GET_CLASS_MASK(h)          \
6102 	(1UL << DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS))
6103 
6104 /* Macro for creating flag initializer from a class number.
6105  * Unsigned type cast is needed to avoid warnings about coercing
6106  * a signed integer to an unsigned one; the largest class values
6107  * have the highest bit (bit 31) set which causes this.
6108  */
6109 #define DUK_HOBJECT_CLASS_AS_FLAGS(v)          (((duk_uint_t) (v)) << DUK_HOBJECT_FLAG_CLASS_BASE)
6110 
6111 /* E5 Section 8.6.2 + custom classes */
6112 #define DUK_HOBJECT_CLASS_NONE                 0
6113 #define DUK_HOBJECT_CLASS_OBJECT               1
6114 #define DUK_HOBJECT_CLASS_ARRAY                2
6115 #define DUK_HOBJECT_CLASS_FUNCTION             3
6116 #define DUK_HOBJECT_CLASS_ARGUMENTS            4
6117 #define DUK_HOBJECT_CLASS_BOOLEAN              5
6118 #define DUK_HOBJECT_CLASS_DATE                 6
6119 #define DUK_HOBJECT_CLASS_ERROR                7
6120 #define DUK_HOBJECT_CLASS_JSON                 8
6121 #define DUK_HOBJECT_CLASS_MATH                 9
6122 #define DUK_HOBJECT_CLASS_NUMBER               10
6123 #define DUK_HOBJECT_CLASS_REGEXP               11
6124 #define DUK_HOBJECT_CLASS_STRING               12
6125 #define DUK_HOBJECT_CLASS_GLOBAL               13
6126 #define DUK_HOBJECT_CLASS_SYMBOL               14
6127 #define DUK_HOBJECT_CLASS_OBJENV               15  /* custom */
6128 #define DUK_HOBJECT_CLASS_DECENV               16  /* custom */
6129 #define DUK_HOBJECT_CLASS_POINTER              17  /* custom */
6130 #define DUK_HOBJECT_CLASS_THREAD               18  /* custom; implies DUK_HOBJECT_IS_THREAD */
6131 #define DUK_HOBJECT_CLASS_BUFOBJ_MIN           19
6132 #define DUK_HOBJECT_CLASS_ARRAYBUFFER          19  /* implies DUK_HOBJECT_IS_BUFOBJ */
6133 #define DUK_HOBJECT_CLASS_DATAVIEW             20
6134 #define DUK_HOBJECT_CLASS_INT8ARRAY            21
6135 #define DUK_HOBJECT_CLASS_UINT8ARRAY           22
6136 #define DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY    23
6137 #define DUK_HOBJECT_CLASS_INT16ARRAY           24
6138 #define DUK_HOBJECT_CLASS_UINT16ARRAY          25
6139 #define DUK_HOBJECT_CLASS_INT32ARRAY           26
6140 #define DUK_HOBJECT_CLASS_UINT32ARRAY          27
6141 #define DUK_HOBJECT_CLASS_FLOAT32ARRAY         28
6142 #define DUK_HOBJECT_CLASS_FLOAT64ARRAY         29
6143 #define DUK_HOBJECT_CLASS_BUFOBJ_MAX           29
6144 #define DUK_HOBJECT_CLASS_MAX                  29
6145 
6146 /* Class masks. */
6147 #define DUK_HOBJECT_CMASK_ALL                  ((1UL << (DUK_HOBJECT_CLASS_MAX + 1)) - 1UL)
6148 #define DUK_HOBJECT_CMASK_NONE                 (1UL << DUK_HOBJECT_CLASS_NONE)
6149 #define DUK_HOBJECT_CMASK_ARGUMENTS            (1UL << DUK_HOBJECT_CLASS_ARGUMENTS)
6150 #define DUK_HOBJECT_CMASK_ARRAY                (1UL << DUK_HOBJECT_CLASS_ARRAY)
6151 #define DUK_HOBJECT_CMASK_BOOLEAN              (1UL << DUK_HOBJECT_CLASS_BOOLEAN)
6152 #define DUK_HOBJECT_CMASK_DATE                 (1UL << DUK_HOBJECT_CLASS_DATE)
6153 #define DUK_HOBJECT_CMASK_ERROR                (1UL << DUK_HOBJECT_CLASS_ERROR)
6154 #define DUK_HOBJECT_CMASK_FUNCTION             (1UL << DUK_HOBJECT_CLASS_FUNCTION)
6155 #define DUK_HOBJECT_CMASK_JSON                 (1UL << DUK_HOBJECT_CLASS_JSON)
6156 #define DUK_HOBJECT_CMASK_MATH                 (1UL << DUK_HOBJECT_CLASS_MATH)
6157 #define DUK_HOBJECT_CMASK_NUMBER               (1UL << DUK_HOBJECT_CLASS_NUMBER)
6158 #define DUK_HOBJECT_CMASK_OBJECT               (1UL << DUK_HOBJECT_CLASS_OBJECT)
6159 #define DUK_HOBJECT_CMASK_REGEXP               (1UL << DUK_HOBJECT_CLASS_REGEXP)
6160 #define DUK_HOBJECT_CMASK_STRING               (1UL << DUK_HOBJECT_CLASS_STRING)
6161 #define DUK_HOBJECT_CMASK_GLOBAL               (1UL << DUK_HOBJECT_CLASS_GLOBAL)
6162 #define DUK_HOBJECT_CMASK_SYMBOL               (1UL << DUK_HOBJECT_CLASS_SYMBOL)
6163 #define DUK_HOBJECT_CMASK_OBJENV               (1UL << DUK_HOBJECT_CLASS_OBJENV)
6164 #define DUK_HOBJECT_CMASK_DECENV               (1UL << DUK_HOBJECT_CLASS_DECENV)
6165 #define DUK_HOBJECT_CMASK_POINTER              (1UL << DUK_HOBJECT_CLASS_POINTER)
6166 #define DUK_HOBJECT_CMASK_ARRAYBUFFER          (1UL << DUK_HOBJECT_CLASS_ARRAYBUFFER)
6167 #define DUK_HOBJECT_CMASK_DATAVIEW             (1UL << DUK_HOBJECT_CLASS_DATAVIEW)
6168 #define DUK_HOBJECT_CMASK_INT8ARRAY            (1UL << DUK_HOBJECT_CLASS_INT8ARRAY)
6169 #define DUK_HOBJECT_CMASK_UINT8ARRAY           (1UL << DUK_HOBJECT_CLASS_UINT8ARRAY)
6170 #define DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY    (1UL << DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY)
6171 #define DUK_HOBJECT_CMASK_INT16ARRAY           (1UL << DUK_HOBJECT_CLASS_INT16ARRAY)
6172 #define DUK_HOBJECT_CMASK_UINT16ARRAY          (1UL << DUK_HOBJECT_CLASS_UINT16ARRAY)
6173 #define DUK_HOBJECT_CMASK_INT32ARRAY           (1UL << DUK_HOBJECT_CLASS_INT32ARRAY)
6174 #define DUK_HOBJECT_CMASK_UINT32ARRAY          (1UL << DUK_HOBJECT_CLASS_UINT32ARRAY)
6175 #define DUK_HOBJECT_CMASK_FLOAT32ARRAY         (1UL << DUK_HOBJECT_CLASS_FLOAT32ARRAY)
6176 #define DUK_HOBJECT_CMASK_FLOAT64ARRAY         (1UL << DUK_HOBJECT_CLASS_FLOAT64ARRAY)
6177 
6178 #define DUK_HOBJECT_CMASK_ALL_BUFOBJS \
6179 	(DUK_HOBJECT_CMASK_ARRAYBUFFER | \
6180 	 DUK_HOBJECT_CMASK_DATAVIEW | \
6181 	 DUK_HOBJECT_CMASK_INT8ARRAY | \
6182 	 DUK_HOBJECT_CMASK_UINT8ARRAY | \
6183 	 DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY | \
6184 	 DUK_HOBJECT_CMASK_INT16ARRAY | \
6185 	 DUK_HOBJECT_CMASK_UINT16ARRAY | \
6186 	 DUK_HOBJECT_CMASK_INT32ARRAY | \
6187 	 DUK_HOBJECT_CMASK_UINT32ARRAY | \
6188 	 DUK_HOBJECT_CMASK_FLOAT32ARRAY | \
6189 	 DUK_HOBJECT_CMASK_FLOAT64ARRAY)
6190 
6191 #define DUK_HOBJECT_IS_OBJENV(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_OBJENV)
6192 #define DUK_HOBJECT_IS_DECENV(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DECENV)
6193 #define DUK_HOBJECT_IS_ENV(h)                  (DUK_HOBJECT_IS_OBJENV((h)) || DUK_HOBJECT_IS_DECENV((h)))
6194 #define DUK_HOBJECT_IS_ARRAY(h)                DUK_HOBJECT_HAS_EXOTIC_ARRAY((h))  /* Rely on class Array <=> exotic Array */
6195 #define DUK_HOBJECT_IS_BOUNDFUNC(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6196 #define DUK_HOBJECT_IS_COMPFUNC(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6197 #define DUK_HOBJECT_IS_NATFUNC(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6198 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6199 #define DUK_HOBJECT_IS_BUFOBJ(h)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6200 #else
6201 #define DUK_HOBJECT_IS_BUFOBJ(h)               0
6202 #endif
6203 #define DUK_HOBJECT_IS_THREAD(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_THREAD)
6204 #if defined(DUK_USE_ES6_PROXY)
6205 #define DUK_HOBJECT_IS_PROXY(h)                DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((h))
6206 #else
6207 #define DUK_HOBJECT_IS_PROXY(h)                0
6208 #endif
6209 
6210 #define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
6211                                                         DUK_HOBJECT_FLAG_COMPFUNC | \
6212                                                         DUK_HOBJECT_FLAG_NATFUNC)
6213 
6214 #define DUK_HOBJECT_IS_FUNCTION(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
6215                                                         DUK_HOBJECT_FLAG_BOUNDFUNC | \
6216                                                         DUK_HOBJECT_FLAG_COMPFUNC | \
6217                                                         DUK_HOBJECT_FLAG_NATFUNC)
6218 
6219 #define DUK_HOBJECT_IS_CALLABLE(h)             DUK_HOBJECT_HAS_CALLABLE((h))
6220 
6221 /* Object has any exotic behavior(s). */
6222 #define DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS      (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
6223                                                 DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS | \
6224                                                 DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
6225                                                 DUK_HOBJECT_FLAG_BUFOBJ | \
6226                                                 DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6227 #define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS)
6228 
6229 /* Object has any virtual properties (not counting Proxy behavior). */
6230 #define DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS     (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
6231                                                 DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
6232                                                 DUK_HOBJECT_FLAG_BUFOBJ)
6233 #define DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(h)  DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS)
6234 
6235 #define DUK_HOBJECT_HAS_EXTENSIBLE(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
6236 #define DUK_HOBJECT_HAS_CONSTRUCTABLE(h)       DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
6237 #define DUK_HOBJECT_HAS_CALLABLE(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
6238 #define DUK_HOBJECT_HAS_BOUNDFUNC(h)           DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6239 #define DUK_HOBJECT_HAS_COMPFUNC(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6240 #define DUK_HOBJECT_HAS_NATFUNC(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6241 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6242 #define DUK_HOBJECT_HAS_BUFOBJ(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6243 #else
6244 #define DUK_HOBJECT_HAS_BUFOBJ(h)              0
6245 #endif
6246 #define DUK_HOBJECT_HAS_FASTREFS(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
6247 #define DUK_HOBJECT_HAS_ARRAY_PART(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
6248 #define DUK_HOBJECT_HAS_STRICT(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
6249 #define DUK_HOBJECT_HAS_NOTAIL(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
6250 #define DUK_HOBJECT_HAS_NEWENV(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
6251 #define DUK_HOBJECT_HAS_NAMEBINDING(h)         DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
6252 #define DUK_HOBJECT_HAS_CREATEARGS(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
6253 #define DUK_HOBJECT_HAS_HAVE_FINALIZER(h)      DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
6254 #define DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
6255 #define DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
6256 #define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
6257 #if defined(DUK_USE_ES6_PROXY)
6258 #define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6259 #else
6260 #define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)     0
6261 #endif
6262 #define DUK_HOBJECT_HAS_SPECIAL_CALL(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
6263 
6264 #define DUK_HOBJECT_SET_EXTENSIBLE(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
6265 #define DUK_HOBJECT_SET_CONSTRUCTABLE(h)       DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
6266 #define DUK_HOBJECT_SET_CALLABLE(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
6267 #define DUK_HOBJECT_SET_BOUNDFUNC(h)           DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6268 #define DUK_HOBJECT_SET_COMPFUNC(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6269 #define DUK_HOBJECT_SET_NATFUNC(h)             DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6270 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6271 #define DUK_HOBJECT_SET_BUFOBJ(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6272 #endif
6273 #define DUK_HOBJECT_SET_FASTREFS(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
6274 #define DUK_HOBJECT_SET_ARRAY_PART(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
6275 #define DUK_HOBJECT_SET_STRICT(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
6276 #define DUK_HOBJECT_SET_NOTAIL(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
6277 #define DUK_HOBJECT_SET_NEWENV(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
6278 #define DUK_HOBJECT_SET_NAMEBINDING(h)         DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
6279 #define DUK_HOBJECT_SET_CREATEARGS(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
6280 #define DUK_HOBJECT_SET_HAVE_FINALIZER(h)      DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
6281 #define DUK_HOBJECT_SET_EXOTIC_ARRAY(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
6282 #define DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
6283 #define DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
6284 #if defined(DUK_USE_ES6_PROXY)
6285 #define DUK_HOBJECT_SET_EXOTIC_PROXYOBJ(h)     DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6286 #endif
6287 #define DUK_HOBJECT_SET_SPECIAL_CALL(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
6288 
6289 #define DUK_HOBJECT_CLEAR_EXTENSIBLE(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
6290 #define DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
6291 #define DUK_HOBJECT_CLEAR_CALLABLE(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
6292 #define DUK_HOBJECT_CLEAR_BOUNDFUNC(h)         DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6293 #define DUK_HOBJECT_CLEAR_COMPFUNC(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6294 #define DUK_HOBJECT_CLEAR_NATFUNC(h)           DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6295 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6296 #define DUK_HOBJECT_CLEAR_BUFOBJ(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6297 #endif
6298 #define DUK_HOBJECT_CLEAR_FASTREFS(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
6299 #define DUK_HOBJECT_CLEAR_ARRAY_PART(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
6300 #define DUK_HOBJECT_CLEAR_STRICT(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
6301 #define DUK_HOBJECT_CLEAR_NOTAIL(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
6302 #define DUK_HOBJECT_CLEAR_NEWENV(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
6303 #define DUK_HOBJECT_CLEAR_NAMEBINDING(h)       DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
6304 #define DUK_HOBJECT_CLEAR_CREATEARGS(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
6305 #define DUK_HOBJECT_CLEAR_HAVE_FINALIZER(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
6306 #define DUK_HOBJECT_CLEAR_EXOTIC_ARRAY(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
6307 #define DUK_HOBJECT_CLEAR_EXOTIC_STRINGOBJ(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
6308 #define DUK_HOBJECT_CLEAR_EXOTIC_ARGUMENTS(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
6309 #if defined(DUK_USE_ES6_PROXY)
6310 #define DUK_HOBJECT_CLEAR_EXOTIC_PROXYOBJ(h)   DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6311 #endif
6312 #define DUK_HOBJECT_CLEAR_SPECIAL_CALL(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
6313 
6314 /* Object can/cannot use FASTREFS, i.e. has no strong reference fields beyond
6315  * duk_hobject base header.  This is used just for asserts so doesn't need to
6316  * be optimized.
6317  */
6318 #define DUK_HOBJECT_PROHIBITS_FASTREFS(h) \
6319 	(DUK_HOBJECT_IS_COMPFUNC((h)) || DUK_HOBJECT_IS_DECENV((h)) || DUK_HOBJECT_IS_OBJENV((h)) || \
6320 	 DUK_HOBJECT_IS_BUFOBJ((h)) || DUK_HOBJECT_IS_THREAD((h)) || DUK_HOBJECT_IS_PROXY((h)) || \
6321 	 DUK_HOBJECT_IS_BOUNDFUNC((h)))
6322 #define DUK_HOBJECT_ALLOWS_FASTREFS(h) (!DUK_HOBJECT_PROHIBITS_FASTREFS((h)))
6323 
6324 /* Flags used for property attributes in duk_propdesc and packed flags.
6325  * Must fit into 8 bits.
6326  */
6327 #define DUK_PROPDESC_FLAG_WRITABLE              (1U << 0)    /* E5 Section 8.6.1 */
6328 #define DUK_PROPDESC_FLAG_ENUMERABLE            (1U << 1)    /* E5 Section 8.6.1 */
6329 #define DUK_PROPDESC_FLAG_CONFIGURABLE          (1U << 2)    /* E5 Section 8.6.1 */
6330 #define DUK_PROPDESC_FLAG_ACCESSOR              (1U << 3)    /* accessor */
6331 #define DUK_PROPDESC_FLAG_VIRTUAL               (1U << 4)    /* property is virtual: used in duk_propdesc, never stored
6332                                                              * (used by e.g. buffer virtual properties)
6333                                                              */
6334 #define DUK_PROPDESC_FLAGS_MASK                 (DUK_PROPDESC_FLAG_WRITABLE | \
6335                                                  DUK_PROPDESC_FLAG_ENUMERABLE | \
6336                                                  DUK_PROPDESC_FLAG_CONFIGURABLE | \
6337                                                  DUK_PROPDESC_FLAG_ACCESSOR)
6338 
6339 /* Additional flags which are passed in the same flags argument as property
6340  * flags but are not stored in object properties.
6341  */
6342 #define DUK_PROPDESC_FLAG_NO_OVERWRITE          (1U << 4)    /* internal define property: skip write silently if exists */
6343 
6344 /* Convenience defines for property attributes. */
6345 #define DUK_PROPDESC_FLAGS_NONE                 0
6346 #define DUK_PROPDESC_FLAGS_W                    (DUK_PROPDESC_FLAG_WRITABLE)
6347 #define DUK_PROPDESC_FLAGS_E                    (DUK_PROPDESC_FLAG_ENUMERABLE)
6348 #define DUK_PROPDESC_FLAGS_C                    (DUK_PROPDESC_FLAG_CONFIGURABLE)
6349 #define DUK_PROPDESC_FLAGS_WE                   (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE)
6350 #define DUK_PROPDESC_FLAGS_WC                   (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
6351 #define DUK_PROPDESC_FLAGS_EC                   (DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
6352 #define DUK_PROPDESC_FLAGS_WEC                  (DUK_PROPDESC_FLAG_WRITABLE | \
6353                                                  DUK_PROPDESC_FLAG_ENUMERABLE | \
6354                                                  DUK_PROPDESC_FLAG_CONFIGURABLE)
6355 
6356 /* Flags for duk_hobject_get_own_propdesc() and variants. */
6357 #define DUK_GETDESC_FLAG_PUSH_VALUE          (1U << 0)  /* push value to stack */
6358 #define DUK_GETDESC_FLAG_IGNORE_PROTOLOOP    (1U << 1)  /* don't throw for prototype loop */
6359 
6360 /*
6361  *  Macro for object validity check
6362  *
6363  *  Assert for currently guaranteed relations between flags, for instance.
6364  */
6365 
6366 #define DUK_ASSERT_HOBJECT_VALID(h) do { \
6367 		DUK_ASSERT((h) != NULL); \
6368 		DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE((h)) || \
6369 		           DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FUNCTION); \
6370 		DUK_ASSERT(!DUK_HOBJECT_IS_BUFOBJ((h)) || \
6371 		           (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAYBUFFER || \
6372 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DATAVIEW || \
6373 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT8ARRAY || \
6374 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8ARRAY || \
6375 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY || \
6376 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT16ARRAY || \
6377 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT16ARRAY || \
6378 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT32ARRAY || \
6379 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT32ARRAY || \
6380 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT32ARRAY || \
6381 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT64ARRAY)); \
6382 		/* Object is an Array <=> object has exotic array behavior */ \
6383 		DUK_ASSERT((DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAY && DUK_HOBJECT_HAS_EXOTIC_ARRAY((h))) || \
6384 		           (DUK_HOBJECT_GET_CLASS_NUMBER((h)) != DUK_HOBJECT_CLASS_ARRAY && !DUK_HOBJECT_HAS_EXOTIC_ARRAY((h)))); \
6385 	} while (0)
6386 
6387 /*
6388  *  Macros to access the 'props' allocation.
6389  */
6390 
6391 #if defined(DUK_USE_HEAPPTR16)
6392 #define DUK_HOBJECT_GET_PROPS(heap,h) \
6393 	((duk_uint8_t *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (h))->h_extra16))
6394 #define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
6395 		((duk_heaphdr *) (h))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
6396 	} while (0)
6397 #else
6398 #define DUK_HOBJECT_GET_PROPS(heap,h) \
6399 	((h)->props)
6400 #define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
6401 		(h)->props = (duk_uint8_t *) (x); \
6402 	} while (0)
6403 #endif
6404 
6405 #if defined(DUK_USE_HOBJECT_LAYOUT_1)
6406 /* LAYOUT 1 */
6407 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
6408 	((duk_hstring **) (void *) ( \
6409 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
6410 	))
6411 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
6412 	((duk_propvalue *) (void *) ( \
6413 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6414 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_hstring *) \
6415 	))
6416 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
6417 	((duk_uint8_t *) (void *) ( \
6418 		DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
6419 	))
6420 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
6421 	((duk_tval *) (void *) ( \
6422 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6423 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) \
6424 	))
6425 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
6426 	((duk_uint32_t *) (void *) ( \
6427 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6428 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6429 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
6430 	))
6431 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
6432 	( \
6433 		(n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6434 		(n_arr) * sizeof(duk_tval) + \
6435 		(n_hash) * sizeof(duk_uint32_t) \
6436 	)
6437 #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 { \
6438 		(set_e_k) = (duk_hstring **) (void *) (p_base); \
6439 		(set_e_pv) = (duk_propvalue *) (void *) ((set_e_k) + (n_ent)); \
6440 		(set_e_f) = (duk_uint8_t *) (void *) ((set_e_pv) + (n_ent)); \
6441 		(set_a) = (duk_tval *) (void *) ((set_e_f) + (n_ent)); \
6442 		(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
6443 	} while (0)
6444 #elif defined(DUK_USE_HOBJECT_LAYOUT_2)
6445 /* LAYOUT 2 */
6446 #if (DUK_USE_ALIGN_BY == 4)
6447 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((4 - (e_sz)) & 0x03)
6448 #elif (DUK_USE_ALIGN_BY == 8)
6449 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((8 - (e_sz)) & 0x07)
6450 #elif (DUK_USE_ALIGN_BY == 1)
6451 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) 0
6452 #else
6453 #error invalid DUK_USE_ALIGN_BY
6454 #endif
6455 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
6456 	((duk_hstring **) (void *) ( \
6457 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6458 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
6459 	))
6460 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
6461 	((duk_propvalue *) (void *) ( \
6462 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
6463 	))
6464 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
6465 	((duk_uint8_t *) (void *) ( \
6466 		DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
6467 	))
6468 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
6469 	((duk_tval *) (void *) ( \
6470 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6471 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6472 			DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) \
6473 	))
6474 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
6475 	((duk_uint32_t *) (void *) ( \
6476 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6477 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6478 			DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) + \
6479 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
6480 	))
6481 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
6482 	( \
6483 		(n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6484 		DUK_HOBJECT_E_FLAG_PADDING((n_ent)) + \
6485 		(n_arr) * sizeof(duk_tval) + \
6486 		(n_hash) * sizeof(duk_uint32_t) \
6487 	)
6488 #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 { \
6489 		(set_e_pv) = (duk_propvalue *) (void *) (p_base); \
6490 		(set_e_k) = (duk_hstring **) (void *) ((set_e_pv) + (n_ent)); \
6491 		(set_e_f) = (duk_uint8_t *) (void *) ((set_e_k) + (n_ent)); \
6492 		(set_a) = (duk_tval *) (void *) (((duk_uint8_t *) (set_e_f)) + \
6493 		                                 sizeof(duk_uint8_t) * (n_ent) + \
6494 		                                 DUK_HOBJECT_E_FLAG_PADDING((n_ent))); \
6495 		(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
6496 	} while (0)
6497 #elif defined(DUK_USE_HOBJECT_LAYOUT_3)
6498 /* LAYOUT 3 */
6499 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
6500 	((duk_hstring **) (void *) ( \
6501 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6502 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) + \
6503 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
6504 	))
6505 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
6506 	((duk_propvalue *) (void *) ( \
6507 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
6508 	))
6509 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
6510 	((duk_uint8_t *) (void *) ( \
6511 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6512 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
6513 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) + \
6514 			DUK_HOBJECT_GET_HSIZE((h)) * sizeof(duk_uint32_t) \
6515 	))
6516 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
6517 	((duk_tval *) (void *) ( \
6518 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6519 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
6520 	))
6521 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
6522 	((duk_uint32_t *) (void *) ( \
6523 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6524 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
6525 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
6526 	))
6527 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
6528 	( \
6529 		(n_ent) * (sizeof(duk_propvalue) + sizeof(duk_hstring *) + sizeof(duk_uint8_t)) + \
6530 		(n_arr) * sizeof(duk_tval) + \
6531 		(n_hash) * sizeof(duk_uint32_t) \
6532 	)
6533 #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 { \
6534 		(set_e_pv) = (duk_propvalue *) (void *) (p_base); \
6535 		(set_a) = (duk_tval *) (void *) ((set_e_pv) + (n_ent)); \
6536 		(set_e_k) = (duk_hstring **) (void *) ((set_a) + (n_arr)); \
6537 		(set_h) = (duk_uint32_t *) (void *) ((set_e_k) + (n_ent)); \
6538 		(set_e_f) = (duk_uint8_t *) (void *) ((set_h) + (n_hash)); \
6539 	} while (0)
6540 #else
6541 #error invalid hobject layout defines
6542 #endif  /* hobject property layout */
6543 
6544 #define DUK_HOBJECT_P_ALLOC_SIZE(h) \
6545 	DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE((h)), DUK_HOBJECT_GET_ASIZE((h)), DUK_HOBJECT_GET_HSIZE((h)))
6546 
6547 #define DUK_HOBJECT_E_GET_KEY(heap,h,i)              (DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
6548 #define DUK_HOBJECT_E_GET_KEY_PTR(heap,h,i)          (&DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
6549 #define DUK_HOBJECT_E_GET_VALUE(heap,h,i)            (DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
6550 #define DUK_HOBJECT_E_GET_VALUE_PTR(heap,h,i)        (&DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
6551 #define DUK_HOBJECT_E_GET_VALUE_TVAL(heap,h,i)       (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
6552 #define DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap,h,i)   (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
6553 #define DUK_HOBJECT_E_GET_VALUE_GETTER(heap,h,i)     (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
6554 #define DUK_HOBJECT_E_GET_VALUE_GETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
6555 #define DUK_HOBJECT_E_GET_VALUE_SETTER(heap,h,i)     (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
6556 #define DUK_HOBJECT_E_GET_VALUE_SETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
6557 #define DUK_HOBJECT_E_GET_FLAGS(heap,h,i)            (DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
6558 #define DUK_HOBJECT_E_GET_FLAGS_PTR(heap,h,i)        (&DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
6559 #define DUK_HOBJECT_A_GET_VALUE(heap,h,i)            (DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
6560 #define DUK_HOBJECT_A_GET_VALUE_PTR(heap,h,i)        (&DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
6561 #define DUK_HOBJECT_H_GET_INDEX(heap,h,i)            (DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
6562 #define DUK_HOBJECT_H_GET_INDEX_PTR(heap,h,i)        (&DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
6563 
6564 #define DUK_HOBJECT_E_SET_KEY(heap,h,i,k)  do { \
6565 		DUK_HOBJECT_E_GET_KEY((heap), (h), (i)) = (k); \
6566 	} while (0)
6567 #define DUK_HOBJECT_E_SET_VALUE(heap,h,i,v)  do { \
6568 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)) = (v); \
6569 	} while (0)
6570 #define DUK_HOBJECT_E_SET_VALUE_TVAL(heap,h,i,v)  do { \
6571 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v = (v); \
6572 	} while (0)
6573 #define DUK_HOBJECT_E_SET_VALUE_GETTER(heap,h,i,v)  do { \
6574 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get = (v); \
6575 	} while (0)
6576 #define DUK_HOBJECT_E_SET_VALUE_SETTER(heap,h,i,v)  do { \
6577 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set = (v); \
6578 	} while (0)
6579 #define DUK_HOBJECT_E_SET_FLAGS(heap,h,i,f)  do { \
6580 		DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) = (duk_uint8_t) (f); \
6581 	} while (0)
6582 #define DUK_HOBJECT_A_SET_VALUE(heap,h,i,v)  do { \
6583 		DUK_HOBJECT_A_GET_VALUE((heap), (h), (i)) = (v); \
6584 	} while (0)
6585 #define DUK_HOBJECT_A_SET_VALUE_TVAL(heap,h,i,v) \
6586 	DUK_HOBJECT_A_SET_VALUE((heap), (h), (i), (v))  /* alias for above */
6587 #define DUK_HOBJECT_H_SET_INDEX(heap,h,i,v)  do { \
6588 		DUK_HOBJECT_H_GET_INDEX((heap), (h), (i)) = (v); \
6589 	} while (0)
6590 
6591 #define DUK_HOBJECT_E_SET_FLAG_BITS(heap,h,i,mask)  do { \
6592 		DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] |= (mask); \
6593 	} while (0)
6594 
6595 #define DUK_HOBJECT_E_CLEAR_FLAG_BITS(heap,h,i,mask)  do { \
6596 		DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] &= ~(mask); \
6597 	} while (0)
6598 
6599 #define DUK_HOBJECT_E_SLOT_IS_WRITABLE(heap,h,i)     ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_WRITABLE) != 0)
6600 #define DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(heap,h,i)   ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
6601 #define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
6602 #define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap,h,i)     ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
6603 
6604 #define DUK_HOBJECT_E_SLOT_SET_WRITABLE(heap,h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
6605 #define DUK_HOBJECT_E_SLOT_SET_ENUMERABLE(heap,h,i)      DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
6606 #define DUK_HOBJECT_E_SLOT_SET_CONFIGURABLE(heap,h,i)    DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
6607 #define DUK_HOBJECT_E_SLOT_SET_ACCESSOR(heap,h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
6608 
6609 #define DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(heap,h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
6610 #define DUK_HOBJECT_E_SLOT_CLEAR_ENUMERABLE(heap,h,i)    DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
6611 #define DUK_HOBJECT_E_SLOT_CLEAR_CONFIGURABLE(heap,h,i)  DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
6612 #define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(heap,h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
6613 
6614 #define DUK_PROPDESC_IS_WRITABLE(p)             (((p)->flags & DUK_PROPDESC_FLAG_WRITABLE) != 0)
6615 #define DUK_PROPDESC_IS_ENUMERABLE(p)           (((p)->flags & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
6616 #define DUK_PROPDESC_IS_CONFIGURABLE(p)         (((p)->flags & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
6617 #define DUK_PROPDESC_IS_ACCESSOR(p)             (((p)->flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
6618 
6619 #define DUK_HOBJECT_HASHIDX_UNUSED              0xffffffffUL
6620 #define DUK_HOBJECT_HASHIDX_DELETED             0xfffffffeUL
6621 
6622 /*
6623  *  Macros for accessing size fields
6624  */
6625 
6626 #if defined(DUK_USE_OBJSIZES16)
6627 #define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size16)
6628 #define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size16 = (v); } while (0)
6629 #define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next16)
6630 #define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next16 = (v); } while (0)
6631 #define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next16++)
6632 #define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size16)
6633 #define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size16 = (v); } while (0)
6634 #if defined(DUK_USE_HOBJECT_HASH_PART)
6635 #define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size16)
6636 #define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size16 = (v); } while (0)
6637 #else
6638 #define DUK_HOBJECT_GET_HSIZE(h) 0
6639 #define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
6640 #endif
6641 #else
6642 #define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size)
6643 #define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size = (v); } while (0)
6644 #define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next)
6645 #define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next = (v); } while (0)
6646 #define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next++)
6647 #define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size)
6648 #define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size = (v); } while (0)
6649 #if defined(DUK_USE_HOBJECT_HASH_PART)
6650 #define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size)
6651 #define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size = (v); } while (0)
6652 #else
6653 #define DUK_HOBJECT_GET_HSIZE(h) 0
6654 #define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
6655 #endif
6656 #endif
6657 
6658 /*
6659  *  Misc
6660  */
6661 
6662 /* Maximum prototype traversal depth.  Sanity limit which handles e.g.
6663  * prototype loops (even complex ones like 1->2->3->4->2->3->4->2->3->4).
6664  */
6665 #define DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY      10000L
6666 
6667 /*
6668  *  ECMAScript [[Class]]
6669  */
6670 
6671 /* range check not necessary because all 4-bit values are mapped */
6672 #define DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(n)  duk_class_number_to_stridx[(n)]
6673 
6674 #define DUK_HOBJECT_GET_CLASS_STRING(heap,h)          \
6675 	DUK_HEAP_GET_STRING( \
6676 		(heap), \
6677 		DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(DUK_HOBJECT_GET_CLASS_NUMBER((h))) \
6678 	)
6679 
6680 /*
6681  *  Macros for property handling
6682  */
6683 
6684 #if defined(DUK_USE_HEAPPTR16)
6685 #define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
6686 	((duk_hobject *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->prototype16))
6687 #define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
6688 		(h)->prototype16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
6689 	} while (0)
6690 #else
6691 #define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
6692 	((h)->prototype)
6693 #define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
6694 		(h)->prototype = (x); \
6695 	} while (0)
6696 #endif
6697 
6698 /* Set prototype, DECREF earlier value, INCREF new value (tolerating NULLs). */
6699 #define DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr,h,p)       duk_hobject_set_prototype_updref((thr), (h), (p))
6700 
6701 /* Set initial prototype, assume NULL previous prototype, INCREF new value,
6702  * tolerate NULL.
6703  */
6704 #define DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr,h,proto) do { \
6705 		duk_hthread *duk__thr = (thr); \
6706 		duk_hobject *duk__obj = (h); \
6707 		duk_hobject *duk__proto = (proto); \
6708 		DUK_UNREF(duk__thr); \
6709 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(duk__thr->heap, duk__obj) == NULL); \
6710 		DUK_HOBJECT_SET_PROTOTYPE(duk__thr->heap, duk__obj, duk__proto); \
6711 		DUK_HOBJECT_INCREF_ALLOWNULL(duk__thr, duk__proto); \
6712 	} while (0)
6713 
6714 /*
6715  *  Finalizer check
6716  */
6717 
6718 #if defined(DUK_USE_HEAPPTR16)
6719 #define DUK_HOBJECT_HAS_FINALIZER_FAST(heap,h) duk_hobject_has_finalizer_fast_raw((heap), (h))
6720 #else
6721 #define DUK_HOBJECT_HAS_FINALIZER_FAST(heap,h) duk_hobject_has_finalizer_fast_raw((h))
6722 #endif
6723 
6724 /*
6725  *  Resizing and hash behavior
6726  */
6727 
6728 /* Sanity limit on max number of properties (allocated, not necessarily used).
6729  * This is somewhat arbitrary, but if we're close to 2**32 properties some
6730  * algorithms will fail (e.g. hash size selection, next prime selection).
6731  * Also, we use negative array/entry table indices to indicate 'not found',
6732  * so anything above 0x80000000 will cause trouble now.
6733  */
6734 #if defined(DUK_USE_OBJSIZES16)
6735 #define DUK_HOBJECT_MAX_PROPERTIES       0x0000ffffUL
6736 #else
6737 #define DUK_HOBJECT_MAX_PROPERTIES       0x3fffffffUL   /* 2**30-1 ~= 1G properties */
6738 #endif
6739 
6740 /* internal align target for props allocation, must be 2*n for some n */
6741 #if (DUK_USE_ALIGN_BY == 4)
6742 #define DUK_HOBJECT_ALIGN_TARGET         4
6743 #elif (DUK_USE_ALIGN_BY == 8)
6744 #define DUK_HOBJECT_ALIGN_TARGET         8
6745 #elif (DUK_USE_ALIGN_BY == 1)
6746 #define DUK_HOBJECT_ALIGN_TARGET         1
6747 #else
6748 #error invalid DUK_USE_ALIGN_BY
6749 #endif
6750 
6751 /*
6752  *  PC-to-line constants
6753  */
6754 
6755 #define DUK_PC2LINE_SKIP    64
6756 
6757 /* maximum length for a SKIP-1 diffstream: 35 bits per entry, rounded up to bytes */
6758 #define DUK_PC2LINE_MAX_DIFF_LENGTH    (((DUK_PC2LINE_SKIP - 1) * 35 + 7) / 8)
6759 
6760 /*
6761  *  Struct defs
6762  */
6763 
6764 struct duk_propaccessor {
6765 	duk_hobject *get;
6766 	duk_hobject *set;
6767 };
6768 
6769 union duk_propvalue {
6770 	/* The get/set pointers could be 16-bit pointer compressed but it
6771 	 * would make no difference on 32-bit platforms because duk_tval is
6772 	 * 8 bytes or more anyway.
6773 	 */
6774 	duk_tval v;
6775 	duk_propaccessor a;
6776 };
6777 
6778 struct duk_propdesc {
6779 	/* read-only values 'lifted' for ease of use */
6780 	duk_small_uint_t flags;
6781 	duk_hobject *get;
6782 	duk_hobject *set;
6783 
6784 	/* for updating (all are set to < 0 for virtual properties) */
6785 	duk_int_t e_idx;  /* prop index in 'entry part', < 0 if not there */
6786 	duk_int_t h_idx;  /* prop index in 'hash part', < 0 if not there */
6787 	duk_int_t a_idx;  /* prop index in 'array part', < 0 if not there */
6788 };
6789 
6790 struct duk_hobject {
6791 	duk_heaphdr hdr;
6792 
6793 	/*
6794 	 *  'props' contains {key,value,flags} entries, optional array entries, and
6795 	 *  an optional hash lookup table for non-array entries in a single 'sliced'
6796 	 *  allocation.  There are several layout options, which differ slightly in
6797 	 *  generated code size/speed and alignment/padding; duk_features.h selects
6798 	 *  the layout used.
6799 	 *
6800 	 *  Layout 1 (DUK_USE_HOBJECT_LAYOUT_1):
6801 	 *
6802 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
6803 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
6804 	 *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_next gc reachable)
6805 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
6806 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
6807 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
6808 	 *
6809 	 *  Layout 2 (DUK_USE_HOBJECT_LAYOUT_2):
6810 	 *
6811 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
6812 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
6813 	 *    e_size * sizeof(duk_uint8_t) + pad     bytes of   entry flags (e_next gc reachable)
6814 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
6815 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
6816 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
6817 	 *
6818 	 *  Layout 3 (DUK_USE_HOBJECT_LAYOUT_3):
6819 	 *
6820 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
6821 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
6822 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
6823 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
6824 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
6825 	 *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_next gc reachable)
6826 	 *
6827 	 *  In layout 1, the 'e_next' count is rounded to 4 or 8 on platforms
6828 	 *  requiring 4 or 8 byte alignment.  This ensures proper alignment
6829 	 *  for the entries, at the cost of memory footprint.  However, it's
6830 	 *  probably preferable to use another layout on such platforms instead.
6831 	 *
6832 	 *  In layout 2, the key and value parts are swapped to avoid padding
6833 	 *  the key array on platforms requiring alignment by 8.  The flags part
6834 	 *  is padded to get alignment for array entries.  The 'e_next' count does
6835 	 *  not need to be rounded as in layout 1.
6836 	 *
6837 	 *  In layout 3, entry values and array values are always aligned properly,
6838 	 *  and assuming pointers are at most 8 bytes, so are the entry keys.  Hash
6839 	 *  indices will be properly aligned (assuming pointers are at least 4 bytes).
6840 	 *  Finally, flags don't need additional alignment.  This layout provides
6841 	 *  compact allocations without padding (even on platforms with alignment
6842 	 *  requirements) at the cost of a bit slower lookups.
6843 	 *
6844 	 *  Objects with few keys don't have a hash index; keys are looked up linearly,
6845 	 *  which is cache efficient because the keys are consecutive.  Larger objects
6846 	 *  have a hash index part which contains integer indexes to the entries part.
6847 	 *
6848 	 *  A single allocation reduces memory allocation overhead but requires more
6849 	 *  work when any part needs to be resized.  A sliced allocation for entries
6850 	 *  makes linear key matching faster on most platforms (more locality) and
6851 	 *  skimps on flags size (which would be followed by 3 bytes of padding in
6852 	 *  most architectures if entries were placed in a struct).
6853 	 *
6854 	 *  'props' also contains internal properties distinguished with a non-BMP
6855 	 *  prefix.  Often used properties should be placed early in 'props' whenever
6856 	 *  possible to make accessing them as fast a possible.
6857 	 */
6858 
6859 #if defined(DUK_USE_HEAPPTR16)
6860 	/* Located in duk_heaphdr h_extra16.  Subclasses of duk_hobject (like
6861 	 * duk_hcompfunc) are not free to use h_extra16 for this reason.
6862 	 */
6863 #else
6864 	duk_uint8_t *props;
6865 #endif
6866 
6867 	/* prototype: the only internal property lifted outside 'e' as it is so central */
6868 #if defined(DUK_USE_HEAPPTR16)
6869 	duk_uint16_t prototype16;
6870 #else
6871 	duk_hobject *prototype;
6872 #endif
6873 
6874 #if defined(DUK_USE_OBJSIZES16)
6875 	duk_uint16_t e_size16;
6876 	duk_uint16_t e_next16;
6877 	duk_uint16_t a_size16;
6878 #if defined(DUK_USE_HOBJECT_HASH_PART)
6879 	duk_uint16_t h_size16;
6880 #endif
6881 #else
6882 	duk_uint32_t e_size;  /* entry part size */
6883 	duk_uint32_t e_next;  /* index for next new key ([0,e_next[ are gc reachable) */
6884 	duk_uint32_t a_size;  /* array part size (entirely gc reachable) */
6885 #if defined(DUK_USE_HOBJECT_HASH_PART)
6886 	duk_uint32_t h_size;  /* hash part size or 0 if unused */
6887 #endif
6888 #endif
6889 };
6890 
6891 /*
6892  *  Exposed data
6893  */
6894 
6895 #if !defined(DUK_SINGLE_FILE)
6896 DUK_INTERNAL_DECL duk_uint8_t duk_class_number_to_stridx[32];
6897 #endif  /* !DUK_SINGLE_FILE */
6898 
6899 /*
6900  *  Prototypes
6901  */
6902 
6903 /* alloc and init */
6904 DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags);
6905 DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6906 DUK_INTERNAL_DECL duk_harray *duk_harray_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6907 DUK_INTERNAL_DECL duk_hcompfunc *duk_hcompfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6908 DUK_INTERNAL_DECL duk_hnatfunc *duk_hnatfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6909 DUK_INTERNAL_DECL duk_hboundfunc *duk_hboundfunc_alloc(duk_heap *heap, duk_uint_t hobject_flags);
6910 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6911 DUK_INTERNAL_DECL duk_hbufobj *duk_hbufobj_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6912 #endif
6913 DUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags);
6914 DUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6915 DUK_INTERNAL_DECL duk_hdecenv *duk_hdecenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6916 DUK_INTERNAL_DECL duk_hobjenv *duk_hobjenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6917 DUK_INTERNAL_DECL duk_hproxy *duk_hproxy_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6918 
6919 /* resize */
6920 DUK_INTERNAL_DECL void duk_hobject_realloc_props(duk_hthread *thr,
6921                                                  duk_hobject *obj,
6922                                                  duk_uint32_t new_e_size,
6923                                                  duk_uint32_t new_a_size,
6924                                                  duk_uint32_t new_h_size,
6925                                                  duk_bool_t abandon_array);
6926 DUK_INTERNAL_DECL void duk_hobject_resize_entrypart(duk_hthread *thr,
6927                                                     duk_hobject *obj,
6928                                                     duk_uint32_t new_e_size);
6929 #if 0  /*unused*/
6930 DUK_INTERNAL_DECL void duk_hobject_resize_arraypart(duk_hthread *thr,
6931                                                     duk_hobject *obj,
6932                                                     duk_uint32_t new_a_size);
6933 #endif
6934 
6935 /* low-level property functions */
6936 DUK_INTERNAL_DECL duk_bool_t duk_hobject_find_existing_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx);
6937 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key);
6938 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_uint_t *out_attrs);
6939 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i);
6940 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);
6941 
6942 /* XXX: when optimizing for guaranteed property slots, use a guaranteed
6943  * slot for internal value; this call can then access it directly.
6944  */
6945 #define duk_hobject_get_internal_value_tval_ptr(heap,obj) \
6946 	duk_hobject_find_existing_entry_tval_ptr((heap), (obj), DUK_HEAP_STRING_INT_VALUE((heap)))
6947 
6948 /* core property functions */
6949 DUK_INTERNAL_DECL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
6950 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);
6951 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);
6952 DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
6953 
6954 /* internal property functions */
6955 #define DUK_DELPROP_FLAG_THROW  (1U << 0)
6956 #define DUK_DELPROP_FLAG_FORCE  (1U << 1)
6957 DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
6958 DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key);
6959 DUK_INTERNAL_DECL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
6960 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);
6961 DUK_INTERNAL_DECL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj);
6962 #if defined(DUK_USE_HEAPPTR16)
6963 DUK_INTERNAL_DECL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_heap *heap, duk_hobject *obj);
6964 #else
6965 DUK_INTERNAL_DECL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_hobject *obj);
6966 #endif
6967 
6968 /* helpers for defineProperty() and defineProperties() */
6969 DUK_INTERNAL_DECL void duk_hobject_prepare_property_descriptor(duk_hthread *thr,
6970                                                                duk_idx_t idx_in,
6971                                                                duk_uint_t *out_defprop_flags,
6972                                                                duk_idx_t *out_idx_value,
6973                                                                duk_hobject **out_getter,
6974                                                                duk_hobject **out_setter);
6975 DUK_INTERNAL_DECL duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
6976                                                                 duk_uint_t defprop_flags,
6977                                                                 duk_hobject *obj,
6978                                                                 duk_hstring *key,
6979                                                                 duk_idx_t idx_value,
6980                                                                 duk_hobject *get,
6981                                                                 duk_hobject *set,
6982                                                                 duk_bool_t throw_flag);
6983 
6984 /* Object built-in methods */
6985 DUK_INTERNAL_DECL void duk_hobject_object_get_own_property_descriptor(duk_hthread *thr, duk_idx_t obj_idx);
6986 DUK_INTERNAL_DECL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze);
6987 DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen);
6988 DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_ownprop_helper(duk_hthread *thr, duk_small_uint_t required_desc_flags);
6989 
6990 /* internal properties */
6991 DUK_INTERNAL_DECL duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv);
6992 DUK_INTERNAL_DECL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj);
6993 
6994 /* hobject management functions */
6995 DUK_INTERNAL_DECL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj);
6996 
6997 /* ES2015 proxy */
6998 #if defined(DUK_USE_ES6_PROXY)
6999 DUK_INTERNAL_DECL duk_bool_t duk_hobject_proxy_check(duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler);
7000 DUK_INTERNAL_DECL duk_hobject *duk_hobject_resolve_proxy_target(duk_hobject *obj);
7001 #endif
7002 
7003 /* enumeration */
7004 DUK_INTERNAL_DECL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint_t enum_flags);
7005 DUK_INTERNAL_DECL duk_ret_t duk_hobject_get_enumerated_keys(duk_hthread *thr, duk_small_uint_t enum_flags);
7006 DUK_INTERNAL_DECL duk_bool_t duk_hobject_enumerator_next(duk_hthread *thr, duk_bool_t get_value);
7007 
7008 /* macros */
7009 DUK_INTERNAL_DECL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p);
7010 
7011 /* pc2line */
7012 #if defined(DUK_USE_PC2LINE)
7013 DUK_INTERNAL_DECL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length);
7014 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_idx_t idx_func, duk_uint_fast32_t pc);
7015 #endif
7016 
7017 /* misc */
7018 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);
7019 
7020 #if !defined(DUK_USE_OBJECT_BUILTIN)
7021 /* These declarations are needed when related built-in is disabled and
7022  * genbuiltins.py won't automatically emit the declerations.
7023  */
7024 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_hthread *thr);
7025 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_hthread *thr);
7026 #endif
7027 
7028 #endif  /* DUK_HOBJECT_H_INCLUDED */
7029 /* #include duk_hcompfunc.h */
7030 #line 1 "duk_hcompfunc.h"
7031 /*
7032  *  Heap compiled function (ECMAScript function) representation.
7033  *
7034  *  There is a single data buffer containing the ECMAScript function's
7035  *  bytecode, constants, and inner functions.
7036  */
7037 
7038 #if !defined(DUK_HCOMPFUNC_H_INCLUDED)
7039 #define DUK_HCOMPFUNC_H_INCLUDED
7040 
7041 /*
7042  *  Field accessor macros
7043  */
7044 
7045 /* XXX: casts could be improved, especially for GET/SET DATA */
7046 
7047 #if defined(DUK_USE_HEAPPTR16)
7048 #define DUK_HCOMPFUNC_GET_DATA(heap,h) \
7049 	((duk_hbuffer_fixed *) (void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16))
7050 #define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \
7051 		(h)->data16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7052 	} while (0)
7053 #define DUK_HCOMPFUNC_GET_FUNCS(heap,h)  \
7054 	((duk_hobject **) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->funcs16)))
7055 #define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v)  do { \
7056 		(h)->funcs16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7057 	} while (0)
7058 #define DUK_HCOMPFUNC_GET_BYTECODE(heap,h)  \
7059 	((duk_instr_t *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->bytecode16)))
7060 #define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v)  do { \
7061 		(h)->bytecode16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7062 	} while (0)
7063 #define DUK_HCOMPFUNC_GET_LEXENV(heap,h)  \
7064 	((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->lex_env16)))
7065 #define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v)  do { \
7066 		(h)->lex_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7067 	} while (0)
7068 #define DUK_HCOMPFUNC_GET_VARENV(heap,h)  \
7069 	((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->var_env16)))
7070 #define DUK_HCOMPFUNC_SET_VARENV(heap,h,v)  do { \
7071 		(h)->var_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7072 	} while (0)
7073 #else
7074 #define DUK_HCOMPFUNC_GET_DATA(heap,h)  ((duk_hbuffer_fixed *) (void *) (h)->data)
7075 #define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \
7076 		(h)->data = (duk_hbuffer *) (v); \
7077 	} while (0)
7078 #define DUK_HCOMPFUNC_GET_FUNCS(heap,h)  ((h)->funcs)
7079 #define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v)  do { \
7080 		(h)->funcs = (v); \
7081 	} while (0)
7082 #define DUK_HCOMPFUNC_GET_BYTECODE(heap,h)  ((h)->bytecode)
7083 #define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v)  do { \
7084 		(h)->bytecode = (v); \
7085 	} while (0)
7086 #define DUK_HCOMPFUNC_GET_LEXENV(heap,h)  ((h)->lex_env)
7087 #define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v)  do { \
7088 		(h)->lex_env = (v); \
7089 	} while (0)
7090 #define DUK_HCOMPFUNC_GET_VARENV(heap,h)  ((h)->var_env)
7091 #define DUK_HCOMPFUNC_SET_VARENV(heap,h,v)  do { \
7092 		(h)->var_env = (v); \
7093 	} while (0)
7094 #endif
7095 
7096 /*
7097  *  Accessor macros for function specific data areas
7098  */
7099 
7100 /* Note: assumes 'data' is always a fixed buffer */
7101 #define DUK_HCOMPFUNC_GET_BUFFER_BASE(heap,h)  \
7102 	DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h)))
7103 
7104 #define DUK_HCOMPFUNC_GET_CONSTS_BASE(heap,h)  \
7105 	((duk_tval *) (void *) DUK_HCOMPFUNC_GET_BUFFER_BASE((heap), (h)))
7106 
7107 #define DUK_HCOMPFUNC_GET_FUNCS_BASE(heap,h)  \
7108 	DUK_HCOMPFUNC_GET_FUNCS((heap), (h))
7109 
7110 #define DUK_HCOMPFUNC_GET_CODE_BASE(heap,h)  \
7111 	DUK_HCOMPFUNC_GET_BYTECODE((heap), (h))
7112 
7113 #define DUK_HCOMPFUNC_GET_CONSTS_END(heap,h)  \
7114 	((duk_tval *) (void *) DUK_HCOMPFUNC_GET_FUNCS((heap), (h)))
7115 
7116 #define DUK_HCOMPFUNC_GET_FUNCS_END(heap,h)  \
7117 	((duk_hobject **) (void *) DUK_HCOMPFUNC_GET_BYTECODE((heap), (h)))
7118 
7119 /* XXX: double evaluation of DUK_HCOMPFUNC_GET_DATA() */
7120 #define DUK_HCOMPFUNC_GET_CODE_END(heap,h)  \
7121 	((duk_instr_t *) (void *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h))) + \
7122 	                DUK_HBUFFER_GET_SIZE((duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA((heap), h))))
7123 
7124 #define DUK_HCOMPFUNC_GET_CONSTS_SIZE(heap,h)  \
7125 	( \
7126 	 (duk_size_t) \
7127 	 ( \
7128 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_END((heap), (h))) - \
7129 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_BASE((heap), (h))) \
7130 	 ) \
7131 	)
7132 
7133 #define DUK_HCOMPFUNC_GET_FUNCS_SIZE(heap,h)  \
7134 	( \
7135 	 (duk_size_t) \
7136 	 ( \
7137 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_END((heap), (h))) - \
7138 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_BASE((heap), (h))) \
7139 	 ) \
7140 	)
7141 
7142 #define DUK_HCOMPFUNC_GET_CODE_SIZE(heap,h)  \
7143 	( \
7144 	 (duk_size_t) \
7145 	 ( \
7146 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_END((heap),(h))) - \
7147 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_BASE((heap),(h))) \
7148 	 ) \
7149 	)
7150 
7151 #define DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap,h)  \
7152 	((duk_size_t) (DUK_HCOMPFUNC_GET_CONSTS_SIZE((heap), (h)) / sizeof(duk_tval)))
7153 
7154 #define DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap,h)  \
7155 	((duk_size_t) (DUK_HCOMPFUNC_GET_FUNCS_SIZE((heap), (h)) / sizeof(duk_hobject *)))
7156 
7157 #define DUK_HCOMPFUNC_GET_CODE_COUNT(heap,h)  \
7158 	((duk_size_t) (DUK_HCOMPFUNC_GET_CODE_SIZE((heap), (h)) / sizeof(duk_instr_t)))
7159 
7160 /*
7161  *  Validity assert
7162  */
7163 
7164 #define DUK_ASSERT_HCOMPFUNC_VALID(h) do { \
7165 		DUK_ASSERT((h) != NULL); \
7166 	} while (0)
7167 
7168 /*
7169  *  Main struct
7170  */
7171 
7172 struct duk_hcompfunc {
7173 	/* shared object part */
7174 	duk_hobject obj;
7175 
7176 	/*
7177 	 *  Pointers to function data area for faster access.  Function
7178 	 *  data is a buffer shared between all closures of the same
7179 	 *  "template" function.  The data buffer is always fixed (non-
7180 	 *  dynamic, hence stable), with a layout as follows:
7181 	 *
7182 	 *    constants (duk_tval)
7183 	 *    inner functions (duk_hobject *)
7184 	 *    bytecode (duk_instr_t)
7185 	 *
7186 	 *  Note: bytecode end address can be computed from 'data' buffer
7187 	 *  size.  It is not strictly necessary functionally, assuming
7188 	 *  bytecode never jumps outside its allocated area.  However,
7189 	 *  it's a safety/robustness feature for avoiding the chance of
7190 	 *  executing random data as bytecode due to a compiler error.
7191 	 *
7192 	 *  Note: values in the data buffer must be incref'd (they will
7193 	 *  be decref'd on release) for every compiledfunction referring
7194 	 *  to the 'data' element.
7195 	 */
7196 
7197 	/* Data area, fixed allocation, stable data ptrs. */
7198 #if defined(DUK_USE_HEAPPTR16)
7199 	duk_uint16_t data16;
7200 #else
7201 	duk_hbuffer *data;
7202 #endif
7203 
7204 	/* No need for constants pointer (= same as data).
7205 	 *
7206 	 * When using 16-bit packing alignment to 4 is nice.  'funcs' will be
7207 	 * 4-byte aligned because 'constants' are duk_tvals.  For now the
7208 	 * inner function pointers are not compressed, so that 'bytecode' will
7209 	 * also be 4-byte aligned.
7210 	 */
7211 #if defined(DUK_USE_HEAPPTR16)
7212 	duk_uint16_t funcs16;
7213 	duk_uint16_t bytecode16;
7214 #else
7215 	duk_hobject **funcs;
7216 	duk_instr_t *bytecode;
7217 #endif
7218 
7219 	/* Lexenv: lexical environment of closure, NULL for templates.
7220 	 * Varenv: variable environment of closure, NULL for templates.
7221 	 */
7222 #if defined(DUK_USE_HEAPPTR16)
7223 	duk_uint16_t lex_env16;
7224 	duk_uint16_t var_env16;
7225 #else
7226 	duk_hobject *lex_env;
7227 	duk_hobject *var_env;
7228 #endif
7229 
7230 	/*
7231 	 *  'nregs' registers are allocated on function entry, at most 'nargs'
7232 	 *  are initialized to arguments, and the rest to undefined.  Arguments
7233 	 *  above 'nregs' are not mapped to registers.  All registers in the
7234 	 *  active stack range must be initialized because they are GC reachable.
7235 	 *  'nargs' is needed so that if the function is given more than 'nargs'
7236 	 *  arguments, the additional arguments do not 'clobber' registers
7237 	 *  beyond 'nregs' which must be consistently initialized to undefined.
7238 	 *
7239 	 *  Usually there is no need to know which registers are mapped to
7240 	 *  local variables.  Registers may be allocated to variable in any
7241 	 *  way (even including gaps).  However, a register-variable mapping
7242 	 *  must be the same for the duration of the function execution and
7243 	 *  the register cannot be used for anything else.
7244 	 *
7245 	 *  When looking up variables by name, the '_Varmap' map is used.
7246 	 *  When an activation closes, registers mapped to arguments are
7247 	 *  copied into the environment record based on the same map.  The
7248 	 *  reverse map (from register to variable) is not currently needed
7249 	 *  at run time, except for debugging, so it is not maintained.
7250 	 */
7251 
7252 	duk_uint16_t nregs;                /* regs to allocate */
7253 	duk_uint16_t nargs;                /* number of arguments allocated to regs */
7254 
7255 	/*
7256 	 *  Additional control information is placed into the object itself
7257 	 *  as internal properties to avoid unnecessary fields for the
7258 	 *  majority of functions.  The compiler tries to omit internal
7259 	 *  control fields when possible.
7260 	 *
7261 	 *  Function templates:
7262 	 *
7263 	 *    {
7264 	 *      name: "func",    // declaration, named function expressions
7265 	 *      fileName: <debug info for creating nice errors>
7266 	 *      _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
7267 	 *      _Formals: [ "arg1", "arg2" ],
7268 	 *      _Source: "function func(arg1, arg2) { ... }",
7269 	 *      _Pc2line: <debug info for pc-to-line mapping>,
7270 	 *    }
7271 	 *
7272 	 *  Function instances:
7273 	 *
7274 	 *    {
7275 	 *      length: 2,
7276 	 *      prototype: { constructor: <func> },
7277 	 *      caller: <thrower>,
7278 	 *      arguments: <thrower>,
7279 	 *      name: "func",    // declaration, named function expressions
7280 	 *      fileName: <debug info for creating nice errors>
7281 	 *      _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
7282 	 *      _Formals: [ "arg1", "arg2" ],
7283 	 *      _Source: "function func(arg1, arg2) { ... }",
7284 	 *      _Pc2line: <debug info for pc-to-line mapping>,
7285 	 *    }
7286 	 *
7287 	 *  More detailed description of these properties can be found
7288 	 *  in the documentation.
7289 	 */
7290 
7291 #if defined(DUK_USE_DEBUGGER_SUPPORT)
7292 	/* Line number range for function.  Needed during debugging to
7293 	 * determine active breakpoints.
7294 	 */
7295 	duk_uint32_t start_line;
7296 	duk_uint32_t end_line;
7297 #endif
7298 };
7299 
7300 #endif  /* DUK_HCOMPFUNC_H_INCLUDED */
7301 /* #include duk_hnatfunc.h */
7302 #line 1 "duk_hnatfunc.h"
7303 /*
7304  *  Heap native function representation.
7305  */
7306 
7307 #if !defined(DUK_HNATFUNC_H_INCLUDED)
7308 #define DUK_HNATFUNC_H_INCLUDED
7309 
7310 #define DUK_HNATFUNC_NARGS_VARARGS  ((duk_int16_t) -1)
7311 #define DUK_HNATFUNC_NARGS_MAX      ((duk_int16_t) 0x7fff)
7312 
7313 struct duk_hnatfunc {
7314 	/* shared object part */
7315 	duk_hobject obj;
7316 
7317 	duk_c_function func;
7318 	duk_int16_t nargs;
7319 	duk_int16_t magic;
7320 
7321 	/* The 'magic' field allows an opaque 16-bit field to be accessed by the
7322 	 * Duktape/C function.  This allows, for instance, the same native function
7323 	 * to be used for a set of very similar functions, with the 'magic' field
7324 	 * providing the necessary non-argument flags / values to guide the behavior
7325 	 * of the native function.  The value is signed on purpose: it is easier to
7326 	 * convert a signed value to unsigned (simply AND with 0xffff) than vice
7327 	 * versa.
7328 	 *
7329 	 * Note: cannot place nargs/magic into the heaphdr flags, because
7330 	 * duk_hobject takes almost all flags already.
7331 	 */
7332 };
7333 
7334 #endif  /* DUK_HNATFUNC_H_INCLUDED */
7335 /* #include duk_hboundfunc.h */
7336 #line 1 "duk_hboundfunc.h"
7337 /*
7338  *  Bound function representation.
7339  */
7340 
7341 #if !defined(DUK_HBOUNDFUNC_H_INCLUDED)
7342 #define DUK_HBOUNDFUNC_H_INCLUDED
7343 
7344 /* Artificial limit for args length.  Ensures arithmetic won't overflow
7345  * 32 bits when combining bound functions.
7346  */
7347 #define DUK_HBOUNDFUNC_MAX_ARGS 0x20000000UL
7348 
7349 #define DUK_ASSERT_HBOUNDFUNC_VALID(h) do { \
7350 		DUK_ASSERT((h) != NULL); \
7351 		DUK_ASSERT(DUK_HOBJECT_IS_BOUNDFUNC((duk_hobject *) (h))); \
7352 		DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(&(h)->target) || \
7353 		           (DUK_TVAL_IS_OBJECT(&(h)->target) && \
7354 		            DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(&(h)->target)))); \
7355 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(&(h)->this_binding)); \
7356 		DUK_ASSERT((h)->nargs == 0 || (h)->args != NULL); \
7357 	} while (0)
7358 
7359 struct duk_hboundfunc {
7360 	/* Shared object part. */
7361 	duk_hobject obj;
7362 
7363 	/* Final target function, stored as duk_tval so that lightfunc can be
7364 	 * represented too.
7365 	 */
7366 	duk_tval target;
7367 
7368 	/* This binding. */
7369 	duk_tval this_binding;
7370 
7371 	/* Arguments to prepend. */
7372 	duk_tval *args;  /* Separate allocation. */
7373 	duk_idx_t nargs;
7374 };
7375 
7376 #endif  /* DUK_HBOUNDFUNC_H_INCLUDED */
7377 /* #include duk_hbufobj.h */
7378 #line 1 "duk_hbufobj.h"
7379 /*
7380  *  Heap Buffer object representation.  Used for all Buffer variants.
7381  */
7382 
7383 #if !defined(DUK_HBUFOBJ_H_INCLUDED)
7384 #define DUK_HBUFOBJ_H_INCLUDED
7385 
7386 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
7387 
7388 /* All element accessors are host endian now (driven by TypedArray spec). */
7389 #define DUK_HBUFOBJ_ELEM_UINT8           0
7390 #define DUK_HBUFOBJ_ELEM_UINT8CLAMPED    1
7391 #define DUK_HBUFOBJ_ELEM_INT8            2
7392 #define DUK_HBUFOBJ_ELEM_UINT16          3
7393 #define DUK_HBUFOBJ_ELEM_INT16           4
7394 #define DUK_HBUFOBJ_ELEM_UINT32          5
7395 #define DUK_HBUFOBJ_ELEM_INT32           6
7396 #define DUK_HBUFOBJ_ELEM_FLOAT32         7
7397 #define DUK_HBUFOBJ_ELEM_FLOAT64         8
7398 #define DUK_HBUFOBJ_ELEM_MAX             8
7399 
7400 #define DUK_ASSERT_HBUFOBJ_VALID(h) do { \
7401 		DUK_ASSERT((h) != NULL); \
7402 		DUK_ASSERT((h)->shift <= 3); \
7403 		DUK_ASSERT((h)->elem_type <= DUK_HBUFOBJ_ELEM_MAX); \
7404 		DUK_ASSERT(((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT8) || \
7405 		           ((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT8CLAMPED) || \
7406 		           ((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT8) || \
7407 		           ((h)->shift == 1 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT16) || \
7408 		           ((h)->shift == 1 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT16) || \
7409 		           ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT32) || \
7410 		           ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT32) || \
7411 		           ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_FLOAT32) || \
7412 		           ((h)->shift == 3 && (h)->elem_type == DUK_HBUFOBJ_ELEM_FLOAT64)); \
7413 		DUK_ASSERT((h)->is_typedarray == 0 || (h)->is_typedarray == 1); \
7414 		DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) (h))); \
7415 		if ((h)->buf == NULL) { \
7416 			DUK_ASSERT((h)->offset == 0); \
7417 			DUK_ASSERT((h)->length == 0); \
7418 		} else { \
7419 			/* No assertions for offset or length; in particular, \
7420 			 * it's OK for length to be longer than underlying \
7421 			 * buffer.  Just ensure they don't wrap when added. \
7422 			 */ \
7423 			DUK_ASSERT((h)->offset + (h)->length >= (h)->offset); \
7424 		} \
7425 	} while (0)
7426 
7427 /* Get the current data pointer (caller must ensure buf != NULL) as a
7428  * duk_uint8_t ptr.  Note that the result may be NULL if the underlying
7429  * buffer has zero size and is not a fixed buffer.
7430  */
7431 #define DUK_HBUFOBJ_GET_SLICE_BASE(heap,h) \
7432 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7433 	(((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR((heap), (h)->buf)) + (h)->offset))
7434 
7435 /* True if slice is full, i.e. offset is zero and length covers the entire
7436  * buffer.  This status may change independently of the duk_hbufobj if
7437  * the underlying buffer is dynamic and changes without the hbufobj
7438  * being changed.
7439  */
7440 #define DUK_HBUFOBJ_FULL_SLICE(h) \
7441 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7442 	((h)->offset == 0 && (h)->length == DUK_HBUFFER_GET_SIZE((h)->buf)))
7443 
7444 /* Validate that the whole slice [0,length[ is contained in the underlying
7445  * buffer.  Caller must ensure 'buf' != NULL.
7446  */
7447 #define DUK_HBUFOBJ_VALID_SLICE(h) \
7448 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7449 	((h)->offset + (h)->length <= DUK_HBUFFER_GET_SIZE((h)->buf)))
7450 
7451 /* Validate byte read/write for virtual 'offset', i.e. check that the
7452  * offset, taking into account h->offset, is within the underlying
7453  * buffer size.  This is a safety check which is needed to ensure
7454  * that even a misconfigured duk_hbufobj never causes memory unsafe
7455  * behavior (e.g. if an underlying dynamic buffer changes after being
7456  * setup).  Caller must ensure 'buf' != NULL.
7457  */
7458 #define DUK_HBUFOBJ_VALID_BYTEOFFSET_INCL(h,off) \
7459 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7460 	((h)->offset + (off) < DUK_HBUFFER_GET_SIZE((h)->buf)))
7461 
7462 #define DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h,off) \
7463 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7464 	((h)->offset + (off) <= DUK_HBUFFER_GET_SIZE((h)->buf)))
7465 
7466 /* Clamp an input byte length (already assumed to be within the nominal
7467  * duk_hbufobj 'length') to the current dynamic buffer limits to yield
7468  * a byte length limit that's safe for memory accesses.  This value can
7469  * be invalidated by any side effect because it may trigger a user
7470  * callback that resizes the underlying buffer.
7471  */
7472 #define DUK_HBUFOBJ_CLAMP_BYTELENGTH(h,len) \
7473 	(DUK_ASSERT_EXPR((h) != NULL), \
7474 	duk_hbufobj_clamp_bytelength((h), (len)))
7475 
7476 /* Typed arrays have virtual indices, ArrayBuffer and DataView do not. */
7477 #define DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h)  ((h)->is_typedarray)
7478 
7479 struct duk_hbufobj {
7480 	/* Shared object part. */
7481 	duk_hobject obj;
7482 
7483 	/* Underlying buffer (refcounted), may be NULL. */
7484 	duk_hbuffer *buf;
7485 
7486 	/* .buffer reference to an ArrayBuffer, may be NULL. */
7487 	duk_hobject *buf_prop;
7488 
7489 	/* Slice and accessor information.
7490 	 *
7491 	 * Because the underlying buffer may be dynamic, these may be
7492 	 * invalidated by the buffer being modified so that both offset
7493 	 * and length should be validated before every access.  Behavior
7494 	 * when the underlying buffer has changed doesn't need to be clean:
7495 	 * virtual 'length' doesn't need to be affected, reads can return
7496 	 * zero/NaN, and writes can be ignored.
7497 	 *
7498 	 * Note that a data pointer cannot be precomputed because 'buf' may
7499 	 * be dynamic and its pointer unstable.
7500 	 */
7501 
7502 	duk_uint_t offset;       /* byte offset to buf */
7503 	duk_uint_t length;       /* byte index limit for element access, exclusive */
7504 	duk_uint8_t shift;       /* element size shift:
7505 	                          *   0 = u8/i8
7506 	                          *   1 = u16/i16
7507 	                          *   2 = u32/i32/float
7508 	                          *   3 = double
7509 	                          */
7510 	duk_uint8_t elem_type;   /* element type */
7511 	duk_uint8_t is_typedarray;
7512 };
7513 
7514 DUK_INTERNAL_DECL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_uint_t len);
7515 DUK_INTERNAL_DECL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_hbuffer *h_buf);
7516 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);
7517 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);
7518 DUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx);
7519 
7520 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
7521 #endif  /* DUK_HBUFOBJ_H_INCLUDED */
7522 /* #include duk_hthread.h */
7523 #line 1 "duk_hthread.h"
7524 /*
7525  *  Heap thread object representation.
7526  *
7527  *  duk_hthread is also the 'context' for public API functions via a
7528  *  different typedef.  Most API calls operate on the topmost frame
7529  *  of the value stack only.
7530  */
7531 
7532 #if !defined(DUK_HTHREAD_H_INCLUDED)
7533 #define DUK_HTHREAD_H_INCLUDED
7534 
7535 /*
7536  *  Stack constants
7537  */
7538 
7539 /* Initial valstack size, roughly 0.7kiB. */
7540 #define DUK_VALSTACK_INITIAL_SIZE       96U
7541 
7542 /* Internal extra elements assumed on function entry, always added to
7543  * user-defined 'extra' for e.g. the duk_check_stack() call.
7544  */
7545 #define DUK_VALSTACK_INTERNAL_EXTRA     32U
7546 
7547 /* Number of elements guaranteed to be user accessible (in addition to call
7548  * arguments) on Duktape/C function entry.  This is the major public API
7549  * commitment.
7550  */
7551 #define DUK_VALSTACK_API_ENTRY_MINIMUM  DUK_API_ENTRY_STACK
7552 
7553 /*
7554  *  Activation defines
7555  */
7556 
7557 #define DUK_ACT_FLAG_STRICT             (1U << 0)  /* function executes in strict mode */
7558 #define DUK_ACT_FLAG_TAILCALLED         (1U << 1)  /* activation has tail called one or more times */
7559 #define DUK_ACT_FLAG_CONSTRUCT          (1U << 2)  /* function executes as a constructor (called via "new") */
7560 #define DUK_ACT_FLAG_PREVENT_YIELD      (1U << 3)  /* activation prevents yield (native call or "new") */
7561 #define DUK_ACT_FLAG_DIRECT_EVAL        (1U << 4)  /* activation is a direct eval call */
7562 #define DUK_ACT_FLAG_CONSTRUCT_PROXY    (1U << 5)  /* activation is for Proxy 'construct' call, special return value handling */
7563 #define DUK_ACT_FLAG_BREAKPOINT_ACTIVE  (1U << 6)  /* activation has active breakpoint(s) */
7564 
7565 #define DUK_ACT_GET_FUNC(act)           ((act)->func)
7566 
7567 /*
7568  *  Flags for __FILE__ / __LINE__ registered into tracedata
7569  */
7570 
7571 #define DUK_TB_FLAG_NOBLAME_FILELINE    (1U << 0)  /* don't report __FILE__ / __LINE__ as fileName/lineNumber */
7572 
7573 /*
7574  *  Catcher defines
7575  */
7576 
7577 /* XXX: remove catcher type entirely */
7578 
7579 /* flags field: LLLLLLFT, L = label (24 bits), F = flags (4 bits), T = type (4 bits) */
7580 #define DUK_CAT_TYPE_MASK            0x0000000fUL
7581 #define DUK_CAT_TYPE_BITS            4
7582 #define DUK_CAT_LABEL_MASK           0xffffff00UL
7583 #define DUK_CAT_LABEL_BITS           24
7584 #define DUK_CAT_LABEL_SHIFT          8
7585 
7586 #define DUK_CAT_FLAG_CATCH_ENABLED          (1U << 4)   /* catch part will catch */
7587 #define DUK_CAT_FLAG_FINALLY_ENABLED        (1U << 5)   /* finally part will catch */
7588 #define DUK_CAT_FLAG_CATCH_BINDING_ENABLED  (1U << 6)   /* request to create catch binding */
7589 #define DUK_CAT_FLAG_LEXENV_ACTIVE          (1U << 7)   /* catch or with binding is currently active */
7590 
7591 #define DUK_CAT_TYPE_UNKNOWN         0
7592 #define DUK_CAT_TYPE_TCF             1
7593 #define DUK_CAT_TYPE_LABEL           2
7594 
7595 #define DUK_CAT_GET_TYPE(c)          ((c)->flags & DUK_CAT_TYPE_MASK)
7596 #define DUK_CAT_GET_LABEL(c)         (((c)->flags & DUK_CAT_LABEL_MASK) >> DUK_CAT_LABEL_SHIFT)
7597 
7598 #define DUK_CAT_HAS_CATCH_ENABLED(c)           ((c)->flags & DUK_CAT_FLAG_CATCH_ENABLED)
7599 #define DUK_CAT_HAS_FINALLY_ENABLED(c)         ((c)->flags & DUK_CAT_FLAG_FINALLY_ENABLED)
7600 #define DUK_CAT_HAS_CATCH_BINDING_ENABLED(c)   ((c)->flags & DUK_CAT_FLAG_CATCH_BINDING_ENABLED)
7601 #define DUK_CAT_HAS_LEXENV_ACTIVE(c)           ((c)->flags & DUK_CAT_FLAG_LEXENV_ACTIVE)
7602 
7603 #define DUK_CAT_SET_CATCH_ENABLED(c)    do { \
7604 		(c)->flags |= DUK_CAT_FLAG_CATCH_ENABLED; \
7605 	} while (0)
7606 #define DUK_CAT_SET_FINALLY_ENABLED(c)  do { \
7607 		(c)->flags |= DUK_CAT_FLAG_FINALLY_ENABLED; \
7608 	} while (0)
7609 #define DUK_CAT_SET_CATCH_BINDING_ENABLED(c)    do { \
7610 		(c)->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
7611 	} while (0)
7612 #define DUK_CAT_SET_LEXENV_ACTIVE(c)    do { \
7613 		(c)->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE; \
7614 	} while (0)
7615 
7616 #define DUK_CAT_CLEAR_CATCH_ENABLED(c)    do { \
7617 		(c)->flags &= ~DUK_CAT_FLAG_CATCH_ENABLED; \
7618 	} while (0)
7619 #define DUK_CAT_CLEAR_FINALLY_ENABLED(c)  do { \
7620 		(c)->flags &= ~DUK_CAT_FLAG_FINALLY_ENABLED; \
7621 	} while (0)
7622 #define DUK_CAT_CLEAR_CATCH_BINDING_ENABLED(c)    do { \
7623 		(c)->flags &= ~DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
7624 	} while (0)
7625 #define DUK_CAT_CLEAR_LEXENV_ACTIVE(c)    do { \
7626 		(c)->flags &= ~DUK_CAT_FLAG_LEXENV_ACTIVE; \
7627 	} while (0)
7628 
7629 /*
7630  *  Thread defines
7631  */
7632 
7633 #if defined(DUK_USE_ROM_STRINGS)
7634 #define DUK_HTHREAD_GET_STRING(thr,idx) \
7635 	((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
7636 #else  /* DUK_USE_ROM_STRINGS */
7637 #if defined(DUK_USE_HEAPPTR16)
7638 #define DUK_HTHREAD_GET_STRING(thr,idx) \
7639 	((duk_hstring *) DUK_USE_HEAPPTR_DEC16((thr)->heap->heap_udata, (thr)->strs16[(idx)]))
7640 #else
7641 #define DUK_HTHREAD_GET_STRING(thr,idx) \
7642 	((thr)->strs[(idx)])
7643 #endif
7644 #endif  /* DUK_USE_ROM_STRINGS */
7645 
7646 /* values for the state field */
7647 #define DUK_HTHREAD_STATE_INACTIVE     1   /* thread not currently running */
7648 #define DUK_HTHREAD_STATE_RUNNING      2   /* thread currently running (only one at a time) */
7649 #define DUK_HTHREAD_STATE_RESUMED      3   /* thread resumed another thread (active but not running) */
7650 #define DUK_HTHREAD_STATE_YIELDED      4   /* thread has yielded */
7651 #define DUK_HTHREAD_STATE_TERMINATED   5   /* thread has terminated */
7652 
7653 /* Executor interrupt default interval when nothing else requires a
7654  * smaller value.  The default interval must be small enough to allow
7655  * for reasonable execution timeout checking but large enough to keep
7656  * impact on execution performance low.
7657  */
7658 #if defined(DUK_USE_INTERRUPT_COUNTER)
7659 #define DUK_HTHREAD_INTCTR_DEFAULT     (256L * 1024L)
7660 #endif
7661 
7662 /*
7663  *  Assert context is valid: non-NULL pointer, fields look sane.
7664  *
7665  *  This is used by public API call entrypoints to catch invalid 'ctx' pointers
7666  *  as early as possible; invalid 'ctx' pointers cause very odd and difficult to
7667  *  diagnose behavior so it's worth checking even when the check is not 100%.
7668  */
7669 
7670 /* Assertions for internals. */
7671 #define DUK_ASSERT_HTHREAD_VALID(thr) do { \
7672 		DUK_ASSERT((thr) != NULL); \
7673 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) (thr)) == DUK_HTYPE_OBJECT); \
7674 		DUK_ASSERT(DUK_HOBJECT_IS_THREAD((duk_hobject *) (thr))); \
7675 		DUK_ASSERT((thr)->unused1 == 0); \
7676 		DUK_ASSERT((thr)->unused2 == 0); \
7677 	} while (0)
7678 
7679 /* Assertions for public API calls; a bit stronger. */
7680 #define DUK_ASSERT_CTX_VALID(thr) do { \
7681 		DUK_ASSERT((thr) != NULL); \
7682 		DUK_ASSERT_HTHREAD_VALID((thr)); \
7683 		DUK_ASSERT((thr)->valstack != NULL); \
7684 		DUK_ASSERT((thr)->valstack_bottom != NULL); \
7685 		DUK_ASSERT((thr)->valstack_top != NULL); \
7686 		DUK_ASSERT((thr)->valstack_end != NULL); \
7687 		DUK_ASSERT((thr)->valstack_alloc_end != NULL); \
7688 		DUK_ASSERT((thr)->valstack_alloc_end >= (thr)->valstack); \
7689 		DUK_ASSERT((thr)->valstack_end >= (thr)->valstack); \
7690 		DUK_ASSERT((thr)->valstack_top >= (thr)->valstack); \
7691 		DUK_ASSERT((thr)->valstack_top >= (thr)->valstack_bottom); \
7692 		DUK_ASSERT((thr)->valstack_end >= (thr)->valstack_top); \
7693 		DUK_ASSERT((thr)->valstack_alloc_end >= (thr)->valstack_end); \
7694 	} while (0)
7695 
7696 /* Assertions for API call entry specifically.  Checks 'ctx' but also may
7697  * check internal state (e.g. not in a debugger transport callback).
7698  */
7699 #define DUK_ASSERT_API_ENTRY(thr) do { \
7700 		DUK_ASSERT_CTX_VALID((thr)); \
7701 		DUK_ASSERT((thr)->heap != NULL); \
7702 		DUK_ASSERT((thr)->heap->dbg_calling_transport == 0); \
7703 	} while (0)
7704 
7705 /*
7706  *  Assertion helpers.
7707  */
7708 
7709 #define DUK_ASSERT_STRIDX_VALID(val) \
7710 	DUK_ASSERT((duk_uint_t) (val) < DUK_HEAP_NUM_STRINGS)
7711 
7712 #define DUK_ASSERT_BIDX_VALID(val) \
7713 	DUK_ASSERT((duk_uint_t) (val) < DUK_NUM_BUILTINS)
7714 
7715 /*
7716  *  Misc
7717  */
7718 
7719 /* Fast access to 'this' binding.  Assumes there's a call in progress. */
7720 #define DUK_HTHREAD_THIS_PTR(thr) \
7721 	(DUK_ASSERT_EXPR((thr) != NULL), \
7722 	 DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \
7723 	 (thr)->valstack_bottom - 1)
7724 
7725 /*
7726  *  Struct defines
7727  */
7728 
7729 /* Fields are ordered for alignment/packing. */
7730 struct duk_activation {
7731 	duk_tval tv_func;       /* borrowed: full duk_tval for function being executed; for lightfuncs */
7732 	duk_hobject *func;      /* borrowed: function being executed; for bound function calls, this is the final, real function, NULL for lightfuncs */
7733 	duk_activation *parent; /* previous (parent) activation (or NULL if none) */
7734 	duk_hobject *var_env;   /* current variable environment (may be NULL if delayed) */
7735 	duk_hobject *lex_env;   /* current lexical environment (may be NULL if delayed) */
7736 	duk_catcher *cat;       /* current catcher (or NULL) */
7737 
7738 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
7739 	/* Previous value of 'func' caller, restored when unwound.  Only in use
7740 	 * when 'func' is non-strict.
7741 	 */
7742 	duk_hobject *prev_caller;
7743 #endif
7744 
7745 	duk_instr_t *curr_pc;   /* next instruction to execute (points to 'func' bytecode, stable pointer), NULL for native calls */
7746 
7747 	/* bottom_byteoff and retval_byteoff are only used for book-keeping
7748 	 * of ECMAScript-initiated calls, to allow returning to an ECMAScript
7749 	 * function properly.
7750 	 */
7751 
7752 	/* Bottom of valstack for this activation, used to reset
7753 	 * valstack_bottom on return; offset is absolute.  There's
7754 	 * no need to track 'top' because native call handling deals
7755 	 * with that using locals, and for ECMAScript returns 'nregs'
7756 	 * indicates the necessary top.
7757 	 */
7758 	duk_size_t bottom_byteoff;
7759 
7760 	/* Return value when returning to this activation (points to caller
7761 	 * reg, not callee reg); offset is absolute (only set if activation is
7762 	 * not topmost).
7763 	 *
7764 	 * Note: bottom_byteoff is always set, while retval_byteoff is only
7765 	 * applicable for activations below the topmost one.  Currently
7766 	 * retval_byteoff for the topmost activation is considered garbage
7767 	 * (and it not initialized on entry or cleared on return; may contain
7768 	 * previous or garbage values).
7769 	 */
7770 	duk_size_t retval_byteoff;
7771 
7772 	/* Current 'this' binding is the value just below bottom.
7773 	 * Previously, 'this' binding was handled with an index to the
7774 	 * (calling) valstack.  This works for everything except tail
7775 	 * calls, which must not "accumulate" valstack temps.
7776 	 */
7777 
7778 	/* Value stack reserve (valstack_end) byte offset to be restored
7779 	 * when returning to this activation.  Only used by the bytecode
7780 	 * executor.
7781 	 */
7782 	duk_size_t reserve_byteoff;
7783 
7784 #if defined(DUK_USE_DEBUGGER_SUPPORT)
7785 	duk_uint32_t prev_line; /* needed for stepping */
7786 #endif
7787 
7788 	duk_small_uint_t flags;
7789 };
7790 
7791 struct duk_catcher {
7792 	duk_catcher *parent;            /* previous (parent) catcher (or NULL if none) */
7793 	duk_hstring *h_varname;         /* borrowed reference to catch variable name (or NULL if none) */
7794 	                                /* (reference is valid as long activation exists) */
7795 	duk_instr_t *pc_base;           /* resume execution from pc_base or pc_base+1 (points to 'func' bytecode, stable pointer) */
7796 	duk_size_t idx_base;            /* idx_base and idx_base+1 get completion value and type */
7797 	duk_uint32_t flags;             /* type and control flags, label number */
7798 	/* XXX: could pack 'flags' and 'idx_base' to same value in practice,
7799 	 * on 32-bit targets this would make duk_catcher 16 bytes.
7800 	 */
7801 };
7802 
7803 struct duk_hthread {
7804 	/* Shared object part */
7805 	duk_hobject obj;
7806 
7807 	/* Pointer to bytecode executor's 'curr_pc' variable.  Used to copy
7808 	 * the current PC back into the topmost activation when activation
7809 	 * state is about to change (or "syncing" is otherwise needed).  This
7810 	 * is rather awkward but important for performance, see execution.rst.
7811 	 */
7812 	duk_instr_t **ptr_curr_pc;
7813 
7814 	/* Backpointers. */
7815 	duk_heap *heap;
7816 
7817 	/* Current strictness flag: affects API calls. */
7818 	duk_uint8_t strict;
7819 
7820 	/* Thread state. */
7821 	duk_uint8_t state;
7822 	duk_uint8_t unused1;
7823 	duk_uint8_t unused2;
7824 
7825 	/* XXX: Valstack and callstack are currently assumed to have non-NULL
7826 	 * pointers.  Relaxing this would not lead to big benefits (except
7827 	 * perhaps for terminated threads).
7828 	 */
7829 
7830 	/* Value stack: these are expressed as pointers for faster stack
7831 	 * manipulation.  [valstack,valstack_top[ is GC-reachable,
7832 	 * [valstack_top,valstack_alloc_end[ is not GC-reachable but kept
7833 	 * initialized as 'undefined'.  [valstack,valstack_end[ is the
7834 	 * guaranteed/reserved space and the valstack cannot be resized to
7835 	 * a smaller size.  [valstack_end,valstack_alloc_end[ is currently
7836 	 * allocated slack that can be used to grow the current guaranteed
7837 	 * space but may be shrunk away without notice.
7838 	 *
7839 	 *
7840 	 * <----------------------- guaranteed --->
7841 	 *                                        <---- slack --->
7842 	 *               <--- frame --->
7843 	 * .-------------+=============+----------+--------------.
7844 	 * |xxxxxxxxxxxxx|yyyyyyyyyyyyy|uuuuuuuuuu|uuuuuuuuuuuuuu|
7845 	 * `-------------+=============+----------+--------------'
7846 	 *
7847 	 * ^             ^             ^          ^              ^
7848 	 * |             |             |          |              |
7849 	 * valstack      bottom        top        end            alloc_end
7850 	 *
7851 	 *     xxx = arbitrary values, below current frame
7852 	 *     yyy = arbitrary values, inside current frame
7853 	 *     uuu = outside active value stack, initialized to 'undefined'
7854 	 */
7855 	duk_tval *valstack;                     /* start of valstack allocation */
7856 	duk_tval *valstack_end;                 /* end of valstack reservation/guarantee (exclusive) */
7857 	duk_tval *valstack_alloc_end;           /* end of valstack allocation */
7858 	duk_tval *valstack_bottom;              /* bottom of current frame */
7859 	duk_tval *valstack_top;                 /* top of current frame (exclusive) */
7860 
7861 	/* Call stack, represented as a linked list starting from the current
7862 	 * activation (or NULL if nothing is active).
7863 	 */
7864 	duk_activation *callstack_curr;         /* current activation (or NULL if none) */
7865 	duk_size_t callstack_top;               /* number of activation records in callstack (0 if none) */
7866 	duk_size_t callstack_preventcount;      /* number of activation records in callstack preventing a yield */
7867 
7868 	/* Yield/resume book-keeping. */
7869 	duk_hthread *resumer;                   /* who resumed us (if any) */
7870 
7871 	/* Current compiler state (if any), used for augmenting SyntaxErrors. */
7872 	duk_compiler_ctx *compile_ctx;
7873 
7874 #if defined(DUK_USE_INTERRUPT_COUNTER)
7875 	/* Interrupt counter for triggering a slow path check for execution
7876 	 * timeout, debugger interaction such as breakpoints, etc.  The value
7877 	 * is valid for the current running thread, and both the init and
7878 	 * counter values are copied whenever a thread switch occurs.  It's
7879 	 * important for the counter to be conveniently accessible for the
7880 	 * bytecode executor inner loop for performance reasons.
7881 	 */
7882 	duk_int_t interrupt_counter;    /* countdown state */
7883 	duk_int_t interrupt_init;       /* start value for current countdown */
7884 #endif
7885 
7886 	/* Builtin-objects; may or may not be shared with other threads,
7887 	 * threads existing in different "compartments" will have different
7888 	 * built-ins.  Must be stored on a per-thread basis because there
7889 	 * is no intermediate structure for a thread group / compartment.
7890 	 * This takes quite a lot of space, currently 43x4 = 172 bytes on
7891 	 * 32-bit platforms.
7892 	 *
7893 	 * In some cases the builtins array could be ROM based, but it's
7894 	 * sometimes edited (e.g. for sandboxing) so it's better to keep
7895 	 * this array in RAM.
7896 	 */
7897 	duk_hobject *builtins[DUK_NUM_BUILTINS];
7898 
7899 	/* Convenience copies from heap/vm for faster access. */
7900 #if defined(DUK_USE_ROM_STRINGS)
7901 	/* No field needed when strings are in ROM. */
7902 #else
7903 #if defined(DUK_USE_HEAPPTR16)
7904 	duk_uint16_t *strs16;
7905 #else
7906 	duk_hstring **strs;
7907 #endif
7908 #endif
7909 };
7910 
7911 /*
7912  *  Prototypes
7913  */
7914 
7915 DUK_INTERNAL_DECL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to);
7916 DUK_INTERNAL_DECL void duk_hthread_create_builtin_objects(duk_hthread *thr);
7917 DUK_INTERNAL_DECL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr);
7918 DUK_INTERNAL_DECL void duk_hthread_terminate(duk_hthread *thr);
7919 
7920 DUK_INTERNAL_DECL duk_activation *duk_hthread_activation_alloc(duk_hthread *thr);
7921 DUK_INTERNAL_DECL void duk_hthread_activation_free(duk_hthread *thr, duk_activation *act);
7922 DUK_INTERNAL_DECL void duk_hthread_activation_unwind_norz(duk_hthread *thr);
7923 DUK_INTERNAL_DECL void duk_hthread_activation_unwind_reuse_norz(duk_hthread *thr);
7924 DUK_INTERNAL_DECL duk_activation *duk_hthread_get_activation_for_level(duk_hthread *thr, duk_int_t level);
7925 
7926 DUK_INTERNAL_DECL duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr);
7927 DUK_INTERNAL_DECL void duk_hthread_catcher_free(duk_hthread *thr, duk_catcher *cat);
7928 DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_norz(duk_hthread *thr, duk_activation *act);
7929 DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_nolexenv_norz(duk_hthread *thr, duk_activation *act);
7930 
7931 #if defined(DUK_USE_FINALIZER_TORTURE)
7932 DUK_INTERNAL_DECL void duk_hthread_valstack_torture_realloc(duk_hthread *thr);
7933 #endif
7934 
7935 DUK_INTERNAL_DECL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud);  /* indirect allocs */
7936 
7937 #if defined(DUK_USE_DEBUGGER_SUPPORT)
7938 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act);
7939 #endif
7940 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act);
7941 DUK_INTERNAL_DECL void duk_hthread_sync_currpc(duk_hthread *thr);
7942 DUK_INTERNAL_DECL void duk_hthread_sync_and_null_currpc(duk_hthread *thr);
7943 
7944 #endif  /* DUK_HTHREAD_H_INCLUDED */
7945 /* #include duk_harray.h */
7946 #line 1 "duk_harray.h"
7947 /*
7948  *  Array object representation, used for actual Array instances.
7949  *
7950  *  All objects with the exotic array behavior (which must coincide with having
7951  *  internal class array) MUST be duk_harrays.  No other object can be a
7952  *  duk_harray.  However, duk_harrays may not always have an array part.
7953  */
7954 
7955 #if !defined(DUK_HARRAY_H_INCLUDED)
7956 #define DUK_HARRAY_H_INCLUDED
7957 
7958 #define DUK_ASSERT_HARRAY_VALID(h) do { \
7959 		DUK_ASSERT((h) != NULL); \
7960 		DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) (h))); \
7961 		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY((duk_hobject *) (h))); \
7962 	} while (0)
7963 
7964 #define DUK_HARRAY_LENGTH_WRITABLE(h)         (!(h)->length_nonwritable)
7965 #define DUK_HARRAY_LENGTH_NONWRITABLE(h)      ((h)->length_nonwritable)
7966 #define DUK_HARRAY_SET_LENGTH_WRITABLE(h)     do { (h)->length_nonwritable = 0; } while (0)
7967 #define DUK_HARRAY_SET_LENGTH_NONWRITABLE(h)  do { (h)->length_nonwritable = 1; } while (0)
7968 
7969 struct duk_harray {
7970 	/* Shared object part. */
7971 	duk_hobject obj;
7972 
7973 	/* Array .length.
7974 	 *
7975 	 * At present Array .length may be smaller, equal, or even larger
7976 	 * than the allocated underlying array part.  Fast path code must
7977 	 * always take this into account carefully.
7978 	 */
7979 	duk_uint32_t length;
7980 
7981 	/* Array .length property attributes.  The property is always
7982 	 * non-enumerable and non-configurable.  It's initially writable
7983 	 * but per Object.defineProperty() rules it can be made non-writable
7984 	 * even if it is non-configurable.  Thus we need to track the
7985 	 * writability explicitly.
7986 	 *
7987 	 * XXX: this field to be eliminated and moved into duk_hobject
7988 	 * flags field to save space.
7989 	 */
7990 	duk_bool_t length_nonwritable;
7991 };
7992 
7993 #endif  /* DUK_HARRAY_H_INCLUDED */
7994 /* #include duk_henv.h */
7995 #line 1 "duk_henv.h"
7996 /*
7997  *  Environment object representation.
7998  */
7999 
8000 #if !defined(DUK_HENV_H_INCLUDED)
8001 #define DUK_HENV_H_INCLUDED
8002 
8003 #define DUK_ASSERT_HDECENV_VALID(h) do { \
8004 		DUK_ASSERT((h) != NULL); \
8005 		DUK_ASSERT(DUK_HOBJECT_IS_DECENV((duk_hobject *) (h))); \
8006 		DUK_ASSERT((h)->thread == NULL || (h)->varmap != NULL); \
8007 	} while (0)
8008 
8009 #define DUK_ASSERT_HOBJENV_VALID(h) do { \
8010 		DUK_ASSERT((h) != NULL); \
8011 		DUK_ASSERT(DUK_HOBJECT_IS_OBJENV((duk_hobject *) (h))); \
8012 		DUK_ASSERT((h)->target != NULL); \
8013 		DUK_ASSERT((h)->has_this == 0 || (h)->has_this == 1); \
8014 	} while (0)
8015 
8016 struct duk_hdecenv {
8017 	/* Shared object part. */
8018 	duk_hobject obj;
8019 
8020 	/* These control variables provide enough information to access live
8021 	 * variables for a closure that is still open.  If thread == NULL,
8022 	 * the record is closed and the identifiers are in the property table.
8023 	 */
8024 	duk_hthread *thread;
8025 	duk_hobject *varmap;
8026 	duk_size_t regbase_byteoff;
8027 };
8028 
8029 struct duk_hobjenv {
8030 	/* Shared object part. */
8031 	duk_hobject obj;
8032 
8033 	/* Target object and 'this' binding for object binding. */
8034 	duk_hobject *target;
8035 
8036 	/* The 'target' object is used as a this binding in only some object
8037 	 * environments.  For example, the global environment does not provide
8038 	 * a this binding, but a with statement does.
8039 	 */
8040 	duk_bool_t has_this;
8041 };
8042 
8043 #endif  /* DUK_HENV_H_INCLUDED */
8044 /* #include duk_hbuffer.h */
8045 #line 1 "duk_hbuffer.h"
8046 /*
8047  *  Heap buffer representation.
8048  *
8049  *  Heap allocated user data buffer which is either:
8050  *
8051  *    1. A fixed size buffer (data follows header statically)
8052  *    2. A dynamic size buffer (data pointer follows header)
8053  *
8054  *  The data pointer for a variable size buffer of zero size may be NULL.
8055  */
8056 
8057 #if !defined(DUK_HBUFFER_H_INCLUDED)
8058 #define DUK_HBUFFER_H_INCLUDED
8059 
8060 /*
8061  *  Flags
8062  *
8063  *  Fixed buffer:     0
8064  *  Dynamic buffer:   DUK_HBUFFER_FLAG_DYNAMIC
8065  *  External buffer:  DUK_HBUFFER_FLAG_DYNAMIC | DUK_HBUFFER_FLAG_EXTERNAL
8066  */
8067 
8068 #define DUK_HBUFFER_FLAG_DYNAMIC                  DUK_HEAPHDR_USER_FLAG(0)    /* buffer is behind a pointer, dynamic or external */
8069 #define DUK_HBUFFER_FLAG_EXTERNAL                 DUK_HEAPHDR_USER_FLAG(1)    /* buffer pointer is to an externally allocated buffer */
8070 
8071 #define DUK_HBUFFER_HAS_DYNAMIC(x)                DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
8072 #define DUK_HBUFFER_HAS_EXTERNAL(x)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
8073 
8074 #define DUK_HBUFFER_SET_DYNAMIC(x)                DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
8075 #define DUK_HBUFFER_SET_EXTERNAL(x)               DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
8076 
8077 #define DUK_HBUFFER_CLEAR_DYNAMIC(x)              DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
8078 #define DUK_HBUFFER_CLEAR_EXTERNAL(x)             DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
8079 
8080 /*
8081  *  Misc defines
8082  */
8083 
8084 /* Impose a maximum buffer length for now.  Restricted artificially to
8085  * ensure resize computations or adding a heap header length won't
8086  * overflow size_t and that a signed duk_int_t can hold a buffer
8087  * length.  The limit should be synchronized with DUK_HSTRING_MAX_BYTELEN.
8088  */
8089 
8090 #if defined(DUK_USE_BUFLEN16)
8091 #define DUK_HBUFFER_MAX_BYTELEN                   (0x0000ffffUL)
8092 #else
8093 /* Intentionally not 0x7fffffffUL; at least JSON code expects that
8094  * 2*len + 2 fits in 32 bits.
8095  */
8096 #define DUK_HBUFFER_MAX_BYTELEN                   (0x7ffffffeUL)
8097 #endif
8098 
8099 /*
8100  *  Field access
8101  */
8102 
8103 #if defined(DUK_USE_BUFLEN16)
8104 /* size stored in duk_heaphdr unused flag bits */
8105 #define DUK_HBUFFER_GET_SIZE(x)     ((x)->hdr.h_flags >> 16)
8106 #define DUK_HBUFFER_SET_SIZE(x,v)   do { \
8107 		duk_size_t duk__v; \
8108 		duk__v = (v); \
8109 		DUK_ASSERT(duk__v <= 0xffffUL); \
8110 		(x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | (((duk_uint32_t) duk__v) << 16); \
8111 	} while (0)
8112 #define DUK_HBUFFER_ADD_SIZE(x,dv)  do { \
8113 		(x)->hdr.h_flags += ((dv) << 16); \
8114 	} while (0)
8115 #define DUK_HBUFFER_SUB_SIZE(x,dv)  do { \
8116 		(x)->hdr.h_flags -= ((dv) << 16); \
8117 	} while (0)
8118 #else
8119 #define DUK_HBUFFER_GET_SIZE(x)     (((duk_hbuffer *) (x))->size)
8120 #define DUK_HBUFFER_SET_SIZE(x,v)   do { \
8121 		((duk_hbuffer *) (x))->size = (v); \
8122 	} while (0)
8123 #define DUK_HBUFFER_ADD_SIZE(x,dv)  do { \
8124 		(x)->size += (dv); \
8125 	} while (0)
8126 #define DUK_HBUFFER_SUB_SIZE(x,dv)  do { \
8127 		(x)->size -= (dv); \
8128 	} while (0)
8129 #endif
8130 
8131 #define DUK_HBUFFER_FIXED_GET_SIZE(x)       DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
8132 #define DUK_HBUFFER_FIXED_SET_SIZE(x,v)     DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x))
8133 
8134 #define DUK_HBUFFER_DYNAMIC_GET_SIZE(x)     DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
8135 #define DUK_HBUFFER_DYNAMIC_SET_SIZE(x,v)   DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
8136 #define DUK_HBUFFER_DYNAMIC_ADD_SIZE(x,dv)  DUK_HBUFFER_ADD_SIZE((duk_hbuffer *) (x), (dv))
8137 #define DUK_HBUFFER_DYNAMIC_SUB_SIZE(x,dv)  DUK_HBUFFER_SUB_SIZE((duk_hbuffer *) (x), (dv))
8138 
8139 #define DUK_HBUFFER_EXTERNAL_GET_SIZE(x)    DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
8140 #define DUK_HBUFFER_EXTERNAL_SET_SIZE(x,v)  DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
8141 
8142 #define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap,x)    ((duk_uint8_t *) (((duk_hbuffer_fixed *) (void *) (x)) + 1))
8143 
8144 #if defined(DUK_USE_HEAPPTR16)
8145 #define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) \
8146 	((void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (x))->h_extra16))
8147 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v)     do { \
8148 		((duk_heaphdr *) (x))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
8149 	} while (0)
8150 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x)  do { \
8151 		((duk_heaphdr *) (x))->h_extra16 = 0;  /* assume 0 <=> NULL */ \
8152 	} while (0)
8153 #else
8154 #define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x)       ((x)->curr_alloc)
8155 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v)     do { \
8156 		(x)->curr_alloc = (void *) (v); \
8157 	} while (0)
8158 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x)  do { \
8159 		(x)->curr_alloc = (void *) NULL; \
8160 	} while (0)
8161 #endif
8162 
8163 /* No pointer compression because pointer is potentially outside of
8164  * Duktape heap.
8165  */
8166 #if defined(DUK_USE_HEAPPTR16)
8167 #define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
8168 	((void *) (x)->curr_alloc)
8169 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v)     do { \
8170 		(x)->curr_alloc = (void *) (v); \
8171 	} while (0)
8172 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x)  do { \
8173 		(x)->curr_alloc = (void *) NULL; \
8174 	} while (0)
8175 #else
8176 #define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
8177 	((void *) (x)->curr_alloc)
8178 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v)     do { \
8179 		(x)->curr_alloc = (void *) (v); \
8180 	} while (0)
8181 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x)  do { \
8182 		(x)->curr_alloc = (void *) NULL; \
8183 	} while (0)
8184 #endif
8185 
8186 /* Get a pointer to the current buffer contents (matching current allocation
8187  * size).  May be NULL for zero size dynamic/external buffer.
8188  */
8189 #if defined(DUK_USE_HEAPPTR16)
8190 #define DUK_HBUFFER_GET_DATA_PTR(heap,x)  ( \
8191 	DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
8192 		( \
8193 			DUK_HBUFFER_HAS_EXTERNAL((x)) ? \
8194 				DUK_HBUFFER_EXTERNAL_GET_DATA_PTR((heap), (duk_hbuffer_external *) (x)) : \
8195 				DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) \
8196 		) : \
8197 		DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (void *) (x)) \
8198 	)
8199 #else
8200 /* Without heap pointer compression duk_hbuffer_dynamic and duk_hbuffer_external
8201  * have the same layout so checking for fixed vs. dynamic (or external) is enough.
8202  */
8203 #define DUK_HBUFFER_GET_DATA_PTR(heap,x)  ( \
8204 	DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
8205 		DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) : \
8206 		DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (void *) (x)) \
8207 	)
8208 #endif
8209 
8210 /*
8211  *  Structs
8212  */
8213 
8214 /* Shared prefix for all buffer types. */
8215 struct duk_hbuffer {
8216 	duk_heaphdr hdr;
8217 
8218 	/* It's not strictly necessary to track the current size, but
8219 	 * it is useful for writing robust native code.
8220 	 */
8221 
8222 	/* Current size. */
8223 #if defined(DUK_USE_BUFLEN16)
8224 	/* Stored in duk_heaphdr unused flags. */
8225 #else
8226 	duk_size_t size;
8227 #endif
8228 
8229 	/*
8230 	 *  Data following the header depends on the DUK_HBUFFER_FLAG_DYNAMIC
8231 	 *  flag.
8232 	 *
8233 	 *  If the flag is clear (the buffer is a fixed size one), the buffer
8234 	 *  data follows the header directly, consisting of 'size' bytes.
8235 	 *
8236 	 *  If the flag is set, the actual buffer is allocated separately, and
8237 	 *  a few control fields follow the header.  Specifically:
8238 	 *
8239 	 *    - a "void *" pointing to the current allocation
8240 	 *    - a duk_size_t indicating the full allocated size (always >= 'size')
8241 	 *
8242 	 *  If DUK_HBUFFER_FLAG_EXTERNAL is set, the buffer has been allocated
8243 	 *  by user code, so that Duktape won't be able to resize it and won't
8244 	 *  free it.  This allows buffers to point to e.g. an externally
8245 	 *  allocated structure such as a frame buffer.
8246 	 *
8247 	 *  Unlike strings, no terminator byte (NUL) is guaranteed after the
8248 	 *  data.  This would be convenient, but would pad aligned user buffers
8249 	 *  unnecessarily upwards in size.  For instance, if user code requested
8250 	 *  a 64-byte dynamic buffer, 65 bytes would actually be allocated which
8251 	 *  would then potentially round upwards to perhaps 68 or 72 bytes.
8252 	 */
8253 };
8254 
8255 /* Fixed buffer; data follows struct, with proper alignment guaranteed by
8256  * struct size.
8257  */
8258 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
8259 #pragma pack(push, 8)
8260 #endif
8261 struct duk_hbuffer_fixed {
8262 	/* A union is used here as a portable struct size / alignment trick:
8263 	 * by adding a 32-bit or a 64-bit (unused) union member, the size of
8264 	 * the struct is effectively forced to be a multiple of 4 or 8 bytes
8265 	 * (respectively) without increasing the size of the struct unless
8266 	 * necessary.
8267 	 */
8268 	union {
8269 		struct {
8270 			duk_heaphdr hdr;
8271 #if defined(DUK_USE_BUFLEN16)
8272 			/* Stored in duk_heaphdr unused flags. */
8273 #else
8274 			duk_size_t size;
8275 #endif
8276 		} s;
8277 #if (DUK_USE_ALIGN_BY == 4)
8278 		duk_uint32_t dummy_for_align4;
8279 #elif (DUK_USE_ALIGN_BY == 8)
8280 		duk_double_t dummy_for_align8_1;
8281 #if defined(DUK_USE_64BIT_OPS)
8282 		duk_uint64_t dummy_for_align8_2;
8283 #endif
8284 #elif (DUK_USE_ALIGN_BY == 1)
8285 		/* no extra padding */
8286 #else
8287 #error invalid DUK_USE_ALIGN_BY
8288 #endif
8289 	} u;
8290 
8291 	/*
8292 	 *  Data follows the struct header.  The struct size is padded by the
8293 	 *  compiler based on the struct members.  This guarantees that the
8294 	 *  buffer data will be aligned-by-4 but not necessarily aligned-by-8.
8295 	 *
8296 	 *  On platforms where alignment does not matter, the struct padding
8297 	 *  could be removed (if there is any).  On platforms where alignment
8298 	 *  by 8 is required, the struct size must be forced to be a multiple
8299 	 *  of 8 by some means.  Without it, some user code may break, and also
8300 	 *  Duktape itself breaks (e.g. the compiler stores duk_tvals in a
8301 	 *  dynamic buffer).
8302 	 */
8303 }
8304 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR)
8305 __attribute__ ((aligned (8)))
8306 #elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR)
8307 __attribute__ ((aligned (8)))
8308 #endif
8309 ;
8310 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
8311 #pragma pack(pop)
8312 #endif
8313 
8314 /* Dynamic buffer with 'curr_alloc' pointing to a dynamic area allocated using
8315  * heap allocation primitives.  Also used for external buffers when low memory
8316  * options are not used.
8317  */
8318 struct duk_hbuffer_dynamic {
8319 	duk_heaphdr hdr;
8320 
8321 #if defined(DUK_USE_BUFLEN16)
8322 	/* Stored in duk_heaphdr unused flags. */
8323 #else
8324 	duk_size_t size;
8325 #endif
8326 
8327 #if defined(DUK_USE_HEAPPTR16)
8328 	/* Stored in duk_heaphdr h_extra16. */
8329 #else
8330 	void *curr_alloc;  /* may be NULL if alloc_size == 0 */
8331 #endif
8332 
8333 	/*
8334 	 *  Allocation size for 'curr_alloc' is alloc_size.  There is no
8335 	 *  automatic NUL terminator for buffers (see above for rationale).
8336 	 *
8337 	 *  'curr_alloc' is explicitly allocated with heap allocation
8338 	 *  primitives and will thus always have alignment suitable for
8339 	 *  e.g. duk_tval and an IEEE double.
8340 	 */
8341 };
8342 
8343 /* External buffer with 'curr_alloc' managed by user code and pointing to an
8344  * arbitrary address.  When heap pointer compression is not used, this struct
8345  * has the same layout as duk_hbuffer_dynamic.
8346  */
8347 struct duk_hbuffer_external {
8348 	duk_heaphdr hdr;
8349 
8350 #if defined(DUK_USE_BUFLEN16)
8351 	/* Stored in duk_heaphdr unused flags. */
8352 #else
8353 	duk_size_t size;
8354 #endif
8355 
8356 	/* Cannot be compressed as a heap pointer because may point to
8357 	 * an arbitrary address.
8358 	 */
8359 	void *curr_alloc;  /* may be NULL if alloc_size == 0 */
8360 };
8361 
8362 /*
8363  *  Prototypes
8364  */
8365 
8366 DUK_INTERNAL_DECL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata);
8367 DUK_INTERNAL_DECL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud);  /* indirect allocs */
8368 
8369 /* dynamic buffer ops */
8370 DUK_INTERNAL_DECL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size);
8371 DUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf);
8372 
8373 #endif  /* DUK_HBUFFER_H_INCLUDED */
8374 /* #include duk_hproxy.h */
8375 #line 1 "duk_hproxy.h"
8376 /*
8377  *  Proxy object representation.
8378  */
8379 
8380 #if !defined(DUK_HPROXY_H_INCLUDED)
8381 #define DUK_HPROXY_H_INCLUDED
8382 
8383 #define DUK_ASSERT_HPROXY_VALID(h) do { \
8384 		DUK_ASSERT((h) != NULL); \
8385 		DUK_ASSERT((h)->target != NULL); \
8386 		DUK_ASSERT((h)->handler != NULL); \
8387 		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((duk_hobject *) (h))); \
8388 	} while (0)
8389 
8390 struct duk_hproxy {
8391 	/* Shared object part. */
8392 	duk_hobject obj;
8393 
8394 	/* Proxy target object. */
8395 	duk_hobject *target;
8396 
8397 	/* Proxy handlers (traps). */
8398 	duk_hobject *handler;
8399 };
8400 
8401 #endif  /* DUK_HPROXY_H_INCLUDED */
8402 /* #include duk_heap.h */
8403 #line 1 "duk_heap.h"
8404 /*
8405  *  Heap structure.
8406  *
8407  *  Heap contains allocated heap objects, interned strings, and built-in
8408  *  strings for one or more threads.
8409  */
8410 
8411 #if !defined(DUK_HEAP_H_INCLUDED)
8412 #define DUK_HEAP_H_INCLUDED
8413 
8414 /* alloc function typedefs in duktape.h */
8415 
8416 /*
8417  *  Heap flags
8418  */
8419 
8420 #define DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED            (1U << 0)  /* mark-and-sweep marking reached a recursion limit and must use multi-pass marking */
8421 #define DUK_HEAP_FLAG_INTERRUPT_RUNNING                        (1U << 1)  /* executor interrupt running (used to avoid nested interrupts) */
8422 #define DUK_HEAP_FLAG_FINALIZER_NORESCUE                       (1U << 2)  /* heap destruction ongoing, finalizer rescue no longer possible */
8423 #define DUK_HEAP_FLAG_DEBUGGER_PAUSED                          (1U << 3)  /* debugger is paused: talk with debug client until step/resume */
8424 
8425 #define DUK__HEAP_HAS_FLAGS(heap,bits)               ((heap)->flags & (bits))
8426 #define DUK__HEAP_SET_FLAGS(heap,bits)  do { \
8427 		(heap)->flags |= (bits); \
8428 	} while (0)
8429 #define DUK__HEAP_CLEAR_FLAGS(heap,bits)  do { \
8430 		(heap)->flags &= ~(bits); \
8431 	} while (0)
8432 
8433 #define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)   DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
8434 #define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap)               DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
8435 #define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap)              DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
8436 #define DUK_HEAP_HAS_DEBUGGER_PAUSED(heap)                 DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
8437 
8438 #define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap)   DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
8439 #define DUK_HEAP_SET_INTERRUPT_RUNNING(heap)               DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
8440 #define DUK_HEAP_SET_FINALIZER_NORESCUE(heap)              DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
8441 #define DUK_HEAP_SET_DEBUGGER_PAUSED(heap)                 DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
8442 
8443 #define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
8444 #define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap)             DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
8445 #define DUK_HEAP_CLEAR_FINALIZER_NORESCUE(heap)            DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
8446 #define DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap)               DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
8447 
8448 /*
8449  *  Longjmp types, also double as identifying continuation type for a rethrow (in 'finally')
8450  */
8451 
8452 #define DUK_LJ_TYPE_UNKNOWN      0    /* unused */
8453 #define DUK_LJ_TYPE_THROW        1    /* value1 -> error object */
8454 #define DUK_LJ_TYPE_YIELD        2    /* value1 -> yield value, iserror -> error / normal */
8455 #define DUK_LJ_TYPE_RESUME       3    /* value1 -> resume value, value2 -> resumee thread, iserror -> error/normal */
8456 #define DUK_LJ_TYPE_BREAK        4    /* value1 -> label number, pseudo-type to indicate a break continuation (for ENDFIN) */
8457 #define DUK_LJ_TYPE_CONTINUE     5    /* value1 -> label number, pseudo-type to indicate a continue continuation (for ENDFIN) */
8458 #define DUK_LJ_TYPE_RETURN       6    /* value1 -> return value, pseudo-type to indicate a return continuation (for ENDFIN) */
8459 #define DUK_LJ_TYPE_NORMAL       7    /* no value, pseudo-type to indicate a normal continuation (for ENDFIN) */
8460 
8461 /*
8462  *  Mark-and-sweep flags
8463  *
8464  *  These are separate from heap level flags now but could be merged.
8465  *  The heap structure only contains a 'base mark-and-sweep flags'
8466  *  field and the GC caller can impose further flags.
8467  */
8468 
8469 /* Emergency mark-and-sweep: try extra hard, even at the cost of
8470  * performance.
8471  */
8472 #define DUK_MS_FLAG_EMERGENCY                (1U << 0)
8473 
8474 /* Voluntary mark-and-sweep: triggered periodically. */
8475 #define DUK_MS_FLAG_VOLUNTARY                (1U << 1)
8476 
8477 /* Postpone rescue decisions for reachable objects with FINALIZED set.
8478  * Used during finalize_list processing to avoid incorrect rescue
8479  * decisions due to finalize_list being a reachability root.
8480  */
8481 #define DUK_MS_FLAG_POSTPONE_RESCUE          (1U << 2)
8482 
8483 /* Don't compact objects; needed during object property table resize
8484  * to prevent a recursive resize.  It would suffice to protect only the
8485  * current object being resized, but this is not yet implemented.
8486  */
8487 #define DUK_MS_FLAG_NO_OBJECT_COMPACTION     (1U << 3)
8488 
8489 /*
8490  *  Thread switching
8491  *
8492  *  To switch heap->curr_thread, use the macro below so that interrupt counters
8493  *  get updated correctly.  The macro allows a NULL target thread because that
8494  *  happens e.g. in call handling.
8495  */
8496 
8497 #if defined(DUK_USE_INTERRUPT_COUNTER)
8498 #define DUK_HEAP_SWITCH_THREAD(heap,newthr)  duk_heap_switch_thread((heap), (newthr))
8499 #else
8500 #define DUK_HEAP_SWITCH_THREAD(heap,newthr)  do { \
8501 		(heap)->curr_thread = (newthr); \
8502 	} while (0)
8503 #endif
8504 
8505 /*
8506  *  Stats
8507  */
8508 
8509 #if defined(DUK_USE_DEBUG)
8510 #define DUK_STATS_INC(heap,fieldname) do { \
8511 		(heap)->fieldname += 1; \
8512 	} while (0)
8513 #else
8514 #define DUK_STATS_INC(heap,fieldname) do {} while (0)
8515 #endif
8516 
8517 /*
8518  *  Other heap related defines
8519  */
8520 
8521 /* Mark-and-sweep interval is relative to combined count of objects and
8522  * strings kept in the heap during the latest mark-and-sweep pass.
8523  * Fixed point .8 multiplier and .0 adder.  Trigger count (interval) is
8524  * decreased by each (re)allocation attempt (regardless of size), and each
8525  * refzero processed object.
8526  *
8527  * 'SKIP' indicates how many (re)allocations to wait until a retry if
8528  * GC is skipped because there is no thread do it with yet (happens
8529  * only during init phases).
8530  */
8531 #if defined(DUK_USE_REFERENCE_COUNTING)
8532 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT              12800L  /* 50x heap size */
8533 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD               1024L
8534 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP              256L
8535 #else
8536 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT              256L    /* 1x heap size */
8537 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD               1024L
8538 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP              256L
8539 #endif
8540 
8541 /* GC torture. */
8542 #if defined(DUK_USE_GC_TORTURE)
8543 #define DUK_GC_TORTURE(heap) do { duk_heap_mark_and_sweep((heap), 0); } while (0)
8544 #else
8545 #define DUK_GC_TORTURE(heap) do { } while (0)
8546 #endif
8547 
8548 /* Stringcache is used for speeding up char-offset-to-byte-offset
8549  * translations for non-ASCII strings.
8550  */
8551 #define DUK_HEAP_STRCACHE_SIZE                            4
8552 #define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT                16  /* strings up to the this length are not cached */
8553 
8554 /* Some list management macros. */
8555 #define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap,hdr)     duk_heap_insert_into_heap_allocated((heap), (hdr))
8556 #if defined(DUK_USE_REFERENCE_COUNTING)
8557 #define DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap,hdr)     duk_heap_remove_from_heap_allocated((heap), (hdr))
8558 #endif
8559 #if defined(DUK_USE_FINALIZER_SUPPORT)
8560 #define DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap,hdr)      duk_heap_insert_into_finalize_list((heap), (hdr))
8561 #define DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(heap,hdr)      duk_heap_remove_from_finalize_list((heap), (hdr))
8562 #endif
8563 
8564 /*
8565  *  Built-in strings
8566  */
8567 
8568 /* heap string indices are autogenerated in duk_strings.h */
8569 #if defined(DUK_USE_ROM_STRINGS)
8570 #define DUK_HEAP_GET_STRING(heap,idx) \
8571 	((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
8572 #else  /* DUK_USE_ROM_STRINGS */
8573 #if defined(DUK_USE_HEAPPTR16)
8574 #define DUK_HEAP_GET_STRING(heap,idx) \
8575 	((duk_hstring *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (heap)->strs16[(idx)]))
8576 #else
8577 #define DUK_HEAP_GET_STRING(heap,idx) \
8578 	((heap)->strs[(idx)])
8579 #endif
8580 #endif  /* DUK_USE_ROM_STRINGS */
8581 
8582 /*
8583  *  Raw memory calls: relative to heap, but no GC interaction
8584  */
8585 
8586 #define DUK_ALLOC_RAW(heap,size) \
8587 	((heap)->alloc_func((heap)->heap_udata, (size)))
8588 
8589 #define DUK_REALLOC_RAW(heap,ptr,newsize) \
8590 	((heap)->realloc_func((heap)->heap_udata, (void *) (ptr), (newsize)))
8591 
8592 #define DUK_FREE_RAW(heap,ptr) \
8593 	((heap)->free_func((heap)->heap_udata, (void *) (ptr)))
8594 
8595 /*
8596  *  Memory calls: relative to heap, GC interaction, but no error throwing.
8597  *
8598  *  XXX: Currently a mark-and-sweep triggered by memory allocation will run
8599  *  using the heap->heap_thread.  This thread is also used for running
8600  *  mark-and-sweep finalization; this is not ideal because it breaks the
8601  *  isolation between multiple global environments.
8602  *
8603  *  Notes:
8604  *
8605  *    - DUK_FREE() is required to ignore NULL and any other possible return
8606  *      value of a zero-sized alloc/realloc (same as ANSI C free()).
8607  *
8608  *    - There is no DUK_REALLOC_ZEROED because we don't assume to know the
8609  *      old size.  Caller must zero the reallocated memory.
8610  *
8611  *    - DUK_REALLOC_INDIRECT() must be used when a mark-and-sweep triggered
8612  *      by an allocation failure might invalidate the original 'ptr', thus
8613  *      causing a realloc retry to use an invalid pointer.  Example: we're
8614  *      reallocating the value stack and a finalizer resizes the same value
8615  *      stack during mark-and-sweep.  The indirect variant requests for the
8616  *      current location of the pointer being reallocated using a callback
8617  *      right before every realloc attempt; this circuitous approach is used
8618  *      to avoid strict aliasing issues in a more straightforward indirect
8619  *      pointer (void **) approach.  Note: the pointer in the storage
8620  *      location is read but is NOT updated; the caller must do that.
8621  */
8622 
8623 /* callback for indirect reallocs, request for current pointer */
8624 typedef void *(*duk_mem_getptr)(duk_heap *heap, void *ud);
8625 
8626 #define DUK_ALLOC(heap,size)                            duk_heap_mem_alloc((heap), (size))
8627 #define DUK_ALLOC_ZEROED(heap,size)                     duk_heap_mem_alloc_zeroed((heap), (size))
8628 #define DUK_REALLOC(heap,ptr,newsize)                   duk_heap_mem_realloc((heap), (ptr), (newsize))
8629 #define DUK_REALLOC_INDIRECT(heap,cb,ud,newsize)        duk_heap_mem_realloc_indirect((heap), (cb), (ud), (newsize))
8630 #define DUK_FREE(heap,ptr)                              duk_heap_mem_free((heap), (ptr))
8631 
8632 /*
8633  *  Checked allocation, relative to a thread
8634  *
8635  *  DUK_FREE_CHECKED() doesn't actually throw, but accepts a 'thr' argument
8636  *  for convenience.
8637  */
8638 
8639 #define DUK_ALLOC_CHECKED(thr,size)                     duk_heap_mem_alloc_checked((thr), (size))
8640 #define DUK_ALLOC_CHECKED_ZEROED(thr,size)              duk_heap_mem_alloc_checked_zeroed((thr), (size))
8641 #define DUK_FREE_CHECKED(thr,ptr)                       duk_heap_mem_free((thr)->heap, (ptr))
8642 
8643 /*
8644  *  Memory constants
8645  */
8646 
8647 #define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT           10  /* Retry allocation after mark-and-sweep for this
8648                                                               * many times.  A single mark-and-sweep round is
8649                                                               * not guaranteed to free all unreferenced memory
8650                                                               * because of finalization (in fact, ANY number of
8651                                                               * rounds is strictly not enough).
8652                                                               */
8653 
8654 #define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT  3  /* Starting from this round, use emergency mode
8655                                                               * for mark-and-sweep.
8656                                                               */
8657 
8658 /*
8659  *  Debugger support
8660  */
8661 
8662 /* Maximum number of breakpoints.  Only breakpoints that are set are
8663  * consulted so increasing this has no performance impact.
8664  */
8665 #define DUK_HEAP_MAX_BREAKPOINTS          16
8666 
8667 /* Opcode interval for a Date-based status/peek rate limit check.  Only
8668  * relevant when debugger is attached.  Requesting a timestamp may be a
8669  * slow operation on some platforms so this shouldn't be too low.  On the
8670  * other hand a high value makes Duktape react to a pause request slowly.
8671  */
8672 #define DUK_HEAP_DBG_RATELIMIT_OPCODES    4000
8673 
8674 /* Milliseconds between status notify and transport peeks. */
8675 #define DUK_HEAP_DBG_RATELIMIT_MILLISECS  200
8676 
8677 /* Debugger pause flags. */
8678 #define DUK_PAUSE_FLAG_ONE_OPCODE        (1U << 0)   /* pause when a single opcode has been executed */
8679 #define DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE (1U << 1)   /* one opcode pause actually active; artifact of current implementation */
8680 #define DUK_PAUSE_FLAG_LINE_CHANGE       (1U << 2)   /* pause when current line number changes */
8681 #define DUK_PAUSE_FLAG_FUNC_ENTRY        (1U << 3)   /* pause when entering a function */
8682 #define DUK_PAUSE_FLAG_FUNC_EXIT         (1U << 4)   /* pause when exiting current function */
8683 #define DUK_PAUSE_FLAG_CAUGHT_ERROR      (1U << 5)   /* pause when about to throw an error that is caught */
8684 #define DUK_PAUSE_FLAG_UNCAUGHT_ERROR    (1U << 6)   /* pause when about to throw an error that won't be caught */
8685 
8686 struct duk_breakpoint {
8687 	duk_hstring *filename;
8688 	duk_uint32_t line;
8689 };
8690 
8691 /*
8692  *  String cache should ideally be at duk_hthread level, but that would
8693  *  cause string finalization to slow down relative to the number of
8694  *  threads; string finalization must check the string cache for "weak"
8695  *  references to the string being finalized to avoid dead pointers.
8696  *
8697  *  Thus, string caches are now at the heap level now.
8698  */
8699 
8700 struct duk_strcache_entry {
8701 	duk_hstring *h;
8702 	duk_uint32_t bidx;
8703 	duk_uint32_t cidx;
8704 };
8705 
8706 /*
8707  *  Longjmp state, contains the information needed to perform a longjmp.
8708  *  Longjmp related values are written to value1, value2, and iserror.
8709  */
8710 
8711 struct duk_ljstate {
8712 	duk_jmpbuf *jmpbuf_ptr;   /* current setjmp() catchpoint */
8713 	duk_small_uint_t type;    /* longjmp type */
8714 	duk_bool_t iserror;       /* isError flag for yield */
8715 	duk_tval value1;          /* 1st related value (type specific) */
8716 	duk_tval value2;          /* 2nd related value (type specific) */
8717 };
8718 
8719 #define DUK_ASSERT_LJSTATE_UNSET(heap) do { \
8720 		DUK_ASSERT(heap != NULL); \
8721 		DUK_ASSERT(heap->lj.type == DUK_LJ_TYPE_UNKNOWN); \
8722 		DUK_ASSERT(heap->lj.iserror == 0); \
8723 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&heap->lj.value1)); \
8724 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&heap->lj.value2)); \
8725 	} while (0)
8726 #define DUK_ASSERT_LJSTATE_SET(heap) do { \
8727 		DUK_ASSERT(heap != NULL); \
8728 		DUK_ASSERT(heap->lj.type != DUK_LJ_TYPE_UNKNOWN); \
8729 	} while (0)
8730 
8731 /*
8732  *  Literal intern cache
8733  */
8734 
8735 struct duk_litcache_entry {
8736 	const duk_uint8_t *addr;
8737 	duk_hstring *h;
8738 };
8739 
8740 /*
8741  *  Main heap structure
8742  */
8743 
8744 struct duk_heap {
8745 	duk_small_uint_t flags;
8746 
8747 	/* Allocator functions. */
8748 	duk_alloc_function alloc_func;
8749 	duk_realloc_function realloc_func;
8750 	duk_free_function free_func;
8751 
8752 	/* Heap udata, used for allocator functions but also for other heap
8753 	 * level callbacks like fatal function, pointer compression, etc.
8754 	 */
8755 	void *heap_udata;
8756 
8757 	/* Fatal error handling, called e.g. when a longjmp() is needed but
8758 	 * lj.jmpbuf_ptr is NULL.  fatal_func must never return; it's not
8759 	 * declared as "noreturn" because doing that for typedefs is a bit
8760 	 * challenging portability-wise.
8761 	 */
8762 	duk_fatal_function fatal_func;
8763 
8764 	/* Main list of allocated heap objects.  Objects are either here,
8765 	 * in finalize_list waiting for processing, or in refzero_list
8766 	 * temporarily while a DECREF refzero cascade finishes.
8767 	 */
8768 	duk_heaphdr *heap_allocated;
8769 
8770 	/* Temporary work list for freeing a cascade of objects when a DECREF
8771 	 * (or DECREF_NORZ) encounters a zero refcount.  Using a work list
8772 	 * allows fixed C stack size when refcounts go to zero for a chain of
8773 	 * objects.  Outside of DECREF this is always a NULL because DECREF is
8774 	 * processed without side effects (only memory free calls).
8775 	 */
8776 #if defined(DUK_USE_REFERENCE_COUNTING)
8777 	duk_heaphdr *refzero_list;
8778 #endif
8779 
8780 #if defined(DUK_USE_FINALIZER_SUPPORT)
8781 	/* Work list for objects to be finalized. */
8782 	duk_heaphdr *finalize_list;
8783 #if defined(DUK_USE_ASSERTIONS)
8784 	/* Object whose finalizer is executing right now (no nesting). */
8785 	duk_heaphdr *currently_finalizing;
8786 #endif
8787 #endif
8788 
8789 	/* Freelist for duk_activations and duk_catchers. */
8790 #if defined(DUK_USE_CACHE_ACTIVATION)
8791 	duk_activation *activation_free;
8792 #endif
8793 #if defined(DUK_USE_CACHE_CATCHER)
8794 	duk_catcher *catcher_free;
8795 #endif
8796 
8797 	/* Voluntary mark-and-sweep trigger counter.  Intentionally signed
8798 	 * because we continue decreasing the value when voluntary GC cannot
8799 	 * run.
8800 	 */
8801 #if defined(DUK_USE_VOLUNTARY_GC)
8802 	duk_int_t ms_trigger_counter;
8803 #endif
8804 
8805 	/* Mark-and-sweep recursion control: too deep recursion causes
8806 	 * multi-pass processing to avoid growing C stack without bound.
8807 	 */
8808 	duk_uint_t ms_recursion_depth;
8809 
8810 	/* Mark-and-sweep flags automatically active (used for critical sections). */
8811 	duk_small_uint_t ms_base_flags;
8812 
8813 	/* Mark-and-sweep running flag.  Prevents re-entry, and also causes
8814 	 * refzero events to be ignored (= objects won't be queued to refzero_list).
8815 	 */
8816 	duk_uint_t ms_running;
8817 
8818 	/* Mark-and-sweep prevent count, stacking.  Used to avoid M&S side
8819 	 * effects (besides finalizers which are controlled separately) such
8820 	 * as compacting the string table or object property tables.  This
8821 	 * is also bumped when ms_running is set to prevent recursive re-entry.
8822 	 * Can also be bumped when mark-and-sweep is not running.
8823 	 */
8824 	duk_uint_t ms_prevent_count;
8825 
8826 	/* Finalizer processing prevent count, stacking.  Bumped when finalizers
8827 	 * are processed to prevent recursive finalizer processing (first call site
8828 	 * processing finalizers handles all finalizers until the list is empty).
8829 	 * Can also be bumped explicitly to prevent finalizer execution.
8830 	 */
8831 	duk_uint_t pf_prevent_count;
8832 
8833 	/* When processing finalize_list, don't actually run finalizers but
8834 	 * queue finalizable objects back to heap_allocated as is.  This is
8835 	 * used during heap destruction to deal with finalizers that keep
8836 	 * on creating more finalizable garbage.
8837 	 */
8838 	duk_uint_t pf_skip_finalizers;
8839 
8840 #if defined(DUK_USE_ASSERTIONS)
8841 	/* Set when we're in a critical path where an error throw would cause
8842 	 * e.g. sandboxing/protected call violations or state corruption.  This
8843 	 * is just used for asserts.
8844 	 */
8845 	duk_bool_t error_not_allowed;
8846 #endif
8847 
8848 #if defined(DUK_USE_ASSERTIONS)
8849 	/* Set when heap is still being initialized, helps with writing
8850 	 * some assertions.
8851 	 */
8852 	duk_bool_t heap_initializing;
8853 #endif
8854 
8855 	/* Marker for detecting internal "double faults", errors thrown when
8856 	 * we're trying to create an error object, see duk_error_throw.c.
8857 	 */
8858 	duk_bool_t creating_error;
8859 
8860 	/* Marker for indicating we're calling a user error augmentation
8861 	 * (errCreate/errThrow) function.  Errors created/thrown during
8862 	 * such a call are not augmented.
8863 	 */
8864 #if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
8865 	duk_bool_t augmenting_error;
8866 #endif
8867 
8868 	/* Longjmp state. */
8869 	duk_ljstate lj;
8870 
8871 	/* Heap thread, used internally and for finalization. */
8872 	duk_hthread *heap_thread;
8873 
8874 	/* Current running thread. */
8875 	duk_hthread *curr_thread;
8876 
8877 	/* Heap level "stash" object (e.g., various reachability roots). */
8878 	duk_hobject *heap_object;
8879 
8880 	/* duk_handle_call / duk_handle_safe_call recursion depth limiting */
8881 	duk_int_t call_recursion_depth;
8882 	duk_int_t call_recursion_limit;
8883 
8884 	/* Mix-in value for computing string hashes; should be reasonably unpredictable. */
8885 	duk_uint32_t hash_seed;
8886 
8887 	/* Random number state for duk_util_tinyrandom.c. */
8888 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
8889 #if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
8890 	duk_uint32_t rnd_state;  /* State for Shamir's three-op algorithm */
8891 #else
8892 	duk_uint64_t rnd_state[2];  /* State for xoroshiro128+ */
8893 #endif
8894 #endif
8895 
8896 	/* Counter for unique local symbol creation. */
8897 	/* XXX: When 64-bit types are available, it would be more efficient to
8898 	 * use a duk_uint64_t at least for incrementing but maybe also for
8899 	 * string formatting in the Symbol constructor.
8900 	 */
8901 	duk_uint32_t sym_counter[2];
8902 
8903 	/* For manual debugging: instruction count based on executor and
8904 	 * interrupt counter book-keeping.  Inspect debug logs to see how
8905 	 * they match up.
8906 	 */
8907 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
8908 	duk_int_t inst_count_exec;
8909 	duk_int_t inst_count_interrupt;
8910 #endif
8911 
8912 	/* Debugger state. */
8913 #if defined(DUK_USE_DEBUGGER_SUPPORT)
8914 	/* Callbacks and udata; dbg_read_cb != NULL is used to indicate attached state. */
8915 	duk_debug_read_function dbg_read_cb;                /* required, NULL implies detached */
8916 	duk_debug_write_function dbg_write_cb;              /* required */
8917 	duk_debug_peek_function dbg_peek_cb;
8918 	duk_debug_read_flush_function dbg_read_flush_cb;
8919 	duk_debug_write_flush_function dbg_write_flush_cb;
8920 	duk_debug_request_function dbg_request_cb;
8921 	duk_debug_detached_function dbg_detached_cb;
8922 	void *dbg_udata;
8923 
8924 	/* The following are only relevant when debugger is attached. */
8925 	duk_bool_t dbg_processing;              /* currently processing messages or breakpoints: don't enter message processing recursively (e.g. no breakpoints when processing debugger eval) */
8926 	duk_bool_t dbg_state_dirty;             /* resend state next time executor is about to run */
8927 	duk_bool_t dbg_force_restart;           /* force executor restart to recheck breakpoints; used to handle function returns (see GH-303) */
8928 	duk_bool_t dbg_detaching;               /* debugger detaching; used to avoid calling detach handler recursively */
8929 	duk_small_uint_t dbg_pause_flags;       /* flags for automatic pause behavior */
8930 	duk_activation *dbg_pause_act;          /* activation related to pause behavior (pause on line change, function entry/exit) */
8931 	duk_uint32_t dbg_pause_startline;       /* starting line number for line change related pause behavior */
8932 	duk_breakpoint dbg_breakpoints[DUK_HEAP_MAX_BREAKPOINTS];  /* breakpoints: [0,breakpoint_count[ gc reachable */
8933 	duk_small_uint_t dbg_breakpoint_count;
8934 	duk_breakpoint *dbg_breakpoints_active[DUK_HEAP_MAX_BREAKPOINTS + 1];  /* currently active breakpoints: NULL term, borrowed pointers */
8935 	/* XXX: make active breakpoints actual copies instead of pointers? */
8936 
8937 	/* These are for rate limiting Status notifications and transport peeking. */
8938 	duk_uint_t dbg_exec_counter;            /* cumulative opcode execution count (overflows are OK) */
8939 	duk_uint_t dbg_last_counter;            /* value of dbg_exec_counter when we last did a Date-based check */
8940 	duk_double_t dbg_last_time;             /* time when status/peek was last done (Date-based rate limit) */
8941 
8942 	/* Used to support single-byte stream lookahead. */
8943 	duk_bool_t dbg_have_next_byte;
8944 	duk_uint8_t dbg_next_byte;
8945 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
8946 #if defined(DUK_USE_ASSERTIONS)
8947 	duk_bool_t dbg_calling_transport;       /* transport call in progress, calling into Duktape forbidden */
8948 #endif
8949 
8950 	/* String intern table (weak refs). */
8951 #if defined(DUK_USE_STRTAB_PTRCOMP)
8952 	duk_uint16_t *strtable16;
8953 #else
8954 	duk_hstring **strtable;
8955 #endif
8956 	duk_uint32_t st_mask;    /* mask for lookup, st_size - 1 */
8957 	duk_uint32_t st_size;    /* stringtable size */
8958 #if (DUK_USE_STRTAB_MINSIZE != DUK_USE_STRTAB_MAXSIZE)
8959 	duk_uint32_t st_count;   /* string count for resize load factor checks */
8960 #endif
8961 	duk_bool_t st_resizing;  /* string table is being resized; avoid recursive resize */
8962 
8963 	/* String access cache (codepoint offset -> byte offset) for fast string
8964 	 * character looping; 'weak' reference which needs special handling in GC.
8965 	 */
8966 	duk_strcache_entry strcache[DUK_HEAP_STRCACHE_SIZE];
8967 
8968 #if defined(DUK_USE_LITCACHE_SIZE)
8969 	/* Literal intern cache.  When enabled, strings interned as literals
8970 	 * (e.g. duk_push_literal()) will be pinned and cached for the lifetime
8971 	 * of the heap.
8972 	 */
8973 	duk_litcache_entry litcache[DUK_USE_LITCACHE_SIZE];
8974 #endif
8975 
8976 	/* Built-in strings. */
8977 #if defined(DUK_USE_ROM_STRINGS)
8978 	/* No field needed when strings are in ROM. */
8979 #else
8980 #if defined(DUK_USE_HEAPPTR16)
8981 	duk_uint16_t strs16[DUK_HEAP_NUM_STRINGS];
8982 #else
8983 	duk_hstring *strs[DUK_HEAP_NUM_STRINGS];
8984 #endif
8985 #endif
8986 
8987 	/* Stats. */
8988 #if defined(DUK_USE_DEBUG)
8989 	duk_int_t stats_exec_opcodes;
8990 	duk_int_t stats_exec_interrupt;
8991 	duk_int_t stats_exec_throw;
8992 	duk_int_t stats_call_all;
8993 	duk_int_t stats_call_tailcall;
8994 	duk_int_t stats_call_ecmatoecma;
8995 	duk_int_t stats_safecall_all;
8996 	duk_int_t stats_safecall_nothrow;
8997 	duk_int_t stats_safecall_throw;
8998 	duk_int_t stats_ms_try_count;
8999 	duk_int_t stats_ms_skip_count;
9000 	duk_int_t stats_ms_emergency_count;
9001 	duk_int_t stats_strtab_intern_hit;
9002 	duk_int_t stats_strtab_intern_miss;
9003 	duk_int_t stats_strtab_resize_check;
9004 	duk_int_t stats_strtab_resize_grow;
9005 	duk_int_t stats_strtab_resize_shrink;
9006 	duk_int_t stats_strtab_litcache_hit;
9007 	duk_int_t stats_strtab_litcache_miss;
9008 	duk_int_t stats_strtab_litcache_pin;
9009 	duk_int_t stats_object_realloc_props;
9010 	duk_int_t stats_object_abandon_array;
9011 	duk_int_t stats_getownpropdesc_count;
9012 	duk_int_t stats_getownpropdesc_hit;
9013 	duk_int_t stats_getownpropdesc_miss;
9014 	duk_int_t stats_getpropdesc_count;
9015 	duk_int_t stats_getpropdesc_hit;
9016 	duk_int_t stats_getpropdesc_miss;
9017 	duk_int_t stats_getprop_all;
9018 	duk_int_t stats_getprop_arrayidx;
9019 	duk_int_t stats_getprop_bufobjidx;
9020 	duk_int_t stats_getprop_bufferidx;
9021 	duk_int_t stats_getprop_bufferlen;
9022 	duk_int_t stats_getprop_stringidx;
9023 	duk_int_t stats_getprop_stringlen;
9024 	duk_int_t stats_getprop_proxy;
9025 	duk_int_t stats_getprop_arguments;
9026 	duk_int_t stats_putprop_all;
9027 	duk_int_t stats_putprop_arrayidx;
9028 	duk_int_t stats_putprop_bufobjidx;
9029 	duk_int_t stats_putprop_bufferidx;
9030 	duk_int_t stats_putprop_proxy;
9031 	duk_int_t stats_getvar_all;
9032 	duk_int_t stats_putvar_all;
9033 #endif
9034 };
9035 
9036 /*
9037  *  Prototypes
9038  */
9039 
9040 DUK_INTERNAL_DECL
9041 duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
9042                          duk_realloc_function realloc_func,
9043                          duk_free_function free_func,
9044                          void *heap_udata,
9045                          duk_fatal_function fatal_func);
9046 DUK_INTERNAL_DECL void duk_heap_free(duk_heap *heap);
9047 DUK_INTERNAL_DECL void duk_free_hobject(duk_heap *heap, duk_hobject *h);
9048 DUK_INTERNAL_DECL void duk_free_hbuffer(duk_heap *heap, duk_hbuffer *h);
9049 DUK_INTERNAL_DECL void duk_free_hstring(duk_heap *heap, duk_hstring *h);
9050 DUK_INTERNAL_DECL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr);
9051 
9052 DUK_INTERNAL_DECL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);
9053 #if defined(DUK_USE_REFERENCE_COUNTING)
9054 DUK_INTERNAL_DECL void duk_heap_remove_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);
9055 #endif
9056 #if defined(DUK_USE_FINALIZER_SUPPORT)
9057 DUK_INTERNAL_DECL void duk_heap_insert_into_finalize_list(duk_heap *heap, duk_heaphdr *hdr);
9058 DUK_INTERNAL_DECL void duk_heap_remove_from_finalize_list(duk_heap *heap, duk_heaphdr *hdr);
9059 #endif
9060 #if defined(DUK_USE_ASSERTIONS)
9061 DUK_INTERNAL_DECL duk_bool_t duk_heap_in_heap_allocated(duk_heap *heap, duk_heaphdr *ptr);
9062 #endif
9063 #if defined(DUK_USE_INTERRUPT_COUNTER)
9064 DUK_INTERNAL_DECL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr);
9065 #endif
9066 
9067 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen);
9068 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t len);
9069 #if defined(DUK_USE_LITCACHE_SIZE)
9070 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_literal_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen);
9071 #endif
9072 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_u32(duk_heap *heap, duk_uint32_t val);
9073 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_u32_checked(duk_hthread *thr, duk_uint32_t val);
9074 #if defined(DUK_USE_REFERENCE_COUNTING)
9075 DUK_INTERNAL_DECL void duk_heap_strtable_unlink(duk_heap *heap, duk_hstring *h);
9076 #endif
9077 DUK_INTERNAL_DECL void duk_heap_strtable_unlink_prev(duk_heap *heap, duk_hstring *h, duk_hstring *prev);
9078 DUK_INTERNAL_DECL void duk_heap_strtable_force_resize(duk_heap *heap);
9079 DUK_INTERNAL void duk_heap_strtable_free(duk_heap *heap);
9080 #if defined(DUK_USE_DEBUG)
9081 DUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap);
9082 #endif
9083 
9084 DUK_INTERNAL_DECL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h);
9085 DUK_INTERNAL_DECL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset);
9086 
9087 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
9088 DUK_INTERNAL_DECL void *duk_default_alloc_function(void *udata, duk_size_t size);
9089 DUK_INTERNAL_DECL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize);
9090 DUK_INTERNAL_DECL void duk_default_free_function(void *udata, void *ptr);
9091 #endif
9092 
9093 DUK_INTERNAL_DECL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size);
9094 DUK_INTERNAL_DECL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size);
9095 DUK_INTERNAL_DECL void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size);
9096 DUK_INTERNAL_DECL void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size);
9097 DUK_INTERNAL_DECL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize);
9098 DUK_INTERNAL_DECL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize);
9099 DUK_INTERNAL_DECL void duk_heap_mem_free(duk_heap *heap, void *ptr);
9100 
9101 DUK_INTERNAL_DECL void duk_heap_free_freelists(duk_heap *heap);
9102 
9103 #if defined(DUK_USE_FINALIZER_SUPPORT)
9104 DUK_INTERNAL_DECL void duk_heap_run_finalizer(duk_heap *heap, duk_hobject *obj);
9105 DUK_INTERNAL_DECL void duk_heap_process_finalize_list(duk_heap *heap);
9106 #endif  /* DUK_USE_FINALIZER_SUPPORT */
9107 
9108 DUK_INTERNAL_DECL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags);
9109 
9110 DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len);
9111 
9112 #endif  /* DUK_HEAP_H_INCLUDED */
9113 /* #include duk_debugger.h */
9114 #line 1 "duk_debugger.h"
9115 #if !defined(DUK_DEBUGGER_H_INCLUDED)
9116 #define DUK_DEBUGGER_H_INCLUDED
9117 
9118 /* Debugger protocol version is defined in the public API header. */
9119 
9120 /* Initial bytes for markers. */
9121 #define DUK_DBG_IB_EOM                   0x00
9122 #define DUK_DBG_IB_REQUEST               0x01
9123 #define DUK_DBG_IB_REPLY                 0x02
9124 #define DUK_DBG_IB_ERROR                 0x03
9125 #define DUK_DBG_IB_NOTIFY                0x04
9126 
9127 /* Other initial bytes. */
9128 #define DUK_DBG_IB_INT4                  0x10
9129 #define DUK_DBG_IB_STR4                  0x11
9130 #define DUK_DBG_IB_STR2                  0x12
9131 #define DUK_DBG_IB_BUF4                  0x13
9132 #define DUK_DBG_IB_BUF2                  0x14
9133 #define DUK_DBG_IB_UNUSED                0x15
9134 #define DUK_DBG_IB_UNDEFINED             0x16
9135 #define DUK_DBG_IB_NULL                  0x17
9136 #define DUK_DBG_IB_TRUE                  0x18
9137 #define DUK_DBG_IB_FALSE                 0x19
9138 #define DUK_DBG_IB_NUMBER                0x1a
9139 #define DUK_DBG_IB_OBJECT                0x1b
9140 #define DUK_DBG_IB_POINTER               0x1c
9141 #define DUK_DBG_IB_LIGHTFUNC             0x1d
9142 #define DUK_DBG_IB_HEAPPTR               0x1e
9143 /* The short string/integer initial bytes starting from 0x60 don't have
9144  * defines now.
9145  */
9146 
9147 /* Error codes. */
9148 #define DUK_DBG_ERR_UNKNOWN              0x00
9149 #define DUK_DBG_ERR_UNSUPPORTED          0x01
9150 #define DUK_DBG_ERR_TOOMANY              0x02
9151 #define DUK_DBG_ERR_NOTFOUND             0x03
9152 #define DUK_DBG_ERR_APPLICATION          0x04
9153 
9154 /* Commands and notifys initiated by Duktape. */
9155 #define DUK_DBG_CMD_STATUS               0x01
9156 #define DUK_DBG_CMD_UNUSED_2             0x02  /* Duktape 1.x: print notify */
9157 #define DUK_DBG_CMD_UNUSED_3             0x03  /* Duktape 1.x: alert notify */
9158 #define DUK_DBG_CMD_UNUSED_4             0x04  /* Duktape 1.x: log notify */
9159 #define DUK_DBG_CMD_THROW                0x05
9160 #define DUK_DBG_CMD_DETACHING            0x06
9161 #define DUK_DBG_CMD_APPNOTIFY            0x07
9162 
9163 /* Commands initiated by debug client. */
9164 #define DUK_DBG_CMD_BASICINFO            0x10
9165 #define DUK_DBG_CMD_TRIGGERSTATUS        0x11
9166 #define DUK_DBG_CMD_PAUSE                0x12
9167 #define DUK_DBG_CMD_RESUME               0x13
9168 #define DUK_DBG_CMD_STEPINTO             0x14
9169 #define DUK_DBG_CMD_STEPOVER             0x15
9170 #define DUK_DBG_CMD_STEPOUT              0x16
9171 #define DUK_DBG_CMD_LISTBREAK            0x17
9172 #define DUK_DBG_CMD_ADDBREAK             0x18
9173 #define DUK_DBG_CMD_DELBREAK             0x19
9174 #define DUK_DBG_CMD_GETVAR               0x1a
9175 #define DUK_DBG_CMD_PUTVAR               0x1b
9176 #define DUK_DBG_CMD_GETCALLSTACK         0x1c
9177 #define DUK_DBG_CMD_GETLOCALS            0x1d
9178 #define DUK_DBG_CMD_EVAL                 0x1e
9179 #define DUK_DBG_CMD_DETACH               0x1f
9180 #define DUK_DBG_CMD_DUMPHEAP             0x20
9181 #define DUK_DBG_CMD_GETBYTECODE          0x21
9182 #define DUK_DBG_CMD_APPREQUEST           0x22
9183 #define DUK_DBG_CMD_GETHEAPOBJINFO       0x23
9184 #define DUK_DBG_CMD_GETOBJPROPDESC       0x24
9185 #define DUK_DBG_CMD_GETOBJPROPDESCRANGE  0x25
9186 
9187 /* The low 8 bits map directly to duk_hobject.h DUK_PROPDESC_FLAG_xxx.
9188  * The remaining flags are specific to the debugger.
9189  */
9190 #define DUK_DBG_PROPFLAG_SYMBOL          (1U << 8)
9191 #define DUK_DBG_PROPFLAG_HIDDEN          (1U << 9)
9192 
9193 #if defined(DUK_USE_DEBUGGER_SUPPORT)
9194 DUK_INTERNAL_DECL void duk_debug_do_detach(duk_heap *heap);
9195 
9196 DUK_INTERNAL_DECL duk_bool_t duk_debug_read_peek(duk_hthread *thr);
9197 DUK_INTERNAL_DECL void duk_debug_write_flush(duk_hthread *thr);
9198 
9199 DUK_INTERNAL_DECL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length);
9200 DUK_INTERNAL_DECL void duk_debug_skip_byte(duk_hthread *thr);
9201 
9202 DUK_INTERNAL_DECL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length);
9203 DUK_INTERNAL_DECL duk_uint8_t duk_debug_read_byte(duk_hthread *thr);
9204 DUK_INTERNAL_DECL duk_int32_t duk_debug_read_int(duk_hthread *thr);
9205 DUK_INTERNAL_DECL duk_hstring *duk_debug_read_hstring(duk_hthread *thr);
9206 /* XXX: exposed duk_debug_read_pointer */
9207 /* XXX: exposed duk_debug_read_buffer */
9208 /* XXX: exposed duk_debug_read_hbuffer */
9209 #if 0
9210 DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr);
9211 #endif
9212 #if defined(DUK_USE_DEBUGGER_INSPECT)
9213 DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr);
9214 #endif
9215 DUK_INTERNAL_DECL duk_tval *duk_debug_read_tval(duk_hthread *thr);
9216 
9217 DUK_INTERNAL_DECL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length);
9218 DUK_INTERNAL_DECL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x);
9219 DUK_INTERNAL_DECL void duk_debug_write_unused(duk_hthread *thr);
9220 DUK_INTERNAL_DECL void duk_debug_write_undefined(duk_hthread *thr);
9221 #if defined(DUK_USE_DEBUGGER_INSPECT)
9222 DUK_INTERNAL_DECL void duk_debug_write_null(duk_hthread *thr);
9223 #endif
9224 DUK_INTERNAL_DECL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val);
9225 DUK_INTERNAL_DECL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x);
9226 DUK_INTERNAL_DECL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x);
9227 DUK_INTERNAL_DECL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length);
9228 DUK_INTERNAL_DECL void duk_debug_write_cstring(duk_hthread *thr, const char *data);
9229 DUK_INTERNAL_DECL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h);
9230 DUK_INTERNAL_DECL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length);
9231 DUK_INTERNAL_DECL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h);
9232 DUK_INTERNAL_DECL void duk_debug_write_pointer(duk_hthread *thr, void *ptr);
9233 #if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
9234 DUK_INTERNAL_DECL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h);
9235 #endif
9236 DUK_INTERNAL_DECL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj);
9237 DUK_INTERNAL_DECL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv);
9238 #if 0  /* unused */
9239 DUK_INTERNAL_DECL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command);
9240 #endif
9241 DUK_INTERNAL_DECL void duk_debug_write_reply(duk_hthread *thr);
9242 DUK_INTERNAL_DECL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg);
9243 DUK_INTERNAL_DECL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command);
9244 DUK_INTERNAL_DECL void duk_debug_write_eom(duk_hthread *thr);
9245 
9246 DUK_INTERNAL_DECL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr);
9247 DUK_INTERNAL_DECL void duk_debug_send_status(duk_hthread *thr);
9248 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
9249 DUK_INTERNAL_DECL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal);
9250 #endif
9251 
9252 DUK_INTERNAL_DECL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc);
9253 DUK_INTERNAL_DECL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block);
9254 
9255 DUK_INTERNAL_DECL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line);
9256 DUK_INTERNAL_DECL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index);
9257 
9258 DUK_INTERNAL_DECL duk_bool_t duk_debug_is_attached(duk_heap *heap);
9259 DUK_INTERNAL_DECL duk_bool_t duk_debug_is_paused(duk_heap *heap);
9260 DUK_INTERNAL_DECL void duk_debug_set_paused(duk_heap *heap);
9261 DUK_INTERNAL_DECL void duk_debug_clear_paused(duk_heap *heap);
9262 DUK_INTERNAL_DECL void duk_debug_clear_pause_state(duk_heap *heap);
9263 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
9264 
9265 #endif  /* DUK_DEBUGGER_H_INCLUDED */
9266 /* #include duk_debug.h */
9267 #line 1 "duk_debug.h"
9268 /*
9269  *  Debugging macros, DUK_DPRINT() and its variants in particular.
9270  *
9271  *  DUK_DPRINT() allows formatted debug prints, and supports standard
9272  *  and Duktape specific formatters.  See duk_debug_vsnprintf.c for details.
9273  *
9274  *  DUK_D(x), DUK_DD(x), and DUK_DDD(x) are used together with log macros
9275  *  for technical reasons.  They are concretely used to hide 'x' from the
9276  *  compiler when the corresponding log level is disabled.  This allows
9277  *  clean builds on non-C99 compilers, at the cost of more verbose code.
9278  *  Examples:
9279  *
9280  *    DUK_D(DUK_DPRINT("foo"));
9281  *    DUK_DD(DUK_DDPRINT("foo"));
9282  *    DUK_DDD(DUK_DDDPRINT("foo"));
9283  *
9284  *  This approach is preferable to the old "double parentheses" hack because
9285  *  double parentheses make the C99 solution worse: __FILE__ and __LINE__ can
9286  *  no longer be added transparently without going through globals, which
9287  *  works poorly with threading.
9288  */
9289 
9290 #if !defined(DUK_DEBUG_H_INCLUDED)
9291 #define DUK_DEBUG_H_INCLUDED
9292 
9293 #if defined(DUK_USE_DEBUG)
9294 
9295 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
9296 #define DUK_D(x) x
9297 #else
9298 #define DUK_D(x) do { } while (0) /* omit */
9299 #endif
9300 
9301 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
9302 #define DUK_DD(x) x
9303 #else
9304 #define DUK_DD(x) do { } while (0) /* omit */
9305 #endif
9306 
9307 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
9308 #define DUK_DDD(x) x
9309 #else
9310 #define DUK_DDD(x) do { } while (0) /* omit */
9311 #endif
9312 
9313 /*
9314  *  Exposed debug macros: debugging enabled
9315  */
9316 
9317 #if defined(DUK_USE_VARIADIC_MACROS)
9318 
9319 /* Note: combining __FILE__, __LINE__, and __func__ into fmt would be
9320  * possible compile time, but waste some space with shared function names.
9321  */
9322 #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__);
9323 
9324 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
9325 #define DUK_DPRINT(...)          DUK__DEBUG_LOG(DUK_LEVEL_DEBUG, __VA_ARGS__)
9326 #else
9327 #define DUK_DPRINT(...)
9328 #endif
9329 
9330 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
9331 #define DUK_DDPRINT(...)         DUK__DEBUG_LOG(DUK_LEVEL_DDEBUG, __VA_ARGS__)
9332 #else
9333 #define DUK_DDPRINT(...)
9334 #endif
9335 
9336 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
9337 #define DUK_DDDPRINT(...)        DUK__DEBUG_LOG(DUK_LEVEL_DDDEBUG, __VA_ARGS__)
9338 #else
9339 #define DUK_DDDPRINT(...)
9340 #endif
9341 
9342 #else  /* DUK_USE_VARIADIC_MACROS */
9343 
9344 #define DUK__DEBUG_STASH(lev)    \
9345 	(void) DUK_SNPRINTF(duk_debug_file_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FILE_MACRO), \
9346 	(void) (duk_debug_file_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), \
9347 	(void) (duk_debug_line_stash = (duk_int_t) DUK_LINE_MACRO), \
9348 	(void) DUK_SNPRINTF(duk_debug_func_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FUNC_MACRO), \
9349 	(void) (duk_debug_func_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), \
9350 	(void) (duk_debug_level_stash = (lev))
9351 
9352 /* Without variadic macros resort to comma expression trickery to handle debug
9353  * prints.  This generates a lot of harmless warnings.  These hacks are not
9354  * needed normally because DUK_D() and friends will hide the entire debug log
9355  * statement from the compiler.
9356  */
9357 
9358 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
9359 #define DUK_DPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DEBUG), (void) duk_debug_log  /* args go here in parens */
9360 #else
9361 #define DUK_DPRINT  0 && /* args go here as a comma expression in parens */
9362 #endif
9363 
9364 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
9365 #define DUK_DDPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DDEBUG), (void) duk_debug_log  /* args go here in parens */
9366 #else
9367 #define DUK_DDPRINT  0 && /* args */
9368 #endif
9369 
9370 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
9371 #define DUK_DDDPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DDDEBUG), (void) duk_debug_log  /* args go here in parens */
9372 #else
9373 #define DUK_DDDPRINT  0 && /* args */
9374 #endif
9375 
9376 #endif  /* DUK_USE_VARIADIC_MACROS */
9377 
9378 #else  /* DUK_USE_DEBUG */
9379 
9380 /*
9381  *  Exposed debug macros: debugging disabled
9382  */
9383 
9384 #define DUK_D(x) do { } while (0) /* omit */
9385 #define DUK_DD(x) do { } while (0) /* omit */
9386 #define DUK_DDD(x) do { } while (0) /* omit */
9387 
9388 #if defined(DUK_USE_VARIADIC_MACROS)
9389 
9390 #define DUK_DPRINT(...)
9391 #define DUK_DDPRINT(...)
9392 #define DUK_DDDPRINT(...)
9393 
9394 #else  /* DUK_USE_VARIADIC_MACROS */
9395 
9396 #define DUK_DPRINT    0 && /* args go here as a comma expression in parens */
9397 #define DUK_DDPRINT   0 && /* args */
9398 #define DUK_DDDPRINT  0 && /* args */
9399 
9400 #endif  /* DUK_USE_VARIADIC_MACROS */
9401 
9402 #endif  /* DUK_USE_DEBUG */
9403 
9404 /*
9405  *  Structs
9406  */
9407 
9408 #if defined(DUK_USE_DEBUG)
9409 struct duk_fixedbuffer {
9410 	duk_uint8_t *buffer;
9411 	duk_size_t length;
9412 	duk_size_t offset;
9413 	duk_bool_t truncated;
9414 };
9415 #endif
9416 
9417 /*
9418  *  Prototypes
9419  */
9420 
9421 #if defined(DUK_USE_DEBUG)
9422 DUK_INTERNAL_DECL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap);
9423 #if 0  /*unused*/
9424 DUK_INTERNAL_DECL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...);
9425 #endif
9426 DUK_INTERNAL_DECL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size);
9427 
9428 #if defined(DUK_USE_VARIADIC_MACROS)
9429 DUK_INTERNAL_DECL void duk_debug_log(duk_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...);
9430 #else  /* DUK_USE_VARIADIC_MACROS */
9431 /* parameter passing, not thread safe */
9432 #define DUK_DEBUG_STASH_SIZE  128
9433 #if !defined(DUK_SINGLE_FILE)
9434 DUK_INTERNAL_DECL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
9435 DUK_INTERNAL_DECL duk_int_t duk_debug_line_stash;
9436 DUK_INTERNAL_DECL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
9437 DUK_INTERNAL_DECL duk_int_t duk_debug_level_stash;
9438 #endif
9439 DUK_INTERNAL_DECL void duk_debug_log(const char *fmt, ...);
9440 #endif  /* DUK_USE_VARIADIC_MACROS */
9441 
9442 DUK_INTERNAL_DECL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length);
9443 DUK_INTERNAL_DECL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x);
9444 DUK_INTERNAL_DECL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x);
9445 DUK_INTERNAL_DECL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...);
9446 DUK_INTERNAL_DECL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size);
9447 DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
9448 
9449 #endif  /* DUK_USE_DEBUG */
9450 
9451 #endif  /* DUK_DEBUG_H_INCLUDED */
9452 /* #include duk_error.h */
9453 #line 1 "duk_error.h"
9454 /*
9455  *  Error handling macros, assertion macro, error codes.
9456  *
9457  *  There are three types of 'errors':
9458  *
9459  *    1. Ordinary errors relative to a thread, cause a longjmp, catchable.
9460  *    2. Fatal errors relative to a heap, cause fatal handler to be called.
9461  *    3. Fatal errors without context, cause the default (not heap specific)
9462  *       fatal handler to be called.
9463  *
9464  *  Fatal errors without context are used by debug code such as assertions.
9465  *  By providing a fatal error handler for a Duktape heap, user code can
9466  *  avoid fatal errors without context in non-debug builds.
9467  */
9468 
9469 #if !defined(DUK_ERROR_H_INCLUDED)
9470 #define DUK_ERROR_H_INCLUDED
9471 
9472 /*
9473  *  Error codes: defined in duktape.h
9474  *
9475  *  Error codes are used as a shorthand to throw exceptions from inside
9476  *  the implementation.  The appropriate ECMAScript object is constructed
9477  *  based on the code.  ECMAScript code throws objects directly.  The error
9478  *  codes are defined in the public API header because they are also used
9479  *  by calling code.
9480  */
9481 
9482 /*
9483  *  Normal error
9484  *
9485  *  Normal error is thrown with a longjmp() through the current setjmp()
9486  *  catchpoint record in the duk_heap.  The 'curr_thread' of the duk_heap
9487  *  identifies the throwing thread.
9488  *
9489  *  Error formatting is usually unnecessary.  The error macros provide a
9490  *  zero argument version (no formatting) and separate macros for small
9491  *  argument counts.  Variadic macros are not used to avoid portability
9492  *  issues and avoid the need for stash-based workarounds when they're not
9493  *  available.  Vararg calls are avoided for non-formatted error calls
9494  *  because vararg call sites are larger than normal, and there are a lot
9495  *  of call sites with no formatting.
9496  *
9497  *  Note that special formatting provided by debug macros is NOT available.
9498  *
9499  *  The _RAW variants allow the caller to specify file and line.  This makes
9500  *  it easier to write checked calls which want to use the call site of the
9501  *  checked function, not the error macro call inside the checked function.
9502  */
9503 
9504 #if defined(DUK_USE_VERBOSE_ERRORS)
9505 
9506 /* Because there are quite many call sites, pack error code (require at most
9507  * 8-bit) into a single argument.
9508  */
9509 #define DUK_ERROR(thr,err,msg) do { \
9510 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9511 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9512 		duk_err_handle_error((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
9513 	} while (0)
9514 #define DUK_ERROR_RAW(thr,file,line,err,msg) do { \
9515 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9516 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9517 		duk_err_handle_error((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
9518 	} while (0)
9519 
9520 #define DUK_ERROR_FMT1(thr,err,fmt,arg1) do { \
9521 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9522 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9523 		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
9524 	} while (0)
9525 #define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) do { \
9526 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9527 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9528 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
9529 	} while (0)
9530 
9531 #define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) do { \
9532 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9533 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9534 		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
9535 	} while (0)
9536 #define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) do { \
9537 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9538 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9539 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
9540 	} while (0)
9541 
9542 #define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) do { \
9543 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9544 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9545 		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
9546 	} while (0)
9547 #define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) do { \
9548 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9549 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9550 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
9551 	} while (0)
9552 
9553 #define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) do { \
9554 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9555 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9556 		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)); \
9557 	} while (0)
9558 #define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) do { \
9559 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9560 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9561 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3), (arg4)); \
9562 	} while (0)
9563 
9564 #else  /* DUK_USE_VERBOSE_ERRORS */
9565 
9566 #define DUK_ERROR(thr,err,msg)                    duk_err_handle_error((thr), (err))
9567 #define DUK_ERROR_RAW(thr,file,line,err,msg)      duk_err_handle_error((thr), (err))
9568 
9569 #define DUK_ERROR_FMT1(thr,err,fmt,arg1) DUK_ERROR((thr),(err),(fmt))
9570 #define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
9571 
9572 #define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) DUK_ERROR((thr),(err),(fmt))
9573 #define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
9574 
9575 #define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) DUK_ERROR((thr),(err),(fmt))
9576 #define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
9577 
9578 #define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR((thr),(err),(fmt))
9579 #define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
9580 
9581 #endif  /* DUK_USE_VERBOSE_ERRORS */
9582 
9583 /*
9584  *  Fatal error without context
9585  *
9586  *  The macro is an expression to make it compatible with DUK_ASSERT_EXPR().
9587  */
9588 
9589 #define DUK_FATAL_WITHOUT_CONTEXT(msg) \
9590 	duk_default_fatal_handler(NULL, (msg))
9591 
9592 /*
9593  *  Error throwing helpers
9594  *
9595  *  The goal is to provide verbose and configurable error messages.  Call
9596  *  sites should be clean in source code and compile to a small footprint.
9597  *  Small footprint is also useful for performance because small cold paths
9598  *  reduce code cache pressure.  Adding macros here only makes sense if there
9599  *  are enough call sites to get concrete benefits.
9600  *
9601  *  DUK_ERROR_xxx() macros are generic and can be used anywhere.
9602  *
9603  *  DUK_DCERROR_xxx() macros can only be used in Duktape/C functions where
9604  *  the "return DUK_RET_xxx;" shorthand is available for low memory targets.
9605  *  The DUK_DCERROR_xxx() macros always either throw or perform a
9606  *  'return DUK_RET_xxx' from the calling function.
9607  */
9608 
9609 #if defined(DUK_USE_VERBOSE_ERRORS)
9610 /* Verbose errors with key/value summaries (non-paranoid) or without key/value
9611  * summaries (paranoid, for some security sensitive environments), the paranoid
9612  * vs. non-paranoid distinction affects only a few specific errors.
9613  */
9614 #if defined(DUK_USE_PARANOID_ERRORS)
9615 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
9616 		duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx), (expectname)); \
9617 	} while (0)
9618 #else  /* DUK_USE_PARANOID_ERRORS */
9619 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
9620 		duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx), (expectname)); \
9621 	} while (0)
9622 #endif  /* DUK_USE_PARANOID_ERRORS */
9623 
9624 #define DUK_ERROR_INTERNAL(thr) do { \
9625 		duk_err_error_internal((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9626 	} while (0)
9627 #define DUK_DCERROR_INTERNAL(thr) do { \
9628 		DUK_ERROR_INTERNAL((thr)); \
9629 		return 0; \
9630 	} while (0)
9631 #define DUK_ERROR_ALLOC_FAILED(thr) do { \
9632 		duk_err_error_alloc_failed((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9633 	} while (0)
9634 #define DUK_ERROR_UNSUPPORTED(thr) do { \
9635 		DUK_ERROR((thr), DUK_ERR_ERROR, DUK_STR_UNSUPPORTED); \
9636 	} while (0)
9637 #define DUK_ERROR_ERROR(thr,msg) do { \
9638 		duk_err_error((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
9639 	} while (0)
9640 #define DUK_ERROR_RANGE_INDEX(thr,idx) do { \
9641 		duk_err_range_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx)); \
9642 	} while (0)
9643 #define DUK_ERROR_RANGE_PUSH_BEYOND(thr) do { \
9644 		duk_err_range_push_beyond((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9645 	} while (0)
9646 #define DUK_ERROR_RANGE_INVALID_ARGS(thr) do { \
9647 		DUK_ERROR_RANGE((thr), DUK_STR_INVALID_ARGS); \
9648 	} while (0)
9649 #define DUK_DCERROR_RANGE_INVALID_ARGS(thr) do { \
9650 		DUK_ERROR_RANGE_INVALID_ARGS((thr)); \
9651 		return 0; \
9652 	} while (0)
9653 #define DUK_ERROR_RANGE_INVALID_COUNT(thr) do { \
9654 		DUK_ERROR_RANGE((thr), DUK_STR_INVALID_COUNT); \
9655 	} while (0)
9656 #define DUK_DCERROR_RANGE_INVALID_COUNT(thr) do { \
9657 		DUK_ERROR_RANGE_INVALID_COUNT((thr)); \
9658 		return 0; \
9659 	} while (0)
9660 #define DUK_ERROR_RANGE_INVALID_LENGTH(thr) do { \
9661 		DUK_ERROR_RANGE((thr), DUK_STR_INVALID_LENGTH); \
9662 	} while (0)
9663 #define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) do { \
9664 		DUK_ERROR_RANGE_INVALID_LENGTH((thr)); \
9665 		return 0; \
9666 	} while (0)
9667 #define DUK_ERROR_RANGE(thr,msg) do { \
9668 		duk_err_range((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
9669 	} while (0)
9670 #define DUK_ERROR_EVAL(thr,msg) do { \
9671 		DUK_ERROR((thr), DUK_ERR_EVAL_ERROR, (msg)); \
9672 	} while (0)
9673 #define DUK_ERROR_REFERENCE(thr,msg) do { \
9674 		DUK_ERROR((thr), DUK_ERR_REFERENCE_ERROR, (msg)); \
9675 	} while (0)
9676 #define DUK_ERROR_SYNTAX(thr,msg) do { \
9677 		DUK_ERROR((thr), DUK_ERR_SYNTAX_ERROR, (msg)); \
9678 	} while (0)
9679 #define DUK_ERROR_TYPE_INVALID_ARGS(thr) do { \
9680 		duk_err_type_invalid_args((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9681 	} while (0)
9682 #define DUK_DCERROR_TYPE_INVALID_ARGS(thr) do { \
9683 		DUK_ERROR_TYPE_INVALID_ARGS((thr)); \
9684 		return 0; \
9685 	} while (0)
9686 #define DUK_ERROR_TYPE_INVALID_STATE(thr) do { \
9687 		duk_err_type_invalid_state((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9688 	} while (0)
9689 #define DUK_DCERROR_TYPE_INVALID_STATE(thr) do { \
9690 		DUK_ERROR_TYPE_INVALID_STATE((thr)); \
9691 		return 0; \
9692 	} while (0)
9693 #define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9694 		duk_err_type_invalid_trap_result((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9695 	} while (0)
9696 #define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9697 		DUK_ERROR_TYPE((thr), DUK_STR_INVALID_TRAP_RESULT); \
9698 	} while (0)
9699 #define DUK_ERROR_TYPE(thr,msg) do { \
9700 		DUK_ERROR((thr), DUK_ERR_TYPE_ERROR, (msg)); \
9701 	} while (0)
9702 #define DUK_ERROR_URI(thr,msg) do { \
9703 		DUK_ERROR((thr), DUK_ERR_URI_ERROR, (msg)); \
9704 	} while (0)
9705 #else  /* DUK_USE_VERBOSE_ERRORS */
9706 /* Non-verbose errors for low memory targets: no file, line, or message. */
9707 
9708 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
9709 		duk_err_type((thr)); \
9710 	} while (0)
9711 
9712 #define DUK_ERROR_INTERNAL(thr) do { \
9713 		duk_err_error((thr)); \
9714 	} while (0)
9715 #define DUK_DCERROR_INTERNAL(thr) do { \
9716 		DUK_UNREF((thr)); \
9717 		return DUK_RET_ERROR; \
9718 	} while (0)
9719 #define DUK_ERROR_ALLOC_FAILED(thr) do { \
9720 		duk_err_error((thr)); \
9721 	} while (0)
9722 #define DUK_ERROR_UNSUPPORTED(thr) do { \
9723 		duk_err_error((thr)); \
9724 	} while (0)
9725 #define DUK_ERROR_ERROR(thr,msg) do { \
9726 		duk_err_error((thr)); \
9727 	} while (0)
9728 #define DUK_ERROR_RANGE_INDEX(thr,idx) do { \
9729 		duk_err_range((thr)); \
9730 	} while (0)
9731 #define DUK_ERROR_RANGE_PUSH_BEYOND(thr) do { \
9732 		duk_err_range((thr)); \
9733 	} while (0)
9734 #define DUK_ERROR_RANGE_INVALID_ARGS(thr) do { \
9735 		duk_err_range((thr)); \
9736 	} while (0)
9737 #define DUK_DCERROR_RANGE_INVALID_ARGS(thr) do { \
9738 		DUK_UNREF((thr)); \
9739 		return DUK_RET_RANGE_ERROR; \
9740 	} while (0)
9741 #define DUK_ERROR_RANGE_INVALID_COUNT(thr) do { \
9742 		duk_err_range((thr)); \
9743 	} while (0)
9744 #define DUK_DCERROR_RANGE_INVALID_COUNT(thr) do { \
9745 		DUK_UNREF((thr)); \
9746 		return DUK_RET_RANGE_ERROR; \
9747 	} while (0)
9748 #define DUK_ERROR_RANGE_INVALID_LENGTH(thr) do { \
9749 		duk_err_range((thr)); \
9750 	} while (0)
9751 #define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) do { \
9752 		DUK_UNREF((thr)); \
9753 		return DUK_RET_RANGE_ERROR; \
9754 	} while (0)
9755 #define DUK_ERROR_RANGE(thr,msg) do { \
9756 		duk_err_range((thr)); \
9757 	} while (0)
9758 #define DUK_ERROR_EVAL(thr,msg) do { \
9759 		duk_err_eval((thr)); \
9760 	} while (0)
9761 #define DUK_ERROR_REFERENCE(thr,msg) do { \
9762 		duk_err_reference((thr)); \
9763 	} while (0)
9764 #define DUK_ERROR_SYNTAX(thr,msg) do { \
9765 		duk_err_syntax((thr)); \
9766 	} while (0)
9767 #define DUK_ERROR_TYPE_INVALID_ARGS(thr) do { \
9768 		duk_err_type((thr)); \
9769 	} while (0)
9770 #define DUK_DCERROR_TYPE_INVALID_ARGS(thr) do { \
9771 		DUK_UNREF((thr)); \
9772 		return DUK_RET_TYPE_ERROR; \
9773 	} while (0)
9774 #define DUK_ERROR_TYPE_INVALID_STATE(thr) do { \
9775 		duk_err_type((thr)); \
9776 	} while (0)
9777 #define DUK_DCERROR_TYPE_INVALID_STATE(thr) do { \
9778 		duk_err_type((thr)); \
9779 	} while (0)
9780 #define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9781 		duk_err_type((thr)); \
9782 	} while (0)
9783 #define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9784 		DUK_UNREF((thr)); \
9785 		return DUK_RET_TYPE_ERROR; \
9786 	} while (0)
9787 #define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9788 		duk_err_type((thr)); \
9789 	} while (0)
9790 #define DUK_ERROR_TYPE(thr,msg) do { \
9791 		duk_err_type((thr)); \
9792 	} while (0)
9793 #define DUK_ERROR_URI(thr,msg) do { \
9794 		duk_err_uri((thr)); \
9795 	} while (0)
9796 #endif  /* DUK_USE_VERBOSE_ERRORS */
9797 
9798 /*
9799  *  Assert macro: failure causes a fatal error.
9800  *
9801  *  NOTE: since the assert macro doesn't take a heap/context argument, there's
9802  *  no way to look up a heap/context specific fatal error handler which may have
9803  *  been given by the application.  Instead, assertion failures always use the
9804  *  internal default fatal error handler; it can be replaced via duk_config.h
9805  *  and then applies to all Duktape heaps.
9806  */
9807 
9808 #if defined(DUK_USE_ASSERTIONS)
9809 
9810 /* The message should be a compile time constant without formatting (less risk);
9811  * we don't care about assertion text size because they're not used in production
9812  * builds.
9813  */
9814 #define DUK_ASSERT(x)  do { \
9815 	if (!(x)) { \
9816 		DUK_FATAL_WITHOUT_CONTEXT("assertion failed: " #x \
9817 			" (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"); \
9818 	} \
9819 	} while (0)
9820 
9821 /* Assertion compatible inside a comma expression, evaluates to void. */
9822 #define DUK_ASSERT_EXPR(x) \
9823 	((void) ((x) ? 0 : (DUK_FATAL_WITHOUT_CONTEXT("assertion failed: " #x \
9824 				" (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"), 0)))
9825 
9826 #else  /* DUK_USE_ASSERTIONS */
9827 
9828 #define DUK_ASSERT(x)  do { /* assertion omitted */ } while (0)
9829 
9830 #define DUK_ASSERT_EXPR(x)  ((void) 0)
9831 
9832 #endif  /* DUK_USE_ASSERTIONS */
9833 
9834 /* this variant is used when an assert would generate a compile warning by
9835  * being always true (e.g. >= 0 comparison for an unsigned value
9836  */
9837 #define DUK_ASSERT_DISABLE(x)  do { /* assertion disabled */ } while (0)
9838 
9839 /*
9840  *  Assertion helpers
9841  */
9842 
9843 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
9844 #define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h)  do { \
9845 		DUK_ASSERT((h) == NULL || DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) (h)) > 0); \
9846 	} while (0)
9847 #define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv)  do { \
9848 		if ((tv) != NULL && DUK_TVAL_IS_HEAP_ALLOCATED((tv))) { \
9849 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(DUK_TVAL_GET_HEAPHDR((tv))) > 0); \
9850 		} \
9851 	} while (0)
9852 #else
9853 #define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h)  /* no refcount check */
9854 #define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv)    /* no refcount check */
9855 #endif
9856 
9857 #define DUK_ASSERT_TOP(ctx,n)  DUK_ASSERT((duk_idx_t) duk_get_top((ctx)) == (duk_idx_t) (n))
9858 
9859 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_PACKED_TVAL)
9860 #define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)  do { \
9861 		duk_double_union duk__assert_tmp_du; \
9862 		duk__assert_tmp_du.d = (dval); \
9863 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&duk__assert_tmp_du)); \
9864 	} while (0)
9865 #else
9866 #define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)  /* nop */
9867 #endif
9868 
9869 #define DUK_ASSERT_VS_SPACE(thr) \
9870 	DUK_ASSERT(thr->valstack_top < thr->valstack_end)
9871 
9872 /*
9873  *  Helper to initialize a memory area (e.g. struct) with garbage when
9874  *  assertions enabled.
9875  */
9876 
9877 #if defined(DUK_USE_ASSERTIONS)
9878 #define DUK_ASSERT_SET_GARBAGE(ptr,size) do { \
9879 		duk_memset_unsafe((void *) (ptr), 0x5a, size); \
9880 	} while (0)
9881 #else
9882 #define DUK_ASSERT_SET_GARBAGE(ptr,size) do {} while (0)
9883 #endif
9884 
9885 /*
9886  *  Helper for valstack space
9887  *
9888  *  Caller of DUK_ASSERT_VALSTACK_SPACE() estimates the number of free stack entries
9889  *  required for its own use, and any child calls which are not (a) Duktape API calls
9890  *  or (b) Duktape calls which involve extending the valstack (e.g. getter call).
9891  */
9892 
9893 #define DUK_VALSTACK_ASSERT_EXTRA  5  /* this is added to checks to allow for Duktape
9894                                        * API calls in addition to function's own use
9895                                        */
9896 #if defined(DUK_USE_ASSERTIONS)
9897 #define DUK_ASSERT_VALSTACK_SPACE(thr,n)   do { \
9898 		DUK_ASSERT((thr) != NULL); \
9899 		DUK_ASSERT((thr)->valstack_end - (thr)->valstack_top >= (n) + DUK_VALSTACK_ASSERT_EXTRA); \
9900 	} while (0)
9901 #else
9902 #define DUK_ASSERT_VALSTACK_SPACE(thr,n)   /* no valstack space check */
9903 #endif
9904 
9905 /*
9906  *  Prototypes
9907  */
9908 
9909 #if defined(DUK_USE_VERBOSE_ERRORS)
9910 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));
9911 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, ...));
9912 #else  /* DUK_USE_VERBOSE_ERRORS */
9913 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code));
9914 #endif  /* DUK_USE_VERBOSE_ERRORS */
9915 
9916 #if defined(DUK_USE_VERBOSE_ERRORS)
9917 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));
9918 #else
9919 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code));
9920 #endif
9921 
9922 DUK_NORETURN(DUK_INTERNAL_DECL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc));
9923 
9924 #define DUK_AUGMENT_FLAG_NOBLAME_FILELINE  (1U << 0)  /* if set, don't blame C file/line for .fileName and .lineNumber */
9925 #define DUK_AUGMENT_FLAG_SKIP_ONE          (1U << 1)  /* if set, skip topmost activation in traceback construction */
9926 
9927 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
9928 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);
9929 #endif
9930 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
9931 DUK_INTERNAL_DECL void duk_err_augment_error_throw(duk_hthread *thr);
9932 #endif
9933 
9934 #if defined(DUK_USE_VERBOSE_ERRORS)
9935 #if defined(DUK_USE_PARANOID_ERRORS)
9936 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));
9937 #else
9938 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));
9939 #endif
9940 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber));
9941 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error_alloc_failed(duk_hthread *thr, const char *filename, duk_int_t linenumber));
9942 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
9943 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx));
9944 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range_push_beyond(duk_hthread *thr, const char *filename, duk_int_t linenumber));
9945 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
9946 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_args(duk_hthread *thr, const char *filename, duk_int_t linenumber));
9947 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_state(duk_hthread *thr, const char *filename, duk_int_t linenumber));
9948 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_trap_result(duk_hthread *thr, const char *filename, duk_int_t linenumber));
9949 #else  /* DUK_VERBOSE_ERRORS */
9950 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error(duk_hthread *thr));
9951 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr));
9952 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_eval(duk_hthread *thr));
9953 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_reference(duk_hthread *thr));
9954 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_syntax(duk_hthread *thr));
9955 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type(duk_hthread *thr));
9956 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_uri(duk_hthread *thr));
9957 #endif /* DUK_VERBOSE_ERRORS */
9958 
9959 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_longjmp(duk_hthread *thr));
9960 
9961 DUK_NORETURN(DUK_INTERNAL_DECL void duk_default_fatal_handler(void *udata, const char *msg));
9962 
9963 DUK_INTERNAL_DECL void duk_err_setup_ljstate1(duk_hthread *thr, duk_small_uint_t lj_type, duk_tval *tv_val);
9964 #if defined(DUK_USE_DEBUGGER_SUPPORT)
9965 DUK_INTERNAL_DECL void duk_err_check_debugger_integration(duk_hthread *thr);
9966 #endif
9967 
9968 DUK_INTERNAL_DECL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t err_code);
9969 
9970 #endif  /* DUK_ERROR_H_INCLUDED */
9971 /* #include duk_unicode.h */
9972 #line 1 "duk_unicode.h"
9973 /*
9974  *  Unicode helpers
9975  */
9976 
9977 #if !defined(DUK_UNICODE_H_INCLUDED)
9978 #define DUK_UNICODE_H_INCLUDED
9979 
9980 /*
9981  *  UTF-8 / XUTF-8 / CESU-8 constants
9982  */
9983 
9984 #define DUK_UNICODE_MAX_XUTF8_LENGTH      7   /* up to 36 bit codepoints */
9985 #define DUK_UNICODE_MAX_XUTF8_BMP_LENGTH  3   /* all codepoints up to U+FFFF */
9986 #define DUK_UNICODE_MAX_CESU8_LENGTH      6   /* all codepoints up to U+10FFFF */
9987 #define DUK_UNICODE_MAX_CESU8_BMP_LENGTH  3   /* all codepoints up to U+FFFF */
9988 
9989 /*
9990  *  Useful Unicode codepoints
9991  *
9992  *  Integer constants must be signed to avoid unexpected coercions
9993  *  in comparisons.
9994  */
9995 
9996 #define DUK_UNICODE_CP_ZWNJ                   0x200cL  /* zero-width non-joiner */
9997 #define DUK_UNICODE_CP_ZWJ                    0x200dL  /* zero-width joiner */
9998 #define DUK_UNICODE_CP_REPLACEMENT_CHARACTER  0xfffdL  /* http://en.wikipedia.org/wiki/Replacement_character#Replacement_character */
9999 
10000 /*
10001  *  ASCII character constants
10002  *
10003  *  C character literals like 'x' have a platform specific value and do
10004  *  not match ASCII (UTF-8) values on e.g. EBCDIC platforms.  So, use
10005  *  these (admittedly awkward) constants instead.  These constants must
10006  *  also have signed values to avoid unexpected coercions in comparisons.
10007  *
10008  *  http://en.wikipedia.org/wiki/ASCII
10009  */
10010 
10011 #define DUK_ASC_NUL              0x00
10012 #define DUK_ASC_SOH              0x01
10013 #define DUK_ASC_STX              0x02
10014 #define DUK_ASC_ETX              0x03
10015 #define DUK_ASC_EOT              0x04
10016 #define DUK_ASC_ENQ              0x05
10017 #define DUK_ASC_ACK              0x06
10018 #define DUK_ASC_BEL              0x07
10019 #define DUK_ASC_BS               0x08
10020 #define DUK_ASC_HT               0x09
10021 #define DUK_ASC_LF               0x0a
10022 #define DUK_ASC_VT               0x0b
10023 #define DUK_ASC_FF               0x0c
10024 #define DUK_ASC_CR               0x0d
10025 #define DUK_ASC_SO               0x0e
10026 #define DUK_ASC_SI               0x0f
10027 #define DUK_ASC_DLE              0x10
10028 #define DUK_ASC_DC1              0x11
10029 #define DUK_ASC_DC2              0x12
10030 #define DUK_ASC_DC3              0x13
10031 #define DUK_ASC_DC4              0x14
10032 #define DUK_ASC_NAK              0x15
10033 #define DUK_ASC_SYN              0x16
10034 #define DUK_ASC_ETB              0x17
10035 #define DUK_ASC_CAN              0x18
10036 #define DUK_ASC_EM               0x19
10037 #define DUK_ASC_SUB              0x1a
10038 #define DUK_ASC_ESC              0x1b
10039 #define DUK_ASC_FS               0x1c
10040 #define DUK_ASC_GS               0x1d
10041 #define DUK_ASC_RS               0x1e
10042 #define DUK_ASC_US               0x1f
10043 #define DUK_ASC_SPACE            0x20
10044 #define DUK_ASC_EXCLAMATION      0x21
10045 #define DUK_ASC_DOUBLEQUOTE      0x22
10046 #define DUK_ASC_HASH             0x23
10047 #define DUK_ASC_DOLLAR           0x24
10048 #define DUK_ASC_PERCENT          0x25
10049 #define DUK_ASC_AMP              0x26
10050 #define DUK_ASC_SINGLEQUOTE      0x27
10051 #define DUK_ASC_LPAREN           0x28
10052 #define DUK_ASC_RPAREN           0x29
10053 #define DUK_ASC_STAR             0x2a
10054 #define DUK_ASC_PLUS             0x2b
10055 #define DUK_ASC_COMMA            0x2c
10056 #define DUK_ASC_MINUS            0x2d
10057 #define DUK_ASC_PERIOD           0x2e
10058 #define DUK_ASC_SLASH            0x2f
10059 #define DUK_ASC_0                0x30
10060 #define DUK_ASC_1                0x31
10061 #define DUK_ASC_2                0x32
10062 #define DUK_ASC_3                0x33
10063 #define DUK_ASC_4                0x34
10064 #define DUK_ASC_5                0x35
10065 #define DUK_ASC_6                0x36
10066 #define DUK_ASC_7                0x37
10067 #define DUK_ASC_8                0x38
10068 #define DUK_ASC_9                0x39
10069 #define DUK_ASC_COLON            0x3a
10070 #define DUK_ASC_SEMICOLON        0x3b
10071 #define DUK_ASC_LANGLE           0x3c
10072 #define DUK_ASC_EQUALS           0x3d
10073 #define DUK_ASC_RANGLE           0x3e
10074 #define DUK_ASC_QUESTION         0x3f
10075 #define DUK_ASC_ATSIGN           0x40
10076 #define DUK_ASC_UC_A             0x41
10077 #define DUK_ASC_UC_B             0x42
10078 #define DUK_ASC_UC_C             0x43
10079 #define DUK_ASC_UC_D             0x44
10080 #define DUK_ASC_UC_E             0x45
10081 #define DUK_ASC_UC_F             0x46
10082 #define DUK_ASC_UC_G             0x47
10083 #define DUK_ASC_UC_H             0x48
10084 #define DUK_ASC_UC_I             0x49
10085 #define DUK_ASC_UC_J             0x4a
10086 #define DUK_ASC_UC_K             0x4b
10087 #define DUK_ASC_UC_L             0x4c
10088 #define DUK_ASC_UC_M             0x4d
10089 #define DUK_ASC_UC_N             0x4e
10090 #define DUK_ASC_UC_O             0x4f
10091 #define DUK_ASC_UC_P             0x50
10092 #define DUK_ASC_UC_Q             0x51
10093 #define DUK_ASC_UC_R             0x52
10094 #define DUK_ASC_UC_S             0x53
10095 #define DUK_ASC_UC_T             0x54
10096 #define DUK_ASC_UC_U             0x55
10097 #define DUK_ASC_UC_V             0x56
10098 #define DUK_ASC_UC_W             0x57
10099 #define DUK_ASC_UC_X             0x58
10100 #define DUK_ASC_UC_Y             0x59
10101 #define DUK_ASC_UC_Z             0x5a
10102 #define DUK_ASC_LBRACKET         0x5b
10103 #define DUK_ASC_BACKSLASH        0x5c
10104 #define DUK_ASC_RBRACKET         0x5d
10105 #define DUK_ASC_CARET            0x5e
10106 #define DUK_ASC_UNDERSCORE       0x5f
10107 #define DUK_ASC_GRAVE            0x60
10108 #define DUK_ASC_LC_A             0x61
10109 #define DUK_ASC_LC_B             0x62
10110 #define DUK_ASC_LC_C             0x63
10111 #define DUK_ASC_LC_D             0x64
10112 #define DUK_ASC_LC_E             0x65
10113 #define DUK_ASC_LC_F             0x66
10114 #define DUK_ASC_LC_G             0x67
10115 #define DUK_ASC_LC_H             0x68
10116 #define DUK_ASC_LC_I             0x69
10117 #define DUK_ASC_LC_J             0x6a
10118 #define DUK_ASC_LC_K             0x6b
10119 #define DUK_ASC_LC_L             0x6c
10120 #define DUK_ASC_LC_M             0x6d
10121 #define DUK_ASC_LC_N             0x6e
10122 #define DUK_ASC_LC_O             0x6f
10123 #define DUK_ASC_LC_P             0x70
10124 #define DUK_ASC_LC_Q             0x71
10125 #define DUK_ASC_LC_R             0x72
10126 #define DUK_ASC_LC_S             0x73
10127 #define DUK_ASC_LC_T             0x74
10128 #define DUK_ASC_LC_U             0x75
10129 #define DUK_ASC_LC_V             0x76
10130 #define DUK_ASC_LC_W             0x77
10131 #define DUK_ASC_LC_X             0x78
10132 #define DUK_ASC_LC_Y             0x79
10133 #define DUK_ASC_LC_Z             0x7a
10134 #define DUK_ASC_LCURLY           0x7b
10135 #define DUK_ASC_PIPE             0x7c
10136 #define DUK_ASC_RCURLY           0x7d
10137 #define DUK_ASC_TILDE            0x7e
10138 #define DUK_ASC_DEL              0x7f
10139 
10140 /*
10141  *  Miscellaneous
10142  */
10143 
10144 /* Uppercase A is 0x41, lowercase a is 0x61; OR 0x20 to convert uppercase
10145  * to lowercase.
10146  */
10147 #define DUK_LOWERCASE_CHAR_ASCII(x)  ((x) | 0x20)
10148 
10149 /*
10150  *  Unicode tables
10151  */
10152 
10153 #if defined(DUK_USE_SOURCE_NONBMP)
10154 /*
10155  *  Automatically generated by extract_chars.py, do not edit!
10156  */
10157 
10158 extern const duk_uint8_t duk_unicode_ids_noa[1063];
10159 #else
10160 /*
10161  *  Automatically generated by extract_chars.py, do not edit!
10162  */
10163 
10164 extern const duk_uint8_t duk_unicode_ids_noabmp[626];
10165 #endif
10166 
10167 #if defined(DUK_USE_SOURCE_NONBMP)
10168 /*
10169  *  Automatically generated by extract_chars.py, do not edit!
10170  */
10171 
10172 extern const duk_uint8_t duk_unicode_ids_m_let_noa[42];
10173 #else
10174 /*
10175  *  Automatically generated by extract_chars.py, do not edit!
10176  */
10177 
10178 extern const duk_uint8_t duk_unicode_ids_m_let_noabmp[24];
10179 #endif
10180 
10181 #if defined(DUK_USE_SOURCE_NONBMP)
10182 /*
10183  *  Automatically generated by extract_chars.py, do not edit!
10184  */
10185 
10186 extern const duk_uint8_t duk_unicode_idp_m_ids_noa[549];
10187 #else
10188 /*
10189  *  Automatically generated by extract_chars.py, do not edit!
10190  */
10191 
10192 extern const duk_uint8_t duk_unicode_idp_m_ids_noabmp[358];
10193 #endif
10194 
10195 /*
10196  *  Automatically generated by extract_caseconv.py, do not edit!
10197  */
10198 
10199 extern const duk_uint8_t duk_unicode_caseconv_uc[1386];
10200 extern const duk_uint8_t duk_unicode_caseconv_lc[680];
10201 
10202 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
10203 /*
10204  *  Automatically generated by extract_caseconv.py, do not edit!
10205  */
10206 
10207 extern const duk_uint16_t duk_unicode_re_canon_lookup[65536];
10208 #endif
10209 
10210 #if defined(DUK_USE_REGEXP_CANON_BITMAP)
10211 /*
10212  *  Automatically generated by extract_caseconv.py, do not edit!
10213  */
10214 
10215 #define DUK_CANON_BITMAP_BLKSIZE                                      32
10216 #define DUK_CANON_BITMAP_BLKSHIFT                                     5
10217 #define DUK_CANON_BITMAP_BLKMASK                                      31
10218 extern const duk_uint8_t duk_unicode_re_canon_bitmap[256];
10219 #endif
10220 
10221 /*
10222  *  Extern
10223  */
10224 
10225 /* duk_unicode_support.c */
10226 #if !defined(DUK_SINGLE_FILE)
10227 DUK_INTERNAL_DECL const duk_uint8_t duk_unicode_xutf8_markers[7];
10228 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_digit[2];
10229 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_white[22];
10230 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_wordchar[8];
10231 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_digit[4];
10232 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_white[24];
10233 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10];
10234 DUK_INTERNAL_DECL const duk_int8_t duk_is_idchar_tab[128];
10235 #endif  /* !DUK_SINGLE_FILE */
10236 
10237 /*
10238  *  Prototypes
10239  */
10240 
10241 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp);
10242 #if defined(DUK_USE_ASSERTIONS)
10243 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp);
10244 #endif
10245 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out);
10246 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out);
10247 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);
10248 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);
10249 DUK_INTERNAL_DECL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen);
10250 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp);
10251 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp);
10252 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp);
10253 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp);
10254 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp);
10255 DUK_INTERNAL_DECL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase);
10256 #if defined(DUK_USE_REGEXP_SUPPORT)
10257 DUK_INTERNAL_DECL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp);
10258 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp);
10259 #endif
10260 
10261 #endif  /* DUK_UNICODE_H_INCLUDED */
10262 /* #include duk_json.h */
10263 #line 1 "duk_json.h"
10264 /*
10265  *  Defines for JSON, especially duk_bi_json.c.
10266  */
10267 
10268 #if !defined(DUK_JSON_H_INCLUDED)
10269 #define DUK_JSON_H_INCLUDED
10270 
10271 /* Encoding/decoding flags */
10272 #define DUK_JSON_FLAG_ASCII_ONLY              (1U << 0)  /* escape any non-ASCII characters */
10273 #define DUK_JSON_FLAG_AVOID_KEY_QUOTES        (1U << 1)  /* avoid key quotes when key is an ASCII Identifier */
10274 #define DUK_JSON_FLAG_EXT_CUSTOM              (1U << 2)  /* extended types: custom encoding */
10275 #define DUK_JSON_FLAG_EXT_COMPATIBLE          (1U << 3)  /* extended types: compatible encoding */
10276 
10277 /* How much stack to require on entry to object/array encode */
10278 #define DUK_JSON_ENC_REQSTACK                 32
10279 
10280 /* How much stack to require on entry to object/array decode */
10281 #define DUK_JSON_DEC_REQSTACK                 32
10282 
10283 /* How large a loop detection stack to use */
10284 #define DUK_JSON_ENC_LOOPARRAY                64
10285 
10286 /* Encoding state.  Heap object references are all borrowed. */
10287 typedef struct {
10288 	duk_hthread *thr;
10289 	duk_bufwriter_ctx bw;        /* output bufwriter */
10290 	duk_hobject *h_replacer;     /* replacer function */
10291 	duk_hstring *h_gap;          /* gap (if empty string, NULL) */
10292 	duk_idx_t idx_proplist;      /* explicit PropertyList */
10293 	duk_idx_t idx_loop;          /* valstack index of loop detection object */
10294 	duk_small_uint_t flags;
10295 	duk_small_uint_t flag_ascii_only;
10296 	duk_small_uint_t flag_avoid_key_quotes;
10297 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
10298 	duk_small_uint_t flag_ext_custom;
10299 	duk_small_uint_t flag_ext_compatible;
10300 	duk_small_uint_t flag_ext_custom_or_compatible;
10301 #endif
10302 	duk_uint_t recursion_depth;
10303 	duk_uint_t recursion_limit;
10304 	duk_uint_t mask_for_undefined;      /* type bit mask: types which certainly produce 'undefined' */
10305 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
10306 	duk_small_uint_t stridx_custom_undefined;
10307 	duk_small_uint_t stridx_custom_nan;
10308 	duk_small_uint_t stridx_custom_neginf;
10309 	duk_small_uint_t stridx_custom_posinf;
10310 	duk_small_uint_t stridx_custom_function;
10311 #endif
10312 	duk_hobject *visiting[DUK_JSON_ENC_LOOPARRAY];  /* indexed by recursion_depth */
10313 } duk_json_enc_ctx;
10314 
10315 typedef struct {
10316 	duk_hthread *thr;
10317 	const duk_uint8_t *p;
10318 	const duk_uint8_t *p_start;
10319 	const duk_uint8_t *p_end;
10320 	duk_idx_t idx_reviver;
10321 	duk_small_uint_t flags;
10322 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
10323 	duk_small_uint_t flag_ext_custom;
10324 	duk_small_uint_t flag_ext_compatible;
10325 	duk_small_uint_t flag_ext_custom_or_compatible;
10326 #endif
10327 	duk_int_t recursion_depth;
10328 	duk_int_t recursion_limit;
10329 } duk_json_dec_ctx;
10330 
10331 #endif  /* DUK_JSON_H_INCLUDED */
10332 /* #include duk_js.h */
10333 #line 1 "duk_js.h"
10334 /*
10335  *  ECMAScript execution, support primitives.
10336  */
10337 
10338 #if !defined(DUK_JS_H_INCLUDED)
10339 #define DUK_JS_H_INCLUDED
10340 
10341 /* Flags for call handling.  Lowest flags must match bytecode DUK_BC_CALL_FLAG_xxx 1:1. */
10342 #define DUK_CALL_FLAG_TAILCALL                 (1U << 0)  /* setup for a tail call */
10343 #define DUK_CALL_FLAG_CONSTRUCT                (1U << 1)  /* constructor call (i.e. called as 'new Foo()') */
10344 #define DUK_CALL_FLAG_CALLED_AS_EVAL           (1U << 2)  /* call was made using the identifier 'eval' */
10345 #define DUK_CALL_FLAG_ALLOW_ECMATOECMA         (1U << 3)  /* ecma-to-ecma call with executor reuse is possible */
10346 #define DUK_CALL_FLAG_DIRECT_EVAL              (1U << 4)  /* call is a direct eval call */
10347 #define DUK_CALL_FLAG_CONSTRUCT_PROXY          (1U << 5)  /* handled via 'construct' proxy trap, check return value invariant(s) */
10348 #define DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED (1U << 6)  /* prototype of 'default instance' updated, temporary flag in call handling */
10349 
10350 /* Flags for duk_js_equals_helper(). */
10351 #define DUK_EQUALS_FLAG_SAMEVALUE            (1U << 0)  /* use SameValue instead of non-strict equality */
10352 #define DUK_EQUALS_FLAG_STRICT               (1U << 1)  /* use strict equality instead of non-strict equality */
10353 
10354 /* Flags for duk_js_compare_helper(). */
10355 #define DUK_COMPARE_FLAG_NEGATE              (1U << 0)  /* negate result */
10356 #define DUK_COMPARE_FLAG_EVAL_LEFT_FIRST     (1U << 1)  /* eval left argument first */
10357 
10358 /* conversions, coercions, comparison, etc */
10359 DUK_INTERNAL_DECL duk_bool_t duk_js_toboolean(duk_tval *tv);
10360 DUK_INTERNAL_DECL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv);
10361 DUK_INTERNAL_DECL duk_double_t duk_js_tointeger_number(duk_double_t x);
10362 DUK_INTERNAL_DECL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv);
10363 DUK_INTERNAL_DECL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv);
10364 DUK_INTERNAL_DECL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv);
10365 DUK_INTERNAL_DECL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv);
10366 DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_string(const duk_uint8_t *str, duk_uint32_t blen);
10367 #if !defined(DUK_USE_HSTRING_ARRIDX)
10368 DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_hstring_fast_known(duk_hstring *h);
10369 DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h);
10370 #endif
10371 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);
10372 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);
10373 DUK_INTERNAL_DECL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2);
10374 #if 0  /* unused */
10375 DUK_INTERNAL_DECL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2);
10376 #endif
10377 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);
10378 DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
10379 #if defined(DUK_USE_SYMBOL_BUILTIN)
10380 DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof_ordinary(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
10381 #endif
10382 DUK_INTERNAL_DECL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
10383 DUK_INTERNAL_DECL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x);
10384 
10385 /* arithmetic */
10386 DUK_INTERNAL_DECL double duk_js_arith_pow(double x, double y);
10387 DUK_INTERNAL_DECL double duk_js_arith_mod(double x, double y);
10388 
10389 #define duk_js_equals(thr,tv_x,tv_y) \
10390 	duk_js_equals_helper((thr), (tv_x), (tv_y), 0)
10391 #define duk_js_strict_equals(tv_x,tv_y) \
10392 	duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_STRICT)
10393 #define duk_js_samevalue(tv_x,tv_y) \
10394 	duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_SAMEVALUE)
10395 
10396 /* E5 Sections 11.8.1, 11.8.5; x < y */
10397 #define duk_js_lessthan(thr,tv_x,tv_y) \
10398 	duk_js_compare_helper((thr), (tv_x), (tv_Y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
10399 
10400 /* E5 Sections 11.8.2, 11.8.5; x > y  -->  y < x */
10401 #define duk_js_greaterthan(thr,tv_x,tv_y) \
10402 	duk_js_compare_helper((thr), (tv_y), (tv_x), 0)
10403 
10404 /* E5 Sections 11.8.3, 11.8.5; x <= y  -->  not (x > y)  -->  not (y < x) */
10405 #define duk_js_lessthanorequal(thr,tv_x,tv_y) \
10406 	duk_js_compare_helper((thr), (tv_y), (tv_x), DUK_COMPARE_FLAG_NEGATE)
10407 
10408 /* E5 Sections 11.8.4, 11.8.5; x >= y  -->  not (x < y) */
10409 #define duk_js_greaterthanorequal(thr,tv_x,tv_y) \
10410 	duk_js_compare_helper((thr), (tv_x), (tv_y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
10411 
10412 /* identifiers and environment handling */
10413 #if 0  /*unused*/
10414 DUK_INTERNAL duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
10415 #endif
10416 DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_bool_t throw_flag);
10417 DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_bool_t throw_flag);
10418 DUK_INTERNAL_DECL void duk_js_putvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_tval *val, duk_bool_t strict);
10419 DUK_INTERNAL_DECL void duk_js_putvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_bool_t strict);
10420 #if 0  /*unused*/
10421 DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
10422 #endif
10423 DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name);
10424 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);
10425 DUK_INTERNAL_DECL void duk_js_init_activation_environment_records_delayed(duk_hthread *thr, duk_activation *act);
10426 DUK_INTERNAL_DECL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env);
10427 DUK_INTERNAL_DECL duk_hobject *duk_create_activation_environment_record(duk_hthread *thr, duk_hobject *func, duk_size_t bottom_byteoff);
10428 DUK_INTERNAL_DECL void duk_js_push_closure(duk_hthread *thr,
10429                                            duk_hcompfunc *fun_temp,
10430                                            duk_hobject *outer_var_env,
10431                                            duk_hobject *outer_lex_env,
10432                                            duk_bool_t add_auto_proto);
10433 
10434 /* call handling */
10435 DUK_INTERNAL_DECL duk_int_t duk_handle_call_unprotected(duk_hthread *thr, duk_idx_t idx_func, duk_small_uint_t call_flags);
10436 DUK_INTERNAL_DECL duk_int_t duk_handle_call_unprotected_nargs(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags);
10437 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);
10438 DUK_INTERNAL_DECL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uint_t proxy_invariant);
10439 #if defined(DUK_USE_VERBOSE_ERRORS)
10440 DUK_INTERNAL_DECL void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_targ, duk_tval *tv_base, duk_tval *tv_key);
10441 #endif
10442 
10443 /* bytecode execution */
10444 DUK_INTERNAL_DECL void duk_js_execute_bytecode(duk_hthread *exec_thr);
10445 
10446 #endif  /* DUK_JS_H_INCLUDED */
10447 /* #include duk_numconv.h */
10448 #line 1 "duk_numconv.h"
10449 /*
10450  *  Number-to-string conversion.  The semantics of these is very tightly
10451  *  bound with the ECMAScript semantics required for call sites.
10452  */
10453 
10454 #if !defined(DUK_NUMCONV_H_INCLUDED)
10455 #define DUK_NUMCONV_H_INCLUDED
10456 
10457 /* Output a specified number of digits instead of using the shortest
10458  * form.  Used for toPrecision() and toFixed().
10459  */
10460 #define DUK_N2S_FLAG_FIXED_FORMAT         (1U << 0)
10461 
10462 /* Force exponential format.  Used for toExponential(). */
10463 #define DUK_N2S_FLAG_FORCE_EXP            (1U << 1)
10464 
10465 /* If number would need zero padding (for whole number part), use
10466  * exponential format instead.  E.g. if input number is 12300, 3
10467  * digits are generated ("123"), output "1.23e+4" instead of "12300".
10468  * Used for toPrecision().
10469  */
10470 #define DUK_N2S_FLAG_NO_ZERO_PAD          (1U << 2)
10471 
10472 /* Digit count indicates number of fractions (i.e. an absolute
10473  * digit index instead of a relative one).  Used together with
10474  * DUK_N2S_FLAG_FIXED_FORMAT for toFixed().
10475  */
10476 #define DUK_N2S_FLAG_FRACTION_DIGITS      (1U << 3)
10477 
10478 /*
10479  *  String-to-number conversion
10480  */
10481 
10482 /* Maximum exponent value when parsing numbers.  This is not strictly
10483  * compliant as there should be no upper limit, but as we parse the
10484  * exponent without a bigint, impose some limit.  The limit should be
10485  * small enough that multiplying it (or limit-1 to be precise) won't
10486  * overflow signed 32-bit integer range.  Exponent is only parsed with
10487  * radix 10, but with maximum radix (36) a safe limit is:
10488  * (10000000*36).toString(16) -> '15752a00'
10489  */
10490 #define DUK_S2N_MAX_EXPONENT              10000000L
10491 
10492 /* Trim white space (= allow leading and trailing whitespace) */
10493 #define DUK_S2N_FLAG_TRIM_WHITE           (1U << 0)
10494 
10495 /* Allow exponent */
10496 #define DUK_S2N_FLAG_ALLOW_EXP            (1U << 1)
10497 
10498 /* Allow trailing garbage (e.g. treat "123foo" as "123) */
10499 #define DUK_S2N_FLAG_ALLOW_GARBAGE        (1U << 2)
10500 
10501 /* Allow leading plus sign */
10502 #define DUK_S2N_FLAG_ALLOW_PLUS           (1U << 3)
10503 
10504 /* Allow leading minus sign */
10505 #define DUK_S2N_FLAG_ALLOW_MINUS          (1U << 4)
10506 
10507 /* Allow 'Infinity' */
10508 #define DUK_S2N_FLAG_ALLOW_INF            (1U << 5)
10509 
10510 /* Allow fraction part */
10511 #define DUK_S2N_FLAG_ALLOW_FRAC           (1U << 6)
10512 
10513 /* Allow naked fraction (e.g. ".123") */
10514 #define DUK_S2N_FLAG_ALLOW_NAKED_FRAC     (1U << 7)
10515 
10516 /* Allow empty fraction (e.g. "123.") */
10517 #define DUK_S2N_FLAG_ALLOW_EMPTY_FRAC     (1U << 8)
10518 
10519 /* Allow empty string to be interpreted as 0 */
10520 #define DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO  (1U << 9)
10521 
10522 /* Allow leading zeroes (e.g. "0123" -> "123") */
10523 #define DUK_S2N_FLAG_ALLOW_LEADING_ZERO   (1U << 10)
10524 
10525 /* Allow automatic detection of hex base ("0x" or "0X" prefix),
10526  * overrides radix argument and forces integer mode.
10527  */
10528 #define DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT   (1U << 11)
10529 
10530 /* Allow automatic detection of legacy octal base ("0n"),
10531  * overrides radix argument and forces integer mode.
10532  */
10533 #define DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT   (1U << 12)
10534 
10535 /* Allow automatic detection of ES2015 octal base ("0o123"),
10536  * overrides radix argument and forces integer mode.
10537  */
10538 #define DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT   (1U << 13)
10539 
10540 /* Allow automatic detection of ES2015 binary base ("0b10001"),
10541  * overrides radix argument and forces integer mode.
10542  */
10543 #define DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT   (1U << 14)
10544 
10545 /*
10546  *  Prototypes
10547  */
10548 
10549 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);
10550 DUK_INTERNAL_DECL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags);
10551 
10552 #endif  /* DUK_NUMCONV_H_INCLUDED */
10553 /* #include duk_bi_protos.h */
10554 #line 1 "duk_bi_protos.h"
10555 /*
10556  *  Prototypes for built-in functions not automatically covered by the
10557  *  header declarations emitted by genbuiltins.py.
10558  */
10559 
10560 #if !defined(DUK_BUILTIN_PROTOS_H_INCLUDED)
10561 #define DUK_BUILTIN_PROTOS_H_INCLUDED
10562 
10563 /* Buffer size needed for ISO 8601 formatting.
10564  * Accurate value is 32 + 1 for NUL termination:
10565  *   >>> len('+123456-01-23T12:34:56.123+12:34')
10566  *   32
10567  * Include additional space to be safe.
10568  */
10569 #define  DUK_BI_DATE_ISO8601_BUFSIZE  40
10570 
10571 /* Helpers exposed for internal use */
10572 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);
10573 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags);
10574 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year);
10575 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x);
10576 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t year);
10577 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x);
10578 /* Built-in providers */
10579 #if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
10580 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_gettimeofday(void);
10581 #endif
10582 #if defined(DUK_USE_DATE_NOW_TIME)
10583 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_time(void);
10584 #endif
10585 #if defined(DUK_USE_DATE_NOW_WINDOWS)
10586 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows(void);
10587 #endif
10588 #if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
10589 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows_subms(void);
10590 #endif
10591 #if defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S) || defined(DUK_USE_DATE_TZO_GMTIME)
10592 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d);
10593 #endif
10594 #if defined(DUK_USE_DATE_TZO_WINDOWS)
10595 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d);
10596 #endif
10597 #if defined(DUK_USE_DATE_TZO_WINDOWS_NO_DST)
10598 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d);
10599 #endif
10600 #if defined(DUK_USE_DATE_PRS_STRPTIME)
10601 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr, const char *str);
10602 #endif
10603 #if defined(DUK_USE_DATE_PRS_GETDATE)
10604 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const char *str);
10605 #endif
10606 #if defined(DUK_USE_DATE_FMT_STRFTIME)
10607 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);
10608 #endif
10609 
10610 #if defined(DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME)
10611 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_monotonic_time_clock_gettime(void);
10612 #endif
10613 #if defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC)
10614 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_monotonic_time_windows_qpc(void);
10615 #endif
10616 
10617 DUK_INTERNAL_DECL
10618 void duk_bi_json_parse_helper(duk_hthread *thr,
10619                               duk_idx_t idx_value,
10620                               duk_idx_t idx_reviver,
10621                               duk_small_uint_t flags);
10622 DUK_INTERNAL_DECL
10623 void duk_bi_json_stringify_helper(duk_hthread *thr,
10624                                   duk_idx_t idx_value,
10625                                   duk_idx_t idx_replacer,
10626                                   duk_idx_t idx_space,
10627                                   duk_small_uint_t flags);
10628 
10629 DUK_INTERNAL_DECL duk_ret_t duk_textdecoder_decode_utf8_nodejs(duk_hthread *thr);
10630 
10631 #if defined(DUK_USE_ES6_PROXY)
10632 DUK_INTERNAL_DECL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h_proxy_target, duk_uint_t flags);
10633 #endif
10634 
10635 #endif  /* DUK_BUILTIN_PROTOS_H_INCLUDED */
10636 /* #include duk_selftest.h */
10637 #line 1 "duk_selftest.h"
10638 /*
10639  *  Selftest code
10640  */
10641 
10642 #if !defined(DUK_SELFTEST_H_INCLUDED)
10643 #define DUK_SELFTEST_H_INCLUDED
10644 
10645 #if defined(DUK_USE_SELF_TESTS)
10646 DUK_INTERNAL_DECL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_func,
10647                                                     duk_realloc_function realloc_func,
10648                                                     duk_free_function free_func,
10649                                                     void *udata);
10650 #endif
10651 
10652 #endif  /* DUK_SELFTEST_H_INCLUDED */
10653 #line 82 "duk_internal.h"
10654 
10655 #endif  /* DUK_INTERNAL_H_INCLUDED */
10656 #line 10 "duk_replacements.c"
10657 
10658 #if defined(DUK_USE_COMPUTED_NAN)
10659 DUK_INTERNAL double duk_computed_nan;
10660 #endif
10661 
10662 #if defined(DUK_USE_COMPUTED_INFINITY)
10663 DUK_INTERNAL double duk_computed_infinity;
10664 #endif
10665 
10666 #if defined(DUK_USE_REPL_FPCLASSIFY)
duk_repl_fpclassify(double x)10667 DUK_INTERNAL int duk_repl_fpclassify(double x) {
10668 	duk_double_union u;
10669 	duk_uint_fast16_t expt;
10670 	duk_small_int_t mzero;
10671 
10672 	u.d = x;
10673 	expt = (duk_uint_fast16_t) (u.us[DUK_DBL_IDX_US0] & 0x7ff0UL);
10674 	if (expt > 0x0000UL && expt < 0x7ff0UL) {
10675 		/* expt values [0x001,0x7fe] = normal */
10676 		return DUK_FP_NORMAL;
10677 	}
10678 
10679 	mzero = (u.ui[DUK_DBL_IDX_UI1] == 0 && (u.ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) == 0);
10680 	if (expt == 0x0000UL) {
10681 		/* expt 0x000 is zero/subnormal */
10682 		if (mzero) {
10683 			return DUK_FP_ZERO;
10684 		} else {
10685 			return DUK_FP_SUBNORMAL;
10686 		}
10687 	} else {
10688 		/* expt 0xfff is infinite/nan */
10689 		if (mzero) {
10690 			return DUK_FP_INFINITE;
10691 		} else {
10692 			return DUK_FP_NAN;
10693 		}
10694 	}
10695 }
10696 #endif
10697 
10698 #if defined(DUK_USE_REPL_SIGNBIT)
duk_repl_signbit(double x)10699 DUK_INTERNAL int duk_repl_signbit(double x) {
10700 	duk_double_union u;
10701 	u.d = x;
10702 	return (int) (u.uc[DUK_DBL_IDX_UC0] & 0x80UL);
10703 }
10704 #endif
10705 
10706 #if defined(DUK_USE_REPL_ISFINITE)
duk_repl_isfinite(double x)10707 DUK_INTERNAL int duk_repl_isfinite(double x) {
10708 	int c = DUK_FPCLASSIFY(x);
10709 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
10710 		return 0;
10711 	} else {
10712 		return 1;
10713 	}
10714 }
10715 #endif
10716 
10717 #if defined(DUK_USE_REPL_ISNAN)
duk_repl_isnan(double x)10718 DUK_INTERNAL int duk_repl_isnan(double x) {
10719 	int c = DUK_FPCLASSIFY(x);
10720 	return (c == DUK_FP_NAN);
10721 }
10722 #endif
10723 
10724 #if defined(DUK_USE_REPL_ISINF)
duk_repl_isinf(double x)10725 DUK_INTERNAL int duk_repl_isinf(double x) {
10726 	int c = DUK_FPCLASSIFY(x);
10727 	return (c == DUK_FP_INFINITE);
10728 }
10729 #endif
10730 #line 1 "duk_debug_macros.c"
10731 /*
10732  *  Debugging macro calls.
10733  */
10734 
10735 /* #include duk_internal.h -> already included */
10736 
10737 #if defined(DUK_USE_DEBUG)
10738 
10739 /*
10740  *  Debugging enabled
10741  */
10742 
10743 #include <stdio.h>
10744 #include <stdlib.h>
10745 #include <stdarg.h>
10746 
10747 #if !defined(DUK_USE_DEBUG_WRITE)
10748 #error debugging enabled (DUK_USE_DEBUG) but DUK_USE_DEBUG_WRITE not defined
10749 #endif
10750 
10751 #define DUK__DEBUG_BUFSIZE  DUK_USE_DEBUG_BUFSIZE
10752 
10753 #if defined(DUK_USE_VARIADIC_MACROS)
10754 
duk_debug_log(duk_int_t level,const char * file,duk_int_t line,const char * func,const char * fmt,...)10755 DUK_INTERNAL void duk_debug_log(duk_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...) {
10756 	va_list ap;
10757 	long arg_level;
10758 	const char *arg_file;
10759 	long arg_line;
10760 	const char *arg_func;
10761 	const char *arg_msg;
10762 	char buf[DUK__DEBUG_BUFSIZE];
10763 
10764 	va_start(ap, fmt);
10765 
10766 	duk_memzero((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);
10767 	duk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
10768 
10769 	arg_level = (long) level;
10770 	arg_file = (const char *) file;
10771 	arg_line = (long) line;
10772 	arg_func = (const char *) func;
10773 	arg_msg = (const char *) buf;
10774 	DUK_USE_DEBUG_WRITE(arg_level, arg_file, arg_line, arg_func, arg_msg);
10775 
10776 	va_end(ap);
10777 }
10778 
10779 #else  /* DUK_USE_VARIADIC_MACROS */
10780 
10781 DUK_INTERNAL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
10782 DUK_INTERNAL duk_int_t duk_debug_line_stash;
10783 DUK_INTERNAL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
10784 DUK_INTERNAL duk_int_t duk_debug_level_stash;
10785 
duk_debug_log(const char * fmt,...)10786 DUK_INTERNAL void duk_debug_log(const char *fmt, ...) {
10787 	va_list ap;
10788 	long arg_level;
10789 	const char *arg_file;
10790 	long arg_line;
10791 	const char *arg_func;
10792 	const char *arg_msg;
10793 	char buf[DUK__DEBUG_BUFSIZE];
10794 
10795 	va_start(ap, fmt);
10796 
10797 	duk_memzero((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);
10798 	duk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
10799 
10800 	arg_level = (long) duk_debug_level_stash;
10801 	arg_file = (const char *) duk_debug_file_stash;
10802 	arg_line = (long) duk_debug_line_stash;
10803 	arg_func = (const char *) duk_debug_func_stash;
10804 	arg_msg = (const char *) buf;
10805 	DUK_USE_DEBUG_WRITE(arg_level, arg_file, arg_line, arg_func, arg_msg);
10806 
10807 	va_end(ap);
10808 }
10809 
10810 #endif  /* DUK_USE_VARIADIC_MACROS */
10811 
10812 #else  /* DUK_USE_DEBUG */
10813 
10814 /*
10815  *  Debugging disabled
10816  */
10817 
10818 #endif  /* DUK_USE_DEBUG */
10819 
10820 /* automatic undefs */
10821 #undef DUK__DEBUG_BUFSIZE
10822 #line 1 "duk_builtins.c"
10823 /*
10824  *  Automatically generated by genbuiltins.py, do not edit!
10825  */
10826 
10827 /* #include duk_internal.h -> already included */
10828 
10829 #if defined(DUK_USE_ASSERTIONS)
10830 #define DUK__REFCINIT(refc) 0 /*h_assert_refcount*/, (refc) /*actual*/
10831 #else
10832 #define DUK__REFCINIT(refc) (refc) /*actual*/
10833 #endif
10834 
10835 #if defined(DUK_USE_ROM_STRINGS)
10836 #error ROM support not enabled, rerun configure.py with --rom-support
10837 #else  /* DUK_USE_ROM_STRINGS */
10838 DUK_INTERNAL const duk_uint8_t duk_strings_data[967] = {
10839 79,40,209,144,168,105,6,78,54,139,89,185,44,48,46,90,120,8,154,140,35,103,
10840 35,113,193,73,5,52,112,180,104,166,135,52,188,4,98,12,27,146,156,80,211,31,
10841 129,115,150,64,52,220,109,24,18,68,156,24,38,67,114,36,55,9,119,151,132,
10842 140,93,18,113,128,153,201,212,201,205,2,248,8,196,24,224,104,82,146,40,224,
10843 193,48,114,168,37,147,196,54,123,28,4,98,12,43,148,67,103,177,192,70,32,
10844 196,121,68,54,123,28,18,192,199,144,124,4,98,12,43,136,108,244,117,184,8,
10845 196,24,95,40,134,207,71,91,128,140,65,133,113,13,158,158,151,1,24,131,11,
10846 229,16,217,233,233,112,17,136,48,206,21,110,4,244,244,184,8,196,24,103,10,
10847 183,2,122,218,156,4,98,12,24,203,112,64,179,113,193,79,8,218,155,131,32,
10848 184,70,212,220,13,10,82,68,252,123,144,217,146,38,228,207,18,0,100,37,64,
10849 178,212,11,161,17,104,162,96,10,200,193,57,165,65,169,16,5,100,81,27,70,18,
10850 32,10,200,68,185,13,116,221,197,184,64,89,57,41,197,13,49,234,5,208,156,
10851 113,87,55,118,147,20,187,56,161,166,92,221,212,73,210,236,226,134,153,115,
10852 119,76,201,203,179,138,26,99,73,212,136,136,164,25,174,137,56,32,72,137,
10853 101,23,52,45,13,34,86,9,79,136,104,201,114,149,96,52,138,134,140,151,75,
10854 226,233,186,120,121,22,39,54,83,141,5,55,68,236,36,164,3,16,225,115,150,64,
10855 52,205,163,2,72,154,83,138,26,99,75,12,11,150,103,5,36,20,211,70,140,133,
10856 67,72,49,241,160,227,81,196,52,168,106,39,132,252,183,136,105,80,212,79,2,
10857 249,110,128,126,88,95,133,109,237,237,237,151,235,127,46,249,119,203,190,
10858 186,206,33,181,2,208,61,190,12,19,34,65,19,81,132,108,228,97,1,107,33,12,
10859 32,45,100,137,64,247,175,9,19,155,41,198,130,155,134,69,146,100,227,226,
10860 231,146,51,192,204,73,140,224,145,221,102,241,68,196,169,248,30,75,12,11,
10861 151,242,233,187,143,138,24,137,162,164,255,253,63,3,201,97,129,114,254,92,
10862 112,75,136,108,166,6,136,159,255,167,224,121,44,48,46,95,203,166,238,74,
10863 113,67,77,201,128,223,255,223,224,121,44,48,46,95,203,145,46,9,205,16,39,
10864 201,62,36,0,192,21,147,255,238,145,39,199,197,211,116,240,242,113,197,78,
10865 214,211,226,233,187,107,105,19,119,37,56,161,166,52,221,212,201,205,36,240,
10866 242,16,96,152,12,178,52,211,56,228,73,150,83,0,148,39,137,75,67,73,198,209,
10867 129,36,85,185,201,196,2,32,193,48,17,160,97,16,84,44,156,104,24,67,189,200,
10868 108,201,19,238,114,96,137,137,50,238,113,164,188,211,185,192,226,100,19,
10869 134,68,110,112,174,139,0,185,31,115,149,4,88,7,159,115,146,117,34,34,35,
10870 115,143,22,146,208,210,19,115,140,3,207,185,202,130,36,109,85,185,194,161,
10871 160,90,50,72,155,115,149,2,232,67,137,204,122,22,66,161,175,164,210,72,199,
10872 130,137,1,50,32,145,143,38,120,186,195,35,106,51,146,230,8,36,77,109,65,38,
10873 226,72,159,191,189,181,70,140,133,222,249,212,227,66,125,245,187,251,219,
10874 77,3,119,190,117,56,208,159,125,110,254,246,210,26,93,239,157,78,52,39,223,
10875 93,191,189,180,212,52,187,223,58,156,104,79,190,187,127,123,104,180,104,
10876 183,190,117,56,208,159,125,102,254,209,104,209,124,234,113,161,62,250,80,
10877 196,128,81,4,9,16,162,4,196,116,9,205,154,27,66,32,100,13,12,98,68,227,33,
10878 65,69,204,195,34,201,50,8,110,33,23,34,28,168,104,22,188,12,174,138,11,70,
10879 138,104,115,68,130,137,13,82,27,41,129,162,35,138,54,146,198,137,39,72,180,
10880 210,178,38,35,146,103,68,139,51,197,214,28,227,131,79,15,35,138,58,130,37,
10881 19,155,41,146,174,64,203,99,161,100,37,145,51,148,75,4,164,66,54,140,49,46,
10882 247,70,103,37,230,70,142,70,67,30,232,204,178,163,201,18,54,139,89,39,26,
10883 16,165,2,228,69,33,143,89,24,70,206,73,67,102,72,148,2,32,214,73,157,224,
10884 18,128,98,29,241,69,65,50,37,241,116,200,41,144,102,125,2,180,8,210,152,38,
10885 129,23,8,34,198,
10886 };
10887 #endif  /* DUK_USE_ROM_STRINGS */
10888 
10889 #if defined(DUK_USE_ROM_OBJECTS)
10890 #error ROM support not enabled, rerun configure.py with --rom-support
10891 #else  /* DUK_USE_ROM_OBJECTS */
10892 /* native functions: 177 */
10893 DUK_INTERNAL const duk_c_function duk_bi_native_functions[177] = {
10894 	NULL,
10895 	duk_bi_array_constructor,
10896 	duk_bi_array_constructor_is_array,
10897 	duk_bi_array_prototype_concat,
10898 	duk_bi_array_prototype_indexof_shared,
10899 	duk_bi_array_prototype_iter_shared,
10900 	duk_bi_array_prototype_join_shared,
10901 	duk_bi_array_prototype_pop,
10902 	duk_bi_array_prototype_push,
10903 	duk_bi_array_prototype_reduce_shared,
10904 	duk_bi_array_prototype_reverse,
10905 	duk_bi_array_prototype_shift,
10906 	duk_bi_array_prototype_slice,
10907 	duk_bi_array_prototype_sort,
10908 	duk_bi_array_prototype_splice,
10909 	duk_bi_array_prototype_to_string,
10910 	duk_bi_array_prototype_unshift,
10911 	duk_bi_arraybuffer_constructor,
10912 	duk_bi_arraybuffer_isview,
10913 	duk_bi_boolean_constructor,
10914 	duk_bi_boolean_prototype_tostring_shared,
10915 	duk_bi_buffer_compare_shared,
10916 	duk_bi_buffer_readfield,
10917 	duk_bi_buffer_slice_shared,
10918 	duk_bi_buffer_writefield,
10919 	duk_bi_dataview_constructor,
10920 	duk_bi_date_constructor,
10921 	duk_bi_date_constructor_now,
10922 	duk_bi_date_constructor_parse,
10923 	duk_bi_date_constructor_utc,
10924 	duk_bi_date_prototype_get_shared,
10925 	duk_bi_date_prototype_get_timezone_offset,
10926 	duk_bi_date_prototype_set_shared,
10927 	duk_bi_date_prototype_set_time,
10928 	duk_bi_date_prototype_to_json,
10929 	duk_bi_date_prototype_tostring_shared,
10930 	duk_bi_date_prototype_value_of,
10931 	duk_bi_duktape_object_act,
10932 	duk_bi_duktape_object_compact,
10933 	duk_bi_duktape_object_dec,
10934 	duk_bi_duktape_object_enc,
10935 	duk_bi_duktape_object_fin,
10936 	duk_bi_duktape_object_gc,
10937 	duk_bi_duktape_object_info,
10938 	duk_bi_error_constructor_shared,
10939 	duk_bi_error_prototype_filename_getter,
10940 	duk_bi_error_prototype_filename_setter,
10941 	duk_bi_error_prototype_linenumber_getter,
10942 	duk_bi_error_prototype_linenumber_setter,
10943 	duk_bi_error_prototype_stack_getter,
10944 	duk_bi_error_prototype_stack_setter,
10945 	duk_bi_error_prototype_to_string,
10946 	duk_bi_function_constructor,
10947 	duk_bi_function_prototype,
10948 	duk_bi_function_prototype_apply,
10949 	duk_bi_function_prototype_bind,
10950 	duk_bi_function_prototype_call,
10951 	duk_bi_function_prototype_to_string,
10952 	duk_bi_global_object_decode_uri,
10953 	duk_bi_global_object_decode_uri_component,
10954 	duk_bi_global_object_encode_uri,
10955 	duk_bi_global_object_encode_uri_component,
10956 	duk_bi_global_object_escape,
10957 	duk_bi_global_object_eval,
10958 	duk_bi_global_object_is_finite,
10959 	duk_bi_global_object_is_nan,
10960 	duk_bi_global_object_parse_float,
10961 	duk_bi_global_object_parse_int,
10962 	duk_bi_global_object_unescape,
10963 	duk_bi_json_object_parse,
10964 	duk_bi_json_object_stringify,
10965 	duk_bi_math_object_clz32,
10966 	duk_bi_math_object_hypot,
10967 	duk_bi_math_object_imul,
10968 	duk_bi_math_object_max,
10969 	duk_bi_math_object_min,
10970 	duk_bi_math_object_onearg_shared,
10971 	duk_bi_math_object_random,
10972 	duk_bi_math_object_sign,
10973 	duk_bi_math_object_twoarg_shared,
10974 	duk_bi_native_function_length,
10975 	duk_bi_native_function_name,
10976 	duk_bi_nodejs_buffer_byte_length,
10977 	duk_bi_nodejs_buffer_concat,
10978 	duk_bi_nodejs_buffer_constructor,
10979 	duk_bi_nodejs_buffer_copy,
10980 	duk_bi_nodejs_buffer_fill,
10981 	duk_bi_nodejs_buffer_is_buffer,
10982 	duk_bi_nodejs_buffer_is_encoding,
10983 	duk_bi_nodejs_buffer_tojson,
10984 	duk_bi_nodejs_buffer_tostring,
10985 	duk_bi_nodejs_buffer_write,
10986 	duk_bi_number_check_shared,
10987 	duk_bi_number_constructor,
10988 	duk_bi_number_prototype_to_exponential,
10989 	duk_bi_number_prototype_to_fixed,
10990 	duk_bi_number_prototype_to_locale_string,
10991 	duk_bi_number_prototype_to_precision,
10992 	duk_bi_number_prototype_to_string,
10993 	duk_bi_number_prototype_value_of,
10994 	duk_bi_object_constructor,
10995 	duk_bi_object_constructor_assign,
10996 	duk_bi_object_constructor_create,
10997 	duk_bi_object_constructor_define_properties,
10998 	duk_bi_object_constructor_define_property,
10999 	duk_bi_object_constructor_get_own_property_descriptor,
11000 	duk_bi_object_constructor_is,
11001 	duk_bi_object_constructor_is_extensible,
11002 	duk_bi_object_constructor_is_sealed_frozen_shared,
11003 	duk_bi_object_constructor_keys_shared,
11004 	duk_bi_object_constructor_prevent_extensions,
11005 	duk_bi_object_constructor_seal_freeze_shared,
11006 	duk_bi_object_getprototype_shared,
11007 	duk_bi_object_prototype_defineaccessor,
11008 	duk_bi_object_prototype_has_own_property,
11009 	duk_bi_object_prototype_is_prototype_of,
11010 	duk_bi_object_prototype_lookupaccessor,
11011 	duk_bi_object_prototype_property_is_enumerable,
11012 	duk_bi_object_prototype_to_locale_string,
11013 	duk_bi_object_prototype_to_string,
11014 	duk_bi_object_prototype_value_of,
11015 	duk_bi_object_setprototype_shared,
11016 	duk_bi_performance_now,
11017 	duk_bi_pointer_constructor,
11018 	duk_bi_pointer_prototype_tostring_shared,
11019 	duk_bi_proxy_constructor,
11020 	duk_bi_reflect_apply,
11021 	duk_bi_reflect_construct,
11022 	duk_bi_reflect_object_delete_property,
11023 	duk_bi_reflect_object_get,
11024 	duk_bi_reflect_object_has,
11025 	duk_bi_reflect_object_set,
11026 	duk_bi_regexp_constructor,
11027 	duk_bi_regexp_prototype_exec,
11028 	duk_bi_regexp_prototype_flags,
11029 	duk_bi_regexp_prototype_shared_getter,
11030 	duk_bi_regexp_prototype_test,
11031 	duk_bi_regexp_prototype_tostring,
11032 	duk_bi_string_constructor,
11033 	duk_bi_string_constructor_from_char_code,
11034 	duk_bi_string_constructor_from_code_point,
11035 	duk_bi_string_prototype_caseconv_shared,
11036 	duk_bi_string_prototype_char_at,
11037 	duk_bi_string_prototype_char_code_at,
11038 	duk_bi_string_prototype_concat,
11039 	duk_bi_string_prototype_includes,
11040 	duk_bi_string_prototype_indexof_shared,
11041 	duk_bi_string_prototype_locale_compare,
11042 	duk_bi_string_prototype_match,
11043 	duk_bi_string_prototype_repeat,
11044 	duk_bi_string_prototype_replace,
11045 	duk_bi_string_prototype_search,
11046 	duk_bi_string_prototype_slice,
11047 	duk_bi_string_prototype_split,
11048 	duk_bi_string_prototype_startswith_endswith,
11049 	duk_bi_string_prototype_substr,
11050 	duk_bi_string_prototype_substring,
11051 	duk_bi_string_prototype_to_string,
11052 	duk_bi_string_prototype_trim,
11053 	duk_bi_textdecoder_constructor,
11054 	duk_bi_textdecoder_prototype_decode,
11055 	duk_bi_textdecoder_prototype_shared_getter,
11056 	duk_bi_textencoder_constructor,
11057 	duk_bi_textencoder_prototype_encode,
11058 	duk_bi_textencoder_prototype_encoding_getter,
11059 	duk_bi_thread_constructor,
11060 	duk_bi_thread_current,
11061 	duk_bi_thread_resume,
11062 	duk_bi_thread_yield,
11063 	duk_bi_type_error_thrower,
11064 	duk_bi_typedarray_buffer_getter,
11065 	duk_bi_typedarray_bytelength_getter,
11066 	duk_bi_typedarray_byteoffset_getter,
11067 	duk_bi_typedarray_constructor,
11068 	duk_bi_typedarray_set,
11069 	duk_bi_uint8array_allocplain,
11070 	duk_bi_uint8array_plainof,
11071 };
11072 #if defined(DUK_USE_DOUBLE_LE)
11073 DUK_INTERNAL const duk_uint8_t duk_builtins_data[4116] = {
11074 144,148,105,224,32,68,52,228,62,12,104,200,165,132,52,167,194,138,105,243,
11075 124,57,28,211,57,18,64,52,238,126,44,138,111,171,241,164,19,87,129,30,33,
11076 167,16,145,159,8,211,136,9,225,42,5,240,145,139,163,163,8,211,136,10,228,
11077 64,211,19,132,140,93,29,56,70,156,64,119,34,66,146,36,104,137,194,70,46,
11078 142,172,35,78,32,47,146,195,102,11,240,145,139,163,175,8,211,136,9,228,240,
11079 242,112,145,139,163,179,8,211,136,8,237,34,130,118,49,116,118,225,26,48,0,
11080 1,82,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
11081 33,8,66,26,179,233,97,167,60,150,34,33,154,112,0,1,75,247,35,79,95,237,198,
11082 174,200,47,31,23,95,17,13,51,19,35,93,68,216,209,128,0,10,208,174,79,15,32,
11083 248,8,196,24,8,107,192,0,5,106,118,27,94,0,0,43,83,227,94,0,0,43,84,46,215,
11084 128,0,10,213,28,198,188,0,0,86,169,100,53,224,0,2,181,79,85,175,0,0,21,170,
11085 154,45,120,0,0,173,85,217,107,192,0,5,106,182,243,86,193,106,52,127,130,
11086 249,50,94,124,35,68,225,146,49,13,31,186,23,201,146,243,224,200,39,12,145,
11087 136,67,134,19,49,0,0,0,0,0,0,3,225,255,51,0,0,0,0,0,0,3,193,255,47,18,1,
11088 172,19,120,71,10,25,196,136,113,162,156,136,199,42,57,204,144,115,132,240,
11089 149,2,248,72,197,209,58,2,185,16,52,196,225,35,23,68,233,14,228,72,82,68,
11090 141,17,56,72,197,209,58,130,249,44,54,96,191,9,24,186,39,88,79,39,135,147,
11091 132,140,93,19,176,35,180,138,9,216,197,209,59,82,79,35,40,242,65,248,58,42,
11092 96,121,14,232,94,62,46,190,15,42,31,145,33,86,65,76,242,214,143,73,48,242,
11093 243,79,49,56,243,115,207,57,64,243,180,79,61,72,243,244,207,65,80,244,53,
11094 79,69,88,244,98,30,8,200,156,67,102,120,241,79,4,100,78,21,110,4,207,32,47,
11095 147,37,231,194,52,78,25,34,122,81,124,153,47,62,12,130,112,201,19,211,139,
11096 121,34,87,69,128,104,137,239,83,18,238,108,165,2,162,92,104,56,220,233,1,8,
11097 151,10,134,162,100,206,16,18,50,9,195,39,105,20,101,136,18,25,4,225,147,
11098 180,138,5,215,49,238,105,27,60,185,1,36,104,156,50,118,145,70,96,129,34,52,
11099 78,25,59,72,160,93,115,30,230,145,179,204,144,12,73,8,15,38,104,128,138,52,
11100 146,16,30,77,1,0,2,11,132,193,198,36,248,248,186,110,158,30,78,56,188,194,
11101 70,183,170,136,48,98,79,142,179,120,248,185,228,140,241,193,146,66,138,31,
11102 55,71,138,128,153,137,62,58,205,227,226,231,146,51,199,26,6,18,92,146,64,
11103 96,74,72,51,120,43,192,97,68,128,153,56,72,7,12,133,67,73,199,197,207,36,
11104 103,142,35,2,3,33,80,210,113,241,115,201,25,160,146,225,160,9,34,1,124,178,
11105 1,139,18,19,36,229,146,8,190,36,169,27,62,18,243,35,100,135,54,92,162,2,17,
11106 46,72,128,89,7,200,32,33,18,225,98,236,145,188,130,64,196,75,132,188,200,
11107 217,32,43,39,28,128,69,19,18,228,144,42,98,79,142,179,120,248,185,228,140,
11108 241,201,97,129,114,229,201,37,2,68,184,200,1,147,93,159,153,213,34,235,250,
11109 96,48,157,32,24,94,160,1,199,4,184,235,55,143,139,158,72,207,28,226,3,81,
11110 46,62,46,155,167,135,147,142,47,60,129,71,197,207,36,103,142,34,92,35,104,
11111 194,68,1,89,58,36,8,109,109,12,133,67,73,195,18,115,36,118,182,185,168,8,
11112 109,109,12,133,67,73,201,18,115,36,118,182,185,168,130,27,91,75,115,149,71,
11113 240,196,156,201,29,173,174,129,2,27,91,75,115,149,71,242,68,156,201,29,173,
11114 174,129,34,12,16,28,128,62,191,42,3,71,146,68,4,16,22,188,161,240,16,40,
11115 104,242,103,196,16,93,158,125,96,110,115,235,64,131,16,16,58,37,192,70,32,
11116 194,144,114,25,67,95,40,6,18,8,32,48,156,209,2,108,124,96,224,144,6,247,62,
11117 16,0,143,164,143,12,248,15,18,84,145,145,34,128,11,35,160,179,140,0,44,150,
11118 129,18,58,0,146,116,103,32,128,105,61,104,17,36,175,1,232,217,29,5,156,179,
11119 224,58,26,50,95,142,43,159,64,181,130,83,226,26,50,95,142,43,159,192,7,255,
11120 248,41,42,72,226,1,160,18,78,97,32,26,64,114,186,60,32,4,120,6,148,13,128,
11121 124,3,76,12,84,46,100,140,3,78,13,18,14,130,36,67,232,23,18,14,130,39,34,
11122 131,30,113,15,224,3,255,253,6,48,40,194,197,204,224,142,8,240,78,25,60,231,
11123 192,210,197,204,224,156,50,113,238,67,103,232,62,28,138,156,104,82,170,107,
11124 255,32,48,191,144,1,132,112,71,128,159,168,128,161,28,17,224,156,50,112,19,
11125 245,144,22,39,12,156,123,144,217,240,19,245,146,3,9,205,16,39,236,62,3,161,
11126 163,37,248,226,251,141,1,107,4,167,196,52,100,191,28,95,113,164,13,91,132,
11127 5,147,130,115,30,8,147,222,64,43,1,49,31,224,64,60,72,245,128,68,249,32,13,
11128 34,2,34,63,204,128,89,45,2,39,209,0,89,61,104,159,213,0,153,80,50,156,80,
11129 211,126,16,11,155,184,183,88,145,224,129,34,122,64,17,155,184,183,8,11,39,
11130 22,235,18,60,16,36,79,72,1,115,119,40,247,146,60,16,36,79,72,32,140,221,
11131 197,184,64,89,57,71,188,145,224,129,34,122,65,1,39,20,51,244,0,52,72,242,2,
11132 127,18,2,165,48,70,114,229,145,51,253,141,1,4,104,229,203,34,103,251,26,64,
11133 132,52,75,160,201,47,105,160,26,84,12,167,31,186,8,50,0,114,58,113,163,46,
11134 190,120,35,11,60,4,25,68,81,61,96,47,181,80,46,132,129,255,255,255,255,255,
11135 255,222,254,39,172,67,118,170,5,208,144,0,64,0,0,0,0,0,0,51,16,0,0,0,0,0,0,
11136 62,31,200,245,238,146,38,138,147,105,13,42,26,137,226,0,0,0,0,0,0,7,131,
11137 249,30,180,134,4,209,82,109,33,165,67,81,60,64,0,0,0,0,0,0,240,255,15,210,
11138 62,72,91,155,0,0,0,0,0,0,2,192,240,135,88,11,237,72,5,38,210,27,50,24,145,
11139 129,255,255,255,255,255,254,126,134,67,172,67,118,164,2,147,105,13,153,12,
11140 72,192,255,255,255,255,255,255,63,195,16,240,70,68,226,27,51,199,138,120,
11141 35,34,112,171,112,38,121,7,16,137,112,168,106,38,77,193,1,40,151,16,217,
11142 144,196,142,224,144,21,18,227,65,198,238,9,67,81,46,72,5,39,16,217,144,196,
11143 142,224,152,228,148,227,64,0,0,0,0,0,0,0,0,131,175,223,16,194,111,8,97,119,
11144 224,3,205,220,42,46,65,238,200,13,155,184,75,189,205,35,102,128,47,116,64,
11145 92,221,199,196,130,68,144,230,239,72,65,152,12,21,224,140,137,92,128,62,
11146 210,98,177,252,3,107,173,88,3,146,211,141,32,0,0,0,0,0,3,225,255,19,175,
11147 188,0,100,221,193,130,100,228,167,20,52,215,129,3,38,238,77,12,39,37,56,
11148 161,166,188,10,194,94,6,18,155,184,183,8,11,39,6,9,147,146,156,80,211,94,7,
11149 18,155,184,183,8,11,39,38,134,19,146,156,80,211,94,8,12,53,224,130,195,222,
11150 8,77,133,210,24,91,224,3,152,147,228,208,194,95,0,44,196,159,11,69,175,152,
11151 32,35,100,33,135,24,147,237,38,34,246,139,95,48,64,70,200,68,8,49,39,198,
11152 57,179,61,144,138,22,98,79,180,152,153,215,54,103,178,17,129,204,73,240,96,
11153 153,44,132,112,163,18,125,164,196,62,130,100,178,18,1,140,73,240,96,197,
11154 144,146,18,98,79,180,152,135,208,98,200,74,8,49,39,195,186,145,149,144,150,
11155 22,98,79,180,152,143,215,82,50,178,19,2,140,73,241,136,109,38,73,89,9,161,
11156 166,36,251,73,137,157,67,105,50,74,200,78,10,49,39,201,16,78,104,229,100,
11157 39,134,152,147,237,38,41,116,130,115,71,43,33,64,60,196,159,24,133,173,18,
11158 32,156,209,202,200,81,18,49,39,218,76,76,234,22,180,72,130,115,71,43,33,72,
11159 68,196,159,38,134,19,46,105,56,226,150,68,157,160,1,228,73,242,104,97,46,
11160 16,31,34,79,140,66,214,137,16,78,104,229,108,169,137,72,147,237,38,38,117,
11161 11,90,36,65,57,163,149,178,168,21,34,79,146,32,156,209,202,218,250,161,178,
11162 36,251,73,138,93,32,156,209,202,218,250,193,82,36,248,196,54,147,36,173,
11163 191,174,27,34,79,180,152,153,212,54,147,36,173,191,176,17,34,79,135,117,35,
11164 43,115,236,133,200,147,237,38,35,245,212,140,173,207,180,15,34,79,131,4,
11165 201,108,173,133,72,147,237,38,33,244,19,37,178,184,17,34,79,140,115,102,
11166 123,107,238,133,200,147,237,38,38,117,205,153,237,175,188,23,34,79,133,162,
11167 215,204,16,17,182,254,248,116,137,62,210,98,47,104,181,243,4,4,109,191,192,
11168 131,152,147,230,8,8,217,12,16,60,137,62,96,128,141,178,193,160,206,1,201,
11169 176,113,146,0,0,0,0,0,0,0,0,49,185,252,65,137,207,227,37,215,207,227,12,86,
11170 127,24,152,188,254,49,88,33,46,65,120,72,4,153,37,63,33,13,127,148,4,26,0,
11171 57,62,6,228,163,228,74,86,215,62,55,28,110,179,226,113,70,223,62,47,24,38,
11172 191,30,2,125,32,40,20,87,114,41,225,42,5,240,145,139,163,145,41,68,250,128,
11173 80,41,174,228,85,200,129,166,39,9,24,186,57,18,148,79,172,5,2,170,238,69,
11174 220,137,10,72,145,162,39,9,24,186,57,18,148,79,176,5,2,186,238,69,124,150,
11175 27,48,95,132,140,93,28,137,74,39,218,2,129,101,119,34,158,79,15,39,9,24,
11176 186,57,18,148,79,184,5,2,218,238,69,29,164,80,78,198,46,142,68,165,16,64,
11177 28,24,61,73,25,33,205,128,0,0,0,0,1,167,166,129,108,242,151,15,39,8,34,26,
11178 87,97,200,3,0,167,129,32,8,194,195,16,6,84,55,10,60,3,35,69,132,30,1,140,
11179 130,193,143,1,196,230,60,2,158,8,131,153,64,115,42,46,191,176,8,194,246,0,
11180 80,5,220,193,95,6,234,5,100,225,35,23,71,35,6,228,140,93,29,180,55,108,145,
11181 139,163,182,112,52,107,67,76,56,3,153,132,20,28,76,156,89,26,105,158,62,0,
11182 0,42,193,2,201,104,17,41,34,156,204,176,160,226,100,226,200,211,76,241,240,
11183 0,1,86,2,131,137,147,142,41,100,73,199,192,0,5,96,6,13,10,82,70,62,0,0,42,
11184 130,88,115,18,124,67,103,177,69,49,129,6,36,249,68,54,123,20,82,216,65,137,
11185 62,33,179,209,214,162,152,208,147,18,124,162,27,61,29,106,41,112,32,196,
11186 159,16,217,233,233,81,76,112,73,137,62,81,13,158,158,149,20,186,20,98,79,
11187 133,91,129,61,61,42,41,120,40,196,159,10,183,2,122,218,148,82,248,60,137,
11188 62,33,179,216,166,216,192,137,18,124,162,27,61,138,109,108,34,68,159,16,
11189 217,232,235,83,108,104,76,137,62,81,13,158,142,181,54,184,17,34,79,136,108,
11190 244,244,169,182,56,38,68,159,40,134,207,79,74,155,93,10,145,39,194,173,192,
11191 158,158,149,54,188,21,34,79,133,91,129,61,109,74,109,125,155,51,136,71,161,
11192 196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,7,129,249,155,51,168,71,
11193 161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,7,129,249,155,51,200,
11194 71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,7,129,249,155,51,
11195 232,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,0,2,1,155,52,
11196 8,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,0,2,1,155,52,40,
11197 71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,155,52,72,
11198 71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,155,52,
11199 104,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,155,
11200 52,136,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,1,2,1,135,
11201 52,166,32,76,72,1,246,136,235,103,177,69,0,136,144,3,226,27,61,138,41,44,
11202 50,36,0,251,68,117,179,209,214,234,201,69,16,50,36,0,251,68,117,179,209,
11203 214,232,73,69,34,5,196,128,31,16,217,232,235,117,100,162,147,2,226,64,15,
11204 136,108,244,117,186,18,81,74,129,145,32,7,218,35,173,158,158,151,86,74,40,
11205 161,145,32,7,218,35,173,158,158,151,66,74,41,20,46,36,0,248,134,207,79,75,
11206 171,37,20,154,23,18,0,124,67,103,167,165,208,146,138,85,11,137,0,62,21,110,
11207 4,250,178,81,70,11,137,0,62,21,110,4,250,18,81,72,193,145,32,7,193,186,129,
11208 89,58,178,81,71,12,137,0,62,13,212,10,201,208,146,138,71,10,137,0,62,209,
11209 29,108,250,178,81,104,1,81,32,7,218,35,173,159,66,74,45,32,38,36,0,248,134,
11210 207,171,37,22,160,19,18,0,124,67,103,208,146,139,88,10,180,81,50,118,136,
11211 235,103,177,77,128,155,69,19,39,16,217,236,83,105,97,182,138,38,78,209,29,
11212 108,244,117,186,178,83,100,13,180,81,50,118,136,235,103,163,173,208,146,
11213 155,68,12,180,81,50,113,13,158,142,183,86,74,109,48,50,209,68,201,196,54,
11214 122,58,221,9,41,181,64,219,69,19,39,104,142,182,122,122,93,89,41,178,134,
11215 218,40,153,59,68,117,179,211,210,232,73,77,162,134,90,40,153,56,134,207,79,
11216 75,171,37,54,154,25,104,162,100,226,27,61,61,46,132,148,218,168,101,162,
11217 137,147,133,91,129,62,172,148,217,131,45,20,76,156,42,220,9,244,36,166,209,
11218 131,109,20,76,156,27,168,21,147,171,37,54,112,219,69,19,39,6,234,5,100,232,
11219 73,77,163,133,218,40,153,59,68,117,179,234,201,78,32,5,218,40,153,59,68,
11220 117,179,232,73,78,36,5,90,40,153,56,134,207,171,37,56,160,21,104,162,100,
11221 226,27,62,132,148,226,195,95,182,97,176,218,128,8,84,45,123,38,1,137,10,1,
11222 114,160,64,56,156,199,130,36,160,72,8,39,63,27,24,1,100,180,8,148,146,0,45,
11223 162,137,147,111,2,8,4,16,7,8,96,120,72,13,42,226,145,97,87,224,168,1,58,
11224 182,232,232,64,22,85,181,187,177,107,2,64,7,213,183,74,7,121,207,215,242,
11225 17,119,49,248,94,173,198,210,36,15,232,34,182,84,113,95,115,240,221,91,141,
11226 163,160,72,1,220,164,194,175,121,123,103,224,186,244,64,24,45,68,84,251,33,
11227 9,64,15,217,66,51,209,218,210,129,154,118,254,205,61,65,204,126,23,178,132,
11228 103,165,3,52,237,253,154,122,131,216,254,168,48,6,90,130,1,0,39,75,80,72,8,
11229 9,33,186,130,80,64,76,13,212,19,2,130,96,110,150,173,0,65,6,51,212,20,128,
11230 65,17,11,212,19,130,137,121,211,210,209,144,6,39,75,80,80,0,201,119,234,10,
11231 8,41,86,231,71,80,80,129,79,135,186,122,69,224,34,25,69,233,80,3,91,141,
11232 168,40,96,139,113,180,181,5,36,21,110,54,142,134,160,165,1,176,23,211,47,0,
11233 216,134,233,215,128,111,117,181,104,128,209,3,70,230,106,64,5,139,168,209,
11234 234,10,32,36,144,102,234,136,3,146,27,168,40,160,146,132,103,168,40,192,
11235 115,3,117,5,28,22,113,163,69,168,41,103,1,66,188,17,145,52,40,4,202,113,67,
11236 76,130,227,68,194,13,240,108,0,0,83,96,0,2,161,0,104,146,84,97,48,0,1,78,
11237 192,56,169,24,145,179,192,0,5,48,8,56,16,32,128,56,18,52,125,166,86,147,
11238 182,140,28,50,21,13,39,31,23,60,145,158,56,140,141,47,113,6,155,186,188,24,
11239 49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,197,68,14,49,
11240 39,199,197,211,116,240,242,113,197,230,18,180,253,228,3,17,46,18,243,35,
11241 100,128,172,156,114,70,163,146,76,34,248,146,164,108,248,75,204,141,146,28,
11242 217,114,137,27,78,251,241,173,234,162,160,225,1,3,34,92,170,9,105,164,32,
11243 225,64,131,155,1,193,133,7,19,39,22,70,154,103,143,128,0,10,176,20,28,76,
11244 156,113,75,34,78,62,0,0,43,0,48,104,82,146,49,240,0,1,84,11,180,192,0,5,
11245 114,1,18,160,65,24,131,20,145,25,172,48,132,122,28,76,146,218,121,35,180,
11246 69,145,132,108,224,0,0,0,0,0,0,120,31,153,172,56,132,122,28,76,146,218,121,
11247 35,180,69,145,132,108,224,0,0,0,0,0,0,120,31,168,160,45,110,23,30,176,33,
11248 184,0,0,175,32,29,235,2,27,199,23,0,0,22,4,51,88,129,8,244,56,153,37,180,
11249 242,71,104,139,35,8,217,192,0,0,0,0,0,0,240,63,51,88,145,8,244,56,153,37,
11250 180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,88,161,8,244,56,153,37,
11251 180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,88,177,8,244,56,153,37,
11252 180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,88,193,8,244,56,153,
11253 37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,88,209,8,244,56,
11254 153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,88,225,8,244,
11255 56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,32,64,32,227,194,0,
11256 97,57,162,4,245,232,5,34,92,35,68,225,161,166,218,16,16,137,112,52,41,73,
11257 29,153,1,65,196,201,197,145,166,153,245,200,3,137,204,120,34,74,8,200,58,
11258 112,28,211,32,130,52,78,26,26,110,248,0,0,164,4,12,70,137,195,39,252,73,
11259 240,117,32,57,168,97,4,104,156,52,52,221,255,160,20,160,152,23,223,250,32,
11260 148,25,174,137,58,23,51,191,244,84,12,50,9,195,39,240,81,238,2,3,107,173,
11261 214,3,192,
11262 };
11263 #elif defined(DUK_USE_DOUBLE_BE)
11264 DUK_INTERNAL const duk_uint8_t duk_builtins_data[4116] = {
11265 144,148,105,224,32,68,52,228,62,12,104,200,165,132,52,167,194,138,105,243,
11266 124,57,28,211,57,18,64,52,238,126,44,138,111,171,241,164,19,87,129,30,33,
11267 167,16,145,159,8,211,136,9,225,42,5,240,145,139,163,163,8,211,136,10,228,
11268 64,211,19,132,140,93,29,56,70,156,64,119,34,66,146,36,104,137,194,70,46,
11269 142,172,35,78,32,47,146,195,102,11,240,145,139,163,175,8,211,136,9,228,240,
11270 242,112,145,139,163,179,8,211,136,8,237,34,130,118,49,116,118,225,26,48,0,
11271 1,82,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
11272 33,8,66,26,179,233,97,167,60,150,34,33,154,112,0,1,75,247,35,79,95,237,198,
11273 174,200,47,31,23,95,17,13,51,19,35,93,68,216,209,128,0,10,208,174,79,15,32,
11274 248,8,196,24,8,107,192,0,5,106,118,27,94,0,0,43,83,227,94,0,0,43,84,46,215,
11275 128,0,10,213,28,198,188,0,0,86,169,100,53,224,0,2,181,79,85,175,0,0,21,170,
11276 154,45,120,0,0,173,85,217,107,192,0,5,106,182,243,86,193,106,52,127,130,
11277 249,50,94,124,35,68,225,146,49,13,31,186,23,201,146,243,224,200,39,12,145,
11278 136,67,134,19,49,1,255,224,0,0,0,0,0,3,51,1,255,192,0,0,0,0,0,3,47,18,1,
11279 172,19,120,71,10,25,196,136,113,162,156,136,199,42,57,204,144,115,132,240,
11280 149,2,248,72,197,209,58,2,185,16,52,196,225,35,23,68,233,14,228,72,82,68,
11281 141,17,56,72,197,209,58,130,249,44,54,96,191,9,24,186,39,88,79,39,135,147,
11282 132,140,93,19,176,35,180,138,9,216,197,209,59,82,79,35,40,242,65,248,58,42,
11283 96,121,14,232,94,62,46,190,15,42,31,145,33,86,65,76,242,214,143,73,48,242,
11284 243,79,49,56,243,115,207,57,64,243,180,79,61,72,243,244,207,65,80,244,53,
11285 79,69,88,244,98,30,8,200,156,67,102,120,241,79,4,100,78,21,110,4,207,32,47,
11286 147,37,231,194,52,78,25,34,122,81,124,153,47,62,12,130,112,201,19,211,139,
11287 121,34,87,69,128,104,137,239,83,18,238,108,165,2,162,92,104,56,220,233,1,8,
11288 151,10,134,162,100,206,16,18,50,9,195,39,105,20,101,136,18,25,4,225,147,
11289 180,138,5,215,49,238,105,27,60,185,1,36,104,156,50,118,145,70,96,129,34,52,
11290 78,25,59,72,160,93,115,30,230,145,179,204,144,12,73,8,15,38,104,128,138,52,
11291 146,16,30,77,1,0,2,11,132,193,198,36,248,248,186,110,158,30,78,56,188,194,
11292 70,183,170,136,48,98,79,142,179,120,248,185,228,140,241,193,146,66,138,31,
11293 55,71,138,128,153,137,62,58,205,227,226,231,146,51,199,26,6,18,92,146,64,
11294 96,74,72,51,120,43,192,97,68,128,153,56,72,7,12,133,67,73,199,197,207,36,
11295 103,142,35,2,3,33,80,210,113,241,115,201,25,160,146,225,160,9,34,1,124,178,
11296 1,139,18,19,36,229,146,8,190,36,169,27,62,18,243,35,100,135,54,92,162,2,17,
11297 46,72,128,89,7,200,32,33,18,225,98,236,145,188,130,64,196,75,132,188,200,
11298 217,32,43,39,28,128,69,19,18,228,144,42,98,79,142,179,120,248,185,228,140,
11299 241,201,97,129,114,229,201,37,2,68,184,200,1,147,93,159,153,213,34,235,250,
11300 96,48,157,32,24,94,160,1,199,4,184,235,55,143,139,158,72,207,28,226,3,81,
11301 46,62,46,155,167,135,147,142,47,60,129,71,197,207,36,103,142,34,92,35,104,
11302 194,68,1,89,58,36,8,109,109,12,133,67,73,195,18,115,36,118,182,185,168,8,
11303 109,109,12,133,67,73,201,18,115,36,118,182,185,168,130,27,91,75,115,149,71,
11304 240,196,156,201,29,173,174,129,2,27,91,75,115,149,71,242,68,156,201,29,173,
11305 174,129,34,12,16,28,128,62,191,42,3,71,146,68,4,16,22,188,161,240,16,40,
11306 104,242,103,196,16,93,158,125,96,110,115,235,64,131,16,16,58,37,192,70,32,
11307 194,144,114,25,67,95,40,6,18,8,32,48,156,209,2,108,124,96,224,144,6,247,62,
11308 16,0,143,164,143,12,248,15,18,84,145,145,34,128,11,35,160,179,140,0,44,150,
11309 129,18,58,0,146,116,103,32,128,105,61,104,17,36,175,1,232,217,29,5,156,179,
11310 224,58,26,50,95,142,43,159,64,181,130,83,226,26,50,95,142,43,159,192,7,255,
11311 248,41,42,72,226,1,160,18,78,97,32,26,64,114,186,60,32,4,120,6,148,13,128,
11312 124,3,76,12,84,46,100,140,3,78,13,18,14,130,36,67,232,23,18,14,130,39,34,
11313 131,30,113,15,224,3,255,253,6,48,40,194,197,204,224,142,8,240,78,25,60,231,
11314 192,210,197,204,224,156,50,113,238,67,103,232,62,28,138,156,104,82,170,107,
11315 255,32,48,191,144,1,132,112,71,128,159,168,128,161,28,17,224,156,50,112,19,
11316 245,144,22,39,12,156,123,144,217,240,19,245,146,3,9,205,16,39,236,62,3,161,
11317 163,37,248,226,251,141,1,107,4,167,196,52,100,191,28,95,113,164,13,91,132,
11318 5,147,130,115,30,8,147,222,64,43,1,49,31,224,64,60,72,245,128,68,249,32,13,
11319 34,2,34,63,204,128,89,45,2,39,209,0,89,61,104,159,213,0,153,80,50,156,80,
11320 211,126,16,11,155,184,183,88,145,224,129,34,122,64,17,155,184,183,8,11,39,
11321 22,235,18,60,16,36,79,72,1,115,119,40,247,146,60,16,36,79,72,32,140,221,
11322 197,184,64,89,57,71,188,145,224,129,34,122,65,1,39,20,51,244,0,52,72,242,2,
11323 127,18,2,165,48,70,114,229,145,51,253,141,1,4,104,229,203,34,103,251,26,64,
11324 132,52,75,160,201,47,105,160,26,84,12,167,31,186,8,50,0,114,58,113,163,46,
11325 190,120,35,11,60,4,25,68,81,61,96,47,181,80,46,132,128,255,223,255,255,255,
11326 255,255,254,39,172,67,118,170,5,208,144,0,0,0,0,0,0,0,0,115,16,31,254,0,0,
11327 0,0,0,0,8,245,238,146,38,138,147,105,13,42,26,137,226,3,255,128,0,0,0,0,0,
11328 1,30,180,134,4,209,82,109,33,165,67,81,60,64,255,240,0,0,0,0,0,0,15,210,62,
11329 72,91,155,0,242,192,0,0,0,0,0,0,135,88,11,237,72,5,38,210,27,50,24,145,128,
11330 134,127,255,255,255,255,255,254,67,172,67,118,164,2,147,105,13,153,12,72,
11331 192,195,63,255,255,255,255,255,255,16,240,70,68,226,27,51,199,138,120,35,
11332 34,112,171,112,38,121,7,16,137,112,168,106,38,77,193,1,40,151,16,217,144,
11333 196,142,224,144,21,18,227,65,198,238,9,67,81,46,72,5,39,16,217,144,196,142,
11334 224,152,228,148,227,64,0,0,0,0,0,0,0,0,131,175,223,16,194,111,8,97,119,224,
11335 3,205,220,42,46,65,238,200,13,155,184,75,189,205,35,102,128,47,116,64,92,
11336 221,199,196,130,68,144,230,239,72,65,152,12,21,224,140,137,92,128,62,210,
11337 98,177,252,3,107,173,88,3,146,211,141,33,255,224,0,0,0,0,0,3,19,175,188,0,
11338 100,221,193,130,100,228,167,20,52,215,129,3,38,238,77,12,39,37,56,161,166,
11339 188,10,194,94,6,18,155,184,183,8,11,39,6,9,147,146,156,80,211,94,7,18,155,
11340 184,183,8,11,39,38,134,19,146,156,80,211,94,8,12,53,224,130,195,222,8,77,
11341 133,210,24,91,224,3,152,147,228,208,194,95,0,44,196,159,11,69,175,152,32,
11342 35,100,33,135,24,147,237,38,34,246,139,95,48,64,70,200,68,8,49,39,198,57,
11343 179,61,144,138,22,98,79,180,152,153,215,54,103,178,17,129,204,73,240,96,
11344 153,44,132,112,163,18,125,164,196,62,130,100,178,18,1,140,73,240,96,197,
11345 144,146,18,98,79,180,152,135,208,98,200,74,8,49,39,195,186,145,149,144,150,
11346 22,98,79,180,152,143,215,82,50,178,19,2,140,73,241,136,109,38,73,89,9,161,
11347 166,36,251,73,137,157,67,105,50,74,200,78,10,49,39,201,16,78,104,229,100,
11348 39,134,152,147,237,38,41,116,130,115,71,43,33,64,60,196,159,24,133,173,18,
11349 32,156,209,202,200,81,18,49,39,218,76,76,234,22,180,72,130,115,71,43,33,72,
11350 68,196,159,38,134,19,46,105,56,226,150,68,157,160,1,228,73,242,104,97,46,
11351 16,31,34,79,140,66,214,137,16,78,104,229,108,169,137,72,147,237,38,38,117,
11352 11,90,36,65,57,163,149,178,168,21,34,79,146,32,156,209,202,218,250,161,178,
11353 36,251,73,138,93,32,156,209,202,218,250,193,82,36,248,196,54,147,36,173,
11354 191,174,27,34,79,180,152,153,212,54,147,36,173,191,176,17,34,79,135,117,35,
11355 43,115,236,133,200,147,237,38,35,245,212,140,173,207,180,15,34,79,131,4,
11356 201,108,173,133,72,147,237,38,33,244,19,37,178,184,17,34,79,140,115,102,
11357 123,107,238,133,200,147,237,38,38,117,205,153,237,175,188,23,34,79,133,162,
11358 215,204,16,17,182,254,248,116,137,62,210,98,47,104,181,243,4,4,109,191,192,
11359 131,152,147,230,8,8,217,12,16,60,137,62,96,128,141,178,193,160,206,1,201,
11360 176,113,146,0,0,0,0,0,0,0,0,49,185,252,65,137,207,227,37,215,207,227,12,86,
11361 127,24,152,188,254,49,88,33,46,65,120,72,4,153,37,63,33,13,127,148,4,26,0,
11362 57,62,6,228,163,228,74,86,215,62,55,28,110,179,226,113,70,223,62,47,24,38,
11363 191,30,2,125,32,40,20,87,114,41,225,42,5,240,145,139,163,145,41,68,250,128,
11364 80,41,174,228,85,200,129,166,39,9,24,186,57,18,148,79,172,5,2,170,238,69,
11365 220,137,10,72,145,162,39,9,24,186,57,18,148,79,176,5,2,186,238,69,124,150,
11366 27,48,95,132,140,93,28,137,74,39,218,2,129,101,119,34,158,79,15,39,9,24,
11367 186,57,18,148,79,184,5,2,218,238,69,29,164,80,78,198,46,142,68,165,16,64,
11368 28,24,61,73,25,33,205,128,129,167,166,0,0,0,0,1,108,242,151,15,39,8,34,26,
11369 87,97,200,3,0,167,129,32,8,194,195,16,6,84,55,10,60,3,35,69,132,30,1,140,
11370 130,193,143,1,196,230,60,2,158,8,131,153,64,115,42,46,191,176,8,194,246,0,
11371 80,5,220,193,95,6,234,5,100,225,35,23,71,35,6,228,140,93,29,180,55,108,145,
11372 139,163,182,112,52,107,67,76,56,3,153,132,20,28,76,156,89,26,105,158,62,0,
11373 0,42,193,2,201,104,17,41,34,156,204,176,160,226,100,226,200,211,76,241,240,
11374 0,1,86,2,131,137,147,142,41,100,73,199,192,0,5,96,6,13,10,82,70,62,0,0,42,
11375 130,88,115,18,124,67,103,177,69,49,129,6,36,249,68,54,123,20,82,216,65,137,
11376 62,33,179,209,214,162,152,208,147,18,124,162,27,61,29,106,41,112,32,196,
11377 159,16,217,233,233,81,76,112,73,137,62,81,13,158,158,149,20,186,20,98,79,
11378 133,91,129,61,61,42,41,120,40,196,159,10,183,2,122,218,148,82,248,60,137,
11379 62,33,179,216,166,216,192,137,18,124,162,27,61,138,109,108,34,68,159,16,
11380 217,232,235,83,108,104,76,137,62,81,13,158,142,181,54,184,17,34,79,136,108,
11381 244,244,169,182,56,38,68,159,40,134,207,79,74,155,93,10,145,39,194,173,192,
11382 158,158,149,54,188,21,34,79,133,91,129,61,109,74,109,125,155,51,136,71,161,
11383 196,201,45,167,146,59,68,89,24,70,206,1,255,128,0,0,0,0,0,1,155,51,168,71,
11384 161,196,201,45,167,146,59,68,89,24,70,206,1,255,128,0,0,0,0,0,1,155,51,200,
11385 71,161,196,201,45,167,146,59,68,89,24,70,206,1,255,128,0,0,0,0,0,1,155,51,
11386 232,71,161,196,201,45,167,146,59,68,89,24,70,206,2,0,0,0,0,0,0,0,1,155,52,
11387 8,71,161,196,201,45,167,146,59,68,89,24,70,206,2,0,0,0,0,0,0,0,1,155,52,40,
11388 71,161,196,201,45,167,146,59,68,89,24,70,206,2,0,128,0,0,0,0,0,1,155,52,72,
11389 71,161,196,201,45,167,146,59,68,89,24,70,206,2,0,128,0,0,0,0,0,1,155,52,
11390 104,71,161,196,201,45,167,146,59,68,89,24,70,206,2,0,128,0,0,0,0,0,1,155,
11391 52,136,71,161,196,201,45,167,146,59,68,89,24,70,206,2,1,0,0,0,0,0,0,1,135,
11392 52,166,32,76,72,1,246,136,235,103,177,69,0,136,144,3,226,27,61,138,41,44,
11393 50,36,0,251,68,117,179,209,214,234,201,69,16,50,36,0,251,68,117,179,209,
11394 214,232,73,69,34,5,196,128,31,16,217,232,235,117,100,162,147,2,226,64,15,
11395 136,108,244,117,186,18,81,74,129,145,32,7,218,35,173,158,158,151,86,74,40,
11396 161,145,32,7,218,35,173,158,158,151,66,74,41,20,46,36,0,248,134,207,79,75,
11397 171,37,20,154,23,18,0,124,67,103,167,165,208,146,138,85,11,137,0,62,21,110,
11398 4,250,178,81,70,11,137,0,62,21,110,4,250,18,81,72,193,145,32,7,193,186,129,
11399 89,58,178,81,71,12,137,0,62,13,212,10,201,208,146,138,71,10,137,0,62,209,
11400 29,108,250,178,81,104,1,81,32,7,218,35,173,159,66,74,45,32,38,36,0,248,134,
11401 207,171,37,22,160,19,18,0,124,67,103,208,146,139,88,10,180,81,50,118,136,
11402 235,103,177,77,128,155,69,19,39,16,217,236,83,105,97,182,138,38,78,209,29,
11403 108,244,117,186,178,83,100,13,180,81,50,118,136,235,103,163,173,208,146,
11404 155,68,12,180,81,50,113,13,158,142,183,86,74,109,48,50,209,68,201,196,54,
11405 122,58,221,9,41,181,64,219,69,19,39,104,142,182,122,122,93,89,41,178,134,
11406 218,40,153,59,68,117,179,211,210,232,73,77,162,134,90,40,153,56,134,207,79,
11407 75,171,37,54,154,25,104,162,100,226,27,61,61,46,132,148,218,168,101,162,
11408 137,147,133,91,129,62,172,148,217,131,45,20,76,156,42,220,9,244,36,166,209,
11409 131,109,20,76,156,27,168,21,147,171,37,54,112,219,69,19,39,6,234,5,100,232,
11410 73,77,163,133,218,40,153,59,68,117,179,234,201,78,32,5,218,40,153,59,68,
11411 117,179,232,73,78,36,5,90,40,153,56,134,207,171,37,56,160,21,104,162,100,
11412 226,27,62,132,148,226,195,95,182,97,176,218,128,8,84,45,123,38,1,137,10,1,
11413 114,160,64,56,156,199,130,36,160,72,8,39,63,27,24,1,100,180,8,148,146,0,45,
11414 162,137,147,111,2,8,4,16,7,8,96,120,72,8,0,183,225,81,98,138,237,33,58,182,
11415 232,232,64,64,2,107,177,187,181,85,22,7,213,183,74,1,255,49,114,23,247,209,
11416 207,120,94,173,198,210,36,3,255,113,84,118,82,184,47,224,221,91,141,163,
11417 160,72,7,251,121,111,98,164,220,161,192,186,244,64,64,9,33,251,84,68,45,24,
11418 15,217,66,51,209,218,210,128,127,205,65,60,204,254,119,154,23,178,132,103,
11419 165,0,255,218,130,121,153,252,239,54,168,48,6,90,130,1,0,39,75,80,72,8,9,
11420 33,186,130,80,64,76,13,212,19,2,130,96,110,150,173,0,65,6,51,212,20,128,65,
11421 17,11,212,19,130,137,121,211,210,209,144,6,39,75,80,80,0,201,119,234,10,8,
11422 41,86,231,71,80,80,129,79,135,186,122,69,224,34,25,69,233,80,3,91,141,168,
11423 40,96,139,113,180,181,5,36,21,110,54,142,134,160,165,1,176,23,211,47,0,216,
11424 134,233,215,128,111,117,181,104,128,209,3,70,230,106,64,5,139,168,209,234,
11425 10,32,36,144,102,234,136,3,146,27,168,40,160,146,132,103,168,40,192,115,3,
11426 117,5,28,22,113,163,69,168,41,103,1,66,188,17,145,52,40,4,202,113,67,76,
11427 130,227,68,194,13,240,108,0,0,83,96,0,2,161,0,104,146,84,97,48,0,1,78,192,
11428 56,169,24,145,179,192,0,5,48,8,56,16,32,128,56,18,52,125,166,86,147,182,
11429 140,28,50,21,13,39,31,23,60,145,158,56,140,141,47,113,6,155,186,188,24,49,
11430 39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,197,68,14,49,39,
11431 199,197,211,116,240,242,113,197,230,18,180,253,228,3,17,46,18,243,35,100,
11432 128,172,156,114,70,163,146,76,34,248,146,164,108,248,75,204,141,146,28,217,
11433 114,137,27,78,251,241,173,234,162,160,225,1,3,34,92,170,9,105,164,32,225,
11434 64,131,155,1,193,133,7,19,39,22,70,154,103,143,128,0,10,176,20,28,76,156,
11435 113,75,34,78,62,0,0,43,0,48,104,82,146,49,240,0,1,84,11,180,192,0,5,114,1,
11436 18,160,65,24,131,20,145,25,172,48,132,122,28,76,146,218,121,35,180,69,145,
11437 132,108,224,31,248,0,0,0,0,0,0,25,172,56,132,122,28,76,146,218,121,35,180,
11438 69,145,132,108,224,31,248,0,0,0,0,0,0,40,160,45,110,23,30,176,33,184,0,0,
11439 175,32,29,235,2,27,199,23,0,0,22,4,51,88,129,8,244,56,153,37,180,242,71,
11440 104,139,35,8,217,192,63,240,0,0,0,0,0,0,51,88,145,8,244,56,153,37,180,242,
11441 71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,88,161,8,244,56,153,37,180,242,
11442 71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,88,177,8,244,56,153,37,180,242,
11443 71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,88,193,8,244,56,153,37,180,
11444 242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,88,209,8,244,56,153,37,
11445 180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,88,225,8,244,56,153,
11446 37,180,242,71,104,139,35,8,217,192,64,32,0,0,0,0,0,0,32,227,194,0,97,57,
11447 162,4,245,232,5,34,92,35,68,225,161,166,218,16,16,137,112,52,41,73,29,153,
11448 1,65,196,201,197,145,166,153,245,200,3,137,204,120,34,74,8,200,58,112,28,
11449 211,32,130,52,78,26,26,110,248,0,0,164,4,12,70,137,195,39,252,73,240,117,
11450 32,57,168,97,4,104,156,52,52,221,255,160,20,160,152,23,223,250,32,148,25,
11451 174,137,58,23,51,191,244,84,12,50,9,195,39,240,81,238,2,3,107,173,214,3,
11452 192,
11453 };
11454 #elif defined(DUK_USE_DOUBLE_ME)
11455 DUK_INTERNAL const duk_uint8_t duk_builtins_data[4116] = {
11456 144,148,105,224,32,68,52,228,62,12,104,200,165,132,52,167,194,138,105,243,
11457 124,57,28,211,57,18,64,52,238,126,44,138,111,171,241,164,19,87,129,30,33,
11458 167,16,145,159,8,211,136,9,225,42,5,240,145,139,163,163,8,211,136,10,228,
11459 64,211,19,132,140,93,29,56,70,156,64,119,34,66,146,36,104,137,194,70,46,
11460 142,172,35,78,32,47,146,195,102,11,240,145,139,163,175,8,211,136,9,228,240,
11461 242,112,145,139,163,179,8,211,136,8,237,34,130,118,49,116,118,225,26,48,0,
11462 1,82,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
11463 33,8,66,26,179,233,97,167,60,150,34,33,154,112,0,1,75,247,35,79,95,237,198,
11464 174,200,47,31,23,95,17,13,51,19,35,93,68,216,209,128,0,10,208,174,79,15,32,
11465 248,8,196,24,8,107,192,0,5,106,118,27,94,0,0,43,83,227,94,0,0,43,84,46,215,
11466 128,0,10,213,28,198,188,0,0,86,169,100,53,224,0,2,181,79,85,175,0,0,21,170,
11467 154,45,120,0,0,173,85,217,107,192,0,5,106,182,243,86,193,106,52,127,130,
11468 249,50,94,124,35,68,225,146,49,13,31,186,23,201,146,243,224,200,39,12,145,
11469 136,67,134,19,49,0,0,3,225,252,0,0,0,3,51,0,0,3,193,252,0,0,0,3,47,18,1,
11470 172,19,120,71,10,25,196,136,113,162,156,136,199,42,57,204,144,115,132,240,
11471 149,2,248,72,197,209,58,2,185,16,52,196,225,35,23,68,233,14,228,72,82,68,
11472 141,17,56,72,197,209,58,130,249,44,54,96,191,9,24,186,39,88,79,39,135,147,
11473 132,140,93,19,176,35,180,138,9,216,197,209,59,82,79,35,40,242,65,248,58,42,
11474 96,121,14,232,94,62,46,190,15,42,31,145,33,86,65,76,242,214,143,73,48,242,
11475 243,79,49,56,243,115,207,57,64,243,180,79,61,72,243,244,207,65,80,244,53,
11476 79,69,88,244,98,30,8,200,156,67,102,120,241,79,4,100,78,21,110,4,207,32,47,
11477 147,37,231,194,52,78,25,34,122,81,124,153,47,62,12,130,112,201,19,211,139,
11478 121,34,87,69,128,104,137,239,83,18,238,108,165,2,162,92,104,56,220,233,1,8,
11479 151,10,134,162,100,206,16,18,50,9,195,39,105,20,101,136,18,25,4,225,147,
11480 180,138,5,215,49,238,105,27,60,185,1,36,104,156,50,118,145,70,96,129,34,52,
11481 78,25,59,72,160,93,115,30,230,145,179,204,144,12,73,8,15,38,104,128,138,52,
11482 146,16,30,77,1,0,2,11,132,193,198,36,248,248,186,110,158,30,78,56,188,194,
11483 70,183,170,136,48,98,79,142,179,120,248,185,228,140,241,193,146,66,138,31,
11484 55,71,138,128,153,137,62,58,205,227,226,231,146,51,199,26,6,18,92,146,64,
11485 96,74,72,51,120,43,192,97,68,128,153,56,72,7,12,133,67,73,199,197,207,36,
11486 103,142,35,2,3,33,80,210,113,241,115,201,25,160,146,225,160,9,34,1,124,178,
11487 1,139,18,19,36,229,146,8,190,36,169,27,62,18,243,35,100,135,54,92,162,2,17,
11488 46,72,128,89,7,200,32,33,18,225,98,236,145,188,130,64,196,75,132,188,200,
11489 217,32,43,39,28,128,69,19,18,228,144,42,98,79,142,179,120,248,185,228,140,
11490 241,201,97,129,114,229,201,37,2,68,184,200,1,147,93,159,153,213,34,235,250,
11491 96,48,157,32,24,94,160,1,199,4,184,235,55,143,139,158,72,207,28,226,3,81,
11492 46,62,46,155,167,135,147,142,47,60,129,71,197,207,36,103,142,34,92,35,104,
11493 194,68,1,89,58,36,8,109,109,12,133,67,73,195,18,115,36,118,182,185,168,8,
11494 109,109,12,133,67,73,201,18,115,36,118,182,185,168,130,27,91,75,115,149,71,
11495 240,196,156,201,29,173,174,129,2,27,91,75,115,149,71,242,68,156,201,29,173,
11496 174,129,34,12,16,28,128,62,191,42,3,71,146,68,4,16,22,188,161,240,16,40,
11497 104,242,103,196,16,93,158,125,96,110,115,235,64,131,16,16,58,37,192,70,32,
11498 194,144,114,25,67,95,40,6,18,8,32,48,156,209,2,108,124,96,224,144,6,247,62,
11499 16,0,143,164,143,12,248,15,18,84,145,145,34,128,11,35,160,179,140,0,44,150,
11500 129,18,58,0,146,116,103,32,128,105,61,104,17,36,175,1,232,217,29,5,156,179,
11501 224,58,26,50,95,142,43,159,64,181,130,83,226,26,50,95,142,43,159,192,7,255,
11502 248,41,42,72,226,1,160,18,78,97,32,26,64,114,186,60,32,4,120,6,148,13,128,
11503 124,3,76,12,84,46,100,140,3,78,13,18,14,130,36,67,232,23,18,14,130,39,34,
11504 131,30,113,15,224,3,255,253,6,48,40,194,197,204,224,142,8,240,78,25,60,231,
11505 192,210,197,204,224,156,50,113,238,67,103,232,62,28,138,156,104,82,170,107,
11506 255,32,48,191,144,1,132,112,71,128,159,168,128,161,28,17,224,156,50,112,19,
11507 245,144,22,39,12,156,123,144,217,240,19,245,146,3,9,205,16,39,236,62,3,161,
11508 163,37,248,226,251,141,1,107,4,167,196,52,100,191,28,95,113,164,13,91,132,
11509 5,147,130,115,30,8,147,222,64,43,1,49,31,224,64,60,72,245,128,68,249,32,13,
11510 34,2,34,63,204,128,89,45,2,39,209,0,89,61,104,159,213,0,153,80,50,156,80,
11511 211,126,16,11,155,184,183,88,145,224,129,34,122,64,17,155,184,183,8,11,39,
11512 22,235,18,60,16,36,79,72,1,115,119,40,247,146,60,16,36,79,72,32,140,221,
11513 197,184,64,89,57,71,188,145,224,129,34,122,65,1,39,20,51,244,0,52,72,242,2,
11514 127,18,2,165,48,70,114,229,145,51,253,141,1,4,104,229,203,34,103,251,26,64,
11515 132,52,75,160,201,47,105,160,26,84,12,167,31,186,8,50,0,114,58,113,163,46,
11516 190,120,35,11,60,4,25,68,81,61,96,47,181,80,46,132,129,255,255,222,255,255,
11517 255,255,254,39,172,67,118,170,5,208,144,0,0,0,0,0,64,0,0,51,16,0,0,62,31,
11518 192,0,0,0,8,245,238,146,38,138,147,105,13,42,26,137,226,0,0,7,131,248,0,0,
11519 0,1,30,180,134,4,209,82,109,33,165,67,81,60,64,0,0,240,255,0,0,0,0,15,210,
11520 62,72,91,155,0,0,2,192,240,0,0,0,0,135,88,11,237,72,5,38,210,27,50,24,145,
11521 129,255,254,126,135,255,255,255,254,67,172,67,118,164,2,147,105,13,153,12,
11522 72,192,255,255,63,195,255,255,255,255,16,240,70,68,226,27,51,199,138,120,
11523 35,34,112,171,112,38,121,7,16,137,112,168,106,38,77,193,1,40,151,16,217,
11524 144,196,142,224,144,21,18,227,65,198,238,9,67,81,46,72,5,39,16,217,144,196,
11525 142,224,152,228,148,227,64,0,0,0,0,0,0,0,0,131,175,223,16,194,111,8,97,119,
11526 224,3,205,220,42,46,65,238,200,13,155,184,75,189,205,35,102,128,47,116,64,
11527 92,221,199,196,130,68,144,230,239,72,65,152,12,21,224,140,137,92,128,62,
11528 210,98,177,252,3,107,173,88,3,146,211,141,32,0,3,225,252,0,0,0,3,19,175,
11529 188,0,100,221,193,130,100,228,167,20,52,215,129,3,38,238,77,12,39,37,56,
11530 161,166,188,10,194,94,6,18,155,184,183,8,11,39,6,9,147,146,156,80,211,94,7,
11531 18,155,184,183,8,11,39,38,134,19,146,156,80,211,94,8,12,53,224,130,195,222,
11532 8,77,133,210,24,91,224,3,152,147,228,208,194,95,0,44,196,159,11,69,175,152,
11533 32,35,100,33,135,24,147,237,38,34,246,139,95,48,64,70,200,68,8,49,39,198,
11534 57,179,61,144,138,22,98,79,180,152,153,215,54,103,178,17,129,204,73,240,96,
11535 153,44,132,112,163,18,125,164,196,62,130,100,178,18,1,140,73,240,96,197,
11536 144,146,18,98,79,180,152,135,208,98,200,74,8,49,39,195,186,145,149,144,150,
11537 22,98,79,180,152,143,215,82,50,178,19,2,140,73,241,136,109,38,73,89,9,161,
11538 166,36,251,73,137,157,67,105,50,74,200,78,10,49,39,201,16,78,104,229,100,
11539 39,134,152,147,237,38,41,116,130,115,71,43,33,64,60,196,159,24,133,173,18,
11540 32,156,209,202,200,81,18,49,39,218,76,76,234,22,180,72,130,115,71,43,33,72,
11541 68,196,159,38,134,19,46,105,56,226,150,68,157,160,1,228,73,242,104,97,46,
11542 16,31,34,79,140,66,214,137,16,78,104,229,108,169,137,72,147,237,38,38,117,
11543 11,90,36,65,57,163,149,178,168,21,34,79,146,32,156,209,202,218,250,161,178,
11544 36,251,73,138,93,32,156,209,202,218,250,193,82,36,248,196,54,147,36,173,
11545 191,174,27,34,79,180,152,153,212,54,147,36,173,191,176,17,34,79,135,117,35,
11546 43,115,236,133,200,147,237,38,35,245,212,140,173,207,180,15,34,79,131,4,
11547 201,108,173,133,72,147,237,38,33,244,19,37,178,184,17,34,79,140,115,102,
11548 123,107,238,133,200,147,237,38,38,117,205,153,237,175,188,23,34,79,133,162,
11549 215,204,16,17,182,254,248,116,137,62,210,98,47,104,181,243,4,4,109,191,192,
11550 131,152,147,230,8,8,217,12,16,60,137,62,96,128,141,178,193,160,206,1,201,
11551 176,113,146,0,0,0,0,0,0,0,0,49,185,252,65,137,207,227,37,215,207,227,12,86,
11552 127,24,152,188,254,49,88,33,46,65,120,72,4,153,37,63,33,13,127,148,4,26,0,
11553 57,62,6,228,163,228,74,86,215,62,55,28,110,179,226,113,70,223,62,47,24,38,
11554 191,30,2,125,32,40,20,87,114,41,225,42,5,240,145,139,163,145,41,68,250,128,
11555 80,41,174,228,85,200,129,166,39,9,24,186,57,18,148,79,172,5,2,170,238,69,
11556 220,137,10,72,145,162,39,9,24,186,57,18,148,79,176,5,2,186,238,69,124,150,
11557 27,48,95,132,140,93,28,137,74,39,218,2,129,101,119,34,158,79,15,39,9,24,
11558 186,57,18,148,79,184,5,2,218,238,69,29,164,80,78,198,46,142,68,165,16,64,
11559 28,24,61,73,25,33,205,128,1,167,166,128,0,0,0,1,108,242,151,15,39,8,34,26,
11560 87,97,200,3,0,167,129,32,8,194,195,16,6,84,55,10,60,3,35,69,132,30,1,140,
11561 130,193,143,1,196,230,60,2,158,8,131,153,64,115,42,46,191,176,8,194,246,0,
11562 80,5,220,193,95,6,234,5,100,225,35,23,71,35,6,228,140,93,29,180,55,108,145,
11563 139,163,182,112,52,107,67,76,56,3,153,132,20,28,76,156,89,26,105,158,62,0,
11564 0,42,193,2,201,104,17,41,34,156,204,176,160,226,100,226,200,211,76,241,240,
11565 0,1,86,2,131,137,147,142,41,100,73,199,192,0,5,96,6,13,10,82,70,62,0,0,42,
11566 130,88,115,18,124,67,103,177,69,49,129,6,36,249,68,54,123,20,82,216,65,137,
11567 62,33,179,209,214,162,152,208,147,18,124,162,27,61,29,106,41,112,32,196,
11568 159,16,217,233,233,81,76,112,73,137,62,81,13,158,158,149,20,186,20,98,79,
11569 133,91,129,61,61,42,41,120,40,196,159,10,183,2,122,218,148,82,248,60,137,
11570 62,33,179,216,166,216,192,137,18,124,162,27,61,138,109,108,34,68,159,16,
11571 217,232,235,83,108,104,76,137,62,81,13,158,142,181,54,184,17,34,79,136,108,
11572 244,244,169,182,56,38,68,159,40,134,207,79,74,155,93,10,145,39,194,173,192,
11573 158,158,149,54,188,21,34,79,133,91,129,61,109,74,109,125,155,51,136,71,161,
11574 196,201,45,167,146,59,68,89,24,70,206,0,0,7,129,248,0,0,0,1,155,51,168,71,
11575 161,196,201,45,167,146,59,68,89,24,70,206,0,0,7,129,248,0,0,0,1,155,51,200,
11576 71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,7,129,248,0,0,0,1,155,51,
11577 232,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,2,0,0,0,0,1,155,52,
11578 8,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,2,0,0,0,0,1,155,52,40,
11579 71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,155,52,72,
11580 71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,155,52,
11581 104,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,155,
11582 52,136,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,1,2,0,0,0,0,1,135,
11583 52,166,32,76,72,1,246,136,235,103,177,69,0,136,144,3,226,27,61,138,41,44,
11584 50,36,0,251,68,117,179,209,214,234,201,69,16,50,36,0,251,68,117,179,209,
11585 214,232,73,69,34,5,196,128,31,16,217,232,235,117,100,162,147,2,226,64,15,
11586 136,108,244,117,186,18,81,74,129,145,32,7,218,35,173,158,158,151,86,74,40,
11587 161,145,32,7,218,35,173,158,158,151,66,74,41,20,46,36,0,248,134,207,79,75,
11588 171,37,20,154,23,18,0,124,67,103,167,165,208,146,138,85,11,137,0,62,21,110,
11589 4,250,178,81,70,11,137,0,62,21,110,4,250,18,81,72,193,145,32,7,193,186,129,
11590 89,58,178,81,71,12,137,0,62,13,212,10,201,208,146,138,71,10,137,0,62,209,
11591 29,108,250,178,81,104,1,81,32,7,218,35,173,159,66,74,45,32,38,36,0,248,134,
11592 207,171,37,22,160,19,18,0,124,67,103,208,146,139,88,10,180,81,50,118,136,
11593 235,103,177,77,128,155,69,19,39,16,217,236,83,105,97,182,138,38,78,209,29,
11594 108,244,117,186,178,83,100,13,180,81,50,118,136,235,103,163,173,208,146,
11595 155,68,12,180,81,50,113,13,158,142,183,86,74,109,48,50,209,68,201,196,54,
11596 122,58,221,9,41,181,64,219,69,19,39,104,142,182,122,122,93,89,41,178,134,
11597 218,40,153,59,68,117,179,211,210,232,73,77,162,134,90,40,153,56,134,207,79,
11598 75,171,37,54,154,25,104,162,100,226,27,61,61,46,132,148,218,168,101,162,
11599 137,147,133,91,129,62,172,148,217,131,45,20,76,156,42,220,9,244,36,166,209,
11600 131,109,20,76,156,27,168,21,147,171,37,54,112,219,69,19,39,6,234,5,100,232,
11601 73,77,163,133,218,40,153,59,68,117,179,234,201,78,32,5,218,40,153,59,68,
11602 117,179,232,73,78,36,5,90,40,153,56,134,207,171,37,56,160,21,104,162,100,
11603 226,27,62,132,148,226,195,95,182,97,176,218,128,8,84,45,123,38,1,137,10,1,
11604 114,160,64,56,156,199,130,36,160,72,8,39,63,27,24,1,100,180,8,148,146,0,45,
11605 162,137,147,111,2,8,4,16,7,8,96,120,72,1,87,224,168,13,42,226,145,97,58,
11606 182,232,232,64,177,107,2,64,22,85,181,187,7,213,183,74,2,17,119,49,255,121,
11607 207,215,240,94,173,198,210,36,4,113,95,115,255,232,34,182,80,221,91,141,
11608 163,160,72,15,121,123,103,225,220,164,194,160,186,244,64,251,33,9,64,24,45,
11609 68,84,15,217,66,51,209,218,210,129,61,65,204,127,154,118,254,204,23,178,
11610 132,103,165,2,122,131,216,255,52,237,253,154,168,48,6,90,130,1,0,39,75,80,
11611 72,8,9,33,186,130,80,64,76,13,212,19,2,130,96,110,150,173,0,65,6,51,212,20,
11612 128,65,17,11,212,19,130,137,121,211,210,209,144,6,39,75,80,80,0,201,119,
11613 234,10,8,41,86,231,71,80,80,129,79,135,186,122,69,224,34,25,69,233,80,3,91,
11614 141,168,40,96,139,113,180,181,5,36,21,110,54,142,134,160,165,1,176,23,211,
11615 47,0,216,134,233,215,128,111,117,181,104,128,209,3,70,230,106,64,5,139,168,
11616 209,234,10,32,36,144,102,234,136,3,146,27,168,40,160,146,132,103,168,40,
11617 192,115,3,117,5,28,22,113,163,69,168,41,103,1,66,188,17,145,52,40,4,202,
11618 113,67,76,130,227,68,194,13,240,108,0,0,83,96,0,2,161,0,104,146,84,97,48,0,
11619 1,78,192,56,169,24,145,179,192,0,5,48,8,56,16,32,128,56,18,52,125,166,86,
11620 147,182,140,28,50,21,13,39,31,23,60,145,158,56,140,141,47,113,6,155,186,
11621 188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,197,68,
11622 14,49,39,199,197,211,116,240,242,113,197,230,18,180,253,228,3,17,46,18,243,
11623 35,100,128,172,156,114,70,163,146,76,34,248,146,164,108,248,75,204,141,146,
11624 28,217,114,137,27,78,251,241,173,234,162,160,225,1,3,34,92,170,9,105,164,
11625 32,225,64,131,155,1,193,133,7,19,39,22,70,154,103,143,128,0,10,176,20,28,
11626 76,156,113,75,34,78,62,0,0,43,0,48,104,82,146,49,240,0,1,84,11,180,192,0,5,
11627 114,1,18,160,65,24,131,20,145,25,172,48,132,122,28,76,146,218,121,35,180,
11628 69,145,132,108,224,0,0,120,31,128,0,0,0,25,172,56,132,122,28,76,146,218,
11629 121,35,180,69,145,132,108,224,0,0,120,31,128,0,0,0,40,160,45,110,23,30,176,
11630 33,184,0,0,175,32,29,235,2,27,199,23,0,0,22,4,51,88,129,8,244,56,153,37,
11631 180,242,71,104,139,35,8,217,192,0,0,240,63,0,0,0,0,51,88,145,8,244,56,153,
11632 37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,88,161,8,244,56,153,
11633 37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,88,177,8,244,56,153,
11634 37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,88,193,8,244,56,
11635 153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,88,209,8,244,
11636 56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,88,225,8,
11637 244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,32,64,0,0,0,0,32,227,194,
11638 0,97,57,162,4,245,232,5,34,92,35,68,225,161,166,218,16,16,137,112,52,41,73,
11639 29,153,1,65,196,201,197,145,166,153,245,200,3,137,204,120,34,74,8,200,58,
11640 112,28,211,32,130,52,78,26,26,110,248,0,0,164,4,12,70,137,195,39,252,73,
11641 240,117,32,57,168,97,4,104,156,52,52,221,255,160,20,160,152,23,223,250,32,
11642 148,25,174,137,58,23,51,191,244,84,12,50,9,195,39,240,81,238,2,3,107,173,
11643 214,3,192,
11644 };
11645 #else
11646 #error invalid endianness defines
11647 #endif
11648 #endif  /* DUK_USE_ROM_OBJECTS */
11649 
11650 /* automatic undefs */
11651 #undef DUK__REFCINIT
11652 #line 1 "duk_error_macros.c"
11653 /*
11654  *  Error and fatal handling.
11655  */
11656 
11657 /* #include duk_internal.h -> already included */
11658 
11659 #define DUK__ERRFMT_BUFSIZE  256  /* size for formatting buffers */
11660 
11661 #if defined(DUK_USE_VERBOSE_ERRORS)
11662 
duk_err_handle_error_fmt(duk_hthread * thr,const char * filename,duk_uint_t line_and_code,const char * fmt,...)11663 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, ...) {
11664 	va_list ap;
11665 	char msg[DUK__ERRFMT_BUFSIZE];
11666 	va_start(ap, fmt);
11667 	(void) DUK_VSNPRINTF(msg, sizeof(msg), fmt, ap);
11668 	msg[sizeof(msg) - 1] = (char) 0;
11669 	duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
11670 	va_end(ap);  /* dead code, but ensures portability (see Linux man page notes) */
11671 }
11672 
duk_err_handle_error(duk_hthread * thr,const char * filename,duk_uint_t line_and_code,const char * msg)11673 DUK_INTERNAL DUK_COLD void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg) {
11674 	duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
11675 }
11676 
11677 #else  /* DUK_USE_VERBOSE_ERRORS */
11678 
duk_err_handle_error(duk_hthread * thr,duk_errcode_t code)11679 DUK_INTERNAL DUK_COLD void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code) {
11680 	duk_err_create_and_throw(thr, code);
11681 }
11682 
11683 #endif  /* DUK_USE_VERBOSE_ERRORS */
11684 
11685 /*
11686  *  Error throwing helpers
11687  */
11688 
11689 #if defined(DUK_USE_VERBOSE_ERRORS)
11690 #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)11691 DUK_INTERNAL DUK_COLD void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name) {
11692 	DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
11693 	                   expect_name, duk_get_type_name(thr, idx), (long) idx);
11694 }
11695 #else
duk_err_require_type_index(duk_hthread * thr,const char * filename,duk_int_t linenumber,duk_idx_t idx,const char * expect_name)11696 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) {
11697 	DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
11698 	                   expect_name, duk_push_string_readable(thr, idx), (long) idx);
11699 }
11700 #endif
duk_err_error_internal(duk_hthread * thr,const char * filename,duk_int_t linenumber)11701 DUK_INTERNAL DUK_COLD void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11702 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, DUK_STR_INTERNAL_ERROR);
11703 }
duk_err_error_alloc_failed(duk_hthread * thr,const char * filename,duk_int_t linenumber)11704 DUK_INTERNAL DUK_COLD void duk_err_error_alloc_failed(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11705 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, DUK_STR_ALLOC_FAILED);
11706 }
duk_err_error(duk_hthread * thr,const char * filename,duk_int_t linenumber,const char * message)11707 DUK_INTERNAL DUK_COLD void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
11708 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, message);
11709 }
duk_err_range(duk_hthread * thr,const char * filename,duk_int_t linenumber,const char * message)11710 DUK_INTERNAL DUK_COLD void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
11711 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, message);
11712 }
duk_err_range_index(duk_hthread * thr,const char * filename,duk_int_t linenumber,duk_idx_t idx)11713 DUK_INTERNAL DUK_COLD void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx) {
11714 	DUK_ERROR_RAW_FMT1(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, "invalid stack index %ld", (long) (idx));
11715 }
duk_err_range_push_beyond(duk_hthread * thr,const char * filename,duk_int_t linenumber)11716 DUK_INTERNAL DUK_COLD void duk_err_range_push_beyond(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11717 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
11718 }
duk_err_type_invalid_args(duk_hthread * thr,const char * filename,duk_int_t linenumber)11719 DUK_INTERNAL DUK_COLD void duk_err_type_invalid_args(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11720 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_ARGS);
11721 }
duk_err_type_invalid_state(duk_hthread * thr,const char * filename,duk_int_t linenumber)11722 DUK_INTERNAL DUK_COLD void duk_err_type_invalid_state(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11723 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_STATE);
11724 }
duk_err_type_invalid_trap_result(duk_hthread * thr,const char * filename,duk_int_t linenumber)11725 DUK_INTERNAL DUK_COLD void duk_err_type_invalid_trap_result(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11726 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_TRAP_RESULT);
11727 }
11728 #else
11729 /* The file/line arguments are NULL and 0, they're ignored by DUK_ERROR_RAW()
11730  * when non-verbose errors are used.
11731  */
11732 
11733 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)11734 DUK_LOCAL void duk__err_shared(duk_hthread *thr, duk_errcode_t code) {
11735 	DUK_ERROR_RAW(thr, NULL, 0, code, NULL);
11736 }
duk_err_error(duk_hthread * thr)11737 DUK_INTERNAL DUK_COLD void duk_err_error(duk_hthread *thr) {
11738 	duk__err_shared(thr, DUK_ERR_ERROR);
11739 }
duk_err_range(duk_hthread * thr)11740 DUK_INTERNAL DUK_COLD void duk_err_range(duk_hthread *thr) {
11741 	duk__err_shared(thr, DUK_ERR_RANGE_ERROR);
11742 }
duk_err_eval(duk_hthread * thr)11743 DUK_INTERNAL DUK_COLD void duk_err_eval(duk_hthread *thr) {
11744 	duk__err_shared(thr, DUK_ERR_EVAL_ERROR);
11745 }
duk_err_reference(duk_hthread * thr)11746 DUK_INTERNAL DUK_COLD void duk_err_reference(duk_hthread *thr) {
11747 	duk__err_shared(thr, DUK_ERR_REFERENCE_ERROR);
11748 }
duk_err_syntax(duk_hthread * thr)11749 DUK_INTERNAL DUK_COLD void duk_err_syntax(duk_hthread *thr) {
11750 	duk__err_shared(thr, DUK_ERR_SYNTAX_ERROR);
11751 }
duk_err_type(duk_hthread * thr)11752 DUK_INTERNAL DUK_COLD void duk_err_type(duk_hthread *thr) {
11753 	duk__err_shared(thr, DUK_ERR_TYPE_ERROR);
11754 }
duk_err_uri(duk_hthread * thr)11755 DUK_INTERNAL DUK_COLD void duk_err_uri(duk_hthread *thr) {
11756 	duk__err_shared(thr, DUK_ERR_URI_ERROR);
11757 }
11758 #endif
11759 
11760 /*
11761  *  Default fatal error handler
11762  */
11763 
duk_default_fatal_handler(void * udata,const char * msg)11764 DUK_INTERNAL DUK_COLD void duk_default_fatal_handler(void *udata, const char *msg) {
11765 	DUK_UNREF(udata);
11766 	DUK_UNREF(msg);
11767 
11768 	msg = msg ? msg : "NULL";
11769 
11770 #if defined(DUK_USE_FATAL_HANDLER)
11771 	/* duk_config.h provided a custom default fatal handler. */
11772 	DUK_D(DUK_DPRINT("custom default fatal error handler called: %s", msg));
11773 	DUK_USE_FATAL_HANDLER(udata, msg);
11774 #elif defined(DUK_USE_CPP_EXCEPTIONS)
11775 	/* With C++ use a duk_fatal_exception which user code can catch in
11776 	 * a natural way.
11777 	 */
11778 	DUK_D(DUK_DPRINT("built-in default C++ fatal error handler called: %s", msg));
11779 	throw duk_fatal_exception(msg);
11780 #else
11781 	/* Default behavior is to abort() on error.  There's no printout
11782 	 * which makes this awkward, so it's always recommended to use an
11783 	 * explicit fatal error handler.
11784 	 *
11785 	 * ====================================================================
11786 	 * NOTE: If you are seeing this, you are most likely dealing with an
11787 	 * uncaught error.  You should provide a fatal error handler in Duktape
11788 	 * heap creation, and should consider using a protected call as your
11789 	 * first call into an empty Duktape context to properly handle errors.
11790 	 * See:
11791 	 *   - http://duktape.org/guide.html#error-handling
11792 	 *   - http://wiki.duktape.org/HowtoFatalErrors.html
11793 	 *   - http://duktape.org/api.html#taglist-protected
11794 	 * ====================================================================
11795 	 */
11796 	DUK_D(DUK_DPRINT("built-in default fatal error handler called: %s", msg));
11797 	DUK_ABORT();
11798 #endif
11799 
11800 	DUK_D(DUK_DPRINT("fatal error handler returned, enter forever loop"));
11801 	for (;;) {
11802 		/* Loop forever to ensure we don't return. */
11803 	}
11804 }
11805 
11806 /* automatic undefs */
11807 #undef DUK__ERRFMT_BUFSIZE
11808 #line 1 "duk_unicode_support.c"
11809 /*
11810  *  Various Unicode help functions for character classification predicates,
11811  *  case conversion, decoding, etc.
11812  */
11813 
11814 /* #include duk_internal.h -> already included */
11815 
11816 /*
11817  *  Fast path tables
11818  */
11819 
11820 #if defined(DUK_USE_IDCHAR_FASTPATH)
11821 DUK_INTERNAL const duk_int8_t duk_is_idchar_tab[128] = {
11822 	/* 0: not IdentifierStart or IdentifierPart
11823 	 * 1: IdentifierStart and IdentifierPart
11824 	 * -1: IdentifierPart only
11825 	 */
11826 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x00...0x0f */
11827 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x10...0x1f */
11828 	0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x20...0x2f */
11829 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,  0,  0,  0,  0,  0,   /* 0x30...0x3f */
11830 	0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,   /* 0x40...0x4f */
11831 	1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  1,   /* 0x50...0x5f */
11832 	0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,   /* 0x60...0x6f */
11833 	1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0    /* 0x70...0x7f */
11834 };
11835 #endif
11836 
11837 /*
11838  *  XUTF-8 and CESU-8 encoding/decoding
11839  */
11840 
duk_unicode_get_xutf8_length(duk_ucodepoint_t cp)11841 DUK_INTERNAL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp) {
11842 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
11843 	if (x < 0x80UL) {
11844 		/* 7 bits */
11845 		return 1;
11846 	} else if (x < 0x800UL) {
11847 		/* 11 bits */
11848 		return 2;
11849 	} else if (x < 0x10000UL) {
11850 		/* 16 bits */
11851 		return 3;
11852 	} else if (x < 0x200000UL) {
11853 		/* 21 bits */
11854 		return 4;
11855 	} else if (x < 0x4000000UL) {
11856 		/* 26 bits */
11857 		return 5;
11858 	} else if (x < (duk_ucodepoint_t) 0x80000000UL) {
11859 		/* 31 bits */
11860 		return 6;
11861 	} else {
11862 		/* 36 bits */
11863 		return 7;
11864 	}
11865 }
11866 
11867 #if defined(DUK_USE_ASSERTIONS)
duk_unicode_get_cesu8_length(duk_ucodepoint_t cp)11868 DUK_INTERNAL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp) {
11869 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
11870 	if (x < 0x80UL) {
11871 		/* 7 bits */
11872 		return 1;
11873 	} else if (x < 0x800UL) {
11874 		/* 11 bits */
11875 		return 2;
11876 	} else if (x < 0x10000UL) {
11877 		/* 16 bits */
11878 		return 3;
11879 	} else {
11880 		/* Encoded as surrogate pair, each encoding to 3 bytes for
11881 		 * 6 bytes total.  Codepoints above U+10FFFF encode as 6 bytes
11882 		 * too, see duk_unicode_encode_cesu8().
11883 		  */
11884 		return 3 + 3;
11885 	}
11886 }
11887 #endif  /* DUK_USE_ASSERTIONS */
11888 
11889 DUK_INTERNAL const duk_uint8_t duk_unicode_xutf8_markers[7] = {
11890 	0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe
11891 };
11892 
11893 /* Encode to extended UTF-8; 'out' must have space for at least
11894  * DUK_UNICODE_MAX_XUTF8_LENGTH bytes.  Allows encoding of any
11895  * 32-bit (unsigned) codepoint.
11896  */
duk_unicode_encode_xutf8(duk_ucodepoint_t cp,duk_uint8_t * out)11897 DUK_INTERNAL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out) {
11898 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
11899 	duk_small_int_t len;
11900 	duk_uint8_t marker;
11901 	duk_small_int_t i;
11902 
11903 	len = duk_unicode_get_xutf8_length(cp);
11904 	DUK_ASSERT(len > 0);
11905 
11906 	marker = duk_unicode_xutf8_markers[len - 1];  /* 64-bit OK because always >= 0 */
11907 
11908 	i = len;
11909 	DUK_ASSERT(i > 0);
11910 	do {
11911 		i--;
11912 		if (i > 0) {
11913 			out[i] = (duk_uint8_t) (0x80 + (x & 0x3f));
11914 			x >>= 6;
11915 		} else {
11916 			/* Note: masking of 'x' is not necessary because of
11917 			 * range check and shifting -> no bits overlapping
11918 			 * the marker should be set.
11919 			 */
11920 			out[0] = (duk_uint8_t) (marker + x);
11921 		}
11922 	} while (i > 0);
11923 
11924 	return len;
11925 }
11926 
11927 /* Encode to CESU-8; 'out' must have space for at least
11928  * DUK_UNICODE_MAX_CESU8_LENGTH bytes; codepoints above U+10FFFF
11929  * will encode to garbage but won't overwrite the output buffer.
11930  */
duk_unicode_encode_cesu8(duk_ucodepoint_t cp,duk_uint8_t * out)11931 DUK_INTERNAL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out) {
11932 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
11933 	duk_small_int_t len;
11934 
11935 	if (x < 0x80UL) {
11936 		out[0] = (duk_uint8_t) x;
11937 		len = 1;
11938 	} else if (x < 0x800UL) {
11939 		out[0] = (duk_uint8_t) (0xc0 + ((x >> 6) & 0x1f));
11940 		out[1] = (duk_uint8_t) (0x80 + (x & 0x3f));
11941 		len = 2;
11942 	} else if (x < 0x10000UL) {
11943 		/* surrogate pairs get encoded here */
11944 		out[0] = (duk_uint8_t) (0xe0 + ((x >> 12) & 0x0f));
11945 		out[1] = (duk_uint8_t) (0x80 + ((x >> 6) & 0x3f));
11946 		out[2] = (duk_uint8_t) (0x80 + (x & 0x3f));
11947 		len = 3;
11948 	} else {
11949 		/*
11950 		 *  Unicode codepoints above U+FFFF are encoded as surrogate
11951 		 *  pairs here.  This ensures that all CESU-8 codepoints are
11952 		 *  16-bit values as expected in ECMAScript.  The surrogate
11953 		 *  pairs always get a 3-byte encoding (each) in CESU-8.
11954 		 *  See: http://en.wikipedia.org/wiki/Surrogate_pair
11955 		 *
11956 		 *  20-bit codepoint, 10 bits (A and B) per surrogate pair:
11957 		 *
11958 		 *    x = 0b00000000 0000AAAA AAAAAABB BBBBBBBB
11959 		 *  sp1 = 0b110110AA AAAAAAAA  (0xd800 + ((x >> 10) & 0x3ff))
11960 		 *  sp2 = 0b110111BB BBBBBBBB  (0xdc00 + (x & 0x3ff))
11961 		 *
11962 		 *  Encoded into CESU-8:
11963 		 *
11964 		 *  sp1 -> 0b11101101  (0xe0 + ((sp1 >> 12) & 0x0f))
11965 		 *      -> 0b1010AAAA  (0x80 + ((sp1 >> 6) & 0x3f))
11966 		 *      -> 0b10AAAAAA  (0x80 + (sp1 & 0x3f))
11967 		 *  sp2 -> 0b11101101  (0xe0 + ((sp2 >> 12) & 0x0f))
11968 		 *      -> 0b1011BBBB  (0x80 + ((sp2 >> 6) & 0x3f))
11969 		 *      -> 0b10BBBBBB  (0x80 + (sp2 & 0x3f))
11970 		 *
11971 		 *  Note that 0x10000 must be subtracted first.  The code below
11972 		 *  avoids the sp1, sp2 temporaries which saves around 20 bytes
11973 		 *  of code.
11974 		 */
11975 
11976 		x -= 0x10000UL;
11977 
11978 		out[0] = (duk_uint8_t) (0xed);
11979 		out[1] = (duk_uint8_t) (0xa0 + ((x >> 16) & 0x0f));
11980 		out[2] = (duk_uint8_t) (0x80 + ((x >> 10) & 0x3f));
11981 		out[3] = (duk_uint8_t) (0xed);
11982 		out[4] = (duk_uint8_t) (0xb0 + ((x >> 6) & 0x0f));
11983 		out[5] = (duk_uint8_t) (0x80 + (x & 0x3f));
11984 		len = 6;
11985 	}
11986 
11987 	return len;
11988 }
11989 
11990 /* 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)11991 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) {
11992 	const duk_uint8_t *p;
11993 	duk_uint32_t res;
11994 	duk_uint_fast8_t ch;
11995 	duk_small_int_t n;
11996 
11997 	DUK_UNREF(thr);
11998 
11999 	p = *ptr;
12000 	if (p < ptr_start || p >= ptr_end) {
12001 		goto fail;
12002 	}
12003 
12004 	/*
12005 	 *  UTF-8 decoder which accepts longer than standard byte sequences.
12006 	 *  This allows full 32-bit code points to be used.
12007 	 */
12008 
12009 	ch = (duk_uint_fast8_t) (*p++);
12010 	if (ch < 0x80) {
12011 		/* 0xxx xxxx   [7 bits] */
12012 		res = (duk_uint32_t) (ch & 0x7f);
12013 		n = 0;
12014 	} else if (ch < 0xc0) {
12015 		/* 10xx xxxx -> invalid */
12016 		goto fail;
12017 	} else if (ch < 0xe0) {
12018 		/* 110x xxxx   10xx xxxx   [11 bits] */
12019 		res = (duk_uint32_t) (ch & 0x1f);
12020 		n = 1;
12021 	} else if (ch < 0xf0) {
12022 		/* 1110 xxxx   10xx xxxx   10xx xxxx   [16 bits] */
12023 		res = (duk_uint32_t) (ch & 0x0f);
12024 		n = 2;
12025 	} else if (ch < 0xf8) {
12026 		/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx   [21 bits] */
12027 		res = (duk_uint32_t) (ch & 0x07);
12028 		n = 3;
12029 	} else if (ch < 0xfc) {
12030 		/* 1111 10xx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [26 bits] */
12031 		res = (duk_uint32_t) (ch & 0x03);
12032 		n = 4;
12033 	} else if (ch < 0xfe) {
12034 		/* 1111 110x   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [31 bits] */
12035 		res = (duk_uint32_t) (ch & 0x01);
12036 		n = 5;
12037 	} else if (ch < 0xff) {
12038 		/* 1111 1110   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [36 bits] */
12039 		res = (duk_uint32_t) (0);
12040 		n = 6;
12041 	} else {
12042 		/* 8-byte format could be:
12043 		 * 1111 1111   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [41 bits]
12044 		 *
12045 		 * However, this format would not have a zero bit following the
12046 		 * leading one bits and would not allow 0xFF to be used as an
12047 		 * "invalid xutf-8" marker for internal keys.  Further, 8-byte
12048 		 * encodings (up to 41 bit code points) are not currently needed.
12049 		 */
12050 		goto fail;
12051 	}
12052 
12053 	DUK_ASSERT(p >= ptr_start);  /* verified at beginning */
12054 	if (p + n > ptr_end) {
12055 		/* check pointer at end */
12056 		goto fail;
12057 	}
12058 
12059 	while (n > 0) {
12060 		DUK_ASSERT(p >= ptr_start && p < ptr_end);
12061 		ch = (duk_uint_fast8_t) (*p++);
12062 #if 0
12063 		if (ch & 0xc0 != 0x80) {
12064 			/* not a continuation byte */
12065 			p--;
12066 			*ptr = p;
12067 			*out_cp = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
12068 			return 1;
12069 		}
12070 #endif
12071 		res = (res << 6) + (duk_uint32_t) (ch & 0x3f);
12072 		n--;
12073 	}
12074 
12075 	*ptr = p;
12076 	*out_cp = res;
12077 	return 1;
12078 
12079  fail:
12080 	return 0;
12081 }
12082 
12083 /* 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)12084 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) {
12085 	duk_ucodepoint_t cp;
12086 
12087 	if (duk_unicode_decode_xutf8(thr, ptr, ptr_start, ptr_end, &cp)) {
12088 		return cp;
12089 	}
12090 	DUK_ERROR_INTERNAL(thr);
12091 	DUK_WO_NORETURN(return 0;);
12092 }
12093 
12094 /* Compute (extended) utf-8 length without codepoint encoding validation,
12095  * used for string interning.
12096  *
12097  * NOTE: This algorithm is performance critical, more so than string hashing
12098  * in some cases.  It is needed when interning a string and needs to scan
12099  * every byte of the string with no skipping.  Having an ASCII fast path
12100  * is useful if possible in the algorithm.  The current algorithms were
12101  * chosen from several variants, based on x64 gcc -O2 testing.  See:
12102  * https://github.com/svaarala/duktape/pull/422
12103  *
12104  * NOTE: must match tools/dukutil.py:duk_unicode_unvalidated_utf8_length().
12105  */
12106 
12107 #if defined(DUK_USE_PREFER_SIZE)
12108 /* Small variant; roughly 150 bytes smaller than the fast variant. */
duk_unicode_unvalidated_utf8_length(const duk_uint8_t * data,duk_size_t blen)12109 DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {
12110 	const duk_uint8_t *p;
12111 	const duk_uint8_t *p_end;
12112 	duk_size_t ncont;
12113 	duk_size_t clen;
12114 
12115 	p = data;
12116 	p_end = data + blen;
12117 	ncont = 0;
12118 	while (p != p_end) {
12119 		duk_uint8_t x;
12120 		x = *p++;
12121 		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
12122 			ncont++;
12123 		}
12124 	}
12125 
12126 	DUK_ASSERT(ncont <= blen);
12127 	clen = blen - ncont;
12128 	DUK_ASSERT(clen <= blen);
12129 	return clen;
12130 }
12131 #else  /* DUK_USE_PREFER_SIZE */
12132 /* This seems like a good overall approach.  Fast path for ASCII in 4 byte
12133  * blocks.
12134  */
duk_unicode_unvalidated_utf8_length(const duk_uint8_t * data,duk_size_t blen)12135 DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {
12136 	const duk_uint8_t *p;
12137 	const duk_uint8_t *p_end;
12138 	const duk_uint32_t *p32_end;
12139 	const duk_uint32_t *p32;
12140 	duk_size_t ncont;
12141 	duk_size_t clen;
12142 
12143 	ncont = 0;  /* number of continuation (non-initial) bytes in [0x80,0xbf] */
12144 	p = data;
12145 	p_end = data + blen;
12146 	if (blen < 16) {
12147 		goto skip_fastpath;
12148 	}
12149 
12150 	/* Align 'p' to 4; the input data may have arbitrary alignment.
12151 	 * End of string check not needed because blen >= 16.
12152 	 */
12153 	while (((duk_size_t) (const void *) p) & 0x03U) {
12154 		duk_uint8_t x;
12155 		x = *p++;
12156 		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
12157 			ncont++;
12158 		}
12159 	}
12160 
12161 	/* Full, aligned 4-byte reads. */
12162 	p32_end = (const duk_uint32_t *) (const void *) (p + ((duk_size_t) (p_end - p) & (duk_size_t) (~0x03)));
12163 	p32 = (const duk_uint32_t *) (const void *) p;
12164 	while (p32 != (const duk_uint32_t *) p32_end) {
12165 		duk_uint32_t x;
12166 		x = *p32++;
12167 		if (DUK_LIKELY((x & 0x80808080UL) == 0)) {
12168 			;  /* ASCII fast path */
12169 		} else {
12170 			/* Flip highest bit of each byte which changes
12171 			 * the bit pattern 10xxxxxx into 00xxxxxx which
12172 			 * allows an easy bit mask test.
12173 			 */
12174 			x ^= 0x80808080UL;
12175 			if (DUK_UNLIKELY(!(x & 0xc0000000UL))) {
12176 				ncont++;
12177 			}
12178 			if (DUK_UNLIKELY(!(x & 0x00c00000UL))) {
12179 				ncont++;
12180 			}
12181 			if (DUK_UNLIKELY(!(x & 0x0000c000UL))) {
12182 				ncont++;
12183 			}
12184 			if (DUK_UNLIKELY(!(x & 0x000000c0UL))) {
12185 				ncont++;
12186 			}
12187 		}
12188 	}
12189 	p = (const duk_uint8_t *) p32;
12190 	/* Fall through to handle the rest. */
12191 
12192  skip_fastpath:
12193 	while (p != p_end) {
12194 		duk_uint8_t x;
12195 		x = *p++;
12196 		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
12197 			ncont++;
12198 		}
12199 	}
12200 
12201 	DUK_ASSERT(ncont <= blen);
12202 	clen = blen - ncont;
12203 	DUK_ASSERT(clen <= blen);
12204 	return clen;
12205 }
12206 #endif  /* DUK_USE_PREFER_SIZE */
12207 
12208 /*
12209  *  Unicode range matcher
12210  *
12211  *  Matches a codepoint against a packed bitstream of character ranges.
12212  *  Used for slow path Unicode matching.
12213  */
12214 
12215 /* Must match tools/extract_chars.py, generate_match_table3(). */
duk__uni_decode_value(duk_bitdecoder_ctx * bd_ctx)12216 DUK_LOCAL duk_uint32_t duk__uni_decode_value(duk_bitdecoder_ctx *bd_ctx) {
12217 	duk_uint32_t t;
12218 
12219 	t = (duk_uint32_t) duk_bd_decode(bd_ctx, 4);
12220 	if (t <= 0x0eU) {
12221 		return t;
12222 	}
12223 	t = (duk_uint32_t) duk_bd_decode(bd_ctx, 8);
12224 	if (t <= 0xfdU) {
12225 		return t + 0x0f;
12226 	}
12227 	if (t == 0xfeU) {
12228 		t = (duk_uint32_t) duk_bd_decode(bd_ctx, 12);
12229 		return t + 0x0fU + 0xfeU;
12230 	} else {
12231 		t = (duk_uint32_t) duk_bd_decode(bd_ctx, 24);
12232 		return t + 0x0fU + 0xfeU + 0x1000UL;
12233 	}
12234 }
12235 
duk__uni_range_match(const duk_uint8_t * unitab,duk_size_t unilen,duk_codepoint_t cp)12236 DUK_LOCAL duk_small_int_t duk__uni_range_match(const duk_uint8_t *unitab, duk_size_t unilen, duk_codepoint_t cp) {
12237 	duk_bitdecoder_ctx bd_ctx;
12238 	duk_codepoint_t prev_re;
12239 
12240 	duk_memzero(&bd_ctx, sizeof(bd_ctx));
12241 	bd_ctx.data = (const duk_uint8_t *) unitab;
12242 	bd_ctx.length = (duk_size_t) unilen;
12243 
12244 	prev_re = 0;
12245 	for (;;) {
12246 		duk_codepoint_t r1, r2;
12247 		r1 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
12248 		if (r1 == 0) {
12249 			break;
12250 		}
12251 		r2 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
12252 
12253 		r1 = prev_re + r1;
12254 		r2 = r1 + r2;
12255 		prev_re = r2;
12256 
12257 		/* [r1,r2] is the range */
12258 
12259 		DUK_DDD(DUK_DDDPRINT("duk__uni_range_match: cp=%06lx range=[0x%06lx,0x%06lx]",
12260 		                     (unsigned long) cp, (unsigned long) r1, (unsigned long) r2));
12261 		if (cp >= r1 && cp <= r2) {
12262 			return 1;
12263 		}
12264 	}
12265 
12266 	return 0;
12267 }
12268 
12269 /*
12270  *  "WhiteSpace" production check.
12271  */
12272 
duk_unicode_is_whitespace(duk_codepoint_t cp)12273 DUK_INTERNAL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp) {
12274 	/*
12275 	 *  E5 Section 7.2 specifies six characters specifically as
12276 	 *  white space:
12277 	 *
12278 	 *    0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULATION;;;;
12279 	 *    000B;<control>;Cc;0;S;;;;;N;LINE TABULATION;;;;
12280 	 *    000C;<control>;Cc;0;WS;;;;;N;FORM FEED (FF);;;;
12281 	 *    0020;SPACE;Zs;0;WS;;;;;N;;;;;
12282 	 *    00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
12283 	 *    FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;;
12284 	 *
12285 	 *  It also specifies any Unicode category 'Zs' characters as white
12286 	 *  space.  These can be extracted with the "tools/extract_chars.py" script.
12287 	 *  Current result:
12288 	 *
12289 	 *    RAW OUTPUT:
12290 	 *    ===========
12291 	 *    0020;SPACE;Zs;0;WS;;;;;N;;;;;
12292 	 *    00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
12293 	 *    1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;;
12294 	 *    180E;MONGOLIAN VOWEL SEPARATOR;Zs;0;WS;;;;;N;;;;;
12295 	 *    2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;;
12296 	 *    2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;;
12297 	 *    2002;EN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12298 	 *    2003;EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12299 	 *    2004;THREE-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12300 	 *    2005;FOUR-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12301 	 *    2006;SIX-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12302 	 *    2007;FIGURE SPACE;Zs;0;WS;<noBreak> 0020;;;;N;;;;;
12303 	 *    2008;PUNCTUATION SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12304 	 *    2009;THIN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12305 	 *    200A;HAIR SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12306 	 *    202F;NARROW NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;;;;;
12307 	 *    205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12308 	 *    3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;;
12309 	 *
12310 	 *    RANGES:
12311 	 *    =======
12312 	 *    0x0020
12313 	 *    0x00a0
12314 	 *    0x1680
12315 	 *    0x180e
12316 	 *    0x2000 ... 0x200a
12317 	 *    0x202f
12318 	 *    0x205f
12319 	 *    0x3000
12320 	 *
12321 	 *  A manual decoder (below) is probably most compact for this.
12322 	 */
12323 
12324 	duk_uint_fast8_t lo;
12325 	duk_uint_fast32_t hi;
12326 
12327 	/* cp == -1 (EOF) never matches and causes return value 0 */
12328 
12329 	lo = (duk_uint_fast8_t) (cp & 0xff);
12330 	hi = (duk_uint_fast32_t) (cp >> 8);  /* does not fit into an uchar */
12331 
12332 	if (hi == 0x0000UL) {
12333 		if (lo == 0x09U || lo == 0x0bU || lo == 0x0cU ||
12334 		    lo == 0x20U || lo == 0xa0U) {
12335 			return 1;
12336 		}
12337 	} else if (hi == 0x0020UL) {
12338 		if (lo <= 0x0aU || lo == 0x2fU || lo == 0x5fU) {
12339 			return 1;
12340 		}
12341 	} else if (cp == 0x1680L || cp == 0x180eL || cp == 0x3000L ||
12342 	           cp == 0xfeffL) {
12343 		return 1;
12344 	}
12345 
12346 	return 0;
12347 }
12348 
12349 /*
12350  *  "LineTerminator" production check.
12351  */
12352 
duk_unicode_is_line_terminator(duk_codepoint_t cp)12353 DUK_INTERNAL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp) {
12354 	/*
12355 	 *  E5 Section 7.3
12356 	 *
12357 	 *  A LineTerminatorSequence essentially merges <CR> <LF> sequences
12358 	 *  into a single line terminator.  This must be handled by the caller.
12359 	 */
12360 
12361 	if (cp == 0x000aL || cp == 0x000dL || cp == 0x2028L ||
12362 	    cp == 0x2029L) {
12363 		return 1;
12364 	}
12365 
12366 	return 0;
12367 }
12368 
12369 /*
12370  *  "IdentifierStart" production check.
12371  */
12372 
duk_unicode_is_identifier_start(duk_codepoint_t cp)12373 DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp) {
12374 	/*
12375 	 *  E5 Section 7.6:
12376 	 *
12377 	 *    IdentifierStart:
12378 	 *      UnicodeLetter
12379 	 *      $
12380 	 *      _
12381 	 *      \ UnicodeEscapeSequence
12382 	 *
12383 	 *  IdentifierStart production has one multi-character production:
12384 	 *
12385 	 *    \ UnicodeEscapeSequence
12386 	 *
12387 	 *  The '\' character is -not- matched by this function.  Rather, the caller
12388 	 *  should decode the escape and then call this function to check whether the
12389 	 *  decoded character is acceptable (see discussion in E5 Section 7.6).
12390 	 *
12391 	 *  The "UnicodeLetter" alternative of the production allows letters
12392 	 *  from various Unicode categories.  These can be extracted with the
12393 	 *  "tools/extract_chars.py" script.
12394 	 *
12395 	 *  Because the result has hundreds of Unicode codepoint ranges, matching
12396 	 *  for any values >= 0x80 are done using a very slow range-by-range scan
12397 	 *  and a packed range format.
12398 	 *
12399 	 *  The ASCII portion (codepoints 0x00 ... 0x7f) is fast-pathed below because
12400 	 *  it matters the most.  The ASCII related ranges of IdentifierStart are:
12401 	 *
12402 	 *    0x0041 ... 0x005a     ['A' ... 'Z']
12403 	 *    0x0061 ... 0x007a     ['a' ... 'z']
12404 	 *    0x0024                ['$']
12405 	 *    0x005f                ['_']
12406 	 */
12407 
12408 	/* ASCII (and EOF) fast path -- quick accept and reject */
12409 	if (cp <= 0x7fL) {
12410 #if defined(DUK_USE_IDCHAR_FASTPATH)
12411 		return (cp >= 0) && (duk_is_idchar_tab[cp] > 0);
12412 #else
12413 		if ((cp >= 'a' && cp <= 'z') ||
12414 		    (cp >= 'A' && cp <= 'Z') ||
12415 		    cp == '_' || cp == '$') {
12416 			return 1;
12417 		}
12418 		return 0;
12419 #endif
12420 	}
12421 
12422 	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
12423 
12424 #if defined(DUK_USE_SOURCE_NONBMP)
12425 	if (duk__uni_range_match(duk_unicode_ids_noa,
12426 	                         (duk_size_t) sizeof(duk_unicode_ids_noa),
12427 	                         (duk_codepoint_t) cp)) {
12428 		return 1;
12429 	}
12430 	return 0;
12431 #else
12432 	if (cp < 0x10000L) {
12433 		if (duk__uni_range_match(duk_unicode_ids_noabmp,
12434 		                         sizeof(duk_unicode_ids_noabmp),
12435 		                         (duk_codepoint_t) cp)) {
12436 			return 1;
12437 		}
12438 		return 0;
12439 	} else {
12440 		/* without explicit non-BMP support, assume non-BMP characters
12441 		 * are always accepted as identifier characters.
12442 		 */
12443 		return 1;
12444 	}
12445 #endif
12446 }
12447 
12448 /*
12449  *  "IdentifierPart" production check.
12450  */
12451 
duk_unicode_is_identifier_part(duk_codepoint_t cp)12452 DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp) {
12453 	/*
12454 	 *  E5 Section 7.6:
12455 	 *
12456 	 *    IdentifierPart:
12457 	 *      IdentifierStart
12458 	 *      UnicodeCombiningMark
12459 	 *      UnicodeDigit
12460 	 *      UnicodeConnectorPunctuation
12461 	 *      <ZWNJ>  [U+200C]
12462 	 *      <ZWJ>   [U+200D]
12463 	 *
12464 	 *  IdentifierPart production has one multi-character production
12465 	 *  as part of its IdentifierStart alternative.  The '\' character
12466 	 *  of an escape sequence is not matched here, see discussion in
12467 	 *  duk_unicode_is_identifier_start().
12468 	 *
12469 	 *  To match non-ASCII characters (codepoints >= 0x80), a very slow
12470 	 *  linear range-by-range scan is used.  The codepoint is first compared
12471 	 *  to the IdentifierStart ranges, and if it doesn't match, then to a
12472 	 *  set consisting of code points in IdentifierPart but not in
12473 	 *  IdentifierStart.  This is done to keep the unicode range data small,
12474 	 *  at the expense of speed.
12475 	 *
12476 	 *  The ASCII fast path consists of:
12477 	 *
12478 	 *    0x0030 ... 0x0039     ['0' ... '9', UnicodeDigit]
12479 	 *    0x0041 ... 0x005a     ['A' ... 'Z', IdentifierStart]
12480 	 *    0x0061 ... 0x007a     ['a' ... 'z', IdentifierStart]
12481 	 *    0x0024                ['$', IdentifierStart]
12482 	 *    0x005f                ['_', IdentifierStart and
12483 	 *                                UnicodeConnectorPunctuation]
12484 	 *
12485 	 *  UnicodeCombiningMark has no code points <= 0x7f.
12486 	 *
12487 	 *  The matching code reuses the "identifier start" tables, and then
12488 	 *  consults a separate range set for characters in "identifier part"
12489 	 *  but not in "identifier start".  These can be extracted with the
12490 	 *  "tools/extract_chars.py" script.
12491 	 *
12492 	 *  UnicodeCombiningMark -> categories Mn, Mc
12493 	 *  UnicodeDigit -> categories Nd
12494 	 *  UnicodeConnectorPunctuation -> categories Pc
12495 	 */
12496 
12497 	/* ASCII (and EOF) fast path -- quick accept and reject */
12498 	if (cp <= 0x7fL) {
12499 #if defined(DUK_USE_IDCHAR_FASTPATH)
12500 		return (cp >= 0) && (duk_is_idchar_tab[cp] != 0);
12501 #else
12502 		if ((cp >= 'a' && cp <= 'z') ||
12503 		    (cp >= 'A' && cp <= 'Z') ||
12504 		    (cp >= '0' && cp <= '9') ||
12505 		    cp == '_' || cp == '$') {
12506 			return 1;
12507 		}
12508 		return 0;
12509 #endif
12510 	}
12511 
12512 	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
12513 
12514 #if defined(DUK_USE_SOURCE_NONBMP)
12515 	if (duk__uni_range_match(duk_unicode_ids_noa,
12516 	                         sizeof(duk_unicode_ids_noa),
12517 	                         (duk_codepoint_t) cp) ||
12518 	    duk__uni_range_match(duk_unicode_idp_m_ids_noa,
12519 	                         sizeof(duk_unicode_idp_m_ids_noa),
12520 	                         (duk_codepoint_t) cp)) {
12521 		return 1;
12522 	}
12523 	return 0;
12524 #else
12525 	if (cp < 0x10000L) {
12526 		if (duk__uni_range_match(duk_unicode_ids_noabmp,
12527 		                         sizeof(duk_unicode_ids_noabmp),
12528 		                         (duk_codepoint_t) cp) ||
12529 		    duk__uni_range_match(duk_unicode_idp_m_ids_noabmp,
12530 		                         sizeof(duk_unicode_idp_m_ids_noabmp),
12531 		                         (duk_codepoint_t) cp)) {
12532 			return 1;
12533 		}
12534 		return 0;
12535 	} else {
12536 		/* without explicit non-BMP support, assume non-BMP characters
12537 		 * are always accepted as identifier characters.
12538 		 */
12539 		return 1;
12540 	}
12541 #endif
12542 }
12543 
12544 /*
12545  *  Unicode letter check.
12546  */
12547 
duk_unicode_is_letter(duk_codepoint_t cp)12548 DUK_INTERNAL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp) {
12549 	/*
12550 	 *  Unicode letter is now taken to be the categories:
12551 	 *
12552 	 *    Lu, Ll, Lt, Lm, Lo
12553 	 *
12554 	 *  (Not sure if this is exactly correct.)
12555 	 *
12556 	 *  The ASCII fast path consists of:
12557 	 *
12558 	 *    0x0041 ... 0x005a     ['A' ... 'Z']
12559 	 *    0x0061 ... 0x007a     ['a' ... 'z']
12560 	 */
12561 
12562 	/* ASCII (and EOF) fast path -- quick accept and reject */
12563 	if (cp <= 0x7fL) {
12564 		if ((cp >= 'a' && cp <= 'z') ||
12565 		    (cp >= 'A' && cp <= 'Z')) {
12566 			return 1;
12567 		}
12568 		return 0;
12569 	}
12570 
12571 	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
12572 
12573 #if defined(DUK_USE_SOURCE_NONBMP)
12574 	if (duk__uni_range_match(duk_unicode_ids_noa,
12575 	                         sizeof(duk_unicode_ids_noa),
12576 	                         (duk_codepoint_t) cp) &&
12577 	    !duk__uni_range_match(duk_unicode_ids_m_let_noa,
12578 	                          sizeof(duk_unicode_ids_m_let_noa),
12579 	                          (duk_codepoint_t) cp)) {
12580 		return 1;
12581 	}
12582 	return 0;
12583 #else
12584 	if (cp < 0x10000L) {
12585 		if (duk__uni_range_match(duk_unicode_ids_noabmp,
12586 		                         sizeof(duk_unicode_ids_noabmp),
12587 		                         (duk_codepoint_t) cp) &&
12588 		    !duk__uni_range_match(duk_unicode_ids_m_let_noabmp,
12589 		                          sizeof(duk_unicode_ids_m_let_noabmp),
12590 		                          (duk_codepoint_t) cp)) {
12591 			return 1;
12592 		}
12593 		return 0;
12594 	} else {
12595 		/* without explicit non-BMP support, assume non-BMP characters
12596 		 * are always accepted as letters.
12597 		 */
12598 		return 1;
12599 	}
12600 #endif
12601 }
12602 
12603 /*
12604  *  Complex case conversion helper which decodes a bit-packed conversion
12605  *  control stream generated by tools/extract_caseconv.py.  The conversion
12606  *  is very slow because it runs through the conversion data in a linear
12607  *  fashion to save space (which is why ASCII characters have a special
12608  *  fast path before arriving here).
12609  *
12610  *  The particular bit counts etc have been determined experimentally to
12611  *  be small but still sufficient, and must match the Python script
12612  *  (tools/extract_caseconv.py).
12613  *
12614  *  The return value is the case converted codepoint or -1 if the conversion
12615  *  results in multiple characters (this is useful for regexp Canonicalization
12616  *  operation).  If 'buf' is not NULL, the result codepoint(s) are also
12617  *  appended to the hbuffer.
12618  *
12619  *  Context and locale specific rules must be checked before consulting
12620  *  this function.
12621  */
12622 
12623 DUK_LOCAL
duk__slow_case_conversion(duk_hthread * thr,duk_bufwriter_ctx * bw,duk_codepoint_t cp,duk_bitdecoder_ctx * bd_ctx)12624 duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr,
12625                                           duk_bufwriter_ctx *bw,
12626                                           duk_codepoint_t cp,
12627                                           duk_bitdecoder_ctx *bd_ctx) {
12628 	duk_small_int_t skip = 0;
12629 	duk_small_int_t n;
12630 	duk_small_int_t t;
12631 	duk_small_int_t count;
12632 	duk_codepoint_t tmp_cp;
12633 	duk_codepoint_t start_i;
12634 	duk_codepoint_t start_o;
12635 
12636 	DUK_ASSERT(bd_ctx != NULL);
12637 	DUK_UNREF(thr);
12638 
12639 	DUK_DDD(DUK_DDDPRINT("slow case conversion for codepoint: %ld", (long) cp));
12640 
12641 	/* range conversion with a "skip" */
12642 	DUK_DDD(DUK_DDDPRINT("checking ranges"));
12643 	for (;;) {
12644 		skip++;
12645 		n = (duk_small_int_t) duk_bd_decode(bd_ctx, 6);
12646 		if (n == 0x3f) {
12647 			/* end marker */
12648 			break;
12649 		}
12650 		DUK_DDD(DUK_DDDPRINT("skip=%ld, n=%ld", (long) skip, (long) n));
12651 
12652 		while (n--) {
12653 			start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12654 			start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12655 			count = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
12656 			DUK_DDD(DUK_DDDPRINT("range: start_i=%ld, start_o=%ld, count=%ld, skip=%ld",
12657 			                     (long) start_i, (long) start_o, (long) count, (long) skip));
12658 
12659 			if (cp >= start_i) {
12660 				tmp_cp = cp - start_i;  /* always >= 0 */
12661 				if (tmp_cp < (duk_codepoint_t) count * (duk_codepoint_t) skip &&
12662 				    (tmp_cp % (duk_codepoint_t) skip) == 0) {
12663 					DUK_DDD(DUK_DDDPRINT("range matches input codepoint"));
12664 					cp = start_o + tmp_cp;
12665 					goto single;
12666 				}
12667 			}
12668 		}
12669 	}
12670 
12671 	/* 1:1 conversion */
12672 	n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
12673 	DUK_DDD(DUK_DDDPRINT("checking 1:1 conversions (count %ld)", (long) n));
12674 	while (n--) {
12675 		start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12676 		start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12677 		DUK_DDD(DUK_DDDPRINT("1:1 conversion %ld -> %ld", (long) start_i, (long) start_o));
12678 		if (cp == start_i) {
12679 			DUK_DDD(DUK_DDDPRINT("1:1 matches input codepoint"));
12680 			cp = start_o;
12681 			goto single;
12682 		}
12683 	}
12684 
12685 	/* complex, multicharacter conversion */
12686 	n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
12687 	DUK_DDD(DUK_DDDPRINT("checking 1:n conversions (count %ld)", (long) n));
12688 	while (n--) {
12689 		start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12690 		t = (duk_small_int_t) duk_bd_decode(bd_ctx, 2);
12691 		DUK_DDD(DUK_DDDPRINT("1:n conversion %ld -> %ld chars", (long) start_i, (long) t));
12692 		if (cp == start_i) {
12693 			DUK_DDD(DUK_DDDPRINT("1:n matches input codepoint"));
12694 			if (bw != NULL) {
12695 				while (t--) {
12696 					tmp_cp = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12697 					DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) tmp_cp);
12698 				}
12699 			}
12700 			return -1;
12701 		} else {
12702 			while (t--) {
12703 				(void) duk_bd_decode(bd_ctx, 16);
12704 			}
12705 		}
12706 	}
12707 
12708 	/* default: no change */
12709 	DUK_DDD(DUK_DDDPRINT("no rule matches, output is same as input"));
12710 	/* fall through */
12711 
12712  single:
12713 	if (bw != NULL) {
12714 		DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);
12715 	}
12716 	return cp;
12717 }
12718 
12719 /*
12720  *  Case conversion helper, with context/local sensitivity.
12721  *  For proper case conversion, one needs to know the character
12722  *  and the preceding and following characters, as well as
12723  *  locale/language.
12724  */
12725 
12726 /* XXX: add 'language' argument when locale/language sensitive rule
12727  * support added.
12728  */
12729 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)12730 duk_codepoint_t duk__case_transform_helper(duk_hthread *thr,
12731                                            duk_bufwriter_ctx *bw,
12732                                            duk_codepoint_t cp,
12733                                            duk_codepoint_t prev,
12734                                            duk_codepoint_t next,
12735                                            duk_bool_t uppercase) {
12736 	duk_bitdecoder_ctx bd_ctx;
12737 
12738 	/* fast path for ASCII */
12739 	if (cp < 0x80L) {
12740 		/* XXX: there are language sensitive rules for the ASCII range.
12741 		 * If/when language/locale support is implemented, they need to
12742 		 * be implemented here for the fast path.  There are no context
12743 		 * sensitive rules for ASCII range.
12744 		 */
12745 
12746 		if (uppercase) {
12747 			if (cp >= 'a' && cp <= 'z') {
12748 				cp = cp - 'a' + 'A';
12749 			}
12750 		} else {
12751 			if (cp >= 'A' && cp <= 'Z') {
12752 				cp = cp - 'A' + 'a';
12753 			}
12754 		}
12755 
12756 		if (bw != NULL) {
12757 			DUK_BW_WRITE_RAW_U8(thr, bw, (duk_uint8_t) cp);
12758 		}
12759 		return cp;
12760 	}
12761 
12762 	/* context and locale specific rules which cannot currently be represented
12763 	 * in the caseconv bitstream: hardcoded rules in C
12764 	 */
12765 	if (uppercase) {
12766 		/* XXX: turkish / azeri */
12767 	} else {
12768 		/*
12769 		 *  Final sigma context specific rule.  This is a rather tricky
12770 		 *  rule and this handling is probably not 100% correct now.
12771 		 *  The rule is not locale/language specific so it is supported.
12772 		 */
12773 
12774 		if (cp == 0x03a3L &&    /* U+03A3 = GREEK CAPITAL LETTER SIGMA */
12775 		    duk_unicode_is_letter(prev) &&        /* prev exists and is not a letter */
12776 		    !duk_unicode_is_letter(next)) {       /* next does not exist or next is not a letter */
12777 			/* Capital sigma occurred at "end of word", lowercase to
12778 			 * U+03C2 = GREEK SMALL LETTER FINAL SIGMA.  Otherwise
12779 			 * fall through and let the normal rules lowercase it to
12780 			 * U+03C3 = GREEK SMALL LETTER SIGMA.
12781 			 */
12782 			cp = 0x03c2L;
12783 			goto singlechar;
12784 		}
12785 
12786 		/* XXX: lithuanian not implemented */
12787 		/* XXX: lithuanian, explicit dot rules */
12788 		/* XXX: turkish / azeri, lowercase rules */
12789 	}
12790 
12791 	/* 1:1 or special conversions, but not locale/context specific: script generated rules */
12792 	duk_memzero(&bd_ctx, sizeof(bd_ctx));
12793 	if (uppercase) {
12794 		bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_uc;
12795 		bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_uc);
12796 	} else {
12797 		bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_lc;
12798 		bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_lc);
12799 	}
12800 	return duk__slow_case_conversion(thr, bw, cp, &bd_ctx);
12801 
12802  singlechar:
12803 	if (bw != NULL) {
12804 		DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);
12805 	}
12806 	return cp;
12807 
12808  /* unused now, not needed until Turkish/Azeri */
12809 #if 0
12810  nochar:
12811 	return -1;
12812 #endif
12813 }
12814 
12815 /*
12816  *  Replace valstack top with case converted version.
12817  */
12818 
duk_unicode_case_convert_string(duk_hthread * thr,duk_bool_t uppercase)12819 DUK_INTERNAL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase) {
12820 	duk_hstring *h_input;
12821 	duk_bufwriter_ctx bw_alloc;
12822 	duk_bufwriter_ctx *bw;
12823 	const duk_uint8_t *p, *p_start, *p_end;
12824 	duk_codepoint_t prev, curr, next;
12825 
12826 	h_input = duk_require_hstring(thr, -1);  /* Accept symbols. */
12827 	DUK_ASSERT(h_input != NULL);
12828 
12829 	bw = &bw_alloc;
12830 	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));
12831 
12832 	/* [ ... input buffer ] */
12833 
12834 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
12835 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
12836 	p = p_start;
12837 
12838 	prev = -1; DUK_UNREF(prev);
12839 	curr = -1;
12840 	next = -1;
12841 	for (;;) {
12842 		prev = curr;
12843 		curr = next;
12844 		next = -1;
12845 		if (p < p_end) {
12846 			next = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
12847 		} else {
12848 			/* end of input and last char has been processed */
12849 			if (curr < 0) {
12850 				break;
12851 			}
12852 		}
12853 
12854 		/* on first round, skip */
12855 		if (curr >= 0) {
12856 			/* XXX: could add a fast path to process chunks of input codepoints,
12857 			 * but relative benefit would be quite small.
12858 			 */
12859 
12860 			/* Ensure space for maximum multi-character result; estimate is overkill. */
12861 			DUK_BW_ENSURE(thr, bw, 8 * DUK_UNICODE_MAX_XUTF8_LENGTH);
12862 
12863 			duk__case_transform_helper(thr,
12864 			                           bw,
12865 			                           (duk_codepoint_t) curr,
12866 			                           prev,
12867 			                           next,
12868 			                           uppercase);
12869 		}
12870 	}
12871 
12872 	DUK_BW_COMPACT(thr, bw);
12873 	(void) duk_buffer_to_string(thr, -1);  /* Safe, output is encoded. */
12874 	/* invalidates h_buf pointer */
12875 	duk_remove_m2(thr);
12876 }
12877 
12878 #if defined(DUK_USE_REGEXP_SUPPORT)
12879 
12880 /*
12881  *  Canonicalize() abstract operation needed for canonicalization of individual
12882  *  codepoints during regexp compilation and execution, see E5 Section 15.10.2.8.
12883  *  Note that codepoints are canonicalized one character at a time, so no context
12884  *  specific rules can apply.  Locale specific rules can apply, though.
12885  */
12886 
duk_unicode_re_canonicalize_char(duk_hthread * thr,duk_codepoint_t cp)12887 DUK_INTERNAL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp) {
12888 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
12889 	/* Fast canonicalization lookup at the cost of 128kB footprint. */
12890 	DUK_ASSERT(cp >= 0);
12891 	DUK_UNREF(thr);
12892 	if (DUK_LIKELY(cp < 0x10000L)) {
12893 		return (duk_codepoint_t) duk_unicode_re_canon_lookup[cp];
12894 	}
12895 	return cp;
12896 #else  /* DUK_USE_REGEXP_CANON_WORKAROUND */
12897 	duk_codepoint_t y;
12898 
12899 	y = duk__case_transform_helper(thr,
12900 	                               NULL,    /* NULL is allowed, no output */
12901 	                               cp,      /* curr char */
12902 	                               -1,      /* prev char */
12903 	                               -1,      /* next char */
12904 	                               1);      /* uppercase */
12905 
12906 	if ((y < 0) || (cp >= 0x80 && y < 0x80)) {
12907 		/* multiple codepoint conversion or non-ASCII mapped to ASCII
12908 		 * --> leave as is.
12909 		 */
12910 		return cp;
12911 	}
12912 
12913 	return y;
12914 #endif  /* DUK_USE_REGEXP_CANON_WORKAROUND */
12915 }
12916 
12917 /*
12918  *  E5 Section 15.10.2.6 "IsWordChar" abstract operation.  Assume
12919  *  x < 0 for characters read outside the string.
12920  */
12921 
duk_unicode_re_is_wordchar(duk_codepoint_t x)12922 DUK_INTERNAL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t x) {
12923 	/*
12924 	 *  Note: the description in E5 Section 15.10.2.6 has a typo, it
12925 	 *  contains 'A' twice and lacks 'a'; the intent is [0-9a-zA-Z_].
12926 	 */
12927 	if ((x >= '0' && x <= '9') ||
12928 	    (x >= 'a' && x <= 'z') ||
12929 	    (x >= 'A' && x <= 'Z') ||
12930 	    (x == '_')) {
12931 		return 1;
12932 	}
12933 	return 0;
12934 }
12935 
12936 /*
12937  *  Regexp range tables
12938  */
12939 
12940 /* exposed because lexer needs these too */
12941 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_digit[2] = {
12942 	(duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
12943 };
12944 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_white[22] = {
12945 	(duk_uint16_t) 0x0009UL, (duk_uint16_t) 0x000DUL,
12946 	(duk_uint16_t) 0x0020UL, (duk_uint16_t) 0x0020UL,
12947 	(duk_uint16_t) 0x00A0UL, (duk_uint16_t) 0x00A0UL,
12948 	(duk_uint16_t) 0x1680UL, (duk_uint16_t) 0x1680UL,
12949 	(duk_uint16_t) 0x180EUL, (duk_uint16_t) 0x180EUL,
12950 	(duk_uint16_t) 0x2000UL, (duk_uint16_t) 0x200AUL,
12951 	(duk_uint16_t) 0x2028UL, (duk_uint16_t) 0x2029UL,
12952 	(duk_uint16_t) 0x202FUL, (duk_uint16_t) 0x202FUL,
12953 	(duk_uint16_t) 0x205FUL, (duk_uint16_t) 0x205FUL,
12954 	(duk_uint16_t) 0x3000UL, (duk_uint16_t) 0x3000UL,
12955 	(duk_uint16_t) 0xFEFFUL, (duk_uint16_t) 0xFEFFUL,
12956 };
12957 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_wordchar[8] = {
12958 	(duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
12959 	(duk_uint16_t) 0x0041UL, (duk_uint16_t) 0x005AUL,
12960 	(duk_uint16_t) 0x005FUL, (duk_uint16_t) 0x005FUL,
12961 	(duk_uint16_t) 0x0061UL, (duk_uint16_t) 0x007AUL,
12962 };
12963 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_digit[4] = {
12964 	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
12965 	(duk_uint16_t) 0x003AUL, (duk_uint16_t) 0xFFFFUL,
12966 };
12967 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_white[24] = {
12968 	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x0008UL,
12969 	(duk_uint16_t) 0x000EUL, (duk_uint16_t) 0x001FUL,
12970 	(duk_uint16_t) 0x0021UL, (duk_uint16_t) 0x009FUL,
12971 	(duk_uint16_t) 0x00A1UL, (duk_uint16_t) 0x167FUL,
12972 	(duk_uint16_t) 0x1681UL, (duk_uint16_t) 0x180DUL,
12973 	(duk_uint16_t) 0x180FUL, (duk_uint16_t) 0x1FFFUL,
12974 	(duk_uint16_t) 0x200BUL, (duk_uint16_t) 0x2027UL,
12975 	(duk_uint16_t) 0x202AUL, (duk_uint16_t) 0x202EUL,
12976 	(duk_uint16_t) 0x2030UL, (duk_uint16_t) 0x205EUL,
12977 	(duk_uint16_t) 0x2060UL, (duk_uint16_t) 0x2FFFUL,
12978 	(duk_uint16_t) 0x3001UL, (duk_uint16_t) 0xFEFEUL,
12979 	(duk_uint16_t) 0xFF00UL, (duk_uint16_t) 0xFFFFUL,
12980 };
12981 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10] = {
12982 	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
12983 	(duk_uint16_t) 0x003AUL, (duk_uint16_t) 0x0040UL,
12984 	(duk_uint16_t) 0x005BUL, (duk_uint16_t) 0x005EUL,
12985 	(duk_uint16_t) 0x0060UL, (duk_uint16_t) 0x0060UL,
12986 	(duk_uint16_t) 0x007BUL, (duk_uint16_t) 0xFFFFUL,
12987 };
12988 
12989 #endif  /* DUK_USE_REGEXP_SUPPORT */
12990 #line 1 "duk_util_misc.c"
12991 /*
12992  *  Misc util stuff.
12993  */
12994 
12995 /* #include duk_internal.h -> already included */
12996 
12997 /*
12998  *  Lowercase digits for radix values 2 to 36.  Also doubles as lowercase
12999  *  hex nybble table.
13000  */
13001 
13002 DUK_INTERNAL const duk_uint8_t duk_lc_digits[36] = {
13003 	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
13004 	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
13005 	DUK_ASC_8, DUK_ASC_9, DUK_ASC_LC_A, DUK_ASC_LC_B,
13006 	DUK_ASC_LC_C, DUK_ASC_LC_D, DUK_ASC_LC_E, DUK_ASC_LC_F,
13007 	DUK_ASC_LC_G, DUK_ASC_LC_H, DUK_ASC_LC_I, DUK_ASC_LC_J,
13008 	DUK_ASC_LC_K, DUK_ASC_LC_L, DUK_ASC_LC_M, DUK_ASC_LC_N,
13009 	DUK_ASC_LC_O, DUK_ASC_LC_P, DUK_ASC_LC_Q, DUK_ASC_LC_R,
13010 	DUK_ASC_LC_S, DUK_ASC_LC_T, DUK_ASC_LC_U, DUK_ASC_LC_V,
13011 	DUK_ASC_LC_W, DUK_ASC_LC_X, DUK_ASC_LC_Y, DUK_ASC_LC_Z
13012 };
13013 
13014 DUK_INTERNAL const duk_uint8_t duk_uc_nybbles[16] = {
13015 	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
13016 	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
13017 	DUK_ASC_8, DUK_ASC_9, DUK_ASC_UC_A, DUK_ASC_UC_B,
13018 	DUK_ASC_UC_C, DUK_ASC_UC_D, DUK_ASC_UC_E, DUK_ASC_UC_F
13019 };
13020 
13021 /*
13022  *  Table for hex decoding ASCII hex digits
13023  */
13024 
13025 DUK_INTERNAL const duk_int8_t duk_hex_dectab[256] = {
13026 	/* -1 if invalid */
13027 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x00-0x0f */
13028 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x10-0x1f */
13029 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x20-0x2f */
13030 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,  /* 0x30-0x3f */
13031 	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x40-0x4f */
13032 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x50-0x5f */
13033 	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x60-0x6f */
13034 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x70-0x7f */
13035 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x80-0x8f */
13036 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x90-0x9f */
13037 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xa0-0xaf */
13038 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xb0-0xbf */
13039 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xc0-0xcf */
13040 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xd0-0xdf */
13041 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xe0-0xef */
13042 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1   /* 0xf0-0xff */
13043 };
13044 
13045 #if defined(DUK_USE_HEX_FASTPATH)
13046 /* Preshifted << 4.  Must use 16-bit entry to allow negative value signaling. */
13047 DUK_INTERNAL const duk_int16_t duk_hex_dectab_shift4[256] = {
13048 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x00-0x0f */
13049 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x10-0x1f */
13050 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x20-0x2f */
13051 	0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x30-0x3f */
13052 	  -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x40-0x4f */
13053 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x50-0x5f */
13054 	  -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x60-0x6f */
13055 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x70-0x7f */
13056 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x80-0x8f */
13057 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x90-0x9f */
13058 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xa0-0xaf */
13059 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xb0-0xbf */
13060 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xc0-0xcf */
13061 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xd0-0xdf */
13062 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xe0-0xef */
13063 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1   /* 0xf0-0xff */
13064 };
13065 #endif
13066 
13067 /*
13068  *  Table for hex encoding bytes
13069  */
13070 
13071 #if defined(DUK_USE_HEX_FASTPATH)
13072 /* Lookup to encode one byte directly into 2 characters:
13073  *
13074  *   def genhextab(bswap):
13075  *       for i in xrange(256):
13076  *           t = chr(i).encode('hex')
13077  *           if bswap:
13078  *               t = t[1] + t[0]
13079  *           print('0x' + t.encode('hex') + 'U')
13080  *   print('big endian'); genhextab(False)
13081  *   print('little endian'); genhextab(True)
13082 */
13083 DUK_INTERNAL const duk_uint16_t duk_hex_enctab[256] = {
13084 #if defined(DUK_USE_INTEGER_BE)
13085 	0x3030U, 0x3031U, 0x3032U, 0x3033U, 0x3034U, 0x3035U, 0x3036U, 0x3037U,
13086 	0x3038U, 0x3039U, 0x3061U, 0x3062U, 0x3063U, 0x3064U, 0x3065U, 0x3066U,
13087 	0x3130U, 0x3131U, 0x3132U, 0x3133U, 0x3134U, 0x3135U, 0x3136U, 0x3137U,
13088 	0x3138U, 0x3139U, 0x3161U, 0x3162U, 0x3163U, 0x3164U, 0x3165U, 0x3166U,
13089 	0x3230U, 0x3231U, 0x3232U, 0x3233U, 0x3234U, 0x3235U, 0x3236U, 0x3237U,
13090 	0x3238U, 0x3239U, 0x3261U, 0x3262U, 0x3263U, 0x3264U, 0x3265U, 0x3266U,
13091 	0x3330U, 0x3331U, 0x3332U, 0x3333U, 0x3334U, 0x3335U, 0x3336U, 0x3337U,
13092 	0x3338U, 0x3339U, 0x3361U, 0x3362U, 0x3363U, 0x3364U, 0x3365U, 0x3366U,
13093 	0x3430U, 0x3431U, 0x3432U, 0x3433U, 0x3434U, 0x3435U, 0x3436U, 0x3437U,
13094 	0x3438U, 0x3439U, 0x3461U, 0x3462U, 0x3463U, 0x3464U, 0x3465U, 0x3466U,
13095 	0x3530U, 0x3531U, 0x3532U, 0x3533U, 0x3534U, 0x3535U, 0x3536U, 0x3537U,
13096 	0x3538U, 0x3539U, 0x3561U, 0x3562U, 0x3563U, 0x3564U, 0x3565U, 0x3566U,
13097 	0x3630U, 0x3631U, 0x3632U, 0x3633U, 0x3634U, 0x3635U, 0x3636U, 0x3637U,
13098 	0x3638U, 0x3639U, 0x3661U, 0x3662U, 0x3663U, 0x3664U, 0x3665U, 0x3666U,
13099 	0x3730U, 0x3731U, 0x3732U, 0x3733U, 0x3734U, 0x3735U, 0x3736U, 0x3737U,
13100 	0x3738U, 0x3739U, 0x3761U, 0x3762U, 0x3763U, 0x3764U, 0x3765U, 0x3766U,
13101 	0x3830U, 0x3831U, 0x3832U, 0x3833U, 0x3834U, 0x3835U, 0x3836U, 0x3837U,
13102 	0x3838U, 0x3839U, 0x3861U, 0x3862U, 0x3863U, 0x3864U, 0x3865U, 0x3866U,
13103 	0x3930U, 0x3931U, 0x3932U, 0x3933U, 0x3934U, 0x3935U, 0x3936U, 0x3937U,
13104 	0x3938U, 0x3939U, 0x3961U, 0x3962U, 0x3963U, 0x3964U, 0x3965U, 0x3966U,
13105 	0x6130U, 0x6131U, 0x6132U, 0x6133U, 0x6134U, 0x6135U, 0x6136U, 0x6137U,
13106 	0x6138U, 0x6139U, 0x6161U, 0x6162U, 0x6163U, 0x6164U, 0x6165U, 0x6166U,
13107 	0x6230U, 0x6231U, 0x6232U, 0x6233U, 0x6234U, 0x6235U, 0x6236U, 0x6237U,
13108 	0x6238U, 0x6239U, 0x6261U, 0x6262U, 0x6263U, 0x6264U, 0x6265U, 0x6266U,
13109 	0x6330U, 0x6331U, 0x6332U, 0x6333U, 0x6334U, 0x6335U, 0x6336U, 0x6337U,
13110 	0x6338U, 0x6339U, 0x6361U, 0x6362U, 0x6363U, 0x6364U, 0x6365U, 0x6366U,
13111 	0x6430U, 0x6431U, 0x6432U, 0x6433U, 0x6434U, 0x6435U, 0x6436U, 0x6437U,
13112 	0x6438U, 0x6439U, 0x6461U, 0x6462U, 0x6463U, 0x6464U, 0x6465U, 0x6466U,
13113 	0x6530U, 0x6531U, 0x6532U, 0x6533U, 0x6534U, 0x6535U, 0x6536U, 0x6537U,
13114 	0x6538U, 0x6539U, 0x6561U, 0x6562U, 0x6563U, 0x6564U, 0x6565U, 0x6566U,
13115 	0x6630U, 0x6631U, 0x6632U, 0x6633U, 0x6634U, 0x6635U, 0x6636U, 0x6637U,
13116 	0x6638U, 0x6639U, 0x6661U, 0x6662U, 0x6663U, 0x6664U, 0x6665U, 0x6666U
13117 #else  /* DUK_USE_INTEGER_BE */
13118 	0x3030U, 0x3130U, 0x3230U, 0x3330U, 0x3430U, 0x3530U, 0x3630U, 0x3730U,
13119 	0x3830U, 0x3930U, 0x6130U, 0x6230U, 0x6330U, 0x6430U, 0x6530U, 0x6630U,
13120 	0x3031U, 0x3131U, 0x3231U, 0x3331U, 0x3431U, 0x3531U, 0x3631U, 0x3731U,
13121 	0x3831U, 0x3931U, 0x6131U, 0x6231U, 0x6331U, 0x6431U, 0x6531U, 0x6631U,
13122 	0x3032U, 0x3132U, 0x3232U, 0x3332U, 0x3432U, 0x3532U, 0x3632U, 0x3732U,
13123 	0x3832U, 0x3932U, 0x6132U, 0x6232U, 0x6332U, 0x6432U, 0x6532U, 0x6632U,
13124 	0x3033U, 0x3133U, 0x3233U, 0x3333U, 0x3433U, 0x3533U, 0x3633U, 0x3733U,
13125 	0x3833U, 0x3933U, 0x6133U, 0x6233U, 0x6333U, 0x6433U, 0x6533U, 0x6633U,
13126 	0x3034U, 0x3134U, 0x3234U, 0x3334U, 0x3434U, 0x3534U, 0x3634U, 0x3734U,
13127 	0x3834U, 0x3934U, 0x6134U, 0x6234U, 0x6334U, 0x6434U, 0x6534U, 0x6634U,
13128 	0x3035U, 0x3135U, 0x3235U, 0x3335U, 0x3435U, 0x3535U, 0x3635U, 0x3735U,
13129 	0x3835U, 0x3935U, 0x6135U, 0x6235U, 0x6335U, 0x6435U, 0x6535U, 0x6635U,
13130 	0x3036U, 0x3136U, 0x3236U, 0x3336U, 0x3436U, 0x3536U, 0x3636U, 0x3736U,
13131 	0x3836U, 0x3936U, 0x6136U, 0x6236U, 0x6336U, 0x6436U, 0x6536U, 0x6636U,
13132 	0x3037U, 0x3137U, 0x3237U, 0x3337U, 0x3437U, 0x3537U, 0x3637U, 0x3737U,
13133 	0x3837U, 0x3937U, 0x6137U, 0x6237U, 0x6337U, 0x6437U, 0x6537U, 0x6637U,
13134 	0x3038U, 0x3138U, 0x3238U, 0x3338U, 0x3438U, 0x3538U, 0x3638U, 0x3738U,
13135 	0x3838U, 0x3938U, 0x6138U, 0x6238U, 0x6338U, 0x6438U, 0x6538U, 0x6638U,
13136 	0x3039U, 0x3139U, 0x3239U, 0x3339U, 0x3439U, 0x3539U, 0x3639U, 0x3739U,
13137 	0x3839U, 0x3939U, 0x6139U, 0x6239U, 0x6339U, 0x6439U, 0x6539U, 0x6639U,
13138 	0x3061U, 0x3161U, 0x3261U, 0x3361U, 0x3461U, 0x3561U, 0x3661U, 0x3761U,
13139 	0x3861U, 0x3961U, 0x6161U, 0x6261U, 0x6361U, 0x6461U, 0x6561U, 0x6661U,
13140 	0x3062U, 0x3162U, 0x3262U, 0x3362U, 0x3462U, 0x3562U, 0x3662U, 0x3762U,
13141 	0x3862U, 0x3962U, 0x6162U, 0x6262U, 0x6362U, 0x6462U, 0x6562U, 0x6662U,
13142 	0x3063U, 0x3163U, 0x3263U, 0x3363U, 0x3463U, 0x3563U, 0x3663U, 0x3763U,
13143 	0x3863U, 0x3963U, 0x6163U, 0x6263U, 0x6363U, 0x6463U, 0x6563U, 0x6663U,
13144 	0x3064U, 0x3164U, 0x3264U, 0x3364U, 0x3464U, 0x3564U, 0x3664U, 0x3764U,
13145 	0x3864U, 0x3964U, 0x6164U, 0x6264U, 0x6364U, 0x6464U, 0x6564U, 0x6664U,
13146 	0x3065U, 0x3165U, 0x3265U, 0x3365U, 0x3465U, 0x3565U, 0x3665U, 0x3765U,
13147 	0x3865U, 0x3965U, 0x6165U, 0x6265U, 0x6365U, 0x6465U, 0x6565U, 0x6665U,
13148 	0x3066U, 0x3166U, 0x3266U, 0x3366U, 0x3466U, 0x3566U, 0x3666U, 0x3766U,
13149 	0x3866U, 0x3966U, 0x6166U, 0x6266U, 0x6366U, 0x6466U, 0x6566U, 0x6666U
13150 #endif  /* DUK_USE_INTEGER_BE */
13151 };
13152 #endif  /* DUK_USE_HEX_FASTPATH */
13153 
13154 /*
13155  *  Arbitrary byteswap for potentially unaligned values
13156  *
13157  *  Used to byteswap pointers e.g. in debugger code.
13158  */
13159 
13160 #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)13161 DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) {
13162 	duk_uint8_t tmp;
13163 	duk_uint8_t *q = p + len - 1;
13164 
13165 	while (p - q < 0) {
13166 		tmp = *p;
13167 		*p = *q;
13168 		*q = tmp;
13169 		p++;
13170 		q--;
13171 	}
13172 }
13173 #endif
13174 #line 1 "duk_hobject_class.c"
13175 /*
13176  *  Hobject ECMAScript [[Class]].
13177  */
13178 
13179 /* #include duk_internal.h -> already included */
13180 
13181 #if (DUK_STRIDX_UC_ARGUMENTS > 255)
13182 #error constant too large
13183 #endif
13184 #if (DUK_STRIDX_ARRAY > 255)
13185 #error constant too large
13186 #endif
13187 #if (DUK_STRIDX_UC_BOOLEAN > 255)
13188 #error constant too large
13189 #endif
13190 #if (DUK_STRIDX_DATE > 255)
13191 #error constant too large
13192 #endif
13193 #if (DUK_STRIDX_UC_ERROR > 255)
13194 #error constant too large
13195 #endif
13196 #if (DUK_STRIDX_UC_FUNCTION > 255)
13197 #error constant too large
13198 #endif
13199 #if (DUK_STRIDX_JSON > 255)
13200 #error constant too large
13201 #endif
13202 #if (DUK_STRIDX_MATH > 255)
13203 #error constant too large
13204 #endif
13205 #if (DUK_STRIDX_UC_NUMBER > 255)
13206 #error constant too large
13207 #endif
13208 #if (DUK_STRIDX_UC_OBJECT > 255)
13209 #error constant too large
13210 #endif
13211 #if (DUK_STRIDX_REG_EXP > 255)
13212 #error constant too large
13213 #endif
13214 #if (DUK_STRIDX_UC_STRING > 255)
13215 #error constant too large
13216 #endif
13217 #if (DUK_STRIDX_GLOBAL > 255)
13218 #error constant too large
13219 #endif
13220 #if (DUK_STRIDX_OBJ_ENV > 255)
13221 #error constant too large
13222 #endif
13223 #if (DUK_STRIDX_DEC_ENV > 255)
13224 #error constant too large
13225 #endif
13226 #if (DUK_STRIDX_UC_POINTER > 255)
13227 #error constant too large
13228 #endif
13229 #if (DUK_STRIDX_UC_THREAD > 255)
13230 #error constant too large
13231 #endif
13232 #if (DUK_STRIDX_ARRAY_BUFFER > 255)
13233 #error constant too large
13234 #endif
13235 #if (DUK_STRIDX_DATA_VIEW > 255)
13236 #error constant too large
13237 #endif
13238 #if (DUK_STRIDX_INT8_ARRAY > 255)
13239 #error constant too large
13240 #endif
13241 #if (DUK_STRIDX_UINT8_ARRAY > 255)
13242 #error constant too large
13243 #endif
13244 #if (DUK_STRIDX_UINT8_CLAMPED_ARRAY > 255)
13245 #error constant too large
13246 #endif
13247 #if (DUK_STRIDX_INT16_ARRAY > 255)
13248 #error constant too large
13249 #endif
13250 #if (DUK_STRIDX_UINT16_ARRAY > 255)
13251 #error constant too large
13252 #endif
13253 #if (DUK_STRIDX_INT32_ARRAY > 255)
13254 #error constant too large
13255 #endif
13256 #if (DUK_STRIDX_UINT32_ARRAY > 255)
13257 #error constant too large
13258 #endif
13259 #if (DUK_STRIDX_FLOAT32_ARRAY > 255)
13260 #error constant too large
13261 #endif
13262 #if (DUK_STRIDX_FLOAT64_ARRAY > 255)
13263 #error constant too large
13264 #endif
13265 #if (DUK_STRIDX_EMPTY_STRING > 255)
13266 #error constant too large
13267 #endif
13268 
13269 /* Note: assumes that these string indexes are 8-bit, genstrings.py must ensure that */
13270 DUK_INTERNAL duk_uint8_t duk_class_number_to_stridx[32] = {
13271 	DUK_STRIDX_EMPTY_STRING,  /* NONE, intentionally empty */
13272 	DUK_STRIDX_UC_OBJECT,
13273 	DUK_STRIDX_ARRAY,
13274 	DUK_STRIDX_UC_FUNCTION,
13275 	DUK_STRIDX_UC_ARGUMENTS,
13276 	DUK_STRIDX_UC_BOOLEAN,
13277 	DUK_STRIDX_DATE,
13278 	DUK_STRIDX_UC_ERROR,
13279 	DUK_STRIDX_JSON,
13280 	DUK_STRIDX_MATH,
13281 	DUK_STRIDX_UC_NUMBER,
13282 	DUK_STRIDX_REG_EXP,
13283 	DUK_STRIDX_UC_STRING,
13284 	DUK_STRIDX_GLOBAL,
13285 	DUK_STRIDX_UC_SYMBOL,
13286 	DUK_STRIDX_OBJ_ENV,
13287 	DUK_STRIDX_DEC_ENV,
13288 	DUK_STRIDX_UC_POINTER,
13289 	DUK_STRIDX_UC_THREAD,
13290 	DUK_STRIDX_ARRAY_BUFFER,
13291 	DUK_STRIDX_DATA_VIEW,
13292 	DUK_STRIDX_INT8_ARRAY,
13293 	DUK_STRIDX_UINT8_ARRAY,
13294 	DUK_STRIDX_UINT8_CLAMPED_ARRAY,
13295 	DUK_STRIDX_INT16_ARRAY,
13296 	DUK_STRIDX_UINT16_ARRAY,
13297 	DUK_STRIDX_INT32_ARRAY,
13298 	DUK_STRIDX_UINT32_ARRAY,
13299 	DUK_STRIDX_FLOAT32_ARRAY,
13300 	DUK_STRIDX_FLOAT64_ARRAY,
13301 	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
13302 	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
13303 };
13304 #line 1 "duk_alloc_default.c"
13305 /*
13306  *  Default allocation functions.
13307  *
13308  *  Assumes behavior such as malloc allowing zero size, yielding
13309  *  a NULL or a unique pointer which is a no-op for free.
13310  */
13311 
13312 /* #include duk_internal.h -> already included */
13313 
13314 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
duk_default_alloc_function(void * udata,duk_size_t size)13315 DUK_INTERNAL void *duk_default_alloc_function(void *udata, duk_size_t size) {
13316 	void *res;
13317 	DUK_UNREF(udata);
13318 	res = DUK_ANSI_MALLOC(size);
13319 	DUK_DDD(DUK_DDDPRINT("default alloc function: %lu -> %p",
13320 	                     (unsigned long) size, (void *) res));
13321 	return res;
13322 }
13323 
duk_default_realloc_function(void * udata,void * ptr,duk_size_t newsize)13324 DUK_INTERNAL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize) {
13325 	void *res;
13326 	DUK_UNREF(udata);
13327 	res = DUK_ANSI_REALLOC(ptr, newsize);
13328 	DUK_DDD(DUK_DDDPRINT("default realloc function: %p %lu -> %p",
13329 	                     (void *) ptr, (unsigned long) newsize, (void *) res));
13330 	return res;
13331 }
13332 
duk_default_free_function(void * udata,void * ptr)13333 DUK_INTERNAL void duk_default_free_function(void *udata, void *ptr) {
13334 	DUK_DDD(DUK_DDDPRINT("default free function: %p", (void *) ptr));
13335 	DUK_UNREF(udata);
13336 	DUK_ANSI_FREE(ptr);
13337 }
13338 #endif  /* DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS */
13339 #line 1 "duk_api_buffer.c"
13340 /*
13341  *  Buffer
13342  */
13343 
13344 /* #include duk_internal.h -> already included */
13345 
duk_resize_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t new_size)13346 DUK_EXTERNAL void *duk_resize_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t new_size) {
13347 	duk_hbuffer_dynamic *h;
13348 
13349 	DUK_ASSERT_API_ENTRY(thr);
13350 
13351 	h = (duk_hbuffer_dynamic *) duk_require_hbuffer(thr, idx);
13352 	DUK_ASSERT(h != NULL);
13353 
13354 	if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
13355 		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
13356 		DUK_WO_NORETURN(return NULL;);
13357 	}
13358 
13359 	/* Maximum size check is handled by callee. */
13360 	duk_hbuffer_resize(thr, h, new_size);
13361 
13362 	return DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
13363 }
13364 
duk_steal_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)13365 DUK_EXTERNAL void *duk_steal_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
13366 	duk_hbuffer_dynamic *h;
13367 	void *ptr;
13368 	duk_size_t sz;
13369 
13370 	DUK_ASSERT_API_ENTRY(thr);
13371 
13372 	h = (duk_hbuffer_dynamic *) duk_require_hbuffer(thr, idx);
13373 	DUK_ASSERT(h != NULL);
13374 
13375 	if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
13376 		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
13377 		DUK_WO_NORETURN(return NULL;);
13378 	}
13379 
13380 	/* Forget the previous allocation, setting size to 0 and alloc to
13381 	 * NULL.  Caller is responsible for freeing the previous allocation.
13382 	 * Getting the allocation and clearing it is done in the same API
13383 	 * call to avoid any chance of a realloc.
13384 	 */
13385 	ptr = DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
13386 	sz = DUK_HBUFFER_DYNAMIC_GET_SIZE(h);
13387 	if (out_size) {
13388 		*out_size = sz;
13389 	}
13390 	DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(thr->heap, h);
13391 	DUK_HBUFFER_DYNAMIC_SET_SIZE(h, 0);
13392 
13393 	return ptr;
13394 }
13395 
duk_config_buffer(duk_hthread * thr,duk_idx_t idx,void * ptr,duk_size_t len)13396 DUK_EXTERNAL void duk_config_buffer(duk_hthread *thr, duk_idx_t idx, void *ptr, duk_size_t len) {
13397 	duk_hbuffer_external *h;
13398 
13399 	DUK_ASSERT_API_ENTRY(thr);
13400 
13401 	h = (duk_hbuffer_external *) duk_require_hbuffer(thr, idx);
13402 	DUK_ASSERT(h != NULL);
13403 
13404 	if (!DUK_HBUFFER_HAS_EXTERNAL(h)) {
13405 		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
13406 		DUK_WO_NORETURN(return;);
13407 	}
13408 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h));
13409 
13410 	DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(thr->heap, h, ptr);
13411 	DUK_HBUFFER_EXTERNAL_SET_SIZE(h, len);
13412 }
13413 #line 1 "duk_api_bytecode.c"
13414 /*
13415  *  Bytecode dump/load
13416  *
13417  *  The bytecode load primitive is more important performance-wise than the
13418  *  dump primitive.
13419  *
13420  *  Unlike most Duktape API calls, bytecode dump/load is not guaranteed to be
13421  *  memory safe for invalid arguments - caller beware!  There's little point
13422  *  in trying to achieve memory safety unless bytecode instructions are also
13423  *  validated which is not easy to do with indirect register references etc.
13424  */
13425 
13426 /* #include duk_internal.h -> already included */
13427 
13428 #if defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
13429 
13430 #define DUK__SER_MARKER  0xbf
13431 #define DUK__SER_STRING  0x00
13432 #define DUK__SER_NUMBER  0x01
13433 #define DUK__BYTECODE_INITIAL_ALLOC 256
13434 #define DUK__NO_FORMALS  0xffffffffUL
13435 
13436 /*
13437  *  Dump/load helpers, xxx_raw() helpers do no buffer checks
13438  */
13439 
duk__load_string_raw(duk_hthread * thr,duk_uint8_t * p)13440 DUK_LOCAL duk_uint8_t *duk__load_string_raw(duk_hthread *thr, duk_uint8_t *p) {
13441 	duk_uint32_t len;
13442 
13443 	len = DUK_RAW_READ_U32_BE(p);
13444 	duk_push_lstring(thr, (const char *) p, len);
13445 	p += len;
13446 	return p;
13447 }
13448 
duk__load_buffer_raw(duk_hthread * thr,duk_uint8_t * p)13449 DUK_LOCAL duk_uint8_t *duk__load_buffer_raw(duk_hthread *thr, duk_uint8_t *p) {
13450 	duk_uint32_t len;
13451 	duk_uint8_t *buf;
13452 
13453 	len = DUK_RAW_READ_U32_BE(p);
13454 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len);
13455 	DUK_ASSERT(buf != NULL);
13456 	duk_memcpy((void *) buf, (const void *) p, (size_t) len);
13457 	p += len;
13458 	return p;
13459 }
13460 
duk__dump_hstring_raw(duk_uint8_t * p,duk_hstring * h)13461 DUK_LOCAL duk_uint8_t *duk__dump_hstring_raw(duk_uint8_t *p, duk_hstring *h) {
13462 	duk_size_t len;
13463 	duk_uint32_t tmp32;
13464 
13465 	DUK_ASSERT(h != NULL);
13466 
13467 	len = DUK_HSTRING_GET_BYTELEN(h);
13468 	DUK_ASSERT(len <= 0xffffffffUL);  /* string limits */
13469 	tmp32 = (duk_uint32_t) len;
13470 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13471 	duk_memcpy((void *) p,
13472 	           (const void *) DUK_HSTRING_GET_DATA(h),
13473 	           len);
13474 	p += len;
13475 	return p;
13476 }
13477 
duk__dump_hbuffer_raw(duk_hthread * thr,duk_uint8_t * p,duk_hbuffer * h)13478 DUK_LOCAL duk_uint8_t *duk__dump_hbuffer_raw(duk_hthread *thr, duk_uint8_t *p, duk_hbuffer *h) {
13479 	duk_size_t len;
13480 	duk_uint32_t tmp32;
13481 
13482 	DUK_ASSERT(thr != NULL);
13483 	DUK_ASSERT(h != NULL);
13484 	DUK_UNREF(thr);
13485 
13486 	len = DUK_HBUFFER_GET_SIZE(h);
13487 	DUK_ASSERT(len <= 0xffffffffUL);  /* buffer limits */
13488 	tmp32 = (duk_uint32_t) len;
13489 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13490 	/* When len == 0, buffer data pointer may be NULL. */
13491 	duk_memcpy_unsafe((void *) p,
13492 	                  (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h),
13493 	                  len);
13494 	p += len;
13495 	return p;
13496 }
13497 
duk__dump_string_prop(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func,duk_small_uint_t stridx)13498 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) {
13499 	duk_hstring *h_str;
13500 	duk_tval *tv;
13501 
13502 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
13503 	if (tv != NULL && DUK_TVAL_IS_STRING(tv)) {
13504 		h_str = DUK_TVAL_GET_STRING(tv);
13505 		DUK_ASSERT(h_str != NULL);
13506 	} else {
13507 		h_str = DUK_HTHREAD_STRING_EMPTY_STRING(thr);
13508 		DUK_ASSERT(h_str != NULL);
13509 	}
13510 	DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13511 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(h_str), p);
13512 	p = duk__dump_hstring_raw(p, h_str);
13513 	return p;
13514 }
13515 
duk__dump_buffer_prop(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func,duk_small_uint_t stridx)13516 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) {
13517 	duk_tval *tv;
13518 
13519 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
13520 	if (tv != NULL && DUK_TVAL_IS_BUFFER(tv)) {
13521 		duk_hbuffer *h_buf;
13522 		h_buf = DUK_TVAL_GET_BUFFER(tv);
13523 		DUK_ASSERT(h_buf != NULL);
13524 		DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13525 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HBUFFER_GET_SIZE(h_buf), p);
13526 		p = duk__dump_hbuffer_raw(thr, p, h_buf);
13527 	} else {
13528 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13529 		DUK_RAW_WRITE_U32_BE(p, 0);
13530 	}
13531 	return p;
13532 }
13533 
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)13534 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) {
13535 	duk_tval *tv;
13536 	duk_uint32_t val;
13537 
13538 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
13539 	if (tv != NULL && DUK_TVAL_IS_NUMBER(tv)) {
13540 		val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv);
13541 	} else {
13542 		val = def_value;
13543 	}
13544 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13545 	DUK_RAW_WRITE_U32_BE(p, val);
13546 	return p;
13547 }
13548 
duk__dump_varmap(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func)13549 DUK_LOCAL duk_uint8_t *duk__dump_varmap(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
13550 	duk_tval *tv;
13551 
13552 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
13553 	if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
13554 		duk_hobject *h;
13555 		duk_uint_fast32_t i;
13556 
13557 		h = DUK_TVAL_GET_OBJECT(tv);
13558 		DUK_ASSERT(h != NULL);
13559 
13560 		/* We know _Varmap only has own properties so walk property
13561 		 * table directly.  We also know _Varmap is dense and all
13562 		 * values are numbers; assert for these.  GC and finalizers
13563 		 * shouldn't affect _Varmap so side effects should be fine.
13564 		 */
13565 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
13566 			duk_hstring *key;
13567 			duk_tval *tv_val;
13568 			duk_uint32_t val;
13569 
13570 			key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i);
13571 			DUK_ASSERT(key != NULL);  /* _Varmap is dense */
13572 			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h, i));
13573 			tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, i);
13574 			DUK_ASSERT(tv_val != NULL);
13575 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_val));  /* known to be number; in fact an integer */
13576 #if defined(DUK_USE_FASTINT)
13577 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_val));
13578 			DUK_ASSERT(DUK_TVAL_GET_FASTINT(tv_val) == (duk_int64_t) DUK_TVAL_GET_FASTINT_U32(tv_val));  /* known to be 32-bit */
13579 			val = DUK_TVAL_GET_FASTINT_U32(tv_val);
13580 #else
13581 			val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv_val);
13582 #endif
13583 
13584 			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13585 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(key) + 4U, p);
13586 			p = duk__dump_hstring_raw(p, key);
13587 			DUK_RAW_WRITE_U32_BE(p, val);
13588 		}
13589 	}
13590 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13591 	DUK_RAW_WRITE_U32_BE(p, 0);  /* end of _Varmap */
13592 	return p;
13593 }
13594 
duk__dump_formals(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func)13595 DUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
13596 	duk_tval *tv;
13597 
13598 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_FORMALS(thr));
13599 	if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
13600 		duk_harray *h;
13601 		duk_uint32_t i;
13602 
13603 		/* Here we rely on _Formals being a dense array containing
13604 		 * strings.  This should be the case unless _Formals has been
13605 		 * tweaked by the application (which we don't support right
13606 		 * now).
13607 		 */
13608 		h = (duk_harray *) DUK_TVAL_GET_OBJECT(tv);
13609 		DUK_ASSERT(h != NULL);
13610 		DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) h));
13611 		DUK_ASSERT(h->length <= DUK_HOBJECT_GET_ASIZE((duk_hobject *) h));
13612 
13613 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13614 		DUK_ASSERT(h->length != DUK__NO_FORMALS);  /* limits */
13615 		DUK_RAW_WRITE_U32_BE(p, h->length);
13616 
13617 		for (i = 0; i < h->length; i++) {
13618 			duk_tval *tv_val;
13619 			duk_hstring *varname;
13620 
13621 			tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, (duk_hobject *) h, i);
13622 			DUK_ASSERT(tv_val != NULL);
13623 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv_val));
13624 
13625 			varname = DUK_TVAL_GET_STRING(tv_val);
13626 			DUK_ASSERT(varname != NULL);
13627 			DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(varname) >= 1);
13628 
13629 			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13630 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(varname), p);
13631 			p = duk__dump_hstring_raw(p, varname);
13632 		}
13633 	} else {
13634 		DUK_DD(DUK_DDPRINT("dumping function without _Formals, emit marker to indicate missing _Formals"));
13635 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13636 		DUK_RAW_WRITE_U32_BE(p, DUK__NO_FORMALS);  /* marker: no formals */
13637 	}
13638 	return p;
13639 }
13640 
duk__dump_func(duk_hthread * thr,duk_hcompfunc * func,duk_bufwriter_ctx * bw_ctx,duk_uint8_t * p)13641 static duk_uint8_t *duk__dump_func(duk_hthread *thr, duk_hcompfunc *func, duk_bufwriter_ctx *bw_ctx, duk_uint8_t *p) {
13642 	duk_tval *tv, *tv_end;
13643 	duk_instr_t *ins, *ins_end;
13644 	duk_hobject **fn, **fn_end;
13645 	duk_hstring *h_str;
13646 	duk_uint32_t count_instr;
13647 	duk_uint32_t tmp32;
13648 	duk_uint16_t tmp16;
13649 	duk_double_t d;
13650 
13651 	DUK_DD(DUK_DDPRINT("dumping function %p to %p: "
13652 	                   "consts=[%p,%p[ (%ld bytes, %ld items), "
13653 	                   "funcs=[%p,%p[ (%ld bytes, %ld items), "
13654 	                   "code=[%p,%p[ (%ld bytes, %ld items)",
13655 	                   (void *) func,
13656 	                   (void *) p,
13657 	                   (void *) DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, func),
13658 	                   (void *) DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, func),
13659 	                   (long) DUK_HCOMPFUNC_GET_CONSTS_SIZE(thr->heap, func),
13660 	                   (long) DUK_HCOMPFUNC_GET_CONSTS_COUNT(thr->heap, func),
13661 	                   (void *) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, func),
13662 	                   (void *) DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, func),
13663 	                   (long) DUK_HCOMPFUNC_GET_FUNCS_SIZE(thr->heap, func),
13664 	                   (long) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, func),
13665 	                   (void *) DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, func),
13666 	                   (void *) DUK_HCOMPFUNC_GET_CODE_END(thr->heap, func),
13667 	                   (long) DUK_HCOMPFUNC_GET_CODE_SIZE(thr->heap, func),
13668 	                   (long) DUK_HCOMPFUNC_GET_CODE_COUNT(thr->heap, func)));
13669 
13670 	DUK_ASSERT(DUK_USE_ESBC_MAX_BYTES <= 0x7fffffffUL);  /* ensures no overflow */
13671 	count_instr = (duk_uint32_t) DUK_HCOMPFUNC_GET_CODE_COUNT(thr->heap, func);
13672 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 3U * 4U + 2U * 2U + 3U * 4U + count_instr * 4U, p);
13673 
13674 	/* Fixed header info. */
13675 	tmp32 = count_instr;
13676 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13677 	tmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_CONSTS_COUNT(thr->heap, func);
13678 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13679 	tmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, func);
13680 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13681 	tmp16 = func->nregs;
13682 	DUK_RAW_WRITE_U16_BE(p, tmp16);
13683 	tmp16 = func->nargs;
13684 	DUK_RAW_WRITE_U16_BE(p, tmp16);
13685 #if defined(DUK_USE_DEBUGGER_SUPPORT)
13686 	tmp32 = func->start_line;
13687 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13688 	tmp32 = func->end_line;
13689 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13690 #else
13691 	DUK_RAW_WRITE_U32_BE(p, 0);
13692 	DUK_RAW_WRITE_U32_BE(p, 0);
13693 #endif
13694 	tmp32 = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) func);  /* masks flags, only duk_hobject flags */
13695 	tmp32 &= ~(DUK_HOBJECT_FLAG_HAVE_FINALIZER);  /* finalizer flag is lost */
13696 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13697 
13698 	/* Bytecode instructions: endian conversion needed unless
13699 	 * platform is big endian.
13700 	 */
13701 	ins = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, func);
13702 	ins_end = DUK_HCOMPFUNC_GET_CODE_END(thr->heap, func);
13703 	DUK_ASSERT((duk_size_t) (ins_end - ins) == (duk_size_t) count_instr);
13704 #if defined(DUK_USE_INTEGER_BE)
13705 	duk_memcpy_unsafe((void *) p, (const void *) ins, (size_t) (ins_end - ins));
13706 	p += (size_t) (ins_end - ins);
13707 #else
13708 	while (ins != ins_end) {
13709 		tmp32 = (duk_uint32_t) (*ins);
13710 		DUK_RAW_WRITE_U32_BE(p, tmp32);
13711 		ins++;
13712 	}
13713 #endif
13714 
13715 	/* Constants: variable size encoding. */
13716 	tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, func);
13717 	tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, func);
13718 	while (tv != tv_end) {
13719 		/* constants are strings or numbers now */
13720 		DUK_ASSERT(DUK_TVAL_IS_STRING(tv) ||
13721 		           DUK_TVAL_IS_NUMBER(tv));
13722 
13723 		if (DUK_TVAL_IS_STRING(tv)) {
13724 			h_str = DUK_TVAL_GET_STRING(tv);
13725 			DUK_ASSERT(h_str != NULL);
13726 			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13727 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 4U + DUK_HSTRING_GET_BYTELEN(h_str), p);
13728 			*p++ = DUK__SER_STRING;
13729 			p = duk__dump_hstring_raw(p, h_str);
13730 		} else {
13731 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
13732 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 8U, p);
13733 			*p++ = DUK__SER_NUMBER;
13734 			d = DUK_TVAL_GET_NUMBER(tv);
13735 			DUK_RAW_WRITE_DOUBLE_BE(p, d);
13736 		}
13737 		tv++;
13738 	}
13739 
13740 	/* Inner functions recursively. */
13741 	fn = (duk_hobject **) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, func);
13742 	fn_end = (duk_hobject **) DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, func);
13743 	while (fn != fn_end) {
13744 		/* XXX: This causes recursion up to inner function depth
13745 		 * which is normally not an issue, e.g. mark-and-sweep uses
13746 		 * a recursion limiter to avoid C stack issues.  Avoiding
13747 		 * this would mean some sort of a work list or just refusing
13748 		 * to serialize deep functions.
13749 		 */
13750 		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(*fn));
13751 		p = duk__dump_func(thr, (duk_hcompfunc *) *fn, bw_ctx, p);
13752 		fn++;
13753 	}
13754 
13755 	/* Lexenv and varenv are not dumped. */
13756 
13757 	/* Object extra properties.
13758 	 *
13759 	 * There are some difference between function templates and functions.
13760 	 * For example, function templates don't have .length and nargs is
13761 	 * normally used to instantiate the functions.
13762 	 */
13763 
13764 	p = duk__dump_uint32_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_LENGTH, (duk_uint32_t) func->nargs);
13765 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
13766 	p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_NAME);
13767 #endif
13768 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
13769 	p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_FILE_NAME);
13770 #endif
13771 #if defined(DUK_USE_PC2LINE)
13772 	p = duk__dump_buffer_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_INT_PC2LINE);
13773 #endif
13774 	p = duk__dump_varmap(thr, p, bw_ctx, (duk_hobject *) func);
13775 	p = duk__dump_formals(thr, p, bw_ctx, (duk_hobject *) func);
13776 
13777 	DUK_DD(DUK_DDPRINT("serialized function %p -> final pointer %p", (void *) func, (void *) p));
13778 
13779 	return p;
13780 }
13781 
13782 /* Load a function from bytecode.  The function object returned here must
13783  * match what is created by duk_js_push_closure() with respect to its flags,
13784  * properties, etc.
13785  *
13786  * NOTE: there are intentionally no input buffer length / bound checks.
13787  * Adding them would be easy but wouldn't ensure memory safety as untrusted
13788  * or broken bytecode is unsafe during execution unless the opcodes themselves
13789  * are validated (which is quite complex, especially for indirect opcodes).
13790  */
13791 
13792 #define DUK__ASSERT_LEFT(n) do { \
13793 		DUK_ASSERT((duk_size_t) (p_end - p) >= (duk_size_t) (n)); \
13794 	} while (0)
13795 
duk__load_func(duk_hthread * thr,duk_uint8_t * p,duk_uint8_t * p_end)13796 static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t *p_end) {
13797 	duk_hcompfunc *h_fun;
13798 	duk_hbuffer *h_data;
13799 	duk_size_t data_size;
13800 	duk_uint32_t count_instr, count_const, count_funcs;
13801 	duk_uint32_t n;
13802 	duk_uint32_t tmp32;
13803 	duk_small_uint_t const_type;
13804 	duk_uint8_t *fun_data;
13805 	duk_uint8_t *q;
13806 	duk_idx_t idx_base;
13807 	duk_tval *tv1;
13808 	duk_uarridx_t arr_idx;
13809 	duk_uarridx_t arr_limit;
13810 	duk_hobject *func_env;
13811 	duk_bool_t need_pop;
13812 
13813 	/* XXX: There's some overlap with duk_js_closure() here, but
13814 	 * seems difficult to share code.  Ensure that the final function
13815 	 * looks the same as created by duk_js_closure().
13816 	 */
13817 
13818 	DUK_ASSERT(thr != NULL);
13819 
13820 	DUK_DD(DUK_DDPRINT("loading function, p=%p, p_end=%p", (void *) p, (void *) p_end));
13821 
13822 	DUK__ASSERT_LEFT(3 * 4);
13823 	count_instr = DUK_RAW_READ_U32_BE(p);
13824 	count_const = DUK_RAW_READ_U32_BE(p);
13825 	count_funcs = DUK_RAW_READ_U32_BE(p);
13826 
13827 	data_size = sizeof(duk_tval) * count_const +
13828 	            sizeof(duk_hobject *) * count_funcs +
13829 	            sizeof(duk_instr_t) * count_instr;
13830 
13831 	DUK_DD(DUK_DDPRINT("instr=%ld, const=%ld, funcs=%ld, data_size=%ld",
13832 	                   (long) count_instr, (long) count_const,
13833 	                   (long) count_const, (long) data_size));
13834 
13835 	/* Value stack is used to ensure reachability of constants and
13836 	 * inner functions being loaded.  Require enough space to handle
13837 	 * large functions correctly.
13838 	 */
13839 	duk_require_stack(thr, (duk_idx_t) (2 + count_const + count_funcs));
13840 	idx_base = duk_get_top(thr);
13841 
13842 	/* Push function object, init flags etc.  This must match
13843 	 * duk_js_push_closure() quite carefully.
13844 	 */
13845 	h_fun = duk_push_hcompfunc(thr);
13846 	DUK_ASSERT(h_fun != NULL);
13847 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) h_fun));
13848 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, h_fun) == NULL);
13849 	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, h_fun) == NULL);
13850 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, h_fun) == NULL);
13851 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_fun) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
13852 
13853 	h_fun->nregs = DUK_RAW_READ_U16_BE(p);
13854 	h_fun->nargs = DUK_RAW_READ_U16_BE(p);
13855 #if defined(DUK_USE_DEBUGGER_SUPPORT)
13856 	h_fun->start_line = DUK_RAW_READ_U32_BE(p);
13857 	h_fun->end_line = DUK_RAW_READ_U32_BE(p);
13858 #else
13859 	p += 8;  /* skip line info */
13860 #endif
13861 
13862 	/* duk_hcompfunc flags; quite version specific */
13863 	tmp32 = DUK_RAW_READ_U32_BE(p);
13864 	DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) h_fun, tmp32);  /* masks flags to only change duk_hobject flags */
13865 
13866 	/* standard prototype (no need to set here, already set) */
13867 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_fun) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
13868 #if 0
13869 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &h_fun->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
13870 #endif
13871 
13872 	/* assert just a few critical flags */
13873 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h_fun) == DUK_HTYPE_OBJECT);
13874 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&h_fun->obj));
13875 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(&h_fun->obj));
13876 	DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(&h_fun->obj));
13877 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(&h_fun->obj));
13878 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&h_fun->obj));
13879 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&h_fun->obj));
13880 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&h_fun->obj));
13881 
13882 	/* Create function 'data' buffer but don't attach it yet. */
13883 	fun_data = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, data_size);
13884 	DUK_ASSERT(fun_data != NULL);
13885 
13886 	/* Load bytecode instructions. */
13887 	DUK_ASSERT(sizeof(duk_instr_t) == 4);
13888 	DUK__ASSERT_LEFT(count_instr * sizeof(duk_instr_t));
13889 #if defined(DUK_USE_INTEGER_BE)
13890 	q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
13891 	duk_memcpy((void *) q,
13892 	           (const void *) p,
13893 	           sizeof(duk_instr_t) * count_instr);
13894 	p += sizeof(duk_instr_t) * count_instr;
13895 #else
13896 	q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
13897 	for (n = count_instr; n > 0; n--) {
13898 		*((duk_instr_t *) (void *) q) = DUK_RAW_READ_U32_BE(p);
13899 		q += sizeof(duk_instr_t);
13900 	}
13901 #endif
13902 
13903 	/* Load constants onto value stack but don't yet copy to buffer. */
13904 	for (n = count_const; n > 0; n--) {
13905 		DUK__ASSERT_LEFT(1);
13906 		const_type = DUK_RAW_READ_U8(p);
13907 		switch (const_type) {
13908 		case DUK__SER_STRING: {
13909 			p = duk__load_string_raw(thr, p);
13910 			break;
13911 		}
13912 		case DUK__SER_NUMBER: {
13913 			/* Important to do a fastint check so that constants are
13914 			 * properly read back as fastints.
13915 			 */
13916 			duk_tval tv_tmp;
13917 			duk_double_t val;
13918 			DUK__ASSERT_LEFT(8);
13919 			val = DUK_RAW_READ_DOUBLE_BE(p);
13920 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(&tv_tmp, val);
13921 			duk_push_tval(thr, &tv_tmp);
13922 			break;
13923 		}
13924 		default: {
13925 			goto format_error;
13926 		}
13927 		}
13928 	}
13929 
13930 	/* Load inner functions to value stack, but don't yet copy to buffer. */
13931 	for (n = count_funcs; n > 0; n--) {
13932 		p = duk__load_func(thr, p, p_end);
13933 		if (p == NULL) {
13934 			goto format_error;
13935 		}
13936 	}
13937 
13938 	/* With constants and inner functions on value stack, we can now
13939 	 * atomically finish the function 'data' buffer, bump refcounts,
13940 	 * etc.
13941 	 *
13942 	 * Here we take advantage of the value stack being just a duk_tval
13943 	 * array: we can just memcpy() the constants as long as we incref
13944 	 * them afterwards.
13945 	 */
13946 
13947 	h_data = (duk_hbuffer *) duk_known_hbuffer(thr, idx_base + 1);
13948 	DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC(h_data));
13949 	DUK_HCOMPFUNC_SET_DATA(thr->heap, h_fun, h_data);
13950 	DUK_HBUFFER_INCREF(thr, h_data);
13951 
13952 	tv1 = duk_get_tval(thr, idx_base + 2);  /* may be NULL if no constants or inner funcs */
13953 	DUK_ASSERT((count_const == 0 && count_funcs == 0) || tv1 != NULL);
13954 
13955 	q = fun_data;
13956 	duk_memcpy_unsafe((void *) q, (const void *) tv1, sizeof(duk_tval) * count_const);
13957 	for (n = count_const; n > 0; n--) {
13958 		DUK_TVAL_INCREF_FAST(thr, (duk_tval *) (void *) q);  /* no side effects */
13959 		q += sizeof(duk_tval);
13960 	}
13961 	tv1 += count_const;
13962 
13963 	DUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_fun, (duk_hobject **) (void *) q);
13964 	for (n = count_funcs; n > 0; n--) {
13965 		duk_hobject *h_obj;
13966 
13967 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
13968 		h_obj = DUK_TVAL_GET_OBJECT(tv1);
13969 		DUK_ASSERT(h_obj != NULL);
13970 		tv1++;
13971 		DUK_HOBJECT_INCREF(thr, h_obj);
13972 
13973 		*((duk_hobject **) (void *) q) = h_obj;
13974 		q += sizeof(duk_hobject *);
13975 	}
13976 
13977 	DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, h_fun, (duk_instr_t *) (void *) q);
13978 
13979 	/* The function object is now reachable and refcounts are fine,
13980 	 * so we can pop off all the temporaries.
13981 	 */
13982 	DUK_DDD(DUK_DDDPRINT("function is reachable, reset top; func: %!iT", duk_get_tval(thr, idx_base)));
13983 	duk_set_top(thr, idx_base + 1);
13984 
13985 	/* Setup function properties. */
13986 	tmp32 = DUK_RAW_READ_U32_BE(p);
13987 	duk_push_u32(thr, tmp32);
13988 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
13989 
13990 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
13991 	p = duk__load_string_raw(thr, p);  /* -> [ func funcname ] */
13992 	func_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
13993 	DUK_ASSERT(func_env != NULL);
13994 	need_pop = 0;
13995 	if (DUK_HOBJECT_HAS_NAMEBINDING((duk_hobject *) h_fun)) {
13996 		/* Original function instance/template had NAMEBINDING.
13997 		 * Must create a lexical environment on loading to allow
13998 		 * recursive functions like 'function foo() { foo(); }'.
13999 		 */
14000 		duk_hdecenv *new_env;
14001 
14002 		new_env = duk_hdecenv_alloc(thr,
14003 		                            DUK_HOBJECT_FLAG_EXTENSIBLE |
14004 		                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
14005 		DUK_ASSERT(new_env != NULL);
14006 		DUK_ASSERT(new_env->thread == NULL);  /* Closed. */
14007 		DUK_ASSERT(new_env->varmap == NULL);
14008 		DUK_ASSERT(new_env->regbase_byteoff == 0);
14009 		DUK_ASSERT_HDECENV_VALID(new_env);
14010 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
14011 		DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, func_env);
14012 		DUK_HOBJECT_INCREF(thr, func_env);
14013 
14014 		func_env = (duk_hobject *) new_env;
14015 
14016 		duk_push_hobject(thr, (duk_hobject *) new_env);
14017 
14018 		duk_dup_m2(thr);                                  /* -> [ func funcname env funcname ] */
14019 		duk_dup(thr, idx_base);                           /* -> [ func funcname env funcname func ] */
14020 		duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_NONE);  /* -> [ func funcname env ] */
14021 
14022 		need_pop = 1;  /* Need to pop env, but -after- updating h_fun and increfs. */
14023 	}
14024 	DUK_ASSERT(func_env != NULL);
14025 	DUK_HCOMPFUNC_SET_LEXENV(thr->heap, h_fun, func_env);
14026 	DUK_HCOMPFUNC_SET_VARENV(thr->heap, h_fun, func_env);
14027 	DUK_HOBJECT_INCREF(thr, func_env);
14028 	DUK_HOBJECT_INCREF(thr, func_env);
14029 	if (need_pop) {
14030 		duk_pop(thr);
14031 	}
14032 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
14033 #endif  /* DUK_USE_FUNC_NAME_PROPERTY */
14034 
14035 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
14036 	p = duk__load_string_raw(thr, p);
14037 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C);
14038 #endif  /* DUK_USE_FUNC_FILENAME_PROPERTY */
14039 
14040 	if (DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_fun)) {
14041 		/* Restore empty external .prototype only for constructable
14042 		 * functions.
14043 		 */
14044 		duk_push_object(thr);
14045 		duk_dup_m2(thr);
14046 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);  /* func.prototype.constructor = func */
14047 		duk_compact_m1(thr);
14048 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);
14049 	}
14050 
14051 #if defined(DUK_USE_PC2LINE)
14052 	p = duk__load_buffer_raw(thr, p);
14053 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_WC);
14054 #endif  /* DUK_USE_PC2LINE */
14055 
14056 	duk_push_object(thr);  /* _Varmap */
14057 	for (;;) {
14058 		/* XXX: awkward */
14059 		p = duk__load_string_raw(thr, p);
14060 		if (duk_get_length(thr, -1) == 0) {
14061 			duk_pop(thr);
14062 			break;
14063 		}
14064 		tmp32 = DUK_RAW_READ_U32_BE(p);
14065 		duk_push_u32(thr, tmp32);
14066 		duk_put_prop(thr, -3);
14067 	}
14068 	duk_compact_m1(thr);
14069 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);
14070 
14071 	/* _Formals may have been missing in the original function, which is
14072 	 * handled using a marker length.
14073 	 */
14074 	arr_limit = DUK_RAW_READ_U32_BE(p);
14075 	if (arr_limit != DUK__NO_FORMALS) {
14076 		duk_push_array(thr);  /* _Formals */
14077 		for (arr_idx = 0; arr_idx < arr_limit; arr_idx++) {
14078 			p = duk__load_string_raw(thr, p);
14079 			duk_put_prop_index(thr, -2, arr_idx);
14080 		}
14081 		duk_compact_m1(thr);
14082 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);
14083 	} else {
14084 		DUK_DD(DUK_DDPRINT("no _Formals in dumped function"));
14085 	}
14086 
14087 	/* Return with final function pushed on stack top. */
14088 	DUK_DD(DUK_DDPRINT("final loaded function: %!iT", duk_get_tval(thr, -1)));
14089 	DUK_ASSERT_TOP(thr, idx_base + 1);
14090 	return p;
14091 
14092  format_error:
14093 	return NULL;
14094 }
14095 
duk_dump_function(duk_hthread * thr)14096 DUK_EXTERNAL void duk_dump_function(duk_hthread *thr) {
14097 	duk_hcompfunc *func;
14098 	duk_bufwriter_ctx bw_ctx_alloc;
14099 	duk_bufwriter_ctx *bw_ctx = &bw_ctx_alloc;
14100 	duk_uint8_t *p;
14101 
14102 	DUK_ASSERT_API_ENTRY(thr);
14103 
14104 	/* Bound functions don't have all properties so we'd either need to
14105 	 * lookup the non-bound target function or reject bound functions.
14106 	 * For now, bound functions are rejected with TypeError.
14107 	 */
14108 	func = duk_require_hcompfunc(thr, -1);
14109 	DUK_ASSERT(func != NULL);
14110 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&func->obj));
14111 
14112 	/* Estimating the result size beforehand would be costly, so
14113 	 * start with a reasonable size and extend as needed.
14114 	 */
14115 	DUK_BW_INIT_PUSHBUF(thr, bw_ctx, DUK__BYTECODE_INITIAL_ALLOC);
14116 	p = DUK_BW_GET_PTR(thr, bw_ctx);
14117 	*p++ = DUK__SER_MARKER;
14118 	p = duk__dump_func(thr, func, bw_ctx, p);
14119 	DUK_BW_SET_PTR(thr, bw_ctx, p);
14120 	DUK_BW_COMPACT(thr, bw_ctx);
14121 
14122 	DUK_DD(DUK_DDPRINT("serialized result: %!T", duk_get_tval(thr, -1)));
14123 
14124 	duk_remove_m2(thr);  /* [ ... func buf ] -> [ ... buf ] */
14125 }
14126 
duk_load_function(duk_hthread * thr)14127 DUK_EXTERNAL void duk_load_function(duk_hthread *thr) {
14128 	duk_uint8_t *p_buf, *p, *p_end;
14129 	duk_size_t sz;
14130 
14131 	DUK_ASSERT_API_ENTRY(thr);
14132 
14133 	p_buf = (duk_uint8_t *) duk_require_buffer(thr, -1, &sz);
14134 	DUK_ASSERT(p_buf != NULL);
14135 
14136 	/* The caller is responsible for being sure that bytecode being loaded
14137 	 * is valid and trusted.  Invalid bytecode can cause memory unsafe
14138 	 * behavior directly during loading or later during bytecode execution
14139 	 * (instruction validation would be quite complex to implement).
14140 	 *
14141 	 * This signature check is the only sanity check for detecting
14142 	 * accidental invalid inputs.  The initial byte ensures no ordinary
14143 	 * string or Symbol will be accepted by accident.
14144 	 */
14145 	p = p_buf;
14146 	p_end = p_buf + sz;
14147 	if (sz < 1 || p[0] != DUK__SER_MARKER) {
14148 		goto format_error;
14149 	}
14150 	p++;
14151 
14152 	p = duk__load_func(thr, p, p_end);
14153 	if (p == NULL) {
14154 		goto format_error;
14155 	}
14156 
14157 	duk_remove_m2(thr);  /* [ ... buf func ] -> [ ... func ] */
14158 	return;
14159 
14160  format_error:
14161 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BYTECODE);
14162 	DUK_WO_NORETURN(return;);
14163 }
14164 
14165 #else  /* DUK_USE_BYTECODE_DUMP_SUPPORT */
14166 
duk_dump_function(duk_hthread * thr)14167 DUK_EXTERNAL void duk_dump_function(duk_hthread *thr) {
14168 	DUK_ASSERT_API_ENTRY(thr);
14169 	DUK_ERROR_UNSUPPORTED(thr);
14170 	DUK_WO_NORETURN(return;);
14171 }
14172 
duk_load_function(duk_hthread * thr)14173 DUK_EXTERNAL void duk_load_function(duk_hthread *thr) {
14174 	DUK_ASSERT_API_ENTRY(thr);
14175 	DUK_ERROR_UNSUPPORTED(thr);
14176 	DUK_WO_NORETURN(return;);
14177 }
14178 
14179 #endif  /* DUK_USE_BYTECODE_DUMP_SUPPORT */
14180 
14181 /* automatic undefs */
14182 #undef DUK__ASSERT_LEFT
14183 #undef DUK__BYTECODE_INITIAL_ALLOC
14184 #undef DUK__NO_FORMALS
14185 #undef DUK__SER_MARKER
14186 #undef DUK__SER_NUMBER
14187 #undef DUK__SER_STRING
14188 #line 1 "duk_api_call.c"
14189 /*
14190  *  Calls.
14191  *
14192  *  Protected variants should avoid ever throwing an error.  Must be careful
14193  *  to catch errors related to value stack manipulation and property lookup,
14194  *  not just the call itself.
14195  *
14196  *  The only exception is when arguments are insane, e.g. nargs/nrets are out
14197  *  of bounds; in such cases an error is thrown for two reasons.  First, we
14198  *  can't always respect the value stack input/output guarantees in such cases
14199  *  so the caller would end up with the value stack in an unexpected state.
14200  *  Second, an attempt to create an error might itself fail (although this
14201  *  could be avoided by pushing a preallocated object/string or a primitive
14202  *  value).
14203  */
14204 
14205 /* #include duk_internal.h -> already included */
14206 
14207 /*
14208  *  Helpers
14209  */
14210 
14211 struct duk__pcall_prop_args {
14212 	duk_idx_t obj_idx;
14213 	duk_idx_t nargs;
14214 	duk_small_uint_t call_flags;
14215 };
14216 typedef struct duk__pcall_prop_args duk__pcall_prop_args;
14217 
14218 struct duk__pcall_method_args {
14219 	duk_idx_t nargs;
14220 	duk_small_uint_t call_flags;
14221 };
14222 typedef struct duk__pcall_method_args duk__pcall_method_args;
14223 
14224 struct duk__pcall_args {
14225 	duk_idx_t nargs;
14226 	duk_small_uint_t call_flags;
14227 };
14228 typedef struct duk__pcall_args duk__pcall_args;
14229 
14230 /* Compute and validate idx_func for a certain 'nargs' and 'other'
14231  * parameter count (1 or 2, depending on whether 'this' binding is
14232  * present).
14233  */
duk__call_get_idx_func(duk_hthread * thr,duk_idx_t nargs,duk_idx_t other)14234 DUK_LOCAL duk_idx_t duk__call_get_idx_func(duk_hthread *thr, duk_idx_t nargs, duk_idx_t other) {
14235 	duk_idx_t idx_func;
14236 
14237 	/* XXX: byte arithmetic? */
14238 
14239 	DUK_ASSERT(other >= 0);
14240 
14241 	idx_func = duk_get_top(thr) - nargs - other;
14242 	if (DUK_UNLIKELY((idx_func | nargs) < 0)) {  /* idx_func < 0 || nargs < 0; OR sign bits */
14243 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14244 		DUK_WO_NORETURN(return 0;);
14245 	}
14246 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14247 	return idx_func;
14248 }
14249 
14250 /* Compute idx_func, assume index will be valid.  This is a valid assumption
14251  * for protected calls: nargs < 0 is checked explicitly and duk_safe_call()
14252  * validates the argument count.
14253  */
duk__call_get_idx_func_unvalidated(duk_hthread * thr,duk_idx_t nargs,duk_idx_t other)14254 DUK_LOCAL duk_idx_t duk__call_get_idx_func_unvalidated(duk_hthread *thr, duk_idx_t nargs, duk_idx_t other) {
14255 	duk_idx_t idx_func;
14256 
14257 	/* XXX: byte arithmetic? */
14258 
14259 	DUK_ASSERT(nargs >= 0);
14260 	DUK_ASSERT(other >= 0);
14261 
14262 	idx_func = duk_get_top(thr) - nargs - other;
14263 	DUK_ASSERT(idx_func >= 0);
14264 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14265 	return idx_func;
14266 }
14267 
14268 /* Prepare value stack for a method call through an object property.
14269  * May currently throw an error e.g. when getting the property.
14270  */
duk__call_prop_prep_stack(duk_hthread * thr,duk_idx_t normalized_obj_idx,duk_idx_t nargs)14271 DUK_LOCAL void duk__call_prop_prep_stack(duk_hthread *thr, duk_idx_t normalized_obj_idx, duk_idx_t nargs) {
14272 	DUK_ASSERT_CTX_VALID(thr);
14273 	DUK_ASSERT(nargs >= 0);
14274 
14275 	DUK_DDD(DUK_DDDPRINT("duk__call_prop_prep_stack, normalized_obj_idx=%ld, nargs=%ld, stacktop=%ld",
14276 	                     (long) normalized_obj_idx, (long) nargs, (long) duk_get_top(thr)));
14277 
14278 	/* [... key arg1 ... argN] */
14279 
14280 	/* duplicate key */
14281 	duk_dup(thr, -nargs - 1);  /* Note: -nargs alone would fail for nargs == 0, this is OK */
14282 	(void) duk_get_prop(thr, normalized_obj_idx);
14283 
14284 	DUK_DDD(DUK_DDDPRINT("func: %!T", (duk_tval *) duk_get_tval(thr, -1)));
14285 
14286 #if defined(DUK_USE_VERBOSE_ERRORS)
14287 	if (DUK_UNLIKELY(!duk_is_callable(thr, -1))) {
14288 		duk_tval *tv_targ;
14289 		duk_tval *tv_base;
14290 		duk_tval *tv_key;
14291 
14292 		tv_targ = DUK_GET_TVAL_NEGIDX(thr, -1);
14293 		tv_base = DUK_GET_TVAL_POSIDX(thr, normalized_obj_idx);
14294 		tv_key = DUK_GET_TVAL_NEGIDX(thr, -nargs - 2);
14295 		DUK_ASSERT(tv_targ >= thr->valstack_bottom && tv_targ < thr->valstack_top);
14296 		DUK_ASSERT(tv_base >= thr->valstack_bottom && tv_base < thr->valstack_top);
14297 		DUK_ASSERT(tv_key >= thr->valstack_bottom && tv_key < thr->valstack_top);
14298 
14299 		duk_call_setup_propcall_error(thr, tv_targ, tv_base, tv_key);
14300 	}
14301 #endif
14302 
14303 	/* [... key arg1 ... argN func] */
14304 
14305 	duk_replace(thr, -nargs - 2);
14306 
14307 	/* [... func arg1 ... argN] */
14308 
14309 	duk_dup(thr, normalized_obj_idx);
14310 	duk_insert(thr, -nargs - 1);
14311 
14312 	/* [... func this arg1 ... argN] */
14313 }
14314 
duk_call(duk_hthread * thr,duk_idx_t nargs)14315 DUK_EXTERNAL void duk_call(duk_hthread *thr, duk_idx_t nargs) {
14316 	duk_small_uint_t call_flags;
14317 	duk_idx_t idx_func;
14318 
14319 	DUK_ASSERT_API_ENTRY(thr);
14320 
14321 	idx_func = duk__call_get_idx_func(thr, nargs, 1);
14322 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14323 
14324 	duk_insert_undefined(thr, idx_func + 1);
14325 
14326 	call_flags = 0;  /* not protected, respect reclimit, not constructor */
14327 	duk_handle_call_unprotected(thr, idx_func, call_flags);
14328 }
14329 
duk_call_method(duk_hthread * thr,duk_idx_t nargs)14330 DUK_EXTERNAL void duk_call_method(duk_hthread *thr, duk_idx_t nargs) {
14331 	duk_small_uint_t call_flags;
14332 	duk_idx_t idx_func;
14333 
14334 	DUK_ASSERT_API_ENTRY(thr);
14335 
14336 	idx_func = duk__call_get_idx_func(thr, nargs, 2);
14337 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14338 
14339 	call_flags = 0;  /* not protected, respect reclimit, not constructor */
14340 	duk_handle_call_unprotected(thr, idx_func, call_flags);
14341 }
14342 
duk_call_prop(duk_hthread * thr,duk_idx_t obj_idx,duk_idx_t nargs)14343 DUK_EXTERNAL void duk_call_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t nargs) {
14344 	/*
14345 	 *  XXX: if duk_handle_call() took values through indices, this could be
14346 	 *  made much more sensible.  However, duk_handle_call() needs to fudge
14347 	 *  the 'this' and 'func' values to handle bound functions, which is now
14348 	 *  done "in-place", so this is not a trivial change.
14349 	 */
14350 
14351 	DUK_ASSERT_API_ENTRY(thr);
14352 
14353 	obj_idx = duk_require_normalize_index(thr, obj_idx);  /* make absolute */
14354 	if (DUK_UNLIKELY(nargs < 0)) {
14355 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14356 		DUK_WO_NORETURN(return;);
14357 	}
14358 
14359 	duk__call_prop_prep_stack(thr, obj_idx, nargs);
14360 
14361 	duk_call_method(thr, nargs);
14362 }
14363 
duk__pcall_raw(duk_hthread * thr,void * udata)14364 DUK_LOCAL duk_ret_t duk__pcall_raw(duk_hthread *thr, void *udata) {
14365 	duk__pcall_args *args;
14366 	duk_idx_t idx_func;
14367 	duk_int_t ret;
14368 
14369 	DUK_ASSERT_CTX_VALID(thr);
14370 	DUK_ASSERT(udata != NULL);
14371 
14372 	args = (duk__pcall_args *) udata;
14373 	idx_func = duk__call_get_idx_func_unvalidated(thr, args->nargs, 1);
14374 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14375 
14376 	duk_insert_undefined(thr, idx_func + 1);
14377 
14378 	ret = duk_handle_call_unprotected(thr, idx_func, args->call_flags);
14379 	DUK_ASSERT(ret == 0);
14380 	DUK_UNREF(ret);
14381 
14382 	return 1;
14383 }
14384 
duk_pcall(duk_hthread * thr,duk_idx_t nargs)14385 DUK_EXTERNAL duk_int_t duk_pcall(duk_hthread *thr, duk_idx_t nargs) {
14386 	duk__pcall_args args;
14387 
14388 	DUK_ASSERT_API_ENTRY(thr);
14389 
14390 	args.nargs = nargs;
14391 	if (DUK_UNLIKELY(nargs < 0)) {
14392 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14393 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14394 	}
14395 	args.call_flags = 0;
14396 
14397 	return duk_safe_call(thr, duk__pcall_raw, (void *) &args /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
14398 }
14399 
duk__pcall_method_raw(duk_hthread * thr,void * udata)14400 DUK_LOCAL duk_ret_t duk__pcall_method_raw(duk_hthread *thr, void *udata) {
14401 	duk__pcall_method_args *args;
14402 	duk_idx_t idx_func;
14403 	duk_int_t ret;
14404 
14405 	DUK_ASSERT_CTX_VALID(thr);
14406 	DUK_ASSERT(udata != NULL);
14407 
14408 	args = (duk__pcall_method_args *) udata;
14409 
14410 	idx_func = duk__call_get_idx_func_unvalidated(thr, args->nargs, 2);
14411 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14412 
14413 	ret = duk_handle_call_unprotected(thr, idx_func, args->call_flags);
14414 	DUK_ASSERT(ret == 0);
14415 	DUK_UNREF(ret);
14416 
14417 	return 1;
14418 }
14419 
duk_pcall_method_flags(duk_hthread * thr,duk_idx_t nargs,duk_small_uint_t call_flags)14420 DUK_INTERNAL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags) {
14421 	duk__pcall_method_args args;
14422 
14423 	DUK_ASSERT_API_ENTRY(thr);
14424 
14425 	args.nargs = nargs;
14426 	if (DUK_UNLIKELY(nargs < 0)) {
14427 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14428 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14429 	}
14430 	args.call_flags = call_flags;
14431 
14432 	return duk_safe_call(thr, duk__pcall_method_raw, (void *) &args /*udata*/, nargs + 2 /*nargs*/, 1 /*nrets*/);
14433 }
14434 
duk_pcall_method(duk_hthread * thr,duk_idx_t nargs)14435 DUK_EXTERNAL duk_int_t duk_pcall_method(duk_hthread *thr, duk_idx_t nargs) {
14436 	DUK_ASSERT_API_ENTRY(thr);
14437 
14438 	return duk_pcall_method_flags(thr, nargs, 0);
14439 }
14440 
duk__pcall_prop_raw(duk_hthread * thr,void * udata)14441 DUK_LOCAL duk_ret_t duk__pcall_prop_raw(duk_hthread *thr, void *udata) {
14442 	duk__pcall_prop_args *args;
14443 	duk_idx_t obj_idx;
14444 	duk_int_t ret;
14445 
14446 	DUK_ASSERT_CTX_VALID(thr);
14447 	DUK_ASSERT(udata != NULL);
14448 
14449 	args = (duk__pcall_prop_args *) udata;
14450 
14451 	obj_idx = duk_require_normalize_index(thr, args->obj_idx);  /* make absolute */
14452 	duk__call_prop_prep_stack(thr, obj_idx, args->nargs);
14453 
14454 	ret = duk_handle_call_unprotected_nargs(thr, args->nargs, args->call_flags);
14455 	DUK_ASSERT(ret == 0);
14456 	DUK_UNREF(ret);
14457 	return 1;
14458 }
14459 
duk_pcall_prop(duk_hthread * thr,duk_idx_t obj_idx,duk_idx_t nargs)14460 DUK_EXTERNAL duk_int_t duk_pcall_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t nargs) {
14461 	duk__pcall_prop_args args;
14462 
14463 	DUK_ASSERT_API_ENTRY(thr);
14464 
14465 	args.obj_idx = obj_idx;
14466 	args.nargs = nargs;
14467 	if (DUK_UNLIKELY(nargs < 0)) {
14468 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14469 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14470 	}
14471 	args.call_flags = 0;
14472 
14473 	return duk_safe_call(thr, duk__pcall_prop_raw, (void *) &args /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
14474 }
14475 
duk_safe_call(duk_hthread * thr,duk_safe_call_function func,void * udata,duk_idx_t nargs,duk_idx_t nrets)14476 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) {
14477 	duk_int_t rc;
14478 
14479 	DUK_ASSERT_API_ENTRY(thr);
14480 
14481 	/* nargs condition; fail if: top - bottom < nargs
14482 	 *                      <=>  top < bottom + nargs
14483 	 * nrets condition; fail if: end - (top - nargs) < nrets
14484 	 *                      <=>  end - top + nargs < nrets
14485 	 *                      <=>  end + nargs < top + nrets
14486 	 */
14487 	/* XXX: check for any reserve? */
14488 
14489 	if (DUK_UNLIKELY((nargs | nrets) < 0 ||  /* nargs < 0 || nrets < 0; OR sign bits */
14490 	                 thr->valstack_top < thr->valstack_bottom + nargs ||        /* nargs too large compared to top */
14491 	                 thr->valstack_end + nargs < thr->valstack_top + nrets)) {  /* nrets too large compared to reserve */
14492 		DUK_D(DUK_DPRINT("not enough stack reserve for safe call or invalid arguments: "
14493 		                 "nargs=%ld < 0 (?), nrets=%ld < 0 (?), top=%ld < bottom=%ld + nargs=%ld (?), "
14494 		                 "end=%ld + nargs=%ld < top=%ld + nrets=%ld (?)",
14495 		                  (long) nargs,
14496 		                  (long) nrets,
14497 		                  (long) (thr->valstack_top - thr->valstack),
14498 		                  (long) (thr->valstack_bottom - thr->valstack),
14499 		                  (long) nargs,
14500 		                  (long) (thr->valstack_end - thr->valstack),
14501 		                  (long) nargs,
14502 		                  (long) (thr->valstack_top - thr->valstack),
14503 		                  (long) nrets));
14504 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14505 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14506 	}
14507 
14508 	rc = duk_handle_safe_call(thr,           /* thread */
14509 	                          func,          /* func */
14510 	                          udata,         /* udata */
14511 	                          nargs,         /* num_stack_args */
14512 	                          nrets);        /* num_stack_res */
14513 
14514 	return rc;
14515 }
14516 
duk_new(duk_hthread * thr,duk_idx_t nargs)14517 DUK_EXTERNAL void duk_new(duk_hthread *thr, duk_idx_t nargs) {
14518 	duk_idx_t idx_func;
14519 
14520 	DUK_ASSERT_API_ENTRY(thr);
14521 
14522 	idx_func = duk__call_get_idx_func(thr, nargs, 1);
14523 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14524 
14525 	duk_push_object(thr);  /* default instance; internal proto updated by call handling */
14526 	duk_insert(thr, idx_func + 1);
14527 
14528 	duk_handle_call_unprotected(thr, idx_func, DUK_CALL_FLAG_CONSTRUCT);
14529 }
14530 
duk__pnew_helper(duk_hthread * thr,void * udata)14531 DUK_LOCAL duk_ret_t duk__pnew_helper(duk_hthread *thr, void *udata) {
14532 	duk_idx_t nargs;
14533 
14534 	DUK_ASSERT(udata != NULL);
14535 	nargs = *((duk_idx_t *) udata);
14536 
14537 	duk_new(thr, nargs);
14538 	return 1;
14539 }
14540 
duk_pnew(duk_hthread * thr,duk_idx_t nargs)14541 DUK_EXTERNAL duk_int_t duk_pnew(duk_hthread *thr, duk_idx_t nargs) {
14542 	duk_int_t rc;
14543 
14544 	DUK_ASSERT_API_ENTRY(thr);
14545 
14546 	/* For now, just use duk_safe_call() to wrap duk_new().  We can't
14547 	 * simply use a protected duk_handle_call() because pushing the
14548 	 * default instance might throw.
14549 	 */
14550 
14551 	if (DUK_UNLIKELY(nargs < 0)) {
14552 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14553 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14554 	}
14555 
14556 	rc = duk_safe_call(thr, duk__pnew_helper, (void *) &nargs /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
14557 	return rc;
14558 }
14559 
duk_is_constructor_call(duk_hthread * thr)14560 DUK_EXTERNAL duk_bool_t duk_is_constructor_call(duk_hthread *thr) {
14561 	duk_activation *act;
14562 
14563 	DUK_ASSERT_API_ENTRY(thr);
14564 
14565 	act = thr->callstack_curr;
14566 	if (act != NULL) {
14567 		return ((act->flags & DUK_ACT_FLAG_CONSTRUCT) != 0 ? 1 : 0);
14568 	}
14569 	return 0;
14570 }
14571 
14572 /* XXX: Make this obsolete by adding a function flag for rejecting a
14573  * non-constructor call automatically?
14574  */
duk_require_constructor_call(duk_hthread * thr)14575 DUK_INTERNAL void duk_require_constructor_call(duk_hthread *thr) {
14576 	DUK_ASSERT_API_ENTRY(thr);
14577 
14578 	if (!duk_is_constructor_call(thr)) {
14579 		DUK_ERROR_TYPE(thr, DUK_STR_CONSTRUCT_ONLY);
14580 		DUK_WO_NORETURN(return;);
14581 	}
14582 }
14583 
duk_is_strict_call(duk_hthread * thr)14584 DUK_EXTERNAL duk_bool_t duk_is_strict_call(duk_hthread *thr) {
14585 	duk_activation *act;
14586 
14587 	/* For user code this could just return 1 (strict) always
14588 	 * because all Duktape/C functions are considered strict,
14589 	 * and strict is also the default when nothing is running.
14590 	 * However, Duktape may call this function internally when
14591 	 * the current activation is an ECMAScript function, so
14592 	 * this cannot be replaced by a 'return 1' without fixing
14593 	 * the internal call sites.
14594 	 */
14595 
14596 	DUK_ASSERT_API_ENTRY(thr);
14597 
14598 	act = thr->callstack_curr;
14599 	if (act != NULL) {
14600 		return ((act->flags & DUK_ACT_FLAG_STRICT) != 0 ? 1 : 0);
14601 	} else {
14602 		/* Strict by default. */
14603 		return 1;
14604 	}
14605 }
14606 
14607 /*
14608  *  Duktape/C function magic
14609  */
14610 
duk_get_current_magic(duk_hthread * thr)14611 DUK_EXTERNAL duk_int_t duk_get_current_magic(duk_hthread *thr) {
14612 	duk_activation *act;
14613 	duk_hobject *func;
14614 
14615 	DUK_ASSERT_API_ENTRY(thr);
14616 
14617 	act = thr->callstack_curr;
14618 	if (act) {
14619 		func = DUK_ACT_GET_FUNC(act);
14620 		if (!func) {
14621 			duk_tval *tv = &act->tv_func;
14622 			duk_small_uint_t lf_flags;
14623 			lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
14624 			return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
14625 		}
14626 		DUK_ASSERT(func != NULL);
14627 
14628 		if (DUK_HOBJECT_IS_NATFUNC(func)) {
14629 			duk_hnatfunc *nf = (duk_hnatfunc *) func;
14630 			return (duk_int_t) nf->magic;
14631 		}
14632 	}
14633 	return 0;
14634 }
14635 
duk_get_magic(duk_hthread * thr,duk_idx_t idx)14636 DUK_EXTERNAL duk_int_t duk_get_magic(duk_hthread *thr, duk_idx_t idx) {
14637 	duk_tval *tv;
14638 	duk_hobject *h;
14639 
14640 	DUK_ASSERT_API_ENTRY(thr);
14641 
14642 	tv = duk_require_tval(thr, idx);
14643 	if (DUK_TVAL_IS_OBJECT(tv)) {
14644 		h = DUK_TVAL_GET_OBJECT(tv);
14645 		DUK_ASSERT(h != NULL);
14646 		if (!DUK_HOBJECT_HAS_NATFUNC(h)) {
14647 			goto type_error;
14648 		}
14649 		return (duk_int_t) ((duk_hnatfunc *) h)->magic;
14650 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
14651 		duk_small_uint_t lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
14652 		return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
14653 	}
14654 
14655 	/* fall through */
14656  type_error:
14657 	DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);
14658 	DUK_WO_NORETURN(return 0;);
14659 }
14660 
duk_set_magic(duk_hthread * thr,duk_idx_t idx,duk_int_t magic)14661 DUK_EXTERNAL void duk_set_magic(duk_hthread *thr, duk_idx_t idx, duk_int_t magic) {
14662 	duk_hnatfunc *nf;
14663 
14664 	DUK_ASSERT_API_ENTRY(thr);
14665 
14666 	nf = duk_require_hnatfunc(thr, idx);
14667 	DUK_ASSERT(nf != NULL);
14668 	nf->magic = (duk_int16_t) magic;
14669 }
14670 
14671 /*
14672  *  Misc helpers
14673  */
14674 
14675 /* Resolve a bound function on value stack top to a non-bound target
14676  * (leave other values as is).
14677  */
duk_resolve_nonbound_function(duk_hthread * thr)14678 DUK_INTERNAL void duk_resolve_nonbound_function(duk_hthread *thr) {
14679 	duk_tval *tv;
14680 
14681 	DUK_ASSERT_HTHREAD_VALID(thr);
14682 
14683 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
14684 	if (DUK_TVAL_IS_OBJECT(tv)) {
14685 		duk_hobject *h;
14686 
14687 		h = DUK_TVAL_GET_OBJECT(tv);
14688 		DUK_ASSERT(h != NULL);
14689 		if (DUK_HOBJECT_HAS_BOUNDFUNC(h)) {
14690 			duk_push_tval(thr, &((duk_hboundfunc *) (void *) h)->target);
14691 			duk_replace(thr, -2);
14692 #if 0
14693 			DUK_TVAL_SET_TVAL(tv, &((duk_hboundfunc *) h)->target);
14694 			DUK_TVAL_INCREF(thr, tv);
14695 			DUK_HOBJECT_DECREF_NORZ(thr, h);
14696 #endif
14697 			/* Rely on Function.prototype.bind() on never creating a bound
14698 			 * function whose target is not proper.  This is now safe
14699 			 * because the target is not even an internal property but a
14700 			 * struct member.
14701 			 */
14702 			DUK_ASSERT(duk_is_lightfunc(thr, -1) || duk_is_callable(thr, -1));
14703 		}
14704 	}
14705 
14706 	/* Lightfuncs cannot be bound but are always callable and
14707 	 * constructable.
14708 	 */
14709 }
14710 #line 1 "duk_api_codec.c"
14711 /*
14712  *  Encoding and decoding basic formats: hex, base64.
14713  *
14714  *  These are in-place operations which may allow an optimized implementation.
14715  *
14716  *  Base-64: https://tools.ietf.org/html/rfc4648#section-4
14717  */
14718 
14719 /* #include duk_internal.h -> already included */
14720 
14721 /*
14722  *  Misc helpers
14723  */
14724 
14725 /* Shared handling for encode/decode argument.  Fast path handling for
14726  * buffer and string values because they're the most common.  In particular,
14727  * avoid creating a temporary string or buffer when possible.
14728  */
duk__prep_codec_arg(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)14729 DUK_LOCAL const duk_uint8_t *duk__prep_codec_arg(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
14730 	void *ptr;
14731 	duk_bool_t isbuffer;
14732 
14733 	DUK_ASSERT(duk_is_valid_index(thr, idx));  /* checked by caller */
14734 
14735 	/* XXX: with def_ptr set to a stack related pointer, isbuffer could
14736 	 * be removed from the helper?
14737 	 */
14738 	ptr = duk_get_buffer_data_raw(thr, idx, out_len, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, &isbuffer);
14739 	if (isbuffer) {
14740 		DUK_ASSERT(*out_len == 0 || ptr != NULL);
14741 		return (const duk_uint8_t *) ptr;
14742 	}
14743 	return (const duk_uint8_t *) duk_to_lstring(thr, idx, out_len);
14744 }
14745 
14746 /*
14747  *  Base64
14748  */
14749 
14750 #if defined(DUK_USE_BASE64_SUPPORT)
14751 /* Bytes emitted for number of padding characters in range [0,4]. */
14752 DUK_LOCAL const duk_int8_t duk__base64_decode_nequal_step[5] = {
14753 	3,   /* #### -> 24 bits, emit 3 bytes */
14754 	2,   /* ###= -> 18 bits, emit 2 bytes */
14755 	1,   /* ##== -> 12 bits, emit 1 byte */
14756 	-1,  /* #=== -> 6 bits, error */
14757 	0,   /* ==== -> 0 bits, emit 0 bytes */
14758 };
14759 
14760 #if defined(DUK_USE_BASE64_FASTPATH)
14761 DUK_LOCAL const duk_uint8_t duk__base64_enctab_fast[64] = {
14762 	0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, 0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU, 0x50U,  /* A...P */
14763 	0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U, 0x58U, 0x59U, 0x5aU, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U,  /* Q...f */
14764 	0x67U, 0x68U, 0x69U, 0x6aU, 0x6bU, 0x6cU, 0x6dU, 0x6eU, 0x6fU, 0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U,  /* g...v */
14765 	0x77U, 0x78U, 0x79U, 0x7aU, 0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U, 0x38U, 0x39U, 0x2bU, 0x2fU   /* w.../ */
14766 };
14767 #endif  /* DUK_USE_BASE64_FASTPATH */
14768 
14769 #if defined(DUK_USE_BASE64_FASTPATH)
14770 /* Decode table for one byte of input:
14771  *   -1 = allowed whitespace
14772  *   -2 = padding
14773  *   -3 = error
14774  *    0...63 decoded bytes
14775  */
14776 DUK_LOCAL const duk_int8_t duk__base64_dectab_fast[256] = {
14777 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -1, -1, -3, -3, -1, -3, -3,  /* 0x00...0x0f */
14778 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0x10...0x1f */
14779 	-1, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, 62, -3, -3, -3, 63,  /* 0x20...0x2f */
14780 	52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -3, -3, -3, -2, -3, -3,  /* 0x30...0x3f */
14781 	-3,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,  /* 0x40...0x4f */
14782 	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -3, -3, -3, -3, -3,  /* 0x50...0x5f */
14783 	-3, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,  /* 0x60...0x6f */
14784 	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -3, -3, -3, -3, -3,  /* 0x70...0x7f */
14785 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0x80...0x8f */
14786 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0x90...0x9f */
14787 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xa0...0xaf */
14788 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xb0...0xbf */
14789 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xc0...0xcf */
14790 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xd0...0xdf */
14791 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xe0...0xef */
14792 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3   /* 0xf0...0xff */
14793 };
14794 #endif  /* DUK_USE_BASE64_FASTPATH */
14795 
14796 #if defined(DUK_USE_BASE64_FASTPATH)
duk__base64_encode_fast_3(const duk_uint8_t * src,duk_uint8_t * dst)14797 DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_3(const duk_uint8_t *src, duk_uint8_t *dst) {
14798 	duk_uint_t t;
14799 
14800 	t = (duk_uint_t) src[0];
14801 	t = (t << 8) + (duk_uint_t) src[1];
14802 	t = (t << 8) + (duk_uint_t) src[2];
14803 
14804 	dst[0] = duk__base64_enctab_fast[t >> 18];
14805 	dst[1] = duk__base64_enctab_fast[(t >> 12) & 0x3fU];
14806 	dst[2] = duk__base64_enctab_fast[(t >> 6) & 0x3fU];
14807 	dst[3] = duk__base64_enctab_fast[t & 0x3fU];
14808 
14809 #if 0
14810 	/* Tested: not faster on x64, most likely due to aliasing between
14811 	 * output and input index computation.
14812 	 */
14813 	/* aaaaaabb bbbbcccc ccdddddd */
14814 	dst[0] = duk__base64_enctab_fast[(src[0] >> 2) & 0x3fU];
14815 	dst[1] = duk__base64_enctab_fast[((src[0] << 4) & 0x30U) | ((src[1] >> 4) & 0x0fU)];
14816 	dst[2] = duk__base64_enctab_fast[((src[1] << 2) & 0x3fU) | ((src[2] >> 6) & 0x03U)];
14817 	dst[3] = duk__base64_enctab_fast[src[2] & 0x3fU];
14818 #endif
14819 }
14820 
duk__base64_encode_fast_2(const duk_uint8_t * src,duk_uint8_t * dst)14821 DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_2(const duk_uint8_t *src, duk_uint8_t *dst) {
14822 	duk_uint_t t;
14823 
14824 	t = (duk_uint_t) src[0];
14825 	t = (t << 8) + (duk_uint_t) src[1];
14826 	dst[0] = duk__base64_enctab_fast[t >> 10];           /* XXXXXX-- -------- */
14827 	dst[1] = duk__base64_enctab_fast[(t >> 4) & 0x3fU];  /* ------XX XXXX---- */
14828 	dst[2] = duk__base64_enctab_fast[(t << 2) & 0x3fU];  /* -------- ----XXXX */
14829 	dst[3] = DUK_ASC_EQUALS;
14830 }
14831 
duk__base64_encode_fast_1(const duk_uint8_t * src,duk_uint8_t * dst)14832 DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_1(const duk_uint8_t *src, duk_uint8_t *dst) {
14833 	duk_uint_t t;
14834 
14835 	t = (duk_uint_t) src[0];
14836 	dst[0] = duk__base64_enctab_fast[t >> 2];            /* XXXXXX-- */
14837 	dst[1] = duk__base64_enctab_fast[(t << 4) & 0x3fU];  /* ------XX */
14838 	dst[2] = DUK_ASC_EQUALS;
14839 	dst[3] = DUK_ASC_EQUALS;
14840 }
14841 
duk__base64_encode_helper(const duk_uint8_t * src,duk_size_t srclen,duk_uint8_t * dst)14842 DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
14843 	duk_size_t n;
14844 	const duk_uint8_t *p;
14845 	duk_uint8_t *q;
14846 
14847 	n = srclen;
14848 	p = src;
14849 	q = dst;
14850 
14851 	if (n >= 16U) {
14852 		/* Fast path, unrolled by 4, allows interleaving.  Process
14853 		 * 12-byte input chunks which encode to 16-char output chunks.
14854 		 * Only enter when at least one block is emitted (avoids div+mul
14855 		 * for short inputs too).
14856 		 */
14857 		const duk_uint8_t *p_end_fast;
14858 
14859 		p_end_fast = p + ((n / 12U) * 12U);
14860 		DUK_ASSERT(p_end_fast >= p + 12);
14861 		do {
14862 			duk__base64_encode_fast_3(p, q);
14863 			duk__base64_encode_fast_3(p + 3, q + 4);
14864 			duk__base64_encode_fast_3(p + 6, q + 8);
14865 			duk__base64_encode_fast_3(p + 9, q + 12);
14866 			p += 12;
14867 			q += 16;
14868 		} while (DUK_LIKELY(p != p_end_fast));
14869 
14870 		DUK_ASSERT(src + srclen >= p);
14871 		n = (duk_size_t) (src + srclen - p);
14872 		DUK_ASSERT(n < 12U);
14873 	}
14874 
14875 	/* Remainder. */
14876 	while (n >= 3U) {
14877 		duk__base64_encode_fast_3(p, q);
14878 		p += 3;
14879 		q += 4;
14880 		n -= 3U;
14881 	}
14882 	DUK_ASSERT(n == 0U || n == 1U || n == 2U);
14883 	if (n == 1U) {
14884 		duk__base64_encode_fast_1(p, q);
14885 #if 0  /* Unnecessary. */
14886 		p += 1;
14887 		q += 4;
14888 		n -= 1U;
14889 #endif
14890 	} else if (n == 2U) {
14891 		duk__base64_encode_fast_2(p, q);
14892 #if 0  /* Unnecessary. */
14893 		p += 2;
14894 		q += 4;
14895 		n -= 2U;
14896 #endif
14897 	} else {
14898 		DUK_ASSERT(n == 0U);  /* nothing to do */
14899 		;
14900 	}
14901 }
14902 #else  /* DUK_USE_BASE64_FASTPATH */
duk__base64_encode_helper(const duk_uint8_t * src,duk_size_t srclen,duk_uint8_t * dst)14903 DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
14904 	duk_small_uint_t i, npad;
14905 	duk_uint_t t, x, y;
14906 	const duk_uint8_t *p;
14907 	const duk_uint8_t *p_end;
14908 	duk_uint8_t *q;
14909 
14910 	p = src;
14911 	p_end = src + srclen;
14912 	q = dst;
14913 	npad = 0U;
14914 
14915 	while (p < p_end) {
14916 		/* Read 3 bytes into 't', padded by zero. */
14917 		t = 0;
14918 		for (i = 0; i < 3; i++) {
14919 			t = t << 8;
14920 			if (p < p_end) {
14921 				t += (duk_uint_t) (*p++);
14922 			} else {
14923 				/* This only happens on the last loop and we're
14924 				 * guaranteed to exit on the next loop.
14925 				 */
14926 				npad++;
14927 			}
14928 		}
14929 		DUK_ASSERT(npad <= 2U);
14930 
14931 		/* Emit 4 encoded characters.  If npad > 0, some of the
14932 		 * chars will be incorrect (zero bits) but we fix up the
14933 		 * padding after the loop.  A straightforward 64-byte
14934 		 * lookup would be faster and cleaner, but this is shorter.
14935 		 */
14936 		for (i = 0; i < 4; i++) {
14937 			x = ((t >> 18) & 0x3fU);
14938 			t = t << 6;
14939 
14940 			if (x <= 51U) {
14941 				if (x <= 25) {
14942 					y = x + DUK_ASC_UC_A;
14943 				} else {
14944 					y = x - 26 + DUK_ASC_LC_A;
14945 				}
14946 			} else {
14947 				if (x <= 61U) {
14948 					y = x - 52 + DUK_ASC_0;
14949 				} else if (x == 62) {
14950 					y = DUK_ASC_PLUS;
14951 				} else {
14952 					DUK_ASSERT(x == 63);
14953 					y = DUK_ASC_SLASH;
14954 				}
14955 			}
14956 
14957 			*q++ = (duk_uint8_t) y;
14958 		}
14959 	}
14960 
14961 	/* Handle padding by rewriting 0-2 bogus characters at the end.
14962 	 *
14963 	 *  Missing bytes    npad     base64 example
14964 	 *    0               0         ####
14965 	 *    1               1         ###=
14966 	 *    2               2         ##==
14967 	 */
14968 	DUK_ASSERT(npad <= 2U);
14969 	while (npad > 0U) {
14970 		*(q - npad) = DUK_ASC_EQUALS;
14971 		npad--;
14972 	}
14973 }
14974 #endif  /* DUK_USE_BASE64_FASTPATH */
14975 
14976 #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)14977 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) {
14978 	duk_int_t x;
14979 	duk_uint_t t;
14980 	duk_small_uint_t n_equal;
14981 	duk_int8_t step;
14982 	const duk_uint8_t *p;
14983 	const duk_uint8_t *p_end;
14984 	const duk_uint8_t *p_end_safe;
14985 	duk_uint8_t *q;
14986 
14987 	p = src;
14988 	p_end = src + srclen;
14989 	p_end_safe = p_end - 8;  /* If 'src <= src_end_safe', safe to read 8 bytes. */
14990 	q = dst;
14991 
14992 	/* Alternate between a fast path which processes clean groups with no
14993 	 * padding or whitespace, and a slow path which processes one arbitrary
14994 	 * group and then re-enters the fast path.  This handles e.g. base64
14995 	 * with newlines reasonably well because the majority of a line is in
14996 	 * the fast path.
14997 	 */
14998 	for (;;) {
14999 		/* Fast path, on each loop handle two 4-char input groups.
15000 		 * If both are clean, emit 6 bytes and continue.  If first
15001 		 * is clean, emit 3 bytes and drop out; otherwise emit
15002 		 * nothing and drop out.  This approach could be extended to
15003 		 * more groups per loop, but for inputs with e.g. periodic
15004 		 * newlines (which are common) it might not be an improvement.
15005 		 */
15006 		while (DUK_LIKELY(p <= p_end_safe)) {
15007 			duk_int_t t1, t2;
15008 
15009 			/* The lookup byte is intentionally sign extended to
15010 			 * (at least) 32 bits and then ORed.  This ensures
15011 			 * that is at least 1 byte is negative, the highest
15012 			 * bit of the accumulator will be set at the end and
15013 			 * we don't need to check every byte.
15014 			 *
15015 			 * Read all input bytes first before writing output
15016 			 * bytes to minimize aliasing.
15017 			 */
15018 			DUK_DDD(DUK_DDDPRINT("fast loop: p=%p, p_end_safe=%p, p_end=%p",
15019 			                     (const void *) p, (const void *) p_end_safe, (const void *) p_end));
15020 
15021 			t1 = (duk_int_t) duk__base64_dectab_fast[p[0]];
15022 			t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[1]];
15023 			t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[2]];
15024 			t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[3]];
15025 
15026 			t2 = (duk_int_t) duk__base64_dectab_fast[p[4]];
15027 			t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[5]];
15028 			t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[6]];
15029 			t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[7]];
15030 
15031 			q[0] = (duk_uint8_t) (((duk_uint_t) t1 >> 16) & 0xffU);
15032 			q[1] = (duk_uint8_t) (((duk_uint_t) t1 >> 8) & 0xffU);
15033 			q[2] = (duk_uint8_t) ((duk_uint_t) t1 & 0xffU);
15034 
15035 			q[3] = (duk_uint8_t) (((duk_uint_t) t2 >> 16) & 0xffU);
15036 			q[4] = (duk_uint8_t) (((duk_uint_t) t2 >> 8) & 0xffU);
15037 			q[5] = (duk_uint8_t) ((duk_uint_t) t2 & 0xffU);
15038 
15039 			/* Optimistic check using one branch. */
15040 			if (DUK_LIKELY((t1 | t2) >= 0)) {
15041 				p += 8;
15042 				q += 6;
15043 			} else if (t1 >= 0) {
15044 				DUK_DDD(DUK_DDDPRINT("fast loop first group was clean, second was not, process one slow path group"));
15045 				DUK_ASSERT(t2 < 0);
15046 				p += 4;
15047 				q += 3;
15048 				break;
15049 			} else {
15050 				DUK_DDD(DUK_DDDPRINT("fast loop first group was not clean, second does not matter, process one slow path group"));
15051 				DUK_ASSERT(t1 < 0);
15052 				break;
15053 			}
15054 		}  /* fast path */
15055 
15056 		/* Slow path step 1: try to scan a 4-character encoded group,
15057 		 * end-of-input, or start-of-padding.  We exit with:
15058 		 *   1. n_chars == 4: full group, no padding, no end-of-input.
15059 		 *   2. n_chars < 4: partial group (may also be 0), encountered
15060 		 *      padding or end of input.
15061 		 *
15062 		 * The accumulator is initialized to 1; this allows us to detect
15063 		 * a full group by comparing >= 0x1000000 without an extra
15064 		 * counter variable.
15065 		 */
15066 		t = 1UL;
15067 		for (;;) {
15068 			DUK_DDD(DUK_DDDPRINT("slow loop: p=%p, p_end=%p, t=%lu",
15069 			                     (const void *) p, (const void *) p_end, (unsigned long) t));
15070 
15071 			if (DUK_LIKELY(p < p_end)) {
15072 				x = duk__base64_dectab_fast[*p++];
15073 				if (DUK_LIKELY(x >= 0)) {
15074 					DUK_ASSERT(x >= 0 && x <= 63);
15075 					t = (t << 6) + (duk_uint_t) x;
15076 					if (t >= 0x1000000UL) {
15077 						break;
15078 					}
15079 				} else if (x == -1) {
15080 					continue;  /* allowed ascii whitespace */
15081 				} else if (x == -2) {
15082 					p--;
15083 					break;  /* start of padding */
15084 				} else {
15085 					DUK_ASSERT(x == -3);
15086 					goto decode_error;
15087 				}
15088 			} else {
15089 				break;  /* end of input */
15090 			}
15091 		}  /* slow path step 1 */
15092 
15093 		/* Complete the padding by simulating pad characters,
15094 		 * regardless of actual input padding chars.
15095 		 */
15096 		n_equal = 0;
15097 		while (t < 0x1000000UL) {
15098 			t = (t << 6) + 0U;
15099 			n_equal++;
15100 		}
15101 
15102 		/* Slow path step 2: deal with full/partial group, padding,
15103 		 * etc.  Note that for num chars in [0,3] we intentionally emit
15104 		 * 3 bytes but don't step forward that much, buffer space is
15105 		 * guaranteed in setup.
15106 		 *
15107 		 *  num chars:
15108 		 *   0      ####   no output (= step 0)
15109 		 *   1      #===   reject, 6 bits of data
15110 		 *   2      ##==   12 bits of data, output 1 byte (= step 1)
15111 		 *   3      ###=   18 bits of data, output 2 bytes (= step 2)
15112 		 *   4      ####   24 bits of data, output 3 bytes (= step 3)
15113 		 */
15114 		q[0] = (duk_uint8_t) ((t >> 16) & 0xffU);
15115 		q[1] = (duk_uint8_t) ((t >> 8) & 0xffU);
15116 		q[2] = (duk_uint8_t) (t & 0xffU);
15117 
15118 		DUK_ASSERT(n_equal <= 4);
15119 		step = duk__base64_decode_nequal_step[n_equal];
15120 		if (DUK_UNLIKELY(step < 0)) {
15121 			goto decode_error;
15122 		}
15123 		q += step;
15124 
15125 		/* Slow path step 3: read and ignore padding and whitespace
15126 		 * until (a) next non-padding and non-whitespace character
15127 		 * after which we resume the fast path, or (b) end of input.
15128 		 * This allows us to accept missing, partial, full, and extra
15129 		 * padding cases uniformly.  We also support concatenated
15130 		 * base-64 documents because we resume scanning afterwards.
15131 		 *
15132 		 * Note that to support concatenated documents well, the '='
15133 		 * padding found inside the input must also allow for 'extra'
15134 		 * padding.  For example, 'Zm===' decodes to 'f' and has one
15135 		 * extra padding char.  So, 'Zm===Zm' should decode 'ff', even
15136 		 * though the standard break-up would be 'Zm==' + '=Zm' which
15137 		 * doesn't make sense.
15138 		 *
15139 		 * We also accept prepended padding like '==Zm9', because it
15140 		 * is equivalent to an empty document with extra padding ('==')
15141 		 * followed by a valid document.
15142 		 */
15143 
15144 		for (;;) {
15145 			if (DUK_UNLIKELY(p >= p_end)) {
15146 				goto done;
15147 			}
15148 			x = duk__base64_dectab_fast[*p++];
15149 			if (x == -1 || x == -2) {
15150 				;  /* padding or whitespace, keep eating */
15151 			} else {
15152 				p--;
15153 				break;  /* backtrack and go back to fast path, even for -1 */
15154 			}
15155 		}  /* slow path step 3 */
15156 	}  /* outer fast+slow path loop */
15157 
15158  done:
15159 	DUK_DDD(DUK_DDDPRINT("done; p=%p, p_end=%p",
15160 	                     (const void *) p, (const void *) p_end));
15161 
15162 	DUK_ASSERT(p == p_end);
15163 
15164 	*out_dst_final = q;
15165 	return 1;
15166 
15167  decode_error:
15168 	return 0;
15169 }
15170 #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)15171 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) {
15172 	duk_uint_t t, x;
15173 	duk_int_t y;
15174 	duk_int8_t step;
15175 	const duk_uint8_t *p;
15176 	const duk_uint8_t *p_end;
15177 	duk_uint8_t *q;
15178 	/* 0x09, 0x0a, or 0x0d */
15179 	duk_uint32_t mask_white = (1U << 9) | (1U << 10) | (1U << 13);
15180 
15181 	/* 't' tracks progress of the decoded group:
15182 	 *
15183 	 *  t == 1             no valid chars yet
15184 	 *  t >= 0x40          1x6 = 6 bits shifted in
15185 	 *  t >= 0x1000        2x6 = 12 bits shifted in
15186 	 *  t >= 0x40000       3x6 = 18 bits shifted in
15187 	 *  t >= 0x1000000     4x6 = 24 bits shifted in
15188 	 *
15189 	 * By initializing t=1 there's no need for a separate counter for
15190 	 * the number of characters found so far.
15191 	 */
15192 	p = src;
15193 	p_end = src + srclen;
15194 	q = dst;
15195 	t = 1UL;
15196 
15197 	for (;;) {
15198 		duk_small_uint_t n_equal;
15199 
15200 		DUK_ASSERT(t >= 1U);
15201 		if (p >= p_end) {
15202 			/* End of input: if input exists, treat like
15203 			 * start of padding, finish the block, then
15204 			 * re-enter here to see we're done.
15205 			 */
15206 			if (t == 1U) {
15207 				break;
15208 			} else {
15209 				goto simulate_padding;
15210 			}
15211 		}
15212 
15213 		x = *p++;
15214 
15215 		if (x >= 0x41U) {
15216 			/* Valid: a-z and A-Z. */
15217 			DUK_ASSERT(x >= 0x41U && x <= 0xffU);
15218 			if (x >= 0x61U && x <= 0x7aU) {
15219 				y = (duk_int_t) x - 0x61 + 26;
15220 			} else if (x <= 0x5aU) {
15221 				y = (duk_int_t) x - 0x41;
15222 			} else {
15223 				goto decode_error;
15224 			}
15225 		} else if (x >= 0x30U) {
15226 			/* Valid: 0-9 and =. */
15227 			DUK_ASSERT(x >= 0x30U && x <= 0x40U);
15228 			if (x <= 0x39U) {
15229 				y = (duk_int_t) x - 0x30 + 52;
15230 			} else if (x == 0x3dU) {
15231 				/* Skip padding and whitespace unless we're in the
15232 				 * middle of a block.  Otherwise complete group by
15233 				 * simulating shifting in the correct padding.
15234 				 */
15235 				if (t == 1U) {
15236 					continue;
15237 				}
15238 				goto simulate_padding;
15239 			} else {
15240 				goto decode_error;
15241 			}
15242 		} else if (x >= 0x20U) {
15243 			/* Valid: +, /, and 0x20 whitespace. */
15244 			DUK_ASSERT(x >= 0x20U && x <= 0x2fU);
15245 			if (x == 0x2bU) {
15246 				y = 62;
15247 			} else if (x == 0x2fU) {
15248 				y = 63;
15249 			} else if (x == 0x20U) {
15250 				continue;
15251 			} else {
15252 				goto decode_error;
15253 			}
15254 		} else {
15255 			/* Valid: whitespace. */
15256 			duk_uint32_t m;
15257 			DUK_ASSERT(x < 0x20U);  /* 0x00 to 0x1f */
15258 			m = (1U << x);
15259 			if (mask_white & m) {
15260 				/* Allow basic ASCII whitespace. */
15261 				continue;
15262 			} else {
15263 				goto decode_error;
15264 			}
15265 		}
15266 
15267 		DUK_ASSERT(y >= 0 && y <= 63);
15268 		t = (t << 6) + (duk_uint_t) y;
15269 		if (t < 0x1000000UL) {
15270 			continue;
15271 		}
15272 		/* fall through; no padding will be added */
15273 
15274 	 simulate_padding:
15275 		n_equal = 0;
15276 		while (t < 0x1000000UL) {
15277 			t = (t << 6) + 0U;
15278 			n_equal++;
15279 		}
15280 
15281 		/* Output 3 bytes from 't' and advance as needed. */
15282 		q[0] = (duk_uint8_t) ((t >> 16) & 0xffU);
15283 		q[1] = (duk_uint8_t) ((t >> 8) & 0xffU);
15284 		q[2] = (duk_uint8_t) (t & 0xffU);
15285 
15286 		DUK_ASSERT(n_equal <= 4U);
15287 		step = duk__base64_decode_nequal_step[n_equal];
15288 		if (step < 0) {
15289 			goto decode_error;
15290 		}
15291 		q += step;
15292 
15293 		/* Re-enter loop.  The actual padding characters are skipped
15294 		 * by the main loop.  This handles cases like missing, partial,
15295 		 * full, and extra padding, and allows parsing of concatenated
15296 		 * documents (with extra padding) like: Zm===Zm.  Also extra
15297 		 * prepended padding is accepted: ===Zm9v.
15298 		 */
15299 		t = 1U;
15300 	}
15301 	DUK_ASSERT(t == 1UL);
15302 
15303 	*out_dst_final = q;
15304 	return 1;
15305 
15306  decode_error:
15307 	return 0;
15308 }
15309 #endif  /* DUK_USE_BASE64_FASTPATH */
15310 
duk_base64_encode(duk_hthread * thr,duk_idx_t idx)15311 DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) {
15312 	const duk_uint8_t *src;
15313 	duk_size_t srclen;
15314 	duk_size_t dstlen;
15315 	duk_uint8_t *dst;
15316 	const char *ret;
15317 
15318 	DUK_ASSERT_API_ENTRY(thr);
15319 
15320 	idx = duk_require_normalize_index(thr, idx);
15321 	src = duk__prep_codec_arg(thr, idx, &srclen);
15322 	/* Note: for srclen=0, src may be NULL */
15323 
15324 	/* Compute exact output length.  Computation must not wrap; this
15325 	 * limit works for 32-bit size_t:
15326 	 * >>> srclen = 3221225469
15327 	 * >>> '%x' % ((srclen + 2) / 3 * 4)
15328 	 * 'fffffffc'
15329 	 */
15330 	if (srclen > 3221225469UL) {
15331 		goto type_error;
15332 	}
15333 	dstlen = (srclen + 2U) / 3U * 4U;
15334 	dst = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, dstlen);
15335 
15336 	duk__base64_encode_helper((const duk_uint8_t *) src, srclen, dst);
15337 
15338 	ret = duk_buffer_to_string(thr, -1);  /* Safe, result is ASCII. */
15339 	duk_replace(thr, idx);
15340 	return ret;
15341 
15342  type_error:
15343 	DUK_ERROR_TYPE(thr, DUK_STR_BASE64_ENCODE_FAILED);
15344 	DUK_WO_NORETURN(return NULL;);
15345 }
15346 
duk_base64_decode(duk_hthread * thr,duk_idx_t idx)15347 DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) {
15348 	const duk_uint8_t *src;
15349 	duk_size_t srclen;
15350 	duk_size_t dstlen;
15351 	duk_uint8_t *dst;
15352 	duk_uint8_t *dst_final;
15353 
15354 	DUK_ASSERT_API_ENTRY(thr);
15355 
15356 	idx = duk_require_normalize_index(thr, idx);
15357 	src = duk__prep_codec_arg(thr, idx, &srclen);
15358 
15359 	/* Round up and add safety margin.  Avoid addition before division to
15360 	 * avoid possibility of wrapping.  Margin includes +3 for rounding up,
15361 	 * and +3 for one extra group: the decoder may emit and then backtrack
15362 	 * a full group (3 bytes) from zero-sized input for technical reasons.
15363 	 * Similarly, 'xx' may ecause 1+3 = bytes to be emitted and then
15364 	 * backtracked.
15365 	 */
15366 	dstlen = (srclen / 4) * 3 + 6;  /* upper limit, assuming no whitespace etc */
15367 	dst = (duk_uint8_t *) duk_push_dynamic_buffer(thr, dstlen);
15368 	/* Note: for dstlen=0, dst may be NULL */
15369 
15370 	if (!duk__base64_decode_helper((const duk_uint8_t *) src, srclen, dst, &dst_final)) {
15371 		goto type_error;
15372 	}
15373 
15374 	/* XXX: convert to fixed buffer? */
15375 	(void) duk_resize_buffer(thr, -1, (duk_size_t) (dst_final - dst));
15376 	duk_replace(thr, idx);
15377 	return;
15378 
15379  type_error:
15380 	DUK_ERROR_TYPE(thr, DUK_STR_BASE64_DECODE_FAILED);
15381 	DUK_WO_NORETURN(return;);
15382 }
15383 #else  /* DUK_USE_BASE64_SUPPORT */
duk_base64_encode(duk_hthread * thr,duk_idx_t idx)15384 DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) {
15385 	DUK_UNREF(idx);
15386 	DUK_ERROR_UNSUPPORTED(thr);
15387 	DUK_WO_NORETURN(return;);
15388 }
15389 
duk_base64_decode(duk_hthread * thr,duk_idx_t idx)15390 DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) {
15391 	DUK_UNREF(idx);
15392 	DUK_ERROR_UNSUPPORTED(thr);
15393 	DUK_WO_NORETURN(return;);
15394 }
15395 #endif  /* DUK_USE_BASE64_SUPPORT */
15396 
15397 /*
15398  *  Hex
15399  */
15400 
15401 #if defined(DUK_USE_HEX_SUPPORT)
duk_hex_encode(duk_hthread * thr,duk_idx_t idx)15402 DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {
15403 	const duk_uint8_t *inp;
15404 	duk_size_t len;
15405 	duk_size_t i;
15406 	duk_uint8_t *buf;
15407 	const char *ret;
15408 #if defined(DUK_USE_HEX_FASTPATH)
15409 	duk_size_t len_safe;
15410 	duk_uint16_t *p16;
15411 #endif
15412 
15413 	DUK_ASSERT_API_ENTRY(thr);
15414 
15415 	idx = duk_require_normalize_index(thr, idx);
15416 	inp = duk__prep_codec_arg(thr, idx, &len);
15417 	DUK_ASSERT(inp != NULL || len == 0);
15418 
15419 	/* Fixed buffer, no zeroing because we'll fill all the data. */
15420 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len * 2);
15421 	DUK_ASSERT(buf != NULL);
15422 
15423 #if defined(DUK_USE_HEX_FASTPATH)
15424 	DUK_ASSERT((((duk_size_t) buf) & 0x01U) == 0);   /* pointer is aligned, guaranteed for fixed buffer */
15425 	p16 = (duk_uint16_t *) (void *) buf;
15426 	len_safe = len & ~0x03U;
15427 	for (i = 0; i < len_safe; i += 4) {
15428 		p16[0] = duk_hex_enctab[inp[i]];
15429 		p16[1] = duk_hex_enctab[inp[i + 1]];
15430 		p16[2] = duk_hex_enctab[inp[i + 2]];
15431 		p16[3] = duk_hex_enctab[inp[i + 3]];
15432 		p16 += 4;
15433 	}
15434 	for (; i < len; i++) {
15435 		*p16++ = duk_hex_enctab[inp[i]];
15436 	}
15437 #else  /* DUK_USE_HEX_FASTPATH */
15438 	for (i = 0; i < len; i++) {
15439 		duk_small_uint_t t;
15440 		t = (duk_small_uint_t) inp[i];
15441 		buf[i*2 + 0] = duk_lc_digits[t >> 4];
15442 		buf[i*2 + 1] = duk_lc_digits[t & 0x0f];
15443 	}
15444 #endif  /* DUK_USE_HEX_FASTPATH */
15445 
15446 	/* XXX: Using a string return value forces a string intern which is
15447 	 * not always necessary.  As a rough performance measure, hex encode
15448 	 * time for tests/perf/test-hex-encode.js dropped from ~35s to ~15s
15449 	 * without string coercion.  Change to returning a buffer and let the
15450 	 * caller coerce to string if necessary?
15451 	 */
15452 
15453 	ret = duk_buffer_to_string(thr, -1);  /* Safe, result is ASCII. */
15454 	duk_replace(thr, idx);
15455 	return ret;
15456 }
15457 
duk_hex_decode(duk_hthread * thr,duk_idx_t idx)15458 DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) {
15459 	const duk_uint8_t *inp;
15460 	duk_size_t len;
15461 	duk_size_t i;
15462 	duk_int_t t;
15463 	duk_uint8_t *buf;
15464 #if defined(DUK_USE_HEX_FASTPATH)
15465 	duk_int_t chk;
15466 	duk_uint8_t *p;
15467 	duk_size_t len_safe;
15468 #endif
15469 
15470 	DUK_ASSERT_API_ENTRY(thr);
15471 
15472 	idx = duk_require_normalize_index(thr, idx);
15473 	inp = duk__prep_codec_arg(thr, idx, &len);
15474 	DUK_ASSERT(inp != NULL || len == 0);
15475 
15476 	if (len & 0x01) {
15477 		goto type_error;
15478 	}
15479 
15480 	/* Fixed buffer, no zeroing because we'll fill all the data. */
15481 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len / 2);
15482 	DUK_ASSERT(buf != NULL);
15483 
15484 #if defined(DUK_USE_HEX_FASTPATH)
15485 	p = buf;
15486 	len_safe = len & ~0x07U;
15487 	for (i = 0; i < len_safe; i += 8) {
15488 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i]]) |
15489 		    ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
15490 		chk = t;
15491 		p[0] = (duk_uint8_t) t;
15492 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 2]]) |
15493 		    ((duk_int_t) duk_hex_dectab[inp[i + 3]]);
15494 		chk |= t;
15495 		p[1] = (duk_uint8_t) t;
15496 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 4]]) |
15497 		    ((duk_int_t) duk_hex_dectab[inp[i + 5]]);
15498 		chk |= t;
15499 		p[2] = (duk_uint8_t) t;
15500 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 6]]) |
15501 		    ((duk_int_t) duk_hex_dectab[inp[i + 7]]);
15502 		chk |= t;
15503 		p[3] = (duk_uint8_t) t;
15504 		p += 4;
15505 
15506 		/* Check if any lookup above had a negative result. */
15507 		if (DUK_UNLIKELY(chk < 0)) {
15508 			goto type_error;
15509 		}
15510 	}
15511 	for (; i < len; i += 2) {
15512 		/* First cast to duk_int_t to sign extend, second cast to
15513 		 * duk_uint_t to avoid signed left shift, and final cast to
15514 		 * duk_int_t result type.
15515 		 */
15516 		t = (duk_int_t) ((((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i]]) << 4U) |
15517 		                 ((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i + 1]]));
15518 		if (DUK_UNLIKELY(t < 0)) {
15519 			goto type_error;
15520 		}
15521 		*p++ = (duk_uint8_t) t;
15522 	}
15523 #else  /* DUK_USE_HEX_FASTPATH */
15524 	for (i = 0; i < len; i += 2) {
15525 		/* For invalid characters the value -1 gets extended to
15526 		 * at least 16 bits.  If either nybble is invalid, the
15527 		 * resulting 't' will be < 0.
15528 		 */
15529 		t = (duk_int_t) ((((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i]]) << 4U) |
15530 		                 ((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i + 1]]));
15531 		if (DUK_UNLIKELY(t < 0)) {
15532 			goto type_error;
15533 		}
15534 		buf[i >> 1] = (duk_uint8_t) t;
15535 	}
15536 #endif  /* DUK_USE_HEX_FASTPATH */
15537 
15538 	duk_replace(thr, idx);
15539 	return;
15540 
15541  type_error:
15542 	DUK_ERROR_TYPE(thr, DUK_STR_HEX_DECODE_FAILED);
15543 	DUK_WO_NORETURN(return;);
15544 }
15545 #else  /* DUK_USE_HEX_SUPPORT */
duk_hex_encode(duk_hthread * thr,duk_idx_t idx)15546 DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {
15547 	DUK_UNREF(idx);
15548 	DUK_ERROR_UNSUPPORTED(thr);
15549 	DUK_WO_NORETURN(return;);
15550 }
duk_hex_decode(duk_hthread * thr,duk_idx_t idx)15551 DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) {
15552 	DUK_UNREF(idx);
15553 	DUK_ERROR_UNSUPPORTED(thr);
15554 	DUK_WO_NORETURN(return;);
15555 }
15556 #endif  /* DUK_USE_HEX_SUPPORT */
15557 
15558 /*
15559  *  JSON
15560  */
15561 
15562 #if defined(DUK_USE_JSON_SUPPORT)
duk_json_encode(duk_hthread * thr,duk_idx_t idx)15563 DUK_EXTERNAL const char *duk_json_encode(duk_hthread *thr, duk_idx_t idx) {
15564 #if defined(DUK_USE_ASSERTIONS)
15565 	duk_idx_t top_at_entry;
15566 #endif
15567 	const char *ret;
15568 
15569 	DUK_ASSERT_API_ENTRY(thr);
15570 #if defined(DUK_USE_ASSERTIONS)
15571 	top_at_entry = duk_get_top(thr);
15572 #endif
15573 
15574 	idx = duk_require_normalize_index(thr, idx);
15575 	duk_bi_json_stringify_helper(thr,
15576 	                             idx /*idx_value*/,
15577 	                             DUK_INVALID_INDEX /*idx_replacer*/,
15578 	                             DUK_INVALID_INDEX /*idx_space*/,
15579 	                             0 /*flags*/);
15580 	DUK_ASSERT(duk_is_string(thr, -1));
15581 	duk_replace(thr, idx);
15582 	ret = duk_get_string(thr, idx);
15583 
15584 	DUK_ASSERT(duk_get_top(thr) == top_at_entry);
15585 
15586 	return ret;
15587 }
15588 
duk_json_decode(duk_hthread * thr,duk_idx_t idx)15589 DUK_EXTERNAL void duk_json_decode(duk_hthread *thr, duk_idx_t idx) {
15590 #if defined(DUK_USE_ASSERTIONS)
15591 	duk_idx_t top_at_entry;
15592 #endif
15593 
15594 	DUK_ASSERT_API_ENTRY(thr);
15595 #if defined(DUK_USE_ASSERTIONS)
15596 	top_at_entry = duk_get_top(thr);
15597 #endif
15598 
15599 	idx = duk_require_normalize_index(thr, idx);
15600 	duk_bi_json_parse_helper(thr,
15601 	                         idx /*idx_value*/,
15602 	                         DUK_INVALID_INDEX /*idx_reviver*/,
15603 	                         0 /*flags*/);
15604 	duk_replace(thr, idx);
15605 
15606 	DUK_ASSERT(duk_get_top(thr) == top_at_entry);
15607 }
15608 #else  /* DUK_USE_JSON_SUPPORT */
duk_json_encode(duk_hthread * thr,duk_idx_t idx)15609 DUK_EXTERNAL const char *duk_json_encode(duk_hthread *thr, duk_idx_t idx) {
15610 	DUK_ASSERT_API_ENTRY(thr);
15611 	DUK_UNREF(idx);
15612 	DUK_ERROR_UNSUPPORTED(thr);
15613 	DUK_WO_NORETURN(return NULL;);
15614 }
15615 
duk_json_decode(duk_hthread * thr,duk_idx_t idx)15616 DUK_EXTERNAL void duk_json_decode(duk_hthread *thr, duk_idx_t idx) {
15617 	DUK_ASSERT_API_ENTRY(thr);
15618 	DUK_UNREF(idx);
15619 	DUK_ERROR_UNSUPPORTED(thr);
15620 	DUK_WO_NORETURN(return;);
15621 }
15622 #endif  /* DUK_USE_JSON_SUPPORT */
15623 #line 1 "duk_api_compile.c"
15624 /*
15625  *  Compilation and evaluation
15626  */
15627 
15628 /* #include duk_internal.h -> already included */
15629 
15630 typedef struct duk__compile_raw_args duk__compile_raw_args;
15631 struct duk__compile_raw_args {
15632 	duk_size_t src_length;  /* should be first on 64-bit platforms */
15633 	const duk_uint8_t *src_buffer;
15634 	duk_uint_t flags;
15635 };
15636 
15637 /* 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)15638 DUK_EXTERNAL duk_int_t duk_eval_raw(duk_hthread *thr, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
15639 	duk_int_t rc;
15640 
15641 	DUK_ASSERT_API_ENTRY(thr);
15642 
15643 	/* Note: strictness is *not* inherited from the current Duktape/C.
15644 	 * This would be confusing because the current strictness state
15645 	 * depends on whether we're running inside a Duktape/C activation
15646 	 * (= strict mode) or outside of any activation (= non-strict mode).
15647 	 * See tests/api/test-eval-strictness.c for more discussion.
15648 	 */
15649 
15650 	/* [ ... source? filename? ] (depends on flags) */
15651 
15652 	rc = duk_compile_raw(thr, src_buffer, src_length, flags | DUK_COMPILE_EVAL);  /* may be safe, or non-safe depending on flags */
15653 
15654 	/* [ ... closure/error ] */
15655 
15656 	if (rc != DUK_EXEC_SUCCESS) {
15657 		rc = DUK_EXEC_ERROR;
15658 		goto got_rc;
15659 	}
15660 
15661 	duk_push_global_object(thr);  /* explicit 'this' binding, see GH-164 */
15662 
15663 	if (flags & DUK_COMPILE_SAFE) {
15664 		rc = duk_pcall_method(thr, 0);
15665 	} else {
15666 		duk_call_method(thr, 0);
15667 		rc = DUK_EXEC_SUCCESS;
15668 	}
15669 
15670 	/* [ ... result/error ] */
15671 
15672  got_rc:
15673 	if (flags & DUK_COMPILE_NORESULT) {
15674 		duk_pop(thr);
15675 	}
15676 
15677 	return rc;
15678 }
15679 
15680 /* Helper which can be called both directly and with duk_safe_call(). */
duk__do_compile(duk_hthread * thr,void * udata)15681 DUK_LOCAL duk_ret_t duk__do_compile(duk_hthread *thr, void *udata) {
15682 	duk__compile_raw_args *comp_args;
15683 	duk_uint_t flags;
15684 	duk_hcompfunc *h_templ;
15685 
15686 	DUK_ASSERT_CTX_VALID(thr);
15687 	DUK_ASSERT(udata != NULL);
15688 
15689 	/* Note: strictness is not inherited from the current Duktape/C
15690 	 * context.  Otherwise it would not be possible to compile
15691 	 * non-strict code inside a Duktape/C activation (which is
15692 	 * always strict now).  See tests/api/test-eval-strictness.c
15693 	 * for discussion.
15694 	 */
15695 
15696 	/* [ ... source? filename? ] (depends on flags) */
15697 
15698 	comp_args = (duk__compile_raw_args *) udata;
15699 	flags = comp_args->flags;
15700 
15701 	if (flags & DUK_COMPILE_NOFILENAME) {
15702 		/* Automatic filename: 'eval' or 'input'. */
15703 		duk_push_hstring_stridx(thr, (flags & DUK_COMPILE_EVAL) ? DUK_STRIDX_EVAL : DUK_STRIDX_INPUT);
15704 	}
15705 
15706 	/* [ ... source? filename ] */
15707 
15708 	if (!comp_args->src_buffer) {
15709 		duk_hstring *h_sourcecode;
15710 
15711 		h_sourcecode = duk_get_hstring(thr, -2);
15712 		if ((flags & DUK_COMPILE_NOSOURCE) ||  /* args incorrect */
15713 		    (h_sourcecode == NULL)) {          /* e.g. duk_push_string_file_raw() pushed undefined */
15714 			DUK_ERROR_TYPE(thr, DUK_STR_NO_SOURCECODE);
15715 			DUK_WO_NORETURN(return 0;);
15716 		}
15717 		DUK_ASSERT(h_sourcecode != NULL);
15718 		comp_args->src_buffer = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode);
15719 		comp_args->src_length = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode);
15720 	}
15721 	DUK_ASSERT(comp_args->src_buffer != NULL);
15722 
15723 	if (flags & DUK_COMPILE_FUNCTION) {
15724 		flags |= DUK_COMPILE_EVAL | DUK_COMPILE_FUNCEXPR;
15725 	}
15726 
15727 	/* [ ... source? filename ] */
15728 
15729 	duk_js_compile(thr, comp_args->src_buffer, comp_args->src_length, flags);
15730 
15731 	/* [ ... source? func_template ] */
15732 
15733 	if (flags & DUK_COMPILE_NOSOURCE) {
15734 		;
15735 	} else {
15736 		duk_remove_m2(thr);
15737 	}
15738 
15739 	/* [ ... func_template ] */
15740 
15741 	h_templ = (duk_hcompfunc *) duk_known_hobject(thr, -1);
15742 	duk_js_push_closure(thr,
15743 	                   h_templ,
15744 	                   thr->builtins[DUK_BIDX_GLOBAL_ENV],
15745 	                   thr->builtins[DUK_BIDX_GLOBAL_ENV],
15746 	                   1 /*add_auto_proto*/);
15747 	duk_remove_m2(thr);   /* -> [ ... closure ] */
15748 
15749 	/* [ ... closure ] */
15750 
15751 	return 1;
15752 }
15753 
duk_compile_raw(duk_hthread * thr,const char * src_buffer,duk_size_t src_length,duk_uint_t flags)15754 DUK_EXTERNAL duk_int_t duk_compile_raw(duk_hthread *thr, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
15755 	duk__compile_raw_args comp_args_alloc;
15756 	duk__compile_raw_args *comp_args = &comp_args_alloc;
15757 
15758 	DUK_ASSERT_API_ENTRY(thr);
15759 
15760 	if ((flags & DUK_COMPILE_STRLEN) && (src_buffer != NULL)) {
15761 		/* String length is computed here to avoid multiple evaluation
15762 		 * of a macro argument in the calling side.
15763 		 */
15764 		src_length = DUK_STRLEN(src_buffer);
15765 	}
15766 
15767 	comp_args->src_buffer = (const duk_uint8_t *) src_buffer;
15768 	comp_args->src_length = src_length;
15769 	comp_args->flags = flags;
15770 
15771 	/* [ ... source? filename? ] (depends on flags) */
15772 
15773 	if (flags & DUK_COMPILE_SAFE) {
15774 		duk_int_t rc;
15775 		duk_int_t nargs;
15776 		duk_int_t nrets = 1;
15777 
15778 		/* Arguments can be: [ source? filename? &comp_args] so that
15779 		 * nargs is 1 to 3.  Call site encodes the correct nargs count
15780 		 * directly into flags.
15781 		 */
15782 		nargs = flags & 0x07;
15783 		DUK_ASSERT(nargs == ((flags & DUK_COMPILE_NOSOURCE) ? 0 : 1) +
15784 		                    ((flags & DUK_COMPILE_NOFILENAME) ? 0 : 1));
15785 		rc = duk_safe_call(thr, duk__do_compile, (void *) comp_args, nargs, nrets);
15786 
15787 		/* [ ... closure ] */
15788 		return rc;
15789 	}
15790 
15791 	(void) duk__do_compile(thr, (void *) comp_args);
15792 
15793 	/* [ ... closure ] */
15794 	return DUK_EXEC_SUCCESS;
15795 }
15796 #line 1 "duk_api_debug.c"
15797 /*
15798  *  Debugging related API calls
15799  */
15800 
15801 /* #include duk_internal.h -> already included */
15802 
15803 #if defined(DUK_USE_JSON_SUPPORT)
duk_push_context_dump(duk_hthread * thr)15804 DUK_EXTERNAL void duk_push_context_dump(duk_hthread *thr) {
15805 	duk_idx_t idx;
15806 	duk_idx_t top;
15807 
15808 	DUK_ASSERT_API_ENTRY(thr);
15809 
15810 	/* We don't duk_require_stack() here now, but rely on the caller having
15811 	 * enough space.
15812 	 */
15813 
15814 	top = duk_get_top(thr);
15815 	duk_push_array(thr);
15816 	for (idx = 0; idx < top; idx++) {
15817 		duk_dup(thr, idx);
15818 		duk_put_prop_index(thr, -2, (duk_uarridx_t) idx);
15819 	}
15820 
15821 	/* XXX: conversion errors should not propagate outwards.
15822 	 * Perhaps values need to be coerced individually?
15823 	 */
15824 	duk_bi_json_stringify_helper(thr,
15825 	                             duk_get_top_index(thr),  /*idx_value*/
15826 	                             DUK_INVALID_INDEX,  /*idx_replacer*/
15827 	                             DUK_INVALID_INDEX,  /*idx_space*/
15828 	                             DUK_JSON_FLAG_EXT_CUSTOM |
15829 	                             DUK_JSON_FLAG_ASCII_ONLY |
15830 	                             DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
15831 
15832 	duk_push_sprintf(thr, "ctx: top=%ld, stack=%s", (long) top, (const char *) duk_safe_to_string(thr, -1));
15833 	duk_replace(thr, -3);  /* [ ... arr jsonx(arr) res ] -> [ ... res jsonx(arr) ] */
15834 	duk_pop(thr);
15835 	DUK_ASSERT(duk_is_string(thr, -1));
15836 }
15837 #else  /* DUK_USE_JSON_SUPPORT */
duk_push_context_dump(duk_hthread * thr)15838 DUK_EXTERNAL void duk_push_context_dump(duk_hthread *thr) {
15839 	DUK_ASSERT_API_ENTRY(thr);
15840 	DUK_ERROR_UNSUPPORTED(thr);
15841 	DUK_WO_NORETURN(return;);
15842 }
15843 #endif  /* DUK_USE_JSON_SUPPORT */
15844 
15845 #if defined(DUK_USE_DEBUGGER_SUPPORT)
15846 
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)15847 DUK_EXTERNAL void duk_debugger_attach(duk_hthread *thr,
15848                                       duk_debug_read_function read_cb,
15849                                       duk_debug_write_function write_cb,
15850                                       duk_debug_peek_function peek_cb,
15851                                       duk_debug_read_flush_function read_flush_cb,
15852                                       duk_debug_write_flush_function write_flush_cb,
15853                                       duk_debug_request_function request_cb,
15854                                       duk_debug_detached_function detached_cb,
15855                                       void *udata) {
15856 	duk_heap *heap;
15857 	const char *str;
15858 	duk_size_t len;
15859 
15860 	/* XXX: should there be an error or an automatic detach if
15861 	 * already attached?
15862 	 */
15863 
15864 	DUK_D(DUK_DPRINT("application called duk_debugger_attach()"));
15865 
15866 	DUK_ASSERT_API_ENTRY(thr);
15867 	DUK_ASSERT(read_cb != NULL);
15868 	DUK_ASSERT(write_cb != NULL);
15869 	/* Other callbacks are optional. */
15870 
15871 	heap = thr->heap;
15872 	heap->dbg_read_cb = read_cb;
15873 	heap->dbg_write_cb = write_cb;
15874 	heap->dbg_peek_cb = peek_cb;
15875 	heap->dbg_read_flush_cb = read_flush_cb;
15876 	heap->dbg_write_flush_cb = write_flush_cb;
15877 	heap->dbg_request_cb = request_cb;
15878 	heap->dbg_detached_cb = detached_cb;
15879 	heap->dbg_udata = udata;
15880 	heap->dbg_have_next_byte = 0;
15881 
15882 	/* Start in paused state. */
15883 	heap->dbg_processing = 0;
15884 	heap->dbg_state_dirty = 0;
15885 	heap->dbg_force_restart = 0;
15886 	heap->dbg_pause_flags = 0;
15887 	heap->dbg_pause_act = NULL;
15888 	heap->dbg_pause_startline = 0;
15889 	heap->dbg_exec_counter = 0;
15890 	heap->dbg_last_counter = 0;
15891 	heap->dbg_last_time = 0.0;
15892 	duk_debug_set_paused(heap);  /* XXX: overlap with fields above */
15893 
15894 	/* Send version identification and flush right afterwards.  Note that
15895 	 * we must write raw, unframed bytes here.
15896 	 */
15897 	duk_push_sprintf(thr, "%ld %ld %s %s\n",
15898 	                 (long) DUK_DEBUG_PROTOCOL_VERSION,
15899 	                 (long) DUK_VERSION,
15900 	                 (const char *) DUK_GIT_DESCRIBE,
15901 	                 (const char *) DUK_USE_TARGET_INFO);
15902 	str = duk_get_lstring(thr, -1, &len);
15903 	DUK_ASSERT(str != NULL);
15904 	duk_debug_write_bytes(thr, (const duk_uint8_t *) str, len);
15905 	duk_debug_write_flush(thr);
15906 	duk_pop(thr);
15907 }
15908 
duk_debugger_detach(duk_hthread * thr)15909 DUK_EXTERNAL void duk_debugger_detach(duk_hthread *thr) {
15910 	DUK_D(DUK_DPRINT("application called duk_debugger_detach()"));
15911 
15912 	DUK_ASSERT_API_ENTRY(thr);
15913 	DUK_ASSERT(thr->heap != NULL);
15914 
15915 	/* Can be called multiple times with no harm. */
15916 	duk_debug_do_detach(thr->heap);
15917 }
15918 
duk_debugger_cooperate(duk_hthread * thr)15919 DUK_EXTERNAL void duk_debugger_cooperate(duk_hthread *thr) {
15920 	duk_bool_t processed_messages;
15921 
15922 	DUK_ASSERT_API_ENTRY(thr);
15923 	DUK_ASSERT(thr->heap != NULL);
15924 
15925 	if (!duk_debug_is_attached(thr->heap)) {
15926 		return;
15927 	}
15928 	if (thr->callstack_curr != NULL || thr->heap->dbg_processing) {
15929 		/* Calling duk_debugger_cooperate() while Duktape is being
15930 		 * called into is not supported.  This is not a 100% check
15931 		 * but prevents any damage in most cases.
15932 		 */
15933 		return;
15934 	}
15935 
15936 	processed_messages = duk_debug_process_messages(thr, 1 /*no_block*/);
15937 	DUK_UNREF(processed_messages);
15938 }
15939 
duk_debugger_notify(duk_hthread * thr,duk_idx_t nvalues)15940 DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_hthread *thr, duk_idx_t nvalues) {
15941 	duk_idx_t top;
15942 	duk_idx_t idx;
15943 	duk_bool_t ret = 0;
15944 
15945 	DUK_ASSERT_API_ENTRY(thr);
15946 	DUK_ASSERT(thr->heap != NULL);
15947 
15948 	DUK_D(DUK_DPRINT("application called duk_debugger_notify() with nvalues=%ld", (long) nvalues));
15949 
15950 	top = duk_get_top(thr);
15951 	if (top < nvalues) {
15952 		DUK_ERROR_RANGE(thr, "not enough stack values for notify");
15953 		DUK_WO_NORETURN(return 0;);
15954 	}
15955 	if (duk_debug_is_attached(thr->heap)) {
15956 		duk_debug_write_notify(thr, DUK_DBG_CMD_APPNOTIFY);
15957 		for (idx = top - nvalues; idx < top; idx++) {
15958 			duk_tval *tv = DUK_GET_TVAL_POSIDX(thr, idx);
15959 			duk_debug_write_tval(thr, tv);
15960 		}
15961 		duk_debug_write_eom(thr);
15962 
15963 		/* Return non-zero (true) if we have a good reason to believe
15964 		 * the notify was delivered; if we're still attached at least
15965 		 * a transport error was not indicated by the transport write
15966 		 * callback.  This is not a 100% guarantee of course.
15967 		 */
15968 		if (duk_debug_is_attached(thr->heap)) {
15969 			ret = 1;
15970 		}
15971 	}
15972 	duk_pop_n(thr, nvalues);
15973 	return ret;
15974 }
15975 
duk_debugger_pause(duk_hthread * thr)15976 DUK_EXTERNAL void duk_debugger_pause(duk_hthread *thr) {
15977 	DUK_ASSERT_API_ENTRY(thr);
15978 	DUK_ASSERT(thr->heap != NULL);
15979 
15980 	DUK_D(DUK_DPRINT("application called duk_debugger_pause()"));
15981 
15982 	/* Treat like a debugger statement: ignore when not attached. */
15983 	if (duk_debug_is_attached(thr->heap)) {
15984 		if (duk_debug_is_paused(thr->heap)) {
15985 			DUK_D(DUK_DPRINT("duk_debugger_pause() called when already paused; ignoring"));
15986 		} else {
15987 			duk_debug_set_paused(thr->heap);
15988 
15989 			/* Pause on the next opcode executed.  This is always safe to do even
15990 			 * inside the debugger message loop: the interrupt counter will be reset
15991 			 * to its proper value when the message loop exits.
15992 			 */
15993 			thr->interrupt_init = 1;
15994 			thr->interrupt_counter = 0;
15995 		}
15996 	}
15997 }
15998 
15999 #else  /* DUK_USE_DEBUGGER_SUPPORT */
16000 
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)16001 DUK_EXTERNAL void duk_debugger_attach(duk_hthread *thr,
16002                                       duk_debug_read_function read_cb,
16003                                       duk_debug_write_function write_cb,
16004                                       duk_debug_peek_function peek_cb,
16005                                       duk_debug_read_flush_function read_flush_cb,
16006                                       duk_debug_write_flush_function write_flush_cb,
16007                                       duk_debug_request_function request_cb,
16008                                       duk_debug_detached_function detached_cb,
16009                                       void *udata) {
16010 	DUK_ASSERT_API_ENTRY(thr);
16011 	DUK_UNREF(read_cb);
16012 	DUK_UNREF(write_cb);
16013 	DUK_UNREF(peek_cb);
16014 	DUK_UNREF(read_flush_cb);
16015 	DUK_UNREF(write_flush_cb);
16016 	DUK_UNREF(request_cb);
16017 	DUK_UNREF(detached_cb);
16018 	DUK_UNREF(udata);
16019 	DUK_ERROR_TYPE(thr, "no debugger support");
16020 	DUK_WO_NORETURN(return;);
16021 }
16022 
duk_debugger_detach(duk_hthread * thr)16023 DUK_EXTERNAL void duk_debugger_detach(duk_hthread *thr) {
16024 	DUK_ASSERT_API_ENTRY(thr);
16025 	DUK_ERROR_TYPE(thr, "no debugger support");
16026 	DUK_WO_NORETURN(return;);
16027 }
16028 
duk_debugger_cooperate(duk_hthread * thr)16029 DUK_EXTERNAL void duk_debugger_cooperate(duk_hthread *thr) {
16030 	/* nop */
16031 	DUK_ASSERT_API_ENTRY(thr);
16032 	DUK_UNREF(thr);
16033 }
16034 
duk_debugger_notify(duk_hthread * thr,duk_idx_t nvalues)16035 DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_hthread *thr, duk_idx_t nvalues) {
16036 	duk_idx_t top;
16037 
16038 	DUK_ASSERT_API_ENTRY(thr);
16039 
16040 	top = duk_get_top(thr);
16041 	if (top < nvalues) {
16042 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
16043 		DUK_WO_NORETURN(return 0;);
16044 	}
16045 
16046 	/* No debugger support, just pop values. */
16047 	duk_pop_n(thr, nvalues);
16048 	return 0;
16049 }
16050 
duk_debugger_pause(duk_hthread * thr)16051 DUK_EXTERNAL void duk_debugger_pause(duk_hthread *thr) {
16052 	/* Treat like debugger statement: nop */
16053 	DUK_ASSERT_API_ENTRY(thr);
16054 	DUK_UNREF(thr);
16055 }
16056 
16057 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
16058 #line 1 "duk_api_heap.c"
16059 /*
16060  *  Heap creation and destruction
16061  */
16062 
16063 /* #include duk_internal.h -> already included */
16064 
16065 typedef struct duk_internal_thread_state duk_internal_thread_state;
16066 
16067 struct duk_internal_thread_state {
16068 	duk_ljstate lj;
16069 	duk_bool_t creating_error;
16070 	duk_hthread *curr_thread;
16071 	duk_int_t call_recursion_depth;
16072 };
16073 
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)16074 DUK_EXTERNAL duk_hthread *duk_create_heap(duk_alloc_function alloc_func,
16075                                           duk_realloc_function realloc_func,
16076                                           duk_free_function free_func,
16077                                           void *heap_udata,
16078                                           duk_fatal_function fatal_handler) {
16079 	duk_heap *heap = NULL;
16080 	duk_hthread *thr;
16081 
16082 	/* Assume that either all memory funcs are NULL or non-NULL, mixed
16083 	 * cases will now be unsafe.
16084 	 */
16085 
16086 	/* XXX: just assert non-NULL values here and make caller arguments
16087 	 * do the defaulting to the default implementations (smaller code)?
16088 	 */
16089 
16090 	if (!alloc_func) {
16091 		DUK_ASSERT(realloc_func == NULL);
16092 		DUK_ASSERT(free_func == NULL);
16093 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
16094 		alloc_func = duk_default_alloc_function;
16095 		realloc_func = duk_default_realloc_function;
16096 		free_func = duk_default_free_function;
16097 #else
16098 		DUK_D(DUK_DPRINT("no allocation functions given and no default providers"));
16099 		return NULL;
16100 #endif
16101 	} else {
16102 		DUK_ASSERT(realloc_func != NULL);
16103 		DUK_ASSERT(free_func != NULL);
16104 	}
16105 
16106 	if (!fatal_handler) {
16107 		fatal_handler = duk_default_fatal_handler;
16108 	}
16109 
16110 	DUK_ASSERT(alloc_func != NULL);
16111 	DUK_ASSERT(realloc_func != NULL);
16112 	DUK_ASSERT(free_func != NULL);
16113 	DUK_ASSERT(fatal_handler != NULL);
16114 
16115 	heap = duk_heap_alloc(alloc_func, realloc_func, free_func, heap_udata, fatal_handler);
16116 	if (!heap) {
16117 		return NULL;
16118 	}
16119 	thr = heap->heap_thread;
16120 	DUK_ASSERT(thr != NULL);
16121 	DUK_ASSERT(thr->heap != NULL);
16122 	return thr;
16123 }
16124 
duk_destroy_heap(duk_hthread * thr)16125 DUK_EXTERNAL void duk_destroy_heap(duk_hthread *thr) {
16126 	duk_heap *heap;
16127 
16128 	if (!thr) {
16129 		return;
16130 	}
16131 	DUK_ASSERT_API_ENTRY(thr);
16132 	heap = thr->heap;
16133 	DUK_ASSERT(heap != NULL);
16134 
16135 	duk_heap_free(heap);
16136 }
16137 
duk_suspend(duk_hthread * thr,duk_thread_state * state)16138 DUK_EXTERNAL void duk_suspend(duk_hthread *thr, duk_thread_state *state) {
16139 	duk_internal_thread_state *snapshot = (duk_internal_thread_state *) (void *) state;
16140 	duk_heap *heap;
16141 	duk_ljstate *lj;
16142 
16143 	DUK_ASSERT_API_ENTRY(thr);
16144 	DUK_ASSERT(thr->heap != NULL);
16145 	DUK_ASSERT(state != NULL);  /* unvalidated */
16146 
16147 	/* Currently not supported when called from within a finalizer.
16148 	 * If that is done, the finalizer will remain running indefinitely,
16149 	 * preventing other finalizers from executing.  The assert is a bit
16150 	 * wider, checking that it would be OK to run pending finalizers.
16151 	 */
16152 	DUK_ASSERT(thr->heap->pf_prevent_count == 0);
16153 
16154 	/* Currently not supported to duk_suspend() from an errCreate()
16155 	 * call.
16156 	 */
16157 	DUK_ASSERT(thr->heap->creating_error == 0);
16158 
16159 	heap = thr->heap;
16160 	lj = &heap->lj;
16161 
16162 	duk_push_tval(thr, &lj->value1);
16163 	duk_push_tval(thr, &lj->value2);
16164 
16165 	/* XXX: creating_error == 0 is asserted above, so no need to store. */
16166 	duk_memcpy((void *) &snapshot->lj, (const void *) lj, sizeof(duk_ljstate));
16167 	snapshot->creating_error = heap->creating_error;
16168 	snapshot->curr_thread = heap->curr_thread;
16169 	snapshot->call_recursion_depth = heap->call_recursion_depth;
16170 
16171 	lj->jmpbuf_ptr = NULL;
16172 	lj->type = DUK_LJ_TYPE_UNKNOWN;
16173 	DUK_TVAL_SET_UNDEFINED(&lj->value1);
16174 	DUK_TVAL_SET_UNDEFINED(&lj->value2);
16175 	heap->creating_error = 0;
16176 	heap->curr_thread = NULL;
16177 	heap->call_recursion_depth = 0;
16178 }
16179 
duk_resume(duk_hthread * thr,const duk_thread_state * state)16180 DUK_EXTERNAL void duk_resume(duk_hthread *thr, const duk_thread_state *state) {
16181 	const duk_internal_thread_state *snapshot = (const duk_internal_thread_state *) (const void *) state;
16182 	duk_heap *heap;
16183 
16184 	DUK_ASSERT_API_ENTRY(thr);
16185 	DUK_ASSERT(thr->heap != NULL);
16186 	DUK_ASSERT(state != NULL);  /* unvalidated */
16187 
16188 	/* Shouldn't be necessary if duk_suspend() is called before
16189 	 * duk_resume(), but assert in case API sequence is incorrect.
16190 	 */
16191 	DUK_ASSERT(thr->heap->pf_prevent_count == 0);
16192 	DUK_ASSERT(thr->heap->creating_error == 0);
16193 
16194 	heap = thr->heap;
16195 
16196 	duk_memcpy((void *) &heap->lj, (const void *) &snapshot->lj, sizeof(duk_ljstate));
16197 	heap->creating_error = snapshot->creating_error;
16198 	heap->curr_thread = snapshot->curr_thread;
16199 	heap->call_recursion_depth = snapshot->call_recursion_depth;
16200 
16201 	duk_pop_2(thr);
16202 }
16203 
16204 /* XXX: better place for this */
duk_set_global_object(duk_hthread * thr)16205 DUK_EXTERNAL void duk_set_global_object(duk_hthread *thr) {
16206 	duk_hobject *h_glob;
16207 	duk_hobject *h_prev_glob;
16208 	duk_hobjenv *h_env;
16209 	duk_hobject *h_prev_env;
16210 
16211 	DUK_ASSERT_API_ENTRY(thr);
16212 
16213 	DUK_D(DUK_DPRINT("replace global object with: %!T", duk_get_tval(thr, -1)));
16214 
16215 	h_glob = duk_require_hobject(thr, -1);
16216 	DUK_ASSERT(h_glob != NULL);
16217 
16218 	/*
16219 	 *  Replace global object.
16220 	 */
16221 
16222 	h_prev_glob = thr->builtins[DUK_BIDX_GLOBAL];
16223 	DUK_UNREF(h_prev_glob);
16224 	thr->builtins[DUK_BIDX_GLOBAL] = h_glob;
16225 	DUK_HOBJECT_INCREF(thr, h_glob);
16226 	DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_glob);  /* side effects, in theory (referenced by global env) */
16227 
16228 	/*
16229 	 *  Replace lexical environment for global scope
16230 	 *
16231 	 *  Create a new object environment for the global lexical scope.
16232 	 *  We can't just reset the _Target property of the current one,
16233 	 *  because the lexical scope is shared by other threads with the
16234 	 *  same (initial) built-ins.
16235 	 */
16236 
16237 	h_env = duk_hobjenv_alloc(thr,
16238 	                          DUK_HOBJECT_FLAG_EXTENSIBLE |
16239 	                          DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
16240 	DUK_ASSERT(h_env != NULL);
16241 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_env) == NULL);
16242 
16243 	DUK_ASSERT(h_env->target == NULL);
16244 	DUK_ASSERT(h_glob != NULL);
16245 	h_env->target = h_glob;
16246 	DUK_HOBJECT_INCREF(thr, h_glob);
16247 	DUK_ASSERT(h_env->has_this == 0);
16248 
16249 	/* [ ... new_glob ] */
16250 
16251 	h_prev_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
16252 	thr->builtins[DUK_BIDX_GLOBAL_ENV] = (duk_hobject *) h_env;
16253 	DUK_HOBJECT_INCREF(thr, (duk_hobject *) h_env);
16254 	DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_env);  /* side effects */
16255 	DUK_UNREF(h_env);  /* without refcounts */
16256 	DUK_UNREF(h_prev_env);
16257 
16258 	/* [ ... new_glob ] */
16259 
16260 	duk_pop(thr);
16261 
16262 	/* [ ... ] */
16263 }
16264 #line 1 "duk_api_inspect.c"
16265 /*
16266  *  Inspection
16267  */
16268 
16269 /* #include duk_internal.h -> already included */
16270 
16271 /* For footprint efficient multiple value setting: arrays are much better than
16272  * varargs, format string with parsing is often better than string pointer arrays.
16273  */
duk__inspect_multiple_uint(duk_hthread * thr,const char * fmt,duk_int_t * vals)16274 DUK_LOCAL void duk__inspect_multiple_uint(duk_hthread *thr, const char *fmt, duk_int_t *vals) {
16275 	duk_int_t val;
16276 	const char *p;
16277 	const char *p_curr;
16278 	duk_size_t len;
16279 
16280 	for (p = fmt;;) {
16281 		len = DUK_STRLEN(p);
16282 		p_curr = p;
16283 		p += len + 1;
16284 		if (len == 0) {
16285 			/* Double NUL (= empty key) terminates. */
16286 			break;
16287 		}
16288 		val = *vals++;
16289 		if (val >= 0) {
16290 			/* Negative values are markers to skip key. */
16291 			duk_push_string(thr, p_curr);
16292 			duk_push_int(thr, val);
16293 			duk_put_prop(thr, -3);
16294 		}
16295 	}
16296 }
16297 
16298 /* Raw helper to extract internal information / statistics about a value.
16299  * The return value is an object with properties that are version specific.
16300  * The properties must not expose anything that would lead to security
16301  * issues (e.g. exposing compiled function 'data' buffer might be an issue).
16302  * Currently only counts and sizes and such are given so there shouldn't
16303  * be security implications.
16304  */
16305 
16306 #define DUK__IDX_TYPE     0
16307 #define DUK__IDX_ITAG     1
16308 #define DUK__IDX_REFC     2
16309 #define DUK__IDX_HBYTES   3
16310 #define DUK__IDX_CLASS    4
16311 #define DUK__IDX_PBYTES   5
16312 #define DUK__IDX_ESIZE    6
16313 #define DUK__IDX_ENEXT    7
16314 #define DUK__IDX_ASIZE    8
16315 #define DUK__IDX_HSIZE    9
16316 #define DUK__IDX_BCBYTES  10
16317 #define DUK__IDX_DBYTES   11
16318 #define DUK__IDX_TSTATE   12
16319 #define DUK__IDX_VARIANT  13
16320 
duk_inspect_value(duk_hthread * thr,duk_idx_t idx)16321 DUK_EXTERNAL void duk_inspect_value(duk_hthread *thr, duk_idx_t idx) {
16322 	duk_tval *tv;
16323 	duk_heaphdr *h;
16324 	/* The temporary values should be in an array rather than individual
16325 	 * variables which (in practice) ensures that the compiler won't map
16326 	 * them to registers and emit a lot of unnecessary shuffling code.
16327 	 */
16328 	duk_int_t vals[14];
16329 
16330 	DUK_ASSERT_API_ENTRY(thr);
16331 
16332 	/* Assume two's complement and set everything to -1. */
16333 	duk_memset((void *) &vals, (int) 0xff, sizeof(vals));
16334 	DUK_ASSERT(vals[DUK__IDX_TYPE] == -1);  /* spot check one */
16335 
16336 	tv = duk_get_tval_or_unused(thr, idx);
16337 	h = (DUK_TVAL_IS_HEAP_ALLOCATED(tv) ? DUK_TVAL_GET_HEAPHDR(tv) : NULL);
16338 
16339 	vals[DUK__IDX_TYPE] = duk_get_type_tval(tv);
16340 	vals[DUK__IDX_ITAG] = (duk_int_t) DUK_TVAL_GET_TAG(tv);
16341 
16342 	duk_push_bare_object(thr);  /* Invalidates 'tv'. */
16343 	tv = NULL;
16344 
16345 	if (h == NULL) {
16346 		goto finish;
16347 	}
16348 	duk_push_pointer(thr, (void *) h);
16349 	duk_put_prop_literal(thr, -2, "hptr");
16350 
16351 #if 0
16352 	/* Covers a lot of information, e.g. buffer and string variants. */
16353 	duk_push_uint(thr, (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));
16354 	duk_put_prop_literal(thr, -2, "hflags");
16355 #endif
16356 
16357 #if defined(DUK_USE_REFERENCE_COUNTING)
16358 	vals[DUK__IDX_REFC] = (duk_int_t) DUK_HEAPHDR_GET_REFCOUNT(h);
16359 #endif
16360 	vals[DUK__IDX_VARIANT] = 0;
16361 
16362 	/* Heaphdr size and additional allocation size, followed by
16363 	 * type specific stuff (with varying value count).
16364 	 */
16365 	switch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(h)) {
16366 	case DUK_HTYPE_STRING: {
16367 		duk_hstring *h_str = (duk_hstring *) h;
16368 		vals[DUK__IDX_HBYTES] = (duk_int_t) (sizeof(duk_hstring) + DUK_HSTRING_GET_BYTELEN(h_str) + 1);
16369 #if defined(DUK_USE_HSTRING_EXTDATA)
16370 		if (DUK_HSTRING_HAS_EXTDATA(h_str)) {
16371 			vals[DUK__IDX_VARIANT] = 1;
16372 		}
16373 #endif
16374 		break;
16375 	}
16376 	case DUK_HTYPE_OBJECT: {
16377 		duk_hobject *h_obj = (duk_hobject *) h;
16378 
16379 		/* XXX: variants here are maybe pointless; class is enough? */
16380 		if (DUK_HOBJECT_IS_ARRAY(h_obj)) {
16381 			vals[DUK__IDX_HBYTES] = sizeof(duk_harray);
16382 		} else if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
16383 			vals[DUK__IDX_HBYTES] = sizeof(duk_hcompfunc);
16384 		} else if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
16385 			vals[DUK__IDX_HBYTES] = sizeof(duk_hnatfunc);
16386 		} else if (DUK_HOBJECT_IS_THREAD(h_obj)) {
16387 			vals[DUK__IDX_HBYTES] = sizeof(duk_hthread);
16388 			vals[DUK__IDX_TSTATE] = ((duk_hthread *) h_obj)->state;
16389 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
16390 		} else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
16391 			vals[DUK__IDX_HBYTES] = sizeof(duk_hbufobj);
16392 			/* XXX: some size information */
16393 #endif
16394 		} else {
16395 			vals[DUK__IDX_HBYTES] = (duk_small_uint_t) sizeof(duk_hobject);
16396 		}
16397 
16398 		vals[DUK__IDX_CLASS] = (duk_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
16399 		vals[DUK__IDX_PBYTES] = (duk_int_t) DUK_HOBJECT_P_ALLOC_SIZE(h_obj);
16400 		vals[DUK__IDX_ESIZE] = (duk_int_t) DUK_HOBJECT_GET_ESIZE(h_obj);
16401 		vals[DUK__IDX_ENEXT] = (duk_int_t) DUK_HOBJECT_GET_ENEXT(h_obj);
16402 		vals[DUK__IDX_ASIZE] = (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj);
16403 		vals[DUK__IDX_HSIZE] = (duk_int_t) DUK_HOBJECT_GET_HSIZE(h_obj);
16404 
16405 		/* Note: e_next indicates the number of gc-reachable entries
16406 		 * in the entry part, and also indicates the index where the
16407 		 * next new property would be inserted.  It does *not* indicate
16408 		 * the number of non-NULL keys present in the object.  That
16409 		 * value could be counted separately but requires a pass through
16410 		 * the key list.
16411 		 */
16412 
16413 		if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
16414 			duk_hbuffer *h_data = (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(thr->heap, (duk_hcompfunc *) h_obj);
16415 			vals[DUK__IDX_BCBYTES] = (duk_int_t) (h_data ? DUK_HBUFFER_GET_SIZE(h_data) : 0);
16416 		}
16417 		break;
16418 	}
16419 	case DUK_HTYPE_BUFFER: {
16420 		duk_hbuffer *h_buf = (duk_hbuffer *) h;
16421 
16422 		if (DUK_HBUFFER_HAS_DYNAMIC(h_buf)) {
16423 			if (DUK_HBUFFER_HAS_EXTERNAL(h_buf)) {
16424 				vals[DUK__IDX_VARIANT] = 2;  /* buffer variant 2: external */
16425 				vals[DUK__IDX_HBYTES] = (duk_uint_t) (sizeof(duk_hbuffer_external));
16426 			} else {
16427 				/* When alloc_size == 0 the second allocation may not
16428 				 * actually exist.
16429 				 */
16430 				vals[DUK__IDX_VARIANT] = 1;  /* buffer variant 1: dynamic */
16431 				vals[DUK__IDX_HBYTES] = (duk_uint_t) (sizeof(duk_hbuffer_dynamic));
16432 			}
16433 			vals[DUK__IDX_DBYTES] = (duk_int_t) (DUK_HBUFFER_GET_SIZE(h_buf));
16434 		} else {
16435 			DUK_ASSERT(vals[DUK__IDX_VARIANT] == 0);  /* buffer variant 0: fixed */
16436 			vals[DUK__IDX_HBYTES] = (duk_int_t) (sizeof(duk_hbuffer_fixed) + DUK_HBUFFER_GET_SIZE(h_buf));
16437 		}
16438 		break;
16439 	}
16440 	}
16441 
16442  finish:
16443 	duk__inspect_multiple_uint(thr,
16444 	    "type" "\x00" "itag" "\x00" "refc" "\x00" "hbytes" "\x00" "class" "\x00"
16445 	    "pbytes" "\x00" "esize" "\x00" "enext" "\x00" "asize" "\x00" "hsize" "\x00"
16446 	    "bcbytes" "\x00" "dbytes" "\x00" "tstate" "\x00" "variant" "\x00" "\x00",
16447 	    (duk_int_t *) &vals);
16448 }
16449 
duk_inspect_callstack_entry(duk_hthread * thr,duk_int_t level)16450 DUK_EXTERNAL void duk_inspect_callstack_entry(duk_hthread *thr, duk_int_t level) {
16451 	duk_activation *act;
16452 	duk_uint_fast32_t pc;
16453 	duk_uint_fast32_t line;
16454 
16455 	DUK_ASSERT_API_ENTRY(thr);
16456 
16457 	/* -1   = top callstack entry
16458 	 * -2   = caller of level -1
16459 	 * etc
16460 	 */
16461 	act = duk_hthread_get_activation_for_level(thr, level);
16462 	if (act == NULL) {
16463 		duk_push_undefined(thr);
16464 		return;
16465 	}
16466 	duk_push_bare_object(thr);
16467 
16468 	/* Relevant PC is just before current one because PC is
16469 	 * post-incremented.  This should match what error augment
16470 	 * code does.
16471 	 */
16472 	pc = duk_hthread_get_act_prev_pc(thr, act);
16473 
16474 	duk_push_tval(thr, &act->tv_func);
16475 
16476 	duk_push_uint(thr, (duk_uint_t) pc);
16477 	duk_put_prop_stridx_short(thr, -3, DUK_STRIDX_PC);
16478 
16479 #if defined(DUK_USE_PC2LINE)
16480 	line = duk_hobject_pc2line_query(thr, -1, pc);
16481 #else
16482 	line = 0;
16483 #endif
16484 	duk_push_uint(thr, (duk_uint_t) line);
16485 	duk_put_prop_stridx_short(thr, -3, DUK_STRIDX_LINE_NUMBER);
16486 
16487 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_LC_FUNCTION);
16488 	/* Providing access to e.g. act->lex_env would be dangerous: these
16489 	 * internal structures must never be accessible to the application.
16490 	 * Duktape relies on them having consistent data, and this consistency
16491 	 * is only asserted for, not checked for.
16492 	 */
16493 }
16494 
16495 /* automatic undefs */
16496 #undef DUK__IDX_ASIZE
16497 #undef DUK__IDX_BCBYTES
16498 #undef DUK__IDX_CLASS
16499 #undef DUK__IDX_DBYTES
16500 #undef DUK__IDX_ENEXT
16501 #undef DUK__IDX_ESIZE
16502 #undef DUK__IDX_HBYTES
16503 #undef DUK__IDX_HSIZE
16504 #undef DUK__IDX_ITAG
16505 #undef DUK__IDX_PBYTES
16506 #undef DUK__IDX_REFC
16507 #undef DUK__IDX_TSTATE
16508 #undef DUK__IDX_TYPE
16509 #undef DUK__IDX_VARIANT
16510 #line 1 "duk_api_memory.c"
16511 /*
16512  *  Memory calls.
16513  */
16514 
16515 /* #include duk_internal.h -> already included */
16516 
duk_alloc_raw(duk_hthread * thr,duk_size_t size)16517 DUK_EXTERNAL void *duk_alloc_raw(duk_hthread *thr, duk_size_t size) {
16518 	DUK_ASSERT_API_ENTRY(thr);
16519 
16520 	return DUK_ALLOC_RAW(thr->heap, size);
16521 }
16522 
duk_free_raw(duk_hthread * thr,void * ptr)16523 DUK_EXTERNAL void duk_free_raw(duk_hthread *thr, void *ptr) {
16524 	DUK_ASSERT_API_ENTRY(thr);
16525 
16526 	DUK_FREE_RAW(thr->heap, ptr);
16527 }
16528 
duk_realloc_raw(duk_hthread * thr,void * ptr,duk_size_t size)16529 DUK_EXTERNAL void *duk_realloc_raw(duk_hthread *thr, void *ptr, duk_size_t size) {
16530 	DUK_ASSERT_API_ENTRY(thr);
16531 
16532 	return DUK_REALLOC_RAW(thr->heap, ptr, size);
16533 }
16534 
duk_alloc(duk_hthread * thr,duk_size_t size)16535 DUK_EXTERNAL void *duk_alloc(duk_hthread *thr, duk_size_t size) {
16536 	DUK_ASSERT_API_ENTRY(thr);
16537 
16538 	return DUK_ALLOC(thr->heap, size);
16539 }
16540 
duk_free(duk_hthread * thr,void * ptr)16541 DUK_EXTERNAL void duk_free(duk_hthread *thr, void *ptr) {
16542 	DUK_ASSERT_API_ENTRY(thr);
16543 
16544 	DUK_FREE_CHECKED(thr, ptr);
16545 }
16546 
duk_realloc(duk_hthread * thr,void * ptr,duk_size_t size)16547 DUK_EXTERNAL void *duk_realloc(duk_hthread *thr, void *ptr, duk_size_t size) {
16548 	DUK_ASSERT_API_ENTRY(thr);
16549 
16550 	/*
16551 	 *  Note: since this is an exposed API call, there should be
16552 	 *  no way a mark-and-sweep could have a side effect on the
16553 	 *  memory allocation behind 'ptr'; the pointer should never
16554 	 *  be something that Duktape wants to change.
16555 	 *
16556 	 *  Thus, no need to use DUK_REALLOC_INDIRECT (and we don't
16557 	 *  have the storage location here anyway).
16558 	 */
16559 
16560 	return DUK_REALLOC(thr->heap, ptr, size);
16561 }
16562 
duk_get_memory_functions(duk_hthread * thr,duk_memory_functions * out_funcs)16563 DUK_EXTERNAL void duk_get_memory_functions(duk_hthread *thr, duk_memory_functions *out_funcs) {
16564 	duk_heap *heap;
16565 
16566 	DUK_ASSERT_API_ENTRY(thr);
16567 	DUK_ASSERT(out_funcs != NULL);
16568 	DUK_ASSERT(thr != NULL);
16569 	DUK_ASSERT(thr->heap != NULL);
16570 
16571 	heap = thr->heap;
16572 	out_funcs->alloc_func = heap->alloc_func;
16573 	out_funcs->realloc_func = heap->realloc_func;
16574 	out_funcs->free_func = heap->free_func;
16575 	out_funcs->udata = heap->heap_udata;
16576 }
16577 
duk_gc(duk_hthread * thr,duk_uint_t flags)16578 DUK_EXTERNAL void duk_gc(duk_hthread *thr, duk_uint_t flags) {
16579 	duk_heap *heap;
16580 	duk_small_uint_t ms_flags;
16581 
16582 	DUK_ASSERT_API_ENTRY(thr);
16583 	heap = thr->heap;
16584 	DUK_ASSERT(heap != NULL);
16585 
16586 	DUK_D(DUK_DPRINT("mark-and-sweep requested by application"));
16587 	DUK_ASSERT(DUK_GC_COMPACT == DUK_MS_FLAG_EMERGENCY);  /* Compact flag is 1:1 with emergency flag which forces compaction. */
16588 	ms_flags = (duk_small_uint_t) flags;
16589 	duk_heap_mark_and_sweep(heap, ms_flags);
16590 }
16591 #line 1 "duk_api_object.c"
16592 /*
16593  *  Object handling: property access and other support functions.
16594  */
16595 
16596 /* #include duk_internal.h -> already included */
16597 
16598 /*
16599  *  Property handling
16600  *
16601  *  The API exposes only the most common property handling functions.
16602  *  The caller can invoke ECMAScript built-ins for full control (e.g.
16603  *  defineProperty, getOwnPropertyDescriptor).
16604  */
16605 
duk_get_prop(duk_hthread * thr,duk_idx_t obj_idx)16606 DUK_EXTERNAL duk_bool_t duk_get_prop(duk_hthread *thr, duk_idx_t obj_idx) {
16607 	duk_tval *tv_obj;
16608 	duk_tval *tv_key;
16609 	duk_bool_t rc;
16610 
16611 	DUK_ASSERT_API_ENTRY(thr);
16612 
16613 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
16614 	 * resize is not necessary for a property get right now.
16615 	 */
16616 
16617 	tv_obj = duk_require_tval(thr, obj_idx);
16618 	tv_key = duk_require_tval(thr, -1);
16619 
16620 	rc = duk_hobject_getprop(thr, tv_obj, tv_key);
16621 	DUK_ASSERT(rc == 0 || rc == 1);
16622 	/* a value is left on stack regardless of rc */
16623 
16624 	duk_remove_m2(thr);  /* remove key */
16625 	DUK_ASSERT(duk_is_undefined(thr, -1) || rc == 1);
16626 	return rc;  /* 1 if property found, 0 otherwise */
16627 }
16628 
duk_get_prop_string(duk_hthread * thr,duk_idx_t obj_idx,const char * key)16629 DUK_EXTERNAL duk_bool_t duk_get_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
16630 	DUK_ASSERT_API_ENTRY(thr);
16631 	DUK_ASSERT(key != NULL);
16632 
16633 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16634 	(void) duk_push_string(thr, key);
16635 	return duk_get_prop(thr, obj_idx);
16636 }
16637 
duk_get_prop_lstring(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)16638 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) {
16639 	DUK_ASSERT_API_ENTRY(thr);
16640 	DUK_ASSERT(key != NULL);
16641 
16642 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16643 	(void) duk_push_lstring(thr, key, key_len);
16644 	return duk_get_prop(thr, obj_idx);
16645 }
16646 
16647 #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)16648 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) {
16649 	DUK_ASSERT_API_ENTRY(thr);
16650 	DUK_ASSERT(key != NULL);
16651 	DUK_ASSERT(key[key_len] == (char) 0);
16652 
16653 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16654 	(void) duk_push_literal_raw(thr, key, key_len);
16655 	return duk_get_prop(thr, obj_idx);
16656 }
16657 #endif
16658 
duk_get_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx)16659 DUK_EXTERNAL duk_bool_t duk_get_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
16660 	DUK_ASSERT_API_ENTRY(thr);
16661 
16662 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16663 	duk_push_uarridx(thr, arr_idx);
16664 	return duk_get_prop(thr, obj_idx);
16665 }
16666 
duk_get_prop_heapptr(duk_hthread * thr,duk_idx_t obj_idx,void * ptr)16667 DUK_EXTERNAL duk_bool_t duk_get_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
16668 	DUK_ASSERT_API_ENTRY(thr);
16669 
16670 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16671 	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
16672 	return duk_get_prop(thr, obj_idx);
16673 }
16674 
duk_get_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)16675 DUK_INTERNAL duk_bool_t duk_get_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
16676 	DUK_ASSERT_API_ENTRY(thr);
16677 	DUK_ASSERT_STRIDX_VALID(stridx);
16678 
16679 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16680 	(void) duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
16681 	return duk_get_prop(thr, obj_idx);
16682 }
16683 
duk_get_prop_stridx_short_raw(duk_hthread * thr,duk_uint_t packed_args)16684 DUK_INTERNAL duk_bool_t duk_get_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
16685 	return duk_get_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
16686 	                                (duk_small_uint_t) (packed_args & 0xffffUL));
16687 }
16688 
duk_get_prop_stridx_boolean(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx,duk_bool_t * out_has_prop)16689 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) {
16690 	duk_bool_t rc;
16691 
16692 	DUK_ASSERT_API_ENTRY(thr);
16693 	DUK_ASSERT_STRIDX_VALID(stridx);
16694 
16695 	rc = duk_get_prop_stridx(thr, obj_idx, stridx);
16696 	if (out_has_prop) {
16697 		*out_has_prop = rc;
16698 	}
16699 	return duk_to_boolean_top_pop(thr);
16700 }
16701 
duk__put_prop_shared(duk_hthread * thr,duk_idx_t obj_idx,duk_idx_t idx_key)16702 DUK_LOCAL duk_bool_t duk__put_prop_shared(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t idx_key) {
16703 	duk_tval *tv_obj;
16704 	duk_tval *tv_key;
16705 	duk_tval *tv_val;
16706 	duk_bool_t throw_flag;
16707 	duk_bool_t rc;
16708 
16709 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
16710 	 * resize is not necessary for a property put right now (putprop protects
16711 	 * against it internally).
16712 	 */
16713 
16714 	/* Key and value indices are either (-2, -1) or (-1, -2).  Given idx_key,
16715 	 * idx_val is always (idx_key ^ 0x01).
16716 	 */
16717 	DUK_ASSERT((idx_key == -2 && (idx_key ^ 1) == -1) ||
16718 	           (idx_key == -1 && (idx_key ^ 1) == -2));
16719 	/* XXX: Direct access; faster validation. */
16720 	tv_obj = duk_require_tval(thr, obj_idx);
16721 	tv_key = duk_require_tval(thr, idx_key);
16722 	tv_val = duk_require_tval(thr, idx_key ^ 1);
16723 	throw_flag = duk_is_strict_call(thr);
16724 
16725 	rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, throw_flag);
16726 	DUK_ASSERT(rc == 0 || rc == 1);
16727 
16728 	duk_pop_2(thr);  /* remove key and value */
16729 	return rc;  /* 1 if property found, 0 otherwise */
16730 }
16731 
duk_put_prop(duk_hthread * thr,duk_idx_t obj_idx)16732 DUK_EXTERNAL duk_bool_t duk_put_prop(duk_hthread *thr, duk_idx_t obj_idx) {
16733 	DUK_ASSERT_API_ENTRY(thr);
16734 	return duk__put_prop_shared(thr, obj_idx, -2);
16735 }
16736 
duk_put_prop_string(duk_hthread * thr,duk_idx_t obj_idx,const char * key)16737 DUK_EXTERNAL duk_bool_t duk_put_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
16738 	DUK_ASSERT_API_ENTRY(thr);
16739 	DUK_ASSERT(key != NULL);
16740 
16741 	/* Careful here and with other duk_put_prop_xxx() helpers: the
16742 	 * target object and the property value may be in the same value
16743 	 * stack slot (unusual, but still conceptually clear).
16744 	 */
16745 	obj_idx = duk_normalize_index(thr, obj_idx);
16746 	(void) duk_push_string(thr, key);
16747 	return duk__put_prop_shared(thr, obj_idx, -1);
16748 }
16749 
duk_put_prop_lstring(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)16750 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) {
16751 	DUK_ASSERT_API_ENTRY(thr);
16752 	DUK_ASSERT(key != NULL);
16753 
16754 	obj_idx = duk_normalize_index(thr, obj_idx);
16755 	(void) duk_push_lstring(thr, key, key_len);
16756 	return duk__put_prop_shared(thr, obj_idx, -1);
16757 }
16758 
16759 #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)16760 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) {
16761 	DUK_ASSERT_API_ENTRY(thr);
16762 	DUK_ASSERT(key != NULL);
16763 	DUK_ASSERT(key[key_len] == (char) 0);
16764 
16765 	obj_idx = duk_normalize_index(thr, obj_idx);
16766 	(void) duk_push_literal_raw(thr, key, key_len);
16767 	return duk__put_prop_shared(thr, obj_idx, -1);
16768 }
16769 #endif
16770 
duk_put_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx)16771 DUK_EXTERNAL duk_bool_t duk_put_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
16772 	DUK_ASSERT_API_ENTRY(thr);
16773 
16774 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16775 	duk_push_uarridx(thr, arr_idx);
16776 	return duk__put_prop_shared(thr, obj_idx, -1);
16777 }
16778 
duk_put_prop_heapptr(duk_hthread * thr,duk_idx_t obj_idx,void * ptr)16779 DUK_EXTERNAL duk_bool_t duk_put_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
16780 	DUK_ASSERT_API_ENTRY(thr);
16781 
16782 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16783 	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
16784 	return duk__put_prop_shared(thr, obj_idx, -1);
16785 }
16786 
16787 
duk_put_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)16788 DUK_INTERNAL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
16789 	DUK_ASSERT_API_ENTRY(thr);
16790 	DUK_ASSERT_STRIDX_VALID(stridx);
16791 
16792 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16793 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
16794 	return duk__put_prop_shared(thr, obj_idx, -1);
16795 }
16796 
duk_put_prop_stridx_short_raw(duk_hthread * thr,duk_uint_t packed_args)16797 DUK_INTERNAL duk_bool_t duk_put_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
16798 	return duk_put_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
16799 	                                (duk_small_uint_t) (packed_args & 0xffffUL));
16800 }
16801 
duk_del_prop(duk_hthread * thr,duk_idx_t obj_idx)16802 DUK_EXTERNAL duk_bool_t duk_del_prop(duk_hthread *thr, duk_idx_t obj_idx) {
16803 	duk_tval *tv_obj;
16804 	duk_tval *tv_key;
16805 	duk_bool_t throw_flag;
16806 	duk_bool_t rc;
16807 
16808 	DUK_ASSERT_API_ENTRY(thr);
16809 
16810 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
16811 	 * resize is not necessary for a property delete right now.
16812 	 */
16813 
16814 	tv_obj = duk_require_tval(thr, obj_idx);
16815 	tv_key = duk_require_tval(thr, -1);
16816 	throw_flag = duk_is_strict_call(thr);
16817 
16818 	rc = duk_hobject_delprop(thr, tv_obj, tv_key, throw_flag);
16819 	DUK_ASSERT(rc == 0 || rc == 1);
16820 
16821 	duk_pop(thr);  /* remove key */
16822 	return rc;
16823 }
16824 
duk_del_prop_string(duk_hthread * thr,duk_idx_t obj_idx,const char * key)16825 DUK_EXTERNAL duk_bool_t duk_del_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
16826 	DUK_ASSERT_API_ENTRY(thr);
16827 	DUK_ASSERT(key != NULL);
16828 
16829 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16830 	(void) duk_push_string(thr, key);
16831 	return duk_del_prop(thr, obj_idx);
16832 }
16833 
duk_del_prop_lstring(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)16834 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) {
16835 	DUK_ASSERT_API_ENTRY(thr);
16836 	DUK_ASSERT(key != NULL);
16837 
16838 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16839 	(void) duk_push_lstring(thr, key, key_len);
16840 	return duk_del_prop(thr, obj_idx);
16841 }
16842 
16843 #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)16844 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) {
16845 	DUK_ASSERT_API_ENTRY(thr);
16846 	DUK_ASSERT(key != NULL);
16847 	DUK_ASSERT(key[key_len] == (char) 0);
16848 
16849 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16850 	(void) duk_push_literal_raw(thr, key, key_len);
16851 	return duk_del_prop(thr, obj_idx);
16852 }
16853 #endif
16854 
duk_del_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx)16855 DUK_EXTERNAL duk_bool_t duk_del_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
16856 	DUK_ASSERT_API_ENTRY(thr);
16857 
16858 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16859 	duk_push_uarridx(thr, arr_idx);
16860 	return duk_del_prop(thr, obj_idx);
16861 }
16862 
duk_del_prop_heapptr(duk_hthread * thr,duk_idx_t obj_idx,void * ptr)16863 DUK_EXTERNAL duk_bool_t duk_del_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
16864 	DUK_ASSERT_API_ENTRY(thr);
16865 
16866 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16867 	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
16868 	return duk_del_prop(thr, obj_idx);
16869 }
16870 
duk_del_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)16871 DUK_INTERNAL duk_bool_t duk_del_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
16872 	DUK_ASSERT_API_ENTRY(thr);
16873 	DUK_ASSERT_STRIDX_VALID(stridx);
16874 
16875 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16876 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
16877 	return duk_del_prop(thr, obj_idx);
16878 }
16879 
16880 #if 0
16881 DUK_INTERNAL duk_bool_t duk_del_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
16882 	return duk_del_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
16883 	                                (duk_small_uint_t) (packed_args & 0xffffUL));
16884 }
16885 #endif
16886 
duk_has_prop(duk_hthread * thr,duk_idx_t obj_idx)16887 DUK_EXTERNAL duk_bool_t duk_has_prop(duk_hthread *thr, duk_idx_t obj_idx) {
16888 	duk_tval *tv_obj;
16889 	duk_tval *tv_key;
16890 	duk_bool_t rc;
16891 
16892 	DUK_ASSERT_API_ENTRY(thr);
16893 
16894 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
16895 	 * resize is not necessary for a property existence check right now.
16896 	 */
16897 
16898 	tv_obj = duk_require_tval(thr, obj_idx);
16899 	tv_key = duk_require_tval(thr, -1);
16900 
16901 	rc = duk_hobject_hasprop(thr, tv_obj, tv_key);
16902 	DUK_ASSERT(rc == 0 || rc == 1);
16903 
16904 	duk_pop(thr);  /* remove key */
16905 	return rc;  /* 1 if property found, 0 otherwise */
16906 }
16907 
duk_has_prop_string(duk_hthread * thr,duk_idx_t obj_idx,const char * key)16908 DUK_EXTERNAL duk_bool_t duk_has_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
16909 	DUK_ASSERT_API_ENTRY(thr);
16910 	DUK_ASSERT(key != NULL);
16911 
16912 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16913 	(void) duk_push_string(thr, key);
16914 	return duk_has_prop(thr, obj_idx);
16915 }
16916 
duk_has_prop_lstring(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)16917 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) {
16918 	DUK_ASSERT_API_ENTRY(thr);
16919 	DUK_ASSERT(key != NULL);
16920 
16921 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16922 	(void) duk_push_lstring(thr, key, key_len);
16923 	return duk_has_prop(thr, obj_idx);
16924 }
16925 
16926 #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)16927 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) {
16928 	DUK_ASSERT_API_ENTRY(thr);
16929 	DUK_ASSERT(key != NULL);
16930 	DUK_ASSERT(key[key_len] == (char) 0);
16931 
16932 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16933 	(void) duk_push_literal_raw(thr, key, key_len);
16934 	return duk_has_prop(thr, obj_idx);
16935 }
16936 #endif
16937 
duk_has_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx)16938 DUK_EXTERNAL duk_bool_t duk_has_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
16939 	DUK_ASSERT_API_ENTRY(thr);
16940 
16941 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16942 	duk_push_uarridx(thr, arr_idx);
16943 	return duk_has_prop(thr, obj_idx);
16944 }
16945 
duk_has_prop_heapptr(duk_hthread * thr,duk_idx_t obj_idx,void * ptr)16946 DUK_EXTERNAL duk_bool_t duk_has_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
16947 	DUK_ASSERT_API_ENTRY(thr);
16948 
16949 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16950 	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
16951 	return duk_has_prop(thr, obj_idx);
16952 }
16953 
duk_has_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)16954 DUK_INTERNAL duk_bool_t duk_has_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
16955 	DUK_ASSERT_API_ENTRY(thr);
16956 	DUK_ASSERT_STRIDX_VALID(stridx);
16957 
16958 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16959 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
16960 	return duk_has_prop(thr, obj_idx);
16961 }
16962 
16963 #if 0
16964 DUK_INTERNAL duk_bool_t duk_has_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
16965 	return duk_has_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
16966 	                                (duk_small_uint_t) (packed_args & 0xffffUL));
16967 }
16968 #endif
16969 
16970 /* Define own property without inheritance lookups and such.  This differs from
16971  * [[DefineOwnProperty]] because special behaviors (like Array 'length') are
16972  * not invoked by this method.  The caller must be careful to invoke any such
16973  * behaviors if necessary.
16974  */
duk_xdef_prop(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t desc_flags)16975 DUK_INTERNAL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t desc_flags) {
16976 	duk_hobject *obj;
16977 	duk_hstring *key;
16978 
16979 	DUK_ASSERT_API_ENTRY(thr);
16980 
16981 	obj = duk_require_hobject(thr, obj_idx);
16982 	DUK_ASSERT(obj != NULL);
16983 	key = duk_to_property_key_hstring(thr, -2);
16984 	DUK_ASSERT(key != NULL);
16985 	DUK_ASSERT(duk_require_tval(thr, -1) != NULL);
16986 
16987 	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
16988 
16989 	duk_pop(thr);  /* pop key */
16990 }
16991 
duk_xdef_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx,duk_small_uint_t desc_flags)16992 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) {
16993 	duk_hobject *obj;
16994 
16995 	DUK_ASSERT_API_ENTRY(thr);
16996 
16997 	obj = duk_require_hobject(thr, obj_idx);
16998 	DUK_ASSERT(obj != NULL);
16999 
17000 	duk_hobject_define_property_internal_arridx(thr, obj, arr_idx, desc_flags);
17001 	/* value popped by call */
17002 }
17003 
duk_xdef_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx,duk_small_uint_t desc_flags)17004 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) {
17005 	duk_hobject *obj;
17006 	duk_hstring *key;
17007 
17008 	DUK_ASSERT_API_ENTRY(thr);
17009 	DUK_ASSERT_STRIDX_VALID(stridx);
17010 
17011 	obj = duk_require_hobject(thr, obj_idx);
17012 	DUK_ASSERT(obj != NULL);
17013 	key = DUK_HTHREAD_GET_STRING(thr, stridx);
17014 	DUK_ASSERT(key != NULL);
17015 	DUK_ASSERT(duk_require_tval(thr, -1) != NULL);
17016 
17017 	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
17018 	/* value popped by call */
17019 }
17020 
duk_xdef_prop_stridx_short_raw(duk_hthread * thr,duk_uint_t packed_args)17021 DUK_INTERNAL void duk_xdef_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
17022 	duk_xdef_prop_stridx(thr, (duk_idx_t) (duk_int8_t) (packed_args >> 24),
17023 	                          (duk_small_uint_t) (packed_args >> 8) & 0xffffUL,
17024 	                          (duk_small_uint_t) (packed_args & 0xffL));
17025 }
17026 
17027 #if 0  /*unused*/
17028 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) {
17029 	duk_hobject *obj;
17030 	duk_hstring *key;
17031 
17032 	DUK_ASSERT_API_ENTRY(thr);
17033 	DUK_ASSERT_STRIDX_VALID(stridx);
17034 	DUK_ASSERT_BIDX_VALID(builtin_idx);
17035 
17036 	obj = duk_require_hobject(thr, obj_idx);
17037 	DUK_ASSERT(obj != NULL);
17038 	key = DUK_HTHREAD_GET_STRING(thr, stridx);
17039 	DUK_ASSERT(key != NULL);
17040 
17041 	duk_push_hobject(thr, thr->builtins[builtin_idx]);
17042 	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
17043 	/* value popped by call */
17044 }
17045 #endif
17046 
17047 /* This is a rare property helper; it sets the global thrower (E5 Section 13.2.3)
17048  * setter/getter into an object property.  This is needed by the 'arguments'
17049  * object creation code, function instance creation code, and Function.prototype.bind().
17050  */
17051 
duk_xdef_prop_stridx_thrower(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)17052 DUK_INTERNAL void duk_xdef_prop_stridx_thrower(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
17053 	DUK_ASSERT_API_ENTRY(thr);
17054 
17055 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17056 	duk_push_hstring_stridx(thr, stridx);
17057 	duk_push_hobject_bidx(thr, DUK_BIDX_TYPE_ERROR_THROWER);
17058 	duk_dup_top(thr);
17059 	duk_def_prop(thr, obj_idx, DUK_DEFPROP_HAVE_SETTER | DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_FORCE);  /* attributes always 0 */
17060 }
17061 
17062 /* Object.getOwnPropertyDescriptor() equivalent C binding. */
duk_get_prop_desc(duk_hthread * thr,duk_idx_t obj_idx,duk_uint_t flags)17063 DUK_EXTERNAL void duk_get_prop_desc(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t flags) {
17064 	DUK_ASSERT_API_ENTRY(thr);
17065 	DUK_UNREF(flags);  /* no flags defined yet */
17066 
17067 	duk_hobject_object_get_own_property_descriptor(thr, obj_idx);  /* [ ... key ] -> [ ... desc ] */
17068 }
17069 
17070 /* Object.defineProperty() equivalent C binding. */
duk_def_prop(duk_hthread * thr,duk_idx_t obj_idx,duk_uint_t flags)17071 DUK_EXTERNAL void duk_def_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t flags) {
17072 	duk_idx_t idx_base;
17073 	duk_hobject *obj;
17074 	duk_hstring *key;
17075 	duk_idx_t idx_value;
17076 	duk_hobject *get;
17077 	duk_hobject *set;
17078 	duk_uint_t is_data_desc;
17079 	duk_uint_t is_acc_desc;
17080 
17081 	DUK_ASSERT_API_ENTRY(thr);
17082 
17083 	obj = duk_require_hobject(thr, obj_idx);
17084 
17085 	is_data_desc = flags & (DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);
17086 	is_acc_desc = flags & (DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
17087 	if (is_data_desc && is_acc_desc) {
17088 		/* "Have" flags must not be conflicting so that they would
17089 		 * apply to both a plain property and an accessor at the same
17090 		 * time.
17091 		 */
17092 		goto fail_invalid_desc;
17093 	}
17094 
17095 	idx_base = duk_get_top_index(thr);
17096 	if (flags & DUK_DEFPROP_HAVE_SETTER) {
17097 		duk_require_type_mask(thr, idx_base, DUK_TYPE_MASK_UNDEFINED |
17098 		                                     DUK_TYPE_MASK_OBJECT |
17099 		                                     DUK_TYPE_MASK_LIGHTFUNC);
17100 		set = duk_get_hobject_promote_lfunc(thr, idx_base);
17101 		if (set != NULL && !DUK_HOBJECT_IS_CALLABLE(set)) {
17102 			goto fail_not_callable;
17103 		}
17104 		idx_base--;
17105 	} else {
17106 		set = NULL;
17107 	}
17108 	if (flags & DUK_DEFPROP_HAVE_GETTER) {
17109 		duk_require_type_mask(thr, idx_base, DUK_TYPE_MASK_UNDEFINED |
17110 		                                     DUK_TYPE_MASK_OBJECT |
17111 		                                     DUK_TYPE_MASK_LIGHTFUNC);
17112 		get = duk_get_hobject_promote_lfunc(thr, idx_base);
17113 		if (get != NULL && !DUK_HOBJECT_IS_CALLABLE(get)) {
17114 			goto fail_not_callable;
17115 		}
17116 		idx_base--;
17117 	} else {
17118 		get = NULL;
17119 	}
17120 	if (flags & DUK_DEFPROP_HAVE_VALUE) {
17121 		idx_value = idx_base;
17122 		idx_base--;
17123 	} else {
17124 		idx_value = (duk_idx_t) -1;
17125 	}
17126 	key = duk_to_property_key_hstring(thr, idx_base);
17127 	DUK_ASSERT(key != NULL);
17128 
17129 	duk_require_valid_index(thr, idx_base);
17130 
17131 	duk_hobject_define_property_helper(thr,
17132 	                                   flags /*defprop_flags*/,
17133 	                                   obj,
17134 	                                   key,
17135 	                                   idx_value,
17136 	                                   get,
17137 	                                   set,
17138 	                                   1 /*throw_flag*/);
17139 
17140 	/* Clean up stack */
17141 
17142 	duk_set_top(thr, idx_base);
17143 
17144 	/* [ ... obj ... ] */
17145 
17146 	return;
17147 
17148  fail_invalid_desc:
17149 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);
17150 	DUK_WO_NORETURN(return;);
17151 
17152  fail_not_callable:
17153 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
17154 	DUK_WO_NORETURN(return;);
17155 }
17156 
17157 /*
17158  *  Object related
17159  *
17160  *  Note: seal() and freeze() are accessible through ECMAScript bindings,
17161  *  and are not exposed through the API.
17162  */
17163 
duk_compact(duk_hthread * thr,duk_idx_t obj_idx)17164 DUK_EXTERNAL void duk_compact(duk_hthread *thr, duk_idx_t obj_idx) {
17165 	duk_hobject *obj;
17166 
17167 	DUK_ASSERT_API_ENTRY(thr);
17168 
17169 	obj = duk_get_hobject(thr, obj_idx);
17170 	if (obj) {
17171 		/* Note: this may fail, caller should protect the call if necessary */
17172 		duk_hobject_compact_props(thr, obj);
17173 	}
17174 }
17175 
duk_compact_m1(duk_hthread * thr)17176 DUK_INTERNAL void duk_compact_m1(duk_hthread *thr) {
17177 	DUK_ASSERT_API_ENTRY(thr);
17178 
17179 	duk_compact(thr, -1);
17180 }
17181 
17182 /* XXX: the duk_hobject_enum.c stack APIs should be reworked */
17183 
duk_enum(duk_hthread * thr,duk_idx_t obj_idx,duk_uint_t enum_flags)17184 DUK_EXTERNAL void duk_enum(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t enum_flags) {
17185 	DUK_ASSERT_API_ENTRY(thr);
17186 
17187 	duk_dup(thr, obj_idx);
17188 	duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
17189 	duk_hobject_enumerator_create(thr, enum_flags);   /* [target] -> [enum] */
17190 }
17191 
duk_next(duk_hthread * thr,duk_idx_t enum_index,duk_bool_t get_value)17192 DUK_EXTERNAL duk_bool_t duk_next(duk_hthread *thr, duk_idx_t enum_index, duk_bool_t get_value) {
17193 	DUK_ASSERT_API_ENTRY(thr);
17194 
17195 	duk_require_hobject(thr, enum_index);
17196 	duk_dup(thr, enum_index);
17197 	return duk_hobject_enumerator_next(thr, get_value);
17198 }
17199 
duk_seal_freeze_raw(duk_hthread * thr,duk_idx_t obj_idx,duk_bool_t is_freeze)17200 DUK_INTERNAL void duk_seal_freeze_raw(duk_hthread *thr, duk_idx_t obj_idx, duk_bool_t is_freeze) {
17201 	duk_tval *tv;
17202 	duk_hobject *h;
17203 
17204 	DUK_ASSERT_API_ENTRY(thr);
17205 
17206 	tv = duk_require_tval(thr, obj_idx);
17207 	DUK_ASSERT(tv != NULL);
17208 
17209 	/* Seal/freeze are quite rare in practice so it'd be nice to get the
17210 	 * correct behavior simply via automatic promotion (at the cost of some
17211 	 * memory churn).  However, the promoted objects don't behave the same,
17212 	 * e.g. promoted lightfuncs are extensible.
17213 	 */
17214 
17215 	switch (DUK_TVAL_GET_TAG(tv)) {
17216 	case DUK_TAG_BUFFER:
17217 		/* Plain buffer: already sealed, but not frozen (and can't be frozen
17218 		 * because index properties can't be made non-writable.
17219 		 */
17220 		if (is_freeze) {
17221 			goto fail_cannot_freeze;
17222 		}
17223 		break;
17224 	case DUK_TAG_LIGHTFUNC:
17225 		/* Lightfunc: already sealed and frozen, success. */
17226 		break;
17227 	case DUK_TAG_OBJECT:
17228 		h = DUK_TVAL_GET_OBJECT(tv);
17229 		DUK_ASSERT(h != NULL);
17230 		if (is_freeze && DUK_HOBJECT_IS_BUFOBJ(h)) {
17231 			/* Buffer objects cannot be frozen because there's no internal
17232 			 * support for making virtual array indices non-writable.
17233 			 */
17234 			DUK_DD(DUK_DDPRINT("cannot freeze a buffer object"));
17235 			goto fail_cannot_freeze;
17236 		}
17237 		duk_hobject_object_seal_freeze_helper(thr, h, is_freeze);
17238 
17239 		/* Sealed and frozen objects cannot gain any more properties,
17240 		 * so this is a good time to compact them.
17241 		 */
17242 		duk_hobject_compact_props(thr, h);
17243 		break;
17244 	default:
17245 		/* ES2015 Sections 19.1.2.5, 19.1.2.17 */
17246 		break;
17247 	}
17248 	return;
17249 
17250  fail_cannot_freeze:
17251 	DUK_ERROR_TYPE_INVALID_ARGS(thr);  /* XXX: proper error message */
17252 	DUK_WO_NORETURN(return;);
17253 }
17254 
duk_seal(duk_hthread * thr,duk_idx_t obj_idx)17255 DUK_EXTERNAL void duk_seal(duk_hthread *thr, duk_idx_t obj_idx) {
17256 	DUK_ASSERT_API_ENTRY(thr);
17257 
17258 	duk_seal_freeze_raw(thr, obj_idx, 0 /*is_freeze*/);
17259 }
17260 
duk_freeze(duk_hthread * thr,duk_idx_t obj_idx)17261 DUK_EXTERNAL void duk_freeze(duk_hthread *thr, duk_idx_t obj_idx) {
17262 	DUK_ASSERT_API_ENTRY(thr);
17263 
17264 	duk_seal_freeze_raw(thr, obj_idx, 1 /*is_freeze*/);
17265 }
17266 
17267 /*
17268  *  Helpers for writing multiple properties
17269  */
17270 
duk_put_function_list(duk_hthread * thr,duk_idx_t obj_idx,const duk_function_list_entry * funcs)17271 DUK_EXTERNAL void duk_put_function_list(duk_hthread *thr, duk_idx_t obj_idx, const duk_function_list_entry *funcs) {
17272 	const duk_function_list_entry *ent = funcs;
17273 
17274 	DUK_ASSERT_API_ENTRY(thr);
17275 
17276 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17277 	if (ent != NULL) {
17278 		while (ent->key != NULL) {
17279 			duk_push_c_function(thr, ent->value, ent->nargs);
17280 			duk_put_prop_string(thr, obj_idx, ent->key);
17281 			ent++;
17282 		}
17283 	}
17284 }
17285 
duk_put_number_list(duk_hthread * thr,duk_idx_t obj_idx,const duk_number_list_entry * numbers)17286 DUK_EXTERNAL void duk_put_number_list(duk_hthread *thr, duk_idx_t obj_idx, const duk_number_list_entry *numbers) {
17287 	const duk_number_list_entry *ent = numbers;
17288 	duk_tval *tv;
17289 
17290 	DUK_ASSERT_API_ENTRY(thr);
17291 
17292 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17293 	if (ent != NULL) {
17294 		while (ent->key != NULL) {
17295 			tv = thr->valstack_top++;
17296 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));  /* value stack init policy */
17297 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, ent->value);  /* no need for decref/incref */
17298 			duk_put_prop_string(thr, obj_idx, ent->key);
17299 			ent++;
17300 		}
17301 	}
17302 }
17303 
17304 /*
17305  *  Shortcut for accessing global object properties
17306  */
17307 
duk_get_global_string(duk_hthread * thr,const char * key)17308 DUK_EXTERNAL duk_bool_t duk_get_global_string(duk_hthread *thr, const char *key) {
17309 	duk_bool_t ret;
17310 
17311 	DUK_ASSERT_API_ENTRY(thr);
17312 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17313 
17314 	/* XXX: direct implementation */
17315 
17316 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17317 	ret = duk_get_prop_string(thr, -1, key);
17318 	duk_remove_m2(thr);
17319 	return ret;
17320 }
17321 
duk_get_global_lstring(duk_hthread * thr,const char * key,duk_size_t key_len)17322 DUK_EXTERNAL duk_bool_t duk_get_global_lstring(duk_hthread *thr, const char *key, duk_size_t key_len) {
17323 	duk_bool_t ret;
17324 
17325 	DUK_ASSERT_API_ENTRY(thr);
17326 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17327 
17328 	/* XXX: direct implementation */
17329 
17330 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17331 	ret = duk_get_prop_lstring(thr, -1, key, key_len);
17332 	duk_remove_m2(thr);
17333 	return ret;
17334 }
17335 
17336 #if !defined(DUK_USE_PREFER_SIZE)
duk_get_global_literal_raw(duk_hthread * thr,const char * key,duk_size_t key_len)17337 DUK_EXTERNAL duk_bool_t duk_get_global_literal_raw(duk_hthread *thr, const char *key, duk_size_t key_len) {
17338 	duk_bool_t ret;
17339 
17340 	DUK_ASSERT_API_ENTRY(thr);
17341 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17342 	DUK_ASSERT(key[key_len] == (char) 0);
17343 
17344 	/* XXX: direct implementation */
17345 
17346 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17347 	ret = duk_get_prop_literal_raw(thr, -1, key, key_len);
17348 	duk_remove_m2(thr);
17349 	return ret;
17350 }
17351 #endif
17352 
duk_get_global_heapptr(duk_hthread * thr,void * ptr)17353 DUK_EXTERNAL duk_bool_t duk_get_global_heapptr(duk_hthread *thr, void *ptr) {
17354 	duk_bool_t ret;
17355 
17356 	DUK_ASSERT_API_ENTRY(thr);
17357 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17358 
17359 	/* XXX: direct implementation */
17360 
17361 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17362 	ret = duk_get_prop_heapptr(thr, -1, ptr);
17363 	duk_remove_m2(thr);
17364 	return ret;
17365 }
17366 
17367 
duk_put_global_string(duk_hthread * thr,const char * key)17368 DUK_EXTERNAL duk_bool_t duk_put_global_string(duk_hthread *thr, const char *key) {
17369 	duk_bool_t ret;
17370 
17371 	DUK_ASSERT_API_ENTRY(thr);
17372 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17373 
17374 	/* XXX: direct implementation */
17375 
17376 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17377 	duk_insert(thr, -2);
17378 	ret = duk_put_prop_string(thr, -2, key);  /* [ ... global val ] -> [ ... global ] */
17379 	duk_pop(thr);
17380 	return ret;
17381 }
17382 
duk_put_global_lstring(duk_hthread * thr,const char * key,duk_size_t key_len)17383 DUK_EXTERNAL duk_bool_t duk_put_global_lstring(duk_hthread *thr, const char *key, duk_size_t key_len) {
17384 	duk_bool_t ret;
17385 
17386 	DUK_ASSERT_API_ENTRY(thr);
17387 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17388 
17389 	/* XXX: direct implementation */
17390 
17391 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17392 	duk_insert(thr, -2);
17393 	ret = duk_put_prop_lstring(thr, -2, key, key_len);  /* [ ... global val ] -> [ ... global ] */
17394 	duk_pop(thr);
17395 	return ret;
17396 }
17397 
17398 #if !defined(DUK_USE_PREFER_SIZE)
duk_put_global_literal_raw(duk_hthread * thr,const char * key,duk_size_t key_len)17399 DUK_EXTERNAL duk_bool_t duk_put_global_literal_raw(duk_hthread *thr, const char *key, duk_size_t key_len) {
17400 	duk_bool_t ret;
17401 
17402 	DUK_ASSERT_API_ENTRY(thr);
17403 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17404 	DUK_ASSERT(key[key_len] == (char) 0);
17405 
17406 	/* XXX: direct implementation */
17407 
17408 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17409 	duk_insert(thr, -2);
17410 	ret = duk_put_prop_literal_raw(thr, -2, key, key_len);  /* [ ... global val ] -> [ ... global ] */
17411 	duk_pop(thr);
17412 	return ret;
17413 }
17414 #endif
17415 
duk_put_global_heapptr(duk_hthread * thr,void * ptr)17416 DUK_EXTERNAL duk_bool_t duk_put_global_heapptr(duk_hthread *thr, void *ptr) {
17417 	duk_bool_t ret;
17418 
17419 	DUK_ASSERT_API_ENTRY(thr);
17420 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17421 
17422 	/* XXX: direct implementation */
17423 
17424 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17425 	duk_insert(thr, -2);
17426 	ret = duk_put_prop_heapptr(thr, -2, ptr);  /* [ ... global val ] -> [ ... global ] */
17427 	duk_pop(thr);
17428 	return ret;
17429 }
17430 
17431 /*
17432  *  ES2015 GetMethod()
17433  */
17434 
duk_get_method_stridx(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t stridx)17435 DUK_INTERNAL duk_bool_t duk_get_method_stridx(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t stridx) {
17436 	(void) duk_get_prop_stridx(thr, idx, stridx);
17437 	if (duk_is_null_or_undefined(thr, -1)) {
17438 		duk_pop_nodecref_unsafe(thr);
17439 		return 0;
17440 	}
17441 	if (!duk_is_callable(thr, -1)) {
17442 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
17443 		DUK_WO_NORETURN(return 0;);
17444 	}
17445 	return 1;
17446 }
17447 
17448 /*
17449  *  Object prototype
17450  */
17451 
duk_get_prototype(duk_hthread * thr,duk_idx_t idx)17452 DUK_EXTERNAL void duk_get_prototype(duk_hthread *thr, duk_idx_t idx) {
17453 	duk_hobject *obj;
17454 	duk_hobject *proto;
17455 
17456 	DUK_ASSERT_API_ENTRY(thr);
17457 
17458 	obj = duk_require_hobject(thr, idx);
17459 	DUK_ASSERT(obj != NULL);
17460 
17461 	/* XXX: shared helper for duk_push_hobject_or_undefined()? */
17462 	proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, obj);
17463 	if (proto) {
17464 		duk_push_hobject(thr, proto);
17465 	} else {
17466 		duk_push_undefined(thr);
17467 	}
17468 }
17469 
duk_set_prototype(duk_hthread * thr,duk_idx_t idx)17470 DUK_EXTERNAL void duk_set_prototype(duk_hthread *thr, duk_idx_t idx) {
17471 	duk_hobject *obj;
17472 	duk_hobject *proto;
17473 
17474 	DUK_ASSERT_API_ENTRY(thr);
17475 
17476 	obj = duk_require_hobject(thr, idx);
17477 	DUK_ASSERT(obj != NULL);
17478 	duk_require_type_mask(thr, -1, DUK_TYPE_MASK_UNDEFINED |
17479 	                               DUK_TYPE_MASK_OBJECT);
17480 	proto = duk_get_hobject(thr, -1);
17481 	/* proto can also be NULL here (allowed explicitly) */
17482 
17483 #if defined(DUK_USE_ROM_OBJECTS)
17484 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
17485 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);  /* XXX: "read only object"? */
17486 		DUK_WO_NORETURN(return;);
17487 	}
17488 #endif
17489 
17490 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, obj, proto);
17491 
17492 	duk_pop(thr);
17493 }
17494 
17495 /*
17496  *  Object finalizer
17497  */
17498 
17499 #if defined(DUK_USE_FINALIZER_SUPPORT)
17500 /* XXX: these could be implemented as macros calling an internal function
17501  * directly.
17502  * XXX: same issue as with Duktape.fin: there's no way to delete the property
17503  * now (just set it to undefined).
17504  */
duk_get_finalizer(duk_hthread * thr,duk_idx_t idx)17505 DUK_EXTERNAL void duk_get_finalizer(duk_hthread *thr, duk_idx_t idx) {
17506 	DUK_ASSERT_API_ENTRY(thr);
17507 
17508 	duk_get_prop_stridx(thr, idx, DUK_STRIDX_INT_FINALIZER);
17509 }
17510 
duk_set_finalizer(duk_hthread * thr,duk_idx_t idx)17511 DUK_EXTERNAL void duk_set_finalizer(duk_hthread *thr, duk_idx_t idx) {
17512 	duk_hobject *h;
17513 	duk_bool_t callable;
17514 
17515 	DUK_ASSERT_API_ENTRY(thr);
17516 
17517 	h = duk_require_hobject(thr, idx);  /* Get before 'put' so that 'idx' is correct. */
17518 	callable = duk_is_callable(thr, -1);
17519 	duk_put_prop_stridx(thr, idx, DUK_STRIDX_INT_FINALIZER);
17520 
17521 	/* In addition to setting the finalizer property, keep a "have
17522 	 * finalizer" flag in duk_hobject in sync so that refzero can do
17523 	 * a very quick finalizer check by walking the prototype chain
17524 	 * and checking the flag alone.  (Note that this means that just
17525 	 * setting _Finalizer on an object won't affect finalizer checks.)
17526 	 *
17527 	 * NOTE: if the argument is a Proxy object, this flag will be set
17528 	 * on the Proxy, not the target.  As a result, the target won't get
17529 	 * a finalizer flag and the Proxy also won't be finalized as there's
17530 	 * an explicit Proxy check in finalization now.
17531 	 */
17532 	if (callable) {
17533 		DUK_HOBJECT_SET_HAVE_FINALIZER(h);
17534 	} else {
17535 		DUK_HOBJECT_CLEAR_HAVE_FINALIZER(h);
17536 	}
17537 }
17538 #else  /* DUK_USE_FINALIZER_SUPPORT */
duk_get_finalizer(duk_hthread * thr,duk_idx_t idx)17539 DUK_EXTERNAL void duk_get_finalizer(duk_hthread *thr, duk_idx_t idx) {
17540 	DUK_ASSERT_API_ENTRY(thr);
17541 	DUK_UNREF(idx);
17542 	DUK_ERROR_UNSUPPORTED(thr);
17543 	DUK_WO_NORETURN(return;);
17544 }
17545 
duk_set_finalizer(duk_hthread * thr,duk_idx_t idx)17546 DUK_EXTERNAL void duk_set_finalizer(duk_hthread *thr, duk_idx_t idx) {
17547 	DUK_ASSERT_API_ENTRY(thr);
17548 	DUK_UNREF(idx);
17549 	DUK_ERROR_UNSUPPORTED(thr);
17550 	DUK_WO_NORETURN(return;);
17551 }
17552 #endif  /* DUK_USE_FINALIZER_SUPPORT */
17553 #line 1 "duk_api_random.c"
17554 /*
17555  *  Random numbers
17556  */
17557 
17558 /* #include duk_internal.h -> already included */
17559 
duk_random(duk_hthread * thr)17560 DUK_EXTERNAL duk_double_t duk_random(duk_hthread *thr) {
17561 	return (duk_double_t) DUK_UTIL_GET_RANDOM_DOUBLE(thr);
17562 }
17563 #line 1 "duk_api_stack.c"
17564 /*
17565  *  API calls related to general value stack manipulation: resizing the value
17566  *  stack, pushing and popping values, type checking and reading values,
17567  *  coercing values, etc.
17568  *
17569  *  Also contains internal functions (such as duk_get_tval()), defined
17570  *  in duk_api_internal.h, with semantics similar to the public API.
17571  */
17572 
17573 /* XXX: repetition of stack pre-checks -> helper or macro or inline */
17574 /* XXX: shared api error strings, and perhaps even throw code for rare cases? */
17575 
17576 /* #include duk_internal.h -> already included */
17577 
17578 /*
17579  *  Forward declarations
17580  */
17581 
17582 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);
17583 
17584 /*
17585  *  Global state for working around missing variadic macros
17586  */
17587 
17588 #if !defined(DUK_USE_VARIADIC_MACROS)
17589 DUK_EXTERNAL const char *duk_api_global_filename = NULL;
17590 DUK_EXTERNAL duk_int_t duk_api_global_line = 0;
17591 #endif
17592 
17593 /*
17594  *  Misc helpers
17595  */
17596 
17597 DUK_LOCAL const char * const duk__symbol_type_strings[4] = {
17598 	"hidden", "global", "local", "wellknown"
17599 };
17600 
17601 #if !defined(DUK_USE_PACKED_TVAL)
17602 DUK_LOCAL const duk_uint_t duk__type_from_tag[] = {
17603 	DUK_TYPE_NUMBER,
17604 	DUK_TYPE_NUMBER,  /* fastint */
17605 	DUK_TYPE_UNDEFINED,
17606 	DUK_TYPE_NULL,
17607 	DUK_TYPE_BOOLEAN,
17608 	DUK_TYPE_POINTER,
17609 	DUK_TYPE_LIGHTFUNC,
17610 	DUK_TYPE_NONE,
17611 	DUK_TYPE_STRING,
17612 	DUK_TYPE_OBJECT,
17613 	DUK_TYPE_BUFFER,
17614 };
17615 DUK_LOCAL const duk_uint_t duk__type_mask_from_tag[] = {
17616 	DUK_TYPE_MASK_NUMBER,
17617 	DUK_TYPE_MASK_NUMBER,  /* fastint */
17618 	DUK_TYPE_MASK_UNDEFINED,
17619 	DUK_TYPE_MASK_NULL,
17620 	DUK_TYPE_MASK_BOOLEAN,
17621 	DUK_TYPE_MASK_POINTER,
17622 	DUK_TYPE_MASK_LIGHTFUNC,
17623 	DUK_TYPE_MASK_NONE,
17624 	DUK_TYPE_MASK_STRING,
17625 	DUK_TYPE_MASK_OBJECT,
17626 	DUK_TYPE_MASK_BUFFER,
17627 };
17628 #endif  /* !DUK_USE_PACKED_TVAL */
17629 
17630 /* Assert that there's room for one value. */
17631 #define DUK__ASSERT_SPACE() do { \
17632 		DUK_ASSERT(!(thr->valstack_top >= thr->valstack_end)); \
17633 	} while (0)
17634 
17635 /* Check that there's room to push one value. */
17636 #if defined(DUK_USE_VALSTACK_UNSAFE)
17637 /* Faster but value stack overruns are memory unsafe. */
17638 #define DUK__CHECK_SPACE() DUK__ASSERT_SPACE()
17639 #else
17640 #define DUK__CHECK_SPACE() do { \
17641 		if (DUK_UNLIKELY(thr->valstack_top >= thr->valstack_end)) { \
17642 			DUK_ERROR_RANGE_PUSH_BEYOND(thr); \
17643 		} \
17644 	} while (0)
17645 #endif
17646 
duk__get_symbol_type(duk_hstring * h)17647 DUK_LOCAL duk_small_uint_t duk__get_symbol_type(duk_hstring *h) {
17648 	const duk_uint8_t *data;
17649 	duk_size_t len;
17650 
17651 	DUK_ASSERT(h != NULL);
17652 	DUK_ASSERT(DUK_HSTRING_HAS_SYMBOL(h));
17653 	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(h) >= 1);  /* always true, symbol prefix */
17654 
17655 	data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
17656 	len = DUK_HSTRING_GET_BYTELEN(h);
17657 	DUK_ASSERT(len >= 1);
17658 
17659 	/* XXX: differentiate between 0x82 and 0xff (hidden vs. internal?)? */
17660 
17661 	if (data[0] == 0xffU) {
17662 		return DUK_SYMBOL_TYPE_HIDDEN;
17663 	} else if (data[0] == 0x82U) {
17664 		return DUK_SYMBOL_TYPE_HIDDEN;
17665 	} else if (data[0] == 0x80U) {
17666 		return DUK_SYMBOL_TYPE_GLOBAL;
17667 	} else if (data[len - 1] != 0xffU) {
17668 		return DUK_SYMBOL_TYPE_LOCAL;
17669 	} else {
17670 		return DUK_SYMBOL_TYPE_WELLKNOWN;
17671 	}
17672 }
17673 
duk__get_symbol_type_string(duk_hstring * h)17674 DUK_LOCAL const char *duk__get_symbol_type_string(duk_hstring *h) {
17675 	duk_small_uint_t idx;
17676 	idx = duk__get_symbol_type(h);
17677 	DUK_ASSERT(idx < sizeof(duk__symbol_type_strings));
17678 	return duk__symbol_type_strings[idx];
17679 }
17680 
17681 DUK_LOCAL_DECL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t tag);
17682 
duk__api_coerce_d2i(duk_hthread * thr,duk_idx_t idx,duk_int_t def_value,duk_bool_t require)17683 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) {
17684 	duk_tval *tv;
17685 	duk_small_int_t c;
17686 	duk_double_t d;
17687 
17688 	tv = duk_get_tval_or_unused(thr, idx);
17689 	DUK_ASSERT(tv != NULL);
17690 
17691 	/*
17692 	 *  Special cases like NaN and +/- Infinity are handled explicitly
17693 	 *  because a plain C coercion from double to int handles these cases
17694 	 *  in undesirable ways.  For instance, NaN may coerce to INT_MIN
17695 	 *  (not zero), and INT_MAX + 1 may coerce to INT_MIN (not INT_MAX).
17696 	 *
17697 	 *  This double-to-int coercion differs from ToInteger() because it
17698 	 *  has a finite range (ToInteger() allows e.g. +/- Infinity).  It
17699 	 *  also differs from ToInt32() because the INT_MIN/INT_MAX clamping
17700 	 *  depends on the size of the int type on the platform.  In particular,
17701 	 *  on platforms with a 64-bit int type, the full range is allowed.
17702 	 */
17703 
17704 #if defined(DUK_USE_FASTINT)
17705 	if (DUK_TVAL_IS_FASTINT(tv)) {
17706 		duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
17707 #if (DUK_INT_MAX <= 0x7fffffffL)
17708 		/* Clamping only necessary for 32-bit ints. */
17709 		if (t < DUK_INT_MIN) {
17710 			t = DUK_INT_MIN;
17711 		} else if (t > DUK_INT_MAX) {
17712 			t = DUK_INT_MAX;
17713 		}
17714 #endif
17715 		return (duk_int_t) t;
17716 	}
17717 #endif
17718 
17719 	if (DUK_TVAL_IS_NUMBER(tv)) {
17720 		d = DUK_TVAL_GET_NUMBER(tv);
17721 		c = (duk_small_int_t) DUK_FPCLASSIFY(d);
17722 		if (c == DUK_FP_NAN) {
17723 			return 0;
17724 		} else if (d < (duk_double_t) DUK_INT_MIN) {
17725 			/* covers -Infinity */
17726 			return DUK_INT_MIN;
17727 		} else if (d > (duk_double_t) DUK_INT_MAX) {
17728 			/* covers +Infinity */
17729 			return DUK_INT_MAX;
17730 		} else {
17731 			/* coerce towards zero */
17732 			return (duk_int_t) d;
17733 		}
17734 	}
17735 
17736 	if (require) {
17737 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
17738 		DUK_WO_NORETURN(return 0;);
17739 	}
17740 
17741 	return def_value;
17742 }
17743 
duk__api_coerce_d2ui(duk_hthread * thr,duk_idx_t idx,duk_uint_t def_value,duk_bool_t require)17744 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) {
17745 	duk_tval *tv;
17746 	duk_small_int_t c;
17747 	duk_double_t d;
17748 
17749 	/* Same as above but for unsigned int range. */
17750 
17751 	tv = duk_get_tval_or_unused(thr, idx);
17752 	DUK_ASSERT(tv != NULL);
17753 
17754 #if defined(DUK_USE_FASTINT)
17755 	if (DUK_TVAL_IS_FASTINT(tv)) {
17756 		duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
17757 		if (t < 0) {
17758 			t = 0;
17759 		}
17760 #if (DUK_UINT_MAX <= 0xffffffffUL)
17761 		/* Clamping only necessary for 32-bit ints. */
17762 		else if (t > DUK_UINT_MAX) {
17763 			t = DUK_UINT_MAX;
17764 		}
17765 #endif
17766 		return (duk_uint_t) t;
17767 	}
17768 #endif
17769 
17770 	if (DUK_TVAL_IS_NUMBER(tv)) {
17771 		d = DUK_TVAL_GET_NUMBER(tv);
17772 		c = (duk_small_int_t) DUK_FPCLASSIFY(d);
17773 		if (c == DUK_FP_NAN) {
17774 			return 0;
17775 		} else if (d < 0.0) {
17776 			/* covers -Infinity */
17777 			return (duk_uint_t) 0;
17778 		} else if (d > (duk_double_t) DUK_UINT_MAX) {
17779 			/* covers +Infinity */
17780 			return (duk_uint_t) DUK_UINT_MAX;
17781 		} else {
17782 			/* coerce towards zero */
17783 			return (duk_uint_t) d;
17784 		}
17785 	}
17786 
17787 	if (require) {
17788 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
17789 		DUK_WO_NORETURN(return 0;);
17790 	}
17791 
17792 	return def_value;
17793 }
17794 
17795 /*
17796  *  Stack index validation/normalization and getting a stack duk_tval ptr.
17797  *
17798  *  These are called by many API entrypoints so the implementations must be
17799  *  fast and "inlined".
17800  *
17801  *  There's some repetition because of this; keep the functions in sync.
17802  */
17803 
duk_normalize_index(duk_hthread * thr,duk_idx_t idx)17804 DUK_EXTERNAL duk_idx_t duk_normalize_index(duk_hthread *thr, duk_idx_t idx) {
17805 	duk_uidx_t vs_size;
17806 	duk_uidx_t uidx;
17807 
17808 	DUK_ASSERT_API_ENTRY(thr);
17809 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
17810 
17811 	/* Care must be taken to avoid pointer wrapping in the index
17812 	 * validation.  For instance, on a 32-bit platform with 8-byte
17813 	 * duk_tval the index 0x20000000UL would wrap the memory space
17814 	 * once.
17815 	 */
17816 
17817 	/* Assume value stack sizes (in elements) fits into duk_idx_t. */
17818 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
17819 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
17820 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
17821 
17822 	if (idx < 0) {
17823 		uidx = vs_size + (duk_uidx_t) idx;
17824 	} else {
17825 		/* since index non-negative */
17826 		DUK_ASSERT(idx != DUK_INVALID_INDEX);
17827 		uidx = (duk_uidx_t) idx;
17828 	}
17829 
17830 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
17831 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
17832 
17833 	if (DUK_LIKELY(uidx < vs_size)) {
17834 		return (duk_idx_t) uidx;
17835 	}
17836 	return DUK_INVALID_INDEX;
17837 }
17838 
duk_require_normalize_index(duk_hthread * thr,duk_idx_t idx)17839 DUK_EXTERNAL duk_idx_t duk_require_normalize_index(duk_hthread *thr, duk_idx_t idx) {
17840 	duk_uidx_t vs_size;
17841 	duk_uidx_t uidx;
17842 
17843 	DUK_ASSERT_API_ENTRY(thr);
17844 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
17845 
17846 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
17847 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
17848 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
17849 
17850 	if (idx < 0) {
17851 		uidx = vs_size + (duk_uidx_t) idx;
17852 	} else {
17853 		DUK_ASSERT(idx != DUK_INVALID_INDEX);
17854 		uidx = (duk_uidx_t) idx;
17855 	}
17856 
17857 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
17858 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
17859 
17860 	if (DUK_LIKELY(uidx < vs_size)) {
17861 		return (duk_idx_t) uidx;
17862 	}
17863 	DUK_ERROR_RANGE_INDEX(thr, idx);
17864 	DUK_WO_NORETURN(return 0;);
17865 }
17866 
duk_get_tval(duk_hthread * thr,duk_idx_t idx)17867 DUK_INTERNAL duk_tval *duk_get_tval(duk_hthread *thr, duk_idx_t idx) {
17868 	duk_uidx_t vs_size;
17869 	duk_uidx_t uidx;
17870 
17871 	DUK_ASSERT_API_ENTRY(thr);
17872 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
17873 
17874 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
17875 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
17876 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
17877 
17878 	if (idx < 0) {
17879 		uidx = vs_size + (duk_uidx_t) idx;
17880 	} else {
17881 		DUK_ASSERT(idx != DUK_INVALID_INDEX);
17882 		uidx = (duk_uidx_t) idx;
17883 	}
17884 
17885 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
17886 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
17887 
17888 	if (DUK_LIKELY(uidx < vs_size)) {
17889 		return thr->valstack_bottom + uidx;
17890 	}
17891 	return NULL;
17892 }
17893 
17894 /* Variant of duk_get_tval() which is guaranteed to return a valid duk_tval
17895  * pointer.  When duk_get_tval() would return NULL, this variant returns a
17896  * pointer to a duk_tval with tag DUK_TAG_UNUSED.  This allows the call site
17897  * to avoid an unnecessary NULL check which sometimes leads to better code.
17898  * The return duk_tval is read only (at least for the UNUSED value).
17899  */
17900 DUK_LOCAL const duk_tval_unused duk__const_tval_unused = DUK_TVAL_UNUSED_INITIALIZER();
17901 
duk_get_tval_or_unused(duk_hthread * thr,duk_idx_t idx)17902 DUK_INTERNAL duk_tval *duk_get_tval_or_unused(duk_hthread *thr, duk_idx_t idx) {
17903 	duk_tval *tv;
17904 
17905 	DUK_ASSERT_API_ENTRY(thr);
17906 
17907 	tv = duk_get_tval(thr, idx);
17908 	if (tv != NULL) {
17909 		return tv;
17910 	}
17911 	return (duk_tval *) DUK_LOSE_CONST(&duk__const_tval_unused);
17912 }
17913 
duk_require_tval(duk_hthread * thr,duk_idx_t idx)17914 DUK_INTERNAL duk_tval *duk_require_tval(duk_hthread *thr, duk_idx_t idx) {
17915 	duk_uidx_t vs_size;
17916 	duk_uidx_t uidx;
17917 
17918 	DUK_ASSERT_API_ENTRY(thr);
17919 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
17920 
17921 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
17922 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
17923 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
17924 
17925 	/* Use unsigned arithmetic to optimize comparison. */
17926 	if (idx < 0) {
17927 		uidx = vs_size + (duk_uidx_t) idx;
17928 	} else {
17929 		DUK_ASSERT(idx != DUK_INVALID_INDEX);
17930 		uidx = (duk_uidx_t) idx;
17931 	}
17932 
17933 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
17934 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
17935 
17936 	if (DUK_LIKELY(uidx < vs_size)) {
17937 		return thr->valstack_bottom + uidx;
17938 	}
17939 	DUK_ERROR_RANGE_INDEX(thr, idx);
17940 	DUK_WO_NORETURN(return NULL;);
17941 }
17942 
17943 /* Non-critical. */
duk_is_valid_index(duk_hthread * thr,duk_idx_t idx)17944 DUK_EXTERNAL duk_bool_t duk_is_valid_index(duk_hthread *thr, duk_idx_t idx) {
17945 	DUK_ASSERT_API_ENTRY(thr);
17946 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
17947 
17948 	return (duk_normalize_index(thr, idx) >= 0);
17949 }
17950 
17951 /* Non-critical. */
duk_require_valid_index(duk_hthread * thr,duk_idx_t idx)17952 DUK_EXTERNAL void duk_require_valid_index(duk_hthread *thr, duk_idx_t idx) {
17953 	DUK_ASSERT_API_ENTRY(thr);
17954 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
17955 
17956 	if (DUK_UNLIKELY(duk_normalize_index(thr, idx) < 0)) {
17957 		DUK_ERROR_RANGE_INDEX(thr, idx);
17958 		DUK_WO_NORETURN(return;);
17959 	}
17960 }
17961 
17962 /*
17963  *  Value stack top handling
17964  */
17965 
duk_get_top(duk_hthread * thr)17966 DUK_EXTERNAL duk_idx_t duk_get_top(duk_hthread *thr) {
17967 	DUK_ASSERT_API_ENTRY(thr);
17968 
17969 	return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
17970 }
17971 
17972 /* Internal helper to get current top but to require a minimum top value
17973  * (TypeError if not met).
17974  */
duk_get_top_require_min(duk_hthread * thr,duk_idx_t min_top)17975 DUK_INTERNAL duk_idx_t duk_get_top_require_min(duk_hthread *thr, duk_idx_t min_top) {
17976 	duk_idx_t ret;
17977 
17978 	DUK_ASSERT_API_ENTRY(thr);
17979 
17980 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
17981 	if (DUK_UNLIKELY(ret < min_top)) {
17982 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
17983 		DUK_WO_NORETURN(return 0;);
17984 	}
17985 	return ret;
17986 }
17987 
17988 /* Set stack top within currently allocated range, but don't reallocate.
17989  * This is performance critical especially for call handling, so whenever
17990  * changing, profile and look at generated code.
17991  */
duk_set_top(duk_hthread * thr,duk_idx_t idx)17992 DUK_EXTERNAL void duk_set_top(duk_hthread *thr, duk_idx_t idx) {
17993 	duk_uidx_t vs_size;
17994 	duk_uidx_t vs_limit;
17995 	duk_uidx_t uidx;
17996 	duk_tval *tv;
17997 
17998 	DUK_ASSERT_API_ENTRY(thr);
17999 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
18000 
18001 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18002 	DUK_ASSERT(thr->valstack_end >= thr->valstack_bottom);
18003 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
18004 	vs_limit = (duk_uidx_t) (thr->valstack_end - thr->valstack_bottom);
18005 
18006 	if (idx < 0) {
18007 		/* Negative indices are always within allocated stack but
18008 		 * must not go below zero index.
18009 		 */
18010 		uidx = vs_size + (duk_uidx_t) idx;
18011 	} else {
18012 		/* Positive index can be higher than valstack top but must
18013 		 * not go above allocated stack (equality is OK).
18014 		 */
18015 		uidx = (duk_uidx_t) idx;
18016 	}
18017 
18018 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
18019 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
18020 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_limit);
18021 
18022 #if defined(DUK_USE_VALSTACK_UNSAFE)
18023 	DUK_ASSERT(uidx <= vs_limit);
18024 	DUK_UNREF(vs_limit);
18025 #else
18026 	if (DUK_UNLIKELY(uidx > vs_limit)) {
18027 		DUK_ERROR_RANGE_INDEX(thr, idx);
18028 		DUK_WO_NORETURN(return;);
18029 	}
18030 #endif
18031 	DUK_ASSERT(uidx <= vs_limit);
18032 
18033 	/* Handle change in value stack top.  Respect value stack
18034 	 * initialization policy: 'undefined' above top.  Note that
18035 	 * DECREF may cause a side effect that reallocates valstack,
18036 	 * so must relookup after DECREF.
18037 	 */
18038 
18039 	if (uidx >= vs_size) {
18040 		/* Stack size increases or stays the same. */
18041 #if defined(DUK_USE_ASSERTIONS)
18042 		duk_uidx_t count;
18043 
18044 		count = uidx - vs_size;
18045 		while (count != 0) {
18046 			count--;
18047 			tv = thr->valstack_top + count;
18048 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
18049 		}
18050 #endif
18051 		thr->valstack_top = thr->valstack_bottom + uidx;
18052 	} else {
18053 		/* Stack size decreases. */
18054 #if defined(DUK_USE_REFERENCE_COUNTING)
18055 		duk_uidx_t count;
18056 		duk_tval *tv_end;
18057 
18058 		count = vs_size - uidx;
18059 		DUK_ASSERT(count > 0);
18060 		tv = thr->valstack_top;
18061 		tv_end = tv - count;
18062 		DUK_ASSERT(tv > tv_end);  /* Because count > 0. */
18063 		do {
18064 			tv--;
18065 			DUK_ASSERT(tv >= thr->valstack_bottom);
18066 			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
18067 		} while (tv != tv_end);
18068 		thr->valstack_top = tv_end;
18069 		DUK_REFZERO_CHECK_FAST(thr);
18070 #else  /* DUK_USE_REFERENCE_COUNTING */
18071 		duk_uidx_t count;
18072 		duk_tval *tv_end;
18073 
18074 		count = vs_size - uidx;
18075 		tv = thr->valstack_top;
18076 		tv_end = tv - count;
18077 		DUK_ASSERT(tv > tv_end);
18078 		do {
18079 			tv--;
18080 			DUK_TVAL_SET_UNDEFINED(tv);
18081 		} while (tv != tv_end);
18082 		thr->valstack_top = tv_end;
18083 #endif  /* DUK_USE_REFERENCE_COUNTING */
18084 	}
18085 }
18086 
18087 /* Internal variant with a non-negative index and no runtime size checks. */
18088 #if defined(DUK_USE_PREFER_SIZE)
duk_set_top_unsafe(duk_hthread * thr,duk_idx_t idx)18089 DUK_INTERNAL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx) {
18090 	DUK_ASSERT_API_ENTRY(thr);
18091 
18092 	duk_set_top(thr, idx);
18093 }
18094 #else  /* DUK_USE_PREFER_SIZE */
duk_set_top_unsafe(duk_hthread * thr,duk_idx_t idx)18095 DUK_INTERNAL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx) {
18096 	duk_uidx_t uidx;
18097 	duk_uidx_t vs_size;
18098 	duk_tval *tv;
18099 
18100 	DUK_ASSERT_API_ENTRY(thr);
18101 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18102 	DUK_ASSERT(thr->valstack_end >= thr->valstack_bottom);
18103 	DUK_ASSERT(idx >= 0);
18104 	DUK_ASSERT(idx <= (duk_idx_t) (thr->valstack_end - thr->valstack_bottom));
18105 
18106 	/* XXX: byte arithmetic */
18107 	uidx = (duk_uidx_t) idx;
18108 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
18109 
18110 	if (uidx >= vs_size) {
18111 		/* Stack size increases or stays the same. */
18112 #if defined(DUK_USE_ASSERTIONS)
18113 		duk_uidx_t count;
18114 
18115 		count = uidx - vs_size;
18116 		while (count != 0) {
18117 			count--;
18118 			tv = thr->valstack_top + count;
18119 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
18120 		}
18121 #endif
18122 		thr->valstack_top = thr->valstack_bottom + uidx;
18123 	} else {
18124 		/* Stack size decreases. */
18125 #if defined(DUK_USE_REFERENCE_COUNTING)
18126 		duk_uidx_t count;
18127 		duk_tval *tv_end;
18128 
18129 		count = vs_size - uidx;
18130 		DUK_ASSERT(count > 0);
18131 		tv = thr->valstack_top;
18132 		tv_end = tv - count;
18133 		DUK_ASSERT(tv > tv_end);  /* Because count > 0. */
18134 		do {
18135 			tv--;
18136 			DUK_ASSERT(tv >= thr->valstack_bottom);
18137 			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
18138 		} while (tv != tv_end);
18139 		thr->valstack_top = tv_end;
18140 		DUK_REFZERO_CHECK_FAST(thr);
18141 #else  /* DUK_USE_REFERENCE_COUNTING */
18142 		duk_uidx_t count;
18143 		duk_tval *tv_end;
18144 
18145 		count = vs_size - uidx;
18146 		tv = thr->valstack_top;
18147 		tv_end = tv - count;
18148 		DUK_ASSERT(tv > tv_end);
18149 		do {
18150 			tv--;
18151 			DUK_TVAL_SET_UNDEFINED(tv);
18152 		} while (tv != tv_end);
18153 		thr->valstack_top = tv_end;
18154 #endif  /* DUK_USE_REFERENCE_COUNTING */
18155 	}
18156 }
18157 #endif  /* DUK_USE_PREFER_SIZE */
18158 
18159 /* Internal helper: set top to 'top', and set [idx_wipe_start,top[ to
18160  * 'undefined' (doing nothing if idx_wipe_start == top).  Indices are
18161  * positive and within value stack reserve.  This is used by call handling.
18162  */
duk_set_top_and_wipe(duk_hthread * thr,duk_idx_t top,duk_idx_t idx_wipe_start)18163 DUK_INTERNAL void duk_set_top_and_wipe(duk_hthread *thr, duk_idx_t top, duk_idx_t idx_wipe_start) {
18164 	DUK_ASSERT_API_ENTRY(thr);
18165 	DUK_ASSERT(top >= 0);
18166 	DUK_ASSERT(idx_wipe_start >= 0);
18167 	DUK_ASSERT(idx_wipe_start <= top);
18168 	DUK_ASSERT(thr->valstack_bottom + top <= thr->valstack_end);
18169 	DUK_ASSERT(thr->valstack_bottom + idx_wipe_start <= thr->valstack_end);
18170 
18171 	duk_set_top_unsafe(thr, idx_wipe_start);
18172 	duk_set_top_unsafe(thr, top);
18173 }
18174 
duk_get_top_index(duk_hthread * thr)18175 DUK_EXTERNAL duk_idx_t duk_get_top_index(duk_hthread *thr) {
18176 	duk_idx_t ret;
18177 
18178 	DUK_ASSERT_API_ENTRY(thr);
18179 
18180 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
18181 	if (DUK_UNLIKELY(ret < 0)) {
18182 		/* Return invalid index; if caller uses this without checking
18183 		 * in another API call, the index won't map to a valid stack
18184 		 * entry.
18185 		 */
18186 		return DUK_INVALID_INDEX;
18187 	}
18188 	return ret;
18189 }
18190 
18191 /* Internal variant: call assumes there is at least one element on the value
18192  * stack frame; this is only asserted for.
18193  */
duk_get_top_index_unsafe(duk_hthread * thr)18194 DUK_INTERNAL duk_idx_t duk_get_top_index_unsafe(duk_hthread *thr) {
18195 	duk_idx_t ret;
18196 
18197 	DUK_ASSERT_API_ENTRY(thr);
18198 
18199 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
18200 	return ret;
18201 }
18202 
duk_require_top_index(duk_hthread * thr)18203 DUK_EXTERNAL duk_idx_t duk_require_top_index(duk_hthread *thr) {
18204 	duk_idx_t ret;
18205 
18206 	DUK_ASSERT_API_ENTRY(thr);
18207 
18208 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
18209 	if (DUK_UNLIKELY(ret < 0)) {
18210 		DUK_ERROR_RANGE_INDEX(thr, -1);
18211 		DUK_WO_NORETURN(return 0;);
18212 	}
18213 	return ret;
18214 }
18215 
18216 /*
18217  *  Value stack resizing.
18218  *
18219  *  This resizing happens above the current "top": the value stack can be
18220  *  grown or shrunk, but the "top" is not affected.  The value stack cannot
18221  *  be resized to a size below the current reserve.
18222  *
18223  *  The low level reallocation primitive must carefully recompute all value
18224  *  stack pointers, and must also work if ALL pointers are NULL.  The resize
18225  *  is quite tricky because the valstack realloc may cause a mark-and-sweep,
18226  *  which may run finalizers.  Running finalizers may resize the valstack
18227  *  recursively (the same value stack we're working on).  So, after realloc
18228  *  returns, we know that the valstack bottom, top, and reserve should still
18229  *  be the same (there should not be live values above the "top"), but its
18230  *  underlying size, alloc_end, and base pointer may have changed.
18231  *
18232  *  'new_size' is known to be <= DUK_USE_VALSTACK_LIMIT, which ensures that
18233  *  size_t and pointer arithmetic won't wrap in duk__resize_valstack().
18234  */
18235 
18236 /* Low level valstack resize primitive, used for both grow and shrink.  All
18237  * adjustments for slack etc have already been done.  Doesn't throw but does
18238  * have allocation side effects.
18239  */
duk__resize_valstack(duk_hthread * thr,duk_size_t new_size)18240 DUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__resize_valstack(duk_hthread *thr, duk_size_t new_size) {
18241 	duk_tval *pre_valstack;
18242 	duk_tval *pre_bottom;
18243 	duk_tval *pre_top;
18244 	duk_tval *pre_end;
18245 	duk_tval *pre_alloc_end;
18246 	duk_ptrdiff_t ptr_diff;
18247 	duk_tval *new_valstack;
18248 	duk_size_t new_alloc_size;
18249 	duk_tval *tv_prev_alloc_end;
18250 	duk_tval *p;
18251 
18252 	DUK_ASSERT_HTHREAD_VALID(thr);
18253 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
18254 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18255 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
18256 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
18257 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) <= new_size);  /* can't resize below 'top' */
18258 	DUK_ASSERT(new_size <= DUK_USE_VALSTACK_LIMIT);  /* valstack limit caller has check, prevents wrapping */
18259 	DUK_ASSERT(new_size <= DUK_SIZE_MAX / sizeof(duk_tval));  /* specific assert for wrapping */
18260 
18261 	/* Pre-realloc pointer copies for asserts and debug logs. */
18262 	pre_valstack = thr->valstack;
18263 	pre_bottom = thr->valstack_bottom;
18264 	pre_top = thr->valstack_top;
18265 	pre_end = thr->valstack_end;
18266 	pre_alloc_end = thr->valstack_alloc_end;
18267 
18268 	DUK_UNREF(pre_valstack);
18269 	DUK_UNREF(pre_bottom);
18270 	DUK_UNREF(pre_top);
18271 	DUK_UNREF(pre_end);
18272 	DUK_UNREF(pre_alloc_end);
18273 
18274 	/* If finalizer torture enabled, force base pointer change every time
18275 	 * when it would be allowed.
18276 	 */
18277 #if defined(DUK_USE_FINALIZER_TORTURE)
18278 	if (thr->heap->pf_prevent_count == 0) {
18279 		duk_hthread_valstack_torture_realloc(thr);
18280 	}
18281 #endif
18282 
18283 	/* Allocate a new valstack using DUK_REALLOC_DIRECT() to deal with
18284 	 * a side effect changing the base pointer.
18285 	 */
18286 	new_alloc_size = sizeof(duk_tval) * new_size;
18287 	new_valstack = (duk_tval *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_valstack_ptr, (void *) thr, new_alloc_size);
18288 	if (DUK_UNLIKELY(new_valstack == NULL)) {
18289 		/* Because new_size != 0, if condition doesn't need to be
18290 		 * (new_valstack != NULL || new_size == 0).
18291 		 */
18292 		DUK_ASSERT(new_size != 0);
18293 		DUK_D(DUK_DPRINT("failed to resize valstack to %lu entries (%lu bytes)",
18294 		                 (unsigned long) new_size, (unsigned long) new_alloc_size));
18295 		return 0;
18296 	}
18297 
18298 	/* Debug log any changes in pointer(s) by side effects.  These don't
18299 	 * necessarily imply any incorrect behavior, but should be rare in
18300 	 * practice.
18301 	 */
18302 #if defined(DUK_USE_DEBUG)
18303 	if (thr->valstack != pre_valstack) {
18304 		DUK_D(DUK_DPRINT("valstack base pointer changed during valstack resize: %p -> %p",
18305 		                 (void *) pre_valstack, (void *) thr->valstack));
18306 	}
18307 	if (thr->valstack_bottom != pre_bottom) {
18308 		DUK_D(DUK_DPRINT("valstack bottom pointer changed during valstack resize: %p -> %p",
18309 		                 (void *) pre_bottom, (void *) thr->valstack_bottom));
18310 	}
18311 	if (thr->valstack_top != pre_top) {
18312 		DUK_D(DUK_DPRINT("valstack top pointer changed during valstack resize: %p -> %p",
18313 		                 (void *) pre_top, (void *) thr->valstack_top));
18314 	}
18315 	if (thr->valstack_end != pre_end) {
18316 		DUK_D(DUK_DPRINT("valstack end pointer changed during valstack resize: %p -> %p",
18317 		                 (void *) pre_end, (void *) thr->valstack_end));
18318 	}
18319 	if (thr->valstack_alloc_end != pre_alloc_end) {
18320 		DUK_D(DUK_DPRINT("valstack alloc_end pointer changed during valstack resize: %p -> %p",
18321 		                 (void *) pre_alloc_end, (void *) thr->valstack_alloc_end));
18322 	}
18323 #endif
18324 
18325 	/* Assertions: offsets for bottom, top, and end (reserve) must not
18326 	 * have changed even with side effects because they are always
18327 	 * restored in unwind.  For alloc_end there's no guarantee: it may
18328 	 * have grown or shrunk (but remain above 'end').
18329 	 */
18330 	DUK_ASSERT(thr->valstack_bottom - thr->valstack == pre_bottom - pre_valstack);
18331 	DUK_ASSERT(thr->valstack_top - thr->valstack == pre_top - pre_valstack);
18332 	DUK_ASSERT(thr->valstack_end - thr->valstack == pre_end - pre_valstack);
18333 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
18334 
18335 	/* Write new pointers.  Most pointers can be handled as a pointer
18336 	 * difference.
18337 	 */
18338 	ptr_diff = (duk_ptrdiff_t) ((duk_uint8_t *) new_valstack - (duk_uint8_t *) thr->valstack);
18339 	tv_prev_alloc_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_alloc_end + ptr_diff);
18340 	thr->valstack = new_valstack;
18341 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + ptr_diff);
18342 	thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_top + ptr_diff);
18343 	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_end + ptr_diff);
18344 	thr->valstack_alloc_end = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + new_alloc_size);
18345 
18346 	/* Assertions: pointer sanity after pointer updates. */
18347 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
18348 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18349 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
18350 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
18351 
18352 	DUK_D(DUK_DPRINT("resized valstack %lu -> %lu elements (%lu -> %lu bytes): "
18353 	                 "base=%p -> %p, bottom=%p -> %p (%ld), top=%p -> %p (%ld), "
18354 	                 "end=%p -> %p (%ld), alloc_end=%p -> %p (%ld);"
18355 	                 " tv_prev_alloc_end=%p (-> %ld inits; <0 means shrink)",
18356 	                 (unsigned long) (pre_alloc_end - pre_valstack),
18357 	                 (unsigned long) new_size,
18358 	                 (unsigned long) ((duk_uint8_t *) pre_alloc_end - (duk_uint8_t *) pre_valstack),
18359 	                 (unsigned long) new_alloc_size,
18360 	                 (void *) pre_valstack, (void *) thr->valstack,
18361 	                 (void *) pre_bottom, (void *) thr->valstack_bottom, (long) (thr->valstack_bottom - thr->valstack),
18362 	                 (void *) pre_top, (void *) thr->valstack_top, (long) (thr->valstack_top - thr->valstack),
18363 	                 (void *) pre_end, (void *) thr->valstack_end, (long) (thr->valstack_end - thr->valstack),
18364 	                 (void *) pre_alloc_end, (void *) thr->valstack_alloc_end, (long) (thr->valstack_alloc_end - thr->valstack),
18365 	                 (void *) tv_prev_alloc_end, (long) (thr->valstack_alloc_end - tv_prev_alloc_end)));
18366 
18367 	/* If allocation grew, init any new slots to 'undefined'. */
18368 	p = tv_prev_alloc_end;
18369 	while (p < thr->valstack_alloc_end) {
18370 		/* Never executed if new size is smaller. */
18371 		DUK_TVAL_SET_UNDEFINED(p);
18372 		p++;
18373 	}
18374 
18375 	/* Assert for value stack initialization policy. */
18376 #if defined(DUK_USE_ASSERTIONS)
18377 	p = thr->valstack_top;
18378 	while (p < thr->valstack_alloc_end) {
18379 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(p));
18380 		p++;
18381 	}
18382 #endif
18383 
18384 	return 1;
18385 }
18386 
duk__valstack_grow(duk_hthread * thr,duk_size_t min_bytes,duk_bool_t throw_on_error)18387 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) {
18388 	duk_size_t min_size;
18389 	duk_size_t new_size;
18390 
18391 	DUK_ASSERT(min_bytes / sizeof(duk_tval) * sizeof(duk_tval) == min_bytes);
18392 	min_size = min_bytes / sizeof(duk_tval);  /* from bytes to slots */
18393 
18394 #if defined(DUK_USE_VALSTACK_GROW_SHIFT)
18395 	/* New size is minimum size plus a proportional slack, e.g. shift of
18396 	 * 2 means a 25% slack.
18397 	 */
18398 	new_size = min_size + (min_size >> DUK_USE_VALSTACK_GROW_SHIFT);
18399 #else
18400 	/* New size is tight with no slack.  This is sometimes preferred in
18401 	 * low memory environments.
18402 	 */
18403 	new_size = min_size;
18404 #endif
18405 
18406 	if (DUK_UNLIKELY(new_size > DUK_USE_VALSTACK_LIMIT || new_size < min_size /*wrap*/)) {
18407 		/* Note: may be triggered even if minimal new_size would not reach the limit,
18408 		 * plan limit accordingly.
18409 		 */
18410 		if (throw_on_error) {
18411 			DUK_ERROR_RANGE(thr, DUK_STR_VALSTACK_LIMIT);
18412 			DUK_WO_NORETURN(return 0;);
18413 		}
18414 		return 0;
18415 	}
18416 
18417 	if (duk__resize_valstack(thr, new_size) == 0) {
18418 		if (throw_on_error) {
18419 			DUK_ERROR_ALLOC_FAILED(thr);
18420 			DUK_WO_NORETURN(return 0;);
18421 		}
18422 		return 0;
18423 	}
18424 
18425 	thr->valstack_end = thr->valstack + min_size;
18426 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
18427 
18428 	return 1;
18429 }
18430 
18431 /* Hot, inlined value stack grow check.  Because value stack almost never
18432  * grows, the actual resize call is in a NOINLINE helper.
18433  */
duk_valstack_grow_check_throw(duk_hthread * thr,duk_size_t min_bytes)18434 DUK_INTERNAL DUK_INLINE void duk_valstack_grow_check_throw(duk_hthread *thr, duk_size_t min_bytes) {
18435 	duk_tval *tv;
18436 
18437 	tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + min_bytes);
18438 	if (DUK_LIKELY(thr->valstack_end >= tv)) {
18439 		return;
18440 	}
18441 	if (DUK_LIKELY(thr->valstack_alloc_end >= tv)) {
18442 		/* Values in [valstack_top,valstack_alloc_end[ are initialized
18443 		 * to 'undefined' so we can just move the end pointer.
18444 		 */
18445 		thr->valstack_end = tv;
18446 		return;
18447 	}
18448 	(void) duk__valstack_grow(thr, min_bytes, 1 /*throw_on_error*/);
18449 }
18450 
18451 /* Hot, inlined value stack grow check which doesn't throw. */
duk_valstack_grow_check_nothrow(duk_hthread * thr,duk_size_t min_bytes)18452 DUK_INTERNAL DUK_INLINE duk_bool_t duk_valstack_grow_check_nothrow(duk_hthread *thr, duk_size_t min_bytes) {
18453 	duk_tval *tv;
18454 
18455 	tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + min_bytes);
18456 	if (DUK_LIKELY(thr->valstack_end >= tv)) {
18457 		return 1;
18458 	}
18459 	if (DUK_LIKELY(thr->valstack_alloc_end >= tv)) {
18460 		thr->valstack_end = tv;
18461 		return 1;
18462 	}
18463 	return duk__valstack_grow(thr, min_bytes, 0 /*throw_on_error*/);
18464 }
18465 
18466 /* Value stack shrink check, called from mark-and-sweep. */
duk_valstack_shrink_check_nothrow(duk_hthread * thr,duk_bool_t snug)18467 DUK_INTERNAL void duk_valstack_shrink_check_nothrow(duk_hthread *thr, duk_bool_t snug) {
18468 	duk_size_t alloc_bytes;
18469 	duk_size_t reserve_bytes;
18470 	duk_size_t shrink_bytes;
18471 
18472 	alloc_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_alloc_end - (duk_uint8_t *) thr->valstack);
18473 	reserve_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
18474 	DUK_ASSERT(alloc_bytes >= reserve_bytes);
18475 
18476 	/* We're free to shrink the value stack allocation down to
18477 	 * reserve_bytes but not more.  If 'snug' (emergency GC)
18478 	 * shrink whatever we can.  Otherwise only shrink if the new
18479 	 * size would be considerably smaller.
18480 	 */
18481 
18482 #if defined(DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT)
18483 	if (snug) {
18484 		shrink_bytes = reserve_bytes;
18485 	} else {
18486 		duk_size_t proportion, slack;
18487 
18488 		/* Require that value stack shrinks by at least X% of its
18489 		 * current size.  For example, shift of 2 means at least
18490 		 * 25%.  The proportion is computed as bytes and may not
18491 		 * be a multiple of sizeof(duk_tval); that's OK here.
18492 		 */
18493 		proportion = alloc_bytes >> DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT;
18494 		if (alloc_bytes - reserve_bytes < proportion) {
18495 			/* Too little would be freed, do nothing. */
18496 			return;
18497 		}
18498 
18499 		/* Keep a slack after shrinking.  The slack is again a
18500 		 * proportion of the current size (the proportion should
18501 		 * of course be smaller than the check proportion above).
18502 		 */
18503 #if defined(DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT)
18504 		DUK_ASSERT(DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT > DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT);
18505 		slack = alloc_bytes >> DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT;
18506 #else
18507 		slack = 0;
18508 #endif
18509 		shrink_bytes = reserve_bytes +
18510 		               slack / sizeof(duk_tval) * sizeof(duk_tval);  /* multiple of duk_tval */
18511 	}
18512 #else  /* DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT */
18513 	/* Always snug, useful in some low memory environments. */
18514 	DUK_UNREF(snug);
18515 	shrink_bytes = reserve_bytes;
18516 #endif  /* DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT */
18517 
18518 	DUK_D(DUK_DPRINT("valstack shrink check: alloc_bytes=%ld, reserve_bytes=%ld, shrink_bytes=%ld (unvalidated)",
18519 	                 (long) alloc_bytes, (long) reserve_bytes, (long) shrink_bytes));
18520 	DUK_ASSERT(shrink_bytes >= reserve_bytes);
18521 	if (shrink_bytes >= alloc_bytes) {
18522 		/* Skip if shrink target is same as current one (or higher,
18523 		 * though that shouldn't happen in practice).
18524 		 */
18525 		return;
18526 	}
18527 	DUK_ASSERT(shrink_bytes / sizeof(duk_tval) * sizeof(duk_tval) == shrink_bytes);
18528 
18529 	DUK_D(DUK_DPRINT("valstack shrink check: decided to shrink, snug: %ld", (long) snug));
18530 
18531 	duk__resize_valstack(thr, shrink_bytes / sizeof(duk_tval));
18532 }
18533 
duk_check_stack(duk_hthread * thr,duk_idx_t extra)18534 DUK_EXTERNAL duk_bool_t duk_check_stack(duk_hthread *thr, duk_idx_t extra) {
18535 	duk_size_t min_new_bytes;
18536 
18537 	DUK_ASSERT_API_ENTRY(thr);
18538 	DUK_ASSERT(thr != NULL);
18539 
18540 	if (DUK_UNLIKELY(extra < 0 || extra > DUK_USE_VALSTACK_LIMIT)) {
18541 		if (extra < 0) {
18542 			/* Clamping to zero makes the API more robust to calling code
18543 			 * calculation errors.
18544 			 */
18545 			extra = 0;
18546 		} else {
18547 			/* Cause grow check to fail without wrapping arithmetic. */
18548 			extra = DUK_USE_VALSTACK_LIMIT;
18549 		}
18550 	}
18551 
18552 	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack) +
18553 	                sizeof(duk_tval) * ((duk_size_t) extra + DUK_VALSTACK_INTERNAL_EXTRA);
18554 	return duk_valstack_grow_check_nothrow(thr, min_new_bytes);
18555 }
18556 
duk_require_stack(duk_hthread * thr,duk_idx_t extra)18557 DUK_EXTERNAL void duk_require_stack(duk_hthread *thr, duk_idx_t extra) {
18558 	duk_size_t min_new_bytes;
18559 
18560 	DUK_ASSERT_API_ENTRY(thr);
18561 	DUK_ASSERT(thr != NULL);
18562 
18563 	if (DUK_UNLIKELY(extra < 0 || extra > DUK_USE_VALSTACK_LIMIT)) {
18564 		if (extra < 0) {
18565 			/* Clamping to zero makes the API more robust to calling code
18566 			 * calculation errors.
18567 			 */
18568 			extra = 0;
18569 		} else {
18570 			/* Cause grow check to fail without wrapping arithmetic. */
18571 			extra = DUK_USE_VALSTACK_LIMIT;
18572 		}
18573 	}
18574 
18575 	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack) +
18576 	                sizeof(duk_tval) * ((duk_size_t) extra + DUK_VALSTACK_INTERNAL_EXTRA);
18577 	duk_valstack_grow_check_throw(thr, min_new_bytes);
18578 }
18579 
duk_check_stack_top(duk_hthread * thr,duk_idx_t top)18580 DUK_EXTERNAL duk_bool_t duk_check_stack_top(duk_hthread *thr, duk_idx_t top) {
18581 	duk_size_t min_new_bytes;
18582 
18583 	DUK_ASSERT_API_ENTRY(thr);
18584 
18585 	if (DUK_UNLIKELY(top < 0 || top > DUK_USE_VALSTACK_LIMIT)) {
18586 		if (top < 0) {
18587 			/* Clamping to zero makes the API more robust to calling code
18588 			 * calculation errors.
18589 			 */
18590 			top = 0;
18591 		} else {
18592 			/* Cause grow check to fail without wrapping arithmetic. */
18593 			top = DUK_USE_VALSTACK_LIMIT;
18594 		}
18595 	}
18596 
18597 	DUK_ASSERT(top >= 0);
18598 	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) +
18599 	                sizeof(duk_tval) * ((duk_size_t) top + DUK_VALSTACK_INTERNAL_EXTRA);
18600 	return duk_valstack_grow_check_nothrow(thr, min_new_bytes);
18601 }
18602 
duk_require_stack_top(duk_hthread * thr,duk_idx_t top)18603 DUK_EXTERNAL void duk_require_stack_top(duk_hthread *thr, duk_idx_t top) {
18604 	duk_size_t min_new_bytes;
18605 
18606 	DUK_ASSERT_API_ENTRY(thr);
18607 
18608 	if (DUK_UNLIKELY(top < 0 || top > DUK_USE_VALSTACK_LIMIT)) {
18609 		if (top < 0) {
18610 			/* Clamping to zero makes the API more robust to calling code
18611 			 * calculation errors.
18612 			 */
18613 			top = 0;
18614 		} else {
18615 			/* Cause grow check to fail without wrapping arithmetic. */
18616 			top = DUK_USE_VALSTACK_LIMIT;
18617 		}
18618 	}
18619 
18620 	DUK_ASSERT(top >= 0);
18621 	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) +
18622 	                sizeof(duk_tval) * ((duk_size_t) top + DUK_VALSTACK_INTERNAL_EXTRA);
18623 	duk_valstack_grow_check_throw(thr, min_new_bytes);
18624 }
18625 
18626 /*
18627  *  Basic stack manipulation: swap, dup, insert, replace, etc
18628  */
18629 
duk_swap(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)18630 DUK_EXTERNAL void duk_swap(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
18631 	duk_tval *tv1;
18632 	duk_tval *tv2;
18633 	duk_tval tv_tmp;
18634 
18635 	DUK_ASSERT_API_ENTRY(thr);
18636 
18637 	tv1 = duk_require_tval(thr, idx1);
18638 	DUK_ASSERT(tv1 != NULL);
18639 	tv2 = duk_require_tval(thr, idx2);
18640 	DUK_ASSERT(tv2 != NULL);
18641 
18642 	/* If tv1==tv2 this is a NOP, no check is needed */
18643 	DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
18644 	DUK_TVAL_SET_TVAL(tv1, tv2);
18645 	DUK_TVAL_SET_TVAL(tv2, &tv_tmp);
18646 }
18647 
duk_swap_top(duk_hthread * thr,duk_idx_t idx)18648 DUK_EXTERNAL void duk_swap_top(duk_hthread *thr, duk_idx_t idx) {
18649 	DUK_ASSERT_API_ENTRY(thr);
18650 
18651 	duk_swap(thr, idx, -1);
18652 }
18653 
duk_dup(duk_hthread * thr,duk_idx_t from_idx)18654 DUK_EXTERNAL void duk_dup(duk_hthread *thr, duk_idx_t from_idx) {
18655 	duk_tval *tv_from;
18656 	duk_tval *tv_to;
18657 
18658 	DUK_ASSERT_API_ENTRY(thr);
18659 	DUK__CHECK_SPACE();
18660 
18661 	tv_from = duk_require_tval(thr, from_idx);
18662 	tv_to = thr->valstack_top++;
18663 	DUK_ASSERT(tv_from != NULL);
18664 	DUK_ASSERT(tv_to != NULL);
18665 	DUK_TVAL_SET_TVAL(tv_to, tv_from);
18666 	DUK_TVAL_INCREF(thr, tv_to);  /* no side effects */
18667 }
18668 
duk_dup_top(duk_hthread * thr)18669 DUK_EXTERNAL void duk_dup_top(duk_hthread *thr) {
18670 #if defined(DUK_USE_PREFER_SIZE)
18671 	duk_dup(thr, -1);
18672 #else
18673 	duk_tval *tv_from;
18674 	duk_tval *tv_to;
18675 
18676 	DUK_ASSERT_API_ENTRY(thr);
18677 	DUK__CHECK_SPACE();
18678 
18679 	if (DUK_UNLIKELY(thr->valstack_top - thr->valstack_bottom <= 0)) {
18680 		DUK_ERROR_RANGE_INDEX(thr, -1);
18681 		DUK_WO_NORETURN(return;);
18682 	}
18683 	tv_from = thr->valstack_top - 1;
18684 	tv_to = thr->valstack_top++;
18685 	DUK_ASSERT(tv_from != NULL);
18686 	DUK_ASSERT(tv_to != NULL);
18687 	DUK_TVAL_SET_TVAL(tv_to, tv_from);
18688 	DUK_TVAL_INCREF(thr, tv_to);  /* no side effects */
18689 #endif
18690 }
18691 
duk_dup_0(duk_hthread * thr)18692 DUK_INTERNAL void duk_dup_0(duk_hthread *thr) {
18693 	DUK_ASSERT_API_ENTRY(thr);
18694 	duk_dup(thr, 0);
18695 }
duk_dup_1(duk_hthread * thr)18696 DUK_INTERNAL void duk_dup_1(duk_hthread *thr) {
18697 	DUK_ASSERT_API_ENTRY(thr);
18698 	duk_dup(thr, 1);
18699 }
duk_dup_2(duk_hthread * thr)18700 DUK_INTERNAL void duk_dup_2(duk_hthread *thr) {
18701 	DUK_ASSERT_API_ENTRY(thr);
18702 	duk_dup(thr, 2);
18703 }
duk_dup_m2(duk_hthread * thr)18704 DUK_INTERNAL void duk_dup_m2(duk_hthread *thr) {
18705 	DUK_ASSERT_API_ENTRY(thr);
18706 	duk_dup(thr, -2);
18707 }
duk_dup_m3(duk_hthread * thr)18708 DUK_INTERNAL void duk_dup_m3(duk_hthread *thr) {
18709 	DUK_ASSERT_API_ENTRY(thr);
18710 	duk_dup(thr, -3);
18711 }
duk_dup_m4(duk_hthread * thr)18712 DUK_INTERNAL void duk_dup_m4(duk_hthread *thr) {
18713 	DUK_ASSERT_API_ENTRY(thr);
18714 	duk_dup(thr, -4);
18715 }
18716 
duk_insert(duk_hthread * thr,duk_idx_t to_idx)18717 DUK_EXTERNAL void duk_insert(duk_hthread *thr, duk_idx_t to_idx) {
18718 	duk_tval *p;
18719 	duk_tval *q;
18720 	duk_tval tv_tmp;
18721 	duk_size_t nbytes;
18722 
18723 	DUK_ASSERT_API_ENTRY(thr);
18724 
18725 	p = duk_require_tval(thr, to_idx);
18726 	DUK_ASSERT(p != NULL);
18727 	q = duk_require_tval(thr, -1);
18728 	DUK_ASSERT(q != NULL);
18729 
18730 	DUK_ASSERT(q >= p);
18731 
18732 	/*              nbytes
18733 	 *           <--------->
18734 	 *    [ ... | p | x | x | q ]
18735 	 * => [ ... | q | p | x | x ]
18736 	 */
18737 
18738 	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));  /* Note: 'q' is top-1 */
18739 
18740 	DUK_DDD(DUK_DDDPRINT("duk_insert: to_idx=%ld, p=%p, q=%p, nbytes=%lu",
18741 	                     (long) to_idx, (void *) p, (void *) q, (unsigned long) nbytes));
18742 
18743 	/* No net refcount changes.  No need to special case nbytes == 0
18744 	 * (p == q).
18745 	 */
18746 	DUK_TVAL_SET_TVAL(&tv_tmp, q);
18747 	duk_memmove((void *) (p + 1), (const void *) p, (size_t) nbytes);
18748 	DUK_TVAL_SET_TVAL(p, &tv_tmp);
18749 }
18750 
duk_insert_undefined(duk_hthread * thr,duk_idx_t idx)18751 DUK_INTERNAL void duk_insert_undefined(duk_hthread *thr, duk_idx_t idx) {
18752 	DUK_ASSERT_API_ENTRY(thr);
18753 	DUK_ASSERT(idx >= 0);  /* Doesn't support negative indices. */
18754 
18755 	duk_push_undefined(thr);
18756 	duk_insert(thr, idx);
18757 }
18758 
duk_insert_undefined_n(duk_hthread * thr,duk_idx_t idx,duk_idx_t count)18759 DUK_INTERNAL void duk_insert_undefined_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {
18760 	duk_tval *tv, *tv_end;
18761 
18762 	DUK_ASSERT_API_ENTRY(thr);
18763 	DUK_ASSERT(idx >= 0);  /* Doesn't support negative indices or count. */
18764 	DUK_ASSERT(count >= 0);
18765 
18766 	tv = duk_reserve_gap(thr, idx, count);
18767 	tv_end = tv + count;
18768 	while (tv != tv_end) {
18769 		DUK_TVAL_SET_UNDEFINED(tv);
18770 		tv++;
18771 	}
18772 }
18773 
duk_replace(duk_hthread * thr,duk_idx_t to_idx)18774 DUK_EXTERNAL void duk_replace(duk_hthread *thr, duk_idx_t to_idx) {
18775 	duk_tval *tv1;
18776 	duk_tval *tv2;
18777 	duk_tval tv_tmp;
18778 
18779 	DUK_ASSERT_API_ENTRY(thr);
18780 
18781 	tv1 = duk_require_tval(thr, -1);
18782 	DUK_ASSERT(tv1 != NULL);
18783 	tv2 = duk_require_tval(thr, to_idx);
18784 	DUK_ASSERT(tv2 != NULL);
18785 
18786 	/* For tv1 == tv2, both pointing to stack top, the end result
18787 	 * is same as duk_pop(thr).
18788 	 */
18789 	DUK_TVAL_SET_TVAL(&tv_tmp, tv2);
18790 	DUK_TVAL_SET_TVAL(tv2, tv1);
18791 	DUK_TVAL_SET_UNDEFINED(tv1);
18792 	thr->valstack_top--;
18793 	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
18794 }
18795 
duk_copy(duk_hthread * thr,duk_idx_t from_idx,duk_idx_t to_idx)18796 DUK_EXTERNAL void duk_copy(duk_hthread *thr, duk_idx_t from_idx, duk_idx_t to_idx) {
18797 	duk_tval *tv1;
18798 	duk_tval *tv2;
18799 
18800 	DUK_ASSERT_API_ENTRY(thr);
18801 
18802 	tv1 = duk_require_tval(thr, from_idx);
18803 	DUK_ASSERT(tv1 != NULL);
18804 	tv2 = duk_require_tval(thr, to_idx);
18805 	DUK_ASSERT(tv2 != NULL);
18806 
18807 	/* For tv1 == tv2, this is a no-op (no explicit check needed). */
18808 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv2, tv1);  /* side effects */
18809 }
18810 
duk_remove(duk_hthread * thr,duk_idx_t idx)18811 DUK_EXTERNAL void duk_remove(duk_hthread *thr, duk_idx_t idx) {
18812 	duk_tval *p;
18813 	duk_tval *q;
18814 #if defined(DUK_USE_REFERENCE_COUNTING)
18815 	duk_tval tv_tmp;
18816 #endif
18817 	duk_size_t nbytes;
18818 
18819 	DUK_ASSERT_API_ENTRY(thr);
18820 
18821 	p = duk_require_tval(thr, idx);
18822 	DUK_ASSERT(p != NULL);
18823 	q = duk_require_tval(thr, -1);
18824 	DUK_ASSERT(q != NULL);
18825 
18826 	DUK_ASSERT(q >= p);
18827 
18828 	/*              nbytes            zero size case
18829 	 *           <--------->
18830 	 *    [ ... | p | x | x | q ]     [ ... | p==q ]
18831 	 * => [ ... | x | x | q ]         [ ... ]
18832 	 */
18833 
18834 #if defined(DUK_USE_REFERENCE_COUNTING)
18835 	/* use a temp: decref only when valstack reachable values are correct */
18836 	DUK_TVAL_SET_TVAL(&tv_tmp, p);
18837 #endif
18838 
18839 	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));  /* Note: 'q' is top-1 */
18840 	duk_memmove((void *) p, (const void *) (p + 1), (size_t) nbytes);
18841 
18842 	DUK_TVAL_SET_UNDEFINED(q);
18843 	thr->valstack_top--;
18844 
18845 #if defined(DUK_USE_REFERENCE_COUNTING)
18846 	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
18847 #endif
18848 }
18849 
duk_remove_unsafe(duk_hthread * thr,duk_idx_t idx)18850 DUK_INTERNAL void duk_remove_unsafe(duk_hthread *thr, duk_idx_t idx) {
18851 	DUK_ASSERT_API_ENTRY(thr);
18852 
18853 	duk_remove(thr, idx);  /* XXX: no optimization for now */
18854 }
18855 
duk_remove_m2(duk_hthread * thr)18856 DUK_INTERNAL void duk_remove_m2(duk_hthread *thr) {
18857 	DUK_ASSERT_API_ENTRY(thr);
18858 
18859 	duk_remove(thr, -2);
18860 }
18861 
duk_remove_n(duk_hthread * thr,duk_idx_t idx,duk_idx_t count)18862 DUK_INTERNAL void duk_remove_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {
18863 #if defined(DUK_USE_PREFER_SIZE)
18864 	/* XXX: maybe too slow even when preferring size? */
18865 	DUK_ASSERT_API_ENTRY(thr);
18866 	DUK_ASSERT(count >= 0);
18867 	DUK_ASSERT(idx >= 0);
18868 
18869 	while (count-- > 0) {
18870 		duk_remove(thr, idx);
18871 	}
18872 #else  /* DUK_USE_PREFER_SIZE */
18873 	duk_tval *tv_src;
18874 	duk_tval *tv_dst;
18875 	duk_tval *tv_newtop;
18876 	duk_tval *tv;
18877 	duk_size_t bytes;
18878 
18879 	DUK_ASSERT_API_ENTRY(thr);
18880 	DUK_ASSERT(count >= 0);
18881 	DUK_ASSERT(idx >= 0);
18882 
18883 	tv_dst = thr->valstack_bottom + idx;
18884 	DUK_ASSERT(tv_dst <= thr->valstack_top);
18885 	tv_src = tv_dst + count;
18886 	DUK_ASSERT(tv_src <= thr->valstack_top);
18887 	bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) tv_src);
18888 
18889 	for (tv = tv_dst; tv < tv_src; tv++) {
18890 		DUK_TVAL_DECREF_NORZ(thr, tv);
18891 	}
18892 
18893 	duk_memmove((void *) tv_dst, (const void *) tv_src, bytes);
18894 
18895 	tv_newtop = thr->valstack_top - count;
18896 	for (tv = tv_newtop; tv < thr->valstack_top; tv++) {
18897 		DUK_TVAL_SET_UNDEFINED(tv);
18898 	}
18899 	thr->valstack_top = tv_newtop;
18900 
18901 	/* When not preferring size, only NORZ macros are used; caller
18902 	 * is expected to DUK_REFZERO_CHECK().
18903 	 */
18904 #endif  /* DUK_USE_PREFER_SIZE */
18905 }
18906 
duk_remove_n_unsafe(duk_hthread * thr,duk_idx_t idx,duk_idx_t count)18907 DUK_INTERNAL void duk_remove_n_unsafe(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {
18908 	DUK_ASSERT_API_ENTRY(thr);
18909 
18910 	duk_remove_n(thr, idx, count);  /* XXX: no optimization for now */
18911 }
18912 
18913 /*
18914  *  Stack slice primitives
18915  */
18916 
duk_xcopymove_raw(duk_hthread * to_thr,duk_hthread * from_thr,duk_idx_t count,duk_bool_t is_copy)18917 DUK_EXTERNAL void duk_xcopymove_raw(duk_hthread *to_thr, duk_hthread *from_thr, duk_idx_t count, duk_bool_t is_copy) {
18918 	void *src;
18919 	duk_size_t nbytes;
18920 	duk_tval *p;
18921 	duk_tval *q;
18922 
18923 	/* XXX: several pointer comparison issues here */
18924 
18925 	DUK_ASSERT_API_ENTRY(to_thr);
18926 	DUK_ASSERT_CTX_VALID(to_thr);
18927 	DUK_ASSERT_CTX_VALID(from_thr);
18928 	DUK_ASSERT(to_thr->heap == from_thr->heap);
18929 
18930 	if (DUK_UNLIKELY(to_thr == from_thr)) {
18931 		DUK_ERROR_TYPE(to_thr, DUK_STR_INVALID_CONTEXT);
18932 		DUK_WO_NORETURN(return;);
18933 	}
18934 	if (DUK_UNLIKELY((duk_uidx_t) count > (duk_uidx_t) DUK_USE_VALSTACK_LIMIT)) {
18935 		/* Maximum value check ensures 'nbytes' won't wrap below.
18936 		 * Also handles negative count.
18937 		 */
18938 		DUK_ERROR_RANGE_INVALID_COUNT(to_thr);
18939 		DUK_WO_NORETURN(return;);
18940 	}
18941 	DUK_ASSERT(count >= 0);
18942 
18943 	nbytes = sizeof(duk_tval) * (duk_size_t) count;
18944 	if (DUK_UNLIKELY(nbytes == 0)) {
18945 		return;
18946 	}
18947 	DUK_ASSERT(to_thr->valstack_top <= to_thr->valstack_end);
18948 	if (DUK_UNLIKELY((duk_size_t) ((duk_uint8_t *) to_thr->valstack_end - (duk_uint8_t *) to_thr->valstack_top) < nbytes)) {
18949 		DUK_ERROR_RANGE_PUSH_BEYOND(to_thr);
18950 		DUK_WO_NORETURN(return;);
18951 	}
18952 	src = (void *) ((duk_uint8_t *) from_thr->valstack_top - nbytes);
18953 	if (DUK_UNLIKELY(src < (void *) from_thr->valstack_bottom)) {
18954 		DUK_ERROR_RANGE_INVALID_COUNT(to_thr);
18955 		DUK_WO_NORETURN(return;);
18956 	}
18957 
18958 	/* Copy values (no overlap even if to_thr == from_thr; that's not
18959 	 * allowed now anyway).
18960 	 */
18961 	DUK_ASSERT(nbytes > 0);
18962 	duk_memcpy((void *) to_thr->valstack_top, (const void *) src, (size_t) nbytes);
18963 
18964 	p = to_thr->valstack_top;
18965 	to_thr->valstack_top = (duk_tval *) (void *) (((duk_uint8_t *) p) + nbytes);
18966 
18967 	if (is_copy) {
18968 		/* Incref copies, keep originals. */
18969 		q = to_thr->valstack_top;
18970 		while (p < q) {
18971 			DUK_TVAL_INCREF(to_thr, p);  /* no side effects */
18972 			p++;
18973 		}
18974 	} else {
18975 		/* No net refcount change. */
18976 		p = from_thr->valstack_top;
18977 		q = (duk_tval *) (void *) (((duk_uint8_t *) p) - nbytes);
18978 		from_thr->valstack_top = q;
18979 
18980 		while (p > q) {
18981 			p--;
18982 			DUK_TVAL_SET_UNDEFINED(p);
18983 			/* XXX: fast primitive to set a bunch of values to UNDEFINED */
18984 		}
18985 	}
18986 }
18987 
18988 /* Internal helper: reserve a gap of 'count' elements at 'idx_base' and return a
18989  * pointer to the gap.  Values in the gap are garbage and MUST be initialized by
18990  * the caller before any side effects may occur.  The caller must ensure there's
18991  * enough stack reserve for 'count' values.
18992  */
duk_reserve_gap(duk_hthread * thr,duk_idx_t idx_base,duk_idx_t count)18993 DUK_INTERNAL duk_tval *duk_reserve_gap(duk_hthread *thr, duk_idx_t idx_base, duk_idx_t count) {
18994 	duk_tval *tv_src;
18995 	duk_tval *tv_dst;
18996 	duk_size_t gap_bytes;
18997 	duk_size_t copy_bytes;
18998 
18999 	/* Caller is responsible for ensuring there's enough preallocated
19000 	 * value stack.
19001 	 */
19002 	DUK_ASSERT_API_ENTRY(thr);
19003 	DUK_ASSERT(count >= 0);
19004 	DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack_top) >= (duk_size_t) count);
19005 
19006 	tv_src = thr->valstack_bottom + idx_base;
19007 	gap_bytes = (duk_size_t) count * sizeof(duk_tval);
19008 	tv_dst = (duk_tval *) (void *) ((duk_uint8_t *) tv_src + gap_bytes);
19009 	copy_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) tv_src);
19010 	thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_top + gap_bytes);
19011 	duk_memmove((void *) tv_dst, (const void *) tv_src, copy_bytes);
19012 
19013 	/* Values in the gap are left as garbage: caller must fill them in
19014 	 * and INCREF them before any side effects.
19015 	 */
19016 	return tv_src;
19017 }
19018 
19019 /*
19020  *  Get/opt/require
19021  */
19022 
duk_require_undefined(duk_hthread * thr,duk_idx_t idx)19023 DUK_EXTERNAL void duk_require_undefined(duk_hthread *thr, duk_idx_t idx) {
19024 	duk_tval *tv;
19025 
19026 	DUK_ASSERT_API_ENTRY(thr);
19027 
19028 	tv = duk_get_tval_or_unused(thr, idx);
19029 	DUK_ASSERT(tv != NULL);
19030 	if (DUK_UNLIKELY(!DUK_TVAL_IS_UNDEFINED(tv))) {
19031 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "undefined", DUK_STR_NOT_UNDEFINED);
19032 		DUK_WO_NORETURN(return;);
19033 	}
19034 }
19035 
duk_require_null(duk_hthread * thr,duk_idx_t idx)19036 DUK_EXTERNAL void duk_require_null(duk_hthread *thr, duk_idx_t idx) {
19037 	duk_tval *tv;
19038 
19039 	DUK_ASSERT_API_ENTRY(thr);
19040 
19041 	tv = duk_get_tval_or_unused(thr, idx);
19042 	DUK_ASSERT(tv != NULL);
19043 	if (DUK_UNLIKELY(!DUK_TVAL_IS_NULL(tv))) {
19044 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "null", DUK_STR_NOT_NULL);
19045 		DUK_WO_NORETURN(return;);
19046 	}
19047 }
19048 
duk__get_boolean_raw(duk_hthread * thr,duk_idx_t idx,duk_bool_t def_value)19049 DUK_LOCAL DUK_ALWAYS_INLINE duk_bool_t duk__get_boolean_raw(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {
19050 	duk_bool_t ret;
19051 	duk_tval *tv;
19052 
19053 	DUK_ASSERT_CTX_VALID(thr);
19054 
19055 	tv = duk_get_tval_or_unused(thr, idx);
19056 	DUK_ASSERT(tv != NULL);
19057 	if (DUK_TVAL_IS_BOOLEAN(tv)) {
19058 		ret = DUK_TVAL_GET_BOOLEAN(tv);
19059 		DUK_ASSERT(ret == 0 || ret == 1);
19060 	} else {
19061 		ret = def_value;
19062 		/* Not guaranteed to be 0 or 1. */
19063 	}
19064 
19065 	return ret;
19066 }
19067 
duk_get_boolean(duk_hthread * thr,duk_idx_t idx)19068 DUK_EXTERNAL duk_bool_t duk_get_boolean(duk_hthread *thr, duk_idx_t idx) {
19069 	DUK_ASSERT_API_ENTRY(thr);
19070 
19071 	return duk__get_boolean_raw(thr, idx, 0);  /* default: false */
19072 }
19073 
duk_get_boolean_default(duk_hthread * thr,duk_idx_t idx,duk_bool_t def_value)19074 DUK_EXTERNAL duk_bool_t duk_get_boolean_default(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {
19075 	DUK_ASSERT_API_ENTRY(thr);
19076 
19077 	return duk__get_boolean_raw(thr, idx, def_value);
19078 }
19079 
duk_require_boolean(duk_hthread * thr,duk_idx_t idx)19080 DUK_EXTERNAL duk_bool_t duk_require_boolean(duk_hthread *thr, duk_idx_t idx) {
19081 	duk_tval *tv;
19082 	duk_bool_t ret;
19083 
19084 	DUK_ASSERT_API_ENTRY(thr);
19085 
19086 	tv = duk_get_tval_or_unused(thr, idx);
19087 	DUK_ASSERT(tv != NULL);
19088 	if (DUK_LIKELY(DUK_TVAL_IS_BOOLEAN(tv))) {
19089 		ret = DUK_TVAL_GET_BOOLEAN(tv);
19090 		DUK_ASSERT(ret == 0 || ret == 1);
19091 		return ret;
19092 	} else {
19093 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "boolean", DUK_STR_NOT_BOOLEAN);
19094 		DUK_WO_NORETURN(return 0;);
19095 	}
19096 }
19097 
duk_opt_boolean(duk_hthread * thr,duk_idx_t idx,duk_bool_t def_value)19098 DUK_EXTERNAL duk_bool_t duk_opt_boolean(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {
19099 	DUK_ASSERT_API_ENTRY(thr);
19100 
19101 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19102 		return def_value;
19103 	}
19104 	return duk_require_boolean(thr, idx);
19105 }
19106 
duk__get_number_raw(duk_hthread * thr,duk_idx_t idx,duk_double_t def_value)19107 DUK_LOCAL DUK_ALWAYS_INLINE duk_double_t duk__get_number_raw(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {
19108 	duk_double_union ret;
19109 	duk_tval *tv;
19110 
19111 	DUK_ASSERT_CTX_VALID(thr);
19112 
19113 	tv = duk_get_tval_or_unused(thr, idx);
19114 	DUK_ASSERT(tv != NULL);
19115 #if defined(DUK_USE_FASTINT)
19116 	if (DUK_TVAL_IS_FASTINT(tv)) {
19117 		ret.d = (duk_double_t) DUK_TVAL_GET_FASTINT(tv);  /* XXX: cast trick */
19118 	}
19119 	else
19120 #endif
19121 	if (DUK_TVAL_IS_DOUBLE(tv)) {
19122 		/* When using packed duk_tval, number must be in NaN-normalized form
19123 		 * for it to be a duk_tval, so no need to normalize.  NOP for unpacked
19124 		 * duk_tval.
19125 		 */
19126 		ret.d = DUK_TVAL_GET_DOUBLE(tv);
19127 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&ret));
19128 	} else {
19129 		ret.d = def_value;
19130 		/* Default value (including NaN) may not be normalized. */
19131 	}
19132 
19133 	return ret.d;
19134 }
19135 
duk_get_number(duk_hthread * thr,duk_idx_t idx)19136 DUK_EXTERNAL duk_double_t duk_get_number(duk_hthread *thr, duk_idx_t idx) {
19137 	DUK_ASSERT_API_ENTRY(thr);
19138 	return duk__get_number_raw(thr, idx, DUK_DOUBLE_NAN);  /* default: NaN */
19139 }
19140 
duk_get_number_default(duk_hthread * thr,duk_idx_t idx,duk_double_t def_value)19141 DUK_EXTERNAL duk_double_t duk_get_number_default(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {
19142 	DUK_ASSERT_API_ENTRY(thr);
19143 	return duk__get_number_raw(thr, idx, def_value);
19144 }
19145 
duk_require_number(duk_hthread * thr,duk_idx_t idx)19146 DUK_EXTERNAL duk_double_t duk_require_number(duk_hthread *thr, duk_idx_t idx) {
19147 	duk_tval *tv;
19148 	duk_double_union ret;
19149 
19150 	DUK_ASSERT_API_ENTRY(thr);
19151 
19152 	tv = duk_get_tval_or_unused(thr, idx);
19153 	DUK_ASSERT(tv != NULL);
19154 	if (DUK_UNLIKELY(!DUK_TVAL_IS_NUMBER(tv))) {
19155 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
19156 		DUK_WO_NORETURN(return 0.0;);
19157 	}
19158 
19159 	ret.d = DUK_TVAL_GET_NUMBER(tv);
19160 
19161 	/* When using packed duk_tval, number must be in NaN-normalized form
19162 	 * for it to be a duk_tval, so no need to normalize.  NOP for unpacked
19163 	 * duk_tval.
19164 	 */
19165 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&ret));
19166 	return ret.d;
19167 }
19168 
duk_opt_number(duk_hthread * thr,duk_idx_t idx,duk_double_t def_value)19169 DUK_EXTERNAL duk_double_t duk_opt_number(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {
19170 	DUK_ASSERT_API_ENTRY(thr);
19171 
19172 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19173 		/* User provided default is not NaN normalized. */
19174 		return def_value;
19175 	}
19176 	return duk_require_number(thr, idx);
19177 }
19178 
duk_get_int(duk_hthread * thr,duk_idx_t idx)19179 DUK_EXTERNAL duk_int_t duk_get_int(duk_hthread *thr, duk_idx_t idx) {
19180 	DUK_ASSERT_API_ENTRY(thr);
19181 
19182 	return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 0 /*require*/);
19183 }
19184 
duk_get_uint(duk_hthread * thr,duk_idx_t idx)19185 DUK_EXTERNAL duk_uint_t duk_get_uint(duk_hthread *thr, duk_idx_t idx) {
19186 	DUK_ASSERT_API_ENTRY(thr);
19187 
19188 	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 0 /*require*/);
19189 }
19190 
duk_get_int_default(duk_hthread * thr,duk_idx_t idx,duk_int_t def_value)19191 DUK_EXTERNAL duk_int_t duk_get_int_default(duk_hthread *thr, duk_idx_t idx, duk_int_t def_value) {
19192 	DUK_ASSERT_API_ENTRY(thr);
19193 
19194 	return (duk_int_t) duk__api_coerce_d2i(thr, idx, def_value, 0 /*require*/);
19195 }
19196 
duk_get_uint_default(duk_hthread * thr,duk_idx_t idx,duk_uint_t def_value)19197 DUK_EXTERNAL duk_uint_t duk_get_uint_default(duk_hthread *thr, duk_idx_t idx, duk_uint_t def_value) {
19198 	DUK_ASSERT_API_ENTRY(thr);
19199 
19200 	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, def_value, 0 /*require*/);
19201 }
19202 
duk_require_int(duk_hthread * thr,duk_idx_t idx)19203 DUK_EXTERNAL duk_int_t duk_require_int(duk_hthread *thr, duk_idx_t idx) {
19204 	DUK_ASSERT_API_ENTRY(thr);
19205 
19206 	return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 1 /*require*/);
19207 }
19208 
duk_require_uint(duk_hthread * thr,duk_idx_t idx)19209 DUK_EXTERNAL duk_uint_t duk_require_uint(duk_hthread *thr, duk_idx_t idx) {
19210 	DUK_ASSERT_API_ENTRY(thr);
19211 
19212 	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 1 /*require*/);
19213 }
19214 
duk_opt_int(duk_hthread * thr,duk_idx_t idx,duk_int_t def_value)19215 DUK_EXTERNAL duk_int_t duk_opt_int(duk_hthread *thr, duk_idx_t idx, duk_int_t def_value) {
19216 	DUK_ASSERT_API_ENTRY(thr);
19217 
19218 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19219 		return def_value;
19220 	}
19221 	return duk_require_int(thr, idx);
19222 }
19223 
duk_opt_uint(duk_hthread * thr,duk_idx_t idx,duk_uint_t def_value)19224 DUK_EXTERNAL duk_uint_t duk_opt_uint(duk_hthread *thr, duk_idx_t idx, duk_uint_t def_value) {
19225 	DUK_ASSERT_API_ENTRY(thr);
19226 
19227 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19228 		return def_value;
19229 	}
19230 	return duk_require_uint(thr, idx);
19231 }
19232 
duk_get_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)19233 DUK_EXTERNAL const char *duk_get_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
19234 	duk_hstring *h;
19235 	const char *ret;
19236 	duk_size_t len;
19237 
19238 	DUK_ASSERT_API_ENTRY(thr);
19239 
19240 	h = duk_get_hstring(thr, idx);
19241 	if (h != NULL) {
19242 		len = DUK_HSTRING_GET_BYTELEN(h);
19243 		ret = (const char *) DUK_HSTRING_GET_DATA(h);
19244 	} else {
19245 		len = 0;
19246 		ret = NULL;
19247 	}
19248 
19249 	if (out_len != NULL) {
19250 		*out_len = len;
19251 	}
19252 	return ret;
19253 }
19254 
duk_require_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)19255 DUK_EXTERNAL const char *duk_require_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
19256 	duk_hstring *h;
19257 
19258 	DUK_ASSERT_API_ENTRY(thr);
19259 
19260 	h = duk_require_hstring(thr, idx);
19261 	DUK_ASSERT(h != NULL);
19262 	if (out_len) {
19263 		*out_len = DUK_HSTRING_GET_BYTELEN(h);
19264 	}
19265 	return (const char *) DUK_HSTRING_GET_DATA(h);
19266 }
19267 
duk_require_lstring_notsymbol(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)19268 DUK_INTERNAL const char *duk_require_lstring_notsymbol(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
19269 	duk_hstring *h;
19270 
19271 	DUK_ASSERT_API_ENTRY(thr);
19272 
19273 	h = duk_require_hstring_notsymbol(thr, idx);
19274 	DUK_ASSERT(h != NULL);
19275 	if (out_len) {
19276 		*out_len = DUK_HSTRING_GET_BYTELEN(h);
19277 	}
19278 	return (const char *) DUK_HSTRING_GET_DATA(h);
19279 }
19280 
duk_get_string(duk_hthread * thr,duk_idx_t idx)19281 DUK_EXTERNAL const char *duk_get_string(duk_hthread *thr, duk_idx_t idx) {
19282 	duk_hstring *h;
19283 
19284 	DUK_ASSERT_API_ENTRY(thr);
19285 
19286 	h = duk_get_hstring(thr, idx);
19287 	if (h != NULL) {
19288 		return (const char *) DUK_HSTRING_GET_DATA(h);
19289 	} else {
19290 		return NULL;
19291 	}
19292 }
19293 
duk_opt_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len,const char * def_ptr,duk_size_t def_len)19294 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) {
19295 	DUK_ASSERT_API_ENTRY(thr);
19296 
19297 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19298 		if (out_len != NULL) {
19299 			*out_len = def_len;
19300 		}
19301 		return def_ptr;
19302 	}
19303 	return duk_require_lstring(thr, idx, out_len);
19304 }
19305 
duk_opt_string(duk_hthread * thr,duk_idx_t idx,const char * def_ptr)19306 DUK_EXTERNAL const char *duk_opt_string(duk_hthread *thr, duk_idx_t idx, const char *def_ptr) {
19307 	DUK_ASSERT_API_ENTRY(thr);
19308 
19309 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19310 		return def_ptr;
19311 	}
19312 	return duk_require_string(thr, idx);
19313 }
19314 
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)19315 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) {
19316 	duk_hstring *h;
19317 	const char *ret;
19318 	duk_size_t len;
19319 
19320 	DUK_ASSERT_API_ENTRY(thr);
19321 
19322 	h = duk_get_hstring(thr, idx);
19323 	if (h != NULL) {
19324 		len = DUK_HSTRING_GET_BYTELEN(h);
19325 		ret = (const char *) DUK_HSTRING_GET_DATA(h);
19326 	} else {
19327 		len = def_len;
19328 		ret = def_ptr;
19329 	}
19330 
19331 	if (out_len != NULL) {
19332 		*out_len = len;
19333 	}
19334 	return ret;
19335 }
19336 
duk_get_string_default(duk_hthread * thr,duk_idx_t idx,const char * def_value)19337 DUK_EXTERNAL const char *duk_get_string_default(duk_hthread *thr, duk_idx_t idx, const char *def_value) {
19338 	duk_hstring *h;
19339 
19340 	DUK_ASSERT_API_ENTRY(thr);
19341 
19342 	h = duk_get_hstring(thr, idx);
19343 	if (h != NULL) {
19344 		return (const char *) DUK_HSTRING_GET_DATA(h);
19345 	} else {
19346 		return def_value;
19347 	}
19348 }
19349 
duk_get_string_notsymbol(duk_hthread * thr,duk_idx_t idx)19350 DUK_INTERNAL const char *duk_get_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {
19351 	duk_hstring *h;
19352 
19353 	DUK_ASSERT_API_ENTRY(thr);
19354 
19355 	h = duk_get_hstring_notsymbol(thr, idx);
19356 	if (h) {
19357 		return (const char *) DUK_HSTRING_GET_DATA(h);
19358 	} else {
19359 		return NULL;
19360 	}
19361 }
19362 
duk_require_string(duk_hthread * thr,duk_idx_t idx)19363 DUK_EXTERNAL const char *duk_require_string(duk_hthread *thr, duk_idx_t idx) {
19364 	DUK_ASSERT_API_ENTRY(thr);
19365 
19366 	return duk_require_lstring(thr, idx, NULL);
19367 }
19368 
duk_require_string_notsymbol(duk_hthread * thr,duk_idx_t idx)19369 DUK_INTERNAL const char *duk_require_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {
19370 	duk_hstring *h;
19371 
19372 	DUK_ASSERT_API_ENTRY(thr);
19373 
19374 	h = duk_require_hstring_notsymbol(thr, idx);
19375 	DUK_ASSERT(h != NULL);
19376 	return (const char *) DUK_HSTRING_GET_DATA(h);
19377 }
19378 
duk_require_object(duk_hthread * thr,duk_idx_t idx)19379 DUK_EXTERNAL void duk_require_object(duk_hthread *thr, duk_idx_t idx) {
19380 	duk_tval *tv;
19381 
19382 	DUK_ASSERT_API_ENTRY(thr);
19383 
19384 	tv = duk_get_tval_or_unused(thr, idx);
19385 	DUK_ASSERT(tv != NULL);
19386 	if (DUK_UNLIKELY(!DUK_TVAL_IS_OBJECT(tv))) {
19387 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
19388 		DUK_WO_NORETURN(return;);
19389 	}
19390 }
19391 
duk__get_pointer_raw(duk_hthread * thr,duk_idx_t idx,void * def_value)19392 DUK_LOCAL void *duk__get_pointer_raw(duk_hthread *thr, duk_idx_t idx, void *def_value) {
19393 	duk_tval *tv;
19394 	void *p;
19395 
19396 	DUK_ASSERT_CTX_VALID(thr);
19397 
19398 	tv = duk_get_tval_or_unused(thr, idx);
19399 	DUK_ASSERT(tv != NULL);
19400 	if (!DUK_TVAL_IS_POINTER(tv)) {
19401 		return def_value;
19402 	}
19403 
19404 	p = DUK_TVAL_GET_POINTER(tv);  /* may be NULL */
19405 	return p;
19406 }
19407 
duk_get_pointer(duk_hthread * thr,duk_idx_t idx)19408 DUK_EXTERNAL void *duk_get_pointer(duk_hthread *thr, duk_idx_t idx) {
19409 	DUK_ASSERT_API_ENTRY(thr);
19410 	return duk__get_pointer_raw(thr, idx, NULL /*def_value*/);
19411 }
19412 
duk_opt_pointer(duk_hthread * thr,duk_idx_t idx,void * def_value)19413 DUK_EXTERNAL void *duk_opt_pointer(duk_hthread *thr, duk_idx_t idx, void *def_value) {
19414 	DUK_ASSERT_API_ENTRY(thr);
19415 
19416 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19417 		return def_value;
19418 	}
19419 	return duk_require_pointer(thr, idx);
19420 }
19421 
duk_get_pointer_default(duk_hthread * thr,duk_idx_t idx,void * def_value)19422 DUK_EXTERNAL void *duk_get_pointer_default(duk_hthread *thr, duk_idx_t idx, void *def_value) {
19423 	DUK_ASSERT_API_ENTRY(thr);
19424 	return duk__get_pointer_raw(thr, idx, def_value);
19425 }
19426 
duk_require_pointer(duk_hthread * thr,duk_idx_t idx)19427 DUK_EXTERNAL void *duk_require_pointer(duk_hthread *thr, duk_idx_t idx) {
19428 	duk_tval *tv;
19429 	void *p;
19430 
19431 	DUK_ASSERT_API_ENTRY(thr);
19432 
19433 	/* Note: here we must be wary of the fact that a pointer may be
19434 	 * valid and be a NULL.
19435 	 */
19436 	tv = duk_get_tval_or_unused(thr, idx);
19437 	DUK_ASSERT(tv != NULL);
19438 	if (DUK_UNLIKELY(!DUK_TVAL_IS_POINTER(tv))) {
19439 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "pointer", DUK_STR_NOT_POINTER);
19440 		DUK_WO_NORETURN(return NULL;);
19441 	}
19442 	p = DUK_TVAL_GET_POINTER(tv);  /* may be NULL */
19443 	return p;
19444 }
19445 
19446 #if 0  /*unused*/
19447 DUK_INTERNAL void *duk_get_voidptr(duk_hthread *thr, duk_idx_t idx) {
19448 	duk_tval *tv;
19449 	duk_heaphdr *h;
19450 
19451 	DUK_ASSERT_API_ENTRY(thr);
19452 
19453 	tv = duk_get_tval_or_unused(thr, idx);
19454 	DUK_ASSERT(tv != NULL);
19455 	if (!DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
19456 		return NULL;
19457 	}
19458 
19459 	h = DUK_TVAL_GET_HEAPHDR(tv);
19460 	DUK_ASSERT(h != NULL);
19461 	return (void *) h;
19462 }
19463 #endif
19464 
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)19465 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) {
19466 	duk_hbuffer *h;
19467 	void *ret;
19468 	duk_size_t len;
19469 	duk_tval *tv;
19470 
19471 	DUK_ASSERT_CTX_VALID(thr);
19472 
19473 	if (out_size != NULL) {
19474 		*out_size = 0;
19475 	}
19476 
19477 	tv = duk_get_tval_or_unused(thr, idx);
19478 	DUK_ASSERT(tv != NULL);
19479 	if (DUK_LIKELY(DUK_TVAL_IS_BUFFER(tv))) {
19480 		h = DUK_TVAL_GET_BUFFER(tv);
19481 		DUK_ASSERT(h != NULL);
19482 
19483 		len = DUK_HBUFFER_GET_SIZE(h);
19484 		ret = DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);
19485 	} else {
19486 		if (throw_flag) {
19487 			DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
19488 			DUK_WO_NORETURN(return NULL;);
19489 		}
19490 		len = def_size;
19491 		ret = def_ptr;
19492 	}
19493 
19494 	if (out_size != NULL) {
19495 		*out_size = len;
19496 	}
19497 	return ret;
19498 }
19499 
duk_get_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)19500 DUK_EXTERNAL void *duk_get_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
19501 	DUK_ASSERT_API_ENTRY(thr);
19502 
19503 	return duk__get_buffer_helper(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/);
19504 }
19505 
duk_opt_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,void * def_ptr,duk_size_t def_size)19506 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) {
19507 	DUK_ASSERT_API_ENTRY(thr);
19508 
19509 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19510 		if (out_size != NULL) {
19511 			*out_size = def_size;
19512 		}
19513 		return def_ptr;
19514 	}
19515 	return duk_require_buffer(thr, idx, out_size);
19516 }
19517 
duk_get_buffer_default(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,void * def_ptr,duk_size_t def_len)19518 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) {
19519 	DUK_ASSERT_API_ENTRY(thr);
19520 
19521 	return duk__get_buffer_helper(thr, idx, out_size, def_ptr, def_len, 0 /*throw_flag*/);
19522 }
19523 
duk_require_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)19524 DUK_EXTERNAL void *duk_require_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
19525 	DUK_ASSERT_API_ENTRY(thr);
19526 
19527 	return duk__get_buffer_helper(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 1 /*throw_flag*/);
19528 }
19529 
19530 /* Get the active buffer data area for a plain buffer or a buffer object.
19531  * Return NULL if the the value is not a buffer.  Note that a buffer may
19532  * have a NULL data pointer when its size is zero, the optional 'out_isbuffer'
19533  * argument allows caller to detect this reliably.
19534  */
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)19535 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) {
19536 	duk_tval *tv;
19537 
19538 	DUK_ASSERT_API_ENTRY(thr);
19539 
19540 	if (out_isbuffer != NULL) {
19541 		*out_isbuffer = 0;
19542 	}
19543 	if (out_size != NULL) {
19544 		*out_size = def_size;
19545 	}
19546 
19547 	tv = duk_get_tval_or_unused(thr, idx);
19548 	DUK_ASSERT(tv != NULL);
19549 
19550 	if (DUK_TVAL_IS_BUFFER(tv)) {
19551 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
19552 		DUK_ASSERT(h != NULL);
19553 		if (out_size != NULL) {
19554 			*out_size = DUK_HBUFFER_GET_SIZE(h);
19555 		}
19556 		if (out_isbuffer != NULL) {
19557 			*out_isbuffer = 1;
19558 		}
19559 		return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);  /* may be NULL (but only if size is 0) */
19560 	}
19561 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
19562 	else if (DUK_TVAL_IS_OBJECT(tv)) {
19563 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
19564 		DUK_ASSERT(h != NULL);
19565 		if (DUK_HOBJECT_IS_BUFOBJ(h)) {
19566 			/* XXX: this is probably a useful shared helper: for a
19567 			 * duk_hbufobj, get a validated buffer pointer/length.
19568 			 */
19569 			duk_hbufobj *h_bufobj = (duk_hbufobj *) h;
19570 			DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
19571 
19572 			if (h_bufobj->buf != NULL &&
19573 			    DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
19574 				duk_uint8_t *p;
19575 
19576 				p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf);
19577 				if (out_size != NULL) {
19578 					*out_size = (duk_size_t) h_bufobj->length;
19579 				}
19580 				if (out_isbuffer != NULL) {
19581 					*out_isbuffer = 1;
19582 				}
19583 				return (void *) (p + h_bufobj->offset);
19584 			}
19585 			/* if slice not fully valid, treat as error */
19586 		}
19587 	}
19588 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
19589 
19590 	if (throw_flag) {
19591 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
19592 		DUK_WO_NORETURN(return NULL;);
19593 	}
19594 	return def_ptr;
19595 }
19596 
duk_get_buffer_data(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)19597 DUK_EXTERNAL void *duk_get_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
19598 	DUK_ASSERT_API_ENTRY(thr);
19599 	return duk_get_buffer_data_raw(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, NULL);
19600 }
19601 
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)19602 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) {
19603 	DUK_ASSERT_API_ENTRY(thr);
19604 	return duk_get_buffer_data_raw(thr, idx, out_size, def_ptr, def_size, 0 /*throw_flag*/, NULL);
19605 }
19606 
duk_opt_buffer_data(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,void * def_ptr,duk_size_t def_size)19607 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) {
19608 	DUK_ASSERT_API_ENTRY(thr);
19609 
19610 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19611 		if (out_size != NULL) {
19612 			*out_size = def_size;
19613 		}
19614 		return def_ptr;
19615 	}
19616 	return duk_require_buffer_data(thr, idx, out_size);
19617 }
19618 
duk_require_buffer_data(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)19619 DUK_EXTERNAL void *duk_require_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
19620 	DUK_ASSERT_API_ENTRY(thr);
19621 	return duk_get_buffer_data_raw(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 1 /*throw_flag*/, NULL);
19622 }
19623 
19624 /* Raw helper for getting a value from the stack, checking its tag.
19625  * The tag cannot be a number because numbers don't have an internal
19626  * tag in the packed representation.
19627  */
19628 
duk__get_tagged_heaphdr_raw(duk_hthread * thr,duk_idx_t idx,duk_uint_t tag)19629 DUK_LOCAL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t tag) {
19630 	duk_tval *tv;
19631 	duk_heaphdr *ret;
19632 
19633 	DUK_ASSERT_CTX_VALID(thr);
19634 
19635 	tv = duk_get_tval_or_unused(thr, idx);
19636 	DUK_ASSERT(tv != NULL);
19637 	if (DUK_TVAL_GET_TAG(tv) != tag) {
19638 		return (duk_heaphdr *) NULL;
19639 	}
19640 
19641 	ret = DUK_TVAL_GET_HEAPHDR(tv);
19642 	DUK_ASSERT(ret != NULL);  /* tagged null pointers should never occur */
19643 	return ret;
19644 
19645 }
19646 
duk_get_hstring(duk_hthread * thr,duk_idx_t idx)19647 DUK_INTERNAL duk_hstring *duk_get_hstring(duk_hthread *thr, duk_idx_t idx) {
19648 	DUK_ASSERT_API_ENTRY(thr);
19649 	return (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
19650 }
19651 
duk_get_hstring_notsymbol(duk_hthread * thr,duk_idx_t idx)19652 DUK_INTERNAL duk_hstring *duk_get_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx) {
19653 	duk_hstring *h;
19654 
19655 	DUK_ASSERT_API_ENTRY(thr);
19656 
19657 	h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
19658 	if (DUK_UNLIKELY(h && DUK_HSTRING_HAS_SYMBOL(h))) {
19659 		return NULL;
19660 	}
19661 	return h;
19662 }
19663 
duk_require_hstring(duk_hthread * thr,duk_idx_t idx)19664 DUK_INTERNAL duk_hstring *duk_require_hstring(duk_hthread *thr, duk_idx_t idx) {
19665 	duk_hstring *h;
19666 
19667 	DUK_ASSERT_API_ENTRY(thr);
19668 
19669 	h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
19670 	if (DUK_UNLIKELY(h == NULL)) {
19671 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "string", DUK_STR_NOT_STRING);
19672 		DUK_WO_NORETURN(return NULL;);
19673 	}
19674 	return h;
19675 }
19676 
duk_require_hstring_notsymbol(duk_hthread * thr,duk_idx_t idx)19677 DUK_INTERNAL duk_hstring *duk_require_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx) {
19678 	duk_hstring *h;
19679 
19680 	DUK_ASSERT_API_ENTRY(thr);
19681 
19682 	h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
19683 	if (DUK_UNLIKELY(h == NULL || DUK_HSTRING_HAS_SYMBOL(h))) {
19684 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "string", DUK_STR_NOT_STRING);
19685 		DUK_WO_NORETURN(return NULL;);
19686 	}
19687 	return h;
19688 }
19689 
duk_get_hobject(duk_hthread * thr,duk_idx_t idx)19690 DUK_INTERNAL duk_hobject *duk_get_hobject(duk_hthread *thr, duk_idx_t idx) {
19691 	DUK_ASSERT_API_ENTRY(thr);
19692 	return (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19693 }
19694 
duk_require_hobject(duk_hthread * thr,duk_idx_t idx)19695 DUK_INTERNAL duk_hobject *duk_require_hobject(duk_hthread *thr, duk_idx_t idx) {
19696 	duk_hobject *h;
19697 
19698 	DUK_ASSERT_API_ENTRY(thr);
19699 
19700 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19701 	if (DUK_UNLIKELY(h == NULL)) {
19702 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
19703 		DUK_WO_NORETURN(return NULL;);
19704 	}
19705 	return h;
19706 }
19707 
duk_get_hbuffer(duk_hthread * thr,duk_idx_t idx)19708 DUK_INTERNAL duk_hbuffer *duk_get_hbuffer(duk_hthread *thr, duk_idx_t idx) {
19709 	DUK_ASSERT_API_ENTRY(thr);
19710 	return (duk_hbuffer *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_BUFFER);
19711 }
19712 
duk_require_hbuffer(duk_hthread * thr,duk_idx_t idx)19713 DUK_INTERNAL duk_hbuffer *duk_require_hbuffer(duk_hthread *thr, duk_idx_t idx) {
19714 	duk_hbuffer *h;
19715 
19716 	DUK_ASSERT_API_ENTRY(thr);
19717 
19718 	h = (duk_hbuffer *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_BUFFER);
19719 	if (DUK_UNLIKELY(h == NULL)) {
19720 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
19721 		DUK_WO_NORETURN(return NULL;);
19722 	}
19723 	return h;
19724 }
19725 
duk_get_hthread(duk_hthread * thr,duk_idx_t idx)19726 DUK_INTERNAL duk_hthread *duk_get_hthread(duk_hthread *thr, duk_idx_t idx) {
19727 	duk_hobject *h;
19728 
19729 	DUK_ASSERT_API_ENTRY(thr);
19730 
19731 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19732 	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_THREAD(h))) {
19733 		h = NULL;
19734 	}
19735 	return (duk_hthread *) h;
19736 }
19737 
duk_require_hthread(duk_hthread * thr,duk_idx_t idx)19738 DUK_INTERNAL duk_hthread *duk_require_hthread(duk_hthread *thr, duk_idx_t idx) {
19739 	duk_hobject *h;
19740 
19741 	DUK_ASSERT_API_ENTRY(thr);
19742 
19743 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19744 	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_THREAD(h)))) {
19745 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "thread", DUK_STR_NOT_THREAD);
19746 		DUK_WO_NORETURN(return NULL;);
19747 	}
19748 	return (duk_hthread *) h;
19749 }
19750 
duk_get_hcompfunc(duk_hthread * thr,duk_idx_t idx)19751 DUK_INTERNAL duk_hcompfunc *duk_get_hcompfunc(duk_hthread *thr, duk_idx_t idx) {
19752 	duk_hobject *h;
19753 
19754 	DUK_ASSERT_API_ENTRY(thr);
19755 
19756 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19757 	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_COMPFUNC(h))) {
19758 		h = NULL;
19759 	}
19760 	return (duk_hcompfunc *) h;
19761 }
19762 
duk_require_hcompfunc(duk_hthread * thr,duk_idx_t idx)19763 DUK_INTERNAL duk_hcompfunc *duk_require_hcompfunc(duk_hthread *thr, duk_idx_t idx) {
19764 	duk_hobject *h;
19765 
19766 	DUK_ASSERT_API_ENTRY(thr);
19767 
19768 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19769 	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_COMPFUNC(h)))) {
19770 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "compiledfunction", DUK_STR_NOT_COMPFUNC);
19771 		DUK_WO_NORETURN(return NULL;);
19772 	}
19773 	return (duk_hcompfunc *) h;
19774 }
19775 
duk_get_hnatfunc(duk_hthread * thr,duk_idx_t idx)19776 DUK_INTERNAL duk_hnatfunc *duk_get_hnatfunc(duk_hthread *thr, duk_idx_t idx) {
19777 	duk_hobject *h;
19778 
19779 	DUK_ASSERT_API_ENTRY(thr);
19780 
19781 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19782 	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_NATFUNC(h))) {
19783 		h = NULL;
19784 	}
19785 	return (duk_hnatfunc *) h;
19786 }
19787 
duk_require_hnatfunc(duk_hthread * thr,duk_idx_t idx)19788 DUK_INTERNAL duk_hnatfunc *duk_require_hnatfunc(duk_hthread *thr, duk_idx_t idx) {
19789 	duk_hobject *h;
19790 
19791 	DUK_ASSERT_API_ENTRY(thr);
19792 
19793 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19794 	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_NATFUNC(h)))) {
19795 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "nativefunction", DUK_STR_NOT_NATFUNC);
19796 		DUK_WO_NORETURN(return NULL;);
19797 	}
19798 	return (duk_hnatfunc *) h;
19799 }
19800 
duk_get_c_function(duk_hthread * thr,duk_idx_t idx)19801 DUK_EXTERNAL duk_c_function duk_get_c_function(duk_hthread *thr, duk_idx_t idx) {
19802 	duk_tval *tv;
19803 	duk_hobject *h;
19804 	duk_hnatfunc *f;
19805 
19806 	DUK_ASSERT_API_ENTRY(thr);
19807 
19808 	tv = duk_get_tval_or_unused(thr, idx);
19809 	DUK_ASSERT(tv != NULL);
19810 	if (DUK_UNLIKELY(!DUK_TVAL_IS_OBJECT(tv))) {
19811 		return NULL;
19812 	}
19813 	h = DUK_TVAL_GET_OBJECT(tv);
19814 	DUK_ASSERT(h != NULL);
19815 
19816 	if (DUK_UNLIKELY(!DUK_HOBJECT_IS_NATFUNC(h))) {
19817 		return NULL;
19818 	}
19819 	DUK_ASSERT(DUK_HOBJECT_HAS_NATFUNC(h));
19820 	f = (duk_hnatfunc *) h;
19821 
19822 	return f->func;
19823 }
19824 
duk_opt_c_function(duk_hthread * thr,duk_idx_t idx,duk_c_function def_value)19825 DUK_EXTERNAL duk_c_function duk_opt_c_function(duk_hthread *thr, duk_idx_t idx, duk_c_function def_value) {
19826 	DUK_ASSERT_API_ENTRY(thr);
19827 
19828 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19829 		return def_value;
19830 	}
19831 	return duk_require_c_function(thr, idx);
19832 }
19833 
duk_get_c_function_default(duk_hthread * thr,duk_idx_t idx,duk_c_function def_value)19834 DUK_EXTERNAL duk_c_function duk_get_c_function_default(duk_hthread *thr, duk_idx_t idx, duk_c_function def_value) {
19835 	duk_c_function ret;
19836 
19837 	DUK_ASSERT_API_ENTRY(thr);
19838 
19839 	ret = duk_get_c_function(thr, idx);
19840 	if (ret != NULL) {
19841 		return ret;
19842 	}
19843 
19844 	return def_value;
19845 }
19846 
duk_require_c_function(duk_hthread * thr,duk_idx_t idx)19847 DUK_EXTERNAL duk_c_function duk_require_c_function(duk_hthread *thr, duk_idx_t idx) {
19848 	duk_c_function ret;
19849 
19850 	DUK_ASSERT_API_ENTRY(thr);
19851 
19852 	ret = duk_get_c_function(thr, idx);
19853 	if (DUK_UNLIKELY(!ret)) {
19854 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "nativefunction", DUK_STR_NOT_NATFUNC);
19855 		DUK_WO_NORETURN(return ret;);
19856 	}
19857 	return ret;
19858 }
19859 
duk_require_function(duk_hthread * thr,duk_idx_t idx)19860 DUK_EXTERNAL void duk_require_function(duk_hthread *thr, duk_idx_t idx) {
19861 	DUK_ASSERT_API_ENTRY(thr);
19862 	if (DUK_UNLIKELY(!duk_is_function(thr, idx))) {
19863 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "function", DUK_STR_NOT_FUNCTION);
19864 		DUK_WO_NORETURN(return;);
19865 	}
19866 }
19867 
duk_require_constructable(duk_hthread * thr,duk_idx_t idx)19868 DUK_INTERNAL void duk_require_constructable(duk_hthread *thr, duk_idx_t idx) {
19869 	duk_hobject *h;
19870 
19871 	DUK_ASSERT_API_ENTRY(thr);
19872 
19873 	h = duk_require_hobject_accept_mask(thr, idx, DUK_TYPE_MASK_LIGHTFUNC);
19874 	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_HAS_CONSTRUCTABLE(h))) {
19875 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "constructable", DUK_STR_NOT_CONSTRUCTABLE);
19876 		DUK_WO_NORETURN(return;);
19877 	}
19878 	/* Lightfuncs (h == NULL) are constructable. */
19879 }
19880 
duk_get_context(duk_hthread * thr,duk_idx_t idx)19881 DUK_EXTERNAL duk_hthread *duk_get_context(duk_hthread *thr, duk_idx_t idx) {
19882 	DUK_ASSERT_API_ENTRY(thr);
19883 
19884 	return duk_get_hthread(thr, idx);
19885 }
19886 
duk_require_context(duk_hthread * thr,duk_idx_t idx)19887 DUK_EXTERNAL duk_hthread *duk_require_context(duk_hthread *thr, duk_idx_t idx) {
19888 	DUK_ASSERT_API_ENTRY(thr);
19889 
19890 	return duk_require_hthread(thr, idx);
19891 }
19892 
duk_opt_context(duk_hthread * thr,duk_idx_t idx,duk_hthread * def_value)19893 DUK_EXTERNAL duk_hthread *duk_opt_context(duk_hthread *thr, duk_idx_t idx, duk_hthread *def_value) {
19894 	DUK_ASSERT_API_ENTRY(thr);
19895 
19896 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19897 		return def_value;
19898 	}
19899 	return duk_require_context(thr, idx);
19900 }
19901 
duk_get_context_default(duk_hthread * thr,duk_idx_t idx,duk_hthread * def_value)19902 DUK_EXTERNAL duk_hthread *duk_get_context_default(duk_hthread *thr, duk_idx_t idx, duk_hthread *def_value) {
19903 	duk_hthread *ret;
19904 
19905 	DUK_ASSERT_API_ENTRY(thr);
19906 
19907 	ret = duk_get_context(thr, idx);
19908 	if (ret != NULL) {
19909 		return ret;
19910 	}
19911 
19912 	return def_value;
19913 }
19914 
duk_get_heapptr(duk_hthread * thr,duk_idx_t idx)19915 DUK_EXTERNAL void *duk_get_heapptr(duk_hthread *thr, duk_idx_t idx) {
19916 	duk_tval *tv;
19917 	void *ret;
19918 
19919 	DUK_ASSERT_API_ENTRY(thr);
19920 
19921 	tv = duk_get_tval_or_unused(thr, idx);
19922 	DUK_ASSERT(tv != NULL);
19923 	if (DUK_UNLIKELY(!DUK_TVAL_IS_HEAP_ALLOCATED(tv))) {
19924 		return (void *) NULL;
19925 	}
19926 
19927 	ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
19928 	DUK_ASSERT(ret != NULL);
19929 	return ret;
19930 }
19931 
duk_opt_heapptr(duk_hthread * thr,duk_idx_t idx,void * def_value)19932 DUK_EXTERNAL void *duk_opt_heapptr(duk_hthread *thr, duk_idx_t idx, void *def_value) {
19933 	DUK_ASSERT_API_ENTRY(thr);
19934 
19935 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19936 		return def_value;
19937 	}
19938 	return duk_require_heapptr(thr, idx);
19939 }
19940 
duk_get_heapptr_default(duk_hthread * thr,duk_idx_t idx,void * def_value)19941 DUK_EXTERNAL void *duk_get_heapptr_default(duk_hthread *thr, duk_idx_t idx, void *def_value) {
19942 	void *ret;
19943 
19944 	DUK_ASSERT_API_ENTRY(thr);
19945 
19946 	ret = duk_get_heapptr(thr, idx);
19947 	if (ret != NULL) {
19948 		return ret;
19949 	}
19950 
19951 	return def_value;
19952 }
19953 
duk_require_heapptr(duk_hthread * thr,duk_idx_t idx)19954 DUK_EXTERNAL void *duk_require_heapptr(duk_hthread *thr, duk_idx_t idx) {
19955 	duk_tval *tv;
19956 	void *ret;
19957 
19958 	DUK_ASSERT_API_ENTRY(thr);
19959 
19960 	tv = duk_get_tval_or_unused(thr, idx);
19961 	DUK_ASSERT(tv != NULL);
19962 	if (DUK_UNLIKELY(!DUK_TVAL_IS_HEAP_ALLOCATED(tv))) {
19963 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "heapobject", DUK_STR_UNEXPECTED_TYPE);
19964 		DUK_WO_NORETURN(return NULL;);
19965 	}
19966 
19967 	ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
19968 	DUK_ASSERT(ret != NULL);
19969 	return ret;
19970 }
19971 
19972 /* 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)19973 DUK_LOCAL duk_hobject *duk__get_hobject_promote_mask_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
19974 	duk_uint_t val_mask;
19975 	duk_hobject *res;
19976 
19977 	DUK_ASSERT_CTX_VALID(thr);
19978 
19979 	res = duk_get_hobject(thr, idx);  /* common case, not promoted */
19980 	if (DUK_LIKELY(res != NULL)) {
19981 		DUK_ASSERT(res != NULL);
19982 		return res;
19983 	}
19984 
19985 	val_mask = duk_get_type_mask(thr, idx);
19986 	if (val_mask & type_mask) {
19987 		if (type_mask & DUK_TYPE_MASK_PROMOTE) {
19988 			res = duk_to_hobject(thr, idx);
19989 			DUK_ASSERT(res != NULL);
19990 			return res;
19991 		} else {
19992 			return NULL;  /* accept without promoting */
19993 		}
19994 	}
19995 
19996 	if (type_mask & DUK_TYPE_MASK_THROW) {
19997 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
19998 		DUK_WO_NORETURN(return NULL;);
19999 	}
20000 	return NULL;
20001 }
20002 
20003 /* Get a duk_hobject * at 'idx'; if the value is not an object but matches the
20004  * supplied 'type_mask', promote it to an object and return the duk_hobject *.
20005  * This is useful for call sites which want an object but also accept a plain
20006  * buffer and/or a lightfunc which gets automatically promoted to an object.
20007  * Return value is NULL if value is neither an object nor a plain type allowed
20008  * by the mask.
20009  */
duk_get_hobject_promote_mask(duk_hthread * thr,duk_idx_t idx,duk_uint_t type_mask)20010 DUK_INTERNAL duk_hobject *duk_get_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
20011 	DUK_ASSERT_API_ENTRY(thr);
20012 	return duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_PROMOTE);
20013 }
20014 
20015 /* Like duk_get_hobject_promote_mask() but throw a TypeError instead of
20016  * returning a NULL.
20017  */
duk_require_hobject_promote_mask(duk_hthread * thr,duk_idx_t idx,duk_uint_t type_mask)20018 DUK_INTERNAL duk_hobject *duk_require_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
20019 	DUK_ASSERT_API_ENTRY(thr);
20020 	return duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_THROW | DUK_TYPE_MASK_PROMOTE);
20021 }
20022 
20023 /* Require a duk_hobject * at 'idx'; if the value is not an object but matches the
20024  * supplied 'type_mask', return a NULL instead.  Otherwise throw a TypeError.
20025  */
duk_require_hobject_accept_mask(duk_hthread * thr,duk_idx_t idx,duk_uint_t type_mask)20026 DUK_INTERNAL duk_hobject *duk_require_hobject_accept_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
20027 	DUK_ASSERT_API_ENTRY(thr);
20028 	return duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_THROW);
20029 }
20030 
duk_get_hobject_with_class(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t classnum)20031 DUK_INTERNAL duk_hobject *duk_get_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum) {
20032 	duk_hobject *h;
20033 
20034 	DUK_ASSERT_API_ENTRY(thr);
20035 	DUK_ASSERT_DISABLE(classnum >= 0);  /* unsigned */
20036 	DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
20037 
20038 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20039 	if (DUK_UNLIKELY(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) != classnum)) {
20040 		h = NULL;
20041 	}
20042 	return h;
20043 }
20044 
duk_require_hobject_with_class(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t classnum)20045 DUK_INTERNAL duk_hobject *duk_require_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum) {
20046 	duk_hobject *h;
20047 
20048 	DUK_ASSERT_API_ENTRY(thr);
20049 	DUK_ASSERT_DISABLE(classnum >= 0);  /* unsigned */
20050 	DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
20051 
20052 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20053 	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) == classnum))) {
20054 		duk_hstring *h_class;
20055 		h_class = DUK_HTHREAD_GET_STRING(thr, DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum));
20056 		DUK_UNREF(h_class);
20057 
20058 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, (const char *) DUK_HSTRING_GET_DATA(h_class), DUK_STR_UNEXPECTED_TYPE);
20059 		DUK_WO_NORETURN(return NULL;);
20060 	}
20061 	return h;
20062 }
20063 
duk_get_length(duk_hthread * thr,duk_idx_t idx)20064 DUK_EXTERNAL duk_size_t duk_get_length(duk_hthread *thr, duk_idx_t idx) {
20065 	duk_tval *tv;
20066 
20067 	DUK_ASSERT_API_ENTRY(thr);
20068 
20069 	tv = duk_get_tval_or_unused(thr, idx);
20070 	DUK_ASSERT(tv != NULL);
20071 
20072 	switch (DUK_TVAL_GET_TAG(tv)) {
20073 	case DUK_TAG_UNDEFINED:
20074 	case DUK_TAG_NULL:
20075 	case DUK_TAG_BOOLEAN:
20076 	case DUK_TAG_POINTER:
20077 		return 0;
20078 #if defined(DUK_USE_PREFER_SIZE)
20079 	/* String and buffer have a virtual non-configurable .length property
20080 	 * which is within size_t range so it can be looked up without specific
20081 	 * type checks.  Lightfuncs inherit from %NativeFunctionPrototype%
20082 	 * which provides an inherited .length accessor; it could be overwritten
20083 	 * to produce unexpected types or values, but just number convert and
20084 	 * duk_size_t cast for now.
20085 	 */
20086 	case DUK_TAG_STRING:
20087 	case DUK_TAG_BUFFER:
20088 	case DUK_TAG_LIGHTFUNC: {
20089 		duk_size_t ret;
20090 		duk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
20091 		ret = (duk_size_t) duk_to_number_m1(thr);
20092 		duk_pop_unsafe(thr);
20093 		return ret;
20094 	}
20095 #else  /* DUK_USE_PREFER_SIZE */
20096 	case DUK_TAG_STRING: {
20097 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
20098 		DUK_ASSERT(h != NULL);
20099 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
20100 			return 0;
20101 		}
20102 		return (duk_size_t) DUK_HSTRING_GET_CHARLEN(h);
20103 	}
20104 	case DUK_TAG_BUFFER: {
20105 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
20106 		DUK_ASSERT(h != NULL);
20107 		return (duk_size_t) DUK_HBUFFER_GET_SIZE(h);
20108 	}
20109 	case DUK_TAG_LIGHTFUNC: {
20110 		/* We could look up the length from the lightfunc duk_tval,
20111 		 * but since Duktape 2.2 lightfunc .length comes from
20112 		 * %NativeFunctionPrototype% which can be overridden, so
20113 		 * look up the property explicitly.
20114 		 */
20115 		duk_size_t ret;
20116 		duk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
20117 		ret = (duk_size_t) duk_to_number_m1(thr);
20118 		duk_pop_unsafe(thr);
20119 		return ret;
20120 	}
20121 #endif  /* DUK_USE_PREFER_SIZE */
20122 	case DUK_TAG_OBJECT: {
20123 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
20124 		DUK_ASSERT(h != NULL);
20125 		return (duk_size_t) duk_hobject_get_length(thr, h);
20126 	}
20127 #if defined(DUK_USE_FASTINT)
20128 	case DUK_TAG_FASTINT:
20129 #endif
20130 	default:
20131 		/* number or 'unused' */
20132 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv) || DUK_TVAL_IS_UNUSED(tv));
20133 		return 0;
20134 	}
20135 
20136 	DUK_UNREACHABLE();
20137 }
20138 
20139 /*
20140  *  duk_known_xxx() helpers
20141  *
20142  *  Used internally when we're 100% sure that a certain index is valid and
20143  *  contains an object of a certain type.  For example, if we duk_push_object()
20144  *  we can then safely duk_known_hobject(thr, -1).  These helpers just assert
20145  *  for the index and type, and if the assumptions are not valid, memory unsafe
20146  *  behavior happens.
20147  */
20148 
duk__known_heaphdr(duk_hthread * thr,duk_idx_t idx)20149 DUK_LOCAL duk_heaphdr *duk__known_heaphdr(duk_hthread *thr, duk_idx_t idx) {
20150 	duk_tval *tv;
20151 	duk_heaphdr *h;
20152 
20153 	DUK_ASSERT_CTX_VALID(thr);
20154 	if (idx < 0) {
20155 		tv = thr->valstack_top + idx;
20156 	} else {
20157 		tv = thr->valstack_bottom + idx;
20158 	}
20159 	DUK_ASSERT(tv >= thr->valstack_bottom);
20160 	DUK_ASSERT(tv < thr->valstack_top);
20161 	h = DUK_TVAL_GET_HEAPHDR(tv);
20162 	DUK_ASSERT(h != NULL);
20163 	return h;
20164 }
20165 
duk_known_hstring(duk_hthread * thr,duk_idx_t idx)20166 DUK_INTERNAL duk_hstring *duk_known_hstring(duk_hthread *thr, duk_idx_t idx) {
20167 	DUK_ASSERT_API_ENTRY(thr);
20168 	DUK_ASSERT(duk_get_hstring(thr, idx) != NULL);
20169 	return (duk_hstring *) duk__known_heaphdr(thr, idx);
20170 }
20171 
duk_known_hobject(duk_hthread * thr,duk_idx_t idx)20172 DUK_INTERNAL duk_hobject *duk_known_hobject(duk_hthread *thr, duk_idx_t idx) {
20173 	DUK_ASSERT_API_ENTRY(thr);
20174 	DUK_ASSERT(duk_get_hobject(thr, idx) != NULL);
20175 	return (duk_hobject *) duk__known_heaphdr(thr, idx);
20176 }
20177 
duk_known_hbuffer(duk_hthread * thr,duk_idx_t idx)20178 DUK_INTERNAL duk_hbuffer *duk_known_hbuffer(duk_hthread *thr, duk_idx_t idx) {
20179 	DUK_ASSERT_API_ENTRY(thr);
20180 	DUK_ASSERT(duk_get_hbuffer(thr, idx) != NULL);
20181 	return (duk_hbuffer *) duk__known_heaphdr(thr, idx);
20182 }
20183 
duk_known_hcompfunc(duk_hthread * thr,duk_idx_t idx)20184 DUK_INTERNAL duk_hcompfunc *duk_known_hcompfunc(duk_hthread *thr, duk_idx_t idx) {
20185 	DUK_ASSERT_API_ENTRY(thr);
20186 	DUK_ASSERT(duk_get_hcompfunc(thr, idx) != NULL);
20187 	return (duk_hcompfunc *) duk__known_heaphdr(thr, idx);
20188 }
20189 
duk_known_hnatfunc(duk_hthread * thr,duk_idx_t idx)20190 DUK_INTERNAL duk_hnatfunc *duk_known_hnatfunc(duk_hthread *thr, duk_idx_t idx) {
20191 	DUK_ASSERT_API_ENTRY(thr);
20192 	DUK_ASSERT(duk_get_hnatfunc(thr, idx) != NULL);
20193 	return (duk_hnatfunc *) duk__known_heaphdr(thr, idx);
20194 }
20195 
duk_set_length(duk_hthread * thr,duk_idx_t idx,duk_size_t len)20196 DUK_EXTERNAL void duk_set_length(duk_hthread *thr, duk_idx_t idx, duk_size_t len) {
20197 	DUK_ASSERT_API_ENTRY(thr);
20198 
20199 	idx = duk_normalize_index(thr, idx);
20200 	duk_push_uint(thr, (duk_uint_t) len);
20201 	duk_put_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
20202 }
20203 
20204 /*
20205  *  Conversions and coercions
20206  *
20207  *  The conversion/coercions are in-place operations on the value stack.
20208  *  Some operations are implemented here directly, while others call a
20209  *  helper in duk_js_ops.c after validating arguments.
20210  */
20211 
20212 /* E5 Section 8.12.8 */
20213 
duk__defaultvalue_coerce_attempt(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t func_stridx)20214 DUK_LOCAL duk_bool_t duk__defaultvalue_coerce_attempt(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t func_stridx) {
20215 	if (duk_get_prop_stridx(thr, idx, func_stridx)) {
20216 		/* [ ... func ] */
20217 		if (duk_is_callable(thr, -1)) {
20218 			duk_dup(thr, idx);         /* -> [ ... func this ] */
20219 			duk_call_method(thr, 0);     /* -> [ ... retval ] */
20220 			if (duk_is_primitive(thr, -1)) {
20221 				duk_replace(thr, idx);
20222 				return 1;
20223 			}
20224 			/* [ ... retval ]; popped below */
20225 		}
20226 	}
20227 	duk_pop_unsafe(thr);  /* [ ... func/retval ] -> [ ... ] */
20228 	return 0;
20229 }
20230 
duk_to_undefined(duk_hthread * thr,duk_idx_t idx)20231 DUK_EXTERNAL void duk_to_undefined(duk_hthread *thr, duk_idx_t idx) {
20232 	duk_tval *tv;
20233 
20234 	DUK_ASSERT_API_ENTRY(thr);
20235 
20236 	tv = duk_require_tval(thr, idx);
20237 	DUK_ASSERT(tv != NULL);
20238 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
20239 }
20240 
duk_to_null(duk_hthread * thr,duk_idx_t idx)20241 DUK_EXTERNAL void duk_to_null(duk_hthread *thr, duk_idx_t idx) {
20242 	duk_tval *tv;
20243 
20244 	DUK_ASSERT_API_ENTRY(thr);
20245 
20246 	tv = duk_require_tval(thr, idx);
20247 	DUK_ASSERT(tv != NULL);
20248 	DUK_TVAL_SET_NULL_UPDREF(thr, tv);  /* side effects */
20249 }
20250 
20251 /* E5 Section 9.1 */
20252 DUK_LOCAL const char * const duk__toprim_hint_strings[3] = {
20253 	"default", "string", "number"
20254 };
duk__to_primitive_helper(duk_hthread * thr,duk_idx_t idx,duk_int_t hint,duk_bool_t check_symbol)20255 DUK_LOCAL void duk__to_primitive_helper(duk_hthread *thr, duk_idx_t idx, duk_int_t hint, duk_bool_t check_symbol) {
20256 	/* Inline initializer for coercers[] is not allowed by old compilers like BCC. */
20257 	duk_small_uint_t coercers[2];
20258 
20259 	DUK_ASSERT_API_ENTRY(thr);
20260 	DUK_ASSERT(hint == DUK_HINT_NONE || hint == DUK_HINT_NUMBER || hint == DUK_HINT_STRING);
20261 
20262 	idx = duk_require_normalize_index(thr, idx);
20263 
20264 	/* If already primitive, return as is. */
20265 	if (!duk_check_type_mask(thr, idx, DUK_TYPE_MASK_OBJECT |
20266 	                                   DUK_TYPE_MASK_LIGHTFUNC |
20267 	                                   DUK_TYPE_MASK_BUFFER)) {
20268 		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */
20269 		return;
20270 	}
20271 
20272 	/* @@toPrimitive lookup.  Also do for plain buffers and lightfuncs
20273 	 * which mimic objects.
20274 	 */
20275 	if (check_symbol && duk_get_method_stridx(thr, idx, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)) {
20276 		DUK_ASSERT(hint >= 0 && (duk_size_t) hint < sizeof(duk__toprim_hint_strings) / sizeof(const char *));
20277 		duk_dup(thr, idx);
20278 		duk_push_string(thr, duk__toprim_hint_strings[hint]);
20279 		duk_call_method(thr, 1);  /* [ ... method value hint ] -> [ ... res] */
20280 		if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |
20281 	                                         DUK_TYPE_MASK_LIGHTFUNC |
20282 		                                 DUK_TYPE_MASK_BUFFER)) {
20283 			goto fail;
20284 		}
20285 		duk_replace(thr, idx);
20286 		return;
20287 	}
20288 
20289 	/* Objects are coerced based on E5 specification.
20290 	 * Lightfuncs are coerced because they behave like
20291 	 * objects even if they're internally a primitive
20292 	 * type.  Same applies to plain buffers, which behave
20293 	 * like ArrayBuffer objects since Duktape 2.x.
20294 	 */
20295 
20296 	/* Hint magic for Date is unnecessary in ES2015 because of
20297 	 * Date.prototype[@@toPrimitive].  However, it is needed if
20298 	 * symbol support is not enabled.
20299 	 */
20300 #if defined(DUK_USE_SYMBOL_BUILTIN)
20301 	if (hint == DUK_HINT_NONE) {
20302 		hint = DUK_HINT_NUMBER;
20303 	}
20304 #else  /* DUK_USE_SYMBOL_BUILTIN */
20305 	if (hint == DUK_HINT_NONE) {
20306 		duk_small_uint_t class_number;
20307 
20308 		class_number = duk_get_class_number(thr, idx);
20309 		if (class_number == DUK_HOBJECT_CLASS_DATE) {
20310 			hint = DUK_HINT_STRING;
20311 		} else {
20312 			hint = DUK_HINT_NUMBER;
20313 		}
20314 	}
20315 #endif  /* DUK_USE_SYMBOL_BUILTIN */
20316 
20317 	coercers[0] = DUK_STRIDX_VALUE_OF;
20318 	coercers[1] = DUK_STRIDX_TO_STRING;
20319 	if (hint == DUK_HINT_STRING) {
20320 		coercers[0] = DUK_STRIDX_TO_STRING;
20321 		coercers[1] = DUK_STRIDX_VALUE_OF;
20322 	}
20323 
20324 	if (duk__defaultvalue_coerce_attempt(thr, idx, coercers[0])) {
20325 		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */
20326 		return;
20327 	}
20328 
20329 	if (duk__defaultvalue_coerce_attempt(thr, idx, coercers[1])) {
20330 		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */
20331 		return;
20332 	}
20333 
20334  fail:
20335 	DUK_ERROR_TYPE(thr, DUK_STR_TOPRIMITIVE_FAILED);
20336 	DUK_WO_NORETURN(return;);
20337 }
20338 
duk_to_primitive(duk_hthread * thr,duk_idx_t idx,duk_int_t hint)20339 DUK_EXTERNAL void duk_to_primitive(duk_hthread *thr, duk_idx_t idx, duk_int_t hint) {
20340 	duk__to_primitive_helper(thr, idx, hint, 1 /*check_symbol*/);
20341 }
20342 
20343 #if defined(DUK_USE_SYMBOL_BUILTIN)
duk_to_primitive_ordinary(duk_hthread * thr,duk_idx_t idx,duk_int_t hint)20344 DUK_INTERNAL void duk_to_primitive_ordinary(duk_hthread *thr, duk_idx_t idx, duk_int_t hint) {
20345 	duk__to_primitive_helper(thr, idx, hint, 0 /*check_symbol*/);
20346 }
20347 #endif
20348 
20349 /* E5 Section 9.2 */
duk_to_boolean(duk_hthread * thr,duk_idx_t idx)20350 DUK_EXTERNAL duk_bool_t duk_to_boolean(duk_hthread *thr, duk_idx_t idx) {
20351 	duk_tval *tv;
20352 	duk_bool_t val;
20353 
20354 	DUK_ASSERT_API_ENTRY(thr);
20355 
20356 	idx = duk_require_normalize_index(thr, idx);
20357 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
20358 	DUK_ASSERT(tv != NULL);
20359 
20360 	val = duk_js_toboolean(tv);
20361 	DUK_ASSERT(val == 0 || val == 1);
20362 
20363 	/* Note: no need to re-lookup tv, conversion is side effect free. */
20364 	DUK_ASSERT(tv != NULL);
20365 	DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, val);  /* side effects */
20366 	return val;
20367 }
20368 
duk_to_boolean_top_pop(duk_hthread * thr)20369 DUK_INTERNAL duk_bool_t duk_to_boolean_top_pop(duk_hthread *thr) {
20370 	duk_tval *tv;
20371 	duk_bool_t val;
20372 
20373 	DUK_ASSERT_API_ENTRY(thr);
20374 
20375 	tv = duk_require_tval(thr, -1);
20376 	DUK_ASSERT(tv != NULL);
20377 
20378 	val = duk_js_toboolean(tv);
20379 	DUK_ASSERT(val == 0 || val == 1);
20380 
20381 	duk_pop_unsafe(thr);
20382 	return val;
20383 }
20384 
duk_to_number(duk_hthread * thr,duk_idx_t idx)20385 DUK_EXTERNAL duk_double_t duk_to_number(duk_hthread *thr, duk_idx_t idx) {
20386 	duk_tval *tv;
20387 	duk_double_t d;
20388 
20389 	DUK_ASSERT_API_ENTRY(thr);
20390 
20391 	/* XXX: No need to normalize; the whole operation could be inlined here to
20392 	 * avoid 'tv' re-lookup.
20393 	 */
20394 	idx = duk_require_normalize_index(thr, idx);
20395 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
20396 	DUK_ASSERT(tv != NULL);
20397 	d = duk_js_tonumber(thr, tv);  /* XXX: fastint coercion? now result will always be a non-fastint */
20398 
20399 	/* ToNumber() may have side effects so must relookup 'tv'. */
20400 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
20401 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d);  /* side effects */
20402 	return d;
20403 }
20404 
duk_to_number_m1(duk_hthread * thr)20405 DUK_INTERNAL duk_double_t duk_to_number_m1(duk_hthread *thr) {
20406 	DUK_ASSERT_API_ENTRY(thr);
20407 	return duk_to_number(thr, -1);
20408 }
duk_to_number_m2(duk_hthread * thr)20409 DUK_INTERNAL duk_double_t duk_to_number_m2(duk_hthread *thr) {
20410 	DUK_ASSERT_API_ENTRY(thr);
20411 	return duk_to_number(thr, -2);
20412 }
20413 
duk_to_number_tval(duk_hthread * thr,duk_tval * tv)20414 DUK_INTERNAL duk_double_t duk_to_number_tval(duk_hthread *thr, duk_tval *tv) {
20415 #if defined(DUK_USE_PREFER_SIZE)
20416 	duk_double_t res;
20417 
20418 	DUK_ASSERT_API_ENTRY(thr);
20419 
20420 	duk_push_tval(thr, tv);
20421 	res = duk_to_number_m1(thr);
20422 	duk_pop_unsafe(thr);
20423 	return res;
20424 #else
20425 	duk_double_t res;
20426 	duk_tval *tv_dst;
20427 
20428 	DUK_ASSERT_API_ENTRY(thr);
20429 	DUK__ASSERT_SPACE();
20430 
20431 	tv_dst = thr->valstack_top++;
20432 	DUK_TVAL_SET_TVAL(tv_dst, tv);
20433 	DUK_TVAL_INCREF(thr, tv_dst);  /* decref not necessary */
20434 	res = duk_to_number_m1(thr);  /* invalidates tv_dst */
20435 
20436 	tv_dst = --thr->valstack_top;
20437 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_dst));
20438 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv_dst));  /* plain number */
20439 	DUK_TVAL_SET_UNDEFINED(tv_dst);  /* valstack init policy */
20440 
20441 	return res;
20442 #endif
20443 }
20444 
20445 /* XXX: combine all the integer conversions: they share everything
20446  * but the helper function for coercion.
20447  */
20448 
20449 typedef duk_double_t (*duk__toint_coercer)(duk_hthread *thr, duk_tval *tv);
20450 
duk__to_int_uint_helper(duk_hthread * thr,duk_idx_t idx,duk__toint_coercer coerce_func)20451 DUK_LOCAL duk_double_t duk__to_int_uint_helper(duk_hthread *thr, duk_idx_t idx, duk__toint_coercer coerce_func) {
20452 	duk_tval *tv;
20453 	duk_double_t d;
20454 
20455 	DUK_ASSERT_CTX_VALID(thr);
20456 
20457 	tv = duk_require_tval(thr, idx);
20458 	DUK_ASSERT(tv != NULL);
20459 
20460 #if defined(DUK_USE_FASTINT)
20461 	/* If argument is a fastint, guarantee that it remains one.
20462 	 * There's no downgrade check for other cases.
20463 	 */
20464 	if (DUK_TVAL_IS_FASTINT(tv)) {
20465 		/* XXX: Unnecessary conversion back and forth. */
20466 		return (duk_double_t) DUK_TVAL_GET_FASTINT(tv);
20467 	}
20468 #endif
20469 	d = coerce_func(thr, tv);
20470 
20471 	/* XXX: fastint? */
20472 
20473 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
20474 	tv = duk_require_tval(thr, idx);
20475 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d);  /* side effects */
20476 	return d;
20477 }
20478 
duk_to_int(duk_hthread * thr,duk_idx_t idx)20479 DUK_EXTERNAL duk_int_t duk_to_int(duk_hthread *thr, duk_idx_t idx) {
20480 	/* Value coercion (in stack): ToInteger(), E5 Section 9.4,
20481 	 * API return value coercion: custom.
20482 	 */
20483 	DUK_ASSERT_API_ENTRY(thr);
20484 	(void) duk__to_int_uint_helper(thr, idx, duk_js_tointeger);
20485 	return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 0 /*require*/);
20486 }
20487 
duk_to_uint(duk_hthread * thr,duk_idx_t idx)20488 DUK_EXTERNAL duk_uint_t duk_to_uint(duk_hthread *thr, duk_idx_t idx) {
20489 	/* Value coercion (in stack): ToInteger(), E5 Section 9.4,
20490 	 * API return value coercion: custom.
20491 	 */
20492 	DUK_ASSERT_API_ENTRY(thr);
20493 	(void) duk__to_int_uint_helper(thr, idx, duk_js_tointeger);
20494 	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 0 /*require*/);
20495 }
20496 
duk_to_int32(duk_hthread * thr,duk_idx_t idx)20497 DUK_EXTERNAL duk_int32_t duk_to_int32(duk_hthread *thr, duk_idx_t idx) {
20498 	duk_tval *tv;
20499 	duk_int32_t ret;
20500 
20501 	DUK_ASSERT_API_ENTRY(thr);
20502 
20503 	tv = duk_require_tval(thr, idx);
20504 	DUK_ASSERT(tv != NULL);
20505 	ret = duk_js_toint32(thr, tv);
20506 
20507 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
20508 	tv = duk_require_tval(thr, idx);
20509 	DUK_TVAL_SET_I32_UPDREF(thr, tv, ret);  /* side effects */
20510 	return ret;
20511 }
20512 
duk_to_uint32(duk_hthread * thr,duk_idx_t idx)20513 DUK_EXTERNAL duk_uint32_t duk_to_uint32(duk_hthread *thr, duk_idx_t idx) {
20514 	duk_tval *tv;
20515 	duk_uint32_t ret;
20516 
20517 	DUK_ASSERT_API_ENTRY(thr);
20518 
20519 	tv = duk_require_tval(thr, idx);
20520 	DUK_ASSERT(tv != NULL);
20521 	ret = duk_js_touint32(thr, tv);
20522 
20523 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
20524 	tv = duk_require_tval(thr, idx);
20525 	DUK_TVAL_SET_U32_UPDREF(thr, tv, ret);  /* side effects */
20526 	return ret;
20527 }
20528 
duk_to_uint16(duk_hthread * thr,duk_idx_t idx)20529 DUK_EXTERNAL duk_uint16_t duk_to_uint16(duk_hthread *thr, duk_idx_t idx) {
20530 	duk_tval *tv;
20531 	duk_uint16_t ret;
20532 
20533 	DUK_ASSERT_API_ENTRY(thr);
20534 
20535 	tv = duk_require_tval(thr, idx);
20536 	DUK_ASSERT(tv != NULL);
20537 	ret = duk_js_touint16(thr, tv);
20538 
20539 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
20540 	tv = duk_require_tval(thr, idx);
20541 	DUK_TVAL_SET_U32_UPDREF(thr, tv, ret);  /* side effects */
20542 	return ret;
20543 }
20544 
20545 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
20546 /* Special coercion for Uint8ClampedArray. */
duk_to_uint8clamped(duk_hthread * thr,duk_idx_t idx)20547 DUK_INTERNAL duk_uint8_t duk_to_uint8clamped(duk_hthread *thr, duk_idx_t idx) {
20548 	duk_double_t d;
20549 	duk_double_t t;
20550 	duk_uint8_t ret;
20551 
20552 	DUK_ASSERT_API_ENTRY(thr);
20553 
20554 	/* XXX: Simplify this algorithm, should be possible to come up with
20555 	 * a shorter and faster algorithm by inspecting IEEE representation
20556 	 * directly.
20557 	 */
20558 
20559 	d = duk_to_number(thr, idx);
20560 	if (d <= 0.0) {
20561 		return 0;
20562 	} else if (d >= 255) {
20563 		return 255;
20564 	} else if (DUK_ISNAN(d)) {
20565 		/* Avoid NaN-to-integer coercion as it is compiler specific. */
20566 		return 0;
20567 	}
20568 
20569 	t = d - DUK_FLOOR(d);
20570 	if (t == 0.5) {
20571 		/* Exact halfway, round to even. */
20572 		ret = (duk_uint8_t) d;
20573 		ret = (ret + 1) & 0xfe;  /* Example: d=3.5, t=0.5 -> ret = (3 + 1) & 0xfe = 4 & 0xfe = 4
20574 		                          * Example: d=4.5, t=0.5 -> ret = (4 + 1) & 0xfe = 5 & 0xfe = 4
20575 		                          */
20576 	} else {
20577 		/* Not halfway, round to nearest. */
20578 		ret = (duk_uint8_t) (d + 0.5);
20579 	}
20580 	return ret;
20581 }
20582 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
20583 
duk_to_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)20584 DUK_EXTERNAL const char *duk_to_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
20585 	DUK_ASSERT_API_ENTRY(thr);
20586 
20587 	(void) duk_to_string(thr, idx);
20588 	DUK_ASSERT(duk_is_string(thr, idx));
20589 	return duk_require_lstring(thr, idx, out_len);
20590 }
20591 
duk__safe_to_string_raw(duk_hthread * thr,void * udata)20592 DUK_LOCAL duk_ret_t duk__safe_to_string_raw(duk_hthread *thr, void *udata) {
20593 	DUK_ASSERT_CTX_VALID(thr);
20594 	DUK_UNREF(udata);
20595 
20596 	duk_to_string(thr, -1);
20597 	return 1;
20598 }
20599 
duk_safe_to_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)20600 DUK_EXTERNAL const char *duk_safe_to_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
20601 	DUK_ASSERT_API_ENTRY(thr);
20602 
20603 	idx = duk_require_normalize_index(thr, idx);
20604 
20605 	/* We intentionally ignore the duk_safe_call() return value and only
20606 	 * check the output type.  This way we don't also need to check that
20607 	 * the returned value is indeed a string in the success case.
20608 	 */
20609 
20610 	duk_dup(thr, idx);
20611 	(void) duk_safe_call(thr, duk__safe_to_string_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
20612 	if (!duk_is_string(thr, -1)) {
20613 		/* Error: try coercing error to string once. */
20614 		(void) duk_safe_call(thr, duk__safe_to_string_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
20615 		if (!duk_is_string(thr, -1)) {
20616 			/* Double error */
20617 			duk_pop_unsafe(thr);
20618 			duk_push_hstring_stridx(thr, DUK_STRIDX_UC_ERROR);
20619 		} else {
20620 			;
20621 		}
20622 	} else {
20623 		/* String; may be a symbol, accepted. */
20624 		;
20625 	}
20626 	DUK_ASSERT(duk_is_string(thr, -1));
20627 
20628 	duk_replace(thr, idx);
20629 	DUK_ASSERT(duk_get_string(thr, idx) != NULL);
20630 	return duk_get_lstring(thr, idx, out_len);
20631 }
20632 
duk_to_property_key_hstring(duk_hthread * thr,duk_idx_t idx)20633 DUK_INTERNAL duk_hstring *duk_to_property_key_hstring(duk_hthread *thr, duk_idx_t idx) {
20634 	duk_hstring *h;
20635 
20636 	DUK_ASSERT_API_ENTRY(thr);
20637 
20638 	duk_to_primitive(thr, idx, DUK_HINT_STRING);  /* needed for e.g. Symbol objects */
20639 	h = duk_get_hstring(thr, idx);
20640 	if (h == NULL) {
20641 		/* The "is string?" check may seem unnecessary, but as things
20642 		 * are duk_to_hstring() invokes ToString() which fails for
20643 		 * symbols.  But since symbols are already strings for Duktape
20644 		 * C API, we check for that before doing the coercion.
20645 		 */
20646 		h = duk_to_hstring(thr, idx);
20647 	}
20648 	DUK_ASSERT(h != NULL);
20649 	return h;
20650 }
20651 
20652 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* only needed by debugger for now */
duk_safe_to_hstring(duk_hthread * thr,duk_idx_t idx)20653 DUK_INTERNAL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx) {
20654 	DUK_ASSERT_API_ENTRY(thr);
20655 
20656 	(void) duk_safe_to_string(thr, idx);
20657 	DUK_ASSERT(duk_is_string(thr, idx));
20658 	DUK_ASSERT(duk_get_hstring(thr, idx) != NULL);
20659 	return duk_known_hstring(thr, idx);
20660 }
20661 #endif
20662 
20663 /* Push Object.prototype.toString() output for 'tv'. */
20664 #if 0  /* See XXX note why this variant doesn't work. */
20665 DUK_INTERNAL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects) {
20666 	duk_uint_t stridx_bidx = 0;  /* (prototype_bidx << 16) + default_tag_stridx */
20667 
20668 	DUK_ASSERT_API_ENTRY(thr);
20669 
20670 	/* Conceptually for any non-undefined/null value we should do a
20671 	 * ToObject() coercion and look up @@toStringTag (from the object
20672 	 * prototype) to see if a custom tag should be used.  Avoid the
20673 	 * actual conversion by doing a prototype lookup without the object
20674 	 * coercion.  However, see problem below.
20675 	 */
20676 
20677 	duk_push_literal(thr, "[object ");  /* -> [ ... "[object" ] */
20678 
20679 	switch (DUK_TVAL_GET_TAG(tv)) {
20680 	case DUK_TAG_UNUSED:  /* Treat like 'undefined', shouldn't happen. */
20681 	case DUK_TAG_UNDEFINED: {
20682 		stridx_bidx = DUK_STRIDX_UC_UNDEFINED;
20683 		goto use_stridx;
20684 	}
20685 	case DUK_TAG_NULL: {
20686 		stridx_bidx = DUK_STRIDX_UC_NULL;
20687 		goto use_stridx;
20688 	}
20689 	case DUK_TAG_BOOLEAN: {
20690 		stridx_bidx = (DUK_BIDX_BOOLEAN_PROTOTYPE << 16) + DUK_STRIDX_UC_BOOLEAN;
20691 		goto use_proto_bidx;
20692 	}
20693 	case DUK_TAG_POINTER: {
20694 		stridx_bidx = (DUK_BIDX_POINTER_PROTOTYPE << 16) + DUK_STRIDX_UC_POINTER;
20695 		goto use_proto_bidx;
20696 	}
20697 	case DUK_TAG_LIGHTFUNC: {
20698 		stridx_bidx = (DUK_BIDX_FUNCTION_PROTOTYPE << 16) + DUK_STRIDX_UC_FUNCTION;
20699 		goto use_proto_bidx;
20700 	}
20701 	case DUK_TAG_STRING: {
20702 		duk_hstring *h;
20703 		h = DUK_TVAL_GET_STRING(tv);
20704 		DUK_ASSERT(h != NULL);
20705 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
20706 			/* Even without DUK_USE_SYMBOL_BUILTIN the Symbol
20707 			 * prototype exists so we can lookup @@toStringTag
20708 			 * and provide [object Symbol] for symbol values
20709 			 * created from C code.
20710 			 */
20711 			stridx_bidx = (DUK_BIDX_SYMBOL_PROTOTYPE << 16) + DUK_STRIDX_UC_SYMBOL;
20712 		} else {
20713 			stridx_bidx = (DUK_BIDX_STRING_PROTOTYPE << 16) + DUK_STRIDX_UC_STRING;
20714 		}
20715 		goto use_proto_bidx;
20716 	}
20717 	case DUK_TAG_OBJECT: {
20718 		duk_push_tval(thr, tv);
20719 		stridx_bidx = 0xffffffffUL;  /* Marker value. */
20720 		goto use_pushed_object;
20721 	}
20722 	case DUK_TAG_BUFFER: {
20723 		stridx_bidx = (DUK_BIDX_UINT8ARRAY_PROTOTYPE << 16) + DUK_STRIDX_UINT8_ARRAY;
20724 		goto use_proto_bidx;
20725 	}
20726 #if defined(DUK_USE_FASTINT)
20727 	case DUK_TAG_FASTINT:
20728 		/* Fall through to generic number case. */
20729 #endif
20730 	default: {
20731 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));  /* number (maybe fastint) */
20732 		stridx_bidx = (DUK_BIDX_NUMBER_PROTOTYPE << 16) + DUK_STRIDX_UC_NUMBER;
20733 		goto use_proto_bidx;
20734 	}
20735 	}
20736 	DUK_ASSERT(0);  /* Never here. */
20737 
20738  use_proto_bidx:
20739 	DUK_ASSERT_BIDX_VALID((stridx_bidx >> 16) & 0xffffUL);
20740 	duk_push_hobject(thr, thr->builtins[(stridx_bidx >> 16) & 0xffffUL]);
20741 	/* Fall through. */
20742 
20743  use_pushed_object:
20744 	/* [ ... "[object" obj ] */
20745 
20746 #if defined(DUK_USE_SYMBOL_BUILTIN)
20747 	/* XXX: better handling with avoid_side_effects == 1; lookup tval
20748 	 * without Proxy or getter side effects, and use it in sanitized
20749 	 * form if it's a string.
20750 	 */
20751 	if (!avoid_side_effects) {
20752 		/* XXX: The problem with using the prototype object as the
20753 		 * lookup base is that if @@toStringTag is a getter, its
20754 		 * 'this' binding must be the ToObject() coerced input value,
20755 		 * not the prototype object of the type.
20756 		 */
20757 		(void) duk_get_prop_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG);
20758 		if (duk_is_string_notsymbol(thr, -1)) {
20759 			duk_remove_m2(thr);
20760 			goto finish;
20761 		}
20762 		duk_pop_unsafe(thr);
20763 	}
20764 #endif
20765 
20766 	if (stridx_bidx == 0xffffffffUL) {
20767 		duk_hobject *h_obj;
20768 		duk_small_uint_t classnum;
20769 
20770 		h_obj = duk_known_hobject(thr, -1);
20771 		DUK_ASSERT(h_obj != NULL);
20772 		classnum = DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
20773 		stridx_bidx = DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum);
20774 	} else {
20775 		/* stridx_bidx already has the desired fallback stridx. */
20776 		;
20777 	}
20778 	duk_pop_unsafe(thr);
20779 	/* Fall through. */
20780 
20781  use_stridx:
20782 	/* [ ... "[object" ] */
20783 	duk_push_hstring_stridx(thr, stridx_bidx & 0xffffUL);
20784 
20785  finish:
20786 	/* [ ... "[object" tag ] */
20787 	duk_push_literal(thr, "]");
20788 	duk_concat(thr, 3);  /* [ ... "[object" tag "]" ] -> [ ... res ] */
20789 }
20790 #endif  /* 0 */
20791 
duk_push_class_string_tval(duk_hthread * thr,duk_tval * tv,duk_bool_t avoid_side_effects)20792 DUK_INTERNAL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects) {
20793 	duk_hobject *h_obj;
20794 	duk_small_uint_t classnum;
20795 	duk_small_uint_t stridx;
20796 	duk_tval tv_tmp;
20797 
20798 	DUK_ASSERT_API_ENTRY(thr);
20799 	DUK_ASSERT(tv != NULL);
20800 
20801 	/* Stabilize 'tv', duk_push_literal() may trigger side effects. */
20802 	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
20803 	tv = &tv_tmp;
20804 
20805 	/* Conceptually for any non-undefined/null value we should do a
20806 	 * ToObject() coercion and look up @@toStringTag (from the object
20807 	 * prototype) to see if a custom result should be used.  We'd like to
20808 	 * avoid the actual conversion, but even for primitive types the
20809 	 * prototype may have @@toStringTag.  What's worse, the @@toStringTag
20810 	 * property may be a getter that must get the object coerced value
20811 	 * (not the prototype) as its 'this' binding.
20812 	 *
20813 	 * For now, do an actual object coercion.  This could be avoided by
20814 	 * doing a side effect free lookup to see if a getter would be invoked.
20815 	 * If not, the value can be read directly and the object coercion could
20816 	 * be avoided.  This may not be worth it in practice, because
20817 	 * Object.prototype.toString() is usually not performance critical.
20818 	 */
20819 
20820 	duk_push_literal(thr, "[object ");  /* -> [ ... "[object" ] */
20821 
20822 	switch (DUK_TVAL_GET_TAG(tv)) {
20823 	case DUK_TAG_UNUSED:  /* Treat like 'undefined', shouldn't happen. */
20824 	case DUK_TAG_UNDEFINED: {
20825 		duk_push_hstring_stridx(thr, DUK_STRIDX_UC_UNDEFINED);
20826 		goto finish;
20827 	}
20828 	case DUK_TAG_NULL: {
20829 		duk_push_hstring_stridx(thr, DUK_STRIDX_UC_NULL);
20830 		goto finish;
20831 	}
20832 	}
20833 
20834 	duk_push_tval(thr, tv);
20835 	tv = NULL;  /* Invalidated by ToObject(). */
20836 	duk_to_object(thr, -1);
20837 
20838 	/* [ ... "[object" obj ] */
20839 
20840 #if defined(DUK_USE_SYMBOL_BUILTIN)
20841 	/* XXX: better handling with avoid_side_effects == 1; lookup tval
20842 	 * without Proxy or getter side effects, and use it in sanitized
20843 	 * form if it's a string.
20844 	 */
20845 	if (!avoid_side_effects) {
20846 		(void) duk_get_prop_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG);
20847 		if (duk_is_string_notsymbol(thr, -1)) {
20848 			duk_remove_m2(thr);
20849 			goto finish;
20850 		}
20851 		duk_pop_unsafe(thr);
20852 	}
20853 #else
20854 	DUK_UNREF(avoid_side_effects);
20855 #endif
20856 
20857 	h_obj = duk_known_hobject(thr, -1);
20858 	DUK_ASSERT(h_obj != NULL);
20859 	classnum = DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
20860 	stridx = DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum);
20861 	duk_pop_unsafe(thr);
20862 	duk_push_hstring_stridx(thr, stridx);
20863 
20864  finish:
20865 	/* [ ... "[object" tag ] */
20866 	duk_push_literal(thr, "]");
20867 	duk_concat(thr, 3);  /* [ ... "[object" tag "]" ] -> [ ... res ] */
20868 }
20869 
20870 /* 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)20871 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) {
20872 	duk_tval *tv;
20873 	duk_tval tv_tmp;
20874 	duk_double_t d, dmin, dmax;
20875 	duk_int_t res;
20876 	duk_bool_t clamped = 0;
20877 
20878 	DUK_ASSERT_API_ENTRY(thr);
20879 
20880 	tv = duk_require_tval(thr, idx);
20881 	DUK_ASSERT(tv != NULL);
20882 	d = duk_js_tointeger(thr, tv);  /* E5 Section 9.4, ToInteger() */
20883 
20884 	dmin = (duk_double_t) minval;
20885 	dmax = (duk_double_t) maxval;
20886 
20887 	if (d < dmin) {
20888 		clamped = 1;
20889 		res = minval;
20890 		d = dmin;
20891 	} else if (d > dmax) {
20892 		clamped = 1;
20893 		res = maxval;
20894 		d = dmax;
20895 	} else {
20896 		res = (duk_int_t) d;
20897 	}
20898 	DUK_UNREF(d);  /* SCANBUILD: with suitable dmin/dmax limits 'd' is unused */
20899 	/* 'd' and 'res' agree here */
20900 
20901 	/* Relookup in case duk_js_tointeger() ends up e.g. coercing an object. */
20902 	tv = duk_get_tval(thr, idx);
20903 	DUK_ASSERT(tv != NULL);  /* not popped by side effect */
20904 	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
20905 #if defined(DUK_USE_FASTINT)
20906 #if (DUK_INT_MAX <= 0x7fffffffL)
20907 	DUK_TVAL_SET_I32(tv, res);
20908 #else
20909 	/* Clamping needed if duk_int_t is 64 bits. */
20910 	if (res >= DUK_FASTINT_MIN && res <= DUK_FASTINT_MAX) {
20911 		DUK_TVAL_SET_FASTINT(tv, res);
20912 	} else {
20913 		DUK_TVAL_SET_NUMBER(tv, d);
20914 	}
20915 #endif
20916 #else
20917 	DUK_TVAL_SET_NUMBER(tv, d);  /* no need to incref */
20918 #endif
20919 	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
20920 
20921 	if (out_clamped) {
20922 		*out_clamped = clamped;
20923 	} else {
20924 		/* coerced value is updated to value stack even when RangeError thrown */
20925 		if (clamped) {
20926 			DUK_ERROR_RANGE(thr, DUK_STR_NUMBER_OUTSIDE_RANGE);
20927 			DUK_WO_NORETURN(return 0;);
20928 		}
20929 	}
20930 
20931 	return res;
20932 }
20933 
duk_to_int_clamped(duk_hthread * thr,duk_idx_t idx,duk_idx_t minval,duk_idx_t maxval)20934 DUK_INTERNAL duk_int_t duk_to_int_clamped(duk_hthread *thr, duk_idx_t idx, duk_idx_t minval, duk_idx_t maxval) {
20935 	duk_bool_t dummy;
20936 
20937 	DUK_ASSERT_API_ENTRY(thr);
20938 
20939 	return duk_to_int_clamped_raw(thr, idx, minval, maxval, &dummy);
20940 }
20941 
duk_to_int_check_range(duk_hthread * thr,duk_idx_t idx,duk_int_t minval,duk_int_t maxval)20942 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) {
20943 	DUK_ASSERT_API_ENTRY(thr);
20944 	return duk_to_int_clamped_raw(thr, idx, minval, maxval, NULL);  /* out_clamped==NULL -> RangeError if outside range */
20945 }
20946 
duk_to_string(duk_hthread * thr,duk_idx_t idx)20947 DUK_EXTERNAL const char *duk_to_string(duk_hthread *thr, duk_idx_t idx) {
20948 	duk_tval *tv;
20949 
20950 	DUK_ASSERT_API_ENTRY(thr);
20951 
20952 	idx = duk_require_normalize_index(thr, idx);
20953 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
20954 	DUK_ASSERT(tv != NULL);
20955 
20956 	switch (DUK_TVAL_GET_TAG(tv)) {
20957 	case DUK_TAG_UNDEFINED: {
20958 		duk_push_hstring_stridx(thr, DUK_STRIDX_LC_UNDEFINED);
20959 		break;
20960 	}
20961 	case DUK_TAG_NULL: {
20962 		duk_push_hstring_stridx(thr, DUK_STRIDX_LC_NULL);
20963 		break;
20964 	}
20965 	case DUK_TAG_BOOLEAN: {
20966 		if (DUK_TVAL_GET_BOOLEAN(tv)) {
20967 			duk_push_hstring_stridx(thr, DUK_STRIDX_TRUE);
20968 		} else {
20969 			duk_push_hstring_stridx(thr, DUK_STRIDX_FALSE);
20970 		}
20971 		break;
20972 	}
20973 	case DUK_TAG_STRING: {
20974 		/* Nop for actual strings, TypeError for Symbols.
20975 		 * Because various internals rely on ToString() coercion of
20976 		 * internal strings, -allow- (NOP) string coercion for hidden
20977 		 * symbols.
20978 		 */
20979 #if 1
20980 		duk_hstring *h;
20981 		h = DUK_TVAL_GET_STRING(tv);
20982 		DUK_ASSERT(h != NULL);
20983 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
20984 			DUK_ERROR_TYPE(thr, DUK_STR_CANNOT_STRING_COERCE_SYMBOL);
20985 			DUK_WO_NORETURN(goto skip_replace;);
20986 		} else {
20987 			goto skip_replace;
20988 		}
20989 #else
20990 		goto skip_replace;
20991 #endif
20992 		break;
20993 	}
20994 	case DUK_TAG_BUFFER: /* Go through Uint8Array.prototype.toString() for coercion. */
20995 	case DUK_TAG_OBJECT: {
20996 		/* Plain buffers: go through ArrayBuffer.prototype.toString()
20997 		 * for coercion.
20998 		 *
20999 		 * Symbol objects: duk_to_primitive() results in a plain symbol
21000 		 * value, and duk_to_string() then causes a TypeError.
21001 		 */
21002 		duk_to_primitive(thr, idx, DUK_HINT_STRING);
21003 		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* ToPrimitive() must guarantee */
21004 		DUK_ASSERT(!duk_is_object(thr, idx));
21005 		return duk_to_string(thr, idx);  /* Note: recursive call */
21006 	}
21007 	case DUK_TAG_POINTER: {
21008 		void *ptr = DUK_TVAL_GET_POINTER(tv);
21009 		if (ptr != NULL) {
21010 			duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) ptr);
21011 		} else {
21012 			/* Represent a null pointer as 'null' to be consistent with
21013 			 * the JX format variant.  Native '%p' format for a NULL
21014 			 * pointer may be e.g. '(nil)'.
21015 			 */
21016 			duk_push_hstring_stridx(thr, DUK_STRIDX_LC_NULL);
21017 		}
21018 		break;
21019 	}
21020 	case DUK_TAG_LIGHTFUNC: {
21021 		/* Should match Function.prototype.toString() */
21022 		duk_push_lightfunc_tostring(thr, tv);
21023 		break;
21024 	}
21025 #if defined(DUK_USE_FASTINT)
21026 	case DUK_TAG_FASTINT:
21027 #endif
21028 	default: {
21029 		/* number */
21030 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21031 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21032 		duk_push_tval(thr, tv);
21033 		duk_numconv_stringify(thr,
21034 		                      10 /*radix*/,
21035 		                      0 /*precision:shortest*/,
21036 		                      0 /*force_exponential*/);
21037 		break;
21038 	}
21039 	}
21040 
21041 	duk_replace(thr, idx);
21042 
21043  skip_replace:
21044 	DUK_ASSERT(duk_is_string(thr, idx));
21045 	return duk_require_string(thr, idx);
21046 }
21047 
duk_to_hstring(duk_hthread * thr,duk_idx_t idx)21048 DUK_INTERNAL duk_hstring *duk_to_hstring(duk_hthread *thr, duk_idx_t idx) {
21049 	duk_hstring *ret;
21050 
21051 	DUK_ASSERT_API_ENTRY(thr);
21052 
21053 	duk_to_string(thr, idx);
21054 	ret = duk_get_hstring(thr, idx);
21055 	DUK_ASSERT(ret != NULL);
21056 	return ret;
21057 }
21058 
duk_to_hstring_m1(duk_hthread * thr)21059 DUK_INTERNAL duk_hstring *duk_to_hstring_m1(duk_hthread *thr) {
21060 	DUK_ASSERT_API_ENTRY(thr);
21061 	return duk_to_hstring(thr, -1);
21062 }
21063 
duk_to_hstring_acceptsymbol(duk_hthread * thr,duk_idx_t idx)21064 DUK_INTERNAL duk_hstring *duk_to_hstring_acceptsymbol(duk_hthread *thr, duk_idx_t idx) {
21065 	duk_hstring *ret;
21066 
21067 	DUK_ASSERT_API_ENTRY(thr);
21068 
21069 	ret = duk_get_hstring(thr, idx);
21070 	if (DUK_UNLIKELY(ret && DUK_HSTRING_HAS_SYMBOL(ret))) {
21071 		return ret;
21072 	}
21073 	return duk_to_hstring(thr, idx);
21074 }
21075 
21076 /* Convert a plain buffer or any buffer object into a string, using the buffer
21077  * bytes 1:1 in the internal string representation.  For views the active byte
21078  * slice (not element slice interpreted as an initializer) is used.  This is
21079  * necessary in Duktape 2.x because ToString(plainBuffer) no longer creates a
21080  * string with the same bytes as in the buffer but rather (usually)
21081  * '[object ArrayBuffer]'.
21082  */
duk_buffer_to_string(duk_hthread * thr,duk_idx_t idx)21083 DUK_EXTERNAL const char *duk_buffer_to_string(duk_hthread *thr, duk_idx_t idx) {
21084 	void *ptr_src;
21085 	duk_size_t len;
21086 	const char *res;
21087 
21088 	DUK_ASSERT_API_ENTRY(thr);
21089 
21090 	idx = duk_require_normalize_index(thr, idx);
21091 
21092 	ptr_src = duk_require_buffer_data(thr, idx, &len);
21093 	DUK_ASSERT(ptr_src != NULL || len == 0);
21094 
21095 	res = duk_push_lstring(thr, (const char *) ptr_src, len);
21096 	duk_replace(thr, idx);
21097 	return res;
21098 }
21099 
duk_to_buffer_raw(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,duk_uint_t mode)21100 DUK_EXTERNAL void *duk_to_buffer_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, duk_uint_t mode) {
21101 	duk_hbuffer *h_buf;
21102 	const duk_uint8_t *src_data;
21103 	duk_size_t src_size;
21104 	duk_uint8_t *dst_data;
21105 
21106 	DUK_ASSERT_API_ENTRY(thr);
21107 
21108 	idx = duk_require_normalize_index(thr, idx);
21109 
21110 	h_buf = duk_get_hbuffer(thr, idx);
21111 	if (h_buf != NULL) {
21112 		/* Buffer is kept as is, with the fixed/dynamic nature of the
21113 		 * buffer only changed if requested.  An external buffer
21114 		 * is converted into a non-external dynamic buffer in a
21115 		 * duk_to_dynamic_buffer() call.
21116 		 */
21117 		duk_uint_t tmp;
21118 		duk_uint8_t *tmp_ptr;
21119 
21120 		tmp_ptr = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf);
21121 		src_data = (const duk_uint8_t *) tmp_ptr;
21122 		src_size = DUK_HBUFFER_GET_SIZE(h_buf);
21123 
21124 		tmp = (DUK_HBUFFER_HAS_DYNAMIC(h_buf) ? DUK_BUF_MODE_DYNAMIC : DUK_BUF_MODE_FIXED);
21125 		if ((tmp == mode && !DUK_HBUFFER_HAS_EXTERNAL(h_buf)) ||
21126 		    mode == DUK_BUF_MODE_DONTCARE) {
21127 			/* Note: src_data may be NULL if input is a zero-size
21128 			 * dynamic buffer.
21129 			 */
21130 			dst_data = tmp_ptr;
21131 			goto skip_copy;
21132 		}
21133 	} else {
21134 		/* Non-buffer value is first ToString() coerced, then converted
21135 		 * to a buffer (fixed buffer is used unless a dynamic buffer is
21136 		 * explicitly requested).  Symbols are rejected with a TypeError.
21137 		 * XXX: C API could maybe allow symbol-to-buffer coercion?
21138 		 */
21139 		src_data = (const duk_uint8_t *) duk_to_lstring(thr, idx, &src_size);
21140 	}
21141 
21142 	dst_data = (duk_uint8_t *) duk_push_buffer(thr, src_size, (mode == DUK_BUF_MODE_DYNAMIC) /*dynamic*/);
21143 	/* dst_data may be NULL if size is zero. */
21144 	duk_memcpy_unsafe((void *) dst_data, (const void *) src_data, (size_t) src_size);
21145 
21146 	duk_replace(thr, idx);
21147  skip_copy:
21148 
21149 	if (out_size) {
21150 		*out_size = src_size;
21151 	}
21152 	return dst_data;
21153 }
21154 
duk_to_pointer(duk_hthread * thr,duk_idx_t idx)21155 DUK_EXTERNAL void *duk_to_pointer(duk_hthread *thr, duk_idx_t idx) {
21156 	duk_tval *tv;
21157 	void *res;
21158 
21159 	DUK_ASSERT_API_ENTRY(thr);
21160 
21161 	idx = duk_require_normalize_index(thr, idx);
21162 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
21163 	DUK_ASSERT(tv != NULL);
21164 
21165 	switch (DUK_TVAL_GET_TAG(tv)) {
21166 	case DUK_TAG_UNDEFINED:
21167 	case DUK_TAG_NULL:
21168 	case DUK_TAG_BOOLEAN:
21169 		res = NULL;
21170 		break;
21171 	case DUK_TAG_POINTER:
21172 		res = DUK_TVAL_GET_POINTER(tv);
21173 		break;
21174 	case DUK_TAG_STRING:
21175 	case DUK_TAG_OBJECT:
21176 	case DUK_TAG_BUFFER:
21177 		/* Heap allocated: return heap pointer which is NOT useful
21178 		 * for the caller, except for debugging.
21179 		 */
21180 		res = (void *) DUK_TVAL_GET_HEAPHDR(tv);
21181 		break;
21182 	case DUK_TAG_LIGHTFUNC:
21183 		/* Function pointers do not always cast correctly to void *
21184 		 * (depends on memory and segmentation model for instance),
21185 		 * so they coerce to NULL.
21186 		 */
21187 		res = NULL;
21188 		break;
21189 #if defined(DUK_USE_FASTINT)
21190 	case DUK_TAG_FASTINT:
21191 #endif
21192 	default:
21193 		/* number */
21194 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21195 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21196 		res = NULL;
21197 		break;
21198 	}
21199 
21200 	duk_push_pointer(thr, res);
21201 	duk_replace(thr, idx);
21202 	return res;
21203 }
21204 
duk__push_func_from_lightfunc(duk_hthread * thr,duk_c_function func,duk_small_uint_t lf_flags)21205 DUK_LOCAL void duk__push_func_from_lightfunc(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags) {
21206 	duk_idx_t nargs;
21207 	duk_uint_t flags = 0;   /* shared flags for a subset of types */
21208 	duk_small_uint_t lf_len;
21209 	duk_hnatfunc *nf;
21210 
21211 	nargs = (duk_idx_t) DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
21212 	if (nargs == DUK_LFUNC_NARGS_VARARGS) {
21213 		nargs = (duk_idx_t) DUK_VARARGS;
21214 	}
21215 
21216 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21217 	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
21218 	        DUK_HOBJECT_FLAG_CALLABLE |
21219 	        DUK_HOBJECT_FLAG_FASTREFS |
21220 	        DUK_HOBJECT_FLAG_NATFUNC |
21221 	        DUK_HOBJECT_FLAG_NEWENV |
21222 	        DUK_HOBJECT_FLAG_STRICT |
21223 	        DUK_HOBJECT_FLAG_NOTAIL |
21224 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
21225 	(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE);
21226 
21227 	lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
21228 	if ((duk_idx_t) lf_len != nargs) {
21229 		/* Explicit length is only needed if it differs from 'nargs'. */
21230 		duk_push_int(thr, (duk_int_t) lf_len);
21231 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);
21232 	}
21233 
21234 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
21235 	duk_push_lightfunc_name_raw(thr, func, lf_flags);
21236 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
21237 #endif
21238 
21239 	nf = duk_known_hnatfunc(thr, -1);
21240 	nf->magic = (duk_int16_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
21241 }
21242 
duk_to_object(duk_hthread * thr,duk_idx_t idx)21243 DUK_EXTERNAL void duk_to_object(duk_hthread *thr, duk_idx_t idx) {
21244 	duk_tval *tv;
21245 	duk_uint_t flags = 0;   /* shared flags for a subset of types */
21246 	duk_small_int_t proto = 0;
21247 
21248 	DUK_ASSERT_API_ENTRY(thr);
21249 
21250 	idx = duk_require_normalize_index(thr, idx);
21251 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
21252 	DUK_ASSERT(tv != NULL);
21253 
21254 	switch (DUK_TVAL_GET_TAG(tv)) {
21255 #if !defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21256 	case DUK_TAG_BUFFER:  /* With no bufferobject support, don't object coerce. */
21257 #endif
21258 	case DUK_TAG_UNDEFINED:
21259 	case DUK_TAG_NULL: {
21260 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE);
21261 		DUK_WO_NORETURN(return;);
21262 		break;
21263 	}
21264 	case DUK_TAG_BOOLEAN: {
21265 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21266 		        DUK_HOBJECT_FLAG_FASTREFS |
21267 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BOOLEAN);
21268 		proto = DUK_BIDX_BOOLEAN_PROTOTYPE;
21269 		goto create_object;
21270 	}
21271 	case DUK_TAG_STRING: {
21272 		duk_hstring *h;
21273 		h = DUK_TVAL_GET_STRING(tv);
21274 		DUK_ASSERT(h != NULL);
21275 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
21276 			flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21277 			        DUK_HOBJECT_FLAG_FASTREFS |
21278 			        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_SYMBOL);
21279 			proto = DUK_BIDX_SYMBOL_PROTOTYPE;
21280 		} else {
21281 			flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21282 			        DUK_HOBJECT_FLAG_FASTREFS |
21283 			        DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
21284 			        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);
21285 			proto = DUK_BIDX_STRING_PROTOTYPE;
21286 		}
21287 		goto create_object;
21288 	}
21289 	case DUK_TAG_OBJECT: {
21290 		/* nop */
21291 		break;
21292 	}
21293 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21294 	case DUK_TAG_BUFFER: {
21295 		/* A plain buffer object coerces to a full ArrayBuffer which
21296 		 * is not fully transparent behavior (ToObject() should be a
21297 		 * nop for an object).  This behavior matches lightfuncs which
21298 		 * also coerce to an equivalent Function object.  There are
21299 		 * also downsides to defining ToObject(plainBuffer) as a no-op;
21300 		 * for example duk_to_hobject() could result in a NULL pointer.
21301 		 */
21302 		duk_hbuffer *h_buf;
21303 
21304 		h_buf = DUK_TVAL_GET_BUFFER(tv);
21305 		DUK_ASSERT(h_buf != NULL);
21306 		duk_hbufobj_push_uint8array_from_plain(thr, h_buf);
21307 		goto replace_value;
21308 	}
21309 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
21310 	case DUK_TAG_POINTER: {
21311 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21312 		        DUK_HOBJECT_FLAG_FASTREFS |
21313 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER);
21314 		proto = DUK_BIDX_POINTER_PROTOTYPE;
21315 		goto create_object;
21316 	}
21317 	case DUK_TAG_LIGHTFUNC: {
21318 		/* Lightfunc coerces to a Function instance with concrete
21319 		 * properties.  Since 'length' is virtual for Duktape/C
21320 		 * functions, don't need to define that.  The result is made
21321 		 * extensible to mimic what happens to strings in object
21322 		 * coercion:
21323 		 *
21324 		 *   > Object.isExtensible(Object('foo'))
21325 		 *   true
21326 		 */
21327 		duk_small_uint_t lf_flags;
21328 		duk_c_function func;
21329 
21330 		DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
21331 		duk__push_func_from_lightfunc(thr, func, lf_flags);
21332 		goto replace_value;
21333 	}
21334 #if defined(DUK_USE_FASTINT)
21335 	case DUK_TAG_FASTINT:
21336 #endif
21337 	default: {
21338 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21339 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21340 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21341 		        DUK_HOBJECT_FLAG_FASTREFS |
21342 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_NUMBER);
21343 		proto = DUK_BIDX_NUMBER_PROTOTYPE;
21344 		goto create_object;
21345 	}
21346 	}
21347 	DUK_ASSERT(duk_is_object(thr, idx));
21348 	return;
21349 
21350  create_object:
21351 	(void) duk_push_object_helper(thr, flags, proto);
21352 
21353 	/* Note: Boolean prototype's internal value property is not writable,
21354 	 * but duk_xdef_prop_stridx() disregards the write protection.  Boolean
21355 	 * instances are immutable.
21356 	 *
21357 	 * String and buffer special behaviors are already enabled which is not
21358 	 * ideal, but a write to the internal value is not affected by them.
21359 	 */
21360 	duk_dup(thr, idx);
21361 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
21362 
21363  replace_value:
21364 	duk_replace(thr, idx);
21365 	DUK_ASSERT(duk_is_object(thr, idx));
21366 }
21367 
duk_to_hobject(duk_hthread * thr,duk_idx_t idx)21368 DUK_INTERNAL duk_hobject *duk_to_hobject(duk_hthread *thr, duk_idx_t idx) {
21369 	duk_hobject *ret;
21370 
21371 	DUK_ASSERT_API_ENTRY(thr);
21372 
21373 	duk_to_object(thr, idx);
21374 	ret = duk_known_hobject(thr, idx);
21375 	return ret;
21376 }
21377 
21378 /*
21379  *  Type checking
21380  */
21381 
duk__tag_check(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t tag)21382 DUK_LOCAL duk_bool_t duk__tag_check(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t tag) {
21383 	duk_tval *tv;
21384 
21385 	tv = duk_get_tval_or_unused(thr, idx);
21386 	DUK_ASSERT(tv != NULL);
21387 	return (DUK_TVAL_GET_TAG(tv) == tag);
21388 }
21389 
duk__obj_flag_any_default_false(duk_hthread * thr,duk_idx_t idx,duk_uint_t flag_mask)21390 DUK_LOCAL duk_bool_t duk__obj_flag_any_default_false(duk_hthread *thr, duk_idx_t idx, duk_uint_t flag_mask) {
21391 	duk_hobject *obj;
21392 
21393 	DUK_ASSERT_API_ENTRY(thr);
21394 
21395 	obj = duk_get_hobject(thr, idx);
21396 	if (obj) {
21397 		return (DUK_HEAPHDR_CHECK_FLAG_BITS((duk_heaphdr *) obj, flag_mask) ? 1 : 0);
21398 	}
21399 	return 0;
21400 }
21401 
duk_get_type_tval(duk_tval * tv)21402 DUK_INTERNAL duk_int_t duk_get_type_tval(duk_tval *tv) {
21403 	DUK_ASSERT(tv != NULL);
21404 
21405 #if defined(DUK_USE_PACKED_TVAL)
21406 	switch (DUK_TVAL_GET_TAG(tv)) {
21407 	case DUK_TAG_UNUSED:
21408 		return DUK_TYPE_NONE;
21409 	case DUK_TAG_UNDEFINED:
21410 		return DUK_TYPE_UNDEFINED;
21411 	case DUK_TAG_NULL:
21412 		return DUK_TYPE_NULL;
21413 	case DUK_TAG_BOOLEAN:
21414 		return DUK_TYPE_BOOLEAN;
21415 	case DUK_TAG_STRING:
21416 		return DUK_TYPE_STRING;
21417 	case DUK_TAG_OBJECT:
21418 		return DUK_TYPE_OBJECT;
21419 	case DUK_TAG_BUFFER:
21420 		return DUK_TYPE_BUFFER;
21421 	case DUK_TAG_POINTER:
21422 		return DUK_TYPE_POINTER;
21423 	case DUK_TAG_LIGHTFUNC:
21424 		return DUK_TYPE_LIGHTFUNC;
21425 #if defined(DUK_USE_FASTINT)
21426 	case DUK_TAG_FASTINT:
21427 #endif
21428 	default:
21429 		/* Note: number has no explicit tag (in 8-byte representation) */
21430 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21431 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21432 		return DUK_TYPE_NUMBER;
21433 	}
21434 #else  /* DUK_USE_PACKED_TVAL */
21435 	DUK_ASSERT(DUK_TVAL_IS_VALID_TAG(tv));
21436 	DUK_ASSERT(sizeof(duk__type_from_tag) / sizeof(duk_uint_t) == DUK_TAG_MAX - DUK_TAG_MIN + 1);
21437 	return (duk_int_t) duk__type_from_tag[DUK_TVAL_GET_TAG(tv) - DUK_TAG_MIN];
21438 #endif  /* DUK_USE_PACKED_TVAL */
21439 }
21440 
duk_get_type(duk_hthread * thr,duk_idx_t idx)21441 DUK_EXTERNAL duk_int_t duk_get_type(duk_hthread *thr, duk_idx_t idx) {
21442 	duk_tval *tv;
21443 
21444 	DUK_ASSERT_API_ENTRY(thr);
21445 
21446 	tv = duk_get_tval_or_unused(thr, idx);
21447 	DUK_ASSERT(tv != NULL);
21448 
21449 	return duk_get_type_tval(tv);
21450 }
21451 
21452 #if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
21453 DUK_LOCAL const char * const duk__type_names[] = {
21454 	"none",
21455 	"undefined",
21456 	"null",
21457 	"boolean",
21458 	"number",
21459 	"string",
21460 	"object",
21461 	"buffer",
21462 	"pointer",
21463 	"lightfunc"
21464 };
21465 
duk_get_type_name(duk_hthread * thr,duk_idx_t idx)21466 DUK_INTERNAL const char *duk_get_type_name(duk_hthread *thr, duk_idx_t idx) {
21467 	duk_int_t type_tag;
21468 
21469 	DUK_ASSERT_API_ENTRY(thr);
21470 
21471 	type_tag = duk_get_type(thr, idx);
21472 	DUK_ASSERT(type_tag >= DUK_TYPE_MIN && type_tag <= DUK_TYPE_MAX);
21473 	DUK_ASSERT(DUK_TYPE_MIN == 0 && sizeof(duk__type_names) / sizeof(const char *) == DUK_TYPE_MAX + 1);
21474 
21475 	return duk__type_names[type_tag];
21476 }
21477 #endif  /* DUK_USE_VERBOSE_ERRORS && DUK_USE_PARANOID_ERRORS */
21478 
duk_get_class_number(duk_hthread * thr,duk_idx_t idx)21479 DUK_INTERNAL duk_small_uint_t duk_get_class_number(duk_hthread *thr, duk_idx_t idx) {
21480 	duk_tval *tv;
21481 	duk_hobject *obj;
21482 
21483 	DUK_ASSERT_API_ENTRY(thr);
21484 
21485 	tv = duk_get_tval_or_unused(thr, idx);
21486 	DUK_ASSERT(tv != NULL);
21487 
21488 	switch (DUK_TVAL_GET_TAG(tv)) {
21489 	case DUK_TAG_OBJECT:
21490 		obj = DUK_TVAL_GET_OBJECT(tv);
21491 		DUK_ASSERT(obj != NULL);
21492 		return DUK_HOBJECT_GET_CLASS_NUMBER(obj);
21493 	case DUK_TAG_BUFFER:
21494 		/* Buffers behave like Uint8Array objects. */
21495 		return DUK_HOBJECT_CLASS_UINT8ARRAY;
21496 	case DUK_TAG_LIGHTFUNC:
21497 		/* Lightfuncs behave like Function objects. */
21498 		return DUK_HOBJECT_CLASS_FUNCTION;
21499 	default:
21500 		/* Primitive or UNUSED, no class number. */
21501 		return DUK_HOBJECT_CLASS_NONE;
21502 	}
21503 }
21504 
duk_check_type(duk_hthread * thr,duk_idx_t idx,duk_int_t type)21505 DUK_EXTERNAL duk_bool_t duk_check_type(duk_hthread *thr, duk_idx_t idx, duk_int_t type) {
21506 	DUK_ASSERT_API_ENTRY(thr);
21507 
21508 	return (duk_get_type(thr, idx) == type) ? 1 : 0;
21509 }
21510 
duk_get_type_mask_tval(duk_tval * tv)21511 DUK_INTERNAL duk_uint_t duk_get_type_mask_tval(duk_tval *tv) {
21512 	DUK_ASSERT(tv != NULL);
21513 
21514 #if defined(DUK_USE_PACKED_TVAL)
21515 	switch (DUK_TVAL_GET_TAG(tv)) {
21516 	case DUK_TAG_UNUSED:
21517 		return DUK_TYPE_MASK_NONE;
21518 	case DUK_TAG_UNDEFINED:
21519 		return DUK_TYPE_MASK_UNDEFINED;
21520 	case DUK_TAG_NULL:
21521 		return DUK_TYPE_MASK_NULL;
21522 	case DUK_TAG_BOOLEAN:
21523 		return DUK_TYPE_MASK_BOOLEAN;
21524 	case DUK_TAG_STRING:
21525 		return DUK_TYPE_MASK_STRING;
21526 	case DUK_TAG_OBJECT:
21527 		return DUK_TYPE_MASK_OBJECT;
21528 	case DUK_TAG_BUFFER:
21529 		return DUK_TYPE_MASK_BUFFER;
21530 	case DUK_TAG_POINTER:
21531 		return DUK_TYPE_MASK_POINTER;
21532 	case DUK_TAG_LIGHTFUNC:
21533 		return DUK_TYPE_MASK_LIGHTFUNC;
21534 #if defined(DUK_USE_FASTINT)
21535 	case DUK_TAG_FASTINT:
21536 #endif
21537 	default:
21538 		/* Note: number has no explicit tag (in 8-byte representation) */
21539 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21540 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21541 		return DUK_TYPE_MASK_NUMBER;
21542 	}
21543 #else  /* DUK_USE_PACKED_TVAL */
21544 	DUK_ASSERT(DUK_TVAL_IS_VALID_TAG(tv));
21545 	DUK_ASSERT(sizeof(duk__type_mask_from_tag) / sizeof(duk_uint_t) == DUK_TAG_MAX - DUK_TAG_MIN + 1);
21546 	return duk__type_mask_from_tag[DUK_TVAL_GET_TAG(tv) - DUK_TAG_MIN];
21547 #endif  /* DUK_USE_PACKED_TVAL */
21548 }
21549 
duk_get_type_mask(duk_hthread * thr,duk_idx_t idx)21550 DUK_EXTERNAL duk_uint_t duk_get_type_mask(duk_hthread *thr, duk_idx_t idx) {
21551 	duk_tval *tv;
21552 
21553 	DUK_ASSERT_API_ENTRY(thr);
21554 
21555 	tv = duk_get_tval_or_unused(thr, idx);
21556 	DUK_ASSERT(tv != NULL);
21557 
21558 	return duk_get_type_mask_tval(tv);
21559 }
21560 
duk_check_type_mask(duk_hthread * thr,duk_idx_t idx,duk_uint_t mask)21561 DUK_EXTERNAL duk_bool_t duk_check_type_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t mask) {
21562 	DUK_ASSERT_API_ENTRY(thr);
21563 
21564 	if (DUK_LIKELY((duk_get_type_mask(thr, idx) & mask) != 0U)) {
21565 		return 1;
21566 	}
21567 	if (mask & DUK_TYPE_MASK_THROW) {
21568 		DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);
21569 		DUK_WO_NORETURN(return 0;);
21570 	}
21571 	return 0;
21572 }
21573 
duk_is_undefined(duk_hthread * thr,duk_idx_t idx)21574 DUK_EXTERNAL duk_bool_t duk_is_undefined(duk_hthread *thr, duk_idx_t idx) {
21575 	DUK_ASSERT_API_ENTRY(thr);
21576 	return duk__tag_check(thr, idx, DUK_TAG_UNDEFINED);
21577 }
21578 
duk_is_null(duk_hthread * thr,duk_idx_t idx)21579 DUK_EXTERNAL duk_bool_t duk_is_null(duk_hthread *thr, duk_idx_t idx) {
21580 	DUK_ASSERT_API_ENTRY(thr);
21581 	return duk__tag_check(thr, idx, DUK_TAG_NULL);
21582 }
21583 
duk_is_boolean(duk_hthread * thr,duk_idx_t idx)21584 DUK_EXTERNAL duk_bool_t duk_is_boolean(duk_hthread *thr, duk_idx_t idx) {
21585 	DUK_ASSERT_API_ENTRY(thr);
21586 	return duk__tag_check(thr, idx, DUK_TAG_BOOLEAN);
21587 }
21588 
duk_is_number(duk_hthread * thr,duk_idx_t idx)21589 DUK_EXTERNAL duk_bool_t duk_is_number(duk_hthread *thr, duk_idx_t idx) {
21590 	duk_tval *tv;
21591 
21592 	DUK_ASSERT_API_ENTRY(thr);
21593 
21594 	/*
21595 	 *  Number is special because it doesn't have a specific
21596 	 *  tag in the 8-byte representation.
21597 	 */
21598 
21599 	/* XXX: shorter version for unpacked representation? */
21600 
21601 	tv = duk_get_tval_or_unused(thr, idx);
21602 	DUK_ASSERT(tv != NULL);
21603 	return DUK_TVAL_IS_NUMBER(tv);
21604 }
21605 
duk_is_nan(duk_hthread * thr,duk_idx_t idx)21606 DUK_EXTERNAL duk_bool_t duk_is_nan(duk_hthread *thr, duk_idx_t idx) {
21607 	/* XXX: This will now return false for non-numbers, even though they would
21608 	 * coerce to NaN (as a general rule).  In particular, duk_get_number()
21609 	 * returns a NaN for non-numbers, so should this function also return
21610 	 * true for non-numbers?
21611 	 */
21612 
21613 	duk_tval *tv;
21614 
21615 	DUK_ASSERT_API_ENTRY(thr);
21616 
21617 	tv = duk_get_tval_or_unused(thr, idx);
21618 	DUK_ASSERT(tv != NULL);
21619 
21620 	/* XXX: for packed duk_tval an explicit "is number" check is unnecessary */
21621 	if (!DUK_TVAL_IS_NUMBER(tv)) {
21622 		return 0;
21623 	}
21624 	return (duk_bool_t) DUK_ISNAN(DUK_TVAL_GET_NUMBER(tv));
21625 }
21626 
duk_is_string(duk_hthread * thr,duk_idx_t idx)21627 DUK_EXTERNAL duk_bool_t duk_is_string(duk_hthread *thr, duk_idx_t idx) {
21628 	DUK_ASSERT_API_ENTRY(thr);
21629 	return duk__tag_check(thr, idx, DUK_TAG_STRING);
21630 }
21631 
duk_is_string_notsymbol(duk_hthread * thr,duk_idx_t idx)21632 DUK_INTERNAL duk_bool_t duk_is_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {
21633 	DUK_ASSERT_API_ENTRY(thr);
21634 	return duk_get_hstring_notsymbol(thr, idx) != NULL;
21635 }
21636 
duk_is_object(duk_hthread * thr,duk_idx_t idx)21637 DUK_EXTERNAL duk_bool_t duk_is_object(duk_hthread *thr, duk_idx_t idx) {
21638 	DUK_ASSERT_API_ENTRY(thr);
21639 	return duk__tag_check(thr, idx, DUK_TAG_OBJECT);
21640 }
21641 
duk_is_buffer(duk_hthread * thr,duk_idx_t idx)21642 DUK_EXTERNAL duk_bool_t duk_is_buffer(duk_hthread *thr, duk_idx_t idx) {
21643 	DUK_ASSERT_API_ENTRY(thr);
21644 	return duk__tag_check(thr, idx, DUK_TAG_BUFFER);
21645 }
21646 
21647 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_is_buffer_data(duk_hthread * thr,duk_idx_t idx)21648 DUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_hthread *thr, duk_idx_t idx) {
21649 	duk_tval *tv;
21650 
21651 	DUK_ASSERT_API_ENTRY(thr);
21652 
21653 	tv = duk_get_tval_or_unused(thr, idx);
21654 	DUK_ASSERT(tv != NULL);
21655 	if (DUK_TVAL_IS_BUFFER(tv)) {
21656 		return 1;
21657 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
21658 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
21659 		DUK_ASSERT(h != NULL);
21660 		if (DUK_HOBJECT_IS_BUFOBJ(h)) {
21661 			return 1;
21662 		}
21663 	}
21664 	return 0;
21665 }
21666 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_is_buffer_data(duk_hthread * thr,duk_idx_t idx)21667 DUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_hthread *thr, duk_idx_t idx) {
21668 	DUK_ASSERT_API_ENTRY(thr);
21669 
21670 	return duk_is_buffer(thr, idx);
21671 }
21672 
21673 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
21674 
duk_is_pointer(duk_hthread * thr,duk_idx_t idx)21675 DUK_EXTERNAL duk_bool_t duk_is_pointer(duk_hthread *thr, duk_idx_t idx) {
21676 	DUK_ASSERT_API_ENTRY(thr);
21677 	return duk__tag_check(thr, idx, DUK_TAG_POINTER);
21678 }
21679 
duk_is_lightfunc(duk_hthread * thr,duk_idx_t idx)21680 DUK_EXTERNAL duk_bool_t duk_is_lightfunc(duk_hthread *thr, duk_idx_t idx) {
21681 	DUK_ASSERT_API_ENTRY(thr);
21682 	return duk__tag_check(thr, idx, DUK_TAG_LIGHTFUNC);
21683 }
21684 
duk_is_symbol(duk_hthread * thr,duk_idx_t idx)21685 DUK_EXTERNAL duk_bool_t duk_is_symbol(duk_hthread *thr, duk_idx_t idx) {
21686 	duk_hstring *h;
21687 
21688 	DUK_ASSERT_API_ENTRY(thr);
21689 	h = duk_get_hstring(thr, idx);
21690 	/* Use DUK_LIKELY() here because caller may be more likely to type
21691 	 * check an expected symbol than not.
21692 	 */
21693 	if (DUK_LIKELY(h != NULL && DUK_HSTRING_HAS_SYMBOL(h))) {
21694 		return 1;
21695 	}
21696 	return 0;
21697 }
21698 
duk_is_array(duk_hthread * thr,duk_idx_t idx)21699 DUK_EXTERNAL duk_bool_t duk_is_array(duk_hthread *thr, duk_idx_t idx) {
21700 	duk_hobject *obj;
21701 
21702 	DUK_ASSERT_API_ENTRY(thr);
21703 
21704 	obj = duk_get_hobject(thr, idx);
21705 	if (obj) {
21706 		return (DUK_HOBJECT_GET_CLASS_NUMBER(obj) == DUK_HOBJECT_CLASS_ARRAY ? 1 : 0);
21707 	}
21708 	return 0;
21709 }
21710 
duk_is_function(duk_hthread * thr,duk_idx_t idx)21711 DUK_EXTERNAL duk_bool_t duk_is_function(duk_hthread *thr, duk_idx_t idx) {
21712 	duk_tval *tv;
21713 
21714 	DUK_ASSERT_API_ENTRY(thr);
21715 
21716 	tv = duk_get_tval_or_unused(thr, idx);
21717 	if (DUK_TVAL_IS_OBJECT(tv)) {
21718 		duk_hobject *h;
21719 		h = DUK_TVAL_GET_OBJECT(tv);
21720 		DUK_ASSERT(h != NULL);
21721 		return DUK_HOBJECT_HAS_CALLABLE(h) ? 1 : 0;
21722 	}
21723 	if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
21724 		return 1;
21725 	}
21726 	return 0;
21727 }
21728 
duk_is_callable_tval(duk_hthread * thr,duk_tval * tv)21729 DUK_INTERNAL duk_bool_t duk_is_callable_tval(duk_hthread *thr, duk_tval *tv) {
21730 	DUK_ASSERT_API_ENTRY(thr);
21731 
21732 	DUK_UNREF(thr);
21733 
21734 	if (DUK_TVAL_IS_OBJECT(tv)) {
21735 		duk_hobject *h;
21736 		h = DUK_TVAL_GET_OBJECT(tv);
21737 		DUK_ASSERT(h != NULL);
21738 		return DUK_HOBJECT_HAS_CALLABLE(h) ? 1 : 0;
21739 	}
21740 	if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
21741 		return 1;
21742 	}
21743 	return 0;
21744 }
21745 
duk_is_constructable(duk_hthread * thr,duk_idx_t idx)21746 DUK_EXTERNAL duk_bool_t duk_is_constructable(duk_hthread *thr, duk_idx_t idx) {
21747 	duk_tval *tv;
21748 
21749 	DUK_ASSERT_API_ENTRY(thr);
21750 
21751 	tv = duk_get_tval_or_unused(thr, idx);
21752 	if (DUK_TVAL_IS_OBJECT(tv)) {
21753 		duk_hobject *h;
21754 		h = DUK_TVAL_GET_OBJECT(tv);
21755 		DUK_ASSERT(h != NULL);
21756 		return DUK_HOBJECT_HAS_CONSTRUCTABLE(h) ? 1 : 0;
21757 	}
21758 	if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
21759 		return 1;
21760 	}
21761 	return 0;
21762 }
21763 
duk_is_c_function(duk_hthread * thr,duk_idx_t idx)21764 DUK_EXTERNAL duk_bool_t duk_is_c_function(duk_hthread *thr, duk_idx_t idx) {
21765 	DUK_ASSERT_API_ENTRY(thr);
21766 	return duk__obj_flag_any_default_false(thr,
21767 	                                       idx,
21768 	                                       DUK_HOBJECT_FLAG_NATFUNC);
21769 }
21770 
duk_is_ecmascript_function(duk_hthread * thr,duk_idx_t idx)21771 DUK_EXTERNAL duk_bool_t duk_is_ecmascript_function(duk_hthread *thr, duk_idx_t idx) {
21772 	DUK_ASSERT_API_ENTRY(thr);
21773 	return duk__obj_flag_any_default_false(thr,
21774 	                                       idx,
21775 	                                       DUK_HOBJECT_FLAG_COMPFUNC);
21776 }
21777 
duk_is_bound_function(duk_hthread * thr,duk_idx_t idx)21778 DUK_EXTERNAL duk_bool_t duk_is_bound_function(duk_hthread *thr, duk_idx_t idx) {
21779 	DUK_ASSERT_API_ENTRY(thr);
21780 	return duk__obj_flag_any_default_false(thr,
21781 	                                       idx,
21782 	                                       DUK_HOBJECT_FLAG_BOUNDFUNC);
21783 }
21784 
duk_is_thread(duk_hthread * thr,duk_idx_t idx)21785 DUK_EXTERNAL duk_bool_t duk_is_thread(duk_hthread *thr, duk_idx_t idx) {
21786 	duk_hobject *obj;
21787 
21788 	DUK_ASSERT_API_ENTRY(thr);
21789 
21790 	obj = duk_get_hobject(thr, idx);
21791 	if (obj) {
21792 		return (DUK_HOBJECT_GET_CLASS_NUMBER(obj) == DUK_HOBJECT_CLASS_THREAD ? 1 : 0);
21793 	}
21794 	return 0;
21795 }
21796 
duk_is_fixed_buffer(duk_hthread * thr,duk_idx_t idx)21797 DUK_EXTERNAL duk_bool_t duk_is_fixed_buffer(duk_hthread *thr, duk_idx_t idx) {
21798 	duk_tval *tv;
21799 
21800 	DUK_ASSERT_API_ENTRY(thr);
21801 
21802 	tv = duk_get_tval_or_unused(thr, idx);
21803 	DUK_ASSERT(tv != NULL);
21804 	if (DUK_TVAL_IS_BUFFER(tv)) {
21805 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
21806 		DUK_ASSERT(h != NULL);
21807 		return (DUK_HBUFFER_HAS_DYNAMIC(h) ? 0 : 1);
21808 	}
21809 	return 0;
21810 }
21811 
duk_is_dynamic_buffer(duk_hthread * thr,duk_idx_t idx)21812 DUK_EXTERNAL duk_bool_t duk_is_dynamic_buffer(duk_hthread *thr, duk_idx_t idx) {
21813 	duk_tval *tv;
21814 
21815 	DUK_ASSERT_API_ENTRY(thr);
21816 
21817 	tv = duk_get_tval_or_unused(thr, idx);
21818 	DUK_ASSERT(tv != NULL);
21819 	if (DUK_TVAL_IS_BUFFER(tv)) {
21820 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
21821 		DUK_ASSERT(h != NULL);
21822 		return (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
21823 	}
21824 	return 0;
21825 }
21826 
duk_is_external_buffer(duk_hthread * thr,duk_idx_t idx)21827 DUK_EXTERNAL duk_bool_t duk_is_external_buffer(duk_hthread *thr, duk_idx_t idx) {
21828 	duk_tval *tv;
21829 
21830 	DUK_ASSERT_API_ENTRY(thr);
21831 
21832 	tv = duk_get_tval_or_unused(thr, idx);
21833 	DUK_ASSERT(tv != NULL);
21834 	if (DUK_TVAL_IS_BUFFER(tv)) {
21835 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
21836 		DUK_ASSERT(h != NULL);
21837 		return (DUK_HBUFFER_HAS_DYNAMIC(h) && DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
21838 	}
21839 	return 0;
21840 }
21841 
duk_get_error_code(duk_hthread * thr,duk_idx_t idx)21842 DUK_EXTERNAL duk_errcode_t duk_get_error_code(duk_hthread *thr, duk_idx_t idx) {
21843 	duk_hobject *h;
21844 	duk_uint_t sanity;
21845 
21846 	DUK_ASSERT_API_ENTRY(thr);
21847 
21848 	h = duk_get_hobject(thr, idx);
21849 
21850 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
21851 	do {
21852 		if (!h) {
21853 			return DUK_ERR_NONE;
21854 		}
21855 
21856 		/* XXX: something more convenient? */
21857 
21858 		if (h == thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE]) {
21859 			return DUK_ERR_EVAL_ERROR;
21860 		}
21861 		if (h == thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE]) {
21862 			return DUK_ERR_RANGE_ERROR;
21863 		}
21864 		if (h == thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE]) {
21865 			return DUK_ERR_REFERENCE_ERROR;
21866 		}
21867 		if (h == thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE]) {
21868 			return DUK_ERR_SYNTAX_ERROR;
21869 		}
21870 		if (h == thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE]) {
21871 			return DUK_ERR_TYPE_ERROR;
21872 		}
21873 		if (h == thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE]) {
21874 			return DUK_ERR_URI_ERROR;
21875 		}
21876 		if (h == thr->builtins[DUK_BIDX_ERROR_PROTOTYPE]) {
21877 			return DUK_ERR_ERROR;
21878 		}
21879 
21880 		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
21881 	} while (--sanity > 0);
21882 
21883 	return DUK_ERR_NONE;
21884 }
21885 
21886 /*
21887  *  Pushers
21888  */
21889 
duk_push_tval(duk_hthread * thr,duk_tval * tv)21890 DUK_INTERNAL void duk_push_tval(duk_hthread *thr, duk_tval *tv) {
21891 	duk_tval *tv_slot;
21892 
21893 	DUK_ASSERT_API_ENTRY(thr);
21894 	DUK_ASSERT(tv != NULL);
21895 
21896 	DUK__CHECK_SPACE();
21897 	tv_slot = thr->valstack_top++;
21898 	DUK_TVAL_SET_TVAL(tv_slot, tv);
21899 	DUK_TVAL_INCREF(thr, tv);  /* no side effects */
21900 }
21901 
duk_push_undefined(duk_hthread * thr)21902 DUK_EXTERNAL void duk_push_undefined(duk_hthread *thr) {
21903 	DUK_ASSERT_API_ENTRY(thr);
21904 
21905 	DUK__CHECK_SPACE();
21906 
21907 	/* Because value stack init policy is 'undefined above top',
21908 	 * we don't need to write, just assert.
21909 	 */
21910 	thr->valstack_top++;
21911 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
21912 }
21913 
duk_push_null(duk_hthread * thr)21914 DUK_EXTERNAL void duk_push_null(duk_hthread *thr) {
21915 	duk_tval *tv_slot;
21916 
21917 	DUK_ASSERT_API_ENTRY(thr);
21918 	DUK__CHECK_SPACE();
21919 	tv_slot = thr->valstack_top++;
21920 	DUK_TVAL_SET_NULL(tv_slot);
21921 }
21922 
duk_push_boolean(duk_hthread * thr,duk_bool_t val)21923 DUK_EXTERNAL void duk_push_boolean(duk_hthread *thr, duk_bool_t val) {
21924 	duk_tval *tv_slot;
21925 	duk_small_int_t b;
21926 
21927 	DUK_ASSERT_API_ENTRY(thr);
21928 	DUK__CHECK_SPACE();
21929 	b = (val ? 1 : 0);  /* ensure value is 1 or 0 (not other non-zero) */
21930 	tv_slot = thr->valstack_top++;
21931 	DUK_TVAL_SET_BOOLEAN(tv_slot, b);
21932 }
21933 
duk_push_true(duk_hthread * thr)21934 DUK_EXTERNAL void duk_push_true(duk_hthread *thr) {
21935 	duk_tval *tv_slot;
21936 
21937 	DUK_ASSERT_API_ENTRY(thr);
21938 	DUK__CHECK_SPACE();
21939 	tv_slot = thr->valstack_top++;
21940 	DUK_TVAL_SET_BOOLEAN_TRUE(tv_slot);
21941 }
21942 
duk_push_false(duk_hthread * thr)21943 DUK_EXTERNAL void duk_push_false(duk_hthread *thr) {
21944 	duk_tval *tv_slot;
21945 
21946 	DUK_ASSERT_API_ENTRY(thr);
21947 	DUK__CHECK_SPACE();
21948 	tv_slot = thr->valstack_top++;
21949 	DUK_TVAL_SET_BOOLEAN_FALSE(tv_slot);
21950 }
21951 
21952 /* normalize NaN which may not match our canonical internal NaN */
duk_push_number(duk_hthread * thr,duk_double_t val)21953 DUK_EXTERNAL void duk_push_number(duk_hthread *thr, duk_double_t val) {
21954 	duk_tval *tv_slot;
21955 	duk_double_union du;
21956 
21957 	DUK_ASSERT_API_ENTRY(thr);
21958 	DUK__CHECK_SPACE();
21959 	du.d = val;
21960 	DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
21961 	tv_slot = thr->valstack_top++;
21962 	DUK_TVAL_SET_NUMBER(tv_slot, du.d);
21963 }
21964 
duk_push_int(duk_hthread * thr,duk_int_t val)21965 DUK_EXTERNAL void duk_push_int(duk_hthread *thr, duk_int_t val) {
21966 #if defined(DUK_USE_FASTINT)
21967 	duk_tval *tv_slot;
21968 
21969 	DUK_ASSERT_API_ENTRY(thr);
21970 	DUK__CHECK_SPACE();
21971 	tv_slot = thr->valstack_top++;
21972 #if DUK_INT_MAX <= 0x7fffffffL
21973 	DUK_TVAL_SET_I32(tv_slot, (duk_int32_t) val);
21974 #else
21975 	if (val >= DUK_FASTINT_MIN && val <= DUK_FASTINT_MAX) {
21976 		DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
21977 	} else {
21978 		duk_double_t = (duk_double_t) val;
21979 		DUK_TVAL_SET_NUMBER(tv_slot, d);
21980 	}
21981 #endif
21982 #else  /* DUK_USE_FASTINT */
21983 	duk_tval *tv_slot;
21984 	duk_double_t d;
21985 
21986 	DUK_ASSERT_API_ENTRY(thr);
21987 	DUK__CHECK_SPACE();
21988 	d = (duk_double_t) val;
21989 	tv_slot = thr->valstack_top++;
21990 	DUK_TVAL_SET_NUMBER(tv_slot, d);
21991 #endif  /* DUK_USE_FASTINT */
21992 }
21993 
duk_push_uint(duk_hthread * thr,duk_uint_t val)21994 DUK_EXTERNAL void duk_push_uint(duk_hthread *thr, duk_uint_t val) {
21995 #if defined(DUK_USE_FASTINT)
21996 	duk_tval *tv_slot;
21997 
21998 	DUK_ASSERT_API_ENTRY(thr);
21999 	DUK__CHECK_SPACE();
22000 	tv_slot = thr->valstack_top++;
22001 #if DUK_UINT_MAX <= 0xffffffffUL
22002 	DUK_TVAL_SET_U32(tv_slot, (duk_uint32_t) val);
22003 #else
22004 	if (val <= DUK_FASTINT_MAX) {  /* val is unsigned so >= 0 */
22005 		/* XXX: take advantage of val being unsigned, no need to mask */
22006 		DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
22007 	} else {
22008 		duk_double_t = (duk_double_t) val;
22009 		DUK_TVAL_SET_NUMBER(tv_slot, d);
22010 	}
22011 #endif
22012 #else  /* DUK_USE_FASTINT */
22013 	duk_tval *tv_slot;
22014 	duk_double_t d;
22015 
22016 	DUK_ASSERT_API_ENTRY(thr);
22017 	DUK__CHECK_SPACE();
22018 	d = (duk_double_t) val;
22019 	tv_slot = thr->valstack_top++;
22020 	DUK_TVAL_SET_NUMBER(tv_slot, d);
22021 #endif  /* DUK_USE_FASTINT */
22022 }
22023 
duk_push_nan(duk_hthread * thr)22024 DUK_EXTERNAL void duk_push_nan(duk_hthread *thr) {
22025 	duk_tval *tv_slot;
22026 	duk_double_union du;
22027 
22028 	DUK_ASSERT_API_ENTRY(thr);
22029 	DUK__CHECK_SPACE();
22030 	DUK_DBLUNION_SET_NAN(&du);
22031 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
22032 	tv_slot = thr->valstack_top++;
22033 	DUK_TVAL_SET_NUMBER(tv_slot, du.d);
22034 }
22035 
duk_push_lstring(duk_hthread * thr,const char * str,duk_size_t len)22036 DUK_EXTERNAL const char *duk_push_lstring(duk_hthread *thr, const char *str, duk_size_t len) {
22037 	duk_hstring *h;
22038 	duk_tval *tv_slot;
22039 
22040 	DUK_ASSERT_API_ENTRY(thr);
22041 
22042 	/* Check stack before interning (avoid hanging temp). */
22043 	DUK__CHECK_SPACE();
22044 
22045 	/* NULL with zero length represents an empty string; NULL with higher
22046 	 * length is also now treated like an empty string although it is
22047 	 * a bit dubious.  This is unlike duk_push_string() which pushes a
22048 	 * 'null' if the input string is a NULL.
22049 	 */
22050 	if (DUK_UNLIKELY(str == NULL)) {
22051 		len = 0U;
22052 	}
22053 
22054 	/* Check for maximum string length. */
22055 	if (DUK_UNLIKELY(len > DUK_HSTRING_MAX_BYTELEN)) {
22056 		DUK_ERROR_RANGE(thr, DUK_STR_STRING_TOO_LONG);
22057 		DUK_WO_NORETURN(return NULL;);
22058 	}
22059 
22060 	h = duk_heap_strtable_intern_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
22061 	DUK_ASSERT(h != NULL);
22062 
22063 	tv_slot = thr->valstack_top++;
22064 	DUK_TVAL_SET_STRING(tv_slot, h);
22065 	DUK_HSTRING_INCREF(thr, h);  /* no side effects */
22066 
22067 	return (const char *) DUK_HSTRING_GET_DATA(h);
22068 }
22069 
duk_push_string(duk_hthread * thr,const char * str)22070 DUK_EXTERNAL const char *duk_push_string(duk_hthread *thr, const char *str) {
22071 	DUK_ASSERT_API_ENTRY(thr);
22072 
22073 	if (str) {
22074 		return duk_push_lstring(thr, str, DUK_STRLEN(str));
22075 	} else {
22076 		duk_push_null(thr);
22077 		return NULL;
22078 	}
22079 }
22080 
22081 #if !defined(DUK_USE_PREFER_SIZE)
22082 #if defined(DUK_USE_LITCACHE_SIZE)
duk_push_literal_raw(duk_hthread * thr,const char * str,duk_size_t len)22083 DUK_EXTERNAL const char *duk_push_literal_raw(duk_hthread *thr, const char *str, duk_size_t len) {
22084 	duk_hstring *h;
22085 	duk_tval *tv_slot;
22086 
22087 	DUK_ASSERT_API_ENTRY(thr);
22088 	DUK_ASSERT(str != NULL);
22089 	DUK_ASSERT(str[len] == (char) 0);
22090 
22091 	/* Check for maximum string length. */
22092 	if (DUK_UNLIKELY(len > DUK_HSTRING_MAX_BYTELEN)) {
22093 		DUK_ERROR_RANGE(thr, DUK_STR_STRING_TOO_LONG);
22094 		DUK_WO_NORETURN(return NULL;);
22095 	}
22096 
22097 	h = duk_heap_strtable_intern_literal_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
22098 	DUK_ASSERT(h != NULL);
22099 
22100 	tv_slot = thr->valstack_top++;
22101 	DUK_TVAL_SET_STRING(tv_slot, h);
22102 	DUK_HSTRING_INCREF(thr, h);  /* no side effects */
22103 
22104 	return (const char *) DUK_HSTRING_GET_DATA(h);
22105 }
22106 #else  /* DUK_USE_LITCACHE_SIZE */
duk_push_literal_raw(duk_hthread * thr,const char * str,duk_size_t len)22107 DUK_EXTERNAL const char *duk_push_literal_raw(duk_hthread *thr, const char *str, duk_size_t len) {
22108 	DUK_ASSERT_API_ENTRY(thr);
22109 	DUK_ASSERT(str != NULL);
22110 	DUK_ASSERT(str[len] == (char) 0);
22111 
22112 	return duk_push_lstring(thr, str, len);
22113 }
22114 #endif  /* DUK_USE_LITCACHE_SIZE */
22115 #endif  /* !DUK_USE_PREFER_SIZE */
22116 
duk_push_pointer(duk_hthread * thr,void * val)22117 DUK_EXTERNAL void duk_push_pointer(duk_hthread *thr, void *val) {
22118 	duk_tval *tv_slot;
22119 
22120 	DUK_ASSERT_API_ENTRY(thr);
22121 	DUK__CHECK_SPACE();
22122 	tv_slot = thr->valstack_top++;
22123 	DUK_TVAL_SET_POINTER(tv_slot, val);
22124 }
22125 
duk_push_uint_to_hstring(duk_hthread * thr,duk_uint_t i)22126 DUK_INTERNAL duk_hstring *duk_push_uint_to_hstring(duk_hthread *thr, duk_uint_t i) {
22127 	duk_hstring *h_tmp;
22128 
22129 	DUK_ASSERT_API_ENTRY(thr);
22130 
22131 	/* XXX: this could be a direct DUK_SPRINTF to a buffer followed by duk_push_string() */
22132 	duk_push_uint(thr, (duk_uint_t) i);
22133 	h_tmp = duk_to_hstring_m1(thr);
22134 	DUK_ASSERT(h_tmp != NULL);
22135 	return h_tmp;
22136 }
22137 
duk__push_this_helper(duk_hthread * thr,duk_small_uint_t check_object_coercible)22138 DUK_LOCAL void duk__push_this_helper(duk_hthread *thr, duk_small_uint_t check_object_coercible) {
22139 	duk_tval *tv_slot;
22140 
22141 	DUK__CHECK_SPACE();
22142 
22143 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* because of valstack init policy */
22144 	tv_slot = thr->valstack_top++;
22145 
22146 	if (DUK_UNLIKELY(thr->callstack_curr == NULL)) {
22147 		if (check_object_coercible) {
22148 			goto type_error;
22149 		}
22150 		/* 'undefined' already on stack top */
22151 	} else {
22152 		duk_tval *tv;
22153 
22154 		/* 'this' binding is just before current activation's bottom */
22155 		DUK_ASSERT(thr->valstack_bottom > thr->valstack);
22156 		tv = thr->valstack_bottom - 1;
22157 		if (check_object_coercible &&
22158 		    (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv))) {
22159 			/* XXX: better macro for DUK_TVAL_IS_UNDEFINED_OR_NULL(tv) */
22160 			goto type_error;
22161 		}
22162 
22163 		DUK_TVAL_SET_TVAL(tv_slot, tv);
22164 		DUK_TVAL_INCREF(thr, tv);
22165 	}
22166 	return;
22167 
22168  type_error:
22169 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE);
22170 	DUK_WO_NORETURN(return;);
22171 }
22172 
duk_push_this(duk_hthread * thr)22173 DUK_EXTERNAL void duk_push_this(duk_hthread *thr) {
22174 	DUK_ASSERT_API_ENTRY(thr);
22175 
22176 	duk__push_this_helper(thr, 0 /*check_object_coercible*/);
22177 }
22178 
duk_push_this_check_object_coercible(duk_hthread * thr)22179 DUK_INTERNAL void duk_push_this_check_object_coercible(duk_hthread *thr) {
22180 	DUK_ASSERT_API_ENTRY(thr);
22181 
22182 	duk__push_this_helper(thr, 1 /*check_object_coercible*/);
22183 }
22184 
duk_push_this_coercible_to_object(duk_hthread * thr)22185 DUK_INTERNAL duk_hobject *duk_push_this_coercible_to_object(duk_hthread *thr) {
22186 	duk_hobject *h;
22187 
22188 	DUK_ASSERT_API_ENTRY(thr);
22189 
22190 	duk__push_this_helper(thr, 1 /*check_object_coercible*/);
22191 	h = duk_to_hobject(thr, -1);
22192 	DUK_ASSERT(h != NULL);
22193 	return h;
22194 }
22195 
duk_push_this_coercible_to_string(duk_hthread * thr)22196 DUK_INTERNAL duk_hstring *duk_push_this_coercible_to_string(duk_hthread *thr) {
22197 	DUK_ASSERT_API_ENTRY(thr);
22198 
22199 	duk__push_this_helper(thr, 1 /*check_object_coercible*/);
22200 	return duk_to_hstring_m1(thr);  /* This will reject all Symbol values; accepts Symbol objects. */
22201 }
22202 
duk_get_borrowed_this_tval(duk_hthread * thr)22203 DUK_INTERNAL duk_tval *duk_get_borrowed_this_tval(duk_hthread *thr) {
22204 	DUK_ASSERT_API_ENTRY(thr);
22205 
22206 	DUK_ASSERT(thr->callstack_top > 0);  /* caller required to know */
22207 	DUK_ASSERT(thr->callstack_curr != NULL);  /* caller required to know */
22208 	DUK_ASSERT(thr->valstack_bottom > thr->valstack);  /* consequence of above */
22209 	DUK_ASSERT(thr->valstack_bottom - 1 >= thr->valstack);  /* 'this' binding exists */
22210 
22211 	return thr->valstack_bottom - 1;
22212 }
22213 
duk_push_new_target(duk_hthread * thr)22214 DUK_EXTERNAL void duk_push_new_target(duk_hthread *thr) {
22215 	duk_activation *act;
22216 
22217 	DUK_ASSERT_API_ENTRY(thr);
22218 
22219 	/* https://www.ecma-international.org/ecma-262/6.0/#sec-meta-properties-runtime-semantics-evaluation
22220 	 * https://www.ecma-international.org/ecma-262/6.0/#sec-getnewtarget
22221 	 *
22222 	 * No newTarget support now, so as a first approximation
22223 	 * use the resolved (non-bound) target function.
22224 	 *
22225 	 * Check CONSTRUCT flag from current function, or if running
22226 	 * direct eval, from a non-direct-eval parent (with possibly
22227 	 * more than one nested direct eval).  An alternative to this
22228 	 * would be to store [[NewTarget]] as a hidden symbol of the
22229 	 * lexical scope, and then just look up that variable.
22230 	 *
22231 	 * Calls from the application will either be for an empty
22232 	 * call stack, or a Duktape/C function as the top activation.
22233 	 */
22234 
22235 	act = thr->callstack_curr;
22236 	for (;;) {
22237 		if (act == NULL) {
22238 			break;
22239 		}
22240 
22241 		if (act->flags & DUK_ACT_FLAG_CONSTRUCT) {
22242 			duk_push_tval(thr, &act->tv_func);
22243 			return;
22244 		} else if (act->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
22245 			act = act->parent;
22246 		} else {
22247 			break;
22248 		}
22249 	}
22250 
22251 	duk_push_undefined(thr);
22252 }
22253 
duk_push_current_function(duk_hthread * thr)22254 DUK_EXTERNAL void duk_push_current_function(duk_hthread *thr) {
22255 	duk_activation *act;
22256 
22257 	DUK_ASSERT_API_ENTRY(thr);
22258 
22259 	act = thr->callstack_curr;
22260 	if (act != NULL) {
22261 		duk_push_tval(thr, &act->tv_func);
22262 	} else {
22263 		duk_push_undefined(thr);
22264 	}
22265 }
22266 
duk_push_current_thread(duk_hthread * thr)22267 DUK_EXTERNAL void duk_push_current_thread(duk_hthread *thr) {
22268 	DUK_ASSERT_API_ENTRY(thr);
22269 
22270 	if (thr->heap->curr_thread) {
22271 		duk_push_hobject(thr, (duk_hobject *) thr->heap->curr_thread);
22272 	} else {
22273 		duk_push_undefined(thr);
22274 	}
22275 }
22276 
duk_push_global_object(duk_hthread * thr)22277 DUK_EXTERNAL void duk_push_global_object(duk_hthread *thr) {
22278 	DUK_ASSERT_API_ENTRY(thr);
22279 
22280 	duk_push_hobject_bidx(thr, DUK_BIDX_GLOBAL);
22281 }
22282 
22283 /* XXX: size optimize */
duk__push_stash(duk_hthread * thr)22284 DUK_LOCAL void duk__push_stash(duk_hthread *thr) {
22285 	if (!duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE)) {
22286 		DUK_DDD(DUK_DDDPRINT("creating heap/global/thread stash on first use"));
22287 		duk_pop_unsafe(thr);
22288 		duk_push_bare_object(thr);
22289 		duk_dup_top(thr);
22290 		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_C);  /* [ ... parent stash stash ] -> [ ... parent stash ] */
22291 	}
22292 	duk_remove_m2(thr);
22293 }
22294 
duk_push_heap_stash(duk_hthread * thr)22295 DUK_EXTERNAL void duk_push_heap_stash(duk_hthread *thr) {
22296 	duk_heap *heap;
22297 	DUK_ASSERT_API_ENTRY(thr);
22298 	heap = thr->heap;
22299 	DUK_ASSERT(heap->heap_object != NULL);
22300 	duk_push_hobject(thr, heap->heap_object);
22301 	duk__push_stash(thr);
22302 }
22303 
duk_push_global_stash(duk_hthread * thr)22304 DUK_EXTERNAL void duk_push_global_stash(duk_hthread *thr) {
22305 	DUK_ASSERT_API_ENTRY(thr);
22306 	duk_push_global_object(thr);
22307 	duk__push_stash(thr);
22308 }
22309 
duk_push_thread_stash(duk_hthread * thr,duk_hthread * target_thr)22310 DUK_EXTERNAL void duk_push_thread_stash(duk_hthread *thr, duk_hthread *target_thr) {
22311 	DUK_ASSERT_API_ENTRY(thr);
22312 	if (DUK_UNLIKELY(target_thr == NULL)) {
22313 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
22314 		DUK_WO_NORETURN(return;);
22315 	}
22316 	duk_push_hobject(thr, (duk_hobject *) target_thr);
22317 	duk__push_stash(thr);
22318 }
22319 
22320 /* 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)22321 DUK_LOCAL duk_int_t duk__try_push_vsprintf(duk_hthread *thr, void *buf, duk_size_t sz, const char *fmt, va_list ap) {
22322 	duk_int_t len;
22323 
22324 	DUK_ASSERT_CTX_VALID(thr);
22325 	DUK_UNREF(thr);
22326 
22327 	/* NUL terminator handling doesn't matter here */
22328 	len = DUK_VSNPRINTF((char *) buf, sz, fmt, ap);
22329 	if (len < (duk_int_t) sz) {
22330 		/* Return value of 'sz' or more indicates output was (potentially)
22331 		 * truncated.
22332 		 */
22333 		return (duk_int_t) len;
22334 	}
22335 	return -1;
22336 }
22337 
duk_push_vsprintf(duk_hthread * thr,const char * fmt,va_list ap)22338 DUK_EXTERNAL const char *duk_push_vsprintf(duk_hthread *thr, const char *fmt, va_list ap) {
22339 	duk_uint8_t stack_buf[DUK_PUSH_SPRINTF_INITIAL_SIZE];
22340 	duk_size_t sz = DUK_PUSH_SPRINTF_INITIAL_SIZE;
22341 	duk_bool_t pushed_buf = 0;
22342 	void *buf;
22343 	duk_int_t len;  /* XXX: duk_ssize_t */
22344 	const char *res;
22345 
22346 	DUK_ASSERT_API_ENTRY(thr);
22347 
22348 	/* special handling of fmt==NULL */
22349 	if (!fmt) {
22350 		duk_hstring *h_str;
22351 		duk_push_hstring_empty(thr);
22352 		h_str = duk_known_hstring(thr, -1);
22353 		return (const char *) DUK_HSTRING_GET_DATA(h_str);
22354 	}
22355 
22356 	/* initial estimate based on format string */
22357 	sz = DUK_STRLEN(fmt) + 16;  /* format plus something to avoid just missing */
22358 	if (sz < DUK_PUSH_SPRINTF_INITIAL_SIZE) {
22359 		sz = DUK_PUSH_SPRINTF_INITIAL_SIZE;
22360 	}
22361 	DUK_ASSERT(sz > 0);
22362 
22363 	/* Try to make do with a stack buffer to avoid allocating a temporary buffer.
22364 	 * This works 99% of the time which is quite nice.
22365 	 */
22366 	for (;;) {
22367 		va_list ap_copy;  /* copied so that 'ap' can be reused */
22368 
22369 		if (sz <= sizeof(stack_buf)) {
22370 			buf = stack_buf;
22371 		} else if (!pushed_buf) {
22372 			pushed_buf = 1;
22373 			buf = duk_push_dynamic_buffer(thr, sz);
22374 		} else {
22375 			buf = duk_resize_buffer(thr, -1, sz);
22376 		}
22377 		DUK_ASSERT(buf != NULL);
22378 
22379 		DUK_VA_COPY(ap_copy, ap);
22380 		len = duk__try_push_vsprintf(thr, buf, sz, fmt, ap_copy);
22381 		va_end(ap_copy);
22382 		if (len >= 0) {
22383 			break;
22384 		}
22385 
22386 		/* failed, resize and try again */
22387 		sz = sz * 2;
22388 		if (DUK_UNLIKELY(sz >= DUK_PUSH_SPRINTF_SANITY_LIMIT)) {
22389 			DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
22390 			DUK_WO_NORETURN(return NULL;);
22391 		}
22392 	}
22393 
22394 	/* Cannot use duk_buffer_to_string() on the buffer because it is
22395 	 * usually larger than 'len'; 'buf' is also usually a stack buffer.
22396 	 */
22397 	res = duk_push_lstring(thr, (const char *) buf, (duk_size_t) len);  /* [ buf? res ] */
22398 	if (pushed_buf) {
22399 		duk_remove_m2(thr);
22400 	}
22401 	return res;
22402 }
22403 
duk_push_sprintf(duk_hthread * thr,const char * fmt,...)22404 DUK_EXTERNAL const char *duk_push_sprintf(duk_hthread *thr, const char *fmt, ...) {
22405 	va_list ap;
22406 	const char *ret;
22407 
22408 	DUK_ASSERT_API_ENTRY(thr);
22409 
22410 	/* allow fmt==NULL */
22411 	va_start(ap, fmt);
22412 	ret = duk_push_vsprintf(thr, fmt, ap);
22413 	va_end(ap);
22414 
22415 	return ret;
22416 }
22417 
duk_push_object_helper(duk_hthread * thr,duk_uint_t hobject_flags_and_class,duk_small_int_t prototype_bidx)22418 DUK_INTERNAL duk_hobject *duk_push_object_helper(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
22419 	duk_tval *tv_slot;
22420 	duk_hobject *h;
22421 
22422 	DUK_ASSERT_API_ENTRY(thr);
22423 	DUK_ASSERT(prototype_bidx == -1 ||
22424 	           (prototype_bidx >= 0 && prototype_bidx < DUK_NUM_BUILTINS));
22425 
22426 	DUK__CHECK_SPACE();
22427 
22428 	h = duk_hobject_alloc(thr, hobject_flags_and_class);
22429 	DUK_ASSERT(h != NULL);
22430 
22431 	DUK_DDD(DUK_DDDPRINT("created object with flags: 0x%08lx", (unsigned long) h->hdr.h_flags));
22432 
22433 	tv_slot = thr->valstack_top;
22434 	DUK_TVAL_SET_OBJECT(tv_slot, h);
22435 	DUK_HOBJECT_INCREF(thr, h);  /* no side effects */
22436 	thr->valstack_top++;
22437 
22438 	/* object is now reachable */
22439 
22440 	if (prototype_bidx >= 0) {
22441 		DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, h, thr->builtins[prototype_bidx]);
22442 	} else {
22443 		DUK_ASSERT(prototype_bidx == -1);
22444 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h) == NULL);
22445 	}
22446 
22447 	return h;
22448 }
22449 
duk_push_object_helper_proto(duk_hthread * thr,duk_uint_t hobject_flags_and_class,duk_hobject * proto)22450 DUK_INTERNAL duk_hobject *duk_push_object_helper_proto(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_hobject *proto) {
22451 	duk_hobject *h;
22452 
22453 	DUK_ASSERT_API_ENTRY(thr);
22454 
22455 	h = duk_push_object_helper(thr, hobject_flags_and_class, -1);
22456 	DUK_ASSERT(h != NULL);
22457 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, h, proto);
22458 	return h;
22459 }
22460 
duk_push_object(duk_hthread * thr)22461 DUK_EXTERNAL duk_idx_t duk_push_object(duk_hthread *thr) {
22462 	DUK_ASSERT_API_ENTRY(thr);
22463 
22464 	(void) duk_push_object_helper(thr,
22465 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
22466 	                              DUK_HOBJECT_FLAG_FASTREFS |
22467 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
22468 	                              DUK_BIDX_OBJECT_PROTOTYPE);
22469 	return duk_get_top_index_unsafe(thr);
22470 }
22471 
duk_push_array(duk_hthread * thr)22472 DUK_EXTERNAL duk_idx_t duk_push_array(duk_hthread *thr) {
22473 	duk_uint_t flags;
22474 	duk_harray *obj;
22475 	duk_idx_t ret;
22476 	duk_tval *tv_slot;
22477 
22478 	DUK_ASSERT_API_ENTRY(thr);
22479 
22480 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
22481 	        DUK_HOBJECT_FLAG_FASTREFS |
22482 	        DUK_HOBJECT_FLAG_ARRAY_PART |
22483 	        DUK_HOBJECT_FLAG_EXOTIC_ARRAY |
22484 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAY);
22485 
22486 	obj = duk_harray_alloc(thr, flags);
22487 	DUK_ASSERT(obj != NULL);
22488 
22489 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_ARRAY_PROTOTYPE]);
22490 
22491 	tv_slot = thr->valstack_top;
22492 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22493 	DUK_HOBJECT_INCREF(thr, obj);  /* XXX: could preallocate with refcount = 1 */
22494 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
22495 	thr->valstack_top++;
22496 
22497 	DUK_ASSERT(obj->length == 0);  /* Array .length starts at zero. */
22498 	return ret;
22499 }
22500 
duk_push_harray(duk_hthread * thr)22501 DUK_INTERNAL duk_harray *duk_push_harray(duk_hthread *thr) {
22502 	/* XXX: API call could do this directly, cast to void in API macro. */
22503 	duk_harray *a;
22504 
22505 	DUK_ASSERT_API_ENTRY(thr);
22506 
22507 	(void) duk_push_array(thr);
22508 	DUK_ASSERT(DUK_TVAL_IS_OBJECT(thr->valstack_top - 1));
22509 	a = (duk_harray *) DUK_TVAL_GET_OBJECT(thr->valstack_top - 1);
22510 	DUK_ASSERT(a != NULL);
22511 	return a;
22512 }
22513 
22514 /* Push a duk_harray with preallocated size (.length also set to match size).
22515  * Caller may then populate array part of the duk_harray directly.
22516  */
duk_push_harray_with_size(duk_hthread * thr,duk_uint32_t size)22517 DUK_INTERNAL duk_harray *duk_push_harray_with_size(duk_hthread *thr, duk_uint32_t size) {
22518 	duk_harray *a;
22519 
22520 	DUK_ASSERT_API_ENTRY(thr);
22521 
22522 	a = duk_push_harray(thr);
22523 
22524 	duk_hobject_realloc_props(thr,
22525 	                          (duk_hobject *) a,
22526 	                          0,
22527 	                          size,
22528 	                          0,
22529 	                          0);
22530 	a->length = size;
22531 	return a;
22532 }
22533 
duk_push_harray_with_size_outptr(duk_hthread * thr,duk_uint32_t size)22534 DUK_INTERNAL duk_tval *duk_push_harray_with_size_outptr(duk_hthread *thr, duk_uint32_t size) {
22535 	duk_harray *a;
22536 
22537 	DUK_ASSERT_API_ENTRY(thr);
22538 
22539 	a = duk_push_harray_with_size(thr, size);
22540 	DUK_ASSERT(a != NULL);
22541 	return DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a);
22542 }
22543 
duk_push_thread_raw(duk_hthread * thr,duk_uint_t flags)22544 DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_hthread *thr, duk_uint_t flags) {
22545 	duk_hthread *obj;
22546 	duk_idx_t ret;
22547 	duk_tval *tv_slot;
22548 
22549 	DUK_ASSERT_API_ENTRY(thr);
22550 
22551 	DUK__CHECK_SPACE();
22552 
22553 	obj = duk_hthread_alloc(thr,
22554 	                        DUK_HOBJECT_FLAG_EXTENSIBLE |
22555 	                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
22556 	DUK_ASSERT(obj != NULL);
22557 	obj->state = DUK_HTHREAD_STATE_INACTIVE;
22558 #if defined(DUK_USE_ROM_STRINGS)
22559 	/* Nothing to initialize, strs[] is in ROM. */
22560 #else
22561 #if defined(DUK_USE_HEAPPTR16)
22562 	obj->strs16 = thr->strs16;
22563 #else
22564 	obj->strs = thr->strs;
22565 #endif
22566 #endif
22567 	DUK_DDD(DUK_DDDPRINT("created thread object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
22568 
22569 	/* make the new thread reachable */
22570 	tv_slot = thr->valstack_top;
22571 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22572 	DUK_HTHREAD_INCREF(thr, obj);
22573 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
22574 	thr->valstack_top++;
22575 
22576 	/* important to do this *after* pushing, to make the thread reachable for gc */
22577 	if (DUK_UNLIKELY(!duk_hthread_init_stacks(thr->heap, obj))) {
22578 		DUK_ERROR_ALLOC_FAILED(thr);
22579 		DUK_WO_NORETURN(return 0;);
22580 	}
22581 
22582 	/* initialize built-ins - either by copying or creating new ones */
22583 	if (flags & DUK_THREAD_NEW_GLOBAL_ENV) {
22584 		duk_hthread_create_builtin_objects(obj);
22585 	} else {
22586 		duk_hthread_copy_builtin_objects(thr, obj);
22587 	}
22588 
22589 	/* default prototype */
22590 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, obj->builtins[DUK_BIDX_THREAD_PROTOTYPE]);
22591 
22592 	/* Initial stack size satisfies the stack slack constraints so there
22593 	 * is no need to require stack here.
22594 	 */
22595 	DUK_ASSERT(DUK_VALSTACK_INITIAL_SIZE >=
22596 	           DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
22597 
22598 	return ret;
22599 }
22600 
duk_push_hcompfunc(duk_hthread * thr)22601 DUK_INTERNAL duk_hcompfunc *duk_push_hcompfunc(duk_hthread *thr) {
22602 	duk_hcompfunc *obj;
22603 	duk_tval *tv_slot;
22604 
22605 	DUK_ASSERT_API_ENTRY(thr);
22606 
22607 	DUK__CHECK_SPACE();
22608 
22609 	/* Template functions are not strictly constructable (they don't
22610 	 * have a "prototype" property for instance), so leave the
22611 	 * DUK_HOBJECT_FLAG_CONSRUCTABLE flag cleared here.
22612 	 */
22613 
22614 	obj = duk_hcompfunc_alloc(thr,
22615 	                          DUK_HOBJECT_FLAG_EXTENSIBLE |
22616 	                          DUK_HOBJECT_FLAG_CALLABLE |
22617 	                          DUK_HOBJECT_FLAG_COMPFUNC |
22618 	                          DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));
22619 	if (DUK_UNLIKELY(obj == NULL)) {
22620 		DUK_ERROR_ALLOC_FAILED(thr);
22621 		DUK_WO_NORETURN(return NULL;);
22622 	}
22623 
22624 	DUK_DDD(DUK_DDDPRINT("created compiled function object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
22625 
22626 	tv_slot = thr->valstack_top;
22627 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22628 	DUK_HOBJECT_INCREF(thr, obj);
22629 	thr->valstack_top++;
22630 
22631 	/* default prototype */
22632 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) obj) == NULL);
22633 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
22634 
22635 	return obj;
22636 }
22637 
duk_push_hboundfunc(duk_hthread * thr)22638 DUK_INTERNAL duk_hboundfunc *duk_push_hboundfunc(duk_hthread *thr) {
22639 	duk_hboundfunc *obj;
22640 	duk_tval *tv_slot;
22641 
22642 	DUK_ASSERT_API_ENTRY(thr);
22643 
22644 	DUK__CHECK_SPACE();
22645 	obj = duk_hboundfunc_alloc(thr->heap,
22646 	                           DUK_HOBJECT_FLAG_EXTENSIBLE |
22647 	                           DUK_HOBJECT_FLAG_BOUNDFUNC |
22648 	                           DUK_HOBJECT_FLAG_CONSTRUCTABLE |
22649 	                           DUK_HOBJECT_FLAG_CALLABLE |
22650 	                           DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));
22651 	if (!obj) {
22652 		DUK_ERROR_ALLOC_FAILED(thr);
22653 		DUK_WO_NORETURN(return NULL;);
22654 	}
22655 
22656 	tv_slot = thr->valstack_top++;
22657 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22658 	DUK_HOBJECT_INCREF(thr, obj);
22659 
22660 	/* Prototype is left as NULL because the caller always sets it (and
22661 	 * it depends on the target function).
22662 	 */
22663 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) obj) == NULL);
22664 
22665 	return obj;
22666 }
22667 
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)22668 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) {
22669 	duk_hnatfunc *obj;
22670 	duk_idx_t ret;
22671 	duk_tval *tv_slot;
22672 	duk_int16_t func_nargs;
22673 
22674 	DUK_ASSERT_CTX_VALID(thr);
22675 
22676 	DUK__CHECK_SPACE();
22677 
22678 	if (DUK_UNLIKELY(func == NULL)) {
22679 		goto api_error;
22680 	}
22681 	if (nargs >= 0 && nargs < DUK_HNATFUNC_NARGS_MAX) {
22682 		func_nargs = (duk_int16_t) nargs;
22683 	} else if (nargs == DUK_VARARGS) {
22684 		func_nargs = DUK_HNATFUNC_NARGS_VARARGS;
22685 	} else {
22686 		goto api_error;
22687 	}
22688 
22689 	obj = duk_hnatfunc_alloc(thr, flags);
22690 	DUK_ASSERT(obj != NULL);
22691 
22692 	obj->func = func;
22693 	obj->nargs = func_nargs;
22694 
22695 	DUK_DDD(DUK_DDDPRINT("created native function object with flags: 0x%08lx, nargs=%ld",
22696 	                     (unsigned long) obj->obj.hdr.h_flags, (long) obj->nargs));
22697 
22698 	tv_slot = thr->valstack_top;
22699 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22700 	DUK_HOBJECT_INCREF(thr, obj);
22701 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
22702 	thr->valstack_top++;
22703 
22704 	DUK_ASSERT_BIDX_VALID(proto_bidx);
22705 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[proto_bidx]);
22706 	return ret;
22707 
22708  api_error:
22709 	DUK_ERROR_TYPE_INVALID_ARGS(thr);
22710 	DUK_WO_NORETURN(return 0;);
22711 }
22712 
duk_push_c_function(duk_hthread * thr,duk_c_function func,duk_int_t nargs)22713 DUK_EXTERNAL duk_idx_t duk_push_c_function(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {
22714 	duk_uint_t flags;
22715 
22716 	DUK_ASSERT_API_ENTRY(thr);
22717 
22718 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
22719 	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
22720 	        DUK_HOBJECT_FLAG_CALLABLE |
22721 	        DUK_HOBJECT_FLAG_FASTREFS |
22722 	        DUK_HOBJECT_FLAG_NATFUNC |
22723 	        DUK_HOBJECT_FLAG_NEWENV |
22724 	        DUK_HOBJECT_FLAG_STRICT |
22725 	        DUK_HOBJECT_FLAG_NOTAIL |
22726 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
22727 
22728 	/* Default prototype is a Duktape specific %NativeFunctionPrototype%
22729 	 * which provides .length and .name getters.
22730 	 */
22731 	return duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE);
22732 }
22733 
duk_push_c_function_builtin(duk_hthread * thr,duk_c_function func,duk_int_t nargs)22734 DUK_INTERNAL void duk_push_c_function_builtin(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {
22735 	duk_uint_t flags;
22736 
22737 	DUK_ASSERT_API_ENTRY(thr);
22738 
22739 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
22740 	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
22741 	        DUK_HOBJECT_FLAG_CALLABLE |
22742 	        DUK_HOBJECT_FLAG_FASTREFS |
22743 	        DUK_HOBJECT_FLAG_NATFUNC |
22744 	        DUK_HOBJECT_FLAG_NEWENV |
22745 	        DUK_HOBJECT_FLAG_STRICT |
22746 	        DUK_HOBJECT_FLAG_NOTAIL |
22747 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
22748 
22749 	/* Must use Function.prototype for standard built-in functions. */
22750 	(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_FUNCTION_PROTOTYPE);
22751 }
22752 
duk_push_c_function_builtin_noconstruct(duk_hthread * thr,duk_c_function func,duk_int_t nargs)22753 DUK_INTERNAL void duk_push_c_function_builtin_noconstruct(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {
22754 	duk_uint_t flags;
22755 
22756 	DUK_ASSERT_API_ENTRY(thr);
22757 
22758 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
22759 	        DUK_HOBJECT_FLAG_CALLABLE |
22760 	        DUK_HOBJECT_FLAG_FASTREFS |
22761 	        DUK_HOBJECT_FLAG_NATFUNC |
22762 	        DUK_HOBJECT_FLAG_NEWENV |
22763 	        DUK_HOBJECT_FLAG_STRICT |
22764 	        DUK_HOBJECT_FLAG_NOTAIL |
22765 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
22766 
22767 	/* Must use Function.prototype for standard built-in functions. */
22768 	(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_FUNCTION_PROTOTYPE);
22769 }
22770 
duk_push_c_lightfunc(duk_hthread * thr,duk_c_function func,duk_idx_t nargs,duk_idx_t length,duk_int_t magic)22771 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) {
22772 	duk_small_uint_t lf_flags;
22773 	duk_tval *tv_slot;
22774 
22775 	DUK_ASSERT_API_ENTRY(thr);
22776 
22777 	DUK__CHECK_SPACE();
22778 
22779 	if (nargs >= DUK_LFUNC_NARGS_MIN && nargs <= DUK_LFUNC_NARGS_MAX) {
22780 		/* as is */
22781 	} else if (nargs == DUK_VARARGS) {
22782 		nargs = DUK_LFUNC_NARGS_VARARGS;
22783 	} else {
22784 		goto api_error;
22785 	}
22786 	if (DUK_UNLIKELY(!(length >= DUK_LFUNC_LENGTH_MIN && length <= DUK_LFUNC_LENGTH_MAX))) {
22787 		goto api_error;
22788 	}
22789 	if (DUK_UNLIKELY(!(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX))) {
22790 		goto api_error;
22791 	}
22792 
22793 	lf_flags = DUK_LFUNC_FLAGS_PACK((duk_small_int_t) magic, (duk_small_uint_t) length, (duk_small_uint_t) nargs);
22794 	tv_slot = thr->valstack_top++;
22795 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_slot));
22796 	DUK_TVAL_SET_LIGHTFUNC(tv_slot, func, lf_flags);
22797 	DUK_ASSERT(tv_slot >= thr->valstack_bottom);
22798 	return (duk_idx_t) (tv_slot - thr->valstack_bottom);
22799 
22800  api_error:
22801 	DUK_ERROR_TYPE_INVALID_ARGS(thr);
22802 	DUK_WO_NORETURN(return 0;);
22803 }
22804 
22805 #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)22806 DUK_INTERNAL duk_hbufobj *duk_push_bufobj_raw(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
22807 	duk_hbufobj *obj;
22808 	duk_tval *tv_slot;
22809 
22810 	DUK_ASSERT_API_ENTRY(thr);
22811 	DUK_ASSERT(prototype_bidx >= 0);
22812 
22813 	DUK__CHECK_SPACE();
22814 
22815 	obj = duk_hbufobj_alloc(thr, hobject_flags_and_class);
22816 	DUK_ASSERT(obj != NULL);
22817 
22818 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[prototype_bidx]);
22819 	DUK_ASSERT_HBUFOBJ_VALID(obj);
22820 
22821 	tv_slot = thr->valstack_top;
22822 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22823 	DUK_HOBJECT_INCREF(thr, obj);
22824 	thr->valstack_top++;
22825 
22826 	return obj;
22827 }
22828 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
22829 
22830 /* XXX: There's quite a bit of overlap with buffer creation handling in
22831  * duk_bi_buffer.c.  Look for overlap and refactor.
22832  */
22833 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22834 #define DUK__PACK_ARGS(classnum,protobidx,elemtype,elemshift,istypedarray) \
22835 	(((classnum) << 24) | ((protobidx) << 16) | ((elemtype) << 8) | ((elemshift) << 4) | (istypedarray))
22836 
22837 static const duk_uint32_t duk__bufobj_flags_lookup[] = {
22838 	/* Node.js Buffers are Uint8Array instances which inherit from Buffer.prototype. */
22839 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_ARRAYBUFFER,       DUK_BIDX_ARRAYBUFFER_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT8,        0, 0),  /* DUK_BUFOBJ_ARRAYBUFFER */
22840 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY,        DUK_BIDX_NODEJS_BUFFER_PROTOTYPE,     DUK_HBUFOBJ_ELEM_UINT8,        0, 1),  /* DUK_BUFOBJ_NODEJS_BUFFER */
22841 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_DATAVIEW,          DUK_BIDX_DATAVIEW_PROTOTYPE,          DUK_HBUFOBJ_ELEM_UINT8,        0, 0),  /* DUK_BUFOBJ_DATAVIEW */
22842 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT8ARRAY,         DUK_BIDX_INT8ARRAY_PROTOTYPE,         DUK_HBUFOBJ_ELEM_INT8,         0, 1),  /* DUK_BUFOBJ_INT8ARRAY */
22843 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY,        DUK_BIDX_UINT8ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_UINT8,        0, 1),  /* DUK_BUFOBJ_UINT8ARRAY */
22844 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY, DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT8CLAMPED, 0, 1),  /* DUK_BUFOBJ_UINT8CLAMPEDARRAY */
22845 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT16ARRAY,        DUK_BIDX_INT16ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_INT16,        1, 1),  /* DUK_BUFOBJ_INT16ARRAY */
22846 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT16ARRAY,       DUK_BIDX_UINT16ARRAY_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT16,       1, 1),  /* DUK_BUFOBJ_UINT16ARRAY */
22847 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT32ARRAY,        DUK_BIDX_INT32ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_INT32,        2, 1),  /* DUK_BUFOBJ_INT32ARRAY */
22848 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT32ARRAY,       DUK_BIDX_UINT32ARRAY_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT32,       2, 1),  /* DUK_BUFOBJ_UINT32ARRAY */
22849 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT32ARRAY,      DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,      DUK_HBUFOBJ_ELEM_FLOAT32,      2, 1),  /* DUK_BUFOBJ_FLOAT32ARRAY */
22850 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT64ARRAY,      DUK_BIDX_FLOAT64ARRAY_PROTOTYPE,      DUK_HBUFOBJ_ELEM_FLOAT64,      3, 1)   /* DUK_BUFOBJ_FLOAT64ARRAY */
22851 };
22852 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
22853 
22854 #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)22855 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) {
22856 	duk_hbufobj *h_bufobj;
22857 	duk_hbuffer *h_val;
22858 	duk_hobject *h_arraybuf;
22859 	duk_uint32_t tmp;
22860 	duk_uint_t classnum;
22861 	duk_uint_t protobidx;
22862 	duk_uint_t lookupidx;
22863 	duk_uint_t uint_offset, uint_length, uint_added;
22864 
22865 	DUK_ASSERT_API_ENTRY(thr);
22866 
22867 	/* The underlying types for offset/length in duk_hbufobj is
22868 	 * duk_uint_t; make sure argument values fit.
22869 	 */
22870 	uint_offset = (duk_uint_t) byte_offset;
22871 	uint_length = (duk_uint_t) byte_length;
22872 	if (sizeof(duk_size_t) != sizeof(duk_uint_t)) {
22873 		if (DUK_UNLIKELY((duk_size_t) uint_offset != byte_offset || (duk_size_t) uint_length != byte_length)) {
22874 			goto range_error;
22875 		}
22876 	}
22877 
22878 	DUK_ASSERT_DISABLE(flags >= 0);  /* flags is unsigned */
22879 	lookupidx = flags;
22880 	if (DUK_UNLIKELY(lookupidx >= sizeof(duk__bufobj_flags_lookup) / sizeof(duk_uint32_t))) {
22881 		goto arg_error;
22882 	}
22883 	tmp = duk__bufobj_flags_lookup[lookupidx];
22884 	classnum = tmp >> 24;
22885 	protobidx = (tmp >> 16) & 0xff;
22886 
22887 	h_arraybuf = duk_get_hobject(thr, idx_buffer);
22888 	if (h_arraybuf != NULL &&  /* argument is an object */
22889 	    flags != DUK_BUFOBJ_ARRAYBUFFER &&  /* creating a view */
22890 	    DUK_HOBJECT_GET_CLASS_NUMBER(h_arraybuf) == DUK_HOBJECT_CLASS_ARRAYBUFFER  /* argument is ArrayBuffer */) {
22891 		duk_uint_t tmp_offset;
22892 
22893 		DUK_ASSERT_HBUFOBJ_VALID((duk_hbufobj *) h_arraybuf);
22894 		h_val = ((duk_hbufobj *) h_arraybuf)->buf;
22895 		if (DUK_UNLIKELY(h_val == NULL)) {
22896 			goto arg_error;
22897 		}
22898 
22899 		tmp_offset = uint_offset + ((duk_hbufobj *) h_arraybuf)->offset;
22900 		if (DUK_UNLIKELY(tmp_offset < uint_offset)) {
22901 			goto range_error;
22902 		}
22903 		uint_offset = tmp_offset;
22904 
22905 		/* Note intentional difference to new TypedArray(): we allow
22906 		 * caller to create an uncovered typed array (which is memory
22907 		 * safe); new TypedArray() rejects it.
22908 		 */
22909 	} else {
22910 		/* Handle unexpected object arguments here too, for nice error
22911 		 * messages.
22912 		 */
22913 		h_arraybuf = NULL;
22914 		h_val = duk_require_hbuffer(thr, idx_buffer);
22915 	}
22916 
22917 	/* Wrap check for offset+length. */
22918 	uint_added = uint_offset + uint_length;
22919 	if (DUK_UNLIKELY(uint_added < uint_offset)) {
22920 		goto range_error;
22921 	}
22922 	DUK_ASSERT(uint_added >= uint_offset && uint_added >= uint_length);
22923 
22924 	DUK_ASSERT(h_val != NULL);
22925 
22926 	h_bufobj = duk_push_bufobj_raw(thr,
22927 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
22928 	                               DUK_HOBJECT_FLAG_BUFOBJ |
22929 	                               DUK_HOBJECT_CLASS_AS_FLAGS(classnum),
22930 	                               (duk_small_int_t) protobidx);
22931 	DUK_ASSERT(h_bufobj != NULL);
22932 
22933 	h_bufobj->buf = h_val;
22934 	DUK_HBUFFER_INCREF(thr, h_val);
22935 	h_bufobj->buf_prop = h_arraybuf;
22936 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, h_arraybuf);
22937 	h_bufobj->offset = uint_offset;
22938 	h_bufobj->length = uint_length;
22939 	h_bufobj->shift = (tmp >> 4) & 0x0f;
22940 	h_bufobj->elem_type = (tmp >> 8) & 0xff;
22941 	h_bufobj->is_typedarray = tmp & 0x0f;
22942 	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
22943 
22944 	/* TypedArray views need an automatic ArrayBuffer which must be
22945 	 * provided as .buffer property of the view.  The ArrayBuffer is
22946 	 * referenced via duk_hbufobj->buf_prop and an inherited .buffer
22947 	 * accessor returns it.  The ArrayBuffer is created lazily on first
22948 	 * access if necessary so we don't need to do anything more here.
22949 	 */
22950 	return;
22951 
22952  range_error:
22953 	DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARGS);
22954 	DUK_WO_NORETURN(return;);
22955 
22956  arg_error:
22957 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_ARGS);
22958 	DUK_WO_NORETURN(return;);
22959 }
22960 #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)22961 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) {
22962 	DUK_ASSERT_API_ENTRY(thr);
22963 	DUK_UNREF(idx_buffer);
22964 	DUK_UNREF(byte_offset);
22965 	DUK_UNREF(byte_length);
22966 	DUK_UNREF(flags);
22967 	DUK_ERROR_UNSUPPORTED(thr);
22968 	DUK_WO_NORETURN(return;);
22969 }
22970 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
22971 
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)22972 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) {
22973 	duk_hobject *proto;
22974 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
22975 	duk_small_uint_t augment_flags;
22976 #endif
22977 
22978 	DUK_ASSERT_API_ENTRY(thr);
22979 	DUK_ASSERT(thr != NULL);
22980 	DUK_UNREF(filename);
22981 	DUK_UNREF(line);
22982 
22983 	/* Error code also packs a tracedata related flag. */
22984 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
22985 	augment_flags = 0;
22986 	if (err_code & DUK_ERRCODE_FLAG_NOBLAME_FILELINE) {
22987 		augment_flags = DUK_AUGMENT_FLAG_NOBLAME_FILELINE;
22988 	}
22989 #endif
22990 	err_code = err_code & (~DUK_ERRCODE_FLAG_NOBLAME_FILELINE);
22991 
22992 	/* error gets its 'name' from the prototype */
22993 	proto = duk_error_prototype_from_code(thr, err_code);
22994 	(void) duk_push_object_helper_proto(thr,
22995 	                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
22996 	                                    DUK_HOBJECT_FLAG_FASTREFS |
22997 	                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR),
22998 	                                    proto);
22999 
23000 	/* ... and its 'message' from an instance property */
23001 	if (fmt) {
23002 		duk_push_vsprintf(thr, fmt, ap);
23003 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
23004 	} else {
23005 		/* If no explicit message given, put error code into message field
23006 		 * (as a number).  This is not fully in keeping with the ECMAScript
23007 		 * error model because messages are supposed to be strings (Error
23008 		 * constructors use ToString() on their argument).  However, it's
23009 		 * probably more useful than having a separate 'code' property.
23010 		 */
23011 		duk_push_int(thr, err_code);
23012 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
23013 	}
23014 
23015 	/* XXX: .code = err_code disabled, not sure if useful */
23016 
23017 	/* Creation time error augmentation */
23018 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
23019 	/* filename may be NULL in which case file/line is not recorded */
23020 	duk_err_augment_error_create(thr, thr, filename, line, augment_flags);  /* may throw an error */
23021 #endif
23022 
23023 	return duk_get_top_index_unsafe(thr);
23024 }
23025 
duk_push_error_object_raw(duk_hthread * thr,duk_errcode_t err_code,const char * filename,duk_int_t line,const char * fmt,...)23026 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, ...) {
23027 	va_list ap;
23028 	duk_idx_t ret;
23029 
23030 	DUK_ASSERT_API_ENTRY(thr);
23031 
23032 	va_start(ap, fmt);
23033 	ret = duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
23034 	va_end(ap);
23035 	return ret;
23036 }
23037 
23038 #if !defined(DUK_USE_VARIADIC_MACROS)
duk_push_error_object_stash(duk_hthread * thr,duk_errcode_t err_code,const char * fmt,...)23039 DUK_EXTERNAL duk_idx_t duk_push_error_object_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, ...) {
23040 	const char *filename = duk_api_global_filename;
23041 	duk_int_t line = duk_api_global_line;
23042 	va_list ap;
23043 	duk_idx_t ret;
23044 
23045 	DUK_ASSERT_API_ENTRY(thr);
23046 
23047 	duk_api_global_filename = NULL;
23048 	duk_api_global_line = 0;
23049 	va_start(ap, fmt);
23050 	ret = duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
23051 	va_end(ap);
23052 	return ret;
23053 }
23054 #endif  /* DUK_USE_VARIADIC_MACROS */
23055 
duk_push_buffer_raw(duk_hthread * thr,duk_size_t size,duk_small_uint_t flags)23056 DUK_EXTERNAL void *duk_push_buffer_raw(duk_hthread *thr, duk_size_t size, duk_small_uint_t flags) {
23057 	duk_tval *tv_slot;
23058 	duk_hbuffer *h;
23059 	void *buf_data;
23060 
23061 	DUK_ASSERT_API_ENTRY(thr);
23062 
23063 	DUK__CHECK_SPACE();
23064 
23065 	/* Check for maximum buffer length. */
23066 	if (DUK_UNLIKELY(size > DUK_HBUFFER_MAX_BYTELEN)) {
23067 		DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);
23068 		DUK_WO_NORETURN(return NULL;);
23069 	}
23070 
23071 	h = duk_hbuffer_alloc(thr->heap, size, flags, &buf_data);
23072 	if (DUK_UNLIKELY(h == NULL)) {
23073 		DUK_ERROR_ALLOC_FAILED(thr);
23074 		DUK_WO_NORETURN(return NULL;);
23075 	}
23076 
23077 	tv_slot = thr->valstack_top;
23078 	DUK_TVAL_SET_BUFFER(tv_slot, h);
23079 	DUK_HBUFFER_INCREF(thr, h);
23080 	thr->valstack_top++;
23081 
23082 	return (void *) buf_data;
23083 }
23084 
duk_push_fixed_buffer_nozero(duk_hthread * thr,duk_size_t len)23085 DUK_INTERNAL void *duk_push_fixed_buffer_nozero(duk_hthread *thr, duk_size_t len) {
23086 	DUK_ASSERT_API_ENTRY(thr);
23087 	return duk_push_buffer_raw(thr, len, DUK_BUF_FLAG_NOZERO);
23088 }
23089 
duk_push_fixed_buffer_zero(duk_hthread * thr,duk_size_t len)23090 DUK_INTERNAL void *duk_push_fixed_buffer_zero(duk_hthread *thr, duk_size_t len) {
23091 	void *ptr;
23092 
23093 	DUK_ASSERT_API_ENTRY(thr);
23094 
23095 	ptr = duk_push_buffer_raw(thr, len, 0);
23096 	DUK_ASSERT(ptr != NULL);
23097 #if !defined(DUK_USE_ZERO_BUFFER_DATA)
23098 	/* ES2015 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA
23099 	 * is not set.
23100 	 */
23101 	duk_memzero((void *) ptr, (size_t) len);
23102 #endif
23103 	return ptr;
23104 }
23105 
23106 #if defined(DUK_USE_ES6_PROXY)
duk_push_proxy(duk_hthread * thr,duk_uint_t proxy_flags)23107 DUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags) {
23108 	duk_hobject *h_target;
23109 	duk_hobject *h_handler;
23110 	duk_hproxy *h_proxy;
23111 	duk_tval *tv_slot;
23112 	duk_uint_t flags;
23113 
23114 	DUK_ASSERT_API_ENTRY(thr);
23115 	DUK_UNREF(proxy_flags);
23116 
23117 	/* DUK__CHECK_SPACE() unnecessary because the Proxy is written to
23118 	 * value stack in-place.
23119 	 */
23120 #if 0
23121 	DUK__CHECK_SPACE();
23122 #endif
23123 
23124 	/* Reject a proxy object as the target because it would need
23125 	 * special handling in property lookups.  (ES2015 has no such
23126 	 * restriction.)
23127 	 */
23128 	h_target = duk_require_hobject_promote_mask(thr, -2, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
23129 	DUK_ASSERT(h_target != NULL);
23130 	if (DUK_HOBJECT_IS_PROXY(h_target)) {
23131 		goto fail_args;
23132 	}
23133 
23134 	/* Reject a proxy object as the handler because it would cause
23135 	 * potentially unbounded recursion.  (ES2015 has no such
23136 	 * restriction.)
23137 	 *
23138 	 * There's little practical reason to use a lightfunc or a plain
23139 	 * buffer as the handler table: one could only provide traps via
23140 	 * their prototype objects (Function.prototype and ArrayBuffer.prototype).
23141 	 * Even so, as lightfuncs and plain buffers mimic their object
23142 	 * counterparts, they're promoted and accepted here.
23143 	 */
23144 	h_handler = duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
23145 	DUK_ASSERT(h_handler != NULL);
23146 	if (DUK_HOBJECT_IS_PROXY(h_handler)) {
23147 		goto fail_args;
23148 	}
23149 
23150 	/* XXX: Proxy object currently has no prototype, so ToPrimitive()
23151 	 * coercion fails which is a bit confusing.
23152 	 */
23153 
23154 	/* CALLABLE and CONSTRUCTABLE flags are copied from the (initial)
23155 	 * target, see ES2015 Sections 9.5.15 and 9.5.13.
23156 	 */
23157 	flags = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h_target) &
23158 	        (DUK_HOBJECT_FLAG_CALLABLE | DUK_HOBJECT_FLAG_CONSTRUCTABLE);
23159 	flags |= DUK_HOBJECT_FLAG_EXTENSIBLE |
23160 	         DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ;
23161 	if (flags & DUK_HOBJECT_FLAG_CALLABLE) {
23162 		flags |= DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION) |
23163 		         DUK_HOBJECT_FLAG_SPECIAL_CALL;
23164 	} else {
23165 		flags |= DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT);
23166 	}
23167 
23168 	h_proxy = duk_hproxy_alloc(thr, flags);
23169 	DUK_ASSERT(h_proxy != NULL);
23170 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_proxy) == NULL);
23171 
23172 	/* Initialize Proxy target and handler references; avoid INCREF
23173 	 * by stealing the value stack refcounts via direct value stack
23174 	 * manipulation.  INCREF is needed for the Proxy itself however.
23175 	 */
23176 	DUK_ASSERT(h_target != NULL);
23177 	h_proxy->target = h_target;
23178 	DUK_ASSERT(h_handler != NULL);
23179 	h_proxy->handler = h_handler;
23180 	DUK_ASSERT_HPROXY_VALID(h_proxy);
23181 
23182 	DUK_ASSERT(duk_get_hobject(thr, -2) == h_target);
23183 	DUK_ASSERT(duk_get_hobject(thr, -1) == h_handler);
23184 	tv_slot = thr->valstack_top - 2;
23185 	DUK_ASSERT(tv_slot >= thr->valstack_bottom);
23186 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) h_proxy);
23187 	DUK_HOBJECT_INCREF(thr, (duk_hobject *) h_proxy);
23188 	tv_slot++;
23189 	DUK_TVAL_SET_UNDEFINED(tv_slot);  /* [ ... target handler ] -> [ ... proxy undefined ] */
23190 	thr->valstack_top = tv_slot;      /* -> [ ... proxy ] */
23191 
23192 	DUK_DD(DUK_DDPRINT("created Proxy: %!iT", duk_get_tval(thr, -1)));
23193 
23194 	return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom - 1);
23195 
23196  fail_args:
23197 	DUK_ERROR_TYPE_INVALID_ARGS(thr);
23198 	DUK_WO_NORETURN(return 0;);
23199 }
23200 #else  /* DUK_USE_ES6_PROXY */
duk_push_proxy(duk_hthread * thr,duk_uint_t proxy_flags)23201 DUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags) {
23202 	DUK_ASSERT_API_ENTRY(thr);
23203 	DUK_UNREF(proxy_flags);
23204 	DUK_ERROR_UNSUPPORTED(thr);
23205 	DUK_WO_NORETURN(return 0;);
23206 }
23207 #endif  /* DUK_USE_ES6_PROXY */
23208 
23209 #if defined(DUK_USE_ASSERTIONS)
duk__validate_push_heapptr(duk_hthread * thr,void * ptr)23210 DUK_LOCAL void duk__validate_push_heapptr(duk_hthread *thr, void *ptr) {
23211 	duk_heaphdr *h;
23212 	duk_heaphdr *curr;
23213 	duk_bool_t found = 0;
23214 
23215 	h = (duk_heaphdr *) ptr;
23216 	if (h == NULL) {
23217 		/* Allowed. */
23218 		return;
23219 	}
23220 	DUK_ASSERT(h != NULL);
23221 	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
23222 
23223 	/* One particular problem case is where an object has been
23224 	 * queued for finalization but the finalizer hasn't yet been
23225 	 * executed.
23226 	 *
23227 	 * Corner case: we're running in a finalizer for object X, and
23228 	 * user code calls duk_push_heapptr() for X itself.  In this
23229 	 * case X will be in finalize_list, and we can detect the case
23230 	 * by seeing that X's FINALIZED flag is set (which is done before
23231 	 * the finalizer starts executing).
23232 	 */
23233 #if defined(DUK_USE_FINALIZER_SUPPORT)
23234 	for (curr = thr->heap->finalize_list;
23235 	     curr != NULL;
23236 	     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
23237 		/* FINALIZABLE is set for all objects on finalize_list
23238 		 * except for an object being finalized right now.  So
23239 		 * can't assert here.
23240 		 */
23241 #if 0
23242 		DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(curr));
23243 #endif
23244 
23245 		if (curr == h) {
23246 			if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h)) {
23247 				/* Object is currently being finalized. */
23248 				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
23249 				found = 1;
23250 			} else {
23251 				/* Not being finalized but on finalize_list,
23252 				 * allowed since Duktape 2.1.
23253 				 */
23254 				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
23255 				found = 1;
23256 			}
23257 		}
23258 	}
23259 #endif  /* DUK_USE_FINALIZER_SUPPORT */
23260 
23261 #if defined(DUK_USE_REFERENCE_COUNTING)
23262 	/* Because refzero_list is now processed to completion inline with
23263 	 * no side effects, it's always empty here.
23264 	 */
23265 	DUK_ASSERT(thr->heap->refzero_list == NULL);
23266 #endif
23267 
23268 	/* If not present in finalize_list (or refzero_list), it
23269 	 * must be either in heap_allocated or the string table.
23270 	 */
23271 	if (DUK_HEAPHDR_IS_STRING(h)) {
23272 		duk_uint32_t i;
23273 		duk_hstring *str;
23274 		duk_heap *heap = thr->heap;
23275 
23276 		DUK_ASSERT(found == 0);
23277 		for (i = 0; i < heap->st_size; i++) {
23278 #if defined(DUK_USE_STRTAB_PTRCOMP)
23279 			str = DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, heap->strtable16[i]);
23280 #else
23281 			str = heap->strtable[i];
23282 #endif
23283 			while (str != NULL) {
23284 				if (str == (duk_hstring *) h) {
23285 					DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
23286 					found = 1;
23287 					break;
23288 				}
23289 				str = str->hdr.h_next;
23290 			}
23291 		}
23292 		DUK_ASSERT(found != 0);
23293 	} else {
23294 		for (curr = thr->heap->heap_allocated;
23295 		     curr != NULL;
23296 		     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
23297 			if (curr == h) {
23298 				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
23299 				found = 1;
23300 			}
23301 		}
23302 		DUK_ASSERT(found != 0);
23303 	}
23304 }
23305 #endif  /* DUK_USE_ASSERTIONS */
23306 
duk_push_heapptr(duk_hthread * thr,void * ptr)23307 DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_hthread *thr, void *ptr) {
23308 	duk_idx_t ret;
23309 	duk_tval *tv;
23310 
23311 	DUK_ASSERT_API_ENTRY(thr);
23312 
23313 	/* Reviving an object using a heap pointer is a dangerous API
23314 	 * operation: if the application doesn't guarantee that the
23315 	 * pointer target is always reachable, difficult-to-diagnose
23316 	 * problems may ensue.  Try to validate the 'ptr' argument to
23317 	 * the extent possible.
23318 	 */
23319 
23320 #if defined(DUK_USE_ASSERTIONS)
23321 	duk__validate_push_heapptr(thr, ptr);
23322 #endif
23323 
23324 	DUK__CHECK_SPACE();
23325 
23326 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
23327 	tv = thr->valstack_top++;
23328 
23329 	if (ptr == NULL) {
23330 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
23331 		return ret;
23332 	}
23333 
23334 	DUK_ASSERT_HEAPHDR_VALID((duk_heaphdr *) ptr);
23335 
23336 	/* If the argument is on finalize_list it has technically been
23337 	 * unreachable before duk_push_heapptr() but it's still safe to
23338 	 * push it.  Starting from Duktape 2.1 allow application code to
23339 	 * do so.  There are two main cases:
23340 	 *
23341 	 *   (1) The object is on the finalize_list and we're called by
23342 	 *       the finalizer for the object being finalized.  In this
23343 	 *       case do nothing: finalize_list handling will deal with
23344 	 *       the object queueing.  This is detected by the object not
23345 	 *       having a FINALIZABLE flag despite being on the finalize_list;
23346 	 *       the flag is cleared for the object being finalized only.
23347 	 *
23348 	 *   (2) The object is on the finalize_list but is not currently
23349 	 *       being processed.  In this case the object can be queued
23350 	 *       back to heap_allocated with a few flags cleared, in effect
23351 	 *       cancelling the finalizer.
23352 	 */
23353 	if (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) ptr))) {
23354 		duk_heaphdr *curr;
23355 
23356 		DUK_D(DUK_DPRINT("duk_push_heapptr() with a pointer on finalize_list, autorescue"));
23357 
23358 		curr = (duk_heaphdr *) ptr;
23359 		DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
23360 
23361 		/* Because FINALIZED is set prior to finalizer call, it will
23362 		 * be set for the object being currently finalized, but not
23363 		 * for other objects on finalize_list.
23364 		 */
23365 		DUK_HEAPHDR_CLEAR_FINALIZED(curr);
23366 
23367 		/* Dequeue object from finalize_list and queue it back to
23368 		 * heap_allocated.
23369 		 */
23370 #if defined(DUK_USE_REFERENCE_COUNTING)
23371 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);  /* Preincremented on finalize_list insert. */
23372 		DUK_HEAPHDR_PREDEC_REFCOUNT(curr);
23373 #endif
23374 		DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(thr->heap, curr);
23375 		DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(thr->heap, curr);
23376 
23377 		/* Continue with the rest. */
23378 	}
23379 
23380 	switch (DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr)) {
23381 	case DUK_HTYPE_STRING:
23382 		DUK_TVAL_SET_STRING(tv, (duk_hstring *) ptr);
23383 		break;
23384 	case DUK_HTYPE_OBJECT:
23385 		DUK_TVAL_SET_OBJECT(tv, (duk_hobject *) ptr);
23386 		break;
23387 	default:
23388 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr) == DUK_HTYPE_BUFFER);
23389 		DUK_TVAL_SET_BUFFER(tv, (duk_hbuffer *) ptr);
23390 		break;
23391 	}
23392 
23393 	DUK_HEAPHDR_INCREF(thr, (duk_heaphdr *) ptr);
23394 
23395 	return ret;
23396 }
23397 
23398 /* Push object with no prototype, i.e. a "bare" object. */
duk_push_bare_object(duk_hthread * thr)23399 DUK_EXTERNAL duk_idx_t duk_push_bare_object(duk_hthread *thr) {
23400 	DUK_ASSERT_API_ENTRY(thr);
23401 
23402 	(void) duk_push_object_helper(thr,
23403 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
23404 	                              DUK_HOBJECT_FLAG_FASTREFS |
23405 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
23406 	                              -1);  /* no prototype */
23407 	return duk_get_top_index_unsafe(thr);
23408 }
23409 
duk_push_hstring(duk_hthread * thr,duk_hstring * h)23410 DUK_INTERNAL void duk_push_hstring(duk_hthread *thr, duk_hstring *h) {
23411 	duk_tval tv;
23412 
23413 	DUK_ASSERT_API_ENTRY(thr);
23414 	DUK_ASSERT(h != NULL);
23415 
23416 	DUK_TVAL_SET_STRING(&tv, h);
23417 	duk_push_tval(thr, &tv);
23418 }
23419 
duk_push_hstring_stridx(duk_hthread * thr,duk_small_uint_t stridx)23420 DUK_INTERNAL void duk_push_hstring_stridx(duk_hthread *thr, duk_small_uint_t stridx) {
23421 	DUK_ASSERT_API_ENTRY(thr);
23422 	DUK_ASSERT_STRIDX_VALID(stridx);
23423 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
23424 }
23425 
duk_push_hstring_empty(duk_hthread * thr)23426 DUK_INTERNAL void duk_push_hstring_empty(duk_hthread *thr) {
23427 	DUK_ASSERT_API_ENTRY(thr);
23428 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, DUK_STRIDX_EMPTY_STRING));
23429 }
23430 
duk_push_hobject(duk_hthread * thr,duk_hobject * h)23431 DUK_INTERNAL void duk_push_hobject(duk_hthread *thr, duk_hobject *h) {
23432 	duk_tval tv;
23433 
23434 	DUK_ASSERT_API_ENTRY(thr);
23435 	DUK_ASSERT(h != NULL);
23436 
23437 	DUK_TVAL_SET_OBJECT(&tv, h);
23438 	duk_push_tval(thr, &tv);
23439 }
23440 
duk_push_hbuffer(duk_hthread * thr,duk_hbuffer * h)23441 DUK_INTERNAL void duk_push_hbuffer(duk_hthread *thr, duk_hbuffer *h) {
23442 	duk_tval tv;
23443 
23444 	DUK_ASSERT_API_ENTRY(thr);
23445 	DUK_ASSERT(h != NULL);
23446 
23447 	DUK_TVAL_SET_BUFFER(&tv, h);
23448 	duk_push_tval(thr, &tv);
23449 }
23450 
duk_push_hobject_bidx(duk_hthread * thr,duk_small_int_t builtin_idx)23451 DUK_INTERNAL void duk_push_hobject_bidx(duk_hthread *thr, duk_small_int_t builtin_idx) {
23452 	DUK_ASSERT_API_ENTRY(thr);
23453 	DUK_ASSERT(builtin_idx >= 0 && builtin_idx < DUK_NUM_BUILTINS);
23454 	DUK_ASSERT(thr->builtins[builtin_idx] != NULL);
23455 
23456 	duk_push_hobject(thr, thr->builtins[builtin_idx]);
23457 }
23458 
23459 /*
23460  *  Poppers
23461  */
23462 
duk__pop_n_unsafe_raw(duk_hthread * thr,duk_idx_t count)23463 DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_n_unsafe_raw(duk_hthread *thr, duk_idx_t count) {
23464 	duk_tval *tv;
23465 #if defined(DUK_USE_REFERENCE_COUNTING)
23466 	duk_tval *tv_end;
23467 #endif
23468 
23469 	DUK_ASSERT_CTX_VALID(thr);
23470 	DUK_ASSERT(count >= 0);
23471 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) count);
23472 
23473 #if defined(DUK_USE_REFERENCE_COUNTING)
23474 	tv = thr->valstack_top;
23475 	tv_end = tv - count;
23476 	while (tv != tv_end) {
23477 		tv--;
23478 		DUK_ASSERT(tv >= thr->valstack_bottom);
23479 		DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
23480 	}
23481 	thr->valstack_top = tv;
23482 	DUK_REFZERO_CHECK_FAST(thr);
23483 #else
23484 	tv = thr->valstack_top;
23485 	while (count > 0) {
23486 		count--;
23487 		tv--;
23488 		DUK_ASSERT(tv >= thr->valstack_bottom);
23489 		DUK_TVAL_SET_UNDEFINED(tv);
23490 	}
23491 	thr->valstack_top = tv;
23492 #endif
23493 
23494 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23495 }
23496 
duk_pop_n(duk_hthread * thr,duk_idx_t count)23497 DUK_EXTERNAL void duk_pop_n(duk_hthread *thr, duk_idx_t count) {
23498 	DUK_ASSERT_API_ENTRY(thr);
23499 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23500 
23501 	if (DUK_UNLIKELY((duk_uidx_t) (thr->valstack_top - thr->valstack_bottom) < (duk_uidx_t) count)) {
23502 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
23503 		DUK_WO_NORETURN(return;);
23504 	}
23505 	DUK_ASSERT(count >= 0);
23506 
23507 	duk__pop_n_unsafe_raw(thr, count);
23508 }
23509 
23510 #if defined(DUK_USE_PREFER_SIZE)
duk_pop_n_unsafe(duk_hthread * thr,duk_idx_t count)23511 DUK_INTERNAL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count) {
23512 	DUK_ASSERT_API_ENTRY(thr);
23513 	duk_pop_n(thr, count);
23514 }
23515 #else  /* DUK_USE_PREFER_SIZE */
duk_pop_n_unsafe(duk_hthread * thr,duk_idx_t count)23516 DUK_INTERNAL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count) {
23517 	DUK_ASSERT_API_ENTRY(thr);
23518 	duk__pop_n_unsafe_raw(thr, count);
23519 }
23520 #endif  /* DUK_USE_PREFER_SIZE */
23521 
23522 /* Pop N elements without DECREF (in effect "stealing" any actual refcounts). */
23523 #if defined(DUK_USE_REFERENCE_COUNTING)
duk_pop_n_nodecref_unsafe(duk_hthread * thr,duk_idx_t count)23524 DUK_INTERNAL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count) {
23525 	duk_tval *tv;
23526 
23527 	DUK_ASSERT_API_ENTRY(thr);
23528 	DUK_ASSERT(count >= 0);
23529 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23530 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) count);
23531 
23532 	tv = thr->valstack_top;
23533 	while (count > 0) {
23534 		count--;
23535 		tv--;
23536 		DUK_ASSERT(tv >= thr->valstack_bottom);
23537 		DUK_TVAL_SET_UNDEFINED(tv);
23538 	}
23539 	thr->valstack_top = tv;
23540 
23541 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23542 }
23543 #else  /* DUK_USE_REFERENCE_COUNTING */
duk_pop_n_nodecref_unsafe(duk_hthread * thr,duk_idx_t count)23544 DUK_INTERNAL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count) {
23545 	DUK_ASSERT_API_ENTRY(thr);
23546 	duk_pop_n_unsafe(thr, count);
23547 }
23548 #endif  /* DUK_USE_REFERENCE_COUNTING */
23549 
23550 /* Popping one element is called so often that when footprint is not an issue,
23551  * compile a specialized function for it.
23552  */
23553 #if defined(DUK_USE_PREFER_SIZE)
duk_pop(duk_hthread * thr)23554 DUK_EXTERNAL void duk_pop(duk_hthread *thr) {
23555 	DUK_ASSERT_API_ENTRY(thr);
23556 	duk_pop_n(thr, 1);
23557 }
duk_pop_unsafe(duk_hthread * thr)23558 DUK_INTERNAL void duk_pop_unsafe(duk_hthread *thr) {
23559 	DUK_ASSERT_API_ENTRY(thr);
23560 	duk_pop_n_unsafe(thr, 1);
23561 }
duk_pop_nodecref_unsafe(duk_hthread * thr)23562 DUK_INTERNAL void duk_pop_nodecref_unsafe(duk_hthread *thr) {
23563 	DUK_ASSERT_API_ENTRY(thr);
23564 	duk_pop_n_nodecref_unsafe(thr, 1);
23565 }
23566 #else  /* DUK_USE_PREFER_SIZE */
duk__pop_unsafe_raw(duk_hthread * thr)23567 DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_unsafe_raw(duk_hthread *thr) {
23568 	duk_tval *tv;
23569 
23570 	DUK_ASSERT_CTX_VALID(thr);
23571 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
23572 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23573 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);
23574 
23575 	tv = --thr->valstack_top;
23576 	DUK_ASSERT(tv >= thr->valstack_bottom);
23577 #if defined(DUK_USE_REFERENCE_COUNTING)
23578 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
23579 #else
23580 	DUK_TVAL_SET_UNDEFINED(tv);
23581 #endif
23582 
23583 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23584 }
duk_pop(duk_hthread * thr)23585 DUK_EXTERNAL void duk_pop(duk_hthread *thr) {
23586 	DUK_ASSERT_API_ENTRY(thr);
23587 
23588 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23589 	if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {
23590 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
23591 		DUK_WO_NORETURN(return;);
23592 	}
23593 
23594 	duk__pop_unsafe_raw(thr);
23595 }
duk_pop_unsafe(duk_hthread * thr)23596 DUK_INTERNAL void duk_pop_unsafe(duk_hthread *thr) {
23597 	DUK_ASSERT_API_ENTRY(thr);
23598 	duk__pop_unsafe_raw(thr);
23599 }
duk_pop_nodecref_unsafe(duk_hthread * thr)23600 DUK_INTERNAL void duk_pop_nodecref_unsafe(duk_hthread *thr) {
23601 	duk_tval *tv;
23602 
23603 	DUK_ASSERT_API_ENTRY(thr);
23604 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
23605 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23606 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);
23607 
23608 	tv = --thr->valstack_top;
23609 	DUK_ASSERT(tv >= thr->valstack_bottom);
23610 	DUK_TVAL_SET_UNDEFINED(tv);
23611 
23612 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23613 }
23614 #endif  /* !DUK_USE_PREFER_SIZE */
23615 
23616 #if defined(DUK_USE_PREFER_SIZE)
duk_pop_undefined(duk_hthread * thr)23617 DUK_INTERNAL void duk_pop_undefined(duk_hthread *thr) {
23618 	DUK_ASSERT_API_ENTRY(thr);
23619 	duk_pop_nodecref_unsafe(thr);
23620 }
23621 #else  /* DUK_USE_PREFER_SIZE */
duk_pop_undefined(duk_hthread * thr)23622 DUK_INTERNAL void duk_pop_undefined(duk_hthread *thr) {
23623 	DUK_ASSERT_API_ENTRY(thr);
23624 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
23625 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23626 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);
23627 
23628 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
23629 	thr->valstack_top--;
23630 
23631 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23632 }
23633 #endif  /* !DUK_USE_PREFER_SIZE */
23634 
23635 #if defined(DUK_USE_PREFER_SIZE)
duk_pop_2(duk_hthread * thr)23636 DUK_EXTERNAL void duk_pop_2(duk_hthread *thr) {
23637 	DUK_ASSERT_API_ENTRY(thr);
23638 	duk_pop_n(thr, 2);
23639 }
duk_pop_2_unsafe(duk_hthread * thr)23640 DUK_INTERNAL void duk_pop_2_unsafe(duk_hthread *thr) {
23641 	DUK_ASSERT_API_ENTRY(thr);
23642 	duk_pop_n_unsafe(thr, 2);
23643 }
duk_pop_2_nodecref_unsafe(duk_hthread * thr)23644 DUK_INTERNAL void duk_pop_2_nodecref_unsafe(duk_hthread *thr) {
23645 	DUK_ASSERT_API_ENTRY(thr);
23646 	duk_pop_n_nodecref_unsafe(thr, 2);
23647 }
23648 #else
duk__pop_2_unsafe_raw(duk_hthread * thr)23649 DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_2_unsafe_raw(duk_hthread *thr) {
23650 	duk_tval *tv;
23651 
23652 	DUK_ASSERT_CTX_VALID(thr);
23653 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
23654 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23655 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 2);
23656 
23657 	tv = --thr->valstack_top;
23658 	DUK_ASSERT(tv >= thr->valstack_bottom);
23659 #if defined(DUK_USE_REFERENCE_COUNTING)
23660 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
23661 #else
23662 	DUK_TVAL_SET_UNDEFINED(tv);
23663 #endif
23664 	tv = --thr->valstack_top;
23665 	DUK_ASSERT(tv >= thr->valstack_bottom);
23666 #if defined(DUK_USE_REFERENCE_COUNTING)
23667 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
23668 #else
23669 	DUK_TVAL_SET_UNDEFINED(tv);
23670 #endif
23671 
23672 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23673 }
duk_pop_2(duk_hthread * thr)23674 DUK_EXTERNAL void duk_pop_2(duk_hthread *thr) {
23675 	DUK_ASSERT_API_ENTRY(thr);
23676 
23677 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23678 	if (DUK_UNLIKELY(thr->valstack_top - 2 < thr->valstack_bottom)) {
23679 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
23680 		DUK_WO_NORETURN(return;);
23681 	}
23682 
23683 	duk__pop_2_unsafe_raw(thr);
23684 }
duk_pop_2_unsafe(duk_hthread * thr)23685 DUK_INTERNAL void duk_pop_2_unsafe(duk_hthread *thr) {
23686 	DUK_ASSERT_API_ENTRY(thr);
23687 	duk__pop_2_unsafe_raw(thr);
23688 }
duk_pop_2_nodecref_unsafe(duk_hthread * thr)23689 DUK_INTERNAL void duk_pop_2_nodecref_unsafe(duk_hthread *thr) {
23690 	DUK_ASSERT_API_ENTRY(thr);
23691 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
23692 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23693 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 2);
23694 
23695 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
23696 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 2));
23697 	thr->valstack_top -= 2;
23698 
23699 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23700 }
23701 #endif  /* !DUK_USE_PREFER_SIZE */
23702 
duk_pop_3(duk_hthread * thr)23703 DUK_EXTERNAL void duk_pop_3(duk_hthread *thr) {
23704 	DUK_ASSERT_API_ENTRY(thr);
23705 	duk_pop_n(thr, 3);
23706 }
23707 
duk_pop_3_unsafe(duk_hthread * thr)23708 DUK_INTERNAL void duk_pop_3_unsafe(duk_hthread *thr) {
23709 	DUK_ASSERT_API_ENTRY(thr);
23710 	duk_pop_n_unsafe(thr, 3);
23711 }
23712 
duk_pop_3_nodecref_unsafe(duk_hthread * thr)23713 DUK_INTERNAL void duk_pop_3_nodecref_unsafe(duk_hthread *thr) {
23714 	DUK_ASSERT_API_ENTRY(thr);
23715 	duk_pop_n_nodecref_unsafe(thr, 3);
23716 }
23717 
23718 /*
23719  *  Pack and unpack (pack value stack entries into an array and vice versa)
23720  */
23721 
23722 /* XXX: pack index range? array index offset? */
duk_pack(duk_hthread * thr,duk_idx_t count)23723 DUK_INTERNAL void duk_pack(duk_hthread *thr, duk_idx_t count) {
23724 	duk_tval *tv_src;
23725 	duk_tval *tv_dst;
23726 	duk_tval *tv_curr;
23727 	duk_tval *tv_limit;
23728 	duk_idx_t top;
23729 
23730 	DUK_ASSERT_API_ENTRY(thr);
23731 
23732 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23733 	top = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
23734 	DUK_ASSERT(top >= 0);
23735 	if (DUK_UNLIKELY((duk_uidx_t) count > (duk_uidx_t) top)) {
23736 		/* Also handles negative count. */
23737 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
23738 		DUK_WO_NORETURN(return;);
23739 	}
23740 	DUK_ASSERT(count >= 0);
23741 
23742 	/* Wrapping is controlled by the check above: value stack top can be
23743 	 * at most DUK_USE_VALSTACK_LIMIT which is low enough so that
23744 	 * multiplying with sizeof(duk_tval) won't wrap.
23745 	 */
23746 	DUK_ASSERT(count >= 0 && count <= (duk_idx_t) DUK_USE_VALSTACK_LIMIT);
23747 	DUK_ASSERT((duk_size_t) count <= DUK_SIZE_MAX / sizeof(duk_tval));  /* no wrapping */
23748 
23749 	tv_dst = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) count);  /* XXX: uninitialized would be OK */
23750 	DUK_ASSERT(count == 0 || tv_dst != NULL);
23751 
23752 	/* Copy value stack values directly to the array part without
23753 	 * any refcount updates: net refcount changes are zero.
23754 	 */
23755 	tv_src = thr->valstack_top - count - 1;
23756 	duk_memcpy_unsafe((void *) tv_dst, (const void *) tv_src, (size_t) count * sizeof(duk_tval));
23757 
23758 	/* Overwrite result array to final value stack location and wipe
23759 	 * the rest; no refcount operations needed.
23760 	 */
23761 
23762 	tv_dst = tv_src;  /* when count == 0, same as tv_src (OK) */
23763 	tv_src = thr->valstack_top - 1;
23764 	DUK_TVAL_SET_TVAL(tv_dst, tv_src);
23765 
23766 	/* XXX: internal helper to wipe a value stack segment? */
23767 	tv_curr = tv_dst + 1;
23768 	tv_limit = thr->valstack_top;
23769 	while (tv_curr != tv_limit) {
23770 		/* Wipe policy: keep as 'undefined'. */
23771 		DUK_TVAL_SET_UNDEFINED(tv_curr);
23772 		tv_curr++;
23773 	}
23774 	thr->valstack_top = tv_dst + 1;
23775 }
23776 
duk_unpack_array_like(duk_hthread * thr,duk_idx_t idx)23777 DUK_INTERNAL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx) {
23778 	duk_tval *tv;
23779 
23780 	DUK_ASSERT_API_ENTRY(thr);
23781 
23782 	tv = duk_require_tval(thr, idx);
23783 	if (DUK_LIKELY(DUK_TVAL_IS_OBJECT(tv))) {
23784 		duk_hobject *h;
23785 		duk_uint32_t len;
23786 		duk_uint32_t i;
23787 
23788 		h = DUK_TVAL_GET_OBJECT(tv);
23789 		DUK_ASSERT(h != NULL);
23790 		DUK_UNREF(h);
23791 
23792 #if defined(DUK_USE_ARRAY_FASTPATH)  /* close enough */
23793 		if (DUK_LIKELY(DUK_HOBJECT_IS_ARRAY(h) &&
23794 		               ((duk_harray *) h)->length <= DUK_HOBJECT_GET_ASIZE(h))) {
23795 			duk_harray *h_arr;
23796 			duk_tval *tv_src;
23797 			duk_tval *tv_dst;
23798 
23799 			h_arr = (duk_harray *) h;
23800 			len = h_arr->length;
23801 			if (DUK_UNLIKELY(len >= 0x80000000UL)) {
23802 				goto fail_over_2g;
23803 			}
23804 			duk_require_stack(thr, (duk_idx_t) len);
23805 
23806 			/* The potential allocation in duk_require_stack() may
23807 			 * run a finalizer which modifies the argArray so that
23808 			 * e.g. becomes sparse.  So, we need to recheck that the
23809 			 * array didn't change size and that there's still a
23810 			 * valid backing array part.
23811 			 *
23812 			 * XXX: alternatively, could prevent finalizers for the
23813 			 * duration.
23814 			 */
23815 			if (DUK_UNLIKELY(len != h_arr->length ||
23816 			                 h_arr->length > DUK_HOBJECT_GET_ASIZE((duk_hobject *) h_arr))) {
23817 				goto skip_fast;
23818 			}
23819 
23820 			/* Main fast path: arguments array is almost always
23821 			 * an actual array (though it might also be an arguments
23822 			 * object).
23823 			 */
23824 
23825 			DUK_DDD(DUK_DDDPRINT("fast path for %ld elements", (long) h_arr->length));
23826 			tv_src = DUK_HOBJECT_A_GET_BASE(thr->heap, h);
23827 			tv_dst = thr->valstack_top;
23828 			while (len-- > 0) {
23829 				DUK_ASSERT(tv_dst < thr->valstack_end);
23830 				if (DUK_UNLIKELY(DUK_TVAL_IS_UNUSED(tv_src))) {
23831 					/* Gaps are very unlikely.  Skip over them,
23832 					 * without an ancestor lookup (technically
23833 					 * not compliant).
23834 					 */
23835 					DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_dst));  /* valstack policy */
23836 				} else {
23837 					DUK_TVAL_SET_TVAL(tv_dst, tv_src);
23838 					DUK_TVAL_INCREF(thr, tv_dst);
23839 				}
23840 				tv_src++;
23841 				tv_dst++;
23842 			}
23843 			DUK_ASSERT(tv_dst <= thr->valstack_end);
23844 			thr->valstack_top = tv_dst;
23845 			return (duk_idx_t) h_arr->length;
23846 		}
23847 	 skip_fast:
23848 #endif  /* DUK_USE_ARRAY_FASTPATH */
23849 
23850 		/* Slow path: actual lookups.  The initial 'length' lookup
23851 		 * decides the output length, regardless of side effects that
23852 		 * may resize or change the argArray while we read the
23853 		 * indices.
23854 		 */
23855 		idx = duk_normalize_index(thr, idx);
23856 		duk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
23857 		len = duk_to_uint32(thr, -1);  /* ToUint32() coercion required */
23858 		if (DUK_UNLIKELY(len >= 0x80000000UL)) {
23859 			goto fail_over_2g;
23860 		}
23861 		duk_pop_unsafe(thr);
23862 		DUK_DDD(DUK_DDDPRINT("slow path for %ld elements", (long) len));
23863 
23864 		duk_require_stack(thr, (duk_idx_t) len);
23865 		for (i = 0; i < len; i++) {
23866 			duk_get_prop_index(thr, idx, (duk_uarridx_t) i);
23867 		}
23868 		return (duk_idx_t) len;
23869 	} else if (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv)) {
23870 		return 0;
23871 	}
23872 
23873 	DUK_ERROR_TYPE_INVALID_ARGS(thr);
23874 	DUK_WO_NORETURN(return 0;);
23875 
23876  fail_over_2g:
23877 	DUK_ERROR_RANGE_INVALID_LENGTH(thr);
23878 	DUK_WO_NORETURN(return 0;);
23879 }
23880 
23881 /*
23882  *  Error throwing
23883  */
23884 
duk_throw_raw(duk_hthread * thr)23885 DUK_EXTERNAL void duk_throw_raw(duk_hthread *thr) {
23886 	duk_tval *tv_val;
23887 
23888 	DUK_ASSERT_API_ENTRY(thr);
23889 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
23890 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23891 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
23892 
23893 	if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {
23894 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
23895 		DUK_WO_NORETURN(return;);
23896 	}
23897 
23898 	/* Errors are augmented when they are created, not when they are
23899 	 * thrown or re-thrown.  The current error handler, however, runs
23900 	 * just before an error is thrown.
23901 	 */
23902 
23903 	/* Sync so that augmentation sees up-to-date activations, NULL
23904 	 * thr->ptr_curr_pc so that it's not used if side effects occur
23905 	 * in augmentation or longjmp handling.
23906 	 */
23907 	duk_hthread_sync_and_null_currpc(thr);
23908 
23909 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
23910 	DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (before throw augment)", (duk_tval *) duk_get_tval(thr, -1)));
23911 	duk_err_augment_error_throw(thr);
23912 #endif
23913 	DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (after throw augment)", (duk_tval *) duk_get_tval(thr, -1)));
23914 
23915 	tv_val = DUK_GET_TVAL_NEGIDX(thr, -1);
23916 	duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, tv_val);
23917 #if defined(DUK_USE_DEBUGGER_SUPPORT)
23918 	duk_err_check_debugger_integration(thr);
23919 #endif
23920 
23921 	/* thr->heap->lj.jmpbuf_ptr is checked by duk_err_longjmp() so we don't
23922 	 * need to check that here.  If the value is NULL, a fatal error occurs
23923 	 * because we can't return.
23924 	 */
23925 
23926 	duk_err_longjmp(thr);
23927 	DUK_UNREACHABLE();
23928 }
23929 
duk_fatal_raw(duk_hthread * thr,const char * err_msg)23930 DUK_EXTERNAL void duk_fatal_raw(duk_hthread *thr, const char *err_msg) {
23931 	DUK_ASSERT_API_ENTRY(thr);
23932 	DUK_ASSERT(thr != NULL);
23933 	DUK_ASSERT(thr->heap != NULL);
23934 	DUK_ASSERT(thr->heap->fatal_func != NULL);
23935 
23936 	DUK_D(DUK_DPRINT("fatal error occurred: %s", err_msg ? err_msg : "NULL"));
23937 
23938 	/* fatal_func should be noreturn, but noreturn declarations on function
23939 	 * pointers has a very spotty support apparently so it's not currently
23940 	 * done.
23941 	 */
23942 	thr->heap->fatal_func(thr->heap->heap_udata, err_msg);
23943 
23944 	/* If the fatal handler returns, all bets are off.  It'd be nice to
23945 	 * print something here but since we don't want to depend on stdio,
23946 	 * there's no way to do so portably.
23947 	 */
23948 	DUK_D(DUK_DPRINT("fatal error handler returned, all bets are off!"));
23949 	for (;;) {
23950 		/* loop forever, don't return (function marked noreturn) */
23951 	}
23952 }
23953 
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)23954 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) {
23955 	DUK_ASSERT_API_ENTRY(thr);
23956 
23957 	duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
23958 	(void) duk_throw(thr);
23959 	DUK_WO_NORETURN(return;);
23960 }
23961 
duk_error_raw(duk_hthread * thr,duk_errcode_t err_code,const char * filename,duk_int_t line,const char * fmt,...)23962 DUK_EXTERNAL void duk_error_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
23963 	va_list ap;
23964 
23965 	DUK_ASSERT_API_ENTRY(thr);
23966 
23967 	va_start(ap, fmt);
23968 	duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
23969 	va_end(ap);
23970 	(void) duk_throw(thr);
23971 	DUK_WO_NORETURN(return;);
23972 }
23973 
23974 #if !defined(DUK_USE_VARIADIC_MACROS)
23975 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));
23976 
duk__throw_error_from_stash(duk_hthread * thr,duk_errcode_t err_code,const char * fmt,va_list ap)23977 DUK_LOCAL void duk__throw_error_from_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, va_list ap) {
23978 	const char *filename;
23979 	duk_int_t line;
23980 
23981 	DUK_ASSERT_CTX_VALID(thr);
23982 
23983 	filename = duk_api_global_filename;
23984 	line = duk_api_global_line;
23985 	duk_api_global_filename = NULL;
23986 	duk_api_global_line = 0;
23987 
23988 	duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
23989 	(void) duk_throw(thr);
23990 	DUK_WO_NORETURN(return;);
23991 }
23992 
23993 #define DUK__ERROR_STASH_SHARED(code) do { \
23994 		va_list ap; \
23995 		va_start(ap, fmt); \
23996 		duk__throw_error_from_stash(thr, (code), fmt, ap); \
23997 		va_end(ap); \
23998 		DUK_WO_NORETURN(return 0;); \
23999 	} while (0)
24000 
duk_error_stash(duk_hthread * thr,duk_errcode_t err_code,const char * fmt,...)24001 DUK_EXTERNAL duk_ret_t duk_error_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, ...) {
24002 	DUK_ASSERT_API_ENTRY(thr);
24003 	DUK__ERROR_STASH_SHARED(err_code);
24004 }
duk_generic_error_stash(duk_hthread * thr,const char * fmt,...)24005 DUK_EXTERNAL duk_ret_t duk_generic_error_stash(duk_hthread *thr, const char *fmt, ...) {
24006 	DUK_ASSERT_API_ENTRY(thr);
24007 	DUK__ERROR_STASH_SHARED(DUK_ERR_ERROR);
24008 }
duk_eval_error_stash(duk_hthread * thr,const char * fmt,...)24009 DUK_EXTERNAL duk_ret_t duk_eval_error_stash(duk_hthread *thr, const char *fmt, ...) {
24010 	DUK_ASSERT_API_ENTRY(thr);
24011 	DUK__ERROR_STASH_SHARED(DUK_ERR_EVAL_ERROR);
24012 }
duk_range_error_stash(duk_hthread * thr,const char * fmt,...)24013 DUK_EXTERNAL duk_ret_t duk_range_error_stash(duk_hthread *thr, const char *fmt, ...) {
24014 	DUK_ASSERT_API_ENTRY(thr);
24015 	DUK__ERROR_STASH_SHARED(DUK_ERR_RANGE_ERROR);
24016 }
duk_reference_error_stash(duk_hthread * thr,const char * fmt,...)24017 DUK_EXTERNAL duk_ret_t duk_reference_error_stash(duk_hthread *thr, const char *fmt, ...) {
24018 	DUK_ASSERT_API_ENTRY(thr);
24019 	DUK__ERROR_STASH_SHARED(DUK_ERR_REFERENCE_ERROR);
24020 }
duk_syntax_error_stash(duk_hthread * thr,const char * fmt,...)24021 DUK_EXTERNAL duk_ret_t duk_syntax_error_stash(duk_hthread *thr, const char *fmt, ...) {
24022 	DUK_ASSERT_API_ENTRY(thr);
24023 	DUK__ERROR_STASH_SHARED(DUK_ERR_SYNTAX_ERROR);
24024 }
duk_type_error_stash(duk_hthread * thr,const char * fmt,...)24025 DUK_EXTERNAL duk_ret_t duk_type_error_stash(duk_hthread *thr, const char *fmt, ...) {
24026 	DUK_ASSERT_API_ENTRY(thr);
24027 	DUK__ERROR_STASH_SHARED(DUK_ERR_TYPE_ERROR);
24028 }
duk_uri_error_stash(duk_hthread * thr,const char * fmt,...)24029 DUK_EXTERNAL duk_ret_t duk_uri_error_stash(duk_hthread *thr, const char *fmt, ...) {
24030 	DUK_ASSERT_API_ENTRY(thr);
24031 	DUK__ERROR_STASH_SHARED(DUK_ERR_URI_ERROR);
24032 }
24033 #endif  /* DUK_USE_VARIADIC_MACROS */
24034 
24035 /*
24036  *  Comparison
24037  */
24038 
duk_equals(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)24039 DUK_EXTERNAL duk_bool_t duk_equals(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
24040 	duk_tval *tv1, *tv2;
24041 
24042 	DUK_ASSERT_API_ENTRY(thr);
24043 
24044 	tv1 = duk_get_tval(thr, idx1);
24045 	tv2 = duk_get_tval(thr, idx2);
24046 	if ((tv1 == NULL) || (tv2 == NULL)) {
24047 		return 0;
24048 	}
24049 
24050 	/* Coercion may be needed, the helper handles that by pushing the
24051 	 * tagged values to the stack.
24052 	 */
24053 	return duk_js_equals(thr, tv1, tv2);
24054 }
24055 
duk_strict_equals(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)24056 DUK_EXTERNAL duk_bool_t duk_strict_equals(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
24057 	duk_tval *tv1, *tv2;
24058 
24059 	DUK_ASSERT_API_ENTRY(thr);
24060 
24061 	tv1 = duk_get_tval(thr, idx1);
24062 	tv2 = duk_get_tval(thr, idx2);
24063 	if ((tv1 == NULL) || (tv2 == NULL)) {
24064 		return 0;
24065 	}
24066 
24067 	/* No coercions or other side effects, so safe */
24068 	return duk_js_strict_equals(tv1, tv2);
24069 }
24070 
duk_samevalue(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)24071 DUK_EXTERNAL duk_bool_t duk_samevalue(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
24072 	duk_tval *tv1, *tv2;
24073 
24074 	DUK_ASSERT_API_ENTRY(thr);
24075 
24076 	tv1 = duk_get_tval(thr, idx1);
24077 	tv2 = duk_get_tval(thr, idx2);
24078 	if ((tv1 == NULL) || (tv2 == NULL)) {
24079 		return 0;
24080 	}
24081 
24082 	/* No coercions or other side effects, so safe */
24083 	return duk_js_samevalue(tv1, tv2);
24084 }
24085 
24086 /*
24087  *  instanceof
24088  */
24089 
duk_instanceof(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)24090 DUK_EXTERNAL duk_bool_t duk_instanceof(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
24091 	duk_tval *tv1, *tv2;
24092 
24093 	DUK_ASSERT_API_ENTRY(thr);
24094 
24095 	/* Index validation is strict, which differs from duk_equals().
24096 	 * The strict behavior mimics how instanceof itself works, e.g.
24097 	 * it is a TypeError if rval is not a -callable- object.  It would
24098 	 * be somewhat inconsistent if rval would be allowed to be
24099 	 * non-existent without a TypeError.
24100 	 */
24101 	tv1 = duk_require_tval(thr, idx1);
24102 	DUK_ASSERT(tv1 != NULL);
24103 	tv2 = duk_require_tval(thr, idx2);
24104 	DUK_ASSERT(tv2 != NULL);
24105 
24106 	return duk_js_instanceof(thr, tv1, tv2);
24107 }
24108 
24109 /*
24110  *  Lightfunc
24111  */
24112 
duk_push_lightfunc_name_raw(duk_hthread * thr,duk_c_function func,duk_small_uint_t lf_flags)24113 DUK_INTERNAL void duk_push_lightfunc_name_raw(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags) {
24114 	/* Lightfunc name, includes Duktape/C native function pointer, which
24115 	 * can often be used to locate the function from a symbol table.
24116 	 * The name also includes the 16-bit duk_tval flags field because it
24117 	 * includes the magic value.  Because a single native function often
24118 	 * provides different functionality depending on the magic value, it
24119 	 * seems reasonably to include it in the name.
24120 	 *
24121 	 * On the other hand, a complicated name increases string table
24122 	 * pressure in low memory environments (but only when function name
24123 	 * is accessed).
24124 	 */
24125 
24126 	DUK_ASSERT_API_ENTRY(thr);
24127 
24128 	duk_push_literal(thr, "light_");
24129 	duk_push_string_funcptr(thr, (duk_uint8_t *) &func, sizeof(func));
24130 	duk_push_sprintf(thr, "_%04x", (unsigned int) lf_flags);
24131 	duk_concat(thr, 3);
24132 }
24133 
duk_push_lightfunc_name(duk_hthread * thr,duk_tval * tv)24134 DUK_INTERNAL void duk_push_lightfunc_name(duk_hthread *thr, duk_tval *tv) {
24135 	duk_c_function func;
24136 	duk_small_uint_t lf_flags;
24137 
24138 	DUK_ASSERT_API_ENTRY(thr);
24139 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));
24140 
24141 	DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
24142 	duk_push_lightfunc_name_raw(thr, func, lf_flags);
24143 }
24144 
duk_push_lightfunc_tostring(duk_hthread * thr,duk_tval * tv)24145 DUK_INTERNAL void duk_push_lightfunc_tostring(duk_hthread *thr, duk_tval *tv) {
24146 	duk_c_function func;
24147 	duk_small_uint_t lf_flags;
24148 
24149 	DUK_ASSERT_API_ENTRY(thr);
24150 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));
24151 
24152 	DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);  /* read before 'tv' potentially invalidated */
24153 	duk_push_literal(thr, "function ");
24154 	duk_push_lightfunc_name_raw(thr, func, lf_flags);
24155 	duk_push_literal(thr, "() { [lightfunc code] }");
24156 	duk_concat(thr, 3);
24157 }
24158 
24159 /*
24160  *  Function pointers
24161  *
24162  *  Printing function pointers is non-portable, so we do that by hex printing
24163  *  bytes from memory.
24164  */
24165 
duk_push_string_funcptr(duk_hthread * thr,duk_uint8_t * ptr,duk_size_t sz)24166 DUK_INTERNAL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, duk_size_t sz) {
24167 	duk_uint8_t buf[32 * 2];
24168 	duk_uint8_t *p, *q;
24169 	duk_small_uint_t i;
24170 	duk_small_uint_t t;
24171 
24172 	DUK_ASSERT_API_ENTRY(thr);
24173 	DUK_ASSERT(sz <= 32);  /* sanity limit for function pointer size */
24174 
24175 	p = buf;
24176 #if defined(DUK_USE_INTEGER_LE)
24177 	q = ptr + sz;
24178 #else
24179 	q = ptr;
24180 #endif
24181 	for (i = 0; i < sz; i++) {
24182 #if defined(DUK_USE_INTEGER_LE)
24183 		t = *(--q);
24184 #else
24185 		t = *(q++);
24186 #endif
24187 		*p++ = duk_lc_digits[t >> 4];
24188 		*p++ = duk_lc_digits[t & 0x0f];
24189 	}
24190 
24191 	duk_push_lstring(thr, (const char *) buf, sz * 2);
24192 }
24193 
24194 /*
24195  *  Push readable string summarizing duk_tval.  The operation is side effect
24196  *  free and will only throw from internal errors (e.g. out of memory).
24197  *  This is used by e.g. property access code to summarize a key/base safely,
24198  *  and is not intended to be fast (but small and safe).
24199  */
24200 
24201 /* String limits for summary strings. */
24202 #define DUK__READABLE_SUMMARY_MAXCHARS 96  /* maximum supported by helper */
24203 #define DUK__READABLE_STRING_MAXCHARS  32  /* for strings/symbols */
24204 #define DUK__READABLE_ERRMSG_MAXCHARS  96  /* for error messages */
24205 
24206 /* String sanitizer which escapes ASCII control characters and a few other
24207  * ASCII characters, passes Unicode as is, and replaces invalid UTF-8 with
24208  * question marks.  No errors are thrown for any input string, except in out
24209  * of memory situations.
24210  */
duk__push_hstring_readable_unicode(duk_hthread * thr,duk_hstring * h_input,duk_small_uint_t maxchars)24211 DUK_LOCAL void duk__push_hstring_readable_unicode(duk_hthread *thr, duk_hstring *h_input, duk_small_uint_t maxchars) {
24212 	const duk_uint8_t *p, *p_start, *p_end;
24213 	duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH * DUK__READABLE_SUMMARY_MAXCHARS +
24214 	                2 /*quotes*/ + 3 /*periods*/];
24215 	duk_uint8_t *q;
24216 	duk_ucodepoint_t cp;
24217 	duk_small_uint_t nchars;
24218 
24219 	DUK_ASSERT_CTX_VALID(thr);
24220 	DUK_ASSERT(h_input != NULL);
24221 	DUK_ASSERT(maxchars <= DUK__READABLE_SUMMARY_MAXCHARS);
24222 
24223 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
24224 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
24225 	p = p_start;
24226 	q = buf;
24227 
24228 	nchars = 0;
24229 	*q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
24230 	for (;;) {
24231 		if (p >= p_end) {
24232 			break;
24233 		}
24234 		if (nchars == maxchars) {
24235 			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
24236 			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
24237 			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
24238 			break;
24239 		}
24240 		if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
24241 			if (cp < 0x20 || cp == 0x7f || cp == DUK_ASC_SINGLEQUOTE || cp == DUK_ASC_BACKSLASH) {
24242 				DUK_ASSERT(DUK_UNICODE_MAX_XUTF8_LENGTH >= 4);  /* estimate is valid */
24243 				DUK_ASSERT((cp >> 4) <= 0x0f);
24244 				*q++ = (duk_uint8_t) DUK_ASC_BACKSLASH;
24245 				*q++ = (duk_uint8_t) DUK_ASC_LC_X;
24246 				*q++ = (duk_uint8_t) duk_lc_digits[cp >> 4];
24247 				*q++ = (duk_uint8_t) duk_lc_digits[cp & 0x0f];
24248 			} else {
24249 				q += duk_unicode_encode_xutf8(cp, q);
24250 			}
24251 		} else {
24252 			p++;  /* advance manually */
24253 			*q++ = (duk_uint8_t) DUK_ASC_QUESTION;
24254 		}
24255 		nchars++;
24256 	}
24257 	*q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
24258 
24259 	duk_push_lstring(thr, (const char *) buf, (duk_size_t) (q - buf));
24260 }
24261 
duk__push_string_tval_readable(duk_hthread * thr,duk_tval * tv,duk_bool_t error_aware)24262 DUK_LOCAL const char *duk__push_string_tval_readable(duk_hthread *thr, duk_tval *tv, duk_bool_t error_aware) {
24263 	DUK_ASSERT_CTX_VALID(thr);
24264 	/* 'tv' may be NULL */
24265 
24266 	if (tv == NULL) {
24267 		duk_push_literal(thr, "none");
24268 	} else {
24269 		switch (DUK_TVAL_GET_TAG(tv)) {
24270 		case DUK_TAG_STRING: {
24271 			duk_hstring *h = DUK_TVAL_GET_STRING(tv);
24272 			if (DUK_HSTRING_HAS_SYMBOL(h)) {
24273 				/* XXX: string summary produces question marks
24274 				 * so this is not very ideal.
24275 				 */
24276 				duk_push_literal(thr, "[Symbol ");
24277 				duk_push_string(thr, duk__get_symbol_type_string(h));
24278 				duk_push_literal(thr, " ");
24279 				duk__push_hstring_readable_unicode(thr, h, DUK__READABLE_STRING_MAXCHARS);
24280 				duk_push_literal(thr, "]");
24281 				duk_concat(thr, 5);
24282 				break;
24283 			}
24284 			duk__push_hstring_readable_unicode(thr, h, DUK__READABLE_STRING_MAXCHARS);
24285 			break;
24286 		}
24287 		case DUK_TAG_OBJECT: {
24288 			duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
24289 			DUK_ASSERT(h != NULL);
24290 
24291 			if (error_aware &&
24292 			    duk_hobject_prototype_chain_contains(thr, h, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {
24293 				/* Get error message in a side effect free way if
24294 				 * possible; if not, summarize as a generic object.
24295 				 * Error message currently gets quoted.
24296 				 */
24297 				/* XXX: better internal getprop call; get without side effects
24298 				 * but traverse inheritance chain.
24299 				 */
24300 				duk_tval *tv_msg;
24301 				tv_msg = duk_hobject_find_existing_entry_tval_ptr(thr->heap, h, DUK_HTHREAD_STRING_MESSAGE(thr));
24302 				if (tv_msg != NULL && DUK_TVAL_IS_STRING(tv_msg)) {
24303 					/* It's critical to avoid recursion so
24304 					 * only summarize a string .message.
24305 					 */
24306 					duk__push_hstring_readable_unicode(thr, DUK_TVAL_GET_STRING(tv_msg), DUK__READABLE_ERRMSG_MAXCHARS);
24307 					break;
24308 				}
24309 			}
24310 			duk_push_class_string_tval(thr, tv, 1 /*avoid_side_effects*/);
24311 			break;
24312 		}
24313 		case DUK_TAG_BUFFER: {
24314 			/* While plain buffers mimic Uint8Arrays, they summarize differently.
24315 			 * This is useful so that the summarized string accurately reflects the
24316 			 * internal type which may matter for figuring out bugs etc.
24317 			 */
24318 			/* XXX: Hex encoded, length limited buffer summary here? */
24319 			duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
24320 			DUK_ASSERT(h != NULL);
24321 			duk_push_sprintf(thr, "[buffer:%ld]", (long) DUK_HBUFFER_GET_SIZE(h));
24322 			break;
24323 		}
24324 		case DUK_TAG_POINTER: {
24325 			/* Surround with parentheses like in JX, ensures NULL pointer
24326 			 * is distinguishable from null value ("(null)" vs "null").
24327 			 */
24328 			duk_push_tval(thr, tv);
24329 			duk_push_sprintf(thr, "(%s)", duk_to_string(thr, -1));
24330 			duk_remove_m2(thr);
24331 			break;
24332 		}
24333 		default: {
24334 			duk_push_tval(thr, tv);
24335 			break;
24336 		}
24337 		}
24338 	}
24339 
24340 	return duk_to_string(thr, -1);
24341 }
duk_push_string_tval_readable(duk_hthread * thr,duk_tval * tv)24342 DUK_INTERNAL const char *duk_push_string_tval_readable(duk_hthread *thr, duk_tval *tv) {
24343 	DUK_ASSERT_API_ENTRY(thr);
24344 	return duk__push_string_tval_readable(thr, tv, 0 /*error_aware*/);
24345 }
24346 
duk_push_string_readable(duk_hthread * thr,duk_idx_t idx)24347 DUK_INTERNAL const char *duk_push_string_readable(duk_hthread *thr, duk_idx_t idx) {
24348 	DUK_ASSERT_API_ENTRY(thr);
24349 	return duk_push_string_tval_readable(thr, duk_get_tval(thr, idx));
24350 }
24351 
duk_push_string_tval_readable_error(duk_hthread * thr,duk_tval * tv)24352 DUK_INTERNAL const char *duk_push_string_tval_readable_error(duk_hthread *thr, duk_tval *tv) {
24353 	DUK_ASSERT_API_ENTRY(thr);
24354 	return duk__push_string_tval_readable(thr, tv, 1 /*error_aware*/);
24355 }
24356 
duk_push_symbol_descriptive_string(duk_hthread * thr,duk_hstring * h)24357 DUK_INTERNAL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstring *h) {
24358 	const duk_uint8_t *p;
24359 	const duk_uint8_t *p_end;
24360 	const duk_uint8_t *q;
24361 
24362 	DUK_ASSERT_API_ENTRY(thr);
24363 
24364 	/* .toString() */
24365 	duk_push_literal(thr, "Symbol(");
24366 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
24367 	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
24368 	DUK_ASSERT(p[0] == 0xff || (p[0] & 0xc0) == 0x80);
24369 	p++;
24370 	for (q = p; q < p_end; q++) {
24371 		if (*q == 0xffU) {
24372 			/* Terminate either at end-of-string (but NUL MUST
24373 			 * be accepted without terminating description) or
24374 			 * 0xFF, which is used to mark start of unique trailer
24375 			 * (and cannot occur in CESU-8 / extended UTF-8).
24376 			 */
24377 			break;
24378 		}
24379 	}
24380 	duk_push_lstring(thr, (const char *) p, (duk_size_t) (q - p));
24381 	duk_push_literal(thr, ")");
24382 	duk_concat(thr, 3);
24383 }
24384 
24385 /*
24386  *  Functions
24387  */
24388 
24389 #if 0  /* not used yet */
24390 DUK_INTERNAL void duk_push_hnatfunc_name(duk_hthread *thr, duk_hnatfunc *h) {
24391 	duk_c_function func;
24392 
24393 	DUK_ASSERT_API_ENTRY(thr);
24394 	DUK_ASSERT(h != NULL);
24395 	DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h));
24396 
24397 	duk_push_sprintf(thr, "native_");
24398 	func = h->func;
24399 	duk_push_string_funcptr(thr, (duk_uint8_t *) &func, sizeof(func));
24400 	duk_push_sprintf(thr, "_%04x_%04x",
24401 	                 (unsigned int) (duk_uint16_t) h->nargs,
24402 	                 (unsigned int) (duk_uint16_t) h->magic);
24403 	duk_concat(thr, 3);
24404 }
24405 #endif
24406 
24407 /*
24408  *  duk_tval slice copy
24409  */
24410 
duk_copy_tvals_incref(duk_hthread * thr,duk_tval * tv_dst,duk_tval * tv_src,duk_size_t count)24411 DUK_INTERNAL void duk_copy_tvals_incref(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_size_t count) {
24412 	duk_tval *tv;
24413 
24414 	DUK_ASSERT_API_ENTRY(thr);
24415 	DUK_UNREF(thr);
24416 	DUK_ASSERT(count * sizeof(duk_tval) >= count);  /* no wrap */
24417 
24418 	duk_memcpy_unsafe((void *) tv_dst, (const void *) tv_src, count * sizeof(duk_tval));
24419 
24420 	tv = tv_dst;
24421 	while (count-- > 0) {
24422 		DUK_TVAL_INCREF(thr, tv);
24423 		tv++;
24424 	}
24425 }
24426 
24427 /* automatic undefs */
24428 #undef DUK__ASSERT_SPACE
24429 #undef DUK__CHECK_SPACE
24430 #undef DUK__ERROR_STASH_SHARED
24431 #undef DUK__PACK_ARGS
24432 #undef DUK__READABLE_ERRMSG_MAXCHARS
24433 #undef DUK__READABLE_STRING_MAXCHARS
24434 #undef DUK__READABLE_SUMMARY_MAXCHARS
24435 #line 1 "duk_api_string.c"
24436 /*
24437  *  String manipulation
24438  */
24439 
24440 /* #include duk_internal.h -> already included */
24441 
duk__concat_and_join_helper(duk_hthread * thr,duk_idx_t count_in,duk_bool_t is_join)24442 DUK_LOCAL void duk__concat_and_join_helper(duk_hthread *thr, duk_idx_t count_in, duk_bool_t is_join) {
24443 	duk_uint_t count;
24444 	duk_uint_t i;
24445 	duk_size_t idx;
24446 	duk_size_t len;
24447 	duk_hstring *h;
24448 	duk_uint8_t *buf;
24449 
24450 	DUK_ASSERT_CTX_VALID(thr);
24451 
24452 	if (DUK_UNLIKELY(count_in <= 0)) {
24453 		if (count_in < 0) {
24454 			DUK_ERROR_RANGE_INVALID_COUNT(thr);
24455 			DUK_WO_NORETURN(return;);
24456 		}
24457 		DUK_ASSERT(count_in == 0);
24458 		duk_push_hstring_empty(thr);
24459 		return;
24460 	}
24461 	count = (duk_uint_t) count_in;
24462 
24463 	if (is_join) {
24464 		duk_size_t t1, t2, limit;
24465 		h = duk_to_hstring(thr, -((duk_idx_t) count) - 1);
24466 		DUK_ASSERT(h != NULL);
24467 
24468 		/* A bit tricky overflow test, see doc/code-issues.rst. */
24469 		t1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
24470 		t2 = (duk_size_t) (count - 1);
24471 		limit = (duk_size_t) DUK_HSTRING_MAX_BYTELEN;
24472 		if (DUK_UNLIKELY(t2 != 0 && t1 > limit / t2)) {
24473 			/* Combined size of separators already overflows. */
24474 			goto error_overflow;
24475 		}
24476 		len = (duk_size_t) (t1 * t2);
24477 	} else {
24478 		len = (duk_size_t) 0;
24479 	}
24480 
24481 	for (i = count; i >= 1; i--) {
24482 		duk_size_t new_len;
24483 		h = duk_to_hstring(thr, -((duk_idx_t) i));
24484 		new_len = len + (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
24485 
24486 		/* Impose a string maximum length, need to handle overflow
24487 		 * correctly.
24488 		 */
24489 		if (new_len < len ||  /* wrapped */
24490 		    new_len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN) {
24491 			goto error_overflow;
24492 		}
24493 		len = new_len;
24494 	}
24495 
24496 	DUK_DDD(DUK_DDDPRINT("join/concat %lu strings, total length %lu bytes",
24497 	                     (unsigned long) count, (unsigned long) len));
24498 
24499 	/* Use stack allocated buffer to ensure reachability in errors
24500 	 * (e.g. intern error).
24501 	 */
24502 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len);
24503 	DUK_ASSERT(buf != NULL);
24504 
24505 	/* [ ... (sep) str1 str2 ... strN buf ] */
24506 
24507 	idx = 0;
24508 	for (i = count; i >= 1; i--) {
24509 		if (is_join && i != count) {
24510 			h = duk_require_hstring(thr, -((duk_idx_t) count) - 2);  /* extra -1 for buffer */
24511 			duk_memcpy(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
24512 			idx += DUK_HSTRING_GET_BYTELEN(h);
24513 		}
24514 		h = duk_require_hstring(thr, -((duk_idx_t) i) - 1);  /* extra -1 for buffer */
24515 		duk_memcpy(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
24516 		idx += DUK_HSTRING_GET_BYTELEN(h);
24517 	}
24518 
24519 	DUK_ASSERT(idx == len);
24520 
24521 	/* [ ... (sep) str1 str2 ... strN buf ] */
24522 
24523 	/* Get rid of the strings early to minimize memory use before intern. */
24524 
24525 	if (is_join) {
24526 		duk_replace(thr, -((duk_idx_t) count) - 2);  /* overwrite sep */
24527 		duk_pop_n(thr, (duk_idx_t) count);
24528 	} else {
24529 		duk_replace(thr, -((duk_idx_t) count) - 1);  /* overwrite str1 */
24530 		duk_pop_n(thr, (duk_idx_t) (count - 1));
24531 	}
24532 
24533 	/* [ ... buf ] */
24534 
24535 	(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */
24536 
24537 	/* [ ... res ] */
24538 	return;
24539 
24540  error_overflow:
24541 	DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
24542 	DUK_WO_NORETURN(return;);
24543 }
24544 
duk_concat(duk_hthread * thr,duk_idx_t count)24545 DUK_EXTERNAL void duk_concat(duk_hthread *thr, duk_idx_t count) {
24546 	DUK_ASSERT_API_ENTRY(thr);
24547 
24548 	duk__concat_and_join_helper(thr, count, 0 /*is_join*/);
24549 }
24550 
24551 #if defined(DUK_USE_PREFER_SIZE)
duk_concat_2(duk_hthread * thr)24552 DUK_INTERNAL void duk_concat_2(duk_hthread *thr) {
24553 	DUK_ASSERT_API_ENTRY(thr);
24554 	duk_concat(thr, 2);
24555 }
24556 #else  /* DUK_USE_PREFER_SIZE */
duk_concat_2(duk_hthread * thr)24557 DUK_INTERNAL void duk_concat_2(duk_hthread *thr) {
24558 	duk_hstring *h1;
24559 	duk_hstring *h2;
24560 	duk_uint8_t *buf;
24561 	duk_size_t len1;
24562 	duk_size_t len2;
24563 	duk_size_t len;
24564 
24565 	DUK_ASSERT_API_ENTRY(thr);
24566 	DUK_ASSERT(duk_get_top(thr) >= 2);  /* Trusted caller. */
24567 
24568 	h1 = duk_to_hstring(thr, -2);
24569 	h2 = duk_to_hstring(thr, -1);
24570 	len1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
24571 	len2 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
24572 	len = len1 + len2;
24573 	if (DUK_UNLIKELY(len < len1 ||  /* wrapped */
24574 	                 len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN)) {
24575 		goto error_overflow;
24576 	}
24577 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len);
24578 	DUK_ASSERT(buf != NULL);
24579 
24580 	duk_memcpy((void *) buf, (const void *) DUK_HSTRING_GET_DATA(h1), (size_t) len1);
24581 	duk_memcpy((void *) (buf + len1), (const void *) DUK_HSTRING_GET_DATA(h2), (size_t) len2);
24582 	(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */
24583 
24584 	/* [ ... str1 str2 buf ] */
24585 
24586 	duk_replace(thr, -3);
24587 	duk_pop_unsafe(thr);
24588 	return;
24589 
24590  error_overflow:
24591 	DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
24592 	DUK_WO_NORETURN(return;);
24593 }
24594 #endif  /* DUK_USE_PREFER_SIZE */
24595 
duk_join(duk_hthread * thr,duk_idx_t count)24596 DUK_EXTERNAL void duk_join(duk_hthread *thr, duk_idx_t count) {
24597 	DUK_ASSERT_API_ENTRY(thr);
24598 
24599 	duk__concat_and_join_helper(thr, count, 1 /*is_join*/);
24600 }
24601 
24602 /* XXX: could map/decode be unified with duk_unicode_support.c code?
24603  * Case conversion needs also the character surroundings though.
24604  */
24605 
duk_decode_string(duk_hthread * thr,duk_idx_t idx,duk_decode_char_function callback,void * udata)24606 DUK_EXTERNAL void duk_decode_string(duk_hthread *thr, duk_idx_t idx, duk_decode_char_function callback, void *udata) {
24607 	duk_hstring *h_input;
24608 	const duk_uint8_t *p, *p_start, *p_end;
24609 	duk_codepoint_t cp;
24610 
24611 	DUK_ASSERT_API_ENTRY(thr);
24612 
24613 	h_input = duk_require_hstring(thr, idx);  /* Accept symbols. */
24614 	DUK_ASSERT(h_input != NULL);
24615 
24616 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
24617 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
24618 	p = p_start;
24619 
24620 	for (;;) {
24621 		if (p >= p_end) {
24622 			break;
24623 		}
24624 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
24625 		callback(udata, cp);
24626 	}
24627 }
24628 
duk_map_string(duk_hthread * thr,duk_idx_t idx,duk_map_char_function callback,void * udata)24629 DUK_EXTERNAL void duk_map_string(duk_hthread *thr, duk_idx_t idx, duk_map_char_function callback, void *udata) {
24630 	duk_hstring *h_input;
24631 	duk_bufwriter_ctx bw_alloc;
24632 	duk_bufwriter_ctx *bw;
24633 	const duk_uint8_t *p, *p_start, *p_end;
24634 	duk_codepoint_t cp;
24635 
24636 	DUK_ASSERT_API_ENTRY(thr);
24637 
24638 	idx = duk_normalize_index(thr, idx);
24639 
24640 	h_input = duk_require_hstring(thr, idx);  /* Accept symbols. */
24641 	DUK_ASSERT(h_input != NULL);
24642 
24643 	bw = &bw_alloc;
24644 	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));  /* Reasonable output estimate. */
24645 
24646 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
24647 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
24648 	p = p_start;
24649 
24650 	for (;;) {
24651 		/* XXX: could write output in chunks with fewer ensure calls,
24652 		 * but relative benefit would be small here.
24653 		 */
24654 
24655 		if (p >= p_end) {
24656 			break;
24657 		}
24658 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
24659 		cp = callback(udata, cp);
24660 
24661 		DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
24662 	}
24663 
24664 	DUK_BW_COMPACT(thr, bw);
24665 	(void) duk_buffer_to_string(thr, -1);  /* Safe, extended UTF-8 encoded. */
24666 	duk_replace(thr, idx);
24667 }
24668 
duk_substring(duk_hthread * thr,duk_idx_t idx,duk_size_t start_offset,duk_size_t end_offset)24669 DUK_EXTERNAL void duk_substring(duk_hthread *thr, duk_idx_t idx, duk_size_t start_offset, duk_size_t end_offset) {
24670 	duk_hstring *h;
24671 	duk_hstring *res;
24672 	duk_size_t start_byte_offset;
24673 	duk_size_t end_byte_offset;
24674 	duk_size_t charlen;
24675 
24676 	DUK_ASSERT_API_ENTRY(thr);
24677 
24678 	idx = duk_require_normalize_index(thr, idx);  /* Accept symbols. */
24679 	h = duk_require_hstring(thr, idx);
24680 	DUK_ASSERT(h != NULL);
24681 
24682 	charlen = DUK_HSTRING_GET_CHARLEN(h);
24683 	if (end_offset >= charlen) {
24684 		end_offset = charlen;
24685 	}
24686 	if (start_offset > end_offset) {
24687 		start_offset = end_offset;
24688 	}
24689 
24690 	DUK_ASSERT_DISABLE(start_offset >= 0);
24691 	DUK_ASSERT(start_offset <= end_offset && start_offset <= DUK_HSTRING_GET_CHARLEN(h));
24692 	DUK_ASSERT_DISABLE(end_offset >= 0);
24693 	DUK_ASSERT(end_offset >= start_offset && end_offset <= DUK_HSTRING_GET_CHARLEN(h));
24694 
24695 	/* Guaranteed by string limits. */
24696 	DUK_ASSERT(start_offset <= DUK_UINT32_MAX);
24697 	DUK_ASSERT(end_offset <= DUK_UINT32_MAX);
24698 
24699 	start_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) start_offset);
24700 	end_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) end_offset);
24701 
24702 	DUK_ASSERT(end_byte_offset >= start_byte_offset);
24703 	DUK_ASSERT(end_byte_offset - start_byte_offset <= DUK_UINT32_MAX);  /* Guaranteed by string limits. */
24704 
24705 	/* No size check is necessary. */
24706 	res = duk_heap_strtable_intern_checked(thr,
24707 	                                       DUK_HSTRING_GET_DATA(h) + start_byte_offset,
24708 	                                       (duk_uint32_t) (end_byte_offset - start_byte_offset));
24709 
24710 	duk_push_hstring(thr, res);
24711 	duk_replace(thr, idx);
24712 }
24713 
24714 /* XXX: this is quite clunky.  Add Unicode helpers to scan backwards and
24715  * forwards with a callback to process codepoints?
24716  */
duk_trim(duk_hthread * thr,duk_idx_t idx)24717 DUK_EXTERNAL void duk_trim(duk_hthread *thr, duk_idx_t idx) {
24718 	duk_hstring *h;
24719 	const duk_uint8_t *p, *p_start, *p_end, *p_tmp1, *p_tmp2;  /* pointers for scanning */
24720 	const duk_uint8_t *q_start, *q_end;  /* start (incl) and end (excl) of trimmed part */
24721 	duk_codepoint_t cp;
24722 
24723 	DUK_ASSERT_API_ENTRY(thr);
24724 
24725 	idx = duk_require_normalize_index(thr, idx);  /* Accept symbols. */
24726 	h = duk_require_hstring(thr, idx);
24727 	DUK_ASSERT(h != NULL);
24728 
24729 	p_start = DUK_HSTRING_GET_DATA(h);
24730 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
24731 
24732 	p = p_start;
24733 	while (p < p_end) {
24734 		p_tmp1 = p;
24735 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp1, p_start, p_end);
24736 		if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {
24737 			break;
24738 		}
24739 		p = p_tmp1;
24740 	}
24741 	q_start = p;
24742 	if (p == p_end) {
24743 		/* Entire string is whitespace. */
24744 		q_end = p;
24745 		goto scan_done;
24746 	}
24747 
24748 	p = p_end;
24749 	while (p > p_start) {
24750 		p_tmp1 = p;
24751 		while (p > p_start) {
24752 			p--;
24753 			if (((*p) & 0xc0) != 0x80) {
24754 				break;
24755 			}
24756 		}
24757 		p_tmp2 = p;
24758 
24759 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp2, p_start, p_end);
24760 		if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {
24761 			p = p_tmp1;
24762 			break;
24763 		}
24764 	}
24765 	q_end = p;
24766 
24767  scan_done:
24768 	/* This may happen when forward and backward scanning disagree
24769 	 * (possible for non-extended-UTF-8 strings).
24770 	 */
24771 	if (q_end < q_start) {
24772 		q_end = q_start;
24773 	}
24774 
24775 	DUK_ASSERT(q_start >= p_start && q_start <= p_end);
24776 	DUK_ASSERT(q_end >= p_start && q_end <= p_end);
24777 	DUK_ASSERT(q_end >= q_start);
24778 
24779 	DUK_DDD(DUK_DDDPRINT("trim: p_start=%p, p_end=%p, q_start=%p, q_end=%p",
24780 	                     (const void *) p_start, (const void *) p_end,
24781 	                     (const void *) q_start, (const void *) q_end));
24782 
24783 	if (q_start == p_start && q_end == p_end) {
24784 		DUK_DDD(DUK_DDDPRINT("nothing was trimmed: avoid interning (hashing etc)"));
24785 		return;
24786 	}
24787 
24788 	duk_push_lstring(thr, (const char *) q_start, (duk_size_t) (q_end - q_start));
24789 	duk_replace(thr, idx);
24790 }
24791 
duk_char_code_at(duk_hthread * thr,duk_idx_t idx,duk_size_t char_offset)24792 DUK_EXTERNAL duk_codepoint_t duk_char_code_at(duk_hthread *thr, duk_idx_t idx, duk_size_t char_offset) {
24793 	duk_hstring *h;
24794 	duk_ucodepoint_t cp;
24795 
24796 	DUK_ASSERT_API_ENTRY(thr);
24797 
24798 	/* XXX: Share code with String.prototype.charCodeAt?  Main difference
24799 	 * is handling of clamped offsets.
24800 	 */
24801 
24802 	h = duk_require_hstring(thr, idx);  /* Accept symbols. */
24803 	DUK_ASSERT(h != NULL);
24804 
24805 	DUK_ASSERT_DISABLE(char_offset >= 0);  /* Always true, arg is unsigned. */
24806 	if (char_offset >= DUK_HSTRING_GET_CHARLEN(h)) {
24807 		return 0;
24808 	}
24809 
24810 	DUK_ASSERT(char_offset <= DUK_UINT_MAX);  /* Guaranteed by string limits. */
24811 	cp = duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) char_offset, 0 /*surrogate_aware*/);
24812 	return (duk_codepoint_t) cp;
24813 }
24814 #line 1 "duk_api_time.c"
24815 /*
24816  *  Date/time.
24817  */
24818 
24819 /* #include duk_internal.h -> already included */
24820 
duk_time_get_ecmascript_time(duk_hthread * thr)24821 DUK_INTERNAL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr) {
24822 	/* ECMAScript time, with millisecond fractions.  Exposed via
24823 	 * duk_get_now() for example.
24824 	 */
24825 	DUK_UNREF(thr);
24826 	return (duk_double_t) DUK_USE_DATE_GET_NOW(thr);
24827 }
24828 
duk_time_get_ecmascript_time_nofrac(duk_hthread * thr)24829 DUK_INTERNAL duk_double_t duk_time_get_ecmascript_time_nofrac(duk_hthread *thr) {
24830 	/* ECMAScript time without millisecond fractions.  Exposed via
24831 	 * the Date built-in which doesn't allow fractions.
24832 	 */
24833 	DUK_UNREF(thr);
24834 	return (duk_double_t) DUK_FLOOR(DUK_USE_DATE_GET_NOW(thr));
24835 }
24836 
duk_time_get_monotonic_time(duk_hthread * thr)24837 DUK_INTERNAL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr) {
24838 	DUK_UNREF(thr);
24839 #if defined(DUK_USE_GET_MONOTONIC_TIME)
24840 	return (duk_double_t) DUK_USE_GET_MONOTONIC_TIME(thr);
24841 #else
24842 	return (duk_double_t) DUK_USE_DATE_GET_NOW(thr);
24843 #endif
24844 }
24845 
duk_get_now(duk_hthread * thr)24846 DUK_EXTERNAL duk_double_t duk_get_now(duk_hthread *thr) {
24847 	DUK_ASSERT_API_ENTRY(thr);
24848 	DUK_UNREF(thr);
24849 
24850 	/* This API intentionally allows millisecond fractions. */
24851 	return duk_time_get_ecmascript_time(thr);
24852 }
24853 
24854 #if 0  /* XXX: worth exposing? */
24855 DUK_EXTERNAL duk_double_t duk_get_monotonic_time(duk_hthread *thr) {
24856 	DUK_ASSERT_API_ENTRY(thr);
24857 	DUK_UNREF(thr);
24858 
24859 	return duk_time_get_monotonic_time(thr);
24860 }
24861 #endif
24862 
duk_time_to_components(duk_hthread * thr,duk_double_t timeval,duk_time_components * comp)24863 DUK_EXTERNAL void duk_time_to_components(duk_hthread *thr, duk_double_t timeval, duk_time_components *comp) {
24864 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
24865 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
24866 	duk_uint_t flags;
24867 
24868 	DUK_ASSERT_API_ENTRY(thr);
24869 	DUK_ASSERT(comp != NULL);  /* XXX: or check? */
24870 	DUK_UNREF(thr);
24871 
24872 	/* Convert as one-based, but change month to zero-based to match the
24873 	 * ECMAScript Date built-in behavior 1:1.
24874 	 */
24875 	flags = DUK_DATE_FLAG_ONEBASED | DUK_DATE_FLAG_NAN_TO_ZERO;
24876 
24877 	duk_bi_date_timeval_to_parts(timeval, parts, dparts, flags);
24878 
24879 	/* XXX: sub-millisecond accuracy for the API */
24880 
24881 	DUK_ASSERT(dparts[DUK_DATE_IDX_MONTH] >= 1.0 && dparts[DUK_DATE_IDX_MONTH] <= 12.0);
24882 	comp->year = dparts[DUK_DATE_IDX_YEAR];
24883 	comp->month = dparts[DUK_DATE_IDX_MONTH] - 1.0;
24884 	comp->day = dparts[DUK_DATE_IDX_DAY];
24885 	comp->hours = dparts[DUK_DATE_IDX_HOUR];
24886 	comp->minutes = dparts[DUK_DATE_IDX_MINUTE];
24887 	comp->seconds = dparts[DUK_DATE_IDX_SECOND];
24888 	comp->milliseconds = dparts[DUK_DATE_IDX_MILLISECOND];
24889 	comp->weekday = dparts[DUK_DATE_IDX_WEEKDAY];
24890 }
24891 
duk_components_to_time(duk_hthread * thr,duk_time_components * comp)24892 DUK_EXTERNAL duk_double_t duk_components_to_time(duk_hthread *thr, duk_time_components *comp) {
24893 	duk_double_t d;
24894 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
24895 	duk_uint_t flags;
24896 
24897 	DUK_ASSERT_API_ENTRY(thr);
24898 	DUK_ASSERT(comp != NULL);  /* XXX: or check? */
24899 	DUK_UNREF(thr);
24900 
24901 	/* Match Date constructor behavior (with UTC time).  Month is given
24902 	 * as zero-based.  Day-of-month is given as one-based so normalize
24903 	 * it to zero-based as the internal conversion helpers expects all
24904 	 * components to be zero-based.
24905 	 */
24906 	flags = 0;
24907 
24908 	/* XXX: expensive conversion; use array format in API instead, or unify
24909 	 * time provider and time API to use same struct?
24910 	 */
24911 
24912 	dparts[DUK_DATE_IDX_YEAR] = comp->year;
24913 	dparts[DUK_DATE_IDX_MONTH] = comp->month;
24914 	dparts[DUK_DATE_IDX_DAY] = comp->day - 1.0;
24915 	dparts[DUK_DATE_IDX_HOUR] = comp->hours;
24916 	dparts[DUK_DATE_IDX_MINUTE] = comp->minutes;
24917 	dparts[DUK_DATE_IDX_SECOND] = comp->seconds;
24918 	dparts[DUK_DATE_IDX_MILLISECOND] = comp->milliseconds;
24919 	dparts[DUK_DATE_IDX_WEEKDAY] = 0;  /* ignored */
24920 
24921 	d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
24922 
24923 	return d;
24924 }
24925 #line 1 "duk_bi_array.c"
24926 /*
24927  *  Array built-ins
24928  *
24929  *  Most Array built-ins are intentionally generic in ECMAScript, and are
24930  *  intended to work even when the 'this' binding is not an Array instance.
24931  *  This ECMAScript feature is also used by much real world code.  For this
24932  *  reason the implementations here don't assume exotic Array behavior or
24933  *  e.g. presence of a .length property.  However, some algorithms have a
24934  *  fast path for duk_harray backed actual Array instances, enabled when
24935  *  footprint is not a concern.
24936  *
24937  *  XXX: the "Throw" flag should be set for (almost?) all [[Put]] and
24938  *  [[Delete]] operations, but it's currently false throughout.  Go through
24939  *  all put/delete cases and check throw flag use.  Need a new API primitive
24940  *  which allows throws flag to be specified.
24941  *
24942  *  XXX: array lengths above 2G won't work reliably.  There are many places
24943  *  where one needs a full signed 32-bit range ([-0xffffffff, 0xffffffff],
24944  *  i.e. -33- bits).  Although array 'length' cannot be written to be outside
24945  *  the unsigned 32-bit range (E5.1 Section 15.4.5.1 throws a RangeError if so)
24946  *  some intermediate values may be above 0xffffffff and this may not be always
24947  *  correctly handled now (duk_uint32_t is not enough for all algorithms).
24948  *  For instance, push() can legitimately write entries beyond length 0xffffffff
24949  *  and cause a RangeError only at the end.  To do this properly, the current
24950  *  push() implementation tracks the array index using a 'double' instead of a
24951  *  duk_uint32_t (which is somewhat awkward).  See test-bi-array-push-maxlen.js.
24952  *
24953  *  On using "put" vs. "def" prop
24954  *  =============================
24955  *
24956  *  Code below must be careful to use the appropriate primitive as it matters
24957  *  for compliance.  When using "put" there may be inherited properties in
24958  *  Array.prototype which cause side effects when values are written.  When
24959  *  using "define" there are no such side effects, and many test262 test cases
24960  *  check for this (for real world code, such side effects are very rare).
24961  *  Both "put" and "define" are used in the E5.1 specification; as a rule,
24962  *  "put" is used when modifying an existing array (or a non-array 'this'
24963  *  binding) and "define" for setting values into a fresh result array.
24964  */
24965 
24966 /* #include duk_internal.h -> already included */
24967 
24968 /* Perform an intermediate join when this many elements have been pushed
24969  * on the value stack.
24970  */
24971 #define  DUK__ARRAY_MID_JOIN_LIMIT  4096
24972 
24973 #if defined(DUK_USE_ARRAY_BUILTIN)
24974 
24975 /*
24976  *  Shared helpers.
24977  */
24978 
24979 /* Shared entry code for many Array built-ins: the 'this' binding is pushed
24980  * on the value stack and object coerced, and the current .length is returned.
24981  * Note that length is left on stack (it could be popped, but that's not
24982  * usually necessary because call handling will clean it up automatically).
24983  */
duk__push_this_obj_len_u32(duk_hthread * thr)24984 DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32(duk_hthread *thr) {
24985 	duk_uint32_t len;
24986 
24987 	/* XXX: push more directly? */
24988 	(void) duk_push_this_coercible_to_object(thr);
24989 	DUK_ASSERT_HOBJECT_VALID(duk_get_hobject(thr, -1));
24990 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_LENGTH);
24991 	len = duk_to_uint32(thr, -1);
24992 
24993 	/* -> [ ... ToObject(this) ToUint32(length) ] */
24994 	return len;
24995 }
24996 
duk__push_this_obj_len_u32_limited(duk_hthread * thr)24997 DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32_limited(duk_hthread *thr) {
24998 	/* Range limited to [0, 0x7fffffff] range, i.e. range that can be
24999 	 * represented with duk_int32_t.  Use this when the method doesn't
25000 	 * handle the full 32-bit unsigned range correctly.
25001 	 */
25002 	duk_uint32_t ret = duk__push_this_obj_len_u32(thr);
25003 	if (DUK_UNLIKELY(ret >= 0x80000000UL)) {
25004 		DUK_ERROR_RANGE_INVALID_LENGTH(thr);
25005 		DUK_WO_NORETURN(return 0U;);
25006 	}
25007 	return ret;
25008 }
25009 
25010 #if defined(DUK_USE_ARRAY_FASTPATH)
25011 /* Check if 'this' binding is an Array instance (duk_harray) which satisfies
25012  * a few other guarantees for fast path operation.  The fast path doesn't
25013  * need to handle all operations, even for duk_harrays, but must handle a
25014  * significant fraction to improve performance.  Return a non-NULL duk_harray
25015  * pointer when all fast path criteria are met, NULL otherwise.
25016  */
duk__arraypart_fastpath_this(duk_hthread * thr)25017 DUK_LOCAL duk_harray *duk__arraypart_fastpath_this(duk_hthread *thr) {
25018 	duk_tval *tv;
25019 	duk_hobject *h;
25020 	duk_uint_t flags_mask, flags_bits, flags_value;
25021 
25022 	DUK_ASSERT(thr->valstack_bottom > thr->valstack);  /* because call in progress */
25023 	tv = DUK_GET_THIS_TVAL_PTR(thr);
25024 
25025 	/* Fast path requires that 'this' is a duk_harray.  Read only arrays
25026 	 * (ROM backed) are also rejected for simplicity.
25027 	 */
25028 	if (!DUK_TVAL_IS_OBJECT(tv)) {
25029 		DUK_DD(DUK_DDPRINT("reject array fast path: not an object"));
25030 		return NULL;
25031 	}
25032 	h = DUK_TVAL_GET_OBJECT(tv);
25033 	DUK_ASSERT(h != NULL);
25034 	flags_mask = DUK_HOBJECT_FLAG_ARRAY_PART | \
25035 	             DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
25036 	             DUK_HEAPHDR_FLAG_READONLY;
25037 	flags_bits = DUK_HOBJECT_FLAG_ARRAY_PART | \
25038 	             DUK_HOBJECT_FLAG_EXOTIC_ARRAY;
25039 	flags_value = DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) h);
25040 	if ((flags_value & flags_mask) != flags_bits) {
25041 		DUK_DD(DUK_DDPRINT("reject array fast path: object flag check failed"));
25042 		return NULL;
25043 	}
25044 
25045 	/* In some cases a duk_harray's 'length' may be larger than the
25046 	 * current array part allocation.  Avoid the fast path in these
25047 	 * cases, so that all fast path code can safely assume that all
25048 	 * items in the range [0,length[ are backed by the current array
25049 	 * part allocation.
25050 	 */
25051 	if (((duk_harray *) h)->length > DUK_HOBJECT_GET_ASIZE(h)) {
25052 		DUK_DD(DUK_DDPRINT("reject array fast path: length > array part size"));
25053 		return NULL;
25054 	}
25055 
25056 	/* Guarantees for fast path. */
25057 	DUK_ASSERT(h != NULL);
25058 	DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0 || DUK_HOBJECT_A_GET_BASE(thr->heap, h) != NULL);
25059 	DUK_ASSERT(((duk_harray *) h)->length <= DUK_HOBJECT_GET_ASIZE(h));
25060 
25061 	DUK_DD(DUK_DDPRINT("array fast path allowed for: %!O", (duk_heaphdr *) h));
25062 	return (duk_harray *) h;
25063 }
25064 #endif  /* DUK_USE_ARRAY_FASTPATH */
25065 
25066 /*
25067  *  Constructor
25068  */
25069 
duk_bi_array_constructor(duk_hthread * thr)25070 DUK_INTERNAL duk_ret_t duk_bi_array_constructor(duk_hthread *thr) {
25071 	duk_idx_t nargs;
25072 	duk_harray *a;
25073 	duk_double_t d;
25074 	duk_uint32_t len;
25075 	duk_uint32_t len_prealloc;
25076 
25077 	nargs = duk_get_top(thr);
25078 
25079 	if (nargs == 1 && duk_is_number(thr, 0)) {
25080 		/* XXX: expensive check (also shared elsewhere - so add a shared internal API call?) */
25081 		d = duk_get_number(thr, 0);
25082 		len = duk_to_uint32(thr, 0);
25083 		if (((duk_double_t) len) != d) {
25084 			DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
25085 		}
25086 
25087 		/* For small lengths create a dense preallocated array.
25088 		 * For large arrays preallocate an initial part.
25089 		 */
25090 		len_prealloc = len < 64 ? len : 64;
25091 		a = duk_push_harray_with_size(thr, len_prealloc);
25092 		DUK_ASSERT(a != NULL);
25093 		a->length = len;
25094 		return 1;
25095 	}
25096 
25097 	duk_pack(thr, nargs);
25098 	return 1;
25099 }
25100 
25101 /*
25102  *  isArray()
25103  */
25104 
duk_bi_array_constructor_is_array(duk_hthread * thr)25105 DUK_INTERNAL duk_ret_t duk_bi_array_constructor_is_array(duk_hthread *thr) {
25106 	duk_hobject *h;
25107 
25108 	h = duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_ARRAY);
25109 	duk_push_boolean(thr, (h != NULL));
25110 	return 1;
25111 }
25112 
25113 /*
25114  *  toString()
25115  */
25116 
duk_bi_array_prototype_to_string(duk_hthread * thr)25117 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_to_string(duk_hthread *thr) {
25118 	(void) duk_push_this_coercible_to_object(thr);
25119 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_JOIN);
25120 
25121 	/* [ ... this func ] */
25122 	if (!duk_is_callable(thr, -1)) {
25123 		/* Fall back to the initial (original) Object.toString().  We don't
25124 		 * currently have pointers to the built-in functions, only the top
25125 		 * level global objects (like "Array") so this is now done in a bit
25126 		 * of a hacky manner.  It would be cleaner to push the (original)
25127 		 * function and use duk_call_method().
25128 		 */
25129 
25130 		/* XXX: 'this' will be ToObject() coerced twice, which is incorrect
25131 		 * but should have no visible side effects.
25132 		 */
25133 		DUK_DDD(DUK_DDDPRINT("this.join is not callable, fall back to (original) Object.toString"));
25134 		duk_set_top(thr, 0);
25135 		return duk_bi_object_prototype_to_string(thr);  /* has access to 'this' binding */
25136 	}
25137 
25138 	/* [ ... this func ] */
25139 
25140 	duk_insert(thr, -2);
25141 
25142 	/* [ ... func this ] */
25143 
25144 	DUK_DDD(DUK_DDDPRINT("calling: func=%!iT, this=%!iT",
25145 	                     (duk_tval *) duk_get_tval(thr, -2),
25146 	                     (duk_tval *) duk_get_tval(thr, -1)));
25147 	duk_call_method(thr, 0);
25148 
25149 	return 1;
25150 }
25151 
25152 /*
25153  *  concat()
25154  */
25155 
duk_bi_array_prototype_concat(duk_hthread * thr)25156 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_concat(duk_hthread *thr) {
25157 	duk_idx_t i, n;
25158 	duk_uint32_t j, idx, len;
25159 	duk_hobject *h;
25160 	duk_size_t tmp_len;
25161 
25162 	/* XXX: In ES2015 Array .length can be up to 2^53-1.  The current
25163 	 * implementation is limited to 2^32-1.
25164 	 */
25165 
25166 	/* XXX: Fast path for array 'this' and array element. */
25167 
25168 	/* XXX: The insert here is a bit expensive if there are a lot of items.
25169 	 * It could also be special cased in the outermost for loop quite easily
25170 	 * (as the element is dup()'d anyway).
25171 	 */
25172 
25173 	(void) duk_push_this_coercible_to_object(thr);
25174 	duk_insert(thr, 0);
25175 	n = duk_get_top(thr);
25176 	duk_push_array(thr);  /* -> [ ToObject(this) item1 ... itemN arr ] */
25177 
25178 	/* NOTE: The Array special behaviors are NOT invoked by duk_xdef_prop_index()
25179 	 * (which differs from the official algorithm).  If no error is thrown, this
25180 	 * doesn't matter as the length is updated at the end.  However, if an error
25181 	 * is thrown, the length will be unset.  That shouldn't matter because the
25182 	 * caller won't get a reference to the intermediate value.
25183 	 */
25184 
25185 	idx = 0;
25186 	for (i = 0; i < n; i++) {
25187 		duk_bool_t spreadable;
25188 		duk_bool_t need_has_check;
25189 
25190 		DUK_ASSERT_TOP(thr, n + 1);
25191 
25192 		/* [ ToObject(this) item1 ... itemN arr ] */
25193 
25194 		h = duk_get_hobject(thr, i);
25195 
25196 		if (h == NULL) {
25197 			spreadable = 0;
25198 		} else {
25199 #if defined(DUK_USE_SYMBOL_BUILTIN)
25200 			duk_get_prop_stridx(thr, i, DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE);
25201 			if (duk_is_undefined(thr, -1)) {
25202 				spreadable = (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY);
25203 			} else {
25204 				spreadable = duk_to_boolean(thr, -1);
25205 			}
25206 			duk_pop_nodecref_unsafe(thr);
25207 #else
25208 			spreadable = (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY);
25209 #endif
25210 		}
25211 
25212 		if (!spreadable) {
25213 			duk_dup(thr, i);
25214 			duk_xdef_prop_index_wec(thr, -2, idx);
25215 			idx++;
25216 			if (DUK_UNLIKELY(idx == 0U)) {
25217 				/* Index after update is 0, and index written
25218 				 * was 0xffffffffUL which is no longer a valid
25219 				 * array index.
25220 				 */
25221 				goto fail_wrap;
25222 			}
25223 			continue;
25224 		}
25225 
25226 		DUK_ASSERT(duk_is_object(thr, i));
25227 		need_has_check = (DUK_HOBJECT_IS_PROXY(h) != 0);  /* Always 0 w/o Proxy support. */
25228 
25229 		/* [ ToObject(this) item1 ... itemN arr ] */
25230 
25231 		tmp_len = duk_get_length(thr, i);
25232 		len = (duk_uint32_t) tmp_len;
25233 		if (DUK_UNLIKELY(tmp_len != (duk_size_t) len)) {
25234 			goto fail_wrap;
25235 		}
25236 		if (DUK_UNLIKELY(idx + len < idx)) {
25237 			/* Result length must be at most 0xffffffffUL to be
25238 			 * a valid 32-bit array index.
25239 			 */
25240 			goto fail_wrap;
25241 		}
25242 		for (j = 0; j < len; j++) {
25243 			/* For a Proxy element, an explicit 'has' check is
25244 			 * needed to allow the Proxy to present gaps.
25245 			 */
25246 			if (need_has_check) {
25247 				if (duk_has_prop_index(thr, i, j)) {
25248 					duk_get_prop_index(thr, i, j);
25249 					duk_xdef_prop_index_wec(thr, -2, idx);
25250 				}
25251 			} else {
25252 				if (duk_get_prop_index(thr, i, j)) {
25253 					duk_xdef_prop_index_wec(thr, -2, idx);
25254 				} else {
25255 					duk_pop_undefined(thr);
25256 				}
25257 			}
25258 			idx++;
25259 			DUK_ASSERT(idx != 0U);  /* Wrap check above. */
25260 		}
25261 	}
25262 
25263 	/* ES5.1 has a specification "bug" in that nonexistent trailing
25264 	 * elements don't affect the result .length.  Test262 and other
25265 	 * engines disagree, and the specification bug was fixed in ES2015
25266 	 * (see NOTE 1 in https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.concat).
25267 	 */
25268 	duk_push_uarridx(thr, idx);
25269 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
25270 
25271 	DUK_ASSERT_TOP(thr, n + 1);
25272 	return 1;
25273 
25274  fail_wrap:
25275 	DUK_ERROR_RANGE_INVALID_LENGTH(thr);
25276 	DUK_WO_NORETURN(return 0;);
25277 }
25278 
25279 /*
25280  *  join(), toLocaleString()
25281  *
25282  *  Note: checking valstack is necessary, but only in the per-element loop.
25283  *
25284  *  Note: the trivial approach of pushing all the elements on the value stack
25285  *  and then calling duk_join() fails when the array contains a large number
25286  *  of elements.  This problem can't be offloaded to duk_join() because the
25287  *  elements to join must be handled here and have special handling.  Current
25288  *  approach is to do intermediate joins with very large number of elements.
25289  *  There is no fancy handling; the prefix gets re-joined multiple times.
25290  */
25291 
duk_bi_array_prototype_join_shared(duk_hthread * thr)25292 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_join_shared(duk_hthread *thr) {
25293 	duk_uint32_t len, count;
25294 	duk_uint32_t idx;
25295 	duk_small_int_t to_locale_string = duk_get_current_magic(thr);
25296 	duk_idx_t valstack_required;
25297 
25298 	/* For join(), nargs is 1.  For toLocaleString(), nargs is 0 and
25299 	 * setting the top essentially pushes an undefined to the stack,
25300 	 * thus defaulting to a comma separator.
25301 	 */
25302 	duk_set_top(thr, 1);
25303 	if (duk_is_undefined(thr, 0)) {
25304 		duk_pop_undefined(thr);
25305 		duk_push_hstring_stridx(thr, DUK_STRIDX_COMMA);
25306 	} else {
25307 		duk_to_string(thr, 0);
25308 	}
25309 
25310 	len = duk__push_this_obj_len_u32(thr);
25311 
25312 	/* [ sep ToObject(this) len ] */
25313 
25314 	DUK_DDD(DUK_DDDPRINT("sep=%!T, this=%!T, len=%lu",
25315 	                     (duk_tval *) duk_get_tval(thr, 0),
25316 	                     (duk_tval *) duk_get_tval(thr, 1),
25317 	                     (unsigned long) len));
25318 
25319 	/* The extra (+4) is tight. */
25320 	valstack_required = (duk_idx_t) ((len >= DUK__ARRAY_MID_JOIN_LIMIT ?
25321 	                                  DUK__ARRAY_MID_JOIN_LIMIT : len) + 4);
25322 	duk_require_stack(thr, valstack_required);
25323 
25324 	duk_dup_0(thr);
25325 
25326 	/* [ sep ToObject(this) len sep ] */
25327 
25328 	count = 0;
25329 	idx = 0;
25330 	for (;;) {
25331 		DUK_DDD(DUK_DDDPRINT("join idx=%ld", (long) idx));
25332 		if (count >= DUK__ARRAY_MID_JOIN_LIMIT ||   /* intermediate join to avoid valstack overflow */
25333 		    idx >= len) { /* end of loop (careful with len==0) */
25334 			/* [ sep ToObject(this) len sep str0 ... str(count-1) ] */
25335 			DUK_DDD(DUK_DDDPRINT("mid/final join, count=%ld, idx=%ld, len=%ld",
25336 			                     (long) count, (long) idx, (long) len));
25337 			duk_join(thr, (duk_idx_t) count);  /* -> [ sep ToObject(this) len str ] */
25338 			duk_dup_0(thr);                    /* -> [ sep ToObject(this) len str sep ] */
25339 			duk_insert(thr, -2);               /* -> [ sep ToObject(this) len sep str ] */
25340 			count = 1;
25341 		}
25342 		if (idx >= len) {
25343 			/* if true, the stack already contains the final result */
25344 			break;
25345 		}
25346 
25347 		duk_get_prop_index(thr, 1, (duk_uarridx_t) idx);
25348 		if (duk_is_null_or_undefined(thr, -1)) {
25349 			duk_pop_nodecref_unsafe(thr);
25350 			duk_push_hstring_empty(thr);
25351 		} else {
25352 			if (to_locale_string) {
25353 				duk_to_object(thr, -1);
25354 				duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_LOCALE_STRING);
25355 				duk_insert(thr, -2);  /* -> [ ... toLocaleString ToObject(val) ] */
25356 				duk_call_method(thr, 0);
25357 			}
25358 			duk_to_string(thr, -1);
25359 		}
25360 
25361 		count++;
25362 		idx++;
25363 	}
25364 
25365 	/* [ sep ToObject(this) len sep result ] */
25366 
25367 	return 1;
25368 }
25369 
25370 /*
25371  *  pop(), push()
25372  */
25373 
25374 #if defined(DUK_USE_ARRAY_FASTPATH)
duk__array_pop_fastpath(duk_hthread * thr,duk_harray * h_arr)25375 DUK_LOCAL duk_ret_t duk__array_pop_fastpath(duk_hthread *thr, duk_harray *h_arr) {
25376 	duk_tval *tv_arraypart;
25377 	duk_tval *tv_val;
25378 	duk_uint32_t len;
25379 
25380 	tv_arraypart = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) h_arr);
25381 	len = h_arr->length;
25382 	if (len <= 0) {
25383 		/* nop, return undefined */
25384 		return 0;
25385 	}
25386 
25387 	len--;
25388 	h_arr->length = len;
25389 
25390 	/* Fast path doesn't check for an index property inherited from
25391 	 * Array.prototype.  This is quite often acceptable; if not,
25392 	 * disable fast path.
25393 	 */
25394 	DUK_ASSERT_VS_SPACE(thr);
25395 	tv_val = tv_arraypart + len;
25396 	if (DUK_TVAL_IS_UNUSED(tv_val)) {
25397 		/* No net refcount change.  Value stack already has
25398 		 * 'undefined' based on value stack init policy.
25399 		 */
25400 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
25401 		DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv_val));
25402 	} else {
25403 		/* No net refcount change. */
25404 		DUK_TVAL_SET_TVAL(thr->valstack_top, tv_val);
25405 		DUK_TVAL_SET_UNUSED(tv_val);
25406 	}
25407 	thr->valstack_top++;
25408 
25409 	/* XXX: there's no shrink check in the fast path now */
25410 
25411 	return 1;
25412 }
25413 #endif  /* DUK_USE_ARRAY_FASTPATH */
25414 
duk_bi_array_prototype_pop(duk_hthread * thr)25415 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_pop(duk_hthread *thr) {
25416 	duk_uint32_t len;
25417 	duk_uint32_t idx;
25418 #if defined(DUK_USE_ARRAY_FASTPATH)
25419 	duk_harray *h_arr;
25420 #endif
25421 
25422 	DUK_ASSERT_TOP(thr, 0);
25423 
25424 #if defined(DUK_USE_ARRAY_FASTPATH)
25425 	h_arr = duk__arraypart_fastpath_this(thr);
25426 	if (h_arr) {
25427 		return duk__array_pop_fastpath(thr, h_arr);
25428 	}
25429 #endif
25430 
25431 	/* XXX: Merge fastpath check into a related call (push this, coerce length, etc)? */
25432 
25433 	len = duk__push_this_obj_len_u32(thr);
25434 	if (len == 0) {
25435 		duk_push_int(thr, 0);
25436 		duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
25437 		return 0;
25438 	}
25439 	idx = len - 1;
25440 
25441 	duk_get_prop_index(thr, 0, (duk_uarridx_t) idx);
25442 	duk_del_prop_index(thr, 0, (duk_uarridx_t) idx);
25443 	duk_push_u32(thr, idx);
25444 	duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
25445 	return 1;
25446 }
25447 
25448 #if defined(DUK_USE_ARRAY_FASTPATH)
duk__array_push_fastpath(duk_hthread * thr,duk_harray * h_arr)25449 DUK_LOCAL duk_ret_t duk__array_push_fastpath(duk_hthread *thr, duk_harray *h_arr) {
25450 	duk_tval *tv_arraypart;
25451 	duk_tval *tv_src;
25452 	duk_tval *tv_dst;
25453 	duk_uint32_t len;
25454 	duk_idx_t i, n;
25455 
25456 	len = h_arr->length;
25457 	tv_arraypart = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) h_arr);
25458 
25459 	n = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
25460 	DUK_ASSERT(n >= 0);
25461 	DUK_ASSERT((duk_uint32_t) n <= DUK_UINT32_MAX);
25462 	if (DUK_UNLIKELY(len + (duk_uint32_t) n < len)) {
25463 		DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
25464 		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);  /* != 0 return value returned as is by caller */
25465 	}
25466 	if (len + (duk_uint32_t) n > DUK_HOBJECT_GET_ASIZE((duk_hobject *) h_arr)) {
25467 		/* Array part would need to be extended.  Rely on slow path
25468 		 * for now.
25469 		 *
25470 		 * XXX: Rework hobject code a bit and add extend support.
25471 		 */
25472 		return 0;
25473 	}
25474 
25475 	tv_src = thr->valstack_bottom;
25476 	tv_dst = tv_arraypart + len;
25477 	for (i = 0; i < n; i++) {
25478 		/* No net refcount change; reset value stack values to
25479 		 * undefined to satisfy value stack init policy.
25480 		 */
25481 		DUK_TVAL_SET_TVAL(tv_dst, tv_src);
25482 		DUK_TVAL_SET_UNDEFINED(tv_src);
25483 		tv_src++;
25484 		tv_dst++;
25485 	}
25486 	thr->valstack_top = thr->valstack_bottom;
25487 	len += (duk_uint32_t) n;
25488 	h_arr->length = len;
25489 
25490 	DUK_ASSERT((duk_uint_t) len == len);
25491 	duk_push_uint(thr, (duk_uint_t) len);
25492 	return 1;
25493 }
25494 #endif  /* DUK_USE_ARRAY_FASTPATH */
25495 
duk_bi_array_prototype_push(duk_hthread * thr)25496 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_push(duk_hthread *thr) {
25497 	/* Note: 'this' is not necessarily an Array object.  The push()
25498 	 * algorithm is supposed to work for other kinds of objects too,
25499 	 * so the algorithm has e.g. an explicit update for the 'length'
25500 	 * property which is normally "magical" in arrays.
25501 	 */
25502 
25503 	duk_uint32_t len;
25504 	duk_idx_t i, n;
25505 #if defined(DUK_USE_ARRAY_FASTPATH)
25506 	duk_harray *h_arr;
25507 #endif
25508 
25509 #if defined(DUK_USE_ARRAY_FASTPATH)
25510 	h_arr = duk__arraypart_fastpath_this(thr);
25511 	if (h_arr) {
25512 		duk_ret_t rc;
25513 		rc = duk__array_push_fastpath(thr, h_arr);
25514 		if (rc != 0) {
25515 			return rc;
25516 		}
25517 		DUK_DD(DUK_DDPRINT("array push() fast path exited, resize case"));
25518 	}
25519 #endif
25520 
25521 	n = duk_get_top(thr);
25522 	len = duk__push_this_obj_len_u32(thr);
25523 
25524 	/* [ arg1 ... argN obj length ] */
25525 
25526 	/* Technically Array.prototype.push() can create an Array with length
25527 	 * longer than 2^32-1, i.e. outside the 32-bit range.  The final length
25528 	 * is *not* wrapped to 32 bits in the specification.
25529 	 *
25530 	 * This implementation tracks length with a uint32 because it's much
25531 	 * more practical.
25532 	 *
25533 	 * See: test-bi-array-push-maxlen.js.
25534 	 */
25535 
25536 	if (len + (duk_uint32_t) n < len) {
25537 		DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
25538 		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
25539 	}
25540 
25541 	for (i = 0; i < n; i++) {
25542 		duk_dup(thr, i);
25543 		duk_put_prop_index(thr, -3, (duk_uarridx_t) (len + (duk_uint32_t) i));
25544 	}
25545 	len += (duk_uint32_t) n;
25546 
25547 	duk_push_u32(thr, len);
25548 	duk_dup_top(thr);
25549 	duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);
25550 
25551 	/* [ arg1 ... argN obj length new_length ] */
25552 	return 1;
25553 }
25554 
25555 /*
25556  *  sort()
25557  *
25558  *  Currently qsort with random pivot.  This is now really, really slow,
25559  *  because there is no fast path for array parts.
25560  *
25561  *  Signed indices are used because qsort() leaves and degenerate cases
25562  *  may use a negative offset.
25563  */
25564 
duk__array_sort_compare(duk_hthread * thr,duk_int_t idx1,duk_int_t idx2)25565 DUK_LOCAL duk_small_int_t duk__array_sort_compare(duk_hthread *thr, duk_int_t idx1, duk_int_t idx2) {
25566 	duk_bool_t have1, have2;
25567 	duk_bool_t undef1, undef2;
25568 	duk_small_int_t ret;
25569 	duk_idx_t idx_obj = 1;  /* fixed offsets in valstack */
25570 	duk_idx_t idx_fn = 0;
25571 	duk_hstring *h1, *h2;
25572 
25573 	/* Fast exit if indices are identical.  This is valid for a non-existent property,
25574 	 * for an undefined value, and almost always for ToString() coerced comparison of
25575 	 * arbitrary values (corner cases where this is not the case include e.g. a an
25576 	 * object with varying ToString() coercion).
25577 	 *
25578 	 * The specification does not prohibit "caching" of values read from the array, so
25579 	 * assuming equality for comparing an index with itself falls into the category of
25580 	 * "caching".
25581 	 *
25582 	 * Also, compareFn may be inconsistent, so skipping a call to compareFn here may
25583 	 * have an effect on the final result.  The specification does not require any
25584 	 * specific behavior for inconsistent compare functions, so again, this fast path
25585 	 * is OK.
25586 	 */
25587 
25588 	if (idx1 == idx2) {
25589 		DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld -> indices identical, quick exit",
25590 		                     (long) idx1, (long) idx2));
25591 		return 0;
25592 	}
25593 
25594 	have1 = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) idx1);
25595 	have2 = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) idx2);
25596 
25597 	DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld, have1=%ld, have2=%ld, val1=%!T, val2=%!T",
25598 	                     (long) idx1, (long) idx2, (long) have1, (long) have2,
25599 	                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
25600 
25601 	if (have1) {
25602 		if (have2) {
25603 			;
25604 		} else {
25605 			ret = -1;
25606 			goto pop_ret;
25607 		}
25608 	} else {
25609 		if (have2) {
25610 			ret = 1;
25611 			goto pop_ret;
25612 		} else {
25613 			ret = 0;
25614 			goto pop_ret;
25615 		}
25616 	}
25617 
25618 	undef1 = duk_is_undefined(thr, -2);
25619 	undef2 = duk_is_undefined(thr, -1);
25620 	if (undef1) {
25621 		if (undef2) {
25622 			ret = 0;
25623 			goto pop_ret;
25624 		} else {
25625 			ret = 1;
25626 			goto pop_ret;
25627 		}
25628 	} else {
25629 		if (undef2) {
25630 			ret = -1;
25631 			goto pop_ret;
25632 		} else {
25633 			;
25634 		}
25635 	}
25636 
25637 	if (!duk_is_undefined(thr, idx_fn)) {
25638 		duk_double_t d;
25639 
25640 		/* No need to check callable; duk_call() will do that. */
25641 		duk_dup(thr, idx_fn);    /* -> [ ... x y fn ] */
25642 		duk_insert(thr, -3);     /* -> [ ... fn x y ] */
25643 		duk_call(thr, 2);        /* -> [ ... res ] */
25644 
25645 		/* ES5 is a bit vague about what to do if the return value is
25646 		 * not a number.  ES2015 provides a concrete description:
25647 		 * http://www.ecma-international.org/ecma-262/6.0/#sec-sortcompare.
25648 		 */
25649 
25650 		d = duk_to_number_m1(thr);
25651 		if (d < 0.0) {
25652 			ret = -1;
25653 		} else if (d > 0.0) {
25654 			ret = 1;
25655 		} else {
25656 			/* Because NaN compares to false, NaN is handled here
25657 			 * without an explicit check above.
25658 			 */
25659 			ret = 0;
25660 		}
25661 
25662 		duk_pop_nodecref_unsafe(thr);
25663 		DUK_DDD(DUK_DDDPRINT("-> result %ld (from comparefn, after coercion)", (long) ret));
25664 		return ret;
25665 	}
25666 
25667 	/* string compare is the default (a bit oddly) */
25668 
25669 	/* XXX: any special handling for plain array; causes repeated coercion now? */
25670 	h1 = duk_to_hstring(thr, -2);
25671 	h2 = duk_to_hstring_m1(thr);
25672 	DUK_ASSERT(h1 != NULL);
25673 	DUK_ASSERT(h2 != NULL);
25674 
25675 	ret = duk_js_string_compare(h1, h2);  /* retval is directly usable */
25676 	goto pop_ret;
25677 
25678  pop_ret:
25679 	duk_pop_2_unsafe(thr);
25680 	DUK_DDD(DUK_DDDPRINT("-> result %ld", (long) ret));
25681 	return ret;
25682 }
25683 
duk__array_sort_swap(duk_hthread * thr,duk_int_t l,duk_int_t r)25684 DUK_LOCAL void duk__array_sort_swap(duk_hthread *thr, duk_int_t l, duk_int_t r) {
25685 	duk_bool_t have_l, have_r;
25686 	duk_idx_t idx_obj = 1;  /* fixed offset in valstack */
25687 
25688 	if (l == r) {
25689 		return;
25690 	}
25691 
25692 	/* swap elements; deal with non-existent elements correctly */
25693 	have_l = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) l);
25694 	have_r = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) r);
25695 
25696 	if (have_r) {
25697 		/* right exists, [[Put]] regardless whether or not left exists */
25698 		duk_put_prop_index(thr, idx_obj, (duk_uarridx_t) l);
25699 	} else {
25700 		duk_del_prop_index(thr, idx_obj, (duk_uarridx_t) l);
25701 		duk_pop_undefined(thr);
25702 	}
25703 
25704 	if (have_l) {
25705 		duk_put_prop_index(thr, idx_obj, (duk_uarridx_t) r);
25706 	} else {
25707 		duk_del_prop_index(thr, idx_obj, (duk_uarridx_t) r);
25708 		duk_pop_undefined(thr);
25709 	}
25710 }
25711 
25712 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
25713 /* 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)25714 DUK_LOCAL void duk__debuglog_qsort_state(duk_hthread *thr, duk_int_t lo, duk_int_t hi, duk_int_t pivot) {
25715 	char buf[4096];
25716 	char *ptr = buf;
25717 	duk_int_t i, n;
25718 	n = (duk_int_t) duk_get_length(thr, 1);
25719 	if (n > 4000) {
25720 		n = 4000;
25721 	}
25722 	*ptr++ = '[';
25723 	for (i = 0; i < n; i++) {
25724 		if (i == pivot) {
25725 			*ptr++ = '|';
25726 		} else if (i == lo) {
25727 			*ptr++ = '<';
25728 		} else if (i == hi) {
25729 			*ptr++ = '>';
25730 		} else if (i >= lo && i <= hi) {
25731 			*ptr++ = '-';
25732 		} else {
25733 			*ptr++ = ' ';
25734 		}
25735 	}
25736 	*ptr++ = ']';
25737 	*ptr++ = '\0';
25738 
25739 	DUK_DDD(DUK_DDDPRINT("%s   (lo=%ld, hi=%ld, pivot=%ld)",
25740 	                     (const char *) buf, (long) lo, (long) hi, (long) pivot));
25741 }
25742 #endif
25743 
duk__array_qsort(duk_hthread * thr,duk_int_t lo,duk_int_t hi)25744 DUK_LOCAL void duk__array_qsort(duk_hthread *thr, duk_int_t lo, duk_int_t hi) {
25745 	duk_int_t p, l, r;
25746 
25747 	/* The lo/hi indices may be crossed and hi < 0 is possible at entry. */
25748 
25749 	DUK_DDD(DUK_DDDPRINT("duk__array_qsort: lo=%ld, hi=%ld, obj=%!T",
25750 	                     (long) lo, (long) hi, (duk_tval *) duk_get_tval(thr, 1)));
25751 
25752 	DUK_ASSERT_TOP(thr, 3);
25753 
25754 	/* In some cases it may be that lo > hi, or hi < 0; these
25755 	 * degenerate cases happen e.g. for empty arrays, and in
25756 	 * recursion leaves.
25757 	 */
25758 
25759 	/* trivial cases */
25760 	if (hi - lo < 1) {
25761 		DUK_DDD(DUK_DDDPRINT("degenerate case, return immediately"));
25762 		return;
25763 	}
25764 	DUK_ASSERT(hi > lo);
25765 	DUK_ASSERT(hi - lo + 1 >= 2);
25766 
25767 	/* randomized pivot selection */
25768 	p = lo + (duk_int_t) (DUK_UTIL_GET_RANDOM_DOUBLE(thr) * (duk_double_t) (hi - lo + 1));
25769 	DUK_ASSERT(p >= lo && p <= hi);
25770 	DUK_DDD(DUK_DDDPRINT("lo=%ld, hi=%ld, chose pivot p=%ld", (long) lo, (long) hi, (long) p));
25771 
25772 	/* move pivot out of the way */
25773 	duk__array_sort_swap(thr, p, lo);
25774 	p = lo;
25775 	DUK_DDD(DUK_DDDPRINT("pivot moved out of the way: %!T", (duk_tval *) duk_get_tval(thr, 1)));
25776 
25777 	l = lo + 1;
25778 	r = hi;
25779 	for (;;) {
25780 		/* find elements to swap */
25781 		for (;;) {
25782 			DUK_DDD(DUK_DDDPRINT("left scan: l=%ld, r=%ld, p=%ld",
25783 			                     (long) l, (long) r, (long) p));
25784 			if (l >= hi) {
25785 				break;
25786 			}
25787 			if (duk__array_sort_compare(thr, l, p) >= 0) {  /* !(l < p) */
25788 				break;
25789 			}
25790 			l++;
25791 		}
25792 		for (;;) {
25793 			DUK_DDD(DUK_DDDPRINT("right scan: l=%ld, r=%ld, p=%ld",
25794 			                     (long) l, (long) r, (long) p));
25795 			if (r <= lo) {
25796 				break;
25797 			}
25798 			if (duk__array_sort_compare(thr, p, r) >= 0) {  /* !(p < r) */
25799 				break;
25800 			}
25801 			r--;
25802 		}
25803 		if (l >= r) {
25804 			goto done;
25805 		}
25806 		DUK_ASSERT(l < r);
25807 
25808 		DUK_DDD(DUK_DDDPRINT("swap %ld and %ld", (long) l, (long) r));
25809 
25810 		duk__array_sort_swap(thr, l, r);
25811 
25812 		DUK_DDD(DUK_DDDPRINT("after swap: %!T", (duk_tval *) duk_get_tval(thr, 1)));
25813 		l++;
25814 		r--;
25815 	}
25816  done:
25817 	/* Note that 'l' and 'r' may cross, i.e. r < l */
25818 	DUK_ASSERT(l >= lo && l <= hi);
25819 	DUK_ASSERT(r >= lo && r <= hi);
25820 
25821 	/* XXX: there's no explicit recursion bound here now.  For the average
25822 	 * qsort recursion depth O(log n) that's not really necessary: e.g. for
25823 	 * 2**32 recursion depth would be about 32 which is OK.  However, qsort
25824 	 * worst case recursion depth is O(n) which may be a problem.
25825 	 */
25826 
25827 	/* move pivot to its final place */
25828 	DUK_DDD(DUK_DDDPRINT("before final pivot swap: %!T", (duk_tval *) duk_get_tval(thr, 1)));
25829 	duk__array_sort_swap(thr, lo, r);
25830 
25831 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
25832 	duk__debuglog_qsort_state(thr, lo, hi, r);
25833 #endif
25834 
25835 	DUK_DDD(DUK_DDDPRINT("recurse: pivot=%ld, obj=%!T", (long) r, (duk_tval *) duk_get_tval(thr, 1)));
25836 	duk__array_qsort(thr, lo, r - 1);
25837 	duk__array_qsort(thr, r + 1, hi);
25838 }
25839 
duk_bi_array_prototype_sort(duk_hthread * thr)25840 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_sort(duk_hthread *thr) {
25841 	duk_uint32_t len;
25842 
25843 	/* XXX: len >= 0x80000000 won't work below because a signed type
25844 	 * is needed by qsort.
25845 	 */
25846 	len = duk__push_this_obj_len_u32_limited(thr);
25847 
25848 	/* stack[0] = compareFn
25849 	 * stack[1] = ToObject(this)
25850 	 * stack[2] = ToUint32(length)
25851 	 */
25852 
25853 	if (len > 0) {
25854 		/* avoid degenerate cases, so that (len - 1) won't underflow */
25855 		duk__array_qsort(thr, (duk_int_t) 0, (duk_int_t) (len - 1));
25856 	}
25857 
25858 	DUK_ASSERT_TOP(thr, 3);
25859 	duk_pop_nodecref_unsafe(thr);
25860 	return 1;  /* return ToObject(this) */
25861 }
25862 
25863 /*
25864  *  splice()
25865  */
25866 
25867 /* XXX: this compiles to over 500 bytes now, even without special handling
25868  * for an array part.  Uses signed ints so does not handle full array range correctly.
25869  */
25870 
25871 /* XXX: can shift() / unshift() use the same helper?
25872  *   shift() is (close to?) <--> splice(0, 1)
25873  *   unshift is (close to?) <--> splice(0, 0, [items])?
25874  */
25875 
duk_bi_array_prototype_splice(duk_hthread * thr)25876 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_splice(duk_hthread *thr) {
25877 	duk_idx_t nargs;
25878 	duk_uint32_t len_u32;
25879 	duk_int_t len;
25880 	duk_bool_t have_delcount;
25881 	duk_int_t item_count;
25882 	duk_int_t act_start;
25883 	duk_int_t del_count;
25884 	duk_int_t i, n;
25885 
25886 	DUK_UNREF(have_delcount);
25887 
25888 	nargs = duk_get_top(thr);
25889 	if (nargs < 2) {
25890 		duk_set_top(thr, 2);
25891 		nargs = 2;
25892 		have_delcount = 0;
25893 	} else {
25894 		have_delcount = 1;
25895 	}
25896 
25897 	/* XXX: len >= 0x80000000 won't work below because we need to be
25898 	 * able to represent -len.
25899 	 */
25900 	len_u32 = duk__push_this_obj_len_u32_limited(thr);
25901 	len = (duk_int_t) len_u32;
25902 	DUK_ASSERT(len >= 0);
25903 
25904 	act_start = duk_to_int_clamped(thr, 0, -len, len);
25905 	if (act_start < 0) {
25906 		act_start = len + act_start;
25907 	}
25908 	DUK_ASSERT(act_start >= 0 && act_start <= len);
25909 
25910 #if defined(DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT)
25911 	if (have_delcount) {
25912 #endif
25913 		del_count = duk_to_int_clamped(thr, 1, 0, len - act_start);
25914 #if defined(DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT)
25915 	} else {
25916 		/* E5.1 standard behavior when deleteCount is not given would be
25917 		 * to treat it just like if 'undefined' was given, which coerces
25918 		 * ultimately to 0.  Real world behavior is to splice to the end
25919 		 * of array, see test-bi-array-proto-splice-no-delcount.js.
25920 		 */
25921 		del_count = len - act_start;
25922 	}
25923 #endif
25924 
25925 	DUK_ASSERT(nargs >= 2);
25926 	item_count = (duk_int_t) (nargs - 2);
25927 
25928 	DUK_ASSERT(del_count >= 0 && del_count <= len - act_start);
25929 	DUK_ASSERT(del_count + act_start <= len);
25930 
25931 	/* For now, restrict result array into 32-bit length range. */
25932 	if (((duk_double_t) len) - ((duk_double_t) del_count) + ((duk_double_t) item_count) > (duk_double_t) DUK_UINT32_MAX) {
25933 		DUK_D(DUK_DPRINT("Array.prototype.splice() would go beyond 32-bit length, throw"));
25934 		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
25935 	}
25936 
25937 	duk_push_array(thr);
25938 
25939 	/* stack[0] = start
25940 	 * stack[1] = deleteCount
25941 	 * stack[2...nargs-1] = items
25942 	 * stack[nargs] = ToObject(this)               -3
25943 	 * stack[nargs+1] = ToUint32(length)           -2
25944 	 * stack[nargs+2] = result array               -1
25945 	 */
25946 
25947 	DUK_ASSERT_TOP(thr, nargs + 3);
25948 
25949 	/* Step 9: copy elements-to-be-deleted into the result array */
25950 
25951 	for (i = 0; i < del_count; i++) {
25952 		if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (act_start + i))) {
25953 			duk_xdef_prop_index_wec(thr, -2, (duk_uarridx_t) i);  /* throw flag irrelevant (false in std alg) */
25954 		} else {
25955 			duk_pop_undefined(thr);
25956 		}
25957 	}
25958 	duk_push_u32(thr, (duk_uint32_t) del_count);
25959 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
25960 
25961 	/* Steps 12 and 13: reorganize elements to make room for itemCount elements */
25962 
25963 	if (item_count < del_count) {
25964 		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 1
25965 		 * -> [ A B F G H ]          (conceptual intermediate step)
25966 		 * -> [ A B . F G H ]        (placeholder marked)
25967 		 *    [ A B C F G H ]        (actual result at this point, C will be replaced)
25968 		 */
25969 
25970 		DUK_ASSERT_TOP(thr, nargs + 3);
25971 
25972 		n = len - del_count;
25973 		for (i = act_start; i < n; i++) {
25974 			if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (i + del_count))) {
25975 				duk_put_prop_index(thr, -4, (duk_uarridx_t) (i + item_count));
25976 			} else {
25977 				duk_pop_undefined(thr);
25978 				duk_del_prop_index(thr, -3, (duk_uarridx_t) (i + item_count));
25979 			}
25980 		}
25981 
25982 		DUK_ASSERT_TOP(thr, nargs + 3);
25983 
25984 		/* loop iterator init and limit changed from standard algorithm */
25985 		n = len - del_count + item_count;
25986 		for (i = len - 1; i >= n; i--) {
25987 			duk_del_prop_index(thr, -3, (duk_uarridx_t) i);
25988 		}
25989 
25990 		DUK_ASSERT_TOP(thr, nargs + 3);
25991 	} else if (item_count > del_count) {
25992 		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 4
25993 		 * -> [ A B F G H ]          (conceptual intermediate step)
25994 		 * -> [ A B . . . . F G H ]  (placeholder marked)
25995 		 *    [ A B C D E F F G H ]  (actual result at this point)
25996 		 */
25997 
25998 		DUK_ASSERT_TOP(thr, nargs + 3);
25999 
26000 		/* loop iterator init and limit changed from standard algorithm */
26001 		for (i = len - del_count - 1; i >= act_start; i--) {
26002 			if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (i + del_count))) {
26003 				duk_put_prop_index(thr, -4, (duk_uarridx_t) (i + item_count));
26004 			} else {
26005 				duk_pop_undefined(thr);
26006 				duk_del_prop_index(thr, -3, (duk_uarridx_t) (i + item_count));
26007 			}
26008 		}
26009 
26010 		DUK_ASSERT_TOP(thr, nargs + 3);
26011 	} else {
26012 		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 3
26013 		 * -> [ A B F G H ]          (conceptual intermediate step)
26014 		 * -> [ A B . . . F G H ]    (placeholder marked)
26015 		 *    [ A B C D E F G H ]    (actual result at this point)
26016 		 */
26017 	}
26018 	DUK_ASSERT_TOP(thr, nargs + 3);
26019 
26020 	/* Step 15: insert itemCount elements into the hole made above */
26021 
26022 	for (i = 0; i < item_count; i++) {
26023 		duk_dup(thr, i + 2);  /* args start at index 2 */
26024 		duk_put_prop_index(thr, -4, (duk_uarridx_t) (act_start + i));
26025 	}
26026 
26027 	/* Step 16: update length; note that the final length may be above 32 bit range
26028 	 * (but we checked above that this isn't the case here)
26029 	 */
26030 
26031 	duk_push_u32(thr, (duk_uint32_t) (len - del_count + item_count));
26032 	duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);
26033 
26034 	/* result array is already at the top of stack */
26035 	DUK_ASSERT_TOP(thr, nargs + 3);
26036 	return 1;
26037 }
26038 
26039 /*
26040  *  reverse()
26041  */
26042 
duk_bi_array_prototype_reverse(duk_hthread * thr)26043 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reverse(duk_hthread *thr) {
26044 	duk_uint32_t len;
26045 	duk_uint32_t middle;
26046 	duk_uint32_t lower, upper;
26047 	duk_bool_t have_lower, have_upper;
26048 
26049 	len = duk__push_this_obj_len_u32(thr);
26050 	middle = len / 2;
26051 
26052 	/* If len <= 1, middle will be 0 and for-loop bails out
26053 	 * immediately (0 < 0 -> false).
26054 	 */
26055 
26056 	for (lower = 0; lower < middle; lower++) {
26057 		DUK_ASSERT(len >= 2);
26058 		DUK_ASSERT_TOP(thr, 2);
26059 
26060 		DUK_ASSERT(len >= lower + 1);
26061 		upper = len - lower - 1;
26062 
26063 		have_lower = duk_get_prop_index(thr, -2, (duk_uarridx_t) lower);
26064 		have_upper = duk_get_prop_index(thr, -3, (duk_uarridx_t) upper);
26065 
26066 		/* [ ToObject(this) ToUint32(length) lowerValue upperValue ] */
26067 
26068 		if (have_upper) {
26069 			duk_put_prop_index(thr, -4, (duk_uarridx_t) lower);
26070 		} else {
26071 			duk_del_prop_index(thr, -4, (duk_uarridx_t) lower);
26072 			duk_pop_undefined(thr);
26073 		}
26074 
26075 		if (have_lower) {
26076 			duk_put_prop_index(thr, -3, (duk_uarridx_t) upper);
26077 		} else {
26078 			duk_del_prop_index(thr, -3, (duk_uarridx_t) upper);
26079 			duk_pop_undefined(thr);
26080 		}
26081 
26082 		DUK_ASSERT_TOP(thr, 2);
26083 	}
26084 
26085 	DUK_ASSERT_TOP(thr, 2);
26086 	duk_pop_unsafe(thr);  /* -> [ ToObject(this) ] */
26087 	return 1;
26088 }
26089 
26090 /*
26091  *  slice()
26092  */
26093 
duk_bi_array_prototype_slice(duk_hthread * thr)26094 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_slice(duk_hthread *thr) {
26095 	duk_uint32_t len_u32;
26096 	duk_int_t len;
26097 	duk_int_t start, end;
26098 	duk_int_t i;
26099 	duk_uarridx_t idx;
26100 	duk_uint32_t res_length = 0;
26101 
26102 	/* XXX: len >= 0x80000000 won't work below because we need to be
26103 	 * able to represent -len.
26104 	 */
26105 	len_u32 = duk__push_this_obj_len_u32_limited(thr);
26106 	len = (duk_int_t) len_u32;
26107 	DUK_ASSERT(len >= 0);
26108 
26109 	duk_push_array(thr);
26110 
26111 	/* stack[0] = start
26112 	 * stack[1] = end
26113 	 * stack[2] = ToObject(this)
26114 	 * stack[3] = ToUint32(length)
26115 	 * stack[4] = result array
26116 	 */
26117 
26118 	start = duk_to_int_clamped(thr, 0, -len, len);
26119 	if (start < 0) {
26120 		start = len + start;
26121 	}
26122 	/* XXX: could duk_is_undefined() provide defaulting undefined to 'len'
26123 	 * (the upper limit)?
26124 	 */
26125 	if (duk_is_undefined(thr, 1)) {
26126 		end = len;
26127 	} else {
26128 		end = duk_to_int_clamped(thr, 1, -len, len);
26129 		if (end < 0) {
26130 			end = len + end;
26131 		}
26132 	}
26133 	DUK_ASSERT(start >= 0 && start <= len);
26134 	DUK_ASSERT(end >= 0 && end <= len);
26135 
26136 	idx = 0;
26137 	for (i = start; i < end; i++) {
26138 		DUK_ASSERT_TOP(thr, 5);
26139 		if (duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
26140 			duk_xdef_prop_index_wec(thr, 4, idx);
26141 			res_length = idx + 1;
26142 		} else {
26143 			duk_pop_undefined(thr);
26144 		}
26145 		idx++;
26146 		DUK_ASSERT_TOP(thr, 5);
26147 	}
26148 
26149 	duk_push_u32(thr, res_length);
26150 	duk_xdef_prop_stridx_short(thr, 4, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
26151 
26152 	DUK_ASSERT_TOP(thr, 5);
26153 	return 1;
26154 }
26155 
26156 /*
26157  *  shift()
26158  */
26159 
duk_bi_array_prototype_shift(duk_hthread * thr)26160 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_shift(duk_hthread *thr) {
26161 	duk_uint32_t len;
26162 	duk_uint32_t i;
26163 
26164 	len = duk__push_this_obj_len_u32(thr);
26165 	if (len == 0) {
26166 		duk_push_int(thr, 0);
26167 		duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
26168 		return 0;
26169 	}
26170 
26171 	duk_get_prop_index(thr, 0, 0);
26172 
26173 	/* stack[0] = object (this)
26174 	 * stack[1] = ToUint32(length)
26175 	 * stack[2] = elem at index 0 (retval)
26176 	 */
26177 
26178 	for (i = 1; i < len; i++) {
26179 		DUK_ASSERT_TOP(thr, 3);
26180 		if (duk_get_prop_index(thr, 0, (duk_uarridx_t) i)) {
26181 			/* fromPresent = true */
26182 			duk_put_prop_index(thr, 0, (duk_uarridx_t) (i - 1));
26183 		} else {
26184 			/* fromPresent = false */
26185 			duk_del_prop_index(thr, 0, (duk_uarridx_t) (i - 1));
26186 			duk_pop_undefined(thr);
26187 		}
26188 	}
26189 	duk_del_prop_index(thr, 0, (duk_uarridx_t) (len - 1));
26190 
26191 	duk_push_u32(thr, (duk_uint32_t) (len - 1));
26192 	duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
26193 
26194 	DUK_ASSERT_TOP(thr, 3);
26195 	return 1;
26196 }
26197 
26198 /*
26199  *  unshift()
26200  */
26201 
duk_bi_array_prototype_unshift(duk_hthread * thr)26202 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_unshift(duk_hthread *thr) {
26203 	duk_idx_t nargs;
26204 	duk_uint32_t len;
26205 	duk_uint32_t i;
26206 
26207 	nargs = duk_get_top(thr);
26208 	len = duk__push_this_obj_len_u32(thr);
26209 
26210 	/* stack[0...nargs-1] = unshift args (vararg)
26211 	 * stack[nargs] = ToObject(this)
26212 	 * stack[nargs+1] = ToUint32(length)
26213 	 */
26214 
26215 	DUK_ASSERT_TOP(thr, nargs + 2);
26216 
26217 	/* Note: unshift() may operate on indices above unsigned 32-bit range
26218 	 * and the final length may be >= 2**32.  However, we restrict the
26219 	 * final result to 32-bit range for practicality.
26220 	 */
26221 
26222 	if (len + (duk_uint32_t) nargs < len) {
26223 		DUK_D(DUK_DPRINT("Array.prototype.unshift() would go beyond 32-bit length, throw"));
26224 		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
26225 	}
26226 
26227 	i = len;
26228 	while (i > 0) {
26229 		DUK_ASSERT_TOP(thr, nargs + 2);
26230 		i--;
26231 		/* k+argCount-1; note that may be above 32-bit range */
26232 
26233 		if (duk_get_prop_index(thr, -2, (duk_uarridx_t) i)) {
26234 			/* fromPresent = true */
26235 			/* [ ... ToObject(this) ToUint32(length) val ] */
26236 			duk_put_prop_index(thr, -3, (duk_uarridx_t) (i + (duk_uint32_t) nargs));  /* -> [ ... ToObject(this) ToUint32(length) ] */
26237 		} else {
26238 			/* fromPresent = false */
26239 			/* [ ... ToObject(this) ToUint32(length) val ] */
26240 			duk_pop_undefined(thr);
26241 			duk_del_prop_index(thr, -2, (duk_uarridx_t) (i + (duk_uint32_t) nargs));  /* -> [ ... ToObject(this) ToUint32(length) ] */
26242 		}
26243 		DUK_ASSERT_TOP(thr, nargs + 2);
26244 	}
26245 
26246 	for (i = 0; i < (duk_uint32_t) nargs; i++) {
26247 		DUK_ASSERT_TOP(thr, nargs + 2);
26248 		duk_dup(thr, (duk_idx_t) i);  /* -> [ ... ToObject(this) ToUint32(length) arg[i] ] */
26249 		duk_put_prop_index(thr, -3, (duk_uarridx_t) i);
26250 		DUK_ASSERT_TOP(thr, nargs + 2);
26251 	}
26252 
26253 	DUK_ASSERT_TOP(thr, nargs + 2);
26254 	duk_push_u32(thr, len + (duk_uint32_t) nargs);
26255 	duk_dup_top(thr);  /* -> [ ... ToObject(this) ToUint32(length) final_len final_len ] */
26256 	duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);
26257 	return 1;
26258 }
26259 
26260 /*
26261  *  indexOf(), lastIndexOf()
26262  */
26263 
duk_bi_array_prototype_indexof_shared(duk_hthread * thr)26264 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_hthread *thr) {
26265 	duk_idx_t nargs;
26266 	duk_int_t i, len;
26267 	duk_int_t from_idx;
26268 	duk_small_int_t idx_step = duk_get_current_magic(thr);  /* idx_step is +1 for indexOf, -1 for lastIndexOf */
26269 
26270 	/* lastIndexOf() needs to be a vararg function because we must distinguish
26271 	 * between an undefined fromIndex and a "not given" fromIndex; indexOf() is
26272 	 * made vararg for symmetry although it doesn't strictly need to be.
26273 	 */
26274 
26275 	nargs = duk_get_top(thr);
26276 	duk_set_top(thr, 2);
26277 
26278 	/* XXX: must be able to represent -len */
26279 	len = (duk_int_t) duk__push_this_obj_len_u32_limited(thr);
26280 	if (len == 0) {
26281 		goto not_found;
26282 	}
26283 
26284 	/* Index clamping is a bit tricky, we must ensure that we'll only iterate
26285 	 * through elements that exist and that the specific requirements from E5.1
26286 	 * Sections 15.4.4.14 and 15.4.4.15 are fulfilled; especially:
26287 	 *
26288 	 *   - indexOf: clamp to [-len,len], negative handling -> [0,len],
26289 	 *     if clamped result is len, for-loop bails out immediately
26290 	 *
26291 	 *   - lastIndexOf: clamp to [-len-1, len-1], negative handling -> [-1, len-1],
26292 	 *     if clamped result is -1, for-loop bails out immediately
26293 	 *
26294 	 * If fromIndex is not given, ToInteger(undefined) = 0, which is correct
26295 	 * for indexOf() but incorrect for lastIndexOf().  Hence special handling,
26296 	 * and why lastIndexOf() needs to be a vararg function.
26297 	 */
26298 
26299 	if (nargs >= 2) {
26300 		/* indexOf: clamp fromIndex to [-len, len]
26301 		 * (if fromIndex == len, for-loop terminates directly)
26302 		 *
26303 		 * lastIndexOf: clamp fromIndex to [-len - 1, len - 1]
26304 		 * (if clamped to -len-1 -> fromIndex becomes -1, terminates for-loop directly)
26305 		 */
26306 		from_idx = duk_to_int_clamped(thr,
26307 		                              1,
26308 		                              (idx_step > 0 ? -len : -len - 1),
26309 		                              (idx_step > 0 ? len : len - 1));
26310 		if (from_idx < 0) {
26311 			/* for lastIndexOf, result may be -1 (mark immediate termination) */
26312 			from_idx = len + from_idx;
26313 		}
26314 	} else {
26315 		/* for indexOf, ToInteger(undefined) would be 0, i.e. correct, but
26316 		 * handle both indexOf and lastIndexOf specially here.
26317 		 */
26318 		if (idx_step > 0) {
26319 			from_idx = 0;
26320 		} else {
26321 			from_idx = len - 1;
26322 		}
26323 	}
26324 
26325 	/* stack[0] = searchElement
26326 	 * stack[1] = fromIndex
26327 	 * stack[2] = object
26328 	 * stack[3] = length (not needed, but not popped above)
26329 	 */
26330 
26331 	for (i = from_idx; i >= 0 && i < len; i += idx_step) {
26332 		DUK_ASSERT_TOP(thr, 4);
26333 
26334 		if (duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
26335 			DUK_ASSERT_TOP(thr, 5);
26336 			if (duk_strict_equals(thr, 0, 4)) {
26337 				duk_push_int(thr, i);
26338 				return 1;
26339 			}
26340 		}
26341 
26342 		duk_pop_unsafe(thr);
26343 	}
26344 
26345  not_found:
26346 	duk_push_int(thr, -1);
26347 	return 1;
26348 }
26349 
26350 /*
26351  *  every(), some(), forEach(), map(), filter()
26352  */
26353 
26354 #define DUK__ITER_EVERY    0
26355 #define DUK__ITER_SOME     1
26356 #define DUK__ITER_FOREACH  2
26357 #define DUK__ITER_MAP      3
26358 #define DUK__ITER_FILTER   4
26359 
26360 /* XXX: This helper is a bit awkward because the handling for the different iteration
26361  * callers is quite different.  This now compiles to a bit less than 500 bytes, so with
26362  * 5 callers the net result is about 100 bytes / caller.
26363  */
26364 
duk_bi_array_prototype_iter_shared(duk_hthread * thr)26365 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_iter_shared(duk_hthread *thr) {
26366 	duk_uint32_t len;
26367 	duk_uint32_t i;
26368 	duk_uarridx_t k;
26369 	duk_bool_t bval;
26370 	duk_small_int_t iter_type = duk_get_current_magic(thr);
26371 	duk_uint32_t res_length = 0;
26372 
26373 	/* each call this helper serves has nargs==2 */
26374 	DUK_ASSERT_TOP(thr, 2);
26375 
26376 	len = duk__push_this_obj_len_u32(thr);
26377 	duk_require_callable(thr, 0);
26378 	/* if thisArg not supplied, behave as if undefined was supplied */
26379 
26380 	if (iter_type == DUK__ITER_MAP || iter_type == DUK__ITER_FILTER) {
26381 		duk_push_array(thr);
26382 	} else {
26383 		duk_push_undefined(thr);
26384 	}
26385 
26386 	/* stack[0] = callback
26387 	 * stack[1] = thisArg
26388 	 * stack[2] = object
26389 	 * stack[3] = ToUint32(length)  (unused, but avoid unnecessary pop)
26390 	 * stack[4] = result array (or undefined)
26391 	 */
26392 
26393 	k = 0;  /* result index for filter() */
26394 	for (i = 0; i < len; i++) {
26395 		DUK_ASSERT_TOP(thr, 5);
26396 
26397 		if (!duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
26398 			/* For 'map' trailing missing elements don't invoke the
26399 			 * callback but count towards the result length.
26400 			 */
26401 			if (iter_type == DUK__ITER_MAP) {
26402 				res_length = i + 1;
26403 			}
26404 			duk_pop_undefined(thr);
26405 			continue;
26406 		}
26407 
26408 		/* The original value needs to be preserved for filter(), hence
26409 		 * this funny order.  We can't re-get the value because of side
26410 		 * effects.
26411 		 */
26412 
26413 		duk_dup_0(thr);
26414 		duk_dup_1(thr);
26415 		duk_dup_m3(thr);
26416 		duk_push_u32(thr, i);
26417 		duk_dup_2(thr);  /* [ ... val callback thisArg val i obj ] */
26418 		duk_call_method(thr, 3); /* -> [ ... val retval ] */
26419 
26420 		switch (iter_type) {
26421 		case DUK__ITER_EVERY:
26422 			bval = duk_to_boolean(thr, -1);
26423 			if (!bval) {
26424 				/* stack top contains 'false' */
26425 				return 1;
26426 			}
26427 			break;
26428 		case DUK__ITER_SOME:
26429 			bval = duk_to_boolean(thr, -1);
26430 			if (bval) {
26431 				/* stack top contains 'true' */
26432 				return 1;
26433 			}
26434 			break;
26435 		case DUK__ITER_FOREACH:
26436 			/* nop */
26437 			break;
26438 		case DUK__ITER_MAP:
26439 			duk_dup_top(thr);
26440 			duk_xdef_prop_index_wec(thr, 4, (duk_uarridx_t) i);  /* retval to result[i] */
26441 			res_length = i + 1;
26442 			break;
26443 		case DUK__ITER_FILTER:
26444 			bval = duk_to_boolean(thr, -1);
26445 			if (bval) {
26446 				duk_dup_m2(thr);  /* orig value */
26447 				duk_xdef_prop_index_wec(thr, 4, (duk_uarridx_t) k);
26448 				k++;
26449 				res_length = k;
26450 			}
26451 			break;
26452 		default:
26453 			DUK_UNREACHABLE();
26454 			break;
26455 		}
26456 		duk_pop_2_unsafe(thr);
26457 
26458 		DUK_ASSERT_TOP(thr, 5);
26459 	}
26460 
26461 	switch (iter_type) {
26462 	case DUK__ITER_EVERY:
26463 		duk_push_true(thr);
26464 		break;
26465 	case DUK__ITER_SOME:
26466 		duk_push_false(thr);
26467 		break;
26468 	case DUK__ITER_FOREACH:
26469 		duk_push_undefined(thr);
26470 		break;
26471 	case DUK__ITER_MAP:
26472 	case DUK__ITER_FILTER:
26473 		DUK_ASSERT_TOP(thr, 5);
26474 		DUK_ASSERT(duk_is_array(thr, -1));  /* topmost element is the result array already */
26475 		duk_push_u32(thr, res_length);
26476 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
26477 		break;
26478 	default:
26479 		DUK_UNREACHABLE();
26480 		break;
26481 	}
26482 
26483 	return 1;
26484 }
26485 
26486 /*
26487  *  reduce(), reduceRight()
26488  */
26489 
duk_bi_array_prototype_reduce_shared(duk_hthread * thr)26490 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_hthread *thr) {
26491 	duk_idx_t nargs;
26492 	duk_bool_t have_acc;
26493 	duk_uint32_t i, len;
26494 	duk_small_int_t idx_step = duk_get_current_magic(thr);  /* idx_step is +1 for reduce, -1 for reduceRight */
26495 
26496 	/* We're a varargs function because we need to detect whether
26497 	 * initialValue was given or not.
26498 	 */
26499 	nargs = duk_get_top(thr);
26500 	DUK_DDD(DUK_DDDPRINT("nargs=%ld", (long) nargs));
26501 
26502 	duk_set_top(thr, 2);
26503 	len = duk__push_this_obj_len_u32(thr);
26504 	duk_require_callable(thr, 0);
26505 
26506 	/* stack[0] = callback fn
26507 	 * stack[1] = initialValue
26508 	 * stack[2] = object (coerced this)
26509 	 * stack[3] = length (not needed, but not popped above)
26510 	 * stack[4] = accumulator
26511 	 */
26512 
26513 	have_acc = 0;
26514 	if (nargs >= 2) {
26515 		duk_dup_1(thr);
26516 		have_acc = 1;
26517 	}
26518 	DUK_DDD(DUK_DDDPRINT("have_acc=%ld, acc=%!T",
26519 	                     (long) have_acc, (duk_tval *) duk_get_tval(thr, 3)));
26520 
26521 	/* For len == 0, i is initialized to len - 1 which underflows.
26522 	 * The condition (i < len) will then exit the for-loop on the
26523 	 * first round which is correct.  Similarly, loop termination
26524 	 * happens by i underflowing.
26525 	 */
26526 
26527 	for (i = (idx_step >= 0 ? 0 : len - 1);
26528 	     i < len;  /* i >= 0 would always be true */
26529 	     i += (duk_uint32_t) idx_step) {
26530 		DUK_DDD(DUK_DDDPRINT("i=%ld, len=%ld, have_acc=%ld, top=%ld, acc=%!T",
26531 		                     (long) i, (long) len, (long) have_acc,
26532 		                     (long) duk_get_top(thr),
26533 		                     (duk_tval *) duk_get_tval(thr, 4)));
26534 
26535 		DUK_ASSERT((have_acc && duk_get_top(thr) == 5) ||
26536 		           (!have_acc && duk_get_top(thr) == 4));
26537 
26538 		if (!duk_has_prop_index(thr, 2, (duk_uarridx_t) i)) {
26539 			continue;
26540 		}
26541 
26542 		if (!have_acc) {
26543 			DUK_ASSERT_TOP(thr, 4);
26544 			duk_get_prop_index(thr, 2, (duk_uarridx_t) i);
26545 			have_acc = 1;
26546 			DUK_ASSERT_TOP(thr, 5);
26547 		} else {
26548 			DUK_ASSERT_TOP(thr, 5);
26549 			duk_dup_0(thr);
26550 			duk_dup(thr, 4);
26551 			duk_get_prop_index(thr, 2, (duk_uarridx_t) i);
26552 			duk_push_u32(thr, i);
26553 			duk_dup_2(thr);
26554 			DUK_DDD(DUK_DDDPRINT("calling reduce function: func=%!T, prev=%!T, curr=%!T, idx=%!T, obj=%!T",
26555 			                     (duk_tval *) duk_get_tval(thr, -5), (duk_tval *) duk_get_tval(thr, -4),
26556 			                     (duk_tval *) duk_get_tval(thr, -3), (duk_tval *) duk_get_tval(thr, -2),
26557 			                     (duk_tval *) duk_get_tval(thr, -1)));
26558 			duk_call(thr, 4);
26559 			DUK_DDD(DUK_DDDPRINT("-> result: %!T", (duk_tval *) duk_get_tval(thr, -1)));
26560 			duk_replace(thr, 4);
26561 			DUK_ASSERT_TOP(thr, 5);
26562 		}
26563 	}
26564 
26565 	if (!have_acc) {
26566 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
26567 	}
26568 
26569 	DUK_ASSERT_TOP(thr, 5);
26570 	return 1;
26571 }
26572 
26573 #endif  /* DUK_USE_ARRAY_BUILTIN */
26574 
26575 /* automatic undefs */
26576 #undef DUK__ARRAY_MID_JOIN_LIMIT
26577 #undef DUK__ITER_EVERY
26578 #undef DUK__ITER_FILTER
26579 #undef DUK__ITER_FOREACH
26580 #undef DUK__ITER_MAP
26581 #undef DUK__ITER_SOME
26582 #line 1 "duk_bi_boolean.c"
26583 /*
26584  *  Boolean built-ins
26585  */
26586 
26587 /* #include duk_internal.h -> already included */
26588 
26589 #if defined(DUK_USE_BOOLEAN_BUILTIN)
26590 
26591 /* Shared helper to provide toString() and valueOf().  Checks 'this', gets
26592  * the primitive value to stack top, and optionally coerces with ToString().
26593  */
duk_bi_boolean_prototype_tostring_shared(duk_hthread * thr)26594 DUK_INTERNAL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_hthread *thr) {
26595 	duk_tval *tv;
26596 	duk_hobject *h;
26597 	duk_small_int_t coerce_tostring = duk_get_current_magic(thr);
26598 
26599 	/* XXX: there is room to use a shared helper here, many built-ins
26600 	 * check the 'this' type, and if it's an object, check its class,
26601 	 * then get its internal value, etc.
26602 	 */
26603 
26604 	duk_push_this(thr);
26605 	tv = duk_get_tval(thr, -1);
26606 	DUK_ASSERT(tv != NULL);
26607 
26608 	if (DUK_TVAL_IS_BOOLEAN(tv)) {
26609 		goto type_ok;
26610 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
26611 		h = DUK_TVAL_GET_OBJECT(tv);
26612 		DUK_ASSERT(h != NULL);
26613 
26614 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_BOOLEAN) {
26615 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
26616 			DUK_ASSERT(duk_is_boolean(thr, -1));
26617 			goto type_ok;
26618 		}
26619 	}
26620 
26621 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
26622 	/* never here */
26623 
26624  type_ok:
26625 	if (coerce_tostring) {
26626 		duk_to_string(thr, -1);
26627 	}
26628 	return 1;
26629 }
26630 
duk_bi_boolean_constructor(duk_hthread * thr)26631 DUK_INTERNAL duk_ret_t duk_bi_boolean_constructor(duk_hthread *thr) {
26632 	duk_hobject *h_this;
26633 
26634 	duk_to_boolean(thr, 0);
26635 
26636 	if (duk_is_constructor_call(thr)) {
26637 		/* XXX: helper; rely on Boolean.prototype as being non-writable, non-configurable */
26638 		duk_push_this(thr);
26639 		h_this = duk_known_hobject(thr, -1);
26640 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE]);
26641 
26642 		DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_BOOLEAN);
26643 
26644 		duk_dup_0(thr);  /* -> [ val obj val ] */
26645 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);  /* XXX: proper flags? */
26646 	}  /* unbalanced stack */
26647 
26648 	return 1;
26649 }
26650 
26651 #endif  /* DUK_USE_BOOLEAN_BUILTIN */
26652 #line 1 "duk_bi_buffer.c"
26653 /*
26654  *  ES2015 TypedArray and Node.js Buffer built-ins
26655  */
26656 
26657 /* #include duk_internal.h -> already included */
26658 
26659 /*
26660  *  Helpers for buffer handling, enabled with DUK_USE_BUFFEROBJECT_SUPPORT.
26661  */
26662 
26663 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
26664 /* Map class number (minus DUK_HOBJECT_CLASS_BUFOBJ_MIN) to a bidx for the
26665  * default internal prototype.
26666  */
26667 static const duk_uint8_t duk__buffer_proto_from_classnum[] = {
26668 	DUK_BIDX_ARRAYBUFFER_PROTOTYPE,
26669 	DUK_BIDX_DATAVIEW_PROTOTYPE,
26670 	DUK_BIDX_INT8ARRAY_PROTOTYPE,
26671 	DUK_BIDX_UINT8ARRAY_PROTOTYPE,
26672 	DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,
26673 	DUK_BIDX_INT16ARRAY_PROTOTYPE,
26674 	DUK_BIDX_UINT16ARRAY_PROTOTYPE,
26675 	DUK_BIDX_INT32ARRAY_PROTOTYPE,
26676 	DUK_BIDX_UINT32ARRAY_PROTOTYPE,
26677 	DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,
26678 	DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
26679 };
26680 
26681 /* Map DUK_HBUFOBJ_ELEM_xxx to duk_hobject class number.
26682  * Sync with duk_hbufobj.h and duk_hobject.h.
26683  */
26684 static const duk_uint8_t duk__buffer_class_from_elemtype[9] = {
26685 	DUK_HOBJECT_CLASS_UINT8ARRAY,
26686 	DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY,
26687 	DUK_HOBJECT_CLASS_INT8ARRAY,
26688 	DUK_HOBJECT_CLASS_UINT16ARRAY,
26689 	DUK_HOBJECT_CLASS_INT16ARRAY,
26690 	DUK_HOBJECT_CLASS_UINT32ARRAY,
26691 	DUK_HOBJECT_CLASS_INT32ARRAY,
26692 	DUK_HOBJECT_CLASS_FLOAT32ARRAY,
26693 	DUK_HOBJECT_CLASS_FLOAT64ARRAY
26694 };
26695 
26696 /* Map DUK_HBUFOBJ_ELEM_xxx to prototype object built-in index.
26697  * Sync with duk_hbufobj.h.
26698  */
26699 static const duk_uint8_t duk__buffer_proto_from_elemtype[9] = {
26700 	DUK_BIDX_UINT8ARRAY_PROTOTYPE,
26701 	DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,
26702 	DUK_BIDX_INT8ARRAY_PROTOTYPE,
26703 	DUK_BIDX_UINT16ARRAY_PROTOTYPE,
26704 	DUK_BIDX_INT16ARRAY_PROTOTYPE,
26705 	DUK_BIDX_UINT32ARRAY_PROTOTYPE,
26706 	DUK_BIDX_INT32ARRAY_PROTOTYPE,
26707 	DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,
26708 	DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
26709 };
26710 
26711 /* Map DUK__FLD_xxx to byte size. */
26712 static const duk_uint8_t duk__buffer_nbytes_from_fldtype[6] = {
26713 	1,  /* DUK__FLD_8BIT */
26714 	2,  /* DUK__FLD_16BIT */
26715 	4,  /* DUK__FLD_32BIT */
26716 	4,  /* DUK__FLD_FLOAT */
26717 	8,  /* DUK__FLD_DOUBLE */
26718 	0   /* DUK__FLD_VARINT; not relevant here */
26719 };
26720 
26721 /* Bitfield for each DUK_HBUFOBJ_ELEM_xxx indicating which element types
26722  * are compatible with a blind byte copy for the TypedArray set() method (also
26723  * used for TypedArray constructor).  Array index is target buffer elem type,
26724  * bitfield indicates compatible source types.  The types must have same byte
26725  * size and they must be coercion compatible.
26726  */
26727 #if !defined(DUK_USE_PREFER_SIZE)
26728 static duk_uint16_t duk__buffer_elemtype_copy_compatible[9] = {
26729 	/* xxx -> DUK_HBUFOBJ_ELEM_UINT8 */
26730 	(1U << DUK_HBUFOBJ_ELEM_UINT8) |
26731 		(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED) |
26732 		(1U << DUK_HBUFOBJ_ELEM_INT8),
26733 
26734 	/* xxx -> DUK_HBUFOBJ_ELEM_UINT8CLAMPED
26735 	 * Note: INT8 is -not- copy compatible, e.g. -1 would coerce to 0x00.
26736 	 */
26737 	(1U << DUK_HBUFOBJ_ELEM_UINT8) |
26738 		(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED),
26739 
26740 	/* xxx -> DUK_HBUFOBJ_ELEM_INT8 */
26741 	(1U << DUK_HBUFOBJ_ELEM_UINT8) |
26742 		(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED) |
26743 		(1U << DUK_HBUFOBJ_ELEM_INT8),
26744 
26745 	/* xxx -> DUK_HBUFOBJ_ELEM_UINT16 */
26746 	(1U << DUK_HBUFOBJ_ELEM_UINT16) |
26747 		(1U << DUK_HBUFOBJ_ELEM_INT16),
26748 
26749 	/* xxx -> DUK_HBUFOBJ_ELEM_INT16 */
26750 	(1U << DUK_HBUFOBJ_ELEM_UINT16) |
26751 		(1U << DUK_HBUFOBJ_ELEM_INT16),
26752 
26753 	/* xxx -> DUK_HBUFOBJ_ELEM_UINT32 */
26754 	(1U << DUK_HBUFOBJ_ELEM_UINT32) |
26755 		(1U << DUK_HBUFOBJ_ELEM_INT32),
26756 
26757 	/* xxx -> DUK_HBUFOBJ_ELEM_INT32 */
26758 	(1U << DUK_HBUFOBJ_ELEM_UINT32) |
26759 		(1U << DUK_HBUFOBJ_ELEM_INT32),
26760 
26761 	/* xxx -> DUK_HBUFOBJ_ELEM_FLOAT32 */
26762 	(1U << DUK_HBUFOBJ_ELEM_FLOAT32),
26763 
26764 	/* xxx -> DUK_HBUFOBJ_ELEM_FLOAT64 */
26765 	(1U << DUK_HBUFOBJ_ELEM_FLOAT64)
26766 };
26767 #endif  /* !DUK_USE_PREFER_SIZE */
26768 
duk__hbufobj_promote_this(duk_hthread * thr)26769 DUK_LOCAL duk_hbufobj *duk__hbufobj_promote_this(duk_hthread *thr) {
26770 	duk_tval *tv_dst;
26771 	duk_hbufobj *res;
26772 
26773 	duk_push_this(thr);
26774 	DUK_ASSERT(duk_is_buffer(thr, -1));
26775 	res = (duk_hbufobj *) duk_to_hobject(thr, -1);
26776 	DUK_ASSERT_HBUFOBJ_VALID(res);
26777 	DUK_DD(DUK_DDPRINT("promoted 'this' automatically to an ArrayBuffer: %!iT", duk_get_tval(thr, -1)));
26778 
26779 	tv_dst = duk_get_borrowed_this_tval(thr);
26780 	DUK_TVAL_SET_OBJECT_UPDREF(thr, tv_dst, (duk_hobject *) res);
26781 	duk_pop(thr);
26782 
26783 	return res;
26784 }
26785 
26786 #define DUK__BUFOBJ_FLAG_THROW    (1 << 0)
26787 #define DUK__BUFOBJ_FLAG_PROMOTE  (1 << 1)
26788 
26789 /* Shared helper.  When DUK__BUFOBJ_FLAG_PROMOTE is given, the return value is
26790  * always a duk_hbufobj *.  Without the flag the return value can also be a
26791  * plain buffer, and the caller must check for it using DUK_HEAPHDR_IS_BUFFER().
26792  */
duk__getrequire_bufobj_this(duk_hthread * thr,duk_small_uint_t flags)26793 DUK_LOCAL duk_heaphdr *duk__getrequire_bufobj_this(duk_hthread *thr, duk_small_uint_t flags) {
26794 	duk_tval *tv;
26795 	duk_hbufobj *h_this;
26796 
26797 	DUK_ASSERT(thr != NULL);
26798 
26799 	tv = duk_get_borrowed_this_tval(thr);
26800 	DUK_ASSERT(tv != NULL);
26801 
26802 	if (DUK_TVAL_IS_OBJECT(tv)) {
26803 		h_this = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);
26804 		DUK_ASSERT(h_this != NULL);
26805 		if (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_this)) {
26806 			DUK_ASSERT_HBUFOBJ_VALID(h_this);
26807 			return (duk_heaphdr *) h_this;
26808 		}
26809 	} else if (DUK_TVAL_IS_BUFFER(tv)) {
26810 		if (flags & DUK__BUFOBJ_FLAG_PROMOTE) {
26811 			/* Promote a plain buffer to a Uint8Array.  This is very
26812 			 * inefficient but allows plain buffer to be used wherever an
26813 			 * Uint8Array is used with very small cost; hot path functions
26814 			 * like index read/write calls should provide direct buffer
26815 			 * support to avoid promotion.
26816 			 */
26817 			/* XXX: make this conditional to a flag if call sites need it? */
26818 			h_this = duk__hbufobj_promote_this(thr);
26819 			DUK_ASSERT(h_this != NULL);
26820 			DUK_ASSERT_HBUFOBJ_VALID(h_this);
26821 			return (duk_heaphdr *) h_this;
26822 		} else {
26823 			/* XXX: ugly, share return pointer for duk_hbuffer. */
26824 			return (duk_heaphdr *) DUK_TVAL_GET_BUFFER(tv);
26825 		}
26826 	}
26827 
26828 	if (flags & DUK__BUFOBJ_FLAG_THROW) {
26829 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER);
26830 		DUK_WO_NORETURN(return NULL;);
26831 	}
26832 	return NULL;
26833 }
26834 
26835 /* Check that 'this' is a duk_hbufobj and return a pointer to it. */
duk__get_bufobj_this(duk_hthread * thr)26836 DUK_LOCAL duk_hbufobj *duk__get_bufobj_this(duk_hthread *thr) {
26837 	return (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_PROMOTE);
26838 }
26839 
26840 /* Check that 'this' is a duk_hbufobj and return a pointer to it
26841  * (NULL if not).
26842  */
duk__require_bufobj_this(duk_hthread * thr)26843 DUK_LOCAL duk_hbufobj *duk__require_bufobj_this(duk_hthread *thr) {
26844 	return (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW | DUK__BUFOBJ_FLAG_PROMOTE);
26845 }
26846 
26847 /* Check that value is a duk_hbufobj and return a pointer to it. */
duk__require_bufobj_value(duk_hthread * thr,duk_idx_t idx)26848 DUK_LOCAL duk_hbufobj *duk__require_bufobj_value(duk_hthread *thr, duk_idx_t idx) {
26849 	duk_tval *tv;
26850 	duk_hbufobj *h_obj;
26851 
26852 	/* Don't accept relative indices now. */
26853 	DUK_ASSERT(idx >= 0);
26854 
26855 	tv = duk_require_tval(thr, idx);
26856 	DUK_ASSERT(tv != NULL);
26857 	if (DUK_TVAL_IS_OBJECT(tv)) {
26858 		h_obj = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);
26859 		DUK_ASSERT(h_obj != NULL);
26860 		if (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_obj)) {
26861 			DUK_ASSERT_HBUFOBJ_VALID(h_obj);
26862 			return h_obj;
26863 		}
26864 	} else if (DUK_TVAL_IS_BUFFER(tv)) {
26865 		h_obj = (duk_hbufobj *) duk_to_hobject(thr, idx);
26866 		DUK_ASSERT(h_obj != NULL);
26867 		DUK_ASSERT_HBUFOBJ_VALID(h_obj);
26868 		return h_obj;
26869 	}
26870 
26871 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER);
26872 	DUK_WO_NORETURN(return NULL;);
26873 }
26874 
duk__set_bufobj_buffer(duk_hthread * thr,duk_hbufobj * h_bufobj,duk_hbuffer * h_val)26875 DUK_LOCAL void duk__set_bufobj_buffer(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_hbuffer *h_val) {
26876 	DUK_ASSERT(thr != NULL);
26877 	DUK_ASSERT(h_bufobj != NULL);
26878 	DUK_ASSERT(h_bufobj->buf == NULL);  /* no need to decref */
26879 	DUK_ASSERT(h_val != NULL);
26880 	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
26881 	DUK_UNREF(thr);
26882 
26883 	h_bufobj->buf = h_val;
26884 	DUK_HBUFFER_INCREF(thr, h_val);
26885 	h_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val);
26886 	DUK_ASSERT(h_bufobj->shift == 0);
26887 	DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFOBJ_ELEM_UINT8);
26888 	DUK_ASSERT(h_bufobj->is_typedarray == 0);
26889 
26890 	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
26891 }
26892 
26893 /* 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)26894 DUK_LOCAL void duk__resolve_offset_opt_length(duk_hthread *thr,
26895                                               duk_hbufobj *h_bufarg,
26896                                               duk_idx_t idx_offset,
26897                                               duk_idx_t idx_length,
26898                                               duk_uint_t *out_offset,
26899                                               duk_uint_t *out_length,
26900                                               duk_bool_t throw_flag) {
26901 	duk_int_t offset_signed;
26902 	duk_int_t length_signed;
26903 	duk_uint_t offset;
26904 	duk_uint_t length;
26905 
26906 	offset_signed = duk_to_int(thr, idx_offset);
26907 	if (offset_signed < 0) {
26908 		goto fail_range;
26909 	}
26910 	offset = (duk_uint_t) offset_signed;
26911 	if (offset > h_bufarg->length) {
26912 		goto fail_range;
26913 	}
26914 	DUK_ASSERT_DISABLE(offset >= 0);  /* unsigned */
26915 	DUK_ASSERT(offset <= h_bufarg->length);
26916 
26917 	if (duk_is_undefined(thr, idx_length)) {
26918 		DUK_ASSERT(h_bufarg->length >= offset);
26919 		length = h_bufarg->length - offset;  /* >= 0 */
26920 	} else {
26921 		length_signed = duk_to_int(thr, idx_length);
26922 		if (length_signed < 0) {
26923 			goto fail_range;
26924 		}
26925 		length = (duk_uint_t) length_signed;
26926 		DUK_ASSERT(h_bufarg->length >= offset);
26927 		if (length > h_bufarg->length - offset) {
26928 			/* Unlike for negative arguments, some call sites
26929 			 * want length to be clamped if it's positive.
26930 			 */
26931 			if (throw_flag) {
26932 				goto fail_range;
26933 			} else {
26934 				length = h_bufarg->length - offset;
26935 			}
26936 		}
26937 	}
26938 	DUK_ASSERT_DISABLE(length >= 0);  /* unsigned */
26939 	DUK_ASSERT(offset + length <= h_bufarg->length);
26940 
26941 	*out_offset = offset;
26942 	*out_length = length;
26943 	return;
26944 
26945  fail_range:
26946 	DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARGS);
26947 	DUK_WO_NORETURN(return;);
26948 }
26949 
26950 /* Shared lenient buffer length clamping helper.  No negative indices, no
26951  * element/byte shifting.
26952  */
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)26953 DUK_LOCAL void duk__clamp_startend_nonegidx_noshift(duk_hthread *thr,
26954                                                     duk_int_t buffer_length,
26955                                                     duk_idx_t idx_start,
26956                                                     duk_idx_t idx_end,
26957                                                     duk_int_t *out_start_offset,
26958                                                     duk_int_t *out_end_offset) {
26959 	duk_int_t start_offset;
26960 	duk_int_t end_offset;
26961 
26962 	DUK_ASSERT(out_start_offset != NULL);
26963 	DUK_ASSERT(out_end_offset != NULL);
26964 
26965 	/* undefined coerces to zero which is correct */
26966 	start_offset = duk_to_int_clamped(thr, idx_start, 0, buffer_length);
26967 	if (duk_is_undefined(thr, idx_end)) {
26968 		end_offset = buffer_length;
26969 	} else {
26970 		end_offset = duk_to_int_clamped(thr, idx_end, start_offset, buffer_length);
26971 	}
26972 
26973 	DUK_ASSERT(start_offset >= 0);
26974 	DUK_ASSERT(start_offset <= buffer_length);
26975 	DUK_ASSERT(end_offset >= 0);
26976 	DUK_ASSERT(end_offset <= buffer_length);
26977 	DUK_ASSERT(start_offset <= end_offset);
26978 
26979 	*out_start_offset = start_offset;
26980 	*out_end_offset = end_offset;
26981 }
26982 
26983 /* Shared lenient buffer length clamping helper.  Indices are treated as
26984  * element indices (though output values are byte offsets) which only
26985  * really matters for TypedArray views as other buffer object have a zero
26986  * shift.  Negative indices are counted from end of input slice; crossed
26987  * indices are clamped to zero length; and final indices are clamped
26988  * against input slice.  Used for e.g. ArrayBuffer slice().
26989  */
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)26990 DUK_LOCAL void duk__clamp_startend_negidx_shifted(duk_hthread *thr,
26991                                                   duk_int_t buffer_length,
26992                                                   duk_uint8_t buffer_shift,
26993                                                   duk_idx_t idx_start,
26994                                                   duk_idx_t idx_end,
26995                                                   duk_int_t *out_start_offset,
26996                                                   duk_int_t *out_end_offset) {
26997 	duk_int_t start_offset;
26998 	duk_int_t end_offset;
26999 
27000 	DUK_ASSERT(out_start_offset != NULL);
27001 	DUK_ASSERT(out_end_offset != NULL);
27002 
27003 	buffer_length >>= buffer_shift;  /* as (full) elements */
27004 
27005 	/* Resolve start/end offset as element indices first; arguments
27006 	 * at idx_start/idx_end are element offsets.  Working with element
27007 	 * indices first also avoids potential for wrapping.
27008 	 */
27009 
27010 	start_offset = duk_to_int(thr, idx_start);
27011 	if (start_offset < 0) {
27012 		start_offset = buffer_length + start_offset;
27013 	}
27014 	if (duk_is_undefined(thr, idx_end)) {
27015 		end_offset = buffer_length;
27016 	} else {
27017 		end_offset = duk_to_int(thr, idx_end);
27018 		if (end_offset < 0) {
27019 			end_offset = buffer_length + end_offset;
27020 		}
27021 	}
27022 	/* Note: start_offset/end_offset can still be < 0 here. */
27023 
27024 	if (start_offset < 0) {
27025 		start_offset = 0;
27026 	} else if (start_offset > buffer_length) {
27027 		start_offset = buffer_length;
27028 	}
27029 	if (end_offset < start_offset) {
27030 		end_offset = start_offset;
27031 	} else if (end_offset > buffer_length) {
27032 		end_offset = buffer_length;
27033 	}
27034 	DUK_ASSERT(start_offset >= 0);
27035 	DUK_ASSERT(start_offset <= buffer_length);
27036 	DUK_ASSERT(end_offset >= 0);
27037 	DUK_ASSERT(end_offset <= buffer_length);
27038 	DUK_ASSERT(start_offset <= end_offset);
27039 
27040 	/* Convert indices to byte offsets. */
27041 	start_offset <<= buffer_shift;
27042 	end_offset <<= buffer_shift;
27043 
27044 	*out_start_offset = start_offset;
27045 	*out_end_offset = end_offset;
27046 }
27047 
duk_hbufobj_promote_plain(duk_hthread * thr,duk_idx_t idx)27048 DUK_INTERNAL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx) {
27049 	if (duk_is_buffer(thr, idx)) {
27050 		duk_to_object(thr, idx);
27051 	}
27052 }
27053 
duk_hbufobj_push_uint8array_from_plain(duk_hthread * thr,duk_hbuffer * h_buf)27054 DUK_INTERNAL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_hbuffer *h_buf) {
27055 	/* Push Uint8Array which will share the same underlying buffer as
27056 	 * the plain buffer argument.  Also create an ArrayBuffer with the
27057 	 * same backing for the result .buffer property.
27058 	 */
27059 
27060 	duk_push_hbuffer(thr, h_buf);
27061 	duk_push_buffer_object(thr, -1, 0, (duk_size_t) DUK_HBUFFER_GET_SIZE(h_buf), DUK_BUFOBJ_UINT8ARRAY);
27062 	duk_remove_m2(thr);
27063 
27064 #if 0
27065 	/* More verbose equivalent; maybe useful if e.g. .buffer is omitted. */
27066 	h_bufobj = duk_push_bufobj_raw(thr,
27067 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27068 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27069 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_UINT8ARRAY),
27070 	                               DUK_BIDX_UINT8ARRAY_PROTOTYPE);
27071 	DUK_ASSERT(h_bufobj != NULL);
27072 	duk__set_bufobj_buffer(thr, h_bufobj, h_buf);
27073 	h_bufobj->is_typedarray = 1;
27074 	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
27075 
27076 	h_arrbuf = duk_push_bufobj_raw(thr,
27077 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27078 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27079 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
27080 	                               DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
27081 	DUK_ASSERT(h_arrbuf != NULL);
27082 	duk__set_bufobj_buffer(thr, h_arrbuf, h_buf);
27083 	DUK_ASSERT(h_arrbuf->is_typedarray == 0);
27084 	DUK_ASSERT_HBUFOBJ_VALID(h_arrbuf);
27085 
27086 	DUK_ASSERT(h_bufobj->buf_prop == NULL);
27087 	h_bufobj->buf_prop = (duk_hobject *) h_arrbuf;
27088 	DUK_ASSERT(h_arrbuf != NULL);
27089 	DUK_HBUFOBJ_INCREF(thr, h_arrbuf);
27090 	duk_pop(thr);
27091 #endif
27092 }
27093 
27094 /* 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)27095 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) {
27096 	duk_double_union du;
27097 
27098 	DUK_ASSERT(elem_size > 0);
27099 	duk_memcpy((void *) du.uc, (const void *) p, (size_t) elem_size);
27100 
27101 	switch (h_bufobj->elem_type) {
27102 	case DUK_HBUFOBJ_ELEM_UINT8:
27103 	case DUK_HBUFOBJ_ELEM_UINT8CLAMPED:
27104 		duk_push_uint(thr, (duk_uint_t) du.uc[0]);
27105 		break;
27106 	case DUK_HBUFOBJ_ELEM_INT8:
27107 		duk_push_int(thr, (duk_int_t) (duk_int8_t) du.uc[0]);
27108 		break;
27109 	case DUK_HBUFOBJ_ELEM_UINT16:
27110 		duk_push_uint(thr, (duk_uint_t) du.us[0]);
27111 		break;
27112 	case DUK_HBUFOBJ_ELEM_INT16:
27113 		duk_push_int(thr, (duk_int_t) (duk_int16_t) du.us[0]);
27114 		break;
27115 	case DUK_HBUFOBJ_ELEM_UINT32:
27116 		duk_push_uint(thr, (duk_uint_t) du.ui[0]);
27117 		break;
27118 	case DUK_HBUFOBJ_ELEM_INT32:
27119 		duk_push_int(thr, (duk_int_t) (duk_int32_t) du.ui[0]);
27120 		break;
27121 	case DUK_HBUFOBJ_ELEM_FLOAT32:
27122 		duk_push_number(thr, (duk_double_t) du.f[0]);
27123 		break;
27124 	case DUK_HBUFOBJ_ELEM_FLOAT64:
27125 		duk_push_number(thr, (duk_double_t) du.d);
27126 		break;
27127 	default:
27128 		DUK_UNREACHABLE();
27129 	}
27130 }
27131 
27132 /* 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)27133 DUK_INTERNAL void duk_hbufobj_validated_write(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {
27134 	duk_double_union du;
27135 
27136 	/* NOTE! Caller must ensure that any side effects from the
27137 	 * coercions below are safe.  If that cannot be guaranteed
27138 	 * (which is normally the case), caller must coerce the
27139 	 * argument using duk_to_number() before any pointer
27140 	 * validations; the result of duk_to_number() always coerces
27141 	 * without side effects here.
27142 	 */
27143 
27144 	switch (h_bufobj->elem_type) {
27145 	case DUK_HBUFOBJ_ELEM_UINT8:
27146 		du.uc[0] = (duk_uint8_t) duk_to_uint32(thr, -1);
27147 		break;
27148 	case DUK_HBUFOBJ_ELEM_UINT8CLAMPED:
27149 		du.uc[0] = (duk_uint8_t) duk_to_uint8clamped(thr, -1);
27150 		break;
27151 	case DUK_HBUFOBJ_ELEM_INT8:
27152 		du.uc[0] = (duk_uint8_t) duk_to_int32(thr, -1);
27153 		break;
27154 	case DUK_HBUFOBJ_ELEM_UINT16:
27155 		du.us[0] = (duk_uint16_t) duk_to_uint32(thr, -1);
27156 		break;
27157 	case DUK_HBUFOBJ_ELEM_INT16:
27158 		du.us[0] = (duk_uint16_t) duk_to_int32(thr, -1);
27159 		break;
27160 	case DUK_HBUFOBJ_ELEM_UINT32:
27161 		du.ui[0] = (duk_uint32_t) duk_to_uint32(thr, -1);
27162 		break;
27163 	case DUK_HBUFOBJ_ELEM_INT32:
27164 		du.ui[0] = (duk_uint32_t) duk_to_int32(thr, -1);
27165 		break;
27166 	case DUK_HBUFOBJ_ELEM_FLOAT32:
27167 		/* A double-to-float cast is undefined behavior in C99 if
27168 		 * the cast is out-of-range, so use a helper.  Example:
27169 		 * runtime error: value -1e+100 is outside the range of representable values of type 'float'
27170 		 */
27171 		du.f[0] = duk_double_to_float_t(duk_to_number_m1(thr));
27172 		break;
27173 	case DUK_HBUFOBJ_ELEM_FLOAT64:
27174 		du.d = (duk_double_t) duk_to_number_m1(thr);
27175 		break;
27176 	default:
27177 		DUK_UNREACHABLE();
27178 	}
27179 
27180 	DUK_ASSERT(elem_size > 0);
27181 	duk_memcpy((void *) p, (const void *) du.uc, (size_t) elem_size);
27182 }
27183 
27184 /* Helper to create a fixed buffer from argument value at index 0.
27185  * Node.js and allocPlain() compatible.
27186  */
duk__hbufobj_fixed_from_argvalue(duk_hthread * thr)27187 DUK_LOCAL duk_hbuffer *duk__hbufobj_fixed_from_argvalue(duk_hthread *thr) {
27188 	duk_int_t len;
27189 	duk_int_t i;
27190 	duk_size_t buf_size;
27191 	duk_uint8_t *buf;
27192 
27193 	switch (duk_get_type(thr, 0)) {
27194 	case DUK_TYPE_NUMBER: {
27195 		len = duk_to_int_clamped(thr, 0, 0, DUK_INT_MAX);
27196 		(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) len);
27197 		break;
27198 	}
27199 	case DUK_TYPE_BUFFER: { /* Treat like Uint8Array. */
27200 		goto slow_copy;
27201 	}
27202 	case DUK_TYPE_OBJECT: {
27203 		duk_hobject *h;
27204 		duk_hbufobj *h_bufobj;
27205 
27206 		/* For Node.js Buffers "Passing an ArrayBuffer returns a Buffer
27207 		 * that shares allocated memory with the given ArrayBuffer."
27208 		 * https://nodejs.org/api/buffer.html#buffer_buffer_from_buffer_alloc_and_buffer_allocunsafe
27209 		 */
27210 
27211 		h = duk_known_hobject(thr, 0);
27212 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAYBUFFER) {
27213 			DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ(h));
27214 			h_bufobj = (duk_hbufobj *) h;
27215 			if (DUK_UNLIKELY(h_bufobj->buf == NULL)) {
27216 				DUK_ERROR_TYPE_INVALID_ARGS(thr);
27217 				DUK_WO_NORETURN(return NULL;);
27218 			}
27219 			if (DUK_UNLIKELY(h_bufobj->offset != 0 || h_bufobj->length != DUK_HBUFFER_GET_SIZE(h_bufobj->buf))) {
27220 				/* No support for ArrayBuffers with slice
27221 				 * offset/length.
27222 				 */
27223 				DUK_ERROR_TYPE_INVALID_ARGS(thr);
27224 				DUK_WO_NORETURN(return NULL;);
27225 			}
27226 			duk_push_hbuffer(thr, h_bufobj->buf);
27227 			return h_bufobj->buf;
27228 		}
27229 		goto slow_copy;
27230 	}
27231 	case DUK_TYPE_STRING: {
27232 		/* ignore encoding for now */
27233 		duk_require_hstring_notsymbol(thr, 0);
27234 		duk_dup_0(thr);
27235 		(void) duk_to_buffer(thr, -1, &buf_size);
27236 		break;
27237 	}
27238 	default:
27239 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
27240 		DUK_WO_NORETURN(return NULL;);
27241 	}
27242 
27243  done:
27244 	DUK_ASSERT(duk_is_buffer(thr, -1));
27245 	return duk_known_hbuffer(thr, -1);
27246 
27247  slow_copy:
27248 	/* XXX: fast path for typed arrays and other buffer objects? */
27249 
27250 	(void) duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
27251 	len = duk_to_int_clamped(thr, -1, 0, DUK_INT_MAX);
27252 	duk_pop(thr);
27253 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len);  /* no zeroing, all indices get initialized */
27254 	for (i = 0; i < len; i++) {
27255 		/* XXX: fast path for array or buffer arguments? */
27256 		duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
27257 		buf[i] = (duk_uint8_t) (duk_to_uint32(thr, -1) & 0xffU);
27258 		duk_pop(thr);
27259 	}
27260 	goto done;
27261 }
27262 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27263 
27264 /*
27265  *  Node.js Buffer constructor
27266  *
27267  *  Node.js Buffers are just Uint8Arrays with internal prototype set to
27268  *  Buffer.prototype so they're handled otherwise the same as Uint8Array.
27269  *  However, the constructor arguments are very different so a separate
27270  *  constructor entry point is used.
27271  */
27272 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_constructor(duk_hthread * thr)27273 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_hthread *thr) {
27274 	duk_hbuffer *h_buf;
27275 
27276 	h_buf = duk__hbufobj_fixed_from_argvalue(thr);
27277 	DUK_ASSERT(h_buf != NULL);
27278 
27279 	duk_push_buffer_object(thr,
27280 	                       -1,
27281 	                       0,
27282 	                       DUK_HBUFFER_FIXED_GET_SIZE((duk_hbuffer_fixed *) (void *) h_buf),
27283 	                       DUK_BUFOBJ_UINT8ARRAY);
27284 	duk_push_hobject_bidx(thr, DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);
27285 	duk_set_prototype(thr, -2);
27286 
27287 	/* XXX: a more direct implementation */
27288 
27289 	return 1;
27290 }
27291 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27292 
27293 /*
27294  *  ArrayBuffer, DataView, and TypedArray constructors
27295  */
27296 
27297 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_arraybuffer_constructor(duk_hthread * thr)27298 DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_constructor(duk_hthread *thr) {
27299 	duk_hbufobj *h_bufobj;
27300 	duk_hbuffer *h_val;
27301 	duk_int_t len;
27302 
27303 	DUK_ASSERT_CTX_VALID(thr);
27304 
27305 	duk_require_constructor_call(thr);
27306 
27307 	len = duk_to_int(thr, 0);
27308 	if (len < 0) {
27309 		goto fail_length;
27310 	}
27311 	(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) len);
27312 	h_val = (duk_hbuffer *) duk_known_hbuffer(thr, -1);
27313 
27314 	h_bufobj = duk_push_bufobj_raw(thr,
27315 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27316 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27317 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
27318 	                               DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
27319 	DUK_ASSERT(h_bufobj != NULL);
27320 
27321 	duk__set_bufobj_buffer(thr, h_bufobj, h_val);
27322 	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
27323 
27324 	return 1;
27325 
27326  fail_length:
27327 	DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
27328 }
27329 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27330 
27331 
27332 /* Format of magic, bits:
27333  *   0...1: elem size shift (0-3)
27334  *   2...5: elem type (DUK_HBUFOBJ_ELEM_xxx)
27335  *
27336  * XXX: add prototype bidx explicitly to magic instead of using a mapping?
27337  */
27338 
27339 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_typedarray_constructor(duk_hthread * thr)27340 DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
27341 	duk_tval *tv;
27342 	duk_hobject *h_obj;
27343 	duk_hbufobj *h_bufobj = NULL;
27344 	duk_hbufobj *h_bufarg = NULL;
27345 	duk_hbuffer *h_val;
27346 	duk_small_uint_t magic;
27347 	duk_small_uint_t shift;
27348 	duk_small_uint_t elem_type;
27349 	duk_small_uint_t elem_size;
27350 	duk_small_uint_t class_num;
27351 	duk_small_uint_t proto_bidx;
27352 	duk_uint_t align_mask;
27353 	duk_uint_t elem_length;
27354 	duk_int_t elem_length_signed;
27355 	duk_uint_t byte_length;
27356 	duk_small_uint_t copy_mode;
27357 
27358 	/* XXX: The same copy helpers could be shared with at least some
27359 	 * buffer functions.
27360 	 */
27361 
27362 	duk_require_constructor_call(thr);
27363 
27364 	/* We could fit built-in index into magic but that'd make the magic
27365 	 * number dependent on built-in numbering (genbuiltins.py doesn't
27366 	 * handle that yet).  So map both class and prototype from the
27367 	 * element type.
27368 	 */
27369 	magic = (duk_small_uint_t) duk_get_current_magic(thr);
27370 	shift = magic & 0x03U;               /* bits 0...1: shift */
27371 	elem_type = (magic >> 2) & 0x0fU;    /* bits 2...5: type */
27372 	elem_size = 1U << shift;
27373 	align_mask = elem_size - 1;
27374 	DUK_ASSERT(elem_type < sizeof(duk__buffer_proto_from_elemtype) / sizeof(duk_uint8_t));
27375 	proto_bidx = duk__buffer_proto_from_elemtype[elem_type];
27376 	DUK_ASSERT(proto_bidx < DUK_NUM_BUILTINS);
27377 	DUK_ASSERT(elem_type < sizeof(duk__buffer_class_from_elemtype) / sizeof(duk_uint8_t));
27378 	class_num = duk__buffer_class_from_elemtype[elem_type];
27379 
27380 	DUK_DD(DUK_DDPRINT("typedarray constructor, magic=%d, shift=%d, elem_type=%d, "
27381 	                   "elem_size=%d, proto_bidx=%d, class_num=%d",
27382 	                   (int) magic, (int) shift, (int) elem_type, (int) elem_size,
27383 	                   (int) proto_bidx, (int) class_num));
27384 
27385 	/* Argument variants.  When the argument is an ArrayBuffer a view to
27386 	 * the same buffer is created; otherwise a new ArrayBuffer is always
27387 	 * created.
27388 	 */
27389 
27390 	/* XXX: initial iteration to treat a plain buffer like an ArrayBuffer:
27391 	 * coerce to an ArrayBuffer object and use that as .buffer.  The underlying
27392 	 * buffer will be the same but result .buffer !== inputPlainBuffer.
27393 	 */
27394 	duk_hbufobj_promote_plain(thr, 0);
27395 
27396 	tv = duk_get_tval(thr, 0);
27397 	DUK_ASSERT(tv != NULL);  /* arg count */
27398 	if (DUK_TVAL_IS_OBJECT(tv)) {
27399 		h_obj = DUK_TVAL_GET_OBJECT(tv);
27400 		DUK_ASSERT(h_obj != NULL);
27401 
27402 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_ARRAYBUFFER) {
27403 			/* ArrayBuffer: unlike any other argument variant, create
27404 			 * a view into the existing buffer.
27405 			 */
27406 
27407 			duk_int_t byte_offset_signed;
27408 			duk_uint_t byte_offset;
27409 
27410 			h_bufarg = (duk_hbufobj *) h_obj;
27411 
27412 			byte_offset_signed = duk_to_int(thr, 1);
27413 			if (byte_offset_signed < 0) {
27414 				goto fail_arguments;
27415 			}
27416 			byte_offset = (duk_uint_t) byte_offset_signed;
27417 			if (byte_offset > h_bufarg->length ||
27418 			    (byte_offset & align_mask) != 0) {
27419 				/* Must be >= 0 and multiple of element size. */
27420 				goto fail_arguments;
27421 			}
27422 			if (duk_is_undefined(thr, 2)) {
27423 				DUK_ASSERT(h_bufarg->length >= byte_offset);
27424 				byte_length = h_bufarg->length - byte_offset;
27425 				if ((byte_length & align_mask) != 0) {
27426 					/* Must be element size multiple from
27427 					 * start offset to end of buffer.
27428 					 */
27429 					goto fail_arguments;
27430 				}
27431 				elem_length = (byte_length >> shift);
27432 			} else {
27433 				elem_length_signed = duk_to_int(thr, 2);
27434 				if (elem_length_signed < 0) {
27435 					goto fail_arguments;
27436 				}
27437 				elem_length = (duk_uint_t) elem_length_signed;
27438 				byte_length = elem_length << shift;
27439 				if ((byte_length >> shift) != elem_length) {
27440 					/* Byte length would overflow. */
27441 					/* XXX: easier check with less code? */
27442 					goto fail_arguments;
27443 				}
27444 				DUK_ASSERT(h_bufarg->length >= byte_offset);
27445 				if (byte_length > h_bufarg->length - byte_offset) {
27446 					/* Not enough data. */
27447 					goto fail_arguments;
27448 				}
27449 			}
27450 			DUK_UNREF(elem_length);
27451 			DUK_ASSERT_DISABLE(byte_offset >= 0);
27452 			DUK_ASSERT(byte_offset <= h_bufarg->length);
27453 			DUK_ASSERT_DISABLE(byte_length >= 0);
27454 			DUK_ASSERT(byte_offset + byte_length <= h_bufarg->length);
27455 			DUK_ASSERT((elem_length << shift) == byte_length);
27456 
27457 			h_bufobj = duk_push_bufobj_raw(thr,
27458 			                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27459 			                               DUK_HOBJECT_FLAG_BUFOBJ |
27460 			                               DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
27461 			                               (duk_small_int_t) proto_bidx);
27462 			h_val = h_bufarg->buf;
27463 			if (h_val == NULL) {
27464 				DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27465 			}
27466 			h_bufobj->buf = h_val;
27467 			DUK_HBUFFER_INCREF(thr, h_val);
27468 			h_bufobj->offset = h_bufarg->offset + byte_offset;
27469 			h_bufobj->length = byte_length;
27470 			h_bufobj->shift = (duk_uint8_t) shift;
27471 			h_bufobj->elem_type = (duk_uint8_t) elem_type;
27472 			h_bufobj->is_typedarray = 1;
27473 			DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
27474 
27475 			/* Set .buffer to the argument ArrayBuffer. */
27476 			DUK_ASSERT(h_bufobj->buf_prop == NULL);
27477 			h_bufobj->buf_prop = (duk_hobject *) h_bufarg;
27478 			DUK_ASSERT(h_bufarg != NULL);
27479 			DUK_HBUFOBJ_INCREF(thr, h_bufarg);
27480 			return 1;
27481 		} else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
27482 			/* TypedArray (or other non-ArrayBuffer duk_hbufobj).
27483 			 * Conceptually same behavior as for an Array-like argument,
27484 			 * with a few fast paths.
27485 			 */
27486 
27487 			h_bufarg = (duk_hbufobj *) h_obj;
27488 			DUK_ASSERT_HBUFOBJ_VALID(h_bufarg);
27489 			elem_length_signed = (duk_int_t) (h_bufarg->length >> h_bufarg->shift);
27490 			if (h_bufarg->buf == NULL) {
27491 				DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27492 			}
27493 
27494 			/* Select copy mode.  Must take into account element
27495 			 * compatibility and validity of the underlying source
27496 			 * buffer.
27497 			 */
27498 
27499 			DUK_DDD(DUK_DDDPRINT("selecting copy mode for bufobj arg, "
27500 			                     "src byte_length=%ld, src shift=%d, "
27501 			                     "src/dst elem_length=%ld; "
27502 			                     "dst shift=%d -> dst byte_length=%ld",
27503 			                     (long) h_bufarg->length, (int) h_bufarg->shift,
27504 			                     (long) elem_length_signed, (int) shift,
27505 			                     (long) (elem_length_signed << shift)));
27506 
27507 			copy_mode = 2;  /* default is explicit index read/write copy */
27508 #if !defined(DUK_USE_PREFER_SIZE)
27509 			/* With a size optimized build copy_mode 2 is enough.
27510 			 * Modes 0 and 1 are faster but conceptually the same.
27511 			 */
27512 			DUK_ASSERT(elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
27513 			if (DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {
27514 				if ((duk__buffer_elemtype_copy_compatible[elem_type] & (1 << h_bufarg->elem_type)) != 0) {
27515 					DUK_DDD(DUK_DDDPRINT("source/target are copy compatible, memcpy"));
27516 					DUK_ASSERT(shift == h_bufarg->shift);  /* byte sizes will match */
27517 					copy_mode = 0;
27518 				} else {
27519 					DUK_DDD(DUK_DDDPRINT("source/target not copy compatible but valid, fast copy"));
27520 					copy_mode = 1;
27521 				}
27522 			}
27523 #endif  /* !DUK_USE_PREFER_SIZE */
27524 		} else {
27525 			/* Array or Array-like */
27526 			elem_length_signed = (duk_int_t) duk_get_length(thr, 0);
27527 			copy_mode = 2;
27528 		}
27529 	} else {
27530 		/* Non-object argument is simply int coerced, matches
27531 		 * V8 behavior (except for "null", which we coerce to
27532 		 * 0 but V8 TypeErrors).
27533 		 */
27534 		elem_length_signed = duk_to_int(thr, 0);
27535 		copy_mode = 3;
27536 	}
27537 	if (elem_length_signed < 0) {
27538 		goto fail_arguments;
27539 	}
27540 	elem_length = (duk_uint_t) elem_length_signed;
27541 	byte_length = (duk_uint_t) (elem_length << shift);
27542 	if ((byte_length >> shift) != elem_length) {
27543 		/* Byte length would overflow. */
27544 		/* XXX: easier check with less code? */
27545 		goto fail_arguments;
27546 	}
27547 
27548 	DUK_DDD(DUK_DDDPRINT("elem_length=%ld, byte_length=%ld",
27549 	                     (long) elem_length, (long) byte_length));
27550 
27551 	/* ArrayBuffer argument is handled specially above; the rest of the
27552 	 * argument variants are handled by shared code below.
27553 	 *
27554 	 * ArrayBuffer in h_bufobj->buf_prop is intentionally left unset.
27555 	 * It will be automatically created by the .buffer accessor on
27556 	 * first access.
27557 	 */
27558 
27559 	/* Push the resulting view object on top of a plain fixed buffer. */
27560 	(void) duk_push_fixed_buffer(thr, byte_length);
27561 	h_val = duk_known_hbuffer(thr, -1);
27562 	DUK_ASSERT(h_val != NULL);
27563 
27564 	h_bufobj = duk_push_bufobj_raw(thr,
27565 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27566 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27567 	                               DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
27568 	                               (duk_small_int_t) proto_bidx);
27569 
27570 	h_bufobj->buf = h_val;
27571 	DUK_HBUFFER_INCREF(thr, h_val);
27572 	DUK_ASSERT(h_bufobj->offset == 0);
27573 	h_bufobj->length = byte_length;
27574 	h_bufobj->shift = (duk_uint8_t) shift;
27575 	h_bufobj->elem_type = (duk_uint8_t) elem_type;
27576 	h_bufobj->is_typedarray = 1;
27577 	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
27578 
27579 	/* Copy values, the copy method depends on the arguments.
27580 	 *
27581 	 * Copy mode decision may depend on the validity of the underlying
27582 	 * buffer of the source argument; there must be no harmful side effects
27583 	 * from there to here for copy_mode to still be valid.
27584 	 */
27585 	DUK_DDD(DUK_DDDPRINT("copy mode: %d", (int) copy_mode));
27586 	switch (copy_mode) {
27587 		/* Copy modes 0 and 1 can be omitted in size optimized build,
27588 		 * copy mode 2 handles them (but more slowly).
27589 		 */
27590 #if !defined(DUK_USE_PREFER_SIZE)
27591 	case 0: {
27592 		/* Use byte copy. */
27593 
27594 		duk_uint8_t *p_src;
27595 		duk_uint8_t *p_dst;
27596 
27597 		DUK_ASSERT(h_bufobj != NULL);
27598 		DUK_ASSERT(h_bufobj->buf != NULL);
27599 		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufobj));
27600 		DUK_ASSERT(h_bufarg != NULL);
27601 		DUK_ASSERT(h_bufarg->buf != NULL);
27602 		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufarg));
27603 
27604 		p_dst = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj);
27605 		p_src = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
27606 
27607 		DUK_DDD(DUK_DDDPRINT("using memcpy: p_src=%p, p_dst=%p, byte_length=%ld",
27608 		                     (void *) p_src, (void *) p_dst, (long) byte_length));
27609 
27610 		duk_memcpy_unsafe((void *) p_dst, (const void *) p_src, (size_t) byte_length);
27611 		break;
27612 	}
27613 	case 1: {
27614 		/* Copy values through direct validated reads and writes. */
27615 
27616 		duk_small_uint_t src_elem_size;
27617 		duk_small_uint_t dst_elem_size;
27618 		duk_uint8_t *p_src;
27619 		duk_uint8_t *p_src_end;
27620 		duk_uint8_t *p_dst;
27621 
27622 		DUK_ASSERT(h_bufobj != NULL);
27623 		DUK_ASSERT(h_bufobj->buf != NULL);
27624 		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufobj));
27625 		DUK_ASSERT(h_bufarg != NULL);
27626 		DUK_ASSERT(h_bufarg->buf != NULL);
27627 		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufarg));
27628 
27629 		src_elem_size = (duk_small_uint_t) (1U << h_bufarg->shift);
27630 		dst_elem_size = elem_size;
27631 
27632 		p_src = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
27633 		p_dst = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj);
27634 		p_src_end = p_src + h_bufarg->length;
27635 
27636 		DUK_DDD(DUK_DDDPRINT("using fast copy: p_src=%p, p_src_end=%p, p_dst=%p, "
27637 		                     "src_elem_size=%d, dst_elem_size=%d",
27638 		                     (void *) p_src, (void *) p_src_end, (void *) p_dst,
27639 		                     (int) src_elem_size, (int) dst_elem_size));
27640 
27641 		while (p_src != p_src_end) {
27642 			DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
27643 			                     "p_src=%p, p_src_end=%p, p_dst=%p",
27644 			                     (void *) p_src, (void *) p_src_end, (void *) p_dst));
27645 			/* A validated read() is always a number, so it's write coercion
27646 			 * is always side effect free an won't invalidate pointers etc.
27647 			 */
27648 			duk_hbufobj_push_validated_read(thr, h_bufarg, p_src, src_elem_size);
27649 			duk_hbufobj_validated_write(thr, h_bufobj, p_dst, dst_elem_size);
27650 			duk_pop(thr);
27651 			p_src += src_elem_size;
27652 			p_dst += dst_elem_size;
27653 		}
27654 		break;
27655 	}
27656 #endif  /* !DUK_USE_PREFER_SIZE */
27657 	case 2: {
27658 		/* Copy values by index reads and writes.  Let virtual
27659 		 * property handling take care of coercion.
27660 		 */
27661 		duk_uint_t i;
27662 
27663 		DUK_DDD(DUK_DDDPRINT("using slow copy"));
27664 
27665 		for (i = 0; i < elem_length; i++) {
27666 			duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
27667 			duk_put_prop_index(thr, -2, (duk_uarridx_t) i);
27668 		}
27669 		break;
27670 	}
27671 	default:
27672 	case 3: {
27673 		/* No copy, leave zero bytes in the buffer.  There's no
27674 		 * ambiguity with Float32/Float64 because zero bytes also
27675 		 * represent 0.0.
27676 		 */
27677 
27678 		DUK_DDD(DUK_DDDPRINT("using no copy"));
27679 		break;
27680 	}
27681 	}
27682 
27683 	return 1;
27684 
27685  fail_arguments:
27686 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
27687 }
27688 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27689 /* When bufferobject support is disabled, new Uint8Array() could still be
27690  * supported to create a plain fixed buffer.  Disabled for now.
27691  */
27692 #if 0
27693 DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
27694 	duk_int_t elem_length_signed;
27695 	duk_uint_t byte_length;
27696 
27697 	/* XXX: The same copy helpers could be shared with at least some
27698 	 * buffer functions.
27699 	 */
27700 
27701 	duk_require_constructor_call(thr);
27702 
27703 	elem_length_signed = duk_require_int(thr, 0);
27704 	if (elem_length_signed < 0) {
27705 		goto fail_arguments;
27706 	}
27707 	byte_length = (duk_uint_t) elem_length_signed;
27708 
27709 	(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) byte_length);
27710 	return 1;
27711 
27712  fail_arguments:
27713 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
27714 }
27715 #endif  /* 0 */
27716 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27717 
27718 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_dataview_constructor(duk_hthread * thr)27719 DUK_INTERNAL duk_ret_t duk_bi_dataview_constructor(duk_hthread *thr) {
27720 	duk_hbufobj *h_bufarg;
27721 	duk_hbufobj *h_bufobj;
27722 	duk_hbuffer *h_val;
27723 	duk_uint_t offset;
27724 	duk_uint_t length;
27725 
27726 	duk_require_constructor_call(thr);
27727 
27728 	h_bufarg = duk__require_bufobj_value(thr, 0);
27729 	DUK_ASSERT(h_bufarg != NULL);
27730 	if (DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_bufarg) != DUK_HOBJECT_CLASS_ARRAYBUFFER) {
27731 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27732 	}
27733 
27734 	duk__resolve_offset_opt_length(thr, h_bufarg, 1, 2, &offset, &length, 1 /*throw_flag*/);
27735 	DUK_ASSERT(offset <= h_bufarg->length);
27736 	DUK_ASSERT(offset + length <= h_bufarg->length);
27737 
27738 	h_bufobj = duk_push_bufobj_raw(thr,
27739 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27740 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27741 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATAVIEW),
27742 	                               DUK_BIDX_DATAVIEW_PROTOTYPE);
27743 
27744 	h_val = h_bufarg->buf;
27745 	if (h_val == NULL) {
27746 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27747 	}
27748 	h_bufobj->buf = h_val;
27749 	DUK_HBUFFER_INCREF(thr, h_val);
27750 	h_bufobj->offset = h_bufarg->offset + offset;
27751 	h_bufobj->length = length;
27752 	DUK_ASSERT(h_bufobj->shift == 0);
27753 	DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFOBJ_ELEM_UINT8);
27754 	DUK_ASSERT(h_bufobj->is_typedarray == 0);
27755 
27756 	DUK_ASSERT(h_bufobj->buf_prop == NULL);
27757 	h_bufobj->buf_prop = (duk_hobject *) h_bufarg;
27758 	DUK_ASSERT(h_bufarg != NULL);
27759 	DUK_HBUFOBJ_INCREF(thr, h_bufarg);
27760 
27761 	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
27762 	return 1;
27763 }
27764 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27765 
27766 /*
27767  *  ArrayBuffer.isView()
27768  */
27769 
27770 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_arraybuffer_isview(duk_hthread * thr)27771 DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_isview(duk_hthread *thr) {
27772 	duk_hobject *h_obj;
27773 	duk_bool_t ret = 0;
27774 
27775 	if (duk_is_buffer(thr, 0)) {
27776 		ret = 1;
27777 	} else {
27778 		h_obj = duk_get_hobject(thr, 0);
27779 		if (h_obj != NULL && DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
27780 			/* DataView needs special casing: ArrayBuffer.isView() is
27781 			 * true, but ->is_typedarray is 0.
27782 			 */
27783 			ret = ((duk_hbufobj *) h_obj)->is_typedarray ||
27784 			      (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_DATAVIEW);
27785 		}
27786 	}
27787 	duk_push_boolean(thr, ret);
27788 	return 1;
27789 }
27790 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27791 
27792 /*
27793  *  Uint8Array.allocPlain()
27794  */
27795 
27796 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_uint8array_allocplain(duk_hthread * thr)27797 DUK_INTERNAL duk_ret_t duk_bi_uint8array_allocplain(duk_hthread *thr) {
27798 	duk__hbufobj_fixed_from_argvalue(thr);
27799 	return 1;
27800 }
27801 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27802 
27803 /*
27804  *  Uint8Array.plainOf()
27805  */
27806 
27807 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_uint8array_plainof(duk_hthread * thr)27808 DUK_INTERNAL duk_ret_t duk_bi_uint8array_plainof(duk_hthread *thr) {
27809 	duk_hbufobj *h_bufobj;
27810 
27811 #if !defined(DUK_USE_PREFER_SIZE)
27812 	/* Avoid churn if argument is already a plain buffer. */
27813 	if (duk_is_buffer(thr, 0)) {
27814 		return 1;
27815 	}
27816 #endif
27817 
27818 	/* Promotes plain buffers to ArrayBuffers, so for a plain buffer
27819 	 * argument we'll create a pointless temporary (but still work
27820 	 * correctly).
27821 	 */
27822 	h_bufobj = duk__require_bufobj_value(thr, 0);
27823 	if (h_bufobj->buf == NULL) {
27824 		duk_push_undefined(thr);
27825 	} else {
27826 		duk_push_hbuffer(thr, h_bufobj->buf);
27827 	}
27828 	return 1;
27829 }
27830 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27831 
27832 /*
27833  *  Node.js Buffer: toString([encoding], [start], [end])
27834  */
27835 
27836 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_tostring(duk_hthread * thr)27837 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_hthread *thr) {
27838 	duk_hbufobj *h_this;
27839 	duk_int_t start_offset, end_offset;
27840 	duk_uint8_t *buf_slice;
27841 	duk_size_t slice_length;
27842 
27843 	h_this = duk__get_bufobj_this(thr);
27844 	if (h_this == NULL) {
27845 		/* XXX: happens e.g. when evaluating: String(Buffer.prototype). */
27846 		duk_push_literal(thr, "[object Object]");
27847 		return 1;
27848 	}
27849 	DUK_ASSERT_HBUFOBJ_VALID(h_this);
27850 
27851 	/* Ignore encoding for now. */
27852 
27853 	duk__clamp_startend_nonegidx_noshift(thr,
27854 	                                     (duk_int_t) h_this->length,
27855 	                                     1 /*idx_start*/,
27856 	                                     2 /*idx_end*/,
27857 	                                     &start_offset,
27858 	                                     &end_offset);
27859 
27860 	slice_length = (duk_size_t) (end_offset - start_offset);
27861 	buf_slice = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, slice_length);  /* all bytes initialized below */
27862 	DUK_ASSERT(buf_slice != NULL);
27863 
27864 	/* Neutered or uncovered, TypeError. */
27865 	if (h_this->buf == NULL ||
27866 	    !DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, (duk_size_t) start_offset + slice_length)) {
27867 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27868 	}
27869 
27870 	/* XXX: ideally we wouldn't make a copy but a view into the buffer for the
27871 	 * decoding process.  Or the decoding helper could be changed to accept
27872 	 * the slice info (a buffer pointer is NOT a good approach because guaranteeing
27873 	 * its stability is difficult).
27874 	 */
27875 
27876 	DUK_ASSERT(DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, (duk_size_t) start_offset + slice_length));
27877 	duk_memcpy_unsafe((void *) buf_slice,
27878 	                  (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
27879 	                  (size_t) slice_length);
27880 
27881 	/* Use the equivalent of: new TextEncoder().encode(this) to convert the
27882 	 * string.  Result will be valid UTF-8; non-CESU-8 inputs are currently
27883 	 * interpreted loosely.  Value stack convention is a bit odd for now.
27884 	 */
27885 	duk_replace(thr, 0);
27886 	duk_set_top(thr, 1);
27887 	return duk_textdecoder_decode_utf8_nodejs(thr);
27888 }
27889 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27890 
27891 /*
27892  *  Node.js Buffer.prototype: toJSON()
27893  */
27894 
27895 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_tojson(duk_hthread * thr)27896 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_hthread *thr) {
27897 	duk_hbufobj *h_this;
27898 	duk_uint8_t *buf;
27899 	duk_uint_t i, n;
27900 	duk_tval *tv;
27901 
27902 	h_this = duk__require_bufobj_this(thr);
27903 	DUK_ASSERT(h_this != NULL);
27904 
27905 	if (h_this->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_this)) {
27906 		/* Serialize uncovered backing buffer as a null; doesn't
27907 		 * really matter as long we're memory safe.
27908 		 */
27909 		duk_push_null(thr);
27910 		return 1;
27911 	}
27912 
27913 	duk_push_object(thr);
27914 	duk_push_hstring_stridx(thr, DUK_STRIDX_UC_BUFFER);
27915 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_TYPE);
27916 
27917 	/* XXX: uninitialized would be OK */
27918 	DUK_ASSERT_DISABLE((duk_size_t) h_this->length <= (duk_size_t) DUK_UINT32_MAX);
27919 	tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) h_this->length);  /* XXX: needs revision with >4G buffers */
27920 
27921 	DUK_ASSERT(h_this->buf != NULL);
27922 	buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
27923 	for (i = 0, n = h_this->length; i < n; i++) {
27924 		DUK_TVAL_SET_U32(tv + i, (duk_uint32_t) buf[i]);  /* no need for decref or incref */
27925 	}
27926 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_DATA);
27927 
27928 	return 1;
27929 }
27930 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27931 
27932 /*
27933  *  Node.js Buffer.prototype.equals()
27934  *  Node.js Buffer.prototype.compare()
27935  *  Node.js Buffer.compare()
27936  */
27937 
27938 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_buffer_compare_shared(duk_hthread * thr)27939 DUK_INTERNAL duk_ret_t duk_bi_buffer_compare_shared(duk_hthread *thr) {
27940 	duk_small_uint_t magic;
27941 	duk_hbufobj *h_bufarg1;
27942 	duk_hbufobj *h_bufarg2;
27943 	duk_small_int_t comp_res;
27944 
27945 	/* XXX: keep support for plain buffers and non-Node.js buffers? */
27946 
27947 	magic = (duk_small_uint_t) duk_get_current_magic(thr);
27948 	if (magic & 0x02U) {
27949 		/* Static call style. */
27950 		h_bufarg1 = duk__require_bufobj_value(thr, 0);
27951 		h_bufarg2 = duk__require_bufobj_value(thr, 1);
27952 	} else {
27953 		h_bufarg1 = duk__require_bufobj_this(thr);
27954 		h_bufarg2 = duk__require_bufobj_value(thr, 0);
27955 	}
27956 	DUK_ASSERT(h_bufarg1 != NULL);
27957 	DUK_ASSERT(h_bufarg2 != NULL);
27958 
27959 	/* We want to compare the slice/view areas of the arguments.
27960 	 * If either slice/view is invalid (underlying buffer is shorter)
27961 	 * ensure equals() is false, but otherwise the only thing that
27962 	 * matters is to be memory safe.
27963 	 */
27964 
27965 	if (DUK_HBUFOBJ_VALID_SLICE(h_bufarg1) &&
27966 	    DUK_HBUFOBJ_VALID_SLICE(h_bufarg2)) {
27967 		comp_res = duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg1->buf) + h_bufarg1->offset,
27968 		                               (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg2->buf) + h_bufarg2->offset,
27969 		                               (duk_size_t) h_bufarg1->length,
27970 		                               (duk_size_t) h_bufarg2->length);
27971 	} else {
27972 		comp_res = -1;  /* either nonzero value is ok */
27973 	}
27974 
27975 	if (magic & 0x01U) {
27976 		/* compare: similar to string comparison but for buffer data. */
27977 		duk_push_int(thr, comp_res);
27978 	} else {
27979 		/* equals */
27980 		duk_push_boolean(thr, (comp_res == 0));
27981 	}
27982 
27983 	return 1;
27984 }
27985 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27986 
27987 /*
27988  *  Node.js Buffer.prototype.fill()
27989  */
27990 
27991 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_fill(duk_hthread * thr)27992 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_fill(duk_hthread *thr) {
27993 	duk_hbufobj *h_this;
27994 	const duk_uint8_t *fill_str_ptr;
27995 	duk_size_t fill_str_len;
27996 	duk_uint8_t fill_value;
27997 	duk_int_t fill_offset;
27998 	duk_int_t fill_end;
27999 	duk_size_t fill_length;
28000 	duk_uint8_t *p;
28001 
28002 	h_this = duk__require_bufobj_this(thr);
28003 	DUK_ASSERT(h_this != NULL);
28004 	if (h_this->buf == NULL) {
28005 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28006 	}
28007 
28008 	/* [ value offset end ] */
28009 
28010 	if (duk_is_string_notsymbol(thr, 0)) {
28011 		fill_str_ptr = (const duk_uint8_t *) duk_get_lstring(thr, 0, &fill_str_len);
28012 		DUK_ASSERT(fill_str_ptr != NULL);
28013 	} else {
28014 		/* Symbols get ToNumber() coerced and cause TypeError. */
28015 		fill_value = (duk_uint8_t) duk_to_uint32(thr, 0);
28016 		fill_str_ptr = (const duk_uint8_t *) &fill_value;
28017 		fill_str_len = 1;
28018 	}
28019 
28020 	/* Fill offset handling is more lenient than in Node.js. */
28021 
28022 	duk__clamp_startend_nonegidx_noshift(thr,
28023 	                                     (duk_int_t) h_this->length,
28024 	                                     1 /*idx_start*/,
28025 	                                     2 /*idx_end*/,
28026 	                                     &fill_offset,
28027 	                                     &fill_end);
28028 
28029 	DUK_DDD(DUK_DDDPRINT("fill: fill_value=%02x, fill_offset=%ld, fill_end=%ld, view length=%ld",
28030 	                     (unsigned int) fill_value, (long) fill_offset, (long) fill_end, (long) h_this->length));
28031 
28032 	DUK_ASSERT(fill_end - fill_offset >= 0);
28033 	DUK_ASSERT(h_this->buf != NULL);
28034 
28035 	p = (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + fill_offset);
28036 	fill_length = (duk_size_t) (fill_end - fill_offset);
28037 	if (fill_str_len == 1) {
28038 		/* Handle single character fills as memset() even when
28039 		 * the fill data comes from a one-char argument.
28040 		 */
28041 		duk_memset_unsafe((void *) p, (int) fill_str_ptr[0], (size_t) fill_length);
28042 	} else if (fill_str_len > 1) {
28043 		duk_size_t i, n, t;
28044 
28045 		for (i = 0, n = (duk_size_t) (fill_end - fill_offset), t = 0; i < n; i++) {
28046 			p[i] = fill_str_ptr[t++];
28047 			if (t >= fill_str_len) {
28048 				t = 0;
28049 			}
28050 		}
28051 	} else {
28052 		DUK_DDD(DUK_DDDPRINT("zero size fill pattern, ignore silently"));
28053 	}
28054 
28055 	/* Return the Buffer to allow chaining: b.fill(0x11).fill(0x22, 3, 5).toString() */
28056 	duk_push_this(thr);
28057 	return 1;
28058 }
28059 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28060 
28061 /*
28062  *  Node.js Buffer.prototype.write(string, [offset], [length], [encoding])
28063  */
28064 
28065 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_write(duk_hthread * thr)28066 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_write(duk_hthread *thr) {
28067 	duk_hbufobj *h_this;
28068 	duk_uint_t offset;
28069 	duk_uint_t length;
28070 	const duk_uint8_t *str_data;
28071 	duk_size_t str_len;
28072 
28073 	/* XXX: very inefficient support for plain buffers */
28074 	h_this = duk__require_bufobj_this(thr);
28075 	DUK_ASSERT(h_this != NULL);
28076 
28077 	/* Argument must be a string, e.g. a buffer is not allowed. */
28078 	str_data = (const duk_uint8_t *) duk_require_lstring_notsymbol(thr, 0, &str_len);
28079 
28080 	duk__resolve_offset_opt_length(thr, h_this, 1, 2, &offset, &length, 0 /*throw_flag*/);
28081 	DUK_ASSERT(offset <= h_this->length);
28082 	DUK_ASSERT(offset + length <= h_this->length);
28083 
28084 	/* XXX: encoding is ignored now. */
28085 
28086 	if (length > str_len) {
28087 		length = (duk_uint_t) str_len;
28088 	}
28089 
28090 	if (DUK_HBUFOBJ_VALID_SLICE(h_this)) {
28091 		/* Cannot overlap. */
28092 		duk_memcpy_unsafe((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset),
28093 		                  (const void *) str_data,
28094 		                  (size_t) length);
28095 	} else {
28096 		DUK_DDD(DUK_DDDPRINT("write() target buffer is not covered, silent ignore"));
28097 	}
28098 
28099 	duk_push_uint(thr, length);
28100 	return 1;
28101 }
28102 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28103 
28104 /*
28105  *  Node.js Buffer.prototype.copy()
28106  */
28107 
28108 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_copy(duk_hthread * thr)28109 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_copy(duk_hthread *thr) {
28110 	duk_hbufobj *h_this;
28111 	duk_hbufobj *h_bufarg;
28112 	duk_int_t source_length;
28113 	duk_int_t target_length;
28114 	duk_int_t target_start, source_start, source_end;
28115 	duk_uint_t target_ustart, source_ustart, source_uend;
28116 	duk_uint_t copy_size = 0;
28117 
28118 	/* [ targetBuffer targetStart sourceStart sourceEnd ] */
28119 
28120 	h_this = duk__require_bufobj_this(thr);
28121 	h_bufarg = duk__require_bufobj_value(thr, 0);
28122 	DUK_ASSERT(h_this != NULL);
28123 	DUK_ASSERT(h_bufarg != NULL);
28124 	source_length = (duk_int_t) h_this->length;
28125 	target_length = (duk_int_t) h_bufarg->length;
28126 
28127 	target_start = duk_to_int(thr, 1);
28128 	source_start = duk_to_int(thr, 2);
28129 	if (duk_is_undefined(thr, 3)) {
28130 		source_end = source_length;
28131 	} else {
28132 		source_end = duk_to_int(thr, 3);
28133 	}
28134 
28135 	DUK_DDD(DUK_DDDPRINT("checking copy args: target_start=%ld, target_length=%ld, "
28136 	                     "source_start=%ld, source_end=%ld, source_length=%ld",
28137 	                     (long) target_start, (long) h_bufarg->length,
28138 	                     (long) source_start, (long) source_end, (long) source_length));
28139 
28140 	/* This behavior mostly mimics Node.js now. */
28141 
28142 	if (source_start < 0 || source_end < 0 || target_start < 0) {
28143 		/* Negative offsets cause a RangeError. */
28144 		goto fail_bounds;
28145 	}
28146 	source_ustart = (duk_uint_t) source_start;
28147 	source_uend = (duk_uint_t) source_end;
28148 	target_ustart = (duk_uint_t) target_start;
28149 	if (source_ustart >= source_uend ||  /* crossed offsets or zero size */
28150 	    source_ustart >= (duk_uint_t) source_length ||  /* source out-of-bounds (but positive) */
28151 	    target_ustart >= (duk_uint_t) target_length) {  /* target out-of-bounds (but positive) */
28152 		goto silent_ignore;
28153 	}
28154 	if (source_uend >= (duk_uint_t) source_length) {
28155 		/* Source end clamped silently to available length. */
28156 		source_uend = (duk_uint_t) source_length;
28157 	}
28158 	copy_size = source_uend - source_ustart;
28159 	if (target_ustart + copy_size > (duk_uint_t) target_length) {
28160 		/* Clamp to target's end if too long.
28161 		 *
28162 		 * NOTE: there's no overflow possibility in the comparison;
28163 		 * both target_ustart and copy_size are >= 0 and based on
28164 		 * values in duk_int_t range.  Adding them as duk_uint_t
28165 		 * values is then guaranteed not to overflow.
28166 		 */
28167 		DUK_ASSERT(target_ustart + copy_size >= target_ustart);  /* no overflow */
28168 		DUK_ASSERT(target_ustart + copy_size >= copy_size);  /* no overflow */
28169 		copy_size = (duk_uint_t) target_length - target_ustart;
28170 	}
28171 
28172 	DUK_DDD(DUK_DDDPRINT("making copy: target_ustart=%lu source_ustart=%lu copy_size=%lu",
28173 	                     (unsigned long) target_ustart, (unsigned long) source_ustart,
28174 	                     (unsigned long) copy_size));
28175 
28176 	DUK_ASSERT(copy_size >= 1);
28177 	DUK_ASSERT(source_ustart <= (duk_uint_t) source_length);
28178 	DUK_ASSERT(source_ustart + copy_size <= (duk_uint_t) source_length);
28179 	DUK_ASSERT(target_ustart <= (duk_uint_t) target_length);
28180 	DUK_ASSERT(target_ustart + copy_size <= (duk_uint_t) target_length);
28181 
28182 	/* Ensure copy is covered by underlying buffers. */
28183 	DUK_ASSERT(h_bufarg->buf != NULL);  /* length check */
28184 	DUK_ASSERT(h_this->buf != NULL);    /* length check */
28185 	if (DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufarg, target_ustart + copy_size) &&
28186 	    DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, source_ustart + copy_size)) {
28187 		/* Must use memmove() because copy area may overlap (source and target
28188 		 * buffer may be the same, or from different slices.
28189 		 */
28190 		duk_memmove_unsafe((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg) + target_ustart),
28191 		                   (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + source_ustart),
28192 		                   (size_t) copy_size);
28193 	} else {
28194 		DUK_DDD(DUK_DDDPRINT("buffer copy not covered by underlying buffer(s), ignoring"));
28195 	}
28196 
28197  silent_ignore:
28198 	/* Return value is like write(), number of bytes written.
28199 	 * The return value matters because of code like:
28200 	 * "off += buf.copy(...)".
28201          */
28202 	duk_push_uint(thr, copy_size);
28203 	return 1;
28204 
28205  fail_bounds:
28206 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
28207 }
28208 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28209 
28210 /*
28211  *  TypedArray.prototype.set()
28212  *
28213  *  TypedArray set() is pretty interesting to implement because:
28214  *
28215  *    - The source argument may be a plain array or a typedarray.  If the
28216  *      source is a TypedArray, values are decoded and re-encoded into the
28217  *      target (not as a plain byte copy).  This may happen even when the
28218  *      element byte size is the same, e.g. integer values may be re-encoded
28219  *      into floats.
28220  *
28221  *    - Source and target may refer to the same underlying buffer, so that
28222  *      the set() operation may overlap.  The specification requires that this
28223  *      must work as if a copy was made before the operation.  Note that this
28224  *      is NOT a simple memmove() situation because the source and target
28225  *      byte sizes may be different -- e.g. a 4-byte source (Int8Array) may
28226  *      expand to a 16-byte target (Uint32Array) so that the target overlaps
28227  *      the source both from beginning and the end (unlike in typical memmove).
28228  *
28229  *    - Even if 'buf' pointers of the source and target differ, there's no
28230  *      guarantee that their memory areas don't overlap.  This may be the
28231  *      case with external buffers.
28232  *
28233  *  Even so, it is nice to optimize for the common case:
28234  *
28235  *    - Source and target separate buffers or non-overlapping.
28236  *
28237  *    - Source and target have a compatible type so that a plain byte copy
28238  *      is possible.  Note that while e.g. uint8 and int8 are compatible
28239  *      (coercion one way or another doesn't change the byte representation),
28240  *      e.g. int8 and uint8clamped are NOT compatible when writing int8
28241  *      values into uint8clamped typedarray (-1 would clamp to 0 for instance).
28242  *
28243  *  See test-bi-typedarray-proto-set.js.
28244  */
28245 
28246 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_typedarray_set(duk_hthread * thr)28247 DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_hthread *thr) {
28248 	duk_hbufobj *h_this;
28249 	duk_hobject *h_obj;
28250 	duk_uarridx_t i, n;
28251 	duk_int_t offset_signed;
28252 	duk_uint_t offset_elems;
28253 	duk_uint_t offset_bytes;
28254 
28255 	h_this = duk__require_bufobj_this(thr);
28256 	DUK_ASSERT(h_this != NULL);
28257 	DUK_ASSERT_HBUFOBJ_VALID(h_this);
28258 
28259 	if (h_this->buf == NULL) {
28260 		DUK_DDD(DUK_DDDPRINT("source neutered, skip copy"));
28261 		return 0;
28262 	}
28263 
28264 	duk_hbufobj_promote_plain(thr, 0);
28265 	h_obj = duk_require_hobject(thr, 0);
28266 
28267 	/* XXX: V8 throws a TypeError for negative values.  Would it
28268 	 * be more useful to interpret negative offsets here from the
28269 	 * end of the buffer too?
28270 	 */
28271 	offset_signed = duk_to_int(thr, 1);
28272 	if (offset_signed < 0) {
28273 		/* For some reason this is a TypeError (at least in V8). */
28274 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28275 	}
28276 	offset_elems = (duk_uint_t) offset_signed;
28277 	offset_bytes = offset_elems << h_this->shift;
28278 	if ((offset_bytes >> h_this->shift) != offset_elems) {
28279 		/* Byte length would overflow. */
28280 		/* XXX: easier check with less code? */
28281 		goto fail_args;
28282 	}
28283 	if (offset_bytes > h_this->length) {
28284 		/* Equality may be OK but >length not.  Checking
28285 		 * this explicitly avoids some overflow cases
28286 		 * below.
28287 		 */
28288 		goto fail_args;
28289 	}
28290 	DUK_ASSERT(offset_bytes <= h_this->length);
28291 
28292 	/* Fast path: source is a TypedArray (or any bufobj). */
28293 
28294 	if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
28295 		duk_hbufobj *h_bufarg;
28296 #if !defined(DUK_USE_PREFER_SIZE)
28297 		duk_uint16_t comp_mask;
28298 #endif
28299 		duk_small_int_t no_overlap = 0;
28300 		duk_uint_t src_length;
28301 		duk_uint_t dst_length;
28302 		duk_uint_t dst_length_elems;
28303 		duk_uint8_t *p_src_base;
28304 		duk_uint8_t *p_src_end;
28305 		duk_uint8_t *p_src;
28306 		duk_uint8_t *p_dst_base;
28307 		duk_uint8_t *p_dst;
28308 		duk_small_uint_t src_elem_size;
28309 		duk_small_uint_t dst_elem_size;
28310 
28311 		h_bufarg = (duk_hbufobj *) h_obj;
28312 		DUK_ASSERT_HBUFOBJ_VALID(h_bufarg);
28313 
28314 		if (h_bufarg->buf == NULL) {
28315 			DUK_DDD(DUK_DDDPRINT("target neutered, skip copy"));
28316 			return 0;
28317 		}
28318 
28319 		/* Nominal size check. */
28320 		src_length = h_bufarg->length;  /* bytes in source */
28321 		dst_length_elems = (src_length >> h_bufarg->shift);  /* elems in source and dest */
28322 		dst_length = dst_length_elems << h_this->shift;  /* bytes in dest */
28323 		if ((dst_length >> h_this->shift) != dst_length_elems) {
28324 			/* Byte length would overflow. */
28325 			/* XXX: easier check with less code? */
28326 			goto fail_args;
28327 		}
28328 		DUK_DDD(DUK_DDDPRINT("nominal size check: src_length=%ld, dst_length=%ld",
28329 		                     (long) src_length, (long) dst_length));
28330 		DUK_ASSERT(offset_bytes <= h_this->length);
28331 		if (dst_length > h_this->length - offset_bytes) {
28332 			/* Overflow not an issue because subtraction is used on the right
28333 			 * side and guaranteed to be >= 0.
28334 			 */
28335 			DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
28336 			goto fail_args;
28337 		}
28338 		if (!DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, offset_bytes + dst_length)) {
28339 			DUK_DDD(DUK_DDDPRINT("copy not covered by underlying target buffer, ignore"));
28340 			return 0;
28341 		}
28342 
28343 		p_src_base = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
28344 		p_dst_base = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset_bytes;
28345 
28346 		/* Check actual underlying buffers for validity and that they
28347 		 * cover the copy.  No side effects are allowed after the check
28348 		 * so that the validity status doesn't change.
28349 		 */
28350 		if (!DUK_HBUFOBJ_VALID_SLICE(h_this) ||
28351 		    !DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {
28352 			/* The condition could be more narrow and check for the
28353 			 * copy area only, but there's no need for fine grained
28354 			 * behavior when the underlying buffer is misconfigured.
28355 			 */
28356 			DUK_DDD(DUK_DDDPRINT("source and/or target not covered by underlying buffer, skip copy"));
28357 			return 0;
28358 		}
28359 
28360 		/* We want to do a straight memory copy if possible: this is
28361 		 * an important operation because .set() is the TypedArray
28362 		 * way to copy chunks of memory.  However, because set()
28363 		 * conceptually works in terms of elements, not all views are
28364 		 * compatible with direct byte copying.
28365 		 *
28366 		 * If we do manage a direct copy, the "overlap issue" handled
28367 		 * below can just be solved using memmove() because the source
28368 		 * and destination element sizes are necessarily equal.
28369 		 */
28370 
28371 #if !defined(DUK_USE_PREFER_SIZE)
28372 		DUK_ASSERT(h_this->elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
28373 		comp_mask = duk__buffer_elemtype_copy_compatible[h_this->elem_type];
28374 		if (comp_mask & (1 << h_bufarg->elem_type)) {
28375 			DUK_ASSERT(src_length == dst_length);
28376 
28377 			DUK_DDD(DUK_DDDPRINT("fast path: able to use memmove() because views are compatible"));
28378 			duk_memmove_unsafe((void *) p_dst_base, (const void *) p_src_base, (size_t) dst_length);
28379 			return 0;
28380 		}
28381 		DUK_DDD(DUK_DDDPRINT("fast path: views are not compatible with a byte copy, copy by item"));
28382 #endif  /* !DUK_USE_PREFER_SIZE */
28383 
28384 		/* We want to avoid making a copy to process set() but that's
28385 		 * not always possible: the source and the target may overlap
28386 		 * and because element sizes are different, the overlap cannot
28387 		 * always be handled with a memmove() or choosing the copy
28388 		 * direction in a certain way.  For example, if source type is
28389 		 * uint8 and target type is uint32, the target area may exceed
28390 		 * the source area from both ends!
28391 		 *
28392 		 * Note that because external buffers may point to the same
28393 		 * memory areas, we must ultimately make this check using
28394 		 * pointers.
28395 		 *
28396 		 * NOTE: careful with side effects: any side effect may cause
28397 		 * a buffer resize (or external buffer pointer/length update)!
28398 		 */
28399 
28400 		DUK_DDD(DUK_DDDPRINT("overlap check: p_src_base=%p, src_length=%ld, "
28401 		                     "p_dst_base=%p, dst_length=%ld",
28402 		                     (void *) p_src_base, (long) src_length,
28403 		                     (void *) p_dst_base, (long) dst_length));
28404 
28405 		if (p_src_base >= p_dst_base + dst_length ||  /* source starts after dest ends */
28406 		    p_src_base + src_length <= p_dst_base) {   /* source ends before dest starts */
28407 			no_overlap = 1;
28408 		}
28409 
28410 		if (!no_overlap) {
28411 			/* There's overlap: the desired end result is that
28412 			 * conceptually a copy is made to avoid "trampling"
28413 			 * of source data by destination writes.  We make
28414 			 * an actual temporary copy to handle this case.
28415 			 */
28416 			duk_uint8_t *p_src_copy;
28417 
28418 			DUK_DDD(DUK_DDDPRINT("there is overlap, make a copy of the source"));
28419 			p_src_copy = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, src_length);
28420 			DUK_ASSERT(p_src_copy != NULL);
28421 			duk_memcpy_unsafe((void *) p_src_copy, (const void *) p_src_base, (size_t) src_length);
28422 
28423 			p_src_base = p_src_copy;  /* use p_src_base from now on */
28424 		}
28425 		/* Value stack intentionally mixed size here. */
28426 
28427 		DUK_DDD(DUK_DDDPRINT("after overlap check: p_src_base=%p, src_length=%ld, "
28428 		                     "p_dst_base=%p, dst_length=%ld, valstack top=%ld",
28429 		                     (void *) p_src_base, (long) src_length,
28430 		                     (void *) p_dst_base, (long) dst_length,
28431 		                     (long) duk_get_top(thr)));
28432 
28433 		/* Ready to make the copy.  We must proceed element by element
28434 		 * and must avoid any side effects that might cause the buffer
28435 		 * validity check above to become invalid.
28436 		 *
28437 		 * Although we work through the value stack here, only plain
28438 		 * numbers are handled which should be side effect safe.
28439 		 */
28440 
28441 		src_elem_size = (duk_small_uint_t) (1U << h_bufarg->shift);
28442 		dst_elem_size = (duk_small_uint_t) (1U << h_this->shift);
28443 		p_src = p_src_base;
28444 		p_dst = p_dst_base;
28445 		p_src_end = p_src_base + src_length;
28446 
28447 		while (p_src != p_src_end) {
28448 			DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
28449 			                     "p_src=%p, p_src_end=%p, p_dst=%p",
28450 			                     (void *) p_src, (void *) p_src_end, (void *) p_dst));
28451 			/* A validated read() is always a number, so it's write coercion
28452 			 * is always side effect free an won't invalidate pointers etc.
28453 			 */
28454 			duk_hbufobj_push_validated_read(thr, h_bufarg, p_src, src_elem_size);
28455 			duk_hbufobj_validated_write(thr, h_this, p_dst, dst_elem_size);
28456 			duk_pop(thr);
28457 			p_src += src_elem_size;
28458 			p_dst += dst_elem_size;
28459 		}
28460 
28461 		return 0;
28462 	} else {
28463 		/* Slow path: quite slow, but we save space by using the property code
28464 		 * to write coerce target values.  We don't need to worry about overlap
28465 		 * here because the source is not a TypedArray.
28466 		 *
28467 		 * We could use the bufobj write coercion helper but since the
28468 		 * property read may have arbitrary side effects, full validity checks
28469 		 * would be needed for every element anyway.
28470 		 */
28471 
28472 		n = (duk_uarridx_t) duk_get_length(thr, 0);
28473 		DUK_ASSERT(offset_bytes <= h_this->length);
28474 		if ((n << h_this->shift) > h_this->length - offset_bytes) {
28475 			/* Overflow not an issue because subtraction is used on the right
28476 			 * side and guaranteed to be >= 0.
28477 			 */
28478 			DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
28479 			goto fail_args;
28480 		}
28481 
28482 		/* There's no need to check for buffer validity status for the
28483 		 * target here: the property access code will do that for each
28484 		 * element.  Moreover, if we did check the validity here, side
28485 		 * effects from reading the source argument might invalidate
28486 		 * the results anyway.
28487 		 */
28488 
28489 		DUK_ASSERT_TOP(thr, 2);
28490 		duk_push_this(thr);
28491 
28492 		for (i = 0; i < n; i++) {
28493 			duk_get_prop_index(thr, 0, i);
28494 			duk_put_prop_index(thr, 2, offset_elems + i);
28495 		}
28496 	}
28497 
28498 	return 0;
28499 
28500  fail_args:
28501 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
28502 }
28503 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28504 
28505 /*
28506  *  Node.js Buffer.prototype.slice([start], [end])
28507  *  ArrayBuffer.prototype.slice(begin, [end])
28508  *  TypedArray.prototype.subarray(begin, [end])
28509  *
28510  *  The API calls are almost identical; negative indices are counted from end
28511  *  of buffer, and final indices are clamped (allowing crossed indices).  Main
28512  *  differences:
28513  *
28514  *    - Copy/view behavior; Node.js .slice() and TypedArray .subarray() create
28515  *      views, ArrayBuffer .slice() creates a copy
28516  *
28517  *    - Resulting object has a different class and prototype depending on the
28518  *      call (or 'this' argument)
28519  *
28520  *    - TypedArray .subarray() arguments are element indices, not byte offsets
28521  *
28522  *    - Plain buffer argument creates a plain buffer slice
28523  */
28524 
28525 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk__arraybuffer_plain_slice(duk_hthread * thr,duk_hbuffer * h_val)28526 DUK_LOCAL void duk__arraybuffer_plain_slice(duk_hthread *thr, duk_hbuffer *h_val) {
28527 	duk_int_t start_offset, end_offset;
28528 	duk_uint_t slice_length;
28529 	duk_uint8_t *p_copy;
28530 	duk_size_t copy_length;
28531 
28532 	duk__clamp_startend_negidx_shifted(thr,
28533 	                                   (duk_int_t) DUK_HBUFFER_GET_SIZE(h_val),
28534 	                                   0 /*buffer_shift*/,
28535 	                                   0 /*idx_start*/,
28536 	                                   1 /*idx_end*/,
28537 	                                   &start_offset,
28538 	                                   &end_offset);
28539 	DUK_ASSERT(end_offset <= (duk_int_t) DUK_HBUFFER_GET_SIZE(h_val));
28540 	DUK_ASSERT(start_offset >= 0);
28541 	DUK_ASSERT(end_offset >= start_offset);
28542 	slice_length = (duk_uint_t) (end_offset - start_offset);
28543 
28544 	p_copy = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) slice_length);
28545 	DUK_ASSERT(p_copy != NULL);
28546 	copy_length = slice_length;
28547 
28548 	duk_memcpy_unsafe((void *) p_copy,
28549 	                  (const void *) ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_val) + start_offset),
28550 	                  copy_length);
28551 }
28552 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
28553 
28554 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
28555 /* Shared helper for slice/subarray operation.
28556  * Magic: 0x01=isView, 0x02=copy, 0x04=Node.js Buffer special handling.
28557  */
duk_bi_buffer_slice_shared(duk_hthread * thr)28558 DUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_hthread *thr) {
28559 	duk_small_int_t magic;
28560 	duk_small_uint_t res_class_num;
28561 	duk_small_int_t res_proto_bidx;
28562 	duk_hbufobj *h_this;
28563 	duk_hbufobj *h_bufobj;
28564 	duk_hbuffer *h_val;
28565 	duk_int_t start_offset, end_offset;
28566 	duk_uint_t slice_length;
28567 	duk_tval *tv;
28568 
28569 	/* [ start end ] */
28570 
28571 	magic = duk_get_current_magic(thr);
28572 
28573 	tv = duk_get_borrowed_this_tval(thr);
28574 	DUK_ASSERT(tv != NULL);
28575 
28576 	if (DUK_TVAL_IS_BUFFER(tv)) {
28577 		/* For plain buffers return a plain buffer slice. */
28578 		h_val = DUK_TVAL_GET_BUFFER(tv);
28579 		DUK_ASSERT(h_val != NULL);
28580 
28581 		if (magic & 0x02) {
28582 			/* Make copy: ArrayBuffer.prototype.slice() uses this. */
28583 			duk__arraybuffer_plain_slice(thr, h_val);
28584 			return 1;
28585 		} else {
28586 			/* View into existing buffer: cannot be done if the
28587 			 * result is a plain buffer because there's no slice
28588 			 * info.  So return an ArrayBuffer instance; coerce
28589 			 * the 'this' binding into an object and behave as if
28590 			 * the original call was for an Object-coerced plain
28591 			 * buffer (handled automatically by duk__require_bufobj_this()).
28592 			 */
28593 
28594 			DUK_DDD(DUK_DDDPRINT("slice() doesn't handle view into plain buffer, coerce 'this' to ArrayBuffer object"));
28595 			/* fall through */
28596 		}
28597 	}
28598 	tv = NULL;  /* No longer valid nor needed. */
28599 
28600 	h_this = duk__require_bufobj_this(thr);
28601 
28602 	/* Slice offsets are element (not byte) offsets, which only matters
28603 	 * for TypedArray views, Node.js Buffer and ArrayBuffer have shift
28604 	 * zero so byte and element offsets are the same.  Negative indices
28605 	 * are counted from end of slice, crossed indices are allowed (and
28606 	 * result in zero length result), and final values are clamped
28607 	 * against the current slice.  There's intentionally no check
28608 	 * against the underlying buffer here.
28609 	 */
28610 
28611 	duk__clamp_startend_negidx_shifted(thr,
28612 	                                   (duk_int_t) h_this->length,
28613 	                                   (duk_uint8_t) h_this->shift,
28614 	                                   0 /*idx_start*/,
28615 	                                   1 /*idx_end*/,
28616 	                                   &start_offset,
28617 	                                   &end_offset);
28618 	DUK_ASSERT(end_offset >= start_offset);
28619 	DUK_ASSERT(start_offset >= 0);
28620 	DUK_ASSERT(end_offset >= 0);
28621 	slice_length = (duk_uint_t) (end_offset - start_offset);
28622 
28623 	/* The resulting buffer object gets the same class and prototype as
28624 	 * the buffer in 'this', e.g. if the input is a Uint8Array the
28625 	 * result is a Uint8Array; if the input is a Float32Array, the
28626 	 * result is a Float32Array.  The result internal prototype should
28627 	 * be the default prototype for the class (e.g. initial value of
28628 	 * Uint8Array.prototype), not copied from the argument (Duktape 1.x
28629 	 * did that).
28630 	 *
28631 	 * Node.js Buffers have special handling: they're Uint8Arrays as far
28632 	 * as the internal class is concerned, so the new Buffer should also
28633 	 * be an Uint8Array but inherit from Buffer.prototype.
28634 	 */
28635 	res_class_num = DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_this);
28636 	DUK_ASSERT(res_class_num >= DUK_HOBJECT_CLASS_BUFOBJ_MIN);  /* type check guarantees */
28637 	DUK_ASSERT(res_class_num <= DUK_HOBJECT_CLASS_BUFOBJ_MAX);
28638 	res_proto_bidx = duk__buffer_proto_from_classnum[res_class_num - DUK_HOBJECT_CLASS_BUFOBJ_MIN];
28639 	if (magic & 0x04) {
28640 		res_proto_bidx = DUK_BIDX_NODEJS_BUFFER_PROTOTYPE;
28641 	}
28642 	h_bufobj = duk_push_bufobj_raw(thr,
28643 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
28644 	                               DUK_HOBJECT_FLAG_BUFOBJ |
28645 	                               DUK_HOBJECT_CLASS_AS_FLAGS(res_class_num),
28646 	                               res_proto_bidx);
28647 	DUK_ASSERT(h_bufobj != NULL);
28648 
28649 	DUK_ASSERT(h_bufobj->length == 0);
28650 	h_bufobj->shift = h_this->shift;  /* inherit */
28651 	h_bufobj->elem_type = h_this->elem_type;  /* inherit */
28652 	h_bufobj->is_typedarray = magic & 0x01;
28653 	DUK_ASSERT(h_bufobj->is_typedarray == 0 || h_bufobj->is_typedarray == 1);
28654 
28655 	h_val = h_this->buf;
28656 	if (h_val == NULL) {
28657 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28658 	}
28659 
28660 	if (magic & 0x02) {
28661 		/* non-zero: make copy */
28662 		duk_uint8_t *p_copy;
28663 		duk_size_t copy_length;
28664 
28665 		p_copy = (duk_uint8_t *) duk_push_fixed_buffer_zero(thr, (duk_size_t) slice_length);  /* must be zeroed, not all bytes always copied */
28666 		DUK_ASSERT(p_copy != NULL);
28667 
28668 		/* Copy slice, respecting underlying buffer limits; remainder
28669 		 * is left as zero.
28670 		 */
28671 		copy_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, slice_length);
28672 		duk_memcpy_unsafe((void *) p_copy,
28673 		                  (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
28674 		                  copy_length);
28675 
28676 		h_val = duk_known_hbuffer(thr, -1);
28677 
28678 		h_bufobj->buf = h_val;
28679 		DUK_HBUFFER_INCREF(thr, h_val);
28680 		h_bufobj->length = slice_length;
28681 		DUK_ASSERT(h_bufobj->offset == 0);
28682 
28683 		duk_pop(thr);  /* reachable so pop OK */
28684 	} else {
28685 		h_bufobj->buf = h_val;
28686 		DUK_HBUFFER_INCREF(thr, h_val);
28687 		h_bufobj->length = slice_length;
28688 		h_bufobj->offset = h_this->offset + (duk_uint_t) start_offset;
28689 
28690 		/* Copy the .buffer property, needed for TypedArray.prototype.subarray().
28691 		 *
28692 		 * XXX: limit copy only for TypedArray classes specifically?
28693 		 */
28694 
28695 		DUK_ASSERT(h_bufobj->buf_prop == NULL);
28696 		h_bufobj->buf_prop = h_this->buf_prop;  /* may be NULL */
28697 		DUK_HOBJECT_INCREF_ALLOWNULL(thr, (duk_hobject *) h_bufobj->buf_prop);
28698 	}
28699 	/* unbalanced stack on purpose */
28700 
28701 	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
28702 	return 1;
28703 }
28704 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28705 
28706 /*
28707  *  Node.js Buffer.isEncoding()
28708  */
28709 
28710 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_is_encoding(duk_hthread * thr)28711 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_hthread *thr) {
28712 	const char *encoding;
28713 
28714 	/* only accept lowercase 'utf8' now. */
28715 
28716 	encoding = duk_to_string(thr, 0);
28717 	DUK_ASSERT(duk_is_string(thr, 0));  /* guaranteed by duk_to_string() */
28718 	duk_push_boolean(thr, DUK_STRCMP(encoding, "utf8") == 0);
28719 	return 1;
28720 }
28721 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28722 
28723 /*
28724  *  Node.js Buffer.isBuffer()
28725  */
28726 
28727 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_is_buffer(duk_hthread * thr)28728 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_hthread *thr) {
28729 	duk_hobject *h;
28730 	duk_hobject *h_proto;
28731 	duk_bool_t ret = 0;
28732 
28733 	DUK_ASSERT(duk_get_top(thr) >= 1);  /* nargs */
28734 	h = duk_get_hobject(thr, 0);
28735 	if (h != NULL) {
28736 		h_proto = thr->builtins[DUK_BIDX_NODEJS_BUFFER_PROTOTYPE];
28737 		DUK_ASSERT(h_proto != NULL);
28738 
28739 		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
28740 		if (h != NULL) {
28741 			ret = duk_hobject_prototype_chain_contains(thr, h, h_proto, 0 /*ignore_loop*/);
28742 		}
28743 	}
28744 
28745 	duk_push_boolean(thr, ret);
28746 	return 1;
28747 }
28748 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28749 
28750 /*
28751  *  Node.js Buffer.byteLength()
28752  */
28753 
28754 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_byte_length(duk_hthread * thr)28755 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_hthread *thr) {
28756 	const char *str;
28757 	duk_size_t len;
28758 
28759 	/* At the moment Buffer(<str>) will just use the string bytes as
28760 	 * is (ignoring encoding), so we return the string length here
28761 	 * unconditionally.
28762 	 */
28763 
28764 	/* XXX: to be revised; Old Node.js behavior just coerces any buffer
28765 	 * values to string:
28766 	 * $ node
28767 	 * > Buffer.byteLength(new Uint32Array(10))
28768 	 * 20
28769 	 * > Buffer.byteLength(new Uint32Array(100))
28770 	 * 20
28771 	 * (The 20 comes from '[object Uint32Array]'.length
28772 	 */
28773 
28774 	str = duk_to_lstring(thr, 0, &len);
28775 	DUK_UNREF(str);
28776 	duk_push_size_t(thr, len);
28777 	return 1;
28778 }
28779 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28780 
28781 /*
28782  *  Node.js Buffer.concat()
28783  */
28784 
28785 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_concat(duk_hthread * thr)28786 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_hthread *thr) {
28787 	duk_hobject *h_arg;
28788 	duk_uint_t total_length;
28789 	duk_hbufobj *h_bufobj;
28790 	duk_hbufobj *h_bufres;
28791 	duk_hbuffer *h_val;
28792 	duk_uint_t i, n;
28793 	duk_uint8_t *p;
28794 	duk_size_t space_left;
28795 	duk_size_t copy_size;
28796 
28797 	/* Node.js accepts only actual Arrays. */
28798 	h_arg = duk_require_hobject(thr, 0);
28799 	if (DUK_HOBJECT_GET_CLASS_NUMBER(h_arg) != DUK_HOBJECT_CLASS_ARRAY) {
28800 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28801 	}
28802 
28803 	/* Compute result length and validate argument buffers. */
28804 	n = (duk_uint_t) duk_get_length(thr, 0);
28805 	total_length = 0;
28806 	for (i = 0; i < n; i++) {
28807 		/* Neutered checks not necessary here: neutered buffers have
28808 		 * zero 'length' so we'll effectively skip them.
28809 		 */
28810 		DUK_ASSERT_TOP(thr, 2);  /* [ array totalLength ] */
28811 		duk_get_prop_index(thr, 0, (duk_uarridx_t) i);  /* -> [ array totalLength buf ] */
28812 		h_bufobj = duk__require_bufobj_value(thr, 2);
28813 		DUK_ASSERT(h_bufobj != NULL);
28814 		total_length += h_bufobj->length;
28815 		if (DUK_UNLIKELY(total_length < h_bufobj->length)) {
28816 			DUK_DCERROR_RANGE_INVALID_ARGS(thr);  /* Wrapped. */
28817 		}
28818 		duk_pop(thr);
28819 	}
28820 	/* In Node.js v0.12.1 a 1-element array is special and won't create a
28821 	 * copy, this was fixed later so an explicit check no longer needed.
28822 	 */
28823 
28824 	/* User totalLength overrides a computed length, but we'll check
28825 	 * every copy in the copy loop.  Note that duk_to_int() can
28826 	 * technically have arbitrary side effects so we need to recheck
28827 	 * the buffers in the copy loop.
28828 	 */
28829 	if (!duk_is_undefined(thr, 1) && n > 0) {
28830 		/* For n == 0, Node.js ignores totalLength argument and
28831 		 * returns a zero length buffer.
28832 		 */
28833 		duk_int_t total_length_signed;
28834 		total_length_signed = duk_to_int(thr, 1);
28835 		if (total_length_signed < 0) {
28836 			DUK_DCERROR_RANGE_INVALID_ARGS(thr);
28837 		}
28838 		total_length = (duk_uint_t) total_length_signed;
28839 	}
28840 
28841 	h_bufres = duk_push_bufobj_raw(thr,
28842 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
28843 	                               DUK_HOBJECT_FLAG_BUFOBJ |
28844 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_UINT8ARRAY),
28845 	                               DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);
28846 	DUK_ASSERT(h_bufres != NULL);
28847 
28848 	p = (duk_uint8_t *) duk_push_fixed_buffer_zero(thr, total_length);  /* must be zeroed, all bytes not necessarily written over */
28849 	DUK_ASSERT(p != NULL);
28850 	space_left = (duk_size_t) total_length;
28851 
28852 	for (i = 0; i < n; i++) {
28853 		DUK_ASSERT_TOP(thr, 4);  /* [ array totalLength bufres buf ] */
28854 
28855 		duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
28856 		h_bufobj = duk__require_bufobj_value(thr, 4);
28857 		DUK_ASSERT(h_bufobj != NULL);
28858 
28859 		copy_size = h_bufobj->length;
28860 		if (copy_size > space_left) {
28861 			copy_size = space_left;
28862 		}
28863 
28864 		if (h_bufobj->buf != NULL &&
28865 		    DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
28866 			duk_memcpy_unsafe((void *) p,
28867 			                  (const void *) DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj),
28868 			                  copy_size);
28869 		} else {
28870 			/* Just skip, leaving zeroes in the result. */
28871 			;
28872 		}
28873 		p += copy_size;
28874 		space_left -= copy_size;
28875 
28876 		duk_pop(thr);
28877 	}
28878 
28879 	h_val = duk_known_hbuffer(thr, -1);
28880 
28881 	duk__set_bufobj_buffer(thr, h_bufres, h_val);
28882 	h_bufres->is_typedarray = 1;
28883 	DUK_ASSERT_HBUFOBJ_VALID(h_bufres);
28884 
28885 	duk_pop(thr);  /* pop plain buffer, now reachable through h_bufres */
28886 
28887 	return 1;  /* return h_bufres */
28888 }
28889 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28890 
28891 /*
28892  *  Shared readfield and writefield methods
28893  *
28894  *  The readfield/writefield methods need support for endianness and field
28895  *  types.  All offsets are byte based so no offset shifting is needed.
28896  */
28897 
28898 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
28899 /* Format of magic, bits:
28900  *   0...1: field type; 0=uint8, 1=uint16, 2=uint32, 3=float, 4=double, 5=unused, 6=unused, 7=unused
28901  *       3: endianness: 0=little, 1=big
28902  *       4: signed: 1=yes, 0=no
28903  *       5: typedarray: 1=yes, 0=no
28904  */
28905 #define  DUK__FLD_8BIT         0
28906 #define  DUK__FLD_16BIT        1
28907 #define  DUK__FLD_32BIT        2
28908 #define  DUK__FLD_FLOAT        3
28909 #define  DUK__FLD_DOUBLE       4
28910 #define  DUK__FLD_VARINT       5
28911 #define  DUK__FLD_BIGENDIAN    (1 << 3)
28912 #define  DUK__FLD_SIGNED       (1 << 4)
28913 #define  DUK__FLD_TYPEDARRAY   (1 << 5)
28914 
28915 /* XXX: split into separate functions for each field type? */
duk_bi_buffer_readfield(duk_hthread * thr)28916 DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {
28917 	duk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(thr);
28918 	duk_small_int_t magic_ftype;
28919 	duk_small_int_t magic_bigendian;
28920 	duk_small_int_t magic_signed;
28921 	duk_small_int_t magic_typedarray;
28922 	duk_small_int_t endswap;
28923 	duk_hbufobj *h_this;
28924 	duk_bool_t no_assert;
28925 	duk_int_t offset_signed;
28926 	duk_uint_t offset;
28927 	duk_uint_t buffer_length;
28928 	duk_uint_t check_length;
28929 	duk_uint8_t *buf;
28930 	duk_double_union du;
28931 
28932 	magic_ftype = magic & 0x0007;
28933 	magic_bigendian = magic & 0x0008;
28934 	magic_signed = magic & 0x0010;
28935 	magic_typedarray = magic & 0x0020;
28936 
28937 	h_this = duk__require_bufobj_this(thr);  /* XXX: very inefficient for plain buffers */
28938 	DUK_ASSERT(h_this != NULL);
28939 	buffer_length = h_this->length;
28940 
28941 	/* [ offset noAssert                 ], when ftype != DUK__FLD_VARINT */
28942 	/* [ offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
28943 	/* [ offset littleEndian             ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
28944 
28945 	/* Handle TypedArray vs. Node.js Buffer arg differences */
28946 	if (magic_typedarray) {
28947 		no_assert = 0;
28948 #if defined(DUK_USE_INTEGER_LE)
28949 		endswap = !duk_to_boolean(thr, 1);  /* 1=little endian */
28950 #else
28951 		endswap = duk_to_boolean(thr, 1);  /* 1=little endian */
28952 #endif
28953 	} else {
28954 		no_assert = duk_to_boolean(thr, (magic_ftype == DUK__FLD_VARINT) ? 2 : 1);
28955 #if defined(DUK_USE_INTEGER_LE)
28956 		endswap = magic_bigendian;
28957 #else
28958 		endswap = !magic_bigendian;
28959 #endif
28960 	}
28961 
28962 	/* Offset is coerced first to signed integer range and then to unsigned.
28963 	 * This ensures we can add a small byte length (1-8) to the offset in
28964 	 * bound checks and not wrap.
28965 	 */
28966 	offset_signed = duk_to_int(thr, 0);
28967 	offset = (duk_uint_t) offset_signed;
28968 	if (offset_signed < 0) {
28969 		goto fail_bounds;
28970 	}
28971 
28972 	DUK_DDD(DUK_DDDPRINT("readfield, buffer_length=%ld, offset=%ld, no_assert=%d, "
28973 	                     "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
28974 	                     "endswap=%d",
28975 	                     (long) buffer_length, (long) offset, (int) no_assert,
28976 	                     (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
28977 	                     (int) (magic_signed >> 4), (int) endswap));
28978 
28979 	/* Update 'buffer_length' to be the effective, safe limit which
28980 	 * takes into account the underlying buffer.  This value will be
28981 	 * potentially invalidated by any side effect.
28982 	 */
28983 	check_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, buffer_length);
28984 	DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
28985 	                     (long) buffer_length, (long) check_length));
28986 
28987 	if (h_this->buf) {
28988 		buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
28989 	} else {
28990 		/* Neutered.  We could go into the switch-case safely with
28991 		 * buf == NULL because check_length == 0.  To avoid scanbuild
28992 		 * warnings, fail directly instead.
28993 		 */
28994 		DUK_ASSERT(check_length == 0);
28995 		goto fail_neutered;
28996 	}
28997 	DUK_ASSERT(buf != NULL);
28998 
28999 	switch (magic_ftype) {
29000 	case DUK__FLD_8BIT: {
29001 		duk_uint8_t tmp;
29002 		if (offset + 1U > check_length) {
29003 			goto fail_bounds;
29004 		}
29005 		tmp = buf[offset];
29006 		if (magic_signed) {
29007 			duk_push_int(thr, (duk_int_t) ((duk_int8_t) tmp));
29008 		} else {
29009 			duk_push_uint(thr, (duk_uint_t) tmp);
29010 		}
29011 		break;
29012 	}
29013 	case DUK__FLD_16BIT: {
29014 		duk_uint16_t tmp;
29015 		if (offset + 2U > check_length) {
29016 			goto fail_bounds;
29017 		}
29018 		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 2);
29019 		tmp = du.us[0];
29020 		if (endswap) {
29021 			tmp = DUK_BSWAP16(tmp);
29022 		}
29023 		if (magic_signed) {
29024 			duk_push_int(thr, (duk_int_t) ((duk_int16_t) tmp));
29025 		} else {
29026 			duk_push_uint(thr, (duk_uint_t) tmp);
29027 		}
29028 		break;
29029 	}
29030 	case DUK__FLD_32BIT: {
29031 		duk_uint32_t tmp;
29032 		if (offset + 4U > check_length) {
29033 			goto fail_bounds;
29034 		}
29035 		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 4);
29036 		tmp = du.ui[0];
29037 		if (endswap) {
29038 			tmp = DUK_BSWAP32(tmp);
29039 		}
29040 		if (magic_signed) {
29041 			duk_push_int(thr, (duk_int_t) ((duk_int32_t) tmp));
29042 		} else {
29043 			duk_push_uint(thr, (duk_uint_t) tmp);
29044 		}
29045 		break;
29046 	}
29047 	case DUK__FLD_FLOAT: {
29048 		duk_uint32_t tmp;
29049 		if (offset + 4U > check_length) {
29050 			goto fail_bounds;
29051 		}
29052 		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 4);
29053 		if (endswap) {
29054 			tmp = du.ui[0];
29055 			tmp = DUK_BSWAP32(tmp);
29056 			du.ui[0] = tmp;
29057 		}
29058 		duk_push_number(thr, (duk_double_t) du.f[0]);
29059 		break;
29060 	}
29061 	case DUK__FLD_DOUBLE: {
29062 		if (offset + 8U > check_length) {
29063 			goto fail_bounds;
29064 		}
29065 		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 8);
29066 		if (endswap) {
29067 			DUK_DBLUNION_BSWAP64(&du);
29068 		}
29069 		duk_push_number(thr, (duk_double_t) du.d);
29070 		break;
29071 	}
29072 	case DUK__FLD_VARINT: {
29073 		/* Node.js Buffer variable width integer field.  We don't really
29074 		 * care about speed here, so aim for shortest algorithm.
29075 		 */
29076 		duk_int_t field_bytelen;
29077 		duk_int_t i, i_step, i_end;
29078 #if defined(DUK_USE_64BIT_OPS)
29079 		duk_int64_t tmp;
29080 		duk_small_uint_t shift_tmp;
29081 #else
29082 		duk_double_t tmp;
29083 		duk_small_int_t highbyte;
29084 #endif
29085 		const duk_uint8_t *p;
29086 
29087 		field_bytelen = duk_get_int(thr, 1);  /* avoid side effects! */
29088 		if (field_bytelen < 1 || field_bytelen > 6) {
29089 			goto fail_field_length;
29090 		}
29091 		if (offset + (duk_uint_t) field_bytelen > check_length) {
29092 			goto fail_bounds;
29093 		}
29094 		p = (const duk_uint8_t *) (buf + offset);
29095 
29096 		/* Slow gathering of value using either 64-bit arithmetic
29097 		 * or IEEE doubles if 64-bit types not available.  Handling
29098 		 * of negative numbers is a bit non-obvious in both cases.
29099 		 */
29100 
29101 		if (magic_bigendian) {
29102 			/* Gather in big endian */
29103 			i = 0;
29104 			i_step = 1;
29105 			i_end = field_bytelen;  /* one i_step over */
29106 		} else {
29107 			/* Gather in little endian */
29108 			i = field_bytelen - 1;
29109 			i_step = -1;
29110 			i_end = -1;  /* one i_step over */
29111 		}
29112 
29113 #if defined(DUK_USE_64BIT_OPS)
29114 		tmp = 0;
29115 		do {
29116 			DUK_ASSERT(i >= 0 && i < field_bytelen);
29117 			tmp = (tmp << 8) + (duk_int64_t) p[i];
29118 			i += i_step;
29119 		} while (i != i_end);
29120 
29121 		if (magic_signed) {
29122 			/* Shift to sign extend.  Left shift must be unsigned
29123 			 * to avoid undefined behavior; right shift must be
29124 			 * signed to sign extend properly.
29125 			 */
29126 			shift_tmp = (duk_small_uint_t) (64U - (duk_small_uint_t) field_bytelen * 8U);
29127 			tmp = (duk_int64_t) ((duk_uint64_t) tmp << shift_tmp) >> shift_tmp;
29128 		}
29129 
29130 		duk_push_i64(thr, tmp);
29131 #else
29132 		highbyte = p[i];
29133 		if (magic_signed && (highbyte & 0x80) != 0) {
29134 			/* 0xff => 255 - 256 = -1; 0x80 => 128 - 256 = -128 */
29135 			tmp = (duk_double_t) (highbyte - 256);
29136 		} else {
29137 			tmp = (duk_double_t) highbyte;
29138 		}
29139 		for (;;) {
29140 			i += i_step;
29141 			if (i == i_end) {
29142 				break;
29143 			}
29144 			DUK_ASSERT(i >= 0 && i < field_bytelen);
29145 			tmp = (tmp * 256.0) + (duk_double_t) p[i];
29146 		}
29147 
29148 		duk_push_number(thr, tmp);
29149 #endif
29150 		break;
29151 	}
29152 	default: {  /* should never happen but default here */
29153 		goto fail_bounds;
29154 	}
29155 	}
29156 
29157 	return 1;
29158 
29159  fail_neutered:
29160  fail_field_length:
29161  fail_bounds:
29162 	if (no_assert) {
29163 		/* Node.js return value for noAssert out-of-bounds reads is
29164 		 * usually (but not always) NaN.  Return NaN consistently.
29165 		 */
29166 		duk_push_nan(thr);
29167 		return 1;
29168 	}
29169 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
29170 }
29171 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29172 
29173 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29174 /* XXX: split into separate functions for each field type? */
duk_bi_buffer_writefield(duk_hthread * thr)29175 DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
29176 	duk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(thr);
29177 	duk_small_int_t magic_ftype;
29178 	duk_small_int_t magic_bigendian;
29179 	duk_small_int_t magic_signed;
29180 	duk_small_int_t magic_typedarray;
29181 	duk_small_int_t endswap;
29182 	duk_hbufobj *h_this;
29183 	duk_bool_t no_assert;
29184 	duk_int_t offset_signed;
29185 	duk_uint_t offset;
29186 	duk_uint_t buffer_length;
29187 	duk_uint_t check_length;
29188 	duk_uint8_t *buf;
29189 	duk_double_union du;
29190 	duk_int_t nbytes = 0;
29191 
29192 	magic_ftype = magic & 0x0007;
29193 	magic_bigendian = magic & 0x0008;
29194 	magic_signed = magic & 0x0010;
29195 	magic_typedarray = magic & 0x0020;
29196 	DUK_UNREF(magic_signed);
29197 
29198 	h_this = duk__require_bufobj_this(thr);  /* XXX: very inefficient for plain buffers */
29199 	DUK_ASSERT(h_this != NULL);
29200 	buffer_length = h_this->length;
29201 
29202 	/* [ value  offset noAssert                 ], when ftype != DUK__FLD_VARINT */
29203 	/* [ value  offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
29204 	/* [ offset value  littleEndian             ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
29205 
29206 	/* Handle TypedArray vs. Node.js Buffer arg differences */
29207 	if (magic_typedarray) {
29208 		no_assert = 0;
29209 #if defined(DUK_USE_INTEGER_LE)
29210 		endswap = !duk_to_boolean(thr, 2);  /* 1=little endian */
29211 #else
29212 		endswap = duk_to_boolean(thr, 2);  /* 1=little endian */
29213 #endif
29214 		duk_swap(thr, 0, 1);  /* offset/value order different from Node.js */
29215 	} else {
29216 		no_assert = duk_to_boolean(thr, (magic_ftype == DUK__FLD_VARINT) ? 3 : 2);
29217 #if defined(DUK_USE_INTEGER_LE)
29218 		endswap = magic_bigendian;
29219 #else
29220 		endswap = !magic_bigendian;
29221 #endif
29222 	}
29223 
29224 	/* Offset is coerced first to signed integer range and then to unsigned.
29225 	 * This ensures we can add a small byte length (1-8) to the offset in
29226 	 * bound checks and not wrap.
29227 	 */
29228 	offset_signed = duk_to_int(thr, 1);
29229 	offset = (duk_uint_t) offset_signed;
29230 
29231 	/* We need 'nbytes' even for a failed offset; return value must be
29232 	 * (offset + nbytes) even when write fails due to invalid offset.
29233 	 */
29234 	if (magic_ftype != DUK__FLD_VARINT) {
29235 		DUK_ASSERT(magic_ftype >= 0 && magic_ftype < (duk_small_int_t) (sizeof(duk__buffer_nbytes_from_fldtype) / sizeof(duk_uint8_t)));
29236 		nbytes = duk__buffer_nbytes_from_fldtype[magic_ftype];
29237 	} else {
29238 		nbytes = duk_get_int(thr, 2);
29239 		if (nbytes < 1 || nbytes > 6) {
29240 			goto fail_field_length;
29241 		}
29242 	}
29243 	DUK_ASSERT(nbytes >= 1 && nbytes <= 8);
29244 
29245 	/* Now we can check offset validity. */
29246 	if (offset_signed < 0) {
29247 		goto fail_bounds;
29248 	}
29249 
29250 	DUK_DDD(DUK_DDDPRINT("writefield, value=%!T, buffer_length=%ld, offset=%ld, no_assert=%d, "
29251 	                     "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
29252 	                     "endswap=%d",
29253 	                     duk_get_tval(thr, 0), (long) buffer_length, (long) offset, (int) no_assert,
29254 	                     (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
29255 	                     (int) (magic_signed >> 4), (int) endswap));
29256 
29257 	/* Coerce value to a number before computing check_length, so that
29258 	 * the field type specific coercion below can't have side effects
29259 	 * that would invalidate check_length.
29260 	 */
29261 	duk_to_number(thr, 0);
29262 
29263 	/* Update 'buffer_length' to be the effective, safe limit which
29264 	 * takes into account the underlying buffer.  This value will be
29265 	 * potentially invalidated by any side effect.
29266 	 */
29267 	check_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, buffer_length);
29268 	DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
29269 	                     (long) buffer_length, (long) check_length));
29270 
29271 	if (h_this->buf) {
29272 		buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
29273 	} else {
29274 		/* Neutered.  We could go into the switch-case safely with
29275 		 * buf == NULL because check_length == 0.  To avoid scanbuild
29276 		 * warnings, fail directly instead.
29277 		 */
29278 		DUK_ASSERT(check_length == 0);
29279 		goto fail_neutered;
29280 	}
29281 	DUK_ASSERT(buf != NULL);
29282 
29283 	switch (magic_ftype) {
29284 	case DUK__FLD_8BIT: {
29285 		if (offset + 1U > check_length) {
29286 			goto fail_bounds;
29287 		}
29288 		/* sign doesn't matter when writing */
29289 		buf[offset] = (duk_uint8_t) duk_to_uint32(thr, 0);
29290 		break;
29291 	}
29292 	case DUK__FLD_16BIT: {
29293 		duk_uint16_t tmp;
29294 		if (offset + 2U > check_length) {
29295 			goto fail_bounds;
29296 		}
29297 		tmp = (duk_uint16_t) duk_to_uint32(thr, 0);
29298 		if (endswap) {
29299 			tmp = DUK_BSWAP16(tmp);
29300 		}
29301 		du.us[0] = tmp;
29302 		/* sign doesn't matter when writing */
29303 		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 2);
29304 		break;
29305 	}
29306 	case DUK__FLD_32BIT: {
29307 		duk_uint32_t tmp;
29308 		if (offset + 4U > check_length) {
29309 			goto fail_bounds;
29310 		}
29311 		tmp = (duk_uint32_t) duk_to_uint32(thr, 0);
29312 		if (endswap) {
29313 			tmp = DUK_BSWAP32(tmp);
29314 		}
29315 		du.ui[0] = tmp;
29316 		/* sign doesn't matter when writing */
29317 		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 4);
29318 		break;
29319 	}
29320 	case DUK__FLD_FLOAT: {
29321 		duk_uint32_t tmp;
29322 		if (offset + 4U > check_length) {
29323 			goto fail_bounds;
29324 		}
29325 		du.f[0] = (duk_float_t) duk_to_number(thr, 0);
29326 		if (endswap) {
29327 			tmp = du.ui[0];
29328 			tmp = DUK_BSWAP32(tmp);
29329 			du.ui[0] = tmp;
29330 		}
29331 		/* sign doesn't matter when writing */
29332 		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 4);
29333 		break;
29334 	}
29335 	case DUK__FLD_DOUBLE: {
29336 		if (offset + 8U > check_length) {
29337 			goto fail_bounds;
29338 		}
29339 		du.d = (duk_double_t) duk_to_number(thr, 0);
29340 		if (endswap) {
29341 			DUK_DBLUNION_BSWAP64(&du);
29342 		}
29343 		/* sign doesn't matter when writing */
29344 		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 8);
29345 		break;
29346 	}
29347 	case DUK__FLD_VARINT: {
29348 		/* Node.js Buffer variable width integer field.  We don't really
29349 		 * care about speed here, so aim for shortest algorithm.
29350 		 */
29351 		duk_int_t field_bytelen;
29352 		duk_int_t i, i_step, i_end;
29353 #if defined(DUK_USE_64BIT_OPS)
29354 		duk_int64_t tmp;
29355 #else
29356 		duk_double_t tmp;
29357 #endif
29358 		duk_uint8_t *p;
29359 
29360 		field_bytelen = (duk_int_t) nbytes;
29361 		if (offset + (duk_uint_t) field_bytelen > check_length) {
29362 			goto fail_bounds;
29363 		}
29364 
29365 		/* Slow writing of value using either 64-bit arithmetic
29366 		 * or IEEE doubles if 64-bit types not available.  There's
29367 		 * no special sign handling when writing varints.
29368 		 */
29369 
29370 		if (magic_bigendian) {
29371 			/* Write in big endian */
29372 			i = field_bytelen;  /* one i_step added at top of loop */
29373 			i_step = -1;
29374 			i_end = 0;
29375 		} else {
29376 			/* Write in little endian */
29377 			i = -1;  /* one i_step added at top of loop */
29378 			i_step = 1;
29379 			i_end = field_bytelen - 1;
29380 		}
29381 
29382 		/* XXX: The duk_to_number() cast followed by integer coercion
29383 		 * is platform specific so NaN, +/- Infinity, and out-of-bounds
29384 		 * values result in platform specific output now.
29385 		 * See: test-bi-nodejs-buffer-proto-varint-special.js
29386 		 */
29387 
29388 #if defined(DUK_USE_64BIT_OPS)
29389 		tmp = (duk_int64_t) duk_to_number(thr, 0);
29390 		p = (duk_uint8_t *) (buf + offset);
29391 		do {
29392 			i += i_step;
29393 			DUK_ASSERT(i >= 0 && i < field_bytelen);
29394 			p[i] = (duk_uint8_t) (tmp & 0xff);
29395 			tmp = tmp >> 8;  /* unnecessary shift for last byte */
29396 		} while (i != i_end);
29397 #else
29398 		tmp = duk_to_number(thr, 0);
29399 		p = (duk_uint8_t *) (buf + offset);
29400 		do {
29401 			i += i_step;
29402 			tmp = DUK_FLOOR(tmp);
29403 			DUK_ASSERT(i >= 0 && i < field_bytelen);
29404 			p[i] = (duk_uint8_t) (DUK_FMOD(tmp, 256.0));
29405 			tmp = tmp / 256.0;  /* unnecessary div for last byte */
29406 		} while (i != i_end);
29407 #endif
29408 		break;
29409 	}
29410 	default: {  /* should never happen but default here */
29411 		goto fail_bounds;
29412 	}
29413 	}
29414 
29415 	/* Node.js Buffer: return offset + #bytes written (i.e. next
29416 	 * write offset).
29417 	 */
29418 	if (magic_typedarray) {
29419 		/* For TypedArrays 'undefined' return value is specified
29420 		 * by ES2015 (matches V8).
29421 		 */
29422 		return 0;
29423 	}
29424 	duk_push_uint(thr, offset + (duk_uint_t) nbytes);
29425 	return 1;
29426 
29427  fail_neutered:
29428  fail_field_length:
29429  fail_bounds:
29430 	if (no_assert) {
29431 		/* Node.js return value for failed writes is offset + #bytes
29432 		 * that would have been written.
29433 		 */
29434 		/* XXX: for negative input offsets, 'offset' will be a large
29435 		 * positive value so the result here is confusing.
29436 		 */
29437 		if (magic_typedarray) {
29438 			return 0;
29439 		}
29440 		duk_push_uint(thr, offset + (duk_uint_t) nbytes);
29441 		return 1;
29442 	}
29443 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
29444 }
29445 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29446 
29447 /*
29448  *  Accessors for .buffer, .byteLength, .byteOffset
29449  */
29450 
29451 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk__autospawn_arraybuffer(duk_hthread * thr,duk_hbuffer * h_buf)29452 DUK_LOCAL duk_hbufobj *duk__autospawn_arraybuffer(duk_hthread *thr, duk_hbuffer *h_buf) {
29453 	duk_hbufobj *h_res;
29454 
29455 	h_res = duk_push_bufobj_raw(thr,
29456 	                            DUK_HOBJECT_FLAG_EXTENSIBLE |
29457 	                            DUK_HOBJECT_FLAG_BUFOBJ |
29458 	                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
29459 	                            DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
29460 	DUK_ASSERT(h_res != NULL);
29461 	DUK_UNREF(h_res);
29462 
29463 	duk__set_bufobj_buffer(thr, h_res, h_buf);
29464 	DUK_ASSERT_HBUFOBJ_VALID(h_res);
29465 	DUK_ASSERT(h_res->buf_prop == NULL);
29466 	return h_res;
29467 }
29468 
duk_bi_typedarray_buffer_getter(duk_hthread * thr)29469 DUK_INTERNAL duk_ret_t duk_bi_typedarray_buffer_getter(duk_hthread *thr) {
29470 	duk_hbufobj *h_bufobj;
29471 
29472 	h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
29473 	DUK_ASSERT(h_bufobj != NULL);
29474 	if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
29475 		DUK_DD(DUK_DDPRINT("autospawn ArrayBuffer for plain buffer"));
29476 		(void) duk__autospawn_arraybuffer(thr, (duk_hbuffer *) h_bufobj);
29477 		return 1;
29478 	} else {
29479 		if (h_bufobj->buf_prop == NULL &&
29480 		    DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_bufobj) != DUK_HOBJECT_CLASS_ARRAYBUFFER &&
29481 		    h_bufobj->buf != NULL) {
29482 			duk_hbufobj *h_arrbuf;
29483 
29484 			DUK_DD(DUK_DDPRINT("autospawn ArrayBuffer for typed array or DataView"));
29485 			h_arrbuf = duk__autospawn_arraybuffer(thr, h_bufobj->buf);
29486 
29487 			if (h_bufobj->buf_prop == NULL) {
29488 				/* Must recheck buf_prop, in case ArrayBuffer
29489 				 * alloc had a side effect which already filled
29490 				 * it!
29491 				 */
29492 
29493 				/* Set ArrayBuffer's .byteOffset and .byteLength based
29494 				 * on the view so that Arraybuffer[view.byteOffset]
29495 				 * matches view[0].
29496 				 */
29497 				h_arrbuf->offset = 0;
29498 				DUK_ASSERT(h_bufobj->offset + h_bufobj->length >= h_bufobj->offset);  /* Wrap check on creation. */
29499 				h_arrbuf->length = h_bufobj->offset + h_bufobj->length;
29500 				DUK_ASSERT(h_arrbuf->buf_prop == NULL);
29501 
29502 				DUK_ASSERT(h_bufobj->buf_prop == NULL);
29503 				h_bufobj->buf_prop = (duk_hobject *) h_arrbuf;
29504 				DUK_HBUFOBJ_INCREF(thr, h_arrbuf);  /* Now reachable and accounted for. */
29505 			}
29506 
29507 			/* Left on stack; pushed for the second time below (OK). */
29508 		}
29509 		if (h_bufobj->buf_prop) {
29510 			duk_push_hobject(thr, h_bufobj->buf_prop);
29511 			return 1;
29512 		}
29513 	}
29514 	return 0;
29515 }
29516 
duk_bi_typedarray_byteoffset_getter(duk_hthread * thr)29517 DUK_INTERNAL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_hthread *thr) {
29518 	duk_hbufobj *h_bufobj;
29519 
29520 	h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
29521 	DUK_ASSERT(h_bufobj != NULL);
29522 	if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
29523 		duk_push_uint(thr, 0);
29524 	} else {
29525 		/* If neutered must return 0; offset is zeroed during
29526 		 * neutering.
29527 		 */
29528 		duk_push_uint(thr, h_bufobj->offset);
29529 	}
29530 	return 1;
29531 }
29532 
duk_bi_typedarray_bytelength_getter(duk_hthread * thr)29533 DUK_INTERNAL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_hthread *thr) {
29534 	duk_hbufobj *h_bufobj;
29535 
29536 	h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
29537 	DUK_ASSERT(h_bufobj != NULL);
29538 	if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
29539 		duk_hbuffer *h_buf;
29540 
29541 		h_buf = (duk_hbuffer *) h_bufobj;
29542 		DUK_ASSERT(DUK_HBUFFER_GET_SIZE(h_buf) <= DUK_UINT_MAX);  /* Buffer limits. */
29543 		duk_push_uint(thr, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));
29544 	} else {
29545 		/* If neutered must return 0; length is zeroed during
29546 		 * neutering.
29547 		 */
29548 		duk_push_uint(thr, h_bufobj->length);
29549 	}
29550 	return 1;
29551 }
29552 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29553 /* No .buffer getter without ArrayBuffer support. */
29554 #if 0
29555 DUK_INTERNAL duk_ret_t duk_bi_typedarray_buffer_getter(duk_hthread *thr) {
29556 	return 0;
29557 }
29558 #endif
29559 
duk_bi_typedarray_byteoffset_getter(duk_hthread * thr)29560 DUK_INTERNAL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_hthread *thr) {
29561 	duk_push_uint(thr, 0);
29562 	return 1;
29563 }
29564 
duk_bi_typedarray_bytelength_getter(duk_hthread * thr)29565 DUK_INTERNAL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_hthread *thr) {
29566 	duk_hbuffer *h_buf;
29567 
29568 	/* XXX: helper? */
29569 	duk_push_this(thr);
29570 	h_buf = duk_require_hbuffer(thr, -1);
29571 	duk_push_uint(thr, DUK_HBUFFER_GET_SIZE(h_buf));
29572 	return 1;
29573 }
29574 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29575 
29576 /* automatic undefs */
29577 #undef DUK__BUFOBJ_FLAG_PROMOTE
29578 #undef DUK__BUFOBJ_FLAG_THROW
29579 #undef DUK__FLD_16BIT
29580 #undef DUK__FLD_32BIT
29581 #undef DUK__FLD_8BIT
29582 #undef DUK__FLD_BIGENDIAN
29583 #undef DUK__FLD_DOUBLE
29584 #undef DUK__FLD_FLOAT
29585 #undef DUK__FLD_SIGNED
29586 #undef DUK__FLD_TYPEDARRAY
29587 #undef DUK__FLD_VARINT
29588 #line 1 "duk_bi_date.c"
29589 /*
29590  *  Date built-ins
29591  *
29592  *  Unlike most built-ins, Date has some platform dependencies for getting
29593  *  UTC time, converting between UTC and local time, and parsing and
29594  *  formatting time values.  These are all abstracted behind DUK_USE_xxx
29595  *  config options.  There are built-in platform specific providers for
29596  *  POSIX and Windows, but external providers can also be used.
29597  *
29598  *  See doc/datetime.rst.
29599  *
29600  */
29601 
29602 /* #include duk_internal.h -> already included */
29603 
29604 /* XXX: currently defines unnecessary symbols when DUK_USE_DATE_BUILTIN is disabled. */
29605 
29606 /*
29607  *  Forward declarations
29608  */
29609 
29610 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);
29611 DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval(duk_hthread *thr, duk_small_uint_t flags);
29612 DUK_LOCAL_DECL void duk__twodigit_year_fixup(duk_hthread *thr, duk_idx_t idx_val);
29613 DUK_LOCAL_DECL duk_ret_t duk__set_this_timeval_from_dparts(duk_hthread *thr, duk_double_t *dparts, duk_small_uint_t flags);
29614 
29615 /*
29616  *  Other file level defines
29617  */
29618 
29619 /* Debug macro to print all parts and dparts (used manually because of debug level). */
29620 #define  DUK__DPRINT_PARTS_AND_DPARTS(parts,dparts)  do { \
29621 		DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld, dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
29622 		                 (long) (parts)[0], (long) (parts)[1], \
29623 		                 (long) (parts)[2], (long) (parts)[3], \
29624 		                 (long) (parts)[4], (long) (parts)[5], \
29625 		                 (long) (parts)[6], (long) (parts)[7], \
29626 		                 (double) (dparts)[0], (double) (dparts)[1], \
29627 		                 (double) (dparts)[2], (double) (dparts)[3], \
29628 		                 (double) (dparts)[4], (double) (dparts)[5], \
29629 		                 (double) (dparts)[6], (double) (dparts)[7])); \
29630 	} while (0)
29631 #define  DUK__DPRINT_PARTS(parts)  do { \
29632 		DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld", \
29633 		                 (long) (parts)[0], (long) (parts)[1], \
29634 		                 (long) (parts)[2], (long) (parts)[3], \
29635 		                 (long) (parts)[4], (long) (parts)[5], \
29636 		                 (long) (parts)[6], (long) (parts)[7])); \
29637 	} while (0)
29638 #define  DUK__DPRINT_DPARTS(dparts)  do { \
29639 		DUK_D(DUK_DPRINT("dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
29640 		                 (double) (dparts)[0], (double) (dparts)[1], \
29641 		                 (double) (dparts)[2], (double) (dparts)[3], \
29642 		                 (double) (dparts)[4], (double) (dparts)[5], \
29643 		                 (double) (dparts)[6], (double) (dparts)[7])); \
29644 	} while (0)
29645 
29646 /* Equivalent year for DST calculations outside [1970,2038[ range, see
29647  * E5 Section 15.9.1.8.  Equivalent year has the same leap-year-ness and
29648  * starts with the same weekday on Jan 1.
29649  * https://bugzilla.mozilla.org/show_bug.cgi?id=351066
29650  */
29651 #define DUK__YEAR(x) ((duk_uint8_t) ((x) - 1970))
29652 DUK_LOCAL duk_uint8_t duk__date_equivyear[14] = {
29653 #if 1
29654 	/* This is based on V8 EquivalentYear() algorithm (see util/genequivyear.py):
29655 	 * http://code.google.com/p/v8/source/browse/trunk/src/date.h#146
29656 	 */
29657 
29658 	/* non-leap year: sunday, monday, ... */
29659 	DUK__YEAR(2023), DUK__YEAR(2035), DUK__YEAR(2019), DUK__YEAR(2031),
29660 	DUK__YEAR(2015), DUK__YEAR(2027), DUK__YEAR(2011),
29661 
29662 	/* leap year: sunday, monday, ... */
29663 	DUK__YEAR(2012), DUK__YEAR(2024), DUK__YEAR(2008), DUK__YEAR(2020),
29664 	DUK__YEAR(2032), DUK__YEAR(2016), DUK__YEAR(2028)
29665 #endif
29666 
29667 #if 0
29668 	/* This is based on Rhino EquivalentYear() algorithm:
29669 	 * https://github.com/mozilla/rhino/blob/f99cc11d616f0cdda2c42bde72b3484df6182947/src/org/mozilla/javascript/NativeDate.java
29670 	 */
29671 
29672 	/* non-leap year: sunday, monday, ... */
29673 	DUK__YEAR(1978), DUK__YEAR(1973), DUK__YEAR(1985), DUK__YEAR(1986),
29674 	DUK__YEAR(1981), DUK__YEAR(1971), DUK__YEAR(1977),
29675 
29676 	/* leap year: sunday, monday, ... */
29677 	DUK__YEAR(1984), DUK__YEAR(1996), DUK__YEAR(1980), DUK__YEAR(1992),
29678 	DUK__YEAR(1976), DUK__YEAR(1988), DUK__YEAR(1972)
29679 #endif
29680 };
29681 
29682 /*
29683  *  ISO 8601 subset parser.
29684  */
29685 
29686 /* Parser part count. */
29687 #define DUK__NUM_ISO8601_PARSER_PARTS  9
29688 
29689 /* Parser part indices. */
29690 #define DUK__PI_YEAR         0
29691 #define DUK__PI_MONTH        1
29692 #define DUK__PI_DAY          2
29693 #define DUK__PI_HOUR         3
29694 #define DUK__PI_MINUTE       4
29695 #define DUK__PI_SECOND       5
29696 #define DUK__PI_MILLISECOND  6
29697 #define DUK__PI_TZHOUR       7
29698 #define DUK__PI_TZMINUTE     8
29699 
29700 /* Parser part masks. */
29701 #define DUK__PM_YEAR         (1 << DUK__PI_YEAR)
29702 #define DUK__PM_MONTH        (1 << DUK__PI_MONTH)
29703 #define DUK__PM_DAY          (1 << DUK__PI_DAY)
29704 #define DUK__PM_HOUR         (1 << DUK__PI_HOUR)
29705 #define DUK__PM_MINUTE       (1 << DUK__PI_MINUTE)
29706 #define DUK__PM_SECOND       (1 << DUK__PI_SECOND)
29707 #define DUK__PM_MILLISECOND  (1 << DUK__PI_MILLISECOND)
29708 #define DUK__PM_TZHOUR       (1 << DUK__PI_TZHOUR)
29709 #define DUK__PM_TZMINUTE     (1 << DUK__PI_TZMINUTE)
29710 
29711 /* Parser separator indices. */
29712 #define DUK__SI_PLUS         0
29713 #define DUK__SI_MINUS        1
29714 #define DUK__SI_T            2
29715 #define DUK__SI_SPACE        3
29716 #define DUK__SI_COLON        4
29717 #define DUK__SI_PERIOD       5
29718 #define DUK__SI_Z            6
29719 #define DUK__SI_NUL          7
29720 
29721 /* Parser separator masks. */
29722 #define DUK__SM_PLUS         (1 << DUK__SI_PLUS)
29723 #define DUK__SM_MINUS        (1 << DUK__SI_MINUS)
29724 #define DUK__SM_T            (1 << DUK__SI_T)
29725 #define DUK__SM_SPACE        (1 << DUK__SI_SPACE)
29726 #define DUK__SM_COLON        (1 << DUK__SI_COLON)
29727 #define DUK__SM_PERIOD       (1 << DUK__SI_PERIOD)
29728 #define DUK__SM_Z            (1 << DUK__SI_Z)
29729 #define DUK__SM_NUL          (1 << DUK__SI_NUL)
29730 
29731 /* Rule control flags. */
29732 #define DUK__CF_NEG          (1 << 0)  /* continue matching, set neg_tzoffset flag */
29733 #define DUK__CF_ACCEPT       (1 << 1)  /* accept string */
29734 #define DUK__CF_ACCEPT_NUL   (1 << 2)  /* accept string if next char is NUL (otherwise reject) */
29735 
29736 #define DUK__PACK_RULE(partmask,sepmask,nextpart,flags)  \
29737 	((duk_uint32_t) (partmask) + \
29738 	 (((duk_uint32_t) (sepmask)) << 9) + \
29739 	 (((duk_uint32_t) (nextpart)) << 17) + \
29740 	 (((duk_uint32_t) (flags)) << 21))
29741 
29742 #define DUK__UNPACK_RULE(rule,var_nextidx,var_flags)  do { \
29743 		(var_nextidx) = (duk_small_uint_t) (((rule) >> 17) & 0x0f); \
29744 		(var_flags) = (duk_small_uint_t) ((rule) >> 21); \
29745 	} while (0)
29746 
29747 #define DUK__RULE_MASK_PART_SEP  0x1ffffUL
29748 
29749 /* Matching separator index is used in the control table */
29750 DUK_LOCAL const duk_uint8_t duk__parse_iso8601_seps[] = {
29751 	DUK_ASC_PLUS /*0*/, DUK_ASC_MINUS /*1*/, DUK_ASC_UC_T /*2*/, DUK_ASC_SPACE /*3*/,
29752 	DUK_ASC_COLON /*4*/, DUK_ASC_PERIOD /*5*/, DUK_ASC_UC_Z /*6*/, DUK_ASC_NUL /*7*/
29753 };
29754 
29755 /* Rule table: first matching rule is used to determine what to do next. */
29756 DUK_LOCAL const duk_uint32_t duk__parse_iso8601_control[] = {
29757 	DUK__PACK_RULE(DUK__PM_YEAR, DUK__SM_MINUS, DUK__PI_MONTH, 0),
29758 	DUK__PACK_RULE(DUK__PM_MONTH, DUK__SM_MINUS, DUK__PI_DAY, 0),
29759 	DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY, DUK__SM_T | DUK__SM_SPACE, DUK__PI_HOUR, 0),
29760 	DUK__PACK_RULE(DUK__PM_HOUR, DUK__SM_COLON, DUK__PI_MINUTE, 0),
29761 	DUK__PACK_RULE(DUK__PM_MINUTE, DUK__SM_COLON, DUK__PI_SECOND, 0),
29762 	DUK__PACK_RULE(DUK__PM_SECOND, DUK__SM_PERIOD, DUK__PI_MILLISECOND, 0),
29763 	DUK__PACK_RULE(DUK__PM_TZHOUR, DUK__SM_COLON, DUK__PI_TZMINUTE, 0),
29764 	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),
29765 	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),
29766 	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),
29767 	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)
29768 
29769 	/* Note1: the specification doesn't require matching a time form with
29770 	 *        just hours ("HH"), but we accept it here, e.g. "2012-01-02T12Z".
29771 	 *
29772 	 * Note2: the specification doesn't require matching a timezone offset
29773 	 *        with just hours ("HH"), but accept it here, e.g. "2012-01-02T03:04:05+02"
29774 	 */
29775 };
29776 
duk__parse_string_iso8601_subset(duk_hthread * thr,const char * str)29777 DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_hthread *thr, const char *str) {
29778 	duk_int_t parts[DUK__NUM_ISO8601_PARSER_PARTS];
29779 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
29780 	duk_double_t d;
29781 	const duk_uint8_t *p;
29782 	duk_small_uint_t part_idx = 0;
29783 	duk_int_t accum = 0;
29784 	duk_small_uint_t ndigits = 0;
29785 	duk_bool_t neg_year = 0;
29786 	duk_bool_t neg_tzoffset = 0;
29787 	duk_uint_fast8_t ch;
29788 	duk_small_uint_t i;
29789 
29790 	/* During parsing, month and day are one-based; set defaults here. */
29791 	duk_memzero(parts, sizeof(parts));
29792 	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] == 0);  /* don't care value, year is mandatory */
29793 	parts[DUK_DATE_IDX_MONTH] = 1;
29794 	parts[DUK_DATE_IDX_DAY] = 1;
29795 
29796 	/* Special handling for year sign. */
29797 	p = (const duk_uint8_t *) str;
29798 	ch = p[0];
29799 	if (ch == DUK_ASC_PLUS) {
29800 		p++;
29801 	} else if (ch == DUK_ASC_MINUS) {
29802 		neg_year = 1;
29803 		p++;
29804 	}
29805 
29806 	for (;;) {
29807 		ch = *p++;
29808 		DUK_DDD(DUK_DDDPRINT("parsing, part_idx=%ld, char=%ld ('%c')",
29809 		                     (long) part_idx, (long) ch,
29810 		                     (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : DUK_ASC_QUESTION)));
29811 
29812 		if (ch >= DUK_ASC_0 && ch <= DUK_ASC_9) {
29813 			if (ndigits >= 9) {
29814 				DUK_DDD(DUK_DDDPRINT("too many digits -> reject"));
29815 				goto reject;
29816 			}
29817 			if (part_idx == DUK__PI_MILLISECOND && ndigits >= 3) {
29818 				/* ignore millisecond fractions after 3 */
29819 			} else {
29820 				accum = accum * 10 + ((duk_int_t) ch) - ((duk_int_t) DUK_ASC_0) + 0x00;
29821 				ndigits++;
29822 			}
29823 		} else {
29824 			duk_uint_fast32_t match_val;
29825 			duk_small_uint_t sep_idx;
29826 
29827 			if (ndigits <= 0) {
29828 				goto reject;
29829 			}
29830 			if (part_idx == DUK__PI_MILLISECOND) {
29831 				/* complete the millisecond field */
29832 				while (ndigits < 3) {
29833 					accum *= 10;
29834 					ndigits++;
29835 				}
29836 			}
29837 			parts[part_idx] = accum;
29838 			DUK_DDD(DUK_DDDPRINT("wrote part %ld -> value %ld", (long) part_idx, (long) accum));
29839 
29840 			accum = 0;
29841 			ndigits = 0;
29842 
29843 			for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t)); i++) {
29844 				if (duk__parse_iso8601_seps[i] == ch) {
29845 					break;
29846 				}
29847 			}
29848 			if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t))) {
29849 				DUK_DDD(DUK_DDDPRINT("separator character doesn't match -> reject"));
29850 				goto reject;
29851 			}
29852 
29853 			sep_idx = i;
29854 			match_val = (1UL << part_idx) + (1UL << (sep_idx + 9));  /* match against rule part/sep bits */
29855 
29856 			for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t)); i++) {
29857 				duk_uint_fast32_t rule = duk__parse_iso8601_control[i];
29858 				duk_small_uint_t nextpart;
29859 				duk_small_uint_t cflags;
29860 
29861 				DUK_DDD(DUK_DDDPRINT("part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, considering rule=0x%08lx",
29862 				                     (long) part_idx, (long) sep_idx,
29863 				                     (unsigned long) match_val, (unsigned long) rule));
29864 
29865 				if ((rule & match_val) != match_val) {
29866 					continue;
29867 				}
29868 
29869 				DUK__UNPACK_RULE(rule, nextpart, cflags);
29870 
29871 				DUK_DDD(DUK_DDDPRINT("rule match -> part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, "
29872 				                     "rule=0x%08lx -> nextpart=%ld, cflags=0x%02lx",
29873 				                     (long) part_idx, (long) sep_idx,
29874 				                     (unsigned long) match_val, (unsigned long) rule,
29875 				                     (long) nextpart, (unsigned long) cflags));
29876 
29877 				if (cflags & DUK__CF_NEG) {
29878 					neg_tzoffset = 1;
29879 				}
29880 
29881 				if (cflags & DUK__CF_ACCEPT) {
29882 					goto accept;
29883 				}
29884 
29885 				if (cflags & DUK__CF_ACCEPT_NUL) {
29886 					DUK_ASSERT(*(p - 1) != (char) 0);
29887 					if (*p == DUK_ASC_NUL) {
29888 						goto accept;
29889 					}
29890 					goto reject;
29891 				}
29892 
29893 				part_idx = nextpart;
29894 				break;
29895 			}  /* rule match */
29896 
29897 			if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t))) {
29898 				DUK_DDD(DUK_DDDPRINT("no rule matches -> reject"));
29899 				goto reject;
29900 			}
29901 
29902 			if (ch == 0) {
29903 				/* This shouldn't be necessary, but check just in case
29904 				 * to avoid any chance of overruns.
29905 				 */
29906 				DUK_DDD(DUK_DDDPRINT("NUL after rule matching (should not happen) -> reject"));
29907 				goto reject;
29908 			}
29909 		}  /* if-digit-else-ctrl */
29910 	}  /* char loop */
29911 
29912 	/* We should never exit the loop above. */
29913 	DUK_UNREACHABLE();
29914 
29915  reject:
29916 	DUK_DDD(DUK_DDDPRINT("reject"));
29917 	return 0;
29918 
29919  accept:
29920 	DUK_DDD(DUK_DDDPRINT("accept"));
29921 
29922 	/* Apply timezone offset to get the main parts in UTC */
29923 	if (neg_year) {
29924 		parts[DUK__PI_YEAR] = -parts[DUK__PI_YEAR];
29925 	}
29926 	if (neg_tzoffset) {
29927 		parts[DUK__PI_HOUR] += parts[DUK__PI_TZHOUR];
29928 		parts[DUK__PI_MINUTE] += parts[DUK__PI_TZMINUTE];
29929 	} else {
29930 		parts[DUK__PI_HOUR] -= parts[DUK__PI_TZHOUR];
29931 		parts[DUK__PI_MINUTE] -= parts[DUK__PI_TZMINUTE];
29932 	}
29933 	parts[DUK__PI_MONTH] -= 1;  /* zero-based month */
29934 	parts[DUK__PI_DAY] -= 1;  /* zero-based day */
29935 
29936 	/* Use double parts, they tolerate unnormalized time.
29937 	 *
29938 	 * Note: DUK_DATE_IDX_WEEKDAY is initialized with a bogus value (DUK__PI_TZHOUR)
29939 	 * on purpose.  It won't be actually used by duk_bi_date_get_timeval_from_dparts(),
29940 	 * but will make the value initialized just in case, and avoid any
29941 	 * potential for Valgrind issues.
29942 	 */
29943 	for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
29944 		DUK_DDD(DUK_DDDPRINT("part[%ld] = %ld", (long) i, (long) parts[i]));
29945 		dparts[i] = parts[i];
29946 	}
29947 
29948 	d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
29949 	duk_push_number(thr, d);
29950 	return 1;
29951 }
29952 
29953 /*
29954  *  Date/time parsing helper.
29955  *
29956  *  Parse a datetime string into a time value.  We must first try to parse
29957  *  the input according to the standard format in E5.1 Section 15.9.1.15.
29958  *  If that fails, we can try to parse using custom parsing, which can
29959  *  either be platform neutral (custom code) or platform specific (using
29960  *  existing platform API calls).
29961  *
29962  *  Note in particular that we must parse whatever toString(), toUTCString(),
29963  *  and toISOString() can produce; see E5.1 Section 15.9.4.2.
29964  *
29965  *  Returns 1 to allow tail calling.
29966  *
29967  *  There is much room for improvement here with respect to supporting
29968  *  alternative datetime formats.  For instance, V8 parses '2012-01-01' as
29969  *  UTC and '2012/01/01' as local time.
29970  */
29971 
duk__parse_string(duk_hthread * thr,const char * str)29972 DUK_LOCAL duk_ret_t duk__parse_string(duk_hthread *thr, const char *str) {
29973 	/* XXX: there is a small risk here: because the ISO 8601 parser is
29974 	 * very loose, it may end up parsing some datetime values which
29975 	 * would be better parsed with a platform specific parser.
29976 	 */
29977 
29978 	DUK_ASSERT(str != NULL);
29979 	DUK_DDD(DUK_DDDPRINT("parse datetime from string '%s'", (const char *) str));
29980 
29981 	if (duk__parse_string_iso8601_subset(thr, str) != 0) {
29982 		return 1;
29983 	}
29984 
29985 #if defined(DUK_USE_DATE_PARSE_STRING)
29986 	/* Contract, either:
29987 	 * - Push value on stack and return 1
29988 	 * - Don't push anything on stack and return 0
29989 	 */
29990 
29991 	if (DUK_USE_DATE_PARSE_STRING(thr, str) != 0) {
29992 		return 1;
29993 	}
29994 #else
29995 	/* No platform-specific parsing, this is not an error. */
29996 #endif
29997 
29998 	duk_push_nan(thr);
29999 	return 1;
30000 }
30001 
30002 /*
30003  *  Calendar helpers
30004  *
30005  *  Some helpers are used for getters and can operate on normalized values
30006  *  which can be represented with 32-bit signed integers.  Other helpers are
30007  *  needed by setters and operate on un-normalized double values, must watch
30008  *  out for non-finite numbers etc.
30009  */
30010 
30011 DUK_LOCAL duk_uint8_t duk__days_in_month[12] = {
30012 	(duk_uint8_t) 31, (duk_uint8_t) 28, (duk_uint8_t) 31, (duk_uint8_t) 30,
30013 	(duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 31,
30014 	(duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31
30015 };
30016 
30017 /* Maximum iteration count for computing UTC-to-local time offset when
30018  * creating an ECMAScript time value from local parts.
30019  */
30020 #define DUK__LOCAL_TZOFFSET_MAXITER   4
30021 
30022 /* Because 'day since epoch' can be negative and is used to compute weekday
30023  * using a modulo operation, add this multiple of 7 to avoid negative values
30024  * when year is below 1970 epoch.  ECMAScript time values are restricted to
30025  * +/- 100 million days from epoch, so this adder fits nicely into 32 bits.
30026  * Round to a multiple of 7 (= floor(100000000 / 7) * 7) and add margin.
30027  */
30028 #define DUK__WEEKDAY_MOD_ADDER  (20000000 * 7)  /* 0x08583b00 */
30029 
duk_bi_date_is_leap_year(duk_int_t year)30030 DUK_INTERNAL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year) {
30031 	if ((year % 4) != 0) {
30032 		return 0;
30033 	}
30034 	if ((year % 100) != 0) {
30035 		return 1;
30036 	}
30037 	if ((year % 400) != 0) {
30038 		return 0;
30039 	}
30040 	return 1;
30041 }
30042 
duk_bi_date_timeval_in_valid_range(duk_double_t x)30043 DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x) {
30044 	return (x >= -DUK_DATE_MSEC_100M_DAYS && x <= DUK_DATE_MSEC_100M_DAYS);
30045 }
30046 
duk_bi_date_timeval_in_leeway_range(duk_double_t x)30047 DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x) {
30048 	return (x >= -DUK_DATE_MSEC_100M_DAYS_LEEWAY && x <= DUK_DATE_MSEC_100M_DAYS_LEEWAY);
30049 }
30050 
duk_bi_date_year_in_valid_range(duk_double_t x)30051 DUK_INTERNAL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t x) {
30052 	return (x >= DUK_DATE_MIN_ECMA_YEAR && x <= DUK_DATE_MAX_ECMA_YEAR);
30053 }
30054 
duk__timeclip(duk_double_t x)30055 DUK_LOCAL duk_double_t duk__timeclip(duk_double_t x) {
30056 	if (!DUK_ISFINITE(x)) {
30057 		return DUK_DOUBLE_NAN;
30058 	}
30059 
30060 	if (!duk_bi_date_timeval_in_valid_range(x)) {
30061 		return DUK_DOUBLE_NAN;
30062 	}
30063 
30064 	x = duk_js_tointeger_number(x);
30065 
30066 	/* Here we'd have the option to normalize -0 to +0. */
30067 	return x;
30068 }
30069 
30070 /* Integer division which floors also negative values correctly. */
duk__div_floor(duk_int_t a,duk_int_t b)30071 DUK_LOCAL duk_int_t duk__div_floor(duk_int_t a, duk_int_t b) {
30072 	DUK_ASSERT(b > 0);
30073 	if (a >= 0) {
30074 		return a / b;
30075 	} else {
30076 		/* e.g. a = -4, b = 5  -->  -4 - 5 + 1 / 5  -->  -8 / 5  -->  -1
30077 		 *      a = -5, b = 5  -->  -5 - 5 + 1 / 5  -->  -9 / 5  -->  -1
30078 		 *      a = -6, b = 5  -->  -6 - 5 + 1 / 5  -->  -10 / 5  -->  -2
30079 		 */
30080 		return (a - b + 1) / b;
30081 	}
30082 }
30083 
30084 /* Compute day number of the first day of a given year. */
duk__day_from_year(duk_int_t year)30085 DUK_LOCAL duk_int_t duk__day_from_year(duk_int_t year) {
30086 	/* Note: in integer arithmetic, (x / 4) is same as floor(x / 4) for non-negative
30087 	 * values, but is incorrect for negative ones.
30088 	 */
30089 	return 365 * (year - 1970)
30090 	       + duk__div_floor(year - 1969, 4)
30091 	       - duk__div_floor(year - 1901, 100)
30092 	       + duk__div_floor(year - 1601, 400);
30093 }
30094 
30095 /* 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)30096 DUK_LOCAL duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_within_year) {
30097 	duk_int_t year;
30098 	duk_int_t diff_days;
30099 
30100 	/* estimate year upwards (towards positive infinity), then back down;
30101 	 * two iterations should be enough
30102 	 */
30103 
30104 	if (day >= 0) {
30105 		year = 1970 + day / 365;
30106 	} else {
30107 		year = 1970 + day / 366;
30108 	}
30109 
30110 	for (;;) {
30111 		diff_days = duk__day_from_year(year) - day;
30112 		DUK_DDD(DUK_DDDPRINT("year=%ld day=%ld, diff_days=%ld", (long) year, (long) day, (long) diff_days));
30113 		if (diff_days <= 0) {
30114 			DUK_ASSERT(-diff_days < 366);  /* fits into duk_small_int_t */
30115 			*out_day_within_year = -diff_days;
30116 			DUK_DDD(DUK_DDDPRINT("--> year=%ld, day-within-year=%ld",
30117 			                     (long) year, (long) *out_day_within_year));
30118 			DUK_ASSERT(*out_day_within_year >= 0);
30119 			DUK_ASSERT(*out_day_within_year < (duk_bi_date_is_leap_year(year) ? 366 : 365));
30120 			return year;
30121 		}
30122 
30123 		/* Note: this is very tricky; we must never 'overshoot' the
30124 		 * correction downwards.
30125 		 */
30126 		year -= 1 + (diff_days - 1) / 366;  /* conservative */
30127 	}
30128 }
30129 
30130 /* Given a (year, month, day-within-month) triple, compute day number.
30131  * The input triple is un-normalized and may contain non-finite values.
30132  */
duk__make_day(duk_double_t year,duk_double_t month,duk_double_t day)30133 DUK_LOCAL duk_double_t duk__make_day(duk_double_t year, duk_double_t month, duk_double_t day) {
30134 	duk_int_t day_num;
30135 	duk_bool_t is_leap;
30136 	duk_small_int_t i, n;
30137 
30138 	/* Assume that year, month, day are all coerced to whole numbers.
30139 	 * They may also be NaN or infinity, in which case this function
30140 	 * must return NaN or infinity to ensure time value becomes NaN.
30141 	 * If 'day' is NaN, the final return will end up returning a NaN,
30142 	 * so it doesn't need to be checked here.
30143 	 */
30144 
30145 	if (!DUK_ISFINITE(year) || !DUK_ISFINITE(month)) {
30146 		return DUK_DOUBLE_NAN;
30147 	}
30148 
30149 	year += DUK_FLOOR(month / 12.0);
30150 
30151 	month = DUK_FMOD(month, 12.0);
30152 	if (month < 0.0) {
30153 		/* handle negative values */
30154 		month += 12.0;
30155 	}
30156 
30157 	/* The algorithm in E5.1 Section 15.9.1.12 normalizes month, but
30158 	 * does not normalize the day-of-month (nor check whether or not
30159 	 * it is finite) because it's not necessary for finding the day
30160 	 * number which matches the (year,month) pair.
30161 	 *
30162 	 * We assume that duk__day_from_year() is exact here.
30163 	 *
30164 	 * Without an explicit infinity / NaN check in the beginning,
30165 	 * day_num would be a bogus integer here.
30166 	 *
30167 	 * It's possible for 'year' to be out of integer range here.
30168 	 * If so, we need to return NaN without integer overflow.
30169 	 * This fixes test-bug-setyear-overflow.js.
30170 	 */
30171 
30172 	if (!duk_bi_date_year_in_valid_range(year)) {
30173 		DUK_DD(DUK_DDPRINT("year not in ecmascript valid range, avoid integer overflow: %lf", (double) year));
30174 		return DUK_DOUBLE_NAN;
30175 	}
30176 	day_num = duk__day_from_year((duk_int_t) year);
30177 	is_leap = duk_bi_date_is_leap_year((duk_int_t) year);
30178 
30179 	n = (duk_small_int_t) month;
30180 	for (i = 0; i < n; i++) {
30181 		day_num += duk__days_in_month[i];
30182 		if (i == 1 && is_leap) {
30183 			day_num++;
30184 		}
30185 	}
30186 
30187 	/* If 'day' is NaN, returns NaN. */
30188 	return (duk_double_t) day_num + day;
30189 }
30190 
30191 /* Split time value into parts.  The time value may contain fractions (it may
30192  * come from duk_time_to_components() API call) which are truncated.  Possible
30193  * local time adjustment has already been applied when reading the time value.
30194  */
duk_bi_date_timeval_to_parts(duk_double_t d,duk_int_t * parts,duk_double_t * dparts,duk_small_uint_t flags)30195 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) {
30196 	duk_double_t d1, d2;
30197 	duk_int_t t1, t2;
30198 	duk_int_t day_since_epoch;
30199 	duk_int_t year;  /* does not fit into 16 bits */
30200 	duk_small_int_t day_in_year;
30201 	duk_small_int_t month;
30202 	duk_small_int_t day;
30203 	duk_small_int_t dim;
30204 	duk_int_t jan1_since_epoch;
30205 	duk_small_int_t jan1_weekday;
30206 	duk_int_t equiv_year;
30207 	duk_small_uint_t i;
30208 	duk_bool_t is_leap;
30209 	duk_small_int_t arridx;
30210 
30211 	DUK_ASSERT(DUK_ISFINITE(d));    /* caller checks */
30212 	d = DUK_FLOOR(d);  /* remove fractions if present */
30213 	DUK_ASSERT(DUK_FLOOR(d) == d);
30214 
30215 	/* The timevalue must be in valid ECMAScript range, but since a local
30216 	 * time offset can be applied, we need to allow a +/- 24h leeway to
30217 	 * the value.  In other words, although the UTC time is within the
30218 	 * ECMAScript range, the local part values can be just outside of it.
30219 	 */
30220 	DUK_UNREF(duk_bi_date_timeval_in_leeway_range);
30221 	DUK_ASSERT(duk_bi_date_timeval_in_leeway_range(d));
30222 
30223 	/* These computations are guaranteed to be exact for the valid
30224 	 * E5 time value range, assuming milliseconds without fractions.
30225 	 */
30226 	d1 = (duk_double_t) DUK_FMOD(d, (double) DUK_DATE_MSEC_DAY);
30227 	if (d1 < 0.0) {
30228 		/* deal with negative values */
30229 		d1 += (duk_double_t) DUK_DATE_MSEC_DAY;
30230 	}
30231 	d2 = DUK_FLOOR((double) (d / (duk_double_t) DUK_DATE_MSEC_DAY));
30232 	DUK_ASSERT(d2 * ((duk_double_t) DUK_DATE_MSEC_DAY) + d1 == d);
30233 	/* now expected to fit into a 32-bit integer */
30234 	t1 = (duk_int_t) d1;
30235 	t2 = (duk_int_t) d2;
30236 	day_since_epoch = t2;
30237 	DUK_ASSERT((duk_double_t) t1 == d1);
30238 	DUK_ASSERT((duk_double_t) t2 == d2);
30239 
30240 	/* t1 = milliseconds within day (fits 32 bit)
30241 	 * t2 = day number from epoch (fits 32 bit, may be negative)
30242 	 */
30243 
30244 	parts[DUK_DATE_IDX_MILLISECOND] = t1 % 1000; t1 /= 1000;
30245 	parts[DUK_DATE_IDX_SECOND] = t1 % 60; t1 /= 60;
30246 	parts[DUK_DATE_IDX_MINUTE] = t1 % 60; t1 /= 60;
30247 	parts[DUK_DATE_IDX_HOUR] = t1;
30248 	DUK_ASSERT(parts[DUK_DATE_IDX_MILLISECOND] >= 0 && parts[DUK_DATE_IDX_MILLISECOND] <= 999);
30249 	DUK_ASSERT(parts[DUK_DATE_IDX_SECOND] >= 0 && parts[DUK_DATE_IDX_SECOND] <= 59);
30250 	DUK_ASSERT(parts[DUK_DATE_IDX_MINUTE] >= 0 && parts[DUK_DATE_IDX_MINUTE] <= 59);
30251 	DUK_ASSERT(parts[DUK_DATE_IDX_HOUR] >= 0 && parts[DUK_DATE_IDX_HOUR] <= 23);
30252 
30253 	DUK_DDD(DUK_DDDPRINT("d=%lf, d1=%lf, d2=%lf, t1=%ld, t2=%ld, parts: hour=%ld min=%ld sec=%ld msec=%ld",
30254 	                     (double) d, (double) d1, (double) d2, (long) t1, (long) t2,
30255 	                     (long) parts[DUK_DATE_IDX_HOUR],
30256 	                     (long) parts[DUK_DATE_IDX_MINUTE],
30257 	                     (long) parts[DUK_DATE_IDX_SECOND],
30258 	                     (long) parts[DUK_DATE_IDX_MILLISECOND]));
30259 
30260 	/* This assert depends on the input parts representing time inside
30261 	 * the ECMAScript range.
30262 	 */
30263 	DUK_ASSERT(t2 + DUK__WEEKDAY_MOD_ADDER >= 0);
30264 	parts[DUK_DATE_IDX_WEEKDAY] = (t2 + 4 + DUK__WEEKDAY_MOD_ADDER) % 7;  /* E5.1 Section 15.9.1.6 */
30265 	DUK_ASSERT(parts[DUK_DATE_IDX_WEEKDAY] >= 0 && parts[DUK_DATE_IDX_WEEKDAY] <= 6);
30266 
30267 	year = duk__year_from_day(t2, &day_in_year);
30268 	day = day_in_year;
30269 	is_leap = duk_bi_date_is_leap_year(year);
30270 	for (month = 0; month < 12; month++) {
30271 		dim = duk__days_in_month[month];
30272 		if (month == 1 && is_leap) {
30273 			dim++;
30274 		}
30275 		DUK_DDD(DUK_DDDPRINT("month=%ld, dim=%ld, day=%ld",
30276 		                     (long) month, (long) dim, (long) day));
30277 		if (day < dim) {
30278 			break;
30279 		}
30280 		day -= dim;
30281 	}
30282 	DUK_DDD(DUK_DDDPRINT("final month=%ld", (long) month));
30283 	DUK_ASSERT(month >= 0 && month <= 11);
30284 	DUK_ASSERT(day >= 0 && day <= 31);
30285 
30286 	/* Equivalent year mapping, used to avoid DST trouble when platform
30287 	 * may fail to provide reasonable DST answers for dates outside the
30288 	 * ordinary range (e.g. 1970-2038).  An equivalent year has the same
30289 	 * leap-year-ness as the original year and begins on the same weekday
30290 	 * (Jan 1).
30291 	 *
30292 	 * The year 2038 is avoided because there seem to be problems with it
30293 	 * on some platforms.  The year 1970 is also avoided as there were
30294 	 * practical problems with it; an equivalent year is used for it too,
30295 	 * which breaks some DST computations for 1970 right now, see e.g.
30296 	 * test-bi-date-tzoffset-brute-fi.js.
30297 	 */
30298 	if ((flags & DUK_DATE_FLAG_EQUIVYEAR) && (year < 1971 || year > 2037)) {
30299 		DUK_ASSERT(is_leap == 0 || is_leap == 1);
30300 
30301 		jan1_since_epoch = day_since_epoch - day_in_year;  /* day number for Jan 1 since epoch */
30302 		DUK_ASSERT(jan1_since_epoch + DUK__WEEKDAY_MOD_ADDER >= 0);
30303 		jan1_weekday = (jan1_since_epoch + 4 + DUK__WEEKDAY_MOD_ADDER) % 7;  /* E5.1 Section 15.9.1.6 */
30304 		DUK_ASSERT(jan1_weekday >= 0 && jan1_weekday <= 6);
30305 		arridx = jan1_weekday;
30306 		if (is_leap) {
30307 			arridx += 7;
30308 		}
30309 		DUK_ASSERT(arridx >= 0 && arridx < (duk_small_int_t) (sizeof(duk__date_equivyear) / sizeof(duk_uint8_t)));
30310 
30311 		equiv_year = (duk_int_t) duk__date_equivyear[arridx] + 1970;
30312 		year = equiv_year;
30313 		DUK_DDD(DUK_DDDPRINT("equiv year mapping, year=%ld, day_in_year=%ld, day_since_epoch=%ld, "
30314 		                     "jan1_since_epoch=%ld, jan1_weekday=%ld -> equiv year %ld",
30315 		                     (long) year, (long) day_in_year, (long) day_since_epoch,
30316 		                     (long) jan1_since_epoch, (long) jan1_weekday, (long) equiv_year));
30317 	}
30318 
30319 	parts[DUK_DATE_IDX_YEAR] = year;
30320 	parts[DUK_DATE_IDX_MONTH] = month;
30321 	parts[DUK_DATE_IDX_DAY] = day;
30322 
30323 	if (flags & DUK_DATE_FLAG_ONEBASED) {
30324 		parts[DUK_DATE_IDX_MONTH]++;  /* zero-based -> one-based */
30325 		parts[DUK_DATE_IDX_DAY]++;    /* -""- */
30326 	}
30327 
30328 	if (dparts != NULL) {
30329 		for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
30330 			dparts[i] = (duk_double_t) parts[i];
30331 		}
30332 	}
30333 }
30334 
30335 /* Compute time value from (double) parts.  The parts can be either UTC
30336  * or local time; if local, they need to be (conceptually) converted into
30337  * UTC time.  The parts may represent valid or invalid time, and may be
30338  * wildly out of range (but may cancel each other and still come out in
30339  * the valid Date range).
30340  */
duk_bi_date_get_timeval_from_dparts(duk_double_t * dparts,duk_small_uint_t flags)30341 DUK_INTERNAL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags) {
30342 #if defined(DUK_USE_PARANOID_DATE_COMPUTATION)
30343 	/* See comments below on MakeTime why these are volatile. */
30344 	volatile duk_double_t tmp_time;
30345 	volatile duk_double_t tmp_day;
30346 	volatile duk_double_t d;
30347 #else
30348 	duk_double_t tmp_time;
30349 	duk_double_t tmp_day;
30350 	duk_double_t d;
30351 #endif
30352 	duk_small_uint_t i;
30353 	duk_int_t tzoff, tzoffprev1, tzoffprev2;
30354 
30355 	/* Expects 'this' at top of stack on entry. */
30356 
30357 	/* Coerce all finite parts with ToInteger().  ToInteger() must not
30358 	 * be called for NaN/Infinity because it will convert e.g. NaN to
30359 	 * zero.  If ToInteger() has already been called, this has no side
30360 	 * effects and is idempotent.
30361 	 *
30362 	 * Don't read dparts[DUK_DATE_IDX_WEEKDAY]; it will cause Valgrind
30363 	 * issues if the value is uninitialized.
30364 	 */
30365 	for (i = 0; i <= DUK_DATE_IDX_MILLISECOND; i++) {
30366 		/* SCANBUILD: scan-build complains here about assigned value
30367 		 * being garbage or undefined.  This is correct but operating
30368 		 * on undefined values has no ill effect and is ignored by the
30369 		 * caller in the case where this happens.
30370 		 */
30371 		d = dparts[i];
30372 		if (DUK_ISFINITE(d)) {
30373 			dparts[i] = duk_js_tointeger_number(d);
30374 		}
30375 	}
30376 
30377 	/* Use explicit steps in computation to try to ensure that
30378 	 * computation happens with intermediate results coerced to
30379 	 * double values (instead of using something more accurate).
30380 	 * E.g. E5.1 Section 15.9.1.11 requires use of IEEE 754
30381 	 * rules (= ECMAScript '+' and '*' operators).
30382 	 *
30383 	 * Without 'volatile' even this approach fails on some platform
30384 	 * and compiler combinations.  For instance, gcc 4.8.1 on Ubuntu
30385 	 * 64-bit, with -m32 and without -std=c99, test-bi-date-canceling.js
30386 	 * would fail because of some optimizations when computing tmp_time
30387 	 * (MakeTime below).  Adding 'volatile' to tmp_time solved this
30388 	 * particular problem (annoyingly, also adding debug prints or
30389 	 * running the executable under valgrind hides it).
30390 	 */
30391 
30392 	/* MakeTime */
30393 	tmp_time = 0.0;
30394 	tmp_time += dparts[DUK_DATE_IDX_HOUR] * ((duk_double_t) DUK_DATE_MSEC_HOUR);
30395 	tmp_time += dparts[DUK_DATE_IDX_MINUTE] * ((duk_double_t) DUK_DATE_MSEC_MINUTE);
30396 	tmp_time += dparts[DUK_DATE_IDX_SECOND] * ((duk_double_t) DUK_DATE_MSEC_SECOND);
30397 	tmp_time += dparts[DUK_DATE_IDX_MILLISECOND];
30398 
30399 	/* MakeDay */
30400 	tmp_day = duk__make_day(dparts[DUK_DATE_IDX_YEAR], dparts[DUK_DATE_IDX_MONTH], dparts[DUK_DATE_IDX_DAY]);
30401 
30402 	/* MakeDate */
30403 	d = tmp_day * ((duk_double_t) DUK_DATE_MSEC_DAY) + tmp_time;
30404 
30405 	DUK_DDD(DUK_DDDPRINT("time=%lf day=%lf --> timeval=%lf",
30406 	                     (double) tmp_time, (double) tmp_day, (double) d));
30407 
30408 	/* Optional UTC conversion. */
30409 	if (flags & DUK_DATE_FLAG_LOCALTIME) {
30410 		/* DUK_USE_DATE_GET_LOCAL_TZOFFSET() needs to be called with a
30411 		 * time value computed from UTC parts.  At this point we only
30412 		 * have 'd' which is a time value computed from local parts, so
30413 		 * it is off by the UTC-to-local time offset which we don't know
30414 		 * yet.  The current solution for computing the UTC-to-local
30415 		 * time offset is to iterate a few times and detect a fixed
30416 		 * point or a two-cycle loop (or a sanity iteration limit),
30417 		 * see test-bi-date-local-parts.js and test-bi-date-tzoffset-basic-fi.js.
30418 		 *
30419 		 * E5.1 Section 15.9.1.9:
30420 		 * UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA)
30421 		 *
30422 		 * For NaN/inf, DUK_USE_DATE_GET_LOCAL_TZOFFSET() returns 0.
30423 		 */
30424 
30425 #if 0
30426 		/* Old solution: don't iterate, incorrect */
30427 		tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
30428 		DUK_DDD(DUK_DDDPRINT("tzoffset w/o iteration, tzoff=%ld", (long) tzoff));
30429 		d -= tzoff * 1000L;
30430 		DUK_UNREF(tzoffprev1);
30431 		DUK_UNREF(tzoffprev2);
30432 #endif
30433 
30434 		/* Iteration solution */
30435 		tzoff = 0;
30436 		tzoffprev1 = 999999999L;  /* invalid value which never matches */
30437 		for (i = 0; i < DUK__LOCAL_TZOFFSET_MAXITER; i++) {
30438 			tzoffprev2 = tzoffprev1;
30439 			tzoffprev1 = tzoff;
30440 			tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d - tzoff * 1000L);
30441 			DUK_DDD(DUK_DDDPRINT("tzoffset iteration, i=%d, tzoff=%ld, tzoffprev1=%ld tzoffprev2=%ld",
30442 			                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
30443 			if (tzoff == tzoffprev1) {
30444 				DUK_DDD(DUK_DDDPRINT("tzoffset iteration finished, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
30445 				                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
30446 				break;
30447 			} else if (tzoff == tzoffprev2) {
30448 				/* Two value cycle, see e.g. test-bi-date-tzoffset-basic-fi.js.
30449 				 * In these cases, favor a higher tzoffset to get a consistent
30450 				 * result which is independent of iteration count.  Not sure if
30451 				 * this is a generically correct solution.
30452 				 */
30453 				DUK_DDD(DUK_DDDPRINT("tzoffset iteration two-value cycle, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
30454 				                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
30455 				if (tzoffprev1 > tzoff) {
30456 					tzoff = tzoffprev1;
30457 				}
30458 				break;
30459 			}
30460 		}
30461 		DUK_DDD(DUK_DDDPRINT("tzoffset iteration, tzoff=%ld", (long) tzoff));
30462 		d -= tzoff * 1000L;
30463 	}
30464 
30465 	/* TimeClip(), which also handles Infinity -> NaN conversion */
30466 	d = duk__timeclip(d);
30467 
30468 	return d;
30469 }
30470 
30471 /*
30472  *  API oriented helpers
30473  */
30474 
30475 /* Push 'this' binding, check that it is a Date object; then push the
30476  * internal time value.  At the end, stack is: [ ... this timeval ].
30477  * Returns the time value.  Local time adjustment is done if requested.
30478  */
duk__push_this_get_timeval_tzoffset(duk_hthread * thr,duk_small_uint_t flags,duk_int_t * out_tzoffset)30479 DUK_LOCAL duk_double_t duk__push_this_get_timeval_tzoffset(duk_hthread *thr, duk_small_uint_t flags, duk_int_t *out_tzoffset) {
30480 	duk_hobject *h;
30481 	duk_double_t d;
30482 	duk_int_t tzoffset = 0;
30483 
30484 	duk_push_this(thr);
30485 	h = duk_get_hobject(thr, -1);  /* XXX: getter with class check, useful in built-ins */
30486 	if (h == NULL || DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_DATE) {
30487 		DUK_ERROR_TYPE(thr, "expected Date");
30488 		DUK_WO_NORETURN(return 0.0;);
30489 	}
30490 
30491 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
30492 	d = duk_to_number_m1(thr);
30493 	duk_pop(thr);
30494 
30495 	if (DUK_ISNAN(d)) {
30496 		if (flags & DUK_DATE_FLAG_NAN_TO_ZERO) {
30497 			d = 0.0;
30498 		}
30499 		if (flags & DUK_DATE_FLAG_NAN_TO_RANGE_ERROR) {
30500 			DUK_ERROR_RANGE(thr, "Invalid Date");
30501 			DUK_WO_NORETURN(return 0.0;);
30502 		}
30503 	}
30504 	/* if no NaN handling flag, may still be NaN here, but not Inf */
30505 	DUK_ASSERT(!DUK_ISINF(d));
30506 
30507 	if (flags & DUK_DATE_FLAG_LOCALTIME) {
30508 		/* Note: DST adjustment is determined using UTC time.
30509 		 * If 'd' is NaN, tzoffset will be 0.
30510 		 */
30511 		tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);  /* seconds */
30512 		d += tzoffset * 1000L;
30513 	}
30514 	if (out_tzoffset) {
30515 		*out_tzoffset = tzoffset;
30516 	}
30517 
30518 	/* [ ... this ] */
30519 	return d;
30520 }
30521 
duk__push_this_get_timeval(duk_hthread * thr,duk_small_uint_t flags)30522 DUK_LOCAL duk_double_t duk__push_this_get_timeval(duk_hthread *thr, duk_small_uint_t flags) {
30523 	return duk__push_this_get_timeval_tzoffset(thr, flags, NULL);
30524 }
30525 
30526 /* Set timeval to 'this' from dparts, push the new time value onto the
30527  * value stack and return 1 (caller can then tail call us).  Expects
30528  * the value stack to contain 'this' on the stack top.
30529  */
duk__set_this_timeval_from_dparts(duk_hthread * thr,duk_double_t * dparts,duk_small_uint_t flags)30530 DUK_LOCAL duk_ret_t duk__set_this_timeval_from_dparts(duk_hthread *thr, duk_double_t *dparts, duk_small_uint_t flags) {
30531 	duk_double_t d;
30532 
30533 	/* [ ... this ] */
30534 
30535 	d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
30536 	duk_push_number(thr, d);  /* -> [ ... this timeval_new ] */
30537 	duk_dup_top(thr);         /* -> [ ... this timeval_new timeval_new ] */
30538 	duk_put_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE);
30539 
30540 	/* stack top: new time value, return 1 to allow tail calls */
30541 	return 1;
30542 }
30543 
30544 /* '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)30545 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) {
30546 	char yearstr[8];   /* "-123456\0" */
30547 	char tzstr[8];     /* "+11:22\0" */
30548 	char sep = (flags & DUK_DATE_FLAG_SEP_T) ? DUK_ASC_UC_T : DUK_ASC_SPACE;
30549 
30550 	DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
30551 	DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
30552 	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= -999999 && parts[DUK_DATE_IDX_YEAR] <= 999999);
30553 
30554 	/* Note: %06d for positive value, %07d for negative value to include
30555 	 * sign and 6 digits.
30556 	 */
30557 	DUK_SNPRINTF(yearstr,
30558 	             sizeof(yearstr),
30559 	             (parts[DUK_DATE_IDX_YEAR] >= 0 && parts[DUK_DATE_IDX_YEAR] <= 9999) ? "%04ld" :
30560 	                    ((parts[DUK_DATE_IDX_YEAR] >= 0) ? "+%06ld" : "%07ld"),
30561 	             (long) parts[DUK_DATE_IDX_YEAR]);
30562 	yearstr[sizeof(yearstr) - 1] = (char) 0;
30563 
30564 	if (flags & DUK_DATE_FLAG_LOCALTIME) {
30565 		/* tzoffset seconds are dropped; 16 bits suffice for
30566 		 * time offset in minutes
30567 		 */
30568 		const char *fmt;
30569 		duk_small_int_t tmp, arg_hours, arg_minutes;
30570 
30571 		if (tzoffset >= 0) {
30572 			tmp = tzoffset;
30573 			fmt = "+%02d:%02d";
30574 		} else {
30575 			tmp = -tzoffset;
30576 			fmt = "-%02d:%02d";
30577 		}
30578 		tmp = tmp / 60;
30579 		arg_hours = tmp / 60;
30580 		arg_minutes = tmp % 60;
30581 		DUK_ASSERT(arg_hours <= 24);  /* Even less is actually guaranteed for a valid tzoffset. */
30582 		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. */
30583 
30584 		DUK_SNPRINTF(tzstr, sizeof(tzstr), fmt, (int) arg_hours, (int) arg_minutes);
30585 		tzstr[sizeof(tzstr) - 1] = (char) 0;
30586 	} else {
30587 		tzstr[0] = DUK_ASC_UC_Z;
30588 		tzstr[1] = (char) 0;
30589 	}
30590 
30591 	/* Unlike year, the other parts fit into 16 bits so %d format
30592 	 * is portable.
30593 	 */
30594 	if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
30595 		DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d%c%02d:%02d:%02d.%03d%s",
30596 		            (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY], (int) sep,
30597 		            (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
30598 		            (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND], (const char *) tzstr);
30599 	} else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
30600 		DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d",
30601 		            (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY]);
30602 	} else {
30603 		DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);
30604 		DUK_SPRINTF((char *) out_buf, "%02d:%02d:%02d.%03d%s",
30605 		            (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
30606 		            (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND],
30607 		            (const char *) tzstr);
30608 	}
30609 }
30610 
30611 /* Helper for string conversion calls: check 'this' binding, get the
30612  * internal time value, and format date and/or time in a few formats.
30613  * Return value allows tail calls.
30614  */
duk__to_string_helper(duk_hthread * thr,duk_small_uint_t flags)30615 DUK_LOCAL duk_ret_t duk__to_string_helper(duk_hthread *thr, duk_small_uint_t flags) {
30616 	duk_double_t d;
30617 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
30618 	duk_int_t tzoffset;  /* seconds, doesn't fit into 16 bits */
30619 	duk_bool_t rc;
30620 	duk_uint8_t buf[DUK_BI_DATE_ISO8601_BUFSIZE];
30621 
30622 	DUK_UNREF(rc);  /* unreferenced with some options */
30623 
30624 	d = duk__push_this_get_timeval_tzoffset(thr, flags, &tzoffset);
30625 	if (DUK_ISNAN(d)) {
30626 		duk_push_hstring_stridx(thr, DUK_STRIDX_INVALID_DATE);
30627 		return 1;
30628 	}
30629 	DUK_ASSERT(DUK_ISFINITE(d));
30630 
30631 	/* formatters always get one-based month/day-of-month */
30632 	duk_bi_date_timeval_to_parts(d, parts, NULL, DUK_DATE_FLAG_ONEBASED);
30633 	DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
30634 	DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
30635 
30636 	if (flags & DUK_DATE_FLAG_TOSTRING_LOCALE) {
30637 		/* try locale specific formatter; if it refuses to format the
30638 		 * string, fall back to an ISO 8601 formatted value in local
30639 		 * time.
30640 		 */
30641 #if defined(DUK_USE_DATE_FORMAT_STRING)
30642 		/* Contract, either:
30643 		 * - Push string to value stack and return 1
30644 		 * - Don't push anything and return 0
30645 		 */
30646 
30647 		rc = DUK_USE_DATE_FORMAT_STRING(thr, parts, tzoffset, flags);
30648 		if (rc != 0) {
30649 			return 1;
30650 		}
30651 #else
30652 		/* No locale specific formatter; this is OK, we fall back
30653 		 * to ISO 8601.
30654 		 */
30655 #endif
30656 	}
30657 
30658 	/* Different calling convention than above used because the helper
30659 	 * is shared.
30660 	 */
30661 	duk__format_parts_iso8601(parts, tzoffset, flags, buf);
30662 	duk_push_string(thr, (const char *) buf);
30663 	return 1;
30664 }
30665 
30666 /* Helper for component getter calls: check 'this' binding, get the
30667  * internal time value, split it into parts (either as UTC time or
30668  * local time), push a specified component as a return value to the
30669  * value stack and return 1 (caller can then tail call us).
30670  */
duk__get_part_helper(duk_hthread * thr,duk_small_uint_t flags_and_idx)30671 DUK_LOCAL duk_ret_t duk__get_part_helper(duk_hthread *thr, duk_small_uint_t flags_and_idx) {
30672 	duk_double_t d;
30673 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
30674 	duk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> DUK_DATE_FLAG_VALUE_SHIFT);  /* unpack args */
30675 
30676 	DUK_ASSERT_DISABLE(idx_part >= 0);  /* unsigned */
30677 	DUK_ASSERT(idx_part < DUK_DATE_IDX_NUM_PARTS);
30678 
30679 	d = duk__push_this_get_timeval(thr, flags_and_idx);
30680 	if (DUK_ISNAN(d)) {
30681 		duk_push_nan(thr);
30682 		return 1;
30683 	}
30684 	DUK_ASSERT(DUK_ISFINITE(d));
30685 
30686 	duk_bi_date_timeval_to_parts(d, parts, NULL, flags_and_idx);  /* no need to mask idx portion */
30687 
30688 	/* Setter APIs detect special year numbers (0...99) and apply a +1900
30689 	 * only in certain cases.  The legacy getYear() getter applies -1900
30690 	 * unconditionally.
30691 	 */
30692 	duk_push_int(thr, (flags_and_idx & DUK_DATE_FLAG_SUB1900) ? parts[idx_part] - 1900 : parts[idx_part]);
30693 	return 1;
30694 }
30695 
30696 /* Helper for component setter calls: check 'this' binding, get the
30697  * internal time value, split it into parts (either as UTC time or
30698  * local time), modify one or more components as specified, recompute
30699  * the time value, set it as the internal value.  Finally, push the
30700  * new time value as a return value to the value stack and return 1
30701  * (caller can then tail call us).
30702  */
duk__set_part_helper(duk_hthread * thr,duk_small_uint_t flags_and_maxnargs)30703 DUK_LOCAL duk_ret_t duk__set_part_helper(duk_hthread *thr, duk_small_uint_t flags_and_maxnargs) {
30704 	duk_double_t d;
30705 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
30706 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
30707 	duk_idx_t nargs;
30708 	duk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> DUK_DATE_FLAG_VALUE_SHIFT);  /* unpack args */
30709 	duk_small_uint_t idx_first, idx;
30710 	duk_small_uint_t i;
30711 
30712 	nargs = duk_get_top(thr);
30713 	d = duk__push_this_get_timeval(thr, flags_and_maxnargs);
30714 	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
30715 
30716 	if (DUK_ISFINITE(d)) {
30717 		duk_bi_date_timeval_to_parts(d, parts, dparts, flags_and_maxnargs);
30718 	} else {
30719 		/* NaN timevalue: we need to coerce the arguments, but
30720 		 * the resulting internal timestamp needs to remain NaN.
30721 		 * This works but is not pretty: parts and dparts will
30722 		 * be partially uninitialized, but we only write to them.
30723 		 */
30724 	}
30725 
30726 	/*
30727 	 *  Determining which datetime components to overwrite based on
30728 	 *  stack arguments is a bit complicated, but important to factor
30729 	 *  out from setters themselves for compactness.
30730 	 *
30731 	 *  If DUK_DATE_FLAG_TIMESETTER, maxnargs indicates setter type:
30732 	 *
30733 	 *   1 -> millisecond
30734 	 *   2 -> second, [millisecond]
30735 	 *   3 -> minute, [second], [millisecond]
30736 	 *   4 -> hour, [minute], [second], [millisecond]
30737 	 *
30738 	 *  Else:
30739 	 *
30740 	 *   1 -> date
30741 	 *   2 -> month, [date]
30742 	 *   3 -> year, [month], [date]
30743 	 *
30744 	 *  By comparing nargs and maxnargs (and flags) we know which
30745 	 *  components to override.  We rely on part index ordering.
30746 	 */
30747 
30748 	if (flags_and_maxnargs & DUK_DATE_FLAG_TIMESETTER) {
30749 		DUK_ASSERT(maxnargs >= 1 && maxnargs <= 4);
30750 		idx_first = DUK_DATE_IDX_MILLISECOND - (maxnargs - 1);
30751 	} else {
30752 		DUK_ASSERT(maxnargs >= 1 && maxnargs <= 3);
30753 		idx_first = DUK_DATE_IDX_DAY - (maxnargs - 1);
30754 	}
30755 	DUK_ASSERT_DISABLE(idx_first >= 0);  /* unsigned */
30756 	DUK_ASSERT(idx_first < DUK_DATE_IDX_NUM_PARTS);
30757 
30758 	for (i = 0; i < maxnargs; i++) {
30759 		if ((duk_idx_t) i >= nargs) {
30760 			/* no argument given -> leave components untouched */
30761 			break;
30762 		}
30763 		idx = idx_first + i;
30764 		DUK_ASSERT_DISABLE(idx >= 0);  /* unsigned */
30765 		DUK_ASSERT(idx < DUK_DATE_IDX_NUM_PARTS);
30766 
30767 		if (idx == DUK_DATE_IDX_YEAR && (flags_and_maxnargs & DUK_DATE_FLAG_YEAR_FIXUP)) {
30768 			duk__twodigit_year_fixup(thr, (duk_idx_t) i);
30769 		}
30770 
30771 		dparts[idx] = duk_to_number(thr, (duk_idx_t) i);
30772 
30773 		if (idx == DUK_DATE_IDX_DAY) {
30774 			/* Day-of-month is one-based in the API, but zero-based
30775 			 * internally, so fix here.  Note that month is zero-based
30776 			 * both in the API and internally.
30777 			 */
30778 			/* SCANBUILD: complains about use of uninitialized values.
30779 			 * The complaint is correct, but operating in undefined
30780 			 * values here is intentional in some cases and the caller
30781 			 * ignores the results.
30782 			 */
30783 			dparts[idx] -= 1.0;
30784 		}
30785 	}
30786 
30787 	/* Leaves new timevalue on stack top and returns 1, which is correct
30788 	 * for part setters.
30789 	 */
30790 	if (DUK_ISFINITE(d)) {
30791 		return duk__set_this_timeval_from_dparts(thr, dparts, flags_and_maxnargs);
30792 	} else {
30793 		/* Internal timevalue is already NaN, so don't touch it. */
30794 		duk_push_nan(thr);
30795 		return 1;
30796 	}
30797 }
30798 
30799 /* Apply ToNumber() to specified index; if ToInteger(val) in [0,99], add
30800  * 1900 and replace value at idx_val.
30801  */
duk__twodigit_year_fixup(duk_hthread * thr,duk_idx_t idx_val)30802 DUK_LOCAL void duk__twodigit_year_fixup(duk_hthread *thr, duk_idx_t idx_val) {
30803 	duk_double_t d;
30804 
30805 	/* XXX: idx_val would fit into 16 bits, but using duk_small_uint_t
30806 	 * might not generate better code due to casting.
30807 	 */
30808 
30809 	/* E5 Sections 15.9.3.1, B.2.4, B.2.5 */
30810 	duk_to_number(thr, idx_val);
30811 	if (duk_is_nan(thr, idx_val)) {
30812 		return;
30813 	}
30814 	duk_dup(thr, idx_val);
30815 	duk_to_int(thr, -1);
30816 	d = duk_get_number(thr, -1);  /* get as double to handle huge numbers correctly */
30817 	if (d >= 0.0 && d <= 99.0) {
30818 		d += 1900.0;
30819 		duk_push_number(thr, d);
30820 		duk_replace(thr, idx_val);
30821 	}
30822 	duk_pop(thr);
30823 }
30824 
30825 /* Set datetime parts from stack arguments, defaulting any missing values.
30826  * Day-of-week is not set; it is not required when setting the time value.
30827  */
duk__set_parts_from_args(duk_hthread * thr,duk_double_t * dparts,duk_idx_t nargs)30828 DUK_LOCAL void duk__set_parts_from_args(duk_hthread *thr, duk_double_t *dparts, duk_idx_t nargs) {
30829 	duk_double_t d;
30830 	duk_small_uint_t i;
30831 	duk_small_uint_t idx;
30832 
30833 	/* Causes a ToNumber() coercion, but doesn't break coercion order since
30834 	 * year is coerced first anyway.
30835 	 */
30836 	duk__twodigit_year_fixup(thr, 0);
30837 
30838 	/* There are at most 7 args, but we use 8 here so that also
30839 	 * DUK_DATE_IDX_WEEKDAY gets initialized (to zero) to avoid the potential
30840 	 * for any Valgrind gripes later.
30841 	 */
30842 	for (i = 0; i < 8; i++) {
30843 		/* Note: rely on index ordering */
30844 		idx = DUK_DATE_IDX_YEAR + i;
30845 		if ((duk_idx_t) i < nargs) {
30846 			d = duk_to_number(thr, (duk_idx_t) i);
30847 			if (idx == DUK_DATE_IDX_DAY) {
30848 				/* Convert day from one-based to zero-based (internal).  This may
30849 				 * cause the day part to be negative, which is OK.
30850 				 */
30851 				d -= 1.0;
30852 			}
30853 		} else {
30854 			/* All components default to 0 except day-of-month which defaults
30855 			 * to 1.  However, because our internal day-of-month is zero-based,
30856 			 * it also defaults to zero here.
30857 			 */
30858 			d = 0.0;
30859 		}
30860 		dparts[idx] = d;
30861 	}
30862 
30863 	DUK_DDD(DUK_DDDPRINT("parts from args -> %lf %lf %lf %lf %lf %lf %lf %lf",
30864 	                     (double) dparts[0], (double) dparts[1],
30865 	                     (double) dparts[2], (double) dparts[3],
30866 	                     (double) dparts[4], (double) dparts[5],
30867 	                     (double) dparts[6], (double) dparts[7]));
30868 }
30869 
30870 /*
30871  *  Indirect magic value lookup for Date methods.
30872  *
30873  *  Date methods don't put their control flags into the function magic value
30874  *  because they wouldn't fit into a LIGHTFUNC's magic field.  Instead, the
30875  *  magic value is set to an index pointing to the array of control flags
30876  *  below.
30877  *
30878  *  This must be kept in strict sync with genbuiltins.py!
30879  */
30880 
30881 static duk_uint16_t duk__date_magics[] = {
30882 	/* 0: toString */
30883 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME,
30884 
30885 	/* 1: toDateString */
30886 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_LOCALTIME,
30887 
30888 	/* 2: toTimeString */
30889 	DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME,
30890 
30891 	/* 3: toLocaleString */
30892 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
30893 
30894 	/* 4: toLocaleDateString */
30895 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
30896 
30897 	/* 5: toLocaleTimeString */
30898 	DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
30899 
30900 	/* 6: toUTCString */
30901 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME,
30902 
30903 	/* 7: toISOString */
30904 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_NAN_TO_RANGE_ERROR + DUK_DATE_FLAG_SEP_T,
30905 
30906 	/* 8: getFullYear */
30907 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
30908 
30909 	/* 9: getUTCFullYear */
30910 	0 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
30911 
30912 	/* 10: getMonth */
30913 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT),
30914 
30915 	/* 11: getUTCMonth */
30916 	0 + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT),
30917 
30918 	/* 12: getDate */
30919 	DUK_DATE_FLAG_ONEBASED + DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT),
30920 
30921 	/* 13: getUTCDate */
30922 	DUK_DATE_FLAG_ONEBASED + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT),
30923 
30924 	/* 14: getDay */
30925 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT),
30926 
30927 	/* 15: getUTCDay */
30928 	0 + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT),
30929 
30930 	/* 16: getHours */
30931 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT),
30932 
30933 	/* 17: getUTCHours */
30934 	0 + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT),
30935 
30936 	/* 18: getMinutes */
30937 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT),
30938 
30939 	/* 19: getUTCMinutes */
30940 	0 + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT),
30941 
30942 	/* 20: getSeconds */
30943 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT),
30944 
30945 	/* 21: getUTCSeconds */
30946 	0 + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT),
30947 
30948 	/* 22: getMilliseconds */
30949 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT),
30950 
30951 	/* 23: getUTCMilliseconds */
30952 	0 + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT),
30953 
30954 	/* 24: setMilliseconds */
30955 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
30956 
30957 	/* 25: setUTCMilliseconds */
30958 	DUK_DATE_FLAG_TIMESETTER + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
30959 
30960 	/* 26: setSeconds */
30961 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
30962 
30963 	/* 27: setUTCSeconds */
30964 	DUK_DATE_FLAG_TIMESETTER + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
30965 
30966 	/* 28: setMinutes */
30967 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
30968 
30969 	/* 29: setUTCMinutes */
30970 	DUK_DATE_FLAG_TIMESETTER + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
30971 
30972 	/* 30: setHours */
30973 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (4 << DUK_DATE_FLAG_VALUE_SHIFT),
30974 
30975 	/* 31: setUTCHours */
30976 	DUK_DATE_FLAG_TIMESETTER + (4 << DUK_DATE_FLAG_VALUE_SHIFT),
30977 
30978 	/* 32: setDate */
30979 	DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
30980 
30981 	/* 33: setUTCDate */
30982 	0 + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
30983 
30984 	/* 34: setMonth */
30985 	DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
30986 
30987 	/* 35: setUTCMonth */
30988 	0 + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
30989 
30990 	/* 36: setFullYear */
30991 	DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
30992 
30993 	/* 37: setUTCFullYear */
30994 	DUK_DATE_FLAG_NAN_TO_ZERO + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
30995 
30996 	/* 38: getYear */
30997 	DUK_DATE_FLAG_LOCALTIME + DUK_DATE_FLAG_SUB1900 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
30998 
30999 	/* 39: setYear */
31000 	DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_YEAR_FIXUP + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
31001 };
31002 
duk__date_get_indirect_magic(duk_hthread * thr)31003 DUK_LOCAL duk_small_uint_t duk__date_get_indirect_magic(duk_hthread *thr) {
31004 	duk_small_uint_t magicidx = (duk_small_uint_t) duk_get_current_magic(thr);
31005 	DUK_ASSERT(magicidx < (duk_small_int_t) (sizeof(duk__date_magics) / sizeof(duk_uint16_t)));
31006 	return (duk_small_uint_t) duk__date_magics[magicidx];
31007 }
31008 
31009 #if defined(DUK_USE_DATE_BUILTIN)
31010 /*
31011  *  Constructor calls
31012  */
31013 
duk_bi_date_constructor(duk_hthread * thr)31014 DUK_INTERNAL duk_ret_t duk_bi_date_constructor(duk_hthread *thr) {
31015 	duk_idx_t nargs = duk_get_top(thr);
31016 	duk_bool_t is_cons = duk_is_constructor_call(thr);
31017 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
31018 	duk_double_t d;
31019 
31020 	DUK_DDD(DUK_DDDPRINT("Date constructor, nargs=%ld, is_cons=%ld", (long) nargs, (long) is_cons));
31021 
31022 	(void) duk_push_object_helper(thr,
31023 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
31024 	                              DUK_HOBJECT_FLAG_FASTREFS |
31025 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATE),
31026 	                              DUK_BIDX_DATE_PROTOTYPE);
31027 
31028 	/* Unlike most built-ins, the internal [[PrimitiveValue]] of a Date
31029 	 * is mutable.
31030 	 */
31031 
31032 	if (nargs == 0 || !is_cons) {
31033 		d = duk__timeclip(duk_time_get_ecmascript_time_nofrac(thr));
31034 		duk_push_number(thr, d);
31035 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
31036 		if (!is_cons) {
31037 			/* called as a normal function: return new Date().toString() */
31038 			duk_to_string(thr, -1);
31039 		}
31040 		return 1;
31041 	} else if (nargs == 1) {
31042 		const char *str;
31043 		duk_to_primitive(thr, 0, DUK_HINT_NONE);
31044 		str = duk_get_string_notsymbol(thr, 0);
31045 		if (str) {
31046 			duk__parse_string(thr, str);
31047 			duk_replace(thr, 0);  /* may be NaN */
31048 		}
31049 		d = duk__timeclip(duk_to_number(thr, 0));  /* symbols fail here */
31050 		duk_push_number(thr, d);
31051 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
31052 		return 1;
31053 	}
31054 
31055 	duk__set_parts_from_args(thr, dparts, nargs);
31056 
31057 	/* Parts are in local time, convert when setting. */
31058 
31059 	(void) duk__set_this_timeval_from_dparts(thr, dparts, DUK_DATE_FLAG_LOCALTIME /*flags*/);  /* -> [ ... this timeval ] */
31060 	duk_pop(thr);  /* -> [ ... this ] */
31061 	return 1;
31062 }
31063 
duk_bi_date_constructor_parse(duk_hthread * thr)31064 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_parse(duk_hthread *thr) {
31065 	return duk__parse_string(thr, duk_to_string(thr, 0));
31066 }
31067 
duk_bi_date_constructor_utc(duk_hthread * thr)31068 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_utc(duk_hthread *thr) {
31069 	duk_idx_t nargs = duk_get_top(thr);
31070 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
31071 	duk_double_t d;
31072 
31073 	/* Behavior for nargs < 2 is implementation dependent: currently we'll
31074 	 * set a NaN time value (matching V8 behavior) in this case.
31075 	 */
31076 
31077 	if (nargs < 2) {
31078 		duk_push_nan(thr);
31079 	} else {
31080 		duk__set_parts_from_args(thr, dparts, nargs);
31081 		d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
31082 		duk_push_number(thr, d);
31083 	}
31084 	return 1;
31085 }
31086 
duk_bi_date_constructor_now(duk_hthread * thr)31087 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_now(duk_hthread *thr) {
31088 	duk_double_t d;
31089 
31090 	d = duk_time_get_ecmascript_time_nofrac(thr);
31091 	DUK_ASSERT(duk__timeclip(d) == d);  /* TimeClip() should never be necessary */
31092 	duk_push_number(thr, d);
31093 	return 1;
31094 }
31095 
31096 /*
31097  *  String/JSON conversions
31098  *
31099  *  Human readable conversions are now basically ISO 8601 with a space
31100  *  (instead of 'T') as the date/time separator.  This is a good baseline
31101  *  and is platform independent.
31102  *
31103  *  A shared native helper to provide many conversions.  Magic value contains
31104  *  a set of flags.  The helper provides:
31105  *
31106  *    toString()
31107  *    toDateString()
31108  *    toTimeString()
31109  *    toLocaleString()
31110  *    toLocaleDateString()
31111  *    toLocaleTimeString()
31112  *    toUTCString()
31113  *    toISOString()
31114  *
31115  *  Notes:
31116  *
31117  *    - Date.prototype.toGMTString() and Date.prototype.toUTCString() are
31118  *      required to be the same ECMAScript function object (!), so it is
31119  *      omitted from here.
31120  *
31121  *    - Date.prototype.toUTCString(): E5.1 specification does not require a
31122  *      specific format, but result should be human readable.  The
31123  *      specification suggests using ISO 8601 format with a space (instead
31124  *      of 'T') separator if a more human readable format is not available.
31125  *
31126  *    - Date.prototype.toISOString(): unlike other conversion functions,
31127  *      toISOString() requires a RangeError for invalid date values.
31128  */
31129 
duk_bi_date_prototype_tostring_shared(duk_hthread * thr)31130 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_hthread *thr) {
31131 	duk_small_uint_t flags = duk__date_get_indirect_magic(thr);
31132 	return duk__to_string_helper(thr, flags);
31133 }
31134 
duk_bi_date_prototype_value_of(duk_hthread * thr)31135 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_value_of(duk_hthread *thr) {
31136 	/* This native function is also used for Date.prototype.getTime()
31137 	 * as their behavior is identical.
31138 	 */
31139 
31140 	duk_double_t d = duk__push_this_get_timeval(thr, 0 /*flags*/);  /* -> [ this ] */
31141 	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
31142 	duk_push_number(thr, d);
31143 	return 1;
31144 }
31145 
duk_bi_date_prototype_to_json(duk_hthread * thr)31146 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_to_json(duk_hthread *thr) {
31147 	/* Note: toJSON() is a generic function which works even if 'this'
31148 	 * is not a Date.  The sole argument is ignored.
31149 	 */
31150 
31151 	duk_push_this(thr);
31152 	duk_to_object(thr, -1);
31153 
31154 	duk_dup_top(thr);
31155 	duk_to_primitive(thr, -1, DUK_HINT_NUMBER);
31156 	if (duk_is_number(thr, -1)) {
31157 		duk_double_t d = duk_get_number(thr, -1);
31158 		if (!DUK_ISFINITE(d)) {
31159 			duk_push_null(thr);
31160 			return 1;
31161 		}
31162 	}
31163 	duk_pop(thr);
31164 
31165 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_ISO_STRING);
31166 	duk_dup_m2(thr);  /* -> [ O toIsoString O ] */
31167 	duk_call_method(thr, 0);
31168 	return 1;
31169 }
31170 
31171 /*
31172  *  Getters.
31173  *
31174  *  Implementing getters is quite easy.  The internal time value is either
31175  *  NaN, or represents milliseconds (without fractions) from Jan 1, 1970.
31176  *  The internal time value can be converted to integer parts, and each
31177  *  part will be normalized and will fit into a 32-bit signed integer.
31178  *
31179  *  A shared native helper to provide all getters.  Magic value contains
31180  *  a set of flags and also packs the date component index argument.  The
31181  *  helper provides:
31182  *
31183  *    getFullYear()
31184  *    getUTCFullYear()
31185  *    getMonth()
31186  *    getUTCMonth()
31187  *    getDate()
31188  *    getUTCDate()
31189  *    getDay()
31190  *    getUTCDay()
31191  *    getHours()
31192  *    getUTCHours()
31193  *    getMinutes()
31194  *    getUTCMinutes()
31195  *    getSeconds()
31196  *    getUTCSeconds()
31197  *    getMilliseconds()
31198  *    getUTCMilliseconds()
31199  *    getYear()
31200  *
31201  *  Notes:
31202  *
31203  *    - Date.prototype.getDate(): 'date' means day-of-month, and is
31204  *      zero-based in internal calculations but public API expects it to
31205  *      be one-based.
31206  *
31207  *    - Date.prototype.getTime() and Date.prototype.valueOf() have identical
31208  *      behavior.  They have separate function objects, but share the same C
31209  *      function (duk_bi_date_prototype_value_of).
31210  */
31211 
duk_bi_date_prototype_get_shared(duk_hthread * thr)31212 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_shared(duk_hthread *thr) {
31213 	duk_small_uint_t flags_and_idx = duk__date_get_indirect_magic(thr);
31214 	return duk__get_part_helper(thr, flags_and_idx);
31215 }
31216 
duk_bi_date_prototype_get_timezone_offset(duk_hthread * thr)31217 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_hthread *thr) {
31218 	/*
31219 	 *  Return (t - LocalTime(t)) in minutes:
31220 	 *
31221 	 *    t - LocalTime(t) = t - (t + LocalTZA + DaylightSavingTA(t))
31222 	 *                     = -(LocalTZA + DaylightSavingTA(t))
31223 	 *
31224 	 *  where DaylightSavingTA() is checked for time 't'.
31225 	 *
31226 	 *  Note that the sign of the result is opposite to common usage,
31227 	 *  e.g. for EE(S)T which normally is +2h or +3h from UTC, this
31228 	 *  function returns -120 or -180.
31229 	 *
31230 	 */
31231 
31232 	duk_double_t d;
31233 	duk_int_t tzoffset;
31234 
31235 	/* Note: DST adjustment is determined using UTC time. */
31236 	d = duk__push_this_get_timeval(thr, 0 /*flags*/);
31237 	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
31238 	if (DUK_ISNAN(d)) {
31239 		duk_push_nan(thr);
31240 	} else {
31241 		DUK_ASSERT(DUK_ISFINITE(d));
31242 		tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
31243 		duk_push_int(thr, -tzoffset / 60);
31244 	}
31245 	return 1;
31246 }
31247 
31248 /*
31249  *  Setters.
31250  *
31251  *  Setters are a bit more complicated than getters.  Component setters
31252  *  break down the current time value into its (normalized) component
31253  *  parts, replace one or more components with -unnormalized- new values,
31254  *  and the components are then converted back into a time value.  As an
31255  *  example of using unnormalized values:
31256  *
31257  *    var d = new Date(1234567890);
31258  *
31259  *  is equivalent to:
31260  *
31261  *    var d = new Date(0);
31262  *    d.setUTCMilliseconds(1234567890);
31263  *
31264  *  A shared native helper to provide almost all setters.  Magic value
31265  *  contains a set of flags and also packs the "maxnargs" argument.  The
31266  *  helper provides:
31267  *
31268  *    setMilliseconds()
31269  *    setUTCMilliseconds()
31270  *    setSeconds()
31271  *    setUTCSeconds()
31272  *    setMinutes()
31273  *    setUTCMinutes()
31274  *    setHours()
31275  *    setUTCHours()
31276  *    setDate()
31277  *    setUTCDate()
31278  *    setMonth()
31279  *    setUTCMonth()
31280  *    setFullYear()
31281  *    setUTCFullYear()
31282  *    setYear()
31283  *
31284  *  Notes:
31285  *
31286  *    - Date.prototype.setYear() (Section B addition): special year check
31287  *      is omitted.  NaN / Infinity will just flow through and ultimately
31288  *      result in a NaN internal time value.
31289  *
31290  *    - Date.prototype.setYear() does not have optional arguments for
31291  *      setting month and day-in-month (like setFullYear()), but we indicate
31292  *      'maxnargs' to be 3 to get the year written to the correct component
31293  *      index in duk__set_part_helper().  The function has nargs == 1, so only
31294  *      the year will be set regardless of actual argument count.
31295  */
31296 
duk_bi_date_prototype_set_shared(duk_hthread * thr)31297 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_shared(duk_hthread *thr) {
31298 	duk_small_uint_t flags_and_maxnargs = duk__date_get_indirect_magic(thr);
31299 	return duk__set_part_helper(thr, flags_and_maxnargs);
31300 }
31301 
duk_bi_date_prototype_set_time(duk_hthread * thr)31302 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_time(duk_hthread *thr) {
31303 	duk_double_t d;
31304 
31305 	(void) duk__push_this_get_timeval(thr, 0 /*flags*/); /* -> [ timeval this ] */
31306 	d = duk__timeclip(duk_to_number(thr, 0));
31307 	duk_push_number(thr, d);
31308 	duk_dup_top(thr);
31309 	duk_put_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE); /* -> [ timeval this timeval ] */
31310 
31311 	return 1;
31312 }
31313 
31314 /*
31315  *  Misc.
31316  */
31317 
31318 #if defined(DUK_USE_SYMBOL_BUILTIN)
duk_bi_date_prototype_toprimitive(duk_hthread * thr)31319 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_toprimitive(duk_hthread *thr) {
31320 	duk_size_t hintlen;
31321 	const char *hintstr;
31322 	duk_int_t hint;
31323 
31324 	/* Invokes OrdinaryToPrimitive() with suitable hint.  Note that the
31325 	 * method is generic, and works on non-Date arguments too.
31326 	 *
31327 	 * https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype-@@toprimitive
31328 	 */
31329 
31330 	duk_push_this(thr);
31331 	duk_require_object(thr, -1);
31332 	DUK_ASSERT_TOP(thr, 2);
31333 
31334 	hintstr = duk_require_lstring(thr, 0, &hintlen);
31335 	if ((hintlen == 6 && DUK_STRCMP(hintstr, "string") == 0) ||
31336 	    (hintlen == 7 && DUK_STRCMP(hintstr, "default") == 0)) {
31337 		hint = DUK_HINT_STRING;
31338 	} else if (hintlen == 6 && DUK_STRCMP(hintstr, "number") == 0) {
31339 		hint = DUK_HINT_NUMBER;
31340 	} else {
31341 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
31342 	}
31343 
31344 	duk_to_primitive_ordinary(thr, -1, hint);
31345 	return 1;
31346 }
31347 #endif  /* DUK_USE_SYMBOL_BUILTIN */
31348 
31349 #endif  /* DUK_USE_DATE_BUILTIN */
31350 
31351 /* automatic undefs */
31352 #undef DUK__CF_ACCEPT
31353 #undef DUK__CF_ACCEPT_NUL
31354 #undef DUK__CF_NEG
31355 #undef DUK__DPRINT_DPARTS
31356 #undef DUK__DPRINT_PARTS
31357 #undef DUK__DPRINT_PARTS_AND_DPARTS
31358 #undef DUK__LOCAL_TZOFFSET_MAXITER
31359 #undef DUK__NUM_ISO8601_PARSER_PARTS
31360 #undef DUK__PACK_RULE
31361 #undef DUK__PI_DAY
31362 #undef DUK__PI_HOUR
31363 #undef DUK__PI_MILLISECOND
31364 #undef DUK__PI_MINUTE
31365 #undef DUK__PI_MONTH
31366 #undef DUK__PI_SECOND
31367 #undef DUK__PI_TZHOUR
31368 #undef DUK__PI_TZMINUTE
31369 #undef DUK__PI_YEAR
31370 #undef DUK__PM_DAY
31371 #undef DUK__PM_HOUR
31372 #undef DUK__PM_MILLISECOND
31373 #undef DUK__PM_MINUTE
31374 #undef DUK__PM_MONTH
31375 #undef DUK__PM_SECOND
31376 #undef DUK__PM_TZHOUR
31377 #undef DUK__PM_TZMINUTE
31378 #undef DUK__PM_YEAR
31379 #undef DUK__RULE_MASK_PART_SEP
31380 #undef DUK__SI_COLON
31381 #undef DUK__SI_MINUS
31382 #undef DUK__SI_NUL
31383 #undef DUK__SI_PERIOD
31384 #undef DUK__SI_PLUS
31385 #undef DUK__SI_SPACE
31386 #undef DUK__SI_T
31387 #undef DUK__SI_Z
31388 #undef DUK__SM_COLON
31389 #undef DUK__SM_MINUS
31390 #undef DUK__SM_NUL
31391 #undef DUK__SM_PERIOD
31392 #undef DUK__SM_PLUS
31393 #undef DUK__SM_SPACE
31394 #undef DUK__SM_T
31395 #undef DUK__SM_Z
31396 #undef DUK__UNPACK_RULE
31397 #undef DUK__WEEKDAY_MOD_ADDER
31398 #undef DUK__YEAR
31399 #line 1 "duk_bi_date_unix.c"
31400 /*
31401  *  Unix-like Date providers
31402  *
31403  *  Generally useful Unix / POSIX / ANSI Date providers.
31404  */
31405 
31406 /* #include duk_internal.h -> already included */
31407 
31408 /* The necessary #includes are in place in duk_config.h. */
31409 
31410 /* Buffer sizes for some UNIX calls.  Larger than strictly necessary
31411  * to avoid Valgrind errors.
31412  */
31413 #define DUK__STRPTIME_BUF_SIZE  64
31414 #define DUK__STRFTIME_BUF_SIZE  64
31415 
31416 #if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
31417 /* Get current ECMAScript time (= UNIX/Posix time, but in milliseconds). */
duk_bi_date_get_now_gettimeofday(void)31418 DUK_INTERNAL duk_double_t duk_bi_date_get_now_gettimeofday(void) {
31419 	struct timeval tv;
31420 	duk_double_t d;
31421 
31422 	if (gettimeofday(&tv, NULL) != 0) {
31423 		DUK_D(DUK_DPRINT("gettimeofday() failed"));
31424 		return 0.0;
31425 	}
31426 
31427 	/* As of Duktape 2.2.0 allow fractions. */
31428 	d = ((duk_double_t) tv.tv_sec) * 1000.0 +
31429 	    ((duk_double_t) tv.tv_usec) / 1000.0;
31430 
31431 	return d;
31432 }
31433 #endif  /* DUK_USE_DATE_NOW_GETTIMEOFDAY */
31434 
31435 #if defined(DUK_USE_DATE_NOW_TIME)
31436 /* Not a very good provider: only full seconds are available. */
duk_bi_date_get_now_time(void)31437 DUK_INTERNAL duk_double_t duk_bi_date_get_now_time(void) {
31438 	time_t t;
31439 
31440 	t = time(NULL);
31441 	if (t == (time_t) -1) {
31442 		DUK_D(DUK_DPRINT("time() failed"));
31443 		return 0.0;
31444 	}
31445 	return ((duk_double_t) t) * 1000.0;
31446 }
31447 #endif  /* DUK_USE_DATE_NOW_TIME */
31448 
31449 #if defined(DUK_USE_DATE_TZO_GMTIME) || defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S)
31450 /* Get local time offset (in seconds) for a certain (UTC) instant 'd'. */
duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d)31451 DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) {
31452 	time_t t, t1, t2;
31453 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
31454 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
31455 	struct tm tms[2];
31456 #if defined(DUK_USE_DATE_TZO_GMTIME)
31457 	struct tm *tm_ptr;
31458 #endif
31459 
31460 	/* For NaN/inf, the return value doesn't matter. */
31461 	if (!DUK_ISFINITE(d)) {
31462 		return 0;
31463 	}
31464 
31465 	/* If not within ECMAScript range, some integer time calculations
31466 	 * won't work correctly (and some asserts will fail), so bail out
31467 	 * if so.  This fixes test-bug-date-insane-setyear.js.  There is
31468 	 * a +/- 24h leeway in this range check to avoid a test262 corner
31469 	 * case documented in test-bug-date-timeval-edges.js.
31470 	 */
31471 	if (!duk_bi_date_timeval_in_leeway_range(d)) {
31472 		DUK_DD(DUK_DDPRINT("timeval not within valid range, skip tzoffset computation to avoid integer overflows"));
31473 		return 0;
31474 	}
31475 
31476 	/*
31477 	 *  This is a bit tricky to implement portably.  The result depends
31478 	 *  on the timestamp (specifically, DST depends on the timestamp).
31479 	 *  If e.g. UNIX APIs are used, they'll have portability issues with
31480 	 *  very small and very large years.
31481 	 *
31482 	 *  Current approach:
31483 	 *
31484 	 *  - Stay within portable UNIX limits by using equivalent year mapping.
31485 	 *    Avoid year 1970 and 2038 as some conversions start to fail, at
31486 	 *    least on some platforms.  Avoiding 1970 means that there are
31487 	 *    currently DST discrepancies for 1970.
31488 	 *
31489 	 *  - Create a UTC and local time breakdowns from 't'.  Then create
31490 	 *    a time_t using gmtime() and localtime() and compute the time
31491 	 *    difference between the two.
31492 	 *
31493 	 *  Equivalent year mapping (E5 Section 15.9.1.8):
31494 	 *
31495 	 *    If the host environment provides functionality for determining
31496 	 *    daylight saving time, the implementation of ECMAScript is free
31497 	 *    to map the year in question to an equivalent year (same
31498 	 *    leap-year-ness and same starting week day for the year) for which
31499 	 *    the host environment provides daylight saving time information.
31500 	 *    The only restriction is that all equivalent years should produce
31501 	 *    the same result.
31502 	 *
31503 	 *  This approach is quite reasonable but not entirely correct, e.g.
31504 	 *  the specification also states (E5 Section 15.9.1.8):
31505 	 *
31506 	 *    The implementation of ECMAScript should not try to determine
31507 	 *    whether the exact time was subject to daylight saving time, but
31508 	 *    just whether daylight saving time would have been in effect if
31509 	 *    the _current daylight saving time algorithm_ had been used at the
31510 	 *    time.  This avoids complications such as taking into account the
31511 	 *    years that the locale observed daylight saving time year round.
31512 	 *
31513 	 *  Since we rely on the platform APIs for conversions between local
31514 	 *  time and UTC, we can't guarantee the above.  Rather, if the platform
31515 	 *  has historical DST rules they will be applied.  This seems to be the
31516 	 *  general preferred direction in ECMAScript standardization (or at least
31517 	 *  implementations) anyway, and even the equivalent year mapping should
31518 	 *  be disabled if the platform is known to handle DST properly for the
31519 	 *  full ECMAScript range.
31520 	 *
31521 	 *  The following has useful discussion and links:
31522 	 *
31523 	 *    https://bugzilla.mozilla.org/show_bug.cgi?id=351066
31524 	 */
31525 
31526 	duk_bi_date_timeval_to_parts(d, parts, dparts, DUK_DATE_FLAG_EQUIVYEAR /*flags*/);
31527 	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= 1970 && parts[DUK_DATE_IDX_YEAR] <= 2038);
31528 
31529 	d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
31530 	DUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0);  /* unsigned 31-bit range */
31531 	t = (time_t) (d / 1000.0);
31532 	DUK_DDD(DUK_DDDPRINT("timeval: %lf -> time_t %ld", (double) d, (long) t));
31533 
31534 	duk_memzero((void *) tms, sizeof(struct tm) * 2);
31535 
31536 #if defined(DUK_USE_DATE_TZO_GMTIME_R)
31537 	(void) gmtime_r(&t, &tms[0]);
31538 	(void) localtime_r(&t, &tms[1]);
31539 #elif defined(DUK_USE_DATE_TZO_GMTIME_S)
31540 	(void) gmtime_s(&t, &tms[0]);
31541 	(void) localtime_s(&t, &tms[1]);
31542 #elif defined(DUK_USE_DATE_TZO_GMTIME)
31543 	tm_ptr = gmtime(&t);
31544 	duk_memcpy((void *) &tms[0], tm_ptr, sizeof(struct tm));
31545 	tm_ptr = localtime(&t);
31546 	duk_memcpy((void *) &tms[1], tm_ptr, sizeof(struct tm));
31547 #else
31548 #error internal error
31549 #endif
31550 	DUK_DDD(DUK_DDDPRINT("gmtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
31551 	                     "wday:%ld,yday:%ld,isdst:%ld}",
31552 	                     (long) tms[0].tm_sec, (long) tms[0].tm_min, (long) tms[0].tm_hour,
31553 	                     (long) tms[0].tm_mday, (long) tms[0].tm_mon, (long) tms[0].tm_year,
31554 	                     (long) tms[0].tm_wday, (long) tms[0].tm_yday, (long) tms[0].tm_isdst));
31555 	DUK_DDD(DUK_DDDPRINT("localtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
31556 	                     "wday:%ld,yday:%ld,isdst:%ld}",
31557 	                     (long) tms[1].tm_sec, (long) tms[1].tm_min, (long) tms[1].tm_hour,
31558 	                     (long) tms[1].tm_mday, (long) tms[1].tm_mon, (long) tms[1].tm_year,
31559 	                     (long) tms[1].tm_wday, (long) tms[1].tm_yday, (long) tms[1].tm_isdst));
31560 
31561 	/* tm_isdst is both an input and an output to mktime(), use 0 to
31562 	 * avoid DST handling in mktime():
31563 	 * - https://github.com/svaarala/duktape/issues/406
31564 	 * - http://stackoverflow.com/questions/8558919/mktime-and-tm-isdst
31565 	 */
31566 	tms[0].tm_isdst = 0;
31567 	tms[1].tm_isdst = 0;
31568 	t1 = mktime(&tms[0]);  /* UTC */
31569 	t2 = mktime(&tms[1]);  /* local */
31570 	if (t1 == (time_t) -1 || t2 == (time_t) -1) {
31571 		/* This check used to be for (t < 0) but on some platforms
31572 		 * time_t is unsigned and apparently the proper way to detect
31573 		 * an mktime() error return is the cast above.  See e.g.:
31574 		 * http://pubs.opengroup.org/onlinepubs/009695299/functions/mktime.html
31575 		 */
31576 		goto mktime_error;
31577 	}
31578 	DUK_DDD(DUK_DDDPRINT("t1=%ld (utc), t2=%ld (local)", (long) t1, (long) t2));
31579 
31580 	/* Compute final offset in seconds, positive if local time ahead of
31581 	 * UTC (returned value is UTC-to-local offset).
31582 	 *
31583 	 * difftime() returns a double, so coercion to int generates quite
31584 	 * a lot of code.  Direct subtraction is not portable, however.
31585 	 * XXX: allow direct subtraction on known platforms.
31586 	 */
31587 #if 0
31588 	return (duk_int_t) (t2 - t1);
31589 #endif
31590 	return (duk_int_t) difftime(t2, t1);
31591 
31592  mktime_error:
31593 	/* XXX: return something more useful, so that caller can throw? */
31594 	DUK_D(DUK_DPRINT("mktime() failed, d=%lf", (double) d));
31595 	return 0;
31596 }
31597 #endif  /* DUK_USE_DATE_TZO_GMTIME */
31598 
31599 #if defined(DUK_USE_DATE_PRS_STRPTIME)
duk_bi_date_parse_string_strptime(duk_hthread * thr,const char * str)31600 DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr, const char *str) {
31601 	struct tm tm;
31602 	time_t t;
31603 	char buf[DUK__STRPTIME_BUF_SIZE];
31604 
31605 	/* Copy to buffer with slack to avoid Valgrind gripes from strptime. */
31606 	DUK_ASSERT(str != NULL);
31607 	duk_memzero(buf, sizeof(buf));  /* valgrind whine without this */
31608 	DUK_SNPRINTF(buf, sizeof(buf), "%s", (const char *) str);
31609 	buf[sizeof(buf) - 1] = (char) 0;
31610 
31611 	DUK_DDD(DUK_DDDPRINT("parsing: '%s'", (const char *) buf));
31612 
31613 	duk_memzero(&tm, sizeof(tm));
31614 	if (strptime((const char *) buf, "%c", &tm) != NULL) {
31615 		DUK_DDD(DUK_DDDPRINT("before mktime: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
31616 		                     "wday:%ld,yday:%ld,isdst:%ld}",
31617 		                     (long) tm.tm_sec, (long) tm.tm_min, (long) tm.tm_hour,
31618 		                     (long) tm.tm_mday, (long) tm.tm_mon, (long) tm.tm_year,
31619 		                     (long) tm.tm_wday, (long) tm.tm_yday, (long) tm.tm_isdst));
31620 		tm.tm_isdst = -1;  /* negative: dst info not available */
31621 
31622 		t = mktime(&tm);
31623 		DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
31624 		if (t >= 0) {
31625 			duk_push_number(thr, ((duk_double_t) t) * 1000.0);
31626 			return 1;
31627 		}
31628 	}
31629 
31630 	return 0;
31631 }
31632 #endif  /* DUK_USE_DATE_PRS_STRPTIME */
31633 
31634 #if defined(DUK_USE_DATE_PRS_GETDATE)
duk_bi_date_parse_string_getdate(duk_hthread * thr,const char * str)31635 DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const char *str) {
31636 	struct tm tm;
31637 	duk_small_int_t rc;
31638 	time_t t;
31639 
31640 	/* For this to work, DATEMSK must be set, so this is not very
31641 	 * convenient for an embeddable interpreter.
31642 	 */
31643 
31644 	duk_memzero(&tm, sizeof(struct tm));
31645 	rc = (duk_small_int_t) getdate_r(str, &tm);
31646 	DUK_DDD(DUK_DDDPRINT("getdate_r() -> %ld", (long) rc));
31647 
31648 	if (rc == 0) {
31649 		t = mktime(&tm);
31650 		DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
31651 		if (t >= 0) {
31652 			duk_push_number(thr, (duk_double_t) t);
31653 			return 1;
31654 		}
31655 	}
31656 
31657 	return 0;
31658 }
31659 #endif  /* DUK_USE_DATE_PRS_GETDATE */
31660 
31661 #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)31662 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) {
31663 	char buf[DUK__STRFTIME_BUF_SIZE];
31664 	struct tm tm;
31665 	const char *fmt;
31666 
31667 	DUK_UNREF(tzoffset);
31668 
31669 	/* If the platform doesn't support the entire ECMAScript range, we need
31670 	 * to return 0 so that the caller can fall back to the default formatter.
31671 	 *
31672 	 * For now, assume that if time_t is 8 bytes or more, the whole ECMAScript
31673 	 * range is supported.  For smaller time_t values (4 bytes in practice),
31674 	 * assumes that the signed 32-bit range is supported.
31675 	 *
31676 	 * XXX: detect this more correctly per platform.  The size of time_t is
31677 	 * probably not an accurate guarantee of strftime() supporting or not
31678 	 * supporting a large time range (the full ECMAScript range).
31679 	 */
31680 	if (sizeof(time_t) < 8 &&
31681 	    (parts[DUK_DATE_IDX_YEAR] < 1970 || parts[DUK_DATE_IDX_YEAR] > 2037)) {
31682 		/* be paranoid for 32-bit time values (even avoiding negative ones) */
31683 		return 0;
31684 	}
31685 
31686 	duk_memzero(&tm, sizeof(tm));
31687 	tm.tm_sec = parts[DUK_DATE_IDX_SECOND];
31688 	tm.tm_min = parts[DUK_DATE_IDX_MINUTE];
31689 	tm.tm_hour = parts[DUK_DATE_IDX_HOUR];
31690 	tm.tm_mday = parts[DUK_DATE_IDX_DAY];       /* already one-based */
31691 	tm.tm_mon = parts[DUK_DATE_IDX_MONTH] - 1;  /* one-based -> zero-based */
31692 	tm.tm_year = parts[DUK_DATE_IDX_YEAR] - 1900;
31693 	tm.tm_wday = parts[DUK_DATE_IDX_WEEKDAY];
31694 	tm.tm_isdst = 0;
31695 
31696 	duk_memzero(buf, sizeof(buf));
31697 	if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
31698 		fmt = "%c";
31699 	} else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
31700 		fmt = "%x";
31701 	} else {
31702 		DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);
31703 		fmt = "%X";
31704 	}
31705 	(void) strftime(buf, sizeof(buf) - 1, fmt, &tm);
31706 	DUK_ASSERT(buf[sizeof(buf) - 1] == 0);
31707 
31708 	duk_push_string(thr, buf);
31709 	return 1;
31710 }
31711 #endif  /* DUK_USE_DATE_FMT_STRFTIME */
31712 
31713 #if defined(DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME)
duk_bi_date_get_monotonic_time_clock_gettime(void)31714 DUK_INTERNAL duk_double_t duk_bi_date_get_monotonic_time_clock_gettime(void) {
31715 	struct timespec ts;
31716 
31717 	if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
31718 		return (duk_double_t) ts.tv_sec * 1000.0 + (duk_double_t) ts.tv_nsec / 1000000.0;
31719 	} else {
31720 		DUK_D(DUK_DPRINT("clock_gettime(CLOCK_MONOTONIC) failed"));
31721 		return 0.0;
31722 	}
31723 }
31724 #endif
31725 
31726 /* automatic undefs */
31727 #undef DUK__STRFTIME_BUF_SIZE
31728 #undef DUK__STRPTIME_BUF_SIZE
31729 #line 1 "duk_bi_date_windows.c"
31730 /*
31731  *  Windows Date providers
31732  *
31733  *  Platform specific links:
31734  *
31735  *    - http://msdn.microsoft.com/en-us/library/windows/desktop/ms725473(v=vs.85).aspx
31736  */
31737 
31738 /* #include duk_internal.h -> already included */
31739 
31740 /* The necessary #includes are in place in duk_config.h. */
31741 
31742 #if defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS)
31743 /* Shared Windows helpers. */
duk__convert_systime_to_ularge(const SYSTEMTIME * st,ULARGE_INTEGER * res)31744 DUK_LOCAL void duk__convert_systime_to_ularge(const SYSTEMTIME *st, ULARGE_INTEGER *res) {
31745 	FILETIME ft;
31746 	if (SystemTimeToFileTime(st, &ft) == 0) {
31747 		DUK_D(DUK_DPRINT("SystemTimeToFileTime() failed, returning 0"));
31748 		res->QuadPart = 0;
31749 	} else {
31750 		res->LowPart = ft.dwLowDateTime;
31751 		res->HighPart = ft.dwHighDateTime;
31752 	}
31753 }
31754 
31755 #if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
duk__convert_filetime_to_ularge(const FILETIME * ft,ULARGE_INTEGER * res)31756 DUK_LOCAL void duk__convert_filetime_to_ularge(const FILETIME *ft, ULARGE_INTEGER *res) {
31757 	res->LowPart = ft->dwLowDateTime;
31758 	res->HighPart = ft->dwHighDateTime;
31759 }
31760 #endif  /* DUK_USE_DATE_NOW_WINDOWS_SUBMS */
31761 
duk__set_systime_jan1970(SYSTEMTIME * st)31762 DUK_LOCAL void duk__set_systime_jan1970(SYSTEMTIME *st) {
31763 	duk_memzero((void *) st, sizeof(*st));
31764 	st->wYear = 1970;
31765 	st->wMonth = 1;
31766 	st->wDayOfWeek = 4;  /* not sure whether or not needed; Thursday */
31767 	st->wDay = 1;
31768 	DUK_ASSERT(st->wHour == 0);
31769 	DUK_ASSERT(st->wMinute == 0);
31770 	DUK_ASSERT(st->wSecond == 0);
31771 	DUK_ASSERT(st->wMilliseconds == 0);
31772 }
31773 #endif  /* defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) */
31774 
31775 #if defined(DUK_USE_DATE_NOW_WINDOWS)
duk_bi_date_get_now_windows(void)31776 DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows(void) {
31777 	/* Suggested step-by-step method from documentation of RtlTimeToSecondsSince1970:
31778 	 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724928(v=vs.85).aspx
31779 	 */
31780 	SYSTEMTIME st1, st2;
31781 	ULARGE_INTEGER tmp1, tmp2;
31782 
31783 	GetSystemTime(&st1);
31784 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
31785 
31786 	duk__set_systime_jan1970(&st2);
31787 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
31788 
31789 	/* Difference is in 100ns units, convert to milliseconds, keeping
31790 	 * fractions since Duktape 2.2.0.  This is only theoretical because
31791 	 * SYSTEMTIME is limited to milliseconds.
31792 	 */
31793 	return (duk_double_t) ((LONGLONG) tmp1.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000.0;
31794 }
31795 #endif  /* DUK_USE_DATE_NOW_WINDOWS */
31796 
31797 #if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
duk_bi_date_get_now_windows_subms(void)31798 DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows_subms(void) {
31799 	/* Variant of the basic algorithm using GetSystemTimePreciseAsFileTime()
31800 	 * for more accuracy.
31801 	 */
31802 	FILETIME ft1;
31803 	SYSTEMTIME st2;
31804 	ULARGE_INTEGER tmp1, tmp2;
31805 
31806 	GetSystemTimePreciseAsFileTime(&ft1);
31807 	duk__convert_filetime_to_ularge((const FILETIME *) &ft1, &tmp1);
31808 
31809 	duk__set_systime_jan1970(&st2);
31810 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
31811 
31812 	/* Difference is in 100ns units, convert to milliseconds, keeping
31813 	 * fractions since Duktape 2.2.0.
31814 	 */
31815 	return (duk_double_t) ((LONGLONG) tmp1.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000.0;
31816 }
31817 #endif  /* DUK_USE_DATE_NOW_WINDOWS */
31818 
31819 #if defined(DUK_USE_DATE_TZO_WINDOWS)
duk_bi_date_get_local_tzoffset_windows(duk_double_t d)31820 DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) {
31821 	SYSTEMTIME st1;
31822 	SYSTEMTIME st2;
31823 	SYSTEMTIME st3;
31824 	ULARGE_INTEGER tmp1;
31825 	ULARGE_INTEGER tmp2;
31826 	ULARGE_INTEGER tmp3;
31827 	FILETIME ft1;
31828 	BOOL ret;
31829 
31830 	/* XXX: handling of timestamps outside Windows supported range.
31831 	 * How does Windows deal with dates before 1600?  Does windows
31832 	 * support all ECMAScript years (like -200000 and +200000)?
31833 	 * Should equivalent year mapping be used here too?  If so, use
31834 	 * a shared helper (currently integrated into timeval-to-parts).
31835 	 */
31836 
31837 	/* Use the approach described in "Remarks" of FileTimeToLocalFileTime:
31838 	 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277(v=vs.85).aspx
31839 	 */
31840 
31841 	duk__set_systime_jan1970(&st1);
31842 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
31843 	tmp2.QuadPart = (ULONGLONG) (d * 10000.0);  /* millisec -> 100ns units since jan 1, 1970 */
31844 	tmp2.QuadPart += tmp1.QuadPart;             /* input 'd' in Windows UTC, 100ns units */
31845 
31846 	ft1.dwLowDateTime = tmp2.LowPart;
31847 	ft1.dwHighDateTime = tmp2.HighPart;
31848 	ret = FileTimeToSystemTime((const FILETIME *) &ft1, &st2);
31849 	if (!ret) {
31850 		DUK_D(DUK_DPRINT("FileTimeToSystemTime() failed, return tzoffset 0"));
31851 		return 0;
31852 	}
31853 	if (SystemTimeToTzSpecificLocalTime((LPTIME_ZONE_INFORMATION) NULL, &st2, &st3) == 0) {
31854 		DUK_D(DUK_DPRINT("SystemTimeToTzSpecificLocalTime() failed, return tzoffset 0"));
31855 		return 0;
31856 	}
31857 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st3, &tmp3);
31858 
31859 	/* Positive if local time ahead of UTC. */
31860 	return (duk_int_t) (((LONGLONG) tmp3.QuadPart - (LONGLONG) tmp2.QuadPart) / DUK_I64_CONSTANT(10000000));  /* seconds */
31861 }
31862 #endif  /* DUK_USE_DATE_TZO_WINDOWS */
31863 
31864 #if defined(DUK_USE_DATE_TZO_WINDOWS_NO_DST)
duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d)31865 DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d) {
31866 	SYSTEMTIME st1;
31867 	SYSTEMTIME st2;
31868 	FILETIME ft1;
31869 	FILETIME ft2;
31870 	ULARGE_INTEGER tmp1;
31871 	ULARGE_INTEGER tmp2;
31872 	BOOL ret;
31873 
31874 	/* Do a similar computation to duk_bi_date_get_local_tzoffset_windows
31875 	 * but without accounting for daylight savings time.  Use this on
31876 	 * Windows platforms (like Durango) that don't support the
31877 	 * SystemTimeToTzSpecificLocalTime() call.
31878 	 */
31879 
31880 	/* current time not needed for this computation */
31881 	DUK_UNREF(d);
31882 
31883 	duk__set_systime_jan1970(&st1);
31884 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
31885 
31886 	ft1.dwLowDateTime = tmp1.LowPart;
31887 	ft1.dwHighDateTime = tmp1.HighPart;
31888 	ret = FileTimeToLocalFileTime((const FILETIME *) &ft1, &ft2);
31889 	if (!ret) {
31890 		DUK_D(DUK_DPRINT("FileTimeToLocalFileTime() failed, return tzoffset 0"));
31891 		return 0;
31892 	}
31893 
31894 	ret = FileTimeToSystemTime((const FILETIME *) &ft2, &st2);
31895 	if (!ret) {
31896 		DUK_D(DUK_DPRINT("FileTimeToSystemTime() failed, return tzoffset 0"));
31897 		return 0;
31898 	}
31899 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
31900 
31901 	return (duk_int_t) (((LONGLONG) tmp2.QuadPart - (LONGLONG) tmp1.QuadPart) / DUK_I64_CONSTANT(10000000));  /* seconds */
31902 }
31903 #endif  /* DUK_USE_DATE_TZO_WINDOWS_NO_DST */
31904 
31905 #if defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC)
duk_bi_date_get_monotonic_time_windows_qpc(void)31906 DUK_INTERNAL duk_double_t duk_bi_date_get_monotonic_time_windows_qpc(void) {
31907 	LARGE_INTEGER count, freq;
31908 
31909 	/* There are legacy issues with QueryPerformanceCounter():
31910 	 * - Potential jumps: https://support.microsoft.com/en-us/help/274323/performance-counter-value-may-unexpectedly-leap-forward
31911 	 * - Differences between cores (XP): https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx#qpc_support_in_windows_versions
31912 	 *
31913 	 * We avoid these by enabling QPC by default only for Vista or later.
31914 	 */
31915 
31916 	if (QueryPerformanceCounter(&count) && QueryPerformanceFrequency(&freq)) {
31917 		/* XXX: QueryPerformanceFrequency() can be cached */
31918 		return (duk_double_t) count.QuadPart / (duk_double_t) freq.QuadPart * 1000.0;
31919 	} else {
31920 		/* MSDN: "On systems that run Windows XP or later, the function
31921 		 * will always succeed and will thus never return zero."
31922 		 * Provide minimal error path just in case user enables this
31923 		 * feature in pre-XP Windows.
31924 		 */
31925 		return 0.0;
31926 	}
31927 }
31928 #endif  /* DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC */
31929 #line 1 "duk_bi_duktape.c"
31930 /*
31931  *  Duktape built-ins
31932  *
31933  *  Size optimization note: it might seem that vararg multipurpose functions
31934  *  like fin(), enc(), and dec() are not very size optimal, but using a single
31935  *  user-visible ECMAScript function saves a lot of run-time footprint; each
31936  *  Function instance takes >100 bytes.  Using a shared native helper and a
31937  *  'magic' value won't save much if there are multiple Function instances
31938  *  anyway.
31939  */
31940 
31941 /* #include duk_internal.h -> already included */
31942 
31943 #if defined(DUK_USE_DUKTAPE_BUILTIN)
31944 
duk_bi_duktape_object_info(duk_hthread * thr)31945 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_info(duk_hthread *thr) {
31946 	duk_inspect_value(thr, -1);
31947 	return 1;
31948 }
31949 
duk_bi_duktape_object_act(duk_hthread * thr)31950 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_act(duk_hthread *thr) {
31951 	duk_int_t level;
31952 
31953 	level = duk_to_int(thr, 0);
31954 	duk_inspect_callstack_entry(thr, level);
31955 	return 1;
31956 }
31957 
duk_bi_duktape_object_gc(duk_hthread * thr)31958 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_gc(duk_hthread *thr) {
31959 	duk_small_uint_t flags;
31960 
31961 	flags = (duk_small_uint_t) duk_get_uint(thr, 0);
31962 	duk_heap_mark_and_sweep(thr->heap, flags);
31963 
31964 	/* XXX: Not sure what the best return value would be in the API.
31965 	 * Return true for now.
31966 	 */
31967 	duk_push_true(thr);
31968 	return 1;
31969 }
31970 
31971 #if defined(DUK_USE_FINALIZER_SUPPORT)
duk_bi_duktape_object_fin(duk_hthread * thr)31972 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_fin(duk_hthread *thr) {
31973 	(void) duk_require_hobject(thr, 0);
31974 	if (duk_get_top(thr) >= 2) {
31975 		/* Set: currently a finalizer is disabled by setting it to
31976 		 * undefined; this does not remove the property at the moment.
31977 		 * The value could be type checked to be either a function
31978 		 * or something else; if something else, the property could
31979 		 * be deleted.  Must use duk_set_finalizer() to keep
31980 		 * DUK_HOBJECT_FLAG_HAVE_FINALIZER in sync.
31981 		 */
31982 		duk_set_top(thr, 2);
31983 		duk_set_finalizer(thr, 0);
31984 		return 0;
31985 	} else {
31986 		/* Get. */
31987 		DUK_ASSERT(duk_get_top(thr) == 1);
31988 		duk_get_finalizer(thr, 0);
31989 		return 1;
31990 	}
31991 }
31992 #endif  /* DUK_USE_FINALIZER_SUPPORT */
31993 
duk_bi_duktape_object_enc(duk_hthread * thr)31994 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_enc(duk_hthread *thr) {
31995 	duk_hstring *h_str;
31996 
31997 	/* Vararg function: must be careful to check/require arguments.
31998 	 * The JSON helpers accept invalid indices and treat them like
31999 	 * non-existent optional parameters.
32000 	 */
32001 
32002 	h_str = duk_require_hstring(thr, 0);  /* Could reject symbols, but no point: won't match comparisons. */
32003 	duk_require_valid_index(thr, 1);
32004 
32005 	if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
32006 		duk_set_top(thr, 2);
32007 		duk_hex_encode(thr, 1);
32008 		DUK_ASSERT_TOP(thr, 2);
32009 	} else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
32010 		duk_set_top(thr, 2);
32011 		duk_base64_encode(thr, 1);
32012 		DUK_ASSERT_TOP(thr, 2);
32013 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)
32014 	} else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
32015 		duk_bi_json_stringify_helper(thr,
32016 		                             1 /*idx_value*/,
32017 		                             2 /*idx_replacer*/,
32018 		                             3 /*idx_space*/,
32019 		                             DUK_JSON_FLAG_EXT_CUSTOM |
32020 		                             DUK_JSON_FLAG_ASCII_ONLY |
32021 		                             DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
32022 #endif
32023 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
32024 	} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
32025 		duk_bi_json_stringify_helper(thr,
32026 		                             1 /*idx_value*/,
32027 		                             2 /*idx_replacer*/,
32028 		                             3 /*idx_space*/,
32029 		                             DUK_JSON_FLAG_EXT_COMPATIBLE |
32030 		                             DUK_JSON_FLAG_ASCII_ONLY /*flags*/);
32031 #endif
32032 	} else {
32033 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
32034 	}
32035 	return 1;
32036 }
32037 
duk_bi_duktape_object_dec(duk_hthread * thr)32038 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_dec(duk_hthread *thr) {
32039 	duk_hstring *h_str;
32040 
32041 	/* Vararg function: must be careful to check/require arguments.
32042 	 * The JSON helpers accept invalid indices and treat them like
32043 	 * non-existent optional parameters.
32044 	 */
32045 
32046 	h_str = duk_require_hstring(thr, 0);  /* Could reject symbols, but no point: won't match comparisons */
32047 	duk_require_valid_index(thr, 1);
32048 
32049 	if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
32050 		duk_set_top(thr, 2);
32051 		duk_hex_decode(thr, 1);
32052 		DUK_ASSERT_TOP(thr, 2);
32053 	} else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
32054 		duk_set_top(thr, 2);
32055 		duk_base64_decode(thr, 1);
32056 		DUK_ASSERT_TOP(thr, 2);
32057 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)
32058 	} else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
32059 		duk_bi_json_parse_helper(thr,
32060 		                         1 /*idx_value*/,
32061 		                         2 /*idx_replacer*/,
32062 		                         DUK_JSON_FLAG_EXT_CUSTOM /*flags*/);
32063 #endif
32064 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
32065 	} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
32066 		duk_bi_json_parse_helper(thr,
32067 		                         1 /*idx_value*/,
32068 		                         2 /*idx_replacer*/,
32069 		                         DUK_JSON_FLAG_EXT_COMPATIBLE /*flags*/);
32070 #endif
32071 	} else {
32072 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
32073 	}
32074 	return 1;
32075 }
32076 
32077 /*
32078  *  Compact an object
32079  */
32080 
duk_bi_duktape_object_compact(duk_hthread * thr)32081 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_compact(duk_hthread *thr) {
32082 	DUK_ASSERT_TOP(thr, 1);
32083 	duk_compact(thr, 0);
32084 	return 1;  /* return the argument object */
32085 }
32086 
32087 #endif  /* DUK_USE_DUKTAPE_BUILTIN */
32088 #line 1 "duk_bi_encoding.c"
32089 /*
32090  *  WHATWG Encoding API built-ins
32091  *
32092  *  API specification: https://encoding.spec.whatwg.org/#api
32093  *  Web IDL: https://www.w3.org/TR/WebIDL/
32094  */
32095 
32096 /* #include duk_internal.h -> already included */
32097 
32098 /*
32099  *  Data structures for encoding/decoding
32100  */
32101 
32102 typedef struct {
32103 	duk_uint8_t *out;      /* where to write next byte(s) */
32104 	duk_codepoint_t lead;  /* lead surrogate */
32105 } duk__encode_context;
32106 
32107 typedef struct {
32108 	/* UTF-8 decoding state */
32109 	duk_codepoint_t codepoint;  /* built up incrementally */
32110 	duk_uint8_t upper;          /* max value of next byte (decode error otherwise) */
32111 	duk_uint8_t lower;          /* min value of next byte (ditto) */
32112 	duk_uint8_t needed;         /* how many more bytes we need */
32113 	duk_uint8_t bom_handled;    /* BOM seen or no longer expected */
32114 
32115 	/* Decoder configuration */
32116 	duk_uint8_t fatal;
32117 	duk_uint8_t ignore_bom;
32118 } duk__decode_context;
32119 
32120 /* The signed duk_codepoint_t type is used to signal a decoded codepoint
32121  * (>= 0) or various other states using negative values.
32122  */
32123 #define DUK__CP_CONTINUE   (-1)  /* continue to next byte, no completed codepoint */
32124 #define DUK__CP_ERROR      (-2)  /* decoding error */
32125 #define DUK__CP_RETRY      (-3)  /* decoding error; retry last byte */
32126 
32127 /*
32128  *  Raw helpers for encoding/decoding
32129  */
32130 
32131 /* Emit UTF-8 (= CESU-8) encoded U+FFFD (replacement char), i.e. ef bf bd. */
duk__utf8_emit_repl(duk_uint8_t * ptr)32132 DUK_LOCAL duk_uint8_t *duk__utf8_emit_repl(duk_uint8_t *ptr) {
32133 	*ptr++ = 0xef;
32134 	*ptr++ = 0xbf;
32135 	*ptr++ = 0xbd;
32136 	return ptr;
32137 }
32138 
duk__utf8_decode_init(duk__decode_context * dec_ctx)32139 DUK_LOCAL void duk__utf8_decode_init(duk__decode_context *dec_ctx) {
32140 	/* (Re)init the decoding state of 'dec_ctx' but leave decoder
32141 	 * configuration fields untouched.
32142 	 */
32143 	dec_ctx->codepoint = 0x0000L;
32144 	dec_ctx->upper = 0xbf;
32145 	dec_ctx->lower = 0x80;
32146 	dec_ctx->needed = 0;
32147 	dec_ctx->bom_handled = 0;
32148 }
32149 
duk__utf8_decode_next(duk__decode_context * dec_ctx,duk_uint8_t x)32150 DUK_LOCAL duk_codepoint_t duk__utf8_decode_next(duk__decode_context *dec_ctx, duk_uint8_t x) {
32151 	/*
32152 	 *  UTF-8 algorithm based on the Encoding specification:
32153 	 *  https://encoding.spec.whatwg.org/#utf-8-decoder
32154 	 *
32155 	 *  Two main states: decoding initial byte vs. decoding continuation
32156 	 *  bytes.  Shortest length encoding is validated by restricting the
32157 	 *  allowed range of first continuation byte using 'lower' and 'upper'.
32158 	 */
32159 
32160 	if (dec_ctx->needed == 0) {
32161 		/* process initial byte */
32162 		if (x <= 0x7f) {
32163 			/* U+0000-U+007F, 1 byte (ASCII) */
32164 			return (duk_codepoint_t) x;
32165 		} else if (x >= 0xc2 && x <= 0xdf) {
32166 			/* U+0080-U+07FF, 2 bytes */
32167 			dec_ctx->needed = 1;
32168 			dec_ctx->codepoint = x & 0x1f;
32169 			DUK_ASSERT(dec_ctx->lower == 0x80);
32170 			DUK_ASSERT(dec_ctx->upper == 0xbf);
32171 			return DUK__CP_CONTINUE;
32172 		} else if (x >= 0xe0 && x <= 0xef) {
32173 			/* U+0800-U+FFFF, 3 bytes */
32174 			if (x == 0xe0) {
32175 				dec_ctx->lower = 0xa0;
32176 				DUK_ASSERT(dec_ctx->upper == 0xbf);
32177 			} else if (x == 0xed) {
32178 				DUK_ASSERT(dec_ctx->lower == 0x80);
32179 				dec_ctx->upper = 0x9f;
32180 			}
32181 			dec_ctx->needed = 2;
32182 			dec_ctx->codepoint = x & 0x0f;
32183 			return DUK__CP_CONTINUE;
32184 		} else if (x >= 0xf0 && x <= 0xf4) {
32185 			/* U+010000-U+10FFFF, 4 bytes */
32186 			if (x == 0xf0) {
32187 				dec_ctx->lower = 0x90;
32188 				DUK_ASSERT(dec_ctx->upper == 0xbf);
32189 			} else if (x == 0xf4) {
32190 				DUK_ASSERT(dec_ctx->lower == 0x80);
32191 				dec_ctx->upper = 0x8f;
32192 			}
32193 			dec_ctx->needed = 3;
32194 			dec_ctx->codepoint = x & 0x07;
32195 			return DUK__CP_CONTINUE;
32196 		} else {
32197 			/* not a legal initial byte */
32198 			return DUK__CP_ERROR;
32199 		}
32200 	} else {
32201 		/* process continuation byte */
32202 		if (x >= dec_ctx->lower && x <= dec_ctx->upper) {
32203 			dec_ctx->lower = 0x80;
32204 			dec_ctx->upper = 0xbf;
32205 			dec_ctx->codepoint = (dec_ctx->codepoint << 6) | (x & 0x3f);
32206 			if (--dec_ctx->needed > 0) {
32207 				/* need more bytes */
32208 				return DUK__CP_CONTINUE;
32209 			} else {
32210 				/* got a codepoint */
32211 				duk_codepoint_t ret;
32212 				DUK_ASSERT(dec_ctx->codepoint <= 0x10ffffL);  /* Decoding rules guarantee. */
32213 				ret = dec_ctx->codepoint;
32214 				dec_ctx->codepoint = 0x0000L;
32215 				dec_ctx->needed = 0;
32216 				return ret;
32217 			}
32218 		} else {
32219 			/* We just encountered an illegal UTF-8 continuation byte.  This might
32220 			 * be the initial byte of the next character; if we return a plain
32221 			 * error status and the decoder is in replacement mode, the character
32222 			 * will be masked.  We still need to alert the caller to the error
32223 			 * though.
32224 			 */
32225 			dec_ctx->codepoint = 0x0000L;
32226 			dec_ctx->needed = 0;
32227 			dec_ctx->lower = 0x80;
32228 			dec_ctx->upper = 0xbf;
32229 			return DUK__CP_RETRY;
32230 		}
32231 	}
32232 }
32233 
32234 #if defined(DUK_USE_ENCODING_BUILTINS)
duk__utf8_encode_char(void * udata,duk_codepoint_t codepoint)32235 DUK_LOCAL void duk__utf8_encode_char(void *udata, duk_codepoint_t codepoint) {
32236 	duk__encode_context *enc_ctx;
32237 
32238 	DUK_ASSERT(codepoint >= 0);
32239 	enc_ctx = (duk__encode_context *) udata;
32240 	DUK_ASSERT(enc_ctx != NULL);
32241 
32242 #if !defined(DUK_USE_PREFER_SIZE)
32243 	if (codepoint <= 0x7f && enc_ctx->lead == 0x0000L) {
32244 		/* Fast path for ASCII. */
32245 		*enc_ctx->out++ = (duk_uint8_t) codepoint;
32246 		return;
32247 	}
32248 #endif
32249 
32250 	if (DUK_UNLIKELY(codepoint > 0x10ffffL)) {
32251 		/* cannot legally encode in UTF-8 */
32252 		codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
32253 	} else if (codepoint >= 0xd800L && codepoint <= 0xdfffL) {
32254 		if (codepoint <= 0xdbffL) {
32255 			/* high surrogate */
32256 			duk_codepoint_t prev_lead = enc_ctx->lead;
32257 			enc_ctx->lead = codepoint;
32258 			if (prev_lead == 0x0000L) {
32259 				/* high surrogate, no output */
32260 				return;
32261 			} else {
32262 				/* consecutive high surrogates, consider first one unpaired */
32263 				codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
32264 			}
32265 		} else {
32266 			/* low surrogate */
32267 			if (enc_ctx->lead != 0x0000L) {
32268 				codepoint = (duk_codepoint_t) (0x010000L + ((enc_ctx->lead - 0xd800L) << 10) + (codepoint - 0xdc00L));
32269 				enc_ctx->lead = 0x0000L;
32270 			} else {
32271 				/* unpaired low surrogate */
32272 				DUK_ASSERT(enc_ctx->lead == 0x0000L);
32273 				codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
32274 			}
32275 		}
32276 	} else {
32277 		if (enc_ctx->lead != 0x0000L) {
32278 			/* unpaired high surrogate: emit replacement character and the input codepoint */
32279 			enc_ctx->lead = 0x0000L;
32280 			enc_ctx->out = duk__utf8_emit_repl(enc_ctx->out);
32281 		}
32282 	}
32283 
32284 	/* Codepoint may be original input, a decoded surrogate pair, or may
32285 	 * have been replaced with U+FFFD.
32286 	 */
32287 	enc_ctx->out += duk_unicode_encode_xutf8((duk_ucodepoint_t) codepoint, enc_ctx->out);
32288 }
32289 #endif  /* DUK_USE_ENCODING_BUILTINS */
32290 
32291 /* Shared helper for buffer-to-string using a TextDecoder() compatible UTF-8
32292  * decoder.
32293  */
duk__decode_helper(duk_hthread * thr,duk__decode_context * dec_ctx)32294 DUK_LOCAL duk_ret_t duk__decode_helper(duk_hthread *thr, duk__decode_context *dec_ctx) {
32295 	const duk_uint8_t *input;
32296 	duk_size_t len = 0;
32297 	duk_size_t len_tmp;
32298 	duk_bool_t stream = 0;
32299 	duk_codepoint_t codepoint;
32300 	duk_uint8_t *output;
32301 	const duk_uint8_t *in;
32302 	duk_uint8_t *out;
32303 
32304 	DUK_ASSERT(dec_ctx != NULL);
32305 
32306 	/* Careful with input buffer pointer: any side effects involving
32307 	 * code execution (e.g. getters, coercion calls, and finalizers)
32308 	 * may cause a resize and invalidate a pointer we've read.  This
32309 	 * is why the pointer is actually looked up at the last minute.
32310 	 * Argument validation must still happen first to match WHATWG
32311 	 * required side effect order.
32312 	 */
32313 
32314 	if (duk_is_undefined(thr, 0)) {
32315 		duk_push_fixed_buffer_nozero(thr, 0);
32316 		duk_replace(thr, 0);
32317 	}
32318 	(void) duk_require_buffer_data(thr, 0, &len);  /* Need 'len', avoid pointer. */
32319 
32320 	if (duk_check_type_mask(thr, 1, DUK_TYPE_MASK_UNDEFINED |
32321 	                                DUK_TYPE_MASK_NULL |
32322 	                                DUK_TYPE_MASK_NONE)) {
32323 		/* Use defaults, treat missing value like undefined. */
32324 	} else {
32325 		duk_require_type_mask(thr, 1, DUK_TYPE_MASK_UNDEFINED |
32326 	                                      DUK_TYPE_MASK_NULL |
32327 	                                      DUK_TYPE_MASK_LIGHTFUNC |
32328 	                                      DUK_TYPE_MASK_BUFFER |
32329 		                              DUK_TYPE_MASK_OBJECT);
32330 		if (duk_get_prop_literal(thr, 1, "stream")) {
32331 			stream = duk_to_boolean(thr, -1);
32332 		}
32333 	}
32334 
32335 	/* Allowance is 3*len in the general case because all bytes may potentially
32336 	 * become U+FFFD.  If the first byte completes a non-BMP codepoint it will
32337 	 * decode to a CESU-8 surrogate pair (6 bytes) so we allow 3 extra bytes to
32338 	 * compensate: (1*3)+3 = 6.  Non-BMP codepoints are safe otherwise because
32339 	 * the 4->6 expansion is well under the 3x allowance.
32340 	 *
32341 	 * XXX: As with TextEncoder, need a better buffer allocation strategy here.
32342 	 */
32343 	if (len >= (DUK_HBUFFER_MAX_BYTELEN / 3) - 3) {
32344 		DUK_ERROR_TYPE(thr, DUK_STR_RESULT_TOO_LONG);
32345 		DUK_WO_NORETURN(return 0;);
32346 	}
32347 	output = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, 3 + (3 * len));  /* used parts will be always manually written over */
32348 
32349 	input = (const duk_uint8_t *) duk_get_buffer_data(thr, 0, &len_tmp);
32350 	DUK_ASSERT(input != NULL || len == 0);
32351 	if (DUK_UNLIKELY(len != len_tmp)) {
32352 		/* Very unlikely but possible: source buffer was resized by
32353 		 * a side effect when fixed buffer was pushed.  Output buffer
32354 		 * may not be large enough to hold output, so just fail if
32355 		 * length has changed.
32356 		 */
32357 		DUK_D(DUK_DPRINT("input buffer resized by side effect, fail"));
32358 		goto fail_type;
32359 	}
32360 
32361 	/* From this point onwards it's critical that no side effect occur
32362 	 * which may disturb 'input': finalizer execution, property accesses,
32363 	 * active coercions, etc.  Even an allocation related mark-and-sweep
32364 	 * may affect the pointer because it may trigger a pending finalizer.
32365 	 */
32366 
32367 	in = input;
32368 	out = output;
32369 	while (in < input + len) {
32370 		codepoint = duk__utf8_decode_next(dec_ctx, *in++);
32371 		if (codepoint < 0) {
32372 			if (codepoint == DUK__CP_CONTINUE) {
32373 				continue;
32374 			}
32375 
32376 			/* Decoding error with or without retry. */
32377 			DUK_ASSERT(codepoint == DUK__CP_ERROR || codepoint == DUK__CP_RETRY);
32378 			if (codepoint == DUK__CP_RETRY) {
32379 				--in;  /* retry last byte */
32380 			}
32381 			/* replacement mode: replace with U+FFFD */
32382 			codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
32383 			if (dec_ctx->fatal) {
32384 				/* fatal mode: throw a TypeError */
32385 				goto fail_type;
32386 			}
32387 			/* Continue with 'codepoint', Unicode replacement. */
32388 		}
32389 		DUK_ASSERT(codepoint >= 0x0000L && codepoint <= 0x10ffffL);
32390 
32391 		if (!dec_ctx->bom_handled) {
32392 			dec_ctx->bom_handled = 1;
32393 			if (codepoint == 0xfeffL && !dec_ctx->ignore_bom) {
32394 				continue;
32395 			}
32396 		}
32397 
32398 		out += duk_unicode_encode_cesu8((duk_ucodepoint_t) codepoint, out);
32399 		DUK_ASSERT(out <= output + (3 + (3 * len)));
32400 	}
32401 
32402 	if (!stream) {
32403 		if (dec_ctx->needed != 0) {
32404 			/* truncated sequence at end of buffer */
32405 			if (dec_ctx->fatal) {
32406 				goto fail_type;
32407 			} else {
32408 				out += duk_unicode_encode_cesu8(DUK_UNICODE_CP_REPLACEMENT_CHARACTER, out);
32409 				DUK_ASSERT(out <= output + (3 + (3 * len)));
32410 			}
32411 		}
32412 		duk__utf8_decode_init(dec_ctx);  /* Initialize decoding state for potential reuse. */
32413 	}
32414 
32415 	/* Output buffer is fixed and thus stable even if there had been
32416 	 * side effects (which there shouldn't be).
32417 	 */
32418 	duk_push_lstring(thr, (const char *) output, (duk_size_t) (out - output));
32419 	return 1;
32420 
32421  fail_type:
32422 	DUK_ERROR_TYPE(thr, DUK_STR_UTF8_DECODE_FAILED);
32423 	DUK_WO_NORETURN(return 0;);
32424 }
32425 
32426 /*
32427  *  Built-in bindings
32428  */
32429 
32430 #if defined(DUK_USE_ENCODING_BUILTINS)
duk_bi_textencoder_constructor(duk_hthread * thr)32431 DUK_INTERNAL duk_ret_t duk_bi_textencoder_constructor(duk_hthread *thr) {
32432 	/* TextEncoder currently requires no persistent state, so the constructor
32433 	 * does nothing on purpose.
32434 	 */
32435 
32436 	duk_require_constructor_call(thr);
32437 	return 0;
32438 }
32439 
duk_bi_textencoder_prototype_encoding_getter(duk_hthread * thr)32440 DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_hthread *thr) {
32441 	duk_push_literal(thr, "utf-8");
32442 	return 1;
32443 }
32444 
duk_bi_textencoder_prototype_encode(duk_hthread * thr)32445 DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encode(duk_hthread *thr) {
32446 	duk__encode_context enc_ctx;
32447 	duk_size_t len;
32448 	duk_size_t final_len;
32449 	duk_uint8_t *output;
32450 
32451 	DUK_ASSERT_TOP(thr, 1);
32452 	if (duk_is_undefined(thr, 0)) {
32453 		len = 0;
32454 	} else {
32455 		duk_hstring *h_input;
32456 
32457 		h_input = duk_to_hstring(thr, 0);
32458 		DUK_ASSERT(h_input != NULL);
32459 
32460 		len = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_input);
32461 		if (len >= DUK_HBUFFER_MAX_BYTELEN / 3) {
32462 			DUK_ERROR_TYPE(thr, DUK_STR_RESULT_TOO_LONG);
32463 			DUK_WO_NORETURN(return 0;);
32464 		}
32465 	}
32466 
32467 	/* Allowance is 3*len because all bytes can potentially be replaced with
32468 	 * U+FFFD -- which rather inconveniently encodes to 3 bytes in UTF-8.
32469 	 * Rely on dynamic buffer data pointer stability: no other code has
32470 	 * access to the data pointer.
32471 	 *
32472 	 * XXX: The buffer allocation strategy used here is rather inefficient.
32473 	 * Maybe switch to a chunk-based strategy, or preprocess the string to
32474 	 * figure out the space needed ahead of time?
32475 	 */
32476 	DUK_ASSERT(3 * len >= len);
32477 	output = (duk_uint8_t *) duk_push_dynamic_buffer(thr, 3 * len);
32478 
32479 	if (len > 0) {
32480 		DUK_ASSERT(duk_is_string(thr, 0));  /* True if len > 0. */
32481 
32482 		/* XXX: duk_decode_string() is used to process the input
32483 		 * string.  For standard ECMAScript strings, represented
32484 		 * internally as CESU-8, this is fine.  However, behavior
32485 		 * beyond CESU-8 is not very strict: codepoints using an
32486 		 * extended form of UTF-8 are also accepted, and invalid
32487 		 * codepoint sequences (which are allowed in Duktape strings)
32488 		 * are not handled as well as they could (e.g. invalid
32489 		 * continuation bytes may mask following codepoints).
32490 		 * This is how ECMAScript code would also see such strings.
32491 		 * Maybe replace duk_decode_string() with an explicit strict
32492 		 * CESU-8 decoder here?
32493 		 */
32494 		enc_ctx.lead = 0x0000L;
32495 		enc_ctx.out = output;
32496 		duk_decode_string(thr, 0, duk__utf8_encode_char, (void *) &enc_ctx);
32497 		if (enc_ctx.lead != 0x0000L) {
32498 			/* unpaired high surrogate at end of string */
32499 			enc_ctx.out = duk__utf8_emit_repl(enc_ctx.out);
32500 			DUK_ASSERT(enc_ctx.out <= output + (3 * len));
32501 		}
32502 
32503 		/* The output buffer is usually very much oversized, so shrink it to
32504 		 * actually needed size.  Pointer stability assumed up to this point.
32505 		 */
32506 		DUK_ASSERT_TOP(thr, 2);
32507 		DUK_ASSERT(output == (duk_uint8_t *) duk_get_buffer_data(thr, -1, NULL));
32508 
32509 		final_len = (duk_size_t) (enc_ctx.out - output);
32510 		duk_resize_buffer(thr, -1, final_len);
32511 		/* 'output' and 'enc_ctx.out' are potentially invalidated by the resize. */
32512 	} else {
32513 		final_len = 0;
32514 	}
32515 
32516 	/* Standard WHATWG output is a Uint8Array.  Here the Uint8Array will
32517 	 * be backed by a dynamic buffer which differs from e.g. Uint8Arrays
32518 	 * created as 'new Uint8Array(N)'.  ECMAScript code won't see the
32519 	 * difference but C code will.  When bufferobjects are not supported,
32520 	 * returns a plain dynamic buffer.
32521 	 */
32522 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
32523 	duk_push_buffer_object(thr, -1, 0, final_len, DUK_BUFOBJ_UINT8ARRAY);
32524 #endif
32525 	return 1;
32526 }
32527 
duk_bi_textdecoder_constructor(duk_hthread * thr)32528 DUK_INTERNAL duk_ret_t duk_bi_textdecoder_constructor(duk_hthread *thr) {
32529 	duk__decode_context *dec_ctx;
32530 	duk_bool_t fatal = 0;
32531 	duk_bool_t ignore_bom = 0;
32532 
32533 	DUK_ASSERT_TOP(thr, 2);
32534 	duk_require_constructor_call(thr);
32535 	if (!duk_is_undefined(thr, 0)) {
32536 		/* XXX: For now ignore 'label' (encoding identifier). */
32537 		duk_to_string(thr, 0);
32538 	}
32539 	if (!duk_is_null_or_undefined(thr, 1)) {
32540 		if (duk_get_prop_literal(thr, 1, "fatal")) {
32541 			fatal = duk_to_boolean(thr, -1);
32542 		}
32543 		if (duk_get_prop_literal(thr, 1, "ignoreBOM")) {
32544 			ignore_bom = duk_to_boolean(thr, -1);
32545 		}
32546 	}
32547 
32548 	duk_push_this(thr);
32549 
32550 	/* The decode context is not assumed to be zeroed; all fields are
32551 	 * initialized explicitly.
32552 	 */
32553 	dec_ctx = (duk__decode_context *) duk_push_fixed_buffer(thr, sizeof(duk__decode_context));
32554 	dec_ctx->fatal = (duk_uint8_t) fatal;
32555 	dec_ctx->ignore_bom = (duk_uint8_t) ignore_bom;
32556 	duk__utf8_decode_init(dec_ctx);  /* Initializes remaining fields. */
32557 
32558 	duk_put_prop_literal(thr, -2, DUK_INTERNAL_SYMBOL("Context"));
32559 	return 0;
32560 }
32561 
32562 /* Get TextDecoder context from 'this'; leaves garbage on stack. */
duk__get_textdecoder_context(duk_hthread * thr)32563 DUK_LOCAL duk__decode_context *duk__get_textdecoder_context(duk_hthread *thr) {
32564 	duk__decode_context *dec_ctx;
32565 	duk_push_this(thr);
32566 	duk_get_prop_literal(thr, -1, DUK_INTERNAL_SYMBOL("Context"));
32567 	dec_ctx = (duk__decode_context *) duk_require_buffer(thr, -1, NULL);
32568 	DUK_ASSERT(dec_ctx != NULL);
32569 	return dec_ctx;
32570 }
32571 
duk_bi_textdecoder_prototype_shared_getter(duk_hthread * thr)32572 DUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_hthread *thr) {
32573 	duk__decode_context *dec_ctx;
32574 	duk_int_t magic;
32575 
32576 	dec_ctx = duk__get_textdecoder_context(thr);
32577 	magic = duk_get_current_magic(thr);
32578 	switch (magic) {
32579 	case 0:
32580 		/* Encoding is now fixed, so _Context lookup is only needed to
32581 		 * validate the 'this' binding (TypeError if not TextDecoder-like).
32582 		 */
32583 		duk_push_literal(thr, "utf-8");
32584 		break;
32585 	case 1:
32586 		duk_push_boolean(thr, dec_ctx->fatal);
32587 		break;
32588 	default:
32589 		duk_push_boolean(thr, dec_ctx->ignore_bom);
32590 		break;
32591 	}
32592 
32593 	return 1;
32594 }
32595 
duk_bi_textdecoder_prototype_decode(duk_hthread * thr)32596 DUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_hthread *thr) {
32597 	duk__decode_context *dec_ctx;
32598 
32599 	dec_ctx = duk__get_textdecoder_context(thr);
32600 	return duk__decode_helper(thr, dec_ctx);
32601 }
32602 #endif  /* DUK_USE_ENCODING_BUILTINS */
32603 
32604 /*
32605  *  Internal helper for Node.js Buffer
32606  */
32607 
32608 /* Internal helper used for Node.js Buffer .toString().  Value stack convention
32609  * is currently odd: it mimics TextDecoder .decode() so that argument must be at
32610  * index 0, and decode options (not present for Buffer) at index 1.  Return value
32611  * is a Duktape/C function return value.
32612  */
duk_textdecoder_decode_utf8_nodejs(duk_hthread * thr)32613 DUK_INTERNAL duk_ret_t duk_textdecoder_decode_utf8_nodejs(duk_hthread *thr) {
32614 	duk__decode_context dec_ctx;
32615 
32616 	dec_ctx.fatal = 0;  /* use replacement chars */
32617 	dec_ctx.ignore_bom = 1;  /* ignore BOMs (matches Node.js Buffer .toString()) */
32618 	duk__utf8_decode_init(&dec_ctx);
32619 
32620 	return duk__decode_helper(thr, &dec_ctx);
32621 }
32622 
32623 /* automatic undefs */
32624 #undef DUK__CP_CONTINUE
32625 #undef DUK__CP_ERROR
32626 #undef DUK__CP_RETRY
32627 #line 1 "duk_bi_error.c"
32628 /*
32629  *  Error built-ins
32630  */
32631 
32632 /* #include duk_internal.h -> already included */
32633 
duk_bi_error_constructor_shared(duk_hthread * thr)32634 DUK_INTERNAL duk_ret_t duk_bi_error_constructor_shared(duk_hthread *thr) {
32635 	/* Behavior for constructor and non-constructor call is
32636 	 * the same except for augmenting the created error.  When
32637 	 * called as a constructor, the caller (duk_new()) will handle
32638 	 * augmentation; when called as normal function, we need to do
32639 	 * it here.
32640 	 */
32641 
32642 	duk_small_int_t bidx_prototype = duk_get_current_magic(thr);
32643 
32644 	/* same for both error and each subclass like TypeError */
32645 	duk_uint_t flags_and_class = DUK_HOBJECT_FLAG_EXTENSIBLE |
32646 	                             DUK_HOBJECT_FLAG_FASTREFS |
32647 	                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR);
32648 
32649 	(void) duk_push_object_helper(thr, flags_and_class, bidx_prototype);
32650 
32651 	/* If message is undefined, the own property 'message' is not set at
32652 	 * all to save property space.  An empty message is inherited anyway.
32653 	 */
32654 	if (!duk_is_undefined(thr, 0)) {
32655 		duk_to_string(thr, 0);
32656 		duk_dup_0(thr);  /* [ message error message ] */
32657 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
32658 	}
32659 
32660 	/* Augment the error if called as a normal function.  __FILE__ and __LINE__
32661 	 * are not desirable in this case.
32662 	 */
32663 
32664 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
32665 	if (!duk_is_constructor_call(thr)) {
32666 		duk_err_augment_error_create(thr, thr, NULL, 0, DUK_AUGMENT_FLAG_NOBLAME_FILELINE);
32667 	}
32668 #endif
32669 
32670 	return 1;
32671 }
32672 
duk_bi_error_prototype_to_string(duk_hthread * thr)32673 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_hthread *thr) {
32674 	/* XXX: optimize with more direct internal access */
32675 
32676 	duk_push_this(thr);
32677 	(void) duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
32678 
32679 	/* [ ... this ] */
32680 
32681 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME);
32682 	if (duk_is_undefined(thr, -1)) {
32683 		duk_pop(thr);
32684 		duk_push_literal(thr, "Error");
32685 	} else {
32686 		duk_to_string(thr, -1);
32687 	}
32688 
32689 	/* [ ... this name ] */
32690 
32691 	/* XXX: Are steps 6 and 7 in E5 Section 15.11.4.4 duplicated by
32692 	 * accident or are they actually needed?  The first ToString()
32693 	 * could conceivably return 'undefined'.
32694 	 */
32695 	duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE);
32696 	if (duk_is_undefined(thr, -1)) {
32697 		duk_pop(thr);
32698 		duk_push_hstring_empty(thr);
32699 	} else {
32700 		duk_to_string(thr, -1);
32701 	}
32702 
32703 	/* [ ... this name message ] */
32704 
32705 	if (duk_get_length(thr, -2) == 0) {
32706 		/* name is empty -> return message */
32707 		return 1;
32708 	}
32709 	if (duk_get_length(thr, -1) == 0) {
32710 		/* message is empty -> return name */
32711 		duk_pop(thr);
32712 		return 1;
32713 	}
32714 	duk_push_literal(thr, ": ");
32715 	duk_insert(thr, -2);  /* ... name ': ' message */
32716 	duk_concat(thr, 3);
32717 
32718 	return 1;
32719 }
32720 
32721 #if defined(DUK_USE_TRACEBACKS)
32722 
32723 /*
32724  *  Traceback handling
32725  *
32726  *  The unified helper decodes the traceback and produces various requested
32727  *  outputs.  It should be optimized for size, and may leave garbage on stack,
32728  *  only the topmost return value matters.  For instance, traceback separator
32729  *  and decoded strings are pushed even when looking for filename only.
32730  *
32731  *  NOTE: although _Tracedata is an internal property, user code can currently
32732  *  write to the array (or replace it with something other than an array).
32733  *  The code below must tolerate arbitrary _Tracedata.  It can throw errors
32734  *  etc, but cannot cause a segfault or memory unsafe behavior.
32735  */
32736 
32737 /* constants arbitrary, chosen for small loads */
32738 #define DUK__OUTPUT_TYPE_TRACEBACK   (-1)
32739 #define DUK__OUTPUT_TYPE_FILENAME    0
32740 #define DUK__OUTPUT_TYPE_LINENUMBER  1
32741 
duk__error_getter_helper(duk_hthread * thr,duk_small_int_t output_type)32742 DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_hthread *thr, duk_small_int_t output_type) {
32743 	duk_idx_t idx_td;
32744 	duk_small_int_t i;  /* traceback depth fits into 16 bits */
32745 	duk_small_int_t t;  /* stack type fits into 16 bits */
32746 	duk_small_int_t count_func = 0;  /* traceback depth ensures fits into 16 bits */
32747 	const char *str_tailcall = " tailcall";
32748 	const char *str_strict = " strict";
32749 	const char *str_construct = " construct";
32750 	const char *str_prevyield = " preventsyield";
32751 	const char *str_directeval = " directeval";
32752 	const char *str_empty = "";
32753 
32754 	DUK_ASSERT_TOP(thr, 0);  /* fixed arg count */
32755 
32756 	duk_push_this(thr);
32757 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_TRACEDATA);
32758 	idx_td = duk_get_top_index(thr);
32759 
32760 	duk_push_hstring_stridx(thr, DUK_STRIDX_NEWLINE_4SPACE);
32761 	duk_push_this(thr);
32762 
32763 	/* [ ... this tracedata sep this ] */
32764 
32765 	/* XXX: skip null filename? */
32766 
32767 	if (duk_check_type(thr, idx_td, DUK_TYPE_OBJECT)) {
32768 		/* Current tracedata contains 2 entries per callstack entry. */
32769 		for (i = 0; ; i += 2) {
32770 			duk_int_t pc;
32771 			duk_uint_t line;
32772 			duk_uint_t flags;
32773 			duk_double_t d;
32774 			const char *funcname;
32775 			const char *filename;
32776 			duk_hobject *h_func;
32777 			duk_hstring *h_name;
32778 
32779 			duk_require_stack(thr, 5);
32780 			duk_get_prop_index(thr, idx_td, (duk_uarridx_t) i);
32781 			duk_get_prop_index(thr, idx_td, (duk_uarridx_t) (i + 1));
32782 			d = duk_to_number_m1(thr);
32783 			pc = duk_double_to_int_t(DUK_FMOD(d, DUK_DOUBLE_2TO32));
32784 			flags = duk_double_to_uint_t(DUK_FLOOR(d / DUK_DOUBLE_2TO32));
32785 			t = (duk_small_int_t) duk_get_type(thr, -2);
32786 
32787 			if (t == DUK_TYPE_OBJECT || t == DUK_TYPE_LIGHTFUNC) {
32788 				/*
32789 				 *  ECMAScript/native function call or lightfunc call
32790 				 */
32791 
32792 				count_func++;
32793 
32794 				/* [ ... v1(func) v2(pc+flags) ] */
32795 
32796 				/* These may be systematically omitted by Duktape
32797 				 * with certain config options, but allow user to
32798 				 * set them on a case-by-case basis.
32799 				 */
32800 				duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);
32801 				duk_get_prop_stridx_short(thr, -3, DUK_STRIDX_FILE_NAME);
32802 
32803 #if defined(DUK_USE_PC2LINE)
32804 				line = (duk_uint_t) duk_hobject_pc2line_query(thr, -4, (duk_uint_fast32_t) pc);
32805 #else
32806 				line = 0;
32807 #endif
32808 
32809 				/* [ ... v1 v2 name filename ] */
32810 
32811 				/* When looking for .fileName/.lineNumber, blame first
32812 				 * function which has a .fileName.
32813 				 */
32814 				if (duk_is_string_notsymbol(thr, -1)) {
32815 					if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
32816 						return 1;
32817 					} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
32818 						duk_push_uint(thr, line);
32819 						return 1;
32820 					}
32821 				}
32822 
32823 				/* XXX: Change 'anon' handling here too, to use empty string for anonymous functions? */
32824 				/* XXX: Could be improved by coercing to a readable duk_tval (especially string escaping) */
32825 				h_name = duk_get_hstring_notsymbol(thr, -2);  /* may be NULL */
32826 				funcname = (h_name == NULL || h_name == DUK_HTHREAD_STRING_EMPTY_STRING(thr)) ?
32827 				           "[anon]" : (const char *) DUK_HSTRING_GET_DATA(h_name);
32828 				filename = duk_get_string_notsymbol(thr, -1);
32829 				filename = filename ? filename : "";
32830 				DUK_ASSERT(funcname != NULL);
32831 				DUK_ASSERT(filename != NULL);
32832 
32833 				h_func = duk_get_hobject(thr, -4);  /* NULL for lightfunc */
32834 
32835 				if (h_func == NULL) {
32836 					duk_push_sprintf(thr, "at %s light%s%s%s%s%s",
32837 					                 (const char *) funcname,
32838 					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
32839 					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
32840 					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
32841 					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
32842 					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
32843 				} else if (DUK_HOBJECT_HAS_NATFUNC(h_func)) {
32844 					duk_push_sprintf(thr, "at %s (%s) native%s%s%s%s%s",
32845 					                 (const char *) funcname,
32846 					                 (const char *) filename,
32847 					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
32848 					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
32849 					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
32850 					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
32851 					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
32852 				} else {
32853 					duk_push_sprintf(thr, "at %s (%s:%lu)%s%s%s%s%s",
32854 					                 (const char *) funcname,
32855 					                 (const char *) filename,
32856 					                 (unsigned long) line,
32857 					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
32858 					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
32859 					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
32860 					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
32861 					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
32862 				}
32863 				duk_replace(thr, -5);   /* [ ... v1 v2 name filename str ] -> [ ... str v2 name filename ] */
32864 				duk_pop_3(thr);         /* -> [ ... str ] */
32865 			} else if (t == DUK_TYPE_STRING) {
32866 				const char *str_file;
32867 
32868 				/*
32869 				 *  __FILE__ / __LINE__ entry, here 'pc' is line number directly.
32870 				 *  Sometimes __FILE__ / __LINE__ is reported as the source for
32871 				 *  the error (fileName, lineNumber), sometimes not.
32872 				 */
32873 
32874 				/* [ ... v1(filename) v2(line+flags) ] */
32875 
32876 				/* When looking for .fileName/.lineNumber, blame compilation
32877 				 * or C call site unless flagged not to do so.
32878 				 */
32879 				if (!(flags & DUK_TB_FLAG_NOBLAME_FILELINE)) {
32880 					if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
32881 						duk_pop(thr);
32882 						return 1;
32883 					} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
32884 						duk_push_int(thr, pc);
32885 						return 1;
32886 					}
32887 				}
32888 
32889 				/* Tracedata is trusted but avoid any risk of using a NULL
32890 				 * for %s format because it has undefined behavior.  Symbols
32891 				 * don't need to be explicitly rejected as they pose no memory
32892 				 * safety issues.
32893 				 */
32894 				str_file = (const char *) duk_get_string(thr, -2);
32895 				duk_push_sprintf(thr, "at [anon] (%s:%ld) internal",
32896 				                 (const char *) (str_file ? str_file : "null"), (long) pc);
32897 				duk_replace(thr, -3);  /* [ ... v1 v2 str ] -> [ ... str v2 ] */
32898 				duk_pop(thr);          /* -> [ ... str ] */
32899 			} else {
32900 				/* unknown, ignore */
32901 				duk_pop_2(thr);
32902 				break;
32903 			}
32904 		}
32905 
32906 		if (count_func >= DUK_USE_TRACEBACK_DEPTH) {
32907 			/* Possibly truncated; there is no explicit truncation
32908 			 * marker so this is the best we can do.
32909 			 */
32910 
32911 			duk_push_hstring_stridx(thr, DUK_STRIDX_BRACKETED_ELLIPSIS);
32912 		}
32913 	}
32914 
32915 	/* [ ... this tracedata sep this str1 ... strN ] */
32916 
32917 	if (output_type != DUK__OUTPUT_TYPE_TRACEBACK) {
32918 		return 0;
32919 	} else {
32920 		/* The 'this' after 'sep' will get ToString() coerced by
32921 		 * duk_join() automatically.  We don't want to do that
32922 		 * coercion when providing .fileName or .lineNumber (GH-254).
32923 		 */
32924 		duk_join(thr, duk_get_top(thr) - (idx_td + 2) /*count, not including sep*/);
32925 		return 1;
32926 	}
32927 }
32928 
32929 /* XXX: Output type could be encoded into native function 'magic' value to
32930  * save space.  For setters the stridx could be encoded into 'magic'.
32931  */
32932 
duk_bi_error_prototype_stack_getter(duk_hthread * thr)32933 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_hthread *thr) {
32934 	return duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_TRACEBACK);
32935 }
32936 
duk_bi_error_prototype_filename_getter(duk_hthread * thr)32937 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_hthread *thr) {
32938 	return duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_FILENAME);
32939 }
32940 
duk_bi_error_prototype_linenumber_getter(duk_hthread * thr)32941 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_hthread *thr) {
32942 	return duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_LINENUMBER);
32943 }
32944 
32945 #else  /* DUK_USE_TRACEBACKS */
32946 
32947 /*
32948  *  Traceback handling when tracebacks disabled.
32949  *
32950  *  The fileName / lineNumber stubs are now necessary because built-in
32951  *  data will include the accessor properties in Error.prototype.  If those
32952  *  are removed for builds without tracebacks, these can also be removed.
32953  *  'stack' should still be present and produce a ToString() equivalent:
32954  *  this is useful for user code which prints a stacktrace and expects to
32955  *  see something useful.  A normal stacktrace also begins with a ToString()
32956  *  of the error so this makes sense.
32957  */
32958 
duk_bi_error_prototype_stack_getter(duk_hthread * thr)32959 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_hthread *thr) {
32960 	/* XXX: remove this native function and map 'stack' accessor
32961 	 * to the toString() implementation directly.
32962 	 */
32963 	return duk_bi_error_prototype_to_string(thr);
32964 }
32965 
duk_bi_error_prototype_filename_getter(duk_hthread * thr)32966 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_hthread *thr) {
32967 	DUK_UNREF(thr);
32968 	return 0;
32969 }
32970 
duk_bi_error_prototype_linenumber_getter(duk_hthread * thr)32971 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_hthread *thr) {
32972 	DUK_UNREF(thr);
32973 	return 0;
32974 }
32975 
32976 #endif  /* DUK_USE_TRACEBACKS */
32977 
duk__error_setter_helper(duk_hthread * thr,duk_small_uint_t stridx_key)32978 DUK_LOCAL duk_ret_t duk__error_setter_helper(duk_hthread *thr, duk_small_uint_t stridx_key) {
32979 	/* Attempt to write 'stack', 'fileName', 'lineNumber' works as if
32980 	 * user code called Object.defineProperty() to create an overriding
32981 	 * own property.  This allows user code to overwrite .fileName etc
32982 	 * intuitively as e.g. "err.fileName = 'dummy'" as one might expect.
32983 	 * See https://github.com/svaarala/duktape/issues/387.
32984 	 */
32985 
32986 	DUK_ASSERT_TOP(thr, 1);  /* fixed arg count: value */
32987 
32988 	duk_push_this(thr);
32989 	duk_push_hstring_stridx(thr, stridx_key);
32990 	duk_dup_0(thr);
32991 
32992 	/* [ ... obj key value ] */
32993 
32994 	DUK_DD(DUK_DDPRINT("error setter: %!T %!T %!T",
32995 	                   duk_get_tval(thr, -3), duk_get_tval(thr, -2), duk_get_tval(thr, -1)));
32996 
32997 	duk_def_prop(thr, -3, DUK_DEFPROP_HAVE_VALUE |
32998 	                      DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE |
32999 	                      DUK_DEFPROP_HAVE_ENUMERABLE | /*not enumerable*/
33000 	                      DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE);
33001 	return 0;
33002 }
33003 
duk_bi_error_prototype_stack_setter(duk_hthread * thr)33004 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_setter(duk_hthread *thr) {
33005 	return duk__error_setter_helper(thr, DUK_STRIDX_STACK);
33006 }
33007 
duk_bi_error_prototype_filename_setter(duk_hthread * thr)33008 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_setter(duk_hthread *thr) {
33009 	return duk__error_setter_helper(thr, DUK_STRIDX_FILE_NAME);
33010 }
33011 
duk_bi_error_prototype_linenumber_setter(duk_hthread * thr)33012 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_hthread *thr) {
33013 	return duk__error_setter_helper(thr, DUK_STRIDX_LINE_NUMBER);
33014 }
33015 
33016 /* automatic undefs */
33017 #undef DUK__OUTPUT_TYPE_FILENAME
33018 #undef DUK__OUTPUT_TYPE_LINENUMBER
33019 #undef DUK__OUTPUT_TYPE_TRACEBACK
33020 #line 1 "duk_bi_function.c"
33021 /*
33022  *  Function built-ins
33023  */
33024 
33025 /* #include duk_internal.h -> already included */
33026 
33027 /* Needed even when Function built-in is disabled. */
duk_bi_function_prototype(duk_hthread * thr)33028 DUK_INTERNAL duk_ret_t duk_bi_function_prototype(duk_hthread *thr) {
33029 	/* ignore arguments, return undefined (E5 Section 15.3.4) */
33030 	DUK_UNREF(thr);
33031 	return 0;
33032 }
33033 
33034 #if defined(DUK_USE_FUNCTION_BUILTIN)
duk_bi_function_constructor(duk_hthread * thr)33035 DUK_INTERNAL duk_ret_t duk_bi_function_constructor(duk_hthread *thr) {
33036 	duk_hstring *h_sourcecode;
33037 	duk_idx_t nargs;
33038 	duk_idx_t i;
33039 	duk_small_uint_t comp_flags;
33040 	duk_hcompfunc *func;
33041 	duk_hobject *outer_lex_env;
33042 	duk_hobject *outer_var_env;
33043 
33044 	/* normal and constructor calls have identical semantics */
33045 
33046 	nargs = duk_get_top(thr);
33047 	for (i = 0; i < nargs; i++) {
33048 		duk_to_string(thr, i);  /* Rejects Symbols during coercion. */
33049 	}
33050 
33051 	if (nargs == 0) {
33052 		duk_push_hstring_empty(thr);
33053 		duk_push_hstring_empty(thr);
33054 	} else if (nargs == 1) {
33055 		/* XXX: cover this with the generic >1 case? */
33056 		duk_push_hstring_empty(thr);
33057 	} else {
33058 		duk_insert(thr, 0);   /* [ arg1 ... argN-1 body] -> [body arg1 ... argN-1] */
33059 		duk_push_literal(thr, ",");
33060 		duk_insert(thr, 1);
33061 		duk_join(thr, nargs - 1);
33062 	}
33063 
33064 	/* [ body formals ], formals is comma separated list that needs to be parsed */
33065 
33066 	DUK_ASSERT_TOP(thr, 2);
33067 
33068 	/* XXX: this placeholder is not always correct, but use for now.
33069 	 * It will fail in corner cases; see test-dev-func-cons-args.js.
33070 	 */
33071 	duk_push_literal(thr, "function(");
33072 	duk_dup_1(thr);
33073 	duk_push_literal(thr, "){");
33074 	duk_dup_0(thr);
33075 	duk_push_literal(thr, "\n}");  /* Newline is important to handle trailing // comment. */
33076 	duk_concat(thr, 5);
33077 
33078 	/* [ body formals source ] */
33079 
33080 	DUK_ASSERT_TOP(thr, 3);
33081 
33082 	/* strictness is not inherited, intentional */
33083 	comp_flags = DUK_COMPILE_FUNCEXPR;
33084 
33085 	duk_push_hstring_stridx(thr, DUK_STRIDX_COMPILE);  /* XXX: copy from caller? */  /* XXX: ignored now */
33086 	h_sourcecode = duk_require_hstring(thr, -2);  /* no symbol check needed; -2 is concat'd code */
33087 	duk_js_compile(thr,
33088 	               (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode),
33089 	               (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode),
33090 	               comp_flags);
33091 
33092 	/* Force .name to 'anonymous' (ES2015). */
33093 	duk_push_literal(thr, "anonymous");
33094 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
33095 
33096 	func = (duk_hcompfunc *) duk_known_hobject(thr, -1);
33097 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) func));
33098 	DUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) func));
33099 
33100 	/* [ body formals source template ] */
33101 
33102 	/* only outer_lex_env matters, as functions always get a new
33103 	 * variable declaration environment.
33104 	 */
33105 
33106 	outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
33107 	outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
33108 
33109 	duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 1 /*add_auto_proto*/);
33110 
33111 	/* [ body formals source template closure ] */
33112 
33113 	return 1;
33114 }
33115 #endif  /* DUK_USE_FUNCTION_BUILTIN */
33116 
33117 #if defined(DUK_USE_FUNCTION_BUILTIN)
duk_bi_function_prototype_to_string(duk_hthread * thr)33118 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_to_string(duk_hthread *thr) {
33119 	duk_tval *tv;
33120 
33121 	/*
33122 	 *  E5 Section 15.3.4.2 places few requirements on the output of
33123 	 *  this function: the result is implementation dependent, must
33124 	 *  follow FunctionDeclaration syntax (in particular, must have a
33125 	 *  name even for anonymous functions or functions with empty name).
33126 	 *  The output does NOT need to compile into anything useful.
33127 	 *
33128 	 *  E6 Section 19.2.3.5 changes the requirements completely: the
33129 	 *  result must either eval() to a functionally equivalent object
33130 	 *  OR eval() to a SyntaxError.
33131 	 *
33132 	 *  We opt for the SyntaxError approach for now, with a syntax that
33133 	 *  mimics V8's native function syntax:
33134 	 *
33135 	 *      'function cos() { [native code] }'
33136 	 *
33137 	 *  but extended with [ecmascript code], [bound code], and
33138 	 *  [lightfunc code].
33139 	 */
33140 
33141 	duk_push_this(thr);
33142 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
33143 	DUK_ASSERT(tv != NULL);
33144 
33145 	if (DUK_TVAL_IS_OBJECT(tv)) {
33146 		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv);
33147 		const char *func_name;
33148 
33149 		/* Function name: missing/undefined is mapped to empty string,
33150 		 * otherwise coerce to string.  No handling for invalid identifier
33151 		 * characters or e.g. '{' in the function name.  This doesn't
33152 		 * really matter as long as a SyntaxError results.  Technically
33153 		 * if the name contained a suitable prefix followed by '//' it
33154 		 * might cause the result to parse without error.
33155 		 */
33156 		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME);
33157 		if (duk_is_undefined(thr, -1)) {
33158 			func_name = "";
33159 		} else {
33160 			func_name = duk_to_string(thr, -1);
33161 			DUK_ASSERT(func_name != NULL);
33162 		}
33163 
33164 		if (DUK_HOBJECT_IS_COMPFUNC(obj)) {
33165 			duk_push_sprintf(thr, "function %s() { [ecmascript code] }", (const char *) func_name);
33166 		} else if (DUK_HOBJECT_IS_NATFUNC(obj)) {
33167 			duk_push_sprintf(thr, "function %s() { [native code] }", (const char *) func_name);
33168 		} else if (DUK_HOBJECT_IS_BOUNDFUNC(obj)) {
33169 			duk_push_sprintf(thr, "function %s() { [bound code] }", (const char *) func_name);
33170 		} else {
33171 			goto type_error;
33172 		}
33173 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
33174 		duk_push_lightfunc_tostring(thr, tv);
33175 	} else {
33176 		goto type_error;
33177 	}
33178 
33179 	return 1;
33180 
33181  type_error:
33182 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
33183 }
33184 #endif
33185 
33186 /* Always present because the native function pointer is needed in call
33187  * handling.
33188  */
duk_bi_function_prototype_call(duk_hthread * thr)33189 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_call(duk_hthread *thr) {
33190 	/* .call() is dealt with in call handling by simulating its
33191 	 * effects so this function is actually never called.
33192 	 */
33193 	DUK_UNREF(thr);
33194 	return DUK_RET_TYPE_ERROR;
33195 }
33196 
duk_bi_function_prototype_apply(duk_hthread * thr)33197 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_apply(duk_hthread *thr) {
33198 	/* Like .call(), never actually called. */
33199 	DUK_UNREF(thr);
33200 	return DUK_RET_TYPE_ERROR;
33201 }
33202 
duk_bi_reflect_apply(duk_hthread * thr)33203 DUK_INTERNAL duk_ret_t duk_bi_reflect_apply(duk_hthread *thr) {
33204 	/* Like .call(), never actually called. */
33205 	DUK_UNREF(thr);
33206 	return DUK_RET_TYPE_ERROR;
33207 }
33208 
duk_bi_reflect_construct(duk_hthread * thr)33209 DUK_INTERNAL duk_ret_t duk_bi_reflect_construct(duk_hthread *thr) {
33210 	/* Like .call(), never actually called. */
33211 	DUK_UNREF(thr);
33212 	return DUK_RET_TYPE_ERROR;
33213 }
33214 
33215 #if defined(DUK_USE_FUNCTION_BUILTIN)
33216 /* Create a bound function which points to a target function which may
33217  * be bound or non-bound.  If the target is bound, the argument lists
33218  * and 'this' binding of the functions are merged and the resulting
33219  * function points directly to the non-bound target.
33220  */
duk_bi_function_prototype_bind(duk_hthread * thr)33221 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_hthread *thr) {
33222 	duk_hboundfunc *h_bound;
33223 	duk_idx_t nargs;  /* bound args, not counting 'this' binding */
33224 	duk_idx_t bound_nargs;
33225 	duk_int_t bound_len;
33226 	duk_tval *tv_prevbound;
33227 	duk_idx_t n_prevbound;
33228 	duk_tval *tv_res;
33229 	duk_tval *tv_tmp;
33230 
33231 	/* XXX: C API call, e.g. duk_push_bound_function(thr, target_idx, nargs); */
33232 
33233 	/* Vararg function, careful arg handling, e.g. thisArg may not
33234 	 * be present.
33235 	 */
33236 	nargs = duk_get_top(thr) - 1;  /* actual args, not counting 'this' binding */
33237 	if (nargs < 0) {
33238 		nargs++;
33239 		duk_push_undefined(thr);
33240 	}
33241 	DUK_ASSERT(nargs >= 0);
33242 
33243 	/* Limit 'nargs' for bound functions to guarantee arithmetic
33244 	 * below will never wrap.
33245 	 */
33246 	if (nargs > (duk_idx_t) DUK_HBOUNDFUNC_MAX_ARGS) {
33247 		DUK_DCERROR_RANGE_INVALID_COUNT(thr);
33248 	}
33249 
33250 	duk_push_this(thr);
33251 	duk_require_callable(thr, -1);
33252 
33253 	/* [ thisArg arg1 ... argN func ]  (thisArg+args == nargs+1 total) */
33254 	DUK_ASSERT_TOP(thr, nargs + 2);
33255 
33256 	/* Create bound function object. */
33257 	h_bound = duk_push_hboundfunc(thr);
33258 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&h_bound->target));
33259 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&h_bound->this_binding));
33260 	DUK_ASSERT(h_bound->args == NULL);
33261 	DUK_ASSERT(h_bound->nargs == 0);
33262 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_bound) == NULL);
33263 
33264 	/* [ thisArg arg1 ... argN func boundFunc ] */
33265 
33266 	/* If the target is a bound function, argument lists must be
33267 	 * merged.  The 'this' binding closest to the target function
33268 	 * wins because in call handling the 'this' gets replaced over
33269 	 * and over again until we call the non-bound function.
33270 	 */
33271 	tv_prevbound = NULL;
33272 	n_prevbound = 0;
33273 	tv_tmp = DUK_GET_TVAL_POSIDX(thr, 0);
33274 	DUK_TVAL_SET_TVAL(&h_bound->this_binding, tv_tmp);
33275 	tv_tmp = DUK_GET_TVAL_NEGIDX(thr, -2);
33276 	DUK_TVAL_SET_TVAL(&h_bound->target, tv_tmp);
33277 
33278 	if (DUK_TVAL_IS_OBJECT(tv_tmp)) {
33279 		duk_hobject *h_target;
33280 		duk_hobject *bound_proto;
33281 
33282 		h_target = DUK_TVAL_GET_OBJECT(tv_tmp);
33283 		DUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(h_target));
33284 
33285 		/* Internal prototype must be copied from the target.
33286 		 * For lightfuncs Function.prototype is used and is already
33287 		 * in place.
33288 		 */
33289 		bound_proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_target);
33290 		DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) h_bound, bound_proto);
33291 
33292 		/* The 'strict' flag is copied to get the special [[Get]] of E5.1
33293 		 * Section 15.3.5.4 to apply when a 'caller' value is a strict bound
33294 		 * function.  Not sure if this is correct, because the specification
33295 		 * is a bit ambiguous on this point but it would make sense.
33296 		 */
33297 		/* Strictness is inherited from target. */
33298 		if (DUK_HOBJECT_HAS_STRICT(h_target)) {
33299 			DUK_HOBJECT_SET_STRICT((duk_hobject *) h_bound);
33300 		}
33301 
33302 		if (DUK_HOBJECT_HAS_BOUNDFUNC(h_target)) {
33303 			duk_hboundfunc *h_boundtarget;
33304 
33305 			h_boundtarget = (duk_hboundfunc *) (void *) h_target;
33306 
33307 			/* The final function should always be non-bound, unless
33308 			 * there's a bug in the internals.  Assert for it.
33309 			 */
33310 			DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(&h_boundtarget->target) ||
33311 			           (DUK_TVAL_IS_OBJECT(&h_boundtarget->target) &&
33312 			            DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(&h_boundtarget->target)) &&
33313 			            !DUK_HOBJECT_IS_BOUNDFUNC(DUK_TVAL_GET_OBJECT(&h_boundtarget->target))));
33314 
33315 			DUK_TVAL_SET_TVAL(&h_bound->target, &h_boundtarget->target);
33316 			DUK_TVAL_SET_TVAL(&h_bound->this_binding, &h_boundtarget->this_binding);
33317 
33318 			tv_prevbound = h_boundtarget->args;
33319 			n_prevbound = h_boundtarget->nargs;
33320 		}
33321 	} else {
33322 		/* Lightfuncs are always strict. */
33323 		duk_hobject *bound_proto;
33324 
33325 		DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_tmp));
33326 		DUK_HOBJECT_SET_STRICT((duk_hobject *) h_bound);
33327 		bound_proto = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
33328 		DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) h_bound, bound_proto);
33329 	}
33330 
33331 	DUK_TVAL_INCREF(thr, &h_bound->target);  /* old values undefined, no decref needed */
33332 	DUK_TVAL_INCREF(thr, &h_bound->this_binding);
33333 
33334 	bound_nargs = n_prevbound + nargs;
33335 	if (bound_nargs > (duk_idx_t) DUK_HBOUNDFUNC_MAX_ARGS) {
33336 		DUK_DCERROR_RANGE_INVALID_COUNT(thr);
33337 	}
33338 	tv_res = (duk_tval *) DUK_ALLOC_CHECKED(thr, ((duk_size_t) bound_nargs) * sizeof(duk_tval));
33339 	DUK_ASSERT(tv_res != NULL || bound_nargs == 0);
33340 	DUK_ASSERT(h_bound->args == NULL);
33341 	DUK_ASSERT(h_bound->nargs == 0);
33342 	h_bound->args = tv_res;
33343 	h_bound->nargs = bound_nargs;
33344 
33345 	DUK_ASSERT(n_prevbound >= 0);
33346 	duk_copy_tvals_incref(thr, tv_res, tv_prevbound, (duk_size_t) n_prevbound);
33347 	DUK_ASSERT(nargs >= 0);
33348 	duk_copy_tvals_incref(thr, tv_res + n_prevbound, DUK_GET_TVAL_POSIDX(thr, 1), (duk_size_t) nargs);
33349 
33350 	/* [ thisArg arg1 ... argN func boundFunc ] */
33351 
33352 	/* Bound function 'length' property is interesting.
33353 	 * For lightfuncs, simply read the virtual property.
33354 	 */
33355 	duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH);
33356 	bound_len = duk_get_int(thr, -1);  /* ES2015: no coercion */
33357 	if (bound_len < nargs) {
33358 		bound_len = 0;
33359 	} else {
33360 		bound_len -= nargs;
33361 	}
33362 	if (sizeof(duk_int_t) > 4 && bound_len > (duk_int_t) DUK_UINT32_MAX) {
33363 		bound_len = (duk_int_t) DUK_UINT32_MAX;
33364 	}
33365 	duk_pop(thr);
33366 	DUK_ASSERT(bound_len >= 0);
33367 	tv_tmp = thr->valstack_top++;
33368 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_tmp));
33369 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv_tmp));
33370 	DUK_TVAL_SET_U32(tv_tmp, (duk_uint32_t) bound_len);  /* in-place update, fastint */
33371 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);  /* attrs in E6 Section 9.2.4 */
33372 
33373 	/* XXX: could these be virtual? */
33374 	/* Caller and arguments must use the same thrower, [[ThrowTypeError]]. */
33375 	duk_xdef_prop_stridx_thrower(thr, -1, DUK_STRIDX_CALLER);
33376 	duk_xdef_prop_stridx_thrower(thr, -1, DUK_STRIDX_LC_ARGUMENTS);
33377 
33378 	/* Function name and fileName (non-standard). */
33379 	duk_push_literal(thr, "bound ");  /* ES2015 19.2.3.2. */
33380 	duk_get_prop_stridx(thr, -3, DUK_STRIDX_NAME);
33381 	if (!duk_is_string_notsymbol(thr, -1)) {
33382 		/* ES2015 has requirement to check that .name of target is a string
33383 		 * (also must check for Symbol); if not, targetName should be the
33384 		 * empty string.  ES2015 19.2.3.2.
33385 		 */
33386 		duk_pop(thr);
33387 		duk_push_hstring_empty(thr);
33388 	}
33389 	duk_concat(thr, 2);
33390 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
33391 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
33392 	duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME);
33393 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C);
33394 #endif
33395 
33396 	DUK_DDD(DUK_DDDPRINT("created bound function: %!iT", (duk_tval *) duk_get_tval(thr, -1)));
33397 
33398 	return 1;
33399 }
33400 #endif  /* DUK_USE_FUNCTION_BUILTIN */
33401 
33402 /* %NativeFunctionPrototype% .length getter. */
duk_bi_native_function_length(duk_hthread * thr)33403 DUK_INTERNAL duk_ret_t duk_bi_native_function_length(duk_hthread *thr) {
33404 	duk_tval *tv;
33405 	duk_hnatfunc *h;
33406 	duk_int16_t func_nargs;
33407 
33408 	tv = duk_get_borrowed_this_tval(thr);
33409 	DUK_ASSERT(tv != NULL);
33410 
33411 	if (DUK_TVAL_IS_OBJECT(tv)) {
33412 		h = (duk_hnatfunc *) DUK_TVAL_GET_OBJECT(tv);
33413 		DUK_ASSERT(h != NULL);
33414 		if (!DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h)) {
33415 			goto fail_type;
33416 		}
33417 		func_nargs = h->nargs;
33418 		duk_push_int(thr, func_nargs == DUK_HNATFUNC_NARGS_VARARGS ? 0 : func_nargs);
33419 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
33420 		duk_small_uint_t lf_flags;
33421 		duk_small_uint_t lf_len;
33422 
33423 		lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
33424 		lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
33425 		duk_push_uint(thr, lf_len);
33426 	} else {
33427 		goto fail_type;
33428 	}
33429 	return 1;
33430 
33431  fail_type:
33432 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
33433 }
33434 
33435 /* %NativeFunctionPrototype% .name getter. */
duk_bi_native_function_name(duk_hthread * thr)33436 DUK_INTERNAL duk_ret_t duk_bi_native_function_name(duk_hthread *thr) {
33437 	duk_tval *tv;
33438 	duk_hnatfunc *h;
33439 
33440 	tv = duk_get_borrowed_this_tval(thr);
33441 	DUK_ASSERT(tv != NULL);
33442 
33443 	if (DUK_TVAL_IS_OBJECT(tv)) {
33444 		h = (duk_hnatfunc *) DUK_TVAL_GET_OBJECT(tv);
33445 		DUK_ASSERT(h != NULL);
33446 		if (!DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h)) {
33447 			goto fail_type;
33448 		}
33449 #if 0
33450 		duk_push_hnatfunc_name(thr, h);
33451 #endif
33452 		duk_push_hstring_empty(thr);
33453 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
33454 		duk_push_lightfunc_name(thr, tv);
33455 	} else {
33456 		goto fail_type;
33457 	}
33458 	return 1;
33459 
33460  fail_type:
33461 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
33462 }
33463 
33464 #if defined(DUK_USE_SYMBOL_BUILTIN)
duk_bi_function_prototype_hasinstance(duk_hthread * thr)33465 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_hasinstance(duk_hthread *thr) {
33466 	/* This binding: RHS, stack index 0: LHS. */
33467 	duk_bool_t ret;
33468 
33469 	ret = duk_js_instanceof_ordinary(thr, DUK_GET_TVAL_POSIDX(thr, 0), DUK_GET_THIS_TVAL_PTR(thr));
33470 	duk_push_boolean(thr, ret);
33471 	return 1;
33472 }
33473 #endif  /* DUK_USE_SYMBOL_BUILTIN */
33474 #line 1 "duk_bi_global.c"
33475 /*
33476  *  Global object built-ins
33477  */
33478 
33479 /* #include duk_internal.h -> already included */
33480 
33481 /*
33482  *  Encoding/decoding helpers
33483  */
33484 
33485 /* XXX: Could add fast path (for each transform callback) with direct byte
33486  * lookups (no shifting) and no explicit check for x < 0x80 before table
33487  * lookup.
33488  */
33489 
33490 /* Macros for creating and checking bitmasks for character encoding.
33491  * Bit number is a bit counterintuitive, but minimizes code size.
33492  */
33493 #define DUK__MKBITS(a,b,c,d,e,f,g,h)  ((duk_uint8_t) ( \
33494 	((a) << 0) | ((b) << 1) | ((c) << 2) | ((d) << 3) | \
33495 	((e) << 4) | ((f) << 5) | ((g) << 6) | ((h) << 7) \
33496 	))
33497 #define DUK__CHECK_BITMASK(table,cp)  ((table)[(cp) >> 3] & (1 << ((cp) & 0x07)))
33498 
33499 /* E5.1 Section 15.1.3.3: uriReserved + uriUnescaped + '#' */
33500 DUK_LOCAL const duk_uint8_t duk__encode_uriunescaped_table[16] = {
33501 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
33502 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
33503 	DUK__MKBITS(0, 1, 0, 1, 1, 0, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x20-0x2f */
33504 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 0, 1, 0, 1),  /* 0x30-0x3f */
33505 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
33506 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
33507 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
33508 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0),  /* 0x70-0x7f */
33509 };
33510 
33511 /* E5.1 Section 15.1.3.4: uriUnescaped */
33512 DUK_LOCAL const duk_uint8_t duk__encode_uricomponent_unescaped_table[16] = {
33513 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
33514 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
33515 	DUK__MKBITS(0, 1, 0, 0, 0, 0, 0, 1), DUK__MKBITS(1, 1, 1, 0, 0, 1, 1, 0),  /* 0x20-0x2f */
33516 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
33517 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
33518 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
33519 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
33520 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0),  /* 0x70-0x7f */
33521 };
33522 
33523 /* E5.1 Section 15.1.3.1: uriReserved + '#' */
33524 DUK_LOCAL const duk_uint8_t duk__decode_uri_reserved_table[16] = {
33525 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
33526 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
33527 	DUK__MKBITS(0, 0, 0, 1, 1, 0, 1, 0), DUK__MKBITS(0, 0, 0, 1, 1, 0, 0, 1),  /* 0x20-0x2f */
33528 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 0, 1),  /* 0x30-0x3f */
33529 	DUK__MKBITS(1, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x40-0x4f */
33530 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x50-0x5f */
33531 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x60-0x6f */
33532 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x70-0x7f */
33533 };
33534 
33535 /* E5.1 Section 15.1.3.2: empty */
33536 DUK_LOCAL const duk_uint8_t duk__decode_uri_component_reserved_table[16] = {
33537 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
33538 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
33539 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x20-0x2f */
33540 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
33541 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x40-0x4f */
33542 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x50-0x5f */
33543 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x60-0x6f */
33544 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x70-0x7f */
33545 };
33546 
33547 #if defined(DUK_USE_SECTION_B)
33548 /* E5.1 Section B.2.2, step 7. */
33549 DUK_LOCAL const duk_uint8_t duk__escape_unescaped_table[16] = {
33550 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
33551 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
33552 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 1, 1),  /* 0x20-0x2f */
33553 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
33554 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
33555 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
33556 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
33557 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 0)   /* 0x70-0x7f */
33558 };
33559 #endif  /* DUK_USE_SECTION_B */
33560 
33561 typedef struct {
33562 	duk_hthread *thr;
33563 	duk_hstring *h_str;
33564 	duk_bufwriter_ctx bw;
33565 	const duk_uint8_t *p;
33566 	const duk_uint8_t *p_start;
33567 	const duk_uint8_t *p_end;
33568 } duk__transform_context;
33569 
33570 typedef void (*duk__transform_callback)(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp);
33571 
33572 /* XXX: refactor and share with other code */
duk__decode_hex_escape(const duk_uint8_t * p,duk_small_int_t n)33573 DUK_LOCAL duk_small_int_t duk__decode_hex_escape(const duk_uint8_t *p, duk_small_int_t n) {
33574 	duk_small_int_t ch;
33575 	duk_small_int_t t = 0;
33576 
33577 	while (n > 0) {
33578 		t = t * 16;
33579 		ch = (duk_small_int_t) duk_hex_dectab[*p++];
33580 		if (DUK_LIKELY(ch >= 0)) {
33581 			t += ch;
33582 		} else {
33583 			return -1;
33584 		}
33585 		n--;
33586 	}
33587 	return t;
33588 }
33589 
duk__transform_helper(duk_hthread * thr,duk__transform_callback callback,const void * udata)33590 DUK_LOCAL int duk__transform_helper(duk_hthread *thr, duk__transform_callback callback, const void *udata) {
33591 	duk__transform_context tfm_ctx_alloc;
33592 	duk__transform_context *tfm_ctx = &tfm_ctx_alloc;
33593 	duk_codepoint_t cp;
33594 
33595 	tfm_ctx->thr = thr;
33596 
33597 	tfm_ctx->h_str = duk_to_hstring(thr, 0);
33598 	DUK_ASSERT(tfm_ctx->h_str != NULL);
33599 
33600 	DUK_BW_INIT_PUSHBUF(thr, &tfm_ctx->bw, DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str));  /* initial size guess */
33601 
33602 	tfm_ctx->p_start = DUK_HSTRING_GET_DATA(tfm_ctx->h_str);
33603 	tfm_ctx->p_end = tfm_ctx->p_start + DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str);
33604 	tfm_ctx->p = tfm_ctx->p_start;
33605 
33606 	while (tfm_ctx->p < tfm_ctx->p_end) {
33607 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end);
33608 		callback(tfm_ctx, udata, cp);
33609 	}
33610 
33611 	DUK_BW_COMPACT(thr, &tfm_ctx->bw);
33612 
33613 	(void) duk_buffer_to_string(thr, -1);  /* Safe if transform is safe. */
33614 	return 1;
33615 }
33616 
duk__transform_callback_encode_uri(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)33617 DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
33618 	duk_uint8_t xutf8_buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
33619 	duk_small_int_t len;
33620 	duk_codepoint_t cp1, cp2;
33621 	duk_small_int_t i, t;
33622 	const duk_uint8_t *unescaped_table = (const duk_uint8_t *) udata;
33623 
33624 	/* UTF-8 encoded bytes escaped as %xx%xx%xx... -> 3 * nbytes.
33625 	 * Codepoint range is restricted so this is a slightly too large
33626 	 * but doesn't matter.
33627 	 */
33628 	DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 3 * DUK_UNICODE_MAX_XUTF8_LENGTH);
33629 
33630 	if (cp < 0) {
33631 		goto uri_error;
33632 	} else if ((cp < 0x80L) && DUK__CHECK_BITMASK(unescaped_table, cp)) {
33633 		DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
33634 		return;
33635 	} else if (cp >= 0xdc00L && cp <= 0xdfffL) {
33636 		goto uri_error;
33637 	} else if (cp >= 0xd800L && cp <= 0xdbffL) {
33638 		/* Needs lookahead */
33639 		if (duk_unicode_decode_xutf8(tfm_ctx->thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end, (duk_ucodepoint_t *) &cp2) == 0) {
33640 			goto uri_error;
33641 		}
33642 		if (!(cp2 >= 0xdc00L && cp2 <= 0xdfffL)) {
33643 			goto uri_error;
33644 		}
33645 		cp1 = cp;
33646 		cp = (duk_codepoint_t) (((cp1 - 0xd800L) << 10) + (cp2 - 0xdc00L) + 0x10000L);
33647 	} else if (cp > 0x10ffffL) {
33648 		/* Although we can allow non-BMP characters (they'll decode
33649 		 * back into surrogate pairs), we don't allow extended UTF-8
33650 		 * characters; they would encode to URIs which won't decode
33651 		 * back because of strict UTF-8 checks in URI decoding.
33652 		 * (However, we could just as well allow them here.)
33653 		 */
33654 		goto uri_error;
33655 	} else {
33656 		/* Non-BMP characters within valid UTF-8 range: encode as is.
33657 		 * They'll decode back into surrogate pairs if the escaped
33658 		 * output is decoded.
33659 		 */
33660 		;
33661 	}
33662 
33663 	len = duk_unicode_encode_xutf8((duk_ucodepoint_t) cp, xutf8_buf);
33664 	for (i = 0; i < len; i++) {
33665 		t = (duk_small_int_t) xutf8_buf[i];
33666 		DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
33667 		                      &tfm_ctx->bw,
33668 		                      DUK_ASC_PERCENT,
33669 		                      (duk_uint8_t) duk_uc_nybbles[t >> 4],
33670                                       (duk_uint8_t) duk_uc_nybbles[t & 0x0f]);
33671 	}
33672 
33673 	return;
33674 
33675  uri_error:
33676 	DUK_ERROR_URI(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
33677 	DUK_WO_NORETURN(return;);
33678 }
33679 
duk__transform_callback_decode_uri(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)33680 DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
33681 	const duk_uint8_t *reserved_table = (const duk_uint8_t *) udata;
33682 	duk_small_uint_t utf8_blen;
33683 	duk_codepoint_t min_cp;
33684 	duk_small_int_t t;  /* must be signed */
33685 	duk_small_uint_t i;
33686 
33687 	/* Maximum write size: XUTF8 path writes max DUK_UNICODE_MAX_XUTF8_LENGTH,
33688 	 * percent escape path writes max two times CESU-8 encoded BMP length.
33689 	 */
33690 	DUK_BW_ENSURE(tfm_ctx->thr,
33691 	              &tfm_ctx->bw,
33692 	              (DUK_UNICODE_MAX_XUTF8_LENGTH >= 2 * DUK_UNICODE_MAX_CESU8_BMP_LENGTH ?
33693 	              DUK_UNICODE_MAX_XUTF8_LENGTH : DUK_UNICODE_MAX_CESU8_BMP_LENGTH));
33694 
33695 	if (cp == (duk_codepoint_t) '%') {
33696 		const duk_uint8_t *p = tfm_ctx->p;
33697 		duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p);  /* bytes left */
33698 
33699 		DUK_DDD(DUK_DDDPRINT("percent encoding, left=%ld", (long) left));
33700 
33701 		if (left < 2) {
33702 			goto uri_error;
33703 		}
33704 
33705 		t = duk__decode_hex_escape(p, 2);
33706 		DUK_DDD(DUK_DDDPRINT("first byte: %ld", (long) t));
33707 		if (t < 0) {
33708 			goto uri_error;
33709 		}
33710 
33711 		if (t < 0x80) {
33712 			if (DUK__CHECK_BITMASK(reserved_table, t)) {
33713 				/* decode '%xx' to '%xx' if decoded char in reserved set */
33714 				DUK_ASSERT(tfm_ctx->p - 1 >= tfm_ctx->p_start);
33715 				DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
33716 				                      &tfm_ctx->bw,
33717 				                      DUK_ASC_PERCENT,
33718 				                      p[0],
33719 				                      p[1]);
33720 			} else {
33721 				DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) t);
33722 			}
33723 			tfm_ctx->p += 2;
33724 			return;
33725 		}
33726 
33727 		/* Decode UTF-8 codepoint from a sequence of hex escapes.  The
33728 		 * first byte of the sequence has been decoded to 't'.
33729 		 *
33730 		 * Note that UTF-8 validation must be strict according to the
33731 		 * specification: E5.1 Section 15.1.3, decode algorithm step
33732 		 * 4.d.vii.8.  URIError from non-shortest encodings is also
33733 		 * specifically noted in the spec.
33734 		 */
33735 
33736 		DUK_ASSERT(t >= 0x80);
33737 		if (t < 0xc0) {
33738 			/* continuation byte */
33739 			goto uri_error;
33740 		} else if (t < 0xe0) {
33741 			/* 110x xxxx; 2 bytes */
33742 			utf8_blen = 2;
33743 			min_cp = 0x80L;
33744 			cp = t & 0x1f;
33745 		} else if (t < 0xf0) {
33746 			/* 1110 xxxx; 3 bytes */
33747 			utf8_blen = 3;
33748 			min_cp = 0x800L;
33749 			cp = t & 0x0f;
33750 		} else if (t < 0xf8) {
33751 			/* 1111 0xxx; 4 bytes */
33752 			utf8_blen = 4;
33753 			min_cp = 0x10000L;
33754 			cp = t & 0x07;
33755 		} else {
33756 			/* extended utf-8 not allowed for URIs */
33757 			goto uri_error;
33758 		}
33759 
33760 		if (left < utf8_blen * 3 - 1) {
33761 			/* '%xx%xx...%xx', p points to char after first '%' */
33762 			goto uri_error;
33763 		}
33764 
33765 		p += 3;
33766 		for (i = 1; i < utf8_blen; i++) {
33767 			/* p points to digit part ('%xy', p points to 'x') */
33768 			t = duk__decode_hex_escape(p, 2);
33769 			DUK_DDD(DUK_DDDPRINT("i=%ld utf8_blen=%ld cp=%ld t=0x%02lx",
33770 			                     (long) i, (long) utf8_blen, (long) cp, (unsigned long) t));
33771 			if (t < 0) {
33772 				goto uri_error;
33773 			}
33774 			if ((t & 0xc0) != 0x80) {
33775 				goto uri_error;
33776 			}
33777 			cp = (cp << 6) + (t & 0x3f);
33778 			p += 3;
33779 		}
33780 		p--;  /* p overshoots */
33781 		tfm_ctx->p = p;
33782 
33783 		DUK_DDD(DUK_DDDPRINT("final cp=%ld, min_cp=%ld", (long) cp, (long) min_cp));
33784 
33785 		if (cp < min_cp || cp > 0x10ffffL || (cp >= 0xd800L && cp <= 0xdfffL)) {
33786 			goto uri_error;
33787 		}
33788 
33789 		/* The E5.1 algorithm checks whether or not a decoded codepoint
33790 		 * is below 0x80 and perhaps may be in the "reserved" set.
33791 		 * This seems pointless because the single byte UTF-8 case is
33792 		 * handled separately, and non-shortest encodings are rejected.
33793 		 * So, 'cp' cannot be below 0x80 here, and thus cannot be in
33794 		 * the reserved set.
33795 		 */
33796 
33797 		/* utf-8 validation ensures these */
33798 		DUK_ASSERT(cp >= 0x80L && cp <= 0x10ffffL);
33799 
33800 		if (cp >= 0x10000L) {
33801 			cp -= 0x10000L;
33802 			DUK_ASSERT(cp < 0x100000L);
33803 
33804 			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp >> 10) + 0xd800L));
33805 			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp & 0x03ffL) + 0xdc00L));
33806 		} else {
33807 			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
33808 		}
33809 	} else {
33810 		DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
33811 	}
33812 	return;
33813 
33814  uri_error:
33815 	DUK_ERROR_URI(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
33816 	DUK_WO_NORETURN(return;);
33817 }
33818 
33819 #if defined(DUK_USE_SECTION_B)
duk__transform_callback_escape(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)33820 DUK_LOCAL void duk__transform_callback_escape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
33821 	DUK_UNREF(udata);
33822 
33823 	DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 6);
33824 
33825 	if (cp < 0) {
33826 		goto esc_error;
33827 	} else if ((cp < 0x80L) && DUK__CHECK_BITMASK(duk__escape_unescaped_table, cp)) {
33828 		DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
33829 	} else if (cp < 0x100L) {
33830 		DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
33831 		                      &tfm_ctx->bw,
33832 		                      (duk_uint8_t) DUK_ASC_PERCENT,
33833 		                      (duk_uint8_t) duk_uc_nybbles[cp >> 4],
33834 		                      (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
33835 	} else if (cp < 0x10000L) {
33836 		DUK_BW_WRITE_RAW_U8_6(tfm_ctx->thr,
33837 		                      &tfm_ctx->bw,
33838 		                      (duk_uint8_t) DUK_ASC_PERCENT,
33839 		                      (duk_uint8_t) DUK_ASC_LC_U,
33840 		                      (duk_uint8_t) duk_uc_nybbles[cp >> 12],
33841 		                      (duk_uint8_t) duk_uc_nybbles[(cp >> 8) & 0x0f],
33842 		                      (duk_uint8_t) duk_uc_nybbles[(cp >> 4) & 0x0f],
33843 		                      (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
33844 	} else {
33845 		/* Characters outside BMP cannot be escape()'d.  We could
33846 		 * encode them as surrogate pairs (for codepoints inside
33847 		 * valid UTF-8 range, but not extended UTF-8).  Because
33848 		 * escape() and unescape() are legacy functions, we don't.
33849 		 */
33850 		goto esc_error;
33851 	}
33852 
33853 	return;
33854 
33855  esc_error:
33856 	DUK_ERROR_TYPE(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
33857 	DUK_WO_NORETURN(return;);
33858 }
33859 
duk__transform_callback_unescape(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)33860 DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
33861 	duk_small_int_t t;
33862 
33863 	DUK_UNREF(udata);
33864 
33865 	if (cp == (duk_codepoint_t) '%') {
33866 		const duk_uint8_t *p = tfm_ctx->p;
33867 		duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p);  /* bytes left */
33868 
33869 		if (left >= 5 && p[0] == 'u' &&
33870 		    ((t = duk__decode_hex_escape(p + 1, 4)) >= 0)) {
33871 			cp = (duk_codepoint_t) t;
33872 			tfm_ctx->p += 5;
33873 		} else if (left >= 2 &&
33874 		           ((t = duk__decode_hex_escape(p, 2)) >= 0)) {
33875 			cp = (duk_codepoint_t) t;
33876 			tfm_ctx->p += 2;
33877 		}
33878 	}
33879 
33880 	DUK_BW_WRITE_ENSURE_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
33881 }
33882 #endif  /* DUK_USE_SECTION_B */
33883 
33884 /*
33885  *  Eval
33886  *
33887  *  Eval needs to handle both a "direct eval" and an "indirect eval".
33888  *  Direct eval handling needs access to the caller's activation so that its
33889  *  lexical environment can be accessed.  A direct eval is only possible from
33890  *  ECMAScript code; an indirect eval call is possible also from C code.
33891  *  When an indirect eval call is made from C code, there may not be a
33892  *  calling activation at all which needs careful handling.
33893  */
33894 
duk_bi_global_object_eval(duk_hthread * thr)33895 DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_hthread *thr) {
33896 	duk_hstring *h;
33897 	duk_activation *act_caller;
33898 	duk_activation *act_eval;
33899 	duk_hcompfunc *func;
33900 	duk_hobject *outer_lex_env;
33901 	duk_hobject *outer_var_env;
33902 	duk_bool_t this_to_global = 1;
33903 	duk_small_uint_t comp_flags;
33904 	duk_int_t level = -2;
33905 	duk_small_uint_t call_flags;
33906 
33907 	DUK_ASSERT(duk_get_top(thr) == 1 || duk_get_top(thr) == 2);  /* 2 when called by debugger */
33908 	DUK_ASSERT(thr->callstack_top >= 1);  /* at least this function exists */
33909 	DUK_ASSERT(thr->callstack_curr != NULL);
33910 	DUK_ASSERT((thr->callstack_curr->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0 || /* indirect eval */
33911 	           (thr->callstack_top >= 2));  /* if direct eval, calling activation must exist */
33912 
33913 	/*
33914 	 *  callstack_top - 1 --> this function
33915 	 *  callstack_top - 2 --> caller (may not exist)
33916 	 *
33917 	 *  If called directly from C, callstack_top might be 1.  If calling
33918 	 *  activation doesn't exist, call must be indirect.
33919 	 */
33920 
33921 	h = duk_get_hstring_notsymbol(thr, 0);
33922 	if (!h) {
33923 		/* Symbol must be returned as is, like any non-string values. */
33924 		return 1;  /* return arg as-is */
33925 	}
33926 
33927 #if defined(DUK_USE_DEBUGGER_SUPPORT)
33928 	/* NOTE: level is used only by the debugger and should never be present
33929 	 * for an ECMAScript eval().
33930 	 */
33931 	DUK_ASSERT(level == -2);  /* by default, use caller's environment */
33932 	if (duk_get_top(thr) >= 2 && duk_is_number(thr, 1)) {
33933 		level = duk_get_int(thr, 1);
33934 	}
33935 	DUK_ASSERT(level <= -2);  /* This is guaranteed by debugger code. */
33936 #endif
33937 
33938 	/* [ source ] */
33939 
33940 	comp_flags = DUK_COMPILE_EVAL;
33941 	act_eval = thr->callstack_curr;  /* this function */
33942 	DUK_ASSERT(act_eval != NULL);
33943 	act_caller = duk_hthread_get_activation_for_level(thr, level);
33944 	if (act_caller != NULL) {
33945 		/* Have a calling activation, check for direct eval (otherwise
33946 		 * assume indirect eval.
33947 		 */
33948 		if ((act_caller->flags & DUK_ACT_FLAG_STRICT) &&
33949 		    (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL)) {
33950 			/* Only direct eval inherits strictness from calling code
33951 			 * (E5.1 Section 10.1.1).
33952 			 */
33953 			comp_flags |= DUK_COMPILE_STRICT;
33954 		}
33955 	} else {
33956 		DUK_ASSERT((act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0);
33957 	}
33958 
33959 	duk_push_hstring_stridx(thr, DUK_STRIDX_INPUT);  /* XXX: copy from caller? */
33960 	duk_js_compile(thr,
33961 	               (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h),
33962 	               (duk_size_t) DUK_HSTRING_GET_BYTELEN(h),
33963 	               comp_flags);
33964 	func = (duk_hcompfunc *) duk_known_hobject(thr, -1);
33965 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) func));
33966 
33967 	/* [ source template ] */
33968 
33969 	/* E5 Section 10.4.2 */
33970 
33971 	if (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
33972 		DUK_ASSERT(thr->callstack_top >= 2);
33973 		DUK_ASSERT(act_caller != NULL);
33974 		if (act_caller->lex_env == NULL) {
33975 			DUK_ASSERT(act_caller->var_env == NULL);
33976 			DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
33977 
33978 			/* this may have side effects, so re-lookup act */
33979 			duk_js_init_activation_environment_records_delayed(thr, act_caller);
33980 		}
33981 		DUK_ASSERT(act_caller->lex_env != NULL);
33982 		DUK_ASSERT(act_caller->var_env != NULL);
33983 
33984 		this_to_global = 0;
33985 
33986 		if (DUK_HOBJECT_HAS_STRICT((duk_hobject *) func)) {
33987 			duk_hdecenv *new_env;
33988 			duk_hobject *act_lex_env;
33989 
33990 			DUK_DDD(DUK_DDDPRINT("direct eval call to a strict function -> "
33991 			                     "var_env and lex_env to a fresh env, "
33992 			                     "this_binding to caller's this_binding"));
33993 
33994 			act_lex_env = act_caller->lex_env;
33995 
33996 			new_env = duk_hdecenv_alloc(thr,
33997 			                            DUK_HOBJECT_FLAG_EXTENSIBLE |
33998 			                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
33999 			DUK_ASSERT(new_env != NULL);
34000 			duk_push_hobject(thr, (duk_hobject *) new_env);
34001 
34002 			DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
34003 			DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, act_lex_env);
34004 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, act_lex_env);
34005 			DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));
34006 
34007 			outer_lex_env = (duk_hobject *) new_env;
34008 			outer_var_env = (duk_hobject *) new_env;
34009 
34010 			duk_insert(thr, 0);  /* stash to bottom of value stack to keep new_env reachable for duration of eval */
34011 
34012 			/* compiler's responsibility */
34013 			DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func));
34014 		} else {
34015 			DUK_DDD(DUK_DDDPRINT("direct eval call to a non-strict function -> "
34016 			                     "var_env and lex_env to caller's envs, "
34017 			                     "this_binding to caller's this_binding"));
34018 
34019 			outer_lex_env = act_caller->lex_env;
34020 			outer_var_env = act_caller->var_env;
34021 
34022 			/* compiler's responsibility */
34023 			DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func));
34024 		}
34025 	} else {
34026 		DUK_DDD(DUK_DDDPRINT("indirect eval call -> var_env and lex_env to "
34027 		                     "global object, this_binding to global object"));
34028 
34029 		this_to_global = 1;
34030 		outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
34031 		outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
34032 	}
34033 
34034 	/* Eval code doesn't need an automatic .prototype object. */
34035 	duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 0 /*add_auto_proto*/);
34036 
34037 	/* [ env? source template closure ] */
34038 
34039 	if (this_to_global) {
34040 		DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
34041 		duk_push_hobject_bidx(thr, DUK_BIDX_GLOBAL);
34042 	} else {
34043 		duk_tval *tv;
34044 		DUK_ASSERT(thr->callstack_top >= 2);
34045 		DUK_ASSERT(act_caller != NULL);
34046 		tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act_caller->bottom_byteoff - sizeof(duk_tval));  /* this is just beneath bottom */
34047 		DUK_ASSERT(tv >= thr->valstack);
34048 		duk_push_tval(thr, tv);
34049 	}
34050 
34051 	DUK_DDD(DUK_DDDPRINT("eval -> lex_env=%!iO, var_env=%!iO, this_binding=%!T",
34052 	                     (duk_heaphdr *) outer_lex_env,
34053 	                     (duk_heaphdr *) outer_var_env,
34054 	                     duk_get_tval(thr, -1)));
34055 
34056 	/* [ env? source template closure this ] */
34057 
34058 	call_flags = 0;
34059 	if (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
34060 		/* Set DIRECT_EVAL flag for the call; it's not strictly
34061 		 * needed for the 'inner' eval call (the eval body) but
34062 		 * current new.target implementation expects to find it
34063 		 * so it can traverse direct eval chains up to the real
34064 		 * calling function.
34065 		 */
34066 		call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
34067 	}
34068 	duk_handle_call_unprotected_nargs(thr, 0, call_flags);
34069 
34070 	/* [ env? source template result ] */
34071 
34072 	return 1;
34073 }
34074 
34075 /*
34076  *  Parsing of ints and floats
34077  */
34078 
34079 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_parse_int(duk_hthread * thr)34080 DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_int(duk_hthread *thr) {
34081 	duk_int32_t radix;
34082 	duk_small_uint_t s2n_flags;
34083 
34084 	DUK_ASSERT_TOP(thr, 2);
34085 	duk_to_string(thr, 0);  /* Reject symbols. */
34086 
34087 	radix = duk_to_int32(thr, 1);
34088 
34089 	/* While parseInt() recognizes 0xdeadbeef, it doesn't recognize
34090 	 * ES2015 0o123 or 0b10001.
34091 	 */
34092 	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
34093 	            DUK_S2N_FLAG_ALLOW_GARBAGE |
34094 	            DUK_S2N_FLAG_ALLOW_PLUS |
34095 	            DUK_S2N_FLAG_ALLOW_MINUS |
34096 	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
34097 	            DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
34098 
34099 	/* Specification stripPrefix maps to DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT.
34100 	 *
34101 	 * Don't autodetect octals (from leading zeroes), require user code to
34102 	 * provide an explicit radix 8 for parsing octal.  See write-up from Mozilla:
34103 	 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt#ECMAScript_5_Removes_Octal_Interpretation
34104 	 */
34105 
34106 	if (radix != 0) {
34107 		if (radix < 2 || radix > 36) {
34108 			goto ret_nan;
34109 		}
34110 		if (radix != 16) {
34111 			s2n_flags &= ~DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
34112 		}
34113 	} else {
34114 		radix = 10;
34115 	}
34116 
34117 	duk_dup_0(thr);
34118 	duk_numconv_parse(thr, (duk_small_int_t) radix, s2n_flags);
34119 	return 1;
34120 
34121  ret_nan:
34122 	duk_push_nan(thr);
34123 	return 1;
34124 }
34125 #endif  /* DUK_USE_GLOBAL_BUILTIN */
34126 
34127 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_parse_float(duk_hthread * thr)34128 DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_float(duk_hthread *thr) {
34129 	duk_small_uint_t s2n_flags;
34130 
34131 	DUK_ASSERT_TOP(thr, 1);
34132 	duk_to_string(thr, 0);  /* Reject symbols. */
34133 
34134 	/* XXX: check flags */
34135 	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
34136 	            DUK_S2N_FLAG_ALLOW_EXP |
34137 	            DUK_S2N_FLAG_ALLOW_GARBAGE |
34138 	            DUK_S2N_FLAG_ALLOW_PLUS |
34139 	            DUK_S2N_FLAG_ALLOW_MINUS |
34140 	            DUK_S2N_FLAG_ALLOW_INF |
34141 	            DUK_S2N_FLAG_ALLOW_FRAC |
34142 	            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
34143 	            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
34144 	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
34145 
34146 	duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
34147 	return 1;
34148 }
34149 #endif  /* DUK_USE_GLOBAL_BUILTIN */
34150 
34151 /*
34152  *  Number checkers
34153  */
34154 
34155 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_is_nan(duk_hthread * thr)34156 DUK_INTERNAL duk_ret_t duk_bi_global_object_is_nan(duk_hthread *thr) {
34157 	duk_double_t d = duk_to_number(thr, 0);
34158 	duk_push_boolean(thr, (duk_bool_t) DUK_ISNAN(d));
34159 	return 1;
34160 }
34161 #endif  /* DUK_USE_GLOBAL_BUILTIN */
34162 
34163 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_is_finite(duk_hthread * thr)34164 DUK_INTERNAL duk_ret_t duk_bi_global_object_is_finite(duk_hthread *thr) {
34165 	duk_double_t d = duk_to_number(thr, 0);
34166 	duk_push_boolean(thr, (duk_bool_t) DUK_ISFINITE(d));
34167 	return 1;
34168 }
34169 #endif  /* DUK_USE_GLOBAL_BUILTIN */
34170 
34171 /*
34172  *  URI handling
34173  */
34174 
34175 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_decode_uri(duk_hthread * thr)34176 DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri(duk_hthread *thr) {
34177 	return duk__transform_helper(thr, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_reserved_table);
34178 }
34179 
duk_bi_global_object_decode_uri_component(duk_hthread * thr)34180 DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri_component(duk_hthread *thr) {
34181 	return duk__transform_helper(thr, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_component_reserved_table);
34182 }
34183 
duk_bi_global_object_encode_uri(duk_hthread * thr)34184 DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri(duk_hthread *thr) {
34185 	return duk__transform_helper(thr, duk__transform_callback_encode_uri, (const void *) duk__encode_uriunescaped_table);
34186 }
34187 
duk_bi_global_object_encode_uri_component(duk_hthread * thr)34188 DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri_component(duk_hthread *thr) {
34189 	return duk__transform_helper(thr, duk__transform_callback_encode_uri, (const void *) duk__encode_uricomponent_unescaped_table);
34190 }
34191 
34192 #if defined(DUK_USE_SECTION_B)
duk_bi_global_object_escape(duk_hthread * thr)34193 DUK_INTERNAL duk_ret_t duk_bi_global_object_escape(duk_hthread *thr) {
34194 	return duk__transform_helper(thr, duk__transform_callback_escape, (const void *) NULL);
34195 }
34196 
duk_bi_global_object_unescape(duk_hthread * thr)34197 DUK_INTERNAL duk_ret_t duk_bi_global_object_unescape(duk_hthread *thr) {
34198 	return duk__transform_helper(thr, duk__transform_callback_unescape, (const void *) NULL);
34199 }
34200 #endif  /* DUK_USE_SECTION_B */
34201 #endif  /* DUK_USE_GLOBAL_BUILTIN */
34202 
34203 /* automatic undefs */
34204 #undef DUK__CHECK_BITMASK
34205 #undef DUK__MKBITS
34206 #line 1 "duk_bi_json.c"
34207 /*
34208  *  JSON built-ins.
34209  *
34210  *  See doc/json.rst.
34211  *
34212  *  Codepoints are handled as duk_uint_fast32_t to ensure that the full
34213  *  unsigned 32-bit range is supported.  This matters to e.g. JX.
34214  *
34215  *  Input parsing doesn't do an explicit end-of-input check at all.  This is
34216  *  safe: input string data is always NUL-terminated (0x00) and valid JSON
34217  *  inputs never contain plain NUL characters, so that as long as syntax checks
34218  *  are correct, we'll never read past the NUL.  This approach reduces code size
34219  *  and improves parsing performance, but it's critical that syntax checks are
34220  *  indeed correct!
34221  */
34222 
34223 /* #include duk_internal.h -> already included */
34224 
34225 #if defined(DUK_USE_JSON_SUPPORT)
34226 
34227 /*
34228  *  Local defines and forward declarations.
34229  */
34230 
34231 #define DUK__JSON_DECSTR_BUFSIZE 128
34232 #define DUK__JSON_DECSTR_CHUNKSIZE 64
34233 #define DUK__JSON_ENCSTR_CHUNKSIZE 64
34234 #define DUK__JSON_STRINGIFY_BUFSIZE 128
34235 #define DUK__JSON_MAX_ESC_LEN 10  /* '\Udeadbeef' */
34236 
34237 DUK_LOCAL_DECL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx);
34238 DUK_LOCAL_DECL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx);
34239 #if defined(DUK_USE_JX)
34240 DUK_LOCAL_DECL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx);
34241 #endif
34242 DUK_LOCAL_DECL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx);
34243 DUK_LOCAL_DECL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx);
34244 DUK_LOCAL_DECL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n);
34245 DUK_LOCAL_DECL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx);
34246 DUK_LOCAL_DECL void duk__dec_string(duk_json_dec_ctx *js_ctx);
34247 #if defined(DUK_USE_JX)
34248 DUK_LOCAL_DECL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx);
34249 DUK_LOCAL_DECL void duk__dec_pointer(duk_json_dec_ctx *js_ctx);
34250 DUK_LOCAL_DECL void duk__dec_buffer(duk_json_dec_ctx *js_ctx);
34251 #endif
34252 DUK_LOCAL_DECL void duk__dec_number(duk_json_dec_ctx *js_ctx);
34253 DUK_LOCAL_DECL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx);
34254 DUK_LOCAL_DECL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx);
34255 DUK_LOCAL_DECL void duk__dec_object(duk_json_dec_ctx *js_ctx);
34256 DUK_LOCAL_DECL void duk__dec_array(duk_json_dec_ctx *js_ctx);
34257 DUK_LOCAL_DECL void duk__dec_value(duk_json_dec_ctx *js_ctx);
34258 DUK_LOCAL_DECL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx);
34259 
34260 DUK_LOCAL_DECL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch);
34261 DUK_LOCAL_DECL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2);
34262 DUK_LOCAL_DECL void duk__unemit_1(duk_json_enc_ctx *js_ctx);
34263 DUK_LOCAL_DECL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h);
34264 #if defined(DUK_USE_FASTINT)
34265 DUK_LOCAL_DECL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p);
34266 #endif
34267 DUK_LOCAL_DECL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx);
34268 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);
34269 DUK_LOCAL_DECL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k);
34270 DUK_LOCAL_DECL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str);
34271 DUK_LOCAL_DECL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
34272 DUK_LOCAL_DECL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
34273 DUK_LOCAL_DECL void duk__enc_object(duk_json_enc_ctx *js_ctx);
34274 DUK_LOCAL_DECL void duk__enc_array(duk_json_enc_ctx *js_ctx);
34275 DUK_LOCAL_DECL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder);
34276 DUK_LOCAL_DECL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv);
34277 DUK_LOCAL_DECL void duk__enc_double(duk_json_enc_ctx *js_ctx);
34278 #if defined(DUK_USE_FASTINT)
34279 DUK_LOCAL_DECL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv);
34280 #endif
34281 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
34282 DUK_LOCAL_DECL void duk__enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
34283 DUK_LOCAL_DECL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr);
34284 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
34285 DUK_LOCAL_DECL void duk__enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj);
34286 #endif
34287 #endif
34288 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
34289 DUK_LOCAL_DECL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
34290 #endif
34291 DUK_LOCAL_DECL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth);
34292 
34293 /*
34294  *  Helper tables
34295  */
34296 
34297 #if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
34298 DUK_LOCAL const duk_uint8_t duk__json_quotestr_lookup[256] = {
34299 	/* 0x00 ... 0x7f: as is
34300 	 * 0x80: escape generically
34301 	 * 0x81: slow path
34302 	 * 0xa0 ... 0xff: backslash + one char
34303 	 */
34304 
34305 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xe2, 0xf4, 0xee, 0x80, 0xe6, 0xf2, 0x80, 0x80,
34306 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
34307 	0x20, 0x21, 0xa2, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
34308 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
34309 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
34310 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0xdc, 0x5d, 0x5e, 0x5f,
34311 	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
34312 	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x81,
34313 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34314 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34315 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34316 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34317 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34318 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34319 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34320 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81
34321 };
34322 #else  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
34323 DUK_LOCAL const duk_uint8_t duk__json_quotestr_esc[14] = {
34324 	DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
34325 	DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
34326 	DUK_ASC_LC_B, DUK_ASC_LC_T, DUK_ASC_LC_N, DUK_ASC_NUL,
34327 	DUK_ASC_LC_F, DUK_ASC_LC_R
34328 };
34329 #endif  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
34330 
34331 #if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
34332 DUK_LOCAL const duk_uint8_t duk__json_decstr_lookup[256] = {
34333 	/* 0x00: slow path
34334 	 * other: as is
34335 	 */
34336 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34337 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34338 	0x20, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
34339 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
34340 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
34341 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x5d, 0x5e, 0x5f,
34342 	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
34343 	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
34344 	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
34345 	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
34346 	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
34347 	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
34348 	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
34349 	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
34350 	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
34351 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
34352 };
34353 #endif  /* DUK_USE_JSON_DECSTRING_FASTPATH */
34354 
34355 #if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
34356 DUK_LOCAL const duk_uint8_t duk__json_eatwhite_lookup[256] = {
34357 	/* 0x00: finish (non-white)
34358 	 * 0x01: continue
34359 	 */
34360 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
34361 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34362 	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34363 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34364 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34365 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34366 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34367 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34368 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34369 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34370 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34371 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34372 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34373 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34374 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34375 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
34376 };
34377 #endif  /* DUK_USE_JSON_EATWHITE_FASTPATH */
34378 
34379 #if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
34380 DUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256] = {
34381 	/* 0x00: finish (not part of number)
34382 	 * 0x01: continue
34383 	 */
34384 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34385 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34386 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00,
34387 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34388 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34389 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34390 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34391 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34392 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34393 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34394 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34395 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34396 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34397 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34398 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34399 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
34400 };
34401 #endif  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
34402 
34403 /*
34404  *  Parsing implementation.
34405  *
34406  *  JSON lexer is now separate from duk_lexer.c because there are numerous
34407  *  small differences making it difficult to share the lexer.
34408  *
34409  *  The parser here works with raw bytes directly; this works because all
34410  *  JSON delimiters are ASCII characters.  Invalid xUTF-8 encoded values
34411  *  inside strings will be passed on without normalization; this is not a
34412  *  compliance concern because compliant inputs will always be valid
34413  *  CESU-8 encodings.
34414  */
34415 
duk__dec_syntax_error(duk_json_dec_ctx * js_ctx)34416 DUK_LOCAL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx) {
34417 	/* Shared handler to minimize parser size.  Cause will be
34418 	 * hidden, unfortunately, but we'll have an offset which
34419 	 * is often quite enough.
34420 	 */
34421 	DUK_ERROR_FMT1(js_ctx->thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_FMT_INVALID_JSON,
34422 	               (long) (js_ctx->p - js_ctx->p_start));
34423 	DUK_WO_NORETURN(return;);
34424 }
34425 
duk__dec_eat_white(duk_json_dec_ctx * js_ctx)34426 DUK_LOCAL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx) {
34427 	const duk_uint8_t *p;
34428 	duk_uint8_t t;
34429 
34430 	p = js_ctx->p;
34431 	for (;;) {
34432 		DUK_ASSERT(p <= js_ctx->p_end);
34433 		t = *p;
34434 
34435 #if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
34436 		/* This fast path is pretty marginal in practice.
34437 		 * XXX: candidate for removal.
34438 		 */
34439 		DUK_ASSERT(duk__json_eatwhite_lookup[0x00] == 0x00);  /* end-of-input breaks */
34440 		if (duk__json_eatwhite_lookup[t] == 0) {
34441 			break;
34442 		}
34443 #else  /* DUK_USE_JSON_EATWHITE_FASTPATH */
34444 		if (!(t == 0x20 || t == 0x0a || t == 0x0d || t == 0x09)) {
34445 			/* NUL also comes here.  Comparison order matters, 0x20
34446 			 * is most common whitespace.
34447 			 */
34448 			break;
34449 		}
34450 #endif  /* DUK_USE_JSON_EATWHITE_FASTPATH */
34451 		p++;
34452 	}
34453 	js_ctx->p = p;
34454 }
34455 
34456 #if defined(DUK_USE_JX)
duk__dec_peek(duk_json_dec_ctx * js_ctx)34457 DUK_LOCAL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx) {
34458 	DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
34459 	return *js_ctx->p;
34460 }
34461 #endif
34462 
duk__dec_get(duk_json_dec_ctx * js_ctx)34463 DUK_LOCAL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx) {
34464 	DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
34465 	return *js_ctx->p++;
34466 }
34467 
duk__dec_get_nonwhite(duk_json_dec_ctx * js_ctx)34468 DUK_LOCAL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx) {
34469 	duk__dec_eat_white(js_ctx);
34470 	return duk__dec_get(js_ctx);
34471 }
34472 
34473 /* For JX, expressing the whole unsigned 32-bit range matters. */
duk__dec_decode_hex_escape(duk_json_dec_ctx * js_ctx,duk_small_uint_t n)34474 DUK_LOCAL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n) {
34475 	duk_small_uint_t i;
34476 	duk_uint_fast32_t res = 0;
34477 	duk_uint8_t x;
34478 	duk_small_int_t t;
34479 
34480 	for (i = 0; i < n; i++) {
34481 		/* XXX: share helper from lexer; duk_lexer.c / hexval(). */
34482 
34483 		x = duk__dec_get(js_ctx);
34484 		DUK_DDD(DUK_DDDPRINT("decode_hex_escape: i=%ld, n=%ld, res=%ld, x=%ld",
34485 		                     (long) i, (long) n, (long) res, (long) x));
34486 
34487 		/* x == 0x00 (EOF) causes syntax_error */
34488 		DUK_ASSERT(duk_hex_dectab[0] == -1);
34489 		t = duk_hex_dectab[x & 0xff];
34490 		if (DUK_LIKELY(t >= 0)) {
34491 			res = (res * 16) + (duk_uint_fast32_t) t;
34492 		} else {
34493 			/* catches EOF and invalid digits */
34494 			goto syntax_error;
34495 		}
34496 	}
34497 
34498 	DUK_DDD(DUK_DDDPRINT("final hex decoded value: %ld", (long) res));
34499 	return res;
34500 
34501  syntax_error:
34502 	duk__dec_syntax_error(js_ctx);
34503 	DUK_UNREACHABLE();
34504 	return 0;
34505 }
34506 
duk__dec_req_stridx(duk_json_dec_ctx * js_ctx,duk_small_uint_t stridx)34507 DUK_LOCAL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx) {
34508 	duk_hstring *h;
34509 	const duk_uint8_t *p;
34510 	duk_uint8_t x, y;
34511 
34512 	/* First character has already been eaten and checked by the caller.
34513 	 * We can scan until a NUL in stridx string because no built-in strings
34514 	 * have internal NULs.
34515 	 */
34516 
34517 	DUK_ASSERT_STRIDX_VALID(stridx);
34518 	h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
34519 	DUK_ASSERT(h != NULL);
34520 
34521 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h) + 1;
34522 	DUK_ASSERT(*(js_ctx->p - 1) == *(p - 1));  /* first character has been matched */
34523 
34524 	for (;;) {
34525 		x = *p;
34526 		if (x == 0) {
34527 			break;
34528 		}
34529 		y = duk__dec_get(js_ctx);
34530 		if (x != y) {
34531 			/* Catches EOF of JSON input. */
34532 			goto syntax_error;
34533 		}
34534 		p++;
34535 	}
34536 
34537 	return;
34538 
34539  syntax_error:
34540 	duk__dec_syntax_error(js_ctx);
34541 	DUK_UNREACHABLE();
34542 }
34543 
duk__dec_string_escape(duk_json_dec_ctx * js_ctx,duk_uint8_t ** ext_p)34544 DUK_LOCAL duk_small_int_t duk__dec_string_escape(duk_json_dec_ctx *js_ctx, duk_uint8_t **ext_p) {
34545 	duk_uint_fast32_t cp;
34546 
34547 	/* EOF (-1) will be cast to an unsigned value first
34548 	 * and then re-cast for the switch.  In any case, it
34549 	 * will match the default case (syntax error).
34550 	 */
34551 	cp = (duk_uint_fast32_t) duk__dec_get(js_ctx);
34552 	switch (cp) {
34553 	case DUK_ASC_BACKSLASH: break;
34554 	case DUK_ASC_DOUBLEQUOTE: break;
34555 	case DUK_ASC_SLASH: break;
34556 	case DUK_ASC_LC_T: cp = 0x09; break;
34557 	case DUK_ASC_LC_N: cp = 0x0a; break;
34558 	case DUK_ASC_LC_R: cp = 0x0d; break;
34559 	case DUK_ASC_LC_F: cp = 0x0c; break;
34560 	case DUK_ASC_LC_B: cp = 0x08; break;
34561 	case DUK_ASC_LC_U: {
34562 		cp = duk__dec_decode_hex_escape(js_ctx, 4);
34563 		break;
34564 	}
34565 #if defined(DUK_USE_JX)
34566 	case DUK_ASC_UC_U: {
34567 		if (js_ctx->flag_ext_custom) {
34568 			cp = duk__dec_decode_hex_escape(js_ctx, 8);
34569 		} else {
34570 			return 1;  /* syntax error */
34571 		}
34572 		break;
34573 	}
34574 	case DUK_ASC_LC_X: {
34575 		if (js_ctx->flag_ext_custom) {
34576 			cp = duk__dec_decode_hex_escape(js_ctx, 2);
34577 		} else {
34578 			return 1;  /* syntax error */
34579 		}
34580 		break;
34581 	}
34582 #endif  /* DUK_USE_JX */
34583 	default:
34584 		/* catches EOF (0x00) */
34585 		return 1;  /* syntax error */
34586 	}
34587 
34588 	DUK_RAW_WRITE_XUTF8(*ext_p, cp);
34589 
34590 	return 0;
34591 }
34592 
duk__dec_string(duk_json_dec_ctx * js_ctx)34593 DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) {
34594 	duk_hthread *thr = js_ctx->thr;
34595 	duk_bufwriter_ctx bw_alloc;
34596 	duk_bufwriter_ctx *bw;
34597 	duk_uint8_t *q;
34598 
34599 	/* '"' was eaten by caller */
34600 
34601 	/* Note that we currently parse -bytes-, not codepoints.
34602 	 * All non-ASCII extended UTF-8 will encode to bytes >= 0x80,
34603 	 * so they'll simply pass through (valid UTF-8 or not).
34604 	 */
34605 
34606 	bw = &bw_alloc;
34607 	DUK_BW_INIT_PUSHBUF(js_ctx->thr, bw, DUK__JSON_DECSTR_BUFSIZE);
34608 	q = DUK_BW_GET_PTR(js_ctx->thr, bw);
34609 
34610 #if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
34611 	for (;;) {
34612 		duk_small_uint_t safe;
34613 		duk_uint8_t b, x;
34614 		const duk_uint8_t *p;
34615 
34616 		/* Select a safe loop count where no output checks are
34617 		 * needed assuming we won't encounter escapes.  Input
34618 		 * bound checks are not necessary as a NUL (guaranteed)
34619 		 * will cause a SyntaxError before we read out of bounds.
34620 		 */
34621 
34622 		safe = DUK__JSON_DECSTR_CHUNKSIZE;
34623 
34624 		/* Ensure space for 1:1 output plus one escape. */
34625 		q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, safe + DUK_UNICODE_MAX_XUTF8_LENGTH, q);
34626 
34627 		p = js_ctx->p;  /* temp copy, write back for next loop */
34628 		for (;;) {
34629 			if (safe == 0) {
34630 				js_ctx->p = p;
34631 				break;
34632 			}
34633 			safe--;
34634 
34635 			/* End of input (NUL) goes through slow path and causes SyntaxError. */
34636 			DUK_ASSERT(duk__json_decstr_lookup[0] == 0x00);
34637 
34638 			b = *p++;
34639 			x = (duk_small_int_t) duk__json_decstr_lookup[b];
34640 			if (DUK_LIKELY(x != 0)) {
34641 				/* Fast path, decode as is. */
34642 				*q++ = b;
34643 			} else if (b == DUK_ASC_DOUBLEQUOTE) {
34644 				js_ctx->p = p;
34645 				goto found_quote;
34646 			} else if (b == DUK_ASC_BACKSLASH) {
34647 				/* We've ensured space for one escaped input; then
34648 				 * bail out and recheck (this makes escape handling
34649 				 * quite slow but it's uncommon).
34650 				 */
34651 				js_ctx->p = p;
34652 				if (duk__dec_string_escape(js_ctx, &q) != 0) {
34653 					goto syntax_error;
34654 				}
34655 				break;
34656 			} else {
34657 				js_ctx->p = p;
34658 				goto syntax_error;
34659 			}
34660 		}
34661 	}
34662  found_quote:
34663 #else  /* DUK_USE_JSON_DECSTRING_FASTPATH */
34664 	for (;;) {
34665 		duk_uint8_t x;
34666 
34667 		q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, DUK_UNICODE_MAX_XUTF8_LENGTH, q);
34668 
34669 		x = duk__dec_get(js_ctx);
34670 
34671 		if (x == DUK_ASC_DOUBLEQUOTE) {
34672 			break;
34673 		} else if (x == DUK_ASC_BACKSLASH) {
34674 			if (duk__dec_string_escape(js_ctx, &q) != 0) {
34675 				goto syntax_error;
34676 			}
34677 		} else if (x < 0x20) {
34678 			/* catches EOF (NUL) */
34679 			goto syntax_error;
34680 		} else {
34681 			*q++ = (duk_uint8_t) x;
34682 		}
34683 	}
34684 #endif  /* DUK_USE_JSON_DECSTRING_FASTPATH */
34685 
34686 	DUK_BW_SETPTR_AND_COMPACT(js_ctx->thr, bw, q);
34687 	(void) duk_buffer_to_string(thr, -1);  /* Safe if input string is safe. */
34688 
34689 	/* [ ... str ] */
34690 
34691 	return;
34692 
34693  syntax_error:
34694 	duk__dec_syntax_error(js_ctx);
34695 	DUK_UNREACHABLE();
34696 }
34697 
34698 #if defined(DUK_USE_JX)
34699 /* Decode a plain string consisting entirely of identifier characters.
34700  * Used to parse plain keys (e.g. "foo: 123").
34701  */
duk__dec_plain_string(duk_json_dec_ctx * js_ctx)34702 DUK_LOCAL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx) {
34703 	duk_hthread *thr = js_ctx->thr;
34704 	const duk_uint8_t *p;
34705 	duk_small_int_t x;
34706 
34707 	/* Caller has already eaten the first char so backtrack one byte. */
34708 
34709 	js_ctx->p--;  /* safe */
34710 	p = js_ctx->p;
34711 
34712 	/* Here again we parse bytes, and non-ASCII UTF-8 will cause end of
34713 	 * parsing (which is correct except if there are non-shortest encodings).
34714 	 * There is also no need to check explicitly for end of input buffer as
34715 	 * the input is NUL padded and NUL will exit the parsing loop.
34716 	 *
34717 	 * Because no unescaping takes place, we can just scan to the end of the
34718 	 * plain string and intern from the input buffer.
34719 	 */
34720 
34721 	for (;;) {
34722 		x = *p;
34723 
34724 		/* There is no need to check the first character specially here
34725 		 * (i.e. reject digits): the caller only accepts valid initial
34726 		 * characters and won't call us if the first character is a digit.
34727 		 * This also ensures that the plain string won't be empty.
34728 		 */
34729 
34730 		if (!duk_unicode_is_identifier_part((duk_codepoint_t) x)) {
34731 			break;
34732 		}
34733 		p++;
34734 	}
34735 
34736 	duk_push_lstring(thr, (const char *) js_ctx->p, (duk_size_t) (p - js_ctx->p));
34737 	js_ctx->p = p;
34738 
34739 	/* [ ... str ] */
34740 }
34741 #endif  /* DUK_USE_JX */
34742 
34743 #if defined(DUK_USE_JX)
duk__dec_pointer(duk_json_dec_ctx * js_ctx)34744 DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) {
34745 	duk_hthread *thr = js_ctx->thr;
34746 	const duk_uint8_t *p;
34747 	duk_small_int_t x;
34748 	void *voidptr;
34749 
34750 	/* Caller has already eaten the first character ('(') which we don't need. */
34751 
34752 	p = js_ctx->p;
34753 
34754 	for (;;) {
34755 		x = *p;
34756 
34757 		/* Assume that the native representation never contains a closing
34758 		 * parenthesis.
34759 		 */
34760 
34761 		if (x == DUK_ASC_RPAREN) {
34762 			break;
34763 		} else if (x <= 0) {
34764 			/* NUL term or -1 (EOF), NUL check would suffice */
34765 			goto syntax_error;
34766 		}
34767 		p++;
34768 	}
34769 
34770 	/* There is no need to NUL delimit the sscanf() call: trailing garbage is
34771 	 * ignored and there is always a NUL terminator which will force an error
34772 	 * if no error is encountered before it.  It's possible that the scan
34773 	 * would scan further than between [js_ctx->p,p[ though and we'd advance
34774 	 * by less than the scanned value.
34775 	 *
34776 	 * Because pointers are platform specific, a failure to scan a pointer
34777 	 * results in a null pointer which is a better placeholder than a missing
34778 	 * value or an error.
34779 	 */
34780 
34781 	voidptr = NULL;
34782 	(void) DUK_SSCANF((const char *) js_ctx->p, DUK_STR_FMT_PTR, &voidptr);
34783 	duk_push_pointer(thr, voidptr);
34784 	js_ctx->p = p + 1;  /* skip ')' */
34785 
34786 	/* [ ... ptr ] */
34787 
34788 	return;
34789 
34790  syntax_error:
34791 	duk__dec_syntax_error(js_ctx);
34792 	DUK_UNREACHABLE();
34793 }
34794 #endif  /* DUK_USE_JX */
34795 
34796 #if defined(DUK_USE_JX)
duk__dec_buffer(duk_json_dec_ctx * js_ctx)34797 DUK_LOCAL void duk__dec_buffer(duk_json_dec_ctx *js_ctx) {
34798 	duk_hthread *thr = js_ctx->thr;
34799 	const duk_uint8_t *p;
34800 	duk_uint8_t *buf;
34801 	duk_size_t src_len;
34802 	duk_small_int_t x;
34803 
34804 	/* Caller has already eaten the first character ('|') which we don't need. */
34805 
34806 	p = js_ctx->p;
34807 
34808 	/* XXX: Would be nice to share the fast path loop from duk_hex_decode()
34809 	 * and avoid creating a temporary buffer.  However, there are some
34810 	 * differences which prevent trivial sharing:
34811 	 *
34812 	 *   - Pipe char detection
34813 	 *   - EOF detection
34814 	 *   - Unknown length of input and output
34815 	 *
34816 	 * The best approach here would be a bufwriter and a reasonaly sized
34817 	 * safe inner loop (e.g. 64 output bytes at a time).
34818 	 */
34819 
34820 	for (;;) {
34821 		x = *p;
34822 
34823 		/* This loop intentionally does not ensure characters are valid
34824 		 * ([0-9a-fA-F]) because the hex decode call below will do that.
34825 		 */
34826 		if (x == DUK_ASC_PIPE) {
34827 			break;
34828 		} else if (x <= 0) {
34829 			/* NUL term or -1 (EOF), NUL check would suffice */
34830 			goto syntax_error;
34831 		}
34832 		p++;
34833 	}
34834 
34835 	/* XXX: this is not very nice; unnecessary copy is made. */
34836 	src_len = (duk_size_t) (p - js_ctx->p);
34837 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, src_len);
34838 	DUK_ASSERT(buf != NULL);
34839 	duk_memcpy((void *) buf, (const void *) js_ctx->p, src_len);
34840 	duk_hex_decode(thr, -1);
34841 
34842 	js_ctx->p = p + 1;  /* skip '|' */
34843 
34844 	/* [ ... buf ] */
34845 
34846 	return;
34847 
34848  syntax_error:
34849 	duk__dec_syntax_error(js_ctx);
34850 	DUK_UNREACHABLE();
34851 }
34852 #endif  /* DUK_USE_JX */
34853 
34854 /* Parse a number, other than NaN or +/- Infinity */
duk__dec_number(duk_json_dec_ctx * js_ctx)34855 DUK_LOCAL void duk__dec_number(duk_json_dec_ctx *js_ctx) {
34856 	duk_hthread *thr = js_ctx->thr;
34857 	const duk_uint8_t *p_start;
34858 	const duk_uint8_t *p;
34859 	duk_uint8_t x;
34860 	duk_small_uint_t s2n_flags;
34861 
34862 	DUK_DDD(DUK_DDDPRINT("parse_number"));
34863 
34864 	p_start = js_ctx->p;
34865 
34866 	/* First pass parse is very lenient (e.g. allows '1.2.3') and extracts a
34867 	 * string for strict number parsing.
34868 	 */
34869 
34870 	p = js_ctx->p;
34871 	for (;;) {
34872 		x = *p;
34873 
34874 		DUK_DDD(DUK_DDDPRINT("parse_number: p_start=%p, p=%p, p_end=%p, x=%ld",
34875 		                     (const void *) p_start, (const void *) p,
34876 		                     (const void *) js_ctx->p_end, (long) x));
34877 
34878 #if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
34879 		/* This fast path is pretty marginal in practice.
34880 		 * XXX: candidate for removal.
34881 		 */
34882 		DUK_ASSERT(duk__json_decnumber_lookup[0x00] == 0x00);  /* end-of-input breaks */
34883 		if (duk__json_decnumber_lookup[x] == 0) {
34884 			break;
34885 		}
34886 #else  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
34887 		if (!((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
34888 		      (x == DUK_ASC_PERIOD || x == DUK_ASC_LC_E ||
34889 		       x == DUK_ASC_UC_E || x == DUK_ASC_MINUS || x == DUK_ASC_PLUS))) {
34890 			/* Plus sign must be accepted for positive exponents
34891 			 * (e.g. '1.5e+2').  This clause catches NULs.
34892 			 */
34893 			break;
34894 		}
34895 #endif  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
34896 		p++;  /* safe, because matched (NUL causes a break) */
34897 	}
34898 	js_ctx->p = p;
34899 
34900 	DUK_ASSERT(js_ctx->p > p_start);
34901 	duk_push_lstring(thr, (const char *) p_start, (duk_size_t) (p - p_start));
34902 
34903 	s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
34904 	            DUK_S2N_FLAG_ALLOW_MINUS |  /* but don't allow leading plus */
34905 	            DUK_S2N_FLAG_ALLOW_FRAC;
34906 
34907 	DUK_DDD(DUK_DDDPRINT("parse_number: string before parsing: %!T",
34908 	                     (duk_tval *) duk_get_tval(thr, -1)));
34909 	duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
34910 	if (duk_is_nan(thr, -1)) {
34911 		duk__dec_syntax_error(js_ctx);
34912 	}
34913 	DUK_ASSERT(duk_is_number(thr, -1));
34914 	DUK_DDD(DUK_DDDPRINT("parse_number: final number: %!T",
34915 	                     (duk_tval *) duk_get_tval(thr, -1)));
34916 
34917 	/* [ ... num ] */
34918 }
34919 
duk__dec_objarr_entry(duk_json_dec_ctx * js_ctx)34920 DUK_LOCAL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx) {
34921 	duk_hthread *thr = js_ctx->thr;
34922 	duk_require_stack(thr, DUK_JSON_DEC_REQSTACK);
34923 
34924 	/* c recursion check */
34925 
34926 	DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */
34927 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
34928 	if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
34929 		DUK_ERROR_RANGE(thr, DUK_STR_JSONDEC_RECLIMIT);
34930 		DUK_WO_NORETURN(return;);
34931 	}
34932 	js_ctx->recursion_depth++;
34933 }
34934 
duk__dec_objarr_exit(duk_json_dec_ctx * js_ctx)34935 DUK_LOCAL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx) {
34936 	/* c recursion check */
34937 
34938 	DUK_ASSERT(js_ctx->recursion_depth > 0);
34939 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
34940 	js_ctx->recursion_depth--;
34941 }
34942 
duk__dec_object(duk_json_dec_ctx * js_ctx)34943 DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) {
34944 	duk_hthread *thr = js_ctx->thr;
34945 	duk_int_t key_count;  /* XXX: a "first" flag would suffice */
34946 	duk_uint8_t x;
34947 
34948 	DUK_DDD(DUK_DDDPRINT("parse_object"));
34949 
34950 	duk__dec_objarr_entry(js_ctx);
34951 
34952 	duk_push_object(thr);
34953 
34954 	/* Initial '{' has been checked and eaten by caller. */
34955 
34956 	key_count = 0;
34957 	for (;;) {
34958 		x = duk__dec_get_nonwhite(js_ctx);
34959 
34960 		DUK_DDD(DUK_DDDPRINT("parse_object: obj=%!T, x=%ld, key_count=%ld",
34961 		                     (duk_tval *) duk_get_tval(thr, -1),
34962 		                     (long) x, (long) key_count));
34963 
34964 		/* handle comma and closing brace */
34965 
34966 		if (x == DUK_ASC_COMMA && key_count > 0) {
34967 			/* accept comma, expect new value */
34968 			x = duk__dec_get_nonwhite(js_ctx);
34969 		} else if (x == DUK_ASC_RCURLY) {
34970 			/* eat closing brace */
34971 			break;
34972 		} else if (key_count == 0) {
34973 			/* accept anything, expect first value (EOF will be
34974 			 * caught by key parsing below.
34975 			 */
34976 			;
34977 		} else {
34978 			/* catches EOF (NUL) and initial comma */
34979 			goto syntax_error;
34980 		}
34981 
34982 		/* parse key and value */
34983 
34984 		if (x == DUK_ASC_DOUBLEQUOTE) {
34985 			duk__dec_string(js_ctx);
34986 #if defined(DUK_USE_JX)
34987 		} else if (js_ctx->flag_ext_custom &&
34988 		           duk_unicode_is_identifier_start((duk_codepoint_t) x)) {
34989 			duk__dec_plain_string(js_ctx);
34990 #endif
34991 		} else {
34992 			goto syntax_error;
34993 		}
34994 
34995 		/* [ ... obj key ] */
34996 
34997 		x = duk__dec_get_nonwhite(js_ctx);
34998 		if (x != DUK_ASC_COLON) {
34999 			goto syntax_error;
35000 		}
35001 
35002 		duk__dec_value(js_ctx);
35003 
35004 		/* [ ... obj key val ] */
35005 
35006 		duk_xdef_prop_wec(thr, -3);
35007 
35008 		/* [ ... obj ] */
35009 
35010 		key_count++;
35011 	}
35012 
35013 	/* [ ... obj ] */
35014 
35015 	DUK_DDD(DUK_DDDPRINT("parse_object: final object is %!T",
35016 	                     (duk_tval *) duk_get_tval(thr, -1)));
35017 
35018 	duk__dec_objarr_exit(js_ctx);
35019 	return;
35020 
35021  syntax_error:
35022 	duk__dec_syntax_error(js_ctx);
35023 	DUK_UNREACHABLE();
35024 }
35025 
duk__dec_array(duk_json_dec_ctx * js_ctx)35026 DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) {
35027 	duk_hthread *thr = js_ctx->thr;
35028 	duk_uarridx_t arr_idx;
35029 	duk_uint8_t x;
35030 
35031 	DUK_DDD(DUK_DDDPRINT("parse_array"));
35032 
35033 	duk__dec_objarr_entry(js_ctx);
35034 
35035 	duk_push_array(thr);
35036 
35037 	/* Initial '[' has been checked and eaten by caller. */
35038 
35039 	arr_idx = 0;
35040 	for (;;) {
35041 		x = duk__dec_get_nonwhite(js_ctx);
35042 
35043 		DUK_DDD(DUK_DDDPRINT("parse_array: arr=%!T, x=%ld, arr_idx=%ld",
35044 		                     (duk_tval *) duk_get_tval(thr, -1),
35045 		                     (long) x, (long) arr_idx));
35046 
35047 		/* handle comma and closing bracket */
35048 
35049 		if ((x == DUK_ASC_COMMA) && (arr_idx != 0)) {
35050 			/* accept comma, expect new value */
35051 			;
35052 		} else if (x == DUK_ASC_RBRACKET) {
35053 			/* eat closing bracket */
35054 			break;
35055 		} else if (arr_idx == 0) {
35056 			/* accept anything, expect first value (EOF will be
35057 			 * caught by duk__dec_value() below.
35058 			 */
35059 			js_ctx->p--;  /* backtrack (safe) */
35060 		} else {
35061 			/* catches EOF (NUL) and initial comma */
35062 			goto syntax_error;
35063 		}
35064 
35065 		/* parse value */
35066 
35067 		duk__dec_value(js_ctx);
35068 
35069 		/* [ ... arr val ] */
35070 
35071 		duk_xdef_prop_index_wec(thr, -2, arr_idx);
35072 		arr_idx++;
35073 	}
35074 
35075 	/* Must set 'length' explicitly when using duk_xdef_prop_xxx() to
35076 	 * set the values.
35077 	 */
35078 
35079 	duk_set_length(thr, -1, arr_idx);
35080 
35081 	/* [ ... arr ] */
35082 
35083 	DUK_DDD(DUK_DDDPRINT("parse_array: final array is %!T",
35084 	                     (duk_tval *) duk_get_tval(thr, -1)));
35085 
35086 	duk__dec_objarr_exit(js_ctx);
35087 	return;
35088 
35089  syntax_error:
35090 	duk__dec_syntax_error(js_ctx);
35091 	DUK_UNREACHABLE();
35092 }
35093 
duk__dec_value(duk_json_dec_ctx * js_ctx)35094 DUK_LOCAL void duk__dec_value(duk_json_dec_ctx *js_ctx) {
35095 	duk_hthread *thr = js_ctx->thr;
35096 	duk_uint8_t x;
35097 
35098 	x = duk__dec_get_nonwhite(js_ctx);
35099 
35100 	DUK_DDD(DUK_DDDPRINT("parse_value: initial x=%ld", (long) x));
35101 
35102 	/* Note: duk__dec_req_stridx() backtracks one char */
35103 
35104 	if (x == DUK_ASC_DOUBLEQUOTE) {
35105 		duk__dec_string(js_ctx);
35106 	} else if ((x >= DUK_ASC_0 && x <= DUK_ASC_9) || (x == DUK_ASC_MINUS)) {
35107 #if defined(DUK_USE_JX)
35108 		if (js_ctx->flag_ext_custom && x == DUK_ASC_MINUS && duk__dec_peek(js_ctx) == DUK_ASC_UC_I) {
35109 			duk__dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY);  /* "-Infinity", '-' has been eaten */
35110 			duk_push_number(thr, -DUK_DOUBLE_INFINITY);
35111 		} else {
35112 #else
35113 		{  /* unconditional block */
35114 #endif
35115 			/* We already ate 'x', so backup one byte. */
35116 			js_ctx->p--;  /* safe */
35117 			duk__dec_number(js_ctx);
35118 		}
35119 	} else if (x == DUK_ASC_LC_T) {
35120 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_TRUE);
35121 		duk_push_true(thr);
35122 	} else if (x == DUK_ASC_LC_F) {
35123 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_FALSE);
35124 		duk_push_false(thr);
35125 	} else if (x == DUK_ASC_LC_N) {
35126 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_NULL);
35127 		duk_push_null(thr);
35128 #if defined(DUK_USE_JX)
35129 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_LC_U) {
35130 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_UNDEFINED);
35131 		duk_push_undefined(thr);
35132 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_N) {
35133 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_NAN);
35134 		duk_push_nan(thr);
35135 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_I) {
35136 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_INFINITY);
35137 		duk_push_number(thr, DUK_DOUBLE_INFINITY);
35138 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_LPAREN) {
35139 		duk__dec_pointer(js_ctx);
35140 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_PIPE) {
35141 		duk__dec_buffer(js_ctx);
35142 #endif
35143 	} else if (x == DUK_ASC_LCURLY) {
35144 		duk__dec_object(js_ctx);
35145 	} else if (x == DUK_ASC_LBRACKET) {
35146 		duk__dec_array(js_ctx);
35147 	} else {
35148 		/* catches EOF (NUL) */
35149 		goto syntax_error;
35150 	}
35151 
35152 	duk__dec_eat_white(js_ctx);
35153 
35154 	/* [ ... val ] */
35155 	return;
35156 
35157  syntax_error:
35158 	duk__dec_syntax_error(js_ctx);
35159 	DUK_UNREACHABLE();
35160 }
35161 
35162 /* Recursive value reviver, implements the Walk() algorithm.  No C recursion
35163  * check is done here because the initial parsing step will already ensure
35164  * there is a reasonable limit on C recursion depth and hence object depth.
35165  */
35166 DUK_LOCAL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) {
35167 	duk_hthread *thr = js_ctx->thr;
35168 	duk_hobject *h;
35169 	duk_uarridx_t i, arr_len;
35170 
35171 	DUK_DDD(DUK_DDDPRINT("walk: top=%ld, holder=%!T, name=%!T",
35172 	                     (long) duk_get_top(thr),
35173 	                     (duk_tval *) duk_get_tval(thr, -2),
35174 	                     (duk_tval *) duk_get_tval(thr, -1)));
35175 
35176 	duk_dup_top(thr);
35177 	duk_get_prop(thr, -3);  /* -> [ ... holder name val ] */
35178 
35179 	h = duk_get_hobject(thr, -1);
35180 	if (h != NULL) {
35181 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
35182 			arr_len = (duk_uarridx_t) duk_get_length(thr, -1);
35183 			for (i = 0; i < arr_len; i++) {
35184 				/* [ ... holder name val ] */
35185 
35186 				DUK_DDD(DUK_DDDPRINT("walk: array, top=%ld, i=%ld, arr_len=%ld, holder=%!T, name=%!T, val=%!T",
35187 				                     (long) duk_get_top(thr), (long) i, (long) arr_len,
35188 				                     (duk_tval *) duk_get_tval(thr, -3), (duk_tval *) duk_get_tval(thr, -2),
35189 				                     (duk_tval *) duk_get_tval(thr, -1)));
35190 
35191 				duk_dup_top(thr);
35192 				(void) duk_push_uint_to_hstring(thr, (duk_uint_t) i);  /* -> [ ... holder name val val ToString(i) ] */
35193 				duk__dec_reviver_walk(js_ctx);  /* -> [ ... holder name val new_elem ] */
35194 
35195 				if (duk_is_undefined(thr, -1)) {
35196 					duk_pop(thr);
35197 					duk_del_prop_index(thr, -1, i);
35198 				} else {
35199 					/* XXX: duk_xdef_prop_index_wec() would be more appropriate
35200 					 * here but it currently makes some assumptions that might
35201 					 * not hold (e.g. that previous property is not an accessor).
35202 					 */
35203 					duk_put_prop_index(thr, -2, i);
35204 				}
35205 			}
35206 		} else {
35207 			/* [ ... holder name val ] */
35208 			duk_enum(thr, -1, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);
35209 			while (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {
35210 				DUK_DDD(DUK_DDDPRINT("walk: object, top=%ld, holder=%!T, name=%!T, val=%!T, enum=%!iT, obj_key=%!T",
35211 				                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -5),
35212 				                     (duk_tval *) duk_get_tval(thr, -4), (duk_tval *) duk_get_tval(thr, -3),
35213 				                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
35214 
35215 				/* [ ... holder name val enum obj_key ] */
35216 				duk_dup_m3(thr);
35217 				duk_dup_m2(thr);
35218 
35219 				/* [ ... holder name val enum obj_key val obj_key ] */
35220 				duk__dec_reviver_walk(js_ctx);
35221 
35222 				/* [ ... holder name val enum obj_key new_elem ] */
35223 				if (duk_is_undefined(thr, -1)) {
35224 					duk_pop(thr);
35225 					duk_del_prop(thr, -3);
35226 				} else {
35227 					/* XXX: duk_xdef_prop_index_wec() would be more appropriate
35228 					 * here but it currently makes some assumptions that might
35229 					 * not hold (e.g. that previous property is not an accessor).
35230 					 *
35231 					 * Using duk_put_prop() works incorrectly with '__proto__'
35232 					 * if the own property with that name has been deleted.  This
35233 					 * does not happen normally, but a clever reviver can trigger
35234 					 * that, see complex reviver case in: test-bug-json-parse-__proto__.js.
35235 					 */
35236 					duk_put_prop(thr, -4);
35237 				}
35238 			}
35239 			duk_pop(thr);  /* pop enum */
35240 		}
35241 	}
35242 
35243 	/* [ ... holder name val ] */
35244 
35245 	duk_dup(thr, js_ctx->idx_reviver);
35246 	duk_insert(thr, -4);  /* -> [ ... reviver holder name val ] */
35247 	duk_call_method(thr, 2);  /* -> [ ... res ] */
35248 
35249 	DUK_DDD(DUK_DDDPRINT("walk: top=%ld, result=%!T",
35250 	                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -1)));
35251 }
35252 
35253 /*
35254  *  Stringify implementation.
35255  */
35256 
35257 #define DUK__EMIT_1(js_ctx,ch)          duk__emit_1((js_ctx), (duk_uint_fast8_t) (ch))
35258 #define DUK__EMIT_2(js_ctx,ch1,ch2)     duk__emit_2((js_ctx), (duk_uint_fast8_t) (ch1), (duk_uint_fast8_t) (ch2))
35259 #define DUK__EMIT_HSTR(js_ctx,h)        duk__emit_hstring((js_ctx), (h))
35260 #if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
35261 #define DUK__EMIT_CSTR(js_ctx,p)        duk__emit_cstring((js_ctx), (p))
35262 #endif
35263 #define DUK__EMIT_STRIDX(js_ctx,i)      duk__emit_stridx((js_ctx), (i))
35264 #define DUK__UNEMIT_1(js_ctx)           duk__unemit_1((js_ctx))
35265 
35266 DUK_LOCAL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch) {
35267 	DUK_BW_WRITE_ENSURE_U8(js_ctx->thr, &js_ctx->bw, ch);
35268 }
35269 
35270 DUK_LOCAL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2) {
35271 	DUK_BW_WRITE_ENSURE_U8_2(js_ctx->thr, &js_ctx->bw, ch1, ch2);
35272 }
35273 
35274 DUK_LOCAL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h) {
35275 	DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
35276 }
35277 
35278 #if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
35279 DUK_LOCAL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *str) {
35280 	DUK_BW_WRITE_ENSURE_CSTRING(js_ctx->thr, &js_ctx->bw, str);
35281 }
35282 #endif
35283 
35284 DUK_LOCAL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx) {
35285 	duk_hstring *h;
35286 
35287 	DUK_ASSERT_STRIDX_VALID(stridx);
35288 	h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
35289 	DUK_ASSERT(h != NULL);
35290 
35291 	DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
35292 }
35293 
35294 DUK_LOCAL void duk__unemit_1(duk_json_enc_ctx *js_ctx) {
35295 	DUK_ASSERT(DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw) >= 1);
35296 	DUK_BW_ADD_PTR(js_ctx->thr, &js_ctx->bw, -1);
35297 }
35298 
35299 #define DUK__MKESC(nybbles,esc1,esc2)  \
35300 	(((duk_uint_fast32_t) (nybbles)) << 16) | \
35301 	(((duk_uint_fast32_t) (esc1)) << 8) | \
35302 	((duk_uint_fast32_t) (esc2))
35303 
35304 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) {
35305 	duk_uint_fast32_t tmp;
35306 	duk_small_uint_t dig;
35307 
35308 	DUK_UNREF(js_ctx);
35309 
35310 	/* Caller ensures space for at least DUK__JSON_MAX_ESC_LEN. */
35311 
35312 	/* Select appropriate escape format automatically, and set 'tmp' to a
35313 	 * value encoding both the escape format character and the nybble count:
35314 	 *
35315 	 *   (nybble_count << 16) | (escape_char1) | (escape_char2)
35316 	 */
35317 
35318 #if defined(DUK_USE_JX)
35319 	if (DUK_LIKELY(cp < 0x100UL)) {
35320 		if (DUK_UNLIKELY(js_ctx->flag_ext_custom != 0U)) {
35321 			tmp = DUK__MKESC(2, DUK_ASC_BACKSLASH, DUK_ASC_LC_X);
35322 		} else {
35323 			tmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U);
35324 		}
35325 	} else
35326 #endif
35327 	if (DUK_LIKELY(cp < 0x10000UL)) {
35328 		tmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U);
35329 	} else {
35330 #if defined(DUK_USE_JX)
35331 		if (DUK_LIKELY(js_ctx->flag_ext_custom != 0U)) {
35332 			tmp = DUK__MKESC(8, DUK_ASC_BACKSLASH, DUK_ASC_UC_U);
35333 		} else
35334 #endif
35335 		{
35336 			/* In compatible mode and standard JSON mode, output
35337 			 * something useful for non-BMP characters.  This won't
35338 			 * roundtrip but will still be more or less readable and
35339 			 * more useful than an error.
35340 			 */
35341 			tmp = DUK__MKESC(8, DUK_ASC_UC_U, DUK_ASC_PLUS);
35342 		}
35343 	}
35344 
35345 	*q++ = (duk_uint8_t) ((tmp >> 8) & 0xff);
35346 	*q++ = (duk_uint8_t) (tmp & 0xff);
35347 
35348 	tmp = tmp >> 16;
35349 	while (tmp > 0) {
35350 		tmp--;
35351 		dig = (duk_small_uint_t) ((cp >> (4 * tmp)) & 0x0f);
35352 		*q++ = duk_lc_digits[dig];
35353 	}
35354 
35355 	return q;
35356 }
35357 
35358 DUK_LOCAL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k) {
35359 	const duk_int8_t *p, *p_start, *p_end;  /* Note: intentionally signed. */
35360 	duk_size_t k_len;
35361 	duk_codepoint_t cp;
35362 
35363 	DUK_ASSERT(k != NULL);
35364 
35365 	/* Accept ASCII strings which conform to identifier requirements
35366 	 * as being emitted without key quotes.  Since we only accept ASCII
35367 	 * there's no need for actual decoding: 'p' is intentionally signed
35368 	 * so that bytes >= 0x80 extend to negative values and are rejected
35369 	 * as invalid identifier codepoints.
35370 	 */
35371 
35372 	if (js_ctx->flag_avoid_key_quotes) {
35373 		k_len = DUK_HSTRING_GET_BYTELEN(k);
35374 		p_start = (const duk_int8_t *) DUK_HSTRING_GET_DATA(k);
35375 		p_end = p_start + k_len;
35376 		p = p_start;
35377 
35378 		if (p == p_end) {
35379 			/* Zero length string is not accepted without quotes */
35380 			goto quote_normally;
35381 		}
35382 		cp = (duk_codepoint_t) (*p++);
35383 		if (DUK_UNLIKELY(!duk_unicode_is_identifier_start(cp))) {
35384 			goto quote_normally;
35385 		}
35386 		while (p < p_end) {
35387 			cp = (duk_codepoint_t) (*p++);
35388 			if (DUK_UNLIKELY(!duk_unicode_is_identifier_part(cp))) {
35389 				goto quote_normally;
35390 			}
35391 		}
35392 
35393 		/* This seems faster than emitting bytes one at a time and
35394 		 * then potentially rewinding.
35395 		 */
35396 		DUK__EMIT_HSTR(js_ctx, k);
35397 		return;
35398 	}
35399 
35400  quote_normally:
35401 	duk__enc_quote_string(js_ctx, k);
35402 }
35403 
35404 /* The Quote(value) operation: quote a string.
35405  *
35406  * Stack policy: [ ] -> [ ].
35407  */
35408 
35409 DUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str) {
35410 	duk_hthread *thr = js_ctx->thr;
35411 	const duk_uint8_t *p, *p_start, *p_end, *p_now, *p_tmp;
35412 	duk_uint8_t *q;
35413 	duk_ucodepoint_t cp;  /* typed for duk_unicode_decode_xutf8() */
35414 
35415 	DUK_DDD(DUK_DDDPRINT("duk__enc_quote_string: h_str=%!O", (duk_heaphdr *) h_str));
35416 
35417 	DUK_ASSERT(h_str != NULL);
35418 	p_start = DUK_HSTRING_GET_DATA(h_str);
35419 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_str);
35420 	p = p_start;
35421 
35422 	DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE);
35423 
35424 	/* Encode string in small chunks, estimating the maximum expansion so that
35425 	 * there's no need to ensure space while processing the chunk.
35426 	 */
35427 
35428 	while (p < p_end) {
35429 		duk_size_t left, now, space;
35430 
35431 		left = (duk_size_t) (p_end - p);
35432 		now = (left > DUK__JSON_ENCSTR_CHUNKSIZE ?
35433 		       DUK__JSON_ENCSTR_CHUNKSIZE : left);
35434 
35435 		/* Maximum expansion per input byte is 6:
35436 		 *   - invalid UTF-8 byte causes "\uXXXX" to be emitted (6/1 = 6).
35437 		 *   - 2-byte UTF-8 encodes as "\uXXXX" (6/2 = 3).
35438 		 *   - 4-byte UTF-8 encodes as "\Uxxxxxxxx" (10/4 = 2.5).
35439 		 */
35440 		space = now * 6;
35441 		q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
35442 
35443 		p_now = p + now;
35444 
35445 		while (p < p_now) {
35446 #if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
35447 			duk_uint8_t b;
35448 
35449 			b = duk__json_quotestr_lookup[*p++];
35450 			if (DUK_LIKELY(b < 0x80)) {
35451 				/* Most input bytes go through here. */
35452 				*q++ = b;
35453 			} else if (b >= 0xa0) {
35454 				*q++ = DUK_ASC_BACKSLASH;
35455 				*q++ = (duk_uint8_t) (b - 0x80);
35456 			} else if (b == 0x80) {
35457 				cp = (duk_ucodepoint_t) (*(p - 1));
35458 				q = duk__emit_esc_auto_fast(js_ctx, cp, q);
35459 			} else if (b == 0x7f && js_ctx->flag_ascii_only) {
35460 				/* 0x7F is special */
35461 				DUK_ASSERT(b == 0x81);
35462 				cp = (duk_ucodepoint_t) 0x7f;
35463 				q = duk__emit_esc_auto_fast(js_ctx, cp, q);
35464 			} else {
35465 				DUK_ASSERT(b == 0x81);
35466 				p--;
35467 
35468 				/* slow path is shared */
35469 #else  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
35470 			cp = *p;
35471 
35472 			if (DUK_LIKELY(cp <= 0x7f)) {
35473 				/* ascii fast path: avoid decoding utf-8 */
35474 				p++;
35475 				if (cp == 0x22 || cp == 0x5c) {
35476 					/* double quote or backslash */
35477 					*q++ = DUK_ASC_BACKSLASH;
35478 					*q++ = (duk_uint8_t) cp;
35479 				} else if (cp < 0x20) {
35480 					duk_uint_fast8_t esc_char;
35481 
35482 					/* This approach is a bit shorter than a straight
35483 					 * if-else-ladder and also a bit faster.
35484 					 */
35485 					if (cp < (sizeof(duk__json_quotestr_esc) / sizeof(duk_uint8_t)) &&
35486 					    (esc_char = duk__json_quotestr_esc[cp]) != 0) {
35487 						*q++ = DUK_ASC_BACKSLASH;
35488 						*q++ = (duk_uint8_t) esc_char;
35489 					} else {
35490 						q = duk__emit_esc_auto_fast(js_ctx, cp, q);
35491 					}
35492 				} else if (cp == 0x7f && js_ctx->flag_ascii_only) {
35493 					q = duk__emit_esc_auto_fast(js_ctx, cp, q);
35494 				} else {
35495 					/* any other printable -> as is */
35496 					*q++ = (duk_uint8_t) cp;
35497 				}
35498 			} else {
35499 				/* slow path is shared */
35500 #endif  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
35501 
35502 				/* slow path decode */
35503 
35504 				/* If XUTF-8 decoding fails, treat the offending byte as a codepoint directly
35505 				 * and go forward one byte.  This is of course very lossy, but allows some kind
35506 				 * of output to be produced even for internal strings which don't conform to
35507 				 * XUTF-8.  All standard ECMAScript strings are always CESU-8, so this behavior
35508 				 * does not violate the ECMAScript specification.  The behavior is applied to
35509 				 * all modes, including ECMAScript standard JSON.  Because the current XUTF-8
35510 				 * decoding is not very strict, this behavior only really affects initial bytes
35511 				 * and truncated codepoints.
35512 				 *
35513 				 * Another alternative would be to scan forwards to start of next codepoint
35514 				 * (or end of input) and emit just one replacement codepoint.
35515 				 */
35516 
35517 				p_tmp = p;
35518 				if (!duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
35519 					/* Decode failed. */
35520 					cp = *p_tmp;
35521 					p = p_tmp + 1;
35522 				}
35523 
35524 #if defined(DUK_USE_NONSTD_JSON_ESC_U2028_U2029)
35525 				if (js_ctx->flag_ascii_only || cp == 0x2028 || cp == 0x2029) {
35526 #else
35527 				if (js_ctx->flag_ascii_only) {
35528 #endif
35529 					q = duk__emit_esc_auto_fast(js_ctx, cp, q);
35530 				} else {
35531 					/* as is */
35532 					DUK_RAW_WRITE_XUTF8(q, cp);
35533 				}
35534 			}
35535 		}
35536 
35537 		DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
35538 	}
35539 
35540 	DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE);
35541 }
35542 
35543 /* Encode a double (checked by caller) from stack top.  Stack top may be
35544  * replaced by serialized string but is not popped (caller does that).
35545  */
35546 DUK_LOCAL void duk__enc_double(duk_json_enc_ctx *js_ctx) {
35547 	duk_hthread *thr;
35548 	duk_tval *tv;
35549 	duk_double_t d;
35550 	duk_small_int_t c;
35551 	duk_small_int_t s;
35552 	duk_small_uint_t stridx;
35553 	duk_small_uint_t n2s_flags;
35554 	duk_hstring *h_str;
35555 
35556 	DUK_ASSERT(js_ctx != NULL);
35557 	thr = js_ctx->thr;
35558 	DUK_ASSERT(thr != NULL);
35559 
35560 	/* Caller must ensure 'tv' is indeed a double and not a fastint! */
35561 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
35562 	DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
35563 	d = DUK_TVAL_GET_DOUBLE(tv);
35564 
35565 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
35566 	s = (duk_small_int_t) DUK_SIGNBIT(d);
35567 	DUK_UNREF(s);
35568 
35569 	if (DUK_LIKELY(!(c == DUK_FP_INFINITE || c == DUK_FP_NAN))) {
35570 		DUK_ASSERT(DUK_ISFINITE(d));
35571 
35572 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
35573 		/* Negative zero needs special handling in JX/JC because
35574 		 * it would otherwise serialize to '0', not '-0'.
35575 		 */
35576 		if (DUK_UNLIKELY(c == DUK_FP_ZERO && s != 0 &&
35577 		                 (js_ctx->flag_ext_custom_or_compatible))) {
35578 			duk_push_hstring_stridx(thr, DUK_STRIDX_MINUS_ZERO);  /* '-0' */
35579 		} else
35580 #endif  /* DUK_USE_JX || DUK_USE_JC */
35581 		{
35582 			n2s_flags = 0;
35583 			/* [ ... number ] -> [ ... string ] */
35584 			duk_numconv_stringify(thr, 10 /*radix*/, 0 /*digits*/, n2s_flags);
35585 		}
35586 		h_str = duk_known_hstring(thr, -1);
35587 		DUK__EMIT_HSTR(js_ctx, h_str);
35588 		return;
35589 	}
35590 
35591 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
35592 	if (!(js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
35593 	                       DUK_JSON_FLAG_EXT_COMPATIBLE))) {
35594 		stridx = DUK_STRIDX_LC_NULL;
35595 	} else if (c == DUK_FP_NAN) {
35596 		stridx = js_ctx->stridx_custom_nan;
35597 	} else if (s == 0) {
35598 		stridx = js_ctx->stridx_custom_posinf;
35599 	} else {
35600 		stridx = js_ctx->stridx_custom_neginf;
35601 	}
35602 #else
35603 	stridx = DUK_STRIDX_LC_NULL;
35604 #endif
35605 	DUK__EMIT_STRIDX(js_ctx, stridx);
35606 }
35607 
35608 #if defined(DUK_USE_FASTINT)
35609 /* Encode a fastint from duk_tval ptr, no value stack effects. */
35610 DUK_LOCAL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
35611 	duk_int64_t v;
35612 
35613 	/* Fastint range is signed 48-bit so longest value is -2^47 = -140737488355328
35614 	 * (16 chars long), longest signed 64-bit value is -2^63 = -9223372036854775808
35615 	 * (20 chars long).  Alloc space for 64-bit range to be safe.
35616 	 */
35617 	duk_uint8_t buf[20 + 1];
35618 
35619 	/* Caller must ensure 'tv' is indeed a fastint! */
35620 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
35621 	v = DUK_TVAL_GET_FASTINT(tv);
35622 
35623 	/* XXX: There are no format strings in duk_config.h yet, could add
35624 	 * one for formatting duk_int64_t.  For now, assumes "%lld" and that
35625 	 * "long long" type exists.  Could also rely on C99 directly but that
35626 	 * won't work for older MSVC.
35627 	 */
35628 	DUK_SPRINTF((char *) buf, "%lld", (long long) v);
35629 	DUK__EMIT_CSTR(js_ctx, (const char *) buf);
35630 }
35631 #endif
35632 
35633 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
35634 #if defined(DUK_USE_HEX_FASTPATH)
35635 DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
35636 	duk_uint8_t *q;
35637 	duk_uint16_t *q16;
35638 	duk_small_uint_t x;
35639 	duk_size_t i, len_safe;
35640 #if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
35641 	duk_bool_t shift_dst;
35642 #endif
35643 
35644 	/* Unlike in duk_hex_encode() 'dst' is not necessarily aligned by 2.
35645 	 * For platforms where unaligned accesses are not allowed, shift 'dst'
35646 	 * ahead by 1 byte to get alignment and then duk_memmove() the result
35647 	 * in place.  The faster encoding loop makes up the difference.
35648 	 * There's always space for one extra byte because a terminator always
35649 	 * follows the hex data and that's been accounted for by the caller.
35650 	 */
35651 
35652 #if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
35653 	q16 = (duk_uint16_t *) (void *) dst;
35654 #else
35655 	shift_dst = (duk_bool_t) (((duk_size_t) dst) & 0x01U);
35656 	if (shift_dst) {
35657 		DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst not aligned -> step to dst + 1"));
35658 		q16 = (duk_uint16_t *) (void *) (dst + 1);
35659 	} else {
35660 		DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst is aligned"));
35661 		q16 = (duk_uint16_t *) (void *) dst;
35662 	}
35663 	DUK_ASSERT((((duk_size_t) q16) & 0x01U) == 0);
35664 #endif
35665 
35666 	len_safe = src_len & ~0x03U;
35667 	for (i = 0; i < len_safe; i += 4) {
35668 		q16[0] = duk_hex_enctab[src[i]];
35669 		q16[1] = duk_hex_enctab[src[i + 1]];
35670 		q16[2] = duk_hex_enctab[src[i + 2]];
35671 		q16[3] = duk_hex_enctab[src[i + 3]];
35672 		q16 += 4;
35673 	}
35674 	q = (duk_uint8_t *) q16;
35675 
35676 #if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
35677 	if (shift_dst) {
35678 		q--;
35679 		duk_memmove((void *) dst, (const void *) (dst + 1), 2 * len_safe);
35680 		DUK_ASSERT(dst + 2 * len_safe == q);
35681 	}
35682 #endif
35683 
35684 	for (; i < src_len; i++) {
35685 		x = src[i];
35686 		*q++ = duk_lc_digits[x >> 4];
35687 		*q++ = duk_lc_digits[x & 0x0f];
35688 	}
35689 
35690 	return q;
35691 }
35692 #else  /* DUK_USE_HEX_FASTPATH */
35693 DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
35694 	const duk_uint8_t *p;
35695 	const duk_uint8_t *p_end;
35696 	duk_uint8_t *q;
35697 	duk_small_uint_t x;
35698 
35699 	p = src;
35700 	p_end = src + src_len;
35701 	q = dst;
35702 	while (p != p_end) {
35703 		x = *p++;
35704 		*q++ = duk_lc_digits[x >> 4];
35705 		*q++ = duk_lc_digits[x & 0x0f];
35706 	}
35707 
35708 	return q;
35709 }
35710 #endif  /* DUK_USE_HEX_FASTPATH */
35711 
35712 DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len) {
35713 	duk_hthread *thr;
35714 	duk_uint8_t *q;
35715 	duk_size_t space;
35716 
35717 	thr = js_ctx->thr;
35718 
35719 	DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);  /* caller checks */
35720 	DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);
35721 
35722 	/* Buffer values are encoded in (lowercase) hex to make the
35723 	 * binary data readable.  Base64 or similar would be more
35724 	 * compact but less readable, and the point of JX/JC
35725 	 * variants is to be as useful to a programmer as possible.
35726 	 */
35727 
35728 	/* The #if defined() clutter here needs to handle the three
35729 	 * cases: (1) JX+JC, (2) JX only, (3) JC only.
35730 	 */
35731 
35732 	/* Note: space must cater for both JX and JC. */
35733 	space = 9 + buf_len * 2 + 2;
35734 	DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7ffffffeUL);
35735 	DUK_ASSERT((space - 2) / 2 >= buf_len);  /* overflow not possible, buffer limits */
35736 	q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
35737 
35738 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
35739 	if (js_ctx->flag_ext_custom)
35740 #endif
35741 #if defined(DUK_USE_JX)
35742 	{
35743 		*q++ = DUK_ASC_PIPE;
35744 		q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
35745 		*q++ = DUK_ASC_PIPE;
35746 
35747 	}
35748 #endif
35749 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
35750 	else
35751 #endif
35752 #if defined(DUK_USE_JC)
35753 	{
35754 		DUK_ASSERT(js_ctx->flag_ext_compatible);
35755 		duk_memcpy((void *) q, (const void *) "{\"_buf\":\"", 9);  /* len: 9 */
35756 		q += 9;
35757 		q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
35758 		*q++ = DUK_ASC_DOUBLEQUOTE;
35759 		*q++ = DUK_ASC_RCURLY;
35760 	}
35761 #endif
35762 
35763 	DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
35764 }
35765 
35766 DUK_LOCAL void duk__enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
35767 	duk__enc_buffer_data(js_ctx,
35768 	                     (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h),
35769 	                     (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
35770 }
35771 #endif  /* DUK_USE_JX || DUK_USE_JC */
35772 
35773 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
35774 DUK_LOCAL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
35775 	duk_size_t i, n;
35776 	const duk_uint8_t *buf;
35777 	duk_uint8_t *q;
35778 
35779 	n = DUK_HBUFFER_GET_SIZE(h);
35780 	if (n == 0) {
35781 		DUK__EMIT_2(js_ctx, DUK_ASC_LCURLY, DUK_ASC_RCURLY);
35782 		return;
35783 	}
35784 
35785 	DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
35786 
35787 	/* Maximum encoded length with 32-bit index: 1 + 10 + 2 + 3 + 1 + 1 = 18,
35788 	 * with 64-bit index: 1 + 20 + 2 + 3 + 1 + 1 = 28.  32 has some slack.
35789 	 *
35790 	 * Note that because the output buffer is reallocated from time to time,
35791 	 * side effects (such as finalizers) affecting the buffer 'h' must be
35792 	 * disabled.  This is the case in the JSON.stringify() fast path.
35793 	 */
35794 
35795 	buf = (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h);
35796 	if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
35797 		for (i = 0; i < n; i++) {
35798 			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth + 1);
35799 			q = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, 32);
35800 			q += DUK_SPRINTF((char *) q, "\"%lu\": %u,", (unsigned long) i, (unsigned int) buf[i]);
35801 			DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q);
35802 		}
35803 	} else {
35804 		q = DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw);
35805 		for (i = 0; i < n; i++) {
35806 			q = DUK_BW_ENSURE_RAW(js_ctx->thr, &js_ctx->bw, 32, q);
35807 			q += DUK_SPRINTF((char *) q, "\"%lu\":%u,", (unsigned long) i, (unsigned int) buf[i]);
35808 		}
35809 		DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q);
35810 	}
35811 	DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
35812 
35813 	if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
35814 		duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
35815 	}
35816 	DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
35817 }
35818 #endif  /* DUK_USE_JSON_STRINGIFY_FASTPATH */
35819 
35820 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
35821 DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) {
35822 	char buf[64];  /* XXX: how to figure correct size? */
35823 	const char *fmt;
35824 
35825 	DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);  /* caller checks */
35826 	DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);
35827 
35828 	duk_memzero(buf, sizeof(buf));
35829 
35830 	/* The #if defined() clutter here needs to handle the three
35831 	 * cases: (1) JX+JC, (2) JX only, (3) JC only.
35832 	 */
35833 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
35834 	if (js_ctx->flag_ext_custom)
35835 #endif
35836 #if defined(DUK_USE_JX)
35837 	{
35838 		fmt = ptr ? "(%p)" : "(null)";
35839 	}
35840 #endif
35841 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
35842 	else
35843 #endif
35844 #if defined(DUK_USE_JC)
35845 	{
35846 		DUK_ASSERT(js_ctx->flag_ext_compatible);
35847 		fmt = ptr ? "{\"_ptr\":\"%p\"}" : "{\"_ptr\":\"null\"}";
35848 	}
35849 #endif
35850 
35851 	/* When ptr == NULL, the format argument is unused. */
35852 	DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr);  /* must not truncate */
35853 	DUK__EMIT_CSTR(js_ctx, buf);
35854 }
35855 #endif  /* DUK_USE_JX || DUK_USE_JC */
35856 
35857 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
35858 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
35859 DUK_LOCAL void duk__enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj) {
35860 	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
35861 
35862 	if (h_bufobj->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
35863 		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
35864 	} else {
35865 		/* Handle both full and partial slice (as long as covered). */
35866 		duk__enc_buffer_data(js_ctx,
35867 		                     (duk_uint8_t *) DUK_HBUFOBJ_GET_SLICE_BASE(js_ctx->thr->heap, h_bufobj),
35868 		                     (duk_size_t) h_bufobj->length);
35869 	}
35870 }
35871 #endif  /* DUK_USE_JX || DUK_USE_JC */
35872 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
35873 
35874 /* Indent helper.  Calling code relies on js_ctx->recursion_depth also being
35875  * directly related to indent depth.
35876  */
35877 #if defined(DUK_USE_PREFER_SIZE)
35878 DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {
35879 	DUK_ASSERT(js_ctx->h_gap != NULL);
35880 	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0);  /* caller guarantees */
35881 
35882 	DUK__EMIT_1(js_ctx, 0x0a);
35883 	while (depth-- > 0) {
35884 		DUK__EMIT_HSTR(js_ctx, js_ctx->h_gap);
35885 	}
35886 }
35887 #else  /* DUK_USE_PREFER_SIZE */
35888 DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {
35889 	const duk_uint8_t *gap_data;
35890 	duk_size_t gap_len;
35891 	duk_size_t avail_bytes;   /* bytes of indent available for copying */
35892 	duk_size_t need_bytes;    /* bytes of indent still needed */
35893 	duk_uint8_t *p_start;
35894 	duk_uint8_t *p;
35895 
35896 	DUK_ASSERT(js_ctx->h_gap != NULL);
35897 	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0);  /* caller guarantees */
35898 
35899 	DUK__EMIT_1(js_ctx, 0x0a);
35900 	if (DUK_UNLIKELY(depth == 0)) {
35901 		return;
35902 	}
35903 
35904 	/* To handle deeper indents efficiently, make use of copies we've
35905 	 * already emitted.  In effect we can emit a sequence of 1, 2, 4,
35906 	 * 8, etc copies, and then finish the last run.  Byte counters
35907 	 * avoid multiply with gap_len on every loop.
35908 	 */
35909 
35910 	gap_data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(js_ctx->h_gap);
35911 	gap_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap);
35912 	DUK_ASSERT(gap_len > 0);
35913 
35914 	need_bytes = gap_len * depth;
35915 	p = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, need_bytes);
35916 	p_start = p;
35917 
35918 	duk_memcpy((void *) p, (const void *) gap_data, (size_t) gap_len);
35919 	p += gap_len;
35920 	avail_bytes = gap_len;
35921 	DUK_ASSERT(need_bytes >= gap_len);
35922 	need_bytes -= gap_len;
35923 
35924 	while (need_bytes >= avail_bytes) {
35925 		duk_memcpy((void *) p, (const void *) p_start, (size_t) avail_bytes);
35926 		p += avail_bytes;
35927 		need_bytes -= avail_bytes;
35928 		avail_bytes <<= 1;
35929 	}
35930 
35931 	DUK_ASSERT(need_bytes < avail_bytes);  /* need_bytes may be zero */
35932 	duk_memcpy((void *) p, (const void *) p_start, (size_t) need_bytes);
35933 	p += need_bytes;
35934 	/*avail_bytes += need_bytes*/
35935 
35936 	DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, p);
35937 }
35938 #endif  /* DUK_USE_PREFER_SIZE */
35939 
35940 /* Shared entry handling for object/array serialization. */
35941 DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
35942 	duk_hthread *thr = js_ctx->thr;
35943 	duk_hobject *h_target;
35944 	duk_uint_fast32_t i, n;
35945 
35946 	*entry_top = duk_get_top(thr);
35947 
35948 	duk_require_stack(thr, DUK_JSON_ENC_REQSTACK);
35949 
35950 	/* Loop check using a hybrid approach: a fixed-size visited[] array
35951 	 * with overflow in a loop check object.
35952 	 */
35953 
35954 	h_target = duk_known_hobject(thr, -1);  /* object or array */
35955 
35956 	n = js_ctx->recursion_depth;
35957 	if (DUK_UNLIKELY(n > DUK_JSON_ENC_LOOPARRAY)) {
35958 		n = DUK_JSON_ENC_LOOPARRAY;
35959 	}
35960 	for (i = 0; i < n; i++) {
35961 		if (DUK_UNLIKELY(js_ctx->visiting[i] == h_target)) {
35962 			DUK_DD(DUK_DDPRINT("slow path loop detect"));
35963 			DUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT);
35964 			DUK_WO_NORETURN(return;);
35965 		}
35966 	}
35967 	if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
35968 		js_ctx->visiting[js_ctx->recursion_depth] = h_target;
35969 	} else {
35970 		duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) h_target);
35971 		duk_dup_top(thr);  /* -> [ ... voidp voidp ] */
35972 		if (duk_has_prop(thr, js_ctx->idx_loop)) {
35973 			DUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT);
35974 			DUK_WO_NORETURN(return;);
35975 		}
35976 		duk_push_true(thr);  /* -> [ ... voidp true ] */
35977 		duk_put_prop(thr, js_ctx->idx_loop);  /* -> [ ... ] */
35978 	}
35979 
35980 	/* C recursion check. */
35981 
35982 	DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */
35983 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
35984 	if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
35985 		DUK_ERROR_RANGE(thr, DUK_STR_JSONENC_RECLIMIT);
35986 		DUK_WO_NORETURN(return;);
35987 	}
35988 	js_ctx->recursion_depth++;
35989 
35990 	DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
35991 	                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop)));
35992 }
35993 
35994 /* Shared exit handling for object/array serialization. */
35995 DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
35996 	duk_hthread *thr = js_ctx->thr;
35997 	duk_hobject *h_target;
35998 
35999 	/* C recursion check. */
36000 
36001 	DUK_ASSERT(js_ctx->recursion_depth > 0);
36002 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
36003 	js_ctx->recursion_depth--;
36004 
36005 	/* Loop check. */
36006 
36007 	h_target = duk_known_hobject(thr, *entry_top - 1);  /* original target at entry_top - 1 */
36008 
36009 	if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
36010 		/* Previous entry was inside visited[], nothing to do. */
36011 	} else {
36012 		duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) h_target);
36013 		duk_del_prop(thr, js_ctx->idx_loop);  /* -> [ ... ] */
36014 	}
36015 
36016 	/* Restore stack top after unbalanced code paths. */
36017 	duk_set_top(thr, *entry_top);
36018 
36019 	DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
36020 	                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop)));
36021 }
36022 
36023 /* The JO(value) operation: encode object.
36024  *
36025  * Stack policy: [ object ] -> [ object ].
36026  */
36027 DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {
36028 	duk_hthread *thr = js_ctx->thr;
36029 	duk_hstring *h_key;
36030 	duk_idx_t entry_top;
36031 	duk_idx_t idx_obj;
36032 	duk_idx_t idx_keys;
36033 	duk_bool_t emitted;
36034 	duk_uarridx_t arr_len, i;
36035 	duk_size_t prev_size;
36036 
36037 	DUK_DDD(DUK_DDDPRINT("duk__enc_object: obj=%!T", (duk_tval *) duk_get_tval(thr, -1)));
36038 
36039 	duk__enc_objarr_entry(js_ctx, &entry_top);
36040 
36041 	idx_obj = entry_top - 1;
36042 
36043 	if (js_ctx->idx_proplist >= 0) {
36044 		idx_keys = js_ctx->idx_proplist;
36045 	} else {
36046 		/* XXX: would be nice to enumerate an object at specified index */
36047 		duk_dup(thr, idx_obj);
36048 		(void) duk_hobject_get_enumerated_keys(thr, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);  /* [ ... target ] -> [ ... target keys ] */
36049 		idx_keys = duk_require_normalize_index(thr, -1);
36050 		/* leave stack unbalanced on purpose */
36051 	}
36052 
36053 	DUK_DDD(DUK_DDDPRINT("idx_keys=%ld, h_keys=%!T",
36054 	                     (long) idx_keys, (duk_tval *) duk_get_tval(thr, idx_keys)));
36055 
36056 	/* Steps 8-10 have been merged to avoid a "partial" variable. */
36057 
36058 	DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
36059 
36060 	/* XXX: keys is an internal object with all keys to be processed
36061 	 * in its (gapless) array part.  Because nobody can touch the keys
36062 	 * object, we could iterate its array part directly (keeping in mind
36063 	 * that it can be reallocated).
36064 	 */
36065 
36066 	arr_len = (duk_uarridx_t) duk_get_length(thr, idx_keys);
36067 	emitted = 0;
36068 	for (i = 0; i < arr_len; i++) {
36069 		duk_get_prop_index(thr, idx_keys, i);  /* -> [ ... key ] */
36070 
36071 		DUK_DDD(DUK_DDDPRINT("object property loop: holder=%!T, key=%!T",
36072 		                     (duk_tval *) duk_get_tval(thr, idx_obj),
36073 		                     (duk_tval *) duk_get_tval(thr, -1)));
36074 
36075 		h_key = duk_known_hstring(thr, -1);
36076 		DUK_ASSERT(h_key != NULL);
36077 		DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(h_key));  /* proplist filtering; enum options */
36078 
36079 		prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
36080 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36081 			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
36082 			duk__enc_key_autoquote(js_ctx, h_key);
36083 			DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
36084 		} else {
36085 			duk__enc_key_autoquote(js_ctx, h_key);
36086 			DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
36087 		}
36088 
36089 		/* [ ... key ] */
36090 
36091 		if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_obj) == 0)) {
36092 			/* Value would yield 'undefined', so skip key altogether.
36093 			 * Side effects have already happened.
36094 			 */
36095 			DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
36096 		} else {
36097 			DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
36098 			emitted = 1;
36099 		}
36100 
36101 		/* [ ... ] */
36102 	}
36103 
36104 	if (emitted) {
36105 		DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
36106 		DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
36107 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36108 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
36109 			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
36110 		}
36111 	}
36112 	DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
36113 
36114 	duk__enc_objarr_exit(js_ctx, &entry_top);
36115 
36116 	DUK_ASSERT_TOP(thr, entry_top);
36117 }
36118 
36119 /* The JA(value) operation: encode array.
36120  *
36121  * Stack policy: [ array ] -> [ array ].
36122  */
36123 DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) {
36124 	duk_hthread *thr = js_ctx->thr;
36125 	duk_idx_t entry_top;
36126 	duk_idx_t idx_arr;
36127 	duk_bool_t emitted;
36128 	duk_uarridx_t i, arr_len;
36129 
36130 	DUK_DDD(DUK_DDDPRINT("duk__enc_array: array=%!T",
36131 	                     (duk_tval *) duk_get_tval(thr, -1)));
36132 
36133 	duk__enc_objarr_entry(js_ctx, &entry_top);
36134 
36135 	idx_arr = entry_top - 1;
36136 
36137 	/* Steps 8-10 have been merged to avoid a "partial" variable. */
36138 
36139 	DUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET);
36140 
36141 	arr_len = (duk_uarridx_t) duk_get_length(thr, idx_arr);
36142 	emitted = 0;
36143 	for (i = 0; i < arr_len; i++) {
36144 		DUK_DDD(DUK_DDDPRINT("array entry loop: array=%!T, index=%ld, arr_len=%ld",
36145 		                     (duk_tval *) duk_get_tval(thr, idx_arr),
36146 		                     (long) i, (long) arr_len));
36147 
36148 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36149 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
36150 			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
36151 		}
36152 
36153 		(void) duk_push_uint_to_hstring(thr, (duk_uint_t) i);  /* -> [ ... key ] */
36154 
36155 		/* [ ... key ] */
36156 
36157 		if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_arr) == 0)) {
36158 			/* Value would normally be omitted, replace with 'null'. */
36159 			DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
36160 		} else {
36161 			;
36162 		}
36163 
36164 		/* [ ... ] */
36165 
36166 		DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
36167 		emitted = 1;
36168 	}
36169 
36170 	if (emitted) {
36171 		DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
36172 		DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
36173 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36174 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
36175 			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
36176 		}
36177 	}
36178 	DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
36179 
36180 	duk__enc_objarr_exit(js_ctx, &entry_top);
36181 
36182 	DUK_ASSERT_TOP(thr, entry_top);
36183 }
36184 
36185 /* The Str(key, holder) operation.
36186  *
36187  * Stack policy: [ ... key ] -> [ ... ]
36188  */
36189 DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder) {
36190 	duk_hthread *thr = js_ctx->thr;
36191 	duk_tval *tv;
36192 	duk_tval *tv_holder;
36193 	duk_tval *tv_key;
36194 	duk_small_int_t c;
36195 
36196 	DUK_DDD(DUK_DDDPRINT("duk__enc_value: idx_holder=%ld, holder=%!T, key=%!T",
36197 	                     (long) idx_holder, (duk_tval *) duk_get_tval(thr, idx_holder),
36198 	                     (duk_tval *) duk_get_tval(thr, -1)));
36199 
36200 	tv_holder = DUK_GET_TVAL_POSIDX(thr, idx_holder);
36201 	DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_holder));
36202 	tv_key = DUK_GET_TVAL_NEGIDX(thr, -1);
36203 	DUK_ASSERT(DUK_TVAL_IS_STRING(tv_key));
36204 	DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING(tv_key)));  /* Caller responsible. */
36205 	(void) duk_hobject_getprop(thr, tv_holder, tv_key);
36206 
36207 	/* -> [ ... key val ] */
36208 
36209 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
36210 
36211 	/* Standard JSON checks for .toJSON() only for actual objects; for
36212 	 * example, setting Number.prototype.toJSON and then serializing a
36213 	 * number won't invoke the .toJSON() method.  However, lightfuncs and
36214 	 * plain buffers mimic objects so we check for their .toJSON() method.
36215 	 */
36216 	if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |
36217 	                                 DUK_TYPE_MASK_LIGHTFUNC |
36218 	                                 DUK_TYPE_MASK_BUFFER)) {
36219 		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_JSON);
36220 		if (duk_is_callable(thr, -1)) {  /* toJSON() can also be a lightfunc */
36221 			DUK_DDD(DUK_DDDPRINT("value is object, has callable toJSON() -> call it"));
36222 			/* XXX: duk_dup_unvalidated(thr, -2) etc. */
36223 			duk_dup_m2(thr);          /* -> [ ... key val toJSON val ] */
36224 			duk_dup_m4(thr);          /* -> [ ... key val toJSON val key ] */
36225 			duk_call_method(thr, 1);  /* -> [ ... key val val' ] */
36226 			duk_remove_m2(thr);       /* -> [ ... key val' ] */
36227 		} else {
36228 			duk_pop(thr);             /* -> [ ... key val ] */
36229 		}
36230 	}
36231 
36232 	/* [ ... key val ] */
36233 
36234 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
36235 
36236 	if (js_ctx->h_replacer) {
36237 		/* XXX: Here a "slice copy" would be useful. */
36238 		DUK_DDD(DUK_DDDPRINT("replacer is set, call replacer"));
36239 		duk_push_hobject(thr, js_ctx->h_replacer);  /* -> [ ... key val replacer ] */
36240 		duk_dup(thr, idx_holder);                   /* -> [ ... key val replacer holder ] */
36241 		duk_dup_m4(thr);                            /* -> [ ... key val replacer holder key ] */
36242 		duk_dup_m4(thr);                            /* -> [ ... key val replacer holder key val ] */
36243 		duk_call_method(thr, 2);                    /* -> [ ... key val val' ] */
36244 		duk_remove_m2(thr);                         /* -> [ ... key val' ] */
36245 	}
36246 
36247 	/* [ ... key val ] */
36248 
36249 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
36250 
36251 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
36252 	if (DUK_TVAL_IS_OBJECT(tv)) {
36253 		duk_hobject *h;
36254 
36255 		h = DUK_TVAL_GET_OBJECT(tv);
36256 		DUK_ASSERT(h != NULL);
36257 
36258 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
36259 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36260 		if (DUK_HOBJECT_IS_BUFOBJ(h) &&
36261 		    js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE)) {
36262 			/* With JX/JC a bufferobject gets serialized specially. */
36263 			duk_hbufobj *h_bufobj;
36264 			h_bufobj = (duk_hbufobj *) h;
36265 			DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
36266 			duk__enc_bufobj(js_ctx, h_bufobj);
36267 			goto pop2_emitted;
36268 		}
36269 		/* Otherwise bufferobjects get serialized as normal objects. */
36270 #endif  /* JX || JC */
36271 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
36272 		c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
36273 		switch (c) {
36274 		case DUK_HOBJECT_CLASS_NUMBER: {
36275 			DUK_DDD(DUK_DDDPRINT("value is a Number object -> coerce with ToNumber()"));
36276 			duk_to_number_m1(thr);
36277 			/* The coercion potentially invokes user .valueOf() and .toString()
36278 			 * but can't result in a function value because ToPrimitive() would
36279 			 * reject such a result: test-dev-json-stringify-coercion-1.js.
36280 			 */
36281 			DUK_ASSERT(!duk_is_callable(thr, -1));
36282 			break;
36283 		}
36284 		case DUK_HOBJECT_CLASS_STRING: {
36285 			DUK_DDD(DUK_DDDPRINT("value is a String object -> coerce with ToString()"));
36286 			duk_to_string(thr, -1);
36287 			/* Same coercion behavior as for Number. */
36288 			DUK_ASSERT(!duk_is_callable(thr, -1));
36289 			break;
36290 		}
36291 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36292 		case DUK_HOBJECT_CLASS_POINTER:
36293 #endif
36294 		case DUK_HOBJECT_CLASS_BOOLEAN: {
36295 			DUK_DDD(DUK_DDDPRINT("value is a Boolean/Buffer/Pointer object -> get internal value"));
36296 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
36297 			duk_remove_m2(thr);
36298 			break;
36299 		}
36300 		default: {
36301 			/* Normal object which doesn't get automatically coerced to a
36302 			 * primitive value.  Functions are checked for specially.  The
36303 			 * primitive value coercions for Number, String, Pointer, and
36304 			 * Boolean can't result in functions so suffices to check here.
36305 			 * Symbol objects are handled like plain objects (their primitive
36306 			 * value is NOT looked up like for e.g. String objects).
36307 			 */
36308 			DUK_ASSERT(h != NULL);
36309 			if (DUK_HOBJECT_IS_CALLABLE(h)) {
36310 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36311 				if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
36312 				                     DUK_JSON_FLAG_EXT_COMPATIBLE)) {
36313 					/* We only get here when doing non-standard JSON encoding */
36314 					DUK_DDD(DUK_DDDPRINT("-> function allowed, serialize to custom format"));
36315 					DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);
36316 					DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
36317 					goto pop2_emitted;
36318 				} else {
36319 					DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
36320 					goto pop2_undef;
36321 				}
36322 #else  /* DUK_USE_JX || DUK_USE_JC */
36323 				DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
36324 				goto pop2_undef;
36325 #endif  /* DUK_USE_JX || DUK_USE_JC */
36326 			}
36327 		}
36328 		}  /* end switch */
36329 	}
36330 
36331 	/* [ ... key val ] */
36332 
36333 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
36334 
36335 	if (duk_check_type_mask(thr, -1, js_ctx->mask_for_undefined)) {
36336 		/* will result in undefined */
36337 		DUK_DDD(DUK_DDDPRINT("-> will result in undefined (type mask check)"));
36338 		goto pop2_undef;
36339 	}
36340 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
36341 
36342 	switch (DUK_TVAL_GET_TAG(tv)) {
36343 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36344 	/* When JX/JC not in use, the type mask above will avoid this case if needed. */
36345 	case DUK_TAG_UNDEFINED: {
36346 		DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
36347 		break;
36348 	}
36349 #endif
36350 	case DUK_TAG_NULL: {
36351 		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
36352 		break;
36353 	}
36354 	case DUK_TAG_BOOLEAN: {
36355 		DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?
36356 		                 DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
36357 		break;
36358 	}
36359 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36360 	/* When JX/JC not in use, the type mask above will avoid this case if needed. */
36361 	case DUK_TAG_POINTER: {
36362 		duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
36363 		break;
36364 	}
36365 #endif  /* DUK_USE_JX || DUK_USE_JC */
36366 	case DUK_TAG_STRING: {
36367 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
36368 		DUK_ASSERT(h != NULL);
36369 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
36370 			goto pop2_undef;
36371 		}
36372 		duk__enc_quote_string(js_ctx, h);
36373 		break;
36374 	}
36375 	case DUK_TAG_OBJECT: {
36376 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
36377 		DUK_ASSERT(h != NULL);
36378 
36379 		/* Function values are handled completely above (including
36380 		 * coercion results):
36381 		 */
36382 		DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE(h));
36383 
36384 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
36385 			duk__enc_array(js_ctx);
36386 		} else {
36387 			duk__enc_object(js_ctx);
36388 		}
36389 		break;
36390 	}
36391 	/* Because plain buffers mimics Uint8Array, they have enumerable
36392 	 * index properties [0,byteLength[.  Because JSON only serializes
36393 	 * enumerable own properties, no properties can be serialized for
36394 	 * plain buffers (all virtual properties are non-enumerable).  However,
36395 	 * there may be a .toJSON() method which was already handled above.
36396 	 */
36397 	case DUK_TAG_BUFFER: {
36398 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36399 		if (js_ctx->flag_ext_custom_or_compatible) {
36400 			duk__enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));
36401 			break;
36402 		}
36403 #endif
36404 
36405 		/* Could implement a fastpath, but the fast path would need
36406 		 * to handle realloc side effects correctly.
36407 		 */
36408 		duk_to_object(thr, -1);
36409 		duk__enc_object(js_ctx);
36410 		break;
36411 	}
36412 	case DUK_TAG_LIGHTFUNC: {
36413 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36414 		/* We only get here when doing non-standard JSON encoding */
36415 		DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);
36416 		DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
36417 #else
36418 		/* Standard JSON omits functions */
36419 		DUK_UNREACHABLE();
36420 #endif
36421 		break;
36422 	}
36423 #if defined(DUK_USE_FASTINT)
36424 	case DUK_TAG_FASTINT:
36425 		/* Number serialization has a significant impact relative to
36426 		 * other fast path code, so careful fast path for fastints.
36427 		 */
36428 		duk__enc_fastint_tval(js_ctx, tv);
36429 		break;
36430 #endif
36431 	default: {
36432 		/* number */
36433 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
36434 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
36435 		/* XXX: A fast path for usual integers would be useful when
36436 		 * fastint support is not enabled.
36437 		 */
36438 		duk__enc_double(js_ctx);
36439 		break;
36440 	}
36441 	}
36442 
36443 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36444  pop2_emitted:
36445 #endif
36446 	duk_pop_2(thr); /* [ ... key val ] -> [ ... ] */
36447 	return 1;  /* emitted */
36448 
36449  pop2_undef:
36450 	duk_pop_2(thr);  /* [ ... key val ] -> [ ... ] */
36451 	return 0;  /* not emitted */
36452 }
36453 
36454 /* E5 Section 15.12.3, main algorithm, step 4.b.ii steps 1-4. */
36455 DUK_LOCAL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv) {
36456 	duk_small_int_t c;
36457 
36458 	/* XXX: some kind of external internal type checker?
36459 	 * - type mask; symbol flag; class mask
36460 	 */
36461 	DUK_ASSERT(tv != NULL);
36462 	if (DUK_TVAL_IS_STRING(tv)) {
36463 		duk_hstring *h;
36464 		h = DUK_TVAL_GET_STRING(tv);
36465 		DUK_ASSERT(h != NULL);
36466 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
36467 			return 0;
36468 		}
36469 		return 1;
36470 	} else if (DUK_TVAL_IS_NUMBER(tv)) {
36471 		return 1;
36472 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
36473 		duk_hobject *h;
36474 		h = DUK_TVAL_GET_OBJECT(tv);
36475 		DUK_ASSERT(h != NULL);
36476 		c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
36477 		if (c == DUK_HOBJECT_CLASS_STRING || c == DUK_HOBJECT_CLASS_NUMBER) {
36478 			return 1;
36479 		}
36480 	}
36481 
36482 	return 0;
36483 }
36484 
36485 /*
36486  *  JSON.stringify() fast path
36487  *
36488  *  Otherwise supports full JSON, JX, and JC features, but bails out on any
36489  *  possible side effect which might change the value being serialized.  The
36490  *  fast path can take advantage of the fact that the value being serialized
36491  *  is unchanged so that we can walk directly through property tables etc.
36492  */
36493 
36494 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
36495 DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
36496 	duk_uint_fast32_t i, n;
36497 
36498 	DUK_DDD(DUK_DDDPRINT("stringify fast: %!T", tv));
36499 
36500 	DUK_ASSERT(js_ctx != NULL);
36501 	DUK_ASSERT(js_ctx->thr != NULL);
36502 
36503 #if 0 /* disabled for now */
36504  restart_match:
36505 #endif
36506 
36507 	DUK_ASSERT(tv != NULL);
36508 
36509 	switch (DUK_TVAL_GET_TAG(tv)) {
36510 	case DUK_TAG_UNDEFINED: {
36511 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36512 		if (js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible) {
36513 			DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
36514 			break;
36515 		} else {
36516 			goto emit_undefined;
36517 		}
36518 #else
36519 		goto emit_undefined;
36520 #endif
36521 	}
36522 	case DUK_TAG_NULL: {
36523 		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
36524 		break;
36525 	}
36526 	case DUK_TAG_BOOLEAN: {
36527 		DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?
36528 		                 DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
36529 		break;
36530 	}
36531 	case DUK_TAG_STRING: {
36532 		duk_hstring *h;
36533 		h = DUK_TVAL_GET_STRING(tv);
36534 		DUK_ASSERT(h != NULL);
36535 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
36536 			goto emit_undefined;
36537 		}
36538 		duk__enc_quote_string(js_ctx, h);
36539 		break;
36540 	}
36541 	case DUK_TAG_OBJECT: {
36542 		duk_hobject *obj;
36543 		duk_tval *tv_val;
36544 		duk_bool_t emitted = 0;
36545 		duk_uint32_t c_bit, c_all, c_array, c_unbox, c_undef,
36546 		             c_func, c_bufobj, c_object, c_abort;
36547 
36548 		/* For objects JSON.stringify() only looks for own, enumerable
36549 		 * properties which is nice for the fast path here.
36550 		 *
36551 		 * For arrays JSON.stringify() uses [[Get]] so it will actually
36552 		 * inherit properties during serialization!  This fast path
36553 		 * supports gappy arrays as long as there's no actual inherited
36554 		 * property (which might be a getter etc).
36555 		 *
36556 		 * Since recursion only happens for objects, we can have both
36557 		 * recursion and loop checks here.  We use a simple, depth-limited
36558 		 * loop check in the fast path because the object-based tracking
36559 		 * is very slow (when tested, it accounted for 50% of fast path
36560 		 * execution time for input data with a lot of small objects!).
36561 		 */
36562 
36563 		/* XXX: for real world code, could just ignore array inheritance
36564 		 * and only look at array own properties.
36565 		 */
36566 
36567 		/* We rely on a few object flag / class number relationships here,
36568 		 * assert for them.
36569 		 */
36570 
36571 		obj = DUK_TVAL_GET_OBJECT(tv);
36572 		DUK_ASSERT(obj != NULL);
36573 		DUK_ASSERT_HOBJECT_VALID(obj);
36574 
36575 		/* Once recursion depth is increased, exit path must decrease
36576 		 * it (though it's OK to abort the fast path).
36577 		 */
36578 
36579 		DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */
36580 		DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
36581 		if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
36582 			DUK_DD(DUK_DDPRINT("fast path recursion limit"));
36583 			DUK_ERROR_RANGE(js_ctx->thr, DUK_STR_JSONDEC_RECLIMIT);
36584 			DUK_WO_NORETURN(return 0;);
36585 		}
36586 
36587 		for (i = 0, n = (duk_uint_fast32_t) js_ctx->recursion_depth; i < n; i++) {
36588 			if (DUK_UNLIKELY(js_ctx->visiting[i] == obj)) {
36589 				DUK_DD(DUK_DDPRINT("fast path loop detect"));
36590 				DUK_ERROR_TYPE(js_ctx->thr, DUK_STR_CYCLIC_INPUT);
36591 				DUK_WO_NORETURN(return 0;);
36592 			}
36593 		}
36594 
36595 		/* Guaranteed by recursion_limit setup so we don't have to
36596 		 * check twice.
36597 		 */
36598 		DUK_ASSERT(js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY);
36599 		js_ctx->visiting[js_ctx->recursion_depth] = obj;
36600 		js_ctx->recursion_depth++;
36601 
36602 		/* If object has a .toJSON() property, we can't be certain
36603 		 * that it wouldn't mutate any value arbitrarily, so bail
36604 		 * out of the fast path.
36605 		 *
36606 		 * If an object is a Proxy we also can't avoid side effects
36607 		 * so abandon.
36608 		 */
36609 		/* XXX: non-callable .toJSON() doesn't need to cause an abort
36610 		 * but does at the moment, probably not worth fixing.
36611 		 */
36612 		if (duk_hobject_hasprop_raw(js_ctx->thr, obj, DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr)) ||
36613 		    DUK_HOBJECT_IS_PROXY(obj)) {
36614 			DUK_DD(DUK_DDPRINT("object has a .toJSON property or object is a Proxy, abort fast path"));
36615 			goto abort_fastpath;
36616 		}
36617 
36618 		/* We could use a switch-case for the class number but it turns out
36619 		 * a small if-else ladder on class masks is better.  The if-ladder
36620 		 * should be in order of relevancy.
36621 		 */
36622 
36623 		/* XXX: move masks to js_ctx? they don't change during one
36624 		 * fast path invocation.
36625 		 */
36626 		DUK_ASSERT(DUK_HOBJECT_CLASS_MAX <= 31);
36627 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36628 		if (js_ctx->flag_ext_custom_or_compatible) {
36629 			c_all = DUK_HOBJECT_CMASK_ALL;
36630 			c_array = DUK_HOBJECT_CMASK_ARRAY;
36631 			c_unbox = DUK_HOBJECT_CMASK_NUMBER |
36632 			          DUK_HOBJECT_CMASK_STRING |
36633 			          DUK_HOBJECT_CMASK_BOOLEAN |
36634 			          DUK_HOBJECT_CMASK_POINTER;  /* Symbols are not unboxed. */
36635 			c_func = DUK_HOBJECT_CMASK_FUNCTION;
36636 			c_bufobj = DUK_HOBJECT_CMASK_ALL_BUFOBJS;
36637 			c_undef = 0;
36638 			c_abort = 0;
36639 			c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef | c_abort);
36640 		}
36641 		else
36642 #endif
36643 		{
36644 			c_all = DUK_HOBJECT_CMASK_ALL;
36645 			c_array = DUK_HOBJECT_CMASK_ARRAY;
36646 			c_unbox = DUK_HOBJECT_CMASK_NUMBER |
36647 			          DUK_HOBJECT_CMASK_STRING |
36648 			          DUK_HOBJECT_CMASK_BOOLEAN;  /* Symbols are not unboxed. */
36649 			c_func = 0;
36650 			c_bufobj = 0;
36651 			c_undef = DUK_HOBJECT_CMASK_FUNCTION |
36652 			          DUK_HOBJECT_CMASK_POINTER;
36653 			/* As the fast path doesn't currently properly support
36654 			 * duk_hbufobj virtual properties, abort fast path if
36655 			 * we encounter them in plain JSON mode.
36656 			 */
36657 			c_abort = DUK_HOBJECT_CMASK_ALL_BUFOBJS;
36658 			c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef | c_abort);
36659 		}
36660 
36661 		c_bit = (duk_uint32_t) DUK_HOBJECT_GET_CLASS_MASK(obj);
36662 		if (c_bit & c_object) {
36663 			/* All other object types. */
36664 			DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
36665 
36666 			/* A non-Array object should not have an array part in practice.
36667 			 * But since it is supported internally (and perhaps used at some
36668 			 * point), check and abandon if that's the case.
36669 			 */
36670 			if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
36671 				DUK_DD(DUK_DDPRINT("non-Array object has array part, abort fast path"));
36672 				goto abort_fastpath;
36673 			}
36674 
36675 			for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(obj); i++) {
36676 				duk_hstring *k;
36677 				duk_size_t prev_size;
36678 
36679 				k = DUK_HOBJECT_E_GET_KEY(js_ctx->thr->heap, obj, i);
36680 				if (!k) {
36681 					continue;
36682 				}
36683 				if (DUK_HSTRING_HAS_ARRIDX(k)) {
36684 					/* If an object has array index keys we would need
36685 					 * to sort them into the ES2015 enumeration order to
36686 					 * be consistent with the slow path.  Abort the fast
36687 					 * path and handle in the slow path for now.
36688 					 */
36689 					DUK_DD(DUK_DDPRINT("property key is an array index, abort fast path"));
36690 					goto abort_fastpath;
36691 				}
36692 				if (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(js_ctx->thr->heap, obj, i)) {
36693 					continue;
36694 				}
36695 				if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(js_ctx->thr->heap, obj, i)) {
36696 					/* Getter might have arbitrary side effects,
36697 					 * so bail out.
36698 					 */
36699 					DUK_DD(DUK_DDPRINT("property is an accessor, abort fast path"));
36700 					goto abort_fastpath;
36701 				}
36702 				if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(k))) {
36703 					continue;
36704 				}
36705 
36706 				tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(js_ctx->thr->heap, obj, i);
36707 
36708 				prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
36709 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36710 					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
36711 					duk__enc_key_autoquote(js_ctx, k);
36712 					DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
36713 				} else {
36714 					duk__enc_key_autoquote(js_ctx, k);
36715 					DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
36716 				}
36717 
36718 				if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) {
36719 					DUK_DD(DUK_DDPRINT("prop value not supported, rewind key and colon"));
36720 					DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
36721 				} else {
36722 					DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
36723 					emitted = 1;
36724 				}
36725 			}
36726 
36727 			/* If any non-Array value had enumerable virtual own
36728 			 * properties, they should be serialized here (actually,
36729 			 * before the explicit properties).  Standard types don't.
36730 			 */
36731 
36732 			if (emitted) {
36733 				DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
36734 				DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
36735 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36736 					DUK_ASSERT(js_ctx->recursion_depth >= 1);
36737 					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
36738 				}
36739 			}
36740 			DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
36741 		} else if (c_bit & c_array) {
36742 			duk_uint_fast32_t arr_len;
36743 			duk_uint_fast32_t asize;
36744 
36745 			DUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET);
36746 
36747 			/* Assume arrays are dense in the fast path. */
36748 			if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
36749 				DUK_DD(DUK_DDPRINT("Array object is sparse, abort fast path"));
36750 				goto abort_fastpath;
36751 			}
36752 
36753 			arr_len = (duk_uint_fast32_t) ((duk_harray *) obj)->length;
36754 			asize = (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(obj);
36755 			/* Array part may be larger than 'length'; if so, iterate
36756 			 * only up to array 'length'.  Array part may also be smaller
36757 			 * than 'length' in some cases.
36758 			 */
36759 			for (i = 0; i < arr_len; i++) {
36760 				duk_tval *tv_arrval;
36761 				duk_hstring *h_tmp;
36762 				duk_bool_t has_inherited;
36763 
36764 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36765 					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
36766 				}
36767 
36768 				if (DUK_LIKELY(i < asize)) {
36769 					tv_arrval = DUK_HOBJECT_A_GET_VALUE_PTR(js_ctx->thr->heap, obj, i);
36770 					if (DUK_LIKELY(!DUK_TVAL_IS_UNUSED(tv_arrval))) {
36771 						/* Expected case: element is present. */
36772 						if (duk__json_stringify_fast_value(js_ctx, tv_arrval) == 0) {
36773 							DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
36774 						}
36775 						goto elem_done;
36776 					}
36777 				}
36778 
36779 				/* Gap in array; check for inherited property,
36780 				 * bail out if one exists.  This should be enough
36781 				 * to support gappy arrays for all practical code.
36782 				 */
36783 
36784 				h_tmp = duk_push_uint_to_hstring(js_ctx->thr, (duk_uint_t) i);
36785 				has_inherited = duk_hobject_hasprop_raw(js_ctx->thr, obj, h_tmp);
36786 				duk_pop(js_ctx->thr);
36787 				if (has_inherited) {
36788 					DUK_D(DUK_DPRINT("gap in array, conflicting inherited property, abort fast path"));
36789 					goto abort_fastpath;
36790 				}
36791 
36792 				/* Ordinary gap, undefined encodes to 'null' in
36793 				 * standard JSON, but JX/JC use their form for
36794 				 * undefined to better preserve the typing.
36795 				 */
36796 				DUK_D(DUK_DPRINT("gap in array, no conflicting inherited property, remain on fast path"));
36797 #if defined(DUK_USE_JX)
36798 				DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
36799 #else
36800 				DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
36801 #endif
36802 				/* fall through */
36803 
36804 			 elem_done:
36805 				DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
36806 				emitted = 1;
36807 			}
36808 
36809 			if (emitted) {
36810 				DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
36811 				DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
36812 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36813 					DUK_ASSERT(js_ctx->recursion_depth >= 1);
36814 					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
36815 				}
36816 			}
36817 			DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
36818 		} else if (c_bit & c_unbox) {
36819 			/* Certain boxed types are required to go through
36820 			 * automatic unboxing.  Rely on internal value being
36821 			 * sane (to avoid infinite recursion).
36822 			 */
36823 			DUK_ASSERT((c_bit & DUK_HOBJECT_CMASK_SYMBOL) == 0);  /* Symbols are not unboxed. */
36824 
36825 #if 1
36826 			/* The code below is incorrect if .toString() or .valueOf() have
36827 			 * have been overridden.  The correct approach would be to look up
36828 			 * the method(s) and if they resolve to the built-in function we
36829 			 * can safely bypass it and look up the internal value directly.
36830 			 * Unimplemented for now, abort fast path for boxed values.
36831 			 */
36832 			goto abort_fastpath;
36833 #else  /* disabled */
36834 			/* Disabled until fixed, see above. */
36835 			duk_tval *tv_internal;
36836 
36837 			DUK_DD(DUK_DDPRINT("auto unboxing in fast path"));
36838 
36839 			tv_internal = duk_hobject_get_internal_value_tval_ptr(js_ctx->thr->heap, obj);
36840 			DUK_ASSERT(tv_internal != NULL);
36841 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv_internal) ||
36842 			           DUK_TVAL_IS_NUMBER(tv_internal) ||
36843 			           DUK_TVAL_IS_BOOLEAN(tv_internal) ||
36844 			           DUK_TVAL_IS_POINTER(tv_internal));
36845 
36846 			tv = tv_internal;
36847 			DUK_ASSERT(js_ctx->recursion_depth > 0);
36848 			js_ctx->recursion_depth--;  /* required to keep recursion depth correct */
36849 			goto restart_match;
36850 #endif  /* disabled */
36851 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36852 		} else if (c_bit & c_func) {
36853 			DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
36854 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
36855 		} else if (c_bit & c_bufobj) {
36856 			duk__enc_bufobj(js_ctx, (duk_hbufobj *) obj);
36857 #endif
36858 #endif
36859 		} else if (c_bit & c_abort) {
36860 			DUK_DD(DUK_DDPRINT("abort fast path for unsupported type"));
36861 			goto abort_fastpath;
36862 		} else {
36863 			DUK_ASSERT((c_bit & c_undef) != 0);
36864 
36865 			/* Must decrease recursion depth before returning. */
36866 			DUK_ASSERT(js_ctx->recursion_depth > 0);
36867 			DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
36868 			js_ctx->recursion_depth--;
36869 			goto emit_undefined;
36870 		}
36871 
36872 		DUK_ASSERT(js_ctx->recursion_depth > 0);
36873 		DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
36874 		js_ctx->recursion_depth--;
36875 		break;
36876 	}
36877 	case DUK_TAG_BUFFER: {
36878 		/* Plain buffers are treated like Uint8Arrays: they have
36879 		 * enumerable indices.  Other virtual properties are not
36880 		 * enumerable, and inherited properties are not serialized.
36881 		 * However, there can be a replacer (not relevant here) or
36882 		 * a .toJSON() method (which we need to check for explicitly).
36883 		 */
36884 
36885 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
36886 		if (duk_hobject_hasprop_raw(js_ctx->thr,
36887 		                            js_ctx->thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE],
36888 		                            DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr))) {
36889 			DUK_DD(DUK_DDPRINT("value is a plain buffer and there's an inherited .toJSON, abort fast path"));
36890 			goto abort_fastpath;
36891 		}
36892 #endif
36893 
36894 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36895 		if (js_ctx->flag_ext_custom_or_compatible) {
36896 			duk__enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));
36897 			break;
36898 		}
36899 #endif
36900 
36901 		/* Plain buffers mimic Uint8Arrays, and have enumerable index
36902 		 * properties.
36903 		 */
36904 		duk__enc_buffer_json_fastpath(js_ctx, DUK_TVAL_GET_BUFFER(tv));
36905 		break;
36906 	}
36907 	case DUK_TAG_POINTER: {
36908 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36909 		if (js_ctx->flag_ext_custom_or_compatible) {
36910 			duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
36911 			break;
36912 		} else {
36913 			goto emit_undefined;
36914 		}
36915 #else
36916 		goto emit_undefined;
36917 #endif
36918 	}
36919 	case DUK_TAG_LIGHTFUNC: {
36920 		/* A lightfunc might also inherit a .toJSON() so just bail out. */
36921 		/* XXX: Could just lookup .toJSON() and continue in fast path,
36922 		 * as it would almost never be defined.
36923 		 */
36924 		DUK_DD(DUK_DDPRINT("value is a lightfunc, abort fast path"));
36925 		goto abort_fastpath;
36926 	}
36927 #if defined(DUK_USE_FASTINT)
36928 	case DUK_TAG_FASTINT: {
36929 		/* Number serialization has a significant impact relative to
36930 		 * other fast path code, so careful fast path for fastints.
36931 		 */
36932 		duk__enc_fastint_tval(js_ctx, tv);
36933 		break;
36934 	}
36935 #endif
36936 	default: {
36937 		/* XXX: A fast path for usual integers would be useful when
36938 		 * fastint support is not enabled.
36939 		 */
36940 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
36941 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
36942 
36943 		/* XXX: Stack discipline is annoying, could be changed in numconv. */
36944 		duk_push_tval(js_ctx->thr, tv);
36945 		duk__enc_double(js_ctx);
36946 		duk_pop(js_ctx->thr);
36947 
36948 #if 0
36949 		/* Could also rely on native sprintf(), but it will handle
36950 		 * values like NaN, Infinity, -0, exponent notation etc in
36951 		 * a JSON-incompatible way.
36952 		 */
36953 		duk_double_t d;
36954 		char buf[64];
36955 
36956 		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
36957 		d = DUK_TVAL_GET_DOUBLE(tv);
36958 		DUK_SPRINTF(buf, "%lg", d);
36959 		DUK__EMIT_CSTR(js_ctx, buf);
36960 #endif
36961 	}
36962 	}
36963 	return 1;  /* not undefined */
36964 
36965  emit_undefined:
36966 	return 0;  /* value was undefined/unsupported */
36967 
36968  abort_fastpath:
36969 	/* Error message doesn't matter: the error is ignored anyway. */
36970 	DUK_DD(DUK_DDPRINT("aborting fast path"));
36971 	DUK_ERROR_INTERNAL(js_ctx->thr);
36972 	DUK_WO_NORETURN(return 0;);
36973 }
36974 
36975 DUK_LOCAL duk_ret_t duk__json_stringify_fast(duk_hthread *thr, void *udata) {
36976 	duk_json_enc_ctx *js_ctx;
36977 	duk_tval *tv;
36978 
36979 	DUK_ASSERT(thr != NULL);
36980 	DUK_ASSERT(udata != NULL);
36981 
36982 	js_ctx = (duk_json_enc_ctx *) udata;
36983 	DUK_ASSERT(js_ctx != NULL);
36984 
36985 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
36986 	if (duk__json_stringify_fast_value(js_ctx, tv) == 0) {
36987 		DUK_DD(DUK_DDPRINT("top level value not supported, fail fast path"));
36988 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);  /* Error message is ignored, so doesn't matter. */
36989 	}
36990 
36991 	return 0;
36992 }
36993 #endif  /* DUK_USE_JSON_STRINGIFY_FASTPATH */
36994 
36995 /*
36996  *  Top level wrappers
36997  */
36998 
36999 DUK_INTERNAL
37000 void duk_bi_json_parse_helper(duk_hthread *thr,
37001                               duk_idx_t idx_value,
37002                               duk_idx_t idx_reviver,
37003                               duk_small_uint_t flags) {
37004 	duk_json_dec_ctx js_ctx_alloc;
37005 	duk_json_dec_ctx *js_ctx = &js_ctx_alloc;
37006 	duk_hstring *h_text;
37007 #if defined(DUK_USE_ASSERTIONS)
37008 	duk_idx_t entry_top = duk_get_top(thr);
37009 #endif
37010 
37011 	/* negative top-relative indices not allowed now */
37012 	DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
37013 	DUK_ASSERT(idx_reviver == DUK_INVALID_INDEX || idx_reviver >= 0);
37014 
37015 	DUK_DDD(DUK_DDDPRINT("JSON parse start: text=%!T, reviver=%!T, flags=0x%08lx, stack_top=%ld",
37016 	                     (duk_tval *) duk_get_tval(thr, idx_value),
37017 	                     (duk_tval *) duk_get_tval(thr, idx_reviver),
37018 	                     (unsigned long) flags,
37019 	                     (long) duk_get_top(thr)));
37020 
37021 	duk_memzero(&js_ctx_alloc, sizeof(js_ctx_alloc));
37022 	js_ctx->thr = thr;
37023 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
37024 	/* nothing now */
37025 #endif
37026 	js_ctx->recursion_limit = DUK_USE_JSON_DEC_RECLIMIT;
37027 	DUK_ASSERT(js_ctx->recursion_depth == 0);
37028 
37029 	/* Flag handling currently assumes that flags are consistent.  This is OK
37030 	 * because the call sites are now strictly controlled.
37031 	 */
37032 
37033 	js_ctx->flags = flags;
37034 #if defined(DUK_USE_JX)
37035 	js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
37036 #endif
37037 #if defined(DUK_USE_JC)
37038 	js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;
37039 #endif
37040 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37041 	js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
37042 #endif
37043 
37044 	h_text = duk_to_hstring(thr, idx_value);  /* coerce in-place; rejects Symbols */
37045 	DUK_ASSERT(h_text != NULL);
37046 
37047 	/* JSON parsing code is allowed to read [p_start,p_end]: p_end is
37048 	 * valid and points to the string NUL terminator (which is always
37049 	 * guaranteed for duk_hstrings.
37050 	 */
37051 	js_ctx->p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text);
37052 	js_ctx->p = js_ctx->p_start;
37053 	js_ctx->p_end = ((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text)) +
37054 	                DUK_HSTRING_GET_BYTELEN(h_text);
37055 	DUK_ASSERT(*(js_ctx->p_end) == 0x00);
37056 
37057 	duk__dec_value(js_ctx);  /* -> [ ... value ] */
37058 
37059 	/* Trailing whitespace has been eaten by duk__dec_value(), so if
37060 	 * we're not at end of input here, it's a SyntaxError.
37061 	 */
37062 
37063 	if (js_ctx->p != js_ctx->p_end) {
37064 		duk__dec_syntax_error(js_ctx);
37065 	}
37066 
37067 	if (duk_is_callable(thr, idx_reviver)) {
37068 		DUK_DDD(DUK_DDDPRINT("applying reviver: %!T",
37069 		                     (duk_tval *) duk_get_tval(thr, idx_reviver)));
37070 
37071 		js_ctx->idx_reviver = idx_reviver;
37072 
37073 		duk_push_object(thr);
37074 		duk_dup_m2(thr);  /* -> [ ... val root val ] */
37075 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_EMPTY_STRING);  /* default attrs ok */
37076 		duk_push_hstring_stridx(thr, DUK_STRIDX_EMPTY_STRING);  /* -> [ ... val root "" ] */
37077 
37078 		DUK_DDD(DUK_DDDPRINT("start reviver walk, root=%!T, name=%!T",
37079 		                     (duk_tval *) duk_get_tval(thr, -2),
37080 		                     (duk_tval *) duk_get_tval(thr, -1)));
37081 
37082 		duk__dec_reviver_walk(js_ctx);  /* [ ... val root "" ] -> [ ... val val' ] */
37083 		duk_remove_m2(thr);             /* -> [ ... val' ] */
37084 	} else {
37085 		DUK_DDD(DUK_DDDPRINT("reviver does not exist or is not callable: %!T",
37086 		                     (duk_tval *) duk_get_tval(thr, idx_reviver)));
37087 	}
37088 
37089 	/* Final result is at stack top. */
37090 
37091 	DUK_DDD(DUK_DDDPRINT("JSON parse end: text=%!T, reviver=%!T, flags=0x%08lx, result=%!T, stack_top=%ld",
37092 	                     (duk_tval *) duk_get_tval(thr, idx_value),
37093 	                     (duk_tval *) duk_get_tval(thr, idx_reviver),
37094 	                     (unsigned long) flags,
37095 	                     (duk_tval *) duk_get_tval(thr, -1),
37096 	                     (long) duk_get_top(thr)));
37097 
37098 	DUK_ASSERT(duk_get_top(thr) == entry_top + 1);
37099 }
37100 
37101 DUK_INTERNAL
37102 void duk_bi_json_stringify_helper(duk_hthread *thr,
37103                                   duk_idx_t idx_value,
37104                                   duk_idx_t idx_replacer,
37105                                   duk_idx_t idx_space,
37106                                   duk_small_uint_t flags) {
37107 	duk_json_enc_ctx js_ctx_alloc;
37108 	duk_json_enc_ctx *js_ctx = &js_ctx_alloc;
37109 	duk_hobject *h;
37110 	duk_idx_t idx_holder;
37111 	duk_idx_t entry_top;
37112 
37113 	/* negative top-relative indices not allowed now */
37114 	DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
37115 	DUK_ASSERT(idx_replacer == DUK_INVALID_INDEX || idx_replacer >= 0);
37116 	DUK_ASSERT(idx_space == DUK_INVALID_INDEX || idx_space >= 0);
37117 
37118 	DUK_DDD(DUK_DDDPRINT("JSON stringify start: value=%!T, replacer=%!T, space=%!T, flags=0x%08lx, stack_top=%ld",
37119 	                     (duk_tval *) duk_get_tval(thr, idx_value),
37120 	                     (duk_tval *) duk_get_tval(thr, idx_replacer),
37121 	                     (duk_tval *) duk_get_tval(thr, idx_space),
37122 	                     (unsigned long) flags,
37123 	                     (long) duk_get_top(thr)));
37124 
37125 	entry_top = duk_get_top(thr);
37126 
37127 	/*
37128 	 *  Context init
37129 	 */
37130 
37131 	duk_memzero(&js_ctx_alloc, sizeof(js_ctx_alloc));
37132 	js_ctx->thr = thr;
37133 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
37134 	js_ctx->h_replacer = NULL;
37135 	js_ctx->h_gap = NULL;
37136 #endif
37137 	js_ctx->idx_proplist = -1;
37138 
37139 	/* Flag handling currently assumes that flags are consistent.  This is OK
37140 	 * because the call sites are now strictly controlled.
37141 	 */
37142 
37143 	js_ctx->flags = flags;
37144 	js_ctx->flag_ascii_only = flags & DUK_JSON_FLAG_ASCII_ONLY;
37145 	js_ctx->flag_avoid_key_quotes = flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES;
37146 #if defined(DUK_USE_JX)
37147 	js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
37148 #endif
37149 #if defined(DUK_USE_JC)
37150 	js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;
37151 #endif
37152 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37153 	js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
37154 #endif
37155 
37156 	/* The #if defined() clutter here handles the JX/JC enable/disable
37157 	 * combinations properly.
37158 	 */
37159 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37160 	js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_NULL;  /* standard JSON; array gaps */
37161 #if defined(DUK_USE_JX)
37162 	if (flags & DUK_JSON_FLAG_EXT_CUSTOM) {
37163 		js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_UNDEFINED;
37164 		js_ctx->stridx_custom_nan = DUK_STRIDX_NAN;
37165 		js_ctx->stridx_custom_neginf = DUK_STRIDX_MINUS_INFINITY;
37166 		js_ctx->stridx_custom_posinf = DUK_STRIDX_INFINITY;
37167 		js_ctx->stridx_custom_function =
37168 		        (flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES) ?
37169 		                DUK_STRIDX_JSON_EXT_FUNCTION2 :
37170 		                DUK_STRIDX_JSON_EXT_FUNCTION1;
37171 	}
37172 #endif  /* DUK_USE_JX */
37173 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
37174 	else
37175 #endif  /* DUK_USE_JX && DUK_USE_JC */
37176 #if defined(DUK_USE_JC)
37177 	if (js_ctx->flags & DUK_JSON_FLAG_EXT_COMPATIBLE) {
37178 		js_ctx->stridx_custom_undefined = DUK_STRIDX_JSON_EXT_UNDEFINED;
37179 		js_ctx->stridx_custom_nan = DUK_STRIDX_JSON_EXT_NAN;
37180 		js_ctx->stridx_custom_neginf = DUK_STRIDX_JSON_EXT_NEGINF;
37181 		js_ctx->stridx_custom_posinf = DUK_STRIDX_JSON_EXT_POSINF;
37182 		js_ctx->stridx_custom_function = DUK_STRIDX_JSON_EXT_FUNCTION1;
37183 	}
37184 #endif  /* DUK_USE_JC */
37185 #endif  /* DUK_USE_JX || DUK_USE_JC */
37186 
37187 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37188 	if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
37189 	                     DUK_JSON_FLAG_EXT_COMPATIBLE)) {
37190 		DUK_ASSERT(js_ctx->mask_for_undefined == 0);  /* already zero */
37191 	}
37192 	else
37193 #endif  /* DUK_USE_JX || DUK_USE_JC */
37194 	{
37195 		/* Plain buffer is treated like ArrayBuffer and serialized.
37196 		 * Lightfuncs are treated like objects, but JSON explicitly
37197 		 * skips serializing Function objects so we can just reject
37198 		 * lightfuncs here.
37199 		 */
37200 		js_ctx->mask_for_undefined = DUK_TYPE_MASK_UNDEFINED |
37201 		                             DUK_TYPE_MASK_POINTER |
37202 		                             DUK_TYPE_MASK_LIGHTFUNC;
37203 	}
37204 
37205 	DUK_BW_INIT_PUSHBUF(thr, &js_ctx->bw, DUK__JSON_STRINGIFY_BUFSIZE);
37206 
37207 	js_ctx->idx_loop = duk_push_bare_object(thr);
37208 	DUK_ASSERT(js_ctx->idx_loop >= 0);
37209 
37210 	/* [ ... buf loop ] */
37211 
37212 	/*
37213 	 *  Process replacer/proplist (2nd argument to JSON.stringify)
37214 	 */
37215 
37216 	h = duk_get_hobject(thr, idx_replacer);
37217 	if (h != NULL) {
37218 		if (DUK_HOBJECT_IS_CALLABLE(h)) {
37219 			js_ctx->h_replacer = h;
37220 		} else if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
37221 			/* Here the specification requires correct array index enumeration
37222 			 * which is a bit tricky for sparse arrays (it is handled by the
37223 			 * enum setup code).  We now enumerate ancestors too, although the
37224 			 * specification is not very clear on whether that is required.
37225 			 */
37226 
37227 			duk_uarridx_t plist_idx = 0;
37228 			duk_small_uint_t enum_flags;
37229 
37230 			js_ctx->idx_proplist = duk_push_array(thr);  /* XXX: array internal? */
37231 
37232 			enum_flags = DUK_ENUM_ARRAY_INDICES_ONLY |
37233 			             DUK_ENUM_SORT_ARRAY_INDICES;  /* expensive flag */
37234 			duk_enum(thr, idx_replacer, enum_flags);
37235 			while (duk_next(thr, -1 /*enum_index*/, 1 /*get_value*/)) {
37236 				/* [ ... proplist enum_obj key val ] */
37237 				if (duk__enc_allow_into_proplist(duk_get_tval(thr, -1))) {
37238 					/* XXX: duplicates should be eliminated here */
37239 					DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> accept",
37240 					                     (duk_tval *) duk_get_tval(thr, -2),
37241 					                     (duk_tval *) duk_get_tval(thr, -1)));
37242 					duk_to_string(thr, -1);  /* extra coercion of strings is OK */
37243 					duk_put_prop_index(thr, -4, plist_idx);  /* -> [ ... proplist enum_obj key ] */
37244 					plist_idx++;
37245 					duk_pop(thr);
37246 				} else {
37247 					DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> reject",
37248 					                     (duk_tval *) duk_get_tval(thr, -2),
37249 					                     (duk_tval *) duk_get_tval(thr, -1)));
37250 					duk_pop_2(thr);
37251 				}
37252                         }
37253                         duk_pop(thr);  /* pop enum */
37254 
37255 			/* [ ... proplist ] */
37256 		}
37257 	}
37258 
37259 	/* [ ... buf loop (proplist) ] */
37260 
37261 	/*
37262 	 *  Process space (3rd argument to JSON.stringify)
37263 	 */
37264 
37265 	h = duk_get_hobject(thr, idx_space);
37266 	if (h != NULL) {
37267 		duk_small_uint_t c = DUK_HOBJECT_GET_CLASS_NUMBER(h);
37268 		if (c == DUK_HOBJECT_CLASS_NUMBER) {
37269 			duk_to_number(thr, idx_space);
37270 		} else if (c == DUK_HOBJECT_CLASS_STRING) {
37271 			duk_to_string(thr, idx_space);
37272 		}
37273 	}
37274 
37275 	if (duk_is_number(thr, idx_space)) {
37276 		duk_small_int_t nspace;
37277 		/* spaces[] must be static to allow initializer with old compilers like BCC */
37278 		static const char spaces[10] = {
37279 			DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
37280 			DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
37281 			DUK_ASC_SPACE, DUK_ASC_SPACE
37282 		};  /* XXX: helper */
37283 
37284 		/* ToInteger() coercion; NaN -> 0, infinities are clamped to 0 and 10 */
37285 		nspace = (duk_small_int_t) duk_to_int_clamped(thr, idx_space, 0 /*minval*/, 10 /*maxval*/);
37286 		DUK_ASSERT(nspace >= 0 && nspace <= 10);
37287 
37288 		duk_push_lstring(thr, spaces, (duk_size_t) nspace);
37289 		js_ctx->h_gap = duk_known_hstring(thr, -1);
37290 		DUK_ASSERT(js_ctx->h_gap != NULL);
37291 	} else if (duk_is_string_notsymbol(thr, idx_space)) {
37292 		duk_dup(thr, idx_space);
37293 		duk_substring(thr, -1, 0, 10);  /* clamp to 10 chars */
37294 		js_ctx->h_gap = duk_known_hstring(thr, -1);
37295 	} else {
37296 		/* nop */
37297 	}
37298 
37299 	if (js_ctx->h_gap != NULL) {
37300 		/* If gap is empty, behave as if not given at all.  Check
37301 		 * against byte length because character length is more
37302 		 * expensive.
37303 		 */
37304 		if (DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) == 0) {
37305 			js_ctx->h_gap = NULL;
37306 		}
37307 	}
37308 
37309 	/* [ ... buf loop (proplist) (gap) ] */
37310 
37311 	/*
37312 	 *  Fast path: assume no mutation, iterate object property tables
37313 	 *  directly; bail out if that assumption doesn't hold.
37314 	 */
37315 
37316 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
37317 	if (js_ctx->h_replacer == NULL &&  /* replacer is a mutation risk */
37318 	    js_ctx->idx_proplist == -1) {  /* proplist is very rare */
37319 		duk_int_t pcall_rc;
37320 		duk_small_uint_t prev_ms_base_flags;
37321 
37322 		DUK_DD(DUK_DDPRINT("try JSON.stringify() fast path"));
37323 
37324 		/* Use recursion_limit to ensure we don't overwrite js_ctx->visiting[]
37325 		 * array so we don't need two counter checks in the fast path.  The
37326 		 * slow path has a much larger recursion limit which we'll use if
37327 		 * necessary.
37328 		 */
37329 		DUK_ASSERT(DUK_USE_JSON_ENC_RECLIMIT >= DUK_JSON_ENC_LOOPARRAY);
37330 		js_ctx->recursion_limit = DUK_JSON_ENC_LOOPARRAY;
37331 		DUK_ASSERT(js_ctx->recursion_depth == 0);
37332 
37333 		/* Execute the fast path in a protected call.  If any error is thrown,
37334 		 * fall back to the slow path.  This includes e.g. recursion limit
37335 		 * because the fast path has a smaller recursion limit (and simpler,
37336 		 * limited loop detection).
37337 		 */
37338 
37339 		duk_dup(thr, idx_value);
37340 
37341 		/* Must prevent finalizers which may have arbitrary side effects. */
37342 		prev_ms_base_flags = thr->heap->ms_base_flags;
37343 		thr->heap->ms_base_flags |=
37344 		        DUK_MS_FLAG_NO_OBJECT_COMPACTION;      /* Avoid attempt to compact any objects. */
37345 		thr->heap->pf_prevent_count++;                 /* Prevent finalizers. */
37346 		DUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */
37347 
37348 		pcall_rc = duk_safe_call(thr, duk__json_stringify_fast, (void *) js_ctx /*udata*/, 1 /*nargs*/, 0 /*nret*/);
37349 
37350 		DUK_ASSERT(thr->heap->pf_prevent_count > 0);
37351 		thr->heap->pf_prevent_count--;
37352 		thr->heap->ms_base_flags = prev_ms_base_flags;
37353 
37354 		if (pcall_rc == DUK_EXEC_SUCCESS) {
37355 			DUK_DD(DUK_DDPRINT("fast path successful"));
37356 			DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
37357 			goto replace_finished;
37358 		}
37359 
37360 		/* We come here for actual aborts (like encountering .toJSON())
37361 		 * but also for recursion/loop errors.  Bufwriter size can be
37362 		 * kept because we'll probably need at least as much as we've
37363 		 * allocated so far.
37364 		 */
37365 		DUK_D(DUK_DPRINT("fast path failed, serialize using slow path instead"));
37366 		DUK_BW_RESET_SIZE(thr, &js_ctx->bw);
37367 		js_ctx->recursion_depth = 0;
37368 	}
37369 #endif
37370 
37371 	/*
37372 	 *  Create wrapper object and serialize
37373 	 */
37374 
37375 	idx_holder = duk_push_object(thr);
37376 	duk_dup(thr, idx_value);
37377 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_EMPTY_STRING);
37378 
37379 	DUK_DDD(DUK_DDDPRINT("before: flags=0x%08lx, loop=%!T, replacer=%!O, "
37380 	                     "proplist=%!T, gap=%!O, holder=%!T",
37381 	                     (unsigned long) js_ctx->flags,
37382 	                     (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop),
37383 	                     (duk_heaphdr *) js_ctx->h_replacer,
37384 	                     (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(thr, js_ctx->idx_proplist) : NULL),
37385 	                     (duk_heaphdr *) js_ctx->h_gap,
37386 	                     (duk_tval *) duk_get_tval(thr, -1)));
37387 
37388 	/* serialize the wrapper with empty string key */
37389 
37390 	duk_push_hstring_empty(thr);
37391 
37392 	/* [ ... buf loop (proplist) (gap) holder "" ] */
37393 
37394 	js_ctx->recursion_limit = DUK_USE_JSON_ENC_RECLIMIT;
37395 	DUK_ASSERT(js_ctx->recursion_depth == 0);
37396 
37397 	if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_holder) == 0)) {  /* [ ... holder key ] -> [ ... holder ] */
37398 		/* Result is undefined. */
37399 		duk_push_undefined(thr);
37400 	} else {
37401 		/* Convert buffer to result string. */
37402 		DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
37403 	}
37404 
37405 	DUK_DDD(DUK_DDDPRINT("after: flags=0x%08lx, loop=%!T, replacer=%!O, "
37406 	                     "proplist=%!T, gap=%!O, holder=%!T",
37407 	                     (unsigned long) js_ctx->flags,
37408 	                     (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop),
37409 	                     (duk_heaphdr *) js_ctx->h_replacer,
37410 	                     (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(thr, js_ctx->idx_proplist) : NULL),
37411 	                     (duk_heaphdr *) js_ctx->h_gap,
37412 	                     (duk_tval *) duk_get_tval(thr, idx_holder)));
37413 
37414 	/* The stack has a variable shape here, so force it to the
37415 	 * desired one explicitly.
37416 	 */
37417 
37418 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
37419  replace_finished:
37420 #endif
37421 	duk_replace(thr, entry_top);
37422 	duk_set_top(thr, entry_top + 1);
37423 
37424 	DUK_DDD(DUK_DDDPRINT("JSON stringify end: value=%!T, replacer=%!T, space=%!T, "
37425 	                     "flags=0x%08lx, result=%!T, stack_top=%ld",
37426 	                     (duk_tval *) duk_get_tval(thr, idx_value),
37427 	                     (duk_tval *) duk_get_tval(thr, idx_replacer),
37428 	                     (duk_tval *) duk_get_tval(thr, idx_space),
37429 	                     (unsigned long) flags,
37430 	                     (duk_tval *) duk_get_tval(thr, -1),
37431 	                     (long) duk_get_top(thr)));
37432 
37433 	DUK_ASSERT(duk_get_top(thr) == entry_top + 1);
37434 }
37435 
37436 #if defined(DUK_USE_JSON_BUILTIN)
37437 
37438 /*
37439  *  Entry points
37440  */
37441 
37442 DUK_INTERNAL duk_ret_t duk_bi_json_object_parse(duk_hthread *thr) {
37443 	duk_bi_json_parse_helper(thr,
37444 	                         0 /*idx_value*/,
37445 	                         1 /*idx_replacer*/,
37446 	                         0 /*flags*/);
37447 	return 1;
37448 }
37449 
37450 DUK_INTERNAL duk_ret_t duk_bi_json_object_stringify(duk_hthread *thr) {
37451 	duk_bi_json_stringify_helper(thr,
37452 	                             0 /*idx_value*/,
37453 	                             1 /*idx_replacer*/,
37454 	                             2 /*idx_space*/,
37455 	                             0 /*flags*/);
37456 	return 1;
37457 }
37458 
37459 #endif  /* DUK_USE_JSON_BUILTIN */
37460 
37461 #endif  /* DUK_USE_JSON_SUPPORT */
37462 
37463 /* automatic undefs */
37464 #undef DUK__EMIT_1
37465 #undef DUK__EMIT_2
37466 #undef DUK__EMIT_CSTR
37467 #undef DUK__EMIT_HSTR
37468 #undef DUK__EMIT_STRIDX
37469 #undef DUK__JSON_DECSTR_BUFSIZE
37470 #undef DUK__JSON_DECSTR_CHUNKSIZE
37471 #undef DUK__JSON_ENCSTR_CHUNKSIZE
37472 #undef DUK__JSON_MAX_ESC_LEN
37473 #undef DUK__JSON_STRINGIFY_BUFSIZE
37474 #undef DUK__MKESC
37475 #undef DUK__UNEMIT_1
37476 #line 1 "duk_bi_math.c"
37477 /*
37478  *  Math built-ins
37479  */
37480 
37481 /* #include duk_internal.h -> already included */
37482 
37483 #if defined(DUK_USE_MATH_BUILTIN)
37484 
37485 /*
37486  *  Use static helpers which can work with math.h functions matching
37487  *  the following signatures. This is not portable if any of these math
37488  *  functions is actually a macro.
37489  *
37490  *  Typing here is intentionally 'double' wherever values interact with
37491  *  the standard library APIs.
37492  */
37493 
37494 typedef double (*duk__one_arg_func)(double);
37495 typedef double (*duk__two_arg_func)(double, double);
37496 
37497 DUK_LOCAL duk_ret_t duk__math_minmax(duk_hthread *thr, duk_double_t initial, duk__two_arg_func min_max) {
37498 	duk_idx_t n = duk_get_top(thr);
37499 	duk_idx_t i;
37500 	duk_double_t res = initial;
37501 	duk_double_t t;
37502 
37503 	/*
37504 	 *  Note: fmax() does not match the E5 semantics.  E5 requires
37505 	 *  that if -any- input to Math.max() is a NaN, the result is a
37506 	 *  NaN.  fmax() will return a NaN only if -both- inputs are NaN.
37507 	 *  Same applies to fmin().
37508 	 *
37509 	 *  Note: every input value must be coerced with ToNumber(), even
37510 	 *  if we know the result will be a NaN anyway: ToNumber() may have
37511 	 *  side effects for which even order of evaluation matters.
37512 	 */
37513 
37514 	for (i = 0; i < n; i++) {
37515 		t = duk_to_number(thr, i);
37516 		if (DUK_FPCLASSIFY(t) == DUK_FP_NAN || DUK_FPCLASSIFY(res) == DUK_FP_NAN) {
37517 			/* Note: not normalized, but duk_push_number() will normalize */
37518 			res = (duk_double_t) DUK_DOUBLE_NAN;
37519 		} else {
37520 			res = (duk_double_t) min_max(res, (double) t);
37521 		}
37522 	}
37523 
37524 	duk_push_number(thr, res);
37525 	return 1;
37526 }
37527 
37528 DUK_LOCAL double duk__fmin_fixed(double x, double y) {
37529 	/* fmin() with args -0 and +0 is not guaranteed to return
37530 	 * -0 as ECMAScript requires.
37531 	 */
37532 	if (x == 0 && y == 0) {
37533 		duk_double_union du1, du2;
37534 		du1.d = x;
37535 		du2.d = y;
37536 
37537 		/* Already checked to be zero so these must hold, and allow us
37538 		 * to check for "x is -0 or y is -0" by ORing the high parts
37539 		 * for comparison.
37540 		 */
37541 		DUK_ASSERT(du1.ui[DUK_DBL_IDX_UI0] == 0 || du1.ui[DUK_DBL_IDX_UI0] == 0x80000000UL);
37542 		DUK_ASSERT(du2.ui[DUK_DBL_IDX_UI0] == 0 || du2.ui[DUK_DBL_IDX_UI0] == 0x80000000UL);
37543 
37544 		/* XXX: what's the safest way of creating a negative zero? */
37545 		if ((du1.ui[DUK_DBL_IDX_UI0] | du2.ui[DUK_DBL_IDX_UI0]) != 0) {
37546 			/* Enter here if either x or y (or both) is -0. */
37547 			return -0.0;
37548 		} else {
37549 			return +0.0;
37550 		}
37551 	}
37552 	return duk_double_fmin(x, y);
37553 }
37554 
37555 DUK_LOCAL double duk__fmax_fixed(double x, double y) {
37556 	/* fmax() with args -0 and +0 is not guaranteed to return
37557 	 * +0 as ECMAScript requires.
37558 	 */
37559 	if (x == 0 && y == 0) {
37560 		if (DUK_SIGNBIT(x) == 0 || DUK_SIGNBIT(y) == 0) {
37561 			return +0.0;
37562 		} else {
37563 			return -0.0;
37564 		}
37565 	}
37566 	return duk_double_fmax(x, y);
37567 }
37568 
37569 #if defined(DUK_USE_ES6)
37570 DUK_LOCAL double duk__cbrt(double x) {
37571 	/* cbrt() is C99.  To avoid hassling embedders with the need to provide a
37572 	 * cube root function, we can get by with pow().  The result is not
37573 	 * identical, but that's OK: ES2015 says it's implementation-dependent.
37574 	 */
37575 
37576 #if defined(DUK_CBRT)
37577 	/* cbrt() matches ES2015 requirements. */
37578 	return DUK_CBRT(x);
37579 #else
37580 	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
37581 
37582 	/* pow() does not, however. */
37583 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {
37584 		return x;
37585 	}
37586 	if (DUK_SIGNBIT(x)) {
37587 		return -DUK_POW(-x, 1.0 / 3.0);
37588 	} else {
37589 		return DUK_POW(x, 1.0 / 3.0);
37590 	}
37591 #endif
37592 }
37593 
37594 DUK_LOCAL double duk__log2(double x) {
37595 #if defined(DUK_LOG2)
37596 	return DUK_LOG2(x);
37597 #else
37598 	return DUK_LOG(x) * DUK_DOUBLE_LOG2E;
37599 #endif
37600 }
37601 
37602 DUK_LOCAL double duk__log10(double x) {
37603 #if defined(DUK_LOG10)
37604 	return DUK_LOG10(x);
37605 #else
37606 	return DUK_LOG(x) * DUK_DOUBLE_LOG10E;
37607 #endif
37608 }
37609 
37610 DUK_LOCAL double duk__trunc(double x) {
37611 #if defined(DUK_TRUNC)
37612 	return DUK_TRUNC(x);
37613 #else
37614 	/* Handles -0 correctly: -0.0 matches 'x >= 0.0' but floor()
37615 	 * is required to return -0 when the argument is -0.
37616 	 */
37617 	return x >= 0.0 ? DUK_FLOOR(x) : DUK_CEIL(x);
37618 #endif
37619 }
37620 #endif  /* DUK_USE_ES6 */
37621 
37622 DUK_LOCAL double duk__round_fixed(double x) {
37623 	/* Numbers half-way between integers must be rounded towards +Infinity,
37624 	 * e.g. -3.5 must be rounded to -3 (not -4).  When rounded to zero, zero
37625 	 * sign must be set appropriately.  E5.1 Section 15.8.2.15.
37626 	 *
37627 	 * Note that ANSI C round() is "round to nearest integer, away from zero",
37628 	 * which is incorrect for negative values.  Here we make do with floor().
37629 	 */
37630 
37631 	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
37632 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {
37633 		return x;
37634 	}
37635 
37636 	/*
37637 	 *  x is finite and non-zero
37638 	 *
37639 	 *  -1.6 -> floor(-1.1) -> -2
37640 	 *  -1.5 -> floor(-1.0) -> -1  (towards +Inf)
37641 	 *  -1.4 -> floor(-0.9) -> -1
37642 	 *  -0.5 -> -0.0               (special case)
37643 	 *  -0.1 -> -0.0               (special case)
37644 	 *  +0.1 -> +0.0               (special case)
37645 	 *  +0.5 -> floor(+1.0) -> 1   (towards +Inf)
37646 	 *  +1.4 -> floor(+1.9) -> 1
37647 	 *  +1.5 -> floor(+2.0) -> 2   (towards +Inf)
37648 	 *  +1.6 -> floor(+2.1) -> 2
37649 	 */
37650 
37651 	if (x >= -0.5 && x < 0.5) {
37652 		/* +0.5 is handled by floor, this is on purpose */
37653 		if (x < 0.0) {
37654 			return -0.0;
37655 		} else {
37656 			return +0.0;
37657 		}
37658 	}
37659 
37660 	return DUK_FLOOR(x + 0.5);
37661 }
37662 
37663 /* Wrappers for calling standard math library methods.  These may be required
37664  * on platforms where one or more of the math built-ins are defined as macros
37665  * or inline functions and are thus not suitable to be used as function pointers.
37666  */
37667 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
37668 DUK_LOCAL double duk__fabs(double x) {
37669 	return DUK_FABS(x);
37670 }
37671 DUK_LOCAL double duk__acos(double x) {
37672 	return DUK_ACOS(x);
37673 }
37674 DUK_LOCAL double duk__asin(double x) {
37675 	return DUK_ASIN(x);
37676 }
37677 DUK_LOCAL double duk__atan(double x) {
37678 	return DUK_ATAN(x);
37679 }
37680 DUK_LOCAL double duk__ceil(double x) {
37681 	return DUK_CEIL(x);
37682 }
37683 DUK_LOCAL double duk__cos(double x) {
37684 	return DUK_COS(x);
37685 }
37686 DUK_LOCAL double duk__exp(double x) {
37687 	return DUK_EXP(x);
37688 }
37689 DUK_LOCAL double duk__floor(double x) {
37690 	return DUK_FLOOR(x);
37691 }
37692 DUK_LOCAL double duk__log(double x) {
37693 	return DUK_LOG(x);
37694 }
37695 DUK_LOCAL double duk__sin(double x) {
37696 	return DUK_SIN(x);
37697 }
37698 DUK_LOCAL double duk__sqrt(double x) {
37699 	return DUK_SQRT(x);
37700 }
37701 DUK_LOCAL double duk__tan(double x) {
37702 	return DUK_TAN(x);
37703 }
37704 DUK_LOCAL double duk__atan2_fixed(double x, double y) {
37705 #if defined(DUK_USE_ATAN2_WORKAROUNDS)
37706 	/* Specific fixes to common atan2() implementation issues:
37707 	 * - test-bug-mingw-math-issues.js
37708 	 */
37709 	if (DUK_ISINF(x) && DUK_ISINF(y)) {
37710 		if (DUK_SIGNBIT(x)) {
37711 			if (DUK_SIGNBIT(y)) {
37712 				return -2.356194490192345;
37713 			} else {
37714 				return -0.7853981633974483;
37715 			}
37716 		} else {
37717 			if (DUK_SIGNBIT(y)) {
37718 				return 2.356194490192345;
37719 			} else {
37720 				return 0.7853981633974483;
37721 			}
37722 		}
37723 	}
37724 #else
37725 	/* Some ISO C assumptions. */
37726 	DUK_ASSERT(DUK_ATAN2(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY) == 0.7853981633974483);
37727 	DUK_ASSERT(DUK_ATAN2(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY) == -0.7853981633974483);
37728 	DUK_ASSERT(DUK_ATAN2(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY) == 2.356194490192345);
37729 	DUK_ASSERT(DUK_ATAN2(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY) == -2.356194490192345);
37730 #endif
37731 
37732 	return DUK_ATAN2(x, y);
37733 }
37734 #endif  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
37735 
37736 /* order must match constants in genbuiltins.py */
37737 DUK_LOCAL const duk__one_arg_func duk__one_arg_funcs[] = {
37738 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
37739 	duk__fabs,
37740 	duk__acos,
37741 	duk__asin,
37742 	duk__atan,
37743 	duk__ceil,
37744 	duk__cos,
37745 	duk__exp,
37746 	duk__floor,
37747 	duk__log,
37748 	duk__round_fixed,
37749 	duk__sin,
37750 	duk__sqrt,
37751 	duk__tan,
37752 #if defined(DUK_USE_ES6)
37753 	duk__cbrt,
37754 	duk__log2,
37755 	duk__log10,
37756 	duk__trunc
37757 #endif
37758 #else  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
37759 	DUK_FABS,
37760 	DUK_ACOS,
37761 	DUK_ASIN,
37762 	DUK_ATAN,
37763 	DUK_CEIL,
37764 	DUK_COS,
37765 	DUK_EXP,
37766 	DUK_FLOOR,
37767 	DUK_LOG,
37768 	duk__round_fixed,
37769 	DUK_SIN,
37770 	DUK_SQRT,
37771 	DUK_TAN,
37772 #if defined(DUK_USE_ES6)
37773 	duk__cbrt,
37774 	duk__log2,
37775 	duk__log10,
37776 	duk__trunc
37777 #endif
37778 #endif  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
37779 };
37780 
37781 /* order must match constants in genbuiltins.py */
37782 DUK_LOCAL const duk__two_arg_func duk__two_arg_funcs[] = {
37783 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
37784 	duk__atan2_fixed,
37785 	duk_js_arith_pow
37786 #else
37787 	duk__atan2_fixed,
37788 	duk_js_arith_pow
37789 #endif
37790 };
37791 
37792 DUK_INTERNAL duk_ret_t duk_bi_math_object_onearg_shared(duk_hthread *thr) {
37793 	duk_small_int_t fun_idx = duk_get_current_magic(thr);
37794 	duk__one_arg_func fun;
37795 	duk_double_t arg1;
37796 
37797 	DUK_ASSERT(fun_idx >= 0);
37798 	DUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__one_arg_funcs) / sizeof(duk__one_arg_func)));
37799 	arg1 = duk_to_number(thr, 0);
37800 	fun = duk__one_arg_funcs[fun_idx];
37801 	duk_push_number(thr, (duk_double_t) fun((double) arg1));
37802 	return 1;
37803 }
37804 
37805 DUK_INTERNAL duk_ret_t duk_bi_math_object_twoarg_shared(duk_hthread *thr) {
37806 	duk_small_int_t fun_idx = duk_get_current_magic(thr);
37807 	duk__two_arg_func fun;
37808 	duk_double_t arg1;
37809 	duk_double_t arg2;
37810 
37811 	DUK_ASSERT(fun_idx >= 0);
37812 	DUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__two_arg_funcs) / sizeof(duk__two_arg_func)));
37813 	arg1 = duk_to_number(thr, 0);  /* explicit ordered evaluation to match coercion semantics */
37814 	arg2 = duk_to_number(thr, 1);
37815 	fun = duk__two_arg_funcs[fun_idx];
37816 	duk_push_number(thr, (duk_double_t) fun((double) arg1, (double) arg2));
37817 	return 1;
37818 }
37819 
37820 DUK_INTERNAL duk_ret_t duk_bi_math_object_max(duk_hthread *thr) {
37821 	return duk__math_minmax(thr, -DUK_DOUBLE_INFINITY, duk__fmax_fixed);
37822 }
37823 
37824 DUK_INTERNAL duk_ret_t duk_bi_math_object_min(duk_hthread *thr) {
37825 	return duk__math_minmax(thr, DUK_DOUBLE_INFINITY, duk__fmin_fixed);
37826 }
37827 
37828 DUK_INTERNAL duk_ret_t duk_bi_math_object_random(duk_hthread *thr) {
37829 	duk_push_number(thr, (duk_double_t) DUK_UTIL_GET_RANDOM_DOUBLE(thr));
37830 	return 1;
37831 }
37832 
37833 #if defined(DUK_USE_ES6)
37834 DUK_INTERNAL duk_ret_t duk_bi_math_object_hypot(duk_hthread *thr) {
37835 	/*
37836 	 *  E6 Section 20.2.2.18: Math.hypot
37837 	 *
37838 	 *  - If no arguments are passed, the result is +0.
37839 	 *  - If any argument is +inf, the result is +inf.
37840 	 *  - If any argument is -inf, the result is +inf.
37841 	 *  - If no argument is +inf or -inf, and any argument is NaN, the result is
37842 	 *    NaN.
37843 	 *  - If all arguments are either +0 or -0, the result is +0.
37844 	 */
37845 
37846 	duk_idx_t nargs;
37847 	duk_idx_t i;
37848 	duk_bool_t found_nan;
37849 	duk_double_t max;
37850 	duk_double_t sum, summand;
37851 	duk_double_t comp, prelim;
37852 	duk_double_t t;
37853 
37854 	nargs = duk_get_top(thr);
37855 
37856 	/* Find the highest value.  Also ToNumber() coerces. */
37857 	max = 0.0;
37858 	found_nan = 0;
37859 	for (i = 0; i < nargs; i++) {
37860 		t = DUK_FABS(duk_to_number(thr, i));
37861 		if (DUK_FPCLASSIFY(t) == DUK_FP_NAN) {
37862 			found_nan = 1;
37863 		} else {
37864 			max = duk_double_fmax(max, t);
37865 		}
37866 	}
37867 
37868 	/* Early return cases. */
37869 	if (max == DUK_DOUBLE_INFINITY) {
37870 		duk_push_number(thr, DUK_DOUBLE_INFINITY);
37871 		return 1;
37872 	} else if (found_nan) {
37873 		duk_push_number(thr, DUK_DOUBLE_NAN);
37874 		return 1;
37875 	} else if (max == 0.0) {
37876 		duk_push_number(thr, 0.0);
37877 		/* Otherwise we'd divide by zero. */
37878 		return 1;
37879 	}
37880 
37881 	/* Use Kahan summation and normalize to the highest value to minimize
37882 	 * floating point rounding error and avoid overflow.
37883 	 *
37884 	 * https://en.wikipedia.org/wiki/Kahan_summation_algorithm
37885 	 */
37886 	sum = 0.0;
37887 	comp = 0.0;
37888 	for (i = 0; i < nargs; i++) {
37889 		t = DUK_FABS(duk_get_number(thr, i)) / max;
37890 		summand = (t * t) - comp;
37891 		prelim = sum + summand;
37892 		comp = (prelim - sum) - summand;
37893 		sum = prelim;
37894 	}
37895 
37896 	duk_push_number(thr, (duk_double_t) DUK_SQRT(sum) * max);
37897 	return 1;
37898 }
37899 #endif  /* DUK_USE_ES6 */
37900 
37901 #if defined(DUK_USE_ES6)
37902 DUK_INTERNAL duk_ret_t duk_bi_math_object_sign(duk_hthread *thr) {
37903 	duk_double_t d;
37904 
37905 	d = duk_to_number(thr, 0);
37906 	if (duk_double_is_nan(d)) {
37907 		DUK_ASSERT(duk_is_nan(thr, -1));
37908 		return 1;  /* NaN input -> return NaN */
37909 	}
37910 	if (d == 0.0) {
37911 		/* Zero sign kept, i.e. -0 -> -0, +0 -> +0. */
37912 		return 1;
37913 	}
37914 	duk_push_int(thr, (d > 0.0 ? 1 : -1));
37915 	return 1;
37916 }
37917 #endif  /* DUK_USE_ES6 */
37918 
37919 #if defined(DUK_USE_ES6)
37920 DUK_INTERNAL duk_ret_t duk_bi_math_object_clz32(duk_hthread *thr) {
37921 	duk_uint32_t x;
37922 	duk_small_uint_t i;
37923 
37924 #if defined(DUK_USE_PREFER_SIZE)
37925 	duk_uint32_t mask;
37926 
37927 	x = duk_to_uint32(thr, 0);
37928 	for (i = 0, mask = 0x80000000UL; mask != 0; mask >>= 1) {
37929 		if (x & mask) {
37930 			break;
37931 		}
37932 		i++;
37933 	}
37934 	DUK_ASSERT(i <= 32);
37935 	duk_push_uint(thr, i);
37936 	return 1;
37937 #else  /* DUK_USE_PREFER_SIZE */
37938 	i = 0;
37939 	x = duk_to_uint32(thr, 0);
37940 	if (x & 0xffff0000UL) {
37941 		x >>= 16;
37942 	} else {
37943 		i += 16;
37944 	}
37945 	if (x & 0x0000ff00UL) {
37946 		x >>= 8;
37947 	} else {
37948 		i += 8;
37949 	}
37950 	if (x & 0x000000f0UL) {
37951 		x >>= 4;
37952 	} else {
37953 		i += 4;
37954 	}
37955 	if (x & 0x0000000cUL) {
37956 		x >>= 2;
37957 	} else {
37958 		i += 2;
37959 	}
37960 	if (x & 0x00000002UL) {
37961 		x >>= 1;
37962 	} else {
37963 		i += 1;
37964 	}
37965 	if (x & 0x00000001UL) {
37966 		;
37967 	} else {
37968 		i += 1;
37969 	}
37970 	DUK_ASSERT(i <= 32);
37971 	duk_push_uint(thr, i);
37972 	return 1;
37973 #endif  /* DUK_USE_PREFER_SIZE */
37974 }
37975 #endif  /* DUK_USE_ES6 */
37976 
37977 #if defined(DUK_USE_ES6)
37978 DUK_INTERNAL duk_ret_t duk_bi_math_object_imul(duk_hthread *thr) {
37979 	duk_uint32_t x, y, z;
37980 
37981 	x = duk_to_uint32(thr, 0);
37982 	y = duk_to_uint32(thr, 1);
37983 	z = x * y;
37984 
37985 	/* While arguments are ToUint32() coerced and the multiplication
37986 	 * is unsigned as such, the final result is curiously interpreted
37987 	 * as a signed 32-bit value.
37988 	 */
37989 	duk_push_i32(thr, (duk_int32_t) z);
37990 	return 1;
37991 }
37992 #endif  /* DUK_USE_ES6 */
37993 
37994 #endif  /* DUK_USE_MATH_BUILTIN */
37995 #line 1 "duk_bi_number.c"
37996 /*
37997  *  Number built-ins
37998  */
37999 
38000 /* #include duk_internal.h -> already included */
38001 
38002 #if defined(DUK_USE_NUMBER_BUILTIN)
38003 
38004 DUK_LOCAL duk_double_t duk__push_this_number_plain(duk_hthread *thr) {
38005 	duk_hobject *h;
38006 
38007 	/* Number built-in accepts a plain number or a Number object (whose
38008 	 * internal value is operated on).  Other types cause TypeError.
38009 	 */
38010 
38011 	duk_push_this(thr);
38012 	if (duk_is_number(thr, -1)) {
38013 		DUK_DDD(DUK_DDDPRINT("plain number value: %!T", (duk_tval *) duk_get_tval(thr, -1)));
38014 		goto done;
38015 	}
38016 	h = duk_get_hobject(thr, -1);
38017 	if (!h ||
38018 	    (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_NUMBER)) {
38019 		DUK_DDD(DUK_DDDPRINT("unacceptable this value: %!T", (duk_tval *) duk_get_tval(thr, -1)));
38020 		DUK_ERROR_TYPE(thr, "number expected");
38021 		DUK_WO_NORETURN(return 0.0;);
38022 	}
38023 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
38024 	DUK_ASSERT(duk_is_number(thr, -1));
38025 	DUK_DDD(DUK_DDDPRINT("number object: %!T, internal value: %!T",
38026 	                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
38027 	duk_remove_m2(thr);
38028 
38029  done:
38030 	return duk_get_number(thr, -1);
38031 }
38032 
38033 DUK_INTERNAL duk_ret_t duk_bi_number_constructor(duk_hthread *thr) {
38034 	duk_idx_t nargs;
38035 	duk_hobject *h_this;
38036 
38037 	/*
38038 	 *  The Number constructor uses ToNumber(arg) for number coercion
38039 	 *  (coercing an undefined argument to NaN).  However, if the
38040 	 *  argument is not given at all, +0 must be used instead.  To do
38041 	 *  this, a vararg function is used.
38042 	 */
38043 
38044 	nargs = duk_get_top(thr);
38045 	if (nargs == 0) {
38046 		duk_push_int(thr, 0);
38047 	}
38048 	duk_to_number(thr, 0);
38049 	duk_set_top(thr, 1);
38050 	DUK_ASSERT_TOP(thr, 1);
38051 
38052 	if (!duk_is_constructor_call(thr)) {
38053 		return 1;
38054 	}
38055 
38056 	/*
38057 	 *  E5 Section 15.7.2.1 requires that the constructed object
38058 	 *  must have the original Number.prototype as its internal
38059 	 *  prototype.  However, since Number.prototype is non-writable
38060 	 *  and non-configurable, this doesn't have to be enforced here:
38061 	 *  The default object (bound to 'this') is OK, though we have
38062 	 *  to change its class.
38063 	 *
38064 	 *  Internal value set to ToNumber(arg) or +0; if no arg given,
38065 	 *  ToNumber(undefined) = NaN, so special treatment is needed
38066 	 *  (above).  String internal value is immutable.
38067 	 */
38068 
38069 	/* XXX: helper */
38070 	duk_push_this(thr);
38071 	h_this = duk_known_hobject(thr, -1);
38072 	DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_NUMBER);
38073 
38074 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE]);
38075 	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_this) == DUK_HOBJECT_CLASS_NUMBER);
38076 	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_this));
38077 
38078 	duk_dup_0(thr);  /* -> [ val obj val ] */
38079 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
38080 	return 0;  /* no return value -> don't replace created value */
38081 }
38082 
38083 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_value_of(duk_hthread *thr) {
38084 	(void) duk__push_this_number_plain(thr);
38085 	return 1;
38086 }
38087 
38088 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_string(duk_hthread *thr) {
38089 	duk_small_int_t radix;
38090 	duk_small_uint_t n2s_flags;
38091 
38092 	(void) duk__push_this_number_plain(thr);
38093 	if (duk_is_undefined(thr, 0)) {
38094 		radix = 10;
38095 	} else {
38096 		radix = (duk_small_int_t) duk_to_int_check_range(thr, 0, 2, 36);
38097 	}
38098 	DUK_DDD(DUK_DDDPRINT("radix=%ld", (long) radix));
38099 
38100 	n2s_flags = 0;
38101 
38102 	duk_numconv_stringify(thr,
38103 	                      radix /*radix*/,
38104 	                      0 /*digits*/,
38105 	                      n2s_flags /*flags*/);
38106 	return 1;
38107 }
38108 
38109 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_hthread *thr) {
38110 	/* XXX: just use toString() for now; permitted although not recommended.
38111 	 * nargs==1, so radix is passed to toString().
38112 	 */
38113 	return duk_bi_number_prototype_to_string(thr);
38114 }
38115 
38116 /*
38117  *  toFixed(), toExponential(), toPrecision()
38118  */
38119 
38120 /* XXX: shared helper for toFixed(), toExponential(), toPrecision()? */
38121 
38122 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_fixed(duk_hthread *thr) {
38123 	duk_small_int_t frac_digits;
38124 	duk_double_t d;
38125 	duk_small_int_t c;
38126 	duk_small_uint_t n2s_flags;
38127 
38128 	/* In ES5.1 frac_digits is coerced first; in ES2015 the 'this number
38129 	 * value' check is done first.
38130 	 */
38131 	d = duk__push_this_number_plain(thr);
38132 	frac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20);
38133 
38134 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
38135 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
38136 		goto use_to_string;
38137 	}
38138 
38139 	if (d >= 1.0e21 || d <= -1.0e21) {
38140 		goto use_to_string;
38141 	}
38142 
38143 	n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
38144 	            DUK_N2S_FLAG_FRACTION_DIGITS;
38145 
38146 	duk_numconv_stringify(thr,
38147 	                      10 /*radix*/,
38148 	                      frac_digits /*digits*/,
38149 	                      n2s_flags /*flags*/);
38150 	return 1;
38151 
38152  use_to_string:
38153 	DUK_ASSERT_TOP(thr, 2);
38154 	duk_to_string(thr, -1);
38155 	return 1;
38156 }
38157 
38158 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_exponential(duk_hthread *thr) {
38159 	duk_bool_t frac_undefined;
38160 	duk_small_int_t frac_digits;
38161 	duk_double_t d;
38162 	duk_small_int_t c;
38163 	duk_small_uint_t n2s_flags;
38164 
38165 	d = duk__push_this_number_plain(thr);
38166 
38167 	frac_undefined = duk_is_undefined(thr, 0);
38168 	duk_to_int(thr, 0);  /* for side effects */
38169 
38170 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
38171 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
38172 		goto use_to_string;
38173 	}
38174 
38175 	frac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20);
38176 
38177 	n2s_flags = DUK_N2S_FLAG_FORCE_EXP |
38178 	           (frac_undefined ? 0 : DUK_N2S_FLAG_FIXED_FORMAT);
38179 
38180 	duk_numconv_stringify(thr,
38181 	                      10 /*radix*/,
38182 	                      frac_digits + 1 /*leading digit + fractions*/,
38183 	                      n2s_flags /*flags*/);
38184 	return 1;
38185 
38186  use_to_string:
38187 	DUK_ASSERT_TOP(thr, 2);
38188 	duk_to_string(thr, -1);
38189 	return 1;
38190 }
38191 
38192 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_precision(duk_hthread *thr) {
38193 	/* The specification has quite awkward order of coercion and
38194 	 * checks for toPrecision().  The operations below are a bit
38195 	 * reordered, within constraints of observable side effects.
38196 	 */
38197 
38198 	duk_double_t d;
38199 	duk_small_int_t prec;
38200 	duk_small_int_t c;
38201 	duk_small_uint_t n2s_flags;
38202 
38203 	DUK_ASSERT_TOP(thr, 1);
38204 
38205 	d = duk__push_this_number_plain(thr);
38206 	if (duk_is_undefined(thr, 0)) {
38207 		goto use_to_string;
38208 	}
38209 	DUK_ASSERT_TOP(thr, 2);
38210 
38211 	duk_to_int(thr, 0);  /* for side effects */
38212 
38213 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
38214 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
38215 		goto use_to_string;
38216 	}
38217 
38218 	prec = (duk_small_int_t) duk_to_int_check_range(thr, 0, 1, 21);
38219 
38220 	n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
38221 	            DUK_N2S_FLAG_NO_ZERO_PAD;
38222 
38223 	duk_numconv_stringify(thr,
38224 	                      10 /*radix*/,
38225 	                      prec /*digits*/,
38226 	                      n2s_flags /*flags*/);
38227 	return 1;
38228 
38229  use_to_string:
38230 	/* Used when precision is undefined; also used for NaN (-> "NaN"),
38231 	 * and +/- infinity (-> "Infinity", "-Infinity").
38232 	 */
38233 
38234 	DUK_ASSERT_TOP(thr, 2);
38235 	duk_to_string(thr, -1);
38236 	return 1;
38237 }
38238 
38239 /*
38240  *  ES2015 isFinite() etc
38241  */
38242 
38243 #if defined(DUK_USE_ES6)
38244 DUK_INTERNAL duk_ret_t duk_bi_number_check_shared(duk_hthread *thr) {
38245 	duk_int_t magic;
38246 	duk_bool_t ret = 0;
38247 
38248 	if (duk_is_number(thr, 0)) {
38249 		duk_double_t d;
38250 
38251 		magic = duk_get_current_magic(thr);
38252 		d = duk_get_number(thr, 0);
38253 
38254 		switch (magic) {
38255 		case 0:  /* isFinite() */
38256 			ret = duk_double_is_finite(d);
38257 			break;
38258 		case 1:  /* isInteger() */
38259 			ret = duk_double_is_integer(d);
38260 			break;
38261 		case 2:  /* isNaN() */
38262 			ret = duk_double_is_nan(d);
38263 			break;
38264 		default:  /* isSafeInteger() */
38265 			DUK_ASSERT(magic == 3);
38266 			ret = duk_double_is_safe_integer(d);
38267 		}
38268 	}
38269 
38270 	duk_push_boolean(thr, ret);
38271 	return 1;
38272 }
38273 #endif  /* DUK_USE_ES6 */
38274 
38275 #endif  /* DUK_USE_NUMBER_BUILTIN */
38276 #line 1 "duk_bi_object.c"
38277 /*
38278  *  Object built-ins
38279  */
38280 
38281 /* #include duk_internal.h -> already included */
38282 
38283 /* Needed even when Object built-in disabled. */
38284 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_string(duk_hthread *thr) {
38285 	duk_tval *tv;
38286 
38287 	tv = DUK_HTHREAD_THIS_PTR(thr);
38288 	duk_push_class_string_tval(thr, tv, 0 /*avoid_side_effects*/);
38289 	return 1;
38290 }
38291 
38292 #if defined(DUK_USE_OBJECT_BUILTIN)
38293 DUK_INTERNAL duk_ret_t duk_bi_object_constructor(duk_hthread *thr) {
38294 	duk_uint_t arg_mask;
38295 
38296 	arg_mask = duk_get_type_mask(thr, 0);
38297 
38298 	if (!duk_is_constructor_call(thr) &&  /* not a constructor call */
38299 	    ((arg_mask & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED)) == 0)) {  /* and argument not null or undefined */
38300 		duk_to_object(thr, 0);
38301 		return 1;
38302 	}
38303 
38304 	/* Pointer and buffer primitive values are treated like other
38305 	 * primitives values which have a fully fledged object counterpart:
38306 	 * promote to an object value.  Lightfuncs and plain buffers are
38307 	 * coerced with ToObject() even they could also be returned as is.
38308 	 */
38309 	if (arg_mask & (DUK_TYPE_MASK_OBJECT |
38310 	                DUK_TYPE_MASK_STRING |
38311 	                DUK_TYPE_MASK_BOOLEAN |
38312 	                DUK_TYPE_MASK_NUMBER |
38313 	                DUK_TYPE_MASK_POINTER |
38314 	                DUK_TYPE_MASK_BUFFER |
38315 	                DUK_TYPE_MASK_LIGHTFUNC)) {
38316 		/* For DUK_TYPE_OBJECT the coercion is a no-op and could
38317 		 * be checked for explicitly, but Object(obj) calls are
38318 		 * not very common so opt for minimal footprint.
38319 		 */
38320 		duk_to_object(thr, 0);
38321 		return 1;
38322 	}
38323 
38324 	(void) duk_push_object_helper(thr,
38325 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
38326 	                              DUK_HOBJECT_FLAG_FASTREFS |
38327 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
38328 	                              DUK_BIDX_OBJECT_PROTOTYPE);
38329 	return 1;
38330 }
38331 #endif  /* DUK_USE_OBJECT_BUILTIN */
38332 
38333 #if defined(DUK_USE_OBJECT_BUILTIN) && defined(DUK_USE_ES6)
38334 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_assign(duk_hthread *thr) {
38335 	duk_idx_t nargs;
38336 	duk_int_t idx;
38337 
38338 	nargs = duk_get_top_require_min(thr, 1 /*min_top*/);
38339 
38340 	duk_to_object(thr, 0);
38341 	for (idx = 1; idx < nargs; idx++) {
38342 		/* E7 19.1.2.1 (step 4a) */
38343 		if (duk_is_null_or_undefined(thr, idx)) {
38344 			continue;
38345 		}
38346 
38347 		/* duk_enum() respects ES2015+ [[OwnPropertyKeys]] ordering, which is
38348 		 * convenient here.
38349 		 */
38350 		duk_to_object(thr, idx);
38351 		duk_enum(thr, idx, DUK_ENUM_OWN_PROPERTIES_ONLY);
38352 		while (duk_next(thr, -1, 1 /*get_value*/)) {
38353 			/* [ target ... enum key value ] */
38354 			duk_put_prop(thr, 0);
38355 			/* [ target ... enum ] */
38356 		}
38357 		/* Could pop enumerator, but unnecessary because of duk_set_top()
38358 		 * below.
38359 		 */
38360 	}
38361 
38362 	duk_set_top(thr, 1);
38363 	return 1;
38364 }
38365 #endif
38366 
38367 #if defined(DUK_USE_OBJECT_BUILTIN) && defined(DUK_USE_ES6)
38368 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is(duk_hthread *thr) {
38369 	DUK_ASSERT_TOP(thr, 2);
38370 	duk_push_boolean(thr, duk_samevalue(thr, 0, 1));
38371 	return 1;
38372 }
38373 #endif
38374 
38375 #if defined(DUK_USE_OBJECT_BUILTIN)
38376 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_create(duk_hthread *thr) {
38377 	duk_hobject *proto;
38378 
38379 	DUK_ASSERT_TOP(thr, 2);
38380 
38381 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
38382 	duk_hbufobj_promote_plain(thr, 0);
38383 #endif
38384 	proto = duk_require_hobject_accept_mask(thr, 0, DUK_TYPE_MASK_NULL);
38385 	DUK_ASSERT(proto != NULL || duk_is_null(thr, 0));
38386 
38387 	(void) duk_push_object_helper_proto(thr,
38388 	                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
38389 	                                    DUK_HOBJECT_FLAG_FASTREFS |
38390 	                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
38391 	                                    proto);
38392 
38393 	if (!duk_is_undefined(thr, 1)) {
38394 		/* [ O Properties obj ] */
38395 
38396 		duk_replace(thr, 0);
38397 
38398 		/* [ obj Properties ] */
38399 
38400 		/* Just call the "original" Object.defineProperties() to
38401 		 * finish up.
38402 		 */
38403 
38404 		return duk_bi_object_constructor_define_properties(thr);
38405 	}
38406 
38407 	/* [ O Properties obj ] */
38408 
38409 	return 1;
38410 }
38411 #endif  /* DUK_USE_OBJECT_BUILTIN */
38412 
38413 #if defined(DUK_USE_OBJECT_BUILTIN)
38414 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_properties(duk_hthread *thr) {
38415 	duk_small_uint_t pass;
38416 	duk_uint_t defprop_flags;
38417 	duk_hobject *obj;
38418 	duk_idx_t idx_value;
38419 	duk_hobject *get;
38420 	duk_hobject *set;
38421 
38422 	/* Lightfunc and plain buffer handling by ToObject() coercion. */
38423 	obj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
38424 	DUK_ASSERT(obj != NULL);
38425 
38426 	duk_to_object(thr, 1);        /* properties object */
38427 
38428 	DUK_DDD(DUK_DDDPRINT("target=%!iT, properties=%!iT",
38429 	                     (duk_tval *) duk_get_tval(thr, 0),
38430 	                     (duk_tval *) duk_get_tval(thr, 1)));
38431 
38432 	/*
38433 	 *  Two pass approach to processing the property descriptors.
38434 	 *  On first pass validate and normalize all descriptors before
38435 	 *  any changes are made to the target object.  On second pass
38436 	 *  make the actual modifications to the target object.
38437 	 *
38438 	 *  Right now we'll just use the same normalize/validate helper
38439 	 *  on both passes, ignoring its outputs on the first pass.
38440 	 */
38441 
38442 	for (pass = 0; pass < 2; pass++) {
38443 		duk_set_top(thr, 2);  /* -> [ hobject props ] */
38444 		duk_enum(thr, 1, DUK_ENUM_OWN_PROPERTIES_ONLY | DUK_ENUM_INCLUDE_SYMBOLS /*enum_flags*/);
38445 
38446 		for (;;) {
38447 			duk_hstring *key;
38448 
38449 			/* [ hobject props enum(props) ] */
38450 
38451 			duk_set_top(thr, 3);
38452 
38453 			if (!duk_next(thr, 2, 1 /*get_value*/)) {
38454 				break;
38455 			}
38456 
38457 			DUK_DDD(DUK_DDDPRINT("-> key=%!iT, desc=%!iT",
38458 			                     (duk_tval *) duk_get_tval(thr, -2),
38459 			                     (duk_tval *) duk_get_tval(thr, -1)));
38460 
38461 			/* [ hobject props enum(props) key desc ] */
38462 
38463 			duk_hobject_prepare_property_descriptor(thr,
38464 			                                        4 /*idx_desc*/,
38465 			                                        &defprop_flags,
38466 			                                        &idx_value,
38467 			                                        &get,
38468 			                                        &set);
38469 
38470 			/* [ hobject props enum(props) key desc [multiple values] ] */
38471 
38472 			if (pass == 0) {
38473 				continue;
38474 			}
38475 
38476 			/* This allows symbols on purpose. */
38477 			key = duk_known_hstring(thr, 3);
38478 			DUK_ASSERT(key != NULL);
38479 
38480 			duk_hobject_define_property_helper(thr,
38481 			                                   defprop_flags,
38482 			                                   obj,
38483 			                                   key,
38484 			                                   idx_value,
38485 			                                   get,
38486 			                                   set,
38487 			                                   1 /*throw_flag*/);
38488 		}
38489 	}
38490 
38491 	/*
38492 	 *  Return target object
38493 	 */
38494 
38495 	duk_dup_0(thr);
38496 	return 1;
38497 }
38498 #endif  /* DUK_USE_OBJECT_BUILTIN */
38499 
38500 #if defined(DUK_USE_OBJECT_BUILTIN)
38501 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_hthread *thr) {
38502 	DUK_ASSERT_TOP(thr, 1);
38503 
38504 	duk_seal_freeze_raw(thr, 0, (duk_bool_t) duk_get_current_magic(thr) /*is_freeze*/);
38505 	return 1;
38506 }
38507 #endif  /* DUK_USE_OBJECT_BUILTIN */
38508 
38509 #if defined(DUK_USE_OBJECT_BUILTIN)
38510 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_hthread *thr) {
38511 	duk_hobject *h;
38512 	duk_bool_t is_frozen;
38513 	duk_uint_t mask;
38514 
38515 	is_frozen = (duk_bool_t) duk_get_current_magic(thr);
38516 	mask = duk_get_type_mask(thr, 0);
38517 	if (mask & (DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {
38518 		DUK_ASSERT(is_frozen == 0 || is_frozen == 1);
38519 		duk_push_boolean(thr, (mask & DUK_TYPE_MASK_LIGHTFUNC) ?
38520 		                          1 :               /* lightfunc always frozen and sealed */
38521 		                          (is_frozen ^ 1)); /* buffer sealed but not frozen (index props writable) */
38522 	} else {
38523 		/* ES2015 Sections 19.1.2.12, 19.1.2.13: anything other than an object
38524 		 * is considered to be already sealed and frozen.
38525 		 */
38526 		h = duk_get_hobject(thr, 0);
38527 		duk_push_boolean(thr, (h == NULL) ||
38528 		                      duk_hobject_object_is_sealed_frozen_helper(thr, h, is_frozen /*is_frozen*/));
38529 	}
38530 	return 1;
38531 }
38532 #endif  /* DUK_USE_OBJECT_BUILTIN */
38533 
38534 #if defined(DUK_USE_OBJECT_BUILTIN)
38535 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_hthread *thr) {
38536 	DUK_ASSERT_TOP(thr, 0);
38537 	(void) duk_push_this_coercible_to_object(thr);
38538 	duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_TO_STRING);
38539 #if 0  /* This is mentioned explicitly in the E5.1 spec, but duk_call_method() checks for it in practice. */
38540 	duk_require_callable(thr, 1);
38541 #endif
38542 	duk_dup_0(thr);  /* -> [ O toString O ] */
38543 	duk_call_method(thr, 0);  /* XXX: call method tail call? */
38544 	return 1;
38545 }
38546 #endif  /* DUK_USE_OBJECT_BUILTIN */
38547 
38548 #if defined(DUK_USE_OBJECT_BUILTIN)
38549 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_value_of(duk_hthread *thr) {
38550 	/* For lightfuncs and plain buffers, returns Object() coerced. */
38551 	(void) duk_push_this_coercible_to_object(thr);
38552 	return 1;
38553 }
38554 #endif  /* DUK_USE_OBJECT_BUILTIN */
38555 
38556 #if defined(DUK_USE_OBJECT_BUILTIN)
38557 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_hthread *thr) {
38558 	duk_hobject *h_v;
38559 	duk_hobject *h_obj;
38560 
38561 	DUK_ASSERT_TOP(thr, 1);
38562 
38563 	h_v = duk_get_hobject(thr, 0);
38564 	if (!h_v) {
38565 		duk_push_false(thr);  /* XXX: tail call: return duk_push_false(thr) */
38566 		return 1;
38567 	}
38568 
38569 	h_obj = duk_push_this_coercible_to_object(thr);
38570 	DUK_ASSERT(h_obj != NULL);
38571 
38572 	/* E5.1 Section 15.2.4.6, step 3.a, lookup proto once before compare.
38573 	 * Prototype loops should cause an error to be thrown.
38574 	 */
38575 	duk_push_boolean(thr, duk_hobject_prototype_chain_contains(thr, DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_v), h_obj, 0 /*ignore_loop*/));
38576 	return 1;
38577 }
38578 #endif  /* DUK_USE_OBJECT_BUILTIN */
38579 
38580 #if defined(DUK_USE_OBJECT_BUILTIN)
38581 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_has_own_property(duk_hthread *thr) {
38582 	return (duk_ret_t) duk_hobject_object_ownprop_helper(thr, 0 /*required_desc_flags*/);
38583 }
38584 #endif  /* DUK_USE_OBJECT_BUILTIN */
38585 
38586 #if defined(DUK_USE_OBJECT_BUILTIN)
38587 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_hthread *thr) {
38588 	return (duk_ret_t) duk_hobject_object_ownprop_helper(thr, DUK_PROPDESC_FLAG_ENUMERABLE /*required_desc_flags*/);
38589 }
38590 #endif  /* DUK_USE_OBJECT_BUILTIN */
38591 
38592 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
38593 /* Shared helper to implement Object.getPrototypeOf,
38594  * Object.prototype.__proto__ getter, and Reflect.getPrototypeOf.
38595  *
38596  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
38597  */
38598 DUK_INTERNAL duk_ret_t duk_bi_object_getprototype_shared(duk_hthread *thr) {
38599 	/*
38600 	 *  magic = 0: __proto__ getter
38601 	 *  magic = 1: Object.getPrototypeOf()
38602 	 *  magic = 2: Reflect.getPrototypeOf()
38603 	 */
38604 
38605 	duk_hobject *h;
38606 	duk_hobject *proto;
38607 	duk_tval *tv;
38608 	duk_int_t magic;
38609 
38610 	magic = duk_get_current_magic(thr);
38611 
38612 	if (magic == 0) {
38613 		DUK_ASSERT_TOP(thr, 0);
38614 		duk_push_this_coercible_to_object(thr);
38615 	}
38616 	DUK_ASSERT(duk_get_top(thr) >= 1);
38617 	if (magic < 2) {
38618 		/* ES2015 Section 19.1.2.9, step 1 */
38619 		duk_to_object(thr, 0);
38620 	}
38621 	tv = DUK_GET_TVAL_POSIDX(thr, 0);
38622 
38623 	switch (DUK_TVAL_GET_TAG(tv)) {
38624 	case DUK_TAG_BUFFER:
38625 		proto = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
38626 		break;
38627 	case DUK_TAG_LIGHTFUNC:
38628 		proto = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
38629 		break;
38630 	case DUK_TAG_OBJECT:
38631 		h = DUK_TVAL_GET_OBJECT(tv);
38632 		proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
38633 		break;
38634 	default:
38635 		/* This implicitly handles CheckObjectCoercible() caused
38636 		 * TypeError.
38637 		 */
38638 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
38639 	}
38640 	if (proto != NULL) {
38641 		duk_push_hobject(thr, proto);
38642 	} else {
38643 		duk_push_null(thr);
38644 	}
38645 	return 1;
38646 }
38647 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
38648 
38649 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
38650 /* Shared helper to implement ES2015 Object.setPrototypeOf,
38651  * Object.prototype.__proto__ setter, and Reflect.setPrototypeOf.
38652  *
38653  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
38654  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.setprototypeof
38655  */
38656 DUK_INTERNAL duk_ret_t duk_bi_object_setprototype_shared(duk_hthread *thr) {
38657 	/*
38658 	 *  magic = 0: __proto__ setter
38659 	 *  magic = 1: Object.setPrototypeOf()
38660 	 *  magic = 2: Reflect.setPrototypeOf()
38661 	 */
38662 
38663 	duk_hobject *h_obj;
38664 	duk_hobject *h_new_proto;
38665 	duk_hobject *h_curr;
38666 	duk_ret_t ret_success = 1;  /* retval for success path */
38667 	duk_uint_t mask;
38668 	duk_int_t magic;
38669 
38670 	/* Preliminaries for __proto__ and setPrototypeOf (E6 19.1.2.18 steps 1-4). */
38671 	magic = duk_get_current_magic(thr);
38672 	if (magic == 0) {
38673 		duk_push_this_check_object_coercible(thr);
38674 		duk_insert(thr, 0);
38675 		if (!duk_check_type_mask(thr, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT)) {
38676 			return 0;
38677 		}
38678 
38679 		/* __proto__ setter returns 'undefined' on success unlike the
38680 		 * setPrototypeOf() call which returns the target object.
38681 		 */
38682 		ret_success = 0;
38683 	} else {
38684 		if (magic == 1) {
38685 			duk_require_object_coercible(thr, 0);
38686 		} else {
38687 			duk_require_hobject_accept_mask(thr, 0,
38688 			                                DUK_TYPE_MASK_LIGHTFUNC |
38689 			                                DUK_TYPE_MASK_BUFFER);
38690 		}
38691 		duk_require_type_mask(thr, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT);
38692 	}
38693 
38694 	h_new_proto = duk_get_hobject(thr, 1);
38695 	/* h_new_proto may be NULL */
38696 
38697 	mask = duk_get_type_mask(thr, 0);
38698 	if (mask & (DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {
38699 		duk_hobject *curr_proto;
38700 		curr_proto = thr->builtins[(mask & DUK_TYPE_MASK_LIGHTFUNC) ?
38701 		                               DUK_BIDX_FUNCTION_PROTOTYPE :
38702 		                               DUK_BIDX_UINT8ARRAY_PROTOTYPE];
38703 		if (h_new_proto == curr_proto) {
38704 			goto skip;
38705 		}
38706 		goto fail_nonextensible;
38707 	}
38708 	h_obj = duk_get_hobject(thr, 0);
38709 	if (h_obj == NULL) {
38710 		goto skip;
38711 	}
38712 	DUK_ASSERT(h_obj != NULL);
38713 
38714 	/* [[SetPrototypeOf]] standard behavior, E6 9.1.2. */
38715 	/* TODO: implement Proxy object support here */
38716 
38717 	if (h_new_proto == DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_obj)) {
38718 		goto skip;
38719 	}
38720 	if (!DUK_HOBJECT_HAS_EXTENSIBLE(h_obj)) {
38721 		goto fail_nonextensible;
38722 	}
38723 	for (h_curr = h_new_proto; h_curr != NULL; h_curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_curr)) {
38724 		/* Loop prevention. */
38725 		if (h_curr == h_obj) {
38726 			goto fail_loop;
38727 		}
38728 	}
38729 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h_obj, h_new_proto);
38730 	/* fall thru */
38731 
38732  skip:
38733 	duk_set_top(thr, 1);
38734 	if (magic == 2) {
38735 		duk_push_true(thr);
38736 	}
38737 	return ret_success;
38738 
38739  fail_nonextensible:
38740  fail_loop:
38741 	if (magic != 2) {
38742 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
38743 	} else {
38744 		duk_push_false(thr);
38745 		return 1;
38746 	}
38747 }
38748 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
38749 
38750 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
38751 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_property(duk_hthread *thr) {
38752 	/*
38753 	 *  magic = 0: Object.defineProperty()
38754 	 *  magic = 1: Reflect.defineProperty()
38755 	 */
38756 
38757 	duk_hobject *obj;
38758 	duk_hstring *key;
38759 	duk_hobject *get;
38760 	duk_hobject *set;
38761 	duk_idx_t idx_value;
38762 	duk_uint_t defprop_flags;
38763 	duk_small_uint_t magic;
38764 	duk_bool_t throw_flag;
38765 	duk_bool_t ret;
38766 
38767 	DUK_ASSERT(thr != NULL);
38768 
38769 	DUK_DDD(DUK_DDDPRINT("Object.defineProperty(): ctx=%p obj=%!T key=%!T desc=%!T",
38770 	                     (void *) thr,
38771 	                     (duk_tval *) duk_get_tval(thr, 0),
38772 	                     (duk_tval *) duk_get_tval(thr, 1),
38773 	                     (duk_tval *) duk_get_tval(thr, 2)));
38774 
38775 	/* [ obj key desc ] */
38776 
38777 	magic = (duk_small_uint_t) duk_get_current_magic(thr);
38778 
38779 	/* Lightfuncs are currently supported by coercing to a temporary
38780 	 * Function object; changes will be allowed (the coerced value is
38781 	 * extensible) but will be lost.  Same for plain buffers.
38782 	 */
38783 	obj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
38784 	DUK_ASSERT(obj != NULL);
38785 	key = duk_to_property_key_hstring(thr, 1);
38786 	(void) duk_require_hobject(thr, 2);
38787 
38788 	DUK_ASSERT(obj != NULL);
38789 	DUK_ASSERT(key != NULL);
38790 	DUK_ASSERT(duk_get_hobject(thr, 2) != NULL);
38791 
38792 	/*
38793 	 *  Validate and convert argument property descriptor (an ECMAScript
38794 	 *  object) into a set of defprop_flags and possibly property value,
38795 	 *  getter, and/or setter values on the value stack.
38796 	 *
38797 	 *  Lightfunc set/get values are coerced to full Functions.
38798 	 */
38799 
38800 	duk_hobject_prepare_property_descriptor(thr,
38801 	                                        2 /*idx_desc*/,
38802 	                                        &defprop_flags,
38803 	                                        &idx_value,
38804 	                                        &get,
38805 	                                        &set);
38806 
38807 	/*
38808 	 *  Use Object.defineProperty() helper for the actual operation.
38809 	 */
38810 
38811 	DUK_ASSERT(magic == 0U || magic == 1U);
38812 	throw_flag = magic ^ 1U;
38813 	ret = duk_hobject_define_property_helper(thr,
38814 	                                         defprop_flags,
38815 	                                         obj,
38816 	                                         key,
38817 	                                         idx_value,
38818 	                                         get,
38819 	                                         set,
38820 	                                         throw_flag);
38821 
38822 	/* Ignore the normalize/validate helper outputs on the value stack,
38823 	 * they're popped automatically.
38824 	 */
38825 
38826 	if (magic == 0U) {
38827 		/* Object.defineProperty(): return target object. */
38828 		duk_push_hobject(thr, obj);
38829 	} else {
38830 		/* Reflect.defineProperty(): return success/fail. */
38831 		duk_push_boolean(thr, ret);
38832 	}
38833 	return 1;
38834 }
38835 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
38836 
38837 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
38838 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_hthread *thr) {
38839 	DUK_ASSERT_TOP(thr, 2);
38840 
38841 	/* ES2015 Section 19.1.2.6, step 1 */
38842 	if (duk_get_current_magic(thr) == 0) {
38843 		duk_to_object(thr, 0);
38844 	}
38845 
38846 	/* [ obj key ] */
38847 
38848 	duk_hobject_object_get_own_property_descriptor(thr, -2);
38849 	return 1;
38850 }
38851 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
38852 
38853 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
38854 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_extensible(duk_hthread *thr) {
38855 	/*
38856 	 *  magic = 0: Object.isExtensible()
38857 	 *  magic = 1: Reflect.isExtensible()
38858 	 */
38859 
38860 	duk_hobject *h;
38861 
38862 	if (duk_get_current_magic(thr) == 0) {
38863 		h = duk_get_hobject(thr, 0);
38864 	} else {
38865 		/* Reflect.isExtensible(): throw if non-object, but we accept lightfuncs
38866 		 * and plain buffers here because they pretend to be objects.
38867 		 */
38868 		h = duk_require_hobject_accept_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
38869 	}
38870 
38871 	duk_push_boolean(thr, (h != NULL) && DUK_HOBJECT_HAS_EXTENSIBLE(h));
38872 	return 1;
38873 }
38874 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
38875 
38876 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
38877 /* Shared helper for various key/symbol listings, magic:
38878  * 0=Object.keys()
38879  * 1=Object.getOwnPropertyNames(),
38880  * 2=Object.getOwnPropertySymbols(),
38881  * 3=Reflect.ownKeys()
38882  */
38883 DUK_LOCAL const duk_small_uint_t duk__object_keys_enum_flags[4] = {
38884 	/* Object.keys() */
38885 	DUK_ENUM_OWN_PROPERTIES_ONLY |
38886 	    DUK_ENUM_NO_PROXY_BEHAVIOR,
38887 
38888 	/* Object.getOwnPropertyNames() */
38889 	DUK_ENUM_INCLUDE_NONENUMERABLE |
38890 	    DUK_ENUM_OWN_PROPERTIES_ONLY |
38891 	    DUK_ENUM_NO_PROXY_BEHAVIOR,
38892 
38893 	/* Object.getOwnPropertySymbols() */
38894 	DUK_ENUM_INCLUDE_SYMBOLS |
38895 	    DUK_ENUM_OWN_PROPERTIES_ONLY |
38896 	    DUK_ENUM_EXCLUDE_STRINGS |
38897 	    DUK_ENUM_INCLUDE_NONENUMERABLE |
38898 	    DUK_ENUM_NO_PROXY_BEHAVIOR,
38899 
38900 	/* Reflect.ownKeys() */
38901 	DUK_ENUM_INCLUDE_SYMBOLS |
38902 	    DUK_ENUM_OWN_PROPERTIES_ONLY |
38903 	    DUK_ENUM_INCLUDE_NONENUMERABLE |
38904 	    DUK_ENUM_NO_PROXY_BEHAVIOR
38905 };
38906 
38907 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_keys_shared(duk_hthread *thr) {
38908 	duk_hobject *obj;
38909 #if defined(DUK_USE_ES6_PROXY)
38910 	duk_hobject *h_proxy_target;
38911 	duk_hobject *h_proxy_handler;
38912 	duk_hobject *h_trap_result;
38913 #endif
38914 	duk_small_uint_t enum_flags;
38915 	duk_int_t magic;
38916 
38917 	DUK_ASSERT_TOP(thr, 1);
38918 
38919 	magic = duk_get_current_magic(thr);
38920 	if (magic == 3) {
38921 		/* ES2015 Section 26.1.11 requires a TypeError for non-objects.  Lightfuncs
38922 		 * and plain buffers pretend to be objects, so accept those too.
38923 		 */
38924 		obj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
38925 	} else {
38926 		/* ES2015: ToObject coerce. */
38927 		obj = duk_to_hobject(thr, 0);
38928 	}
38929 	DUK_ASSERT(obj != NULL);
38930 	DUK_UNREF(obj);
38931 
38932 	/* XXX: proxy chains */
38933 
38934 #if defined(DUK_USE_ES6_PROXY)
38935 	/* XXX: better sharing of code between proxy target call sites */
38936 	if (DUK_LIKELY(!duk_hobject_proxy_check(obj,
38937 	                                        &h_proxy_target,
38938 	                                        &h_proxy_handler))) {
38939 		goto skip_proxy;
38940 	}
38941 
38942 	duk_push_hobject(thr, h_proxy_handler);
38943 	if (!duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_OWN_KEYS)) {
38944 		/* Careful with reachability here: don't pop 'obj' before pushing
38945 		 * proxy target.
38946 		 */
38947 		DUK_DDD(DUK_DDDPRINT("no ownKeys trap, get keys of target instead"));
38948 		duk_pop_2(thr);
38949 		duk_push_hobject(thr, h_proxy_target);
38950 		duk_replace(thr, 0);
38951 		DUK_ASSERT_TOP(thr, 1);
38952 		goto skip_proxy;
38953 	}
38954 
38955 	/* [ obj handler trap ] */
38956 	duk_insert(thr, -2);
38957 	duk_push_hobject(thr, h_proxy_target);  /* -> [ obj trap handler target ] */
38958 	duk_call_method(thr, 1 /*nargs*/);      /* -> [ obj trap_result ] */
38959 	h_trap_result = duk_require_hobject(thr, -1);
38960 	DUK_UNREF(h_trap_result);
38961 
38962 	magic = duk_get_current_magic(thr);
38963 	DUK_ASSERT(magic >= 0 && magic < (duk_int_t) (sizeof(duk__object_keys_enum_flags) / sizeof(duk_small_uint_t)));
38964 	enum_flags = duk__object_keys_enum_flags[magic];
38965 
38966 	duk_proxy_ownkeys_postprocess(thr, h_proxy_target, enum_flags);
38967 	return 1;
38968 
38969  skip_proxy:
38970 #endif  /* DUK_USE_ES6_PROXY */
38971 
38972 	DUK_ASSERT_TOP(thr, 1);
38973 	magic = duk_get_current_magic(thr);
38974 	DUK_ASSERT(magic >= 0 && magic < (duk_int_t) (sizeof(duk__object_keys_enum_flags) / sizeof(duk_small_uint_t)));
38975 	enum_flags = duk__object_keys_enum_flags[magic];
38976 	return duk_hobject_get_enumerated_keys(thr, enum_flags);
38977 }
38978 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
38979 
38980 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
38981 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_hthread *thr) {
38982 	/*
38983 	 *  magic = 0: Object.preventExtensions()
38984 	 *  magic = 1: Reflect.preventExtensions()
38985 	 */
38986 
38987 	duk_hobject *h;
38988 	duk_uint_t mask;
38989 	duk_int_t magic;
38990 
38991 	magic = duk_get_current_magic(thr);
38992 
38993 	/* Silent success for lightfuncs and plain buffers always. */
38994 	mask = DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER;
38995 
38996 	/* Object.preventExtensions() silent success for non-object. */
38997 	if (magic == 0) {
38998 		mask |= DUK_TYPE_MASK_UNDEFINED |
38999 		        DUK_TYPE_MASK_NULL |
39000 		        DUK_TYPE_MASK_BOOLEAN |
39001 		        DUK_TYPE_MASK_NUMBER |
39002 		        DUK_TYPE_MASK_STRING |
39003 		        DUK_TYPE_MASK_POINTER;
39004 	}
39005 
39006 	if (duk_check_type_mask(thr, 0, mask)) {
39007 		/* Not an object, already non-extensible so always success. */
39008 		goto done;
39009 	}
39010 	h = duk_require_hobject(thr, 0);
39011 	DUK_ASSERT(h != NULL);
39012 
39013 	DUK_HOBJECT_CLEAR_EXTENSIBLE(h);
39014 
39015 	/* A non-extensible object cannot gain any more properties,
39016 	 * so this is a good time to compact.
39017 	 */
39018 	duk_hobject_compact_props(thr, h);
39019 
39020  done:
39021 	if (magic == 1) {
39022 		duk_push_true(thr);
39023 	}
39024 	return 1;
39025 }
39026 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
39027 
39028 /*
39029  *  __defineGetter__, __defineSetter__, __lookupGetter__, __lookupSetter__
39030  */
39031 
39032 #if defined(DUK_USE_ES8)
39033 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_defineaccessor(duk_hthread *thr) {
39034 	duk_push_this(thr);
39035 	duk_insert(thr, 0);
39036 	duk_to_object(thr, 0);
39037 	duk_require_callable(thr, 2);
39038 
39039 	/* [ ToObject(this) key getter/setter ] */
39040 
39041 	/* ToPropertyKey() coercion is not needed, duk_def_prop() does it. */
39042 	duk_def_prop(thr, 0, DUK_DEFPROP_SET_ENUMERABLE |
39043 	                     DUK_DEFPROP_SET_CONFIGURABLE |
39044 	                     (duk_get_current_magic(thr) ? DUK_DEFPROP_HAVE_SETTER : DUK_DEFPROP_HAVE_GETTER));
39045 	return 0;
39046 }
39047 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_lookupaccessor(duk_hthread *thr) {
39048 	duk_uint_t sanity;
39049 
39050 	duk_push_this(thr);
39051 	duk_to_object(thr, -1);
39052 
39053 	/* XXX: Prototype walk (with sanity) should be a core property
39054 	 * operation, could add a flag to e.g. duk_get_prop_desc().
39055 	 */
39056 
39057 	/* ToPropertyKey() coercion is not needed, duk_get_prop_desc() does it. */
39058 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
39059 	while (!duk_is_undefined(thr, -1)) {
39060 		/* [ key obj ] */
39061 		duk_dup(thr, 0);
39062 		duk_get_prop_desc(thr, 1, 0 /*flags*/);
39063 		if (!duk_is_undefined(thr, -1)) {
39064 			duk_get_prop_stridx(thr, -1, (duk_get_current_magic(thr) != 0 ? DUK_STRIDX_SET : DUK_STRIDX_GET));
39065 			return 1;
39066 		}
39067 		duk_pop(thr);
39068 
39069 		if (DUK_UNLIKELY(sanity-- == 0)) {
39070 			DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
39071 			DUK_WO_NORETURN(return 0;);
39072 		}
39073 
39074 		duk_get_prototype(thr, -1);
39075 		duk_remove(thr, -2);
39076 	}
39077 	return 1;
39078 }
39079 #endif  /* DUK_USE_ES8 */
39080 #line 1 "duk_bi_performance.c"
39081 /*
39082  *  High resolution time API (performance.now() et al)
39083  *
39084  *  API specification: https://encoding.spec.whatwg.org/#ap://www.w3.org/TR/hr-time/
39085  */
39086 
39087 /* #include duk_internal.h -> already included */
39088 
39089 #if defined(DUK_USE_PERFORMANCE_BUILTIN)
39090 DUK_INTERNAL duk_ret_t duk_bi_performance_now(duk_hthread *thr) {
39091 	/* From API spec:
39092 	 * The DOMHighResTimeStamp type is used to store a time value in
39093 	 * milliseconds, measured relative from the time origin, global
39094 	 * monotonic clock, or a time value that represents a duration
39095 	 * between two DOMHighResTimeStamp's.
39096 	 */
39097 	duk_push_number(thr, duk_time_get_monotonic_time(thr));
39098 	return 1;
39099 }
39100 
39101 #if 0  /* Missing until semantics decided. */
39102 DUK_INTERNAL duk_ret_t duk_bi_performance_timeorigin_getter(duk_hthread *thr) {
39103 	/* No decision yet how to handle timeOrigins, e.g. should one be
39104 	 * initialized per heap, or per global object set.  See
39105 	 * https://www.w3.org/TR/hr-time/#time-origin.
39106 	 */
39107 	duk_push_uint(thr, 0);
39108 	return 1;
39109 }
39110 #endif  /* 0 */
39111 #endif  /* DUK_USE_PERFORMANCE_BUILTIN */
39112 #line 1 "duk_bi_pointer.c"
39113 /*
39114  *  Pointer built-ins
39115  */
39116 
39117 /* #include duk_internal.h -> already included */
39118 
39119 /*
39120  *  Constructor
39121  */
39122 
39123 DUK_INTERNAL duk_ret_t duk_bi_pointer_constructor(duk_hthread *thr) {
39124 	/* XXX: this behavior is quite useless now; it would be nice to be able
39125 	 * to create pointer values from e.g. numbers or strings.  Numbers are
39126 	 * problematic on 64-bit platforms though.  Hex encoded strings?
39127 	 */
39128 	if (duk_get_top(thr) == 0) {
39129 		duk_push_pointer(thr, NULL);
39130 	} else {
39131 		duk_to_pointer(thr, 0);
39132 	}
39133 	DUK_ASSERT(duk_is_pointer(thr, 0));
39134 	duk_set_top(thr, 1);
39135 
39136 	if (duk_is_constructor_call(thr)) {
39137 		(void) duk_push_object_helper(thr,
39138 		                              DUK_HOBJECT_FLAG_EXTENSIBLE |
39139 		                              DUK_HOBJECT_FLAG_FASTREFS |
39140 		                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER),
39141 		                              DUK_BIDX_POINTER_PROTOTYPE);
39142 
39143 		/* Pointer object internal value is immutable */
39144 		duk_dup_0(thr);
39145 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
39146 	}
39147 	/* Note: unbalanced stack on purpose */
39148 
39149 	return 1;
39150 }
39151 
39152 /*
39153  *  toString(), valueOf()
39154  */
39155 
39156 DUK_INTERNAL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_hthread *thr) {
39157 	duk_tval *tv;
39158 	duk_small_int_t to_string = duk_get_current_magic(thr);
39159 
39160 	duk_push_this(thr);
39161 	tv = duk_require_tval(thr, -1);
39162 	DUK_ASSERT(tv != NULL);
39163 
39164 	if (DUK_TVAL_IS_POINTER(tv)) {
39165 		/* nop */
39166 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
39167 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
39168 		DUK_ASSERT(h != NULL);
39169 
39170 		/* Must be a "pointer object", i.e. class "Pointer" */
39171 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_POINTER) {
39172 			goto type_error;
39173 		}
39174 
39175 		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
39176 	} else {
39177 		goto type_error;
39178 	}
39179 
39180 	if (to_string) {
39181 		duk_to_string(thr, -1);
39182 	}
39183 	return 1;
39184 
39185  type_error:
39186 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
39187 }
39188 #line 1 "duk_bi_promise.c"
39189 /*
39190  *  Promise built-in
39191  */
39192 
39193 /* #include duk_internal.h -> already included */
39194 
39195 #if defined(DUK_USE_PROMISE_BUILTIN)
39196 
39197 DUK_INTERNAL duk_ret_t duk_bi_promise_constructor(duk_hthread *thr) {
39198 	DUK_ERROR_TYPE(thr, "unimplemented");
39199 	DUK_WO_NORETURN(return 0;);
39200 }
39201 
39202 DUK_INTERNAL duk_ret_t duk_bi_promise_all(duk_hthread *thr) {
39203 	DUK_ERROR_TYPE(thr, "unimplemented");
39204 	DUK_WO_NORETURN(return 0;);
39205 }
39206 
39207 DUK_INTERNAL duk_ret_t duk_bi_promise_race(duk_hthread *thr) {
39208 	DUK_ERROR_TYPE(thr, "unimplemented");
39209 	DUK_WO_NORETURN(return 0;);
39210 }
39211 
39212 DUK_INTERNAL duk_ret_t duk_bi_promise_reject(duk_hthread *thr) {
39213 	DUK_ERROR_TYPE(thr, "unimplemented");
39214 	DUK_WO_NORETURN(return 0;);
39215 }
39216 
39217 DUK_INTERNAL duk_ret_t duk_bi_promise_resolve(duk_hthread *thr) {
39218 	DUK_ERROR_TYPE(thr, "unimplemented");
39219 	DUK_WO_NORETURN(return 0;);
39220 }
39221 
39222 DUK_INTERNAL duk_ret_t duk_bi_promise_catch(duk_hthread *thr) {
39223 	DUK_ERROR_TYPE(thr, "unimplemented");
39224 	DUK_WO_NORETURN(return 0;);
39225 }
39226 
39227 DUK_INTERNAL duk_ret_t duk_bi_promise_then(duk_hthread *thr) {
39228 	DUK_ERROR_TYPE(thr, "unimplemented");
39229 	DUK_WO_NORETURN(return 0;);
39230 }
39231 
39232 #endif  /* DUK_USE_PROMISE_BUILTIN */
39233 #line 1 "duk_bi_proxy.c"
39234 /*
39235  *  Proxy built-in (ES2015)
39236  */
39237 
39238 /* #include duk_internal.h -> already included */
39239 
39240 #if defined(DUK_USE_ES6_PROXY)
39241 /* Post-process a Proxy ownKeys() result at stack top.  Push a cleaned up
39242  * array of valid result keys (strings or symbols).  TypeError for invalid
39243  * values.  Flags are shared with duk_enum().
39244  */
39245 DUK_INTERNAL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h_proxy_target, duk_uint_t flags) {
39246 	duk_uarridx_t i, len, idx;
39247 	duk_propdesc desc;
39248 
39249 	DUK_ASSERT_CTX_VALID(thr);
39250 	DUK_ASSERT(h_proxy_target != NULL);
39251 
39252 	len = (duk_uarridx_t) duk_get_length(thr, -1);
39253 	idx = 0;
39254 	duk_push_array(thr);
39255 	/* XXX: preallocated dense array, fill in directly */
39256 	for (i = 0; i < len; i++) {
39257 		duk_hstring *h;
39258 
39259 		/* [ obj trap_result res_arr ] */
39260 		(void) duk_get_prop_index(thr, -2, i);
39261 		h = duk_get_hstring(thr, -1);
39262 		if (h == NULL) {
39263 			DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr);
39264 			DUK_WO_NORETURN(return;);
39265 		}
39266 
39267 		if (!(flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
39268 			/* No support for 'getOwnPropertyDescriptor' trap yet,
39269 			 * so check enumerability always from target object
39270 			 * descriptor.
39271 			 */
39272 			if (duk_hobject_get_own_propdesc(thr, h_proxy_target, duk_known_hstring(thr, -1), &desc, 0 /*flags*/)) {
39273 				if ((desc.flags & DUK_PROPDESC_FLAG_ENUMERABLE) == 0) {
39274 					DUK_DDD(DUK_DDDPRINT("ignore non-enumerable property: %!T", duk_get_tval(thr, -1)));
39275 					goto skip_key;
39276 				}
39277 			} else {
39278 				DUK_DDD(DUK_DDDPRINT("ignore non-existent property: %!T", duk_get_tval(thr, -1)));
39279 				goto skip_key;
39280 			}
39281 		}
39282 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
39283 			if (!(flags & DUK_ENUM_INCLUDE_SYMBOLS)) {
39284 				DUK_DDD(DUK_DDDPRINT("ignore symbol property: %!T", duk_get_tval(thr, -1)));
39285 				goto skip_key;
39286 			}
39287 			if (DUK_HSTRING_HAS_HIDDEN(h) && !(flags & DUK_ENUM_INCLUDE_HIDDEN)) {
39288 				DUK_DDD(DUK_DDDPRINT("ignore hidden symbol property: %!T", duk_get_tval(thr, -1)));
39289 				goto skip_key;
39290 			}
39291 		} else {
39292 			if (flags & DUK_ENUM_EXCLUDE_STRINGS) {
39293 				DUK_DDD(DUK_DDDPRINT("ignore string property: %!T", duk_get_tval(thr, -1)));
39294 				goto skip_key;
39295 			}
39296 		}
39297 
39298 		/* [ obj trap_result res_arr propname ] */
39299 		duk_put_prop_index(thr, -2, idx++);
39300 		continue;
39301 
39302 	 skip_key:
39303 		duk_pop(thr);
39304 		continue;
39305 	}
39306 
39307 	/* XXX: Missing trap result validation for non-configurable target keys
39308 	 * (must be present), for non-extensible target all target keys must be
39309 	 * present and no extra keys can be present.
39310 	 * http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys
39311 	 */
39312 
39313 	/* XXX: The key enumerability check should trigger the "getOwnPropertyDescriptor"
39314 	 * trap which has not yet been implemented.  In the absence of such a trap,
39315 	 * the enumerability should be checked from the target object; this is
39316 	 * handled above.
39317 	 */
39318 }
39319 #endif  /* DUK_USE_ES6_PROXY */
39320 
39321 #if defined(DUK_USE_ES6_PROXY)
39322 DUK_INTERNAL duk_ret_t duk_bi_proxy_constructor(duk_hthread *thr) {
39323 	DUK_ASSERT_TOP(thr, 2);  /* [ target handler ] */
39324 
39325 	duk_require_constructor_call(thr);
39326 	duk_push_proxy(thr, 0 /*flags*/);  /* [ target handler ] -> [ proxy ] */
39327 	return 1;  /* replacement */
39328 }
39329 #endif  /* DUK_USE_ES6_PROXY */
39330 #line 1 "duk_bi_reflect.c"
39331 /*
39332  *  'Reflect' built-in (ES2016 Section 26.1)
39333  *  http://www.ecma-international.org/ecma-262/7.0/#sec-reflect-object
39334  *
39335  *  Many Reflect built-in functions are provided by shared helpers in
39336  *  duk_bi_object.c or duk_bi_function.c.
39337  */
39338 
39339 /* #include duk_internal.h -> already included */
39340 
39341 #if defined(DUK_USE_REFLECT_BUILTIN)
39342 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_delete_property(duk_hthread *thr) {
39343 	duk_tval *tv_obj;
39344 	duk_tval *tv_key;
39345 	duk_bool_t ret;
39346 
39347 	DUK_ASSERT_TOP(thr, 2);
39348 	(void) duk_require_hobject(thr, 0);
39349 	(void) duk_to_string(thr, 1);
39350 
39351 	/* [ target key ] */
39352 
39353 	DUK_ASSERT(thr != NULL);
39354 	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
39355 	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
39356 	ret = duk_hobject_delprop(thr, tv_obj, tv_key, 0 /*throw_flag*/);
39357 	duk_push_boolean(thr, ret);
39358 	return 1;
39359 }
39360 
39361 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_get(duk_hthread *thr) {
39362 	duk_tval *tv_obj;
39363 	duk_tval *tv_key;
39364 	duk_idx_t nargs;
39365 
39366 	DUK_ASSERT(thr != NULL);
39367 	nargs = duk_get_top_require_min(thr, 2 /*min_top*/);
39368 	(void) duk_require_hobject(thr, 0);
39369 	(void) duk_to_string(thr, 1);
39370 	if (nargs >= 3 && !duk_strict_equals(thr, 0, 2)) {
39371 		/* XXX: [[Get]] receiver currently unsupported */
39372 		DUK_ERROR_UNSUPPORTED(thr);
39373 		DUK_WO_NORETURN(return 0;);
39374 	}
39375 
39376 	/* [ target key receiver? ...? ] */
39377 
39378 	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
39379 	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
39380 	(void) duk_hobject_getprop(thr, tv_obj, tv_key);  /* This could also be a duk_get_prop(). */
39381 	return 1;
39382 }
39383 
39384 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_has(duk_hthread *thr) {
39385 	duk_tval *tv_obj;
39386 	duk_tval *tv_key;
39387 	duk_bool_t ret;
39388 
39389 	DUK_ASSERT(thr != NULL);
39390 	DUK_ASSERT_TOP(thr, 2);
39391 	(void) duk_require_hobject(thr, 0);
39392 	(void) duk_to_string(thr, 1);
39393 
39394 	/* [ target key ] */
39395 
39396 	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
39397 	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
39398 	ret = duk_hobject_hasprop(thr, tv_obj, tv_key);
39399 	duk_push_boolean(thr, ret);
39400 	return 1;
39401 }
39402 
39403 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_set(duk_hthread *thr) {
39404 	duk_tval *tv_obj;
39405 	duk_tval *tv_key;
39406 	duk_tval *tv_val;
39407 	duk_idx_t nargs;
39408 	duk_bool_t ret;
39409 
39410 	DUK_ASSERT(thr != NULL);
39411 	nargs = duk_get_top_require_min(thr, 3 /*min_top*/);
39412 	(void) duk_require_hobject(thr, 0);
39413 	(void) duk_to_string(thr, 1);
39414 	if (nargs >= 4 && !duk_strict_equals(thr, 0, 3)) {
39415 		/* XXX: [[Set]] receiver currently unsupported */
39416 		DUK_ERROR_UNSUPPORTED(thr);
39417 		DUK_WO_NORETURN(return 0;);
39418 	}
39419 
39420 	/* [ target key value receiver? ...? ] */
39421 
39422 	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
39423 	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
39424 	tv_val = DUK_GET_TVAL_POSIDX(thr, 2);
39425 	ret = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, 0 /*throw_flag*/);
39426 	duk_push_boolean(thr, ret);
39427 	return 1;
39428 }
39429 #endif  /* DUK_USE_REFLECT_BUILTIN */
39430 #line 1 "duk_bi_regexp.c"
39431 /*
39432  *  RegExp built-ins
39433  */
39434 
39435 /* #include duk_internal.h -> already included */
39436 
39437 #if defined(DUK_USE_REGEXP_SUPPORT)
39438 
39439 DUK_LOCAL void duk__get_this_regexp(duk_hthread *thr) {
39440 	duk_hobject *h;
39441 
39442 	duk_push_this(thr);
39443 	h = duk_require_hobject_with_class(thr, -1, DUK_HOBJECT_CLASS_REGEXP);
39444 	DUK_ASSERT(h != NULL);
39445 	DUK_UNREF(h);
39446 	duk_insert(thr, 0);  /* prepend regexp to valstack 0 index */
39447 }
39448 
39449 /* XXX: much to improve (code size) */
39450 DUK_INTERNAL duk_ret_t duk_bi_regexp_constructor(duk_hthread *thr) {
39451 	duk_hobject *h_pattern;
39452 
39453 	DUK_ASSERT_TOP(thr, 2);
39454 	h_pattern = duk_get_hobject(thr, 0);
39455 
39456 	if (!duk_is_constructor_call(thr) &&
39457 	    h_pattern != NULL &&
39458 	    DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP &&
39459 	    duk_is_undefined(thr, 1)) {
39460 		/* Called as a function, pattern has [[Class]] "RegExp" and
39461 		 * flags is undefined -> return object as is.
39462 		 */
39463 		/* XXX: ES2015 has a NewTarget SameValue() check which is not
39464 		 * yet implemented.
39465 		 */
39466 		duk_dup_0(thr);
39467 		return 1;
39468 	}
39469 
39470 	/* Else functionality is identical for function call and constructor
39471 	 * call.
39472 	 */
39473 
39474 	if (h_pattern != NULL &&
39475 	    DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP) {
39476 		duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_SOURCE);
39477 		if (duk_is_undefined(thr, 1)) {
39478 			/* In ES5 one would need to read the flags individually;
39479 			 * in ES2015 just read .flags.
39480 			 */
39481 			duk_get_prop_stridx(thr, 0, DUK_STRIDX_FLAGS);
39482 		} else {
39483 			/* In ES2015 allowed; overrides argument RegExp flags. */
39484 			duk_dup_1(thr);
39485 		}
39486 	} else {
39487 		if (duk_is_undefined(thr, 0)) {
39488 			duk_push_hstring_empty(thr);
39489 		} else {
39490 			duk_dup_0(thr);
39491 			duk_to_string(thr, -1);  /* Rejects Symbols. */
39492 		}
39493 		if (duk_is_undefined(thr, 1)) {
39494 			duk_push_hstring_empty(thr);
39495 		} else {
39496 			duk_dup_1(thr);
39497 			duk_to_string(thr, -1);  /* Rejects Symbols. */
39498 		}
39499 
39500 		/* [ ... pattern flags ] */
39501 	}
39502 
39503 	DUK_DDD(DUK_DDDPRINT("RegExp constructor/function call, pattern=%!T, flags=%!T",
39504 	                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
39505 
39506 	/* [ ... pattern flags ] (both uncoerced) */
39507 
39508 	duk_to_string(thr, -2);
39509 	duk_to_string(thr, -1);
39510 	duk_regexp_compile(thr);
39511 
39512 	/* [ ... bytecode escaped_source ] */
39513 
39514 	duk_regexp_create_instance(thr);
39515 
39516 	/* [ ... RegExp ] */
39517 
39518 	return 1;
39519 }
39520 
39521 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_exec(duk_hthread *thr) {
39522 	duk__get_this_regexp(thr);
39523 
39524 	/* [ regexp input ] */
39525 
39526 	duk_regexp_match(thr);
39527 
39528 	/* [ result ] */
39529 
39530 	return 1;
39531 }
39532 
39533 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_test(duk_hthread *thr) {
39534 	duk__get_this_regexp(thr);
39535 
39536 	/* [ regexp input ] */
39537 
39538 	/* result object is created and discarded; wasteful but saves code space */
39539 	duk_regexp_match(thr);
39540 
39541 	/* [ result ] */
39542 
39543 	duk_push_boolean(thr, (duk_is_null(thr, -1) ? 0 : 1));
39544 
39545 	return 1;
39546 }
39547 
39548 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_tostring(duk_hthread *thr) {
39549 	/* This must be generic in ES2015 and later. */
39550 	DUK_ASSERT_TOP(thr, 0);
39551 	duk_push_this(thr);
39552 	duk_push_literal(thr, "/");
39553 	duk_get_prop_stridx(thr, 0, DUK_STRIDX_SOURCE);
39554 	duk_dup_m2(thr);  /* another "/" */
39555 	duk_get_prop_stridx(thr, 0, DUK_STRIDX_FLAGS);
39556 	duk_concat(thr, 4);
39557 	return 1;
39558 }
39559 
39560 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_flags(duk_hthread *thr) {
39561 	/* .flags is ES2015 but present even when ES2015 bindings are
39562 	 * disabled because the constructor relies on it.
39563 	 */
39564 	duk_uint8_t buf[8];  /* enough for all flags + NUL */
39565 	duk_uint8_t *p = buf;
39566 
39567 	/* .flags is generic and works on any object. */
39568 	duk_push_this(thr);
39569 	(void) duk_require_hobject(thr, -1);
39570 	if (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL)) {
39571 		*p++ = DUK_ASC_LC_G;
39572 	}
39573 	if (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_IGNORE_CASE, NULL)) {
39574 		*p++ = DUK_ASC_LC_I;
39575 	}
39576 	if (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_MULTILINE, NULL)) {
39577 		*p++ = DUK_ASC_LC_M;
39578 	}
39579 	/* .unicode: to be added */
39580 	/* .sticky: to be added */
39581 	*p++ = DUK_ASC_NUL;
39582 	DUK_ASSERT((duk_size_t) (p - buf) <= sizeof(buf));
39583 
39584 	duk_push_string(thr, (const char *) buf);
39585 	return 1;
39586 }
39587 
39588 /* Shared helper for providing .source, .global, .multiline, etc getters. */
39589 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_hthread *thr) {
39590 	duk_hstring *h_bc;
39591 	duk_small_uint_t re_flags;
39592 	duk_hobject *h;
39593 	duk_int_t magic;
39594 
39595 	DUK_ASSERT_TOP(thr, 0);
39596 
39597 	duk_push_this(thr);
39598 	h = duk_require_hobject(thr, -1);
39599 	magic = duk_get_current_magic(thr);
39600 
39601 	if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_REGEXP) {
39602 		duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_INT_SOURCE);
39603 		duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_INT_BYTECODE);
39604 		h_bc = duk_require_hstring(thr, -1);
39605 		re_flags = (duk_small_uint_t) DUK_HSTRING_GET_DATA(h_bc)[0];  /* Safe even if h_bc length is 0 (= NUL) */
39606 		duk_pop(thr);
39607 	} else if (h == thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]) {
39608 		/* In ES2015 and ES2016 a TypeError would be thrown here.
39609 		 * However, this had real world issues so ES2017 draft
39610 		 * allows RegExp.prototype specifically, returning '(?:)'
39611 		 * for .source and undefined for all flags.
39612 		 */
39613 		if (magic != 16 /* .source */) {
39614 			return 0;
39615 		}
39616 		duk_push_literal(thr, "(?:)");  /* .source handled by switch-case */
39617 		re_flags = 0;
39618 	} else {
39619 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
39620 	}
39621 
39622 	/* [ regexp source ] */
39623 
39624 	switch (magic) {
39625 	case 0: {  /* global */
39626 		duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_GLOBAL));
39627 		break;
39628 	}
39629 	case 1: {  /* ignoreCase */
39630 		duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_IGNORE_CASE));
39631 		break;
39632 	}
39633 	case 2: {  /* multiline */
39634 		duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_MULTILINE));
39635 		break;
39636 	}
39637 #if 0
39638 	/* Don't provide until implemented to avoid interfering with feature
39639 	 * detection in user code.
39640 	 */
39641 	case 3:    /* sticky */
39642 	case 4: {  /* unicode */
39643 		duk_push_false(thr);
39644 		break;
39645 	}
39646 #endif
39647 	default: {  /* source */
39648 		/* leave 'source' on top */
39649 		break;
39650 	}
39651 	}
39652 
39653 	return 1;
39654 }
39655 
39656 #endif  /* DUK_USE_REGEXP_SUPPORT */
39657 #line 1 "duk_bi_string.c"
39658 /*
39659  *  String built-ins
39660  *
39661  *  Most String built-ins must only accept strings (or String objects).
39662  *  Symbols, represented internally as strings, must be generally rejected.
39663  *  The duk_push_this_coercible_to_string() helper does this automatically.
39664  */
39665 
39666 /* XXX: There are several limitations in the current implementation for
39667  * strings with >= 0x80000000UL characters.  In some cases one would need
39668  * to be able to represent the range [-0xffffffff,0xffffffff] and so on.
39669  * Generally character and byte length are assumed to fit into signed 32
39670  * bits (< 0x80000000UL).  Places with issues are not marked explicitly
39671  * below in all cases, look for signed type usage (duk_int_t etc) for
39672  * offsets/lengths.
39673  */
39674 
39675 /* #include duk_internal.h -> already included */
39676 
39677 #if defined(DUK_USE_STRING_BUILTIN)
39678 
39679 /*
39680  *  Helpers
39681  */
39682 
39683 DUK_LOCAL duk_hstring *duk__str_tostring_notregexp(duk_hthread *thr, duk_idx_t idx) {
39684 	duk_hstring *h;
39685 
39686 	if (duk_get_class_number(thr, idx) == DUK_HOBJECT_CLASS_REGEXP) {
39687 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
39688 		DUK_WO_NORETURN(return NULL;);
39689 	}
39690 	h = duk_to_hstring(thr, idx);
39691 	DUK_ASSERT(h != NULL);
39692 
39693 	return h;
39694 }
39695 
39696 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) {
39697 	duk_int_t cpos;
39698 	duk_int_t bpos;
39699 	const duk_uint8_t *p_start, *p_end, *p;
39700 	const duk_uint8_t *q_start;
39701 	duk_int_t q_blen;
39702 	duk_uint8_t firstbyte;
39703 	duk_uint8_t t;
39704 
39705 	cpos = start_cpos;
39706 
39707 	/* Empty searchstring always matches; cpos must be clamped here.
39708 	 * (If q_blen were < 0 due to clamped coercion, it would also be
39709 	 * caught here.)
39710 	 */
39711 	q_start = DUK_HSTRING_GET_DATA(h_search);
39712 	q_blen = (duk_int_t) DUK_HSTRING_GET_BYTELEN(h_search);
39713 	if (q_blen <= 0) {
39714 		return cpos;
39715 	}
39716 	DUK_ASSERT(q_blen > 0);
39717 
39718 	bpos = (duk_int_t) duk_heap_strcache_offset_char2byte(thr, h_this, (duk_uint32_t) cpos);
39719 
39720 	p_start = DUK_HSTRING_GET_DATA(h_this);
39721 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_this);
39722 	p = p_start + bpos;
39723 
39724 	/* This loop is optimized for size.  For speed, there should be
39725 	 * two separate loops, and we should ensure that memcmp() can be
39726 	 * used without an extra "will searchstring fit" check.  Doing
39727 	 * the preconditioning for 'p' and 'p_end' is easy but cpos
39728 	 * must be updated if 'p' is wound back (backward scanning).
39729 	 */
39730 
39731 	firstbyte = q_start[0];  /* leading byte of match string */
39732 	while (p <= p_end && p >= p_start) {
39733 		t = *p;
39734 
39735 		/* For ECMAScript strings, this check can only match for
39736 		 * initial UTF-8 bytes (not continuation bytes).  For other
39737 		 * strings all bets are off.
39738 		 */
39739 
39740 		if ((t == firstbyte) && ((duk_size_t) (p_end - p) >= (duk_size_t) q_blen)) {
39741 			DUK_ASSERT(q_blen > 0);
39742 			if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
39743 				return cpos;
39744 			}
39745 		}
39746 
39747 		/* track cpos while scanning */
39748 		if (backwards) {
39749 			/* when going backwards, we decrement cpos 'early';
39750 			 * 'p' may point to a continuation byte of the char
39751 			 * at offset 'cpos', but that's OK because we'll
39752 			 * backtrack all the way to the initial byte.
39753 			 */
39754 			if ((t & 0xc0) != 0x80) {
39755 				cpos--;
39756 			}
39757 			p--;
39758 		} else {
39759 			if ((t & 0xc0) != 0x80) {
39760 				cpos++;
39761 			}
39762 			p++;
39763 		}
39764 	}
39765 
39766 	/* Not found.  Empty string case is handled specially above. */
39767 	return -1;
39768 }
39769 
39770 /*
39771  *  Constructor
39772  */
39773 
39774 DUK_INTERNAL duk_ret_t duk_bi_string_constructor(duk_hthread *thr) {
39775 	duk_hstring *h;
39776 	duk_uint_t flags;
39777 
39778 	/* String constructor needs to distinguish between an argument not given at all
39779 	 * vs. given as 'undefined'.  We're a vararg function to handle this properly.
39780 	 */
39781 
39782 	/* XXX: copy current activation flags to thr, including current magic,
39783 	 * is_constructor_call etc.  This takes a few bytes in duk_hthread but
39784 	 * makes call sites smaller (there are >30 is_constructor_call and get
39785 	 * current magic call sites.
39786 	 */
39787 
39788 	if (duk_get_top(thr) == 0) {
39789 		duk_push_hstring_empty(thr);
39790 	} else {
39791 		h = duk_to_hstring_acceptsymbol(thr, 0);
39792 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h) && !duk_is_constructor_call(thr))) {
39793 			duk_push_symbol_descriptive_string(thr, h);
39794 			duk_replace(thr, 0);
39795 		}
39796 	}
39797 	duk_to_string(thr, 0);  /* catches symbol argument for constructor call */
39798 	DUK_ASSERT(duk_is_string(thr, 0));
39799 	duk_set_top(thr, 1);  /* Top may be 1 or larger. */
39800 
39801 	if (duk_is_constructor_call(thr)) {
39802 		/* String object internal value is immutable */
39803 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
39804 		        DUK_HOBJECT_FLAG_FASTREFS |
39805 		        DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
39806 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);
39807 		duk_push_object_helper(thr, flags, DUK_BIDX_STRING_PROTOTYPE);
39808 		duk_dup_0(thr);
39809 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
39810 	}
39811 	/* Note: unbalanced stack on purpose */
39812 
39813 	return 1;
39814 }
39815 
39816 DUK_LOCAL duk_ret_t duk__construct_from_codepoints(duk_hthread *thr, duk_bool_t nonbmp) {
39817 	duk_bufwriter_ctx bw_alloc;
39818 	duk_bufwriter_ctx *bw;
39819 	duk_idx_t i, n;
39820 	duk_ucodepoint_t cp;
39821 
39822 	/* XXX: It would be nice to build the string directly but ToUint16()
39823 	 * coercion is needed so a generic helper would not be very
39824 	 * helpful (perhaps coerce the value stack first here and then
39825 	 * build a string from a duk_tval number sequence in one go?).
39826 	 */
39827 
39828 	n = duk_get_top(thr);
39829 
39830 	bw = &bw_alloc;
39831 	DUK_BW_INIT_PUSHBUF(thr, bw, (duk_size_t) n);  /* initial estimate for ASCII only codepoints */
39832 
39833 	for (i = 0; i < n; i++) {
39834 		/* XXX: could improve bufwriter handling to write multiple codepoints
39835 		 * with one ensure call but the relative benefit would be quite small.
39836 		 */
39837 
39838 		if (nonbmp) {
39839 			/* ES2015 requires that (1) SameValue(cp, ToInteger(cp)) and
39840 			 * (2) cp >= 0 and cp <= 0x10ffff.  This check does not
39841 			 * implement the steps exactly but the outcome should be
39842 			 * the same.
39843 			 */
39844 			duk_int32_t i32 = 0;
39845 			if (!duk_is_whole_get_int32(duk_to_number(thr, i), &i32) ||
39846 			    i32 < 0 || i32 > 0x10ffffL) {
39847 				DUK_DCERROR_RANGE_INVALID_ARGS(thr);
39848 			}
39849 			DUK_ASSERT(i32 >= 0 && i32 <= 0x10ffffL);
39850 			cp = (duk_ucodepoint_t) i32;
39851 			DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);
39852 		} else {
39853 #if defined(DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT)
39854 			/* ToUint16() coercion is mandatory in the E5.1 specification, but
39855 			 * this non-compliant behavior makes more sense because we support
39856 			 * non-BMP codepoints.  Don't use CESU-8 because that'd create
39857 			 * surrogate pairs.
39858 			 */
39859 			cp = (duk_ucodepoint_t) duk_to_uint32(thr, i);
39860 			DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
39861 #else
39862 			cp = (duk_ucodepoint_t) duk_to_uint16(thr, i);
39863 			DUK_ASSERT(cp >= 0 && cp <= 0x10ffffL);
39864 			DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);
39865 #endif
39866 		}
39867 	}
39868 
39869 	DUK_BW_COMPACT(thr, bw);
39870 	(void) duk_buffer_to_string(thr, -1);  /* Safe, extended UTF-8 or CESU-8 encoded. */
39871 	return 1;
39872 }
39873 
39874 DUK_INTERNAL duk_ret_t duk_bi_string_constructor_from_char_code(duk_hthread *thr) {
39875 	return duk__construct_from_codepoints(thr, 0 /*nonbmp*/);
39876 }
39877 
39878 #if defined(DUK_USE_ES6)
39879 DUK_INTERNAL duk_ret_t duk_bi_string_constructor_from_code_point(duk_hthread *thr) {
39880 	return duk__construct_from_codepoints(thr, 1 /*nonbmp*/);
39881 }
39882 #endif
39883 
39884 /*
39885  *  toString(), valueOf()
39886  */
39887 
39888 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_to_string(duk_hthread *thr) {
39889 	duk_tval *tv;
39890 
39891 	duk_push_this(thr);
39892 	tv = duk_require_tval(thr, -1);
39893 	DUK_ASSERT(tv != NULL);
39894 
39895 	if (DUK_TVAL_IS_STRING(tv)) {
39896 		/* return as is */
39897 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
39898 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
39899 		DUK_ASSERT(h != NULL);
39900 
39901 		/* Must be a "string object", i.e. class "String" */
39902 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_STRING) {
39903 			goto type_error;
39904 		}
39905 
39906 		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
39907 		DUK_ASSERT(duk_is_string(thr, -1));
39908 	} else {
39909 		goto type_error;
39910 	}
39911 
39912 	(void) duk_require_hstring_notsymbol(thr, -1);  /* Reject symbols (and wrapped symbols). */
39913 	return 1;
39914 
39915  type_error:
39916 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
39917 }
39918 
39919 /*
39920  *  Character and charcode access
39921  */
39922 
39923 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_at(duk_hthread *thr) {
39924 	duk_hstring *h;
39925 	duk_int_t pos;
39926 
39927 	/* XXX: faster implementation */
39928 
39929 	h = duk_push_this_coercible_to_string(thr);
39930 	DUK_ASSERT(h != NULL);
39931 
39932 	pos = duk_to_int(thr, 0);
39933 
39934 	if (sizeof(duk_size_t) >= sizeof(duk_uint_t)) {
39935 		/* Cast to duk_size_t works in this case:
39936 		 * - If pos < 0, (duk_size_t) pos will always be
39937 		 *   >= max_charlen, and result will be the empty string
39938 		 *   (see duk_substring()).
39939 		 * - If pos >= 0, pos + 1 cannot wrap.
39940 		 */
39941 		DUK_ASSERT((duk_size_t) DUK_INT_MIN >= DUK_HSTRING_MAX_BYTELEN);
39942 		DUK_ASSERT((duk_size_t) DUK_INT_MAX + 1U > (duk_size_t) DUK_INT_MAX);
39943 		duk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) pos + 1U);
39944 	} else {
39945 		/* If size_t is smaller than int, explicit bounds checks
39946 		 * are needed because an int may wrap multiple times.
39947 		 */
39948 		if (DUK_UNLIKELY(pos < 0 || (duk_uint_t) pos >= (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h))) {
39949 			duk_push_hstring_empty(thr);
39950 		} else {
39951 			duk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) pos + 1U);
39952 		}
39953 	}
39954 
39955 	return 1;
39956 }
39957 
39958 /* Magic: 0=charCodeAt, 1=codePointAt */
39959 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_code_at(duk_hthread *thr) {
39960 	duk_int_t pos;
39961 	duk_hstring *h;
39962 	duk_bool_t clamped;
39963 	duk_uint32_t cp;
39964 	duk_int_t magic;
39965 
39966 	/* XXX: faster implementation */
39967 
39968 	DUK_DDD(DUK_DDDPRINT("arg=%!T", (duk_tval *) duk_get_tval(thr, 0)));
39969 
39970 	h = duk_push_this_coercible_to_string(thr);
39971 	DUK_ASSERT(h != NULL);
39972 
39973 	pos = duk_to_int_clamped_raw(thr,
39974 	                             0 /*index*/,
39975 	                             0 /*min(incl)*/,
39976 	                             (duk_int_t) DUK_HSTRING_GET_CHARLEN(h) - 1 /*max(incl)*/,
39977 	                             &clamped /*out_clamped*/);
39978 #if defined(DUK_USE_ES6)
39979 	magic = duk_get_current_magic(thr);
39980 #else
39981 	DUK_ASSERT(duk_get_current_magic(thr) == 0);
39982 	magic = 0;
39983 #endif
39984 	if (clamped) {
39985 		/* For out-of-bounds indices .charCodeAt() returns NaN and
39986 		 * .codePointAt() returns undefined.
39987 		 */
39988 		if (magic != 0) {
39989 			return 0;
39990 		}
39991 		duk_push_nan(thr);
39992 	} else {
39993 		DUK_ASSERT(pos >= 0);
39994 		cp = (duk_uint32_t) duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) pos, (duk_bool_t) magic /*surrogate_aware*/);
39995 		duk_push_u32(thr, cp);
39996 	}
39997 	return 1;
39998 }
39999 
40000 /*
40001  *  substring(), substr(), slice()
40002  */
40003 
40004 /* XXX: any chance of merging these three similar but still slightly
40005  * different algorithms so that footprint would be reduced?
40006  */
40007 
40008 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substring(duk_hthread *thr) {
40009 	duk_hstring *h;
40010 	duk_int_t start_pos, end_pos;
40011 	duk_int_t len;
40012 
40013 	h = duk_push_this_coercible_to_string(thr);
40014 	DUK_ASSERT(h != NULL);
40015 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
40016 
40017 	/* [ start end str ] */
40018 
40019 	start_pos = duk_to_int_clamped(thr, 0, 0, len);
40020 	if (duk_is_undefined(thr, 1)) {
40021 		end_pos = len;
40022 	} else {
40023 		end_pos = duk_to_int_clamped(thr, 1, 0, len);
40024 	}
40025 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
40026 	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
40027 
40028 	if (start_pos > end_pos) {
40029 		duk_int_t tmp = start_pos;
40030 		start_pos = end_pos;
40031 		end_pos = tmp;
40032 	}
40033 
40034 	DUK_ASSERT(end_pos >= start_pos);
40035 
40036 	duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
40037 	return 1;
40038 }
40039 
40040 #if defined(DUK_USE_SECTION_B)
40041 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substr(duk_hthread *thr) {
40042 	duk_hstring *h;
40043 	duk_int_t start_pos, end_pos;
40044 	duk_int_t len;
40045 
40046 	/* Unlike non-obsolete String calls, substr() algorithm in E5.1
40047 	 * specification will happily coerce undefined and null to strings
40048 	 * ("undefined" and "null").
40049 	 */
40050 	duk_push_this(thr);
40051 	h = duk_to_hstring_m1(thr);  /* Reject Symbols. */
40052 	DUK_ASSERT(h != NULL);
40053 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
40054 
40055 	/* [ start length str ] */
40056 
40057 	/* The implementation for computing of start_pos and end_pos differs
40058 	 * from the standard algorithm, but is intended to result in the exactly
40059 	 * same behavior.  This is not always obvious.
40060 	 */
40061 
40062 	/* combines steps 2 and 5; -len ensures max() not needed for step 5 */
40063 	start_pos = duk_to_int_clamped(thr, 0, -len, len);
40064 	if (start_pos < 0) {
40065 		start_pos = len + start_pos;
40066 	}
40067 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
40068 
40069 	/* combines steps 3, 6; step 7 is not needed */
40070 	if (duk_is_undefined(thr, 1)) {
40071 		end_pos = len;
40072 	} else {
40073 		DUK_ASSERT(start_pos <= len);
40074 		end_pos = start_pos + duk_to_int_clamped(thr, 1, 0, len - start_pos);
40075 	}
40076 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
40077 	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
40078 	DUK_ASSERT(end_pos >= start_pos);
40079 
40080 	duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
40081 	return 1;
40082 }
40083 #endif  /* DUK_USE_SECTION_B */
40084 
40085 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_slice(duk_hthread *thr) {
40086 	duk_hstring *h;
40087 	duk_int_t start_pos, end_pos;
40088 	duk_int_t len;
40089 
40090 	h = duk_push_this_coercible_to_string(thr);
40091 	DUK_ASSERT(h != NULL);
40092 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
40093 
40094 	/* [ start end str ] */
40095 
40096 	start_pos = duk_to_int_clamped(thr, 0, -len, len);
40097 	if (start_pos < 0) {
40098 		start_pos = len + start_pos;
40099 	}
40100 	if (duk_is_undefined(thr, 1)) {
40101 		end_pos = len;
40102 	} else {
40103 		end_pos = duk_to_int_clamped(thr, 1, -len, len);
40104 		if (end_pos < 0) {
40105 			end_pos = len + end_pos;
40106 		}
40107 	}
40108 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
40109 	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
40110 
40111 	if (end_pos < start_pos) {
40112 		end_pos = start_pos;
40113 	}
40114 
40115 	DUK_ASSERT(end_pos >= start_pos);
40116 
40117 	duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
40118 	return 1;
40119 }
40120 
40121 /*
40122  *  Case conversion
40123  */
40124 
40125 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_hthread *thr) {
40126 	duk_small_int_t uppercase = duk_get_current_magic(thr);
40127 
40128 	(void) duk_push_this_coercible_to_string(thr);
40129 	duk_unicode_case_convert_string(thr, (duk_bool_t) uppercase);
40130 	return 1;
40131 }
40132 
40133 /*
40134  *  indexOf() and lastIndexOf()
40135  */
40136 
40137 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_hthread *thr) {
40138 	duk_hstring *h_this;
40139 	duk_hstring *h_search;
40140 	duk_int_t clen_this;
40141 	duk_int_t cpos;
40142 	duk_small_uint_t is_lastindexof = (duk_small_uint_t) duk_get_current_magic(thr);  /* 0=indexOf, 1=lastIndexOf */
40143 
40144 	h_this = duk_push_this_coercible_to_string(thr);
40145 	DUK_ASSERT(h_this != NULL);
40146 	clen_this = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h_this);
40147 
40148 	h_search = duk_to_hstring(thr, 0);
40149 	DUK_ASSERT(h_search != NULL);
40150 
40151 	duk_to_number(thr, 1);
40152 	if (duk_is_nan(thr, 1) && is_lastindexof) {
40153 		/* indexOf: NaN should cause pos to be zero.
40154 		 * lastIndexOf: NaN should cause pos to be +Infinity
40155 		 * (and later be clamped to len).
40156 		 */
40157 		cpos = clen_this;
40158 	} else {
40159 		cpos = duk_to_int_clamped(thr, 1, 0, clen_this);
40160 	}
40161 
40162 	cpos = duk__str_search_shared(thr, h_this, h_search, cpos, is_lastindexof /*backwards*/);
40163 	duk_push_int(thr, cpos);
40164 	return 1;
40165 }
40166 
40167 /*
40168  *  replace()
40169  */
40170 
40171 /* XXX: the current implementation works but is quite clunky; it compiles
40172  * to almost 1,4kB of x86 code so it needs to be simplified (better approach,
40173  * shared helpers, etc).  Some ideas for refactoring:
40174  *
40175  * - a primitive to convert a string into a regexp matcher (reduces matching
40176  *   code at the cost of making matching much slower)
40177  * - use replace() as a basic helper for match() and split(), which are both
40178  *   much simpler
40179  * - API call to get_prop and to_boolean
40180  */
40181 
40182 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {
40183 	duk_hstring *h_input;
40184 	duk_hstring *h_match;
40185 	duk_hstring *h_search;
40186 	duk_hobject *h_re;
40187 	duk_bufwriter_ctx bw_alloc;
40188 	duk_bufwriter_ctx *bw;
40189 #if defined(DUK_USE_REGEXP_SUPPORT)
40190 	duk_bool_t is_regexp;
40191 	duk_bool_t is_global;
40192 #endif
40193 	duk_bool_t is_repl_func;
40194 	duk_uint32_t match_start_coff, match_start_boff;
40195 #if defined(DUK_USE_REGEXP_SUPPORT)
40196 	duk_int_t match_caps;
40197 #endif
40198 	duk_uint32_t prev_match_end_boff;
40199 	const duk_uint8_t *r_start, *r_end, *r;   /* repl string scan */
40200 	duk_size_t tmp_sz;
40201 
40202 	DUK_ASSERT_TOP(thr, 2);
40203 	h_input = duk_push_this_coercible_to_string(thr);
40204 	DUK_ASSERT(h_input != NULL);
40205 
40206 	bw = &bw_alloc;
40207 	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));  /* input size is good output starting point */
40208 
40209 	DUK_ASSERT_TOP(thr, 4);
40210 
40211 	/* stack[0] = search value
40212 	 * stack[1] = replace value
40213 	 * stack[2] = input string
40214 	 * stack[3] = result buffer
40215 	 */
40216 
40217 	h_re = duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_REGEXP);
40218 	if (h_re) {
40219 #if defined(DUK_USE_REGEXP_SUPPORT)
40220 		is_regexp = 1;
40221 		is_global = duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL);
40222 
40223 		if (is_global) {
40224 			/* start match from beginning */
40225 			duk_push_int(thr, 0);
40226 			duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40227 		}
40228 #else  /* DUK_USE_REGEXP_SUPPORT */
40229 		DUK_DCERROR_UNSUPPORTED(thr);
40230 #endif  /* DUK_USE_REGEXP_SUPPORT */
40231 	} else {
40232 		duk_to_string(thr, 0);  /* rejects symbols */
40233 #if defined(DUK_USE_REGEXP_SUPPORT)
40234 		is_regexp = 0;
40235 		is_global = 0;
40236 #endif
40237 	}
40238 
40239 	if (duk_is_function(thr, 1)) {
40240 		is_repl_func = 1;
40241 		r_start = NULL;
40242 		r_end = NULL;
40243 	} else {
40244 		duk_hstring *h_repl;
40245 
40246 		is_repl_func = 0;
40247 		h_repl = duk_to_hstring(thr, 1);  /* reject symbols */
40248 		DUK_ASSERT(h_repl != NULL);
40249 		r_start = DUK_HSTRING_GET_DATA(h_repl);
40250 		r_end = r_start + DUK_HSTRING_GET_BYTELEN(h_repl);
40251 	}
40252 
40253 	prev_match_end_boff = 0;
40254 
40255 	for (;;) {
40256 		/*
40257 		 *  If matching with a regexp:
40258 		 *    - non-global RegExp: lastIndex not touched on a match, zeroed
40259 		 *      on a non-match
40260 		 *    - global RegExp: on match, lastIndex will be updated by regexp
40261 		 *      executor to point to next char after the matching part (so that
40262 		 *      characters in the matching part are not matched again)
40263 		 *
40264 		 *  If matching with a string:
40265 		 *    - always non-global match, find first occurrence
40266 		 *
40267 		 *  We need:
40268 		 *    - The character offset of start-of-match for the replacer function
40269 		 *    - The byte offsets for start-of-match and end-of-match to implement
40270 		 *      the replacement values $&, $`, and $', and to copy non-matching
40271 		 *      input string portions (including header and trailer) verbatim.
40272 		 *
40273 		 *  NOTE: the E5.1 specification is a bit vague how the RegExp should
40274 		 *  behave in the replacement process; e.g. is matching done first for
40275 		 *  all matches (in the global RegExp case) before any replacer calls
40276 		 *  are made?  See: test-bi-string-proto-replace.js for discussion.
40277 		 */
40278 
40279 		DUK_ASSERT_TOP(thr, 4);
40280 
40281 #if defined(DUK_USE_REGEXP_SUPPORT)
40282 		if (is_regexp) {
40283 			duk_dup_0(thr);
40284 			duk_dup_2(thr);
40285 			duk_regexp_match(thr);  /* [ ... regexp input ] -> [ res_obj ] */
40286 			if (!duk_is_object(thr, -1)) {
40287 				duk_pop(thr);
40288 				break;
40289 			}
40290 
40291 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);
40292 			DUK_ASSERT(duk_is_number(thr, -1));
40293 			match_start_coff = duk_get_uint(thr, -1);
40294 			duk_pop(thr);
40295 
40296 			duk_get_prop_index(thr, -1, 0);
40297 			DUK_ASSERT(duk_is_string(thr, -1));
40298 			h_match = duk_known_hstring(thr, -1);
40299 			duk_pop(thr);  /* h_match is borrowed, remains reachable through match_obj */
40300 
40301 			if (DUK_HSTRING_GET_BYTELEN(h_match) == 0) {
40302 				/* This should be equivalent to match() algorithm step 8.f.iii.2:
40303 				 * detect an empty match and allow it, but don't allow it twice.
40304 				 */
40305 				duk_uint32_t last_index;
40306 
40307 				duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40308 				last_index = (duk_uint32_t) duk_get_uint(thr, -1);
40309 				DUK_DDD(DUK_DDDPRINT("empty match, bump lastIndex: %ld -> %ld",
40310 				                     (long) last_index, (long) (last_index + 1)));
40311 				duk_pop(thr);
40312 				duk_push_uint(thr, (duk_uint_t) (last_index + 1));
40313 				duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40314 			}
40315 
40316 			DUK_ASSERT(duk_get_length(thr, -1) <= DUK_INT_MAX);  /* string limits */
40317 			match_caps = (duk_int_t) duk_get_length(thr, -1);
40318 		} else {
40319 #else  /* DUK_USE_REGEXP_SUPPORT */
40320 		{  /* unconditionally */
40321 #endif  /* DUK_USE_REGEXP_SUPPORT */
40322 			const duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
40323 			const duk_uint8_t *q_start;               /* match string */
40324 			duk_size_t q_blen;
40325 
40326 #if defined(DUK_USE_REGEXP_SUPPORT)
40327 			DUK_ASSERT(!is_global);  /* single match always */
40328 #endif
40329 
40330 			p_start = DUK_HSTRING_GET_DATA(h_input);
40331 			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
40332 			p = p_start;
40333 
40334 			h_search = duk_known_hstring(thr, 0);
40335 			q_start = DUK_HSTRING_GET_DATA(h_search);
40336 			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_search);
40337 
40338 			p_end -= q_blen;  /* ensure full memcmp() fits in while */
40339 
40340 			match_start_coff = 0;
40341 
40342 			while (p <= p_end) {
40343 				DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
40344 				if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
40345 					duk_dup_0(thr);
40346 					h_match = duk_known_hstring(thr, -1);
40347 #if defined(DUK_USE_REGEXP_SUPPORT)
40348 					match_caps = 0;
40349 #endif
40350 					goto found;
40351 				}
40352 
40353 				/* track utf-8 non-continuation bytes */
40354 				if ((p[0] & 0xc0) != 0x80) {
40355 					match_start_coff++;
40356 				}
40357 				p++;
40358 			}
40359 
40360 			/* not found */
40361 			break;
40362 		}
40363 	 found:
40364 
40365 		/* stack[0] = search value
40366 		 * stack[1] = replace value
40367 		 * stack[2] = input string
40368 		 * stack[3] = result buffer
40369 		 * stack[4] = regexp match OR match string
40370 		 */
40371 
40372 		match_start_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
40373 
40374 		tmp_sz = (duk_size_t) (match_start_boff - prev_match_end_boff);
40375 		DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
40376 
40377 		prev_match_end_boff = match_start_boff + DUK_HSTRING_GET_BYTELEN(h_match);
40378 
40379 		if (is_repl_func) {
40380 			duk_idx_t idx_args;
40381 			duk_hstring *h_repl;
40382 
40383 			/* regexp res_obj is at index 4 */
40384 
40385 			duk_dup_1(thr);
40386 			idx_args = duk_get_top(thr);
40387 
40388 #if defined(DUK_USE_REGEXP_SUPPORT)
40389 			if (is_regexp) {
40390 				duk_int_t idx;
40391 				duk_require_stack(thr, match_caps + 2);
40392 				for (idx = 0; idx < match_caps; idx++) {
40393 					/* match followed by capture(s) */
40394 					duk_get_prop_index(thr, 4, (duk_uarridx_t) idx);
40395 				}
40396 			} else {
40397 #else  /* DUK_USE_REGEXP_SUPPORT */
40398 			{  /* unconditionally */
40399 #endif  /* DUK_USE_REGEXP_SUPPORT */
40400 				/* match == search string, by definition */
40401 				duk_dup_0(thr);
40402 			}
40403 			duk_push_uint(thr, (duk_uint_t) match_start_coff);
40404 			duk_dup_2(thr);
40405 
40406 			/* [ ... replacer match [captures] match_char_offset input ] */
40407 
40408 			duk_call(thr, duk_get_top(thr) - idx_args);
40409 			h_repl = duk_to_hstring_m1(thr);  /* -> [ ... repl_value ] */
40410 			DUK_ASSERT(h_repl != NULL);
40411 
40412 			DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_repl);
40413 
40414 			duk_pop(thr);  /* repl_value */
40415 		} else {
40416 			r = r_start;
40417 
40418 			while (r < r_end) {
40419 				duk_int_t ch1;
40420 				duk_int_t ch2;
40421 #if defined(DUK_USE_REGEXP_SUPPORT)
40422 				duk_int_t ch3;
40423 #endif
40424 				duk_size_t left;
40425 
40426 				ch1 = *r++;
40427 				if (ch1 != DUK_ASC_DOLLAR) {
40428 					goto repl_write;
40429 				}
40430 				DUK_ASSERT(r <= r_end);
40431 				left = (duk_size_t) (r_end - r);
40432 
40433 				if (left <= 0) {
40434 					goto repl_write;
40435 				}
40436 
40437 				ch2 = r[0];
40438 				switch (ch2) {
40439 				case DUK_ASC_DOLLAR: {
40440 					ch1 = (1 << 8) + DUK_ASC_DOLLAR;
40441 					goto repl_write;
40442 				}
40443 				case DUK_ASC_AMP: {
40444 					DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_match);
40445 					r++;
40446 					continue;
40447 				}
40448 				case DUK_ASC_GRAVE: {
40449 					tmp_sz = (duk_size_t) match_start_boff;
40450 					DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input), tmp_sz);
40451 					r++;
40452 					continue;
40453 				}
40454 				case DUK_ASC_SINGLEQUOTE: {
40455 					duk_uint32_t match_end_boff;
40456 
40457 					/* Use match charlen instead of bytelen, just in case the input and
40458 					 * match codepoint encodings would have different lengths.
40459 					 */
40460 					/* XXX: charlen computed here, and also in char2byte helper. */
40461 					match_end_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr,
40462 					                                                                   h_input,
40463 					                                                                   match_start_coff + (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_match));
40464 
40465 					tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - match_end_boff);
40466 					DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + match_end_boff, tmp_sz);
40467 					r++;
40468 					continue;
40469 				}
40470 				default: {
40471 #if defined(DUK_USE_REGEXP_SUPPORT)
40472 					duk_int_t capnum, captmp, capadv;
40473 					/* XXX: optional check, match_caps is zero if no regexp,
40474 					 * so dollar will be interpreted literally anyway.
40475 					 */
40476 
40477 					if (!is_regexp) {
40478 						goto repl_write;
40479 					}
40480 
40481 					if (!(ch2 >= DUK_ASC_0 && ch2 <= DUK_ASC_9)) {
40482 						goto repl_write;
40483 					}
40484 					capnum = ch2 - DUK_ASC_0;
40485 					capadv = 1;
40486 
40487 					if (left >= 2) {
40488 						ch3 = r[1];
40489 						if (ch3 >= DUK_ASC_0 && ch3 <= DUK_ASC_9) {
40490 							captmp = capnum * 10 + (ch3 - DUK_ASC_0);
40491 							if (captmp < match_caps) {
40492 								capnum = captmp;
40493 								capadv = 2;
40494 							}
40495 						}
40496 					}
40497 
40498 					if (capnum > 0 && capnum < match_caps) {
40499 						DUK_ASSERT(is_regexp != 0);  /* match_caps == 0 without regexps */
40500 
40501 						/* regexp res_obj is at offset 4 */
40502 						duk_get_prop_index(thr, 4, (duk_uarridx_t) capnum);
40503 						if (duk_is_string(thr, -1)) {
40504 							duk_hstring *h_tmp_str;
40505 
40506 							h_tmp_str = duk_known_hstring(thr, -1);
40507 
40508 							DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_tmp_str);
40509 						} else {
40510 							/* undefined -> skip (replaced with empty) */
40511 						}
40512 						duk_pop(thr);
40513 						r += capadv;
40514 						continue;
40515 					} else {
40516 						goto repl_write;
40517 					}
40518 #else  /* DUK_USE_REGEXP_SUPPORT */
40519 					goto repl_write;  /* unconditionally */
40520 #endif  /* DUK_USE_REGEXP_SUPPORT */
40521 				}  /* default case */
40522 				}  /* switch (ch2) */
40523 
40524 			 repl_write:
40525 				/* ch1 = (r_increment << 8) + byte */
40526 
40527 				DUK_BW_WRITE_ENSURE_U8(thr, bw, (duk_uint8_t) (ch1 & 0xff));
40528 				r += ch1 >> 8;
40529 			}  /* while repl */
40530 		}  /* if (is_repl_func) */
40531 
40532 		duk_pop(thr);  /* pop regexp res_obj or match string */
40533 
40534 #if defined(DUK_USE_REGEXP_SUPPORT)
40535 		if (!is_global) {
40536 #else
40537 		{  /* unconditionally; is_global==0 */
40538 #endif
40539 			break;
40540 		}
40541 	}
40542 
40543 	/* trailer */
40544 	tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff);
40545 	DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
40546 
40547 	DUK_ASSERT_TOP(thr, 4);
40548 	DUK_BW_COMPACT(thr, bw);
40549 	(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */
40550 	return 1;
40551 }
40552 
40553 /*
40554  *  split()
40555  */
40556 
40557 /* XXX: very messy now, but works; clean up, remove unused variables (nomimally
40558  * used so compiler doesn't complain).
40559  */
40560 
40561 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_hthread *thr) {
40562 	duk_hstring *h_input;
40563 	duk_hstring *h_sep;
40564 	duk_uint32_t limit;
40565 	duk_uint32_t arr_idx;
40566 #if defined(DUK_USE_REGEXP_SUPPORT)
40567 	duk_bool_t is_regexp;
40568 #endif
40569 	duk_bool_t matched;  /* set to 1 if any match exists (needed for empty input special case) */
40570 	duk_uint32_t prev_match_end_coff, prev_match_end_boff;
40571 	duk_uint32_t match_start_boff, match_start_coff;
40572 	duk_uint32_t match_end_boff, match_end_coff;
40573 
40574 	h_input = duk_push_this_coercible_to_string(thr);
40575 	DUK_ASSERT(h_input != NULL);
40576 
40577 	duk_push_array(thr);
40578 
40579 	if (duk_is_undefined(thr, 1)) {
40580 		limit = 0xffffffffUL;
40581 	} else {
40582 		limit = duk_to_uint32(thr, 1);
40583 	}
40584 
40585 	if (limit == 0) {
40586 		return 1;
40587 	}
40588 
40589 	/* If the separator is a RegExp, make a "clone" of it.  The specification
40590 	 * algorithm calls [[Match]] directly for specific indices; we emulate this
40591 	 * by tweaking lastIndex and using a "force global" variant of duk_regexp_match()
40592 	 * which will use global-style matching even when the RegExp itself is non-global.
40593 	 */
40594 
40595 	if (duk_is_undefined(thr, 0)) {
40596 		/* The spec algorithm first does "R = ToString(separator)" before checking
40597 		 * whether separator is undefined.  Since this is side effect free, we can
40598 		 * skip the ToString() here.
40599 		 */
40600 		duk_dup_2(thr);
40601 		duk_put_prop_index(thr, 3, 0);
40602 		return 1;
40603 	} else if (duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_REGEXP) != NULL) {
40604 #if defined(DUK_USE_REGEXP_SUPPORT)
40605 		duk_push_hobject_bidx(thr, DUK_BIDX_REGEXP_CONSTRUCTOR);
40606 		duk_dup_0(thr);
40607 		duk_new(thr, 1);  /* [ ... RegExp val ] -> [ ... res ] */
40608 		duk_replace(thr, 0);
40609 		/* lastIndex is initialized to zero by new RegExp() */
40610 		is_regexp = 1;
40611 #else
40612 		DUK_DCERROR_UNSUPPORTED(thr);
40613 #endif
40614 	} else {
40615 		duk_to_string(thr, 0);
40616 #if defined(DUK_USE_REGEXP_SUPPORT)
40617 		is_regexp = 0;
40618 #endif
40619 	}
40620 
40621 	/* stack[0] = separator (string or regexp)
40622 	 * stack[1] = limit
40623 	 * stack[2] = input string
40624 	 * stack[3] = result array
40625 	 */
40626 
40627 	prev_match_end_boff = 0;
40628 	prev_match_end_coff = 0;
40629 	arr_idx = 0;
40630 	matched = 0;
40631 
40632 	for (;;) {
40633 		/*
40634 		 *  The specification uses RegExp [[Match]] to attempt match at specific
40635 		 *  offsets.  We don't have such a primitive, so we use an actual RegExp
40636 		 *  and tweak lastIndex.  Since the RegExp may be non-global, we use a
40637 		 *  special variant which forces global-like behavior for matching.
40638 		 */
40639 
40640 		DUK_ASSERT_TOP(thr, 4);
40641 
40642 #if defined(DUK_USE_REGEXP_SUPPORT)
40643 		if (is_regexp) {
40644 			duk_dup_0(thr);
40645 			duk_dup_2(thr);
40646 			duk_regexp_match_force_global(thr);  /* [ ... regexp input ] -> [ res_obj ] */
40647 			if (!duk_is_object(thr, -1)) {
40648 				duk_pop(thr);
40649 				break;
40650 			}
40651 			matched = 1;
40652 
40653 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);
40654 			DUK_ASSERT(duk_is_number(thr, -1));
40655 			match_start_coff = duk_get_uint(thr, -1);
40656 			match_start_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
40657 			duk_pop(thr);
40658 
40659 			if (match_start_coff == DUK_HSTRING_GET_CHARLEN(h_input)) {
40660 				/* don't allow an empty match at the end of the string */
40661 				duk_pop(thr);
40662 				break;
40663 			}
40664 
40665 			duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40666 			DUK_ASSERT(duk_is_number(thr, -1));
40667 			match_end_coff = duk_get_uint(thr, -1);
40668 			match_end_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_end_coff);
40669 			duk_pop(thr);
40670 
40671 			/* empty match -> bump and continue */
40672 			if (prev_match_end_boff == match_end_boff) {
40673 				duk_push_uint(thr, (duk_uint_t) (match_end_coff + 1));
40674 				duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40675 				duk_pop(thr);
40676 				continue;
40677 			}
40678 		} else {
40679 #else  /* DUK_USE_REGEXP_SUPPORT */
40680 		{  /* unconditionally */
40681 #endif  /* DUK_USE_REGEXP_SUPPORT */
40682 			const duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
40683 			const duk_uint8_t *q_start;               /* match string */
40684 			duk_size_t q_blen, q_clen;
40685 
40686 			p_start = DUK_HSTRING_GET_DATA(h_input);
40687 			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
40688 			p = p_start + prev_match_end_boff;
40689 
40690 			h_sep = duk_known_hstring(thr, 0);  /* symbol already rejected above */
40691 			q_start = DUK_HSTRING_GET_DATA(h_sep);
40692 			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sep);
40693 			q_clen = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_sep);
40694 
40695 			p_end -= q_blen;  /* ensure full memcmp() fits in while */
40696 
40697 			match_start_coff = prev_match_end_coff;
40698 
40699 			if (q_blen == 0) {
40700 				/* Handle empty separator case: it will always match, and always
40701 				 * triggers the check in step 13.c.iii initially.  Note that we
40702 				 * must skip to either end of string or start of first codepoint,
40703 				 * skipping over any continuation bytes!
40704 				 *
40705 				 * Don't allow an empty string to match at the end of the input.
40706 				 */
40707 
40708 				matched = 1;  /* empty separator can always match */
40709 
40710 				match_start_coff++;
40711 				p++;
40712 				while (p < p_end) {
40713 					if ((p[0] & 0xc0) != 0x80) {
40714 						goto found;
40715 					}
40716 					p++;
40717 				}
40718 				goto not_found;
40719 			}
40720 
40721 			DUK_ASSERT(q_blen > 0 && q_clen > 0);
40722 			while (p <= p_end) {
40723 				DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
40724 				DUK_ASSERT(q_blen > 0);  /* no issues with empty memcmp() */
40725 				if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
40726 					/* never an empty match, so step 13.c.iii can't be triggered */
40727 					goto found;
40728 				}
40729 
40730 				/* track utf-8 non-continuation bytes */
40731 				if ((p[0] & 0xc0) != 0x80) {
40732 					match_start_coff++;
40733 				}
40734 				p++;
40735 			}
40736 
40737 		 not_found:
40738 			/* not found */
40739 			break;
40740 
40741 		 found:
40742 			matched = 1;
40743 			match_start_boff = (duk_uint32_t) (p - p_start);
40744 			match_end_coff = (duk_uint32_t) (match_start_coff + q_clen);  /* constrained by string length */
40745 			match_end_boff = (duk_uint32_t) (match_start_boff + q_blen);  /* ditto */
40746 
40747 			/* empty match (may happen with empty separator) -> bump and continue */
40748 			if (prev_match_end_boff == match_end_boff) {
40749 				prev_match_end_boff++;
40750 				prev_match_end_coff++;
40751 				continue;
40752 			}
40753 		}  /* if (is_regexp) */
40754 
40755 		/* stack[0] = separator (string or regexp)
40756 		 * stack[1] = limit
40757 		 * stack[2] = input string
40758 		 * stack[3] = result array
40759 		 * stack[4] = regexp res_obj (if is_regexp)
40760 		 */
40761 
40762 		DUK_DDD(DUK_DDDPRINT("split; match_start b=%ld,c=%ld, match_end b=%ld,c=%ld, prev_end b=%ld,c=%ld",
40763 		                     (long) match_start_boff, (long) match_start_coff,
40764 		                     (long) match_end_boff, (long) match_end_coff,
40765 		                     (long) prev_match_end_boff, (long) prev_match_end_coff));
40766 
40767 		duk_push_lstring(thr,
40768 		                 (const char *) (DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff),
40769 		                 (duk_size_t) (match_start_boff - prev_match_end_boff));
40770 		duk_put_prop_index(thr, 3, arr_idx);
40771 		arr_idx++;
40772 		if (arr_idx >= limit) {
40773 			goto hit_limit;
40774 		}
40775 
40776 #if defined(DUK_USE_REGEXP_SUPPORT)
40777 		if (is_regexp) {
40778 			duk_size_t i, len;
40779 
40780 			len = duk_get_length(thr, 4);
40781 			for (i = 1; i < len; i++) {
40782 				DUK_ASSERT(i <= DUK_UARRIDX_MAX);  /* cannot have >4G captures */
40783 				duk_get_prop_index(thr, 4, (duk_uarridx_t) i);
40784 				duk_put_prop_index(thr, 3, arr_idx);
40785 				arr_idx++;
40786 				if (arr_idx >= limit) {
40787 					goto hit_limit;
40788 				}
40789 			}
40790 
40791 			duk_pop(thr);
40792 			/* lastIndex already set up for next match */
40793 		} else {
40794 #else  /* DUK_USE_REGEXP_SUPPORT */
40795 		{  /* unconditionally */
40796 #endif  /* DUK_USE_REGEXP_SUPPORT */
40797 			/* no action */
40798 		}
40799 
40800 		prev_match_end_boff = match_end_boff;
40801 		prev_match_end_coff = match_end_coff;
40802 		continue;
40803 	}  /* for */
40804 
40805 	/* Combined step 11 (empty string special case) and 14-15. */
40806 
40807 	DUK_DDD(DUK_DDDPRINT("split trailer; prev_end b=%ld,c=%ld",
40808 	                     (long) prev_match_end_boff, (long) prev_match_end_coff));
40809 
40810 	if (DUK_HSTRING_GET_BYTELEN(h_input) > 0 || !matched) {
40811 		/* Add trailer if:
40812 		 *   a) non-empty input
40813 		 *   b) empty input and no (zero size) match found (step 11)
40814 		 */
40815 
40816 		duk_push_lstring(thr,
40817 		                 (const char *) DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff,
40818 		                 (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff));
40819 		duk_put_prop_index(thr, 3, arr_idx);
40820 		/* No arr_idx update or limit check */
40821 	}
40822 
40823 	return 1;
40824 
40825  hit_limit:
40826 #if defined(DUK_USE_REGEXP_SUPPORT)
40827 	if (is_regexp) {
40828 		duk_pop(thr);
40829 	}
40830 #endif
40831 
40832 	return 1;
40833 }
40834 
40835 /*
40836  *  Various
40837  */
40838 
40839 #if defined(DUK_USE_REGEXP_SUPPORT)
40840 DUK_LOCAL void duk__to_regexp_helper(duk_hthread *thr, duk_idx_t idx, duk_bool_t force_new) {
40841 	duk_hobject *h;
40842 
40843 	/* Shared helper for match() steps 3-4, search() steps 3-4. */
40844 
40845 	DUK_ASSERT(idx >= 0);
40846 
40847 	if (force_new) {
40848 		goto do_new;
40849 	}
40850 
40851 	h = duk_get_hobject_with_class(thr, idx, DUK_HOBJECT_CLASS_REGEXP);
40852 	if (!h) {
40853 		goto do_new;
40854 	}
40855 	return;
40856 
40857  do_new:
40858 	duk_push_hobject_bidx(thr, DUK_BIDX_REGEXP_CONSTRUCTOR);
40859 	duk_dup(thr, idx);
40860 	duk_new(thr, 1);  /* [ ... RegExp val ] -> [ ... res ] */
40861 	duk_replace(thr, idx);
40862 }
40863 #endif  /* DUK_USE_REGEXP_SUPPORT */
40864 
40865 #if defined(DUK_USE_REGEXP_SUPPORT)
40866 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_search(duk_hthread *thr) {
40867 	/* Easiest way to implement the search required by the specification
40868 	 * is to do a RegExp test() with lastIndex forced to zero.  To avoid
40869 	 * side effects on the argument, "clone" the RegExp if a RegExp was
40870 	 * given as input.
40871 	 *
40872 	 * The global flag of the RegExp should be ignored; setting lastIndex
40873 	 * to zero (which happens when "cloning" the RegExp) should have an
40874 	 * equivalent effect.
40875 	 */
40876 
40877 	DUK_ASSERT_TOP(thr, 1);
40878 	(void) duk_push_this_coercible_to_string(thr);  /* at index 1 */
40879 	duk__to_regexp_helper(thr, 0 /*index*/, 1 /*force_new*/);
40880 
40881 	/* stack[0] = regexp
40882 	 * stack[1] = string
40883 	 */
40884 
40885 	/* Avoid using RegExp.prototype methods, as they're writable and
40886 	 * configurable and may have been changed.
40887 	 */
40888 
40889 	duk_dup_0(thr);
40890 	duk_dup_1(thr);  /* [ ... re_obj input ] */
40891 	duk_regexp_match(thr);  /* -> [ ... res_obj ] */
40892 
40893 	if (!duk_is_object(thr, -1)) {
40894 		duk_push_int(thr, -1);
40895 		return 1;
40896 	}
40897 
40898 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);
40899 	DUK_ASSERT(duk_is_number(thr, -1));
40900 	return 1;
40901 }
40902 #endif  /* DUK_USE_REGEXP_SUPPORT */
40903 
40904 #if defined(DUK_USE_REGEXP_SUPPORT)
40905 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_match(duk_hthread *thr) {
40906 	duk_bool_t global;
40907 	duk_int_t prev_last_index;
40908 	duk_int_t this_index;
40909 	duk_int_t arr_idx;
40910 
40911 	DUK_ASSERT_TOP(thr, 1);
40912 	(void) duk_push_this_coercible_to_string(thr);
40913 	duk__to_regexp_helper(thr, 0 /*index*/, 0 /*force_new*/);
40914 	global = duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL);
40915 	DUK_ASSERT_TOP(thr, 2);
40916 
40917 	/* stack[0] = regexp
40918 	 * stack[1] = string
40919 	 */
40920 
40921 	if (!global) {
40922 		duk_regexp_match(thr);  /* -> [ res_obj ] */
40923 		return 1;  /* return 'res_obj' */
40924 	}
40925 
40926 	/* Global case is more complex. */
40927 
40928 	/* [ regexp string ] */
40929 
40930 	duk_push_int(thr, 0);
40931 	duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40932 	duk_push_array(thr);
40933 
40934 	/* [ regexp string res_arr ] */
40935 
40936 	prev_last_index = 0;
40937 	arr_idx = 0;
40938 
40939 	for (;;) {
40940 		DUK_ASSERT_TOP(thr, 3);
40941 
40942 		duk_dup_0(thr);
40943 		duk_dup_1(thr);
40944 		duk_regexp_match(thr);  /* -> [ ... regexp string ] -> [ ... res_obj ] */
40945 
40946 		if (!duk_is_object(thr, -1)) {
40947 			duk_pop(thr);
40948 			break;
40949 		}
40950 
40951 		duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40952 		DUK_ASSERT(duk_is_number(thr, -1));
40953 		this_index = duk_get_int(thr, -1);
40954 		duk_pop(thr);
40955 
40956 		if (this_index == prev_last_index) {
40957 			this_index++;
40958 			duk_push_int(thr, this_index);
40959 			duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40960 		}
40961 		prev_last_index = this_index;
40962 
40963 		duk_get_prop_index(thr, -1, 0);  /* match string */
40964 		duk_put_prop_index(thr, 2, (duk_uarridx_t) arr_idx);
40965 		arr_idx++;
40966 		duk_pop(thr);  /* res_obj */
40967 	}
40968 
40969 	if (arr_idx == 0) {
40970 		duk_push_null(thr);
40971 	}
40972 
40973 	return 1;  /* return 'res_arr' or 'null' */
40974 }
40975 #endif  /* DUK_USE_REGEXP_SUPPORT */
40976 
40977 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_concat(duk_hthread *thr) {
40978 	/* duk_concat() coerces arguments with ToString() in correct order */
40979 	(void) duk_push_this_coercible_to_string(thr);
40980 	duk_insert(thr, 0);  /* this is relatively expensive */
40981 	duk_concat(thr, duk_get_top(thr));
40982 	return 1;
40983 }
40984 
40985 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_trim(duk_hthread *thr) {
40986 	DUK_ASSERT_TOP(thr, 0);
40987 	(void) duk_push_this_coercible_to_string(thr);
40988 	duk_trim(thr, 0);
40989 	DUK_ASSERT_TOP(thr, 1);
40990 	return 1;
40991 }
40992 
40993 #if defined(DUK_USE_ES6)
40994 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_repeat(duk_hthread *thr) {
40995 	duk_hstring *h_input;
40996 	duk_size_t input_blen;
40997 	duk_size_t result_len;
40998 	duk_int_t count_signed;
40999 	duk_uint_t count;
41000 	const duk_uint8_t *src;
41001 	duk_uint8_t *buf;
41002 	duk_uint8_t *p;
41003 	duk_double_t d;
41004 #if !defined(DUK_USE_PREFER_SIZE)
41005 	duk_size_t copy_size;
41006 	duk_uint8_t *p_end;
41007 #endif
41008 
41009 	DUK_ASSERT_TOP(thr, 1);
41010 	h_input = duk_push_this_coercible_to_string(thr);
41011 	DUK_ASSERT(h_input != NULL);
41012 	input_blen = DUK_HSTRING_GET_BYTELEN(h_input);
41013 
41014 	/* Count is ToNumber() coerced; +Infinity must be always rejected
41015 	 * (even if input string is zero length), as well as negative values
41016 	 * and -Infinity.  -Infinity doesn't require an explicit check
41017 	 * because duk_get_int() clamps it to DUK_INT_MIN which gets rejected
41018 	 * as a negative value (regardless of input string length).
41019 	 */
41020 	d = duk_to_number(thr, 0);
41021 	if (duk_double_is_posinf(d)) {
41022 		goto fail_range;
41023 	}
41024 	count_signed = duk_get_int(thr, 0);
41025 	if (count_signed < 0) {
41026 		goto fail_range;
41027 	}
41028 	count = (duk_uint_t) count_signed;
41029 
41030 	/* Overflow check for result length. */
41031 	result_len = count * input_blen;
41032 	if (count != 0 && result_len / count != input_blen) {
41033 		goto fail_range;
41034 	}
41035 
41036 	/* Temporary fixed buffer, later converted to string. */
41037 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, result_len);
41038 	DUK_ASSERT(buf != NULL);
41039 	src = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
41040 	DUK_ASSERT(src != NULL);
41041 
41042 #if defined(DUK_USE_PREFER_SIZE)
41043 	p = buf;
41044 	while (count-- > 0) {
41045 		duk_memcpy((void *) p, (const void *) src, input_blen);  /* copy size may be zero, but pointers are valid */
41046 		p += input_blen;
41047 	}
41048 #else  /* DUK_USE_PREFER_SIZE */
41049 	/* Take advantage of already copied pieces to speed up the process
41050 	 * especially for small repeated strings.
41051 	 */
41052 	p = buf;
41053 	p_end = p + result_len;
41054 	copy_size = input_blen;
41055 	for (;;) {
41056 		duk_size_t remain = (duk_size_t) (p_end - p);
41057 		DUK_DDD(DUK_DDDPRINT("remain=%ld, copy_size=%ld, input_blen=%ld, result_len=%ld",
41058 		                     (long) remain, (long) copy_size, (long) input_blen,
41059 		                     (long) result_len));
41060 		if (remain <= copy_size) {
41061 			/* If result_len is zero, this case is taken and does
41062 			 * a zero size copy (with valid pointers).
41063 			 */
41064 			duk_memcpy((void *) p, (const void *) src, remain);
41065 			break;
41066 		} else {
41067 			duk_memcpy((void *) p, (const void *) src, copy_size);
41068 			p += copy_size;
41069 		}
41070 
41071 		src = (const duk_uint8_t *) buf;  /* Use buf as source for larger copies. */
41072 		copy_size = (duk_size_t) (p - buf);
41073 	}
41074 #endif  /* DUK_USE_PREFER_SIZE */
41075 
41076 	/* XXX: It would be useful to be able to create a duk_hstring with
41077 	 * a certain byte size whose data area wasn't initialized and which
41078 	 * wasn't in the string table yet.  This would allow a string to be
41079 	 * constructed directly without a buffer temporary and when it was
41080 	 * finished, it could be injected into the string table.  Currently
41081 	 * this isn't possible because duk_hstrings are only tracked by the
41082 	 * intern table (they are not in heap_allocated).
41083 	 */
41084 
41085 	duk_buffer_to_string(thr, -1);  /* Safe if input is safe. */
41086 	return 1;
41087 
41088  fail_range:
41089 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
41090 }
41091 #endif  /* DUK_USE_ES6 */
41092 
41093 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_locale_compare(duk_hthread *thr) {
41094 	duk_hstring *h1;
41095 	duk_hstring *h2;
41096 	duk_size_t h1_len, h2_len, prefix_len;
41097 	duk_small_int_t ret = 0;
41098 	duk_small_int_t rc;
41099 
41100 	/* The current implementation of localeCompare() is simply a codepoint
41101 	 * by codepoint comparison, implemented with a simple string compare
41102 	 * because UTF-8 should preserve codepoint ordering (assuming valid
41103 	 * shortest UTF-8 encoding).
41104 	 *
41105 	 * The specification requires that the return value must be related
41106 	 * to the sort order: e.g. negative means that 'this' comes before
41107 	 * 'that' in sort order.  We assume an ascending sort order.
41108 	 */
41109 
41110 	/* XXX: could share code with duk_js_ops.c, duk_js_compare_helper */
41111 
41112 	h1 = duk_push_this_coercible_to_string(thr);
41113 	DUK_ASSERT(h1 != NULL);
41114 
41115 	h2 = duk_to_hstring(thr, 0);
41116 	DUK_ASSERT(h2 != NULL);
41117 
41118 	h1_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
41119 	h2_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
41120 	prefix_len = (h1_len <= h2_len ? h1_len : h2_len);
41121 
41122 	rc = (duk_small_int_t) duk_memcmp((const void *) DUK_HSTRING_GET_DATA(h1),
41123 	                                  (const void *) DUK_HSTRING_GET_DATA(h2),
41124 	                                  (size_t) prefix_len);
41125 
41126 	if (rc < 0) {
41127 		ret = -1;
41128 		goto done;
41129 	} else if (rc > 0) {
41130 		ret = 1;
41131 		goto done;
41132 	}
41133 
41134 	/* prefix matches, lengths matter now */
41135 	if (h1_len > h2_len) {
41136 		ret = 1;
41137 		goto done;
41138 	} else if (h1_len == h2_len) {
41139 		DUK_ASSERT(ret == 0);
41140 		goto done;
41141 	}
41142 	ret = -1;
41143 	goto done;
41144 
41145  done:
41146 	duk_push_int(thr, (duk_int_t) ret);
41147 	return 1;
41148 }
41149 
41150 #if defined(DUK_USE_ES6)
41151 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_hthread *thr) {
41152 	duk_int_t magic;
41153 	duk_hstring *h;
41154 	duk_hstring *h_search;
41155 	duk_size_t blen_search;
41156 	const duk_uint8_t *p_cmp_start;
41157 	duk_bool_t result;
41158 
41159 	h = duk_push_this_coercible_to_string(thr);
41160 	DUK_ASSERT(h != NULL);
41161 
41162 	h_search = duk__str_tostring_notregexp(thr, 0);
41163 	DUK_ASSERT(h_search != NULL);
41164 
41165 	magic = duk_get_current_magic(thr);
41166 
41167 	p_cmp_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
41168 	blen_search = DUK_HSTRING_GET_BYTELEN(h_search);
41169 
41170 	if (duk_is_undefined(thr, 1)) {
41171 		if (magic) {
41172 			p_cmp_start = p_cmp_start + DUK_HSTRING_GET_BYTELEN(h) - blen_search;
41173 		} else {
41174 			/* p_cmp_start already OK */
41175 		}
41176 	} else {
41177 		duk_int_t len;
41178 		duk_int_t pos;
41179 
41180 		DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= DUK_INT_MAX);
41181 		len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
41182 		pos = duk_to_int_clamped(thr, 1, 0, len);
41183 		DUK_ASSERT(pos >= 0 && pos <= len);
41184 
41185 		if (magic) {
41186 			p_cmp_start -= blen_search;  /* Conceptually subtracted last, but do already here. */
41187 		}
41188 		DUK_ASSERT(pos >= 0 && pos <= len);
41189 
41190 		p_cmp_start += duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) pos);
41191 	}
41192 
41193 	/* The main comparison can be done using a memcmp() rather than
41194 	 * doing codepoint comparisons: for CESU-8 strings there is a
41195 	 * canonical representation for every codepoint.  But we do need
41196 	 * to deal with the char/byte offset translation to find the
41197 	 * comparison range.
41198 	 */
41199 
41200 	result = 0;
41201 	if (p_cmp_start >= DUK_HSTRING_GET_DATA(h) &&
41202 	    (duk_size_t) (p_cmp_start - (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h)) + blen_search <= DUK_HSTRING_GET_BYTELEN(h)) {
41203 		if (duk_memcmp((const void *) p_cmp_start,
41204 		               (const void *) DUK_HSTRING_GET_DATA(h_search),
41205 		               (size_t) blen_search) == 0) {
41206 			result = 1;
41207 		}
41208 	}
41209 
41210 	duk_push_boolean(thr, result);
41211 	return 1;
41212 }
41213 #endif  /* DUK_USE_ES6 */
41214 
41215 #if defined(DUK_USE_ES6)
41216 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_includes(duk_hthread *thr) {
41217 	duk_hstring *h;
41218 	duk_hstring *h_search;
41219 	duk_int_t len;
41220 	duk_int_t pos;
41221 
41222 	h = duk_push_this_coercible_to_string(thr);
41223 	DUK_ASSERT(h != NULL);
41224 
41225 	h_search = duk__str_tostring_notregexp(thr, 0);
41226 	DUK_ASSERT(h_search != NULL);
41227 
41228 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
41229 	pos = duk_to_int_clamped(thr, 1, 0, len);
41230 	DUK_ASSERT(pos >= 0 && pos <= len);
41231 
41232 	pos = duk__str_search_shared(thr, h, h_search, pos, 0 /*backwards*/);
41233 	duk_push_boolean(thr, pos >= 0);
41234 	return 1;
41235 }
41236 #endif  /* DUK_USE_ES6 */
41237 #endif  /* DUK_USE_STRING_BUILTIN */
41238 #line 1 "duk_bi_symbol.c"
41239 /*
41240  *  Symbol built-in
41241  */
41242 
41243 /* #include duk_internal.h -> already included */
41244 
41245 #if defined(DUK_USE_SYMBOL_BUILTIN)
41246 
41247 /*
41248  *  Constructor
41249  */
41250 
41251 DUK_INTERNAL duk_ret_t duk_bi_symbol_constructor_shared(duk_hthread *thr) {
41252 	const duk_uint8_t *desc;
41253 	duk_size_t len;
41254 	duk_uint8_t *buf;
41255 	duk_uint8_t *p;
41256 	duk_int_t magic;
41257 
41258 	magic = duk_get_current_magic(thr);
41259 	if (duk_is_undefined(thr, 0) && (magic == 0)) {
41260 		/* Symbol() accepts undefined and empty string, but they are
41261 		 * treated differently.
41262 		 */
41263 		desc = NULL;
41264 		len = 0;
41265 	} else {
41266 		/* Symbol.for() coerces undefined to 'undefined' */
41267 		desc = (const duk_uint8_t *) duk_to_lstring(thr, 0, &len);
41268 	}
41269 
41270 	/* Maximum symbol data length:
41271 	 *   +1    initial byte (0x80 or 0x81)
41272 	 *   +len  description
41273 	 *   +1    0xff after description, before unique suffix
41274 	 *   +17   autogenerated unique suffix: 'ffffffff-ffffffff' is longest
41275 	 *   +1    0xff after unique suffix for symbols with undefined description
41276 	 */
41277 	buf = (duk_uint8_t *) duk_push_fixed_buffer(thr, 1 + len + 1 + 17 + 1);
41278 	DUK_ASSERT(buf != NULL);
41279 	p = buf + 1;
41280 	DUK_ASSERT(desc != NULL || len == 0);  /* may be NULL if len is 0 */
41281 	duk_memcpy_unsafe((void *) p, (const void *) desc, len);
41282 	p += len;
41283 	if (magic == 0) {
41284 		/* Symbol(): create unique symbol.  Use two 32-bit values
41285 		 * to avoid dependency on 64-bit types and 64-bit integer
41286 		 * formatting (at least for now).
41287 		 */
41288 		if (++thr->heap->sym_counter[0] == 0) {
41289 			thr->heap->sym_counter[1]++;
41290 		}
41291 		p += DUK_SPRINTF((char *) p, "\xFF" "%lx-%lx",
41292 		                 (unsigned long) thr->heap->sym_counter[1],
41293 		                 (unsigned long) thr->heap->sym_counter[0]);
41294 		if (desc == NULL) {
41295 			/* Special case for 'undefined' description, trailing
41296 			 * 0xff distinguishes from empty string description,
41297 			 * but needs minimal special case handling elsewhere.
41298 			 */
41299 			*p++ = 0xff;
41300 		}
41301 		buf[0] = 0x81;
41302 	} else {
41303 		/* Symbol.for(): create a global symbol */
41304 		buf[0] = 0x80;
41305 	}
41306 
41307 	duk_push_lstring(thr, (const char *) buf, (duk_size_t) (p - buf));
41308 	DUK_DDD(DUK_DDDPRINT("created symbol: %!T", duk_get_tval(thr, -1)));
41309 	return 1;
41310 }
41311 
41312 DUK_LOCAL duk_hstring *duk__auto_unbox_symbol(duk_hthread *thr, duk_tval *tv_arg) {
41313 	duk_tval *tv;
41314 	duk_tval tv_val;
41315 	duk_hobject *h_obj;
41316 	duk_hstring *h_str;
41317 
41318 	DUK_ASSERT(tv_arg != NULL);
41319 
41320 	/* XXX: add internal helper: duk_auto_unbox_tval(thr, tv, mask); */
41321 	/* XXX: add internal helper: duk_auto_unbox(thr, tv, idx); */
41322 
41323 	tv = tv_arg;
41324 	if (DUK_TVAL_IS_OBJECT(tv)) {
41325 		h_obj = DUK_TVAL_GET_OBJECT(tv);
41326 		DUK_ASSERT(h_obj != NULL);
41327 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_SYMBOL) {
41328 			if (!duk_hobject_get_internal_value(thr->heap, h_obj, &tv_val)) {
41329 				return NULL;
41330 			}
41331 			tv = &tv_val;
41332 		} else {
41333 			return NULL;
41334 		}
41335 	}
41336 
41337 	if (!DUK_TVAL_IS_STRING(tv)) {
41338 		return NULL;
41339 	}
41340 	h_str = DUK_TVAL_GET_STRING(tv);
41341 	DUK_ASSERT(h_str != NULL);
41342 
41343 	/* Here symbol is more expected than not. */
41344 	if (DUK_UNLIKELY(!DUK_HSTRING_HAS_SYMBOL(h_str))) {
41345 		return NULL;
41346 	}
41347 
41348 	return h_str;
41349 }
41350 
41351 DUK_INTERNAL duk_ret_t duk_bi_symbol_tostring_shared(duk_hthread *thr) {
41352 	duk_hstring *h_str;
41353 
41354 	h_str = duk__auto_unbox_symbol(thr, DUK_HTHREAD_THIS_PTR(thr));
41355 	if (h_str == NULL) {
41356 		return DUK_RET_TYPE_ERROR;
41357 	}
41358 
41359 	if (duk_get_current_magic(thr) == 0) {
41360 		/* .toString() */
41361 		duk_push_symbol_descriptive_string(thr, h_str);
41362 	} else {
41363 		/* .valueOf() */
41364 		duk_push_hstring(thr, h_str);
41365 	}
41366 	return 1;
41367 }
41368 
41369 DUK_INTERNAL duk_ret_t duk_bi_symbol_key_for(duk_hthread *thr) {
41370 	duk_hstring *h;
41371 	const duk_uint8_t *p;
41372 
41373 	/* Argument must be a symbol but not checked here.  The initial byte
41374 	 * check will catch non-symbol strings.
41375 	 */
41376 	h = duk_require_hstring(thr, 0);
41377 	DUK_ASSERT(h != NULL);
41378 
41379 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
41380 	DUK_ASSERT(p != NULL);
41381 
41382 	/* Even for zero length strings there's at least one NUL byte so
41383 	 * we can safely check the initial byte.
41384 	 */
41385 	if (p[0] == 0x80) {
41386 		/* Global symbol, return its key (bytes just after the initial byte). */
41387 		duk_push_lstring(thr, (const char *) (p + 1), (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h) - 1));
41388 		return 1;
41389 	} else if (p[0] == 0x81 || p[0] == 0x82 || p[0] == 0xff) {
41390 		/* Local symbol or hidden symbol, return undefined. */
41391 		return 0;
41392 	}
41393 
41394 	/* Covers normal strings and unknown initial bytes. */
41395 	return DUK_RET_TYPE_ERROR;
41396 }
41397 
41398 DUK_INTERNAL duk_ret_t duk_bi_symbol_toprimitive(duk_hthread *thr) {
41399 	duk_hstring *h_str;
41400 
41401 	h_str = duk__auto_unbox_symbol(thr, DUK_HTHREAD_THIS_PTR(thr));
41402 	if (h_str == NULL) {
41403 		return DUK_RET_TYPE_ERROR;
41404 	}
41405 	duk_push_hstring(thr, h_str);
41406 	return 1;
41407 }
41408 
41409 #endif  /* DUK_USE_SYMBOL_BUILTIN */
41410 #line 1 "duk_bi_thread.c"
41411 /*
41412  *  Thread builtins
41413  */
41414 
41415 /* #include duk_internal.h -> already included */
41416 
41417 /*
41418  *  Constructor
41419  */
41420 
41421 #if defined(DUK_USE_COROUTINE_SUPPORT)
41422 DUK_INTERNAL duk_ret_t duk_bi_thread_constructor(duk_hthread *thr) {
41423 	duk_hthread *new_thr;
41424 	duk_hobject *func;
41425 
41426 	/* Check that the argument is callable; this is not 100% because we
41427 	 * don't allow native functions to be a thread's initial function.
41428 	 * Resume will reject such functions in any case.
41429 	 */
41430 	/* XXX: need a duk_require_func_promote_lfunc() */
41431 	func = duk_require_hobject_promote_lfunc(thr, 0);
41432 	DUK_ASSERT(func != NULL);
41433 	duk_require_callable(thr, 0);
41434 
41435 	duk_push_thread(thr);
41436 	new_thr = (duk_hthread *) duk_known_hobject(thr, -1);
41437 	new_thr->state = DUK_HTHREAD_STATE_INACTIVE;
41438 
41439 	/* push initial function call to new thread stack; this is
41440 	 * picked up by resume().
41441 	 */
41442 	duk_push_hobject(new_thr, func);
41443 
41444 	return 1;  /* return thread */
41445 }
41446 #endif
41447 
41448 /*
41449  *  Resume a thread.
41450  *
41451  *  The thread must be in resumable state, either (a) new thread which hasn't
41452  *  yet started, or (b) a thread which has previously yielded.  This method
41453  *  must be called from an ECMAScript function.
41454  *
41455  *  Args:
41456  *    - thread
41457  *    - value
41458  *    - isError (defaults to false)
41459  *
41460  *  Note: yield and resume handling is currently asymmetric.
41461  */
41462 
41463 #if defined(DUK_USE_COROUTINE_SUPPORT)
41464 DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_hthread *ctx) {
41465 	duk_hthread *thr = (duk_hthread *) ctx;
41466 	duk_hthread *thr_resume;
41467 	duk_hobject *caller_func;
41468 	duk_small_uint_t is_error;
41469 
41470 	DUK_DDD(DUK_DDDPRINT("Duktape.Thread.resume(): thread=%!T, value=%!T, is_error=%!T",
41471 	                     (duk_tval *) duk_get_tval(thr, 0),
41472 	                     (duk_tval *) duk_get_tval(thr, 1),
41473 	                     (duk_tval *) duk_get_tval(thr, 2)));
41474 
41475 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
41476 	DUK_ASSERT(thr->heap->curr_thread == thr);
41477 
41478 	thr_resume = duk_require_hthread(thr, 0);
41479 	DUK_ASSERT(duk_get_top(thr) == 3);
41480 	is_error = (duk_small_uint_t) duk_to_boolean_top_pop(thr);
41481 	DUK_ASSERT(duk_get_top(thr) == 2);
41482 
41483 	/* [ thread value ] */
41484 
41485 	/*
41486 	 *  Thread state and calling context checks
41487 	 */
41488 
41489 	if (thr->callstack_top < 2) {
41490 		DUK_DD(DUK_DDPRINT("resume state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.resume)"));
41491 		goto state_error;
41492 	}
41493 	DUK_ASSERT(thr->callstack_curr != NULL);
41494 	DUK_ASSERT(thr->callstack_curr->parent != NULL);
41495 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);  /* us */
41496 	DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
41497 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL);  /* caller */
41498 
41499 	caller_func = DUK_ACT_GET_FUNC(thr->callstack_curr->parent);
41500 	if (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) {
41501 		DUK_DD(DUK_DDPRINT("resume state invalid: caller must be ECMAScript code"));
41502 		goto state_error;
41503 	}
41504 
41505 	/* Note: there is no requirement that: 'thr->callstack_preventcount == 1'
41506 	 * like for yield.
41507 	 */
41508 
41509 	if (thr_resume->state != DUK_HTHREAD_STATE_INACTIVE &&
41510 	    thr_resume->state != DUK_HTHREAD_STATE_YIELDED) {
41511 		DUK_DD(DUK_DDPRINT("resume state invalid: target thread must be INACTIVE or YIELDED"));
41512 		goto state_error;
41513 	}
41514 
41515 	DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE ||
41516 	           thr_resume->state == DUK_HTHREAD_STATE_YIELDED);
41517 
41518 	/* Further state-dependent pre-checks */
41519 
41520 	if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
41521 		/* no pre-checks now, assume a previous yield() has left things in
41522 		 * tip-top shape (longjmp handler will assert for these).
41523 		 */
41524 	} else {
41525 		duk_hobject *h_fun;
41526 
41527 		DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE);
41528 
41529 		/* The initial function must be an ECMAScript function (but
41530 		 * can be bound).  We must make sure of that before we longjmp
41531 		 * because an error in the RESUME handler call processing will
41532 		 * not be handled very cleanly.
41533 		 */
41534 		if ((thr_resume->callstack_top != 0) ||
41535 		    (thr_resume->valstack_top - thr_resume->valstack != 1)) {
41536 			goto state_error;
41537 		}
41538 
41539 		duk_push_tval(thr, DUK_GET_TVAL_NEGIDX(thr_resume, -1));
41540 		duk_resolve_nonbound_function(thr);
41541 		h_fun = duk_require_hobject(thr, -1);  /* reject lightfuncs on purpose */
41542 		if (!DUK_HOBJECT_IS_CALLABLE(h_fun) || !DUK_HOBJECT_IS_COMPFUNC(h_fun)) {
41543 			goto state_error;
41544 		}
41545 		duk_pop(thr);
41546 	}
41547 
41548 	/*
41549 	 *  The error object has been augmented with a traceback and other
41550 	 *  info from its creation point -- usually another thread.  The
41551 	 *  error handler is called here right before throwing, but it also
41552 	 *  runs in the resumer's thread.  It might be nice to get a traceback
41553 	 *  from the resumee but this is not the case now.
41554 	 */
41555 
41556 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
41557 	if (is_error) {
41558 		DUK_ASSERT_TOP(thr, 2);  /* value (error) is at stack top */
41559 		duk_err_augment_error_throw(thr);  /* in resumer's context */
41560 	}
41561 #endif
41562 
41563 #if defined(DUK_USE_DEBUG)
41564 	if (is_error) {
41565 		DUK_DDD(DUK_DDDPRINT("RESUME ERROR: thread=%!T, value=%!T",
41566 		                     (duk_tval *) duk_get_tval(thr, 0),
41567 		                     (duk_tval *) duk_get_tval(thr, 1)));
41568 	} else if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
41569 		DUK_DDD(DUK_DDDPRINT("RESUME NORMAL: thread=%!T, value=%!T",
41570 		                     (duk_tval *) duk_get_tval(thr, 0),
41571 		                     (duk_tval *) duk_get_tval(thr, 1)));
41572 	} else {
41573 		DUK_DDD(DUK_DDDPRINT("RESUME INITIAL: thread=%!T, value=%!T",
41574 		                     (duk_tval *) duk_get_tval(thr, 0),
41575 		                     (duk_tval *) duk_get_tval(thr, 1)));
41576 	}
41577 #endif
41578 
41579 	thr->heap->lj.type = DUK_LJ_TYPE_RESUME;
41580 
41581 	/* lj value2: thread */
41582 	DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
41583 	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value2, &thr->valstack_bottom[0]);  /* side effects */
41584 
41585 	/* lj value1: value */
41586 	DUK_ASSERT(thr->valstack_bottom + 1 < thr->valstack_top);
41587 	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[1]);  /* side effects */
41588 	DUK_TVAL_CHKFAST_INPLACE_SLOW(&thr->heap->lj.value1);
41589 
41590 	thr->heap->lj.iserror = is_error;
41591 
41592 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* call is from executor, so we know we have a jmpbuf */
41593 	duk_err_longjmp(thr);  /* execution resumes in bytecode executor */
41594 	DUK_UNREACHABLE();
41595 	/* Never here, fall through to error (from compiler point of view). */
41596 
41597  state_error:
41598 	DUK_DCERROR_TYPE_INVALID_STATE(thr);
41599 }
41600 #endif
41601 
41602 /*
41603  *  Yield the current thread.
41604  *
41605  *  The thread must be in yieldable state: it must have a resumer, and there
41606  *  must not be any yield-preventing calls (native calls and constructor calls,
41607  *  currently) in the thread's call stack (otherwise a resume would not be
41608  *  possible later).  This method must be called from an ECMAScript function.
41609  *
41610  *  Args:
41611  *    - value
41612  *    - isError (defaults to false)
41613  *
41614  *  Note: yield and resume handling is currently asymmetric.
41615  */
41616 
41617 #if defined(DUK_USE_COROUTINE_SUPPORT)
41618 DUK_INTERNAL duk_ret_t duk_bi_thread_yield(duk_hthread *thr) {
41619 	duk_hobject *caller_func;
41620 	duk_small_uint_t is_error;
41621 
41622 	DUK_DDD(DUK_DDDPRINT("Duktape.Thread.yield(): value=%!T, is_error=%!T",
41623 	                     (duk_tval *) duk_get_tval(thr, 0),
41624 	                     (duk_tval *) duk_get_tval(thr, 1)));
41625 
41626 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
41627 	DUK_ASSERT(thr->heap->curr_thread == thr);
41628 
41629 	DUK_ASSERT(duk_get_top(thr) == 2);
41630 	is_error = (duk_small_uint_t) duk_to_boolean_top_pop(thr);
41631 	DUK_ASSERT(duk_get_top(thr) == 1);
41632 
41633 	/* [ value ] */
41634 
41635 	/*
41636 	 *  Thread state and calling context checks
41637 	 */
41638 
41639 	if (!thr->resumer) {
41640 		DUK_DD(DUK_DDPRINT("yield state invalid: current thread must have a resumer"));
41641 		goto state_error;
41642 	}
41643 	DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);
41644 
41645 	if (thr->callstack_top < 2) {
41646 		DUK_DD(DUK_DDPRINT("yield state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.yield)"));
41647 		goto state_error;
41648 	}
41649 	DUK_ASSERT(thr->callstack_curr != NULL);
41650 	DUK_ASSERT(thr->callstack_curr->parent != NULL);
41651 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);  /* us */
41652 	DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
41653 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL);  /* caller */
41654 
41655 	caller_func = DUK_ACT_GET_FUNC(thr->callstack_curr->parent);
41656 	if (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) {
41657 		DUK_DD(DUK_DDPRINT("yield state invalid: caller must be ECMAScript code"));
41658 		goto state_error;
41659 	}
41660 
41661 	DUK_ASSERT(thr->callstack_preventcount >= 1);  /* should never be zero, because we (Duktape.Thread.yield) are on the stack */
41662 	if (thr->callstack_preventcount != 1) {
41663 		/* Note: the only yield-preventing call is Duktape.Thread.yield(), hence check for 1, not 0 */
41664 		DUK_DD(DUK_DDPRINT("yield state invalid: there must be no yield-preventing calls in current thread callstack (preventcount is %ld)",
41665 		                   (long) thr->callstack_preventcount));
41666 		goto state_error;
41667 	}
41668 
41669 	/*
41670 	 *  The error object has been augmented with a traceback and other
41671 	 *  info from its creation point -- usually the current thread.
41672 	 *  The error handler, however, is called right before throwing
41673 	 *  and runs in the yielder's thread.
41674 	 */
41675 
41676 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
41677 	if (is_error) {
41678 		DUK_ASSERT_TOP(thr, 1);  /* value (error) is at stack top */
41679 		duk_err_augment_error_throw(thr);  /* in yielder's context */
41680 	}
41681 #endif
41682 
41683 #if defined(DUK_USE_DEBUG)
41684 	if (is_error) {
41685 		DUK_DDD(DUK_DDDPRINT("YIELD ERROR: value=%!T",
41686 		                     (duk_tval *) duk_get_tval(thr, 0)));
41687 	} else {
41688 		DUK_DDD(DUK_DDDPRINT("YIELD NORMAL: value=%!T",
41689 		                     (duk_tval *) duk_get_tval(thr, 0)));
41690 	}
41691 #endif
41692 
41693 	/*
41694 	 *  Process yield
41695 	 *
41696 	 *  After longjmp(), processing continues in bytecode executor longjmp
41697 	 *  handler, which will e.g. update thr->resumer to NULL.
41698 	 */
41699 
41700 	thr->heap->lj.type = DUK_LJ_TYPE_YIELD;
41701 
41702 	/* lj value1: value */
41703 	DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
41704 	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[0]);  /* side effects */
41705 	DUK_TVAL_CHKFAST_INPLACE_SLOW(&thr->heap->lj.value1);
41706 
41707 	thr->heap->lj.iserror = is_error;
41708 
41709 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* call is from executor, so we know we have a jmpbuf */
41710 	duk_err_longjmp(thr);  /* execution resumes in bytecode executor */
41711 	DUK_UNREACHABLE();
41712 	/* Never here, fall through to error (from compiler point of view). */
41713 
41714  state_error:
41715 	DUK_DCERROR_TYPE_INVALID_STATE(thr);
41716 }
41717 #endif
41718 
41719 #if defined(DUK_USE_COROUTINE_SUPPORT)
41720 DUK_INTERNAL duk_ret_t duk_bi_thread_current(duk_hthread *thr) {
41721 	duk_push_current_thread(thr);
41722 	return 1;
41723 }
41724 #endif
41725 #line 1 "duk_bi_thrower.c"
41726 /*
41727  *  Type error thrower, E5 Section 13.2.3.
41728  */
41729 
41730 /* #include duk_internal.h -> already included */
41731 
41732 DUK_INTERNAL duk_ret_t duk_bi_type_error_thrower(duk_hthread *thr) {
41733 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
41734 }
41735 #line 1 "duk_debug_fixedbuffer.c"
41736 /*
41737  *  Fixed buffer helper useful for debugging, requires no allocation
41738  *  which is critical for debugging.
41739  */
41740 
41741 /* #include duk_internal.h -> already included */
41742 
41743 #if defined(DUK_USE_DEBUG)
41744 
41745 DUK_INTERNAL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length) {
41746 	duk_size_t avail;
41747 	duk_size_t copylen;
41748 
41749 	avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
41750 	if (length > avail) {
41751 		copylen = avail;
41752 		fb->truncated = 1;
41753 	} else {
41754 		copylen = length;
41755 	}
41756 	duk_memcpy_unsafe(fb->buffer + fb->offset, buffer, copylen);
41757 	fb->offset += copylen;
41758 }
41759 
41760 DUK_INTERNAL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x) {
41761 	duk_fb_put_bytes(fb, (const duk_uint8_t *) &x, 1);
41762 }
41763 
41764 DUK_INTERNAL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x) {
41765 	duk_fb_put_bytes(fb, (const duk_uint8_t *) x, (duk_size_t) DUK_STRLEN(x));
41766 }
41767 
41768 DUK_INTERNAL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...) {
41769 	duk_size_t avail;
41770 	va_list ap;
41771 
41772 	va_start(ap, fmt);
41773 	avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
41774 	if (avail > 0) {
41775 		duk_int_t res = (duk_int_t) DUK_VSNPRINTF((char *) (fb->buffer + fb->offset), avail, fmt, ap);
41776 		if (res < 0) {
41777 			/* error */
41778 		} else if ((duk_size_t) res >= avail) {
41779 			/* (maybe) truncated */
41780 			fb->offset += avail;
41781 			if ((duk_size_t) res > avail) {
41782 				/* actual chars dropped (not just NUL term) */
41783 				fb->truncated = 1;
41784 			}
41785 		} else {
41786 			/* normal */
41787 			fb->offset += (duk_size_t) res;
41788 		}
41789 	}
41790 	va_end(ap);
41791 }
41792 
41793 DUK_INTERNAL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size) {
41794 	char buf[64+1];
41795 	duk_debug_format_funcptr(buf, sizeof(buf), fptr, fptr_size);
41796 	buf[sizeof(buf) - 1] = (char) 0;
41797 	duk_fb_put_cstring(fb, buf);
41798 }
41799 
41800 DUK_INTERNAL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb) {
41801 	return (fb->offset >= fb->length);
41802 }
41803 
41804 #endif  /* DUK_USE_DEBUG */
41805 #line 1 "duk_debug_vsnprintf.c"
41806 /*
41807  *  Custom formatter for debug printing, allowing Duktape specific data
41808  *  structures (such as tagged values and heap objects) to be printed with
41809  *  a nice format string.  Because debug printing should not affect execution
41810  *  state, formatting here must be independent of execution (see implications
41811  *  below) and must not allocate memory.
41812  *
41813  *  Custom format tags begin with a '%!' to safely distinguish them from
41814  *  standard format tags.  The following conversions are supported:
41815  *
41816  *     %!T    tagged value (duk_tval *)
41817  *     %!O    heap object (duk_heaphdr *)
41818  *     %!I    decoded bytecode instruction
41819  *     %!C    bytecode instruction opcode name (arg is long)
41820  *
41821  *  Everything is serialized in a JSON-like manner.  The default depth is one
41822  *  level, internal prototype is not followed, and internal properties are not
41823  *  serialized.  The following modifiers change this behavior:
41824  *
41825  *     @      print pointers
41826  *     #      print binary representations (where applicable)
41827  *     d      deep traversal of own properties (not prototype)
41828  *     p      follow prototype chain (useless without 'd')
41829  *     i      include internal properties (other than prototype)
41830  *     x      hexdump buffers
41831  *     h      heavy formatting
41832  *
41833  *  For instance, the following serializes objects recursively, but does not
41834  *  follow the prototype chain nor print internal properties: "%!dO".
41835  *
41836  *  Notes:
41837  *
41838  *    * Standard snprintf return value semantics seem to vary.  This
41839  *      implementation returns the number of bytes it actually wrote
41840  *      (excluding the null terminator).  If retval == buffer size,
41841  *      output was truncated (except for corner cases).
41842  *
41843  *    * Output format is intentionally different from ECMAScript
41844  *      formatting requirements, as formatting here serves debugging
41845  *      of internals.
41846  *
41847  *    * Depth checking (and updating) is done in each type printer
41848  *      separately, to allow them to call each other freely.
41849  *
41850  *    * Some pathological structures might take ages to print (e.g.
41851  *      self recursion with 100 properties pointing to the object
41852  *      itself).  To guard against these, each printer also checks
41853  *      whether the output buffer is full; if so, early exit.
41854  *
41855  *    * Reference loops are detected using a loop stack.
41856  */
41857 
41858 /* #include duk_internal.h -> already included */
41859 
41860 #if defined(DUK_USE_DEBUG)
41861 
41862 /* #include stdio.h -> already included */
41863 /* #include stdarg.h -> already included */
41864 #include <string.h>
41865 
41866 /* list of conversion specifiers that terminate a format tag;
41867  * this is unfortunately guesswork.
41868  */
41869 #define DUK__ALLOWED_STANDARD_SPECIFIERS  "diouxXeEfFgGaAcsCSpnm"
41870 
41871 /* maximum length of standard format tag that we support */
41872 #define DUK__MAX_FORMAT_TAG_LENGTH  32
41873 
41874 /* heapobj recursion depth when deep printing is selected */
41875 #define DUK__DEEP_DEPTH_LIMIT  8
41876 
41877 /* maximum recursion depth for loop detection stacks */
41878 #define DUK__LOOP_STACK_DEPTH  256
41879 
41880 /* must match bytecode defines now; build autogenerate? */
41881 DUK_LOCAL const char * const duk__bc_optab[256] = {
41882 	"LDREG", "STREG", "JUMP", "LDCONST", "LDINT", "LDINTX", "LDTHIS", "LDUNDEF",
41883 	"LDNULL", "LDTRUE", "LDFALSE", "GETVAR", "BNOT", "LNOT", "UNM", "UNP",
41884 	"EQ_RR", "EQ_CR", "EQ_RC", "EQ_CC", "NEQ_RR", "NEQ_CR", "NEQ_RC", "NEQ_CC",
41885 	"SEQ_RR", "SEQ_CR", "SEQ_RC", "SEQ_CC", "SNEQ_RR", "SNEQ_CR", "SNEQ_RC", "SNEQ_CC",
41886 
41887 	"GT_RR", "GT_CR", "GT_RC", "GT_CC", "GE_RR", "GE_CR", "GE_RC", "GE_CC",
41888 	"LT_RR", "LT_CR", "LT_RC", "LT_CC", "LE_RR", "LE_CR", "LE_RC", "LE_CC",
41889 	"IFTRUE_R", "IFTRUE_C", "IFFALSE_R", "IFFALSE_C", "ADD_RR", "ADD_CR", "ADD_RC", "ADD_CC",
41890 	"SUB_RR", "SUB_CR", "SUB_RC", "SUB_CC", "MUL_RR", "MUL_CR", "MUL_RC", "MUL_CC",
41891 
41892 	"DIV_RR", "DIV_CR", "DIV_RC", "DIV_CC", "MOD_RR", "MOD_CR", "MOD_RC", "MOD_CC",
41893 	"EXP_RR", "EXP_CR", "EXP_RC", "EXP_CC", "BAND_RR", "BAND_CR", "BAND_RC", "BAND_CC",
41894 	"BOR_RR", "BOR_CR", "BOR_RC", "BOR_CC", "BXOR_RR", "BXOR_CR", "BXOR_RC", "BXOR_CC",
41895 	"BASL_RR", "BASL_CR", "BASL_RC", "BASL_CC", "BLSR_RR", "BLSR_CR", "BLSR_RC", "BLSR_CC",
41896 
41897 	"BASR_RR", "BASR_CR", "BASR_RC", "BASR_CC", "INSTOF_RR", "INSTOF_CR", "INSTOF_RC", "INSTOF_CC",
41898 	"IN_RR", "IN_CR", "IN_RC", "IN_CC", "GETPROP_RR", "GETPROP_CR", "GETPROP_RC", "GETPROP_CC",
41899 	"PUTPROP_RR", "PUTPROP_CR", "PUTPROP_RC", "PUTPROP_CC", "DELPROP_RR", "DELPROP_CR", "DELPROP_RC", "DELPROP_CC",
41900 	"PREINCR", "PREDECR", "POSTINCR", "POSTDECR", "PREINCV", "PREDECV", "POSTINCV", "POSTDECV",
41901 
41902 	"PREINCP_RR", "PREINCP_CR", "PREINCP_RC", "PREINCP_CC", "PREDECP_RR", "PREDECP_CR", "PREDECP_RC", "PREDECP_CC",
41903 	"POSTINCP_RR", "POSTINCP_CR", "POSTINCP_RC", "POSTINCP_CC", "POSTDECP_RR", "POSTDECP_CR", "POSTDECP_RC", "POSTDECP_CC",
41904 	"DECLVAR_RR", "DECLVAR_CR", "DECLVAR_RC", "DECLVAR_CC", "REGEXP_RR", "REGEXP_RC", "REGEXP_CR", "REGEXP_CC",
41905 	"CLOSURE", "TYPEOF", "TYPEOFID", "PUTVAR", "DELVAR", "RETREG", "RETUNDEF", "RETCONST",
41906 
41907 	"RETCONSTN", "LABEL", "ENDLABEL", "BREAK", "CONTINUE", "TRYCATCH", "ENDTRY", "ENDCATCH",
41908 	"ENDFIN", "THROW", "INVLHS", "CSREG", "CSVAR_RR", "CSVAR_CR", "CSVAR_RC", "CSVAR_CC",
41909 	"CALL0", "CALL1", "CALL2", "CALL3", "CALL4", "CALL5", "CALL6", "CALL7",
41910 	"CALL8", "CALL9", "CALL10", "CALL11", "CALL12", "CALL13", "CALL14", "CALL15",
41911 
41912 	"NEWOBJ", "NEWARR", "MPUTOBJ", "MPUTOBJI", "INITSET", "INITGET", "MPUTARR", "MPUTARRI",
41913 	"SETALEN", "INITENUM", "NEXTENUM", "NEWTARGET", "DEBUGGER", "NOP", "INVALID", "UNUSED207",
41914 	"GETPROPC_RR", "GETPROPC_CR", "GETPROPC_RC", "GETPROPC_CC", "UNUSED212", "UNUSED213", "UNUSED214", "UNUSED215",
41915 	"UNUSED216", "UNUSED217", "UNUSED218", "UNUSED219", "UNUSED220", "UNUSED221", "UNUSED222", "UNUSED223",
41916 
41917 	"UNUSED224", "UNUSED225", "UNUSED226", "UNUSED227", "UNUSED228", "UNUSED229", "UNUSED230", "UNUSED231",
41918 	"UNUSED232", "UNUSED233", "UNUSED234", "UNUSED235", "UNUSED236", "UNUSED237", "UNUSED238", "UNUSED239",
41919 	"UNUSED240", "UNUSED241", "UNUSED242", "UNUSED243", "UNUSED244", "UNUSED245", "UNUSED246", "UNUSED247",
41920 	"UNUSED248", "UNUSED249", "UNUSED250", "UNUSED251", "UNUSED252", "UNUSED253", "UNUSED254", "UNUSED255"
41921 };
41922 
41923 typedef struct duk__dprint_state duk__dprint_state;
41924 struct duk__dprint_state {
41925 	duk_fixedbuffer *fb;
41926 
41927 	/* loop_stack_index could be perhaps be replaced by 'depth', but it's nice
41928 	 * to not couple these two mechanisms unnecessarily.
41929 	 */
41930 	duk_hobject *loop_stack[DUK__LOOP_STACK_DEPTH];
41931 	duk_int_t loop_stack_index;
41932 	duk_int_t loop_stack_limit;
41933 
41934 	duk_int_t depth;
41935 	duk_int_t depth_limit;
41936 
41937 	duk_bool_t pointer;
41938 	duk_bool_t heavy;
41939 	duk_bool_t binary;
41940 	duk_bool_t follow_proto;
41941 	duk_bool_t internal;
41942 	duk_bool_t hexdump;
41943 };
41944 
41945 /* helpers */
41946 DUK_LOCAL_DECL void duk__print_hstring(duk__dprint_state *st, duk_hstring *k, duk_bool_t quotes);
41947 DUK_LOCAL_DECL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h);
41948 DUK_LOCAL_DECL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h);
41949 DUK_LOCAL_DECL void duk__print_tval(duk__dprint_state *st, duk_tval *tv);
41950 DUK_LOCAL_DECL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins);
41951 DUK_LOCAL_DECL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
41952 DUK_LOCAL_DECL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
41953 DUK_LOCAL_DECL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h);
41954 
41955 DUK_LOCAL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
41956 	duk_fixedbuffer *fb = st->fb;
41957 
41958 	if (st->heavy) {
41959 		duk_fb_sprintf(fb, "(%p)", (void *) h);
41960 	}
41961 
41962 	if (!h) {
41963 		return;
41964 	}
41965 
41966 	if (st->binary) {
41967 		duk_size_t i;
41968 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
41969 		for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
41970 			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
41971 		}
41972 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
41973 	}
41974 
41975 #if defined(DUK_USE_REFERENCE_COUNTING)  /* currently implicitly also DUK_USE_DOUBLE_LINKED_HEAP */
41976 	if (st->heavy) {
41977 		duk_fb_sprintf(fb, "[h_next=%p,h_prev=%p,h_refcount=%lu,h_flags=%08lx,type=%ld,"
41978 		               "reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
41979 		               (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
41980 		               (void *) DUK_HEAPHDR_GET_PREV(NULL, h),
41981 		               (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(h),
41982 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
41983 		               (long) DUK_HEAPHDR_GET_TYPE(h),
41984 		               (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
41985 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
41986 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
41987 		               (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
41988 	}
41989 #else
41990 	if (st->heavy) {
41991 		duk_fb_sprintf(fb, "[h_next=%p,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
41992 		               (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
41993 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
41994 		               (long) DUK_HEAPHDR_GET_TYPE(h),
41995 		               (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
41996 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
41997 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
41998 		               (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
41999 	}
42000 #endif
42001 }
42002 
42003 DUK_LOCAL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h) {
42004 	duk_fixedbuffer *fb = st->fb;
42005 
42006 	if (st->heavy) {
42007 		duk_fb_sprintf(fb, "(%p)", (void *) h);
42008 	}
42009 
42010 	if (!h) {
42011 		return;
42012 	}
42013 
42014 	if (st->binary) {
42015 		duk_size_t i;
42016 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
42017 		for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
42018 			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
42019 		}
42020 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
42021 	}
42022 
42023 #if defined(DUK_USE_REFERENCE_COUNTING)
42024 	if (st->heavy) {
42025 		duk_fb_sprintf(fb, "[h_refcount=%lu,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
42026 		               (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h),
42027 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
42028 		               (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
42029 		               (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
42030 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
42031 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
42032 		               (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
42033 	}
42034 #else
42035 	if (st->heavy) {
42036 		duk_fb_sprintf(fb, "[h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
42037 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
42038 		               (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
42039 		               (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
42040 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
42041 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
42042 		               (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
42043 	}
42044 #endif
42045 }
42046 
42047 DUK_LOCAL void duk__print_hstring(duk__dprint_state *st, duk_hstring *h, duk_bool_t quotes) {
42048 	duk_fixedbuffer *fb = st->fb;
42049 	const duk_uint8_t *p;
42050 	const duk_uint8_t *p_end;
42051 
42052 	/* terminal type: no depth check */
42053 
42054 	if (duk_fb_is_full(fb)) {
42055 		return;
42056 	}
42057 
42058 	duk__print_shared_heaphdr_string(st, &h->hdr);
42059 
42060 	if (!h) {
42061 		duk_fb_put_cstring(fb, "NULL");
42062 		return;
42063 	}
42064 
42065 	p = DUK_HSTRING_GET_DATA(h);
42066 	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
42067 
42068 	if (p_end > p && p[0] == DUK_ASC_UNDERSCORE) {
42069 		/* If property key begins with underscore, encode it with
42070 		 * forced quotes (e.g. "_Foo") to distinguish it from encoded
42071 		 * internal properties (e.g. \x82Bar -> _Bar).
42072 		 */
42073 		quotes = 1;
42074 	}
42075 
42076 	if (quotes) {
42077 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
42078 	}
42079 	while (p < p_end) {
42080 		duk_uint8_t ch = *p++;
42081 
42082 		/* two special escapes: '\' and '"', other printables as is */
42083 		if (ch == '\\') {
42084 			duk_fb_sprintf(fb, "\\\\");
42085 		} else if (ch == '"') {
42086 			duk_fb_sprintf(fb, "\\\"");
42087 		} else if (ch >= 0x20 && ch <= 0x7e) {
42088 			duk_fb_put_byte(fb, ch);
42089 		} else if (ch == 0x82 && !quotes) {
42090 			/* encode \x82Bar as _Bar if no quotes are
42091 			 * applied, this is for readable internal keys.
42092 			 */
42093 			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_UNDERSCORE);
42094 		} else {
42095 			duk_fb_sprintf(fb, "\\x%02lx", (unsigned long) ch);
42096 		}
42097 	}
42098 	if (quotes) {
42099 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
42100 	}
42101 #if defined(DUK_USE_REFERENCE_COUNTING)
42102 	/* XXX: limit to quoted strings only, to save keys from being cluttered? */
42103 	duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
42104 #endif
42105 }
42106 
42107 #define DUK__COMMA()  do { \
42108 		if (first) { \
42109 			first = 0; \
42110 		} else { \
42111 			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA); \
42112 		} \
42113 	} while (0)
42114 
42115 DUK_LOCAL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h) {
42116 	duk_fixedbuffer *fb = st->fb;
42117 	duk_uint_fast32_t i;
42118 	duk_tval *tv;
42119 	duk_hstring *key;
42120 	duk_bool_t first = 1;
42121 	const char *brace1 = "{";
42122 	const char *brace2 = "}";
42123 	duk_bool_t pushed_loopstack = 0;
42124 
42125 	if (duk_fb_is_full(fb)) {
42126 		return;
42127 	}
42128 
42129 	duk__print_shared_heaphdr(st, &h->hdr);
42130 
42131 	if (h && DUK_HOBJECT_HAS_ARRAY_PART(h)) {
42132 		brace1 = "[";
42133 		brace2 = "]";
42134 	}
42135 
42136 	if (!h) {
42137 		duk_fb_put_cstring(fb, "NULL");
42138 		goto finished;
42139 	}
42140 
42141 	if (st->depth >= st->depth_limit) {
42142 		const char *subtype = "generic";
42143 
42144 		if (DUK_HOBJECT_IS_COMPFUNC(h)) {
42145 			subtype = "compfunc";
42146 		} else if (DUK_HOBJECT_IS_NATFUNC(h)) {
42147 			subtype = "natfunc";
42148 		} else if (DUK_HOBJECT_IS_THREAD(h)) {
42149 			subtype = "thread";
42150 		} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
42151 			subtype = "bufobj";
42152 		} else if (DUK_HOBJECT_IS_ARRAY(h)) {
42153 			subtype = "array";
42154 		}
42155 		duk_fb_sprintf(fb, "%sobject/%s %p%s", (const char *) brace1, subtype, (void *) h, (const char *) brace2);
42156 		return;
42157 	}
42158 
42159 	for (i = 0; i < (duk_uint_fast32_t) st->loop_stack_index; i++) {
42160 		if (st->loop_stack[i] == h) {
42161 			duk_fb_sprintf(fb, "%sLOOP:%p%s", (const char *) brace1, (void *) h, (const char *) brace2);
42162 			return;
42163 		}
42164 	}
42165 
42166 	/* after this, return paths should 'goto finished' for decrement */
42167 	st->depth++;
42168 
42169 	if (st->loop_stack_index >= st->loop_stack_limit) {
42170 		duk_fb_sprintf(fb, "%sOUT-OF-LOOP-STACK%s", (const char *) brace1, (const char *) brace2);
42171 		goto finished;
42172 	}
42173 	st->loop_stack[st->loop_stack_index++] = h;
42174 	pushed_loopstack = 1;
42175 
42176 	/*
42177 	 *  Notation: double underscore used for internal properties which are not
42178 	 *  stored in the property allocation (e.g. '__valstack').
42179 	 */
42180 
42181 	duk_fb_put_cstring(fb, brace1);
42182 
42183 	if (DUK_HOBJECT_GET_PROPS(NULL, h)) {
42184 		duk_uint32_t a_limit;
42185 
42186 		a_limit = DUK_HOBJECT_GET_ASIZE(h);
42187 		if (st->internal) {
42188 			/* dump all allocated entries, unused entries print as 'unused',
42189 			 * note that these may extend beyond current 'length' and look
42190 			 * a bit funny.
42191 			 */
42192 		} else {
42193 			/* leave out trailing 'unused' elements */
42194 			while (a_limit > 0) {
42195 				tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, a_limit - 1);
42196 				if (!DUK_TVAL_IS_UNUSED(tv)) {
42197 					break;
42198 				}
42199 				a_limit--;
42200 			}
42201 		}
42202 
42203 		for (i = 0; i < a_limit; i++) {
42204 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, i);
42205 			DUK__COMMA();
42206 			duk__print_tval(st, tv);
42207 		}
42208 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(h); i++) {
42209 			key = DUK_HOBJECT_E_GET_KEY(NULL, h, i);
42210 			if (!key) {
42211 				continue;
42212 			}
42213 			if (!st->internal && DUK_HSTRING_HAS_HIDDEN(key)) {
42214 				continue;
42215 			}
42216 			DUK__COMMA();
42217 			duk__print_hstring(st, key, 0);
42218 			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COLON);
42219 			if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(NULL, h, i)) {
42220 				duk_fb_sprintf(fb, "[get:%p,set:%p]",
42221 				               (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.get,
42222 				               (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.set);
42223 			} else {
42224 				tv = &DUK_HOBJECT_E_GET_VALUE(NULL, h, i).v;
42225 				duk__print_tval(st, tv);
42226 			}
42227 			if (st->heavy) {
42228 				duk_fb_sprintf(fb, "<%02lx>", (unsigned long) DUK_HOBJECT_E_GET_FLAGS(NULL, h, i));
42229 			}
42230 		}
42231 	}
42232 	if (st->internal) {
42233 		if (DUK_HOBJECT_IS_ARRAY(h)) {
42234 			DUK__COMMA(); duk_fb_sprintf(fb, "__array:true");
42235 		}
42236 		if (DUK_HOBJECT_HAS_EXTENSIBLE(h)) {
42237 			DUK__COMMA(); duk_fb_sprintf(fb, "__extensible:true");
42238 		}
42239 		if (DUK_HOBJECT_HAS_CONSTRUCTABLE(h)) {
42240 			DUK__COMMA(); duk_fb_sprintf(fb, "__constructable:true");
42241 		}
42242 		if (DUK_HOBJECT_HAS_BOUNDFUNC(h)) {
42243 			DUK__COMMA(); duk_fb_sprintf(fb, "__boundfunc:true");
42244 		}
42245 		if (DUK_HOBJECT_HAS_COMPFUNC(h)) {
42246 			DUK__COMMA(); duk_fb_sprintf(fb, "__compfunc:true");
42247 		}
42248 		if (DUK_HOBJECT_HAS_NATFUNC(h)) {
42249 			DUK__COMMA(); duk_fb_sprintf(fb, "__natfunc:true");
42250 		}
42251 		if (DUK_HOBJECT_HAS_BUFOBJ(h)) {
42252 			DUK__COMMA(); duk_fb_sprintf(fb, "__bufobj:true");
42253 		}
42254 		if (DUK_HOBJECT_IS_THREAD(h)) {
42255 			DUK__COMMA(); duk_fb_sprintf(fb, "__thread:true");
42256 		}
42257 		if (DUK_HOBJECT_HAS_ARRAY_PART(h)) {
42258 			DUK__COMMA(); duk_fb_sprintf(fb, "__array_part:true");
42259 		}
42260 		if (DUK_HOBJECT_HAS_STRICT(h)) {
42261 			DUK__COMMA(); duk_fb_sprintf(fb, "__strict:true");
42262 		}
42263 		if (DUK_HOBJECT_HAS_NOTAIL(h)) {
42264 			DUK__COMMA(); duk_fb_sprintf(fb, "__notail:true");
42265 		}
42266 		if (DUK_HOBJECT_HAS_NEWENV(h)) {
42267 			DUK__COMMA(); duk_fb_sprintf(fb, "__newenv:true");
42268 		}
42269 		if (DUK_HOBJECT_HAS_NAMEBINDING(h)) {
42270 			DUK__COMMA(); duk_fb_sprintf(fb, "__namebinding:true");
42271 		}
42272 		if (DUK_HOBJECT_HAS_CREATEARGS(h)) {
42273 			DUK__COMMA(); duk_fb_sprintf(fb, "__createargs:true");
42274 		}
42275 		if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)) {
42276 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_array:true");
42277 		}
42278 		if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)) {
42279 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_stringobj:true");
42280 		}
42281 		if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)) {
42282 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_arguments:true");
42283 		}
42284 		if (DUK_HOBJECT_IS_BUFOBJ(h)) {
42285 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_bufobj:true");
42286 		}
42287 		if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)) {
42288 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_proxyobj:true");
42289 		}
42290 	}
42291 
42292 	if (st->internal && DUK_HOBJECT_IS_ARRAY(h)) {
42293 		duk_harray *a = (duk_harray *) h;
42294 		DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) a->length);
42295 		DUK__COMMA(); duk_fb_sprintf(fb, "__length_nonwritable:%ld", (long) a->length_nonwritable);
42296 	} else if (st->internal && DUK_HOBJECT_IS_COMPFUNC(h)) {
42297 		duk_hcompfunc *f = (duk_hcompfunc *) h;
42298 		DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
42299 		duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));
42300 		DUK__COMMA(); duk_fb_put_cstring(fb, "__lexenv:"); duk__print_hobject(st, DUK_HCOMPFUNC_GET_LEXENV(NULL, f));
42301 		DUK__COMMA(); duk_fb_put_cstring(fb, "__varenv:"); duk__print_hobject(st, DUK_HCOMPFUNC_GET_VARENV(NULL, f));
42302 		DUK__COMMA(); duk_fb_sprintf(fb, "__nregs:%ld", (long) f->nregs);
42303 		DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
42304 #if defined(DUK_USE_DEBUGGER_SUPPORT)
42305 		DUK__COMMA(); duk_fb_sprintf(fb, "__start_line:%ld", (long) f->start_line);
42306 		DUK__COMMA(); duk_fb_sprintf(fb, "__end_line:%ld", (long) f->end_line);
42307 #endif
42308 		DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
42309 		duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));
42310 	} else if (st->internal && DUK_HOBJECT_IS_NATFUNC(h)) {
42311 		duk_hnatfunc *f = (duk_hnatfunc *) h;
42312 		DUK__COMMA(); duk_fb_sprintf(fb, "__func:");
42313 		duk_fb_put_funcptr(fb, (duk_uint8_t *) &f->func, sizeof(f->func));
42314 		DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
42315 		DUK__COMMA(); duk_fb_sprintf(fb, "__magic:%ld", (long) f->magic);
42316 	} else if (st->internal && DUK_HOBJECT_IS_DECENV(h)) {
42317 		duk_hdecenv *e = (duk_hdecenv *) h;
42318 		DUK__COMMA(); duk_fb_sprintf(fb, "__thread:"); duk__print_hobject(st, (duk_hobject *) e->thread);
42319 		DUK__COMMA(); duk_fb_sprintf(fb, "__varmap:"); duk__print_hobject(st, (duk_hobject *) e->varmap);
42320 		DUK__COMMA(); duk_fb_sprintf(fb, "__regbase_byteoff:%ld", (long) e->regbase_byteoff);
42321 	} else if (st->internal && DUK_HOBJECT_IS_OBJENV(h)) {
42322 		duk_hobjenv *e = (duk_hobjenv *) h;
42323 		DUK__COMMA(); duk_fb_sprintf(fb, "__target:"); duk__print_hobject(st, (duk_hobject *) e->target);
42324 		DUK__COMMA(); duk_fb_sprintf(fb, "__has_this:%ld", (long) e->has_this);
42325 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
42326 	} else if (st->internal && DUK_HOBJECT_IS_BUFOBJ(h)) {
42327 		duk_hbufobj *b = (duk_hbufobj *) h;
42328 		DUK__COMMA(); duk_fb_sprintf(fb, "__buf:");
42329 		duk__print_hbuffer(st, (duk_hbuffer *) b->buf);
42330 		DUK__COMMA(); duk_fb_sprintf(fb, "__buf_prop:");
42331 		duk__print_hobject(st, (duk_hobject *) b->buf_prop);
42332 		DUK__COMMA(); duk_fb_sprintf(fb, "__offset:%ld", (long) b->offset);
42333 		DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) b->length);
42334 		DUK__COMMA(); duk_fb_sprintf(fb, "__shift:%ld", (long) b->shift);
42335 		DUK__COMMA(); duk_fb_sprintf(fb, "__elemtype:%ld", (long) b->elem_type);
42336 #endif
42337 	} else if (st->internal && DUK_HOBJECT_IS_PROXY(h)) {
42338 		duk_hproxy *p = (duk_hproxy *) h;
42339 		DUK__COMMA(); duk_fb_sprintf(fb, "__target:");
42340 		duk__print_hobject(st, p->target);
42341 		DUK__COMMA(); duk_fb_sprintf(fb, "__handler:");
42342 		duk__print_hobject(st, p->handler);
42343 	} else if (st->internal && DUK_HOBJECT_IS_THREAD(h)) {
42344 		duk_hthread *t = (duk_hthread *) h;
42345 		DUK__COMMA(); duk_fb_sprintf(fb, "__ptr_curr_pc:%p", (void *) t->ptr_curr_pc);
42346 		DUK__COMMA(); duk_fb_sprintf(fb, "__heap:%p", (void *) t->heap);
42347 		DUK__COMMA(); duk_fb_sprintf(fb, "__strict:%ld", (long) t->strict);
42348 		DUK__COMMA(); duk_fb_sprintf(fb, "__state:%ld", (long) t->state);
42349 		DUK__COMMA(); duk_fb_sprintf(fb, "__unused1:%ld", (long) t->unused1);
42350 		DUK__COMMA(); duk_fb_sprintf(fb, "__unused2:%ld", (long) t->unused2);
42351 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack:%p", (void *) t->valstack);
42352 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_end:%p/%ld", (void *) t->valstack_end, (long) (t->valstack_end - t->valstack));
42353 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_alloc_end:%p/%ld", (void *) t->valstack_alloc_end, (long) (t->valstack_alloc_end - t->valstack));
42354 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_bottom:%p/%ld", (void *) t->valstack_bottom, (long) (t->valstack_bottom - t->valstack));
42355 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_top:%p/%ld", (void *) t->valstack_top, (long) (t->valstack_top - t->valstack));
42356 		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_curr:%p", (void *) t->callstack_curr);
42357 		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_top:%ld", (long) t->callstack_top);
42358 		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_preventcount:%ld", (long) t->callstack_preventcount);
42359 		DUK__COMMA(); duk_fb_sprintf(fb, "__resumer:"); duk__print_hobject(st, (duk_hobject *) t->resumer);
42360 		DUK__COMMA(); duk_fb_sprintf(fb, "__compile_ctx:%p", (void *) t->compile_ctx);
42361 #if defined(DUK_USE_INTERRUPT_COUNTER)
42362 		DUK__COMMA(); duk_fb_sprintf(fb, "__interrupt_counter:%ld", (long) t->interrupt_counter);
42363 		DUK__COMMA(); duk_fb_sprintf(fb, "__interrupt_init:%ld", (long) t->interrupt_init);
42364 #endif
42365 
42366 		/* XXX: print built-ins array? */
42367 
42368 	}
42369 #if defined(DUK_USE_REFERENCE_COUNTING)
42370 	if (st->internal) {
42371 		DUK__COMMA(); duk_fb_sprintf(fb, "__refcount:%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h));
42372 	}
42373 #endif
42374 	if (st->internal) {
42375 		DUK__COMMA(); duk_fb_sprintf(fb, "__class:%ld", (long) DUK_HOBJECT_GET_CLASS_NUMBER(h));
42376 	}
42377 
42378 	DUK__COMMA(); duk_fb_sprintf(fb, "__heapptr:%p", (void *) h);  /* own pointer */
42379 
42380 	/* prototype should be last, for readability */
42381 	if (DUK_HOBJECT_GET_PROTOTYPE(NULL, h)) {
42382 		if (st->follow_proto) {
42383 			DUK__COMMA(); duk_fb_put_cstring(fb, "__prototype:"); duk__print_hobject(st, DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
42384 		} else {
42385 			DUK__COMMA(); duk_fb_sprintf(fb, "__prototype:%p", (void *) DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
42386 		}
42387 	}
42388 
42389 	duk_fb_put_cstring(fb, brace2);
42390 
42391 #if defined(DUK_USE_HOBJECT_HASH_PART)
42392 	if (st->heavy && DUK_HOBJECT_GET_HSIZE(h) > 0) {
42393 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
42394 		for (i = 0; i < DUK_HOBJECT_GET_HSIZE(h); i++) {
42395 			duk_uint_t h_idx = DUK_HOBJECT_H_GET_INDEX(NULL, h, i);
42396 			if (i > 0) {
42397 				duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA);
42398 			}
42399 			if (h_idx == DUK_HOBJECT_HASHIDX_UNUSED) {
42400 				duk_fb_sprintf(fb, "u");
42401 			} else if (h_idx == DUK_HOBJECT_HASHIDX_DELETED) {
42402 				duk_fb_sprintf(fb, "d");
42403 			} else {
42404 				duk_fb_sprintf(fb, "%ld", (long) h_idx);
42405 			}
42406 		}
42407 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
42408 	}
42409 #endif
42410 
42411  finished:
42412 	st->depth--;
42413 	if (pushed_loopstack) {
42414 		st->loop_stack_index--;
42415 		st->loop_stack[st->loop_stack_index] = NULL;
42416 	}
42417 }
42418 
42419 DUK_LOCAL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h) {
42420 	duk_fixedbuffer *fb = st->fb;
42421 	duk_size_t i, n;
42422 	duk_uint8_t *p;
42423 
42424 	if (duk_fb_is_full(fb)) {
42425 		return;
42426 	}
42427 
42428 	/* terminal type: no depth check */
42429 
42430 	if (!h) {
42431 		duk_fb_put_cstring(fb, "NULL");
42432 		return;
42433 	}
42434 
42435 	if (DUK_HBUFFER_HAS_DYNAMIC(h)) {
42436 		if (DUK_HBUFFER_HAS_EXTERNAL(h)) {
42437 			duk_hbuffer_external *g = (duk_hbuffer_external *) h;
42438 			duk_fb_sprintf(fb, "buffer:external:%p:%ld",
42439 			               (void *) DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(NULL, g),
42440 			               (long) DUK_HBUFFER_EXTERNAL_GET_SIZE(g));
42441 		} else {
42442 			duk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;
42443 			duk_fb_sprintf(fb, "buffer:dynamic:%p:%ld",
42444 			               (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(NULL, g),
42445 			               (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(g));
42446 		}
42447 	} else {
42448 		duk_fb_sprintf(fb, "buffer:fixed:%ld", (long) DUK_HBUFFER_GET_SIZE(h));
42449 	}
42450 
42451 #if defined(DUK_USE_REFERENCE_COUNTING)
42452 	duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
42453 #endif
42454 
42455 	if (st->hexdump) {
42456 		duk_fb_sprintf(fb, "=[");
42457 		n = DUK_HBUFFER_GET_SIZE(h);
42458 		p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(NULL, h);
42459 		for (i = 0; i < n; i++) {
42460 			duk_fb_sprintf(fb, "%02lx", (unsigned long) p[i]);
42461 		}
42462 		duk_fb_sprintf(fb, "]");
42463 	}
42464 }
42465 
42466 DUK_LOCAL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
42467 	duk_fixedbuffer *fb = st->fb;
42468 
42469 	if (duk_fb_is_full(fb)) {
42470 		return;
42471 	}
42472 
42473 	if (!h) {
42474 		duk_fb_put_cstring(fb, "NULL");
42475 		return;
42476 	}
42477 
42478 	switch (DUK_HEAPHDR_GET_TYPE(h)) {
42479 	case DUK_HTYPE_STRING:
42480 		duk__print_hstring(st, (duk_hstring *) h, 1);
42481 		break;
42482 	case DUK_HTYPE_OBJECT:
42483 		duk__print_hobject(st, (duk_hobject *) h);
42484 		break;
42485 	case DUK_HTYPE_BUFFER:
42486 		duk__print_hbuffer(st, (duk_hbuffer *) h);
42487 		break;
42488 	default:
42489 		duk_fb_sprintf(fb, "[unknown htype %ld]", (long) DUK_HEAPHDR_GET_TYPE(h));
42490 		break;
42491 	}
42492 }
42493 
42494 DUK_LOCAL void duk__print_tval(duk__dprint_state *st, duk_tval *tv) {
42495 	duk_fixedbuffer *fb = st->fb;
42496 
42497 	if (duk_fb_is_full(fb)) {
42498 		return;
42499 	}
42500 
42501 	/* depth check is done when printing an actual type */
42502 
42503 	if (st->heavy) {
42504 		duk_fb_sprintf(fb, "(%p)", (void *) tv);
42505 	}
42506 
42507 	if (!tv) {
42508 		duk_fb_put_cstring(fb, "NULL");
42509 		return;
42510 	}
42511 
42512 	if (st->binary) {
42513 		duk_size_t i;
42514 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
42515 		for (i = 0; i < (duk_size_t) sizeof(*tv); i++) {
42516 			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)tv)[i]);
42517 		}
42518 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
42519 	}
42520 
42521 	if (st->heavy) {
42522 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
42523 	}
42524 	switch (DUK_TVAL_GET_TAG(tv)) {
42525 	case DUK_TAG_UNDEFINED: {
42526 		duk_fb_put_cstring(fb, "undefined");
42527 		break;
42528 	}
42529 	case DUK_TAG_UNUSED: {
42530 		duk_fb_put_cstring(fb, "unused");
42531 		break;
42532 	}
42533 	case DUK_TAG_NULL: {
42534 		duk_fb_put_cstring(fb, "null");
42535 		break;
42536 	}
42537 	case DUK_TAG_BOOLEAN: {
42538 		duk_fb_put_cstring(fb, DUK_TVAL_GET_BOOLEAN(tv) ? "true" : "false");
42539 		break;
42540 	}
42541 	case DUK_TAG_STRING: {
42542 		/* Note: string is a terminal heap object, so no depth check here */
42543 		duk__print_hstring(st, DUK_TVAL_GET_STRING(tv), 1);
42544 		break;
42545 	}
42546 	case DUK_TAG_OBJECT: {
42547 		duk__print_hobject(st, DUK_TVAL_GET_OBJECT(tv));
42548 		break;
42549 	}
42550 	case DUK_TAG_BUFFER: {
42551 		duk__print_hbuffer(st, DUK_TVAL_GET_BUFFER(tv));
42552 		break;
42553 	}
42554 	case DUK_TAG_POINTER: {
42555 		duk_fb_sprintf(fb, "pointer:%p", (void *) DUK_TVAL_GET_POINTER(tv));
42556 		break;
42557 	}
42558 	case DUK_TAG_LIGHTFUNC: {
42559 		duk_c_function func;
42560 		duk_small_uint_t lf_flags;
42561 
42562 		DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
42563 		duk_fb_sprintf(fb, "lightfunc:");
42564 		duk_fb_put_funcptr(fb, (duk_uint8_t *) &func, sizeof(func));
42565 		duk_fb_sprintf(fb, ":%04lx", (long) lf_flags);
42566 		break;
42567 	}
42568 #if defined(DUK_USE_FASTINT)
42569 	case DUK_TAG_FASTINT:
42570 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
42571 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
42572 		duk_fb_sprintf(fb, "%.18g_F", (double) DUK_TVAL_GET_NUMBER(tv));
42573 		break;
42574 #endif
42575 	default: {
42576 		/* IEEE double is approximately 16 decimal digits; print a couple extra */
42577 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
42578 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
42579 		duk_fb_sprintf(fb, "%.18g", (double) DUK_TVAL_GET_NUMBER(tv));
42580 		break;
42581 	}
42582 	}
42583 	if (st->heavy) {
42584 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
42585 	}
42586 }
42587 
42588 DUK_LOCAL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins) {
42589 	duk_fixedbuffer *fb = st->fb;
42590 	duk_small_int_t op;
42591 	const char *op_name;
42592 
42593 	op = (duk_small_int_t) DUK_DEC_OP(ins);
42594 	op_name = duk__bc_optab[op];
42595 
42596 	/* XXX: option to fix opcode length so it lines up nicely */
42597 
42598 	if (op == DUK_OP_JUMP) {
42599 		duk_int_t diff1 = (duk_int_t) (DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS);  /* from next pc */
42600 		duk_int_t diff2 = diff1 + 1;                                          /* from curr pc */
42601 
42602 		duk_fb_sprintf(fb, "%s %ld (to pc%c%ld)",
42603 		               (const char *) op_name, (long) diff1,
42604 		               (int) (diff2 >= 0 ? '+' : '-'),  /* char format: use int */
42605 		               (long) (diff2 >= 0 ? diff2 : -diff2));
42606 	} else {
42607 		duk_fb_sprintf(fb, "%s %ld, %ld, %ld",
42608 		               (const char *) op_name, (long) DUK_DEC_A(ins),
42609 		               (long) DUK_DEC_B(ins), (long) DUK_DEC_C(ins));
42610 	}
42611 }
42612 
42613 DUK_LOCAL void duk__print_opcode(duk__dprint_state *st, duk_small_int_t opcode) {
42614 	duk_fixedbuffer *fb = st->fb;
42615 
42616 	if (opcode < DUK_BC_OP_MIN || opcode > DUK_BC_OP_MAX) {
42617 		duk_fb_sprintf(fb, "?(%ld)", (long) opcode);
42618 	} else {
42619 		duk_fb_sprintf(fb, "%s", (const char *) duk__bc_optab[opcode]);
42620 	}
42621 }
42622 
42623 DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap) {
42624 	duk_fixedbuffer fb;
42625 	const char *p = format;
42626 	const char *p_end = p + DUK_STRLEN(format);
42627 	duk_int_t retval;
42628 
42629 	duk_memzero(&fb, sizeof(fb));
42630 	fb.buffer = (duk_uint8_t *) str;
42631 	fb.length = size;
42632 	fb.offset = 0;
42633 	fb.truncated = 0;
42634 
42635 	while (p < p_end) {
42636 		char ch = *p++;
42637 		const char *p_begfmt = NULL;
42638 		duk_bool_t got_exclamation = 0;
42639 		duk_bool_t got_long = 0;  /* %lf, %ld etc */
42640 		duk__dprint_state st;
42641 
42642 		if (ch != DUK_ASC_PERCENT) {
42643 			duk_fb_put_byte(&fb, (duk_uint8_t) ch);
42644 			continue;
42645 		}
42646 
42647 		/*
42648 		 *  Format tag parsing.  Since we don't understand all the
42649 		 *  possible format tags allowed, we just scan for a terminating
42650 		 *  specifier and keep track of relevant modifiers that we do
42651 		 *  understand.  See man 3 printf.
42652 		 */
42653 
42654 		duk_memzero(&st, sizeof(st));
42655 		st.fb = &fb;
42656 		st.depth = 0;
42657 		st.depth_limit = 1;
42658 		st.loop_stack_index = 0;
42659 		st.loop_stack_limit = DUK__LOOP_STACK_DEPTH;
42660 
42661 		p_begfmt = p - 1;
42662 		while (p < p_end) {
42663 			ch = *p++;
42664 
42665 			if (ch == DUK_ASC_STAR) {
42666 				/* unsupported: would consume multiple args */
42667 				goto format_error;
42668 			} else if (ch == DUK_ASC_PERCENT) {
42669 				duk_fb_put_byte(&fb, (duk_uint8_t) DUK_ASC_PERCENT);
42670 				break;
42671 			} else if (ch == DUK_ASC_EXCLAMATION) {
42672 				got_exclamation = 1;
42673 			} else if (!got_exclamation && ch == DUK_ASC_LC_L) {
42674 				got_long = 1;
42675 			} else if (got_exclamation && ch == DUK_ASC_LC_D) {
42676 				st.depth_limit = DUK__DEEP_DEPTH_LIMIT;
42677 			} else if (got_exclamation && ch == DUK_ASC_LC_P) {
42678 				st.follow_proto = 1;
42679 			} else if (got_exclamation && ch == DUK_ASC_LC_I) {
42680 				st.internal = 1;
42681 			} else if (got_exclamation && ch == DUK_ASC_LC_X) {
42682 				st.hexdump = 1;
42683 			} else if (got_exclamation && ch == DUK_ASC_LC_H) {
42684 				st.heavy = 1;
42685 			} else if (got_exclamation && ch == DUK_ASC_ATSIGN) {
42686 				st.pointer = 1;
42687 			} else if (got_exclamation && ch == DUK_ASC_HASH) {
42688 				st.binary = 1;
42689 			} else if (got_exclamation && ch == DUK_ASC_UC_T) {
42690 				duk_tval *t = va_arg(ap, duk_tval *);
42691 				if (st.pointer && !st.heavy) {
42692 					duk_fb_sprintf(&fb, "(%p)", (void *) t);
42693 				}
42694 				duk__print_tval(&st, t);
42695 				break;
42696 			} else if (got_exclamation && ch == DUK_ASC_UC_O) {
42697 				duk_heaphdr *t = va_arg(ap, duk_heaphdr *);
42698 				if (st.pointer && !st.heavy) {
42699 					duk_fb_sprintf(&fb, "(%p)", (void *) t);
42700 				}
42701 				duk__print_heaphdr(&st, t);
42702 				break;
42703 			} else if (got_exclamation && ch == DUK_ASC_UC_I) {
42704 				duk_instr_t t = va_arg(ap, duk_instr_t);
42705 				duk__print_instr(&st, t);
42706 				break;
42707 			} else if (got_exclamation && ch == DUK_ASC_UC_C) {
42708 				long t = va_arg(ap, long);
42709 				duk__print_opcode(&st, (duk_small_int_t) t);
42710 				break;
42711 			} else if (!got_exclamation && strchr(DUK__ALLOWED_STANDARD_SPECIFIERS, (int) ch)) {
42712 				char fmtbuf[DUK__MAX_FORMAT_TAG_LENGTH];
42713 				duk_size_t fmtlen;
42714 
42715 				DUK_ASSERT(p >= p_begfmt);
42716 				fmtlen = (duk_size_t) (p - p_begfmt);
42717 				if (fmtlen >= sizeof(fmtbuf)) {
42718 					/* format is too large, abort */
42719 					goto format_error;
42720 				}
42721 				duk_memzero(fmtbuf, sizeof(fmtbuf));
42722 				duk_memcpy(fmtbuf, p_begfmt, fmtlen);
42723 
42724 				/* assume exactly 1 arg, which is why '*' is forbidden; arg size still
42725 				 * depends on type though.
42726 				 */
42727 
42728 				if (ch == DUK_ASC_LC_F || ch == DUK_ASC_LC_G || ch == DUK_ASC_LC_E) {
42729 					/* %f and %lf both consume a 'long' */
42730 					double arg = va_arg(ap, double);
42731 					duk_fb_sprintf(&fb, fmtbuf, arg);
42732 				} else if (ch == DUK_ASC_LC_D && got_long) {
42733 					/* %ld */
42734 					long arg = va_arg(ap, long);
42735 					duk_fb_sprintf(&fb, fmtbuf, arg);
42736 				} else if (ch == DUK_ASC_LC_D) {
42737 					/* %d; only 16 bits are guaranteed */
42738 					int arg = va_arg(ap, int);
42739 					duk_fb_sprintf(&fb, fmtbuf, arg);
42740 				} else if (ch == DUK_ASC_LC_U && got_long) {
42741 					/* %lu */
42742 					unsigned long arg = va_arg(ap, unsigned long);
42743 					duk_fb_sprintf(&fb, fmtbuf, arg);
42744 				} else if (ch == DUK_ASC_LC_U) {
42745 					/* %u; only 16 bits are guaranteed */
42746 					unsigned int arg = va_arg(ap, unsigned int);
42747 					duk_fb_sprintf(&fb, fmtbuf, arg);
42748 				} else if (ch == DUK_ASC_LC_X && got_long) {
42749 					/* %lx */
42750 					unsigned long arg = va_arg(ap, unsigned long);
42751 					duk_fb_sprintf(&fb, fmtbuf, arg);
42752 				} else if (ch == DUK_ASC_LC_X) {
42753 					/* %x; only 16 bits are guaranteed */
42754 					unsigned int arg = va_arg(ap, unsigned int);
42755 					duk_fb_sprintf(&fb, fmtbuf, arg);
42756 				} else if (ch == DUK_ASC_LC_S) {
42757 					/* %s */
42758 					const char *arg = va_arg(ap, const char *);
42759 					if (arg == NULL) {
42760 						/* '%s' and NULL is not portable, so special case
42761 						 * it for debug printing.
42762 						 */
42763 						duk_fb_sprintf(&fb, "NULL");
42764 					} else {
42765 						duk_fb_sprintf(&fb, fmtbuf, arg);
42766 					}
42767 				} else if (ch == DUK_ASC_LC_P) {
42768 					/* %p */
42769 					void *arg = va_arg(ap, void *);
42770 					if (arg == NULL) {
42771 						/* '%p' and NULL is portable, but special case it
42772 						 * anyway to get a standard NULL marker in logs.
42773 						 */
42774 						duk_fb_sprintf(&fb, "NULL");
42775 					} else {
42776 						duk_fb_sprintf(&fb, fmtbuf, arg);
42777 					}
42778 				} else if (ch == DUK_ASC_LC_C) {
42779 					/* '%c', passed concretely as int */
42780 					int arg = va_arg(ap, int);
42781 					duk_fb_sprintf(&fb, fmtbuf, arg);
42782 				} else {
42783 					/* Should not happen. */
42784 					duk_fb_sprintf(&fb, "INVALID-FORMAT(%s)", (const char *) fmtbuf);
42785 				}
42786 				break;
42787 			} else {
42788 				/* ignore */
42789 			}
42790 		}
42791 	}
42792 	goto done;
42793 
42794  format_error:
42795 	duk_fb_put_cstring(&fb, "FMTERR");
42796 	/* fall through */
42797 
42798  done:
42799 	retval = (duk_int_t) fb.offset;
42800 	duk_fb_put_byte(&fb, (duk_uint8_t) 0);
42801 
42802 	/* return total chars written excluding terminator */
42803 	return retval;
42804 }
42805 
42806 #if 0  /*unused*/
42807 DUK_INTERNAL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...) {
42808 	duk_int_t retval;
42809 	va_list ap;
42810 	va_start(ap, format);
42811 	retval = duk_debug_vsnprintf(str, size, format, ap);
42812 	va_end(ap);
42813 	return retval;
42814 }
42815 #endif
42816 
42817 /* Formatting function pointers is tricky: there is no standard pointer for
42818  * function pointers and the size of a function pointer may depend on the
42819  * specific pointer type.  This helper formats a function pointer based on
42820  * its memory layout to get something useful on most platforms.
42821  */
42822 DUK_INTERNAL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size) {
42823 	duk_size_t i;
42824 	duk_uint8_t *p = (duk_uint8_t *) buf;
42825 	duk_uint8_t *p_end = (duk_uint8_t *) (buf + buf_size - 1);
42826 
42827 	DUK_ASSERT(buf != NULL);
42828 	duk_memzero(buf, buf_size);
42829 
42830 	for (i = 0; i < fptr_size; i++) {
42831 		duk_int_t left = (duk_int_t) (p_end - p);
42832 		duk_uint8_t ch;
42833 		if (left <= 0) {
42834 			break;
42835 		}
42836 
42837 		/* Quite approximate but should be useful for little and big endian. */
42838 #if defined(DUK_USE_INTEGER_BE)
42839 		ch = fptr[i];
42840 #else
42841 		ch = fptr[fptr_size - 1 - i];
42842 #endif
42843 		p += DUK_SNPRINTF((char *) p, (duk_size_t) left, "%02lx", (unsigned long) ch);
42844 	}
42845 }
42846 
42847 #endif  /* DUK_USE_DEBUG */
42848 
42849 /* automatic undefs */
42850 #undef DUK__ALLOWED_STANDARD_SPECIFIERS
42851 #undef DUK__COMMA
42852 #undef DUK__DEEP_DEPTH_LIMIT
42853 #undef DUK__LOOP_STACK_DEPTH
42854 #undef DUK__MAX_FORMAT_TAG_LENGTH
42855 #line 1 "duk_debugger.c"
42856 /*
42857  *  Duktape debugger
42858  */
42859 
42860 /* #include duk_internal.h -> already included */
42861 
42862 #if defined(DUK_USE_DEBUGGER_SUPPORT)
42863 
42864 /*
42865  *  Assert helpers
42866  */
42867 
42868 #if defined(DUK_USE_ASSERTIONS)
42869 #define DUK__DBG_TPORT_ENTER() do { \
42870 		DUK_ASSERT(heap->dbg_calling_transport == 0); \
42871 		heap->dbg_calling_transport = 1; \
42872 	} while (0)
42873 #define DUK__DBG_TPORT_EXIT() do { \
42874 		DUK_ASSERT(heap->dbg_calling_transport == 1); \
42875 		heap->dbg_calling_transport = 0; \
42876 	} while (0)
42877 #else
42878 #define DUK__DBG_TPORT_ENTER() do {} while (0)
42879 #define DUK__DBG_TPORT_EXIT() do {} while (0)
42880 #endif
42881 
42882 /*
42883  *  Helper structs
42884  */
42885 
42886 typedef union {
42887 	void *p;
42888 	duk_uint_t b[1];
42889 	/* Use b[] to access the size of the union, which is strictly not
42890 	 * correct.  Can't use fixed size unless there's feature detection
42891 	 * for pointer byte size.
42892 	 */
42893 } duk__ptr_union;
42894 
42895 /*
42896  *  Detach handling
42897  */
42898 
42899 #define DUK__SET_CONN_BROKEN(thr,reason) do { \
42900 		/* For now shared handler is fine. */ \
42901 		duk__debug_do_detach1((thr)->heap, (reason)); \
42902 	} while (0)
42903 
42904 DUK_LOCAL void duk__debug_do_detach1(duk_heap *heap, duk_int_t reason) {
42905 	/* Can be called multiple times with no harm.  Mark the transport
42906 	 * bad (dbg_read_cb == NULL) and clear state except for the detached
42907 	 * callback and the udata field.  The detached callback is delayed
42908 	 * to the message loop so that it can be called between messages;
42909 	 * this avoids corner cases related to immediate debugger reattach
42910 	 * inside the detached callback.
42911 	 */
42912 
42913 	if (heap->dbg_detaching) {
42914 		DUK_D(DUK_DPRINT("debugger already detaching, ignore detach1"));
42915 		return;
42916 	}
42917 
42918 	DUK_D(DUK_DPRINT("debugger transport detaching, marking transport broken"));
42919 
42920 	heap->dbg_detaching = 1;  /* prevent multiple in-progress detaches */
42921 
42922 	if (heap->dbg_write_cb != NULL) {
42923 		duk_hthread *thr;
42924 
42925 		thr = heap->heap_thread;
42926 		DUK_ASSERT(thr != NULL);
42927 
42928 		duk_debug_write_notify(thr, DUK_DBG_CMD_DETACHING);
42929 		duk_debug_write_int(thr, reason);
42930 		duk_debug_write_eom(thr);
42931 	}
42932 
42933 	heap->dbg_read_cb = NULL;
42934 	heap->dbg_write_cb = NULL;
42935 	heap->dbg_peek_cb = NULL;
42936 	heap->dbg_read_flush_cb = NULL;
42937 	heap->dbg_write_flush_cb = NULL;
42938 	heap->dbg_request_cb = NULL;
42939 	/* heap->dbg_detached_cb: keep */
42940 	/* heap->dbg_udata: keep */
42941 	/* heap->dbg_processing: keep on purpose to avoid debugger re-entry in detaching state */
42942 	heap->dbg_state_dirty = 0;
42943 	heap->dbg_force_restart = 0;
42944 	heap->dbg_pause_flags = 0;
42945 	heap->dbg_pause_act = NULL;
42946 	heap->dbg_pause_startline = 0;
42947 	heap->dbg_have_next_byte = 0;
42948 	duk_debug_clear_paused(heap);  /* XXX: some overlap with field inits above */
42949 	heap->dbg_state_dirty = 0;     /* XXX: clear_paused sets dirty; rework? */
42950 
42951 	/* Ensure there are no stale active breakpoint pointers.
42952 	 * Breakpoint list is currently kept - we could empty it
42953 	 * here but we'd need to handle refcounts correctly, and
42954 	 * we'd need a 'thr' reference for that.
42955 	 *
42956 	 * XXX: clear breakpoint on either attach or detach?
42957 	 */
42958 	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
42959 }
42960 
42961 DUK_LOCAL void duk__debug_do_detach2(duk_heap *heap) {
42962 	duk_debug_detached_function detached_cb;
42963 	void *detached_udata;
42964 	duk_hthread *thr;
42965 
42966 	thr = heap->heap_thread;
42967 	if (thr == NULL) {
42968 		DUK_ASSERT(heap->dbg_detached_cb == NULL);
42969 		return;
42970 	}
42971 
42972 	/* Safe to call multiple times. */
42973 
42974 	detached_cb = heap->dbg_detached_cb;
42975 	detached_udata = heap->dbg_udata;
42976 	heap->dbg_detached_cb = NULL;
42977 	heap->dbg_udata = NULL;
42978 
42979 	if (detached_cb) {
42980 		/* Careful here: state must be wiped before the call
42981 		 * so that we can cleanly handle a re-attach from
42982 		 * inside the callback.
42983 		 */
42984 		DUK_D(DUK_DPRINT("detached during message loop, delayed call to detached_cb"));
42985 		detached_cb(thr, detached_udata);
42986 	}
42987 
42988 	heap->dbg_detaching = 0;
42989 }
42990 
42991 DUK_INTERNAL void duk_debug_do_detach(duk_heap *heap) {
42992 	duk__debug_do_detach1(heap, 0);
42993 	duk__debug_do_detach2(heap);
42994 }
42995 
42996 /* Called on a read/write error: NULL all callbacks except the detached
42997  * callback so that we never accidentally call them after a read/write
42998  * error has been indicated.  This is especially important for the transport
42999  * I/O callbacks to fulfill guaranteed callback semantics.
43000  */
43001 DUK_LOCAL void duk__debug_null_most_callbacks(duk_hthread *thr) {
43002 	duk_heap *heap;
43003 
43004 	DUK_ASSERT(thr != NULL);
43005 
43006 	heap = thr->heap;
43007 	DUK_D(DUK_DPRINT("transport read/write error, NULL all callbacks expected detached"));
43008 	heap->dbg_read_cb = NULL;
43009 	heap->dbg_write_cb = NULL;  /* this is especially critical to avoid another write call in detach1() */
43010 	heap->dbg_peek_cb = NULL;
43011 	heap->dbg_read_flush_cb = NULL;
43012 	heap->dbg_write_flush_cb = NULL;
43013 	heap->dbg_request_cb = NULL;
43014 	/* keep heap->dbg_detached_cb */
43015 }
43016 
43017 /*
43018  *  Pause handling
43019  */
43020 
43021 DUK_LOCAL void duk__debug_set_pause_state(duk_hthread *thr, duk_heap *heap, duk_small_uint_t pause_flags) {
43022 	duk_uint_fast32_t line;
43023 
43024 	line = duk_debug_curr_line(thr);
43025 	if (line == 0) {
43026 		/* No line info for current function. */
43027 		duk_small_uint_t updated_flags;
43028 
43029 		updated_flags = pause_flags & ~(DUK_PAUSE_FLAG_LINE_CHANGE);
43030 		DUK_D(DUK_DPRINT("no line info for current activation, disable line-based pause flags: 0x%08lx -> 0x%08lx",
43031 		                 (long) pause_flags, (long) updated_flags));
43032 		pause_flags = updated_flags;
43033 	}
43034 
43035 	heap->dbg_pause_flags = pause_flags;
43036 	heap->dbg_pause_act = thr->callstack_curr;
43037 	heap->dbg_pause_startline = (duk_uint32_t) line;
43038 	heap->dbg_state_dirty = 1;
43039 
43040 	DUK_D(DUK_DPRINT("set state for automatic pause triggers, flags=0x%08lx, act=%p, startline=%ld",
43041 	                 (long) heap->dbg_pause_flags, (void *) heap->dbg_pause_act,
43042 	                 (long) heap->dbg_pause_startline));
43043 }
43044 
43045 /*
43046  *  Debug connection peek and flush primitives
43047  */
43048 
43049 DUK_INTERNAL duk_bool_t duk_debug_read_peek(duk_hthread *thr) {
43050 	duk_heap *heap;
43051 	duk_bool_t ret;
43052 
43053 	DUK_ASSERT(thr != NULL);
43054 	heap = thr->heap;
43055 	DUK_ASSERT(heap != NULL);
43056 
43057 	if (heap->dbg_read_cb == NULL) {
43058 		DUK_D(DUK_DPRINT("attempt to peek in detached state, return zero (= no data)"));
43059 		return 0;
43060 	}
43061 	if (heap->dbg_peek_cb == NULL) {
43062 		DUK_DD(DUK_DDPRINT("no peek callback, return zero (= no data)"));
43063 		return 0;
43064 	}
43065 
43066 	DUK__DBG_TPORT_ENTER();
43067 	ret = (duk_bool_t) (heap->dbg_peek_cb(heap->dbg_udata) > 0);
43068 	DUK__DBG_TPORT_EXIT();
43069 	return ret;
43070 }
43071 
43072 DUK_INTERNAL void duk_debug_read_flush(duk_hthread *thr) {
43073 	duk_heap *heap;
43074 
43075 	DUK_ASSERT(thr != NULL);
43076 	heap = thr->heap;
43077 	DUK_ASSERT(heap != NULL);
43078 
43079 	if (heap->dbg_read_cb == NULL) {
43080 		DUK_D(DUK_DPRINT("attempt to read flush in detached state, ignore"));
43081 		return;
43082 	}
43083 	if (heap->dbg_read_flush_cb == NULL) {
43084 		DUK_DD(DUK_DDPRINT("no read flush callback, ignore"));
43085 		return;
43086 	}
43087 
43088 	DUK__DBG_TPORT_ENTER();
43089 	heap->dbg_read_flush_cb(heap->dbg_udata);
43090 	DUK__DBG_TPORT_EXIT();
43091 }
43092 
43093 DUK_INTERNAL void duk_debug_write_flush(duk_hthread *thr) {
43094 	duk_heap *heap;
43095 
43096 	DUK_ASSERT(thr != NULL);
43097 	heap = thr->heap;
43098 	DUK_ASSERT(heap != NULL);
43099 
43100 	if (heap->dbg_read_cb == NULL) {
43101 		DUK_D(DUK_DPRINT("attempt to write flush in detached state, ignore"));
43102 		return;
43103 	}
43104 	if (heap->dbg_write_flush_cb == NULL) {
43105 		DUK_DD(DUK_DDPRINT("no write flush callback, ignore"));
43106 		return;
43107 	}
43108 
43109 	DUK__DBG_TPORT_ENTER();
43110 	heap->dbg_write_flush_cb(heap->dbg_udata);
43111 	DUK__DBG_TPORT_EXIT();
43112 }
43113 
43114 /*
43115  *  Debug connection skip primitives
43116  */
43117 
43118 /* Skip fully. */
43119 DUK_INTERNAL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length) {
43120 	duk_uint8_t dummy[64];
43121 	duk_size_t now;
43122 
43123 	DUK_ASSERT(thr != NULL);
43124 
43125 	while (length > 0) {
43126 		now = (length > sizeof(dummy) ? sizeof(dummy) : length);
43127 		duk_debug_read_bytes(thr, dummy, now);
43128 		length -= now;
43129 	}
43130 }
43131 
43132 DUK_INTERNAL void duk_debug_skip_byte(duk_hthread *thr) {
43133 	DUK_ASSERT(thr != NULL);
43134 
43135 	(void) duk_debug_read_byte(thr);
43136 }
43137 
43138 /*
43139  *  Debug connection read primitives
43140  */
43141 
43142 /* Peek ahead in the stream one byte. */
43143 DUK_INTERNAL uint8_t duk_debug_peek_byte(duk_hthread *thr) {
43144 	/* It is important not to call this if the last byte read was an EOM.
43145 	 * Reading ahead in this scenario would cause unnecessary blocking if
43146 	 * another message is not available.
43147 	 */
43148 
43149 	duk_uint8_t x;
43150 
43151 	x = duk_debug_read_byte(thr);
43152 	thr->heap->dbg_have_next_byte = 1;
43153 	thr->heap->dbg_next_byte = x;
43154 	return x;
43155 }
43156 
43157 /* Read fully. */
43158 DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length) {
43159 	duk_heap *heap;
43160 	duk_uint8_t *p;
43161 	duk_size_t left;
43162 	duk_size_t got;
43163 
43164 	DUK_ASSERT(thr != NULL);
43165 	heap = thr->heap;
43166 	DUK_ASSERT(heap != NULL);
43167 	DUK_ASSERT(data != NULL);
43168 
43169 	if (heap->dbg_read_cb == NULL) {
43170 		DUK_D(DUK_DPRINT("attempt to read %ld bytes in detached state, return zero data", (long) length));
43171 		goto fail;
43172 	}
43173 
43174 	/* NOTE: length may be zero */
43175 	p = data;
43176 	if (length >= 1 && heap->dbg_have_next_byte) {
43177 		heap->dbg_have_next_byte = 0;
43178 		*p++ = heap->dbg_next_byte;
43179 	}
43180 	for (;;) {
43181 		left = (duk_size_t) ((data + length) - p);
43182 		if (left == 0) {
43183 			break;
43184 		}
43185 		DUK_ASSERT(heap->dbg_read_cb != NULL);
43186 		DUK_ASSERT(left >= 1);
43187 #if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
43188 		left = 1;
43189 #endif
43190 		DUK__DBG_TPORT_ENTER();
43191 		got = heap->dbg_read_cb(heap->dbg_udata, (char *) p, left);
43192 		DUK__DBG_TPORT_EXIT();
43193 
43194 		if (got == 0 || got > left) {
43195 			DUK_D(DUK_DPRINT("connection error during read, return zero data"));
43196 			duk__debug_null_most_callbacks(thr);  /* avoid calling write callback in detach1() */
43197 			DUK__SET_CONN_BROKEN(thr, 1);
43198 			goto fail;
43199 		}
43200 		p += got;
43201 	}
43202 	return;
43203 
43204  fail:
43205 	duk_memzero((void *) data, (size_t) length);
43206 }
43207 
43208 DUK_INTERNAL duk_uint8_t duk_debug_read_byte(duk_hthread *thr) {
43209 	duk_uint8_t x;
43210 
43211 	x = 0;  /* just in case callback is broken and won't write 'x' */
43212 	duk_debug_read_bytes(thr, &x, 1);
43213 	return x;
43214 }
43215 
43216 DUK_LOCAL duk_uint32_t duk__debug_read_uint32_raw(duk_hthread *thr) {
43217 	duk_uint8_t buf[4];
43218 
43219 	DUK_ASSERT(thr != NULL);
43220 
43221 	duk_debug_read_bytes(thr, buf, 4);
43222 	return ((duk_uint32_t) buf[0] << 24) |
43223 	       ((duk_uint32_t) buf[1] << 16) |
43224 	       ((duk_uint32_t) buf[2] << 8) |
43225 	       (duk_uint32_t) buf[3];
43226 }
43227 
43228 DUK_LOCAL duk_int32_t duk__debug_read_int32_raw(duk_hthread *thr) {
43229 	return (duk_int32_t) duk__debug_read_uint32_raw(thr);
43230 }
43231 
43232 DUK_LOCAL duk_uint16_t duk__debug_read_uint16_raw(duk_hthread *thr) {
43233 	duk_uint8_t buf[2];
43234 
43235 	DUK_ASSERT(thr != NULL);
43236 
43237 	duk_debug_read_bytes(thr, buf, 2);
43238 	return ((duk_uint16_t) buf[0] << 8) |
43239 	       (duk_uint16_t) buf[1];
43240 }
43241 
43242 DUK_INTERNAL duk_int32_t duk_debug_read_int(duk_hthread *thr) {
43243 	duk_small_uint_t x;
43244 	duk_small_uint_t t;
43245 
43246 	DUK_ASSERT(thr != NULL);
43247 
43248 	x = duk_debug_read_byte(thr);
43249 	if (x >= 0xc0) {
43250 		t = duk_debug_read_byte(thr);
43251 		return (duk_int32_t) (((x - 0xc0) << 8) + t);
43252 	} else if (x >= 0x80) {
43253 		return (duk_int32_t) (x - 0x80);
43254 	} else if (x == DUK_DBG_IB_INT4) {
43255 		return (duk_int32_t) duk__debug_read_uint32_raw(thr);
43256 	}
43257 
43258 	DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
43259 	DUK__SET_CONN_BROKEN(thr, 1);
43260 	return 0;
43261 }
43262 
43263 DUK_LOCAL duk_hstring *duk__debug_read_hstring_raw(duk_hthread *thr, duk_uint32_t len) {
43264 	duk_uint8_t buf[31];
43265 	duk_uint8_t *p;
43266 
43267 	if (len <= sizeof(buf)) {
43268 		duk_debug_read_bytes(thr, buf, (duk_size_t) len);
43269 		duk_push_lstring(thr, (const char *) buf, (duk_size_t) len);
43270 	} else {
43271 		p = (duk_uint8_t *) duk_push_fixed_buffer(thr, (duk_size_t) len);  /* zero for paranoia */
43272 		DUK_ASSERT(p != NULL);
43273 		duk_debug_read_bytes(thr, p, (duk_size_t) len);
43274 		(void) duk_buffer_to_string(thr, -1);  /* Safety relies on debug client, which is OK. */
43275 	}
43276 
43277 	return duk_require_hstring(thr, -1);
43278 }
43279 
43280 DUK_INTERNAL duk_hstring *duk_debug_read_hstring(duk_hthread *thr) {
43281 	duk_small_uint_t x;
43282 	duk_uint32_t len;
43283 
43284 	DUK_ASSERT(thr != NULL);
43285 
43286 	x = duk_debug_read_byte(thr);
43287 	if (x >= 0x60 && x <= 0x7f) {
43288 		/* For short strings, use a fixed temp buffer. */
43289 		len = (duk_uint32_t) (x - 0x60);
43290 	} else if (x == DUK_DBG_IB_STR2) {
43291 		len = (duk_uint32_t) duk__debug_read_uint16_raw(thr);
43292 	} else if (x == DUK_DBG_IB_STR4) {
43293 		len = (duk_uint32_t) duk__debug_read_uint32_raw(thr);
43294 	} else {
43295 		goto fail;
43296 	}
43297 
43298 	return duk__debug_read_hstring_raw(thr, len);
43299 
43300  fail:
43301 	DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
43302 	DUK__SET_CONN_BROKEN(thr, 1);
43303 	duk_push_hstring_empty(thr);  /* always push some string */
43304 	return duk_require_hstring(thr, -1);
43305 }
43306 
43307 DUK_LOCAL duk_hbuffer *duk__debug_read_hbuffer_raw(duk_hthread *thr, duk_uint32_t len) {
43308 	duk_uint8_t *p;
43309 
43310 	p = (duk_uint8_t *) duk_push_fixed_buffer(thr, (duk_size_t) len);  /* zero for paranoia */
43311 	DUK_ASSERT(p != NULL);
43312 	duk_debug_read_bytes(thr, p, (duk_size_t) len);
43313 
43314 	return duk_require_hbuffer(thr, -1);
43315 }
43316 
43317 DUK_LOCAL void *duk__debug_read_pointer_raw(duk_hthread *thr) {
43318 	duk_small_uint_t x;
43319 	duk__ptr_union pu;
43320 
43321 	DUK_ASSERT(thr != NULL);
43322 
43323 	x = duk_debug_read_byte(thr);
43324 	if (x != sizeof(pu)) {
43325 		goto fail;
43326 	}
43327 	duk_debug_read_bytes(thr, (duk_uint8_t *) &pu.p, sizeof(pu));
43328 #if defined(DUK_USE_INTEGER_LE)
43329 	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
43330 #endif
43331 	return (void *) pu.p;
43332 
43333  fail:
43334 	DUK_D(DUK_DPRINT("debug connection error: failed to decode pointer"));
43335 	DUK__SET_CONN_BROKEN(thr, 1);
43336 	return (void *) NULL;
43337 }
43338 
43339 DUK_LOCAL duk_double_t duk__debug_read_double_raw(duk_hthread *thr) {
43340 	duk_double_union du;
43341 
43342 	DUK_ASSERT(sizeof(du.uc) == 8);
43343 	duk_debug_read_bytes(thr, (duk_uint8_t *) du.uc, sizeof(du.uc));
43344 	DUK_DBLUNION_DOUBLE_NTOH(&du);
43345 	return du.d;
43346 }
43347 
43348 #if 0
43349 DUK_INTERNAL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr) {
43350 	duk_small_uint_t x;
43351 
43352 	DUK_ASSERT(thr != NULL);
43353 
43354 	x = duk_debug_read_byte(thr);
43355 	if (x != DUK_DBG_IB_HEAPPTR) {
43356 		goto fail;
43357 	}
43358 
43359 	return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
43360 
43361  fail:
43362 	DUK_D(DUK_DPRINT("debug connection error: failed to decode heapptr"));
43363 	DUK__SET_CONN_BROKEN(thr, 1);
43364 	return NULL;
43365 }
43366 #endif
43367 
43368 DUK_INTERNAL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr) {
43369 	duk_small_uint_t x;
43370 
43371 	DUK_ASSERT(thr != NULL);
43372 
43373 	x = duk_debug_read_byte(thr);
43374 	switch (x) {
43375 	case DUK_DBG_IB_OBJECT:
43376 	case DUK_DBG_IB_POINTER:
43377 	case DUK_DBG_IB_HEAPPTR:
43378 		/* Accept any pointer-like value; for 'object' dvalue, read
43379 		 * and ignore the class number.
43380 		 */
43381 		if (x == DUK_DBG_IB_OBJECT) {
43382 			duk_debug_skip_byte(thr);
43383 		}
43384 		break;
43385 	default:
43386 		goto fail;
43387 	}
43388 
43389 	return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
43390 
43391  fail:
43392 	DUK_D(DUK_DPRINT("debug connection error: failed to decode any pointer (object, pointer, heapptr)"));
43393 	DUK__SET_CONN_BROKEN(thr, 1);
43394 	return NULL;
43395 }
43396 
43397 DUK_INTERNAL duk_tval *duk_debug_read_tval(duk_hthread *thr) {
43398 	duk_uint8_t x;
43399 	duk_uint_t t;
43400 	duk_uint32_t len;
43401 
43402 	DUK_ASSERT(thr != NULL);
43403 
43404 	x = duk_debug_read_byte(thr);
43405 
43406 	if (x >= 0xc0) {
43407 		t = (duk_uint_t) (x - 0xc0);
43408 		t = (t << 8) + duk_debug_read_byte(thr);
43409 		duk_push_uint(thr, (duk_uint_t) t);
43410 		goto return_ptr;
43411 	}
43412 	if (x >= 0x80) {
43413 		duk_push_uint(thr, (duk_uint_t) (x - 0x80));
43414 		goto return_ptr;
43415 	}
43416 	if (x >= 0x60) {
43417 		len = (duk_uint32_t) (x - 0x60);
43418 		duk__debug_read_hstring_raw(thr, len);
43419 		goto return_ptr;
43420 	}
43421 
43422 	switch (x) {
43423 	case DUK_DBG_IB_INT4: {
43424 		duk_int32_t i = duk__debug_read_int32_raw(thr);
43425 		duk_push_i32(thr, i);
43426 		break;
43427 	}
43428 	case DUK_DBG_IB_STR4: {
43429 		len = duk__debug_read_uint32_raw(thr);
43430 		duk__debug_read_hstring_raw(thr, len);
43431 		break;
43432 	}
43433 	case DUK_DBG_IB_STR2: {
43434 		len = duk__debug_read_uint16_raw(thr);
43435 		duk__debug_read_hstring_raw(thr, len);
43436 		break;
43437 	}
43438 	case DUK_DBG_IB_BUF4: {
43439 		len = duk__debug_read_uint32_raw(thr);
43440 		duk__debug_read_hbuffer_raw(thr, len);
43441 		break;
43442 	}
43443 	case DUK_DBG_IB_BUF2: {
43444 		len = duk__debug_read_uint16_raw(thr);
43445 		duk__debug_read_hbuffer_raw(thr, len);
43446 		break;
43447 	}
43448 	case DUK_DBG_IB_UNDEFINED: {
43449 		duk_push_undefined(thr);
43450 		break;
43451 	}
43452 	case DUK_DBG_IB_NULL: {
43453 		duk_push_null(thr);
43454 		break;
43455 	}
43456 	case DUK_DBG_IB_TRUE: {
43457 		duk_push_true(thr);
43458 		break;
43459 	}
43460 	case DUK_DBG_IB_FALSE: {
43461 		duk_push_false(thr);
43462 		break;
43463 	}
43464 	case DUK_DBG_IB_NUMBER: {
43465 		duk_double_t d;
43466 		d = duk__debug_read_double_raw(thr);
43467 		duk_push_number(thr, d);
43468 		break;
43469 	}
43470 	case DUK_DBG_IB_OBJECT: {
43471 		duk_heaphdr *h;
43472 		duk_debug_skip_byte(thr);
43473 		h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
43474 		duk_push_heapptr(thr, (void *) h);
43475 		break;
43476 	}
43477 	case DUK_DBG_IB_POINTER: {
43478 		void *ptr;
43479 		ptr = duk__debug_read_pointer_raw(thr);
43480 		duk_push_pointer(thr, ptr);
43481 		break;
43482 	}
43483 	case DUK_DBG_IB_LIGHTFUNC: {
43484 		/* XXX: Not needed for now, so not implemented.  Note that
43485 		 * function pointers may have different size/layout than
43486 		 * a void pointer.
43487 		 */
43488 		DUK_D(DUK_DPRINT("reading lightfunc values unimplemented"));
43489 		goto fail;
43490 	}
43491 	case DUK_DBG_IB_HEAPPTR: {
43492 		duk_heaphdr *h;
43493 		h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
43494 		duk_push_heapptr(thr, (void *) h);
43495 		break;
43496 	}
43497 	case DUK_DBG_IB_UNUSED:  /* unused: not accepted in inbound messages */
43498 	default:
43499 		goto fail;
43500 	}
43501 
43502  return_ptr:
43503 	return DUK_GET_TVAL_NEGIDX(thr, -1);
43504 
43505  fail:
43506 	DUK_D(DUK_DPRINT("debug connection error: failed to decode tval"));
43507 	DUK__SET_CONN_BROKEN(thr, 1);
43508 	return NULL;
43509 }
43510 
43511 /*
43512  *  Debug connection write primitives
43513  */
43514 
43515 /* Write fully. */
43516 DUK_INTERNAL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length) {
43517 	duk_heap *heap;
43518 	const duk_uint8_t *p;
43519 	duk_size_t left;
43520 	duk_size_t got;
43521 
43522 	DUK_ASSERT(thr != NULL);
43523 	DUK_ASSERT(length == 0 || data != NULL);
43524 	heap = thr->heap;
43525 	DUK_ASSERT(heap != NULL);
43526 
43527 	if (heap->dbg_write_cb == NULL) {
43528 		DUK_D(DUK_DPRINT("attempt to write %ld bytes in detached state, ignore", (long) length));
43529 		return;
43530 	}
43531 	if (length == 0) {
43532 		/* Avoid doing an actual write callback with length == 0,
43533 		 * because that's reserved for a write flush.
43534 		 */
43535 		return;
43536 	}
43537 	DUK_ASSERT(data != NULL);
43538 
43539 	p = data;
43540 	for (;;) {
43541 		left = (duk_size_t) ((data + length) - p);
43542 		if (left == 0) {
43543 			break;
43544 		}
43545 		DUK_ASSERT(heap->dbg_write_cb != NULL);
43546 		DUK_ASSERT(left >= 1);
43547 #if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
43548 		left = 1;
43549 #endif
43550 		DUK__DBG_TPORT_ENTER();
43551 		got = heap->dbg_write_cb(heap->dbg_udata, (const char *) p, left);
43552 		DUK__DBG_TPORT_EXIT();
43553 
43554 		if (got == 0 || got > left) {
43555 			duk__debug_null_most_callbacks(thr);  /* avoid calling write callback in detach1() */
43556 			DUK_D(DUK_DPRINT("connection error during write"));
43557 			DUK__SET_CONN_BROKEN(thr, 1);
43558 			return;
43559 		}
43560 		p += got;
43561 	}
43562 }
43563 
43564 DUK_INTERNAL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x) {
43565 	duk_debug_write_bytes(thr, (const duk_uint8_t *) &x, 1);
43566 }
43567 
43568 DUK_INTERNAL void duk_debug_write_unused(duk_hthread *thr) {
43569 	duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
43570 }
43571 
43572 DUK_INTERNAL void duk_debug_write_undefined(duk_hthread *thr) {
43573 	duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
43574 }
43575 
43576 #if defined(DUK_USE_DEBUGGER_INSPECT)
43577 DUK_INTERNAL void duk_debug_write_null(duk_hthread *thr) {
43578 	duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
43579 }
43580 #endif
43581 
43582 DUK_INTERNAL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val) {
43583 	duk_debug_write_byte(thr, val ? DUK_DBG_IB_TRUE : DUK_DBG_IB_FALSE);
43584 }
43585 
43586 /* Write signed 32-bit integer. */
43587 DUK_INTERNAL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x) {
43588 	duk_uint8_t buf[5];
43589 	duk_size_t len;
43590 
43591 	DUK_ASSERT(thr != NULL);
43592 
43593 	if (x >= 0 && x <= 0x3fL) {
43594 		buf[0] = (duk_uint8_t) (0x80 + x);
43595 		len = 1;
43596 	} else if (x >= 0 && x <= 0x3fffL) {
43597 		buf[0] = (duk_uint8_t) (0xc0 + (x >> 8));
43598 		buf[1] = (duk_uint8_t) (x & 0xff);
43599 		len = 2;
43600 	} else {
43601 		/* Signed integers always map to 4 bytes now. */
43602 		buf[0] = (duk_uint8_t) DUK_DBG_IB_INT4;
43603 		buf[1] = (duk_uint8_t) ((x >> 24) & 0xff);
43604 		buf[2] = (duk_uint8_t) ((x >> 16) & 0xff);
43605 		buf[3] = (duk_uint8_t) ((x >> 8) & 0xff);
43606 		buf[4] = (duk_uint8_t) (x & 0xff);
43607 		len = 5;
43608 	}
43609 	duk_debug_write_bytes(thr, buf, len);
43610 }
43611 
43612 /* Write unsigned 32-bit integer. */
43613 DUK_INTERNAL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x) {
43614 	/* The debugger protocol doesn't support a plain integer encoding for
43615 	 * the full 32-bit unsigned range (only 32-bit signed).  For now,
43616 	 * unsigned 32-bit values simply written as signed ones.  This is not
43617 	 * a concrete issue except for 32-bit heaphdr fields.  Proper solutions
43618 	 * would be to (a) write such integers as IEEE doubles or (b) add an
43619 	 * unsigned 32-bit dvalue.
43620 	 */
43621 	if (x >= 0x80000000UL) {
43622 		DUK_D(DUK_DPRINT("writing unsigned integer 0x%08lx as signed integer",
43623 		                 (long) x));
43624 	}
43625 	duk_debug_write_int(thr, (duk_int32_t) x);
43626 }
43627 
43628 DUK_INTERNAL void duk_debug_write_strbuf(duk_hthread *thr, const char *data, duk_size_t length, duk_uint8_t marker_base) {
43629 	duk_uint8_t buf[5];
43630 	duk_size_t buflen;
43631 
43632 	DUK_ASSERT(thr != NULL);
43633 	DUK_ASSERT(length == 0 || data != NULL);
43634 
43635 	if (length <= 0x1fUL && marker_base == DUK_DBG_IB_STR4) {
43636 		/* For strings, special form for short lengths. */
43637 		buf[0] = (duk_uint8_t) (0x60 + length);
43638 		buflen = 1;
43639 	} else if (length <= 0xffffUL) {
43640 		buf[0] = (duk_uint8_t) (marker_base + 1);
43641 		buf[1] = (duk_uint8_t) (length >> 8);
43642 		buf[2] = (duk_uint8_t) (length & 0xff);
43643 		buflen = 3;
43644 	} else {
43645 		buf[0] = (duk_uint8_t) marker_base;
43646 		buf[1] = (duk_uint8_t) (length >> 24);
43647 		buf[2] = (duk_uint8_t) ((length >> 16) & 0xff);
43648 		buf[3] = (duk_uint8_t) ((length >> 8) & 0xff);
43649 		buf[4] = (duk_uint8_t) (length & 0xff);
43650 		buflen = 5;
43651 	}
43652 
43653 	duk_debug_write_bytes(thr, (const duk_uint8_t *) buf, buflen);
43654 	duk_debug_write_bytes(thr, (const duk_uint8_t *) data, length);
43655 }
43656 
43657 DUK_INTERNAL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length) {
43658 	duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_STR4);
43659 }
43660 
43661 DUK_INTERNAL void duk_debug_write_cstring(duk_hthread *thr, const char *data) {
43662 	DUK_ASSERT(thr != NULL);
43663 
43664 	duk_debug_write_string(thr,
43665 	                       data,
43666 	                       data ? DUK_STRLEN(data) : 0);
43667 }
43668 
43669 DUK_INTERNAL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h) {
43670 	DUK_ASSERT(thr != NULL);
43671 
43672 	/* XXX: differentiate null pointer from empty string? */
43673 	duk_debug_write_string(thr,
43674 	                       (h != NULL ? (const char *) DUK_HSTRING_GET_DATA(h) : NULL),
43675 	                       (h != NULL ? (duk_size_t) DUK_HSTRING_GET_BYTELEN(h) : 0));
43676 }
43677 
43678 DUK_LOCAL void duk__debug_write_hstring_safe_top(duk_hthread *thr) {
43679 	duk_debug_write_hstring(thr, duk_safe_to_hstring(thr, -1));
43680 }
43681 
43682 DUK_INTERNAL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length) {
43683 	duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_BUF4);
43684 }
43685 
43686 DUK_INTERNAL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h) {
43687 	DUK_ASSERT(thr != NULL);
43688 
43689 	duk_debug_write_buffer(thr,
43690 	                       (h != NULL ? (const char *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h) : NULL),
43691 	                       (h != NULL ? (duk_size_t) DUK_HBUFFER_GET_SIZE(h) : 0));
43692 }
43693 
43694 DUK_LOCAL void duk__debug_write_pointer_raw(duk_hthread *thr, void *ptr, duk_uint8_t ibyte) {
43695 	duk_uint8_t buf[2];
43696 	duk__ptr_union pu;
43697 
43698 	DUK_ASSERT(thr != NULL);
43699 	DUK_ASSERT(sizeof(ptr) >= 1 && sizeof(ptr) <= 16);
43700 	/* ptr may be NULL */
43701 
43702 	buf[0] = ibyte;
43703 	buf[1] = sizeof(pu);
43704 	duk_debug_write_bytes(thr, buf, 2);
43705 	pu.p = (void *) ptr;
43706 #if defined(DUK_USE_INTEGER_LE)
43707 	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
43708 #endif
43709 	duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
43710 }
43711 
43712 DUK_INTERNAL void duk_debug_write_pointer(duk_hthread *thr, void *ptr) {
43713 	duk__debug_write_pointer_raw(thr, ptr, DUK_DBG_IB_POINTER);
43714 }
43715 
43716 #if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
43717 DUK_INTERNAL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h) {
43718 	duk__debug_write_pointer_raw(thr, (void *) h, DUK_DBG_IB_HEAPPTR);
43719 }
43720 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP || DUK_USE_DEBUGGER_INSPECT */
43721 
43722 DUK_INTERNAL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj) {
43723 	duk_uint8_t buf[3];
43724 	duk__ptr_union pu;
43725 
43726 	DUK_ASSERT(thr != NULL);
43727 	DUK_ASSERT(sizeof(obj) >= 1 && sizeof(obj) <= 16);
43728 	DUK_ASSERT(obj != NULL);
43729 
43730 	buf[0] = DUK_DBG_IB_OBJECT;
43731 	buf[1] = (duk_uint8_t) DUK_HOBJECT_GET_CLASS_NUMBER(obj);
43732 	buf[2] = sizeof(pu);
43733 	duk_debug_write_bytes(thr, buf, 3);
43734 	pu.p = (void *) obj;
43735 #if defined(DUK_USE_INTEGER_LE)
43736 	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
43737 #endif
43738 	duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
43739 }
43740 
43741 DUK_INTERNAL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv) {
43742 	duk_c_function lf_func;
43743 	duk_small_uint_t lf_flags;
43744 	duk_uint8_t buf[4];
43745 	duk_double_union du1;
43746 	duk_double_union du2;
43747 	duk_int32_t i32;
43748 
43749 	DUK_ASSERT(thr != NULL);
43750 	DUK_ASSERT(tv != NULL);
43751 
43752 	switch (DUK_TVAL_GET_TAG(tv)) {
43753 	case DUK_TAG_UNDEFINED:
43754 		duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
43755 		break;
43756 	case DUK_TAG_UNUSED:
43757 		duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
43758 		break;
43759 	case DUK_TAG_NULL:
43760 		duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
43761 		break;
43762 	case DUK_TAG_BOOLEAN:
43763 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 ||
43764 		           DUK_TVAL_GET_BOOLEAN(tv) == 1);
43765 		duk_debug_write_boolean(thr, DUK_TVAL_GET_BOOLEAN(tv));
43766 		break;
43767 	case DUK_TAG_POINTER:
43768 		duk_debug_write_pointer(thr, (void *) DUK_TVAL_GET_POINTER(tv));
43769 		break;
43770 	case DUK_TAG_LIGHTFUNC:
43771 		DUK_TVAL_GET_LIGHTFUNC(tv, lf_func, lf_flags);
43772 		buf[0] = DUK_DBG_IB_LIGHTFUNC;
43773 		buf[1] = (duk_uint8_t) (lf_flags >> 8);
43774 		buf[2] = (duk_uint8_t) (lf_flags & 0xff);
43775 		buf[3] = sizeof(lf_func);
43776 		duk_debug_write_bytes(thr, buf, 4);
43777 		duk_debug_write_bytes(thr, (const duk_uint8_t *) &lf_func, sizeof(lf_func));
43778 		break;
43779 	case DUK_TAG_STRING:
43780 		duk_debug_write_hstring(thr, DUK_TVAL_GET_STRING(tv));
43781 		break;
43782 	case DUK_TAG_OBJECT:
43783 		duk_debug_write_hobject(thr, DUK_TVAL_GET_OBJECT(tv));
43784 		break;
43785 	case DUK_TAG_BUFFER:
43786 		duk_debug_write_hbuffer(thr, DUK_TVAL_GET_BUFFER(tv));
43787 		break;
43788 #if defined(DUK_USE_FASTINT)
43789 	case DUK_TAG_FASTINT:
43790 #endif
43791 	default:
43792 		/* Numbers are normalized to big (network) endian.  We can
43793 		 * (but are not required) to use integer dvalues when there's
43794 		 * no loss of precision.
43795 		 *
43796 		 * XXX: share check with other code; this check is slow but
43797 		 * reliable and doesn't require careful exponent/mantissa
43798 		 * mask tricks as in the fastint downgrade code.
43799 		 */
43800 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
43801 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
43802 		du1.d = DUK_TVAL_GET_NUMBER(tv);
43803 		i32 = (duk_int32_t) du1.d;
43804 		du2.d = (duk_double_t) i32;
43805 
43806 		DUK_DD(DUK_DDPRINT("i32=%ld du1=%02x%02x%02x%02x%02x%02x%02x%02x "
43807 		                   "du2=%02x%02x%02x%02x%02x%02x%02x%02x",
43808 		                   (long) i32,
43809 		                   (unsigned int) du1.uc[0], (unsigned int) du1.uc[1],
43810 		                   (unsigned int) du1.uc[2], (unsigned int) du1.uc[3],
43811 		                   (unsigned int) du1.uc[4], (unsigned int) du1.uc[5],
43812 		                   (unsigned int) du1.uc[6], (unsigned int) du1.uc[7],
43813 		                   (unsigned int) du2.uc[0], (unsigned int) du2.uc[1],
43814 		                   (unsigned int) du2.uc[2], (unsigned int) du2.uc[3],
43815 		                   (unsigned int) du2.uc[4], (unsigned int) du2.uc[5],
43816 		                   (unsigned int) du2.uc[6], (unsigned int) du2.uc[7]));
43817 
43818 		if (duk_memcmp((const void *) du1.uc, (const void *) du2.uc, sizeof(du1.uc)) == 0) {
43819 			duk_debug_write_int(thr, i32);
43820 		} else {
43821 			DUK_DBLUNION_DOUBLE_HTON(&du1);
43822 			duk_debug_write_byte(thr, DUK_DBG_IB_NUMBER);
43823 			duk_debug_write_bytes(thr, (const duk_uint8_t *) du1.uc, sizeof(du1.uc));
43824 		}
43825 	}
43826 }
43827 
43828 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
43829 /* Variant for writing duk_tvals so that any heap allocated values are
43830  * written out as tagged heap pointers.
43831  */
43832 DUK_LOCAL void duk__debug_write_tval_heapptr(duk_hthread *thr, duk_tval *tv) {
43833 	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
43834 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
43835 		duk_debug_write_heapptr(thr, h);
43836 	} else {
43837 		duk_debug_write_tval(thr, tv);
43838 	}
43839 }
43840 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
43841 
43842 /*
43843  *  Debug connection message write helpers
43844  */
43845 
43846 #if 0  /* unused */
43847 DUK_INTERNAL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command) {
43848 	duk_debug_write_byte(thr, DUK_DBG_IB_REQUEST);
43849 	duk_debug_write_int(thr, command);
43850 }
43851 #endif
43852 
43853 DUK_INTERNAL void duk_debug_write_reply(duk_hthread *thr) {
43854 	duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
43855 }
43856 
43857 DUK_INTERNAL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg) {
43858 	/* Allow NULL 'msg' */
43859 	duk_debug_write_byte(thr, DUK_DBG_IB_ERROR);
43860 	duk_debug_write_int(thr, (duk_int32_t) err_code);
43861 	duk_debug_write_cstring(thr, msg);
43862 	duk_debug_write_eom(thr);
43863 }
43864 
43865 DUK_INTERNAL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command) {
43866 	duk_debug_write_byte(thr, DUK_DBG_IB_NOTIFY);
43867 	duk_debug_write_int(thr, (duk_int32_t) command);
43868 }
43869 
43870 DUK_INTERNAL void duk_debug_write_eom(duk_hthread *thr) {
43871 	duk_debug_write_byte(thr, DUK_DBG_IB_EOM);
43872 
43873 	/* As an initial implementation, write flush after every EOM (and the
43874 	 * version identifier).  A better implementation would flush only when
43875 	 * Duktape is finished processing messages so that a flush only happens
43876 	 * after all outbound messages are finished on that occasion.
43877 	 */
43878 	duk_debug_write_flush(thr);
43879 }
43880 
43881 /*
43882  *  Status message and helpers
43883  */
43884 
43885 DUK_INTERNAL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr) {
43886 	duk_activation *act;
43887 	duk_uint_fast32_t line;
43888 	duk_uint_fast32_t pc;
43889 
43890 	act = thr->callstack_curr;
43891 	if (act == NULL) {
43892 		return 0;
43893 	}
43894 
43895 	/* We're conceptually between two opcodes; act->pc indicates the next
43896 	 * instruction to be executed.  This is usually the correct pc/line to
43897 	 * indicate in Status.  (For the 'debugger' statement this now reports
43898 	 * the pc/line after the debugger statement because the debugger opcode
43899 	 * has already been executed.)
43900 	 */
43901 
43902 	pc = duk_hthread_get_act_curr_pc(thr, act);
43903 
43904 	/* XXX: this should be optimized to be a raw query and avoid valstack
43905 	 * operations if possible.
43906 	 */
43907 	duk_push_tval(thr, &act->tv_func);
43908 	line = duk_hobject_pc2line_query(thr, -1, pc);
43909 	duk_pop(thr);
43910 	return line;
43911 }
43912 
43913 DUK_INTERNAL void duk_debug_send_status(duk_hthread *thr) {
43914 	duk_activation *act;
43915 
43916 	duk_debug_write_notify(thr, DUK_DBG_CMD_STATUS);
43917 	duk_debug_write_int(thr, (DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) ? 1 : 0));
43918 
43919 	act = thr->callstack_curr;
43920 	if (act == NULL) {
43921 		duk_debug_write_undefined(thr);
43922 		duk_debug_write_undefined(thr);
43923 		duk_debug_write_int(thr, 0);
43924 		duk_debug_write_int(thr, 0);
43925 	} else {
43926 		duk_push_tval(thr, &act->tv_func);
43927 		duk_get_prop_literal(thr, -1, "fileName");
43928 		duk__debug_write_hstring_safe_top(thr);
43929 		duk_get_prop_literal(thr, -2, "name");
43930 		duk__debug_write_hstring_safe_top(thr);
43931 		duk_pop_3(thr);
43932 		/* Report next pc/line to be executed. */
43933 		duk_debug_write_uint(thr, (duk_uint32_t) duk_debug_curr_line(thr));
43934 		duk_debug_write_uint(thr, (duk_uint32_t) duk_hthread_get_act_curr_pc(thr, act));
43935 	}
43936 
43937 	duk_debug_write_eom(thr);
43938 }
43939 
43940 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
43941 DUK_INTERNAL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal) {
43942 	/*
43943 	 *  NFY <int: 5> <int: fatal> <str: msg> <str: filename> <int: linenumber> EOM
43944 	 */
43945 
43946 	duk_activation *act;
43947 	duk_uint32_t pc;
43948 
43949 	DUK_ASSERT(thr->valstack_top > thr->valstack);  /* At least: ... [err] */
43950 
43951 	duk_debug_write_notify(thr, DUK_DBG_CMD_THROW);
43952 	duk_debug_write_int(thr, (duk_int32_t) fatal);
43953 
43954 	/* Report thrown value to client coerced to string */
43955 	duk_dup_top(thr);
43956 	duk__debug_write_hstring_safe_top(thr);
43957 	duk_pop(thr);
43958 
43959 	if (duk_is_error(thr, -1)) {
43960 		/* Error instance, use augmented error data directly */
43961 		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);
43962 		duk__debug_write_hstring_safe_top(thr);
43963 		duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_LINE_NUMBER);
43964 		duk_debug_write_uint(thr, duk_get_uint(thr, -1));
43965 		duk_pop_2(thr);
43966 	} else {
43967 		/* For anything other than an Error instance, we calculate the
43968 		 * error location directly from the current activation if one
43969 		 * exists.
43970 		 */
43971 		act = thr->callstack_curr;
43972 		if (act != NULL) {
43973 			duk_push_tval(thr, &act->tv_func);
43974 			duk_get_prop_literal(thr, -1, "fileName");
43975 			duk__debug_write_hstring_safe_top(thr);
43976 			pc = (duk_uint32_t) duk_hthread_get_act_prev_pc(thr, act);
43977 			duk_debug_write_uint(thr, (duk_uint32_t) duk_hobject_pc2line_query(thr, -2, pc));
43978 			duk_pop_2(thr);
43979 		} else {
43980 			/* Can happen if duk_throw() is called on an empty
43981 			 * callstack.
43982 			 */
43983 			duk_debug_write_cstring(thr, "");
43984 			duk_debug_write_uint(thr, 0);
43985 		}
43986 	}
43987 
43988 	duk_debug_write_eom(thr);
43989 }
43990 #endif  /* DUK_USE_DEBUGGER_THROW_NOTIFY */
43991 
43992 /*
43993  *  Debug message processing
43994  */
43995 
43996 /* Skip dvalue. */
43997 DUK_LOCAL duk_bool_t duk__debug_skip_dvalue(duk_hthread *thr) {
43998 	duk_uint8_t x;
43999 	duk_uint32_t len;
44000 
44001 	x = duk_debug_read_byte(thr);
44002 
44003 	if (x >= 0xc0) {
44004 		duk_debug_skip_byte(thr);
44005 		return 0;
44006 	}
44007 	if (x >= 0x80) {
44008 		return 0;
44009 	}
44010 	if (x >= 0x60) {
44011 		duk_debug_skip_bytes(thr, (duk_size_t) (x - 0x60));
44012 		return 0;
44013 	}
44014 	switch(x) {
44015 	case DUK_DBG_IB_EOM:
44016 		return 1;  /* Return 1: got EOM */
44017 	case DUK_DBG_IB_REQUEST:
44018 	case DUK_DBG_IB_REPLY:
44019 	case DUK_DBG_IB_ERROR:
44020 	case DUK_DBG_IB_NOTIFY:
44021 		break;
44022 	case DUK_DBG_IB_INT4:
44023 		(void) duk__debug_read_uint32_raw(thr);
44024 		break;
44025 	case DUK_DBG_IB_STR4:
44026 	case DUK_DBG_IB_BUF4:
44027 		len = duk__debug_read_uint32_raw(thr);
44028 		duk_debug_skip_bytes(thr, len);
44029 		break;
44030 	case DUK_DBG_IB_STR2:
44031 	case DUK_DBG_IB_BUF2:
44032 		len = duk__debug_read_uint16_raw(thr);
44033 		duk_debug_skip_bytes(thr, len);
44034 		break;
44035 	case DUK_DBG_IB_UNUSED:
44036 	case DUK_DBG_IB_UNDEFINED:
44037 	case DUK_DBG_IB_NULL:
44038 	case DUK_DBG_IB_TRUE:
44039 	case DUK_DBG_IB_FALSE:
44040 		break;
44041 	case DUK_DBG_IB_NUMBER:
44042 		duk_debug_skip_bytes(thr, 8);
44043 		break;
44044 	case DUK_DBG_IB_OBJECT:
44045 		duk_debug_skip_byte(thr);
44046 		len = duk_debug_read_byte(thr);
44047 		duk_debug_skip_bytes(thr, len);
44048 		break;
44049 	case DUK_DBG_IB_POINTER:
44050 	case DUK_DBG_IB_HEAPPTR:
44051 		len = duk_debug_read_byte(thr);
44052 		duk_debug_skip_bytes(thr, len);
44053 		break;
44054 	case DUK_DBG_IB_LIGHTFUNC:
44055 		duk_debug_skip_bytes(thr, 2);
44056 		len = duk_debug_read_byte(thr);
44057 		duk_debug_skip_bytes(thr, len);
44058 		break;
44059 	default:
44060 		goto fail;
44061 	}
44062 
44063 	return 0;
44064 
44065  fail:
44066 	DUK__SET_CONN_BROKEN(thr, 1);
44067 	return 1;  /* Pretend like we got EOM */
44068 }
44069 
44070 /* Skip dvalues to EOM. */
44071 DUK_LOCAL void duk__debug_skip_to_eom(duk_hthread *thr) {
44072 	for (;;) {
44073 		if (duk__debug_skip_dvalue(thr)) {
44074 			break;
44075 		}
44076 	}
44077 }
44078 
44079 /* Read and validate a call stack index.  If index is invalid, write out an
44080  * error message and return zero.
44081  */
44082 DUK_LOCAL duk_int32_t duk__debug_read_validate_csindex(duk_hthread *thr) {
44083 	duk_int32_t level;
44084 	level = duk_debug_read_int(thr);
44085 	if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
44086 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
44087 		return 0;  /* zero indicates failure */
44088 	}
44089 	return level;
44090 }
44091 
44092 /* Read a call stack index and lookup the corresponding duk_activation.
44093  * If index is invalid, write out an error message and return NULL.
44094  */
44095 DUK_LOCAL duk_activation *duk__debug_read_level_get_activation(duk_hthread *thr) {
44096 	duk_activation *act;
44097 	duk_int32_t level;
44098 
44099 	level = duk_debug_read_int(thr);
44100 	act = duk_hthread_get_activation_for_level(thr, level);
44101 	if (act == NULL) {
44102 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
44103 	}
44104 	return act;
44105 }
44106 
44107 /*
44108  *  Simple commands
44109  */
44110 
44111 DUK_LOCAL void duk__debug_handle_basic_info(duk_hthread *thr, duk_heap *heap) {
44112 	DUK_UNREF(heap);
44113 	DUK_D(DUK_DPRINT("debug command Version"));
44114 
44115 	duk_debug_write_reply(thr);
44116 	duk_debug_write_int(thr, DUK_VERSION);
44117 	duk_debug_write_cstring(thr, DUK_GIT_DESCRIBE);
44118 	duk_debug_write_cstring(thr, DUK_USE_TARGET_INFO);
44119 #if defined(DUK_USE_DOUBLE_LE)
44120 	duk_debug_write_int(thr, 1);
44121 #elif defined(DUK_USE_DOUBLE_ME)
44122 	duk_debug_write_int(thr, 2);
44123 #elif defined(DUK_USE_DOUBLE_BE)
44124 	duk_debug_write_int(thr, 3);
44125 #else
44126 	duk_debug_write_int(thr, 0);
44127 #endif
44128 	duk_debug_write_int(thr, (duk_int_t) sizeof(void *));
44129 	duk_debug_write_eom(thr);
44130 }
44131 
44132 DUK_LOCAL void duk__debug_handle_trigger_status(duk_hthread *thr, duk_heap *heap) {
44133 	DUK_UNREF(heap);
44134 	DUK_D(DUK_DPRINT("debug command TriggerStatus"));
44135 
44136 	duk_debug_write_reply(thr);
44137 	duk_debug_write_eom(thr);
44138 	heap->dbg_state_dirty = 1;
44139 }
44140 
44141 DUK_LOCAL void duk__debug_handle_pause(duk_hthread *thr, duk_heap *heap) {
44142 	DUK_D(DUK_DPRINT("debug command Pause"));
44143 	duk_debug_set_paused(heap);
44144 	duk_debug_write_reply(thr);
44145 	duk_debug_write_eom(thr);
44146 }
44147 
44148 DUK_LOCAL void duk__debug_handle_resume(duk_hthread *thr, duk_heap *heap) {
44149 	duk_small_uint_t pause_flags;
44150 
44151 	DUK_D(DUK_DPRINT("debug command Resume"));
44152 
44153 	duk_debug_clear_paused(heap);
44154 
44155 	pause_flags = 0;
44156 #if 0  /* manual testing */
44157 	pause_flags |= DUK_PAUSE_FLAG_ONE_OPCODE;
44158 	pause_flags |= DUK_PAUSE_FLAG_CAUGHT_ERROR;
44159 	pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
44160 #endif
44161 #if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
44162 	pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
44163 #endif
44164 
44165 	duk__debug_set_pause_state(thr, heap, pause_flags);
44166 
44167 	duk_debug_write_reply(thr);
44168 	duk_debug_write_eom(thr);
44169 }
44170 
44171 DUK_LOCAL void duk__debug_handle_step(duk_hthread *thr, duk_heap *heap, duk_int32_t cmd) {
44172 	duk_small_uint_t pause_flags;
44173 
44174 	DUK_D(DUK_DPRINT("debug command StepInto/StepOver/StepOut: %d", (int) cmd));
44175 
44176 	if (cmd == DUK_DBG_CMD_STEPINTO) {
44177 		pause_flags = DUK_PAUSE_FLAG_LINE_CHANGE |
44178 		              DUK_PAUSE_FLAG_FUNC_ENTRY |
44179 		              DUK_PAUSE_FLAG_FUNC_EXIT;
44180 	} else if (cmd == DUK_DBG_CMD_STEPOVER) {
44181 		pause_flags = DUK_PAUSE_FLAG_LINE_CHANGE |
44182 		              DUK_PAUSE_FLAG_FUNC_EXIT;
44183 	} else {
44184 		DUK_ASSERT(cmd == DUK_DBG_CMD_STEPOUT);
44185 		pause_flags = DUK_PAUSE_FLAG_FUNC_EXIT;
44186 	}
44187 #if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
44188 	pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
44189 #endif
44190 
44191 	/* If current activation doesn't have line information, line-based
44192 	 * pause flags are automatically disabled.  As a result, e.g.
44193 	 * StepInto will then pause on (native) function entry or exit.
44194 	 */
44195 	duk_debug_clear_paused(heap);
44196 	duk__debug_set_pause_state(thr, heap, pause_flags);
44197 
44198 	duk_debug_write_reply(thr);
44199 	duk_debug_write_eom(thr);
44200 }
44201 
44202 DUK_LOCAL void duk__debug_handle_list_break(duk_hthread *thr, duk_heap *heap) {
44203 	duk_small_int_t i;
44204 
44205 	DUK_D(DUK_DPRINT("debug command ListBreak"));
44206 	duk_debug_write_reply(thr);
44207 	for (i = 0; i < (duk_small_int_t) heap->dbg_breakpoint_count; i++) {
44208 		duk_debug_write_hstring(thr, heap->dbg_breakpoints[i].filename);
44209 		duk_debug_write_uint(thr, (duk_uint32_t) heap->dbg_breakpoints[i].line);
44210 	}
44211 	duk_debug_write_eom(thr);
44212 }
44213 
44214 DUK_LOCAL void duk__debug_handle_add_break(duk_hthread *thr, duk_heap *heap) {
44215 	duk_hstring *filename;
44216 	duk_uint32_t linenumber;
44217 	duk_small_int_t idx;
44218 
44219 	DUK_UNREF(heap);
44220 
44221 	filename = duk_debug_read_hstring(thr);
44222 	linenumber = (duk_uint32_t) duk_debug_read_int(thr);
44223 	DUK_D(DUK_DPRINT("debug command AddBreak: %!O:%ld", (duk_hobject *) filename, (long) linenumber));
44224 	idx = duk_debug_add_breakpoint(thr, filename, linenumber);
44225 	if (idx >= 0) {
44226 		duk_debug_write_reply(thr);
44227 		duk_debug_write_int(thr, (duk_int32_t) idx);
44228 		duk_debug_write_eom(thr);
44229 	} else {
44230 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_TOOMANY, "no space for breakpoint");
44231 	}
44232 }
44233 
44234 DUK_LOCAL void duk__debug_handle_del_break(duk_hthread *thr, duk_heap *heap) {
44235 	duk_small_uint_t idx;
44236 
44237 	DUK_UNREF(heap);
44238 
44239 	DUK_D(DUK_DPRINT("debug command DelBreak"));
44240 	idx = (duk_small_uint_t) duk_debug_read_int(thr);
44241 	if (duk_debug_remove_breakpoint(thr, idx)) {
44242 		duk_debug_write_reply(thr);
44243 		duk_debug_write_eom(thr);
44244 	} else {
44245 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid breakpoint index");
44246 	}
44247 }
44248 
44249 DUK_LOCAL void duk__debug_handle_get_var(duk_hthread *thr, duk_heap *heap) {
44250 	duk_activation *act;
44251 	duk_hstring *str;
44252 	duk_bool_t rc;
44253 
44254 	DUK_UNREF(heap);
44255 	DUK_D(DUK_DPRINT("debug command GetVar"));
44256 
44257 	act = duk__debug_read_level_get_activation(thr);
44258 	if (act == NULL) {
44259 		return;
44260 	}
44261 	str = duk_debug_read_hstring(thr);  /* push to stack */
44262 	DUK_ASSERT(str != NULL);
44263 
44264 	rc = duk_js_getvar_activation(thr, act, str, 0);
44265 
44266 	duk_debug_write_reply(thr);
44267 	if (rc) {
44268 		duk_debug_write_int(thr, 1);
44269 		DUK_ASSERT(duk_get_tval(thr, -2) != NULL);
44270 		duk_debug_write_tval(thr, duk_get_tval(thr, -2));
44271 	} else {
44272 		duk_debug_write_int(thr, 0);
44273 		duk_debug_write_unused(thr);
44274 	}
44275 	duk_debug_write_eom(thr);
44276 }
44277 
44278 DUK_LOCAL void duk__debug_handle_put_var(duk_hthread *thr, duk_heap *heap) {
44279 	duk_activation *act;
44280 	duk_hstring *str;
44281 	duk_tval *tv;
44282 
44283 	DUK_UNREF(heap);
44284 	DUK_D(DUK_DPRINT("debug command PutVar"));
44285 
44286 	act = duk__debug_read_level_get_activation(thr);
44287 	if (act == NULL) {
44288 		return;
44289 	}
44290 	str = duk_debug_read_hstring(thr);  /* push to stack */
44291 	DUK_ASSERT(str != NULL);
44292 	tv = duk_debug_read_tval(thr);
44293 	if (tv == NULL) {
44294 		/* detached */
44295 		return;
44296 	}
44297 
44298 	duk_js_putvar_activation(thr, act, str, tv, 0);
44299 
44300 	/* XXX: Current putvar implementation doesn't have a success flag,
44301 	 * add one and send to debug client?
44302 	 */
44303 	duk_debug_write_reply(thr);
44304 	duk_debug_write_eom(thr);
44305 }
44306 
44307 DUK_LOCAL void duk__debug_handle_get_call_stack(duk_hthread *thr, duk_heap *heap) {
44308 	duk_hthread *curr_thr = thr;
44309 	duk_activation *curr_act;
44310 	duk_uint_fast32_t pc;
44311 	duk_uint_fast32_t line;
44312 
44313 	DUK_ASSERT(thr != NULL);
44314 	DUK_UNREF(heap);
44315 
44316 	duk_debug_write_reply(thr);
44317 	while (curr_thr != NULL) {
44318 		for (curr_act = curr_thr->callstack_curr; curr_act != NULL; curr_act = curr_act->parent) {
44319 			/* PC/line semantics here are:
44320 			 *   - For callstack top we're conceptually between two
44321 			 *     opcodes and current PC indicates next line to
44322 			 *     execute, so report that (matches Status).
44323 			 *   - For other activations we're conceptually still
44324 			 *     executing the instruction at PC-1, so report that
44325 			 *     (matches error stacktrace behavior).
44326 			 *   - See: https://github.com/svaarala/duktape/issues/281
44327 			 */
44328 
44329 			/* XXX: optimize to use direct reads, i.e. avoid
44330 			 * value stack operations.
44331 			 */
44332 			duk_push_tval(thr, &curr_act->tv_func);
44333 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);
44334 			duk__debug_write_hstring_safe_top(thr);
44335 			duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);
44336 			duk__debug_write_hstring_safe_top(thr);
44337 			pc = duk_hthread_get_act_curr_pc(thr, curr_act);
44338 			if (curr_act != curr_thr->callstack_curr && pc > 0) {
44339 				pc--;
44340 			}
44341 			line = duk_hobject_pc2line_query(thr, -3, pc);
44342 			duk_debug_write_uint(thr, (duk_uint32_t) line);
44343 			duk_debug_write_uint(thr, (duk_uint32_t) pc);
44344 			duk_pop_3(thr);
44345 		}
44346 		curr_thr = curr_thr->resumer;
44347 	}
44348 	/* SCANBUILD: warning about 'thr' potentially being NULL here,
44349 	 * warning is incorrect because thr != NULL always here.
44350 	 */
44351 	duk_debug_write_eom(thr);
44352 }
44353 
44354 DUK_LOCAL void duk__debug_handle_get_locals(duk_hthread *thr, duk_heap *heap) {
44355 	duk_activation *act;
44356 	duk_hstring *varname;
44357 
44358 	DUK_UNREF(heap);
44359 
44360 	act = duk__debug_read_level_get_activation(thr);
44361 	if (act == NULL) {
44362 		return;
44363 	}
44364 
44365 	duk_debug_write_reply(thr);
44366 
44367 	/* XXX: several nice-to-have improvements here:
44368 	 *   - Use direct reads avoiding value stack operations
44369 	 *   - Avoid triggering getters, indicate getter values to debug client
44370 	 *   - If side effects are possible, add error catching
44371 	 */
44372 
44373 	duk_push_tval(thr, &act->tv_func);
44374 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VARMAP);
44375 	if (duk_is_object(thr, -1)) {
44376 		duk_enum(thr, -1, 0 /*enum_flags*/);
44377 		while (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {
44378 			varname = duk_known_hstring(thr, -1);
44379 
44380 			duk_js_getvar_activation(thr, act, varname, 0 /*throw_flag*/);
44381 			/* [ ... func varmap enum key value this ] */
44382 			duk_debug_write_hstring(thr, duk_get_hstring(thr, -3));
44383 			duk_debug_write_tval(thr, duk_get_tval(thr, -2));
44384 			duk_pop_3(thr);  /* -> [ ... func varmap enum ] */
44385 		}
44386 	} else {
44387 		DUK_D(DUK_DPRINT("varmap is not an object in GetLocals, ignore"));
44388 	}
44389 
44390 	duk_debug_write_eom(thr);
44391 }
44392 
44393 DUK_LOCAL void duk__debug_handle_eval(duk_hthread *thr, duk_heap *heap) {
44394 	duk_small_uint_t call_flags;
44395 	duk_int_t call_ret;
44396 	duk_small_int_t eval_err;
44397 	duk_bool_t direct_eval;
44398 	duk_int32_t level;
44399 	duk_idx_t idx_func;
44400 
44401 	DUK_UNREF(heap);
44402 
44403 	DUK_D(DUK_DPRINT("debug command Eval"));
44404 
44405 	/* The eval code is executed within the lexical environment of a specified
44406 	 * activation.  For now, use global object eval() function, with the eval
44407 	 * considered a 'direct call to eval'.
44408 	 *
44409 	 * Callstack index for debug commands only affects scope -- the callstack
44410 	 * as seen by, e.g. Duktape.act() will be the same regardless.
44411 	 */
44412 
44413 	/* nargs == 2 so we can pass a callstack index to eval(). */
44414 	idx_func = duk_get_top(thr);
44415 	duk_push_c_function(thr, duk_bi_global_object_eval, 2 /*nargs*/);
44416 	duk_push_undefined(thr);  /* 'this' binding shouldn't matter here */
44417 
44418 	/* Read callstack index, if non-null. */
44419 	if (duk_debug_peek_byte(thr) == DUK_DBG_IB_NULL) {
44420 		direct_eval = 0;
44421 		level = -1;  /* Not needed, but silences warning. */
44422 		(void) duk_debug_read_byte(thr);
44423 	} else {
44424 		direct_eval = 1;
44425 		level = duk__debug_read_validate_csindex(thr);
44426 		if (level == 0) {
44427 			return;
44428 		}
44429 	}
44430 
44431 	DUK_ASSERT(!direct_eval ||
44432 	           (level < 0 && -level <= (duk_int32_t) thr->callstack_top));
44433 
44434 	(void) duk_debug_read_hstring(thr);
44435 	if (direct_eval) {
44436 		duk_push_int(thr, level - 1);  /* compensate for eval() call */
44437 	}
44438 
44439 	/* [ ... eval "eval" eval_input level? ] */
44440 
44441 	call_flags = 0;
44442 	if (direct_eval) {
44443 		duk_activation *act;
44444 		duk_hobject *fun;
44445 
44446 		act = duk_hthread_get_activation_for_level(thr, level);
44447 		if (act != NULL) {
44448 			fun = DUK_ACT_GET_FUNC(act);
44449 			if (fun != NULL && DUK_HOBJECT_IS_COMPFUNC(fun)) {
44450 				/* Direct eval requires that there's a current
44451 				 * activation and it is an ECMAScript function.
44452 				 * When Eval is executed from e.g. cooperate API
44453 				 * call we'll need to do an indirect eval instead.
44454 				 */
44455 				call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
44456 			}
44457 		}
44458 	}
44459 
44460 	call_ret = duk_pcall_method_flags(thr, duk_get_top(thr) - (idx_func + 2), call_flags);
44461 
44462 	if (call_ret == DUK_EXEC_SUCCESS) {
44463 		eval_err = 0;
44464 		/* Use result value as is. */
44465 	} else {
44466 		/* For errors a string coerced result is most informative
44467 		 * right now, as the debug client doesn't have the capability
44468 		 * to traverse the error object.
44469 		 */
44470 		eval_err = 1;
44471 		duk_safe_to_string(thr, -1);
44472 	}
44473 
44474 	/* [ ... result ] */
44475 
44476 	duk_debug_write_reply(thr);
44477 	duk_debug_write_int(thr, (duk_int32_t) eval_err);
44478 	DUK_ASSERT(duk_get_tval(thr, -1) != NULL);
44479 	duk_debug_write_tval(thr, duk_get_tval(thr, -1));
44480 	duk_debug_write_eom(thr);
44481 }
44482 
44483 DUK_LOCAL void duk__debug_handle_detach(duk_hthread *thr, duk_heap *heap) {
44484 	DUK_UNREF(heap);
44485 	DUK_D(DUK_DPRINT("debug command Detach"));
44486 
44487 	duk_debug_write_reply(thr);
44488 	duk_debug_write_eom(thr);
44489 
44490 	DUK_D(DUK_DPRINT("debug connection detached, mark broken"));
44491 	DUK__SET_CONN_BROKEN(thr, 0);  /* not an error */
44492 }
44493 
44494 DUK_LOCAL void duk__debug_handle_apprequest(duk_hthread *thr, duk_heap *heap) {
44495 	duk_idx_t old_top;
44496 
44497 	DUK_D(DUK_DPRINT("debug command AppRequest"));
44498 
44499 	old_top = duk_get_top(thr);  /* save stack top */
44500 
44501 	if (heap->dbg_request_cb != NULL) {
44502 		duk_idx_t nrets;
44503 		duk_idx_t nvalues = 0;
44504 		duk_idx_t top, idx;
44505 
44506 		/* Read tvals from the message and push them onto the valstack,
44507 		 * then call the request callback to process the request.
44508 		 */
44509 		while (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
44510 			duk_tval *tv;
44511 			if (!duk_check_stack(thr, 1)) {
44512 				DUK_D(DUK_DPRINT("failed to allocate space for request dvalue(s)"));
44513 				goto fail;
44514 			}
44515 			tv = duk_debug_read_tval(thr);  /* push to stack */
44516 			if (tv == NULL) {
44517 				/* detached */
44518 				return;
44519 			}
44520 			nvalues++;
44521 		}
44522 		DUK_ASSERT(duk_get_top(thr) == old_top + nvalues);
44523 
44524 		/* Request callback should push values for reply to client onto valstack */
44525 		DUK_D(DUK_DPRINT("calling into AppRequest request_cb with nvalues=%ld, old_top=%ld, top=%ld",
44526 		                 (long) nvalues, (long) old_top, (long) duk_get_top(thr)));
44527 		nrets = heap->dbg_request_cb(thr, heap->dbg_udata, nvalues);
44528 		DUK_D(DUK_DPRINT("returned from AppRequest request_cb; nvalues=%ld -> nrets=%ld, old_top=%ld, top=%ld",
44529 		                 (long) nvalues, (long) nrets, (long) old_top, (long) duk_get_top(thr)));
44530 		if (nrets >= 0) {
44531 			DUK_ASSERT(duk_get_top(thr) >= old_top + nrets);
44532 			if (duk_get_top(thr) < old_top + nrets) {
44533 				DUK_D(DUK_DPRINT("AppRequest callback doesn't match value stack configuration, "
44534 				                 "top=%ld < old_top=%ld + nrets=%ld; "
44535 				                 "this might mean it's unsafe to continue!",
44536 				                 (long) duk_get_top(thr), (long) old_top, (long) nrets));
44537 				goto fail;
44538 			}
44539 
44540 			/* Reply with tvals pushed by request callback */
44541 			duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
44542 			top = duk_get_top(thr);
44543 			for (idx = top - nrets; idx < top; idx++) {
44544 				duk_debug_write_tval(thr, DUK_GET_TVAL_POSIDX(thr, idx));
44545 			}
44546 			duk_debug_write_eom(thr);
44547 		} else {
44548 			DUK_ASSERT(duk_get_top(thr) >= old_top + 1);
44549 			if (duk_get_top(thr) < old_top + 1) {
44550 				DUK_D(DUK_DPRINT("request callback return value doesn't match value stack configuration"));
44551 				goto fail;
44552 			}
44553 			duk_debug_write_error_eom(thr, DUK_DBG_ERR_APPLICATION, duk_get_string(thr, -1));
44554 		}
44555 
44556 		duk_set_top(thr, old_top);  /* restore stack top */
44557 	} else {
44558 		DUK_D(DUK_DPRINT("no request callback, treat AppRequest as unsupported"));
44559 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "AppRequest unsupported by target");
44560 	}
44561 
44562 	return;
44563 
44564  fail:
44565 	duk_set_top(thr, old_top);  /* restore stack top */
44566 	DUK__SET_CONN_BROKEN(thr, 1);
44567 }
44568 
44569 /*
44570  *  DumpHeap command
44571  */
44572 
44573 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
44574 /* XXX: this has some overlap with object inspection; remove this and make
44575  * DumpHeap return lists of heapptrs instead?
44576  */
44577 DUK_LOCAL void duk__debug_dump_heaphdr(duk_hthread *thr, duk_heap *heap, duk_heaphdr *hdr) {
44578 	DUK_UNREF(heap);
44579 
44580 	duk_debug_write_heapptr(thr, hdr);
44581 	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_TYPE(hdr));
44582 	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_FLAGS_RAW(hdr));
44583 #if defined(DUK_USE_REFERENCE_COUNTING)
44584 	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_REFCOUNT(hdr));
44585 #else
44586 	duk_debug_write_int(thr, (duk_int32_t) -1);
44587 #endif
44588 
44589 	switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
44590 	case DUK_HTYPE_STRING: {
44591 		duk_hstring *h = (duk_hstring *) hdr;
44592 
44593 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_BYTELEN(h));
44594 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_CHARLEN(h));
44595 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_HASH(h));
44596 		duk_debug_write_hstring(thr, h);
44597 		break;
44598 	}
44599 	case DUK_HTYPE_OBJECT: {
44600 		duk_hobject *h = (duk_hobject *) hdr;
44601 		duk_hstring *k;
44602 		duk_uint_fast32_t i;
44603 
44604 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_CLASS_NUMBER(h));
44605 		duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
44606 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ESIZE(h));
44607 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ENEXT(h));
44608 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ASIZE(h));
44609 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_HSIZE(h));
44610 
44611 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
44612 			duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_E_GET_FLAGS(heap, h, i));
44613 			k = DUK_HOBJECT_E_GET_KEY(heap, h, i);
44614 			duk_debug_write_heapptr(thr, (duk_heaphdr *) k);
44615 			if (k == NULL) {
44616 				duk_debug_write_int(thr, 0);  /* isAccessor */
44617 				duk_debug_write_unused(thr);
44618 				continue;
44619 			}
44620 			if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
44621 				duk_debug_write_int(thr, 1);  /* isAccessor */
44622 				duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
44623 				duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
44624 			} else {
44625 				duk_debug_write_int(thr, 0);  /* isAccessor */
44626 
44627 				duk__debug_write_tval_heapptr(thr, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
44628 			}
44629 		}
44630 
44631 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
44632 			/* Note: array dump will include elements beyond
44633 			 * 'length'.
44634 			 */
44635 			duk__debug_write_tval_heapptr(thr, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
44636 		}
44637 		break;
44638 	}
44639 	case DUK_HTYPE_BUFFER: {
44640 		duk_hbuffer *h = (duk_hbuffer *) hdr;
44641 
44642 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HBUFFER_GET_SIZE(h));
44643 		duk_debug_write_buffer(thr, (const char *) DUK_HBUFFER_GET_DATA_PTR(heap, h), (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
44644 		break;
44645 	}
44646 	default: {
44647 		DUK_D(DUK_DPRINT("invalid htype: %d", (int) DUK_HEAPHDR_GET_TYPE(hdr)));
44648 	}
44649 	}
44650 }
44651 
44652 DUK_LOCAL void duk__debug_dump_heap_allocated(duk_hthread *thr, duk_heap *heap) {
44653 	duk_heaphdr *hdr;
44654 
44655 	hdr = heap->heap_allocated;
44656 	while (hdr != NULL) {
44657 		duk__debug_dump_heaphdr(thr, heap, hdr);
44658 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
44659 	}
44660 }
44661 
44662 DUK_LOCAL void duk__debug_dump_strtab(duk_hthread *thr, duk_heap *heap) {
44663 	duk_uint32_t i;
44664 	duk_hstring *h;
44665 
44666 	for (i = 0; i < heap->st_size; i++) {
44667 #if defined(DUK_USE_STRTAB_PTRCOMP)
44668 		h = DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, heap->strtable16[i]);
44669 #else
44670 		h = heap->strtable[i];
44671 #endif
44672 		while (h != NULL) {
44673 			duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
44674 			h = h->hdr.h_next;
44675 		}
44676 	}
44677 }
44678 
44679 DUK_LOCAL void duk__debug_handle_dump_heap(duk_hthread *thr, duk_heap *heap) {
44680 	DUK_D(DUK_DPRINT("debug command DumpHeap"));
44681 
44682 	duk_debug_write_reply(thr);
44683 	duk__debug_dump_heap_allocated(thr, heap);
44684 	duk__debug_dump_strtab(thr, heap);
44685 	duk_debug_write_eom(thr);
44686 }
44687 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
44688 
44689 DUK_LOCAL void duk__debug_handle_get_bytecode(duk_hthread *thr, duk_heap *heap) {
44690 	duk_activation *act;
44691 	duk_hcompfunc *fun = NULL;
44692 	duk_size_t i, n;
44693 	duk_tval *tv;
44694 	duk_hobject **fn;
44695 	duk_int32_t level = -1;
44696 	duk_uint8_t ibyte;
44697 
44698 	DUK_UNREF(heap);
44699 
44700 	DUK_D(DUK_DPRINT("debug command GetBytecode"));
44701 
44702 	ibyte = duk_debug_peek_byte(thr);
44703 	if (ibyte != DUK_DBG_IB_EOM) {
44704 		tv = duk_debug_read_tval(thr);
44705 		if (tv == NULL) {
44706 			/* detached */
44707 			return;
44708 		}
44709 		if (DUK_TVAL_IS_OBJECT(tv)) {
44710 			/* tentative, checked later */
44711 			fun = (duk_hcompfunc *) DUK_TVAL_GET_OBJECT(tv);
44712 			DUK_ASSERT(fun != NULL);
44713 		} else if (DUK_TVAL_IS_NUMBER(tv)) {
44714 			level = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv);
44715 		} else {
44716 			DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!T", tv));
44717 			goto fail_args;
44718 		}
44719 	}
44720 
44721 	if (fun == NULL) {
44722 		act = duk_hthread_get_activation_for_level(thr, level);
44723 		if (act == NULL) {
44724 			goto fail_index;
44725 		}
44726 		fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
44727 	}
44728 
44729 	if (fun == NULL || !DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun)) {
44730 		DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!O", fun));
44731 		goto fail_args;
44732 	}
44733 	DUK_ASSERT(fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun));
44734 
44735 	duk_debug_write_reply(thr);
44736 	n = DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap, fun);
44737 	duk_debug_write_int(thr, (duk_int32_t) n);
44738 	tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, fun);
44739 	for (i = 0; i < n; i++) {
44740 		duk_debug_write_tval(thr, tv);
44741 		tv++;
44742 	}
44743 	n = DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap, fun);
44744 	duk_debug_write_int(thr, (duk_int32_t) n);
44745 	fn = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, fun);
44746 	for (i = 0; i < n; i++) {
44747 		duk_debug_write_hobject(thr, *fn);
44748 		fn++;
44749 	}
44750 	duk_debug_write_string(thr,
44751 	                       (const char *) DUK_HCOMPFUNC_GET_CODE_BASE(heap, fun),
44752 	                       (duk_size_t) DUK_HCOMPFUNC_GET_CODE_SIZE(heap, fun));
44753 	duk_debug_write_eom(thr);
44754 	return;
44755 
44756  fail_args:
44757 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid argument");
44758 	return;
44759 
44760  fail_index:
44761 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
44762 	return;
44763 }
44764 
44765 /*
44766  *  Object inspection commands: GetHeapObjInfo, GetObjPropDesc,
44767  *  GetObjPropDescRange
44768  */
44769 
44770 #if defined(DUK_USE_DEBUGGER_INSPECT)
44771 
44772 #if 0 /* pruned */
44773 DUK_LOCAL const char * const duk__debug_getinfo_heaphdr_keys[] = {
44774 	"reachable",
44775 	"temproot",
44776 	"finalizable",
44777 	"finalized",
44778 	"readonly"
44779 	/* NULL not needed here */
44780 };
44781 DUK_LOCAL duk_uint_t duk__debug_getinfo_heaphdr_masks[] = {
44782 	DUK_HEAPHDR_FLAG_REACHABLE,
44783 	DUK_HEAPHDR_FLAG_TEMPROOT,
44784 	DUK_HEAPHDR_FLAG_FINALIZABLE,
44785 	DUK_HEAPHDR_FLAG_FINALIZED,
44786 	DUK_HEAPHDR_FLAG_READONLY,
44787 	0  /* terminator */
44788 };
44789 #endif
44790 DUK_LOCAL const char * const duk__debug_getinfo_hstring_keys[] = {
44791 #if 0
44792 	"arridx",
44793 	"symbol",
44794 	"hidden",
44795 	"reserved_word",
44796 	"strict_reserved_word",
44797 	"eval_or_arguments",
44798 #endif
44799 	"extdata"
44800 	/* NULL not needed here */
44801 };
44802 DUK_LOCAL duk_uint_t duk__debug_getinfo_hstring_masks[] = {
44803 #if 0
44804 	DUK_HSTRING_FLAG_ARRIDX,
44805 	DUK_HSTRING_FLAG_SYMBOL,
44806 	DUK_HSTRING_FLAG_HIDDEN,
44807 	DUK_HSTRING_FLAG_RESERVED_WORD,
44808 	DUK_HSTRING_FLAG_STRICT_RESERVED_WORD,
44809 	DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS,
44810 #endif
44811 	DUK_HSTRING_FLAG_EXTDATA,
44812 	0  /* terminator */
44813 };
44814 DUK_LOCAL const char * const duk__debug_getinfo_hobject_keys[] = {
44815 	"extensible",
44816 	"constructable",
44817 	"callable",
44818 	"boundfunc",
44819 	"compfunc",
44820 	"natfunc",
44821 	"bufobj",
44822 	"fastrefs",
44823 	"array_part",
44824 	"strict",
44825 	"notail",
44826 	"newenv",
44827 	"namebinding",
44828 	"createargs",
44829 	"have_finalizer",
44830 	"exotic_array",
44831 	"exotic_stringobj",
44832 	"exotic_arguments",
44833 	"exotic_proxyobj",
44834 	"special_call"
44835 	/* NULL not needed here */
44836 };
44837 DUK_LOCAL duk_uint_t duk__debug_getinfo_hobject_masks[] = {
44838 	DUK_HOBJECT_FLAG_EXTENSIBLE,
44839 	DUK_HOBJECT_FLAG_CONSTRUCTABLE,
44840 	DUK_HOBJECT_FLAG_CALLABLE,
44841 	DUK_HOBJECT_FLAG_BOUNDFUNC,
44842 	DUK_HOBJECT_FLAG_COMPFUNC,
44843 	DUK_HOBJECT_FLAG_NATFUNC,
44844 	DUK_HOBJECT_FLAG_BUFOBJ,
44845 	DUK_HOBJECT_FLAG_FASTREFS,
44846 	DUK_HOBJECT_FLAG_ARRAY_PART,
44847 	DUK_HOBJECT_FLAG_STRICT,
44848 	DUK_HOBJECT_FLAG_NOTAIL,
44849 	DUK_HOBJECT_FLAG_NEWENV,
44850 	DUK_HOBJECT_FLAG_NAMEBINDING,
44851 	DUK_HOBJECT_FLAG_CREATEARGS,
44852 	DUK_HOBJECT_FLAG_HAVE_FINALIZER,
44853 	DUK_HOBJECT_FLAG_EXOTIC_ARRAY,
44854 	DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ,
44855 	DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS,
44856 	DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ,
44857 	DUK_HOBJECT_FLAG_SPECIAL_CALL,
44858 	0  /* terminator */
44859 };
44860 DUK_LOCAL const char * const duk__debug_getinfo_hbuffer_keys[] = {
44861 	"dynamic",
44862 	"external"
44863 	/* NULL not needed here */
44864 };
44865 DUK_LOCAL duk_uint_t duk__debug_getinfo_hbuffer_masks[] = {
44866 	DUK_HBUFFER_FLAG_DYNAMIC,
44867 	DUK_HBUFFER_FLAG_EXTERNAL,
44868 	0  /* terminator */
44869 };
44870 
44871 DUK_LOCAL void duk__debug_getinfo_flags_key(duk_hthread *thr, const char *key) {
44872 	duk_debug_write_uint(thr, 0);
44873 	duk_debug_write_cstring(thr, key);
44874 }
44875 
44876 DUK_LOCAL void duk__debug_getinfo_prop_uint(duk_hthread *thr, const char *key, duk_uint_t val) {
44877 	duk_debug_write_uint(thr, 0);
44878 	duk_debug_write_cstring(thr, key);
44879 	duk_debug_write_uint(thr, val);
44880 }
44881 
44882 DUK_LOCAL void duk__debug_getinfo_prop_int(duk_hthread *thr, const char *key, duk_int_t val) {
44883 	duk_debug_write_uint(thr, 0);
44884 	duk_debug_write_cstring(thr, key);
44885 	duk_debug_write_int(thr, val);
44886 }
44887 
44888 DUK_LOCAL void duk__debug_getinfo_prop_bool(duk_hthread *thr, const char *key, duk_bool_t val) {
44889 	duk_debug_write_uint(thr, 0);
44890 	duk_debug_write_cstring(thr, key);
44891 	duk_debug_write_boolean(thr, val);
44892 }
44893 
44894 DUK_LOCAL void duk__debug_getinfo_bitmask(duk_hthread *thr, const char * const * keys, duk_uint_t *masks, duk_uint_t flags) {
44895 	const char *key;
44896 	duk_uint_t mask;
44897 
44898 	for (;;) {
44899 		mask = *masks++;
44900 		if (mask == 0) {
44901 			break;
44902 		}
44903 		key = *keys++;
44904 		DUK_ASSERT(key != NULL);
44905 
44906 		DUK_DD(DUK_DDPRINT("inspect bitmask: key=%s, mask=0x%08lx, flags=0x%08lx", key, (unsigned long) mask, (unsigned long) flags));
44907 		duk__debug_getinfo_prop_bool(thr, key, flags & mask);
44908 	}
44909 }
44910 
44911 /* Inspect a property using a virtual index into a conceptual property list
44912  * consisting of (1) all array part items from [0,a_size[ (even when above
44913  * .length) and (2) all entry part items from [0,e_next[.  Unused slots are
44914  * indicated using dvalue 'unused'.
44915  */
44916 DUK_LOCAL duk_bool_t duk__debug_getprop_index(duk_hthread *thr, duk_heap *heap, duk_hobject *h_obj, duk_uint_t idx) {
44917 	duk_uint_t a_size;
44918 	duk_tval *tv;
44919 	duk_hstring *h_key;
44920 	duk_hobject *h_getset;
44921 	duk_uint_t flags;
44922 
44923 	DUK_UNREF(heap);
44924 
44925 	a_size = DUK_HOBJECT_GET_ASIZE(h_obj);
44926 	if (idx < a_size) {
44927 		duk_debug_write_uint(thr, DUK_PROPDESC_FLAGS_WEC);
44928 		duk_debug_write_uint(thr, idx);
44929 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, h_obj, idx);
44930 		duk_debug_write_tval(thr, tv);
44931 		return 1;
44932 	}
44933 
44934 	idx -= a_size;
44935 	if (idx >= DUK_HOBJECT_GET_ENEXT(h_obj)) {
44936 		return 0;
44937 	}
44938 
44939 	h_key = DUK_HOBJECT_E_GET_KEY(heap, h_obj, idx);
44940 	if (h_key == NULL) {
44941 		duk_debug_write_uint(thr, 0);
44942 		duk_debug_write_null(thr);
44943 		duk_debug_write_unused(thr);
44944 		return 1;
44945 	}
44946 
44947 	flags = DUK_HOBJECT_E_GET_FLAGS(heap, h_obj, idx);
44948 	if (DUK_HSTRING_HAS_SYMBOL(h_key)) {
44949 		flags |= DUK_DBG_PROPFLAG_SYMBOL;
44950 	}
44951 	if (DUK_HSTRING_HAS_HIDDEN(h_key)) {
44952 		flags |= DUK_DBG_PROPFLAG_HIDDEN;
44953 	}
44954 	duk_debug_write_uint(thr, flags);
44955 	duk_debug_write_hstring(thr, h_key);
44956 	if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
44957 		h_getset = DUK_HOBJECT_E_GET_VALUE_GETTER(heap, h_obj, idx);
44958 		if (h_getset) {
44959 			duk_debug_write_hobject(thr, h_getset);
44960 		} else {
44961 			duk_debug_write_null(thr);
44962 		}
44963 		h_getset = DUK_HOBJECT_E_GET_VALUE_SETTER(heap, h_obj, idx);
44964 		if (h_getset) {
44965 			duk_debug_write_hobject(thr, h_getset);
44966 		} else {
44967 			duk_debug_write_null(thr);
44968 		}
44969 	} else {
44970 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, h_obj, idx);
44971 		duk_debug_write_tval(thr, tv);
44972 	}
44973 	return 1;
44974 }
44975 
44976 DUK_LOCAL void duk__debug_handle_get_heap_obj_info(duk_hthread *thr, duk_heap *heap) {
44977 	duk_heaphdr *h;
44978 
44979 	DUK_D(DUK_DPRINT("debug command GetHeapObjInfo"));
44980 	DUK_UNREF(heap);
44981 
44982 	DUK_ASSERT(sizeof(duk__debug_getinfo_hstring_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hstring_masks) / sizeof(duk_uint_t) - 1);
44983 	DUK_ASSERT(sizeof(duk__debug_getinfo_hobject_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hobject_masks) / sizeof(duk_uint_t) - 1);
44984 	DUK_ASSERT(sizeof(duk__debug_getinfo_hbuffer_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hbuffer_masks) / sizeof(duk_uint_t) - 1);
44985 
44986 	h = duk_debug_read_any_ptr(thr);
44987 	if (!h) {
44988 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
44989 		return;
44990 	}
44991 
44992 	duk_debug_write_reply(thr);
44993 
44994 	/* As with all inspection code, we rely on the debug client providing
44995 	 * a valid, non-stale pointer: there's no portable way to safely
44996 	 * validate the pointer here.
44997 	 */
44998 
44999 	duk__debug_getinfo_flags_key(thr, "heapptr");
45000 	duk_debug_write_heapptr(thr, h);
45001 
45002 	/* XXX: comes out as signed now */
45003 	duk__debug_getinfo_prop_uint(thr, "heaphdr_flags", (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));
45004 	duk__debug_getinfo_prop_uint(thr, "heaphdr_type", (duk_uint_t) DUK_HEAPHDR_GET_TYPE(h));
45005 #if defined(DUK_USE_REFERENCE_COUNTING)
45006 	duk__debug_getinfo_prop_uint(thr, "refcount", (duk_uint_t) DUK_HEAPHDR_GET_REFCOUNT(h));
45007 #endif
45008 #if 0 /* pruned */
45009 	duk__debug_getinfo_bitmask(thr,
45010 	                           duk__debug_getinfo_heaphdr_keys,
45011 	                           duk__debug_getinfo_heaphdr_masks,
45012 	                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
45013 #endif
45014 
45015 	switch (DUK_HEAPHDR_GET_TYPE(h)) {
45016 	case DUK_HTYPE_STRING: {
45017 		duk_hstring *h_str;
45018 
45019 		h_str = (duk_hstring *) h;
45020 		duk__debug_getinfo_bitmask(thr,
45021 		                           duk__debug_getinfo_hstring_keys,
45022 		                           duk__debug_getinfo_hstring_masks,
45023 		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
45024 		duk__debug_getinfo_prop_uint(thr, "bytelen", (duk_uint_t) DUK_HSTRING_GET_BYTELEN(h_str));
45025 		duk__debug_getinfo_prop_uint(thr, "charlen", (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h_str));
45026 		duk__debug_getinfo_prop_uint(thr, "hash", (duk_uint_t) DUK_HSTRING_GET_HASH(h_str));
45027 		duk__debug_getinfo_flags_key(thr, "data");
45028 		duk_debug_write_hstring(thr, h_str);
45029 		break;
45030 	}
45031 	case DUK_HTYPE_OBJECT: {
45032 		duk_hobject *h_obj;
45033 		duk_hobject *h_proto;
45034 
45035 		h_obj = (duk_hobject *) h;
45036 		h_proto = DUK_HOBJECT_GET_PROTOTYPE(heap, h_obj);
45037 
45038 		/* duk_hobject specific fields. */
45039 		duk__debug_getinfo_bitmask(thr,
45040 		                           duk__debug_getinfo_hobject_keys,
45041 		                           duk__debug_getinfo_hobject_masks,
45042 		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
45043 		duk__debug_getinfo_prop_uint(thr, "class_number", DUK_HOBJECT_GET_CLASS_NUMBER(h_obj));
45044 		duk__debug_getinfo_flags_key(thr, "class_name");
45045 		duk_debug_write_hstring(thr, DUK_HOBJECT_GET_CLASS_STRING(heap, h_obj));
45046 		duk__debug_getinfo_flags_key(thr, "prototype");
45047 		if (h_proto != NULL) {
45048 			duk_debug_write_hobject(thr, h_proto);
45049 		} else {
45050 			duk_debug_write_null(thr);
45051 		}
45052 		duk__debug_getinfo_flags_key(thr, "props");
45053 		duk_debug_write_pointer(thr, (void *) DUK_HOBJECT_GET_PROPS(heap, h_obj));
45054 		duk__debug_getinfo_prop_uint(thr, "e_size", (duk_uint_t) DUK_HOBJECT_GET_ESIZE(h_obj));
45055 		duk__debug_getinfo_prop_uint(thr, "e_next", (duk_uint_t) DUK_HOBJECT_GET_ENEXT(h_obj));
45056 		duk__debug_getinfo_prop_uint(thr, "a_size", (duk_uint_t) DUK_HOBJECT_GET_ASIZE(h_obj));
45057 		duk__debug_getinfo_prop_uint(thr, "h_size", (duk_uint_t) DUK_HOBJECT_GET_HSIZE(h_obj));
45058 
45059 		if (DUK_HOBJECT_IS_ARRAY(h_obj)) {
45060 			duk_harray *h_arr;
45061 			h_arr = (duk_harray *) h_obj;
45062 
45063 			duk__debug_getinfo_prop_uint(thr, "length", (duk_uint_t) h_arr->length);
45064 			duk__debug_getinfo_prop_bool(thr, "length_nonwritable", h_arr->length_nonwritable);
45065 		}
45066 
45067 		if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
45068 			duk_hnatfunc *h_fun;
45069 			h_fun = (duk_hnatfunc *) h_obj;
45070 
45071 			duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
45072 			duk__debug_getinfo_prop_int(thr, "magic", h_fun->magic);
45073 			duk__debug_getinfo_prop_bool(thr, "varargs", h_fun->magic == DUK_HNATFUNC_NARGS_VARARGS);
45074 			/* Native function pointer may be different from a void pointer,
45075 			 * and we serialize it from memory directly now (no byte swapping etc).
45076 			 */
45077 			duk__debug_getinfo_flags_key(thr, "funcptr");
45078 			duk_debug_write_buffer(thr, (const char *) &h_fun->func, sizeof(h_fun->func));
45079 		}
45080 
45081 		if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
45082 			duk_hcompfunc *h_fun;
45083 			duk_hbuffer *h_buf;
45084 			duk_hobject *h_lexenv;
45085 			duk_hobject *h_varenv;
45086 			h_fun = (duk_hcompfunc *) h_obj;
45087 
45088 			duk__debug_getinfo_prop_int(thr, "nregs", h_fun->nregs);
45089 			duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
45090 
45091 			duk__debug_getinfo_flags_key(thr, "lex_env");
45092 			h_lexenv = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, h_fun);
45093 			if (h_lexenv != NULL) {
45094 				duk_debug_write_hobject(thr, h_lexenv);
45095 			} else {
45096 				duk_debug_write_null(thr);
45097 			}
45098 			duk__debug_getinfo_flags_key(thr, "var_env");
45099 			h_varenv = DUK_HCOMPFUNC_GET_VARENV(thr->heap, h_fun);
45100 			if (h_varenv != NULL) {
45101 				duk_debug_write_hobject(thr, h_varenv);
45102 			} else {
45103 				duk_debug_write_null(thr);
45104 			}
45105 
45106 			duk__debug_getinfo_prop_uint(thr, "start_line", h_fun->start_line);
45107 			duk__debug_getinfo_prop_uint(thr, "end_line", h_fun->end_line);
45108 			h_buf = (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(thr->heap, h_fun);
45109 			if (h_buf != NULL) {
45110 				duk__debug_getinfo_flags_key(thr, "data");
45111 				duk_debug_write_heapptr(thr, (duk_heaphdr *) h_buf);
45112 			}
45113 		}
45114 
45115 		if (DUK_HOBJECT_IS_BOUNDFUNC(h_obj)) {
45116 			duk_hboundfunc *h_bfun;
45117 			h_bfun = (duk_hboundfunc *) (void *) h_obj;
45118 
45119 			duk__debug_getinfo_flags_key(thr, "target");
45120 			duk_debug_write_tval(thr, &h_bfun->target);
45121 			duk__debug_getinfo_flags_key(thr, "this_binding");
45122 			duk_debug_write_tval(thr, &h_bfun->this_binding);
45123 			duk__debug_getinfo_flags_key(thr, "nargs");
45124 			duk_debug_write_int(thr, h_bfun->nargs);
45125 			/* h_bfun->args not exposed now */
45126 		}
45127 
45128 		if (DUK_HOBJECT_IS_THREAD(h_obj)) {
45129 			/* XXX: Currently no inspection of threads, e.g. value stack, call
45130 			 * stack, catch stack, etc.
45131 			 */
45132 			duk_hthread *h_thr;
45133 			h_thr = (duk_hthread *) h_obj;
45134 			DUK_UNREF(h_thr);
45135 		}
45136 
45137 		if (DUK_HOBJECT_IS_DECENV(h_obj)) {
45138 			duk_hdecenv *h_env;
45139 			h_env = (duk_hdecenv *) h_obj;
45140 
45141 			duk__debug_getinfo_flags_key(thr, "thread");
45142 			duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->thread));
45143 			duk__debug_getinfo_flags_key(thr, "varmap");
45144 			duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->varmap));
45145 			duk__debug_getinfo_prop_uint(thr, "regbase", (duk_uint_t) h_env->regbase_byteoff);
45146 		}
45147 
45148 		if (DUK_HOBJECT_IS_OBJENV(h_obj)) {
45149 			duk_hobjenv *h_env;
45150 			h_env = (duk_hobjenv *) h_obj;
45151 
45152 			duk__debug_getinfo_flags_key(thr, "target");
45153 			duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->target));
45154 			duk__debug_getinfo_prop_bool(thr, "has_this", h_env->has_this);
45155 		}
45156 
45157 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
45158 		if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
45159 			duk_hbufobj *h_bufobj;
45160 			h_bufobj = (duk_hbufobj *) h_obj;
45161 
45162 			duk__debug_getinfo_prop_uint(thr, "slice_offset", h_bufobj->offset);
45163 			duk__debug_getinfo_prop_uint(thr, "slice_length", h_bufobj->length);
45164 			duk__debug_getinfo_prop_uint(thr, "elem_shift", (duk_uint_t) h_bufobj->shift);
45165 			duk__debug_getinfo_prop_uint(thr, "elem_type", (duk_uint_t) h_bufobj->elem_type);
45166 			duk__debug_getinfo_prop_bool(thr, "is_typedarray", (duk_uint_t) h_bufobj->is_typedarray);
45167 			if (h_bufobj->buf != NULL) {
45168 				duk__debug_getinfo_flags_key(thr, "buffer");
45169 				duk_debug_write_heapptr(thr, (duk_heaphdr *) h_bufobj->buf);
45170 			}
45171 		}
45172 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
45173 		break;
45174 	}
45175 	case DUK_HTYPE_BUFFER: {
45176 		duk_hbuffer *h_buf;
45177 
45178 		h_buf = (duk_hbuffer *) h;
45179 		duk__debug_getinfo_bitmask(thr,
45180 		                           duk__debug_getinfo_hbuffer_keys,
45181 		                           duk__debug_getinfo_hbuffer_masks,
45182 		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
45183 		duk__debug_getinfo_prop_uint(thr, "size", (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));
45184 		duk__debug_getinfo_flags_key(thr, "dataptr");
45185 		duk_debug_write_pointer(thr, (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf));
45186 		duk__debug_getinfo_flags_key(thr, "data");
45187 		duk_debug_write_hbuffer(thr, h_buf);  /* tolerates NULL h_buf */
45188 		break;
45189 	}
45190 	default: {
45191 		/* Since we already started writing the reply, just emit nothing. */
45192 		DUK_D(DUK_DPRINT("inspect target pointer has invalid heaphdr type"));
45193 	}
45194 	}
45195 
45196 	duk_debug_write_eom(thr);
45197 }
45198 
45199 DUK_LOCAL void duk__debug_handle_get_obj_prop_desc(duk_hthread *thr, duk_heap *heap) {
45200 	duk_heaphdr *h;
45201 	duk_hobject *h_obj;
45202 	duk_hstring *h_key;
45203 	duk_propdesc desc;
45204 
45205 	DUK_D(DUK_DPRINT("debug command GetObjPropDesc"));
45206 	DUK_UNREF(heap);
45207 
45208 	h = duk_debug_read_any_ptr(thr);
45209 	if (!h) {
45210 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
45211 		return;
45212 	}
45213 	h_key = duk_debug_read_hstring(thr);
45214 	if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT || h_key == NULL) {
45215 		goto fail_args;
45216 	}
45217 	h_obj = (duk_hobject *) h;
45218 
45219 	if (duk_hobject_get_own_propdesc(thr, h_obj, h_key, &desc, 0 /*flags*/)) {
45220 		duk_int_t virtual_idx;
45221 		duk_bool_t rc;
45222 
45223 		/* To use the shared helper need the virtual index. */
45224 		DUK_ASSERT(desc.e_idx >= 0 || desc.a_idx >= 0);
45225 		virtual_idx = (desc.a_idx >= 0 ? desc.a_idx :
45226 		               (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj) + desc.e_idx);
45227 
45228 		duk_debug_write_reply(thr);
45229 		rc = duk__debug_getprop_index(thr, heap, h_obj, (duk_uint_t) virtual_idx);
45230 		DUK_ASSERT(rc == 1);
45231 		DUK_UNREF(rc);
45232 		duk_debug_write_eom(thr);
45233 	} else {
45234 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "not found");
45235 	}
45236 	return;
45237 
45238  fail_args:
45239 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
45240 }
45241 
45242 DUK_LOCAL void duk__debug_handle_get_obj_prop_desc_range(duk_hthread *thr, duk_heap *heap) {
45243 	duk_heaphdr *h;
45244 	duk_hobject *h_obj;
45245 	duk_uint_t idx, idx_start, idx_end;
45246 
45247 	DUK_D(DUK_DPRINT("debug command GetObjPropDescRange"));
45248 	DUK_UNREF(heap);
45249 
45250 	h = duk_debug_read_any_ptr(thr);
45251 	idx_start = (duk_uint_t) duk_debug_read_int(thr);
45252 	idx_end = (duk_uint_t) duk_debug_read_int(thr);
45253 	if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT) {
45254 		goto fail_args;
45255 	}
45256 	h_obj = (duk_hobject *) h;
45257 
45258 	/* The index range space is conceptually the array part followed by the
45259 	 * entry part.  Unlike normal enumeration all slots are exposed here as
45260 	 * is and return 'unused' if the slots are not in active use.  In particular
45261 	 * the array part is included for the full a_size regardless of what the
45262 	 * array .length is.
45263 	 */
45264 
45265 	duk_debug_write_reply(thr);
45266 	for (idx = idx_start; idx < idx_end; idx++) {
45267 		if (!duk__debug_getprop_index(thr, heap, h_obj, idx)) {
45268 			break;
45269 		}
45270 	}
45271 	duk_debug_write_eom(thr);
45272 	return;
45273 
45274  fail_args:
45275 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
45276 }
45277 
45278 #endif  /* DUK_USE_DEBUGGER_INSPECT */
45279 
45280 /*
45281  *  Process incoming debug requests
45282  *
45283  *  Individual request handlers can push temporaries on the value stack and
45284  *  rely on duk__debug_process_message() to restore the value stack top
45285  *  automatically.
45286  */
45287 
45288 /* Process one debug message.  Automatically restore value stack top to its
45289  * entry value, so that individual message handlers don't need exact value
45290  * stack handling which is convenient.
45291  */
45292 DUK_LOCAL void duk__debug_process_message(duk_hthread *thr) {
45293 	duk_heap *heap;
45294 	duk_uint8_t x;
45295 	duk_int32_t cmd;
45296 	duk_idx_t entry_top;
45297 
45298 	DUK_ASSERT(thr != NULL);
45299 	heap = thr->heap;
45300 	DUK_ASSERT(heap != NULL);
45301 
45302 	entry_top = duk_get_top(thr);
45303 
45304 	x = duk_debug_read_byte(thr);
45305 	switch (x) {
45306 	case DUK_DBG_IB_REQUEST: {
45307 		cmd = duk_debug_read_int(thr);
45308 		switch (cmd) {
45309 		case DUK_DBG_CMD_BASICINFO: {
45310 			duk__debug_handle_basic_info(thr, heap);
45311 			break;
45312 		}
45313 		case DUK_DBG_CMD_TRIGGERSTATUS: {
45314 			duk__debug_handle_trigger_status(thr, heap);
45315 			break;
45316 		}
45317 		case DUK_DBG_CMD_PAUSE: {
45318 			duk__debug_handle_pause(thr, heap);
45319 			break;
45320 		}
45321 		case DUK_DBG_CMD_RESUME: {
45322 			duk__debug_handle_resume(thr, heap);
45323 			break;
45324 		}
45325 		case DUK_DBG_CMD_STEPINTO:
45326 		case DUK_DBG_CMD_STEPOVER:
45327 		case DUK_DBG_CMD_STEPOUT: {
45328 			duk__debug_handle_step(thr, heap, cmd);
45329 			break;
45330 		}
45331 		case DUK_DBG_CMD_LISTBREAK: {
45332 			duk__debug_handle_list_break(thr, heap);
45333 			break;
45334 		}
45335 		case DUK_DBG_CMD_ADDBREAK: {
45336 			duk__debug_handle_add_break(thr, heap);
45337 			break;
45338 		}
45339 		case DUK_DBG_CMD_DELBREAK: {
45340 			duk__debug_handle_del_break(thr, heap);
45341 			break;
45342 		}
45343 		case DUK_DBG_CMD_GETVAR: {
45344 			duk__debug_handle_get_var(thr, heap);
45345 			break;
45346 		}
45347 		case DUK_DBG_CMD_PUTVAR: {
45348 			duk__debug_handle_put_var(thr, heap);
45349 			break;
45350 		}
45351 		case DUK_DBG_CMD_GETCALLSTACK: {
45352 			duk__debug_handle_get_call_stack(thr, heap);
45353 			break;
45354 		}
45355 		case DUK_DBG_CMD_GETLOCALS: {
45356 			duk__debug_handle_get_locals(thr, heap);
45357 			break;
45358 		}
45359 		case DUK_DBG_CMD_EVAL: {
45360 			duk__debug_handle_eval(thr, heap);
45361 			break;
45362 		}
45363 		case DUK_DBG_CMD_DETACH: {
45364 			/* The actual detached_cb call is postponed to message loop so
45365 			 * we don't need any special precautions here (just skip to EOM
45366 			 * on the already closed connection).
45367 			 */
45368 			duk__debug_handle_detach(thr, heap);
45369 			break;
45370 		}
45371 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
45372 		case DUK_DBG_CMD_DUMPHEAP: {
45373 			duk__debug_handle_dump_heap(thr, heap);
45374 			break;
45375 		}
45376 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
45377 		case DUK_DBG_CMD_GETBYTECODE: {
45378 			duk__debug_handle_get_bytecode(thr, heap);
45379 			break;
45380 		}
45381 		case DUK_DBG_CMD_APPREQUEST: {
45382 			duk__debug_handle_apprequest(thr, heap);
45383 			break;
45384 		}
45385 #if defined(DUK_USE_DEBUGGER_INSPECT)
45386 		case DUK_DBG_CMD_GETHEAPOBJINFO: {
45387 			duk__debug_handle_get_heap_obj_info(thr, heap);
45388 			break;
45389 		}
45390 		case DUK_DBG_CMD_GETOBJPROPDESC: {
45391 			duk__debug_handle_get_obj_prop_desc(thr, heap);
45392 			break;
45393 		}
45394 		case DUK_DBG_CMD_GETOBJPROPDESCRANGE: {
45395 			duk__debug_handle_get_obj_prop_desc_range(thr, heap);
45396 			break;
45397 		}
45398 #endif  /* DUK_USE_DEBUGGER_INSPECT */
45399 		default: {
45400 			DUK_D(DUK_DPRINT("debug command unsupported: %d", (int) cmd));
45401 			duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "unsupported command");
45402 		}
45403 		}  /* switch cmd */
45404 		break;
45405 	}
45406 	case DUK_DBG_IB_REPLY: {
45407 		DUK_D(DUK_DPRINT("debug reply, skipping"));
45408 		break;
45409 	}
45410 	case DUK_DBG_IB_ERROR: {
45411 		DUK_D(DUK_DPRINT("debug error, skipping"));
45412 		break;
45413 	}
45414 	case DUK_DBG_IB_NOTIFY: {
45415 		DUK_D(DUK_DPRINT("debug notify, skipping"));
45416 		break;
45417 	}
45418 	default: {
45419 		DUK_D(DUK_DPRINT("invalid initial byte, drop connection: %d", (int) x));
45420 		goto fail;
45421 	}
45422 	}  /* switch initial byte */
45423 
45424 	DUK_ASSERT(duk_get_top(thr) >= entry_top);
45425 	duk_set_top(thr, entry_top);
45426 	duk__debug_skip_to_eom(thr);
45427 	return;
45428 
45429  fail:
45430 	DUK_ASSERT(duk_get_top(thr) >= entry_top);
45431 	duk_set_top(thr, entry_top);
45432 	DUK__SET_CONN_BROKEN(thr, 1);
45433 	return;
45434 }
45435 
45436 DUK_LOCAL void duk__check_resend_status(duk_hthread *thr) {
45437 	if (thr->heap->dbg_read_cb != NULL && thr->heap->dbg_state_dirty) {
45438 		duk_debug_send_status(thr);
45439 		thr->heap->dbg_state_dirty = 0;
45440 	}
45441 }
45442 
45443 DUK_INTERNAL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block) {
45444 #if defined(DUK_USE_ASSERTIONS)
45445 	duk_idx_t entry_top;
45446 #endif
45447 	duk_bool_t retval = 0;
45448 
45449 	DUK_ASSERT(thr != NULL);
45450 	DUK_ASSERT(thr->heap != NULL);
45451 #if defined(DUK_USE_ASSERTIONS)
45452 	entry_top = duk_get_top(thr);
45453 #endif
45454 
45455 	DUK_D(DUK_DPRINT("process debug messages: read_cb=%s, no_block=%ld, detaching=%ld, processing=%ld",
45456 	                 thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) no_block,
45457 	                 (long) thr->heap->dbg_detaching, (long) thr->heap->dbg_processing));
45458 	DUK_DD(DUK_DDPRINT("top at entry: %ld", (long) duk_get_top(thr)));
45459 
45460 	/* thr->heap->dbg_detaching may be != 0 if a debugger write outside
45461 	 * the message loop caused a transport error and detach1() to run.
45462 	 */
45463 	DUK_ASSERT(thr->heap->dbg_detaching == 0 || thr->heap->dbg_detaching == 1);
45464 	DUK_ASSERT(thr->heap->dbg_processing == 0);
45465 	thr->heap->dbg_processing = 1;
45466 
45467 	/* Ensure dirty state causes a Status even if never process any
45468 	 * messages.  This is expected by the bytecode executor when in
45469 	 * the running state.
45470 	 */
45471 	duk__check_resend_status(thr);
45472 
45473 	for (;;) {
45474 		/* Process messages until we're no longer paused or we peek
45475 		 * and see there's nothing to read right now.
45476 		 */
45477 		DUK_DD(DUK_DDPRINT("top at loop top: %ld", (long) duk_get_top(thr)));
45478 		DUK_ASSERT(thr->heap->dbg_processing == 1);
45479 
45480 		while (thr->heap->dbg_read_cb == NULL && thr->heap->dbg_detaching) {
45481 			/* Detach is pending; can be triggered from outside the
45482 			 * debugger loop (e.g. Status notify write error) or by
45483 			 * previous message handling.  Call detached callback
45484 			 * here, in a controlled state, to ensure a possible
45485 			 * reattach inside the detached_cb is handled correctly.
45486 			 *
45487 			 * Recheck for detach in a while loop: an immediate
45488 			 * reattach involves a call to duk_debugger_attach()
45489 			 * which writes a debugger handshake line immediately
45490 			 * inside the API call.  If the transport write fails
45491 			 * for that handshake, we can immediately end up in a
45492 			 * "transport broken, detaching" case several times here.
45493 			 * Loop back until we're either cleanly attached or
45494 			 * fully detached.
45495 			 *
45496 			 * NOTE: Reset dbg_processing = 1 forcibly, in case we
45497 			 * re-attached; duk_debugger_attach() sets dbg_processing
45498 			 * to 0 at the moment.
45499 			 */
45500 
45501 			DUK_D(DUK_DPRINT("detach pending (dbg_read_cb == NULL, dbg_detaching != 0), call detach2"));
45502 
45503 			duk__debug_do_detach2(thr->heap);
45504 			thr->heap->dbg_processing = 1;  /* may be set to 0 by duk_debugger_attach() inside callback */
45505 
45506 			DUK_D(DUK_DPRINT("after detach2 (and possible reattach): dbg_read_cb=%s, dbg_detaching=%ld",
45507 			                 thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) thr->heap->dbg_detaching));
45508 		}
45509 		DUK_ASSERT(thr->heap->dbg_detaching == 0);  /* true even with reattach */
45510 		DUK_ASSERT(thr->heap->dbg_processing == 1);  /* even after a detach and possible reattach */
45511 
45512 		if (thr->heap->dbg_read_cb == NULL) {
45513 			DUK_D(DUK_DPRINT("debug connection broken (and not detaching), stop processing messages"));
45514 			break;
45515 		}
45516 
45517 		if (!DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || no_block) {
45518 			if (!duk_debug_read_peek(thr)) {
45519 				/* Note: peek cannot currently trigger a detach
45520 				 * so the dbg_detaching == 0 assert outside the
45521 				 * loop is correct.
45522 				 */
45523 				DUK_D(DUK_DPRINT("processing debug message, peek indicated no data, stop processing messages"));
45524 				break;
45525 			}
45526 			DUK_D(DUK_DPRINT("processing debug message, peek indicated there is data, handle it"));
45527 		} else {
45528 			DUK_D(DUK_DPRINT("paused, process debug message, blocking if necessary"));
45529 		}
45530 
45531 		duk__check_resend_status(thr);
45532 		duk__debug_process_message(thr);
45533 		duk__check_resend_status(thr);
45534 
45535 		retval = 1;  /* processed one or more messages */
45536 	}
45537 
45538 	DUK_ASSERT(thr->heap->dbg_detaching == 0);
45539 	DUK_ASSERT(thr->heap->dbg_processing == 1);
45540 	thr->heap->dbg_processing = 0;
45541 
45542 	/* As an initial implementation, read flush after exiting the message
45543 	 * loop.  If transport is broken, this is a no-op (with debug logs).
45544 	 */
45545 	duk_debug_read_flush(thr);  /* this cannot initiate a detach */
45546 	DUK_ASSERT(thr->heap->dbg_detaching == 0);
45547 
45548 	DUK_DD(DUK_DDPRINT("top at exit: %ld", (long) duk_get_top(thr)));
45549 
45550 #if defined(DUK_USE_ASSERTIONS)
45551 	/* Easy to get wrong, so assert for it. */
45552 	DUK_ASSERT(entry_top == duk_get_top(thr));
45553 #endif
45554 
45555 	return retval;
45556 }
45557 
45558 /*
45559  *  Halt execution helper
45560  */
45561 
45562 /* Halt execution and enter a debugger message loop until execution is resumed
45563  * by the client.  PC for the current activation may be temporarily decremented
45564  * so that the "current" instruction will be shown by the client.  This helper
45565  * is callable from anywhere, also outside bytecode executor.
45566  */
45567 
45568 DUK_INTERNAL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc) {
45569 	duk_activation *act;
45570 	duk_hcompfunc *fun;
45571 	duk_instr_t *old_pc = NULL;
45572 
45573 	DUK_ASSERT(thr != NULL);
45574 	DUK_ASSERT(thr->heap != NULL);
45575 	DUK_ASSERT(duk_debug_is_attached(thr->heap));
45576 	DUK_ASSERT(thr->heap->dbg_processing == 0);
45577 	DUK_ASSERT(!duk_debug_is_paused(thr->heap));
45578 
45579 	duk_debug_set_paused(thr->heap);
45580 
45581 	act = thr->callstack_curr;
45582 
45583 	/* NOTE: act may be NULL if an error is thrown outside of any activation,
45584 	 * which may happen in the case of, e.g. syntax errors.
45585 	 */
45586 
45587 	/* Decrement PC if that was requested, this requires a PC sync. */
45588 	if (act != NULL) {
45589 		duk_hthread_sync_currpc(thr);
45590 		old_pc = act->curr_pc;
45591 		fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
45592 
45593 		/* Short circuit if is safe: if act->curr_pc != NULL, 'fun' is
45594 		 * guaranteed to be a non-NULL ECMAScript function.
45595 		 */
45596 		DUK_ASSERT(act->curr_pc == NULL ||
45597 		           (fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun)));
45598 		if (use_prev_pc &&
45599 		    act->curr_pc != NULL &&
45600 		    act->curr_pc > DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, fun)) {
45601 			act->curr_pc--;
45602 		}
45603 	}
45604 
45605 	/* Process debug messages until we are no longer paused. */
45606 
45607 	/* NOTE: This is a bit fragile.  It's important to ensure that
45608 	 * duk_debug_process_messages() never throws an error or
45609 	 * act->curr_pc will never be reset.
45610 	 */
45611 
45612 	thr->heap->dbg_state_dirty = 1;
45613 	while (DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap)) {
45614 		DUK_ASSERT(duk_debug_is_attached(thr->heap));
45615 		DUK_ASSERT(thr->heap->dbg_processing == 0);
45616 		duk_debug_process_messages(thr, 0 /*no_block*/);
45617 	}
45618 
45619 	/* XXX: Decrementing and restoring act->curr_pc works now, but if the
45620 	 * debugger message loop gains the ability to adjust the current PC
45621 	 * (e.g. a forced jump) restoring the PC here will break.  Another
45622 	 * approach would be to use a state flag for the "decrement 1 from
45623 	 * topmost activation's PC" and take it into account whenever dealing
45624 	 * with PC values.
45625 	 */
45626 	if (act != NULL) {
45627 		act->curr_pc = old_pc;  /* restore PC */
45628 	}
45629 }
45630 
45631 /*
45632  *  Breakpoint management
45633  */
45634 
45635 DUK_INTERNAL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line) {
45636 	duk_heap *heap;
45637 	duk_breakpoint *b;
45638 
45639 	/* Caller must trigger recomputation of active breakpoint list.  To
45640 	 * ensure stale values are not used if that doesn't happen, clear the
45641 	 * active breakpoint list here.
45642 	 */
45643 
45644 	DUK_ASSERT(thr != NULL);
45645 	DUK_ASSERT(filename != NULL);
45646 	heap = thr->heap;
45647 	DUK_ASSERT(heap != NULL);
45648 
45649 	if (heap->dbg_breakpoint_count >= DUK_HEAP_MAX_BREAKPOINTS) {
45650 		DUK_D(DUK_DPRINT("failed to add breakpoint for %O:%ld, all breakpoint slots used",
45651 		                 (duk_heaphdr *) filename, (long) line));
45652 		return -1;
45653 	}
45654 	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
45655 	b = heap->dbg_breakpoints + (heap->dbg_breakpoint_count++);
45656 	b->filename = filename;
45657 	b->line = line;
45658 	DUK_HSTRING_INCREF(thr, filename);
45659 
45660 	return (duk_small_int_t) (heap->dbg_breakpoint_count - 1);  /* index */
45661 }
45662 
45663 DUK_INTERNAL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index) {
45664 	duk_heap *heap;
45665 	duk_hstring *h;
45666 	duk_breakpoint *b;
45667 	duk_size_t move_size;
45668 
45669 	/* Caller must trigger recomputation of active breakpoint list.  To
45670 	 * ensure stale values are not used if that doesn't happen, clear the
45671 	 * active breakpoint list here.
45672 	 */
45673 
45674 	DUK_ASSERT(thr != NULL);
45675 	heap = thr->heap;
45676 	DUK_ASSERT(heap != NULL);
45677 	DUK_ASSERT(duk_debug_is_attached(thr->heap));
45678 	DUK_ASSERT_DISABLE(breakpoint_index >= 0);  /* unsigned */
45679 
45680 	if (breakpoint_index >= heap->dbg_breakpoint_count) {
45681 		DUK_D(DUK_DPRINT("invalid breakpoint index: %ld", (long) breakpoint_index));
45682 		return 0;
45683 	}
45684 	b = heap->dbg_breakpoints + breakpoint_index;
45685 
45686 	h = b->filename;
45687 	DUK_ASSERT(h != NULL);
45688 
45689 	move_size = sizeof(duk_breakpoint) * (heap->dbg_breakpoint_count - breakpoint_index - 1);
45690 	duk_memmove((void *) b,
45691 	            (const void *) (b + 1),
45692 	            (size_t) move_size);
45693 
45694 	heap->dbg_breakpoint_count--;
45695 	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
45696 
45697 	DUK_HSTRING_DECREF(thr, h);  /* side effects */
45698 	DUK_UNREF(h);  /* w/o refcounting */
45699 
45700 	/* Breakpoint entries above the used area are left as garbage. */
45701 
45702 	return 1;
45703 }
45704 
45705 /*
45706  *  Misc state management
45707  */
45708 
45709 DUK_INTERNAL duk_bool_t duk_debug_is_attached(duk_heap *heap) {
45710 	return (heap->dbg_read_cb != NULL);
45711 }
45712 
45713 DUK_INTERNAL duk_bool_t duk_debug_is_paused(duk_heap *heap) {
45714 	return (DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) != 0);
45715 }
45716 
45717 DUK_INTERNAL void duk_debug_set_paused(duk_heap *heap) {
45718 	if (duk_debug_is_paused(heap)) {
45719 		DUK_D(DUK_DPRINT("trying to set paused state when already paused, ignoring"));
45720 	} else {
45721 		DUK_HEAP_SET_DEBUGGER_PAUSED(heap);
45722 		heap->dbg_state_dirty = 1;
45723 		duk_debug_clear_pause_state(heap);
45724 		DUK_ASSERT(heap->ms_running == 0);  /* debugger can't be triggered within mark-and-sweep */
45725 		heap->ms_running = 1;  /* prevent mark-and-sweep, prevent refzero queueing */
45726 		heap->ms_prevent_count++;
45727 		DUK_ASSERT(heap->ms_prevent_count != 0);  /* Wrap. */
45728 		DUK_ASSERT(heap->heap_thread != NULL);
45729 	}
45730 }
45731 
45732 DUK_INTERNAL void duk_debug_clear_paused(duk_heap *heap) {
45733 	if (duk_debug_is_paused(heap)) {
45734 		DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap);
45735 		heap->dbg_state_dirty = 1;
45736 		duk_debug_clear_pause_state(heap);
45737 		DUK_ASSERT(heap->ms_running == 1);
45738 		DUK_ASSERT(heap->ms_prevent_count > 0);
45739 		heap->ms_prevent_count--;
45740 		heap->ms_running = 0;
45741 		DUK_ASSERT(heap->heap_thread != NULL);
45742 	} else {
45743 		DUK_D(DUK_DPRINT("trying to clear paused state when not paused, ignoring"));
45744 	}
45745 }
45746 
45747 DUK_INTERNAL void duk_debug_clear_pause_state(duk_heap *heap) {
45748 	heap->dbg_pause_flags = 0;
45749 	heap->dbg_pause_act = NULL;
45750 	heap->dbg_pause_startline = 0;
45751 }
45752 
45753 #else  /* DUK_USE_DEBUGGER_SUPPORT */
45754 
45755 /* No debugger support. */
45756 
45757 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
45758 
45759 /* automatic undefs */
45760 #undef DUK__DBG_TPORT_ENTER
45761 #undef DUK__DBG_TPORT_EXIT
45762 #undef DUK__SET_CONN_BROKEN
45763 #line 1 "duk_error_augment.c"
45764 /*
45765  *  Augmenting errors at their creation site and their throw site.
45766  *
45767  *  When errors are created, traceback data is added by built-in code
45768  *  and a user error handler (if defined) can process or replace the
45769  *  error.  Similarly, when errors are thrown, a user error handler
45770  *  (if defined) can process or replace the error.
45771  *
45772  *  Augmentation and other processing at error creation time is nice
45773  *  because an error is only created once, but it may be thrown and
45774  *  rethrown multiple times.  User error handler registered for processing
45775  *  an error at its throw site must be careful to handle rethrowing in
45776  *  a useful manner.
45777  *
45778  *  Error augmentation may throw an internal error (e.g. alloc error).
45779  *
45780  *  ECMAScript allows throwing any values, so all values cannot be
45781  *  augmented.  Currently, the built-in augmentation at error creation
45782  *  only augments error values which are Error instances (= have the
45783  *  built-in Error.prototype in their prototype chain) and are also
45784  *  extensible.  User error handlers have no limitations in this respect.
45785  */
45786 
45787 /* #include duk_internal.h -> already included */
45788 
45789 /*
45790  *  Helper for calling a user error handler.
45791  *
45792  *  'thr' must be the currently active thread; the error handler is called
45793  *  in its context.  The valstack of 'thr' must have the error value on
45794  *  top, and will be replaced by another error value based on the return
45795  *  value of the error handler.
45796  *
45797  *  The helper calls duk_handle_call() recursively in protected mode.
45798  *  Before that call happens, no longjmps should happen; as a consequence,
45799  *  we must assume that the valstack contains enough temporary space for
45800  *  arguments and such.
45801  *
45802  *  While the error handler runs, any errors thrown will not trigger a
45803  *  recursive error handler call (this is implemented using a heap level
45804  *  flag which will "follow" through any coroutines resumed inside the
45805  *  error handler).  If the error handler is not callable or throws an
45806  *  error, the resulting error replaces the original error (for Duktape
45807  *  internal errors, duk_error_throw.c further substitutes this error with
45808  *  a DoubleError which is not ideal).  This would be easy to change and
45809  *  even signal to the caller.
45810  *
45811  *  The user error handler is stored in 'Duktape.errCreate' or
45812  *  'Duktape.errThrow' depending on whether we're augmenting the error at
45813  *  creation or throw time.  There are several alternatives to this approach,
45814  *  see doc/error-objects.rst for discussion.
45815  *
45816  *  Note: since further longjmp()s may occur while calling the error handler
45817  *  (for many reasons, e.g. a labeled 'break' inside the handler), the
45818  *  caller can make no assumptions on the thr->heap->lj state after the
45819  *  call (this affects especially duk_error_throw.c).  This is not an issue
45820  *  as long as the caller writes to the lj state only after the error handler
45821  *  finishes.
45822  */
45823 
45824 #if defined(DUK_USE_ERRTHROW) || defined(DUK_USE_ERRCREATE)
45825 DUK_LOCAL void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_cb) {
45826 	duk_tval *tv_hnd;
45827 	duk_int_t rc;
45828 
45829 	DUK_ASSERT(thr != NULL);
45830 	DUK_ASSERT(thr->heap != NULL);
45831 	DUK_ASSERT_STRIDX_VALID(stridx_cb);
45832 
45833 	if (thr->heap->augmenting_error) {
45834 		DUK_D(DUK_DPRINT("recursive call to error augmentation, ignore"));
45835 		return;
45836 	}
45837 
45838 	/*
45839 	 *  Check whether or not we have an error handler.
45840 	 *
45841 	 *  We must be careful of not triggering an error when looking up the
45842 	 *  property.  For instance, if the property is a getter, we don't want
45843 	 *  to call it, only plain values are allowed.  The value, if it exists,
45844 	 *  is not checked.  If the value is not a function, a TypeError happens
45845 	 *  when it is called and that error replaces the original one.
45846 	 */
45847 
45848 	DUK_ASSERT_VALSTACK_SPACE(thr, 4);  /* 3 entries actually needed below */
45849 
45850 	/* [ ... errval ] */
45851 
45852 	if (thr->builtins[DUK_BIDX_DUKTAPE] == NULL) {
45853 		/* When creating built-ins, some of the built-ins may not be set
45854 		 * and we want to tolerate that when throwing errors.
45855 		 */
45856 		DUK_DD(DUK_DDPRINT("error occurred when DUK_BIDX_DUKTAPE is NULL, ignoring"));
45857 		return;
45858 	}
45859 	tv_hnd = duk_hobject_find_existing_entry_tval_ptr(thr->heap,
45860 	                                                  thr->builtins[DUK_BIDX_DUKTAPE],
45861 	                                                  DUK_HTHREAD_GET_STRING(thr, stridx_cb));
45862 	if (tv_hnd == NULL) {
45863 		DUK_DD(DUK_DDPRINT("error handler does not exist or is not a plain value: %!T",
45864 		                   (duk_tval *) tv_hnd));
45865 		return;
45866 	}
45867 	DUK_DDD(DUK_DDDPRINT("error handler dump (callability not checked): %!T",
45868 	                     (duk_tval *) tv_hnd));
45869 	duk_push_tval(thr, tv_hnd);
45870 
45871 	/* [ ... errval errhandler ] */
45872 
45873 	duk_insert(thr, -2);  /* -> [ ... errhandler errval ] */
45874 	duk_push_undefined(thr);
45875 	duk_insert(thr, -2);  /* -> [ ... errhandler undefined(= this) errval ] */
45876 
45877 	/* [ ... errhandler undefined errval ] */
45878 
45879 	/*
45880 	 *  heap->augmenting_error prevents recursive re-entry and also causes
45881 	 *  call handling to use a larger (but not unbounded) call stack limit
45882 	 *  for the duration of error augmentation.
45883 	 *
45884 	 *  We ignore errors now: a success return and an error value both
45885 	 *  replace the original error value.  (This would be easy to change.)
45886 	 */
45887 
45888 	DUK_ASSERT(thr->heap->augmenting_error == 0);
45889 	thr->heap->augmenting_error = 1;
45890 
45891 	rc = duk_pcall_method(thr, 1);
45892 	DUK_UNREF(rc);  /* no need to check now: both success and error are OK */
45893 
45894 	DUK_ASSERT(thr->heap->augmenting_error == 1);
45895 	thr->heap->augmenting_error = 0;
45896 
45897 	/* [ ... errval ] */
45898 }
45899 #endif  /* DUK_USE_ERRTHROW || DUK_USE_ERRCREATE */
45900 
45901 /*
45902  *  Add ._Tracedata to an error on the stack top.
45903  */
45904 
45905 #if defined(DUK_USE_TRACEBACKS)
45906 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) {
45907 	duk_activation *act;
45908 	duk_int_t depth;
45909 	duk_int_t arr_size;
45910 	duk_tval *tv;
45911 	duk_hstring *s;
45912 	duk_uint32_t u32;
45913 	duk_double_t d;
45914 
45915 	DUK_ASSERT(thr != NULL);
45916 	DUK_ASSERT(thr_callstack != NULL);
45917 
45918 	/* [ ... error ] */
45919 
45920 	/*
45921 	 *  The traceback format is pretty arcane in an attempt to keep it compact
45922 	 *  and cheap to create.  It may change arbitrarily from version to version.
45923 	 *  It should be decoded/accessed through version specific accessors only.
45924 	 *
45925 	 *  See doc/error-objects.rst.
45926 	 */
45927 
45928 	DUK_DDD(DUK_DDDPRINT("adding traceback to object: %!T",
45929 	                     (duk_tval *) duk_get_tval(thr, -1)));
45930 
45931 	/* Preallocate array to correct size, so that we can just write out
45932 	 * the _Tracedata values into the array part.
45933 	 */
45934 	act = thr->callstack_curr;
45935 	depth = DUK_USE_TRACEBACK_DEPTH;
45936 	DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX);  /* callstack limits */
45937 	if (depth > (duk_int_t) thr_callstack->callstack_top) {
45938 		depth = (duk_int_t) thr_callstack->callstack_top;
45939 	}
45940 	if (depth > 0) {
45941 		if (flags & DUK_AUGMENT_FLAG_SKIP_ONE) {
45942 			DUK_ASSERT(act != NULL);
45943 			act = act->parent;
45944 			depth--;
45945 		}
45946 	}
45947 	arr_size = depth * 2;
45948 	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
45949 		arr_size += 2;
45950 	}
45951 	if (c_filename) {
45952 		/* We need the C filename to be interned before getting the
45953 		 * array part pointer to avoid any GC interference while the
45954 		 * array part is populated.
45955 		 */
45956 		duk_push_string(thr, c_filename);
45957 		arr_size += 2;
45958 	}
45959 
45960 	/* XXX: uninitialized would be OK */
45961 	DUK_D(DUK_DPRINT("preallocated _Tracedata to %ld items", (long) arr_size));
45962 	tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) arr_size);
45963 	DUK_ASSERT(arr_size == 0 || tv != NULL);
45964 
45965 	/* Compiler SyntaxErrors (and other errors) come first, and are
45966 	 * blamed by default (not flagged "noblame").
45967 	 */
45968 	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
45969 		s = thr->compile_ctx->h_filename;
45970 		DUK_TVAL_SET_STRING(tv, s);
45971 		DUK_HSTRING_INCREF(thr, s);
45972 		tv++;
45973 
45974 		u32 = (duk_uint32_t) thr->compile_ctx->curr_token.start_line;  /* (flags<<32) + (line), flags = 0 */
45975 		DUK_TVAL_SET_U32(tv, u32);
45976 		tv++;
45977 	}
45978 
45979 	/* Filename/line from C macros (__FILE__, __LINE__) are added as an
45980 	 * entry with a special format: (string, number).  The number contains
45981 	 * the line and flags.
45982 	 */
45983 
45984 	/* [ ... error c_filename? arr ] */
45985 
45986 	if (c_filename) {
45987 		DUK_ASSERT(DUK_TVAL_IS_STRING(thr->valstack_top - 2));
45988 		s = DUK_TVAL_GET_STRING(thr->valstack_top - 2);  /* interned c_filename */
45989 		DUK_ASSERT(s != NULL);
45990 		DUK_TVAL_SET_STRING(tv, s);
45991 		DUK_HSTRING_INCREF(thr, s);
45992 		tv++;
45993 
45994 		d = ((flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE) ? ((duk_double_t) DUK_TB_FLAG_NOBLAME_FILELINE) * DUK_DOUBLE_2TO32 : 0.0) +
45995 		    (duk_double_t) c_line;
45996 		DUK_TVAL_SET_DOUBLE(tv, d);
45997 		tv++;
45998 	}
45999 
46000 	/* Traceback depth doesn't take into account the filename/line
46001 	 * special handling above (intentional).
46002 	 */
46003 	for (; depth-- > 0; act = act->parent) {
46004 		duk_uint32_t pc;
46005 		duk_tval *tv_src;
46006 
46007 		/* [... arr] */
46008 
46009 		DUK_ASSERT(act != NULL);  /* depth check above, assumes book-keeping is correct */
46010 		DUK_ASSERT_DISABLE(act->pc >= 0);  /* unsigned */
46011 
46012 		/* Add function object. */
46013 		tv_src = &act->tv_func;  /* object (function) or lightfunc */
46014 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_src) || DUK_TVAL_IS_LIGHTFUNC(tv_src));
46015 		DUK_TVAL_SET_TVAL(tv, tv_src);
46016 		DUK_TVAL_INCREF(thr, tv);
46017 		tv++;
46018 
46019 		/* Add a number containing: pc, activation flags.
46020 		 *
46021 		 * PC points to next instruction, find offending PC.  Note that
46022 		 * PC == 0 for native code.
46023 		 */
46024 		pc = (duk_uint32_t) duk_hthread_get_act_prev_pc(thr_callstack, act);
46025 		DUK_ASSERT_DISABLE(pc >= 0);  /* unsigned */
46026 		DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32);  /* assume PC is at most 32 bits and non-negative */
46027 		d = ((duk_double_t) act->flags) * DUK_DOUBLE_2TO32 + (duk_double_t) pc;
46028 		DUK_TVAL_SET_DOUBLE(tv, d);
46029 		tv++;
46030 	}
46031 
46032 #if defined(DUK_USE_ASSERTIONS)
46033 	{
46034 		duk_harray *a;
46035 		a = (duk_harray *) duk_known_hobject(thr, -1);
46036 		DUK_ASSERT(a != NULL);
46037 		DUK_ASSERT((duk_uint32_t) (tv - DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a)) == a->length);
46038 		DUK_ASSERT(a->length == (duk_uint32_t) arr_size);
46039 	}
46040 #endif
46041 
46042 	/* [ ... error c_filename? arr ] */
46043 
46044 	if (c_filename) {
46045 		duk_remove_m2(thr);
46046 	}
46047 
46048 	/* [ ... error arr ] */
46049 
46050 	duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INT_TRACEDATA);  /* -> [ ... error ] */
46051 }
46052 #endif  /* DUK_USE_TRACEBACKS */
46053 
46054 /*
46055  *  Add .fileName and .lineNumber to an error on the stack top.
46056  */
46057 
46058 #if defined(DUK_USE_AUGMENT_ERROR_CREATE) && !defined(DUK_USE_TRACEBACKS)
46059 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) {
46060 #if defined(DUK_USE_ASSERTIONS)
46061 	duk_int_t entry_top;
46062 #endif
46063 
46064 #if defined(DUK_USE_ASSERTIONS)
46065 	entry_top = duk_get_top(thr);
46066 #endif
46067 
46068 	/*
46069 	 *  If tracebacks are disabled, 'fileName' and 'lineNumber' are added
46070 	 *  as plain own properties.  Since Error.prototype has accessors of
46071 	 *  the same name, we need to define own properties directly (cannot
46072 	 *  just use e.g. duk_put_prop_stridx).  Existing properties are not
46073 	 *  overwritten in case they already exist.
46074 	 */
46075 
46076 	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
46077 		/* Compiler SyntaxError (or other error) gets the primary blame.
46078 		 * Currently no flag to prevent blaming.
46079 		 */
46080 		duk_push_uint(thr, (duk_uint_t) thr->compile_ctx->curr_token.start_line);
46081 		duk_push_hstring(thr, thr->compile_ctx->h_filename);
46082 	} else if (c_filename && (flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE) == 0) {
46083 		/* C call site gets blamed next, unless flagged not to do so.
46084 		 * XXX: file/line is disabled in minimal builds, so disable this
46085 		 * too when appropriate.
46086 		 */
46087 		duk_push_int(thr, c_line);
46088 		duk_push_string(thr, c_filename);
46089 	} else {
46090 		/* Finally, blame the innermost callstack entry which has a
46091 		 * .fileName property.
46092 		 */
46093 		duk_small_uint_t depth;
46094 		duk_uint32_t ecma_line;
46095 		duk_activation *act;
46096 
46097 		DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX);  /* callstack limits */
46098 		depth = DUK_USE_TRACEBACK_DEPTH;
46099 		if (depth > thr_callstack->callstack_top) {
46100 			depth = thr_callstack->callstack_top;
46101 		}
46102 		for (act = thr_callstack->callstack_curr; depth-- > 0; act = act->parent) {
46103 			duk_hobject *func;
46104 			duk_uint32_t pc;
46105 
46106 			DUK_ASSERT(act != NULL);
46107 			func = DUK_ACT_GET_FUNC(act);
46108 			if (func == NULL) {
46109 				/* Lightfunc, not blamed now. */
46110 				continue;
46111 			}
46112 
46113 			/* PC points to next instruction, find offending PC,
46114 			 * PC == 0 for native code.
46115 			 */
46116 			pc = duk_hthread_get_act_prev_pc(thr, act);  /* thr argument only used for thr->heap, so specific thread doesn't matter */
46117 			DUK_UNREF(pc);
46118 			DUK_ASSERT_DISABLE(pc >= 0);  /* unsigned */
46119 			DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32);  /* assume PC is at most 32 bits and non-negative */
46120 
46121 			duk_push_hobject(thr, func);
46122 
46123 			/* [ ... error func ] */
46124 
46125 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);
46126 			if (!duk_is_string_notsymbol(thr, -1)) {
46127 				duk_pop_2(thr);
46128 				continue;
46129 			}
46130 
46131 			/* [ ... error func fileName ] */
46132 
46133 			ecma_line = 0;
46134 #if defined(DUK_USE_PC2LINE)
46135 			if (DUK_HOBJECT_IS_COMPFUNC(func)) {
46136 				ecma_line = duk_hobject_pc2line_query(thr, -2, (duk_uint_fast32_t) pc);
46137 			} else {
46138 				/* Native function, no relevant lineNumber. */
46139 			}
46140 #endif  /* DUK_USE_PC2LINE */
46141 			duk_push_u32(thr, ecma_line);
46142 
46143 			/* [ ... error func fileName lineNumber ] */
46144 
46145 			duk_replace(thr, -3);
46146 
46147 			/* [ ... error lineNumber fileName ] */
46148 			goto define_props;
46149 		}
46150 
46151 		/* No activation matches, use undefined for both .fileName and
46152 		 * .lineNumber (matches what we do with a _Tracedata based
46153 		 * no-match lookup.
46154 		 */
46155 		duk_push_undefined(thr);
46156 		duk_push_undefined(thr);
46157 	}
46158 
46159  define_props:
46160 	/* [ ... error lineNumber fileName ] */
46161 #if defined(DUK_USE_ASSERTIONS)
46162 	DUK_ASSERT(duk_get_top(thr) == entry_top + 2);
46163 #endif
46164 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C | DUK_PROPDESC_FLAG_NO_OVERWRITE);
46165 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LINE_NUMBER, DUK_PROPDESC_FLAGS_C | DUK_PROPDESC_FLAG_NO_OVERWRITE);
46166 }
46167 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE && !DUK_USE_TRACEBACKS */
46168 
46169 /*
46170  *  Add line number to a compiler error.
46171  */
46172 
46173 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
46174 DUK_LOCAL void duk__add_compiler_error_line(duk_hthread *thr) {
46175 
46176 	/* Append a "(line NNN)" to the "message" property of any error
46177 	 * thrown during compilation.  Usually compilation errors are
46178 	 * SyntaxErrors but they can also be out-of-memory errors and
46179 	 * the like.
46180 	 */
46181 
46182 	/* [ ... error ] */
46183 
46184 	DUK_ASSERT(duk_is_object(thr, -1));
46185 
46186 	if (!(thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL)) {
46187 		return;
46188 	}
46189 
46190 	DUK_DDD(DUK_DDDPRINT("compile error, before adding line info: %!T",
46191 	                     (duk_tval *) duk_get_tval(thr, -1)));
46192 
46193 	if (duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_MESSAGE)) {
46194 		duk_push_sprintf(thr, " (line %ld)", (long) thr->compile_ctx->curr_token.start_line);
46195 		duk_concat(thr, 2);
46196 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE);
46197 	} else {
46198 		duk_pop(thr);
46199 	}
46200 
46201 	DUK_DDD(DUK_DDDPRINT("compile error, after adding line info: %!T",
46202 	                     (duk_tval *) duk_get_tval(thr, -1)));
46203 }
46204 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE */
46205 
46206 /*
46207  *  Augment an error being created using Duktape specific properties
46208  *  like _Tracedata or .fileName/.lineNumber.
46209  */
46210 
46211 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
46212 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) {
46213 #if defined(DUK_USE_ASSERTIONS)
46214 	duk_int_t entry_top;
46215 #endif
46216 
46217 #if defined(DUK_USE_ASSERTIONS)
46218 	entry_top = duk_get_top(thr);
46219 #endif
46220 	DUK_ASSERT(obj != NULL);
46221 
46222 	DUK_UNREF(obj);  /* unreferenced w/o tracebacks */
46223 
46224 	duk__add_compiler_error_line(thr);
46225 
46226 #if defined(DUK_USE_TRACEBACKS)
46227 	/* If tracebacks are enabled, the '_Tracedata' property is the only
46228 	 * thing we need: 'fileName' and 'lineNumber' are virtual properties
46229 	 * which use '_Tracedata'.
46230 	 */
46231 	if (duk_hobject_hasprop_raw(thr, obj, DUK_HTHREAD_STRING_INT_TRACEDATA(thr))) {
46232 		DUK_DDD(DUK_DDDPRINT("error value already has a '_Tracedata' property, not modifying it"));
46233 	} else {
46234 		duk__add_traceback(thr, thr_callstack, c_filename, c_line, flags);
46235 	}
46236 #else
46237 	/* Without tracebacks the concrete .fileName and .lineNumber need
46238 	 * to be added directly.
46239 	 */
46240 	duk__add_fileline(thr, thr_callstack, c_filename, c_line, flags);
46241 #endif
46242 
46243 #if defined(DUK_USE_ASSERTIONS)
46244 	DUK_ASSERT(duk_get_top(thr) == entry_top);
46245 #endif
46246 }
46247 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE */
46248 
46249 /*
46250  *  Augment an error at creation time with _Tracedata/fileName/lineNumber
46251  *  and allow a user error handler (if defined) to process/replace the error.
46252  *  The error to be augmented is at the stack top.
46253  *
46254  *  thr: thread containing the error value
46255  *  thr_callstack: thread which should be used for generating callstack etc.
46256  *  c_filename: C __FILE__ related to the error
46257  *  c_line: C __LINE__ related to the error
46258  *  flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE:
46259  *      if true, don't fileName/line as error source, otherwise use traceback
46260  *      (needed because user code filename/line are reported but internal ones
46261  *      are not)
46262  */
46263 
46264 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
46265 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) {
46266 	duk_hobject *obj;
46267 
46268 	DUK_ASSERT(thr != NULL);
46269 	DUK_ASSERT(thr_callstack != NULL);
46270 
46271 	/* [ ... error ] */
46272 
46273 	/*
46274 	 *  Criteria for augmenting:
46275 	 *
46276 	 *   - augmentation enabled in build (naturally)
46277 	 *   - error value internal prototype chain contains the built-in
46278 	 *     Error prototype object (i.e. 'val instanceof Error')
46279 	 *
46280 	 *  Additional criteria for built-in augmenting:
46281 	 *
46282 	 *   - error value is an extensible object
46283 	 */
46284 
46285 	obj = duk_get_hobject(thr, -1);
46286 	if (!obj) {
46287 		DUK_DDD(DUK_DDDPRINT("value is not an object, skip both built-in and user augment"));
46288 		return;
46289 	}
46290 	if (!duk_hobject_prototype_chain_contains(thr, obj, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {
46291 		/* If the value has a prototype loop, it's critical not to
46292 		 * throw here.  Instead, assume the value is not to be
46293 		 * augmented.
46294 		 */
46295 		DUK_DDD(DUK_DDDPRINT("value is not an error instance, skip both built-in and user augment"));
46296 		return;
46297 	}
46298 	if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
46299 		DUK_DDD(DUK_DDDPRINT("error meets criteria, built-in augment"));
46300 		duk__err_augment_builtin_create(thr, thr_callstack, c_filename, c_line, obj, flags);
46301 	} else {
46302 		DUK_DDD(DUK_DDDPRINT("error does not meet criteria, no built-in augment"));
46303 	}
46304 
46305 	/* [ ... error ] */
46306 
46307 #if defined(DUK_USE_ERRCREATE)
46308 	duk__err_augment_user(thr, DUK_STRIDX_ERR_CREATE);
46309 #endif
46310 }
46311 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE */
46312 
46313 /*
46314  *  Augment an error at throw time; allow a user error handler (if defined)
46315  *  to process/replace the error.  The error to be augmented is at the
46316  *  stack top.
46317  */
46318 
46319 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
46320 DUK_INTERNAL void duk_err_augment_error_throw(duk_hthread *thr) {
46321 #if defined(DUK_USE_ERRTHROW)
46322 	duk__err_augment_user(thr, DUK_STRIDX_ERR_THROW);
46323 #endif  /* DUK_USE_ERRTHROW */
46324 }
46325 #endif  /* DUK_USE_AUGMENT_ERROR_THROW */
46326 #line 1 "duk_error_longjmp.c"
46327 /*
46328  *  Do a longjmp call, calling the fatal error handler if no
46329  *  catchpoint exists.
46330  */
46331 
46332 /* #include duk_internal.h -> already included */
46333 
46334 #if defined(DUK_USE_PREFER_SIZE)
46335 DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_minimal(duk_hthread *thr));
46336 DUK_LOCAL void duk__uncaught_minimal(duk_hthread *thr) {
46337 	(void) duk_fatal(thr, "uncaught error");
46338 	DUK_WO_NORETURN(return;);
46339 }
46340 #endif
46341 
46342 #if 0
46343 DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_readable(duk_hthread *thr));
46344 DUK_LOCAL void duk__uncaught_readable(duk_hthread *thr) {
46345 	const char *summary;
46346 	char buf[DUK_USE_FATAL_MAXLEN];
46347 
46348 	summary = duk_push_string_tval_readable(thr, &thr->heap->lj.value1);
46349 	DUK_SNPRINTF(buf, sizeof(buf), "uncaught: %s", summary);
46350 	buf[sizeof(buf) - 1] = (char) 0;
46351 	(void) duk_fatal(thr, (const char *) buf);
46352 	DUK_WO_NORETURN(return;);
46353 }
46354 #endif
46355 
46356 #if !defined(DUK_USE_PREFER_SIZE)
46357 DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_error_aware(duk_hthread *thr));
46358 DUK_LOCAL void duk__uncaught_error_aware(duk_hthread *thr) {
46359 	const char *summary;
46360 	char buf[DUK_USE_FATAL_MAXLEN];
46361 
46362 	summary = duk_push_string_tval_readable_error(thr, &thr->heap->lj.value1);
46363 	DUK_ASSERT(summary != NULL);
46364 	DUK_SNPRINTF(buf, sizeof(buf), "uncaught: %s", summary);
46365 	buf[sizeof(buf) - 1] = (char) 0;
46366 	(void) duk_fatal(thr, (const char *) buf);
46367 	DUK_WO_NORETURN(return;);
46368 }
46369 #endif
46370 
46371 DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr) {
46372 	DUK_ASSERT(thr != NULL);
46373 	DUK_ASSERT(thr->heap != NULL);
46374 
46375 	DUK_DD(DUK_DDPRINT("longjmp error: type=%d iserror=%d value1=%!T value2=%!T",
46376 	                   (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
46377 	                   &thr->heap->lj.value1, &thr->heap->lj.value2));
46378 
46379 	/* Prevent finalizer execution during error handling.  All error
46380 	 * handling sites will process pending finalizers once error handling
46381 	 * is complete and we're ready for the side effects.  Does not prevent
46382 	 * refzero freeing or mark-and-sweep during error handling.
46383 	 *
46384 	 * NOTE: when we come here some calling code may have used DECREF
46385 	 * NORZ macros without an explicit DUK_REFZERO_CHECK_xxx() call.
46386 	 * We don't want to do it here because it would just check for
46387 	 * pending finalizers and we prevent that explicitly.  Instead,
46388 	 * the error catcher will run the finalizers once error handling
46389 	 * is complete.
46390 	 */
46391 
46392 	DUK_ASSERT_LJSTATE_SET(thr->heap);
46393 
46394 	thr->heap->pf_prevent_count++;
46395 	DUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */
46396 
46397 #if defined(DUK_USE_ASSERTIONS)
46398 	/* XXX: set this immediately when longjmp state is set */
46399 	DUK_ASSERT(thr->heap->error_not_allowed == 0);  /* Detect error within critical section. */
46400 	thr->heap->error_not_allowed = 1;
46401 #endif
46402 
46403 	DUK_DD(DUK_DDPRINT("about to longjmp, pf_prevent_count=%ld", (long) thr->heap->pf_prevent_count));
46404 
46405 	/* If we don't have a jmpbuf_ptr, there is little we can do except
46406 	 * cause a fatal error.  The caller's expectation is that we never
46407 	 * return.
46408 	 */
46409 	if (!thr->heap->lj.jmpbuf_ptr) {
46410 		DUK_D(DUK_DPRINT("uncaught error: type=%d iserror=%d value1=%!T value2=%!T",
46411 		                 (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
46412 		                 &thr->heap->lj.value1, &thr->heap->lj.value2));
46413 
46414 #if defined(DUK_USE_PREFER_SIZE)
46415 		duk__uncaught_minimal(thr);
46416 #else
46417 		duk__uncaught_error_aware(thr);
46418 #endif
46419 		DUK_UNREACHABLE();
46420 	}
46421 
46422 #if defined(DUK_USE_CPP_EXCEPTIONS)
46423 	throw duk_internal_exception();  /* dummy */
46424 #else
46425 	DUK_LONGJMP(thr->heap->lj.jmpbuf_ptr->jb);
46426 #endif
46427 
46428 	DUK_UNREACHABLE();
46429 }
46430 #line 1 "duk_error_misc.c"
46431 /*
46432  *  Error helpers
46433  */
46434 
46435 /* #include duk_internal.h -> already included */
46436 
46437 /*
46438  *  Helper to walk the thread chain and see if there is an active error
46439  *  catcher.  Protected calls or finally blocks aren't considered catching.
46440  */
46441 
46442 #if defined(DUK_USE_DEBUGGER_SUPPORT)
46443 DUK_LOCAL duk_bool_t duk__have_active_catcher(duk_hthread *thr) {
46444 	/* As noted above, a protected API call won't be counted as a
46445 	 * catcher.  This is usually convenient, e.g. in the case of a top-
46446 	 * level duk_pcall(), but may not always be desirable.  Perhaps add
46447 	 * an argument to treat them as catchers?
46448 	 */
46449 
46450 	duk_activation *act;
46451 	duk_catcher *cat;
46452 
46453 	DUK_ASSERT(thr != NULL);
46454 
46455 	for (; thr != NULL; thr = thr->resumer) {
46456 		for (act = thr->callstack_curr; act != NULL; act = act->parent) {
46457 			for (cat = act->cat; cat != NULL; cat = cat->parent) {
46458 				if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
46459 					return 1;  /* all we need to know */
46460 				}
46461 			}
46462 		}
46463 	}
46464 	return 0;
46465 }
46466 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
46467 
46468 /*
46469  *  Get prototype object for an integer error code.
46470  */
46471 
46472 DUK_INTERNAL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t code) {
46473 	switch (code) {
46474 	case DUK_ERR_EVAL_ERROR:
46475 		return thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE];
46476 	case DUK_ERR_RANGE_ERROR:
46477 		return thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE];
46478 	case DUK_ERR_REFERENCE_ERROR:
46479 		return thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE];
46480 	case DUK_ERR_SYNTAX_ERROR:
46481 		return thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE];
46482 	case DUK_ERR_TYPE_ERROR:
46483 		return thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE];
46484 	case DUK_ERR_URI_ERROR:
46485 		return thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE];
46486 	case DUK_ERR_ERROR:
46487 	default:
46488 		return thr->builtins[DUK_BIDX_ERROR_PROTOTYPE];
46489 	}
46490 }
46491 
46492 /*
46493  *  Helper for debugger throw notify and pause-on-uncaught integration.
46494  */
46495 
46496 #if defined(DUK_USE_DEBUGGER_SUPPORT)
46497 DUK_INTERNAL void duk_err_check_debugger_integration(duk_hthread *thr) {
46498 	duk_bool_t uncaught;
46499 	duk_tval *tv_obj;
46500 
46501 	/* If something is thrown with the debugger attached and nobody will
46502 	 * catch it, execution is paused before the longjmp, turning over
46503 	 * control to the debug client.  This allows local state to be examined
46504 	 * before the stack is unwound.  Errors are not intercepted when debug
46505 	 * message loop is active (e.g. for Eval).
46506 	 */
46507 
46508 	DUK_ASSERT(thr != NULL);
46509 	DUK_ASSERT(thr->heap != NULL);
46510 
46511 	/* XXX: Allow customizing the pause and notify behavior at runtime
46512 	 * using debugger runtime flags.  For now the behavior is fixed using
46513 	 * config options.
46514 	 */
46515 
46516 	if (!duk_debug_is_attached(thr->heap) ||
46517 	    thr->heap->dbg_processing ||
46518 	    thr->heap->lj.type != DUK_LJ_TYPE_THROW ||
46519 	    thr->heap->creating_error) {
46520 		DUK_D(DUK_DPRINT("skip debugger error integration; not attached, debugger processing, not THROW, or error thrown while creating error"));
46521 		return;
46522 	}
46523 
46524 	/* Don't intercept a DoubleError, we may have caused the initial double
46525 	 * fault and attempting to intercept it will cause us to be called
46526 	 * recursively and exhaust the C stack.  (This should no longer happen
46527 	 * for the initial throw because DoubleError path doesn't do a debugger
46528 	 * integration check, but it might happen for rethrows.)
46529 	 */
46530 	tv_obj = &thr->heap->lj.value1;
46531 	if (DUK_TVAL_IS_OBJECT(tv_obj) && DUK_TVAL_GET_OBJECT(tv_obj) == thr->builtins[DUK_BIDX_DOUBLE_ERROR]) {
46532 		DUK_D(DUK_DPRINT("built-in DoubleError instance (re)thrown, not intercepting"));
46533 		return;
46534 	}
46535 
46536 	uncaught = !duk__have_active_catcher(thr);
46537 
46538 	/* Debugger code expects the value at stack top.  This also serves
46539 	 * as a backup: we need to store/restore the longjmp state because
46540 	 * when the debugger is paused Eval commands may be executed and
46541 	 * they can arbitrarily clobber the longjmp state.
46542 	 */
46543 	duk_push_tval(thr, tv_obj);
46544 
46545 	/* Store and reset longjmp state. */
46546 	DUK_ASSERT_LJSTATE_SET(thr->heap);
46547 	DUK_TVAL_DECREF_NORZ(thr, tv_obj);
46548 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));  /* Always for THROW type. */
46549 	DUK_TVAL_SET_UNDEFINED(tv_obj);
46550 	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
46551 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
46552 
46553 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
46554 	/* Report it to the debug client */
46555 	DUK_D(DUK_DPRINT("throw with debugger attached, report to client"));
46556 	duk_debug_send_throw(thr, uncaught);
46557 #endif
46558 
46559 	if (uncaught) {
46560 		if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_UNCAUGHT_ERROR) {
46561 			DUK_D(DUK_DPRINT("PAUSE TRIGGERED by uncaught error"));
46562 			duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
46563 		}
46564 	} else {
46565 		if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_CAUGHT_ERROR) {
46566 			DUK_D(DUK_DPRINT("PAUSE TRIGGERED by caught error"));
46567 			duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
46568 		}
46569 	}
46570 
46571 	/* Restore longjmp state. */
46572 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
46573 	thr->heap->lj.type = DUK_LJ_TYPE_THROW;
46574 	tv_obj = DUK_GET_TVAL_NEGIDX(thr, -1);
46575 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
46576 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
46577 	DUK_TVAL_SET_TVAL(&thr->heap->lj.value1, tv_obj);
46578 	DUK_TVAL_INCREF(thr, tv_obj);
46579 	DUK_ASSERT_LJSTATE_SET(thr->heap);
46580 
46581 	duk_pop(thr);
46582 }
46583 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
46584 
46585 /*
46586  *  Helpers for setting up heap longjmp state.
46587  */
46588 
46589 DUK_INTERNAL void duk_err_setup_ljstate1(duk_hthread *thr, duk_small_uint_t lj_type, duk_tval *tv_val) {
46590 	duk_heap *heap;
46591 
46592 	DUK_ASSERT(thr != NULL);
46593 	heap = thr->heap;
46594 	DUK_ASSERT(heap != NULL);
46595 	DUK_ASSERT(tv_val != NULL);
46596 
46597 	DUK_ASSERT_LJSTATE_UNSET(heap);
46598 
46599 	heap->lj.type = lj_type;
46600 	DUK_TVAL_SET_TVAL(&heap->lj.value1, tv_val);
46601 	DUK_TVAL_INCREF(thr, tv_val);
46602 
46603 	DUK_ASSERT_LJSTATE_SET(heap);
46604 }
46605 #line 1 "duk_error_throw.c"
46606 /*
46607  *  Create and throw an ECMAScript error object based on a code and a message.
46608  *
46609  *  Used when we throw errors internally.  ECMAScript generated error objects
46610  *  are created by ECMAScript code, and the throwing is handled by the bytecode
46611  *  executor.
46612  */
46613 
46614 /* #include duk_internal.h -> already included */
46615 
46616 /*
46617  *  Create and throw an error (originating from Duktape internally)
46618  *
46619  *  Push an error object on top of the stack, possibly throw augmenting
46620  *  the error, and finally longjmp.
46621  *
46622  *  If an error occurs while we're dealing with the current error, we might
46623  *  enter an infinite recursion loop.  This is prevented by detecting a
46624  *  "double fault" through the heap->creating_error flag; the recursion
46625  *  then stops at the second level.
46626  */
46627 
46628 #if defined(DUK_USE_VERBOSE_ERRORS)
46629 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) {
46630 #else
46631 DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code) {
46632 #endif
46633 #if defined(DUK_USE_VERBOSE_ERRORS)
46634 	DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld, msg=%s, filename=%s, line=%ld",
46635 	                   (long) code, (const char *) msg,
46636 	                   (const char *) filename, (long) line));
46637 #else
46638 	DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld", (long) code));
46639 #endif
46640 
46641 	DUK_ASSERT(thr != NULL);
46642 
46643 	/* Even though nested call is possible because we throw an error when
46644 	 * trying to create an error, the potential errors must happen before
46645 	 * the longjmp state is configured.
46646 	 */
46647 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
46648 
46649 	/* Sync so that augmentation sees up-to-date activations, NULL
46650 	 * thr->ptr_curr_pc so that it's not used if side effects occur
46651 	 * in augmentation or longjmp handling.
46652 	 */
46653 	duk_hthread_sync_and_null_currpc(thr);
46654 
46655 	/*
46656 	 *  Create and push an error object onto the top of stack.
46657 	 *  The error is potentially augmented before throwing.
46658 	 *
46659 	 *  If a "double error" occurs, use a fixed error instance
46660 	 *  to avoid further trouble.
46661 	 */
46662 
46663 	if (thr->heap->creating_error) {
46664 		duk_tval tv_val;
46665 		duk_hobject *h_err;
46666 
46667 		thr->heap->creating_error = 0;
46668 
46669 		h_err = thr->builtins[DUK_BIDX_DOUBLE_ERROR];
46670 		if (h_err != NULL) {
46671 			DUK_D(DUK_DPRINT("double fault detected -> use built-in fixed 'double error' instance"));
46672 			DUK_TVAL_SET_OBJECT(&tv_val, h_err);
46673 		} else {
46674 			DUK_D(DUK_DPRINT("double fault detected; there is no built-in fixed 'double error' instance "
46675 			                 "-> use the error code as a number"));
46676 			DUK_TVAL_SET_I32(&tv_val, (duk_int32_t) code);
46677 		}
46678 
46679 		duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, &tv_val);
46680 
46681 		/* No augmentation to avoid any allocations or side effects. */
46682 	} else {
46683 		/* Prevent infinite recursion.  Extra call stack and C
46684 		 * recursion headroom (see GH-191) is added for augmentation.
46685 		 * That is now signalled by heap->augmenting error and taken
46686 		 * into account in call handling without an explicit limit bump.
46687 		 */
46688 		thr->heap->creating_error = 1;
46689 
46690 		duk_require_stack(thr, 1);
46691 
46692 		/* XXX: usually unnecessary '%s' formatting here, but cannot
46693 		 * use 'msg' as a format string directly.
46694 		 */
46695 #if defined(DUK_USE_VERBOSE_ERRORS)
46696 		duk_push_error_object_raw(thr,
46697 		                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
46698 		                          filename,
46699 		                          line,
46700 		                          "%s",
46701 		                          (const char *) msg);
46702 #else
46703 		duk_push_error_object_raw(thr,
46704 		                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
46705 		                          NULL,
46706 		                          0,
46707 		                          NULL);
46708 #endif
46709 
46710 		/* Note that an alloc error may happen during error augmentation.
46711 		 * This may happen both when the original error is an alloc error
46712 		 * and when it's something else.  Because any error in augmentation
46713 		 * must be handled correctly anyway, there's no special check for
46714 		 * avoiding it for alloc errors (this differs from Duktape 1.x).
46715 		 */
46716 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
46717 		DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT (before throw augment)",
46718 		                     (duk_tval *) duk_get_tval(thr, -1)));
46719 		duk_err_augment_error_throw(thr);
46720 #endif
46721 
46722 		duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, DUK_GET_TVAL_NEGIDX(thr, -1));
46723 		thr->heap->creating_error = 0;
46724 
46725 		/* Error is now created and we assume no errors can occur any
46726 		 * more.  Check for debugger Throw integration only when the
46727 		 * error is complete.  If we enter debugger message loop,
46728 		 * creating_error must be 0 so that errors can be thrown in
46729 		 * the paused state, e.g. in Eval commands.
46730 		 */
46731 #if defined(DUK_USE_DEBUGGER_SUPPORT)
46732 		duk_err_check_debugger_integration(thr);
46733 #endif
46734 	}
46735 
46736 	/*
46737 	 *  Finally, longjmp
46738 	 */
46739 
46740 	DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT, %!iT (after throw augment)",
46741 	                     (duk_tval *) &thr->heap->lj.value1, (duk_tval *) &thr->heap->lj.value2));
46742 
46743 	duk_err_longjmp(thr);
46744 	DUK_UNREACHABLE();
46745 }
46746 
46747 /*
46748  *  Helper for C function call negative return values.
46749  */
46750 
46751 DUK_INTERNAL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc) {
46752 	DUK_ASSERT(thr != NULL);
46753 	DUK_ASSERT(rc < 0);
46754 
46755 	/*
46756 	 *  The __FILE__ and __LINE__ information is intentionally not used in the
46757 	 *  creation of the error object, as it isn't useful in the tracedata.  The
46758 	 *  tracedata still contains the function which returned the negative return
46759 	 *  code, and having the file/line of this function isn't very useful.
46760 	 *
46761 	 *  The error messages for DUK_RET_xxx shorthand are intentionally very
46762 	 *  minimal: they're only really useful for low memory targets.
46763 	 */
46764 
46765 	duk_error_raw(thr, -rc, NULL, 0, "error (rc %ld)", (long) rc);
46766 	DUK_WO_NORETURN(return;);
46767 }
46768 #line 1 "duk_hbuffer_alloc.c"
46769 /*
46770  *  duk_hbuffer allocation and freeing.
46771  */
46772 
46773 /* #include duk_internal.h -> already included */
46774 
46775 /* Allocate a new duk_hbuffer of a certain type and return a pointer to it
46776  * (NULL on error).  Write buffer data pointer to 'out_bufdata' (only if
46777  * allocation successful).
46778  */
46779 DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata) {
46780 	duk_hbuffer *res = NULL;
46781 	duk_size_t header_size;
46782 	duk_size_t alloc_size;
46783 
46784 	DUK_ASSERT(heap != NULL);
46785 	DUK_ASSERT(out_bufdata != NULL);
46786 
46787 	DUK_DDD(DUK_DDDPRINT("allocate hbuffer"));
46788 
46789 	/* Size sanity check.  Should not be necessary because caller is
46790 	 * required to check this, but we don't want to cause a segfault
46791 	 * if the size wraps either in duk_size_t computation or when
46792 	 * storing the size in a 16-bit field.
46793 	 */
46794 	if (size > DUK_HBUFFER_MAX_BYTELEN) {
46795 		DUK_D(DUK_DPRINT("hbuffer alloc failed: size too large: %ld", (long) size));
46796 		return NULL;  /* no need to write 'out_bufdata' */
46797 	}
46798 
46799 	if (flags & DUK_BUF_FLAG_EXTERNAL) {
46800 		header_size = sizeof(duk_hbuffer_external);
46801 		alloc_size = sizeof(duk_hbuffer_external);
46802 	} else if (flags & DUK_BUF_FLAG_DYNAMIC) {
46803 		header_size = sizeof(duk_hbuffer_dynamic);
46804 		alloc_size = sizeof(duk_hbuffer_dynamic);
46805 	} else {
46806 		header_size = sizeof(duk_hbuffer_fixed);
46807 		alloc_size = sizeof(duk_hbuffer_fixed) + size;
46808 		DUK_ASSERT(alloc_size >= sizeof(duk_hbuffer_fixed));  /* no wrapping */
46809 	}
46810 
46811 	res = (duk_hbuffer *) DUK_ALLOC(heap, alloc_size);
46812 	if (DUK_UNLIKELY(res == NULL)) {
46813 		goto alloc_error;
46814 	}
46815 
46816 	/* zero everything unless requested not to do so */
46817 #if defined(DUK_USE_ZERO_BUFFER_DATA)
46818 	duk_memzero((void *) res,
46819 	            (flags & DUK_BUF_FLAG_NOZERO) ? header_size : alloc_size);
46820 #else
46821 	duk_memzero((void *) res, header_size);
46822 #endif
46823 
46824 	if (flags & DUK_BUF_FLAG_EXTERNAL) {
46825 		duk_hbuffer_external *h;
46826 		h = (duk_hbuffer_external *) res;
46827 		DUK_UNREF(h);
46828 		*out_bufdata = NULL;
46829 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
46830 #if defined(DUK_USE_HEAPPTR16)
46831 /* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
46832 #else
46833 		DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap, h, NULL);
46834 #endif
46835 #endif
46836 		DUK_ASSERT(DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap, h) == NULL);
46837 	} else if (flags & DUK_BUF_FLAG_DYNAMIC) {
46838 		duk_hbuffer_dynamic *h = (duk_hbuffer_dynamic *) res;
46839 		void *ptr;
46840 
46841 		if (size > 0) {
46842 			DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));  /* alloc external with size zero */
46843 			DUK_DDD(DUK_DDDPRINT("dynamic buffer with nonzero size, alloc actual buffer"));
46844 #if defined(DUK_USE_ZERO_BUFFER_DATA)
46845 			ptr = DUK_ALLOC_ZEROED(heap, size);
46846 #else
46847 			ptr = DUK_ALLOC(heap, size);
46848 #endif
46849 			if (DUK_UNLIKELY(ptr == NULL)) {
46850 				/* Because size > 0, NULL check is correct */
46851 				goto alloc_error;
46852 			}
46853 			*out_bufdata = ptr;
46854 
46855 			DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, ptr);
46856 		} else {
46857 			*out_bufdata = NULL;
46858 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
46859 #if defined(DUK_USE_HEAPPTR16)
46860 /* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
46861 #else
46862 			DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, NULL);
46863 #endif
46864 #endif
46865 			DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, h) == NULL);
46866 		}
46867 	} else {
46868 		*out_bufdata = (void *) ((duk_hbuffer_fixed *) (void *) res + 1);
46869 	}
46870 
46871 	DUK_HBUFFER_SET_SIZE(res, size);
46872 
46873 	DUK_HEAPHDR_SET_TYPE(&res->hdr, DUK_HTYPE_BUFFER);
46874 	if (flags & DUK_BUF_FLAG_DYNAMIC) {
46875 		DUK_HBUFFER_SET_DYNAMIC(res);
46876 		if (flags & DUK_BUF_FLAG_EXTERNAL) {
46877 			DUK_HBUFFER_SET_EXTERNAL(res);
46878 		}
46879 	} else {
46880 		DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));
46881 	}
46882         DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &res->hdr);
46883 
46884 	DUK_DDD(DUK_DDDPRINT("allocated hbuffer: %p", (void *) res));
46885 	return res;
46886 
46887  alloc_error:
46888 	DUK_DD(DUK_DDPRINT("hbuffer allocation failed"));
46889 
46890 	DUK_FREE(heap, res);
46891 	return NULL;  /* no need to write 'out_bufdata' */
46892 }
46893 
46894 /* For indirect allocs. */
46895 
46896 DUK_INTERNAL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud) {
46897 	duk_hbuffer_dynamic *buf = (duk_hbuffer_dynamic *) ud;
46898 	DUK_UNREF(heap);
46899 	return (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, buf);
46900 }
46901 #line 1 "duk_hbuffer_ops.c"
46902 /*
46903  *  duk_hbuffer operations such as resizing and inserting/appending data to
46904  *  a dynamic buffer.
46905  */
46906 
46907 /* #include duk_internal.h -> already included */
46908 
46909 /*
46910  *  Resizing
46911  */
46912 
46913 DUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size) {
46914 	void *res;
46915 	duk_size_t prev_size;
46916 
46917 	DUK_ASSERT(thr != NULL);
46918 	DUK_ASSERT(buf != NULL);
46919 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
46920 	DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));
46921 
46922 	/*
46923 	 *  Maximum size check
46924 	 */
46925 
46926 	if (new_size > DUK_HBUFFER_MAX_BYTELEN) {
46927 		DUK_ERROR_RANGE(thr, "buffer too long");
46928 		DUK_WO_NORETURN(return;);
46929 	}
46930 
46931 	/*
46932 	 *  Note: use indirect realloc variant just in case mark-and-sweep
46933 	 *  (finalizers) might resize this same buffer during garbage
46934 	 *  collection.
46935 	 */
46936 
46937 	res = DUK_REALLOC_INDIRECT(thr->heap, duk_hbuffer_get_dynalloc_ptr, (void *) buf, new_size);
46938 	if (DUK_LIKELY(res != NULL || new_size == 0)) {
46939 		/* 'res' may be NULL if new allocation size is 0. */
46940 
46941 		DUK_DDD(DUK_DDDPRINT("resized dynamic buffer %p:%ld -> %p:%ld",
46942 		                     (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf),
46943 		                     (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(buf),
46944 		                     (void *) res,
46945 		                     (long) new_size));
46946 
46947 		/*
46948 		 *  The entire allocated buffer area, regardless of actual used
46949 		 *  size, is kept zeroed in resizes for simplicity.  If the buffer
46950 		 *  is grown, zero the new part.
46951 		 */
46952 
46953 		prev_size = DUK_HBUFFER_DYNAMIC_GET_SIZE(buf);
46954 		if (new_size > prev_size) {
46955 			DUK_ASSERT(new_size - prev_size > 0);
46956 #if defined(DUK_USE_ZERO_BUFFER_DATA)
46957 			duk_memzero((void *) ((char *) res + prev_size),
46958 			            (duk_size_t) (new_size - prev_size));
46959 #endif
46960 		}
46961 
46962 		DUK_HBUFFER_DYNAMIC_SET_SIZE(buf, new_size);
46963 		DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(thr->heap, buf, res);
46964 	} else {
46965 		DUK_ERROR_ALLOC_FAILED(thr);
46966 		DUK_WO_NORETURN(return;);
46967 	}
46968 
46969 	DUK_ASSERT(res != NULL || new_size == 0);
46970 }
46971 
46972 DUK_INTERNAL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf) {
46973 	DUK_ASSERT(thr != NULL);
46974 	DUK_ASSERT(buf != NULL);
46975 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
46976 	DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));
46977 
46978 	duk_hbuffer_resize(thr, buf, 0);
46979 }
46980 /* #include duk_internal.h -> already included */
46981 #line 2 "duk_hbufobj_misc.c"
46982 
46983 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
46984 DUK_INTERNAL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_uint_t len) {
46985 	duk_uint_t buf_size;
46986 	duk_uint_t buf_avail;
46987 
46988 	DUK_ASSERT(h_bufobj != NULL);
46989 	DUK_ASSERT(h_bufobj->buf != NULL);
46990 
46991 	buf_size = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_bufobj->buf);
46992 	if (h_bufobj->offset > buf_size) {
46993 		/* Slice starting point is beyond current length. */
46994 		return 0;
46995 	}
46996 	buf_avail = buf_size - h_bufobj->offset;
46997 
46998 	return buf_avail >= len ? len : buf_avail;
46999 }
47000 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
47001 #line 1 "duk_heap_alloc.c"
47002 /*
47003  *  duk_heap allocation and freeing.
47004  */
47005 
47006 /* #include duk_internal.h -> already included */
47007 
47008 #if defined(DUK_USE_ROM_STRINGS)
47009 /* Fixed seed value used with ROM strings. */
47010 #define DUK__FIXED_HASH_SEED       0xabcd1234
47011 #endif
47012 
47013 /*
47014  *  Free a heap object.
47015  *
47016  *  Free heap object and its internal (non-heap) pointers.  Assumes that
47017  *  caller has removed the object from heap allocated list or the string
47018  *  intern table, and any weak references (which strings may have) have
47019  *  been already dealt with.
47020  */
47021 
47022 DUK_INTERNAL void duk_free_hobject(duk_heap *heap, duk_hobject *h) {
47023 	DUK_ASSERT(heap != NULL);
47024 	DUK_ASSERT(h != NULL);
47025 
47026 	DUK_FREE(heap, DUK_HOBJECT_GET_PROPS(heap, h));
47027 
47028 	if (DUK_HOBJECT_IS_COMPFUNC(h)) {
47029 		duk_hcompfunc *f = (duk_hcompfunc *) h;
47030 		DUK_UNREF(f);
47031 		/* Currently nothing to free; 'data' is a heap object */
47032 	} else if (DUK_HOBJECT_IS_NATFUNC(h)) {
47033 		duk_hnatfunc *f = (duk_hnatfunc *) h;
47034 		DUK_UNREF(f);
47035 		/* Currently nothing to free */
47036 	} else if (DUK_HOBJECT_IS_THREAD(h)) {
47037 		duk_hthread *t = (duk_hthread *) h;
47038 		duk_activation *act;
47039 
47040 		DUK_FREE(heap, t->valstack);
47041 
47042 		/* Don't free h->resumer because it exists in the heap.
47043 		 * Callstack entries also contain function pointers which
47044 		 * are not freed for the same reason.  They are decref
47045 		 * finalized and the targets are freed if necessary based
47046 		 * on their refcount (or reachability).
47047 		 */
47048 		for (act = t->callstack_curr; act != NULL;) {
47049 			duk_activation *act_next;
47050 			duk_catcher *cat;
47051 
47052 			for (cat = act->cat; cat != NULL;) {
47053 				duk_catcher *cat_next;
47054 
47055 				cat_next = cat->parent;
47056 				DUK_FREE(heap, (void *) cat);
47057 				cat = cat_next;
47058 			}
47059 
47060 			act_next = act->parent;
47061 			DUK_FREE(heap, (void *) act);
47062 			act = act_next;
47063 		}
47064 
47065 		/* XXX: with 'caller' property the callstack would need
47066 		 * to be unwound to update the 'caller' properties of
47067 		 * functions in the callstack.
47068 		 */
47069 	} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
47070 		duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
47071 
47072 		DUK_FREE(heap, f->args);
47073 	}
47074 
47075 	DUK_FREE(heap, (void *) h);
47076 }
47077 
47078 DUK_INTERNAL void duk_free_hbuffer(duk_heap *heap, duk_hbuffer *h) {
47079 	DUK_ASSERT(heap != NULL);
47080 	DUK_ASSERT(h != NULL);
47081 
47082 	if (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h)) {
47083 		duk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;
47084 		DUK_DDD(DUK_DDDPRINT("free dynamic buffer %p", (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g)));
47085 		DUK_FREE(heap, DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g));
47086 	}
47087 	DUK_FREE(heap, (void *) h);
47088 }
47089 
47090 DUK_INTERNAL void duk_free_hstring(duk_heap *heap, duk_hstring *h) {
47091 	DUK_ASSERT(heap != NULL);
47092 	DUK_ASSERT(h != NULL);
47093 
47094 	DUK_UNREF(heap);
47095 	DUK_UNREF(h);
47096 
47097 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_FREE)
47098 	if (DUK_HSTRING_HAS_EXTDATA(h)) {
47099 		DUK_DDD(DUK_DDDPRINT("free extstr: hstring %!O, extdata: %p",
47100 		                     h, DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h)));
47101 		DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h));
47102 	}
47103 #endif
47104 	DUK_FREE(heap, (void *) h);
47105 }
47106 
47107 DUK_INTERNAL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr) {
47108 	DUK_ASSERT(heap);
47109 	DUK_ASSERT(hdr);
47110 
47111 	DUK_DDD(DUK_DDDPRINT("free heaphdr %p, htype %ld", (void *) hdr, (long) DUK_HEAPHDR_GET_TYPE(hdr)));
47112 
47113 	switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
47114 	case DUK_HTYPE_STRING:
47115 		duk_free_hstring(heap, (duk_hstring *) hdr);
47116 		break;
47117 	case DUK_HTYPE_OBJECT:
47118 		duk_free_hobject(heap, (duk_hobject *) hdr);
47119 		break;
47120 	default:
47121 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) == DUK_HTYPE_BUFFER);
47122 		duk_free_hbuffer(heap, (duk_hbuffer *) hdr);
47123 	}
47124 
47125 }
47126 
47127 /*
47128  *  Free the heap.
47129  *
47130  *  Frees heap-related non-heap-tracked allocations such as the
47131  *  string intern table; then frees the heap allocated objects;
47132  *  and finally frees the heap structure itself.  Reference counts
47133  *  and GC markers are ignored (and not updated) in this process,
47134  *  and finalizers won't be called.
47135  *
47136  *  The heap pointer and heap object pointers must not be used
47137  *  after this call.
47138  */
47139 
47140 #if defined(DUK_USE_CACHE_ACTIVATION)
47141 DUK_LOCAL duk_size_t duk__heap_free_activation_freelist(duk_heap *heap) {
47142 	duk_activation *act;
47143 	duk_activation *act_next;
47144 	duk_size_t count_act = 0;
47145 
47146 	for (act = heap->activation_free; act != NULL;) {
47147 		act_next = act->parent;
47148 		DUK_FREE(heap, (void *) act);
47149 		act = act_next;
47150 #if defined(DUK_USE_DEBUG)
47151 		count_act++;
47152 #endif
47153 	}
47154 	heap->activation_free = NULL;  /* needed when called from mark-and-sweep */
47155 	return count_act;
47156 }
47157 #endif  /* DUK_USE_CACHE_ACTIVATION */
47158 
47159 #if defined(DUK_USE_CACHE_CATCHER)
47160 DUK_LOCAL duk_size_t duk__heap_free_catcher_freelist(duk_heap *heap) {
47161 	duk_catcher *cat;
47162 	duk_catcher *cat_next;
47163 	duk_size_t count_cat = 0;
47164 
47165 	for (cat = heap->catcher_free; cat != NULL;) {
47166 		cat_next = cat->parent;
47167 		DUK_FREE(heap, (void *) cat);
47168 		cat = cat_next;
47169 #if defined(DUK_USE_DEBUG)
47170 		count_cat++;
47171 #endif
47172 	}
47173 	heap->catcher_free = NULL;  /* needed when called from mark-and-sweep */
47174 
47175 	return count_cat;
47176 }
47177 #endif  /* DUK_USE_CACHE_CATCHER */
47178 
47179 DUK_INTERNAL void duk_heap_free_freelists(duk_heap *heap) {
47180 	duk_size_t count_act = 0;
47181 	duk_size_t count_cat = 0;
47182 
47183 #if defined(DUK_USE_CACHE_ACTIVATION)
47184 	count_act = duk__heap_free_activation_freelist(heap);
47185 #endif
47186 #if defined(DUK_USE_CACHE_CATCHER)
47187 	count_cat = duk__heap_free_catcher_freelist(heap);
47188 #endif
47189 	DUK_UNREF(heap);
47190 	DUK_UNREF(count_act);
47191 	DUK_UNREF(count_cat);
47192 
47193 	DUK_D(DUK_DPRINT("freed %ld activation freelist entries, %ld catcher freelist entries",
47194 	                 (long) count_act, (long) count_cat));
47195 }
47196 
47197 DUK_LOCAL void duk__free_allocated(duk_heap *heap) {
47198 	duk_heaphdr *curr;
47199 	duk_heaphdr *next;
47200 
47201 	curr = heap->heap_allocated;
47202 	while (curr) {
47203 		/* We don't log or warn about freeing zero refcount objects
47204 		 * because they may happen with finalizer processing.
47205 		 */
47206 
47207 		DUK_DDD(DUK_DDDPRINT("FINALFREE (allocated): %!iO",
47208 		                     (duk_heaphdr *) curr));
47209 		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
47210 		duk_heap_free_heaphdr_raw(heap, curr);
47211 		curr = next;
47212 	}
47213 }
47214 
47215 #if defined(DUK_USE_FINALIZER_SUPPORT)
47216 DUK_LOCAL void duk__free_finalize_list(duk_heap *heap) {
47217 	duk_heaphdr *curr;
47218 	duk_heaphdr *next;
47219 
47220 	curr = heap->finalize_list;
47221 	while (curr) {
47222 		DUK_DDD(DUK_DDDPRINT("FINALFREE (finalize_list): %!iO",
47223 		                     (duk_heaphdr *) curr));
47224 		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
47225 		duk_heap_free_heaphdr_raw(heap, curr);
47226 		curr = next;
47227 	}
47228 }
47229 #endif  /* DUK_USE_FINALIZER_SUPPORT */
47230 
47231 DUK_LOCAL void duk__free_stringtable(duk_heap *heap) {
47232 	/* strings are only tracked by stringtable */
47233 	duk_heap_strtable_free(heap);
47234 }
47235 
47236 #if defined(DUK_USE_FINALIZER_SUPPORT)
47237 DUK_LOCAL void duk__free_run_finalizers(duk_heap *heap) {
47238 	duk_heaphdr *curr;
47239 	duk_uint_t round_no;
47240 	duk_size_t count_all;
47241 	duk_size_t count_finalized;
47242 	duk_size_t curr_limit;
47243 
47244 	DUK_ASSERT(heap != NULL);
47245 
47246 #if defined(DUK_USE_REFERENCE_COUNTING)
47247 	DUK_ASSERT(heap->refzero_list == NULL);  /* refzero not running -> must be empty */
47248 #endif
47249 	DUK_ASSERT(heap->finalize_list == NULL);  /* mark-and-sweep last pass */
47250 
47251 	if (heap->heap_thread == NULL) {
47252 		/* May happen when heap allocation fails right off.  There
47253 		 * cannot be any finalizable objects in this case.
47254 		 */
47255 		DUK_D(DUK_DPRINT("no heap_thread in heap destruct, assume no finalizable objects"));
47256 		return;
47257 	}
47258 
47259 	/* Prevent finalize_list processing and mark-and-sweep entirely.
47260 	 * Setting ms_running = 1 also prevents refzero handling from moving
47261 	 * objects away from the heap_allocated list (the flag name is a bit
47262 	 * misleading here).
47263 	 */
47264 	DUK_ASSERT(heap->pf_prevent_count == 0);
47265 	heap->pf_prevent_count = 1;
47266 	DUK_ASSERT(heap->ms_running == 0);
47267 	heap->ms_running = 1;
47268 	DUK_ASSERT(heap->ms_prevent_count == 0);
47269 	heap->ms_prevent_count = 1;  /* Bump, because mark-and-sweep assumes it's bumped when ms_running is set. */
47270 
47271 	curr_limit = 0;  /* suppress warning, not used */
47272 	for (round_no = 0; ; round_no++) {
47273 		curr = heap->heap_allocated;
47274 		count_all = 0;
47275 		count_finalized = 0;
47276 		while (curr) {
47277 			count_all++;
47278 			if (DUK_HEAPHDR_IS_OBJECT(curr)) {
47279 				/* Only objects in heap_allocated may have finalizers.  Check that
47280 				 * the object itself has a _Finalizer property (own or inherited)
47281 				 * so that we don't execute finalizers for e.g. Proxy objects.
47282 				 */
47283 				DUK_ASSERT(curr != NULL);
47284 
47285 				if (DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) curr)) {
47286 					if (!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) curr)) {
47287 						DUK_ASSERT(DUK_HEAP_HAS_FINALIZER_NORESCUE(heap));  /* maps to finalizer 2nd argument */
47288 						duk_heap_run_finalizer(heap, (duk_hobject *) curr);
47289 						count_finalized++;
47290 					}
47291 				}
47292 			}
47293 			curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
47294 		}
47295 
47296 		/* Each round of finalizer execution may spawn new finalizable objects
47297 		 * which is normal behavior for some applications.  Allow multiple
47298 		 * rounds of finalization, but use a shrinking limit based on the
47299 		 * first round to detect the case where a runaway finalizer creates
47300 		 * an unbounded amount of new finalizable objects.  Finalizer rescue
47301 		 * is not supported: the semantics are unclear because most of the
47302 		 * objects being finalized here are already reachable.  The finalizer
47303 		 * is given a boolean to indicate that rescue is not possible.
47304 		 *
47305 		 * See discussion in: https://github.com/svaarala/duktape/pull/473
47306 		 */
47307 
47308 		if (round_no == 0) {
47309 			/* Cannot wrap: each object is at least 8 bytes so count is
47310 			 * at most 1/8 of that.
47311 			 */
47312 			curr_limit = count_all * 2;
47313 		} else {
47314 			curr_limit = (curr_limit * 3) / 4;   /* Decrease by 25% every round */
47315 		}
47316 		DUK_D(DUK_DPRINT("finalizer round %ld complete, %ld objects, tried to execute %ld finalizers, current limit is %ld",
47317 		                 (long) round_no, (long) count_all, (long) count_finalized, (long) curr_limit));
47318 
47319 		if (count_finalized == 0) {
47320 			DUK_D(DUK_DPRINT("no more finalizable objects, forced finalization finished"));
47321 			break;
47322 		}
47323 		if (count_finalized >= curr_limit) {
47324 			DUK_D(DUK_DPRINT("finalizer count above limit, potentially runaway finalizer; skip remaining finalizers"));
47325 			break;
47326 		}
47327 	}
47328 
47329 	DUK_ASSERT(heap->ms_running == 1);
47330 	heap->ms_running = 0;
47331 	DUK_ASSERT(heap->pf_prevent_count == 1);
47332 	heap->pf_prevent_count = 0;
47333 }
47334 #endif  /* DUK_USE_FINALIZER_SUPPORT */
47335 
47336 DUK_INTERNAL void duk_heap_free(duk_heap *heap) {
47337 	DUK_D(DUK_DPRINT("free heap: %p", (void *) heap));
47338 
47339 #if defined(DUK_USE_DEBUG)
47340 	duk_heap_strtable_dump(heap);
47341 #endif
47342 
47343 #if defined(DUK_USE_DEBUGGER_SUPPORT)
47344 	/* Detach a debugger if attached (can be called multiple times)
47345 	 * safely.
47346 	 */
47347 	/* XXX: Add a flag to reject an attempt to re-attach?  Otherwise
47348 	 * the detached callback may immediately reattach.
47349 	 */
47350 	duk_debug_do_detach(heap);
47351 #endif
47352 
47353 	/* Execute finalizers before freeing the heap, even for reachable
47354 	 * objects.  This gives finalizers the chance to free any native
47355 	 * resources like file handles, allocations made outside Duktape,
47356 	 * etc.  This is quite tricky to get right, so that all finalizer
47357 	 * guarantees are honored.
47358 	 *
47359 	 * Run mark-and-sweep a few times just in case (unreachable object
47360 	 * finalizers run already here).  The last round must rescue objects
47361 	 * from the previous round without running any more finalizers.  This
47362 	 * ensures rescued objects get their FINALIZED flag cleared so that
47363 	 * their finalizer is called once more in forced finalization to
47364 	 * satisfy finalizer guarantees.  However, we don't want to run any
47365 	 * more finalizers because that'd required one more loop, and so on.
47366 	 *
47367 	 * XXX: this perhaps requires an execution time limit.
47368 	 */
47369 	DUK_D(DUK_DPRINT("execute finalizers before freeing heap"));
47370 	DUK_ASSERT(heap->pf_skip_finalizers == 0);
47371 	DUK_D(DUK_DPRINT("forced gc #1 in heap destruction"));
47372 	duk_heap_mark_and_sweep(heap, 0);
47373 	DUK_D(DUK_DPRINT("forced gc #2 in heap destruction"));
47374 	duk_heap_mark_and_sweep(heap, 0);
47375 	DUK_D(DUK_DPRINT("forced gc #3 in heap destruction (don't run finalizers)"));
47376 	heap->pf_skip_finalizers = 1;
47377 	duk_heap_mark_and_sweep(heap, 0);  /* Skip finalizers; queue finalizable objects to heap_allocated. */
47378 
47379 	/* There are never objects in refzero_list at this point, or at any
47380 	 * point beyond a DECREF (even a DECREF_NORZ).  Since Duktape 2.1
47381 	 * refzero_list processing is side effect free, so it is always
47382 	 * processed to completion by a DECREF initially triggering a zero
47383 	 * refcount.
47384 	 */
47385 #if defined(DUK_USE_REFERENCE_COUNTING)
47386 	DUK_ASSERT(heap->refzero_list == NULL);  /* Always processed to completion inline. */
47387 #endif
47388 #if defined(DUK_USE_FINALIZER_SUPPORT)
47389 	DUK_ASSERT(heap->finalize_list == NULL);  /* Last mark-and-sweep with skip_finalizers. */
47390 #endif
47391 
47392 #if defined(DUK_USE_FINALIZER_SUPPORT)
47393 	DUK_D(DUK_DPRINT("run finalizers for remaining finalizable objects"));
47394 	DUK_HEAP_SET_FINALIZER_NORESCUE(heap);  /* Rescue no longer supported. */
47395 	duk__free_run_finalizers(heap);
47396 #endif  /* DUK_USE_FINALIZER_SUPPORT */
47397 
47398 	/* Note: heap->heap_thread, heap->curr_thread, and heap->heap_object
47399 	 * are on the heap allocated list.
47400 	 */
47401 
47402 	DUK_D(DUK_DPRINT("freeing temporary freelists"));
47403 	duk_heap_free_freelists(heap);
47404 
47405 	DUK_D(DUK_DPRINT("freeing heap_allocated of heap: %p", (void *) heap));
47406 	duk__free_allocated(heap);
47407 
47408 #if defined(DUK_USE_REFERENCE_COUNTING)
47409 	DUK_ASSERT(heap->refzero_list == NULL);  /* Always processed to completion inline. */
47410 #endif
47411 
47412 #if defined(DUK_USE_FINALIZER_SUPPORT)
47413 	DUK_D(DUK_DPRINT("freeing finalize_list of heap: %p", (void *) heap));
47414 	duk__free_finalize_list(heap);
47415 #endif
47416 
47417 	DUK_D(DUK_DPRINT("freeing string table of heap: %p", (void *) heap));
47418 	duk__free_stringtable(heap);
47419 
47420 	DUK_D(DUK_DPRINT("freeing heap structure: %p", (void *) heap));
47421 	heap->free_func(heap->heap_udata, heap);
47422 }
47423 
47424 /*
47425  *  Allocate a heap.
47426  *
47427  *  String table is initialized with built-in strings from genbuiltins.py,
47428  *  either by dynamically creating the strings or by referring to ROM strings.
47429  */
47430 
47431 #if defined(DUK_USE_ROM_STRINGS)
47432 DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
47433 #if defined(DUK_USE_ASSERTIONS)
47434 	duk_small_uint_t i;
47435 #endif
47436 
47437 	DUK_UNREF(heap);
47438 
47439 	/* With ROM-based strings, heap->strs[] and thr->strs[] are omitted
47440 	 * so nothing to initialize for strs[].
47441 	 */
47442 
47443 #if defined(DUK_USE_ASSERTIONS)
47444 	for (i = 0; i < sizeof(duk_rom_strings_lookup) / sizeof(const duk_hstring *); i++) {
47445 		const duk_hstring *h;
47446 		duk_uint32_t hash;
47447 
47448 		h = duk_rom_strings_lookup[i];
47449 		while (h != NULL) {
47450 			hash = duk_heap_hashstring(heap, (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
47451 			DUK_DD(DUK_DDPRINT("duk_rom_strings_lookup[%d] -> hash 0x%08lx, computed 0x%08lx",
47452 			                   (int) i, (unsigned long) DUK_HSTRING_GET_HASH(h), (unsigned long) hash));
47453 			DUK_ASSERT(hash == (duk_uint32_t) DUK_HSTRING_GET_HASH(h));
47454 
47455 			h = (const duk_hstring *) h->hdr.h_next;
47456 		}
47457 	}
47458 #endif
47459 	return 1;
47460 }
47461 #else  /* DUK_USE_ROM_STRINGS */
47462 
47463 DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
47464 	duk_bitdecoder_ctx bd_ctx;
47465 	duk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */
47466 	duk_small_uint_t i;
47467 
47468 	duk_memzero(&bd_ctx, sizeof(bd_ctx));
47469 	bd->data = (const duk_uint8_t *) duk_strings_data;
47470 	bd->length = (duk_size_t) DUK_STRDATA_DATA_LENGTH;
47471 
47472 	for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
47473 		duk_uint8_t tmp[DUK_STRDATA_MAX_STRLEN];
47474 		duk_small_uint_t len;
47475 		duk_hstring *h;
47476 
47477 		len = duk_bd_decode_bitpacked_string(bd, tmp);
47478 
47479 		/* No need to length check string: it will never exceed even
47480 		 * the 16-bit length maximum.
47481 		 */
47482 		DUK_ASSERT(len <= 0xffffUL);
47483 		DUK_DDD(DUK_DDDPRINT("intern built-in string %ld", (long) i));
47484 		h = duk_heap_strtable_intern(heap, tmp, len);
47485 		if (!h) {
47486 			goto failed;
47487 		}
47488 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));
47489 
47490 		/* Special flags checks.  Since these strings are always
47491 		 * reachable and a string cannot appear twice in the string
47492 		 * table, there's no need to check/set these flags elsewhere.
47493 		 * The 'internal' flag is set by string intern code.
47494 		 */
47495 		if (i == DUK_STRIDX_EVAL || i == DUK_STRIDX_LC_ARGUMENTS) {
47496 			DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(h);
47497 		}
47498 		if (i >= DUK_STRIDX_START_RESERVED && i < DUK_STRIDX_END_RESERVED) {
47499 			DUK_HSTRING_SET_RESERVED_WORD(h);
47500 			if (i >= DUK_STRIDX_START_STRICT_RESERVED) {
47501 				DUK_HSTRING_SET_STRICT_RESERVED_WORD(h);
47502 			}
47503 		}
47504 
47505 		DUK_DDD(DUK_DDDPRINT("interned: %!O", (duk_heaphdr *) h));
47506 
47507 		/* XXX: The incref macro takes a thread pointer but doesn't
47508 		 * use it right now.
47509 		 */
47510 		DUK_HSTRING_INCREF(_never_referenced_, h);
47511 
47512 #if defined(DUK_USE_HEAPPTR16)
47513 		heap->strs16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
47514 #else
47515 		heap->strs[i] = h;
47516 #endif
47517 	}
47518 
47519 	return 1;
47520 
47521  failed:
47522 	return 0;
47523 }
47524 #endif  /* DUK_USE_ROM_STRINGS */
47525 
47526 DUK_LOCAL duk_bool_t duk__init_heap_thread(duk_heap *heap) {
47527 	duk_hthread *thr;
47528 
47529 	DUK_D(DUK_DPRINT("heap init: alloc heap thread"));
47530 	thr = duk_hthread_alloc_unchecked(heap,
47531 	                                  DUK_HOBJECT_FLAG_EXTENSIBLE |
47532 	                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
47533 	if (thr == NULL) {
47534 		DUK_D(DUK_DPRINT("failed to alloc heap_thread"));
47535 		return 0;
47536 	}
47537 	thr->state = DUK_HTHREAD_STATE_INACTIVE;
47538 #if defined(DUK_USE_ROM_STRINGS)
47539 	/* No strs[] pointer. */
47540 #else  /* DUK_USE_ROM_STRINGS */
47541 #if defined(DUK_USE_HEAPPTR16)
47542 	thr->strs16 = heap->strs16;
47543 #else
47544 	thr->strs = heap->strs;
47545 #endif
47546 #endif  /* DUK_USE_ROM_STRINGS */
47547 
47548 	heap->heap_thread = thr;
47549 	DUK_HTHREAD_INCREF(thr, thr);  /* Note: first argument not really used */
47550 
47551 	/* 'thr' is now reachable */
47552 
47553 	DUK_D(DUK_DPRINT("heap init: init heap thread stacks"));
47554 	if (!duk_hthread_init_stacks(heap, thr)) {
47555 		return 0;
47556 	}
47557 
47558 	/* XXX: this may now fail, and is not handled correctly */
47559 	duk_hthread_create_builtin_objects(thr);
47560 
47561 	/* default prototype */
47562 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) thr, thr->builtins[DUK_BIDX_THREAD_PROTOTYPE]);
47563 
47564 	return 1;
47565 }
47566 
47567 #if defined(DUK_USE_DEBUG)
47568 #define DUK__DUMPSZ(t)  do { \
47569 		DUK_D(DUK_DPRINT("" #t "=%ld", (long) sizeof(t))); \
47570 	} while (0)
47571 
47572 /* These is not 100% because format would need to be non-portable "long long".
47573  * Also print out as doubles to catch cases where the "long" type is not wide
47574  * enough; the limits will then not be printed accurately but the magnitude
47575  * will be correct.
47576  */
47577 #define DUK__DUMPLM_SIGNED_RAW(t,a,b)  do { \
47578 		DUK_D(DUK_DPRINT(t "=[%ld,%ld]=[%lf,%lf]", \
47579 		                 (long) (a), (long) (b), \
47580 		                 (double) (a), (double) (b))); \
47581 	} while (0)
47582 #define DUK__DUMPLM_UNSIGNED_RAW(t,a,b)  do { \
47583 		DUK_D(DUK_DPRINT(t "=[%lu,%lu]=[%lf,%lf]", \
47584 		                 (unsigned long) (a), (unsigned long) (b), \
47585 		                 (double) (a), (double) (b))); \
47586 	} while (0)
47587 #define DUK__DUMPLM_SIGNED(t)  do { \
47588 		DUK__DUMPLM_SIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
47589 	} while (0)
47590 #define DUK__DUMPLM_UNSIGNED(t)  do { \
47591 		DUK__DUMPLM_UNSIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
47592 	} while (0)
47593 
47594 DUK_LOCAL void duk__dump_type_sizes(void) {
47595 	DUK_D(DUK_DPRINT("sizeof()"));
47596 
47597 	/* basic platform types */
47598 	DUK__DUMPSZ(char);
47599 	DUK__DUMPSZ(short);
47600 	DUK__DUMPSZ(int);
47601 	DUK__DUMPSZ(long);
47602 	DUK__DUMPSZ(double);
47603 	DUK__DUMPSZ(void *);
47604 	DUK__DUMPSZ(size_t);
47605 
47606 	/* basic types from duk_features.h */
47607 	DUK__DUMPSZ(duk_uint8_t);
47608 	DUK__DUMPSZ(duk_int8_t);
47609 	DUK__DUMPSZ(duk_uint16_t);
47610 	DUK__DUMPSZ(duk_int16_t);
47611 	DUK__DUMPSZ(duk_uint32_t);
47612 	DUK__DUMPSZ(duk_int32_t);
47613 	DUK__DUMPSZ(duk_uint64_t);
47614 	DUK__DUMPSZ(duk_int64_t);
47615 	DUK__DUMPSZ(duk_uint_least8_t);
47616 	DUK__DUMPSZ(duk_int_least8_t);
47617 	DUK__DUMPSZ(duk_uint_least16_t);
47618 	DUK__DUMPSZ(duk_int_least16_t);
47619 	DUK__DUMPSZ(duk_uint_least32_t);
47620 	DUK__DUMPSZ(duk_int_least32_t);
47621 #if defined(DUK_USE_64BIT_OPS)
47622 	DUK__DUMPSZ(duk_uint_least64_t);
47623 	DUK__DUMPSZ(duk_int_least64_t);
47624 #endif
47625 	DUK__DUMPSZ(duk_uint_fast8_t);
47626 	DUK__DUMPSZ(duk_int_fast8_t);
47627 	DUK__DUMPSZ(duk_uint_fast16_t);
47628 	DUK__DUMPSZ(duk_int_fast16_t);
47629 	DUK__DUMPSZ(duk_uint_fast32_t);
47630 	DUK__DUMPSZ(duk_int_fast32_t);
47631 #if defined(DUK_USE_64BIT_OPS)
47632 	DUK__DUMPSZ(duk_uint_fast64_t);
47633 	DUK__DUMPSZ(duk_int_fast64_t);
47634 #endif
47635 	DUK__DUMPSZ(duk_uintptr_t);
47636 	DUK__DUMPSZ(duk_intptr_t);
47637 	DUK__DUMPSZ(duk_uintmax_t);
47638 	DUK__DUMPSZ(duk_intmax_t);
47639 	DUK__DUMPSZ(duk_double_t);
47640 
47641 	/* important chosen base types */
47642 	DUK__DUMPSZ(duk_int_t);
47643 	DUK__DUMPSZ(duk_uint_t);
47644 	DUK__DUMPSZ(duk_int_fast_t);
47645 	DUK__DUMPSZ(duk_uint_fast_t);
47646 	DUK__DUMPSZ(duk_small_int_t);
47647 	DUK__DUMPSZ(duk_small_uint_t);
47648 	DUK__DUMPSZ(duk_small_int_fast_t);
47649 	DUK__DUMPSZ(duk_small_uint_fast_t);
47650 
47651 	/* some derived types */
47652 	DUK__DUMPSZ(duk_codepoint_t);
47653 	DUK__DUMPSZ(duk_ucodepoint_t);
47654 	DUK__DUMPSZ(duk_idx_t);
47655 	DUK__DUMPSZ(duk_errcode_t);
47656 	DUK__DUMPSZ(duk_uarridx_t);
47657 
47658 	/* tval */
47659 	DUK__DUMPSZ(duk_double_union);
47660 	DUK__DUMPSZ(duk_tval);
47661 
47662 	/* structs from duk_forwdecl.h */
47663 	DUK__DUMPSZ(duk_jmpbuf);  /* just one 'int' for C++ exceptions */
47664 	DUK__DUMPSZ(duk_heaphdr);
47665 	DUK__DUMPSZ(duk_heaphdr_string);
47666 	DUK__DUMPSZ(duk_hstring);
47667 	DUK__DUMPSZ(duk_hstring_external);
47668 	DUK__DUMPSZ(duk_hobject);
47669 	DUK__DUMPSZ(duk_harray);
47670 	DUK__DUMPSZ(duk_hcompfunc);
47671 	DUK__DUMPSZ(duk_hnatfunc);
47672 	DUK__DUMPSZ(duk_hdecenv);
47673 	DUK__DUMPSZ(duk_hobjenv);
47674 	DUK__DUMPSZ(duk_hthread);
47675 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
47676 	DUK__DUMPSZ(duk_hbufobj);
47677 #endif
47678 	DUK__DUMPSZ(duk_hproxy);
47679 	DUK__DUMPSZ(duk_hbuffer);
47680 	DUK__DUMPSZ(duk_hbuffer_fixed);
47681 	DUK__DUMPSZ(duk_hbuffer_dynamic);
47682 	DUK__DUMPSZ(duk_hbuffer_external);
47683 	DUK__DUMPSZ(duk_propaccessor);
47684 	DUK__DUMPSZ(duk_propvalue);
47685 	DUK__DUMPSZ(duk_propdesc);
47686 	DUK__DUMPSZ(duk_heap);
47687 	DUK__DUMPSZ(duk_activation);
47688 	DUK__DUMPSZ(duk_catcher);
47689 	DUK__DUMPSZ(duk_strcache_entry);
47690 	DUK__DUMPSZ(duk_litcache_entry);
47691 	DUK__DUMPSZ(duk_ljstate);
47692 	DUK__DUMPSZ(duk_fixedbuffer);
47693 	DUK__DUMPSZ(duk_bitdecoder_ctx);
47694 	DUK__DUMPSZ(duk_bitencoder_ctx);
47695 	DUK__DUMPSZ(duk_token);
47696 	DUK__DUMPSZ(duk_re_token);
47697 	DUK__DUMPSZ(duk_lexer_point);
47698 	DUK__DUMPSZ(duk_lexer_ctx);
47699 	DUK__DUMPSZ(duk_compiler_instr);
47700 	DUK__DUMPSZ(duk_compiler_func);
47701 	DUK__DUMPSZ(duk_compiler_ctx);
47702 	DUK__DUMPSZ(duk_re_matcher_ctx);
47703 	DUK__DUMPSZ(duk_re_compiler_ctx);
47704 }
47705 DUK_LOCAL void duk__dump_type_limits(void) {
47706 	DUK_D(DUK_DPRINT("limits"));
47707 
47708 	/* basic types */
47709 	DUK__DUMPLM_SIGNED(INT8);
47710 	DUK__DUMPLM_UNSIGNED(UINT8);
47711 	DUK__DUMPLM_SIGNED(INT_FAST8);
47712 	DUK__DUMPLM_UNSIGNED(UINT_FAST8);
47713 	DUK__DUMPLM_SIGNED(INT_LEAST8);
47714 	DUK__DUMPLM_UNSIGNED(UINT_LEAST8);
47715 	DUK__DUMPLM_SIGNED(INT16);
47716 	DUK__DUMPLM_UNSIGNED(UINT16);
47717 	DUK__DUMPLM_SIGNED(INT_FAST16);
47718 	DUK__DUMPLM_UNSIGNED(UINT_FAST16);
47719 	DUK__DUMPLM_SIGNED(INT_LEAST16);
47720 	DUK__DUMPLM_UNSIGNED(UINT_LEAST16);
47721 	DUK__DUMPLM_SIGNED(INT32);
47722 	DUK__DUMPLM_UNSIGNED(UINT32);
47723 	DUK__DUMPLM_SIGNED(INT_FAST32);
47724 	DUK__DUMPLM_UNSIGNED(UINT_FAST32);
47725 	DUK__DUMPLM_SIGNED(INT_LEAST32);
47726 	DUK__DUMPLM_UNSIGNED(UINT_LEAST32);
47727 #if defined(DUK_USE_64BIT_OPS)
47728 	DUK__DUMPLM_SIGNED(INT64);
47729 	DUK__DUMPLM_UNSIGNED(UINT64);
47730 	DUK__DUMPLM_SIGNED(INT_FAST64);
47731 	DUK__DUMPLM_UNSIGNED(UINT_FAST64);
47732 	DUK__DUMPLM_SIGNED(INT_LEAST64);
47733 	DUK__DUMPLM_UNSIGNED(UINT_LEAST64);
47734 #endif
47735 	DUK__DUMPLM_SIGNED(INTPTR);
47736 	DUK__DUMPLM_UNSIGNED(UINTPTR);
47737 	DUK__DUMPLM_SIGNED(INTMAX);
47738 	DUK__DUMPLM_UNSIGNED(UINTMAX);
47739 
47740 	/* derived types */
47741 	DUK__DUMPLM_SIGNED(INT);
47742 	DUK__DUMPLM_UNSIGNED(UINT);
47743 	DUK__DUMPLM_SIGNED(INT_FAST);
47744 	DUK__DUMPLM_UNSIGNED(UINT_FAST);
47745 	DUK__DUMPLM_SIGNED(SMALL_INT);
47746 	DUK__DUMPLM_UNSIGNED(SMALL_UINT);
47747 	DUK__DUMPLM_SIGNED(SMALL_INT_FAST);
47748 	DUK__DUMPLM_UNSIGNED(SMALL_UINT_FAST);
47749 }
47750 
47751 DUK_LOCAL void duk__dump_misc_options(void) {
47752 	DUK_D(DUK_DPRINT("DUK_VERSION: %ld", (long) DUK_VERSION));
47753 	DUK_D(DUK_DPRINT("DUK_GIT_DESCRIBE: %s", DUK_GIT_DESCRIBE));
47754 	DUK_D(DUK_DPRINT("OS string: %s", DUK_USE_OS_STRING));
47755 	DUK_D(DUK_DPRINT("architecture string: %s", DUK_USE_ARCH_STRING));
47756 	DUK_D(DUK_DPRINT("compiler string: %s", DUK_USE_COMPILER_STRING));
47757 	DUK_D(DUK_DPRINT("debug level: %ld", (long) DUK_USE_DEBUG_LEVEL));
47758 #if defined(DUK_USE_PACKED_TVAL)
47759 	DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: yes"));
47760 #else
47761 	DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: no"));
47762 #endif
47763 #if defined(DUK_USE_VARIADIC_MACROS)
47764 	DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: yes"));
47765 #else
47766 	DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: no"));
47767 #endif
47768 #if defined(DUK_USE_INTEGER_LE)
47769 	DUK_D(DUK_DPRINT("integer endianness: little"));
47770 #elif defined(DUK_USE_INTEGER_ME)
47771 	DUK_D(DUK_DPRINT("integer endianness: mixed"));
47772 #elif defined(DUK_USE_INTEGER_BE)
47773 	DUK_D(DUK_DPRINT("integer endianness: big"));
47774 #else
47775 	DUK_D(DUK_DPRINT("integer endianness: ???"));
47776 #endif
47777 #if defined(DUK_USE_DOUBLE_LE)
47778 	DUK_D(DUK_DPRINT("IEEE double endianness: little"));
47779 #elif defined(DUK_USE_DOUBLE_ME)
47780 	DUK_D(DUK_DPRINT("IEEE double endianness: mixed"));
47781 #elif defined(DUK_USE_DOUBLE_BE)
47782 	DUK_D(DUK_DPRINT("IEEE double endianness: big"));
47783 #else
47784 	DUK_D(DUK_DPRINT("IEEE double endianness: ???"));
47785 #endif
47786 }
47787 #endif  /* DUK_USE_DEBUG */
47788 
47789 DUK_INTERNAL
47790 duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
47791                          duk_realloc_function realloc_func,
47792                          duk_free_function free_func,
47793                          void *heap_udata,
47794                          duk_fatal_function fatal_func) {
47795 	duk_heap *res = NULL;
47796 	duk_uint32_t st_initsize;
47797 
47798 	DUK_D(DUK_DPRINT("allocate heap"));
47799 
47800 	/*
47801 	 *  Random config sanity asserts
47802 	 */
47803 
47804 	DUK_ASSERT(DUK_USE_STRTAB_MINSIZE >= 64);
47805 
47806 	DUK_ASSERT((DUK_HTYPE_STRING & 0x01U) == 0);
47807 	DUK_ASSERT((DUK_HTYPE_BUFFER & 0x01U) == 0);
47808 	DUK_ASSERT((DUK_HTYPE_OBJECT & 0x01U) == 1);  /* DUK_HEAPHDR_IS_OBJECT() relies ont his. */
47809 
47810 	/*
47811 	 *  Debug dump type sizes
47812 	 */
47813 
47814 #if defined(DUK_USE_DEBUG)
47815 	duk__dump_misc_options();
47816 	duk__dump_type_sizes();
47817 	duk__dump_type_limits();
47818 #endif
47819 
47820 	/*
47821 	 *  If selftests enabled, run them as early as possible.
47822 	 */
47823 
47824 #if defined(DUK_USE_SELF_TESTS)
47825 	DUK_D(DUK_DPRINT("run self tests"));
47826 	if (duk_selftest_run_tests(alloc_func, realloc_func, free_func, heap_udata) > 0) {
47827 		fatal_func(heap_udata, "self test(s) failed");
47828 	}
47829 	DUK_D(DUK_DPRINT("self tests passed"));
47830 #endif
47831 
47832 	/*
47833 	 *  Important assert-like checks that should be enabled even
47834 	 *  when assertions are otherwise not enabled.
47835 	 */
47836 
47837 #if defined(DUK_USE_EXEC_REGCONST_OPTIMIZE)
47838 	/* Can't check sizeof() using preprocessor so explicit check.
47839 	 * This will be optimized away in practice; unfortunately a
47840 	 * warning is generated on some compilers as a result.
47841 	 */
47842 #if defined(DUK_USE_PACKED_TVAL)
47843 	if (sizeof(duk_tval) != 8) {
47844 #else
47845 	if (sizeof(duk_tval) != 16) {
47846 #endif
47847 		fatal_func(heap_udata, "sizeof(duk_tval) not 8 or 16, cannot use DUK_USE_EXEC_REGCONST_OPTIMIZE option");
47848 	}
47849 #endif  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
47850 
47851 	/*
47852 	 *  Computed values (e.g. INFINITY)
47853 	 */
47854 
47855 #if defined(DUK_USE_COMPUTED_NAN)
47856 	do {
47857 		/* Workaround for some exotic platforms where NAN is missing
47858 		 * and the expression (0.0 / 0.0) does NOT result in a NaN.
47859 		 * Such platforms use the global 'duk_computed_nan' which must
47860 		 * be initialized at runtime.  Use 'volatile' to ensure that
47861 		 * the compiler will actually do the computation and not try
47862 		 * to do constant folding which might result in the original
47863 		 * problem.
47864 		 */
47865 		volatile double dbl1 = 0.0;
47866 		volatile double dbl2 = 0.0;
47867 		duk_computed_nan = dbl1 / dbl2;
47868 	} while (0);
47869 #endif
47870 
47871 #if defined(DUK_USE_COMPUTED_INFINITY)
47872 	do {
47873 		/* Similar workaround for INFINITY. */
47874 		volatile double dbl1 = 1.0;
47875 		volatile double dbl2 = 0.0;
47876 		duk_computed_infinity = dbl1 / dbl2;
47877 	} while (0);
47878 #endif
47879 
47880 	/*
47881 	 *  Allocate heap struct
47882 	 *
47883 	 *  Use a raw call, all macros expect the heap to be initialized
47884 	 */
47885 
47886 #if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 1)
47887 	goto failed;
47888 #endif
47889 	DUK_D(DUK_DPRINT("alloc duk_heap object"));
47890 	res = (duk_heap *) alloc_func(heap_udata, sizeof(duk_heap));
47891 	if (!res) {
47892 		goto failed;
47893 	}
47894 
47895 	/*
47896 	 *  Zero the struct, and start initializing roughly in order
47897 	 */
47898 
47899 	duk_memzero(res, sizeof(*res));
47900 #if defined(DUK_USE_ASSERTIONS)
47901 	res->heap_initializing = 1;
47902 #endif
47903 
47904 	/* explicit NULL inits */
47905 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
47906 	res->heap_udata = NULL;
47907 	res->heap_allocated = NULL;
47908 #if defined(DUK_USE_REFERENCE_COUNTING)
47909 	res->refzero_list = NULL;
47910 #endif
47911 #if defined(DUK_USE_FINALIZER_SUPPORT)
47912 	res->finalize_list = NULL;
47913 #if defined(DUK_USE_ASSERTIONS)
47914 	res->currently_finalizing = NULL;
47915 #endif
47916 #endif
47917 #if defined(DUK_USE_CACHE_ACTIVATION)
47918 	res->activation_free = NULL;
47919 #endif
47920 #if defined(DUK_USE_CACHE_CATCHER)
47921 	res->catcher_free = NULL;
47922 #endif
47923 	res->heap_thread = NULL;
47924 	res->curr_thread = NULL;
47925 	res->heap_object = NULL;
47926 #if defined(DUK_USE_STRTAB_PTRCOMP)
47927 	res->strtable16 = NULL;
47928 #else
47929 	res->strtable = NULL;
47930 #endif
47931 #if defined(DUK_USE_ROM_STRINGS)
47932 	/* no res->strs[] */
47933 #else  /* DUK_USE_ROM_STRINGS */
47934 #if defined(DUK_USE_HEAPPTR16)
47935 	/* res->strs16[] is zeroed and zero decodes to NULL, so no NULL inits. */
47936 #else
47937 	{
47938 		duk_small_uint_t i;
47939 	        for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
47940 			res->strs[i] = NULL;
47941 	        }
47942 	}
47943 #endif
47944 #endif  /* DUK_USE_ROM_STRINGS */
47945 #if defined(DUK_USE_DEBUGGER_SUPPORT)
47946 	res->dbg_read_cb = NULL;
47947 	res->dbg_write_cb = NULL;
47948 	res->dbg_peek_cb = NULL;
47949 	res->dbg_read_flush_cb = NULL;
47950 	res->dbg_write_flush_cb = NULL;
47951 	res->dbg_request_cb = NULL;
47952 	res->dbg_udata = NULL;
47953 	res->dbg_pause_act = NULL;
47954 #endif
47955 #endif  /* DUK_USE_EXPLICIT_NULL_INIT */
47956 
47957 	res->alloc_func = alloc_func;
47958 	res->realloc_func = realloc_func;
47959 	res->free_func = free_func;
47960 	res->heap_udata = heap_udata;
47961 	res->fatal_func = fatal_func;
47962 
47963 	/* XXX: for now there's a pointer packing zero assumption, i.e.
47964 	 * NULL <=> compressed pointer 0.  If this is removed, may need
47965 	 * to precompute e.g. null16 here.
47966 	 */
47967 
47968 	/* res->ms_trigger_counter == 0 -> now causes immediate GC; which is OK */
47969 
47970 	/* Prevent mark-and-sweep and finalizer execution until heap is completely
47971 	 * initialized.
47972 	 */
47973 	DUK_ASSERT(res->ms_prevent_count == 0);
47974 	DUK_ASSERT(res->pf_prevent_count == 0);
47975 	res->ms_prevent_count = 1;
47976 	res->pf_prevent_count = 1;
47977 	DUK_ASSERT(res->ms_running == 0);
47978 
47979 	res->call_recursion_depth = 0;
47980 	res->call_recursion_limit = DUK_USE_NATIVE_CALL_RECLIMIT;
47981 
47982 	/* XXX: use the pointer as a seed for now: mix in time at least */
47983 
47984 	/* The casts through duk_uintptr_t is to avoid the following GCC warning:
47985 	 *
47986 	 *   warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
47987 	 *
47988 	 * This still generates a /Wp64 warning on VS2010 when compiling for x86.
47989 	 */
47990 #if defined(DUK_USE_ROM_STRINGS)
47991 	/* XXX: make a common DUK_USE_ option, and allow custom fixed seed? */
47992 	DUK_D(DUK_DPRINT("using rom strings, force heap hash_seed to fixed value 0x%08lx", (long) DUK__FIXED_HASH_SEED));
47993 	res->hash_seed = (duk_uint32_t) DUK__FIXED_HASH_SEED;
47994 #else  /* DUK_USE_ROM_STRINGS */
47995 	res->hash_seed = (duk_uint32_t) (duk_uintptr_t) res;
47996 #if !defined(DUK_USE_STRHASH_DENSE)
47997 	res->hash_seed ^= 5381;  /* Bernstein hash init value is normally 5381; XOR it in in case pointer low bits are 0 */
47998 #endif
47999 #endif  /* DUK_USE_ROM_STRINGS */
48000 
48001 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
48002 	res->lj.jmpbuf_ptr = NULL;
48003 #endif
48004 	DUK_ASSERT(res->lj.type == DUK_LJ_TYPE_UNKNOWN);  /* zero */
48005 	DUK_ASSERT(res->lj.iserror == 0);
48006 	DUK_TVAL_SET_UNDEFINED(&res->lj.value1);
48007 	DUK_TVAL_SET_UNDEFINED(&res->lj.value2);
48008 
48009 	DUK_ASSERT_LJSTATE_UNSET(res);
48010 
48011 	/*
48012 	 *  Init stringtable: fixed variant
48013 	 */
48014 
48015 	st_initsize = DUK_USE_STRTAB_MINSIZE;
48016 #if defined(DUK_USE_STRTAB_PTRCOMP)
48017 	res->strtable16 = (duk_uint16_t *) alloc_func(heap_udata, sizeof(duk_uint16_t) * st_initsize);
48018 	if (res->strtable16 == NULL) {
48019 		goto failed;
48020 	}
48021 #else
48022 	res->strtable = (duk_hstring **) alloc_func(heap_udata, sizeof(duk_hstring *) * st_initsize);
48023 	if (res->strtable == NULL) {
48024 		goto failed;
48025 	}
48026 #endif
48027 	res->st_size = st_initsize;
48028 	res->st_mask = st_initsize - 1;
48029 #if (DUK_USE_STRTAB_MINSIZE != DUK_USE_STRTAB_MAXSIZE)
48030 	DUK_ASSERT(res->st_count == 0);
48031 #endif
48032 
48033 #if defined(DUK_USE_STRTAB_PTRCOMP)
48034 	/* zero assumption */
48035 	duk_memzero(res->strtable16, sizeof(duk_uint16_t) * st_initsize);
48036 #else
48037 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
48038 	{
48039 		duk_uint32_t i;
48040 	        for (i = 0; i < st_initsize; i++) {
48041 			res->strtable[i] = NULL;
48042 	        }
48043 	}
48044 #else
48045 	duk_memzero(res->strtable, sizeof(duk_hstring *) * st_initsize);
48046 #endif  /* DUK_USE_EXPLICIT_NULL_INIT */
48047 #endif  /* DUK_USE_STRTAB_PTRCOMP */
48048 
48049 	/*
48050 	 *  Init stringcache
48051 	 */
48052 
48053 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
48054 	{
48055 		duk_uint_t i;
48056 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
48057 			res->strcache[i].h = NULL;
48058 		}
48059 	}
48060 #endif
48061 
48062 	/*
48063 	 *  Init litcache
48064 	 */
48065 #if defined(DUK_USE_LITCACHE_SIZE)
48066 	DUK_ASSERT(DUK_USE_LITCACHE_SIZE > 0);
48067 	DUK_ASSERT(DUK_IS_POWER_OF_TWO((duk_uint_t) DUK_USE_LITCACHE_SIZE));
48068 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
48069 	{
48070 		duk_uint_t i;
48071 		for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
48072 			res->litcache[i].addr = NULL;
48073 			res->litcache[i].h = NULL;
48074 		}
48075 	}
48076 #endif
48077 #endif  /* DUK_USE_LITCACHE_SIZE */
48078 
48079 	/* XXX: error handling is incomplete.  It would be cleanest if
48080 	 * there was a setjmp catchpoint, so that all init code could
48081 	 * freely throw errors.  If that were the case, the return code
48082 	 * passing here could be removed.
48083 	 */
48084 
48085 	/*
48086 	 *  Init built-in strings
48087 	 */
48088 
48089 #if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 2)
48090 	goto failed;
48091 #endif
48092 	DUK_D(DUK_DPRINT("heap init: initialize heap strings"));
48093 	if (!duk__init_heap_strings(res)) {
48094 		goto failed;
48095 	}
48096 
48097 	/*
48098 	 *  Init the heap thread
48099 	 */
48100 
48101 #if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 3)
48102 	goto failed;
48103 #endif
48104 	DUK_D(DUK_DPRINT("heap init: initialize heap thread"));
48105 	if (!duk__init_heap_thread(res)) {
48106 		goto failed;
48107 	}
48108 
48109 	/*
48110 	 *  Init the heap object
48111 	 */
48112 
48113 #if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 4)
48114 	goto failed;
48115 #endif
48116 	DUK_D(DUK_DPRINT("heap init: initialize heap object"));
48117 	DUK_ASSERT(res->heap_thread != NULL);
48118 	res->heap_object = duk_hobject_alloc_unchecked(res, DUK_HOBJECT_FLAG_EXTENSIBLE |
48119 	                                                    DUK_HOBJECT_FLAG_FASTREFS |
48120 	                                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT));
48121 	if (res->heap_object == NULL) {
48122 		goto failed;
48123 	}
48124 	DUK_HOBJECT_INCREF(res->heap_thread, res->heap_object);
48125 
48126 	/*
48127 	 *  Odds and ends depending on the heap thread
48128 	 */
48129 
48130 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
48131 #if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
48132 	res->rnd_state = (duk_uint32_t) duk_time_get_ecmascript_time(res->heap_thread);
48133 	duk_util_tinyrandom_prepare_seed(res->heap_thread);
48134 #else
48135 	res->rnd_state[0] = (duk_uint64_t) duk_time_get_ecmascript_time(res->heap_thread);
48136 	DUK_ASSERT(res->rnd_state[1] == 0);  /* Not filled here, filled in by seed preparation. */
48137 #if 0  /* Manual test values matching misc/xoroshiro128plus_test.c. */
48138 	res->rnd_state[0] = DUK_U64_CONSTANT(0xdeadbeef12345678);
48139 	res->rnd_state[1] = DUK_U64_CONSTANT(0xcafed00d12345678);
48140 #endif
48141 	duk_util_tinyrandom_prepare_seed(res->heap_thread);
48142 	/* Mix in heap pointer: this ensures that if two Duktape heaps are
48143 	 * created on the same millisecond, they get a different PRNG
48144 	 * sequence (unless e.g. virtual memory addresses cause also the
48145 	 * heap object pointer to be the same).
48146 	 */
48147 	{
48148 		duk_uint64_t tmp_u64;
48149 		tmp_u64 = 0;
48150 		duk_memcpy((void *) &tmp_u64,
48151 		           (const void *) &res,
48152 		           (size_t) (sizeof(void *) >= sizeof(duk_uint64_t) ? sizeof(duk_uint64_t) : sizeof(void *)));
48153 		res->rnd_state[1] ^= tmp_u64;
48154 	}
48155 	do {
48156 		duk_small_uint_t i;
48157 		for (i = 0; i < 10; i++) {
48158 			/* Throw away a few initial random numbers just in
48159 			 * case.  Probably unnecessary due to SplitMix64
48160 			 * preparation.
48161 			 */
48162 			(void) duk_util_tinyrandom_get_double(res->heap_thread);
48163 		}
48164 	} while (0);
48165 #endif
48166 #endif
48167 
48168 	/*
48169 	 *  Allow finalizer and mark-and-sweep processing.
48170 	 */
48171 
48172 	DUK_D(DUK_DPRINT("heap init: allow finalizer/mark-and-sweep processing"));
48173 	DUK_ASSERT(res->ms_prevent_count == 1);
48174 	DUK_ASSERT(res->pf_prevent_count == 1);
48175 	res->ms_prevent_count = 0;
48176 	res->pf_prevent_count = 0;
48177 	DUK_ASSERT(res->ms_running == 0);
48178 #if defined(DUK_USE_ASSERTIONS)
48179 	res->heap_initializing = 0;
48180 #endif
48181 
48182 	/*
48183 	 *  All done.
48184 	 */
48185 
48186 	DUK_D(DUK_DPRINT("allocated heap: %p", (void *) res));
48187 	return res;
48188 
48189  failed:
48190 	DUK_D(DUK_DPRINT("heap allocation failed"));
48191 
48192 	if (res != NULL) {
48193 		/* Assumes that allocated pointers and alloc funcs are valid
48194 		 * if res exists.
48195 		 */
48196 		DUK_ASSERT(res->ms_prevent_count == 1);
48197 		DUK_ASSERT(res->pf_prevent_count == 1);
48198 		DUK_ASSERT(res->ms_running == 0);
48199 		if (res->heap_thread != NULL) {
48200 			res->ms_prevent_count = 0;
48201 			res->pf_prevent_count = 0;
48202 		}
48203 #if defined(DUK_USE_ASSERTIONS)
48204 		res->heap_initializing = 0;
48205 #endif
48206 
48207 		DUK_ASSERT(res->alloc_func != NULL);
48208 		DUK_ASSERT(res->realloc_func != NULL);
48209 		DUK_ASSERT(res->free_func != NULL);
48210 		duk_heap_free(res);
48211 	}
48212 
48213 	return NULL;
48214 }
48215 
48216 /* automatic undefs */
48217 #undef DUK__DUMPLM_SIGNED
48218 #undef DUK__DUMPLM_SIGNED_RAW
48219 #undef DUK__DUMPLM_UNSIGNED
48220 #undef DUK__DUMPLM_UNSIGNED_RAW
48221 #undef DUK__DUMPSZ
48222 #undef DUK__FIXED_HASH_SEED
48223 #line 1 "duk_heap_finalize.c"
48224 /*
48225  *  Finalizer handling.
48226  */
48227 
48228 /* #include duk_internal.h -> already included */
48229 
48230 #if defined(DUK_USE_FINALIZER_SUPPORT)
48231 
48232 /*
48233  *  Fake torture finalizer.
48234  */
48235 
48236 #if defined(DUK_USE_FINALIZER_TORTURE)
48237 DUK_LOCAL duk_ret_t duk__fake_global_finalizer(duk_hthread *thr) {
48238 	DUK_DD(DUK_DDPRINT("fake global torture finalizer executed"));
48239 
48240 	/* Require a lot of stack to force a value stack grow/shrink. */
48241 	duk_require_stack(thr, 100000);
48242 
48243 	/* Force a reallocation with pointer change for value stack
48244 	 * to maximize side effects.
48245 	 */
48246 	duk_hthread_valstack_torture_realloc(thr);
48247 
48248 	/* Inner function call, error throw. */
48249 	duk_eval_string_noresult(thr,
48250 		"(function dummy() {\n"
48251 		"    dummy.prototype = null;  /* break reference loop */\n"
48252 		"    try {\n"
48253 		"        throw 'fake-finalizer-dummy-error';\n"
48254 		"    } catch (e) {\n"
48255 		"        void e;\n"
48256 		"    }\n"
48257 		"})()");
48258 
48259 	/* The above creates garbage (e.g. a function instance).  Because
48260 	 * the function/prototype reference loop is broken, it gets collected
48261 	 * immediately by DECREF.  If Function.prototype has a _Finalizer
48262 	 * property (happens in some test cases), the garbage gets queued to
48263 	 * finalize_list.  This still won't cause an infinite loop because
48264 	 * the torture finalizer is called once per finalize_list run and
48265 	 * the garbage gets handled in the same run.  (If the garbage needs
48266 	 * mark-and-sweep collection, an infinite loop might ensue.)
48267 	 */
48268 	return 0;
48269 }
48270 
48271 DUK_LOCAL void duk__run_global_torture_finalizer(duk_hthread *thr) {
48272 	DUK_ASSERT(thr != NULL);
48273 
48274 	/* Avoid fake finalization when callstack limit is near.  Otherwise
48275 	 * a callstack limit error will be created, then refzero'ed.  The
48276 	 * +5 headroom is conservative.
48277 	 */
48278 	if (thr->heap->call_recursion_depth + 5 >= thr->heap->call_recursion_limit ||
48279 	    thr->callstack_top + 5 >= DUK_USE_CALLSTACK_LIMIT) {
48280 		DUK_D(DUK_DPRINT("skip global torture finalizer, too little headroom for call recursion or call stack size"));
48281 		return;
48282 	}
48283 
48284 	/* Run fake finalizer.  Avoid creating unnecessary garbage. */
48285 	duk_push_c_function(thr, duk__fake_global_finalizer, 0 /*nargs*/);
48286 	(void) duk_pcall(thr, 0 /*nargs*/);
48287 	duk_pop(thr);
48288 }
48289 #endif  /* DUK_USE_FINALIZER_TORTURE */
48290 
48291 /*
48292  *  Process the finalize_list to completion.
48293  *
48294  *  An object may be placed on finalize_list by either refcounting or
48295  *  mark-and-sweep.  The refcount of objects placed by refcounting will be
48296  *  zero; the refcount of objects placed by mark-and-sweep is > 0.  In both
48297  *  cases the refcount is bumped by 1 artificially so that a REFZERO event
48298  *  can never happen while an object is waiting for finalization.  Without
48299  *  this bump a REFZERO could now happen because user code may call
48300  *  duk_push_heapptr() and then pop a value even when it's on finalize_list.
48301  *
48302  *  List processing assumes refcounts are kept up-to-date at all times, so
48303  *  that once the finalizer returns, a zero refcount is a reliable reason to
48304  *  free the object immediately rather than place it back to the heap.  This
48305  *  is the case because we run outside of refzero_list processing so that
48306  *  DECREF cascades are handled fully inline.
48307  *
48308  *  For mark-and-sweep queued objects (had_zero_refcount false) the object
48309  *  may be freed immediately if its refcount is zero after the finalizer call
48310  *  (i.e. finalizer removed the reference loop for the object).  If not, the
48311  *  next mark-and-sweep will collect the object unless it has become reachable
48312  *  (i.e. rescued) by that time and its refcount hasn't fallen to zero before
48313  *  that.  Mark-and-sweep detects these objects because their FINALIZED flag
48314  *  is set.
48315  *
48316  *  There's an inherent limitation for mark-and-sweep finalizer rescuing: an
48317  *  object won't get refinalized if (1) it's rescued, but (2) becomes
48318  *  unreachable before mark-and-sweep has had time to notice it.  The next
48319  *  mark-and-sweep round simply doesn't have any information of whether the
48320  *  object has been unreachable the whole time or not (the only way to get
48321  *  that information would be a mark-and-sweep pass for *every finalized
48322  *  object*).  This is awkward for the application because the mark-and-sweep
48323  *  round is not generally visible or under full application control.
48324  *
48325  *  For refcount queued objects (had_zero_refcount true) the object is either
48326  *  immediately freed or rescued, and waiting for a mark-and-sweep round is not
48327  *  necessary (or desirable); FINALIZED is cleared when a rescued object is
48328  *  queued back to heap_allocated.  The object is eligible for finalization
48329  *  again (either via refcounting or mark-and-sweep) immediately after being
48330  *  rescued.  If a refcount finalized object is placed into an unreachable
48331  *  reference loop by its finalizer, it will get collected by mark-and-sweep
48332  *  and currently the finalizer will execute again.
48333  *
48334  *  There's a special case where:
48335  *
48336  *    - Mark-and-sweep queues an object to finalize_list for finalization.
48337  *    - The finalizer is executed, FINALIZED is set, and object is queued
48338  *      back to heap_allocated, waiting for a new mark-and-sweep round.
48339  *    - The object's refcount drops to zero before mark-and-sweep has a
48340  *      chance to run another round and make a rescue/free decision.
48341  *
48342  *  This is now handled by refzero code: if an object has a finalizer but
48343  *  FINALIZED is already set, the object is freed without finalizer processing.
48344  *  The outcome is the same as if mark-and-sweep was executed at that point;
48345  *  mark-and-sweep would also free the object without another finalizer run.
48346  *  This could also be changed so that the refzero-triggered finalizer *IS*
48347  *  executed: being refzero collected implies someone has operated on the
48348  *  object so it hasn't been totally unreachable the whole time.  This would
48349  *  risk a finalizer loop however.
48350  */
48351 
48352 DUK_INTERNAL void duk_heap_process_finalize_list(duk_heap *heap) {
48353 	duk_heaphdr *curr;
48354 #if defined(DUK_USE_DEBUG)
48355 	duk_size_t count = 0;
48356 #endif
48357 
48358 	DUK_DDD(DUK_DDDPRINT("duk_heap_process_finalize_list: %p", (void *) heap));
48359 
48360 	if (heap->pf_prevent_count != 0) {
48361 		DUK_DDD(DUK_DDDPRINT("skip finalize_list processing: pf_prevent_count != 0"));
48362 		return;
48363 	}
48364 
48365 	/* Heap alloc prevents mark-and-sweep before heap_thread is ready. */
48366 	DUK_ASSERT(heap != NULL);
48367 	DUK_ASSERT(heap->heap_thread != NULL);
48368 	DUK_ASSERT(heap->heap_thread->valstack != NULL);
48369 #if defined(DUK_USE_REFERENCE_COUNTING)
48370 	DUK_ASSERT(heap->refzero_list == NULL);
48371 #endif
48372 
48373 	DUK_ASSERT(heap->pf_prevent_count == 0);
48374 	heap->pf_prevent_count = 1;
48375 
48376 	/* Mark-and-sweep no longer needs to be prevented when running
48377 	 * finalizers: mark-and-sweep skips any rescue decisions if there
48378 	 * are any objects in finalize_list when mark-and-sweep is entered.
48379 	 * This protects finalized objects from incorrect rescue decisions
48380 	 * caused by finalize_list being a reachability root and only
48381 	 * partially processed.  Freeing decisions are not postponed.
48382 	 */
48383 
48384 	/* When finalizer torture is enabled, make a fake finalizer call with
48385 	 * maximum side effects regardless of whether finalize_list is empty.
48386 	 */
48387 #if defined(DUK_USE_FINALIZER_TORTURE)
48388 	duk__run_global_torture_finalizer(heap->heap_thread);
48389 #endif
48390 
48391 	/* Process finalize_list until it becomes empty.  There's currently no
48392 	 * protection against a finalizer always creating more garbage.
48393 	 */
48394 	while ((curr = heap->finalize_list) != NULL) {
48395 #if defined(DUK_USE_REFERENCE_COUNTING)
48396 		duk_bool_t queue_back;
48397 #endif
48398 
48399 		DUK_DD(DUK_DDPRINT("processing finalize_list entry: %p -> %!iO", (void *) curr, curr));
48400 
48401 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* Only objects have finalizers. */
48402 		DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr));
48403 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(curr));
48404 		DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(curr));  /* All objects on finalize_list will have this flag (except object being finalized right now). */
48405 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));   /* Queueing code ensures. */
48406 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr));  /* ROM objects never get freed (or finalized). */
48407 
48408 #if defined(DUK_USE_ASSERTIONS)
48409 		DUK_ASSERT(heap->currently_finalizing == NULL);
48410 		heap->currently_finalizing = curr;
48411 #endif
48412 
48413 		/* Clear FINALIZABLE for object being finalized, so that
48414 		 * duk_push_heapptr() can properly ignore the object.
48415 		 */
48416 		DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
48417 
48418 		if (DUK_LIKELY(!heap->pf_skip_finalizers)) {
48419 			/* Run the finalizer, duk_heap_run_finalizer() sets
48420 			 * and checks for FINALIZED to prevent the finalizer
48421 			 * from executing multiple times per finalization cycle.
48422 			 * (This safeguard shouldn't be actually needed anymore).
48423 			 */
48424 
48425 #if defined(DUK_USE_REFERENCE_COUNTING)
48426 			duk_bool_t had_zero_refcount;
48427 #endif
48428 
48429 			/* The object's refcount is >0 throughout so it won't be
48430 			 * refzero processed prematurely.
48431 			 */
48432 #if defined(DUK_USE_REFERENCE_COUNTING)
48433 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);
48434 			had_zero_refcount = (DUK_HEAPHDR_GET_REFCOUNT(curr) == 1);  /* Preincremented on finalize_list insert. */
48435 #endif
48436 
48437 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
48438 			duk_heap_run_finalizer(heap, (duk_hobject *) curr);  /* must never longjmp */
48439 			DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(curr));
48440 			/* XXX: assert that object is still in finalize_list
48441 			 * when duk_push_heapptr() allows automatic rescue.
48442 			 */
48443 
48444 #if defined(DUK_USE_REFERENCE_COUNTING)
48445 			DUK_DD(DUK_DDPRINT("refcount after finalizer (includes bump): %ld", (long) DUK_HEAPHDR_GET_REFCOUNT(curr)));
48446 			if (DUK_HEAPHDR_GET_REFCOUNT(curr) == 1) {  /* Only artificial bump in refcount? */
48447 #if defined(DUK_USE_DEBUG)
48448 				if (had_zero_refcount) {
48449 					DUK_DD(DUK_DDPRINT("finalized object's refcount is zero -> free immediately (refcount queued)"));
48450 				} else {
48451 					DUK_DD(DUK_DDPRINT("finalized object's refcount is zero -> free immediately (mark-and-sweep queued)"));
48452 				}
48453 #endif
48454 				queue_back = 0;
48455 			} else
48456 #endif
48457 			{
48458 #if defined(DUK_USE_REFERENCE_COUNTING)
48459 				queue_back = 1;
48460 				if (had_zero_refcount) {
48461 					/* When finalization is triggered
48462 					 * by refzero and we queue the object
48463 					 * back, clear FINALIZED right away
48464 					 * so that the object can be refinalized
48465 					 * immediately if necessary.
48466 					 */
48467 					DUK_HEAPHDR_CLEAR_FINALIZED(curr);
48468 				}
48469 #endif
48470 			}
48471 		} else {
48472 			/* Used during heap destruction: don't actually run finalizers
48473 			 * because we're heading into forced finalization.  Instead,
48474 			 * queue finalizable objects back to the heap_allocated list.
48475 			 */
48476 			DUK_D(DUK_DPRINT("skip finalizers flag set, queue object to heap_allocated without finalizing"));
48477 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
48478 #if defined(DUK_USE_REFERENCE_COUNTING)
48479 			queue_back = 1;
48480 #endif
48481 		}
48482 
48483 		/* Dequeue object from finalize_list.  Note that 'curr' may no
48484 		 * longer be finalize_list head because new objects may have
48485 		 * been queued to the list.  As a result we can't optimize for
48486 		 * the single-linked heap case and must scan the list for
48487 		 * removal, typically the scan is very short however.
48488 		 */
48489 		DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(heap, curr);
48490 
48491 		/* Queue back to heap_allocated or free immediately. */
48492 #if defined(DUK_USE_REFERENCE_COUNTING)
48493 		if (queue_back) {
48494 			/* FINALIZED is only cleared if object originally
48495 			 * queued for finalization by refcounting.  For
48496 			 * mark-and-sweep FINALIZED is left set, so that
48497 			 * next mark-and-sweep round can make a rescue/free
48498 			 * decision.
48499 			 */
48500 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);
48501 			DUK_HEAPHDR_PREDEC_REFCOUNT(curr);  /* Remove artificial refcount bump. */
48502 			DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
48503 			DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, curr);
48504 		} else {
48505 			/* No need to remove the refcount bump here. */
48506 			DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* currently, always the case */
48507 			DUK_DD(DUK_DDPRINT("refcount finalize after finalizer call: %!O", curr));
48508 			duk_hobject_refcount_finalize_norz(heap, (duk_hobject *) curr);
48509 			duk_free_hobject(heap, (duk_hobject *) curr);
48510 			DUK_DD(DUK_DDPRINT("freed hobject after finalization: %p", (void *) curr));
48511 		}
48512 #else  /* DUK_USE_REFERENCE_COUNTING */
48513 		DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
48514 		DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, curr);
48515 #endif  /* DUK_USE_REFERENCE_COUNTING */
48516 
48517 #if defined(DUK_USE_DEBUG)
48518 		count++;
48519 #endif
48520 
48521 #if defined(DUK_USE_ASSERTIONS)
48522 		DUK_ASSERT(heap->currently_finalizing != NULL);
48523 		heap->currently_finalizing = NULL;
48524 #endif
48525 	}
48526 
48527 	/* finalize_list will always be processed completely. */
48528 	DUK_ASSERT(heap->finalize_list == NULL);
48529 
48530 #if 0
48531 	/* While NORZ macros are used above, this is unnecessary because the
48532 	 * only pending side effects are now finalizers, and finalize_list is
48533 	 * empty.
48534 	 */
48535 	DUK_REFZERO_CHECK_SLOW(heap->heap_thread);
48536 #endif
48537 
48538 	/* Prevent count may be bumped while finalizers run, but should always
48539 	 * be reliably unbumped by the time we get here.
48540 	 */
48541 	DUK_ASSERT(heap->pf_prevent_count == 1);
48542 	heap->pf_prevent_count = 0;
48543 
48544 #if defined(DUK_USE_DEBUG)
48545 	DUK_DD(DUK_DDPRINT("duk_heap_process_finalize_list: %ld finalizers called", (long) count));
48546 #endif
48547 }
48548 
48549 /*
48550  *  Run an duk_hobject finalizer.  Must never throw an uncaught error
48551  *  (but may throw caught errors).
48552  *
48553  *  There is no return value.  Any return value or error thrown by
48554  *  the finalizer is ignored (although errors are debug logged).
48555  *
48556  *  Notes:
48557  *
48558  *    - The finalizer thread 'top' assertions are there because it is
48559  *      critical that strict stack policy is observed (i.e. no cruft
48560  *      left on the finalizer stack).
48561  */
48562 
48563 DUK_LOCAL duk_ret_t duk__finalize_helper(duk_hthread *thr, void *udata) {
48564 	DUK_ASSERT(thr != NULL);
48565 	DUK_UNREF(udata);
48566 
48567 	DUK_DDD(DUK_DDDPRINT("protected finalization helper running"));
48568 
48569 	/* [... obj] */
48570 
48571 	/* _Finalizer property is read without checking if the value is
48572 	 * callable or even exists.  This is intentional, and handled
48573 	 * by throwing an error which is caught by the safe call wrapper.
48574 	 *
48575 	 * XXX: Finalizer lookup should traverse the prototype chain (to allow
48576 	 * inherited finalizers) but should not invoke accessors or proxy object
48577 	 * behavior.  At the moment this lookup will invoke proxy behavior, so
48578 	 * caller must ensure that this function is not called if the target is
48579 	 * a Proxy.
48580 	 */
48581 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_FINALIZER);  /* -> [... obj finalizer] */
48582 	duk_dup_m2(thr);
48583 	duk_push_boolean(thr, DUK_HEAP_HAS_FINALIZER_NORESCUE(thr->heap));
48584 	DUK_DDD(DUK_DDDPRINT("calling finalizer"));
48585 	duk_call(thr, 2);  /* [ ... obj finalizer obj heapDestruct ]  -> [ ... obj retval ] */
48586 	DUK_DDD(DUK_DDDPRINT("finalizer returned successfully"));
48587 	return 0;
48588 
48589 	/* Note: we rely on duk_safe_call() to fix up the stack for the caller,
48590 	 * so we don't need to pop stuff here.  There is no return value;
48591 	 * caller determines rescued status based on object refcount.
48592 	 */
48593 }
48594 
48595 DUK_INTERNAL void duk_heap_run_finalizer(duk_heap *heap, duk_hobject *obj) {
48596 	duk_hthread *thr;
48597 	duk_ret_t rc;
48598 #if defined(DUK_USE_ASSERTIONS)
48599 	duk_idx_t entry_top;
48600 #endif
48601 
48602 	DUK_DD(DUK_DDPRINT("running duk_hobject finalizer for object: %p", (void *) obj));
48603 
48604 	DUK_ASSERT(heap != NULL);
48605 	DUK_ASSERT(heap->heap_thread != NULL);
48606 	thr = heap->heap_thread;
48607 	DUK_ASSERT(obj != NULL);
48608 	DUK_ASSERT_VALSTACK_SPACE(heap->heap_thread, 1);
48609 
48610 #if defined(DUK_USE_ASSERTIONS)
48611 	entry_top = duk_get_top(thr);
48612 #endif
48613 	/*
48614 	 *  Get and call the finalizer.  All of this must be wrapped
48615 	 *  in a protected call, because even getting the finalizer
48616 	 *  may trigger an error (getter may throw one, for instance).
48617 	 */
48618 
48619 	/* ROM objects could inherit a finalizer, but they are never deemed
48620 	 * unreachable by mark-and-sweep, and their refcount never falls to 0.
48621 	 */
48622 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
48623 
48624 	/* Duktape 2.1: finalize_list never contains objects with FINALIZED
48625 	 * set, so no need to check here.
48626 	 */
48627 	DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) obj));
48628 #if 0
48629 	if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) obj)) {
48630 		DUK_D(DUK_DPRINT("object already finalized, avoid running finalizer twice: %!O", obj));
48631 		return;
48632 	}
48633 #endif
48634 	DUK_HEAPHDR_SET_FINALIZED((duk_heaphdr *) obj);  /* ensure never re-entered until rescue cycle complete */
48635 
48636 #if defined(DUK_USE_ES6_PROXY)
48637 	if (DUK_HOBJECT_IS_PROXY(obj)) {
48638 		/* This may happen if duk_set_finalizer() or Duktape.fin() is
48639 		 * called for a Proxy object.  In such cases the fast finalizer
48640 		 * flag will be set on the Proxy, not the target, and neither
48641 		 * will be finalized.
48642 		 */
48643 		DUK_D(DUK_DPRINT("object is a Proxy, skip finalizer call"));
48644 		return;
48645 	}
48646 #endif  /* DUK_USE_ES6_PROXY */
48647 
48648 	duk_push_hobject(thr, obj);  /* this also increases refcount by one */
48649 	rc = duk_safe_call(thr, duk__finalize_helper, NULL /*udata*/, 0 /*nargs*/, 1 /*nrets*/);  /* -> [... obj retval/error] */
48650 	DUK_ASSERT_TOP(thr, entry_top + 2);  /* duk_safe_call discipline */
48651 
48652 	if (rc != DUK_EXEC_SUCCESS) {
48653 		/* Note: we ask for one return value from duk_safe_call to get this
48654 		 * error debugging here.
48655 		 */
48656 		DUK_D(DUK_DPRINT("wrapped finalizer call failed for object %p (ignored); error: %!T",
48657 		                 (void *) obj, (duk_tval *) duk_get_tval(thr, -1)));
48658 	}
48659 	duk_pop_2(thr);  /* -> [...] */
48660 
48661 	DUK_ASSERT_TOP(thr, entry_top);
48662 }
48663 
48664 #else  /* DUK_USE_FINALIZER_SUPPORT */
48665 
48666 /* nothing */
48667 
48668 #endif  /* DUK_USE_FINALIZER_SUPPORT */
48669 #line 1 "duk_heap_hashstring.c"
48670 /*
48671  *  String hash computation (interning).
48672  *
48673  *  String hashing is performance critical because a string hash is computed
48674  *  for all new strings which are candidates to be added to the string table.
48675  *  However, strings actually added to the string table go through a codepoint
48676  *  length calculation which dominates performance because it goes through
48677  *  every byte of the input string (but only for strings added).
48678  *
48679  *  The string hash algorithm should be fast, but on the other hand provide
48680  *  good enough hashes to ensure both string table and object property table
48681  *  hash tables work reasonably well (i.e., there aren't too many collisions
48682  *  with real world inputs).  Unless the hash is cryptographic, it's always
48683  *  possible to craft inputs with maximal hash collisions.
48684  *
48685  *  NOTE: The hash algorithms must match tools/dukutil.py:duk_heap_hashstring()
48686  *  for ROM string support!
48687  */
48688 
48689 /* #include duk_internal.h -> already included */
48690 
48691 #if defined(DUK_USE_STRHASH_DENSE)
48692 /* Constants for duk_hashstring(). */
48693 #define DUK__STRHASH_SHORTSTRING   4096L
48694 #define DUK__STRHASH_MEDIUMSTRING  (256L * 1024L)
48695 #define DUK__STRHASH_BLOCKSIZE     256L
48696 
48697 DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
48698 	duk_uint32_t hash;
48699 
48700 	/* Use Murmurhash2 directly for short strings, and use "block skipping"
48701 	 * for long strings: hash an initial part and then sample the rest of
48702 	 * the string with reasonably sized chunks.  An initial offset for the
48703 	 * sampling is computed based on a hash of the initial part of the string;
48704 	 * this is done to (usually) avoid the case where all long strings have
48705 	 * certain offset ranges which are never sampled.
48706 	 *
48707 	 * Skip should depend on length and bound the total time to roughly
48708 	 * logarithmic.  With current values:
48709 	 *
48710 	 *   1M string => 256 * 241 = 61696 bytes (0.06M) of hashing
48711 	 *   1G string => 256 * 16321 = 4178176 bytes (3.98M) of hashing
48712 	 *
48713 	 * XXX: It would be better to compute the skip offset more "smoothly"
48714 	 * instead of having a few boundary values.
48715 	 */
48716 
48717 	/* note: mixing len into seed improves hashing when skipping */
48718 	duk_uint32_t str_seed = heap->hash_seed ^ ((duk_uint32_t) len);
48719 
48720 	if (len <= DUK__STRHASH_SHORTSTRING) {
48721 		hash = duk_util_hashbytes(str, len, str_seed);
48722 	} else {
48723 		duk_size_t off;
48724 		duk_size_t skip;
48725 
48726 		if (len <= DUK__STRHASH_MEDIUMSTRING) {
48727 			skip = (duk_size_t) (16 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
48728 		} else {
48729 			skip = (duk_size_t) (256 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
48730 		}
48731 
48732 		hash = duk_util_hashbytes(str, (duk_size_t) DUK__STRHASH_SHORTSTRING, str_seed);
48733 		off = DUK__STRHASH_SHORTSTRING + (skip * (hash % 256)) / 256;
48734 
48735 		/* XXX: inefficient loop */
48736 		while (off < len) {
48737 			duk_size_t left = len - off;
48738 			duk_size_t now = (duk_size_t) (left > DUK__STRHASH_BLOCKSIZE ? DUK__STRHASH_BLOCKSIZE : left);
48739 			hash ^= duk_util_hashbytes(str + off, now, str_seed);
48740 			off += skip;
48741 		}
48742 	}
48743 
48744 #if defined(DUK_USE_STRHASH16)
48745 	/* Truncate to 16 bits here, so that a computed hash can be compared
48746 	 * against a hash stored in a 16-bit field.
48747 	 */
48748 	hash &= 0x0000ffffUL;
48749 #endif
48750 	return hash;
48751 }
48752 #else  /* DUK_USE_STRHASH_DENSE */
48753 DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
48754 	duk_uint32_t hash;
48755 	duk_size_t step;
48756 	duk_size_t off;
48757 
48758 	/* Slightly modified "Bernstein hash" from:
48759 	 *
48760 	 *     http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
48761 	 *
48762 	 * Modifications: string skipping and reverse direction similar to
48763 	 * Lua 5.1.5, and different hash initializer.
48764 	 *
48765 	 * The reverse direction ensures last byte it always included in the
48766 	 * hash which is a good default as changing parts of the string are
48767 	 * more often in the suffix than in the prefix.
48768 	 */
48769 
48770 	hash = heap->hash_seed ^ ((duk_uint32_t) len);  /* Bernstein hash init value is normally 5381 */
48771 	step = (len >> DUK_USE_STRHASH_SKIP_SHIFT) + 1;
48772 	for (off = len; off >= step; off -= step) {
48773 		DUK_ASSERT(off >= 1);  /* off >= step, and step >= 1 */
48774 		hash = (hash * 33) + str[off - 1];
48775 	}
48776 
48777 #if defined(DUK_USE_STRHASH16)
48778 	/* Truncate to 16 bits here, so that a computed hash can be compared
48779 	 * against a hash stored in a 16-bit field.
48780 	 */
48781 	hash &= 0x0000ffffUL;
48782 #endif
48783 	return hash;
48784 }
48785 #endif  /* DUK_USE_STRHASH_DENSE */
48786 
48787 /* automatic undefs */
48788 #undef DUK__STRHASH_BLOCKSIZE
48789 #undef DUK__STRHASH_MEDIUMSTRING
48790 #undef DUK__STRHASH_SHORTSTRING
48791 #line 1 "duk_heap_markandsweep.c"
48792 /*
48793  *  Mark-and-sweep garbage collection.
48794  */
48795 
48796 /* #include duk_internal.h -> already included */
48797 
48798 DUK_LOCAL_DECL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h);
48799 DUK_LOCAL_DECL void duk__mark_heaphdr_nonnull(duk_heap *heap, duk_heaphdr *h);
48800 DUK_LOCAL_DECL void duk__mark_tval(duk_heap *heap, duk_tval *tv);
48801 DUK_LOCAL_DECL void duk__mark_tvals(duk_heap *heap, duk_tval *tv, duk_idx_t count);
48802 
48803 /*
48804  *  Marking functions for heap types: mark children recursively.
48805  */
48806 
48807 DUK_LOCAL void duk__mark_hstring(duk_heap *heap, duk_hstring *h) {
48808 	DUK_UNREF(heap);
48809 	DUK_UNREF(h);
48810 
48811 	DUK_DDD(DUK_DDDPRINT("duk__mark_hstring: %p", (void *) h));
48812 	DUK_ASSERT(h);
48813 
48814 	/* nothing to process */
48815 }
48816 
48817 DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h) {
48818 	duk_uint_fast32_t i;
48819 
48820 	DUK_DDD(DUK_DDDPRINT("duk__mark_hobject: %p", (void *) h));
48821 
48822 	DUK_ASSERT(h);
48823 
48824 	/* XXX: use advancing pointers instead of index macros -> faster and smaller? */
48825 
48826 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
48827 		duk_hstring *key = DUK_HOBJECT_E_GET_KEY(heap, h, i);
48828 		if (key == NULL) {
48829 			continue;
48830 		}
48831 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) key);
48832 		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
48833 			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
48834 			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
48835 		} else {
48836 			duk__mark_tval(heap, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
48837 		}
48838 	}
48839 
48840 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
48841 		duk__mark_tval(heap, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
48842 	}
48843 
48844 	/* Hash part is a 'weak reference' and does not contribute. */
48845 
48846 	duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
48847 
48848 	/* Fast path for objects which don't have a subclass struct, or have a
48849 	 * subclass struct but nothing that needs marking in the subclass struct.
48850 	 */
48851 	if (DUK_HOBJECT_HAS_FASTREFS(h)) {
48852 		DUK_ASSERT(DUK_HOBJECT_ALLOWS_FASTREFS(h));
48853 		return;
48854 	}
48855 	DUK_ASSERT(DUK_HOBJECT_PROHIBITS_FASTREFS(h));
48856 
48857 	/* XXX: reorg, more common first */
48858 	if (DUK_HOBJECT_IS_COMPFUNC(h)) {
48859 		duk_hcompfunc *f = (duk_hcompfunc *) h;
48860 		duk_tval *tv, *tv_end;
48861 		duk_hobject **fn, **fn_end;
48862 
48863 		DUK_ASSERT_HCOMPFUNC_VALID(f);
48864 
48865 		/* 'data' is reachable through every compiled function which
48866 		 * contains a reference.
48867 		 */
48868 
48869 		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_DATA(heap, f));
48870 		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_LEXENV(heap, f));
48871 		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_VARENV(heap, f));
48872 
48873 		if (DUK_HCOMPFUNC_GET_DATA(heap, f) != NULL) {
48874 			tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);
48875 			tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(heap, f);
48876 			while (tv < tv_end) {
48877 				duk__mark_tval(heap, tv);
48878 				tv++;
48879 			}
48880 
48881 			fn = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, f);
48882 			fn_end = DUK_HCOMPFUNC_GET_FUNCS_END(heap, f);
48883 			while (fn < fn_end) {
48884 				duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) *fn);
48885 				fn++;
48886 			}
48887 		} else {
48888 			/* May happen in some out-of-memory corner cases. */
48889 			DUK_D(DUK_DPRINT("duk_hcompfunc 'data' is NULL, skipping marking"));
48890 		}
48891 	} else if (DUK_HOBJECT_IS_DECENV(h)) {
48892 		duk_hdecenv *e = (duk_hdecenv *) h;
48893 		DUK_ASSERT_HDECENV_VALID(e);
48894 		duk__mark_heaphdr(heap, (duk_heaphdr *) e->thread);
48895 		duk__mark_heaphdr(heap, (duk_heaphdr *) e->varmap);
48896 	} else if (DUK_HOBJECT_IS_OBJENV(h)) {
48897 		duk_hobjenv *e = (duk_hobjenv *) h;
48898 		DUK_ASSERT_HOBJENV_VALID(e);
48899 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) e->target);
48900 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
48901 	} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
48902 		duk_hbufobj *b = (duk_hbufobj *) h;
48903 		DUK_ASSERT_HBUFOBJ_VALID(b);
48904 		duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf);
48905 		duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf_prop);
48906 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
48907 	} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
48908 		duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
48909 		DUK_ASSERT_HBOUNDFUNC_VALID(f);
48910 		duk__mark_tval(heap, &f->target);
48911 		duk__mark_tval(heap, &f->this_binding);
48912 		duk__mark_tvals(heap, f->args, f->nargs);
48913 #if defined(DUK_USE_ES6_PROXY)
48914 	} else if (DUK_HOBJECT_IS_PROXY(h)) {
48915 		duk_hproxy *p = (duk_hproxy *) h;
48916 		DUK_ASSERT_HPROXY_VALID(p);
48917 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) p->target);
48918 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) p->handler);
48919 #endif  /* DUK_USE_ES6_PROXY */
48920 	} else if (DUK_HOBJECT_IS_THREAD(h)) {
48921 		duk_hthread *t = (duk_hthread *) h;
48922 		duk_activation *act;
48923 		duk_tval *tv;
48924 
48925 		DUK_ASSERT_HTHREAD_VALID(t);
48926 
48927 		tv = t->valstack;
48928 		while (tv < t->valstack_top) {
48929 			duk__mark_tval(heap, tv);
48930 			tv++;
48931 		}
48932 
48933 		for (act = t->callstack_curr; act != NULL; act = act->parent) {
48934 			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_ACT_GET_FUNC(act));
48935 			duk__mark_heaphdr(heap, (duk_heaphdr *) act->var_env);
48936 			duk__mark_heaphdr(heap, (duk_heaphdr *) act->lex_env);
48937 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
48938 			duk__mark_heaphdr(heap, (duk_heaphdr *) act->prev_caller);
48939 #endif
48940 #if 0  /* nothing now */
48941 			for (cat = act->cat; cat != NULL; cat = cat->parent) {
48942 			}
48943 #endif
48944 		}
48945 
48946 		duk__mark_heaphdr(heap, (duk_heaphdr *) t->resumer);
48947 
48948 		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
48949 			duk__mark_heaphdr(heap, (duk_heaphdr *) t->builtins[i]);
48950 		}
48951 	} else {
48952 		/* We may come here if the object should have a FASTREFS flag
48953 		 * but it's missing for some reason.  Assert for never getting
48954 		 * here; however, other than performance, this is harmless.
48955 		 */
48956 		DUK_D(DUK_DPRINT("missing FASTREFS flag for: %!iO", h));
48957 		DUK_ASSERT(0);
48958 	}
48959 }
48960 
48961 /* Mark any duk_heaphdr type.  Recursion tracking happens only here. */
48962 DUK_LOCAL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h) {
48963 	DUK_DDD(DUK_DDDPRINT("duk__mark_heaphdr %p, type %ld",
48964 	                     (void *) h,
48965 	                     (h != NULL ? (long) DUK_HEAPHDR_GET_TYPE(h) : (long) -1)));
48966 
48967 	/* XXX: add non-null variant? */
48968 	if (h == NULL) {
48969 		return;
48970 	}
48971 
48972 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(h) || DUK_HEAPHDR_HAS_REACHABLE(h));
48973 
48974 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
48975 	if (!DUK_HEAPHDR_HAS_READONLY(h)) {
48976 		h->h_assert_refcount++;  /* Comparison refcount: bump even if already reachable. */
48977 	}
48978 #endif
48979 	if (DUK_HEAPHDR_HAS_REACHABLE(h)) {
48980 		DUK_DDD(DUK_DDDPRINT("already marked reachable, skip"));
48981 		return;
48982 	}
48983 #if defined(DUK_USE_ROM_OBJECTS)
48984 	/* READONLY objects always have REACHABLE set, so the check above
48985 	 * will prevent READONLY objects from being marked here.
48986 	 */
48987 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(h));
48988 #endif
48989 
48990 	DUK_HEAPHDR_SET_REACHABLE(h);
48991 
48992 	if (heap->ms_recursion_depth >= DUK_USE_MARK_AND_SWEEP_RECLIMIT) {
48993 		DUK_D(DUK_DPRINT("mark-and-sweep recursion limit reached, marking as temproot: %p", (void *) h));
48994 		DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap);
48995 		DUK_HEAPHDR_SET_TEMPROOT(h);
48996 		return;
48997 	}
48998 
48999 	heap->ms_recursion_depth++;
49000 	DUK_ASSERT(heap->ms_recursion_depth != 0);  /* Wrap. */
49001 
49002 	switch (DUK_HEAPHDR_GET_TYPE(h)) {
49003 	case DUK_HTYPE_STRING:
49004 		duk__mark_hstring(heap, (duk_hstring *) h);
49005 		break;
49006 	case DUK_HTYPE_OBJECT:
49007 		duk__mark_hobject(heap, (duk_hobject *) h);
49008 		break;
49009 	case DUK_HTYPE_BUFFER:
49010 		/* nothing to mark */
49011 		break;
49012 	default:
49013 		DUK_D(DUK_DPRINT("attempt to mark heaphdr %p with invalid htype %ld", (void *) h, (long) DUK_HEAPHDR_GET_TYPE(h)));
49014 		DUK_UNREACHABLE();
49015 	}
49016 
49017 	DUK_ASSERT(heap->ms_recursion_depth > 0);
49018 	heap->ms_recursion_depth--;
49019 }
49020 
49021 DUK_LOCAL void duk__mark_tval(duk_heap *heap, duk_tval *tv) {
49022 	DUK_DDD(DUK_DDDPRINT("duk__mark_tval %p", (void *) tv));
49023 	if (tv == NULL) {
49024 		return;
49025 	}
49026 	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
49027 		duk_heaphdr *h;
49028 		h = DUK_TVAL_GET_HEAPHDR(tv);
49029 		DUK_ASSERT(h != NULL);
49030 		duk__mark_heaphdr_nonnull(heap, h);
49031 	}
49032 }
49033 
49034 DUK_LOCAL void duk__mark_tvals(duk_heap *heap, duk_tval *tv, duk_idx_t count) {
49035 	DUK_ASSERT(count == 0 || tv != NULL);
49036 
49037 	while (count-- > 0) {
49038 		if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
49039 			duk_heaphdr *h;
49040 			h = DUK_TVAL_GET_HEAPHDR(tv);
49041 			DUK_ASSERT(h != NULL);
49042 			duk__mark_heaphdr_nonnull(heap, h);
49043 		}
49044 		tv++;
49045 	}
49046 }
49047 
49048 /* Mark any duk_heaphdr type, caller guarantees a non-NULL pointer. */
49049 DUK_LOCAL void duk__mark_heaphdr_nonnull(duk_heap *heap, duk_heaphdr *h) {
49050 	/* For now, just call the generic handler.  Change when call sites
49051 	 * are changed too.
49052 	 */
49053 	duk__mark_heaphdr(heap, h);
49054 }
49055 
49056 /*
49057  *  Mark the heap.
49058  */
49059 
49060 DUK_LOCAL void duk__mark_roots_heap(duk_heap *heap) {
49061 	duk_small_uint_t i;
49062 
49063 	DUK_DD(DUK_DDPRINT("duk__mark_roots_heap: %p", (void *) heap));
49064 
49065 	duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_thread);
49066 	duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_object);
49067 
49068 	for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
49069 		duk_hstring *h = DUK_HEAP_GET_STRING(heap, i);
49070 		duk__mark_heaphdr(heap, (duk_heaphdr *) h);
49071 	}
49072 
49073 	duk__mark_tval(heap, &heap->lj.value1);
49074 	duk__mark_tval(heap, &heap->lj.value2);
49075 
49076 #if defined(DUK_USE_DEBUGGER_SUPPORT)
49077 	for (i = 0; i < heap->dbg_breakpoint_count; i++) {
49078 		duk__mark_heaphdr(heap, (duk_heaphdr *) heap->dbg_breakpoints[i].filename);
49079 	}
49080 #endif
49081 }
49082 
49083 /*
49084  *  Mark unreachable, finalizable objects.
49085  *
49086  *  Such objects will be moved aside and their finalizers run later.  They
49087  *  have to be treated as reachability roots for their properties etc to
49088  *  remain allocated.  This marking is only done for unreachable values which
49089  *  would be swept later.
49090  *
49091  *  Objects are first marked FINALIZABLE and only then marked as reachability
49092  *  roots; otherwise circular references might be handled inconsistently.
49093  */
49094 
49095 #if defined(DUK_USE_FINALIZER_SUPPORT)
49096 DUK_LOCAL void duk__mark_finalizable(duk_heap *heap) {
49097 	duk_heaphdr *hdr;
49098 	duk_size_t count_finalizable = 0;
49099 
49100 	DUK_DD(DUK_DDPRINT("duk__mark_finalizable: %p", (void *) heap));
49101 
49102 	DUK_ASSERT(heap->heap_thread != NULL);
49103 
49104 	hdr = heap->heap_allocated;
49105 	while (hdr != NULL) {
49106 		/* A finalizer is looked up from the object and up its
49107 		 * prototype chain (which allows inherited finalizers).
49108 		 * The finalizer is checked for using a duk_hobject flag
49109 		 * which is kept in sync with the presence and callability
49110 		 * of a _Finalizer hidden symbol.
49111 		 */
49112 
49113 		if (!DUK_HEAPHDR_HAS_REACHABLE(hdr) &&
49114 		    DUK_HEAPHDR_IS_OBJECT(hdr) &&
49115 		    !DUK_HEAPHDR_HAS_FINALIZED(hdr) &&
49116 		    DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) hdr)) {
49117 			/* heaphdr:
49118 			 *  - is not reachable
49119 			 *  - is an object
49120 			 *  - is not a finalized object waiting for rescue/keep decision
49121 			 *  - has a finalizer
49122 			 */
49123 
49124 			DUK_DD(DUK_DDPRINT("unreachable heap object will be "
49125 			                   "finalized -> mark as finalizable "
49126 			                   "and treat as a reachability root: %p",
49127 			                   (void *) hdr));
49128 			DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(hdr));
49129 			DUK_HEAPHDR_SET_FINALIZABLE(hdr);
49130 			count_finalizable++;
49131 		}
49132 
49133 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49134 	}
49135 
49136 	if (count_finalizable == 0) {
49137 		return;
49138 	}
49139 
49140 	DUK_DD(DUK_DDPRINT("marked %ld heap objects as finalizable, now mark them reachable",
49141 	                   (long) count_finalizable));
49142 
49143 	hdr = heap->heap_allocated;
49144 	while (hdr != NULL) {
49145 		if (DUK_HEAPHDR_HAS_FINALIZABLE(hdr)) {
49146 			duk__mark_heaphdr_nonnull(heap, hdr);
49147 		}
49148 
49149 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49150 	}
49151 
49152 	/* Caller will finish the marking process if we hit a recursion limit. */
49153 }
49154 #endif  /* DUK_USE_FINALIZER_SUPPORT */
49155 
49156 /*
49157  *  Mark objects on finalize_list.
49158  */
49159 
49160 #if defined(DUK_USE_FINALIZER_SUPPORT)
49161 DUK_LOCAL void duk__mark_finalize_list(duk_heap *heap) {
49162 	duk_heaphdr *hdr;
49163 #if defined(DUK_USE_DEBUG)
49164 	duk_size_t count_finalize_list = 0;
49165 #endif
49166 
49167 	DUK_DD(DUK_DDPRINT("duk__mark_finalize_list: %p", (void *) heap));
49168 
49169 	hdr = heap->finalize_list;
49170 	while (hdr != NULL) {
49171 		duk__mark_heaphdr_nonnull(heap, hdr);
49172 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49173 #if defined(DUK_USE_DEBUG)
49174 		count_finalize_list++;
49175 #endif
49176 	}
49177 
49178 #if defined(DUK_USE_DEBUG)
49179 	if (count_finalize_list > 0) {
49180 		DUK_D(DUK_DPRINT("marked %ld objects on the finalize_list as reachable (previous finalizer run skipped)",
49181 		                 (long) count_finalize_list));
49182 	}
49183 #endif
49184 }
49185 #endif  /* DUK_USE_FINALIZER_SUPPORT */
49186 
49187 /*
49188  *  Fallback marking handler if recursion limit is reached.
49189  *
49190  *  Iterates 'temproots' until recursion limit is no longer hit.  Temproots
49191  *  can be in heap_allocated or finalize_list; refzero_list is now always
49192  *  empty for mark-and-sweep.  A temproot may occur in finalize_list now if
49193  *  there are objects on the finalize_list and user code creates a reference
49194  *  from an object in heap_allocated to the object in finalize_list (which is
49195  *  now allowed), and it happened to coincide with the recursion depth limit.
49196  *
49197  *  This is a slow scan, but guarantees that we finish with a bounded C stack.
49198  *
49199  *  Note that nodes may have been marked as temproots before this scan begun,
49200  *  OR they may have been marked during the scan (as we process nodes
49201  *  recursively also during the scan).  This is intended behavior.
49202  */
49203 
49204 #if defined(DUK_USE_DEBUG)
49205 DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr, duk_size_t *count) {
49206 #else
49207 DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr) {
49208 #endif
49209 	DUK_ASSERT(hdr != NULL);
49210 
49211 	if (!DUK_HEAPHDR_HAS_TEMPROOT(hdr)) {
49212 		DUK_DDD(DUK_DDDPRINT("not a temp root: %p", (void *) hdr));
49213 		return;
49214 	}
49215 
49216 	DUK_DDD(DUK_DDDPRINT("found a temp root: %p", (void *) hdr));
49217 	DUK_HEAPHDR_CLEAR_TEMPROOT(hdr);
49218 	DUK_HEAPHDR_CLEAR_REACHABLE(hdr);  /* Done so that duk__mark_heaphdr() works correctly. */
49219 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
49220 	hdr->h_assert_refcount--;  /* Same node visited twice. */
49221 #endif
49222 	duk__mark_heaphdr_nonnull(heap, hdr);
49223 
49224 #if defined(DUK_USE_DEBUG)
49225 	(*count)++;
49226 #endif
49227 }
49228 
49229 DUK_LOCAL void duk__mark_temproots_by_heap_scan(duk_heap *heap) {
49230 	duk_heaphdr *hdr;
49231 #if defined(DUK_USE_DEBUG)
49232 	duk_size_t count;
49233 #endif
49234 
49235 	DUK_DD(DUK_DDPRINT("duk__mark_temproots_by_heap_scan: %p", (void *) heap));
49236 
49237 	while (DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)) {
49238 		DUK_DD(DUK_DDPRINT("recursion limit reached, doing heap scan to continue from temproots"));
49239 
49240 #if defined(DUK_USE_DEBUG)
49241 		count = 0;
49242 #endif
49243 		DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap);
49244 
49245 		hdr = heap->heap_allocated;
49246 		while (hdr) {
49247 #if defined(DUK_USE_DEBUG)
49248 			duk__handle_temproot(heap, hdr, &count);
49249 #else
49250 			duk__handle_temproot(heap, hdr);
49251 #endif
49252 			hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49253 		}
49254 
49255 #if defined(DUK_USE_FINALIZER_SUPPORT)
49256 		hdr = heap->finalize_list;
49257 		while (hdr) {
49258 #if defined(DUK_USE_DEBUG)
49259 			duk__handle_temproot(heap, hdr, &count);
49260 #else
49261 			duk__handle_temproot(heap, hdr);
49262 #endif
49263 			hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49264 		}
49265 #endif
49266 
49267 #if defined(DUK_USE_DEBUG)
49268 		DUK_DD(DUK_DDPRINT("temproot mark heap scan processed %ld temp roots", (long) count));
49269 #endif
49270 	}
49271 }
49272 
49273 /*
49274  *  Finalize refcounts for heap elements just about to be freed.
49275  *  This must be done for all objects before freeing to avoid any
49276  *  stale pointer dereferences.
49277  *
49278  *  Note that this must deduce the set of objects to be freed
49279  *  identically to duk__sweep_heap().
49280  */
49281 
49282 #if defined(DUK_USE_REFERENCE_COUNTING)
49283 DUK_LOCAL void duk__finalize_refcounts(duk_heap *heap) {
49284 	duk_heaphdr *hdr;
49285 
49286 	DUK_ASSERT(heap->heap_thread != NULL);
49287 
49288 	DUK_DD(DUK_DDPRINT("duk__finalize_refcounts: heap=%p", (void *) heap));
49289 
49290 	hdr = heap->heap_allocated;
49291 	while (hdr) {
49292 		if (!DUK_HEAPHDR_HAS_REACHABLE(hdr)) {
49293 			/*
49294 			 *  Unreachable object about to be swept.  Finalize target refcounts
49295 			 *  (objects which the unreachable object points to) without doing
49296 			 *  refzero processing.  Recursive decrefs are also prevented when
49297 			 *  refzero processing is disabled.
49298 			 *
49299 			 *  Value cannot be a finalizable object, as they have been made
49300 			 *  temporarily reachable for this round.
49301 			 */
49302 
49303 			DUK_DDD(DUK_DDDPRINT("unreachable object, refcount finalize before sweeping: %p", (void *) hdr));
49304 
49305 			/* Finalize using heap->heap_thread; DECREF has a
49306 			 * suppress check for mark-and-sweep which is based
49307 			 * on heap->ms_running.
49308 			 */
49309 			duk_heaphdr_refcount_finalize_norz(heap, hdr);
49310 		}
49311 
49312 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49313 	}
49314 }
49315 #endif  /* DUK_USE_REFERENCE_COUNTING */
49316 
49317 /*
49318  *  Clear (reachable) flags of finalize_list.
49319  *
49320  *  We could mostly do in the sweep phase when we move objects from the
49321  *  heap into the finalize_list.  However, if a finalizer run is skipped
49322  *  during a mark-and-sweep, the objects on the finalize_list will be marked
49323  *  reachable during the next mark-and-sweep.  Since they're already on the
49324  *  finalize_list, no-one will be clearing their REACHABLE flag so we do it
49325  *  here.  (This now overlaps with the sweep handling in a harmless way.)
49326  */
49327 
49328 #if defined(DUK_USE_FINALIZER_SUPPORT)
49329 DUK_LOCAL void duk__clear_finalize_list_flags(duk_heap *heap) {
49330 	duk_heaphdr *hdr;
49331 
49332 	DUK_DD(DUK_DDPRINT("duk__clear_finalize_list_flags: %p", (void *) heap));
49333 
49334 	hdr = heap->finalize_list;
49335 	while (hdr) {
49336 		DUK_HEAPHDR_CLEAR_REACHABLE(hdr);
49337 #if defined(DUK_USE_ASSERTIONS)
49338 		DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(hdr) || \
49339 		           (heap->currently_finalizing == hdr));
49340 #endif
49341 		/* DUK_HEAPHDR_FLAG_FINALIZED may be set. */
49342 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
49343 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49344 	}
49345 }
49346 #endif  /* DUK_USE_FINALIZER_SUPPORT */
49347 
49348 /*
49349  *  Sweep stringtable.
49350  */
49351 
49352 DUK_LOCAL void duk__sweep_stringtable(duk_heap *heap, duk_size_t *out_count_keep) {
49353 	duk_hstring *h;
49354 	duk_hstring *prev;
49355 	duk_uint32_t i;
49356 #if defined(DUK_USE_DEBUG)
49357 	duk_size_t count_free = 0;
49358 #endif
49359 	duk_size_t count_keep = 0;
49360 
49361 	DUK_DD(DUK_DDPRINT("duk__sweep_stringtable: %p", (void *) heap));
49362 
49363 #if defined(DUK_USE_STRTAB_PTRCOMP)
49364 	if (heap->strtable16 == NULL) {
49365 #else
49366 	if (heap->strtable == NULL) {
49367 #endif
49368 		goto done;
49369 	}
49370 
49371 	for (i = 0; i < heap->st_size; i++) {
49372 #if defined(DUK_USE_STRTAB_PTRCOMP)
49373 		h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
49374 #else
49375 		h = heap->strtable[i];
49376 #endif
49377 		prev = NULL;
49378 		while (h != NULL) {
49379 			duk_hstring *next;
49380 			next = h->hdr.h_next;
49381 
49382 			if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h))
49383 			{
49384 				DUK_HEAPHDR_CLEAR_REACHABLE((duk_heaphdr *) h);
49385 				count_keep++;
49386 				prev = h;
49387 			} else {
49388 #if defined(DUK_USE_DEBUG)
49389 				count_free++;
49390 #endif
49391 
49392 				/* For pinned strings the refcount has been
49393 				 * bumped.  We could unbump it here before
49394 				 * freeing, but that's actually not necessary
49395 				 * except for assertions.
49396 				 */
49397 #if 0
49398 				if (DUK_HSTRING_HAS_PINNED_LITERAL(h)) {
49399 					DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) > 0U);
49400 					DUK_HSTRING_DECREF_NORZ(heap->heap_thread, h);
49401 					DUK_HSTRING_CLEAR_PINNED_LITERAL(h);
49402 				}
49403 #endif
49404 #if defined(DUK_USE_REFERENCE_COUNTING)
49405 				/* Non-zero refcounts should not happen for unreachable strings,
49406 				 * because we refcount finalize all unreachable objects which
49407 				 * should have decreased unreachable string refcounts to zero
49408 				 * (even for cycles).  However, pinned strings have a +1 bump.
49409 				 */
49410 				DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) ==
49411 				           DUK_HSTRING_HAS_PINNED_LITERAL(h) ? 1U : 0U);
49412 #endif
49413 
49414 				/* Deal with weak references first. */
49415 				duk_heap_strcache_string_remove(heap, (duk_hstring *) h);
49416 
49417 				/* Remove the string from the string table. */
49418 				duk_heap_strtable_unlink_prev(heap, (duk_hstring *) h, (duk_hstring *) prev);
49419 
49420 				/* Free inner references (these exist e.g. when external
49421 				 * strings are enabled) and the struct itself.
49422 				 */
49423 				duk_free_hstring(heap, (duk_hstring *) h);
49424 
49425 				/* Don't update 'prev'; it should be last string kept. */
49426 			}
49427 
49428 			h = next;
49429 		}
49430 	}
49431 
49432  done:
49433 #if defined(DUK_USE_DEBUG)
49434 	DUK_D(DUK_DPRINT("mark-and-sweep sweep stringtable: %ld freed, %ld kept",
49435 	                 (long) count_free, (long) count_keep));
49436 #endif
49437 	*out_count_keep = count_keep;
49438 }
49439 
49440 /*
49441  *  Sweep heap.
49442  */
49443 
49444 DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_small_uint_t flags, duk_size_t *out_count_keep) {
49445 	duk_heaphdr *prev;  /* last element that was left in the heap */
49446 	duk_heaphdr *curr;
49447 	duk_heaphdr *next;
49448 #if defined(DUK_USE_DEBUG)
49449 	duk_size_t count_free = 0;
49450 	duk_size_t count_finalize = 0;
49451 	duk_size_t count_rescue = 0;
49452 #endif
49453 	duk_size_t count_keep = 0;
49454 
49455 	DUK_DD(DUK_DDPRINT("duk__sweep_heap: %p", (void *) heap));
49456 
49457 	prev = NULL;
49458 	curr = heap->heap_allocated;
49459 	heap->heap_allocated = NULL;
49460 	while (curr) {
49461 		/* Strings and ROM objects are never placed on the heap allocated list. */
49462 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_STRING);
49463 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr));
49464 
49465 		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
49466 
49467 		if (DUK_HEAPHDR_HAS_REACHABLE(curr)) {
49468 			/*
49469 			 *  Reachable object:
49470 			 *    - If FINALIZABLE -> actually unreachable (but marked
49471 			 *      artificially reachable), queue to finalize_list.
49472 			 *    - If !FINALIZABLE but FINALIZED -> rescued after
49473 			 *      finalizer execution.
49474 			 *    - Otherwise just a normal, reachable object.
49475 			 *
49476 			 *  Objects which are kept are queued to heap_allocated
49477 			 *  tail (we're essentially filtering heap_allocated in
49478 			 *  practice).
49479 			 */
49480 
49481 #if defined(DUK_USE_FINALIZER_SUPPORT)
49482 			if (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZABLE(curr))) {
49483 				DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
49484 				DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);
49485 				DUK_DD(DUK_DDPRINT("sweep; reachable, finalizable --> move to finalize_list: %p", (void *) curr));
49486 
49487 #if defined(DUK_USE_REFERENCE_COUNTING)
49488 				DUK_HEAPHDR_PREINC_REFCOUNT(curr);  /* Bump refcount so that refzero never occurs when pending a finalizer call. */
49489 #endif
49490 				DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap, curr);
49491 #if defined(DUK_USE_DEBUG)
49492 				count_finalize++;
49493 #endif
49494 			}
49495 			else
49496 #endif  /* DUK_USE_FINALIZER_SUPPORT */
49497 			{
49498 				if (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZED(curr))) {
49499 					DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
49500 					DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);
49501 
49502 					if (flags & DUK_MS_FLAG_POSTPONE_RESCUE) {
49503 						DUK_DD(DUK_DDPRINT("sweep; reachable, finalized, but postponing rescue decisions --> keep object (with FINALIZED set): %!iO", curr));
49504 						count_keep++;
49505 					} else {
49506 						DUK_DD(DUK_DDPRINT("sweep; reachable, finalized --> rescued after finalization: %p", (void *) curr));
49507 #if defined(DUK_USE_FINALIZER_SUPPORT)
49508 						DUK_HEAPHDR_CLEAR_FINALIZED(curr);
49509 #endif
49510 #if defined(DUK_USE_DEBUG)
49511 						count_rescue++;
49512 #endif
49513 					}
49514 				} else {
49515 					DUK_DD(DUK_DDPRINT("sweep; reachable --> keep: %!iO", curr));
49516 					count_keep++;
49517 				}
49518 
49519 				if (prev != NULL) {
49520 					DUK_ASSERT(heap->heap_allocated != NULL);
49521 					DUK_HEAPHDR_SET_NEXT(heap, prev, curr);
49522 				} else {
49523 					DUK_ASSERT(heap->heap_allocated == NULL);
49524 					heap->heap_allocated = curr;
49525 				}
49526 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
49527 				DUK_HEAPHDR_SET_PREV(heap, curr, prev);
49528 #endif
49529 				DUK_ASSERT_HEAPHDR_LINKS(heap, prev);
49530 				DUK_ASSERT_HEAPHDR_LINKS(heap, curr);
49531 				prev = curr;
49532 			}
49533 
49534 			/*
49535 			 *  Shrink check for value stacks here.  We're inside
49536 			 *  ms_prevent_count protection which prevents recursive
49537 			 *  mark-and-sweep and refzero finalizers, so there are
49538 			 *  no side effects that would affect the heap lists.
49539 			 */
49540 			if (DUK_HEAPHDR_IS_OBJECT(curr) && DUK_HOBJECT_IS_THREAD((duk_hobject *) curr)) {
49541 				duk_hthread *thr_curr = (duk_hthread *) curr;
49542 				DUK_DD(DUK_DDPRINT("value stack shrink check for thread: %!O", curr));
49543 				duk_valstack_shrink_check_nothrow(thr_curr, flags & DUK_MS_FLAG_EMERGENCY /*snug*/);
49544 			}
49545 
49546 			DUK_HEAPHDR_CLEAR_REACHABLE(curr);
49547 			/* Keep FINALIZED if set, used if rescue decisions are postponed. */
49548 			/* Keep FINALIZABLE for objects on finalize_list. */
49549 			DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr));
49550 		} else {
49551 			/*
49552 			 *  Unreachable object:
49553 			 *    - If FINALIZED, object was finalized but not
49554 			 *      rescued.  This doesn't affect freeing.
49555 			 *    - Otherwise normal unreachable object.
49556 			 *
49557 			 *  There's no guard preventing a FINALIZED object
49558 			 *  from being freed while finalizers execute: the
49559 			 *  artificial finalize_list reachability roots can't
49560 			 *  cause an incorrect free decision (but can cause
49561 			 *  an incorrect rescue decision).
49562 			 */
49563 
49564 #if defined(DUK_USE_REFERENCE_COUNTING)
49565 			/* Non-zero refcounts should not happen because we refcount
49566 			 * finalize all unreachable objects which should cancel out
49567 			 * refcounts (even for cycles).
49568 			 */
49569 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) == 0);
49570 #endif
49571 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
49572 
49573 #if defined(DUK_USE_DEBUG)
49574 			if (DUK_HEAPHDR_HAS_FINALIZED(curr)) {
49575 				DUK_DD(DUK_DDPRINT("sweep; unreachable, finalized --> finalized object not rescued: %p", (void *) curr));
49576 			} else {
49577 				DUK_DD(DUK_DDPRINT("sweep; not reachable --> free: %p", (void *) curr));
49578 			}
49579 
49580 #endif
49581 
49582 			/* Note: object cannot be a finalizable unreachable object, as
49583 			 * they have been marked temporarily reachable for this round,
49584 			 * and are handled above.
49585 			 */
49586 
49587 #if defined(DUK_USE_DEBUG)
49588 			count_free++;
49589 #endif
49590 
49591 			/* Weak refs should be handled here, but no weak refs for
49592 			 * any non-string objects exist right now.
49593 			 */
49594 
49595 			/* Free object and all auxiliary (non-heap) allocs. */
49596 			duk_heap_free_heaphdr_raw(heap, curr);
49597 		}
49598 
49599 		curr = next;
49600 	}
49601 
49602 	if (prev != NULL) {
49603 		DUK_HEAPHDR_SET_NEXT(heap, prev, NULL);
49604 	}
49605 	DUK_ASSERT_HEAPHDR_LINKS(heap, prev);
49606 
49607 #if defined(DUK_USE_DEBUG)
49608 	DUK_D(DUK_DPRINT("mark-and-sweep sweep objects (non-string): %ld freed, %ld kept, %ld rescued, %ld queued for finalization",
49609 	                 (long) count_free, (long) count_keep, (long) count_rescue, (long) count_finalize));
49610 #endif
49611 	*out_count_keep = count_keep;
49612 }
49613 
49614 /*
49615  *  Litcache helpers.
49616  */
49617 
49618 #if defined(DUK_USE_LITCACHE_SIZE)
49619 DUK_LOCAL void duk__wipe_litcache(duk_heap *heap) {
49620 	duk_uint_t i;
49621 	duk_litcache_entry *e;
49622 
49623 	e = heap->litcache;
49624 	for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
49625 		e->addr = NULL;
49626 		/* e->h does not need to be invalidated: when e->addr is
49627 		 * NULL, e->h is considered garbage.
49628 		 */
49629 		e++;
49630 	}
49631 }
49632 #endif  /* DUK_USE_LITCACHE_SIZE */
49633 
49634 /*
49635  *  Object compaction.
49636  *
49637  *  Compaction is assumed to never throw an error.
49638  */
49639 
49640 DUK_LOCAL int duk__protected_compact_object(duk_hthread *thr, void *udata) {
49641 	duk_hobject *obj;
49642 	/* XXX: for threads, compact stacks? */
49643 
49644 	DUK_UNREF(udata);
49645 	obj = duk_known_hobject(thr, -1);
49646 	duk_hobject_compact_props(thr, obj);
49647 	return 0;
49648 }
49649 
49650 #if defined(DUK_USE_DEBUG)
49651 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) {
49652 #else
49653 DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start) {
49654 #endif
49655 	duk_heaphdr *curr;
49656 #if defined(DUK_USE_DEBUG)
49657 	duk_size_t old_size, new_size;
49658 #endif
49659 	duk_hobject *obj;
49660 
49661 	DUK_UNREF(heap);
49662 
49663 	curr = start;
49664 	while (curr) {
49665 		DUK_DDD(DUK_DDDPRINT("mark-and-sweep compact: %p", (void *) curr));
49666 
49667 		if (DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_OBJECT) {
49668 			goto next;
49669 		}
49670 		obj = (duk_hobject *) curr;
49671 
49672 #if defined(DUK_USE_DEBUG)
49673 		old_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
49674 		                                      DUK_HOBJECT_GET_ASIZE(obj),
49675 		                                      DUK_HOBJECT_GET_HSIZE(obj));
49676 #endif
49677 
49678 		DUK_DD(DUK_DDPRINT("compact object: %p", (void *) obj));
49679 		duk_push_hobject(thr, obj);
49680 		/* XXX: disable error handlers for duration of compaction? */
49681 		duk_safe_call(thr, duk__protected_compact_object, NULL, 1, 0);
49682 
49683 #if defined(DUK_USE_DEBUG)
49684 		new_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
49685 		                                      DUK_HOBJECT_GET_ASIZE(obj),
49686 		                                      DUK_HOBJECT_GET_HSIZE(obj));
49687 #endif
49688 
49689 #if defined(DUK_USE_DEBUG)
49690 		(*p_count_compact)++;
49691 		(*p_count_bytes_saved) += (duk_size_t) (old_size - new_size);
49692 #endif
49693 
49694 	 next:
49695 		curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
49696 #if defined(DUK_USE_DEBUG)
49697 		(*p_count_check)++;
49698 #endif
49699 	}
49700 }
49701 
49702 DUK_LOCAL void duk__compact_objects(duk_heap *heap) {
49703 	/* XXX: which lists should participate?  to be finalized? */
49704 #if defined(DUK_USE_DEBUG)
49705 	duk_size_t count_check = 0;
49706 	duk_size_t count_compact = 0;
49707 	duk_size_t count_bytes_saved = 0;
49708 #endif
49709 
49710 	DUK_DD(DUK_DDPRINT("duk__compact_objects: %p", (void *) heap));
49711 
49712 	DUK_ASSERT(heap->heap_thread != NULL);
49713 
49714 #if defined(DUK_USE_DEBUG)
49715 	duk__compact_object_list(heap, heap->heap_thread, heap->heap_allocated, &count_check, &count_compact, &count_bytes_saved);
49716 #if defined(DUK_USE_FINALIZER_SUPPORT)
49717 	duk__compact_object_list(heap, heap->heap_thread, heap->finalize_list, &count_check, &count_compact, &count_bytes_saved);
49718 #endif
49719 #else
49720 	duk__compact_object_list(heap, heap->heap_thread, heap->heap_allocated);
49721 #if defined(DUK_USE_FINALIZER_SUPPORT)
49722 	duk__compact_object_list(heap, heap->heap_thread, heap->finalize_list);
49723 #endif
49724 #endif
49725 #if defined(DUK_USE_REFERENCE_COUNTING)
49726 	DUK_ASSERT(heap->refzero_list == NULL);  /* Always handled to completion inline in DECREF. */
49727 #endif
49728 
49729 #if defined(DUK_USE_DEBUG)
49730 	DUK_D(DUK_DPRINT("mark-and-sweep compact objects: %ld checked, %ld compaction attempts, %ld bytes saved by compaction",
49731 	                 (long) count_check, (long) count_compact, (long) count_bytes_saved));
49732 #endif
49733 }
49734 
49735 /*
49736  *  Assertion helpers.
49737  */
49738 
49739 #if defined(DUK_USE_ASSERTIONS)
49740 DUK_LOCAL void duk__assert_heaphdr_flags(duk_heap *heap) {
49741 	duk_heaphdr *hdr;
49742 
49743 	hdr = heap->heap_allocated;
49744 	while (hdr) {
49745 		DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(hdr));
49746 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
49747 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
49748 		/* may have FINALIZED */
49749 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49750 	}
49751 
49752 #if defined(DUK_USE_REFERENCE_COUNTING)
49753 	DUK_ASSERT(heap->refzero_list == NULL);  /* Always handled to completion inline in DECREF. */
49754 #endif
49755 }
49756 
49757 #if defined(DUK_USE_REFERENCE_COUNTING)
49758 DUK_LOCAL void duk__assert_valid_refcounts(duk_heap *heap) {
49759 	duk_heaphdr *hdr = heap->heap_allocated;
49760 	while (hdr) {
49761 		/* Cannot really assert much w.r.t. refcounts now. */
49762 
49763 		if (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0 &&
49764 		    DUK_HEAPHDR_HAS_FINALIZED(hdr)) {
49765 			/* An object may be in heap_allocated list with a zero
49766 			 * refcount if it has just been finalized and is waiting
49767 			 * to be collected by the next cycle.
49768 			 * (This doesn't currently happen however.)
49769 			 */
49770 		} else if (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0) {
49771 			/* An object may be in heap_allocated list with a zero
49772 			 * refcount also if it is a temporary object created
49773 			 * during debugger paused state.  It will get collected
49774 			 * by mark-and-sweep based on its reachability status
49775 			 * (presumably not reachable because refcount is 0).
49776 			 */
49777 		}
49778 		DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(hdr) >= 0);  /* Unsigned. */
49779 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49780 	}
49781 }
49782 
49783 DUK_LOCAL void duk__clear_assert_refcounts(duk_heap *heap) {
49784 	duk_heaphdr *curr;
49785 	duk_uint32_t i;
49786 
49787 	for (curr = heap->heap_allocated; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
49788 		curr->h_assert_refcount = 0;
49789 	}
49790 #if defined(DUK_USE_FINALIZER_SUPPORT)
49791 	for (curr = heap->finalize_list; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
49792 		curr->h_assert_refcount = 0;
49793 	}
49794 #endif
49795 #if defined(DUK_USE_REFERENCE_COUNTING)
49796 	for (curr = heap->refzero_list; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
49797 		curr->h_assert_refcount = 0;
49798 	}
49799 #endif
49800 
49801 	for (i = 0; i < heap->st_size; i++) {
49802 		duk_hstring *h;
49803 
49804 #if defined(DUK_USE_STRTAB_PTRCOMP)
49805 		h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
49806 #else
49807 		h = heap->strtable[i];
49808 #endif
49809 		while (h != NULL) {
49810 			((duk_heaphdr *) h)->h_assert_refcount = 0;
49811 			h = h->hdr.h_next;
49812 		}
49813 	}
49814 }
49815 
49816 DUK_LOCAL void duk__check_refcount_heaphdr(duk_heaphdr *hdr) {
49817 	duk_bool_t count_ok;
49818 	duk_size_t expect_refc;
49819 
49820 	/* The refcount check only makes sense for reachable objects on
49821 	 * heap_allocated or string table, after the sweep phase.  Prior to
49822 	 * sweep phase refcounts will include references that are not visible
49823 	 * via reachability roots.
49824 	 *
49825 	 * Because we're called after the sweep phase, all heap objects on
49826 	 * heap_allocated are reachable.  REACHABLE flags have already been
49827 	 * cleared so we can't check them.
49828 	 */
49829 
49830 	/* ROM objects have intentionally incorrect refcount (1), but we won't
49831 	 * check them.
49832 	 */
49833 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(hdr));
49834 
49835 	expect_refc = hdr->h_assert_refcount;
49836 	if (DUK_HEAPHDR_IS_STRING(hdr) && DUK_HSTRING_HAS_PINNED_LITERAL((duk_hstring *) hdr)) {
49837 		expect_refc++;
49838 	}
49839 	count_ok = ((duk_size_t) DUK_HEAPHDR_GET_REFCOUNT(hdr) == expect_refc);
49840 	if (!count_ok) {
49841 		DUK_D(DUK_DPRINT("refcount mismatch for: %p: header=%ld counted=%ld --> %!iO",
49842 		                 (void *) hdr, (long) DUK_HEAPHDR_GET_REFCOUNT(hdr),
49843 		                 (long) hdr->h_assert_refcount, hdr));
49844 		DUK_ASSERT(0);
49845 	}
49846 }
49847 
49848 DUK_LOCAL void duk__check_assert_refcounts(duk_heap *heap) {
49849 	duk_heaphdr *curr;
49850 	duk_uint32_t i;
49851 
49852 	for (curr = heap->heap_allocated; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
49853 		duk__check_refcount_heaphdr(curr);
49854 	}
49855 #if defined(DUK_USE_FINALIZER_SUPPORT)
49856 	for (curr = heap->finalize_list; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
49857 		duk__check_refcount_heaphdr(curr);
49858 	}
49859 #endif
49860 
49861 	for (i = 0; i < heap->st_size; i++) {
49862 		duk_hstring *h;
49863 
49864 #if defined(DUK_USE_STRTAB_PTRCOMP)
49865 		h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
49866 #else
49867 		h = heap->strtable[i];
49868 #endif
49869 		while (h != NULL) {
49870 			duk__check_refcount_heaphdr((duk_heaphdr *) h);
49871 			h = h->hdr.h_next;
49872 		}
49873 	}
49874 }
49875 #endif  /* DUK_USE_REFERENCE_COUNTING */
49876 
49877 #if defined(DUK_USE_LITCACHE_SIZE)
49878 DUK_LOCAL void duk__assert_litcache_nulls(duk_heap *heap) {
49879 	duk_uint_t i;
49880 	duk_litcache_entry *e;
49881 
49882 	e = heap->litcache;
49883 	for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
49884 		/* Entry addresses were NULLed before mark-and-sweep, check
49885 		 * that they're still NULL afterwards to ensure no pointers
49886 		 * were recorded through any side effects.
49887 		 */
49888 		DUK_ASSERT(e->addr == NULL);
49889 	}
49890 }
49891 #endif  /* DUK_USE_LITCACHE_SIZE */
49892 #endif  /* DUK_USE_ASSERTIONS */
49893 
49894 /*
49895  *  Stats dump.
49896  */
49897 
49898 #if defined(DUK_USE_DEBUG)
49899 DUK_LOCAL void duk__dump_stats(duk_heap *heap) {
49900 	DUK_D(DUK_DPRINT("stats executor: opcodes=%ld, interrupt=%ld, throw=%ld",
49901 	                 (long) heap->stats_exec_opcodes, (long) heap->stats_exec_interrupt,
49902 	                 (long) heap->stats_exec_throw));
49903 	DUK_D(DUK_DPRINT("stats call: all=%ld, tailcall=%ld, ecmatoecma=%ld",
49904 	                 (long) heap->stats_call_all, (long) heap->stats_call_tailcall,
49905 	                 (long) heap->stats_call_ecmatoecma));
49906 	DUK_D(DUK_DPRINT("stats safecall: all=%ld, nothrow=%ld, throw=%ld",
49907 	                 (long) heap->stats_safecall_all, (long) heap->stats_safecall_nothrow,
49908 	                 (long) heap->stats_safecall_throw));
49909 	DUK_D(DUK_DPRINT("stats mark-and-sweep: try_count=%ld, skip_count=%ld, emergency_count=%ld",
49910 	                 (long) heap->stats_ms_try_count, (long) heap->stats_ms_skip_count,
49911 	                 (long) heap->stats_ms_emergency_count));
49912 	DUK_D(DUK_DPRINT("stats stringtable: intern_hit=%ld, intern_miss=%ld, "
49913 	                 "resize_check=%ld, resize_grow=%ld, resize_shrink=%ld, "
49914 	                 "litcache_hit=%ld, litcache_miss=%ld, litcache_pin=%ld",
49915 	                 (long) heap->stats_strtab_intern_hit, (long) heap->stats_strtab_intern_miss,
49916 	                 (long) heap->stats_strtab_resize_check, (long) heap->stats_strtab_resize_grow,
49917 	                 (long) heap->stats_strtab_resize_shrink, (long) heap->stats_strtab_litcache_hit,
49918 	                 (long) heap->stats_strtab_litcache_miss, (long) heap->stats_strtab_litcache_pin));
49919 	DUK_D(DUK_DPRINT("stats object: realloc_props=%ld, abandon_array=%ld",
49920 	                 (long) heap->stats_object_realloc_props, (long) heap->stats_object_abandon_array));
49921 	DUK_D(DUK_DPRINT("stats getownpropdesc: count=%ld, hit=%ld, miss=%ld",
49922 	                 (long) heap->stats_getownpropdesc_count, (long) heap->stats_getownpropdesc_hit,
49923 	                 (long) heap->stats_getownpropdesc_miss));
49924 	DUK_D(DUK_DPRINT("stats getpropdesc: count=%ld, hit=%ld, miss=%ld",
49925 	                 (long) heap->stats_getpropdesc_count, (long) heap->stats_getpropdesc_hit,
49926 	                 (long) heap->stats_getpropdesc_miss));
49927 	DUK_D(DUK_DPRINT("stats getprop: all=%ld, arrayidx=%ld, bufobjidx=%ld, "
49928 	                 "bufferidx=%ld, bufferlen=%ld, stringidx=%ld, stringlen=%ld, "
49929 	                 "proxy=%ld, arguments=%ld",
49930 	                 (long) heap->stats_getprop_all, (long) heap->stats_getprop_arrayidx,
49931 	                 (long) heap->stats_getprop_bufobjidx, (long) heap->stats_getprop_bufferidx,
49932 	                 (long) heap->stats_getprop_bufferlen, (long) heap->stats_getprop_stringidx,
49933 	                 (long) heap->stats_getprop_stringlen, (long) heap->stats_getprop_proxy,
49934 	                 (long) heap->stats_getprop_arguments));
49935 	DUK_D(DUK_DPRINT("stats putprop: all=%ld, arrayidx=%ld, bufobjidx=%ld, "
49936 	                 "bufferidx=%ld, proxy=%ld",
49937 	                 (long) heap->stats_putprop_all, (long) heap->stats_putprop_arrayidx,
49938 	                 (long) heap->stats_putprop_bufobjidx, (long) heap->stats_putprop_bufferidx,
49939 	                 (long) heap->stats_putprop_proxy));
49940 	DUK_D(DUK_DPRINT("stats getvar: all=%ld",
49941 	                 (long) heap->stats_getvar_all));
49942 	DUK_D(DUK_DPRINT("stats putvar: all=%ld",
49943 	                 (long) heap->stats_putvar_all));
49944 }
49945 #endif  /* DUK_USE_DEBUG */
49946 
49947 /*
49948  *  Main mark-and-sweep function.
49949  *
49950  *  'flags' represents the features requested by the caller.  The current
49951  *  heap->ms_base_flags is ORed automatically into the flags; the base flags
49952  *  mask typically prevents certain mark-and-sweep operation to avoid trouble.
49953  */
49954 
49955 DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags) {
49956 	duk_size_t count_keep_obj;
49957 	duk_size_t count_keep_str;
49958 #if defined(DUK_USE_VOLUNTARY_GC)
49959 	duk_size_t tmp;
49960 #endif
49961 
49962 	DUK_STATS_INC(heap, stats_ms_try_count);
49963 #if defined(DUK_USE_DEBUG)
49964 	if (flags & DUK_MS_FLAG_EMERGENCY) {
49965 		DUK_STATS_INC(heap, stats_ms_emergency_count);
49966 	}
49967 #endif
49968 
49969 	/* If debugger is paused, garbage collection is disabled by default.
49970 	 * This is achieved by bumping ms_prevent_count when becoming paused.
49971 	 */
49972 	DUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) || heap->ms_prevent_count > 0);
49973 
49974 	/* Prevention/recursion check as soon as possible because we may
49975 	 * be called a number of times when voluntary mark-and-sweep is
49976 	 * pending.
49977 	 */
49978 	if (heap->ms_prevent_count != 0) {
49979 		DUK_DD(DUK_DDPRINT("reject recursive mark-and-sweep"));
49980 		DUK_STATS_INC(heap, stats_ms_skip_count);
49981 		return;
49982 	}
49983 	DUK_ASSERT(heap->ms_running == 0);  /* ms_prevent_count is bumped when ms_running is set */
49984 
49985 	/* Heap_thread is used during mark-and-sweep for refcount finalization
49986 	 * (it's also used for finalizer execution once mark-and-sweep is
49987 	 * complete).  Heap allocation code ensures heap_thread is set and
49988 	 * properly initialized before setting ms_prevent_count to 0.
49989 	 */
49990 	DUK_ASSERT(heap->heap_thread != NULL);
49991 	DUK_ASSERT(heap->heap_thread->valstack != NULL);
49992 
49993 	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) starting, requested flags: 0x%08lx, effective flags: 0x%08lx",
49994 	                 (unsigned long) flags, (unsigned long) (flags | heap->ms_base_flags)));
49995 
49996 	flags |= heap->ms_base_flags;
49997 #if defined(DUK_USE_FINALIZER_SUPPORT)
49998 	if (heap->finalize_list != NULL) {
49999 		flags |= DUK_MS_FLAG_POSTPONE_RESCUE;
50000 	}
50001 #endif
50002 
50003 	/*
50004 	 *  Assertions before
50005 	 */
50006 
50007 #if defined(DUK_USE_ASSERTIONS)
50008 	DUK_ASSERT(heap->ms_prevent_count == 0);
50009 	DUK_ASSERT(heap->ms_running == 0);
50010 	DUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(heap));
50011 	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
50012 	DUK_ASSERT(heap->ms_recursion_depth == 0);
50013 	duk__assert_heaphdr_flags(heap);
50014 #if defined(DUK_USE_REFERENCE_COUNTING)
50015 	/* Note: heap->refzero_free_running may be true; a refcount
50016 	 * finalizer may trigger a mark-and-sweep.
50017 	 */
50018 	duk__assert_valid_refcounts(heap);
50019 #endif  /* DUK_USE_REFERENCE_COUNTING */
50020 #endif  /* DUK_USE_ASSERTIONS */
50021 
50022 	/*
50023 	 *  Begin
50024 	 */
50025 
50026 	DUK_ASSERT(heap->ms_prevent_count == 0);
50027 	DUK_ASSERT(heap->ms_running == 0);
50028 	heap->ms_prevent_count = 1;
50029 	heap->ms_running = 1;
50030 
50031 	/*
50032 	 *  Free activation/catcher freelists on every mark-and-sweep for now.
50033 	 *  This is an initial rough draft; ideally we'd keep count of the
50034 	 *  freelist size and free only excess entries.
50035 	 */
50036 
50037 	DUK_D(DUK_DPRINT("freeing temporary freelists"));
50038 	duk_heap_free_freelists(heap);
50039 
50040 	/*
50041 	 *  Mark roots, hoping that recursion limit is not normally hit.
50042 	 *  If recursion limit is hit, run additional reachability rounds
50043 	 *  starting from "temproots" until marking is complete.
50044 	 *
50045 	 *  Marking happens in two phases: first we mark actual reachability
50046 	 *  roots (and run "temproots" to complete the process).  Then we
50047 	 *  check which objects are unreachable and are finalizable; such
50048 	 *  objects are marked as FINALIZABLE and marked as reachability
50049 	 *  (and "temproots" is run again to complete the process).
50050 	 *
50051 	 *  The heap finalize_list must also be marked as a reachability root.
50052 	 *  There may be objects on the list from a previous round if the
50053 	 *  previous run had finalizer skip flag.
50054 	 */
50055 
50056 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
50057 	duk__clear_assert_refcounts(heap);
50058 #endif
50059 #if defined(DUK_USE_LITCACHE_SIZE)
50060 	duk__wipe_litcache(heap);
50061 #endif
50062 	duk__mark_roots_heap(heap);               /* Mark main reachability roots. */
50063 #if defined(DUK_USE_REFERENCE_COUNTING)
50064 	DUK_ASSERT(heap->refzero_list == NULL);   /* Always handled to completion inline in DECREF. */
50065 #endif
50066 	duk__mark_temproots_by_heap_scan(heap);   /* Temproots. */
50067 
50068 #if defined(DUK_USE_FINALIZER_SUPPORT)
50069 	duk__mark_finalizable(heap);              /* Mark finalizable as reachability roots. */
50070 	duk__mark_finalize_list(heap);            /* Mark finalizer work list as reachability roots. */
50071 #endif
50072 	duk__mark_temproots_by_heap_scan(heap);   /* Temproots. */
50073 
50074 	/*
50075 	 *  Sweep garbage and remove marking flags, and move objects with
50076 	 *  finalizers to the finalizer work list.
50077 	 *
50078 	 *  Objects to be swept need to get their refcounts finalized before
50079 	 *  they are swept.  In other words, their target object refcounts
50080 	 *  need to be decreased.  This has to be done before freeing any
50081 	 *  objects to avoid decref'ing dangling pointers (which may happen
50082 	 *  even without bugs, e.g. with reference loops)
50083 	 *
50084 	 *  Because strings don't point to other heap objects, similar
50085 	 *  finalization is not necessary for strings.
50086 	 */
50087 
50088 	/* XXX: more emergency behavior, e.g. find smaller hash sizes etc */
50089 
50090 #if defined(DUK_USE_REFERENCE_COUNTING)
50091 	duk__finalize_refcounts(heap);
50092 #endif
50093 	duk__sweep_heap(heap, flags, &count_keep_obj);
50094 	duk__sweep_stringtable(heap, &count_keep_str);
50095 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
50096 	duk__check_assert_refcounts(heap);
50097 #endif
50098 #if defined(DUK_USE_REFERENCE_COUNTING)
50099 	DUK_ASSERT(heap->refzero_list == NULL);   /* Always handled to completion inline in DECREF. */
50100 #endif
50101 #if defined(DUK_USE_FINALIZER_SUPPORT)
50102 	duk__clear_finalize_list_flags(heap);
50103 #endif
50104 
50105 	/*
50106 	 *  Object compaction (emergency only).
50107 	 *
50108 	 *  Object compaction is a separate step after sweeping, as there is
50109 	 *  more free memory for it to work with.  Also, currently compaction
50110 	 *  may insert new objects into the heap allocated list and the string
50111 	 *  table which we don't want to do during a sweep (the reachability
50112 	 *  flags of such objects would be incorrect).  The objects inserted
50113 	 *  are currently:
50114 	 *
50115 	 *    - a temporary duk_hbuffer for a new properties allocation
50116 	 *    - if array part is abandoned, string keys are interned
50117 	 *
50118 	 *  The object insertions go to the front of the list, so they do not
50119 	 *  cause an infinite loop (they are not compacted).
50120 	 */
50121 
50122 	if ((flags & DUK_MS_FLAG_EMERGENCY) &&
50123 	    !(flags & DUK_MS_FLAG_NO_OBJECT_COMPACTION)) {
50124 		duk__compact_objects(heap);
50125 	}
50126 
50127 	/*
50128 	 *  String table resize check.
50129 	 *
50130 	 *  This is mainly useful in emergency GC: if the string table load
50131 	 *  factor is really low for some reason, we can shrink the string
50132 	 *  table to a smaller size and free some memory in the process.
50133 	 *  Only execute in emergency GC.  String table has internal flags
50134 	 *  to protect against recursive resizing if this mark-and-sweep pass
50135 	 *  was triggered by a string table resize.
50136 	 */
50137 
50138 	if (flags & DUK_MS_FLAG_EMERGENCY) {
50139 		DUK_D(DUK_DPRINT("stringtable resize check in emergency gc"));
50140 		duk_heap_strtable_force_resize(heap);
50141 	}
50142 
50143 	/*
50144 	 *  Finish
50145 	 */
50146 
50147 	DUK_ASSERT(heap->ms_prevent_count == 1);
50148 	heap->ms_prevent_count = 0;
50149 	DUK_ASSERT(heap->ms_running == 1);
50150 	heap->ms_running = 0;
50151 
50152 	/*
50153 	 *  Assertions after
50154 	 */
50155 
50156 #if defined(DUK_USE_ASSERTIONS)
50157 	DUK_ASSERT(heap->ms_prevent_count == 0);
50158 	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
50159 	DUK_ASSERT(heap->ms_recursion_depth == 0);
50160 	duk__assert_heaphdr_flags(heap);
50161 #if defined(DUK_USE_REFERENCE_COUNTING)
50162 	/* Note: heap->refzero_free_running may be true; a refcount
50163 	 * finalizer may trigger a mark-and-sweep.
50164 	 */
50165 	duk__assert_valid_refcounts(heap);
50166 #endif  /* DUK_USE_REFERENCE_COUNTING */
50167 #if defined(DUK_USE_LITCACHE_SIZE)
50168 	duk__assert_litcache_nulls(heap);
50169 #endif  /* DUK_USE_LITCACHE_SIZE */
50170 #endif  /* DUK_USE_ASSERTIONS */
50171 
50172 	/*
50173 	 *  Reset trigger counter
50174 	 */
50175 
50176 #if defined(DUK_USE_VOLUNTARY_GC)
50177 	tmp = (count_keep_obj + count_keep_str) / 256;
50178 	heap->ms_trigger_counter = (duk_int_t) (
50179 	    (tmp * DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT) +
50180 	    DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD);
50181 	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, trigger reset to %ld",
50182 	                 (long) count_keep_obj, (long) count_keep_str, (long) heap->ms_trigger_counter));
50183 #else
50184 	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, no voluntary trigger",
50185 	                 (long) count_keep_obj, (long) count_keep_str));
50186 #endif
50187 
50188 	/*
50189 	 *  Stats dump
50190 	 */
50191 
50192 #if defined(DUK_USE_DEBUG)
50193 	duk__dump_stats(heap);
50194 #endif
50195 
50196 	/*
50197 	 *  Finalize objects in the finalization work list.  Finalized
50198 	 *  objects are queued back to heap_allocated with FINALIZED set.
50199 	 *
50200 	 *  Since finalizers may cause arbitrary side effects, they are
50201 	 *  prevented e.g. during string table and object property allocation
50202 	 *  resizing using heap->pf_prevent_count.  In this case the objects
50203 	 *  remain in the finalization work list after mark-and-sweep exits
50204 	 *  and they may be finalized on the next pass or any DECREF checking
50205 	 *  for finalize_list.
50206 	 *
50207 	 *  As of Duktape 2.1 finalization happens outside mark-and-sweep
50208 	 *  protection.  Mark-and-sweep is allowed while the finalize_list
50209 	 *  is being processed, but no rescue decisions are done while the
50210 	 *  process is on-going.  This avoids incorrect rescue decisions
50211 	 *  if an object is considered reachable (and thus rescued) because
50212 	 *  of a reference via finalize_list (which is considered a reachability
50213 	 *  root).  When finalize_list is being processed, reachable objects
50214 	 *  with FINALIZED set will just keep their FINALIZED flag for later
50215 	 *  mark-and-sweep processing.
50216 	 *
50217 	 *  This could also be handled (a bit better) by having a more refined
50218 	 *  notion of reachability for rescue/free decisions.
50219 	 *
50220 	 *  XXX: avoid finalizer execution when doing emergency GC?
50221 	 */
50222 
50223 #if defined(DUK_USE_FINALIZER_SUPPORT)
50224 	/* Attempt to process finalize_list, pf_prevent_count check
50225 	 * is inside the target.
50226 	 */
50227 	duk_heap_process_finalize_list(heap);
50228 #endif  /* DUK_USE_FINALIZER_SUPPORT */
50229 }
50230 #line 1 "duk_heap_memory.c"
50231 /*
50232  *  Memory allocation handling.
50233  */
50234 
50235 /* #include duk_internal.h -> already included */
50236 
50237 /*
50238  *  Voluntary GC check
50239  */
50240 
50241 #if defined(DUK_USE_VOLUNTARY_GC)
50242 DUK_LOCAL DUK_INLINE void duk__check_voluntary_gc(duk_heap *heap) {
50243 	if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
50244 #if defined(DUK_USE_DEBUG)
50245 		if (heap->ms_prevent_count == 0) {
50246 			DUK_D(DUK_DPRINT("triggering voluntary mark-and-sweep"));
50247 		} else {
50248 			DUK_DD(DUK_DDPRINT("gc blocked -> skip voluntary mark-and-sweep now"));
50249 		}
50250 #endif
50251 
50252 		/* Prevention checks in the call target handle cases where
50253 		 * voluntary GC is not allowed.  The voluntary GC trigger
50254 		 * counter is only rewritten if mark-and-sweep actually runs.
50255 		 */
50256 		duk_heap_mark_and_sweep(heap, DUK_MS_FLAG_VOLUNTARY /*flags*/);
50257 	}
50258 }
50259 #define DUK__VOLUNTARY_PERIODIC_GC(heap)  do { duk__check_voluntary_gc((heap)); } while (0)
50260 #else
50261 #define DUK__VOLUNTARY_PERIODIC_GC(heap)  /* no voluntary gc */
50262 #endif  /* DUK_USE_VOLUNTARY_GC */
50263 
50264 /*
50265  *  Allocate memory with garbage collection
50266  */
50267 
50268 DUK_INTERNAL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
50269 	void *res;
50270 	duk_small_int_t i;
50271 
50272 	DUK_ASSERT(heap != NULL);
50273 	DUK_ASSERT_DISABLE(size >= 0);
50274 
50275 	/*
50276 	 *  Voluntary periodic GC (if enabled)
50277 	 */
50278 
50279 	DUK__VOLUNTARY_PERIODIC_GC(heap);
50280 
50281 	/*
50282 	 *  First attempt
50283 	 */
50284 
50285 #if defined(DUK_USE_GC_TORTURE)
50286 	/* Simulate alloc failure on every alloc, except when mark-and-sweep
50287 	 * is running.
50288 	 */
50289 	if (heap->ms_prevent_count == 0) {
50290 		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first alloc attempt fails"));
50291 		res = NULL;
50292 		DUK_UNREF(res);
50293 		goto skip_attempt;
50294 	}
50295 #endif
50296 	res = heap->alloc_func(heap->heap_udata, size);
50297 	if (DUK_LIKELY(res || size == 0)) {
50298 		/* For zero size allocations NULL is allowed. */
50299 		return res;
50300 	}
50301 #if defined(DUK_USE_GC_TORTURE)
50302  skip_attempt:
50303 #endif
50304 
50305 	DUK_D(DUK_DPRINT("first alloc attempt failed, attempt to gc and retry"));
50306 
50307 #if 0
50308 	/*
50309 	 *  Avoid a GC if GC is already running.  This can happen at a late
50310 	 *  stage in a GC when we try to e.g. resize the stringtable
50311 	 *  or compact objects.
50312 	 *
50313 	 *  NOTE: explicit handling isn't actually be needed: if the GC is
50314 	 *  not allowed, duk_heap_mark_and_sweep() will reject it for every
50315 	 *  attempt in the loop below, resulting in a NULL same as here.
50316 	 */
50317 
50318 	if (heap->ms_prevent_count != 0) {
50319 		DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed, gc in progress (gc skipped), alloc size %ld", (long) size));
50320 		return NULL;
50321 	}
50322 #endif
50323 
50324 	/*
50325 	 *  Retry with several GC attempts.  Initial attempts are made without
50326 	 *  emergency mode; later attempts use emergency mode which minimizes
50327 	 *  memory allocations forcibly.
50328 	 */
50329 
50330 	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
50331 		duk_small_uint_t flags;
50332 
50333 		flags = 0;
50334 		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
50335 			flags |= DUK_MS_FLAG_EMERGENCY;
50336 		}
50337 
50338 		duk_heap_mark_and_sweep(heap, flags);
50339 
50340 		res = heap->alloc_func(heap->heap_udata, size);
50341 		if (res) {
50342 			DUK_D(DUK_DPRINT("duk_heap_mem_alloc() succeeded after gc (pass %ld), alloc size %ld",
50343 			                 (long) (i + 1), (long) size));
50344 			return res;
50345 		}
50346 	}
50347 
50348 	DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed even after gc, alloc size %ld", (long) size));
50349 	return NULL;
50350 }
50351 
50352 DUK_INTERNAL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size) {
50353 	void *res;
50354 
50355 	DUK_ASSERT(heap != NULL);
50356 	DUK_ASSERT_DISABLE(size >= 0);
50357 
50358 	res = DUK_ALLOC(heap, size);
50359 	if (DUK_LIKELY(res != NULL)) {
50360 		duk_memzero(res, size);
50361 	}
50362 	return res;
50363 }
50364 
50365 DUK_INTERNAL void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size) {
50366 	void *res;
50367 
50368 	DUK_ASSERT(thr != NULL);
50369 	res = duk_heap_mem_alloc(thr->heap, size);
50370 	if (DUK_LIKELY(res != NULL || size == 0)) {
50371 		return res;
50372 	}
50373 	DUK_ERROR_ALLOC_FAILED(thr);
50374 	DUK_WO_NORETURN(return NULL;);
50375 }
50376 
50377 DUK_INTERNAL void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size) {
50378 	void *res;
50379 
50380 	DUK_ASSERT(thr != NULL);
50381 	res = duk_heap_mem_alloc_zeroed(thr->heap, size);
50382 	if (DUK_LIKELY(res != NULL || size == 0)) {
50383 		return res;
50384 	}
50385 	DUK_ERROR_ALLOC_FAILED(thr);
50386 	DUK_WO_NORETURN(return NULL;);
50387 }
50388 
50389 /*
50390  *  Reallocate memory with garbage collection
50391  */
50392 
50393 DUK_INTERNAL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
50394 	void *res;
50395 	duk_small_int_t i;
50396 
50397 	DUK_ASSERT(heap != NULL);
50398 	/* ptr may be NULL */
50399 	DUK_ASSERT_DISABLE(newsize >= 0);
50400 
50401 	/*
50402 	 *  Voluntary periodic GC (if enabled)
50403 	 */
50404 
50405 	DUK__VOLUNTARY_PERIODIC_GC(heap);
50406 
50407 	/*
50408 	 *  First attempt
50409 	 */
50410 
50411 #if defined(DUK_USE_GC_TORTURE)
50412 	/* Simulate alloc failure on every realloc, except when mark-and-sweep
50413 	 * is running.
50414 	 */
50415 	if (heap->ms_prevent_count == 0) {
50416 		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first realloc attempt fails"));
50417 		res = NULL;
50418 		DUK_UNREF(res);
50419 		goto skip_attempt;
50420 	}
50421 #endif
50422 	res = heap->realloc_func(heap->heap_udata, ptr, newsize);
50423 	if (DUK_LIKELY(res || newsize == 0)) {
50424 		/* For zero size allocations NULL is allowed. */
50425 		return res;
50426 	}
50427 #if defined(DUK_USE_GC_TORTURE)
50428  skip_attempt:
50429 #endif
50430 
50431 	DUK_D(DUK_DPRINT("first realloc attempt failed, attempt to gc and retry"));
50432 
50433 #if 0
50434 	/*
50435 	 *  Avoid a GC if GC is already running.  See duk_heap_mem_alloc().
50436 	 */
50437 
50438 	if (heap->ms_prevent_count != 0) {
50439 		DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
50440 		return NULL;
50441 	}
50442 #endif
50443 
50444 	/*
50445 	 *  Retry with several GC attempts.  Initial attempts are made without
50446 	 *  emergency mode; later attempts use emergency mode which minimizes
50447 	 *  memory allocations forcibly.
50448 	 */
50449 
50450 	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
50451 		duk_small_uint_t flags;
50452 
50453 		flags = 0;
50454 		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
50455 			flags |= DUK_MS_FLAG_EMERGENCY;
50456 		}
50457 
50458 		duk_heap_mark_and_sweep(heap, flags);
50459 
50460 		res = heap->realloc_func(heap->heap_udata, ptr, newsize);
50461 		if (res || newsize == 0) {
50462 			DUK_D(DUK_DPRINT("duk_heap_mem_realloc() succeeded after gc (pass %ld), alloc size %ld",
50463 			                 (long) (i + 1), (long) newsize));
50464 			return res;
50465 		}
50466 	}
50467 
50468 	DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed even after gc, alloc size %ld", (long) newsize));
50469 	return NULL;
50470 }
50471 
50472 /*
50473  *  Reallocate memory with garbage collection, using a callback to provide
50474  *  the current allocated pointer.  This variant is used when a mark-and-sweep
50475  *  (e.g. finalizers) might change the original pointer.
50476  */
50477 
50478 DUK_INTERNAL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
50479 	void *res;
50480 	duk_small_int_t i;
50481 
50482 	DUK_ASSERT(heap != NULL);
50483 	DUK_ASSERT_DISABLE(newsize >= 0);
50484 
50485 	/*
50486 	 *  Voluntary periodic GC (if enabled)
50487 	 */
50488 
50489 	DUK__VOLUNTARY_PERIODIC_GC(heap);
50490 
50491 	/*
50492 	 *  First attempt
50493 	 */
50494 
50495 #if defined(DUK_USE_GC_TORTURE)
50496 	/* Simulate alloc failure on every realloc, except when mark-and-sweep
50497 	 * is running.
50498 	 */
50499 	if (heap->ms_prevent_count == 0) {
50500 		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first indirect realloc attempt fails"));
50501 		res = NULL;
50502 		DUK_UNREF(res);
50503 		goto skip_attempt;
50504 	}
50505 #endif
50506 	res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
50507 	if (DUK_LIKELY(res || newsize == 0)) {
50508 		/* For zero size allocations NULL is allowed. */
50509 		return res;
50510 	}
50511 #if defined(DUK_USE_GC_TORTURE)
50512  skip_attempt:
50513 #endif
50514 
50515 	DUK_D(DUK_DPRINT("first indirect realloc attempt failed, attempt to gc and retry"));
50516 
50517 #if 0
50518 	/*
50519 	 *  Avoid a GC if GC is already running.  See duk_heap_mem_alloc().
50520 	 */
50521 
50522 	if (heap->ms_prevent_count != 0) {
50523 		DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
50524 		return NULL;
50525 	}
50526 #endif
50527 
50528 	/*
50529 	 *  Retry with several GC attempts.  Initial attempts are made without
50530 	 *  emergency mode; later attempts use emergency mode which minimizes
50531 	 *  memory allocations forcibly.
50532 	 */
50533 
50534 	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
50535 		duk_small_uint_t flags;
50536 
50537 #if defined(DUK_USE_DEBUG)
50538 		void *ptr_pre;
50539 		void *ptr_post;
50540 #endif
50541 
50542 #if defined(DUK_USE_DEBUG)
50543 		ptr_pre = cb(heap, ud);
50544 #endif
50545 		flags = 0;
50546 		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
50547 			flags |= DUK_MS_FLAG_EMERGENCY;
50548 		}
50549 
50550 		duk_heap_mark_and_sweep(heap, flags);
50551 #if defined(DUK_USE_DEBUG)
50552 		ptr_post = cb(heap, ud);
50553 		if (ptr_pre != ptr_post) {
50554 			DUK_DD(DUK_DDPRINT("realloc base pointer changed by mark-and-sweep: %p -> %p",
50555 			                   (void *) ptr_pre, (void *) ptr_post));
50556 		}
50557 #endif
50558 
50559 		/* Note: key issue here is to re-lookup the base pointer on every attempt.
50560 		 * The pointer being reallocated may change after every mark-and-sweep.
50561 		 */
50562 
50563 		res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
50564 		if (res || newsize == 0) {
50565 			DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() succeeded after gc (pass %ld), alloc size %ld",
50566 			                 (long) (i + 1), (long) newsize));
50567 			return res;
50568 		}
50569 	}
50570 
50571 	DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed even after gc, alloc size %ld", (long) newsize));
50572 	return NULL;
50573 }
50574 
50575 /*
50576  *  Free memory
50577  */
50578 
50579 DUK_INTERNAL void duk_heap_mem_free(duk_heap *heap, void *ptr) {
50580 	DUK_ASSERT(heap != NULL);
50581 	/* ptr may be NULL */
50582 
50583 	/* Must behave like a no-op with NULL and any pointer returned from
50584 	 * malloc/realloc with zero size.
50585 	 */
50586 	heap->free_func(heap->heap_udata, ptr);
50587 
50588 	/* Never perform a GC (even voluntary) in a memory free, otherwise
50589 	 * all call sites doing frees would need to deal with the side effects.
50590 	 * No need to update voluntary GC counter either.
50591 	 */
50592 }
50593 
50594 /* automatic undefs */
50595 #undef DUK__VOLUNTARY_PERIODIC_GC
50596 #line 1 "duk_heap_misc.c"
50597 /*
50598  *  Support functions for duk_heap.
50599  */
50600 
50601 /* #include duk_internal.h -> already included */
50602 
50603 DUK_INTERNAL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
50604 	duk_heaphdr *root;
50605 
50606 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);
50607 
50608 	root = heap->heap_allocated;
50609 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
50610 	if (root != NULL) {
50611 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);
50612 		DUK_HEAPHDR_SET_PREV(heap, root, hdr);
50613 	}
50614 	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
50615 #endif
50616 	DUK_HEAPHDR_SET_NEXT(heap, hdr, root);
50617 	DUK_ASSERT_HEAPHDR_LINKS(heap, hdr);
50618 	DUK_ASSERT_HEAPHDR_LINKS(heap, root);
50619 	heap->heap_allocated = hdr;
50620 }
50621 
50622 #if defined(DUK_USE_REFERENCE_COUNTING)
50623 DUK_INTERNAL void duk_heap_remove_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
50624 	duk_heaphdr *prev;
50625 	duk_heaphdr *next;
50626 
50627 	/* Strings are in string table. */
50628 	DUK_ASSERT(hdr != NULL);
50629 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);
50630 
50631 	/* Target 'hdr' must be in heap_allocated (not e.g. finalize_list).
50632 	 * If not, heap lists will become corrupted so assert early for it.
50633 	 */
50634 #if defined(DUK_USE_ASSERTIONS)
50635 	{
50636 		duk_heaphdr *tmp;
50637 		for (tmp = heap->heap_allocated; tmp != NULL; tmp = DUK_HEAPHDR_GET_NEXT(heap, tmp)) {
50638 			if (tmp == hdr) {
50639 				break;
50640 			}
50641 		}
50642 		DUK_ASSERT(tmp == hdr);
50643 	}
50644 #endif
50645 
50646 	/* Read/write only once to minimize pointer compression calls. */
50647 	prev = DUK_HEAPHDR_GET_PREV(heap, hdr);
50648 	next = DUK_HEAPHDR_GET_NEXT(heap, hdr);
50649 
50650 	if (prev != NULL) {
50651 		DUK_ASSERT(heap->heap_allocated != hdr);
50652 		DUK_HEAPHDR_SET_NEXT(heap, prev, next);
50653 	} else {
50654 		DUK_ASSERT(heap->heap_allocated == hdr);
50655 		heap->heap_allocated = next;
50656 	}
50657 	if (next != NULL) {
50658 		DUK_HEAPHDR_SET_PREV(heap, next, prev);
50659 	} else {
50660 		;
50661 	}
50662 }
50663 #endif  /* DUK_USE_REFERENCE_COUNTING */
50664 
50665 #if defined(DUK_USE_FINALIZER_SUPPORT)
50666 DUK_INTERNAL void duk_heap_insert_into_finalize_list(duk_heap *heap, duk_heaphdr *hdr) {
50667 	duk_heaphdr *root;
50668 
50669 	root = heap->finalize_list;
50670 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
50671 	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
50672 	if (root != NULL) {
50673 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);
50674 		DUK_HEAPHDR_SET_PREV(heap, root, hdr);
50675 	}
50676 #endif
50677 	DUK_HEAPHDR_SET_NEXT(heap, hdr, root);
50678 	DUK_ASSERT_HEAPHDR_LINKS(heap, hdr);
50679 	DUK_ASSERT_HEAPHDR_LINKS(heap, root);
50680 	heap->finalize_list = hdr;
50681 }
50682 #endif  /* DUK_USE_FINALIZER_SUPPORT */
50683 
50684 #if defined(DUK_USE_FINALIZER_SUPPORT)
50685 DUK_INTERNAL void duk_heap_remove_from_finalize_list(duk_heap *heap, duk_heaphdr *hdr) {
50686 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
50687 	duk_heaphdr *next;
50688 	duk_heaphdr *prev;
50689 
50690 	next = DUK_HEAPHDR_GET_NEXT(heap, hdr);
50691 	prev = DUK_HEAPHDR_GET_PREV(heap, hdr);
50692 	if (next != NULL) {
50693 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, next) == hdr);
50694 		DUK_HEAPHDR_SET_PREV(heap, next, prev);
50695 	}
50696 	if (prev == NULL) {
50697 		DUK_ASSERT(hdr == heap->finalize_list);
50698 		heap->finalize_list = next;
50699 	} else {
50700 		DUK_ASSERT(hdr != heap->finalize_list);
50701 		DUK_HEAPHDR_SET_NEXT(heap, prev, next);
50702 	}
50703 #else
50704 	duk_heaphdr *next;
50705 	duk_heaphdr *curr;
50706 
50707 	/* Random removal is expensive: we need to locate the previous element
50708 	 * because we don't have a 'prev' pointer.
50709 	 */
50710 	curr = heap->finalize_list;
50711 	if (curr == hdr) {
50712 		heap->finalize_list = DUK_HEAPHDR_GET_NEXT(heap, curr);
50713 	} else {
50714 		DUK_ASSERT(hdr != heap->finalize_list);
50715 		for (;;) {
50716 			DUK_ASSERT(curr != NULL);  /* Caller responsibility. */
50717 
50718 			next = DUK_HEAPHDR_GET_NEXT(heap, curr);
50719 			if (next == hdr) {
50720 				next = DUK_HEAPHDR_GET_NEXT(heap, hdr);
50721 				DUK_HEAPHDR_SET_NEXT(heap, curr, next);
50722 				break;
50723 			}
50724 		}
50725 	}
50726 #endif
50727 }
50728 #endif  /* DUK_USE_FINALIZER_SUPPORT */
50729 
50730 #if defined(DUK_USE_ASSERTIONS)
50731 DUK_INTERNAL duk_bool_t duk_heap_in_heap_allocated(duk_heap *heap, duk_heaphdr *ptr) {
50732 	duk_heaphdr *curr;
50733 	DUK_ASSERT(heap != NULL);
50734 
50735 	for (curr = heap->heap_allocated; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
50736 		if (curr == ptr) {
50737 			return 1;
50738 		}
50739 	}
50740 	return 0;
50741 }
50742 #endif  /* DUK_USE_ASSERTIONS */
50743 
50744 #if defined(DUK_USE_INTERRUPT_COUNTER)
50745 DUK_INTERNAL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr) {
50746 	duk_hthread *curr_thr;
50747 
50748 	DUK_ASSERT(heap != NULL);
50749 
50750 	if (new_thr != NULL) {
50751 		curr_thr = heap->curr_thread;
50752 		if (curr_thr == NULL) {
50753 			/* For initial entry use default value; zero forces an
50754 			 * interrupt before executing the first insturction.
50755 			 */
50756 			DUK_DD(DUK_DDPRINT("switch thread, initial entry, init default interrupt counter"));
50757 			new_thr->interrupt_counter = 0;
50758 			new_thr->interrupt_init = 0;
50759 		} else {
50760 			/* Copy interrupt counter/init value state to new thread (if any).
50761 			 * It's OK for new_thr to be the same as curr_thr.
50762 			 */
50763 #if defined(DUK_USE_DEBUG)
50764 			if (new_thr != curr_thr) {
50765 				DUK_DD(DUK_DDPRINT("switch thread, not initial entry, copy interrupt counter"));
50766 			}
50767 #endif
50768 			new_thr->interrupt_counter = curr_thr->interrupt_counter;
50769 			new_thr->interrupt_init = curr_thr->interrupt_init;
50770 		}
50771 	} else {
50772 		DUK_DD(DUK_DDPRINT("switch thread, new thread is NULL, no interrupt counter changes"));
50773 	}
50774 
50775 	heap->curr_thread = new_thr;  /* may be NULL */
50776 }
50777 #endif  /* DUK_USE_INTERRUPT_COUNTER */
50778 #line 1 "duk_heap_refcount.c"
50779 /*
50780  *  Reference counting implementation.
50781  *
50782  *  INCREF/DECREF, finalization and freeing of objects whose refcount reaches
50783  *  zero (refzero).  These operations are very performance sensitive, so
50784  *  various small tricks are used in an attempt to maximize speed.
50785  */
50786 
50787 /* #include duk_internal.h -> already included */
50788 
50789 #if defined(DUK_USE_REFERENCE_COUNTING)
50790 
50791 #if !defined(DUK_USE_DOUBLE_LINKED_HEAP)
50792 #error internal error, reference counting requires a double linked heap
50793 #endif
50794 
50795 /*
50796  *  Heap object refcount finalization.
50797  *
50798  *  When an object is about to be freed, all other objects it refers to must
50799  *  be decref'd.  Refcount finalization does NOT free the object or its inner
50800  *  allocations (mark-and-sweep shares these helpers), it just manipulates
50801  *  the refcounts.
50802  *
50803  *  Note that any of the DECREFs may cause a refcount to drop to zero.  If so,
50804  *  the object won't be refzero processed inline, but will just be queued to
50805  *  refzero_list and processed by an earlier caller working on refzero_list,
50806  *  eliminating C recursion from even long refzero cascades.  If refzero
50807  *  finalization is triggered by mark-and-sweep, refzero conditions are ignored
50808  *  (objects are not even queued to refzero_list) because mark-and-sweep deals
50809  *  with them; refcounts are still updated so that they remain in sync with
50810  *  actual references.
50811  */
50812 
50813 DUK_LOCAL void duk__decref_tvals_norz(duk_hthread *thr, duk_tval *tv, duk_idx_t count) {
50814 	DUK_ASSERT(count == 0 || tv != NULL);
50815 
50816 	while (count-- > 0) {
50817 		DUK_TVAL_DECREF_NORZ(thr, tv);
50818 		tv++;
50819 	}
50820 }
50821 
50822 DUK_INTERNAL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject *h) {
50823 	duk_hthread *thr;
50824 	duk_uint_fast32_t i;
50825 	duk_uint_fast32_t n;
50826 	duk_propvalue *p_val;
50827 	duk_tval *p_tv;
50828 	duk_hstring **p_key;
50829 	duk_uint8_t *p_flag;
50830 	duk_hobject *h_proto;
50831 
50832 	DUK_ASSERT(heap != NULL);
50833 	DUK_ASSERT(heap->heap_thread != NULL);
50834 	DUK_ASSERT(h);
50835 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h) == DUK_HTYPE_OBJECT);
50836 
50837 	thr = heap->heap_thread;
50838 	DUK_ASSERT(thr != NULL);
50839 
50840 	p_key = DUK_HOBJECT_E_GET_KEY_BASE(heap, h);
50841 	p_val = DUK_HOBJECT_E_GET_VALUE_BASE(heap, h);
50842 	p_flag = DUK_HOBJECT_E_GET_FLAGS_BASE(heap, h);
50843 	n = DUK_HOBJECT_GET_ENEXT(h);
50844 	while (n-- > 0) {
50845 		duk_hstring *key;
50846 
50847 		key = p_key[n];
50848 		if (DUK_UNLIKELY(key == NULL)) {
50849 			continue;
50850 		}
50851 		DUK_HSTRING_DECREF_NORZ(thr, key);
50852 		if (DUK_UNLIKELY(p_flag[n] & DUK_PROPDESC_FLAG_ACCESSOR)) {
50853 			duk_hobject *h_getset;
50854 			h_getset = p_val[n].a.get;
50855 			DUK_ASSERT(h_getset == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_getset));
50856 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_getset);
50857 			h_getset = p_val[n].a.set;
50858 			DUK_ASSERT(h_getset == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_getset));
50859 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_getset);
50860 		} else {
50861 			duk_tval *tv_val;
50862 			tv_val = &p_val[n].v;
50863 			DUK_TVAL_DECREF_NORZ(thr, tv_val);
50864 		}
50865 	}
50866 
50867 	p_tv = DUK_HOBJECT_A_GET_BASE(heap, h);
50868 	n = DUK_HOBJECT_GET_ASIZE(h);
50869 	while (n-- > 0) {
50870 		duk_tval *tv_val;
50871 		tv_val = p_tv + n;
50872 		DUK_TVAL_DECREF_NORZ(thr, tv_val);
50873 	}
50874 
50875 	/* Hash part is a 'weak reference' and doesn't contribute to refcounts. */
50876 
50877 	h_proto = (duk_hobject *) DUK_HOBJECT_GET_PROTOTYPE(heap, h);
50878 	DUK_ASSERT(h_proto == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_proto));
50879 	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_proto);
50880 
50881 	/* XXX: Object subclass tests are quite awkward at present, ideally
50882 	 * we should be able to switch-case here with a dense index (subtype
50883 	 * number or something).  For now, fast path plain objects and arrays
50884 	 * and bit test the rest individually.
50885 	 */
50886 
50887 	if (DUK_HOBJECT_HAS_FASTREFS(h)) {
50888 		/* Plain object or array, nothing more to do.  While a
50889 		 * duk_harray has additional fields, none of them need
50890 		 * DECREF updates.
50891 		 */
50892 		DUK_ASSERT(DUK_HOBJECT_ALLOWS_FASTREFS(h));
50893 		return;
50894 	}
50895 	DUK_ASSERT(DUK_HOBJECT_PROHIBITS_FASTREFS(h));
50896 
50897 	/* Slow path: special object, start bit checks from most likely. */
50898 
50899 	/* XXX: reorg, more common first */
50900 	if (DUK_HOBJECT_IS_COMPFUNC(h)) {
50901 		duk_hcompfunc *f = (duk_hcompfunc *) h;
50902 		duk_tval *tv, *tv_end;
50903 		duk_hobject **funcs, **funcs_end;
50904 
50905 		DUK_ASSERT_HCOMPFUNC_VALID(f);
50906 
50907 		if (DUK_LIKELY(DUK_HCOMPFUNC_GET_DATA(heap, f) != NULL)) {
50908 			tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);
50909 			tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(heap, f);
50910 			while (tv < tv_end) {
50911 				DUK_TVAL_DECREF_NORZ(thr, tv);
50912 				tv++;
50913 			}
50914 
50915 			funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, f);
50916 			funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(heap, f);
50917 			while (funcs < funcs_end) {
50918 				duk_hobject *h_func;
50919 				h_func = *funcs;
50920 				DUK_ASSERT(h_func != NULL);
50921 				DUK_ASSERT(DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_func));
50922 				DUK_HCOMPFUNC_DECREF_NORZ(thr, (duk_hcompfunc *) h_func);
50923 				funcs++;
50924 			}
50925 		} else {
50926 			/* May happen in some out-of-memory corner cases. */
50927 			DUK_D(DUK_DPRINT("duk_hcompfunc 'data' is NULL, skipping decref"));
50928 		}
50929 
50930 		DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_heaphdr *) DUK_HCOMPFUNC_GET_LEXENV(heap, f));
50931 		DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_heaphdr *) DUK_HCOMPFUNC_GET_VARENV(heap, f));
50932 		DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(heap, f));
50933 	} else if (DUK_HOBJECT_IS_DECENV(h)) {
50934 		duk_hdecenv *e = (duk_hdecenv *) h;
50935 		DUK_ASSERT_HDECENV_VALID(e);
50936 		DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr, e->thread);
50937 		DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, e->varmap);
50938 	} else if (DUK_HOBJECT_IS_OBJENV(h)) {
50939 		duk_hobjenv *e = (duk_hobjenv *) h;
50940 		DUK_ASSERT_HOBJENV_VALID(e);
50941 		DUK_ASSERT(e->target != NULL);  /* Required for object environments. */
50942 		DUK_HOBJECT_DECREF_NORZ(thr, e->target);
50943 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
50944 	} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
50945 		duk_hbufobj *b = (duk_hbufobj *) h;
50946 		DUK_ASSERT_HBUFOBJ_VALID(b);
50947 		DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr, (duk_hbuffer *) b->buf);
50948 		DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) b->buf_prop);
50949 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
50950 	} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
50951 		duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
50952 		DUK_ASSERT_HBOUNDFUNC_VALID(f);
50953 		DUK_TVAL_DECREF_NORZ(thr, &f->target);
50954 		DUK_TVAL_DECREF_NORZ(thr, &f->this_binding);
50955 		duk__decref_tvals_norz(thr, f->args, f->nargs);
50956 #if defined(DUK_USE_ES6_PROXY)
50957 	} else if (DUK_HOBJECT_IS_PROXY(h)) {
50958 		duk_hproxy *p = (duk_hproxy *) h;
50959 		DUK_ASSERT_HPROXY_VALID(p);
50960 		DUK_HOBJECT_DECREF_NORZ(thr, p->target);
50961 		DUK_HOBJECT_DECREF_NORZ(thr, p->handler);
50962 #endif  /* DUK_USE_ES6_PROXY */
50963 	} else if (DUK_HOBJECT_IS_THREAD(h)) {
50964 		duk_hthread *t = (duk_hthread *) h;
50965 		duk_activation *act;
50966 		duk_tval *tv;
50967 
50968 		DUK_ASSERT_HTHREAD_VALID(t);
50969 
50970 		tv = t->valstack;
50971 		while (tv < t->valstack_top) {
50972 			DUK_TVAL_DECREF_NORZ(thr, tv);
50973 			tv++;
50974 		}
50975 
50976 		for (act = t->callstack_curr; act != NULL; act = act->parent) {
50977 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) DUK_ACT_GET_FUNC(act));
50978 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->var_env);
50979 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->lex_env);
50980 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
50981 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->prev_caller);
50982 #endif
50983 #if 0  /* nothing now */
50984 			for (cat = act->cat; cat != NULL; cat = cat->parent) {
50985 			}
50986 #endif
50987 		}
50988 
50989 
50990 		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
50991 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) t->builtins[i]);
50992 		}
50993 
50994 		DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr, (duk_hthread *) t->resumer);
50995 	} else {
50996 		/* We may come here if the object should have a FASTREFS flag
50997 		 * but it's missing for some reason.  Assert for never getting
50998 		 * here; however, other than performance, this is harmless.
50999 		 */
51000 		DUK_D(DUK_DPRINT("missing FASTREFS flag for: %!iO", h));
51001 		DUK_ASSERT(0);
51002 	}
51003 }
51004 
51005 DUK_INTERNAL void duk_heaphdr_refcount_finalize_norz(duk_heap *heap, duk_heaphdr *hdr) {
51006 	DUK_ASSERT(heap != NULL);
51007 	DUK_ASSERT(heap->heap_thread != NULL);
51008 	DUK_ASSERT(hdr != NULL);
51009 
51010 	if (DUK_HEAPHDR_IS_OBJECT(hdr)) {
51011 		duk_hobject_refcount_finalize_norz(heap, (duk_hobject *) hdr);
51012 	}
51013 	/* DUK_HTYPE_BUFFER: nothing to finalize */
51014 	/* DUK_HTYPE_STRING: nothing to finalize */
51015 }
51016 
51017 /*
51018  *  Refzero processing for duk_hobject: queue a refzero'ed object to either
51019  *  finalize_list or refzero_list and process the relevent list(s) if
51020  *  necessary.
51021  *
51022  *  Refzero_list is single linked, with only 'prev' pointers set and valid.
51023  *  All 'next' pointers are intentionally left as garbage.  This doesn't
51024  *  matter because refzero_list is processed to completion before any other
51025  *  code (like mark-and-sweep) might walk the list.
51026  *
51027  *  In more detail:
51028  *
51029  *  - On first insert refzero_list is NULL and the new object becomes the
51030  *    first and only element on the list; duk__refcount_free_pending() is
51031  *    called and it starts processing the list from the initial element,
51032  *    i.e. the list tail.
51033  *
51034  *  - As each object is refcount finalized, new objects may be queued to
51035  *    refzero_list head.  Their 'next' pointers are left as garbage, but
51036  *    'prev' points are set correctly, with the element at refzero_list
51037  *    having a NULL 'prev' pointer.  The fact that refzero_list is non-NULL
51038  *    is used to reject (1) recursive duk__refcount_free_pending() and
51039  *    (2) finalize_list processing calls.
51040  *
51041  *  - When we're done with the current object, read its 'prev' pointer and
51042  *    free the object.  If 'prev' is NULL, we've reached head of list and are
51043  *    done: set refzero_list to NULL and process pending finalizers.  Otherwise
51044  *    continue processing the list.
51045  *
51046  *  A refzero cascade is free of side effects because it only involves
51047  *  queueing more objects and freeing memory; finalizer execution is blocked
51048  *  in the code path queueing objects to finalize_list.  As a result the
51049  *  initial refzero call (which triggers duk__refcount_free_pending()) must
51050  *  check finalize_list so that finalizers are executed snappily.
51051  *
51052  *  If finalize_list processing starts first, refzero may occur while we're
51053  *  processing finalizers.  That's fine: that particular refzero cascade is
51054  *  handled to completion without side effects.  Once the cascade is complete,
51055  *  we'll run pending finalizers but notice that we're already doing that and
51056  *  return.
51057  *
51058  *  This could be expanded to allow incremental freeing: just bail out
51059  *  early and resume at a future alloc/decref/refzero.  However, if that
51060  *  were done, the list structure would need to be kept consistent at all
51061  *  times, mark-and-sweep would need to handle refzero_list, etc.
51062  */
51063 
51064 DUK_LOCAL void duk__refcount_free_pending(duk_heap *heap) {
51065 	duk_heaphdr *curr;
51066 #if defined(DUK_USE_DEBUG)
51067 	duk_int_t count = 0;
51068 #endif
51069 
51070 	DUK_ASSERT(heap != NULL);
51071 
51072 	curr = heap->refzero_list;
51073 	DUK_ASSERT(curr != NULL);
51074 	DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, curr) == NULL);  /* We're called on initial insert only. */
51075 	/* curr->next is GARBAGE. */
51076 
51077 	do {
51078 		duk_heaphdr *prev;
51079 
51080 		DUK_DDD(DUK_DDDPRINT("refzero processing %p: %!O", (void *) curr, (duk_heaphdr *) curr));
51081 
51082 #if defined(DUK_USE_DEBUG)
51083 		count++;
51084 #endif
51085 
51086 		DUK_ASSERT(curr != NULL);
51087 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* currently, always the case */
51088 		/* FINALIZED may be set; don't care about flags here. */
51089 
51090 		/* Refcount finalize 'curr'.  Refzero_list must be non-NULL
51091 		 * here to prevent recursive entry to duk__refcount_free_pending().
51092 		 */
51093 		DUK_ASSERT(heap->refzero_list != NULL);
51094 		duk_hobject_refcount_finalize_norz(heap, (duk_hobject *) curr);
51095 
51096 		prev = DUK_HEAPHDR_GET_PREV(heap, curr);
51097 		DUK_ASSERT((prev == NULL && heap->refzero_list == curr) || \
51098 		           (prev != NULL && heap->refzero_list != curr));
51099 		/* prev->next is intentionally not updated and is garbage. */
51100 
51101 		duk_free_hobject(heap, (duk_hobject *) curr);  /* Invalidates 'curr'. */
51102 
51103 		curr = prev;
51104 	} while (curr != NULL);
51105 
51106 	heap->refzero_list = NULL;
51107 
51108 	DUK_DD(DUK_DDPRINT("refzero processed %ld objects", (long) count));
51109 }
51110 
51111 DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hobject(duk_heap *heap, duk_hobject *obj, duk_bool_t skip_free_pending) {
51112 	duk_heaphdr *hdr;
51113 	duk_heaphdr *root;
51114 
51115 	DUK_ASSERT(heap != NULL);
51116 	DUK_ASSERT(heap->heap_thread != NULL);
51117 	DUK_ASSERT(obj != NULL);
51118 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) obj) == DUK_HTYPE_OBJECT);
51119 
51120 	hdr = (duk_heaphdr *) obj;
51121 
51122 	/* Refzero'd objects must be in heap_allocated.  They can't be in
51123 	 * finalize_list because all objects on finalize_list have an
51124 	 * artificial +1 refcount bump.
51125 	 */
51126 #if defined(DUK_USE_ASSERTIONS)
51127 	DUK_ASSERT(duk_heap_in_heap_allocated(heap, (duk_heaphdr *) obj));
51128 #endif
51129 
51130 	DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap, hdr);
51131 
51132 #if defined(DUK_USE_FINALIZER_SUPPORT)
51133 	/* This finalizer check MUST BE side effect free.  It should also be
51134 	 * as fast as possible because it's applied to every object freed.
51135 	 */
51136 	if (DUK_UNLIKELY(DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) hdr) != 0U)) {
51137 		/* Special case: FINALIZED may be set if mark-and-sweep queued
51138 		 * object for finalization, the finalizer was executed (and
51139 		 * FINALIZED set), mark-and-sweep hasn't yet processed the
51140 		 * object again, but its refcount drops to zero.  Free without
51141 		 * running the finalizer again.
51142 		 */
51143 		if (DUK_HEAPHDR_HAS_FINALIZED(hdr)) {
51144 			DUK_D(DUK_DPRINT("refzero'd object has finalizer and FINALIZED is set -> free"));
51145 		} else {
51146 			/* Set FINALIZABLE flag so that all objects on finalize_list
51147 			 * will have it set and are thus detectable based on the
51148 			 * flag alone.
51149 			 */
51150 			DUK_HEAPHDR_SET_FINALIZABLE(hdr);
51151 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(hdr));
51152 
51153 #if defined(DUK_USE_REFERENCE_COUNTING)
51154 			/* Bump refcount on finalize_list insert so that a
51155 			 * refzero can never occur when an object is waiting
51156 			 * for its finalizer call.  Refzero might otherwise
51157 			 * now happen because we allow duk_push_heapptr() for
51158 			 * objects pending finalization.
51159 			 */
51160 			DUK_HEAPHDR_PREINC_REFCOUNT(hdr);
51161 #endif
51162 			DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap, hdr);
51163 
51164 			/* Process finalizers unless skipping is explicitly
51165 			 * requested (NORZ) or refzero_list is being processed
51166 			 * (avoids side effects during a refzero cascade).
51167 			 * If refzero_list is processed, the initial refzero
51168 			 * call will run pending finalizers when refzero_list
51169 			 * is done.
51170 			 */
51171 			if (!skip_free_pending && heap->refzero_list == NULL) {
51172 				duk_heap_process_finalize_list(heap);
51173 			}
51174 			return;
51175 		}
51176 	}
51177 #endif  /* DUK_USE_FINALIZER_SUPPORT */
51178 
51179 	/* No need to finalize, free object via refzero_list. */
51180 
51181 	root = heap->refzero_list;
51182 
51183 	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
51184 	/* 'next' is left as GARBAGE. */
51185 	heap->refzero_list = hdr;
51186 
51187 	if (root == NULL) {
51188 		/* Object is now queued.  Refzero_list was NULL so
51189 		 * no-one is currently processing it; do it here.
51190 		 * With refzero processing just doing a cascade of
51191 		 * free calls, we can process it directly even when
51192 		 * NORZ macros are used: there are no side effects.
51193 		 */
51194 		duk__refcount_free_pending(heap);
51195 		DUK_ASSERT(heap->refzero_list == NULL);
51196 
51197 		/* Process finalizers only after the entire cascade
51198 		 * is finished.  In most cases there's nothing to
51199 		 * finalize, so fast path check to avoid a call.
51200 		 */
51201 #if defined(DUK_USE_FINALIZER_SUPPORT)
51202 		if (!skip_free_pending && DUK_UNLIKELY(heap->finalize_list != NULL)) {
51203 			duk_heap_process_finalize_list(heap);
51204 		}
51205 #endif
51206 	} else {
51207 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);
51208 		DUK_HEAPHDR_SET_PREV(heap, root, hdr);
51209 
51210 		/* Object is now queued.  Because refzero_list was
51211 		 * non-NULL, it's already being processed by someone
51212 		 * in the C call stack, so we're done.
51213 		 */
51214 	}
51215 }
51216 
51217 #if defined(DUK_USE_FINALIZER_SUPPORT)
51218 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_refzero_check_fast(duk_hthread *thr) {
51219 	DUK_ASSERT(thr != NULL);
51220 	DUK_ASSERT(thr->heap != NULL);
51221 	DUK_ASSERT(thr->heap->refzero_list == NULL);  /* Processed to completion inline. */
51222 
51223 	if (DUK_UNLIKELY(thr->heap->finalize_list != NULL)) {
51224 		duk_heap_process_finalize_list(thr->heap);
51225 	}
51226 }
51227 
51228 DUK_INTERNAL void duk_refzero_check_slow(duk_hthread *thr) {
51229 	DUK_ASSERT(thr != NULL);
51230 	DUK_ASSERT(thr->heap != NULL);
51231 	DUK_ASSERT(thr->heap->refzero_list == NULL);  /* Processed to completion inline. */
51232 
51233 	if (DUK_UNLIKELY(thr->heap->finalize_list != NULL)) {
51234 		duk_heap_process_finalize_list(thr->heap);
51235 	}
51236 }
51237 #endif  /* DUK_USE_FINALIZER_SUPPORT */
51238 
51239 /*
51240  *  Refzero processing for duk_hstring.
51241  */
51242 
51243 DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hstring(duk_heap *heap, duk_hstring *str) {
51244 	DUK_ASSERT(heap != NULL);
51245 	DUK_ASSERT(heap->heap_thread != NULL);
51246 	DUK_ASSERT(str != NULL);
51247 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) str) == DUK_HTYPE_STRING);
51248 
51249 	duk_heap_strcache_string_remove(heap, str);
51250 	duk_heap_strtable_unlink(heap, str);
51251 	duk_free_hstring(heap, str);
51252 }
51253 
51254 /*
51255  *  Refzero processing for duk_hbuffer.
51256  */
51257 
51258 DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hbuffer(duk_heap *heap, duk_hbuffer *buf) {
51259 	DUK_ASSERT(heap != NULL);
51260 	DUK_ASSERT(heap->heap_thread != NULL);
51261 	DUK_ASSERT(buf != NULL);
51262 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) buf) == DUK_HTYPE_BUFFER);
51263 
51264 	DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap, (duk_heaphdr *) buf);
51265 	duk_free_hbuffer(heap, buf);
51266 }
51267 
51268 /*
51269  *  Incref and decref functions.
51270  *
51271  *  Decref may trigger immediate refzero handling, which may free and finalize
51272  *  an arbitrary number of objects (a "DECREF cascade").
51273  *
51274  *  Refzero handling is skipped entirely if (1) mark-and-sweep is running or
51275  *  (2) execution is paused in the debugger.  The objects are left in the heap,
51276  *  and will be freed by mark-and-sweep or eventual heap destruction.
51277  *
51278  *  This is necessary during mark-and-sweep because refcounts are also updated
51279  *  during the sweep phase (otherwise objects referenced by a swept object
51280  *  would have incorrect refcounts) which then calls here.  This could be
51281  *  avoided by using separate decref macros in mark-and-sweep; however,
51282  *  mark-and-sweep also calls finalizers which would use the ordinary decref
51283  *  macros anyway.
51284  *
51285  *  We can't process refzeros (= free objects) when the debugger is running
51286  *  as the debugger might make an object unreachable but still continue
51287  *  inspecting it (or even cause it to be pushed back).  So we must rely on
51288  *  mark-and-sweep to collect them.
51289  *
51290  *  The DUK__RZ_SUPPRESS_CHECK() condition is also used in heap destruction
51291  *  when running finalizers for remaining objects: the flag prevents objects
51292  *  from being moved around in heap linked lists while that's being done.
51293  *
51294  *  The suppress condition is important to performance.
51295  */
51296 
51297 #define DUK__RZ_SUPPRESS_ASSERT1() do { \
51298 		DUK_ASSERT(thr != NULL); \
51299 		DUK_ASSERT(thr->heap != NULL); \
51300 		/* When mark-and-sweep runs, heap_thread must exist. */ \
51301 		DUK_ASSERT(thr->heap->ms_running == 0 || thr->heap->heap_thread != NULL); \
51302 		/* When mark-and-sweep runs, the 'thr' argument always matches heap_thread. \
51303 		 * This could be used to e.g. suppress check against 'thr' directly (and \
51304 		 * knowing it would be heap_thread); not really used now. \
51305 		 */ \
51306 		DUK_ASSERT(thr->heap->ms_running == 0 || thr == thr->heap->heap_thread); \
51307 		/* We may be called when the heap is initializing and we process \
51308 		 * refzeros normally, but mark-and-sweep and finalizers are prevented \
51309 		 * if that's the case. \
51310 		 */ \
51311 		DUK_ASSERT(thr->heap->heap_initializing == 0 || thr->heap->ms_prevent_count > 0); \
51312 		DUK_ASSERT(thr->heap->heap_initializing == 0 || thr->heap->pf_prevent_count > 0); \
51313 	} while (0)
51314 
51315 #if defined(DUK_USE_DEBUGGER_SUPPORT)
51316 #define DUK__RZ_SUPPRESS_ASSERT2() do { \
51317 		/* When debugger is paused, ms_running is set. */ \
51318 		DUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || thr->heap->ms_running != 0); \
51319 	} while (0)
51320 #define DUK__RZ_SUPPRESS_COND()  (heap->ms_running != 0)
51321 #else
51322 #define DUK__RZ_SUPPRESS_ASSERT2() do { } while (0)
51323 #define DUK__RZ_SUPPRESS_COND()  (heap->ms_running != 0)
51324 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
51325 
51326 #define DUK__RZ_SUPPRESS_CHECK() do { \
51327 		DUK__RZ_SUPPRESS_ASSERT1(); \
51328 		DUK__RZ_SUPPRESS_ASSERT2(); \
51329 		if (DUK_UNLIKELY(DUK__RZ_SUPPRESS_COND())) { \
51330 			DUK_DDD(DUK_DDDPRINT("refzero handling suppressed (not even queued) when mark-and-sweep running, object: %p", (void *) h)); \
51331 			return; \
51332 		} \
51333 	} while (0)
51334 
51335 #define DUK__RZ_STRING() do { \
51336 		duk__refcount_refzero_hstring(heap, (duk_hstring *) h); \
51337 	} while (0)
51338 #define DUK__RZ_BUFFER() do { \
51339 		duk__refcount_refzero_hbuffer(heap, (duk_hbuffer *) h); \
51340 	} while (0)
51341 #define DUK__RZ_OBJECT() do { \
51342 		duk__refcount_refzero_hobject(heap, (duk_hobject *) h, skip_free_pending); \
51343 	} while (0)
51344 
51345 /* XXX: test the effect of inlining here vs. NOINLINE in refzero helpers */
51346 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
51347 #define DUK__RZ_INLINE DUK_ALWAYS_INLINE
51348 #else
51349 #define DUK__RZ_INLINE /*nop*/
51350 #endif
51351 
51352 DUK_LOCAL DUK__RZ_INLINE void duk__hstring_refzero_helper(duk_hthread *thr, duk_hstring *h) {
51353 	duk_heap *heap;
51354 
51355 	DUK_ASSERT(thr != NULL);
51356 	DUK_ASSERT(h != NULL);
51357 	heap = thr->heap;
51358 
51359 	DUK__RZ_SUPPRESS_CHECK();
51360 	DUK__RZ_STRING();
51361 }
51362 
51363 DUK_LOCAL DUK__RZ_INLINE void duk__hbuffer_refzero_helper(duk_hthread *thr, duk_hbuffer *h) {
51364 	duk_heap *heap;
51365 
51366 	DUK_ASSERT(thr != NULL);
51367 	DUK_ASSERT(h != NULL);
51368 	heap = thr->heap;
51369 
51370 	DUK__RZ_SUPPRESS_CHECK();
51371 	DUK__RZ_BUFFER();
51372 }
51373 
51374 DUK_LOCAL DUK__RZ_INLINE void duk__hobject_refzero_helper(duk_hthread *thr, duk_hobject *h, duk_bool_t skip_free_pending) {
51375 	duk_heap *heap;
51376 
51377 	DUK_ASSERT(thr != NULL);
51378 	DUK_ASSERT(h != NULL);
51379 	heap = thr->heap;
51380 
51381 	DUK__RZ_SUPPRESS_CHECK();
51382 	DUK__RZ_OBJECT();
51383 }
51384 
51385 DUK_LOCAL DUK__RZ_INLINE void duk__heaphdr_refzero_helper(duk_hthread *thr, duk_heaphdr *h, duk_bool_t skip_free_pending) {
51386 	duk_heap *heap;
51387 	duk_small_uint_t htype;
51388 
51389 	DUK_ASSERT(thr != NULL);
51390 	DUK_ASSERT(h != NULL);
51391 	heap = thr->heap;
51392 
51393 	htype = (duk_small_uint_t) DUK_HEAPHDR_GET_TYPE(h);
51394 	DUK__RZ_SUPPRESS_CHECK();
51395 
51396 	switch (htype) {
51397 	case DUK_HTYPE_STRING:
51398 		/* Strings have no internal references but do have "weak"
51399 		 * references in the string cache.  Also note that strings
51400 		 * are not on the heap_allocated list like other heap
51401 		 * elements.
51402 		 */
51403 
51404 		DUK__RZ_STRING();
51405 		break;
51406 
51407 	case DUK_HTYPE_OBJECT:
51408 		/* Objects have internal references.  Must finalize through
51409 		 * the "refzero" work list.
51410 		 */
51411 
51412 		DUK__RZ_OBJECT();
51413 		break;
51414 
51415 	default:
51416 		/* Buffers have no internal references.  However, a dynamic
51417 		 * buffer has a separate allocation for the buffer.  This is
51418 		 * freed by duk_heap_free_heaphdr_raw().
51419 		 */
51420 
51421 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(h) == DUK_HTYPE_BUFFER);
51422 		DUK__RZ_BUFFER();
51423 		break;
51424 	}
51425 }
51426 
51427 DUK_INTERNAL DUK_NOINLINE void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h) {
51428 	duk__heaphdr_refzero_helper(thr, h, 0 /*skip_free_pending*/);
51429 }
51430 
51431 DUK_INTERNAL DUK_NOINLINE void duk_heaphdr_refzero_norz(duk_hthread *thr, duk_heaphdr *h) {
51432 	duk__heaphdr_refzero_helper(thr, h, 1 /*skip_free_pending*/);
51433 }
51434 
51435 DUK_INTERNAL DUK_NOINLINE void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h) {
51436 	duk__hstring_refzero_helper(thr, h);
51437 }
51438 
51439 DUK_INTERNAL DUK_NOINLINE void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h) {
51440 	duk__hbuffer_refzero_helper(thr, h);
51441 }
51442 
51443 DUK_INTERNAL DUK_NOINLINE void duk_hobject_refzero(duk_hthread *thr, duk_hobject *h) {
51444 	duk__hobject_refzero_helper(thr, h, 0 /*skip_free_pending*/);
51445 }
51446 
51447 DUK_INTERNAL DUK_NOINLINE void duk_hobject_refzero_norz(duk_hthread *thr, duk_hobject *h) {
51448 	duk__hobject_refzero_helper(thr, h, 1 /*skip_free_pending*/);
51449 }
51450 
51451 #if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
51452 DUK_INTERNAL void duk_tval_incref(duk_tval *tv) {
51453 	DUK_ASSERT(tv != NULL);
51454 
51455 	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
51456 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
51457 		DUK_ASSERT(h != NULL);
51458 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
51459 		DUK_ASSERT_DISABLE(h->h_refcount >= 0);
51460 		DUK_HEAPHDR_PREINC_REFCOUNT(h);
51461 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) != 0);  /* No wrapping. */
51462 	}
51463 }
51464 
51465 DUK_INTERNAL void duk_tval_decref(duk_hthread *thr, duk_tval *tv) {
51466 	DUK_ASSERT(thr != NULL);
51467 	DUK_ASSERT(tv != NULL);
51468 
51469 	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
51470 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
51471 		DUK_ASSERT(h != NULL);
51472 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
51473 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);
51474 #if 0
51475 		if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
51476 			return;
51477 		}
51478 		duk_heaphdr_refzero(thr, h);
51479 #else
51480 		duk_heaphdr_decref(thr, h);
51481 #endif
51482 	}
51483 }
51484 
51485 DUK_INTERNAL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv) {
51486 	DUK_ASSERT(thr != NULL);
51487 	DUK_ASSERT(tv != NULL);
51488 
51489 	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
51490 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
51491 		DUK_ASSERT(h != NULL);
51492 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
51493 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);
51494 #if 0
51495 		if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
51496 			return;
51497 		}
51498 		duk_heaphdr_refzero_norz(thr, h);
51499 #else
51500 		duk_heaphdr_decref_norz(thr, h);
51501 #endif
51502 	}
51503 }
51504 #endif  /* !DUK_USE_FAST_REFCOUNT_DEFAULT */
51505 
51506 #define DUK__DECREF_ASSERTS() do { \
51507 		DUK_ASSERT(thr != NULL); \
51508 		DUK_ASSERT(thr->heap != NULL); \
51509 		DUK_ASSERT(h != NULL); \
51510 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID((duk_heaphdr *) h)); \
51511 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) >= 1); \
51512 	} while (0)
51513 #if defined(DUK_USE_ROM_OBJECTS)
51514 #define DUK__INCREF_SHARED() do { \
51515 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
51516 			return; \
51517 		} \
51518 		DUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \
51519 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) != 0);  /* No wrapping. */ \
51520 	} while (0)
51521 #define DUK__DECREF_SHARED() do { \
51522 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
51523 			return; \
51524 		} \
51525 		if (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \
51526 			return; \
51527 		} \
51528 	} while (0)
51529 #else
51530 #define DUK__INCREF_SHARED() do { \
51531 		DUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \
51532 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) != 0);  /* No wrapping. */ \
51533 	} while (0)
51534 #define DUK__DECREF_SHARED() do { \
51535 		if (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \
51536 			return; \
51537 		} \
51538 	} while (0)
51539 #endif
51540 
51541 #if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
51542 /* This will in practice be inlined because it's just an INC instructions
51543  * and a bit test + INC when ROM objects are enabled.
51544  */
51545 DUK_INTERNAL void duk_heaphdr_incref(duk_heaphdr *h) {
51546 	DUK_ASSERT(h != NULL);
51547 	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
51548 	DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);
51549 
51550 	DUK__INCREF_SHARED();
51551 }
51552 
51553 DUK_INTERNAL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h) {
51554 	DUK__DECREF_ASSERTS();
51555 	DUK__DECREF_SHARED();
51556 	duk_heaphdr_refzero(thr, h);
51557 
51558 	/* Forced mark-and-sweep when GC torture enabled; this could happen
51559 	 * on any DECREF (but not DECREF_NORZ).
51560 	 */
51561 	DUK_GC_TORTURE(thr->heap);
51562 }
51563 DUK_INTERNAL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h) {
51564 	DUK__DECREF_ASSERTS();
51565 	DUK__DECREF_SHARED();
51566 	duk_heaphdr_refzero_norz(thr, h);
51567 }
51568 #endif  /* !DUK_USE_FAST_REFCOUNT_DEFAULT */
51569 
51570 #if 0  /* Not needed. */
51571 DUK_INTERNAL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h) {
51572 	DUK__DECREF_ASSERTS();
51573 	DUK__DECREF_SHARED();
51574 	duk_hstring_refzero(thr, h);
51575 }
51576 DUK_INTERNAL void duk_hstring_decref_norz(duk_hthread *thr, duk_hstring *h) {
51577 	DUK__DECREF_ASSERTS();
51578 	DUK__DECREF_SHARED();
51579 	duk_hstring_refzero_norz(thr, h);
51580 }
51581 DUK_INTERNAL void duk_hbuffer_decref(duk_hthread *thr, duk_hbuffer *h) {
51582 	DUK__DECREF_ASSERTS();
51583 	DUK__DECREF_SHARED();
51584 	duk_hbuffer_refzero(thr, h);
51585 }
51586 DUK_INTERNAL void duk_hbuffer_decref_norz(duk_hthread *thr, duk_hbuffer *h) {
51587 	DUK__DECREF_ASSERTS();
51588 	DUK__DECREF_SHARED();
51589 	duk_hbuffer_refzero_norz(thr, h);
51590 }
51591 DUK_INTERNAL void duk_hobject_decref(duk_hthread *thr, duk_hobject *h) {
51592 	DUK__DECREF_ASSERTS();
51593 	DUK__DECREF_SHARED();
51594 	duk_hobject_refzero(thr, h);
51595 }
51596 DUK_INTERNAL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h) {
51597 	DUK__DECREF_ASSERTS();
51598 	DUK__DECREF_SHARED();
51599 	duk_hobject_refzero_norz(thr, h);
51600 }
51601 #endif
51602 
51603 #else  /* DUK_USE_REFERENCE_COUNTING */
51604 
51605 /* no refcounting */
51606 
51607 #endif  /* DUK_USE_REFERENCE_COUNTING */
51608 
51609 /* automatic undefs */
51610 #undef DUK__DECREF_ASSERTS
51611 #undef DUK__DECREF_SHARED
51612 #undef DUK__INCREF_SHARED
51613 #undef DUK__RZ_BUFFER
51614 #undef DUK__RZ_INLINE
51615 #undef DUK__RZ_OBJECT
51616 #undef DUK__RZ_STRING
51617 #undef DUK__RZ_SUPPRESS_ASSERT1
51618 #undef DUK__RZ_SUPPRESS_ASSERT2
51619 #undef DUK__RZ_SUPPRESS_CHECK
51620 #undef DUK__RZ_SUPPRESS_COND
51621 #line 1 "duk_heap_stringcache.c"
51622 /*
51623  *  String cache.
51624  *
51625  *  Provides a cache to optimize indexed string lookups.  The cache keeps
51626  *  track of (byte offset, char offset) states for a fixed number of strings.
51627  *  Otherwise we'd need to scan from either end of the string, as we store
51628  *  strings in (extended) UTF-8.
51629  */
51630 
51631 /* #include duk_internal.h -> already included */
51632 
51633 /*
51634  *  Delete references to given hstring from the heap string cache.
51635  *
51636  *  String cache references are 'weak': they are not counted towards
51637  *  reference counts, nor serve as roots for mark-and-sweep.  When an
51638  *  object is about to be freed, such references need to be removed.
51639  */
51640 
51641 DUK_INTERNAL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h) {
51642 	duk_uint_t i;
51643 	for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
51644 		duk_strcache_entry *c = heap->strcache + i;
51645 		if (c->h == h) {
51646 			DUK_DD(DUK_DDPRINT("deleting weak strcache reference to hstring %p from heap %p",
51647 			                   (void *) h, (void *) heap));
51648 			c->h = NULL;
51649 
51650 			/* XXX: the string shouldn't appear twice, but we now loop to the
51651 			 * end anyway; if fixed, add a looping assertion to ensure there
51652 			 * is no duplicate.
51653 			 */
51654 		}
51655 	}
51656 }
51657 
51658 /*
51659  *  String scanning helpers
51660  *
51661  *  All bytes other than UTF-8 continuation bytes ([0x80,0xbf]) are
51662  *  considered to contribute a character.  This must match how string
51663  *  character length is computed.
51664  */
51665 
51666 DUK_LOCAL const duk_uint8_t *duk__scan_forwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
51667 	while (n > 0) {
51668 		for (;;) {
51669 			p++;
51670 			if (p >= q) {
51671 				return NULL;
51672 			}
51673 			if ((*p & 0xc0) != 0x80) {
51674 				break;
51675 			}
51676 		}
51677 		n--;
51678 	}
51679 	return p;
51680 }
51681 
51682 DUK_LOCAL const duk_uint8_t *duk__scan_backwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
51683 	while (n > 0) {
51684 		for (;;) {
51685 			p--;
51686 			if (p < q) {
51687 				return NULL;
51688 			}
51689 			if ((*p & 0xc0) != 0x80) {
51690 				break;
51691 			}
51692 		}
51693 		n--;
51694 	}
51695 	return p;
51696 }
51697 
51698 /*
51699  *  Convert char offset to byte offset
51700  *
51701  *  Avoid using the string cache if possible: for ASCII strings byte and
51702  *  char offsets are equal and for short strings direct scanning may be
51703  *  better than using the string cache (which may evict a more important
51704  *  entry).
51705  *
51706  *  Typing now assumes 32-bit string byte/char offsets (duk_uint_fast32_t).
51707  *  Better typing might be to use duk_size_t.
51708  *
51709  *  Caller should ensure 'char_offset' is within the string bounds [0,charlen]
51710  *  (endpoint is inclusive).  If this is not the case, no memory unsafe
51711  *  behavior will happen but an error will be thrown.
51712  */
51713 
51714 DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset) {
51715 	duk_heap *heap;
51716 	duk_strcache_entry *sce;
51717 	duk_uint_fast32_t byte_offset;
51718 	duk_uint_t i;
51719 	duk_bool_t use_cache;
51720 	duk_uint_fast32_t dist_start, dist_end, dist_sce;
51721 	duk_uint_fast32_t char_length;
51722 	const duk_uint8_t *p_start;
51723 	const duk_uint8_t *p_end;
51724 	const duk_uint8_t *p_found;
51725 
51726 	/*
51727 	 *  For ASCII strings, the answer is simple.
51728 	 */
51729 
51730 	if (DUK_LIKELY(DUK_HSTRING_IS_ASCII(h))) {
51731 		return char_offset;
51732 	}
51733 
51734 	char_length = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h);
51735 	DUK_ASSERT(char_offset <= char_length);
51736 
51737 	if (DUK_LIKELY(DUK_HSTRING_IS_ASCII(h))) {
51738 		/* Must recheck because the 'is ascii' flag may be set
51739 		 * lazily.  Alternatively, we could just compare charlen
51740 		 * to bytelen.
51741 		 */
51742 		return char_offset;
51743 	}
51744 
51745 	/*
51746 	 *  For non-ASCII strings, we need to scan forwards or backwards
51747 	 *  from some starting point.  The starting point may be the start
51748 	 *  or end of the string, or some cached midpoint in the string
51749 	 *  cache.
51750 	 *
51751 	 *  For "short" strings we simply scan without checking or updating
51752 	 *  the cache.  For longer strings we check and update the cache as
51753 	 *  necessary, inserting a new cache entry if none exists.
51754 	 */
51755 
51756 	DUK_DDD(DUK_DDDPRINT("non-ascii string %p, char_offset=%ld, clen=%ld, blen=%ld",
51757 	                     (void *) h, (long) char_offset,
51758 	                     (long) DUK_HSTRING_GET_CHARLEN(h),
51759 	                     (long) DUK_HSTRING_GET_BYTELEN(h)));
51760 
51761 	heap = thr->heap;
51762 	sce = NULL;
51763 	use_cache = (char_length > DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT);
51764 
51765 	if (use_cache) {
51766 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
51767 		DUK_DDD(DUK_DDDPRINT("stringcache before char2byte (using cache):"));
51768 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
51769 			duk_strcache_entry *c = heap->strcache + i;
51770 			DUK_DDD(DUK_DDDPRINT("  [%ld] -> h=%p, cidx=%ld, bidx=%ld",
51771 			                     (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
51772 		}
51773 #endif
51774 
51775 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
51776 			duk_strcache_entry *c = heap->strcache + i;
51777 
51778 			if (c->h == h) {
51779 				sce = c;
51780 				break;
51781 			}
51782 		}
51783 	}
51784 
51785 	/*
51786 	 *  Scan from shortest distance:
51787 	 *    - start of string
51788 	 *    - end of string
51789 	 *    - cache entry (if exists)
51790 	 */
51791 
51792 	DUK_ASSERT(DUK_HSTRING_GET_CHARLEN(h) >= char_offset);
51793 	dist_start = char_offset;
51794 	dist_end = char_length - char_offset;
51795 	dist_sce = 0; DUK_UNREF(dist_sce);  /* initialize for debug prints, needed if sce==NULL */
51796 
51797 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
51798 	p_end = (const duk_uint8_t *) (p_start + DUK_HSTRING_GET_BYTELEN(h));
51799 	p_found = NULL;
51800 
51801 	if (sce) {
51802 		if (char_offset >= sce->cidx) {
51803 			dist_sce = char_offset - sce->cidx;
51804 			if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
51805 				DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
51806 				                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
51807 				                     "scan forwards from sce",
51808 				                     (long) use_cache, (void *) (sce ? sce->h : NULL),
51809 				                     (sce ? (long) sce->cidx : (long) -1),
51810 				                     (sce ? (long) sce->bidx : (long) -1),
51811 				                     (long) dist_start, (long) dist_end, (long) dist_sce));
51812 
51813 				p_found = duk__scan_forwards(p_start + sce->bidx,
51814 				                             p_end,
51815 				                             dist_sce);
51816 				goto scan_done;
51817 			}
51818 		} else {
51819 			dist_sce = sce->cidx - char_offset;
51820 			if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
51821 				DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
51822 				                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
51823 				                     "scan backwards from sce",
51824 				                     (long) use_cache, (void *) (sce ? sce->h : NULL),
51825 				                     (sce ? (long) sce->cidx : (long) -1),
51826 				                     (sce ? (long) sce->bidx : (long) -1),
51827 				                     (long) dist_start, (long) dist_end, (long) dist_sce));
51828 
51829 				p_found = duk__scan_backwards(p_start + sce->bidx,
51830 				                              p_start,
51831 				                              dist_sce);
51832 				goto scan_done;
51833 			}
51834 		}
51835 	}
51836 
51837 	/* no sce, or sce scan not best */
51838 
51839 	if (dist_start <= dist_end) {
51840 		DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
51841 		                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
51842 		                     "scan forwards from string start",
51843 		                     (long) use_cache, (void *) (sce ? sce->h : NULL),
51844 		                     (sce ? (long) sce->cidx : (long) -1),
51845 		                     (sce ? (long) sce->bidx : (long) -1),
51846 		                     (long) dist_start, (long) dist_end, (long) dist_sce));
51847 
51848 		p_found = duk__scan_forwards(p_start,
51849 		                             p_end,
51850 		                             dist_start);
51851 	} else {
51852 		DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
51853 		                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
51854 		                     "scan backwards from string end",
51855 		                     (long) use_cache, (void *) (sce ? sce->h : NULL),
51856 		                     (sce ? (long) sce->cidx : (long) -1),
51857 		                     (sce ? (long) sce->bidx : (long) -1),
51858 		                     (long) dist_start, (long) dist_end, (long) dist_sce));
51859 
51860 		p_found = duk__scan_backwards(p_end,
51861 		                              p_start,
51862 		                              dist_end);
51863 	}
51864 
51865  scan_done:
51866 
51867 	if (DUK_UNLIKELY(p_found == NULL)) {
51868 		/* Scan error: this shouldn't normally happen; it could happen if
51869 		 * string is not valid UTF-8 data, and clen/blen are not consistent
51870 		 * with the scanning algorithm.
51871 		 */
51872 		goto scan_error;
51873 	}
51874 
51875 	DUK_ASSERT(p_found >= p_start);
51876 	DUK_ASSERT(p_found <= p_end);  /* may be equal */
51877 	byte_offset = (duk_uint32_t) (p_found - p_start);
51878 
51879 	DUK_DDD(DUK_DDDPRINT("-> string %p, cidx %ld -> bidx %ld",
51880 	                     (void *) h, (long) char_offset, (long) byte_offset));
51881 
51882 	/*
51883 	 *  Update cache entry (allocating if necessary), and move the
51884 	 *  cache entry to the first place (in an "LRU" policy).
51885 	 */
51886 
51887 	if (use_cache) {
51888 		/* update entry, allocating if necessary */
51889 		if (!sce) {
51890 			sce = heap->strcache + DUK_HEAP_STRCACHE_SIZE - 1;  /* take last entry */
51891 			sce->h = h;
51892 		}
51893 		DUK_ASSERT(sce != NULL);
51894 		sce->bidx = (duk_uint32_t) (p_found - p_start);
51895 		sce->cidx = (duk_uint32_t) char_offset;
51896 
51897 		/* LRU: move our entry to first */
51898 		if (sce > &heap->strcache[0]) {
51899 			/*
51900 			 *   A                  C
51901 			 *   B                  A
51902 			 *   C <- sce    ==>    B
51903 			 *   D                  D
51904 			 */
51905 			duk_strcache_entry tmp;
51906 
51907 			tmp = *sce;
51908 			duk_memmove((void *) (&heap->strcache[1]),
51909 			            (const void *) (&heap->strcache[0]),
51910 			            (size_t) (((char *) sce) - ((char *) &heap->strcache[0])));
51911 			heap->strcache[0] = tmp;
51912 
51913 			/* 'sce' points to the wrong entry here, but is no longer used */
51914 		}
51915 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
51916 		DUK_DDD(DUK_DDDPRINT("stringcache after char2byte (using cache):"));
51917 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
51918 			duk_strcache_entry *c = heap->strcache + i;
51919 			DUK_DDD(DUK_DDDPRINT("  [%ld] -> h=%p, cidx=%ld, bidx=%ld",
51920 			                     (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
51921 		}
51922 #endif
51923 	}
51924 
51925 	return byte_offset;
51926 
51927  scan_error:
51928 	DUK_ERROR_INTERNAL(thr);
51929 	DUK_WO_NORETURN(return 0;);
51930 }
51931 #line 1 "duk_heap_stringtable.c"
51932 /*
51933  *  Heap string table handling, string interning.
51934  */
51935 
51936 /* #include duk_internal.h -> already included */
51937 
51938 /* Resize checks not needed if minsize == maxsize, typical for low memory
51939  * targets.
51940  */
51941 #define DUK__STRTAB_RESIZE_CHECK
51942 #if (DUK_USE_STRTAB_MINSIZE == DUK_USE_STRTAB_MAXSIZE)
51943 #undef DUK__STRTAB_RESIZE_CHECK
51944 #endif
51945 
51946 #if defined(DUK_USE_STRTAB_PTRCOMP)
51947 #define DUK__HEAPPTR_ENC16(heap,ptr)    DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (ptr))
51948 #define DUK__HEAPPTR_DEC16(heap,val)    DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (val))
51949 #define DUK__GET_STRTABLE(heap)         ((heap)->strtable16)
51950 #else
51951 #define DUK__HEAPPTR_ENC16(heap,ptr)    (ptr)
51952 #define DUK__HEAPPTR_DEC16(heap,val)    (val)
51953 #define DUK__GET_STRTABLE(heap)         ((heap)->strtable)
51954 #endif
51955 
51956 #define DUK__STRTAB_U32_MAX_STRLEN      10               /* 4'294'967'295 */
51957 
51958 /*
51959  *  Debug dump stringtable.
51960  */
51961 
51962 #if defined(DUK_USE_DEBUG)
51963 DUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap) {
51964 #if defined(DUK_USE_STRTAB_PTRCOMP)
51965 	duk_uint16_t *strtable;
51966 #else
51967 	duk_hstring **strtable;
51968 #endif
51969 	duk_uint32_t i;
51970 	duk_hstring *h;
51971 	duk_size_t count_total = 0;
51972 	duk_size_t count_chain;
51973 	duk_size_t count_chain_min = DUK_SIZE_MAX;
51974 	duk_size_t count_chain_max = 0;
51975 	duk_size_t count_len[8];  /* chain lengths from 0 to 7 */
51976 
51977 	if (heap == NULL) {
51978 		DUK_D(DUK_DPRINT("string table, heap=NULL"));
51979 		return;
51980 	}
51981 
51982 	strtable = DUK__GET_STRTABLE(heap);
51983 	if (strtable == NULL) {
51984 		DUK_D(DUK_DPRINT("string table, strtab=NULL"));
51985 		return;
51986 	}
51987 
51988 	duk_memzero((void *) count_len, sizeof(count_len));
51989 	for (i = 0; i < heap->st_size; i++) {
51990 		h = DUK__HEAPPTR_DEC16(heap, strtable[i]);
51991 		count_chain = 0;
51992 		while (h != NULL) {
51993 			count_chain++;
51994 			h = h->hdr.h_next;
51995 		}
51996 		if (count_chain < sizeof(count_len) / sizeof(duk_size_t)) {
51997 			count_len[count_chain]++;
51998 		}
51999 		count_chain_max = (count_chain > count_chain_max ? count_chain : count_chain_max);
52000 		count_chain_min = (count_chain < count_chain_min ? count_chain : count_chain_min);
52001 		count_total += count_chain;
52002 	}
52003 
52004 	DUK_D(DUK_DPRINT("string table, strtab=%p, count=%lu, chain min=%lu max=%lu avg=%lf: "
52005 	                 "counts: %lu %lu %lu %lu %lu %lu %lu %lu ...",
52006 	                 (void *) heap->strtable, (unsigned long) count_total,
52007 	                 (unsigned long) count_chain_min, (unsigned long) count_chain_max,
52008 	                 (double) count_total / (double) heap->st_size,
52009 	                 (unsigned long) count_len[0], (unsigned long) count_len[1],
52010 	                 (unsigned long) count_len[2], (unsigned long) count_len[3],
52011 	                 (unsigned long) count_len[4], (unsigned long) count_len[5],
52012 	                 (unsigned long) count_len[6], (unsigned long) count_len[7]));
52013 }
52014 #endif  /* DUK_USE_DEBUG */
52015 
52016 /*
52017  *  Assertion helper to ensure strtable is populated correctly.
52018  */
52019 
52020 #if defined(DUK_USE_ASSERTIONS)
52021 DUK_LOCAL void duk__strtable_assert_checks(duk_heap *heap) {
52022 #if defined(DUK_USE_STRTAB_PTRCOMP)
52023 	duk_uint16_t *strtable;
52024 #else
52025 	duk_hstring **strtable;
52026 #endif
52027 	duk_uint32_t i;
52028 	duk_hstring *h;
52029 	duk_size_t count = 0;
52030 
52031 	DUK_ASSERT(heap != NULL);
52032 
52033 	strtable = DUK__GET_STRTABLE(heap);
52034 	if (strtable != NULL) {
52035 		DUK_ASSERT(heap->st_size != 0);
52036 		DUK_ASSERT(heap->st_mask == heap->st_size - 1);
52037 
52038 		for (i = 0; i < heap->st_size; i++) {
52039 			h = DUK__HEAPPTR_DEC16(heap, strtable[i]);
52040 			while (h != NULL) {
52041 				DUK_ASSERT((DUK_HSTRING_GET_HASH(h) & heap->st_mask) == i);
52042 				count++;
52043 				h = h->hdr.h_next;
52044 			}
52045 		}
52046 	} else {
52047 		DUK_ASSERT(heap->st_size == 0);
52048 		DUK_ASSERT(heap->st_mask == 0);
52049 	}
52050 
52051 #if defined(DUK__STRTAB_RESIZE_CHECK)
52052 	DUK_ASSERT(count == (duk_size_t) heap->st_count);
52053 #endif
52054 }
52055 #endif  /* DUK_USE_ASSERTIONS */
52056 
52057 /*
52058  *  Allocate and initialize a duk_hstring.
52059  *
52060  *  Returns a NULL if allocation or initialization fails for some reason.
52061  *
52062  *  The string won't be inserted into the string table and isn't tracked in
52063  *  any way (link pointers will be NULL).  The caller must place the string
52064  *  into the string table without any risk of a longjmp, otherwise the string
52065  *  is leaked.
52066  */
52067 
52068 DUK_LOCAL duk_hstring *duk__strtable_alloc_hstring(duk_heap *heap,
52069                                                    const duk_uint8_t *str,
52070                                                    duk_uint32_t blen,
52071                                                    duk_uint32_t strhash,
52072                                                    const duk_uint8_t *extdata) {
52073 	duk_hstring *res;
52074 	const duk_uint8_t *data;
52075 #if !defined(DUK_USE_HSTRING_ARRIDX)
52076 	duk_uarridx_t dummy;
52077 #endif
52078 
52079 	DUK_ASSERT(heap != NULL);
52080 	DUK_UNREF(extdata);
52081 
52082 #if defined(DUK_USE_STRLEN16)
52083 	/* If blen <= 0xffffUL, clen is also guaranteed to be <= 0xffffUL. */
52084 	if (blen > 0xffffUL) {
52085 		DUK_D(DUK_DPRINT("16-bit string blen/clen active and blen over 16 bits, reject intern"));
52086 		goto alloc_error;
52087 	}
52088 #endif
52089 
52090 	/* XXX: Memzeroing the allocated structure is not really necessary
52091 	 * because we could just initialize all fields explicitly (almost
52092 	 * all fields are initialized explicitly anyway).
52093 	 */
52094 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
52095 	if (extdata) {
52096 		res = (duk_hstring *) DUK_ALLOC(heap, sizeof(duk_hstring_external));
52097 		if (DUK_UNLIKELY(res == NULL)) {
52098 			goto alloc_error;
52099 		}
52100 		duk_memzero(res, sizeof(duk_hstring_external));
52101 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
52102 		DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
52103 #endif
52104 		DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, DUK_HSTRING_FLAG_EXTDATA);
52105 
52106 		DUK_ASSERT(extdata[blen] == 0);  /* Application responsibility. */
52107 		data = extdata;
52108 		((duk_hstring_external *) res)->extdata = extdata;
52109 	} else
52110 #endif  /* DUK_USE_HSTRING_EXTDATA && DUK_USE_EXTSTR_INTERN_CHECK */
52111 	{
52112 		duk_uint8_t *data_tmp;
52113 
52114 		/* NUL terminate for convenient C access */
52115 		DUK_ASSERT(sizeof(duk_hstring) + blen + 1 > blen);  /* No wrap, limits ensure. */
52116 		res = (duk_hstring *) DUK_ALLOC(heap, sizeof(duk_hstring) + blen + 1);
52117 		if (DUK_UNLIKELY(res == NULL)) {
52118 			goto alloc_error;
52119 		}
52120 		duk_memzero(res, sizeof(duk_hstring));
52121 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
52122 		DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
52123 #endif
52124 		DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0);
52125 
52126 		data_tmp = (duk_uint8_t *) (res + 1);
52127 		duk_memcpy(data_tmp, str, blen);
52128 		data_tmp[blen] = (duk_uint8_t) 0;
52129 		data = (const duk_uint8_t *) data_tmp;
52130 	}
52131 
52132 	DUK_HSTRING_SET_BYTELEN(res, blen);
52133 	DUK_HSTRING_SET_HASH(res, strhash);
52134 
52135 	DUK_ASSERT(!DUK_HSTRING_HAS_ARRIDX(res));
52136 #if defined(DUK_USE_HSTRING_ARRIDX)
52137 	res->arridx = duk_js_to_arrayindex_string(data, blen);
52138 	if (res->arridx != DUK_HSTRING_NO_ARRAY_INDEX) {
52139 #else
52140 	dummy = duk_js_to_arrayindex_string(data, blen);
52141 	if (dummy != DUK_HSTRING_NO_ARRAY_INDEX) {
52142 #endif
52143 		/* Array index strings cannot be symbol strings,
52144 		 * and they're always pure ASCII so blen == clen.
52145 		 */
52146 		DUK_HSTRING_SET_ARRIDX(res);
52147 		DUK_HSTRING_SET_ASCII(res);
52148 		DUK_ASSERT(duk_unicode_unvalidated_utf8_length(data, (duk_size_t) blen) == blen);
52149 	} else {
52150 		/* Because 'data' is NUL-terminated, we don't need a
52151 		 * blen > 0 check here.  For NUL (0x00) the symbol
52152 		 * checks will be false.
52153 		 */
52154 		if (DUK_UNLIKELY(data[0] >= 0x80U)) {
52155 			if (data[0] <= 0x81) {
52156 				DUK_HSTRING_SET_SYMBOL(res);
52157 			} else if (data[0] == 0x82U || data[0] == 0xffU) {
52158 				DUK_HSTRING_SET_HIDDEN(res);
52159 				DUK_HSTRING_SET_SYMBOL(res);
52160 			}
52161 		}
52162 
52163 		/* Using an explicit 'ASCII' flag has larger footprint (one call site
52164 		 * only) but is quite useful for the case when there's no explicit
52165 		 * 'clen' in duk_hstring.
52166 		 *
52167 		 * The flag is set lazily for RAM strings.
52168 		 */
52169 		DUK_ASSERT(!DUK_HSTRING_HAS_ASCII(res));
52170 
52171 #if defined(DUK_USE_HSTRING_LAZY_CLEN)
52172 		/* Charlen initialized to 0, updated on-the-fly. */
52173 #else
52174 		duk_hstring_init_charlen(res);  /* Also sets ASCII flag. */
52175 #endif
52176 	}
52177 
52178 	DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08lx, blen=%ld, has_arridx=%ld, has_extdata=%ld",
52179 	                     (unsigned long) DUK_HSTRING_GET_HASH(res),
52180 	                     (long) DUK_HSTRING_GET_BYTELEN(res),
52181 	                     (long) (DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0),
52182 	                     (long) (DUK_HSTRING_HAS_EXTDATA(res) ? 1 : 0)));
52183 
52184 	DUK_ASSERT(res != NULL);
52185 	return res;
52186 
52187  alloc_error:
52188 	return NULL;
52189 }
52190 
52191 /*
52192  *  Grow strtable allocation in-place.
52193  */
52194 
52195 #if defined(DUK__STRTAB_RESIZE_CHECK)
52196 DUK_LOCAL void duk__strtable_grow_inplace(duk_heap *heap) {
52197 	duk_uint32_t new_st_size;
52198 	duk_uint32_t old_st_size;
52199 	duk_uint32_t i;
52200 	duk_hstring *h;
52201 	duk_hstring *next;
52202 	duk_hstring *prev;
52203 #if defined(DUK_USE_STRTAB_PTRCOMP)
52204 	duk_uint16_t *new_ptr;
52205 	duk_uint16_t *new_ptr_high;
52206 #else
52207 	duk_hstring **new_ptr;
52208 	duk_hstring **new_ptr_high;
52209 #endif
52210 
52211 	DUK_DD(DUK_DDPRINT("grow in-place: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size * 2));
52212 
52213 	DUK_ASSERT(heap != NULL);
52214 	DUK_ASSERT(heap->st_resizing == 1);
52215 	DUK_ASSERT(heap->st_size >= 2);
52216 	DUK_ASSERT((heap->st_size & (heap->st_size - 1)) == 0);  /* 2^N */
52217 	DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
52218 
52219 	DUK_STATS_INC(heap, stats_strtab_resize_grow);
52220 
52221 	new_st_size = heap->st_size << 1U;
52222 	DUK_ASSERT(new_st_size > heap->st_size);  /* No overflow. */
52223 
52224 	/* Reallocate the strtable first and then work in-place to rehash
52225 	 * strings.  We don't need an indirect allocation here: even if GC
52226 	 * is triggered to satisfy the allocation, recursive strtable resize
52227 	 * is prevented by flags.  This is also why we don't need to use
52228 	 * DUK_REALLOC_INDIRECT().
52229 	 */
52230 
52231 #if defined(DUK_USE_STRTAB_PTRCOMP)
52232 	new_ptr = (duk_uint16_t *) DUK_REALLOC(heap, heap->strtable16, sizeof(duk_uint16_t) * new_st_size);
52233 #else
52234 	new_ptr = (duk_hstring **) DUK_REALLOC(heap, heap->strtable, sizeof(duk_hstring *) * new_st_size);
52235 #endif
52236 	if (DUK_UNLIKELY(new_ptr == NULL)) {
52237 		/* If realloc fails we can continue normally: the string table
52238 		 * won't "fill up" although chains will gradually get longer.
52239 		 * When string insertions continue, we'll quite soon try again
52240 		 * with no special handling.
52241 		 */
52242 		DUK_D(DUK_DPRINT("string table grow failed, ignoring"));
52243 		return;
52244 	}
52245 #if defined(DUK_USE_STRTAB_PTRCOMP)
52246 	heap->strtable16 = new_ptr;
52247 #else
52248 	heap->strtable = new_ptr;
52249 #endif
52250 
52251 	/* Rehash a single bucket into two separate ones.  When we grow
52252 	 * by x2 the highest 'new' bit determines whether a string remains
52253 	 * in its old position (bit is 0) or goes to a new one (bit is 1).
52254 	 */
52255 
52256 	old_st_size = heap->st_size;
52257 	new_ptr_high = new_ptr + old_st_size;
52258 	for (i = 0; i < old_st_size; i++) {
52259 		duk_hstring *new_root;
52260 		duk_hstring *new_root_high;
52261 
52262 		h = DUK__HEAPPTR_DEC16(heap, new_ptr[i]);
52263 		new_root = h;
52264 		new_root_high = NULL;
52265 
52266 		prev = NULL;
52267 		while (h != NULL) {
52268 			duk_uint32_t mask;
52269 
52270 			DUK_ASSERT((DUK_HSTRING_GET_HASH(h) & heap->st_mask) == i);
52271 			next = h->hdr.h_next;
52272 
52273 			/* Example: if previous size was 256, previous mask is 0xFF
52274 			 * and size is 0x100 which corresponds to the new bit that
52275 			 * comes into play.
52276 			 */
52277 			DUK_ASSERT(heap->st_mask == old_st_size - 1);
52278 			mask = old_st_size;
52279 			if (DUK_HSTRING_GET_HASH(h) & mask) {
52280 				if (prev != NULL) {
52281 					prev->hdr.h_next = h->hdr.h_next;
52282 				} else {
52283 					DUK_ASSERT(h == new_root);
52284 					new_root = h->hdr.h_next;
52285 				}
52286 
52287 				h->hdr.h_next = new_root_high;
52288 				new_root_high = h;
52289 			} else {
52290 				prev = h;
52291 			}
52292 			h = next;
52293 		}
52294 
52295 		new_ptr[i] = DUK__HEAPPTR_ENC16(heap, new_root);
52296 		new_ptr_high[i] = DUK__HEAPPTR_ENC16(heap, new_root_high);
52297 	}
52298 
52299 	heap->st_size = new_st_size;
52300 	heap->st_mask = new_st_size - 1;
52301 
52302 #if defined(DUK_USE_ASSERTIONS)
52303 	duk__strtable_assert_checks(heap);
52304 #endif
52305 }
52306 #endif  /* DUK__STRTAB_RESIZE_CHECK */
52307 
52308 /*
52309  *  Shrink strtable allocation in-place.
52310  */
52311 
52312 #if defined(DUK__STRTAB_RESIZE_CHECK)
52313 DUK_LOCAL void duk__strtable_shrink_inplace(duk_heap *heap) {
52314 	duk_uint32_t new_st_size;
52315 	duk_uint32_t i;
52316 	duk_hstring *h;
52317 	duk_hstring *other;
52318 	duk_hstring *root;
52319 #if defined(DUK_USE_STRTAB_PTRCOMP)
52320 	duk_uint16_t *old_ptr;
52321 	duk_uint16_t *old_ptr_high;
52322 	duk_uint16_t *new_ptr;
52323 #else
52324 	duk_hstring **old_ptr;
52325 	duk_hstring **old_ptr_high;
52326 	duk_hstring **new_ptr;
52327 #endif
52328 
52329 	DUK_DD(DUK_DDPRINT("shrink in-place: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size / 2));
52330 
52331 	DUK_ASSERT(heap != NULL);
52332 	DUK_ASSERT(heap->st_resizing == 1);
52333 	DUK_ASSERT(heap->st_size >= 2);
52334 	DUK_ASSERT((heap->st_size & (heap->st_size - 1)) == 0);  /* 2^N */
52335 	DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
52336 
52337 	DUK_STATS_INC(heap, stats_strtab_resize_shrink);
52338 
52339 	new_st_size = heap->st_size >> 1U;
52340 
52341 	/* Combine two buckets into a single one.  When we shrink, one hash
52342 	 * bit (highest) disappears.
52343 	 */
52344 	old_ptr = DUK__GET_STRTABLE(heap);
52345 	old_ptr_high = old_ptr + new_st_size;
52346 	for (i = 0; i < new_st_size; i++) {
52347 		h = DUK__HEAPPTR_DEC16(heap, old_ptr[i]);
52348 		other = DUK__HEAPPTR_DEC16(heap, old_ptr_high[i]);
52349 
52350 		if (h == NULL) {
52351 			/* First chain is empty, so use second one as is. */
52352 			root = other;
52353 		} else {
52354 			/* Find end of first chain, and link in the second. */
52355 			root = h;
52356 			while (h->hdr.h_next != NULL) {
52357 				h = h->hdr.h_next;
52358 			}
52359 			h->hdr.h_next = other;
52360 		}
52361 
52362 		old_ptr[i] = DUK__HEAPPTR_ENC16(heap, root);
52363 	}
52364 
52365 	heap->st_size = new_st_size;
52366 	heap->st_mask = new_st_size - 1;
52367 
52368 	/* The strtable is now consistent and we can realloc safely.  Even
52369 	 * if side effects cause string interning or removal the strtable
52370 	 * updates are safe.  Recursive resize has been prevented by caller.
52371 	 * This is also why we don't need to use DUK_REALLOC_INDIRECT().
52372 	 *
52373 	 * We assume a realloc() to a smaller size is guaranteed to succeed.
52374 	 * It would be relatively straightforward to handle the error by
52375 	 * essentially performing a "grow" step to recover.
52376 	 */
52377 
52378 #if defined(DUK_USE_STRTAB_PTRCOMP)
52379 	new_ptr = (duk_uint16_t *) DUK_REALLOC(heap, heap->strtable16, sizeof(duk_uint16_t) * new_st_size);
52380 	DUK_ASSERT(new_ptr != NULL);
52381 	heap->strtable16 = new_ptr;
52382 #else
52383 	new_ptr = (duk_hstring **) DUK_REALLOC(heap, heap->strtable, sizeof(duk_hstring *) * new_st_size);
52384 	DUK_ASSERT(new_ptr != NULL);
52385 	heap->strtable = new_ptr;
52386 #endif
52387 
52388 #if defined(DUK_USE_ASSERTIONS)
52389 	duk__strtable_assert_checks(heap);
52390 #endif
52391 }
52392 #endif  /* DUK__STRTAB_RESIZE_CHECK */
52393 
52394 /*
52395  *  Grow/shrink check.
52396  */
52397 
52398 #if defined(DUK__STRTAB_RESIZE_CHECK)
52399 DUK_LOCAL DUK_COLD DUK_NOINLINE void duk__strtable_resize_check(duk_heap *heap) {
52400 	duk_uint32_t load_factor;  /* fixed point */
52401 
52402 	DUK_ASSERT(heap != NULL);
52403 #if defined(DUK_USE_STRTAB_PTRCOMP)
52404 	DUK_ASSERT(heap->strtable16 != NULL);
52405 #else
52406 	DUK_ASSERT(heap->strtable != NULL);
52407 #endif
52408 
52409 	DUK_STATS_INC(heap, stats_strtab_resize_check);
52410 
52411 	/* Prevent recursive resizing. */
52412 	if (DUK_UNLIKELY(heap->st_resizing != 0U)) {
52413 		DUK_D(DUK_DPRINT("prevent recursive strtable resize"));
52414 		return;
52415 	}
52416 
52417 	heap->st_resizing = 1;
52418 
52419 	DUK_ASSERT(heap->st_size >= 16U);
52420 	DUK_ASSERT((heap->st_size >> 4U) >= 1);
52421 	load_factor = heap->st_count / (heap->st_size >> 4U);
52422 
52423 	DUK_DD(DUK_DDPRINT("resize check string table: size=%lu, count=%lu, load_factor=%lu (fixed point .4; float %lf)",
52424 	                   (unsigned long) heap->st_size, (unsigned long) heap->st_count,
52425 	                   (unsigned long) load_factor,
52426 	                   (double) heap->st_count / (double) heap->st_size));
52427 
52428 	if (load_factor >= DUK_USE_STRTAB_GROW_LIMIT) {
52429 		if (heap->st_size >= DUK_USE_STRTAB_MAXSIZE) {
52430 			DUK_DD(DUK_DDPRINT("want to grow strtable (based on load factor) but already maximum size"));
52431 		} else {
52432 			DUK_D(DUK_DPRINT("grow string table: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size * 2));
52433 #if defined(DUK_USE_DEBUG)
52434 			duk_heap_strtable_dump(heap);
52435 #endif
52436 			duk__strtable_grow_inplace(heap);
52437 		}
52438 	} else if (load_factor <= DUK_USE_STRTAB_SHRINK_LIMIT) {
52439 		if (heap->st_size <= DUK_USE_STRTAB_MINSIZE) {
52440 			DUK_DD(DUK_DDPRINT("want to shrink strtable (based on load factor) but already minimum size"));
52441 		} else {
52442 			DUK_D(DUK_DPRINT("shrink string table: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size / 2));
52443 #if defined(DUK_USE_DEBUG)
52444 			duk_heap_strtable_dump(heap);
52445 #endif
52446 			duk__strtable_shrink_inplace(heap);
52447 		}
52448 	} else {
52449 		DUK_DD(DUK_DDPRINT("no need for strtable resize"));
52450 	}
52451 
52452 	heap->st_resizing = 0;
52453 }
52454 #endif  /* DUK__STRTAB_RESIZE_CHECK */
52455 
52456 /*
52457  *  Torture grow/shrink: unconditionally grow and shrink back.
52458  */
52459 
52460 #if defined(DUK_USE_STRTAB_TORTURE) && defined(DUK__STRTAB_RESIZE_CHECK)
52461 DUK_LOCAL void duk__strtable_resize_torture(duk_heap *heap) {
52462 	duk_uint32_t old_st_size;
52463 
52464 	DUK_ASSERT(heap != NULL);
52465 
52466 	old_st_size = heap->st_size;
52467 	if (old_st_size >= DUK_USE_STRTAB_MAXSIZE) {
52468 		return;
52469 	}
52470 
52471 	heap->st_resizing = 1;
52472 	duk__strtable_grow_inplace(heap);
52473 	if (heap->st_size > old_st_size) {
52474 		duk__strtable_shrink_inplace(heap);
52475 	}
52476 	heap->st_resizing = 0;
52477 }
52478 #endif  /* DUK_USE_STRTAB_TORTURE && DUK__STRTAB_RESIZE_CHECK */
52479 
52480 /*
52481  *  Raw intern; string already checked not to be present.
52482  */
52483 
52484 DUK_LOCAL duk_hstring *duk__strtable_do_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
52485 	duk_hstring *res;
52486 	const duk_uint8_t *extdata;
52487 #if defined(DUK_USE_STRTAB_PTRCOMP)
52488 	duk_uint16_t *slot;
52489 #else
52490 	duk_hstring **slot;
52491 #endif
52492 
52493 	DUK_DDD(DUK_DDDPRINT("do_intern: heap=%p, str=%p, blen=%lu, strhash=%lx, st_size=%lu, st_count=%lu, load=%lf",
52494 	                     (void *) heap, (const void *) str, (unsigned long) blen, (unsigned long) strhash,
52495 	                     (unsigned long) heap->st_size, (unsigned long) heap->st_count,
52496 	                     (double) heap->st_count / (double) heap->st_size));
52497 
52498 	DUK_ASSERT(heap != NULL);
52499 
52500 	/* Prevent any side effects on the string table and the caller provided
52501 	 * str/blen arguments while interning is in progress.  For example, if
52502 	 * the caller provided str/blen from a dynamic buffer, a finalizer
52503 	 * might resize or modify that dynamic buffer, invalidating the call
52504 	 * arguments.
52505 	 *
52506 	 * While finalizers must be prevented, mark-and-sweep itself is fine.
52507 	 * Recursive string table resize is prevented explicitly here.
52508 	 */
52509 
52510 	heap->pf_prevent_count++;
52511 	DUK_ASSERT(heap->pf_prevent_count != 0);  /* Wrap. */
52512 
52513 #if defined(DUK_USE_STRTAB_TORTURE) && defined(DUK__STRTAB_RESIZE_CHECK)
52514 	duk__strtable_resize_torture(heap);
52515 #endif
52516 
52517 	/* String table grow/shrink check.  Because of chaining (and no
52518 	 * accumulation issues as with hash probe chains and DELETED
52519 	 * markers) there's never a mandatory need to resize right now.
52520 	 * Check for the resize only periodically, based on st_count
52521 	 * bit pattern.  Because string table removal doesn't do a shrink
52522 	 * check, we do that also here.
52523 	 *
52524 	 * Do the resize and possible grow/shrink before the new duk_hstring
52525 	 * has been allocated.  Otherwise we may trigger a GC when the result
52526 	 * duk_hstring is not yet strongly referenced.
52527 	 */
52528 
52529 #if defined(DUK__STRTAB_RESIZE_CHECK)
52530 	if (DUK_UNLIKELY((heap->st_count & DUK_USE_STRTAB_RESIZE_CHECK_MASK) == 0)) {
52531 		duk__strtable_resize_check(heap);
52532 	}
52533 #endif
52534 
52535 	/* External string check (low memory optimization). */
52536 
52537 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
52538 	extdata = (const duk_uint8_t *) DUK_USE_EXTSTR_INTERN_CHECK(heap->heap_udata, (void *) DUK_LOSE_CONST(str), (duk_size_t) blen);
52539 #else
52540 	extdata = (const duk_uint8_t *) NULL;
52541 #endif
52542 
52543 	/* Allocate and initialize string, not yet linked.  This may cause a
52544 	 * GC which may cause other strings to be interned and inserted into
52545 	 * the string table before we insert our string.  Finalizer execution
52546 	 * is disabled intentionally to avoid a finalizer from e.g. resizing
52547 	 * a buffer used as a data area for 'str'.
52548 	 */
52549 
52550 	res = duk__strtable_alloc_hstring(heap, str, blen, strhash, extdata);
52551 
52552 	/* Allow side effects again: GC must be avoided until duk_hstring
52553 	 * result (if successful) has been INCREF'd.
52554 	 */
52555 	DUK_ASSERT(heap->pf_prevent_count > 0);
52556 	heap->pf_prevent_count--;
52557 
52558 	/* Alloc error handling. */
52559 
52560 	if (DUK_UNLIKELY(res == NULL)) {
52561 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
52562 		if (extdata != NULL) {
52563 			DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) extdata);
52564 		}
52565 #endif
52566 		return NULL;
52567 	}
52568 
52569 	/* Insert into string table. */
52570 
52571 #if defined(DUK_USE_STRTAB_PTRCOMP)
52572 	slot = heap->strtable16 + (strhash & heap->st_mask);
52573 #else
52574 	slot = heap->strtable + (strhash & heap->st_mask);
52575 #endif
52576 	DUK_ASSERT(res->hdr.h_next == NULL);  /* This is the case now, but unnecessary zeroing/NULLing. */
52577 	res->hdr.h_next = DUK__HEAPPTR_DEC16(heap, *slot);
52578 	*slot = DUK__HEAPPTR_ENC16(heap, res);
52579 
52580 	/* Update string count only for successful inserts. */
52581 
52582 #if defined(DUK__STRTAB_RESIZE_CHECK)
52583 	heap->st_count++;
52584 #endif
52585 
52586 	/* The duk_hstring is in the string table but is not yet strongly
52587 	 * reachable.  Calling code MUST NOT make any allocations or other
52588 	 * side effects before the duk_hstring has been INCREF'd and made
52589 	 * reachable.
52590 	 */
52591 
52592 	return res;
52593 }
52594 
52595 /*
52596  *  Intern a string from str/blen, returning either an existing duk_hstring
52597  *  or adding a new one into the string table.  The input string does -not-
52598  *  need to be NUL terminated.
52599  *
52600  *  The input 'str' argument may point to a Duktape managed data area such as
52601  *  the data area of a dynamic buffer.  It's crucial to avoid any side effects
52602  *  that might affect the data area (e.g. resize the dynamic buffer, or write
52603  *  to the buffer) before the string is fully interned.
52604  */
52605 
52606 #if defined(DUK_USE_ROM_STRINGS)
52607 DUK_LOCAL duk_hstring *duk__strtab_romstring_lookup(duk_heap *heap, const duk_uint8_t *str, duk_size_t blen, duk_uint32_t strhash) {
52608 	duk_size_t lookup_hash;
52609 	duk_hstring *curr;
52610 
52611 	DUK_ASSERT(heap != NULL);
52612 	DUK_UNREF(heap);
52613 
52614 	lookup_hash = (blen << 4);
52615 	if (blen > 0) {
52616 		lookup_hash += str[0];
52617 	}
52618 	lookup_hash &= 0xff;
52619 
52620 	curr = (duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_lookup[lookup_hash]);
52621 	while (curr != NULL) {
52622 		/* Unsafe memcmp() because for zero blen, str may be NULL. */
52623 		if (strhash == DUK_HSTRING_GET_HASH(curr) &&
52624 		    blen == DUK_HSTRING_GET_BYTELEN(curr) &&
52625 		    duk_memcmp_unsafe((const void *) str, (const void *) DUK_HSTRING_GET_DATA(curr), blen) == 0) {
52626 			DUK_DDD(DUK_DDDPRINT("intern check: rom string: %!O, computed hash 0x%08lx, rom hash 0x%08lx",
52627 			                     curr, (unsigned long) strhash, (unsigned long) DUK_HSTRING_GET_HASH(curr)));
52628 			return curr;
52629 		}
52630 		curr = curr->hdr.h_next;
52631 	}
52632 
52633 	return NULL;
52634 }
52635 #endif  /* DUK_USE_ROM_STRINGS */
52636 
52637 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen) {
52638 	duk_uint32_t strhash;
52639 	duk_hstring *h;
52640 
52641 	DUK_DDD(DUK_DDDPRINT("intern check: heap=%p, str=%p, blen=%lu", (void *) heap, (const void *) str, (unsigned long) blen));
52642 
52643 	/* Preliminaries. */
52644 
52645 	/* XXX: maybe just require 'str != NULL' even for zero size? */
52646 	DUK_ASSERT(heap != NULL);
52647 	DUK_ASSERT(blen == 0 || str != NULL);
52648 	DUK_ASSERT(blen <= DUK_HSTRING_MAX_BYTELEN);  /* Caller is responsible for ensuring this. */
52649 	strhash = duk_heap_hashstring(heap, str, (duk_size_t) blen);
52650 
52651 	/* String table lookup. */
52652 
52653 	DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
52654 	DUK_ASSERT(heap->st_size > 0);
52655 	DUK_ASSERT(heap->st_size == heap->st_mask + 1);
52656 #if defined(DUK_USE_STRTAB_PTRCOMP)
52657 	h = DUK__HEAPPTR_DEC16(heap, heap->strtable16[strhash & heap->st_mask]);
52658 #else
52659 	h = heap->strtable[strhash & heap->st_mask];
52660 #endif
52661 	while (h != NULL) {
52662 		if (DUK_HSTRING_GET_HASH(h) == strhash &&
52663 		    DUK_HSTRING_GET_BYTELEN(h) == blen &&
52664 		    duk_memcmp_unsafe((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
52665 			/* Found existing entry. */
52666 			DUK_STATS_INC(heap, stats_strtab_intern_hit);
52667 			return h;
52668 		}
52669 		h = h->hdr.h_next;
52670 	}
52671 
52672 	/* ROM table lookup.  Because this lookup is slower, do it only after
52673 	 * RAM lookup.  This works because no ROM string is ever interned into
52674 	 * the RAM string table.
52675 	 */
52676 
52677 #if defined(DUK_USE_ROM_STRINGS)
52678 	h = duk__strtab_romstring_lookup(heap, str, blen, strhash);
52679 	if (h != NULL) {
52680 		DUK_STATS_INC(heap, stats_strtab_intern_hit);
52681 		return h;
52682 	}
52683 #endif
52684 
52685 	/* Not found in string table; insert. */
52686 
52687 	DUK_STATS_INC(heap, stats_strtab_intern_miss);
52688 	h = duk__strtable_do_intern(heap, str, blen, strhash);
52689 	return h;  /* may be NULL */
52690 }
52691 
52692 /*
52693  *  Intern a string from u32.
52694  */
52695 
52696 /* XXX: Could arrange some special handling because we know that the result
52697  * will have an arridx flag and an ASCII flag, won't need a clen check, etc.
52698  */
52699 
52700 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_u32(duk_heap *heap, duk_uint32_t val) {
52701 	duk_uint8_t buf[DUK__STRTAB_U32_MAX_STRLEN];
52702 	duk_uint8_t *p;
52703 
52704 	DUK_ASSERT(heap != NULL);
52705 
52706 	/* This is smaller and faster than a %lu sprintf. */
52707 	p = buf + sizeof(buf);
52708 	do {
52709 		p--;
52710 		*p = duk_lc_digits[val % 10];
52711 		val = val / 10;
52712 	} while (val != 0);  /* For val == 0, emit exactly one '0'. */
52713 	DUK_ASSERT(p >= buf);
52714 
52715 	return duk_heap_strtable_intern(heap, (const duk_uint8_t *) p, (duk_uint32_t) ((buf + sizeof(buf)) - p));
52716 }
52717 
52718 /*
52719  *  Checked convenience variants.
52720  *
52721  *  XXX: Because the main use case is for the checked variants, make them the
52722  *  main functionality and provide a safe variant separately (it is only needed
52723  *  during heap init).  The problem with that is that longjmp state and error
52724  *  creation must already be possible to throw.
52725  */
52726 
52727 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {
52728 	duk_hstring *res;
52729 
52730 	DUK_ASSERT(thr != NULL);
52731 	DUK_ASSERT(thr->heap != NULL);
52732 	DUK_ASSERT(blen == 0 || str != NULL);
52733 
52734 	res = duk_heap_strtable_intern(thr->heap, str, blen);
52735 	if (DUK_UNLIKELY(res == NULL)) {
52736 		DUK_ERROR_ALLOC_FAILED(thr);
52737 		DUK_WO_NORETURN(return NULL;);
52738 	}
52739 	return res;
52740 }
52741 
52742 #if defined(DUK_USE_LITCACHE_SIZE)
52743 DUK_LOCAL duk_uint_t duk__strtable_litcache_key(const duk_uint8_t *str, duk_uint32_t blen) {
52744 	duk_uintptr_t key;
52745 
52746 	DUK_ASSERT(DUK_USE_LITCACHE_SIZE > 0);
52747 	DUK_ASSERT(DUK_IS_POWER_OF_TWO((duk_uint_t) DUK_USE_LITCACHE_SIZE));
52748 
52749 	key = (duk_uintptr_t) blen ^ (duk_uintptr_t) str;
52750 	key &= (duk_uintptr_t) (DUK_USE_LITCACHE_SIZE - 1);  /* Assumes size is power of 2. */
52751 	/* Due to masking, cast is in 32-bit range. */
52752 	DUK_ASSERT(key <= DUK_UINT_MAX);
52753 	return (duk_uint_t) key;
52754 }
52755 
52756 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_literal_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {
52757 	duk_uint_t key;
52758 	duk_litcache_entry *ent;
52759 	duk_hstring *h;
52760 
52761 	/* Fast path check: literal exists in literal cache. */
52762 	key = duk__strtable_litcache_key(str, blen);
52763 	ent = thr->heap->litcache + key;
52764 	if (ent->addr == str) {
52765 		DUK_DD(DUK_DDPRINT("intern check for cached, pinned literal: str=%p, blen=%ld -> duk_hstring %!O",
52766 		                   (const void *) str, (long) blen, (duk_heaphdr *) ent->h));
52767 		DUK_ASSERT(ent->h != NULL);
52768 		DUK_ASSERT(DUK_HSTRING_HAS_PINNED_LITERAL(ent->h));
52769 		DUK_STATS_INC(thr->heap, stats_strtab_litcache_hit);
52770 		return ent->h;
52771 	}
52772 
52773 	/* Intern and update (overwrite) cache entry. */
52774 	h = duk_heap_strtable_intern_checked(thr, str, blen);
52775 	ent->addr = str;
52776 	ent->h = h;
52777 	DUK_STATS_INC(thr->heap, stats_strtab_litcache_miss);
52778 
52779 	/* Pin the duk_hstring until the next mark-and-sweep.  This means
52780 	 * litcache entries don't need to be invalidated until the next
52781 	 * mark-and-sweep as their target duk_hstring is not freed before
52782 	 * the mark-and-sweep happens.  The pin remains even if the literal
52783 	 * cache entry is overwritten, and is still useful to avoid string
52784 	 * table traffic.
52785 	 */
52786 	if (!DUK_HSTRING_HAS_PINNED_LITERAL(h)) {
52787 		DUK_DD(DUK_DDPRINT("pin duk_hstring because it is a literal: %!O", (duk_heaphdr *) h));
52788 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));
52789 		DUK_HSTRING_INCREF(thr, h);
52790 		DUK_HSTRING_SET_PINNED_LITERAL(h);
52791 		DUK_STATS_INC(thr->heap, stats_strtab_litcache_pin);
52792 	}
52793 
52794 	return h;
52795 }
52796 #endif  /* DUK_USE_LITCACHE_SIZE */
52797 
52798 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_u32_checked(duk_hthread *thr, duk_uint32_t val) {
52799 	duk_hstring *res;
52800 
52801 	DUK_ASSERT(thr != NULL);
52802 	DUK_ASSERT(thr->heap != NULL);
52803 
52804 	res = duk_heap_strtable_intern_u32(thr->heap, val);
52805 	if (DUK_UNLIKELY(res == NULL)) {
52806 		DUK_ERROR_ALLOC_FAILED(thr);
52807 		DUK_WO_NORETURN(return NULL;);
52808 	}
52809 	return res;
52810 }
52811 
52812 /*
52813  *  Remove (unlink) a string from the string table.
52814  *
52815  *  Just unlinks the duk_hstring, leaving link pointers as garbage.
52816  *  Caller must free the string itself.
52817  */
52818 
52819 #if defined(DUK_USE_REFERENCE_COUNTING)
52820 /* Unlink without a 'prev' pointer. */
52821 DUK_INTERNAL void duk_heap_strtable_unlink(duk_heap *heap, duk_hstring *h) {
52822 #if defined(DUK_USE_STRTAB_PTRCOMP)
52823 	duk_uint16_t *slot;
52824 #else
52825 	duk_hstring **slot;
52826 #endif
52827 	duk_hstring *other;
52828 	duk_hstring *prev;
52829 
52830 	DUK_DDD(DUK_DDDPRINT("remove: heap=%p, h=%p, blen=%lu, strhash=%lx",
52831 	                     (void *) heap, (void *) h,
52832 	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_BYTELEN(h) : 0),
52833 	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_HASH(h) : 0)));
52834 
52835 	DUK_ASSERT(heap != NULL);
52836 	DUK_ASSERT(h != NULL);
52837 
52838 #if defined(DUK__STRTAB_RESIZE_CHECK)
52839 	DUK_ASSERT(heap->st_count > 0);
52840 	heap->st_count--;
52841 #endif
52842 
52843 #if defined(DUK_USE_STRTAB_PTRCOMP)
52844 	slot = heap->strtable16 + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
52845 #else
52846 	slot = heap->strtable + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
52847 #endif
52848 	other = DUK__HEAPPTR_DEC16(heap, *slot);
52849 	DUK_ASSERT(other != NULL);  /* At least argument string is in the chain. */
52850 
52851 	prev = NULL;
52852 	while (other != h) {
52853 		prev = other;
52854 		other = other->hdr.h_next;
52855 		DUK_ASSERT(other != NULL);  /* We'll eventually find 'h'. */
52856 	}
52857 	if (prev != NULL) {
52858 		/* Middle of list. */
52859 		prev->hdr.h_next = h->hdr.h_next;
52860 	} else {
52861 		/* Head of list. */
52862 		*slot = DUK__HEAPPTR_ENC16(heap, h->hdr.h_next);
52863 	}
52864 
52865 	/* There's no resize check on a string free.  The next string
52866 	 * intern will do one.
52867 	 */
52868 }
52869 #endif  /* DUK_USE_REFERENCE_COUNTING */
52870 
52871 /* Unlink with a 'prev' pointer. */
52872 DUK_INTERNAL void duk_heap_strtable_unlink_prev(duk_heap *heap, duk_hstring *h, duk_hstring *prev) {
52873 #if defined(DUK_USE_STRTAB_PTRCOMP)
52874 	duk_uint16_t *slot;
52875 #else
52876 	duk_hstring **slot;
52877 #endif
52878 
52879 	DUK_DDD(DUK_DDDPRINT("remove: heap=%p, prev=%p, h=%p, blen=%lu, strhash=%lx",
52880 	                     (void *) heap, (void *) prev, (void *) h,
52881 	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_BYTELEN(h) : 0),
52882 	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_HASH(h) : 0)));
52883 
52884 	DUK_ASSERT(heap != NULL);
52885 	DUK_ASSERT(h != NULL);
52886 	DUK_ASSERT(prev == NULL || prev->hdr.h_next == h);
52887 
52888 #if defined(DUK__STRTAB_RESIZE_CHECK)
52889 	DUK_ASSERT(heap->st_count > 0);
52890 	heap->st_count--;
52891 #endif
52892 
52893 	if (prev != NULL) {
52894 		/* Middle of list. */
52895 		prev->hdr.h_next = h->hdr.h_next;
52896 	} else {
52897 		/* Head of list. */
52898 #if defined(DUK_USE_STRTAB_PTRCOMP)
52899 		slot = heap->strtable16 + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
52900 #else
52901 		slot = heap->strtable + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
52902 #endif
52903 		DUK_ASSERT(DUK__HEAPPTR_DEC16(heap, *slot) == h);
52904 		*slot = DUK__HEAPPTR_ENC16(heap, h->hdr.h_next);
52905 	}
52906 }
52907 
52908 /*
52909  *  Force string table resize check in mark-and-sweep.
52910  */
52911 
52912 DUK_INTERNAL void duk_heap_strtable_force_resize(duk_heap *heap) {
52913 	/* Does only one grow/shrink step if needed.  The heap->st_resizing
52914 	 * flag protects against recursive resizing.
52915 	 */
52916 
52917 	DUK_ASSERT(heap != NULL);
52918 	DUK_UNREF(heap);
52919 
52920 #if defined(DUK__STRTAB_RESIZE_CHECK)
52921 #if defined(DUK_USE_STRTAB_PTRCOMP)
52922 	if (heap->strtable16 != NULL) {
52923 #else
52924 	if (heap->strtable != NULL) {
52925 #endif
52926 		duk__strtable_resize_check(heap);
52927 	}
52928 #endif
52929 }
52930 
52931 /*
52932  *  Free strings in the string table and the string table itself.
52933  */
52934 
52935 DUK_INTERNAL void duk_heap_strtable_free(duk_heap *heap) {
52936 #if defined(DUK_USE_STRTAB_PTRCOMP)
52937 	duk_uint16_t *strtable;
52938 	duk_uint16_t *st;
52939 #else
52940 	duk_hstring **strtable;
52941 	duk_hstring **st;
52942 #endif
52943 	duk_hstring *h;
52944 
52945 	DUK_ASSERT(heap != NULL);
52946 
52947 #if defined(DUK_USE_ASSERTIONS)
52948 	duk__strtable_assert_checks(heap);
52949 #endif
52950 
52951 	/* Strtable can be NULL if heap init fails.  However, in that case
52952 	 * heap->st_size is 0, so strtable == strtable_end and we skip the
52953 	 * loop without a special check.
52954 	 */
52955 	strtable = DUK__GET_STRTABLE(heap);
52956 	st = strtable + heap->st_size;
52957 	DUK_ASSERT(strtable != NULL || heap->st_size == 0);
52958 
52959 	while (strtable != st) {
52960 		--st;
52961 		h = DUK__HEAPPTR_DEC16(heap, *st);
52962 		while (h) {
52963 			duk_hstring *h_next;
52964 			h_next = h->hdr.h_next;
52965 
52966 			/* Strings may have inner refs (extdata) in some cases. */
52967 			duk_free_hstring(heap, h);
52968 
52969 			h = h_next;
52970 		}
52971 	}
52972 
52973 	DUK_FREE(heap, strtable);
52974 }
52975 
52976 /* automatic undefs */
52977 #undef DUK__GET_STRTABLE
52978 #undef DUK__HEAPPTR_DEC16
52979 #undef DUK__HEAPPTR_ENC16
52980 #undef DUK__STRTAB_U32_MAX_STRLEN
52981 #line 1 "duk_hobject_alloc.c"
52982 /*
52983  *  Hobject allocation.
52984  *
52985  *  Provides primitive allocation functions for all object types (plain object,
52986  *  compiled function, native function, thread).  The object return is not yet
52987  *  in "heap allocated" list and has a refcount of zero, so caller must careful.
52988  */
52989 
52990 /* XXX: In most cases there's no need for plain allocation without pushing
52991  * to the value stack.  Maybe rework contract?
52992  */
52993 
52994 /* #include duk_internal.h -> already included */
52995 
52996 /*
52997  *  Helpers.
52998  */
52999 
53000 DUK_LOCAL void duk__init_object_parts(duk_heap *heap, duk_uint_t hobject_flags, duk_hobject *obj) {
53001 	DUK_ASSERT(obj != NULL);
53002 	/* Zeroed by caller. */
53003 
53004 	obj->hdr.h_flags = hobject_flags | DUK_HTYPE_OBJECT;
53005 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(&obj->hdr) == DUK_HTYPE_OBJECT);  /* Assume zero shift. */
53006 
53007 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53008 	DUK_HOBJECT_SET_PROTOTYPE(heap, obj, NULL);
53009 	DUK_HOBJECT_SET_PROPS(heap, obj, NULL);
53010 #endif
53011 #if defined(DUK_USE_HEAPPTR16)
53012 	/* Zero encoded pointer is required to match NULL. */
53013 	DUK_HEAPHDR_SET_NEXT(heap, &obj->hdr, NULL);
53014 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
53015 	DUK_HEAPHDR_SET_PREV(heap, &obj->hdr, NULL);
53016 #endif
53017 #endif
53018 	DUK_ASSERT_HEAPHDR_LINKS(heap, &obj->hdr);
53019 	DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &obj->hdr);
53020 
53021 	/* obj->props is intentionally left as NULL, and duk_hobject_props.c must deal
53022 	 * with this properly.  This is intentional: empty objects consume a minimum
53023 	 * amount of memory.  Further, an initial allocation might fail and cause
53024 	 * 'obj' to "leak" (require a mark-and-sweep) since it is not reachable yet.
53025 	 */
53026 }
53027 
53028 DUK_LOCAL void *duk__hobject_alloc_init(duk_hthread *thr, duk_uint_t hobject_flags, duk_size_t size) {
53029 	void *res;
53030 
53031 	res = (void *) DUK_ALLOC_CHECKED_ZEROED(thr, size);
53032 	DUK_ASSERT(res != NULL);
53033 	duk__init_object_parts(thr->heap, hobject_flags, (duk_hobject *) res);
53034 	return res;
53035 }
53036 
53037 /*
53038  *  Allocate an duk_hobject.
53039  *
53040  *  The allocated object has no allocation for properties; the caller may
53041  *  want to force a resize if a desired size is known.
53042  *
53043  *  The allocated object has zero reference count and is not reachable.
53044  *  The caller MUST make the object reachable and increase its reference
53045  *  count before invoking any operation that might require memory allocation.
53046  */
53047 
53048 DUK_INTERNAL duk_hobject *duk_hobject_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags) {
53049 	duk_hobject *res;
53050 
53051 	DUK_ASSERT(heap != NULL);
53052 
53053 	/* different memory layout, alloc size, and init */
53054 	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_COMPFUNC) == 0);
53055 	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_NATFUNC) == 0);
53056 	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_BOUNDFUNC) == 0);
53057 
53058 	res = (duk_hobject *) DUK_ALLOC_ZEROED(heap, sizeof(duk_hobject));
53059 	if (DUK_UNLIKELY(res == NULL)) {
53060 		return NULL;
53061 	}
53062 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(res));
53063 
53064 	duk__init_object_parts(heap, hobject_flags, res);
53065 
53066 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(res));
53067 	return res;
53068 }
53069 
53070 DUK_INTERNAL duk_hobject *duk_hobject_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53071 	duk_hobject *res;
53072 
53073 	res = (duk_hobject *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hobject));
53074 	return res;
53075 }
53076 
53077 DUK_INTERNAL duk_hcompfunc *duk_hcompfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53078 	duk_hcompfunc *res;
53079 
53080 	res = (duk_hcompfunc *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hcompfunc));
53081 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53082 #if defined(DUK_USE_HEAPPTR16)
53083 	/* NULL pointer is required to encode to zero, so memset is enough. */
53084 #else
53085 	res->data = NULL;
53086 	res->funcs = NULL;
53087 	res->bytecode = NULL;
53088 #endif
53089 	res->lex_env = NULL;
53090 	res->var_env = NULL;
53091 #endif
53092 
53093 	return res;
53094 }
53095 
53096 DUK_INTERNAL duk_hnatfunc *duk_hnatfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53097 	duk_hnatfunc *res;
53098 
53099 	res = (duk_hnatfunc *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hnatfunc));
53100 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53101 	res->func = NULL;
53102 #endif
53103 
53104 	return res;
53105 }
53106 
53107 DUK_INTERNAL duk_hboundfunc *duk_hboundfunc_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
53108 	duk_hboundfunc *res;
53109 
53110 	res = (duk_hboundfunc *) DUK_ALLOC(heap, sizeof(duk_hboundfunc));
53111 	if (!res) {
53112 		return NULL;
53113 	}
53114 	duk_memzero(res, sizeof(duk_hboundfunc));
53115 
53116 	duk__init_object_parts(heap, hobject_flags, &res->obj);
53117 
53118 	DUK_TVAL_SET_UNDEFINED(&res->target);
53119 	DUK_TVAL_SET_UNDEFINED(&res->this_binding);
53120 
53121 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53122 	res->args = NULL;
53123 #endif
53124 
53125 	return res;
53126 }
53127 
53128 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
53129 DUK_INTERNAL duk_hbufobj *duk_hbufobj_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53130 	duk_hbufobj *res;
53131 
53132 	res = (duk_hbufobj *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hbufobj));
53133 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53134 	res->buf = NULL;
53135 	res->buf_prop = NULL;
53136 #endif
53137 
53138 	DUK_ASSERT_HBUFOBJ_VALID(res);
53139 	return res;
53140 }
53141 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
53142 
53143 /* Allocate a new thread.
53144  *
53145  * Leaves the built-ins array uninitialized.  The caller must either
53146  * initialize a new global context or share existing built-ins from
53147  * another thread.
53148  */
53149 DUK_INTERNAL duk_hthread *duk_hthread_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags) {
53150 	duk_hthread *res;
53151 
53152 	res = (duk_hthread *) DUK_ALLOC(heap, sizeof(duk_hthread));
53153 	if (DUK_UNLIKELY(res == NULL)) {
53154 		return NULL;
53155 	}
53156 	duk_memzero(res, sizeof(duk_hthread));
53157 
53158 	duk__init_object_parts(heap, hobject_flags, &res->obj);
53159 
53160 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53161 	res->ptr_curr_pc = NULL;
53162 	res->heap = NULL;
53163 	res->valstack = NULL;
53164 	res->valstack_end = NULL;
53165 	res->valstack_alloc_end = NULL;
53166 	res->valstack_bottom = NULL;
53167 	res->valstack_top = NULL;
53168 	res->callstack_curr = NULL;
53169 	res->resumer = NULL;
53170 	res->compile_ctx = NULL,
53171 #if defined(DUK_USE_HEAPPTR16)
53172 	res->strs16 = NULL;
53173 #else
53174 	res->strs = NULL;
53175 #endif
53176 	{
53177 		duk_small_uint_t i;
53178 		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
53179 			res->builtins[i] = NULL;
53180 		}
53181 	}
53182 #endif
53183 	/* When nothing is running, API calls are in non-strict mode. */
53184 	DUK_ASSERT(res->strict == 0);
53185 
53186 	res->heap = heap;
53187 
53188 	/* XXX: Any reason not to merge duk_hthread_alloc.c here? */
53189 	return res;
53190 }
53191 
53192 DUK_INTERNAL duk_hthread *duk_hthread_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53193 	duk_hthread *res;
53194 
53195 	res = duk_hthread_alloc_unchecked(thr->heap, hobject_flags);
53196 	if (res == NULL) {
53197 		DUK_ERROR_ALLOC_FAILED(thr);
53198 		DUK_WO_NORETURN(return NULL;);
53199 	}
53200 	return res;
53201 }
53202 
53203 DUK_INTERNAL duk_harray *duk_harray_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53204 	duk_harray *res;
53205 
53206 	res = (duk_harray *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_harray));
53207 
53208 	DUK_ASSERT(res->length == 0);
53209 
53210 	return res;
53211 }
53212 
53213 DUK_INTERNAL duk_hdecenv *duk_hdecenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53214 	duk_hdecenv *res;
53215 
53216 	res = (duk_hdecenv *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hdecenv));
53217 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53218 	res->thread = NULL;
53219 	res->varmap = NULL;
53220 #endif
53221 
53222 	DUK_ASSERT(res->thread == NULL);
53223 	DUK_ASSERT(res->varmap == NULL);
53224 	DUK_ASSERT(res->regbase_byteoff == 0);
53225 
53226 	return res;
53227 }
53228 
53229 DUK_INTERNAL duk_hobjenv *duk_hobjenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53230 	duk_hobjenv *res;
53231 
53232 	res = (duk_hobjenv *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hobjenv));
53233 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53234 	res->target = NULL;
53235 #endif
53236 
53237 	DUK_ASSERT(res->target == NULL);
53238 
53239 	return res;
53240 }
53241 
53242 DUK_INTERNAL duk_hproxy *duk_hproxy_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53243 	duk_hproxy *res;
53244 
53245 	res = (duk_hproxy *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hproxy));
53246 
53247 	/* Leave ->target and ->handler uninitialized, as caller will always
53248 	 * explicitly initialize them before any side effects are possible.
53249 	 */
53250 
53251 	return res;
53252 }
53253 #line 1 "duk_hobject_enum.c"
53254 /*
53255  *  Object enumeration support.
53256  *
53257  *  Creates an internal enumeration state object to be used e.g. with for-in
53258  *  enumeration.  The state object contains a snapshot of target object keys
53259  *  and internal control state for enumeration.  Enumerator flags allow caller
53260  *  to e.g. request internal/non-enumerable properties, and to enumerate only
53261  *  "own" properties.
53262  *
53263  *  Also creates the result value for e.g. Object.keys() based on the same
53264  *  internal structure.
53265  *
53266  *  This snapshot-based enumeration approach is used to simplify enumeration:
53267  *  non-snapshot-based approaches are difficult to reconcile with mutating
53268  *  the enumeration target, running multiple long-lived enumerators at the
53269  *  same time, garbage collection details, etc.  The downside is that the
53270  *  enumerator object is memory inefficient especially for iterating arrays.
53271  */
53272 
53273 /* #include duk_internal.h -> already included */
53274 
53275 /* XXX: identify enumeration target with an object index (not top of stack) */
53276 
53277 /* First enumerated key index in enumerator object, must match exactly the
53278  * number of control properties inserted to the enumerator.
53279  */
53280 #define DUK__ENUM_START_INDEX  2
53281 
53282 /* Current implementation suffices for ES2015 for now because there's no symbol
53283  * sorting, so commented out for now.
53284  */
53285 
53286 /*
53287  *  Helper to sort enumeration keys using a callback for pairwise duk_hstring
53288  *  comparisons.  The keys are in the enumeration object entry part, starting
53289  *  from DUK__ENUM_START_INDEX, and the entry part is dense.  Entry part values
53290  *  are all "true", e.g. "1" -> true, "3" -> true, "foo" -> true, "2" -> true,
53291  *  so it suffices to just switch keys without switching values.
53292  *
53293  *  ES2015 [[OwnPropertyKeys]] enumeration order for ordinary objects:
53294  *  (1) array indices in ascending order,
53295  *  (2) non-array-index keys in insertion order, and
53296  *  (3) symbols in insertion order.
53297  *  http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys.
53298  *
53299  *  This rule is applied to "own properties" at each inheritance level;
53300  *  non-duplicate parent keys always follow child keys.  For example,
53301  *  an inherited array index will enumerate -after- a symbol in the
53302  *  child.
53303  *
53304  *  Insertion sort is used because (1) it's simple and compact, (2) works
53305  *  in-place, (3) minimizes operations if data is already nearly sorted,
53306  *  (4) doesn't reorder elements considered equal.
53307  *  http://en.wikipedia.org/wiki/Insertion_sort
53308  */
53309 
53310 /* Sort key, must hold array indices, "not array index" marker, and one more
53311  * higher value for symbols.
53312  */
53313 #if !defined(DUK_USE_SYMBOL_BUILTIN)
53314 typedef duk_uint32_t duk__sort_key_t;
53315 #elif defined(DUK_USE_64BIT_OPS)
53316 typedef duk_uint64_t duk__sort_key_t;
53317 #else
53318 typedef duk_double_t duk__sort_key_t;
53319 #endif
53320 
53321 /* Get sort key for a duk_hstring. */
53322 DUK_LOCAL duk__sort_key_t duk__hstring_sort_key(duk_hstring *x) {
53323 	duk__sort_key_t val;
53324 
53325 	/* For array indices [0,0xfffffffe] use the array index as is.
53326 	 * For strings, use 0xffffffff, the marker 'arridx' already in
53327 	 * duk_hstring.  For symbols, any value above 0xffffffff works,
53328 	 * as long as it is the same for all symbols; currently just add
53329 	 * the masked flag field into the arridx temporary.
53330 	 */
53331 	DUK_ASSERT(x != NULL);
53332 	DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(x) || DUK_HSTRING_GET_ARRIDX_FAST(x) == DUK_HSTRING_NO_ARRAY_INDEX);
53333 
53334 	val = (duk__sort_key_t) DUK_HSTRING_GET_ARRIDX_FAST(x);
53335 
53336 #if defined(DUK_USE_SYMBOL_BUILTIN)
53337 	val = val + (duk__sort_key_t) (DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) x) & DUK_HSTRING_FLAG_SYMBOL);
53338 #endif
53339 
53340 	return (duk__sort_key_t) val;
53341 }
53342 
53343 /* Insert element 'b' after element 'a'? */
53344 DUK_LOCAL duk_bool_t duk__sort_compare_es6(duk_hstring *a, duk_hstring *b, duk__sort_key_t val_b) {
53345 	duk__sort_key_t val_a;
53346 
53347 	DUK_ASSERT(a != NULL);
53348 	DUK_ASSERT(b != NULL);
53349 	DUK_UNREF(b);  /* Not actually needed now, val_b suffices. */
53350 
53351 	val_a = duk__hstring_sort_key(a);
53352 
53353 	if (val_a > val_b) {
53354 		return 0;
53355 	} else {
53356 		return 1;
53357 	}
53358 }
53359 
53360 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) {
53361 	duk_hstring **keys;
53362 	duk_int_fast32_t idx;
53363 
53364 	DUK_ASSERT(h_obj != NULL);
53365 	DUK_ASSERT(idx_start >= DUK__ENUM_START_INDEX);
53366 	DUK_ASSERT(idx_end >= idx_start);
53367 	DUK_UNREF(thr);
53368 
53369 	if (idx_end <= idx_start + 1) {
53370 		return;  /* Zero or one element(s). */
53371 	}
53372 
53373 	keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, h_obj);
53374 
53375 	for (idx = idx_start + 1; idx < idx_end; idx++) {
53376 		duk_hstring *h_curr;
53377 		duk_int_fast32_t idx_insert;
53378 		duk__sort_key_t val_curr;
53379 
53380 		h_curr = keys[idx];
53381 		DUK_ASSERT(h_curr != NULL);
53382 
53383 		/* Scan backwards for insertion place.  This works very well
53384 		 * when the elements are nearly in order which is the common
53385 		 * (and optimized for) case.
53386 		 */
53387 
53388 		val_curr = duk__hstring_sort_key(h_curr);  /* Remains same during scanning. */
53389 		for (idx_insert = idx - 1; idx_insert >= idx_start; idx_insert--) {
53390 			duk_hstring *h_insert;
53391 			h_insert = keys[idx_insert];
53392 			DUK_ASSERT(h_insert != NULL);
53393 
53394 			if (duk__sort_compare_es6(h_insert, h_curr, val_curr)) {
53395 				break;
53396 			}
53397 		}
53398 		/* If we're out of indices, idx_insert == idx_start - 1 and idx_insert++
53399 		 * brings us back to idx_start.
53400 		 */
53401 		idx_insert++;
53402 		DUK_ASSERT(idx_insert >= 0 && idx_insert <= idx);
53403 
53404 		/*        .-- p_insert   .-- p_curr
53405 		 *        v              v
53406 		 *  | ... | insert | ... | curr
53407 		 */
53408 
53409 		/* This could also done when the keys are in order, i.e.
53410 		 * idx_insert == idx.  The result would be an unnecessary
53411 		 * memmove() but we use an explicit check because the keys
53412 		 * are very often in order already.
53413 		 */
53414 		if (idx != idx_insert) {
53415 			duk_memmove((void *) (keys + idx_insert + 1),
53416 			            (const void *) (keys + idx_insert),
53417 			            ((size_t) (idx - idx_insert) * sizeof(duk_hstring *)));
53418 			keys[idx_insert] = h_curr;
53419 		}
53420 	}
53421 }
53422 
53423 /*
53424  *  Create an internal enumerator object E, which has its keys ordered
53425  *  to match desired enumeration ordering.  Also initialize internal control
53426  *  properties for enumeration.
53427  *
53428  *  Note: if an array was used to hold enumeration keys instead, an array
53429  *  scan would be needed to eliminate duplicates found in the prototype chain.
53430  */
53431 
53432 DUK_LOCAL void duk__add_enum_key(duk_hthread *thr, duk_hstring *k) {
53433 	/* 'k' may be unreachable on entry so must push without any
53434 	 * potential for GC.
53435 	 */
53436 	duk_push_hstring(thr, k);
53437 	duk_push_true(thr);
53438 	duk_put_prop(thr, -3);
53439 }
53440 
53441 DUK_LOCAL void duk__add_enum_key_stridx(duk_hthread *thr, duk_small_uint_t stridx) {
53442 	duk__add_enum_key(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
53443 }
53444 
53445 DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint_t enum_flags) {
53446 	duk_hobject *enum_target;
53447 	duk_hobject *curr;
53448 	duk_hobject *res;
53449 #if defined(DUK_USE_ES6_PROXY)
53450 	duk_hobject *h_proxy_target;
53451 	duk_hobject *h_proxy_handler;
53452 	duk_hobject *h_trap_result;
53453 #endif
53454 	duk_uint_fast32_t i, len;  /* used for array, stack, and entry indices */
53455 	duk_uint_fast32_t sort_start_index;
53456 
53457 	DUK_ASSERT(thr != NULL);
53458 
53459 	enum_target = duk_require_hobject(thr, -1);
53460 	DUK_ASSERT(enum_target != NULL);
53461 
53462 	duk_push_bare_object(thr);
53463 	res = duk_known_hobject(thr, -1);
53464 
53465 	/* [enum_target res] */
53466 
53467 	/* Target must be stored so that we can recheck whether or not
53468 	 * keys still exist when we enumerate.  This is not done if the
53469 	 * enumeration result comes from a proxy trap as there is no
53470 	 * real object to check against.
53471 	 */
53472 	duk_push_hobject(thr, enum_target);
53473 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_TARGET);
53474 
53475 	/* Initialize index so that we skip internal control keys. */
53476 	duk_push_int(thr, DUK__ENUM_START_INDEX);
53477 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_NEXT);
53478 
53479 	/*
53480 	 *  Proxy object handling
53481 	 */
53482 
53483 #if defined(DUK_USE_ES6_PROXY)
53484 	if (DUK_LIKELY((enum_flags & DUK_ENUM_NO_PROXY_BEHAVIOR) != 0)) {
53485 		goto skip_proxy;
53486 	}
53487 	if (DUK_LIKELY(!duk_hobject_proxy_check(enum_target,
53488 	                                        &h_proxy_target,
53489 	                                        &h_proxy_handler))) {
53490 		goto skip_proxy;
53491 	}
53492 
53493 	/* XXX: share code with Object.keys() Proxy handling */
53494 
53495 	/* In ES2015 for-in invoked the "enumerate" trap; in ES2016 "enumerate"
53496 	 * has been obsoleted and "ownKeys" is used instead.
53497 	 */
53498 	DUK_DDD(DUK_DDDPRINT("proxy enumeration"));
53499 	duk_push_hobject(thr, h_proxy_handler);
53500 	if (!duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_OWN_KEYS)) {
53501 		/* No need to replace the 'enum_target' value in stack, only the
53502 		 * enum_target reference.  This also ensures that the original
53503 		 * enum target is reachable, which keeps the proxy and the proxy
53504 		 * target reachable.  We do need to replace the internal _Target.
53505 		 */
53506 		DUK_DDD(DUK_DDDPRINT("no ownKeys trap, enumerate proxy target instead"));
53507 		DUK_DDD(DUK_DDDPRINT("h_proxy_target=%!O", (duk_heaphdr *) h_proxy_target));
53508 		enum_target = h_proxy_target;
53509 
53510 		duk_push_hobject(thr, enum_target);  /* -> [ ... enum_target res handler undefined target ] */
53511 		duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_INT_TARGET);
53512 
53513 		duk_pop_2(thr);  /* -> [ ... enum_target res ] */
53514 		goto skip_proxy;
53515 	}
53516 
53517 	/* [ ... enum_target res handler trap ] */
53518 	duk_insert(thr, -2);
53519 	duk_push_hobject(thr, h_proxy_target);    /* -> [ ... enum_target res trap handler target ] */
53520 	duk_call_method(thr, 1 /*nargs*/);        /* -> [ ... enum_target res trap_result ] */
53521 	h_trap_result = duk_require_hobject(thr, -1);
53522 	DUK_UNREF(h_trap_result);
53523 
53524 	duk_proxy_ownkeys_postprocess(thr, h_proxy_target, enum_flags);
53525 	/* -> [ ... enum_target res trap_result keys_array ] */
53526 
53527 	/* Copy cleaned up trap result keys into the enumerator object. */
53528 	/* XXX: result is a dense array; could make use of that. */
53529 	DUK_ASSERT(duk_is_array(thr, -1));
53530 	len = (duk_uint_fast32_t) duk_get_length(thr, -1);
53531 	for (i = 0; i < len; i++) {
53532 		(void) duk_get_prop_index(thr, -1, (duk_uarridx_t) i);
53533 		DUK_ASSERT(duk_is_string(thr, -1));  /* postprocess cleaned up */
53534 		/* [ ... enum_target res trap_result keys_array val ] */
53535 		duk_push_true(thr);
53536 		/* [ ... enum_target res trap_result keys_array val true ] */
53537 		duk_put_prop(thr, -5);
53538 	}
53539 	/* [ ... enum_target res trap_result keys_array ] */
53540 	duk_pop_2(thr);
53541 	duk_remove_m2(thr);
53542 
53543 	/* [ ... res ] */
53544 
53545 	/* The internal _Target property is kept pointing to the original
53546 	 * enumeration target (the proxy object), so that the enumerator
53547 	 * 'next' operation can read property values if so requested.  The
53548 	 * fact that the _Target is a proxy disables key existence check
53549 	 * during enumeration.
53550 	 */
53551 	DUK_DDD(DUK_DDDPRINT("proxy enumeration, final res: %!O", (duk_heaphdr *) res));
53552 	goto compact_and_return;
53553 
53554  skip_proxy:
53555 #endif  /* DUK_USE_ES6_PROXY */
53556 
53557 	curr = enum_target;
53558 	sort_start_index = DUK__ENUM_START_INDEX;
53559 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(res) == DUK__ENUM_START_INDEX);
53560 	while (curr) {
53561 		duk_uint_fast32_t sort_end_index;
53562 #if !defined(DUK_USE_PREFER_SIZE)
53563 		duk_bool_t need_sort = 0;
53564 #endif
53565 
53566 		/* Enumeration proceeds by inheritance level.  Virtual
53567 		 * properties need to be handled specially, followed by
53568 		 * array part, and finally entry part.
53569 		 *
53570 		 * If there are array index keys in the entry part or any
53571 		 * other risk of the ES2015 [[OwnPropertyKeys]] order being
53572 		 * violated, need_sort is set and an explicit ES2015 sort is
53573 		 * done for the inheritance level.
53574 		 */
53575 
53576 		/* XXX: inheriting from proxy */
53577 
53578 		/*
53579 		 *  Virtual properties.
53580 		 *
53581 		 *  String and buffer indices are virtual and always enumerable,
53582 		 *  'length' is virtual and non-enumerable.  Array and arguments
53583 		 *  object props have special behavior but are concrete.
53584 		 *
53585 		 *  String and buffer objects don't have an array part so as long
53586 		 *  as virtual array index keys are enumerated first, we don't
53587 		 *  need to set need_sort.
53588 		 */
53589 
53590 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
53591 		if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr) || DUK_HOBJECT_IS_BUFOBJ(curr)) {
53592 #else
53593 		if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr)) {
53594 #endif
53595 			duk_bool_t have_length = 1;
53596 
53597 			/* String and buffer enumeration behavior is identical now,
53598 			 * so use shared handler.
53599 			 */
53600 			if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr)) {
53601 				duk_hstring *h_val;
53602 				h_val = duk_hobject_get_internal_value_string(thr->heap, curr);
53603 				DUK_ASSERT(h_val != NULL);  /* string objects must not created without internal value */
53604 				len = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_val);
53605 			}
53606 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
53607 			else {
53608 				duk_hbufobj *h_bufobj;
53609 				DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ(curr));
53610 				h_bufobj = (duk_hbufobj *) curr;
53611 
53612 				if (h_bufobj == NULL || !h_bufobj->is_typedarray) {
53613 					/* Zero length seems like a good behavior for neutered buffers.
53614 					 * ArrayBuffer (non-view) and DataView don't have index properties
53615 					 * or .length property.
53616 					 */
53617 					len = 0;
53618 					have_length = 0;
53619 				} else {
53620 					/* There's intentionally no check for
53621 					 * current underlying buffer length.
53622 					 */
53623 					len = (duk_uint_fast32_t) (h_bufobj->length >> h_bufobj->shift);
53624 				}
53625 			}
53626 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
53627 
53628 			for (i = 0; i < len; i++) {
53629 				duk_hstring *k;
53630 
53631 				/* This is a bit fragile: the string is not
53632 				 * reachable until it is pushed by the helper.
53633 				 */
53634 				k = duk_heap_strtable_intern_u32_checked(thr, (duk_uint32_t) i);
53635 				DUK_ASSERT(k);
53636 
53637 				duk__add_enum_key(thr, k);
53638 
53639 				/* [enum_target res] */
53640 			}
53641 
53642 			/* 'length' and other virtual properties are not
53643 			 * enumerable, but are included if non-enumerable
53644 			 * properties are requested.
53645 			 */
53646 
53647 			if (have_length && (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
53648 				duk__add_enum_key_stridx(thr, DUK_STRIDX_LENGTH);
53649 			}
53650 		}
53651 
53652 		/*
53653 		 *  Array part
53654 		 */
53655 
53656 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(curr); i++) {
53657 			duk_hstring *k;
53658 			duk_tval *tv;
53659 
53660 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, curr, i);
53661 			if (DUK_TVAL_IS_UNUSED(tv)) {
53662 				continue;
53663 			}
53664 			k = duk_heap_strtable_intern_u32_checked(thr, (duk_uint32_t) i);  /* Fragile reachability. */
53665 			DUK_ASSERT(k);
53666 
53667 			duk__add_enum_key(thr, k);
53668 
53669 			/* [enum_target res] */
53670 		}
53671 
53672 		if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(curr)) {
53673 			/* Array .length comes after numeric indices. */
53674 			if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
53675 				duk__add_enum_key_stridx(thr, DUK_STRIDX_LENGTH);
53676 			}
53677 		}
53678 
53679 		/*
53680 		 *  Entries part
53681 		 */
53682 
53683 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(curr); i++) {
53684 			duk_hstring *k;
53685 
53686 			k = DUK_HOBJECT_E_GET_KEY(thr->heap, curr, i);
53687 			if (!k) {
53688 				continue;
53689 			}
53690 			if (!(enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) &&
53691 			    !DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(thr->heap, curr, i)) {
53692 				continue;
53693 			}
53694 			if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(k))) {
53695 				if (!(enum_flags & DUK_ENUM_INCLUDE_HIDDEN) &&
53696 				    DUK_HSTRING_HAS_HIDDEN(k)) {
53697 					continue;
53698 				}
53699 				if (!(enum_flags & DUK_ENUM_INCLUDE_SYMBOLS)) {
53700 					continue;
53701 				}
53702 #if !defined(DUK_USE_PREFER_SIZE)
53703 				need_sort = 1;
53704 #endif
53705 			} else {
53706 				DUK_ASSERT(!DUK_HSTRING_HAS_HIDDEN(k));  /* would also have symbol flag */
53707 				if (enum_flags & DUK_ENUM_EXCLUDE_STRINGS) {
53708 					continue;
53709 				}
53710 			}
53711 			if (DUK_HSTRING_HAS_ARRIDX(k)) {
53712 				/* This in currently only possible if the
53713 				 * object has no array part: the array part
53714 				 * is exhaustive when it is present.
53715 				 */
53716 #if !defined(DUK_USE_PREFER_SIZE)
53717 				need_sort = 1;
53718 #endif
53719 			} else {
53720 				if (enum_flags & DUK_ENUM_ARRAY_INDICES_ONLY) {
53721 					continue;
53722 				}
53723 			}
53724 
53725 			DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, curr, i) ||
53726 			           !DUK_TVAL_IS_UNUSED(&DUK_HOBJECT_E_GET_VALUE_PTR(thr->heap, curr, i)->v));
53727 
53728 			duk__add_enum_key(thr, k);
53729 
53730 			/* [enum_target res] */
53731 		}
53732 
53733 		/* Sort enumerated keys according to ES2015 requirements for
53734 		 * the "inheritance level" just processed.  This is far from
53735 		 * optimal, ES2015 semantics could be achieved more efficiently
53736 		 * by handling array index string keys (and symbol keys)
53737 		 * specially above in effect doing the sort inline.
53738 		 *
53739 		 * Skip the sort if array index sorting is requested because
53740 		 * we must consider all keys, also inherited, so an explicit
53741 		 * sort is done for the whole result after we're done with the
53742 		 * prototype chain.
53743 		 *
53744 		 * Also skip the sort if need_sort == 0, i.e. we know for
53745 		 * certain that the enumerated order is already correct.
53746 		 */
53747 		sort_end_index = DUK_HOBJECT_GET_ENEXT(res);
53748 
53749 		if (!(enum_flags & DUK_ENUM_SORT_ARRAY_INDICES)) {
53750 #if defined(DUK_USE_PREFER_SIZE)
53751 			duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) sort_start_index, (duk_int_fast32_t) sort_end_index);
53752 #else
53753 			if (need_sort) {
53754 				DUK_DDD(DUK_DDDPRINT("need to sort"));
53755 				duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) sort_start_index, (duk_int_fast32_t) sort_end_index);
53756 			} else {
53757 				DUK_DDD(DUK_DDDPRINT("no need to sort"));
53758 			}
53759 #endif
53760 		}
53761 
53762 		sort_start_index = sort_end_index;
53763 
53764 		if (enum_flags & DUK_ENUM_OWN_PROPERTIES_ONLY) {
53765 			break;
53766 		}
53767 
53768 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
53769 	}
53770 
53771 	/* [enum_target res] */
53772 
53773 	duk_remove_m2(thr);
53774 
53775 	/* [res] */
53776 
53777 	if (enum_flags & DUK_ENUM_SORT_ARRAY_INDICES) {
53778 		/* Some E5/E5.1 algorithms require that array indices are iterated
53779 		 * in a strictly ascending order.  This is the case for e.g.
53780 		 * Array.prototype.forEach() and JSON.stringify() PropertyList
53781 		 * handling.  The caller can request an explicit sort in these
53782 		 * cases.
53783 		 */
53784 
53785 		/* Sort to ES2015 order which works for pure array incides but
53786 		 * also for mixed keys.
53787 		 */
53788 		duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) DUK__ENUM_START_INDEX, (duk_int_fast32_t) DUK_HOBJECT_GET_ENEXT(res));
53789 	}
53790 
53791 #if defined(DUK_USE_ES6_PROXY)
53792  compact_and_return:
53793 #endif
53794 	/* compact; no need to seal because object is internal */
53795 	duk_hobject_compact_props(thr, res);
53796 
53797 	DUK_DDD(DUK_DDDPRINT("created enumerator object: %!iT", (duk_tval *) duk_get_tval(thr, -1)));
53798 }
53799 
53800 /*
53801  *  Returns non-zero if a key and/or value was enumerated, and:
53802  *
53803  *   [enum] -> [key]        (get_value == 0)
53804  *   [enum] -> [key value]  (get_value == 1)
53805  *
53806  *  Returns zero without pushing anything on the stack otherwise.
53807  */
53808 DUK_INTERNAL duk_bool_t duk_hobject_enumerator_next(duk_hthread *thr, duk_bool_t get_value) {
53809 	duk_hobject *e;
53810 	duk_hobject *enum_target;
53811 	duk_hstring *res = NULL;
53812 	duk_uint_fast32_t idx;
53813 	duk_bool_t check_existence;
53814 
53815 	DUK_ASSERT(thr != NULL);
53816 
53817 	/* [... enum] */
53818 
53819 	e = duk_require_hobject(thr, -1);
53820 
53821 	/* XXX use get tval ptr, more efficient */
53822 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_NEXT);
53823 	idx = (duk_uint_fast32_t) duk_require_uint(thr, -1);
53824 	duk_pop(thr);
53825 	DUK_DDD(DUK_DDDPRINT("enumeration: index is: %ld", (long) idx));
53826 
53827 	/* Enumeration keys are checked against the enumeration target (to see
53828 	 * that they still exist).  In the proxy enumeration case _Target will
53829 	 * be the proxy, and checking key existence against the proxy is not
53830 	 * required (or sensible, as the keys may be fully virtual).
53831 	 */
53832 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_TARGET);
53833 	enum_target = duk_require_hobject(thr, -1);
53834 	DUK_ASSERT(enum_target != NULL);
53835 #if defined(DUK_USE_ES6_PROXY)
53836 	check_existence = (!DUK_HOBJECT_IS_PROXY(enum_target));
53837 #else
53838 	check_existence = 1;
53839 #endif
53840 	duk_pop(thr);  /* still reachable */
53841 
53842 	DUK_DDD(DUK_DDDPRINT("getting next enum value, enum_target=%!iO, enumerator=%!iT",
53843 	                     (duk_heaphdr *) enum_target, (duk_tval *) duk_get_tval(thr, -1)));
53844 
53845 	/* no array part */
53846 	for (;;) {
53847 		duk_hstring *k;
53848 
53849 		if (idx >= DUK_HOBJECT_GET_ENEXT(e)) {
53850 			DUK_DDD(DUK_DDDPRINT("enumeration: ran out of elements"));
53851 			break;
53852 		}
53853 
53854 		/* we know these because enum objects are internally created */
53855 		k = DUK_HOBJECT_E_GET_KEY(thr->heap, e, idx);
53856 		DUK_ASSERT(k != NULL);
53857 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, e, idx));
53858 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(&DUK_HOBJECT_E_GET_VALUE(thr->heap, e, idx).v));
53859 
53860 		idx++;
53861 
53862 		/* recheck that the property still exists */
53863 		if (check_existence && !duk_hobject_hasprop_raw(thr, enum_target, k)) {
53864 			DUK_DDD(DUK_DDDPRINT("property deleted during enumeration, skip"));
53865 			continue;
53866 		}
53867 
53868 		DUK_DDD(DUK_DDDPRINT("enumeration: found element, key: %!O", (duk_heaphdr *) k));
53869 		res = k;
53870 		break;
53871 	}
53872 
53873 	DUK_DDD(DUK_DDDPRINT("enumeration: updating next index to %ld", (long) idx));
53874 
53875 	duk_push_u32(thr, (duk_uint32_t) idx);
53876 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_NEXT);
53877 
53878 	/* [... enum] */
53879 
53880 	if (res) {
53881 		duk_push_hstring(thr, res);
53882 		if (get_value) {
53883 			duk_push_hobject(thr, enum_target);
53884 			duk_dup_m2(thr);       /* -> [... enum key enum_target key] */
53885 			duk_get_prop(thr, -2); /* -> [... enum key enum_target val] */
53886 			duk_remove_m2(thr);    /* -> [... enum key val] */
53887 			duk_remove(thr, -3);   /* -> [... key val] */
53888 		} else {
53889 			duk_remove_m2(thr);    /* -> [... key] */
53890 		}
53891 		return 1;
53892 	} else {
53893 		duk_pop(thr);  /* -> [...] */
53894 		return 0;
53895 	}
53896 }
53897 
53898 /*
53899  *  Get enumerated keys in an ECMAScript array.  Matches Object.keys() behavior
53900  *  described in E5 Section 15.2.3.14.
53901  */
53902 
53903 DUK_INTERNAL duk_ret_t duk_hobject_get_enumerated_keys(duk_hthread *thr, duk_small_uint_t enum_flags) {
53904 	duk_hobject *e;
53905 	duk_hstring **keys;
53906 	duk_tval *tv;
53907 	duk_uint_fast32_t count;
53908 
53909 	DUK_ASSERT(thr != NULL);
53910 	DUK_ASSERT(duk_get_hobject(thr, -1) != NULL);
53911 
53912 	/* Create a temporary enumerator to get the (non-duplicated) key list;
53913 	 * the enumerator state is initialized without being needed, but that
53914 	 * has little impact.
53915 	 */
53916 
53917 	duk_hobject_enumerator_create(thr, enum_flags);
53918 	e = duk_known_hobject(thr, -1);
53919 
53920 	/* [enum_target enum res] */
53921 
53922 	/* Create dense result array to exact size. */
53923 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(e) >= DUK__ENUM_START_INDEX);
53924 	count = (duk_uint32_t) (DUK_HOBJECT_GET_ENEXT(e) - DUK__ENUM_START_INDEX);
53925 
53926 	/* XXX: uninit would be OK */
53927 	tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) count);
53928 	DUK_ASSERT(count == 0 || tv != NULL);
53929 
53930 	/* Fill result array, no side effects. */
53931 
53932 	keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, e);
53933 	keys += DUK__ENUM_START_INDEX;
53934 
53935 	while (count-- > 0) {
53936 		duk_hstring *k;
53937 
53938 		k = *keys++;
53939 		DUK_ASSERT(k != NULL);  /* enumerator must have no keys deleted */
53940 
53941 		DUK_TVAL_SET_STRING(tv, k);
53942 		tv++;
53943 		DUK_HSTRING_INCREF(thr, k);
53944 	}
53945 
53946 	/* [enum_target enum res] */
53947 	duk_remove_m2(thr);
53948 
53949 	/* [enum_target res] */
53950 
53951 	return 1;  /* return 1 to allow callers to tail call */
53952 }
53953 
53954 /* automatic undefs */
53955 #undef DUK__ENUM_START_INDEX
53956 #line 1 "duk_hobject_misc.c"
53957 /*
53958  *  Misc support functions
53959  */
53960 
53961 /* #include duk_internal.h -> already included */
53962 
53963 DUK_INTERNAL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h, duk_hobject *p, duk_bool_t ignore_loop) {
53964 	duk_uint_t sanity;
53965 
53966 	DUK_ASSERT(thr != NULL);
53967 
53968 	/* False if the object is NULL or the prototype 'p' is NULL.
53969 	 * In particular, false if both are NULL (don't compare equal).
53970 	 */
53971 	if (h == NULL || p == NULL) {
53972 		return 0;
53973 	}
53974 
53975 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
53976 	do {
53977 		if (h == p) {
53978 			return 1;
53979 		}
53980 
53981 		if (sanity-- == 0) {
53982 			if (ignore_loop) {
53983 				break;
53984 			} else {
53985 				DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
53986 				DUK_WO_NORETURN(return 0;);
53987 			}
53988 		}
53989 		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
53990 	} while (h);
53991 
53992 	return 0;
53993 }
53994 
53995 DUK_INTERNAL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p) {
53996 #if defined(DUK_USE_REFERENCE_COUNTING)
53997 	duk_hobject *tmp;
53998 
53999 	DUK_ASSERT(h);
54000 	tmp = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
54001 	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
54002 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, p);  /* avoid problems if p == h->prototype */
54003 	DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
54004 #else
54005 	DUK_ASSERT(h);
54006 	DUK_UNREF(thr);
54007 	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
54008 #endif
54009 }
54010 #line 1 "duk_hobject_pc2line.c"
54011 /*
54012  *  Helpers for creating and querying pc2line debug data, which
54013  *  converts a bytecode program counter to a source line number.
54014  *
54015  *  The run-time pc2line data is bit-packed, and documented in:
54016  *
54017  *    doc/function-objects.rst
54018  */
54019 
54020 /* #include duk_internal.h -> already included */
54021 
54022 #if defined(DUK_USE_PC2LINE)
54023 
54024 /* Generate pc2line data for an instruction sequence, leaving a buffer on stack top. */
54025 DUK_INTERNAL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length) {
54026 	duk_hbuffer_dynamic *h_buf;
54027 	duk_bitencoder_ctx be_ctx_alloc;
54028 	duk_bitencoder_ctx *be_ctx = &be_ctx_alloc;
54029 	duk_uint32_t *hdr;
54030 	duk_size_t new_size;
54031 	duk_uint_fast32_t num_header_entries;
54032 	duk_uint_fast32_t curr_offset;
54033 	duk_int_fast32_t curr_line, next_line, diff_line;
54034 	duk_uint_fast32_t curr_pc;
54035 	duk_uint_fast32_t hdr_index;
54036 
54037 	DUK_ASSERT(length <= DUK_COMPILER_MAX_BYTECODE_LENGTH);
54038 
54039 	num_header_entries = (length + DUK_PC2LINE_SKIP - 1) / DUK_PC2LINE_SKIP;
54040 	curr_offset = (duk_uint_fast32_t) (sizeof(duk_uint32_t) + num_header_entries * sizeof(duk_uint32_t) * 2);
54041 
54042 	duk_push_dynamic_buffer(thr, (duk_size_t) curr_offset);
54043 	h_buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, -1);
54044 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buf) && !DUK_HBUFFER_HAS_EXTERNAL(h_buf));
54045 
54046 	hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
54047 	DUK_ASSERT(hdr != NULL);
54048 	hdr[0] = (duk_uint32_t) length;  /* valid pc range is [0, length[ */
54049 
54050 	curr_pc = 0U;
54051 	while (curr_pc < length) {
54052 		new_size = (duk_size_t) (curr_offset + DUK_PC2LINE_MAX_DIFF_LENGTH);
54053 		duk_hbuffer_resize(thr, h_buf, new_size);
54054 
54055 		hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
54056 		DUK_ASSERT(hdr != NULL);
54057 		DUK_ASSERT(curr_pc < length);
54058 		hdr_index = 1 + (curr_pc / DUK_PC2LINE_SKIP) * 2;
54059 		curr_line = (duk_int_fast32_t) instrs[curr_pc].line;
54060 		hdr[hdr_index + 0] = (duk_uint32_t) curr_line;
54061 		hdr[hdr_index + 1] = (duk_uint32_t) curr_offset;
54062 
54063 #if 0
54064 		DUK_DDD(DUK_DDDPRINT("hdr[%ld]: pc=%ld line=%ld offset=%ld",
54065 		                     (long) (curr_pc / DUK_PC2LINE_SKIP),
54066 		                     (long) curr_pc,
54067 		                     (long) hdr[hdr_index + 0],
54068 		                     (long) hdr[hdr_index + 1]));
54069 #endif
54070 
54071 		duk_memzero(be_ctx, sizeof(*be_ctx));
54072 		be_ctx->data = ((duk_uint8_t *) hdr) + curr_offset;
54073 		be_ctx->length = (duk_size_t) DUK_PC2LINE_MAX_DIFF_LENGTH;
54074 
54075 		for (;;) {
54076 			curr_pc++;
54077 			if ( ((curr_pc % DUK_PC2LINE_SKIP) == 0) ||  /* end of diff run */
54078 			     (curr_pc >= length) ) {                 /* end of bytecode */
54079 				break;
54080 			}
54081 			DUK_ASSERT(curr_pc < length);
54082 			next_line = (duk_int32_t) instrs[curr_pc].line;
54083 			diff_line = next_line - curr_line;
54084 
54085 #if 0
54086 			DUK_DDD(DUK_DDDPRINT("curr_line=%ld, next_line=%ld -> diff_line=%ld",
54087 			                     (long) curr_line, (long) next_line, (long) diff_line));
54088 #endif
54089 
54090 			if (diff_line == 0) {
54091 				/* 0 */
54092 				duk_be_encode(be_ctx, 0, 1);
54093 			} else if (diff_line >= 1 && diff_line <= 4) {
54094 				/* 1 0 <2 bits> */
54095 				duk_be_encode(be_ctx, (duk_uint32_t) ((0x02 << 2) + (diff_line - 1)), 4);
54096 			} else if (diff_line >= -0x80 && diff_line <= 0x7f) {
54097 				/* 1 1 0 <8 bits> */
54098 				DUK_ASSERT(diff_line + 0x80 >= 0 && diff_line + 0x80 <= 0xff);
54099 				duk_be_encode(be_ctx, (duk_uint32_t) ((0x06 << 8) + (diff_line + 0x80)), 11);
54100 			} else {
54101 				/* 1 1 1 <32 bits>
54102 				 * Encode in two parts to avoid bitencode 24-bit limitation
54103 				 */
54104 				duk_be_encode(be_ctx, (duk_uint32_t) ((0x07 << 16) + ((next_line >> 16) & 0xffff)), 19);
54105 				duk_be_encode(be_ctx, (duk_uint32_t) (next_line & 0xffff), 16);
54106 			}
54107 
54108 			curr_line = next_line;
54109 		}
54110 
54111 		duk_be_finish(be_ctx);
54112 		DUK_ASSERT(!be_ctx->truncated);
54113 
54114 		/* be_ctx->offset == length of encoded bitstream */
54115 		curr_offset += (duk_uint_fast32_t) be_ctx->offset;
54116 	}
54117 
54118 	/* compact */
54119 	new_size = (duk_size_t) curr_offset;
54120 	duk_hbuffer_resize(thr, h_buf, new_size);
54121 
54122 	(void) duk_to_fixed_buffer(thr, -1, NULL);
54123 
54124 	DUK_DDD(DUK_DDDPRINT("final pc2line data: pc_limit=%ld, length=%ld, %lf bits/opcode --> %!ixT",
54125 	                     (long) length, (long) new_size, (double) new_size * 8.0 / (double) length,
54126 	                     (duk_tval *) duk_get_tval(thr, -1)));
54127 }
54128 
54129 /* PC is unsigned.  If caller does PC arithmetic and gets a negative result,
54130  * it will map to a large PC which is out of bounds and causes a zero to be
54131  * returned.
54132  */
54133 DUK_LOCAL duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hthread *thr, duk_hbuffer_fixed *buf, duk_uint_fast32_t pc) {
54134 	duk_bitdecoder_ctx bd_ctx_alloc;
54135 	duk_bitdecoder_ctx *bd_ctx = &bd_ctx_alloc;
54136 	duk_uint32_t *hdr;
54137 	duk_uint_fast32_t start_offset;
54138 	duk_uint_fast32_t pc_limit;
54139 	duk_uint_fast32_t hdr_index;
54140 	duk_uint_fast32_t pc_base;
54141 	duk_uint_fast32_t n;
54142 	duk_uint_fast32_t curr_line;
54143 
54144 	DUK_ASSERT(buf != NULL);
54145 	DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) buf) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) buf));
54146 	DUK_UNREF(thr);
54147 
54148 	/*
54149 	 *  Use the index in the header to find the right starting point
54150 	 */
54151 
54152 	hdr_index = pc / DUK_PC2LINE_SKIP;
54153 	pc_base = hdr_index * DUK_PC2LINE_SKIP;
54154 	n = pc - pc_base;
54155 
54156 	if (DUK_HBUFFER_FIXED_GET_SIZE(buf) <= sizeof(duk_uint32_t)) {
54157 		DUK_DD(DUK_DDPRINT("pc2line lookup failed: buffer is smaller than minimal header"));
54158 		goto pc2line_error;
54159 	}
54160 
54161 	hdr = (duk_uint32_t *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, buf);
54162 	pc_limit = hdr[0];
54163 	if (pc >= pc_limit) {
54164 		/* Note: pc is unsigned and cannot be negative */
54165 		DUK_DD(DUK_DDPRINT("pc2line lookup failed: pc out of bounds (pc=%ld, limit=%ld)",
54166 		                   (long) pc, (long) pc_limit));
54167 		goto pc2line_error;
54168 	}
54169 
54170 	curr_line = hdr[1 + hdr_index * 2];
54171 	start_offset = hdr[1 + hdr_index * 2 + 1];
54172 	if ((duk_size_t) start_offset > DUK_HBUFFER_FIXED_GET_SIZE(buf)) {
54173 		DUK_DD(DUK_DDPRINT("pc2line lookup failed: start_offset out of bounds (start_offset=%ld, buffer_size=%ld)",
54174 		                   (long) start_offset, (long) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) buf)));
54175 		goto pc2line_error;
54176 	}
54177 
54178 	/*
54179 	 *  Iterate the bitstream (line diffs) until PC is reached
54180 	 */
54181 
54182 	duk_memzero(bd_ctx, sizeof(*bd_ctx));
54183 	bd_ctx->data = ((duk_uint8_t *) hdr) + start_offset;
54184 	bd_ctx->length = (duk_size_t) (DUK_HBUFFER_FIXED_GET_SIZE(buf) - start_offset);
54185 
54186 #if 0
54187 	DUK_DDD(DUK_DDDPRINT("pc2line lookup: pc=%ld -> hdr_index=%ld, pc_base=%ld, n=%ld, start_offset=%ld",
54188 	                     (long) pc, (long) hdr_index, (long) pc_base, (long) n, (long) start_offset));
54189 #endif
54190 
54191 	while (n > 0) {
54192 #if 0
54193 		DUK_DDD(DUK_DDDPRINT("lookup: n=%ld, curr_line=%ld", (long) n, (long) curr_line));
54194 #endif
54195 
54196 		if (duk_bd_decode_flag(bd_ctx)) {
54197 			if (duk_bd_decode_flag(bd_ctx)) {
54198 				if (duk_bd_decode_flag(bd_ctx)) {
54199 					/* 1 1 1 <32 bits> */
54200 					duk_uint_fast32_t t;
54201 					t = duk_bd_decode(bd_ctx, 16);  /* workaround: max nbits = 24 now */
54202 					t = (t << 16) + duk_bd_decode(bd_ctx, 16);
54203 					curr_line = t;
54204 				} else {
54205 					/* 1 1 0 <8 bits> */
54206 					duk_uint_fast32_t t;
54207 					t = duk_bd_decode(bd_ctx, 8);
54208 					curr_line = curr_line + t - 0x80;
54209 				}
54210 			} else {
54211 				/* 1 0 <2 bits> */
54212 				duk_uint_fast32_t t;
54213 				t = duk_bd_decode(bd_ctx, 2);
54214 				curr_line = curr_line + t + 1;
54215 			}
54216 		} else {
54217 			/* 0: no change */
54218 		}
54219 
54220 		n--;
54221 	}
54222 
54223 	DUK_DDD(DUK_DDDPRINT("pc2line lookup result: pc %ld -> line %ld", (long) pc, (long) curr_line));
54224 	return curr_line;
54225 
54226  pc2line_error:
54227 	DUK_D(DUK_DPRINT("pc2line conversion failed for pc=%ld", (long) pc));
54228 	return 0;
54229 }
54230 
54231 DUK_INTERNAL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_idx_t idx_func, duk_uint_fast32_t pc) {
54232 	duk_hbuffer_fixed *pc2line;
54233 	duk_uint_fast32_t line;
54234 
54235 	/* XXX: now that pc2line is used by the debugger quite heavily in
54236 	 * checked execution, this should be optimized to avoid value stack
54237 	 * and perhaps also implement some form of pc2line caching (see
54238 	 * future work in debugger.rst).
54239 	 */
54240 
54241 	duk_get_prop_stridx(thr, idx_func, DUK_STRIDX_INT_PC2LINE);
54242 	pc2line = (duk_hbuffer_fixed *) (void *) duk_get_hbuffer(thr, -1);
54243 	if (pc2line != NULL) {
54244 		DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) pc2line) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) pc2line));
54245 		line = duk__hobject_pc2line_query_raw(thr, pc2line, (duk_uint_fast32_t) pc);
54246 	} else {
54247 		line = 0;
54248 	}
54249 	duk_pop(thr);
54250 
54251 	return line;
54252 }
54253 
54254 #endif  /* DUK_USE_PC2LINE */
54255 #line 1 "duk_hobject_props.c"
54256 /*
54257  *  duk_hobject property access functionality.
54258  *
54259  *  This is very central functionality for size, performance, and compliance.
54260  *  It is also rather intricate; see hobject-algorithms.rst for discussion on
54261  *  the algorithms and memory-management.rst for discussion on refcounts and
54262  *  side effect issues.
54263  *
54264  *  Notes:
54265  *
54266  *    - It might be tempting to assert "refcount nonzero" for objects
54267  *      being operated on, but that's not always correct: objects with
54268  *      a zero refcount may be operated on by the refcount implementation
54269  *      (finalization) for instance.  Hence, no refcount assertions are made.
54270  *
54271  *    - Many operations (memory allocation, identifier operations, etc)
54272  *      may cause arbitrary side effects (e.g. through GC and finalization).
54273  *      These side effects may invalidate duk_tval pointers which point to
54274  *      areas subject to reallocation (like value stack).  Heap objects
54275  *      themselves have stable pointers.  Holding heap object pointers or
54276  *      duk_tval copies is not problematic with respect to side effects;
54277  *      care must be taken when holding and using argument duk_tval pointers.
54278  *
54279  *    - If a finalizer is executed, it may operate on the the same object
54280  *      we're currently dealing with.  For instance, the finalizer might
54281  *      delete a certain property which has already been looked up and
54282  *      confirmed to exist.  Ideally finalizers would be disabled if GC
54283  *      happens during property access.  At the moment property table realloc
54284  *      disables finalizers, and all DECREFs may cause arbitrary changes so
54285  *      handle DECREF carefully.
54286  *
54287  *    - The order of operations for a DECREF matters.  When DECREF is executed,
54288  *      the entire object graph must be consistent; note that a refzero may
54289  *      lead to a mark-and-sweep through a refcount finalizer.  Use NORZ macros
54290  *      and an explicit DUK_REFZERO_CHECK_xxx() if achieving correct order is hard.
54291  */
54292 
54293 /*
54294  *  XXX: array indices are mostly typed as duk_uint32_t here; duk_uarridx_t
54295  *  might be more appropriate.
54296  */
54297 
54298 /* #include duk_internal.h -> already included */
54299 
54300 /*
54301  *  Local defines
54302  */
54303 
54304 #define DUK__NO_ARRAY_INDEX             DUK_HSTRING_NO_ARRAY_INDEX
54305 
54306 /* Marker values for hash part. */
54307 #define DUK__HASH_UNUSED                DUK_HOBJECT_HASHIDX_UNUSED
54308 #define DUK__HASH_DELETED               DUK_HOBJECT_HASHIDX_DELETED
54309 
54310 /* Valstack space that suffices for all local calls, excluding any recursion
54311  * into ECMAScript or Duktape/C calls (Proxy, getters, etc).
54312  */
54313 #define DUK__VALSTACK_SPACE             10
54314 
54315 /* Valstack space allocated especially for proxy lookup which does a
54316  * recursive property lookup.
54317  */
54318 #define DUK__VALSTACK_PROXY_LOOKUP      20
54319 
54320 /*
54321  *  Local prototypes
54322  */
54323 
54324 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);
54325 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);
54326 DUK_LOCAL_DECL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc);
54327 
54328 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);
54329 DUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj);
54330 
54331 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);
54332 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);
54333 
54334 /*
54335  *  Misc helpers
54336  */
54337 
54338 /* Convert a duk_tval number (caller checks) to a 32-bit index.  Returns
54339  * DUK__NO_ARRAY_INDEX if the number is not whole or not a valid array
54340  * index.
54341  */
54342 /* XXX: for fastints, could use a variant which assumes a double duk_tval
54343  * (and doesn't need to check for fastint again).
54344  */
54345 DUK_LOCAL duk_uint32_t duk__tval_number_to_arr_idx(duk_tval *tv) {
54346 	duk_double_t dbl;
54347 	duk_uint32_t idx;
54348 
54349 	DUK_ASSERT(tv != NULL);
54350 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
54351 
54352 	/* -0 is accepted here as index 0 because ToString(-0) == "0" which is
54353 	 * in canonical form and thus an array index.
54354 	 */
54355 	dbl = DUK_TVAL_GET_NUMBER(tv);
54356 	idx = (duk_uint32_t) dbl;
54357 	if ((duk_double_t) idx == dbl) {
54358 	        /* Is whole and within 32 bit range.  If the value happens to be 0xFFFFFFFF,
54359 		 * it's not a valid array index but will then match DUK__NO_ARRAY_INDEX.
54360 		 */
54361 		return idx;
54362 	}
54363 	return DUK__NO_ARRAY_INDEX;
54364 }
54365 
54366 #if defined(DUK_USE_FASTINT)
54367 /* Convert a duk_tval fastint (caller checks) to a 32-bit index. */
54368 DUK_LOCAL duk_uint32_t duk__tval_fastint_to_arr_idx(duk_tval *tv) {
54369 	duk_int64_t t;
54370 
54371 	DUK_ASSERT(tv != NULL);
54372 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
54373 
54374 	t = DUK_TVAL_GET_FASTINT(tv);
54375 	if (((duk_uint64_t) t & ~DUK_U64_CONSTANT(0xffffffff)) != 0) {
54376 		/* Catches >0x100000000 and negative values. */
54377 		return DUK__NO_ARRAY_INDEX;
54378 	}
54379 
54380 	/* If the value happens to be 0xFFFFFFFF, it's not a valid array index
54381 	 * but will then match DUK__NO_ARRAY_INDEX.
54382 	 */
54383 	return (duk_uint32_t) t;
54384 }
54385 #endif  /* DUK_USE_FASTINT */
54386 
54387 /* Convert a duk_tval on the value stack (in a trusted index we don't validate)
54388  * to a string or symbol using ES2015 ToPropertyKey():
54389  * http://www.ecma-international.org/ecma-262/6.0/#sec-topropertykey.
54390  *
54391  * Also check if it's a valid array index and return that (or DUK__NO_ARRAY_INDEX
54392  * if not).
54393  */
54394 DUK_LOCAL duk_uint32_t duk__to_property_key(duk_hthread *thr, duk_idx_t idx, duk_hstring **out_h) {
54395 	duk_uint32_t arr_idx;
54396 	duk_hstring *h;
54397 	duk_tval *tv_dst;
54398 
54399 	DUK_ASSERT(thr != NULL);
54400 	DUK_ASSERT(out_h != NULL);
54401 	DUK_ASSERT(duk_is_valid_index(thr, idx));
54402 	DUK_ASSERT(idx < 0);
54403 
54404 	/* XXX: The revised ES2015 ToPropertyKey() handling (ES5.1 was just
54405 	 * ToString()) involves a ToPrimitive(), a symbol check, and finally
54406 	 * a ToString().  Figure out the best way to have a good fast path
54407 	 * but still be compliant and share code.
54408 	 */
54409 
54410 	tv_dst = DUK_GET_TVAL_NEGIDX(thr, idx);  /* intentionally unvalidated */
54411 	if (DUK_TVAL_IS_STRING(tv_dst)) {
54412 		/* Most important path: strings and plain symbols are used as
54413 		 * is.  For symbols the array index check below is unnecessary
54414 		 * (they're never valid array indices) but checking that the
54415 		 * string is a symbol would make the plain string path slower
54416 		 * unnecessarily.
54417 		 */
54418 		h = DUK_TVAL_GET_STRING(tv_dst);
54419 	} else {
54420 		h = duk_to_property_key_hstring(thr, idx);
54421 	}
54422 	DUK_ASSERT(h != NULL);
54423 	*out_h = h;
54424 
54425 	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(h);
54426 	return arr_idx;
54427 }
54428 
54429 DUK_LOCAL duk_uint32_t duk__push_tval_to_property_key(duk_hthread *thr, duk_tval *tv_key, duk_hstring **out_h) {
54430 	duk_push_tval(thr, tv_key);  /* XXX: could use an unsafe push here */
54431 	return duk__to_property_key(thr, -1, out_h);
54432 }
54433 
54434 /* String is an own (virtual) property of a plain buffer. */
54435 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) {
54436 	DUK_UNREF(thr);
54437 
54438 	/* Virtual index properties.  Checking explicitly for
54439 	 * 'arr_idx != DUK__NO_ARRAY_INDEX' is not necessary
54440 	 * because DUK__NO_ARRAY_INDEXi is always larger than
54441 	 * maximum allowed buffer size.
54442 	 */
54443 	DUK_ASSERT(DUK__NO_ARRAY_INDEX >= DUK_HBUFFER_GET_SIZE(buf));
54444 	if (arr_idx < DUK_HBUFFER_GET_SIZE(buf)) {
54445 		return 1;
54446 	}
54447 
54448 	/* Other virtual properties. */
54449 	return (key == DUK_HTHREAD_STRING_LENGTH(thr));
54450 }
54451 
54452 /*
54453  *  Helpers for managing property storage size
54454  */
54455 
54456 /* Get default hash part size for a certain entry part size. */
54457 #if defined(DUK_USE_HOBJECT_HASH_PART)
54458 DUK_LOCAL duk_uint32_t duk__get_default_h_size(duk_uint32_t e_size) {
54459 	DUK_ASSERT(e_size <= DUK_HOBJECT_MAX_PROPERTIES);
54460 
54461 	if (e_size >= DUK_USE_HOBJECT_HASH_PROP_LIMIT) {
54462 		duk_uint32_t res;
54463 		duk_uint32_t tmp;
54464 
54465 		/* Hash size should be 2^N where N is chosen so that 2^N is
54466 		 * larger than e_size.  Extra shifting is used to ensure hash
54467 		 * is relatively sparse.
54468 		 */
54469 		tmp = e_size;
54470 		res = 2;  /* Result will be 2 ** (N + 1). */
54471 		while (tmp >= 0x40) {
54472 			tmp >>= 6;
54473 			res <<= 6;
54474 		}
54475 		while (tmp != 0) {
54476 			tmp >>= 1;
54477 			res <<= 1;
54478 		}
54479 		DUK_ASSERT((DUK_HOBJECT_MAX_PROPERTIES << 2U) > DUK_HOBJECT_MAX_PROPERTIES);  /* Won't wrap, even shifted by 2. */
54480 		DUK_ASSERT(res > e_size);
54481 		return res;
54482 	} else {
54483 		return 0;
54484 	}
54485 }
54486 #endif  /* USE_PROP_HASH_PART */
54487 
54488 /* Get minimum entry part growth for a certain size. */
54489 DUK_LOCAL duk_uint32_t duk__get_min_grow_e(duk_uint32_t e_size) {
54490 	duk_uint32_t res;
54491 
54492 	DUK_ASSERT(e_size <= DUK_HOBJECT_MAX_PROPERTIES);
54493 
54494 	res = (e_size + DUK_USE_HOBJECT_ENTRY_MINGROW_ADD) / DUK_USE_HOBJECT_ENTRY_MINGROW_DIVISOR;
54495 	DUK_ASSERT(res >= 1);  /* important for callers */
54496 	return res;
54497 }
54498 
54499 /* Get minimum array part growth for a certain size. */
54500 DUK_LOCAL duk_uint32_t duk__get_min_grow_a(duk_uint32_t a_size) {
54501 	duk_uint32_t res;
54502 
54503 	DUK_ASSERT((duk_size_t) a_size <= DUK_HOBJECT_MAX_PROPERTIES);
54504 
54505 	res = (a_size + DUK_USE_HOBJECT_ARRAY_MINGROW_ADD) / DUK_USE_HOBJECT_ARRAY_MINGROW_DIVISOR;
54506 	DUK_ASSERT(res >= 1);  /* important for callers */
54507 	return res;
54508 }
54509 
54510 /* Count actually used entry part entries (non-NULL keys). */
54511 DUK_LOCAL duk_uint32_t duk__count_used_e_keys(duk_hthread *thr, duk_hobject *obj) {
54512 	duk_uint_fast32_t i;
54513 	duk_uint_fast32_t n = 0;
54514 	duk_hstring **e;
54515 
54516 	DUK_ASSERT(obj != NULL);
54517 	DUK_UNREF(thr);
54518 
54519 	e = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, obj);
54520 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
54521 		if (*e++) {
54522 			n++;
54523 		}
54524 	}
54525 	return (duk_uint32_t) n;
54526 }
54527 
54528 /* Count actually used array part entries and array minimum size.
54529  * NOTE: 'out_min_size' can be computed much faster by starting from the
54530  * end and breaking out early when finding first used entry, but this is
54531  * not needed now.
54532  */
54533 DUK_LOCAL void duk__compute_a_stats(duk_hthread *thr, duk_hobject *obj, duk_uint32_t *out_used, duk_uint32_t *out_min_size) {
54534 	duk_uint_fast32_t i;
54535 	duk_uint_fast32_t used = 0;
54536 	duk_uint_fast32_t highest_idx = (duk_uint_fast32_t) -1;  /* see below */
54537 	duk_tval *a;
54538 
54539 	DUK_ASSERT(obj != NULL);
54540 	DUK_ASSERT(out_used != NULL);
54541 	DUK_ASSERT(out_min_size != NULL);
54542 	DUK_UNREF(thr);
54543 
54544 	a = DUK_HOBJECT_A_GET_BASE(thr->heap, obj);
54545 	for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
54546 		duk_tval *tv = a++;
54547 		if (!DUK_TVAL_IS_UNUSED(tv)) {
54548 			used++;
54549 			highest_idx = i;
54550 		}
54551 	}
54552 
54553 	/* Initial value for highest_idx is -1 coerced to unsigned.  This
54554 	 * is a bit odd, but (highest_idx + 1) will then wrap to 0 below
54555 	 * for out_min_size as intended.
54556 	 */
54557 
54558 	*out_used = (duk_uint32_t) used;
54559 	*out_min_size = (duk_uint32_t) (highest_idx + 1);  /* 0 if no used entries */
54560 }
54561 
54562 /* Check array density and indicate whether or not the array part should be abandoned. */
54563 DUK_LOCAL duk_bool_t duk__abandon_array_density_check(duk_uint32_t a_used, duk_uint32_t a_size) {
54564 	/*
54565 	 *  Array abandon check; abandon if:
54566 	 *
54567 	 *    new_used / new_size < limit
54568 	 *    new_used < limit * new_size        || limit is 3 bits fixed point
54569 	 *    new_used < limit' / 8 * new_size   || *8
54570 	 *    8*new_used < limit' * new_size     || :8
54571 	 *    new_used < limit' * (new_size / 8)
54572 	 *
54573 	 *  Here, new_used = a_used, new_size = a_size.
54574 	 *
54575 	 *  Note: some callers use approximate values for a_used and/or a_size
54576 	 *  (e.g. dropping a '+1' term).  This doesn't affect the usefulness
54577 	 *  of the check, but may confuse debugging.
54578 	 */
54579 
54580 	return (a_used < DUK_USE_HOBJECT_ARRAY_ABANDON_LIMIT * (a_size >> 3));
54581 }
54582 
54583 /* Fast check for extending array: check whether or not a slow density check is required. */
54584 DUK_LOCAL duk_bool_t duk__abandon_array_slow_check_required(duk_uint32_t arr_idx, duk_uint32_t old_size) {
54585 	/*
54586 	 *  In a fast check we assume old_size equals old_used (i.e., existing
54587 	 *  array is fully dense).
54588 	 *
54589 	 *  Slow check if:
54590 	 *
54591 	 *    (new_size - old_size) / old_size > limit
54592 	 *    new_size - old_size > limit * old_size
54593 	 *    new_size > (1 + limit) * old_size        || limit' is 3 bits fixed point
54594 	 *    new_size > (1 + (limit' / 8)) * old_size || * 8
54595 	 *    8 * new_size > (8 + limit') * old_size   || : 8
54596 	 *    new_size > (8 + limit') * (old_size / 8)
54597 	 *    new_size > limit'' * (old_size / 8)      || limit'' = 9 -> max 25% increase
54598 	 *    arr_idx + 1 > limit'' * (old_size / 8)
54599 	 *
54600 	 *  This check doesn't work well for small values, so old_size is rounded
54601 	 *  up for the check (and the '+ 1' of arr_idx can be ignored in practice):
54602 	 *
54603 	 *    arr_idx > limit'' * ((old_size + 7) / 8)
54604 	 */
54605 
54606 	return (arr_idx > DUK_USE_HOBJECT_ARRAY_FAST_RESIZE_LIMIT * ((old_size + 7) >> 3));
54607 }
54608 
54609 /*
54610  *  Proxy helpers
54611  */
54612 
54613 #if defined(DUK_USE_ES6_PROXY)
54614 DUK_INTERNAL duk_bool_t duk_hobject_proxy_check(duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler) {
54615 	duk_hproxy *h_proxy;
54616 
54617 	DUK_ASSERT(obj != NULL);
54618 	DUK_ASSERT(out_target != NULL);
54619 	DUK_ASSERT(out_handler != NULL);
54620 
54621 	/* Caller doesn't need to check exotic proxy behavior (but does so for
54622 	 * some fast paths).
54623 	 */
54624 	if (DUK_LIKELY(!DUK_HOBJECT_IS_PROXY(obj))) {
54625 		return 0;
54626 	}
54627 	h_proxy = (duk_hproxy *) obj;
54628 	DUK_ASSERT_HPROXY_VALID(h_proxy);
54629 
54630 	DUK_ASSERT(h_proxy->handler != NULL);
54631 	DUK_ASSERT(h_proxy->target != NULL);
54632 	*out_handler = h_proxy->handler;
54633 	*out_target = h_proxy->target;
54634 
54635 	return 1;
54636 }
54637 #endif  /* DUK_USE_ES6_PROXY */
54638 
54639 /* Get Proxy target object.  If the argument is not a Proxy, return it as is.
54640  * If a Proxy is revoked, an error is thrown.
54641  */
54642 #if defined(DUK_USE_ES6_PROXY)
54643 DUK_INTERNAL duk_hobject *duk_hobject_resolve_proxy_target(duk_hobject *obj) {
54644 	DUK_ASSERT(obj != NULL);
54645 
54646 	/* Resolve Proxy targets until Proxy chain ends.  No explicit check for
54647 	 * a Proxy loop: user code cannot create such a loop (it would only be
54648 	 * possible by editing duk_hproxy references directly).
54649 	 */
54650 
54651 	while (DUK_HOBJECT_IS_PROXY(obj)) {
54652 		duk_hproxy *h_proxy;
54653 
54654 		h_proxy = (duk_hproxy *) obj;
54655 		DUK_ASSERT_HPROXY_VALID(h_proxy);
54656 		obj = h_proxy->target;
54657 		DUK_ASSERT(obj != NULL);
54658 	}
54659 
54660 	DUK_ASSERT(obj != NULL);
54661 	return obj;
54662 }
54663 #endif  /* DUK_USE_ES6_PROXY */
54664 
54665 #if defined(DUK_USE_ES6_PROXY)
54666 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) {
54667 	duk_hobject *h_handler;
54668 
54669 	DUK_ASSERT(thr != NULL);
54670 	DUK_ASSERT(obj != NULL);
54671 	DUK_ASSERT(tv_key != NULL);
54672 	DUK_ASSERT(out_target != NULL);
54673 
54674 	if (!duk_hobject_proxy_check(obj, out_target, &h_handler)) {
54675 		return 0;
54676 	}
54677 	DUK_ASSERT(*out_target != NULL);
54678 	DUK_ASSERT(h_handler != NULL);
54679 
54680 	/* XXX: At the moment Duktape accesses internal keys like _Finalizer using a
54681 	 * normal property set/get which would allow a proxy handler to interfere with
54682 	 * such behavior and to get access to internal key strings.  This is not a problem
54683 	 * as such because internal key strings can be created in other ways too (e.g.
54684 	 * through buffers).  The best fix is to change Duktape internal lookups to
54685 	 * skip proxy behavior.  Until that, internal property accesses bypass the
54686 	 * proxy and are applied to the target (as if the handler did not exist).
54687 	 * This has some side effects, see test-bi-proxy-internal-keys.js.
54688 	 */
54689 
54690 	if (DUK_TVAL_IS_STRING(tv_key)) {
54691 		duk_hstring *h_key = (duk_hstring *) DUK_TVAL_GET_STRING(tv_key);
54692 		DUK_ASSERT(h_key != NULL);
54693 		if (DUK_HSTRING_HAS_HIDDEN(h_key)) {
54694 			/* Symbol accesses must go through proxy lookup in ES2015.
54695 			 * Hidden symbols behave like Duktape 1.x internal keys
54696 			 * and currently won't.
54697 			 */
54698 			DUK_DDD(DUK_DDDPRINT("hidden key, skip proxy handler and apply to target"));
54699 			return 0;
54700 		}
54701 	}
54702 
54703 	/* The handler is looked up with a normal property lookup; it may be an
54704 	 * accessor or the handler object itself may be a proxy object.  If the
54705 	 * handler is a proxy, we need to extend the valstack as we make a
54706 	 * recursive proxy check without a function call in between (in fact
54707 	 * there is no limit to the potential recursion here).
54708 	 *
54709 	 * (For sanity, proxy creation rejects another proxy object as either
54710 	 * the handler or the target at the moment so recursive proxy cases
54711 	 * are not realized now.)
54712 	 */
54713 
54714 	/* XXX: C recursion limit if proxies are allowed as handler/target values */
54715 
54716 	duk_require_stack(thr, DUK__VALSTACK_PROXY_LOOKUP);
54717 	duk_push_hobject(thr, h_handler);
54718 	if (duk_get_prop_stridx_short(thr, -1, stridx_trap)) {
54719 		/* -> [ ... handler trap ] */
54720 		duk_insert(thr, -2);  /* -> [ ... trap handler ] */
54721 
54722 		/* stack prepped for func call: [ ... trap handler ] */
54723 		return 1;
54724 	} else {
54725 		duk_pop_2_unsafe(thr);
54726 		return 0;
54727 	}
54728 }
54729 #endif  /* DUK_USE_ES6_PROXY */
54730 
54731 /*
54732  *  Reallocate property allocation, moving properties to the new allocation.
54733  *
54734  *  Includes key compaction, rehashing, and can also optionally abandon
54735  *  the array part, 'migrating' array entries into the beginning of the
54736  *  new entry part.
54737  *
54738  *  There is no support for in-place reallocation or just compacting keys
54739  *  without resizing the property allocation.  This is intentional to keep
54740  *  code size minimal, but would be useful future work.
54741  *
54742  *  The implementation is relatively straightforward, except for the array
54743  *  abandonment process.  Array abandonment requires that new string keys
54744  *  are interned, which may trigger GC.  All keys interned so far must be
54745  *  reachable for GC at all times and correctly refcounted for; valstack is
54746  *  used for that now.
54747  *
54748  *  Also, a GC triggered during this reallocation process must not interfere
54749  *  with the object being resized.  This is currently controlled by preventing
54750  *  finalizers (as they may affect ANY object) and object compaction in
54751  *  mark-and-sweep.  It would suffice to protect only this particular object
54752  *  from compaction, however.  DECREF refzero cascades are side effect free
54753  *  and OK.
54754  *
54755  *  Note: because we need to potentially resize the valstack (as part
54756  *  of abandoning the array part), any tval pointers to the valstack
54757  *  will become invalid after this call.
54758  */
54759 
54760 DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
54761                                             duk_hobject *obj,
54762                                             duk_uint32_t new_e_size,
54763                                             duk_uint32_t new_a_size,
54764                                             duk_uint32_t new_h_size,
54765                                             duk_bool_t abandon_array) {
54766 	duk_small_uint_t prev_ms_base_flags;
54767 	duk_uint32_t new_alloc_size;
54768 	duk_uint32_t new_e_size_adjusted;
54769 	duk_uint8_t *new_p;
54770 	duk_hstring **new_e_k;
54771 	duk_propvalue *new_e_pv;
54772 	duk_uint8_t *new_e_f;
54773 	duk_tval *new_a;
54774 	duk_uint32_t *new_h;
54775 	duk_uint32_t new_e_next;
54776 	duk_uint_fast32_t i;
54777 	duk_size_t array_copy_size;
54778 #if defined(DUK_USE_ASSERTIONS)
54779 	duk_bool_t prev_error_not_allowed;
54780 #endif
54781 
54782 	DUK_ASSERT(thr != NULL);
54783 	DUK_ASSERT(obj != NULL);
54784 	DUK_ASSERT(!abandon_array || new_a_size == 0);  /* if abandon_array, new_a_size must be 0 */
54785 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || (DUK_HOBJECT_GET_ESIZE(obj) == 0 && DUK_HOBJECT_GET_ASIZE(obj) == 0));
54786 	DUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size);  /* required to guarantee success of rehashing,
54787 	                                                           * intentionally use unadjusted new_e_size
54788 	                                                           */
54789 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
54790 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
54791 
54792 	DUK_STATS_INC(thr->heap, stats_object_realloc_props);
54793 
54794 	/*
54795 	 *  Pre resize assertions.
54796 	 */
54797 
54798 #if defined(DUK_USE_ASSERTIONS)
54799 	/* XXX: pre-checks (such as no duplicate keys) */
54800 #endif
54801 
54802 	/*
54803 	 *  For property layout 1, tweak e_size to ensure that the whole entry
54804 	 *  part (key + val + flags) is a suitable multiple for alignment
54805 	 *  (platform specific).
54806 	 *
54807 	 *  Property layout 2 does not require this tweaking and is preferred
54808 	 *  on low RAM platforms requiring alignment.
54809 	 */
54810 
54811 #if defined(DUK_USE_HOBJECT_LAYOUT_2) || defined(DUK_USE_HOBJECT_LAYOUT_3)
54812 	DUK_DDD(DUK_DDDPRINT("using layout 2 or 3, no need to pad e_size: %ld", (long) new_e_size));
54813 	new_e_size_adjusted = new_e_size;
54814 #elif defined(DUK_USE_HOBJECT_LAYOUT_1) && (DUK_HOBJECT_ALIGN_TARGET == 1)
54815 	DUK_DDD(DUK_DDDPRINT("using layout 1, but no need to pad e_size: %ld", (long) new_e_size));
54816 	new_e_size_adjusted = new_e_size;
54817 #elif defined(DUK_USE_HOBJECT_LAYOUT_1) && ((DUK_HOBJECT_ALIGN_TARGET == 4) || (DUK_HOBJECT_ALIGN_TARGET == 8))
54818 	new_e_size_adjusted = (new_e_size + (duk_uint32_t) DUK_HOBJECT_ALIGN_TARGET - 1U) &
54819 	                      (~((duk_uint32_t) DUK_HOBJECT_ALIGN_TARGET - 1U));
54820 	DUK_DDD(DUK_DDDPRINT("using layout 1, and alignment target is %ld, adjusted e_size: %ld -> %ld",
54821 	                     (long) DUK_HOBJECT_ALIGN_TARGET, (long) new_e_size, (long) new_e_size_adjusted));
54822 	DUK_ASSERT(new_e_size_adjusted >= new_e_size);
54823 #else
54824 #error invalid hobject layout defines
54825 #endif
54826 
54827 	/*
54828 	 *  Debug logging after adjustment.
54829 	 */
54830 
54831 	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 "
54832 	                     "{e_size=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
54833 	                     (void *) obj,
54834 	                     (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
54835 	                                                       DUK_HOBJECT_GET_ASIZE(obj),
54836 	                                                       DUK_HOBJECT_GET_HSIZE(obj)),
54837 	                     (long) DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size),
54838 	                     (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
54839 	                     (long) DUK_HOBJECT_GET_ESIZE(obj),
54840 	                     (long) DUK_HOBJECT_GET_ENEXT(obj),
54841 	                     (long) DUK_HOBJECT_GET_ASIZE(obj),
54842 	                     (long) DUK_HOBJECT_GET_HSIZE(obj),
54843 	                     (long) new_e_size_adjusted,
54844 	                     (long) new_a_size,
54845 	                     (long) new_h_size,
54846 	                     (long) abandon_array,
54847 	                     (long) new_e_size));
54848 
54849 	/*
54850 	 *  Property count check.  This is the only point where we ensure that
54851 	 *  we don't get more (allocated) property space that we can handle.
54852 	 *  There aren't hard limits as such, but some algorithms may fail
54853 	 *  if we get too close to the 4G property limit.
54854 	 *
54855 	 *  Since this works based on allocation size (not actually used size),
54856 	 *  the limit is a bit approximate but good enough in practice.
54857 	 */
54858 
54859 	if (new_e_size_adjusted + new_a_size > DUK_HOBJECT_MAX_PROPERTIES) {
54860 		DUK_ERROR_ALLOC_FAILED(thr);
54861 		DUK_WO_NORETURN(return;);
54862 	}
54863 
54864 	/*
54865 	 *  Compute new alloc size and alloc new area.
54866 	 *
54867 	 *  The new area is not tracked in the heap at all, so it's critical
54868 	 *  we get to free/keep it in a controlled manner.
54869 	 */
54870 
54871 #if defined(DUK_USE_ASSERTIONS)
54872 	/* Whole path must be error throw free, but we may be called from
54873 	 * within error handling so can't assert for error_not_allowed == 0.
54874 	 */
54875 	prev_error_not_allowed = thr->heap->error_not_allowed;
54876 	thr->heap->error_not_allowed = 1;
54877 #endif
54878 	prev_ms_base_flags = thr->heap->ms_base_flags;
54879 	thr->heap->ms_base_flags |=
54880 	        DUK_MS_FLAG_NO_OBJECT_COMPACTION;      /* Avoid attempt to compact the current object (all objects really). */
54881 	thr->heap->pf_prevent_count++;                 /* Avoid finalizers. */
54882 	DUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */
54883 
54884 	new_alloc_size = DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size);
54885 	DUK_DDD(DUK_DDDPRINT("new hobject allocation size is %ld", (long) new_alloc_size));
54886 	if (new_alloc_size == 0) {
54887 		DUK_ASSERT(new_e_size_adjusted == 0);
54888 		DUK_ASSERT(new_a_size == 0);
54889 		DUK_ASSERT(new_h_size == 0);
54890 		new_p = NULL;
54891 	} else {
54892 		/* Alloc may trigger mark-and-sweep but no compaction, and
54893 		 * cannot throw.
54894 		 */
54895 #if 0  /* XXX: inject test */
54896 		if (1) {
54897 			new_p = NULL;
54898 			goto alloc_failed;
54899 		}
54900 #endif
54901 		new_p = (duk_uint8_t *) DUK_ALLOC(thr->heap, new_alloc_size);
54902 		if (new_p == NULL) {
54903 			/* NULL always indicates alloc failure because
54904 			 * new_alloc_size > 0.
54905 			 */
54906 			goto alloc_failed;
54907 		}
54908 	}
54909 
54910 	/* Set up pointers to the new property area: this is hidden behind a macro
54911 	 * because it is memory layout specific.
54912 	 */
54913 	DUK_HOBJECT_P_SET_REALLOC_PTRS(new_p, new_e_k, new_e_pv, new_e_f, new_a, new_h,
54914 	                               new_e_size_adjusted, new_a_size, new_h_size);
54915 	DUK_UNREF(new_h);  /* happens when hash part dropped */
54916 	new_e_next = 0;
54917 
54918 	/* if new_p == NULL, all of these pointers are NULL */
54919 	DUK_ASSERT((new_p != NULL) ||
54920 	           (new_e_k == NULL && new_e_pv == NULL && new_e_f == NULL &&
54921 	            new_a == NULL && new_h == NULL));
54922 
54923 	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",
54924 	                     (long) new_alloc_size, (void *) new_e_k, (void *) new_e_pv, (void *) new_e_f,
54925 	                     (void *) new_a, (void *) new_h));
54926 
54927 	/*
54928 	 *  Migrate array part to start of entries if requested.
54929 	 *
54930 	 *  Note: from an enumeration perspective the order of entry keys matters.
54931 	 *  Array keys should appear wherever they appeared before the array abandon
54932 	 *  operation.  (This no longer matters much because keys are ES2015 sorted.)
54933 	 */
54934 
54935 	if (abandon_array) {
54936 		/* Assuming new_a_size == 0, and that entry part contains
54937 		 * no conflicting keys, refcounts do not need to be adjusted for
54938 		 * the values, as they remain exactly the same.
54939 		 *
54940 		 * The keys, however, need to be interned, incref'd, and be
54941 		 * reachable for GC.  Any intern attempt may trigger a GC and
54942 		 * claim any non-reachable strings, so every key must be reachable
54943 		 * at all times.  Refcounts must be correct to satisfy refcount
54944 		 * assertions.
54945 		 *
54946 		 * A longjmp must not occur here, as the new_p allocation would
54947 		 * leak.  Refcounts would come out correctly as the interned
54948 		 * strings are valstack tracked.
54949 		 */
54950 		DUK_ASSERT(new_a_size == 0);
54951 
54952 		DUK_STATS_INC(thr->heap, stats_object_abandon_array);
54953 
54954 		for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
54955 			duk_tval *tv1;
54956 			duk_tval *tv2;
54957 			duk_hstring *key;
54958 
54959 			DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
54960 
54961 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
54962 			if (DUK_TVAL_IS_UNUSED(tv1)) {
54963 				continue;
54964 			}
54965 
54966 			DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
54967 			           new_e_pv != NULL && new_e_f != NULL);
54968 
54969 			/*
54970 			 *  Intern key via the valstack to ensure reachability behaves
54971 			 *  properly.  We must avoid longjmp's here so use non-checked
54972 			 *  primitives.
54973 			 *
54974 			 *  Note: duk_check_stack() potentially reallocs the valstack,
54975 			 *  invalidating any duk_tval pointers to valstack.  Callers
54976 			 *  must be careful.
54977 			 */
54978 
54979 #if 0  /* XXX: inject test */
54980 			if (1) {
54981 				goto abandon_error;
54982 			}
54983 #endif
54984 			/* Never shrinks; auto-adds DUK_VALSTACK_INTERNAL_EXTRA, which
54985 			 * is generous.
54986 			 */
54987 			if (!duk_check_stack(thr, 1)) {
54988 				goto abandon_error;
54989 			}
54990 			DUK_ASSERT_VALSTACK_SPACE(thr, 1);
54991 			key = duk_heap_strtable_intern_u32(thr->heap, (duk_uint32_t) i);
54992 			if (key == NULL) {
54993 				goto abandon_error;
54994 			}
54995 			duk_push_hstring(thr, key);  /* keep key reachable for GC etc; guaranteed not to fail */
54996 
54997 			/* Key is now reachable in the valstack, don't INCREF
54998 			 * the new allocation yet (we'll steal the refcounts
54999 			 * from the value stack once all keys are done).
55000 			 */
55001 
55002 			new_e_k[new_e_next] = key;
55003 			tv2 = &new_e_pv[new_e_next].v;  /* array entries are all plain values */
55004 			DUK_TVAL_SET_TVAL(tv2, tv1);
55005 			new_e_f[new_e_next] = DUK_PROPDESC_FLAG_WRITABLE |
55006 			                      DUK_PROPDESC_FLAG_ENUMERABLE |
55007 			                      DUK_PROPDESC_FLAG_CONFIGURABLE;
55008 			new_e_next++;
55009 
55010 			/* Note: new_e_next matches pushed temp key count, and nothing can
55011 			 * fail above between the push and this point.
55012 			 */
55013 		}
55014 
55015 		/* Steal refcounts from value stack. */
55016 		DUK_DDD(DUK_DDDPRINT("abandon array: pop %ld key temps from valstack", (long) new_e_next));
55017 		duk_pop_n_nodecref_unsafe(thr, (duk_idx_t) new_e_next);
55018 	}
55019 
55020 	/*
55021 	 *  Copy keys and values in the entry part (compacting them at the same time).
55022 	 */
55023 
55024 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
55025 		duk_hstring *key;
55026 
55027 		DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
55028 
55029 		key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
55030 		if (key == NULL) {
55031 			continue;
55032 		}
55033 
55034 		DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
55035 		           new_e_pv != NULL && new_e_f != NULL);
55036 
55037 		new_e_k[new_e_next] = key;
55038 		new_e_pv[new_e_next] = DUK_HOBJECT_E_GET_VALUE(thr->heap, obj, i);
55039 		new_e_f[new_e_next] = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
55040 		new_e_next++;
55041 	}
55042 	/* the entries [new_e_next, new_e_size_adjusted[ are left uninitialized on purpose (ok, not gc reachable) */
55043 
55044 	/*
55045 	 *  Copy array elements to new array part.  If the new array part is
55046 	 *  larger, initialize the unused entries as UNUSED because they are
55047 	 *  GC reachable.
55048 	 */
55049 
55050 #if defined(DUK_USE_ASSERTIONS)
55051 	/* Caller must have decref'd values above new_a_size (if that is necessary). */
55052 	if (!abandon_array) {
55053 		for (i = new_a_size; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
55054 			duk_tval *tv;
55055 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
55056 			DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));
55057 		}
55058 	}
55059 #endif
55060 	if (new_a_size > DUK_HOBJECT_GET_ASIZE(obj)) {
55061 		array_copy_size = sizeof(duk_tval) * DUK_HOBJECT_GET_ASIZE(obj);
55062 	} else {
55063 		array_copy_size = sizeof(duk_tval) * new_a_size;
55064 	}
55065 
55066 	DUK_ASSERT(new_a != NULL || array_copy_size == 0U);
55067 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || array_copy_size == 0U);
55068 	DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) > 0 || array_copy_size == 0U);
55069 	duk_memcpy_unsafe((void *) new_a,
55070 	                  (const void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj),
55071 	                  array_copy_size);
55072 
55073 	for (i = DUK_HOBJECT_GET_ASIZE(obj); i < new_a_size; i++) {
55074 		duk_tval *tv = &new_a[i];
55075 		DUK_TVAL_SET_UNUSED(tv);
55076 	}
55077 
55078 	/*
55079 	 *  Rebuild the hash part always from scratch (guaranteed to finish
55080 	 *  as long as caller gave consistent parameters).
55081 	 *
55082 	 *  Any resize of hash part requires rehashing.  In addition, by rehashing
55083 	 *  get rid of any elements marked deleted (DUK__HASH_DELETED) which is critical
55084 	 *  to ensuring the hash part never fills up.
55085 	 */
55086 
55087 #if defined(DUK_USE_HOBJECT_HASH_PART)
55088 	if (new_h_size == 0) {
55089 		DUK_DDD(DUK_DDDPRINT("no hash part, no rehash"));
55090 	} else {
55091 		duk_uint32_t mask;
55092 
55093 		DUK_ASSERT(new_h != NULL);
55094 
55095 		/* fill new_h with u32 0xff = UNUSED */
55096 		DUK_ASSERT(new_h_size > 0);
55097 		duk_memset(new_h, 0xff, sizeof(duk_uint32_t) * new_h_size);
55098 
55099 		DUK_ASSERT(new_e_next <= new_h_size);  /* equality not actually possible */
55100 
55101 		mask = new_h_size - 1;
55102 		for (i = 0; i < new_e_next; i++) {
55103 			duk_hstring *key = new_e_k[i];
55104 			duk_uint32_t j, step;
55105 
55106 			DUK_ASSERT(key != NULL);
55107 			j = DUK_HSTRING_GET_HASH(key) & mask;
55108 			step = 1;  /* Cache friendly but clustering prone. */
55109 
55110 			for (;;) {
55111 				DUK_ASSERT(new_h[j] != DUK__HASH_DELETED);  /* should never happen */
55112 				if (new_h[j] == DUK__HASH_UNUSED) {
55113 					DUK_DDD(DUK_DDDPRINT("rebuild hit %ld -> %ld", (long) j, (long) i));
55114 					new_h[j] = (duk_uint32_t) i;
55115 					break;
55116 				}
55117 				DUK_DDD(DUK_DDDPRINT("rebuild miss %ld, step %ld", (long) j, (long) step));
55118 				j = (j + step) & mask;
55119 
55120 				/* Guaranteed to finish (hash is larger than #props). */
55121 			}
55122 		}
55123 	}
55124 #endif  /* DUK_USE_HOBJECT_HASH_PART */
55125 
55126 	/*
55127 	 *  Nice debug log.
55128 	 */
55129 
55130 	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 "
55131 	                   "{p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
55132 	                   (void *) obj,
55133 	                   (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
55134 	                                                     DUK_HOBJECT_GET_ASIZE(obj),
55135 	                                                     DUK_HOBJECT_GET_HSIZE(obj)),
55136 	                   (long) new_alloc_size,
55137 	                   (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
55138 	                   (long) DUK_HOBJECT_GET_ESIZE(obj),
55139 	                   (long) DUK_HOBJECT_GET_ENEXT(obj),
55140 	                   (long) DUK_HOBJECT_GET_ASIZE(obj),
55141 	                   (long) DUK_HOBJECT_GET_HSIZE(obj),
55142 	                   (void *) new_p,
55143 	                   (long) new_e_size_adjusted,
55144 	                   (long) new_e_next,
55145 	                   (long) new_a_size,
55146 	                   (long) new_h_size,
55147 	                   (long) abandon_array,
55148 	                   (long) new_e_size));
55149 
55150 	/*
55151 	 *  All done, switch properties ('p') allocation to new one.
55152 	 */
55153 
55154 	DUK_FREE_CHECKED(thr, DUK_HOBJECT_GET_PROPS(thr->heap, obj));  /* NULL obj->p is OK */
55155 	DUK_HOBJECT_SET_PROPS(thr->heap, obj, new_p);
55156 	DUK_HOBJECT_SET_ESIZE(obj, new_e_size_adjusted);
55157 	DUK_HOBJECT_SET_ENEXT(obj, new_e_next);
55158 	DUK_HOBJECT_SET_ASIZE(obj, new_a_size);
55159 	DUK_HOBJECT_SET_HSIZE(obj, new_h_size);
55160 
55161 	/* Clear array part flag only after switching. */
55162 	if (abandon_array) {
55163 		DUK_HOBJECT_CLEAR_ARRAY_PART(obj);
55164 	}
55165 
55166 	DUK_DDD(DUK_DDDPRINT("resize result: %!O", (duk_heaphdr *) obj));
55167 
55168 	DUK_ASSERT(thr->heap->pf_prevent_count > 0);
55169 	thr->heap->pf_prevent_count--;
55170 	thr->heap->ms_base_flags = prev_ms_base_flags;
55171 #if defined(DUK_USE_ASSERTIONS)
55172 	DUK_ASSERT(thr->heap->error_not_allowed == 1);
55173 	thr->heap->error_not_allowed = prev_error_not_allowed;
55174 #endif
55175 
55176 	/*
55177 	 *  Post resize assertions.
55178 	 */
55179 
55180 #if defined(DUK_USE_ASSERTIONS)
55181 	/* XXX: post-checks (such as no duplicate keys) */
55182 #endif
55183 	return;
55184 
55185 	/*
55186 	 *  Abandon array failed.  We don't need to DECREF anything
55187 	 *  because the references in the new allocation are not
55188 	 *  INCREF'd until abandon is complete.  The string interned
55189 	 *  keys are on the value stack and are handled normally by
55190 	 *  unwind.
55191 	 */
55192 
55193  abandon_error:
55194  alloc_failed:
55195 	DUK_D(DUK_DPRINT("object property table resize failed"));
55196 
55197 	DUK_FREE_CHECKED(thr, new_p);  /* OK for NULL. */
55198 
55199 	thr->heap->pf_prevent_count--;
55200 	thr->heap->ms_base_flags = prev_ms_base_flags;
55201 #if defined(DUK_USE_ASSERTIONS)
55202 	DUK_ASSERT(thr->heap->error_not_allowed == 1);
55203 	thr->heap->error_not_allowed = prev_error_not_allowed;
55204 #endif
55205 
55206 	DUK_ERROR_ALLOC_FAILED(thr);
55207 	DUK_WO_NORETURN(return;);
55208 }
55209 
55210 /*
55211  *  Helpers to resize properties allocation on specific needs.
55212  */
55213 
55214 DUK_INTERNAL void duk_hobject_resize_entrypart(duk_hthread *thr,
55215                                                duk_hobject *obj,
55216                                                duk_uint32_t new_e_size) {
55217 	duk_uint32_t old_e_size;
55218 	duk_uint32_t new_a_size;
55219 	duk_uint32_t new_h_size;
55220 
55221 	DUK_ASSERT(thr != NULL);
55222 	DUK_ASSERT(obj != NULL);
55223 
55224 	old_e_size = DUK_HOBJECT_GET_ESIZE(obj);
55225 	if (old_e_size > new_e_size) {
55226 		new_e_size = old_e_size;
55227 	}
55228 #if defined(DUK_USE_HOBJECT_HASH_PART)
55229 	new_h_size = duk__get_default_h_size(new_e_size);
55230 #else
55231 	new_h_size = 0;
55232 #endif
55233 	new_a_size = DUK_HOBJECT_GET_ASIZE(obj);
55234 
55235 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
55236 }
55237 
55238 #if 0  /*unused */
55239 DUK_INTERNAL void duk_hobject_resize_arraypart(duk_hthread *thr,
55240                                                duk_hobject *obj,
55241                                                duk_uint32_t new_a_size) {
55242 	duk_uint32_t old_a_size;
55243 	duk_uint32_t new_e_size;
55244 	duk_uint32_t new_h_size;
55245 
55246 	DUK_ASSERT(thr != NULL);
55247 	DUK_ASSERT(obj != NULL);
55248 
55249 	if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
55250 		return;
55251 	}
55252 	old_a_size = DUK_HOBJECT_GET_ASIZE(obj);
55253 	if (old_a_size > new_a_size) {
55254 		new_a_size = old_a_size;
55255 	}
55256 	new_e_size = DUK_HOBJECT_GET_ESIZE(obj);
55257 	new_h_size = DUK_HOBJECT_GET_HSIZE(obj);
55258 
55259 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
55260 }
55261 #endif
55262 
55263 /* Grow entry part allocation for one additional entry. */
55264 DUK_LOCAL void duk__grow_props_for_new_entry_item(duk_hthread *thr, duk_hobject *obj) {
55265 	duk_uint32_t old_e_used;  /* actually used, non-NULL entries */
55266 	duk_uint32_t new_e_size;
55267 	duk_uint32_t new_a_size;
55268 	duk_uint32_t new_h_size;
55269 
55270 	DUK_ASSERT(thr != NULL);
55271 	DUK_ASSERT(obj != NULL);
55272 
55273 	/* Duktape 0.11.0 and prior tried to optimize the resize by not
55274 	 * counting the number of actually used keys prior to the resize.
55275 	 * This worked mostly well but also caused weird leak-like behavior
55276 	 * as in: test-bug-object-prop-alloc-unbounded.js.  So, now we count
55277 	 * the keys explicitly to compute the new entry part size.
55278 	 */
55279 
55280 	old_e_used = duk__count_used_e_keys(thr, obj);
55281 	new_e_size = old_e_used + duk__get_min_grow_e(old_e_used);
55282 #if defined(DUK_USE_HOBJECT_HASH_PART)
55283 	new_h_size = duk__get_default_h_size(new_e_size);
55284 #else
55285 	new_h_size = 0;
55286 #endif
55287 	new_a_size = DUK_HOBJECT_GET_ASIZE(obj);
55288 	DUK_ASSERT(new_e_size >= old_e_used + 1);  /* duk__get_min_grow_e() is always >= 1 */
55289 
55290 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
55291 }
55292 
55293 /* Grow array part for a new highest array index. */
55294 DUK_LOCAL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx) {
55295 	duk_uint32_t new_e_size;
55296 	duk_uint32_t new_a_size;
55297 	duk_uint32_t new_h_size;
55298 
55299 	DUK_ASSERT(thr != NULL);
55300 	DUK_ASSERT(obj != NULL);
55301 	DUK_ASSERT(highest_arr_idx >= DUK_HOBJECT_GET_ASIZE(obj));
55302 
55303 	/* minimum new length is highest_arr_idx + 1 */
55304 
55305 	new_e_size = DUK_HOBJECT_GET_ESIZE(obj);
55306 	new_h_size = DUK_HOBJECT_GET_HSIZE(obj);
55307 	new_a_size = highest_arr_idx + duk__get_min_grow_a(highest_arr_idx);
55308 	DUK_ASSERT(new_a_size >= highest_arr_idx + 1);  /* duk__get_min_grow_a() is always >= 1 */
55309 
55310 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
55311 }
55312 
55313 /* Abandon array part, moving array entries into entries part.
55314  * This requires a props resize, which is a heavy operation.
55315  * We also compact the entries part while we're at it, although
55316  * this is not strictly required.
55317  */
55318 DUK_LOCAL void duk__abandon_array_checked(duk_hthread *thr, duk_hobject *obj) {
55319 	duk_uint32_t new_e_size;
55320 	duk_uint32_t new_a_size;
55321 	duk_uint32_t new_h_size;
55322 	duk_uint32_t e_used;  /* actually used, non-NULL keys */
55323 	duk_uint32_t a_used;
55324 	duk_uint32_t a_size;
55325 
55326 	DUK_ASSERT(thr != NULL);
55327 	DUK_ASSERT(obj != NULL);
55328 
55329 	e_used = duk__count_used_e_keys(thr, obj);
55330 	duk__compute_a_stats(thr, obj, &a_used, &a_size);
55331 
55332 	/*
55333 	 *  Must guarantee all actually used array entries will fit into
55334 	 *  new entry part.  Add one growth step to ensure we don't run out
55335 	 *  of space right away.
55336 	 */
55337 
55338 	new_e_size = e_used + a_used;
55339 	new_e_size = new_e_size + duk__get_min_grow_e(new_e_size);
55340 	new_a_size = 0;
55341 #if defined(DUK_USE_HOBJECT_HASH_PART)
55342 	new_h_size = duk__get_default_h_size(new_e_size);
55343 #else
55344 	new_h_size = 0;
55345 #endif
55346 
55347 	DUK_DD(DUK_DDPRINT("abandon array part for hobject %p, "
55348 	                   "array stats before: e_used=%ld, a_used=%ld, a_size=%ld; "
55349 	                   "resize to e_size=%ld, a_size=%ld, h_size=%ld",
55350 	                   (void *) obj, (long) e_used, (long) a_used, (long) a_size,
55351 	                   (long) new_e_size, (long) new_a_size, (long) new_h_size));
55352 
55353 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 1);
55354 }
55355 
55356 /*
55357  *  Compact an object.  Minimizes allocation size for objects which are
55358  *  not likely to be extended.  This is useful for internal and non-
55359  *  extensible objects, but can also be called for non-extensible objects.
55360  *  May abandon the array part if it is computed to be too sparse.
55361  *
55362  *  This call is relatively expensive, as it needs to scan both the
55363  *  entries and the array part.
55364  *
55365  *  The call may fail due to allocation error.
55366  */
55367 
55368 DUK_INTERNAL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj) {
55369 	duk_uint32_t e_size;       /* currently used -> new size */
55370 	duk_uint32_t a_size;       /* currently required */
55371 	duk_uint32_t a_used;       /* actually used */
55372 	duk_uint32_t h_size;
55373 	duk_bool_t abandon_array;
55374 
55375 	DUK_ASSERT(thr != NULL);
55376 	DUK_ASSERT(obj != NULL);
55377 
55378 #if defined(DUK_USE_ROM_OBJECTS)
55379 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
55380 		DUK_DD(DUK_DDPRINT("ignore attempt to compact a rom object"));
55381 		return;
55382 	}
55383 #endif
55384 
55385 	e_size = duk__count_used_e_keys(thr, obj);
55386 	duk__compute_a_stats(thr, obj, &a_used, &a_size);
55387 
55388 	DUK_DD(DUK_DDPRINT("compacting hobject, used e keys %ld, used a keys %ld, min a size %ld, "
55389 	                   "resized array density would be: %ld/%ld = %lf",
55390 	                   (long) e_size, (long) a_used, (long) a_size,
55391 	                   (long) a_used, (long) a_size,
55392 	                   (double) a_used / (double) a_size));
55393 
55394 	if (duk__abandon_array_density_check(a_used, a_size)) {
55395 		DUK_DD(DUK_DDPRINT("decided to abandon array during compaction, a_used=%ld, a_size=%ld",
55396 		                   (long) a_used, (long) a_size));
55397 		abandon_array = 1;
55398 		e_size += a_used;
55399 		a_size = 0;
55400 	} else {
55401 		DUK_DD(DUK_DDPRINT("decided to keep array during compaction"));
55402 		abandon_array = 0;
55403 	}
55404 
55405 #if defined(DUK_USE_HOBJECT_HASH_PART)
55406 	if (e_size >= DUK_USE_HOBJECT_HASH_PROP_LIMIT) {
55407 		h_size = duk__get_default_h_size(e_size);
55408 	} else {
55409 		h_size = 0;
55410 	}
55411 #else
55412 	h_size = 0;
55413 #endif
55414 
55415 	DUK_DD(DUK_DDPRINT("compacting hobject -> new e_size %ld, new a_size=%ld, new h_size=%ld, abandon_array=%ld",
55416 	                   (long) e_size, (long) a_size, (long) h_size, (long) abandon_array));
55417 
55418 	duk_hobject_realloc_props(thr, obj, e_size, a_size, h_size, abandon_array);
55419 }
55420 
55421 /*
55422  *  Find an existing key from entry part either by linear scan or by
55423  *  using the hash index (if it exists).
55424  *
55425  *  Sets entry index (and possibly the hash index) to output variables,
55426  *  which allows the caller to update the entry and hash entries in-place.
55427  *  If entry is not found, both values are set to -1.  If entry is found
55428  *  but there is no hash part, h_idx is set to -1.
55429  */
55430 
55431 DUK_INTERNAL duk_bool_t duk_hobject_find_existing_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx) {
55432 	DUK_ASSERT(obj != NULL);
55433 	DUK_ASSERT(key != NULL);
55434 	DUK_ASSERT(e_idx != NULL);
55435 	DUK_ASSERT(h_idx != NULL);
55436 	DUK_UNREF(heap);
55437 
55438 	if (DUK_LIKELY(DUK_HOBJECT_GET_HSIZE(obj) == 0))
55439 	{
55440 		/* Linear scan: more likely because most objects are small.
55441 		 * This is an important fast path.
55442 		 *
55443 		 * XXX: this might be worth inlining for property lookups.
55444 		 */
55445 		duk_uint_fast32_t i;
55446 		duk_uint_fast32_t n;
55447 		duk_hstring **h_keys_base;
55448 		DUK_DDD(DUK_DDDPRINT("duk_hobject_find_existing_entry() using linear scan for lookup"));
55449 
55450 		h_keys_base = DUK_HOBJECT_E_GET_KEY_BASE(heap, obj);
55451 		n = DUK_HOBJECT_GET_ENEXT(obj);
55452 		for (i = 0; i < n; i++) {
55453 			if (h_keys_base[i] == key) {
55454 				*e_idx = (duk_int_t) i;
55455 				*h_idx = -1;
55456 				return 1;
55457 			}
55458 		}
55459 	}
55460 #if defined(DUK_USE_HOBJECT_HASH_PART)
55461 	else
55462 	{
55463 		/* hash lookup */
55464 		duk_uint32_t n;
55465 		duk_uint32_t i, step;
55466 		duk_uint32_t *h_base;
55467 		duk_uint32_t mask;
55468 
55469 		DUK_DDD(DUK_DDDPRINT("duk_hobject_find_existing_entry() using hash part for lookup"));
55470 
55471 		h_base = DUK_HOBJECT_H_GET_BASE(heap, obj);
55472 		n = DUK_HOBJECT_GET_HSIZE(obj);
55473 		mask = n - 1;
55474 		i = DUK_HSTRING_GET_HASH(key) & mask;
55475 		step = 1;  /* Cache friendly but clustering prone. */
55476 
55477 		for (;;) {
55478 			duk_uint32_t t;
55479 
55480 			DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
55481 			DUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));
55482 			t = h_base[i];
55483 			DUK_ASSERT(t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED ||
55484 			           (t < DUK_HOBJECT_GET_ESIZE(obj)));  /* t >= 0 always true, unsigned */
55485 
55486 			if (t == DUK__HASH_UNUSED) {
55487 				break;
55488 			} else if (t == DUK__HASH_DELETED) {
55489 				DUK_DDD(DUK_DDDPRINT("lookup miss (deleted) i=%ld, t=%ld",
55490 				                     (long) i, (long) t));
55491 			} else {
55492 				DUK_ASSERT(t < DUK_HOBJECT_GET_ESIZE(obj));
55493 				if (DUK_HOBJECT_E_GET_KEY(heap, obj, t) == key) {
55494 					DUK_DDD(DUK_DDDPRINT("lookup hit i=%ld, t=%ld -> key %p",
55495 					                     (long) i, (long) t, (void *) key));
55496 					*e_idx = (duk_int_t) t;
55497 					*h_idx = (duk_int_t) i;
55498 					return 1;
55499 				}
55500 				DUK_DDD(DUK_DDDPRINT("lookup miss i=%ld, t=%ld",
55501 				                     (long) i, (long) t));
55502 			}
55503 			i = (i + step) & mask;
55504 
55505 			/* Guaranteed to finish (hash is larger than #props). */
55506 		}
55507 	}
55508 #endif  /* DUK_USE_HOBJECT_HASH_PART */
55509 
55510 	/* Not found, leave e_idx and h_idx unset. */
55511 	return 0;
55512 }
55513 
55514 /* For internal use: get non-accessor entry value */
55515 DUK_INTERNAL duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key) {
55516 	duk_int_t e_idx;
55517 	duk_int_t h_idx;
55518 
55519 	DUK_ASSERT(obj != NULL);
55520 	DUK_ASSERT(key != NULL);
55521 	DUK_UNREF(heap);
55522 
55523 	if (duk_hobject_find_existing_entry(heap, obj, key, &e_idx, &h_idx)) {
55524 		DUK_ASSERT(e_idx >= 0);
55525 		if (!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
55526 			return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
55527 		}
55528 	}
55529 	return NULL;
55530 }
55531 
55532 /* For internal use: get non-accessor entry value and attributes */
55533 DUK_INTERNAL duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_uint_t *out_attrs) {
55534 	duk_int_t e_idx;
55535 	duk_int_t h_idx;
55536 
55537 	DUK_ASSERT(obj != NULL);
55538 	DUK_ASSERT(key != NULL);
55539 	DUK_ASSERT(out_attrs != NULL);
55540 	DUK_UNREF(heap);
55541 
55542 	if (duk_hobject_find_existing_entry(heap, obj, key, &e_idx, &h_idx)) {
55543 		DUK_ASSERT(e_idx >= 0);
55544 		if (!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
55545 			*out_attrs = DUK_HOBJECT_E_GET_FLAGS(heap, obj, e_idx);
55546 			return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
55547 		}
55548 	}
55549 	/* If not found, out_attrs is left unset. */
55550 	return NULL;
55551 }
55552 
55553 /* For internal use: get array part value */
55554 DUK_INTERNAL duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i) {
55555 	duk_tval *tv;
55556 
55557 	DUK_ASSERT(obj != NULL);
55558 	DUK_UNREF(heap);
55559 
55560 	if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
55561 		return NULL;
55562 	}
55563 	if (i >= DUK_HOBJECT_GET_ASIZE(obj)) {
55564 		return NULL;
55565 	}
55566 	tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, obj, i);
55567 	return tv;
55568 }
55569 
55570 /*
55571  *  Allocate and initialize a new entry, resizing the properties allocation
55572  *  if necessary.  Returns entry index (e_idx) or throws an error if alloc fails.
55573  *
55574  *  Sets the key of the entry (increasing the key's refcount), and updates
55575  *  the hash part if it exists.  Caller must set value and flags, and update
55576  *  the entry value refcount.  A decref for the previous value is not necessary.
55577  */
55578 
55579 DUK_LOCAL duk_int_t duk__hobject_alloc_entry_checked(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {
55580 	duk_uint32_t idx;
55581 
55582 	DUK_ASSERT(thr != NULL);
55583 	DUK_ASSERT(obj != NULL);
55584 	DUK_ASSERT(key != NULL);
55585 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(obj) <= DUK_HOBJECT_GET_ESIZE(obj));
55586 
55587 #if defined(DUK_USE_ASSERTIONS)
55588 	/* key must not already exist in entry part */
55589 	{
55590 		duk_uint_fast32_t i;
55591 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
55592 			DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != key);
55593 		}
55594 	}
55595 #endif
55596 
55597 	if (DUK_HOBJECT_GET_ENEXT(obj) >= DUK_HOBJECT_GET_ESIZE(obj)) {
55598 		/* only need to guarantee 1 more slot, but allocation growth is in chunks */
55599 		DUK_DDD(DUK_DDDPRINT("entry part full, allocate space for one more entry"));
55600 		duk__grow_props_for_new_entry_item(thr, obj);
55601 	}
55602 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(obj) < DUK_HOBJECT_GET_ESIZE(obj));
55603 	idx = DUK_HOBJECT_POSTINC_ENEXT(obj);
55604 
55605 	/* previous value is assumed to be garbage, so don't touch it */
55606 	DUK_HOBJECT_E_SET_KEY(thr->heap, obj, idx, key);
55607 	DUK_HSTRING_INCREF(thr, key);
55608 
55609 #if defined(DUK_USE_HOBJECT_HASH_PART)
55610 	if (DUK_UNLIKELY(DUK_HOBJECT_GET_HSIZE(obj) > 0)) {
55611 		duk_uint32_t n, mask;
55612 		duk_uint32_t i, step;
55613 		duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
55614 
55615 		n = DUK_HOBJECT_GET_HSIZE(obj);
55616 		mask = n - 1;
55617 		i = DUK_HSTRING_GET_HASH(key) & mask;
55618 		step = 1;  /* Cache friendly but clustering prone. */
55619 
55620 		for (;;) {
55621 			duk_uint32_t t = h_base[i];
55622 			if (t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED) {
55623 				DUK_DDD(DUK_DDDPRINT("duk__hobject_alloc_entry_checked() inserted key into hash part, %ld -> %ld",
55624 				                     (long) i, (long) idx));
55625 				DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
55626 				DUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));
55627 				DUK_ASSERT_DISABLE(idx >= 0);
55628 				DUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));
55629 				h_base[i] = idx;
55630 				break;
55631 			}
55632 			DUK_DDD(DUK_DDDPRINT("duk__hobject_alloc_entry_checked() miss %ld", (long) i));
55633 			i = (i + step) & mask;
55634 
55635 			/* Guaranteed to finish (hash is larger than #props). */
55636 		}
55637 	}
55638 #endif  /* DUK_USE_HOBJECT_HASH_PART */
55639 
55640 	/* Note: we could return the hash index here too, but it's not
55641 	 * needed right now.
55642 	 */
55643 
55644 	DUK_ASSERT_DISABLE(idx >= 0);
55645 	DUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));
55646 	DUK_ASSERT(idx < DUK_HOBJECT_GET_ENEXT(obj));
55647 	return (duk_int_t) idx;
55648 }
55649 
55650 /*
55651  *  Object internal value
55652  *
55653  *  Returned value is guaranteed to be reachable / incref'd, caller does not need
55654  *  to incref OR decref.  No proxies or accessors are invoked, no prototype walk.
55655  */
55656 
55657 DUK_INTERNAL duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv_out) {
55658 	duk_int_t e_idx;
55659 	duk_int_t h_idx;
55660 
55661 	DUK_ASSERT(heap != NULL);
55662 	DUK_ASSERT(obj != NULL);
55663 	DUK_ASSERT(tv_out != NULL);
55664 
55665 	/* Always in entry part, no need to look up parents etc. */
55666 	if (duk_hobject_find_existing_entry(heap, obj, DUK_HEAP_STRING_INT_VALUE(heap), &e_idx, &h_idx)) {
55667 		DUK_ASSERT(e_idx >= 0);
55668 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx));
55669 		DUK_TVAL_SET_TVAL(tv_out, DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx));
55670 		return 1;
55671 	}
55672 	DUK_TVAL_SET_UNDEFINED(tv_out);
55673 	return 0;
55674 }
55675 
55676 DUK_INTERNAL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj) {
55677 	duk_tval tv;
55678 
55679 	DUK_ASSERT(heap != NULL);
55680 	DUK_ASSERT(obj != NULL);
55681 
55682 	/* This is not strictly necessary, but avoids compiler warnings; e.g.
55683 	 * gcc won't reliably detect that no uninitialized data is read below.
55684 	 */
55685 	duk_memzero((void *) &tv, sizeof(duk_tval));
55686 
55687 	if (duk_hobject_get_internal_value(heap, obj, &tv)) {
55688 		duk_hstring *h;
55689 		DUK_ASSERT(DUK_TVAL_IS_STRING(&tv));
55690 		h = DUK_TVAL_GET_STRING(&tv);
55691 		/* No explicit check for string vs. symbol, accept both. */
55692 		return h;
55693 	}
55694 
55695 	return NULL;
55696 }
55697 
55698 /*
55699  *  Arguments handling helpers (argument map mainly).
55700  *
55701  *  An arguments object has exotic behavior for some numeric indices.
55702  *  Accesses may translate to identifier operations which may have
55703  *  arbitrary side effects (potentially invalidating any duk_tval
55704  *  pointers).
55705  */
55706 
55707 /* Lookup 'key' from arguments internal 'map', perform a variable lookup
55708  * if mapped, and leave the result on top of stack (and return non-zero).
55709  * Used in E5 Section 10.6 algorithms [[Get]] and [[GetOwnProperty]].
55710  */
55711 DUK_LOCAL
55712 duk_bool_t duk__lookup_arguments_map(duk_hthread *thr,
55713                                      duk_hobject *obj,
55714                                      duk_hstring *key,
55715                                      duk_propdesc *temp_desc,
55716                                      duk_hobject **out_map,
55717                                      duk_hobject **out_varenv) {
55718 	duk_hobject *map;
55719 	duk_hobject *varenv;
55720 	duk_bool_t rc;
55721 
55722 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
55723 
55724 	DUK_DDD(DUK_DDDPRINT("arguments map lookup: thr=%p, obj=%p, key=%p, temp_desc=%p "
55725 	                     "(obj -> %!O, key -> %!O)",
55726 	                     (void *) thr, (void *) obj, (void *) key, (void *) temp_desc,
55727 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
55728 
55729 	if (!duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
55730 		DUK_DDD(DUK_DDDPRINT("-> no 'map'"));
55731 		return 0;
55732 	}
55733 
55734 	map = duk_require_hobject(thr, -1);
55735 	DUK_ASSERT(map != NULL);
55736 	duk_pop_unsafe(thr);  /* map is reachable through obj */
55737 
55738 	if (!duk_hobject_get_own_propdesc(thr, map, key, temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
55739 		DUK_DDD(DUK_DDDPRINT("-> 'map' exists, but key not in map"));
55740 		return 0;
55741 	}
55742 
55743 	/* [... varname] */
55744 	DUK_DDD(DUK_DDDPRINT("-> 'map' exists, and contains key, key is mapped to argument/variable binding %!T",
55745 	                     (duk_tval *) duk_get_tval(thr, -1)));
55746 	DUK_ASSERT(duk_is_string(thr, -1));  /* guaranteed when building arguments */
55747 
55748 	/* get varenv for varname (callee's declarative lexical environment) */
55749 	rc = duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_VARENV(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE);
55750 	DUK_UNREF(rc);
55751 	DUK_ASSERT(rc != 0);  /* arguments MUST have an initialized lexical environment reference */
55752 	varenv = duk_require_hobject(thr, -1);
55753 	DUK_ASSERT(varenv != NULL);
55754 	duk_pop_unsafe(thr);  /* varenv remains reachable through 'obj' */
55755 
55756 	DUK_DDD(DUK_DDDPRINT("arguments varenv is: %!dO", (duk_heaphdr *) varenv));
55757 
55758 	/* success: leave varname in stack */
55759 	*out_map = map;
55760 	*out_varenv = varenv;
55761 	return 1;  /* [... varname] */
55762 }
55763 
55764 /* Lookup 'key' from arguments internal 'map', and leave replacement value
55765  * on stack top if mapped (and return non-zero).
55766  * Used in E5 Section 10.6 algorithm for [[GetOwnProperty]] (used by [[Get]]).
55767  */
55768 DUK_LOCAL duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
55769 	duk_hobject *map;
55770 	duk_hobject *varenv;
55771 	duk_hstring *varname;
55772 
55773 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
55774 
55775 	if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
55776 		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic get behavior"));
55777 		return 0;
55778 	}
55779 
55780 	/* [... varname] */
55781 
55782 	varname = duk_require_hstring(thr, -1);
55783 	DUK_ASSERT(varname != NULL);
55784 	duk_pop_unsafe(thr);  /* varname is still reachable */
55785 
55786 	DUK_DDD(DUK_DDDPRINT("arguments object automatic getvar for a bound variable; "
55787 	                     "key=%!O, varname=%!O",
55788 	                     (duk_heaphdr *) key,
55789 	                     (duk_heaphdr *) varname));
55790 
55791 	(void) duk_js_getvar_envrec(thr, varenv, varname, 1 /*throw*/);
55792 
55793 	/* [... value this_binding] */
55794 
55795 	duk_pop_unsafe(thr);
55796 
55797 	/* leave result on stack top */
55798 	return 1;
55799 }
55800 
55801 /* Lookup 'key' from arguments internal 'map', perform a variable write if mapped.
55802  * Used in E5 Section 10.6 algorithm for [[DefineOwnProperty]] (used by [[Put]]).
55803  * Assumes stack top contains 'put' value (which is NOT popped).
55804  */
55805 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) {
55806 	duk_hobject *map;
55807 	duk_hobject *varenv;
55808 	duk_hstring *varname;
55809 
55810 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
55811 
55812 	if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
55813 		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic put behavior"));
55814 		return;
55815 	}
55816 
55817 	/* [... put_value varname] */
55818 
55819 	varname = duk_require_hstring(thr, -1);
55820 	DUK_ASSERT(varname != NULL);
55821 	duk_pop_unsafe(thr);  /* varname is still reachable */
55822 
55823 	DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
55824 	                     "key=%!O, varname=%!O, value=%!T",
55825 	                     (duk_heaphdr *) key,
55826 	                     (duk_heaphdr *) varname,
55827 	                     (duk_tval *) duk_require_tval(thr, -1)));
55828 
55829 	/* [... put_value] */
55830 
55831 	/*
55832 	 *  Note: although arguments object variable mappings are only established
55833 	 *  for non-strict functions (and a call to a non-strict function created
55834 	 *  the arguments object in question), an inner strict function may be doing
55835 	 *  the actual property write.  Hence the throw_flag applied here comes from
55836 	 *  the property write call.
55837 	 */
55838 
55839 	duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(thr, -1), throw_flag);
55840 
55841 	/* [... put_value] */
55842 }
55843 
55844 /* Lookup 'key' from arguments internal 'map', delete mapping if found.
55845  * Used in E5 Section 10.6 algorithm for [[Delete]].  Note that the
55846  * variable/argument itself (where the map points) is not deleted.
55847  */
55848 DUK_LOCAL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
55849 	duk_hobject *map;
55850 
55851 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
55852 
55853 	if (!duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
55854 		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic delete behavior"));
55855 		return;
55856 	}
55857 
55858 	map = duk_require_hobject(thr, -1);
55859 	DUK_ASSERT(map != NULL);
55860 	duk_pop_unsafe(thr);  /* map is reachable through obj */
55861 
55862 	DUK_DDD(DUK_DDDPRINT("-> have 'map', delete key %!O from map (if exists)); ignore result",
55863 	                     (duk_heaphdr *) key));
55864 
55865 	/* Note: no recursion issue, we can trust 'map' to behave */
55866 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(map));
55867 	DUK_DDD(DUK_DDDPRINT("map before deletion: %!O", (duk_heaphdr *) map));
55868 	(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
55869 	DUK_DDD(DUK_DDDPRINT("map after deletion: %!O", (duk_heaphdr *) map));
55870 }
55871 
55872 /*
55873  *  ECMAScript compliant [[GetOwnProperty]](P), for internal use only.
55874  *
55875  *  If property is found:
55876  *    - Fills descriptor fields to 'out_desc'
55877  *    - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
55878  *      property onto the stack ('undefined' for accessor properties).
55879  *    - Returns non-zero
55880  *
55881  *  If property is not found:
55882  *    - 'out_desc' is left in untouched state (possibly garbage)
55883  *    - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
55884  *      set)
55885  *    - Returns zero
55886  *
55887  *  Notes:
55888  *
55889  *    - Getting a property descriptor may cause an allocation (and hence
55890  *      GC) to take place, hence reachability and refcount of all related
55891  *      values matter.  Reallocation of value stack, properties, etc may
55892  *      invalidate many duk_tval pointers (concretely, those which reside
55893  *      in memory areas subject to reallocation).  However, heap object
55894  *      pointers are never affected (heap objects have stable pointers).
55895  *
55896  *    - The value of a plain property is always reachable and has a non-zero
55897  *      reference count.
55898  *
55899  *    - The value of a virtual property is not necessarily reachable from
55900  *      elsewhere and may have a refcount of zero.  Hence we push it onto
55901  *      the valstack for the caller, which ensures it remains reachable
55902  *      while it is needed.
55903  *
55904  *    - There are no virtual accessor properties.  Hence, all getters and
55905  *      setters are always related to concretely stored properties, which
55906  *      ensures that the get/set functions in the resulting descriptor are
55907  *      reachable and have non-zero refcounts.  Should there be virtual
55908  *      accessor properties later, this would need to change.
55909  */
55910 
55911 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) {
55912 	duk_tval *tv;
55913 
55914 	DUK_DDD(DUK_DDDPRINT("duk_hobject_get_own_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
55915 	                     "arr_idx=%ld (obj -> %!O, key -> %!O)",
55916 	                     (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
55917 	                     (long) flags, (long) arr_idx,
55918 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
55919 
55920 	DUK_ASSERT(thr != NULL);
55921 	DUK_ASSERT(thr->heap != NULL);
55922 	DUK_ASSERT(obj != NULL);
55923 	DUK_ASSERT(key != NULL);
55924 	DUK_ASSERT(out_desc != NULL);
55925 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
55926 
55927 	DUK_STATS_INC(thr->heap, stats_getownpropdesc_count);
55928 
55929 	/* Each code path returning 1 (= found) must fill in all the output
55930 	 * descriptor fields.  We don't do it beforehand because it'd be
55931 	 * unnecessary work if the property isn't found and would happen
55932 	 * multiple times for an inheritance chain.
55933 	 */
55934 	DUK_ASSERT_SET_GARBAGE(out_desc, sizeof(*out_desc));
55935 #if 0
55936 	out_desc->flags = 0;
55937 	out_desc->get = NULL;
55938 	out_desc->set = NULL;
55939 	out_desc->e_idx = -1;
55940 	out_desc->h_idx = -1;
55941 	out_desc->a_idx = -1;
55942 #endif
55943 
55944 	/*
55945 	 *  Try entries part first because it's the common case.
55946 	 *
55947 	 *  Array part lookups are usually handled by the array fast path, and
55948 	 *  are not usually inherited.  Array and entry parts never contain the
55949 	 *  same keys so the entry part vs. array part order doesn't matter.
55950 	 */
55951 
55952 	if (duk_hobject_find_existing_entry(thr->heap, obj, key, &out_desc->e_idx, &out_desc->h_idx)) {
55953 		duk_int_t e_idx = out_desc->e_idx;
55954 		DUK_ASSERT(out_desc->e_idx >= 0);
55955 		out_desc->a_idx = -1;
55956 		out_desc->flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, e_idx);
55957 		out_desc->get = NULL;
55958 		out_desc->set = NULL;
55959 		if (DUK_UNLIKELY(out_desc->flags & DUK_PROPDESC_FLAG_ACCESSOR)) {
55960 			DUK_DDD(DUK_DDDPRINT("-> found accessor property in entry part"));
55961 			out_desc->get = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, e_idx);
55962 			out_desc->set = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, e_idx);
55963 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
55964 				/* a dummy undefined value is pushed to make valstack
55965 				 * behavior uniform for caller
55966 				 */
55967 				duk_push_undefined(thr);
55968 			}
55969 		} else {
55970 			DUK_DDD(DUK_DDDPRINT("-> found plain property in entry part"));
55971 			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
55972 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
55973 				duk_push_tval(thr, tv);
55974 			}
55975 		}
55976 		goto prop_found;
55977 	}
55978 
55979 	/*
55980 	 *  Try array part.
55981 	 */
55982 
55983 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj) && arr_idx != DUK__NO_ARRAY_INDEX) {
55984 		if (arr_idx < DUK_HOBJECT_GET_ASIZE(obj)) {
55985 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
55986 			if (!DUK_TVAL_IS_UNUSED(tv)) {
55987 				DUK_DDD(DUK_DDDPRINT("-> found in array part"));
55988 				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
55989 					duk_push_tval(thr, tv);
55990 				}
55991 				/* implicit attributes */
55992 				out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
55993 				                  DUK_PROPDESC_FLAG_CONFIGURABLE |
55994 				                  DUK_PROPDESC_FLAG_ENUMERABLE;
55995 				out_desc->get = NULL;
55996 				out_desc->set = NULL;
55997 				out_desc->e_idx = -1;
55998 				out_desc->h_idx = -1;
55999 				out_desc->a_idx = (duk_int_t) arr_idx;  /* XXX: limit 2G due to being signed */
56000 				goto prop_found;
56001 			}
56002 		}
56003 	}
56004 
56005 	DUK_DDD(DUK_DDDPRINT("-> not found as a concrete property"));
56006 
56007 	/*
56008 	 *  Not found as a concrete property, check for virtual properties.
56009 	 */
56010 
56011 	if (!DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(obj)) {
56012 		/* Quick skip. */
56013 		goto prop_not_found;
56014 	}
56015 
56016 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
56017 		duk_harray *a;
56018 
56019 		DUK_DDD(DUK_DDDPRINT("array object exotic property get for key: %!O, arr_idx: %ld",
56020 		                     (duk_heaphdr *) key, (long) arr_idx));
56021 
56022 		a = (duk_harray *) obj;
56023 		DUK_ASSERT_HARRAY_VALID(a);
56024 
56025 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
56026 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
56027 
56028 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
56029 				duk_push_uint(thr, (duk_uint_t) a->length);
56030 			}
56031 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
56032 			if (DUK_HARRAY_LENGTH_WRITABLE(a)) {
56033 				out_desc->flags |= DUK_PROPDESC_FLAG_WRITABLE;
56034 			}
56035 			out_desc->get = NULL;
56036 			out_desc->set = NULL;
56037 			out_desc->e_idx = -1;
56038 			out_desc->h_idx = -1;
56039 			out_desc->a_idx = -1;
56040 
56041 			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
56042 			goto prop_found_noexotic;  /* cannot be arguments exotic */
56043 		}
56044 	} else if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj)) {
56045 		DUK_DDD(DUK_DDDPRINT("string object exotic property get for key: %!O, arr_idx: %ld",
56046 		                     (duk_heaphdr *) key, (long) arr_idx));
56047 
56048 		/* XXX: charlen; avoid multiple lookups? */
56049 
56050 		if (arr_idx != DUK__NO_ARRAY_INDEX) {
56051 			duk_hstring *h_val;
56052 
56053 			DUK_DDD(DUK_DDDPRINT("array index exists"));
56054 
56055 			h_val = duk_hobject_get_internal_value_string(thr->heap, obj);
56056 			DUK_ASSERT(h_val);
56057 			if (arr_idx < DUK_HSTRING_GET_CHARLEN(h_val)) {
56058 				DUK_DDD(DUK_DDDPRINT("-> found, array index inside string"));
56059 				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
56060 					duk_push_hstring(thr, h_val);
56061 					duk_substring(thr, -1, arr_idx, arr_idx + 1);  /* [str] -> [substr] */
56062 				}
56063 				out_desc->flags = DUK_PROPDESC_FLAG_ENUMERABLE |  /* E5 Section 15.5.5.2 */
56064 				                  DUK_PROPDESC_FLAG_VIRTUAL;
56065 				out_desc->get = NULL;
56066 				out_desc->set = NULL;
56067 				out_desc->e_idx = -1;
56068 				out_desc->h_idx = -1;
56069 				out_desc->a_idx = -1;
56070 
56071 				DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
56072 				goto prop_found_noexotic;  /* cannot be arguments exotic */
56073 			} else {
56074 				/* index is above internal string length -> property is fully normal */
56075 				DUK_DDD(DUK_DDDPRINT("array index outside string -> normal property"));
56076 			}
56077 		} else if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
56078 			duk_hstring *h_val;
56079 
56080 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
56081 
56082 			h_val = duk_hobject_get_internal_value_string(thr->heap, obj);
56083 			DUK_ASSERT(h_val != NULL);
56084 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
56085 				duk_push_uint(thr, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h_val));
56086 			}
56087 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;  /* E5 Section 15.5.5.1 */
56088 			out_desc->get = NULL;
56089 			out_desc->set = NULL;
56090 			out_desc->e_idx = -1;
56091 			out_desc->h_idx = -1;
56092 			out_desc->a_idx = -1;
56093 
56094 			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
56095 			goto prop_found_noexotic;  /* cannot be arguments exotic */
56096 		}
56097 	}
56098 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
56099 	else if (DUK_HOBJECT_IS_BUFOBJ(obj)) {
56100 		duk_hbufobj *h_bufobj;
56101 		duk_uint_t byte_off;
56102 		duk_small_uint_t elem_size;
56103 
56104 		h_bufobj = (duk_hbufobj *) obj;
56105 		DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
56106 		DUK_DDD(DUK_DDDPRINT("bufobj property get for key: %!O, arr_idx: %ld",
56107 		                     (duk_heaphdr *) key, (long) arr_idx));
56108 
56109 		if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
56110 			DUK_DDD(DUK_DDDPRINT("array index exists"));
56111 
56112 			/* Careful with wrapping: arr_idx upshift may easily wrap, whereas
56113 			 * length downshift won't.
56114 			 */
56115 			if (arr_idx < (h_bufobj->length >> h_bufobj->shift)) {
56116 				byte_off = arr_idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
56117 				elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
56118 				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
56119 					duk_uint8_t *data;
56120 
56121 					if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
56122 						data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
56123 						duk_hbufobj_push_validated_read(thr, h_bufobj, data, elem_size);
56124 					} else {
56125 						DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (read zero)"));
56126 						duk_push_uint(thr, 0);
56127 					}
56128 				}
56129 				out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
56130 				                  DUK_PROPDESC_FLAG_VIRTUAL;
56131 				if (DUK_HOBJECT_GET_CLASS_NUMBER(obj) != DUK_HOBJECT_CLASS_ARRAYBUFFER) {
56132 					/* ArrayBuffer indices are non-standard and are
56133 					 * non-enumerable to avoid their serialization.
56134 					 */
56135 					out_desc->flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
56136 				}
56137 				out_desc->get = NULL;
56138 				out_desc->set = NULL;
56139 				out_desc->e_idx = -1;
56140 				out_desc->h_idx = -1;
56141 				out_desc->a_idx = -1;
56142 
56143 				DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
56144 				goto prop_found_noexotic;  /* cannot be e.g. arguments exotic, since exotic 'traits' are mutually exclusive */
56145 			} else {
56146 				/* index is above internal buffer length -> property is fully normal */
56147 				DUK_DDD(DUK_DDDPRINT("array index outside buffer -> normal property"));
56148 			}
56149 		} else if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
56150 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
56151 
56152 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
56153 				/* Length in elements: take into account shift, but
56154 				 * intentionally don't check the underlying buffer here.
56155 				 */
56156 				duk_push_uint(thr, h_bufobj->length >> h_bufobj->shift);
56157 			}
56158 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
56159 			out_desc->get = NULL;
56160 			out_desc->set = NULL;
56161 			out_desc->e_idx = -1;
56162 			out_desc->h_idx = -1;
56163 			out_desc->a_idx = -1;
56164 
56165 			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
56166 			goto prop_found_noexotic;  /* cannot be arguments exotic */
56167 		}
56168 	}
56169 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
56170 
56171 	/* Array properties have exotic behavior but they are concrete,
56172 	 * so no special handling here.
56173 	 *
56174 	 * Arguments exotic behavior (E5 Section 10.6, [[GetOwnProperty]]
56175 	 * is only relevant as a post-check implemented below; hence no
56176 	 * check here.
56177 	 */
56178 
56179 	/*
56180 	 *  Not found as concrete or virtual.
56181 	 */
56182 
56183  prop_not_found:
56184 	DUK_DDD(DUK_DDDPRINT("-> not found (virtual, entry part, or array part)"));
56185 	DUK_STATS_INC(thr->heap, stats_getownpropdesc_miss);
56186 	return 0;
56187 
56188 	/*
56189 	 *  Found.
56190 	 *
56191 	 *  Arguments object has exotic post-processing, see E5 Section 10.6,
56192 	 *  description of [[GetOwnProperty]] variant for arguments.
56193 	 */
56194 
56195  prop_found:
56196 	DUK_DDD(DUK_DDDPRINT("-> property found, checking for arguments exotic post-behavior"));
56197 
56198 	/* Notes:
56199 	 *  - Only numbered indices are relevant, so arr_idx fast reject is good
56200 	 *    (this is valid unless there are more than 4**32-1 arguments).
56201 	 *  - Since variable lookup has no side effects, this can be skipped if
56202 	 *    DUK_GETDESC_FLAG_PUSH_VALUE is not set.
56203 	 */
56204 
56205 	if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&
56206 	                 arr_idx != DUK__NO_ARRAY_INDEX &&
56207 	                 (flags & DUK_GETDESC_FLAG_PUSH_VALUE))) {
56208 		duk_propdesc temp_desc;
56209 
56210 		/* Magically bound variable cannot be an accessor.  However,
56211 		 * there may be an accessor property (or a plain property) in
56212 		 * place with magic behavior removed.  This happens e.g. when
56213 		 * a magic property is redefined with defineProperty().
56214 		 * Cannot assert for "not accessor" here.
56215 		 */
56216 
56217 		/* replaces top of stack with new value if necessary */
56218 		DUK_ASSERT((flags & DUK_GETDESC_FLAG_PUSH_VALUE) != 0);
56219 
56220 		/* This can perform a variable lookup but only into a declarative
56221 		 * environment which has no side effects.
56222 		 */
56223 		if (duk__check_arguments_map_for_get(thr, obj, key, &temp_desc)) {
56224 			DUK_DDD(DUK_DDDPRINT("-> arguments exotic behavior overrides result: %!T -> %!T",
56225 			                     (duk_tval *) duk_get_tval(thr, -2),
56226 			                     (duk_tval *) duk_get_tval(thr, -1)));
56227 			/* [... old_result result] -> [... result] */
56228 			duk_remove_m2(thr);
56229 		}
56230 	}
56231 
56232  prop_found_noexotic:
56233 	DUK_STATS_INC(thr->heap, stats_getownpropdesc_hit);
56234 	return 1;
56235 }
56236 
56237 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) {
56238 	DUK_ASSERT(thr != NULL);
56239 	DUK_ASSERT(obj != NULL);
56240 	DUK_ASSERT(key != NULL);
56241 	DUK_ASSERT(out_desc != NULL);
56242 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
56243 
56244 	return duk__get_own_propdesc_raw(thr, obj, key, DUK_HSTRING_GET_ARRIDX_SLOW(key), out_desc, flags);
56245 }
56246 
56247 /*
56248  *  ECMAScript compliant [[GetProperty]](P), for internal use only.
56249  *
56250  *  If property is found:
56251  *    - Fills descriptor fields to 'out_desc'
56252  *    - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
56253  *      property onto the stack ('undefined' for accessor properties).
56254  *    - Returns non-zero
56255  *
56256  *  If property is not found:
56257  *    - 'out_desc' is left in untouched state (possibly garbage)
56258  *    - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
56259  *      set)
56260  *    - Returns zero
56261  *
56262  *  May cause arbitrary side effects and invalidate (most) duk_tval
56263  *  pointers.
56264  */
56265 
56266 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) {
56267 	duk_hobject *curr;
56268 	duk_uint32_t arr_idx;
56269 	duk_uint_t sanity;
56270 
56271 	DUK_ASSERT(thr != NULL);
56272 	DUK_ASSERT(thr->heap != NULL);
56273 	DUK_ASSERT(obj != NULL);
56274 	DUK_ASSERT(key != NULL);
56275 	DUK_ASSERT(out_desc != NULL);
56276 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
56277 
56278 	DUK_STATS_INC(thr->heap, stats_getpropdesc_count);
56279 
56280 	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
56281 
56282 	DUK_DDD(DUK_DDDPRINT("duk__get_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
56283 	                     "arr_idx=%ld (obj -> %!O, key -> %!O)",
56284 	                     (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
56285 	                     (long) flags, (long) arr_idx,
56286 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
56287 
56288 	curr = obj;
56289 	DUK_ASSERT(curr != NULL);
56290 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
56291 	do {
56292 		if (duk__get_own_propdesc_raw(thr, curr, key, arr_idx, out_desc, flags)) {
56293 			/* stack contains value (if requested), 'out_desc' is set */
56294 			DUK_STATS_INC(thr->heap, stats_getpropdesc_hit);
56295 			return 1;
56296 		}
56297 
56298 		/* not found in 'curr', next in prototype chain; impose max depth */
56299 		if (DUK_UNLIKELY(sanity-- == 0)) {
56300 			if (flags & DUK_GETDESC_FLAG_IGNORE_PROTOLOOP) {
56301 				/* treat like property not found */
56302 				break;
56303 			} else {
56304 				DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
56305 				DUK_WO_NORETURN(return 0;);
56306 			}
56307 		}
56308 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
56309 	} while (curr != NULL);
56310 
56311 	/* out_desc is left untouched (possibly garbage), caller must use return
56312 	 * value to determine whether out_desc can be looked up
56313 	 */
56314 
56315 	DUK_STATS_INC(thr->heap, stats_getpropdesc_miss);
56316 	return 0;
56317 }
56318 
56319 /*
56320  *  Shallow fast path checks for accessing array elements with numeric
56321  *  indices.  The goal is to try to avoid coercing an array index to an
56322  *  (interned) string for the most common lookups, in particular, for
56323  *  standard Array objects.
56324  *
56325  *  Interning is avoided but only for a very narrow set of cases:
56326  *    - Object has array part, index is within array allocation, and
56327  *      value is not unused (= key exists)
56328  *    - Object has no interfering exotic behavior (e.g. arguments or
56329  *      string object exotic behaviors interfere, array exotic
56330  *      behavior does not).
56331  *
56332  *  Current shortcoming: if key does not exist (even if it is within
56333  *  the array allocation range) a slow path lookup with interning is
56334  *  always required.  This can probably be fixed so that there is a
56335  *  quick fast path for non-existent elements as well, at least for
56336  *  standard Array objects.
56337  */
56338 
56339 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
56340 DUK_LOCAL duk_tval *duk__getprop_shallow_fastpath_array_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) {
56341 	duk_tval *tv;
56342 	duk_uint32_t idx;
56343 
56344 	DUK_UNREF(thr);
56345 
56346 	if (!(DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
56347 	     !DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&
56348 	     !DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj) &&
56349 	     !DUK_HOBJECT_IS_BUFOBJ(obj) &&
56350 	     !DUK_HOBJECT_IS_PROXY(obj))) {
56351 		/* Must have array part and no conflicting exotic behaviors.
56352 		 * Doesn't need to have array special behavior, e.g. Arguments
56353 		 * object has array part.
56354 		 */
56355 		return NULL;
56356 	}
56357 
56358 	/* Arrays never have other exotic behaviors. */
56359 
56360 	DUK_DDD(DUK_DDDPRINT("fast path attempt (no exotic string/arguments/buffer "
56361 	                     "behavior, object has array part)"));
56362 
56363 #if defined(DUK_USE_FASTINT)
56364 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
56365 		idx = duk__tval_fastint_to_arr_idx(tv_key);
56366 	} else
56367 #endif
56368 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
56369 		idx = duk__tval_number_to_arr_idx(tv_key);
56370 	} else {
56371 		DUK_DDD(DUK_DDDPRINT("key is not a number"));
56372 		return NULL;
56373 	}
56374 
56375 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
56376 	 * is 0xffffffffUL.  We don't need to check for that explicitly
56377 	 * because 0xffffffffUL will never be inside object 'a_size'.
56378 	 */
56379 
56380 	if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
56381 		DUK_DDD(DUK_DDDPRINT("key is not an array index or outside array part"));
56382 		return NULL;
56383 	}
56384 	DUK_ASSERT(idx != 0xffffffffUL);
56385 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
56386 
56387 	/* XXX: for array instances we could take a shortcut here and assume
56388 	 * Array.prototype doesn't contain an array index property.
56389 	 */
56390 
56391 	DUK_DDD(DUK_DDDPRINT("key is a valid array index and inside array part"));
56392 	tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
56393 	if (!DUK_TVAL_IS_UNUSED(tv)) {
56394 		DUK_DDD(DUK_DDDPRINT("-> fast path successful"));
56395 		return tv;
56396 	}
56397 
56398 	DUK_DDD(DUK_DDDPRINT("fast path attempt failed, fall back to slow path"));
56399 	return NULL;
56400 }
56401 
56402 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) {
56403 	duk_tval *tv;
56404 	duk_harray *a;
56405 	duk_uint32_t idx;
56406 	duk_uint32_t old_len, new_len;
56407 
56408 	if (!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj) &&
56409 	      DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
56410 	      DUK_HOBJECT_HAS_EXTENSIBLE(obj))) {
56411 		return 0;
56412 	}
56413 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));  /* caller ensures */
56414 
56415 	a = (duk_harray *) obj;
56416 	DUK_ASSERT_HARRAY_VALID(a);
56417 
56418 #if defined(DUK_USE_FASTINT)
56419 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
56420 		idx = duk__tval_fastint_to_arr_idx(tv_key);
56421 	} else
56422 #endif
56423 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
56424 		idx = duk__tval_number_to_arr_idx(tv_key);
56425 	} else {
56426 		DUK_DDD(DUK_DDDPRINT("key is not a number"));
56427 		return 0;
56428 	}
56429 
56430 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
56431 	 * is 0xffffffffUL.  We don't need to check for that explicitly
56432 	 * because 0xffffffffUL will never be inside object 'a_size'.
56433 	 */
56434 
56435 	if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {  /* for resizing of array part, use slow path */
56436 		return 0;
56437 	}
56438 	DUK_ASSERT(idx != 0xffffffffUL);
56439 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
56440 
56441 	old_len = a->length;
56442 
56443 	if (idx >= old_len) {
56444 		DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
56445 		                     "(arr_idx=%ld, old_len=%ld)",
56446 		                     (long) idx, (long) old_len));
56447 		if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
56448 			/* The correct behavior here is either a silent error
56449 			 * or a TypeError, depending on strictness.  Fall back
56450 			 * to the slow path to handle the situation.
56451 			 */
56452 			return 0;
56453 		}
56454 		new_len = idx + 1;
56455 
56456 		((duk_harray *) obj)->length = new_len;
56457 	}
56458 
56459 	tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
56460 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects */
56461 
56462 	DUK_DDD(DUK_DDDPRINT("array fast path success for index %ld", (long) idx));
56463 	return 1;
56464 }
56465 #endif  /* DUK_USE_ARRAY_PROP_FASTPATH */
56466 
56467 /*
56468  *  Fast path for bufobj getprop/putprop
56469  */
56470 
56471 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
56472 DUK_LOCAL duk_bool_t duk__getprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) {
56473 	duk_uint32_t idx;
56474 	duk_hbufobj *h_bufobj;
56475 	duk_uint_t byte_off;
56476 	duk_small_uint_t elem_size;
56477 	duk_uint8_t *data;
56478 
56479 	if (!DUK_HOBJECT_IS_BUFOBJ(obj)) {
56480 		return 0;
56481 	}
56482 	h_bufobj = (duk_hbufobj *) obj;
56483 	if (!DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
56484 		return 0;
56485 	}
56486 
56487 #if defined(DUK_USE_FASTINT)
56488 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
56489 		idx = duk__tval_fastint_to_arr_idx(tv_key);
56490 	} else
56491 #endif
56492 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
56493 		idx = duk__tval_number_to_arr_idx(tv_key);
56494 	} else {
56495 		return 0;
56496 	}
56497 
56498 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
56499 	 * is 0xffffffffUL.  We don't need to check for that explicitly
56500 	 * because 0xffffffffUL will never be inside bufobj length.
56501 	 */
56502 
56503 	/* Careful with wrapping (left shifting idx would be unsafe). */
56504 	if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
56505 		return 0;
56506 	}
56507 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
56508 
56509 	byte_off = idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
56510 	elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
56511 
56512 	if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
56513 		data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
56514 		duk_hbufobj_push_validated_read(thr, h_bufobj, data, elem_size);
56515 	} else {
56516 		DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (read zero)"));
56517 		duk_push_uint(thr, 0);
56518 	}
56519 
56520 	return 1;
56521 }
56522 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
56523 
56524 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
56525 DUK_LOCAL duk_bool_t duk__putprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key, duk_tval *tv_val) {
56526 	duk_uint32_t idx;
56527 	duk_hbufobj *h_bufobj;
56528 	duk_uint_t byte_off;
56529 	duk_small_uint_t elem_size;
56530 	duk_uint8_t *data;
56531 
56532 	if (!(DUK_HOBJECT_IS_BUFOBJ(obj) &&
56533 	      DUK_TVAL_IS_NUMBER(tv_val))) {
56534 		return 0;
56535 	}
56536 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));  /* caller ensures; rom objects are never bufobjs now */
56537 
56538 	h_bufobj = (duk_hbufobj *) obj;
56539 	if (!DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
56540 		return 0;
56541 	}
56542 
56543 #if defined(DUK_USE_FASTINT)
56544 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
56545 		idx = duk__tval_fastint_to_arr_idx(tv_key);
56546 	} else
56547 #endif
56548 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
56549 		idx = duk__tval_number_to_arr_idx(tv_key);
56550 	} else {
56551 		return 0;
56552 	}
56553 
56554 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
56555 	 * is 0xffffffffUL.  We don't need to check for that explicitly
56556 	 * because 0xffffffffUL will never be inside bufobj length.
56557 	 */
56558 
56559 	/* Careful with wrapping (left shifting idx would be unsafe). */
56560 	if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
56561 		return 0;
56562 	}
56563 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
56564 
56565 	byte_off = idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
56566 	elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
56567 
56568 	/* Value is required to be a number in the fast path so there
56569 	 * are no side effects in write coercion.
56570 	 */
56571 	duk_push_tval(thr, tv_val);
56572 	DUK_ASSERT(duk_is_number(thr, -1));
56573 
56574 	if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
56575 		data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
56576 		duk_hbufobj_validated_write(thr, h_bufobj, data, elem_size);
56577 	} else {
56578 		DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (write skipped)"));
56579 	}
56580 
56581 	duk_pop_unsafe(thr);
56582 	return 1;
56583 }
56584 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
56585 
56586 /*
56587  *  GETPROP: ECMAScript property read.
56588  */
56589 
56590 DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
56591 	duk_tval tv_obj_copy;
56592 	duk_tval tv_key_copy;
56593 	duk_hobject *curr = NULL;
56594 	duk_hstring *key = NULL;
56595 	duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
56596 	duk_propdesc desc;
56597 	duk_uint_t sanity;
56598 
56599 	DUK_DDD(DUK_DDDPRINT("getprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
56600 	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
56601 	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));
56602 
56603 	DUK_ASSERT(thr != NULL);
56604 	DUK_ASSERT(thr->heap != NULL);
56605 	DUK_ASSERT(tv_obj != NULL);
56606 	DUK_ASSERT(tv_key != NULL);
56607 
56608 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
56609 
56610 	DUK_STATS_INC(thr->heap, stats_getprop_all);
56611 
56612 	/*
56613 	 *  Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
56614 	 *  them being invalidated by a valstack resize.
56615 	 *
56616 	 *  XXX: this is now an overkill for many fast paths.  Rework this
56617 	 *  to be faster (although switching to a valstack discipline might
56618 	 *  be a better solution overall).
56619 	 */
56620 
56621 	DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
56622 	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
56623 	tv_obj = &tv_obj_copy;
56624 	tv_key = &tv_key_copy;
56625 
56626 	/*
56627 	 *  Coercion and fast path processing
56628 	 */
56629 
56630 	switch (DUK_TVAL_GET_TAG(tv_obj)) {
56631 	case DUK_TAG_UNDEFINED:
56632 	case DUK_TAG_NULL: {
56633 		/* Note: unconditional throw */
56634 		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
56635 #if defined(DUK_USE_PARANOID_ERRORS)
56636 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
56637 #else
56638 		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot read property %s of %s",
56639 		               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
56640 #endif
56641 		DUK_WO_NORETURN(return 0;);
56642 		break;
56643 	}
56644 
56645 	case DUK_TAG_BOOLEAN: {
56646 		DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
56647 		curr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];
56648 		break;
56649 	}
56650 
56651 	case DUK_TAG_STRING: {
56652 		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
56653 		duk_int_t pop_count;
56654 
56655 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
56656 			/* Symbols (ES2015 or hidden) don't have virtual properties. */
56657 			DUK_DDD(DUK_DDDPRINT("base object is a symbol, start lookup from symbol prototype"));
56658 			curr = thr->builtins[DUK_BIDX_SYMBOL_PROTOTYPE];
56659 			break;
56660 		}
56661 
56662 #if defined(DUK_USE_FASTINT)
56663 		if (DUK_TVAL_IS_FASTINT(tv_key)) {
56664 			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
56665 			DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
56666 			pop_count = 0;
56667 		} else
56668 #endif
56669 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
56670 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
56671 			DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path number; arr_idx %ld", (long) arr_idx));
56672 			pop_count = 0;
56673 		} else {
56674 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
56675 			DUK_ASSERT(key != NULL);
56676 			DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
56677 			                     "coercion key is %!T, arr_idx %ld",
56678 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
56679 			pop_count = 1;
56680 		}
56681 
56682 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
56683 		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
56684 			duk_pop_n_unsafe(thr, pop_count);
56685 			duk_push_hstring(thr, h);
56686 			duk_substring(thr, -1, arr_idx, arr_idx + 1);  /* [str] -> [substr] */
56687 
56688 			DUK_STATS_INC(thr->heap, stats_getprop_stringidx);
56689 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is an index inside string length "
56690 			                     "after coercion -> return char)",
56691 			                     (duk_tval *) duk_get_tval(thr, -1)));
56692 			return 1;
56693 		}
56694 
56695 		if (pop_count == 0) {
56696 			/* This is a pretty awkward control flow, but we need to recheck the
56697 			 * key coercion here.
56698 			 */
56699 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
56700 			DUK_ASSERT(key != NULL);
56701 			DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
56702 			                     "coercion key is %!T, arr_idx %ld",
56703 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
56704 		}
56705 
56706 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
56707 			duk_pop_unsafe(thr);  /* [key] -> [] */
56708 			duk_push_uint(thr, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h));  /* [] -> [res] */
56709 
56710 			DUK_STATS_INC(thr->heap, stats_getprop_stringlen);
56711 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is 'length' after coercion -> "
56712 			                     "return string length)",
56713 			                     (duk_tval *) duk_get_tval(thr, -1)));
56714 			return 1;
56715 		}
56716 
56717 		DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
56718 		curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
56719 		goto lookup;  /* avoid double coercion */
56720 	}
56721 
56722 	case DUK_TAG_OBJECT: {
56723 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
56724 		duk_tval *tmp;
56725 #endif
56726 
56727 		curr = DUK_TVAL_GET_OBJECT(tv_obj);
56728 		DUK_ASSERT(curr != NULL);
56729 
56730 		/* XXX: array .length fast path (important in e.g. loops)? */
56731 
56732 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
56733 		tmp = duk__getprop_shallow_fastpath_array_tval(thr, curr, tv_key);
56734 		if (tmp) {
56735 			duk_push_tval(thr, tmp);
56736 
56737 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is object, key is a number, array part "
56738 			                     "fast path)",
56739 			                     (duk_tval *) duk_get_tval(thr, -1)));
56740 			DUK_STATS_INC(thr->heap, stats_getprop_arrayidx);
56741 			return 1;
56742 		}
56743 #endif
56744 
56745 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
56746 		if (duk__getprop_fastpath_bufobj_tval(thr, curr, tv_key) != 0) {
56747 			/* Read value pushed on stack. */
56748 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is bufobj, key is a number, bufobj "
56749 			                     "fast path)",
56750 			                     (duk_tval *) duk_get_tval(thr, -1)));
56751 			DUK_STATS_INC(thr->heap, stats_getprop_bufobjidx);
56752 			return 1;
56753 		}
56754 #endif
56755 
56756 #if defined(DUK_USE_ES6_PROXY)
56757 		if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(curr))) {
56758 			duk_hobject *h_target;
56759 
56760 			if (duk__proxy_check_prop(thr, curr, DUK_STRIDX_GET, tv_key, &h_target)) {
56761 				/* -> [ ... trap handler ] */
56762 				DUK_DDD(DUK_DDDPRINT("-> proxy object 'get' for key %!T", (duk_tval *) tv_key));
56763 				DUK_STATS_INC(thr->heap, stats_getprop_proxy);
56764 				duk_push_hobject(thr, h_target);  /* target */
56765 				duk_push_tval(thr, tv_key);       /* P */
56766 				duk_push_tval(thr, tv_obj);       /* Receiver: Proxy object */
56767 				duk_call_method(thr, 3 /*nargs*/);
56768 
56769 				/* Target object must be checked for a conflicting
56770 				 * non-configurable property.
56771 				 */
56772 				arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
56773 				DUK_ASSERT(key != NULL);
56774 
56775 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
56776 					duk_tval *tv_hook = duk_require_tval(thr, -3);  /* value from hook */
56777 					duk_tval *tv_targ = duk_require_tval(thr, -1);  /* value from target */
56778 					duk_bool_t datadesc_reject;
56779 					duk_bool_t accdesc_reject;
56780 
56781 					DUK_DDD(DUK_DDDPRINT("proxy 'get': target has matching property %!O, check for "
56782 					                     "conflicting property; tv_hook=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
56783 					                     "desc.get=%p, desc.set=%p",
56784 					                     (duk_heaphdr *) key, (duk_tval *) tv_hook, (duk_tval *) tv_targ,
56785 					                     (unsigned long) desc.flags,
56786 					                     (void *) desc.get, (void *) desc.set));
56787 
56788 					datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
56789 					                  !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
56790 					                  !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) &&
56791 					                  !duk_js_samevalue(tv_hook, tv_targ);
56792 					accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
56793 					                 !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
56794 					                 (desc.get == NULL) &&
56795 					                 !DUK_TVAL_IS_UNDEFINED(tv_hook);
56796 					if (datadesc_reject || accdesc_reject) {
56797 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
56798 						DUK_WO_NORETURN(return 0;);
56799 					}
56800 
56801 					duk_pop_2_unsafe(thr);
56802 				} else {
56803 					duk_pop_unsafe(thr);
56804 				}
56805 				return 1;  /* return value */
56806 			}
56807 
56808 			curr = h_target;  /* resume lookup from target */
56809 			DUK_TVAL_SET_OBJECT(tv_obj, curr);
56810 		}
56811 #endif  /* DUK_USE_ES6_PROXY */
56812 
56813 		if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(curr)) {
56814 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
56815 			DUK_ASSERT(key != NULL);
56816 
56817 			DUK_STATS_INC(thr->heap, stats_getprop_arguments);
56818 			if (duk__check_arguments_map_for_get(thr, curr, key, &desc)) {
56819 				DUK_DDD(DUK_DDDPRINT("-> %!T (base is object with arguments exotic behavior, "
56820 				                     "key matches magically bound property -> skip standard "
56821 				                     "Get with replacement value)",
56822 				                     (duk_tval *) duk_get_tval(thr, -1)));
56823 
56824 				/* no need for 'caller' post-check, because 'key' must be an array index */
56825 
56826 				duk_remove_m2(thr);  /* [key result] -> [result] */
56827 				return 1;
56828 			}
56829 
56830 			goto lookup;  /* avoid double coercion */
56831 		}
56832 		break;
56833 	}
56834 
56835 	/* Buffer has virtual properties similar to string, but indexed values
56836 	 * are numbers, not 1-byte buffers/strings which would perform badly.
56837 	 */
56838 	case DUK_TAG_BUFFER: {
56839 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
56840 		duk_int_t pop_count;
56841 
56842 		/*
56843 		 *  Because buffer values are often looped over, a number fast path
56844 		 *  is important.
56845 		 */
56846 
56847 #if defined(DUK_USE_FASTINT)
56848 		if (DUK_TVAL_IS_FASTINT(tv_key)) {
56849 			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
56850 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
56851 			pop_count = 0;
56852 		}
56853 		else
56854 #endif
56855 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
56856 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
56857 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
56858 			pop_count = 0;
56859 		} else {
56860 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
56861 			DUK_ASSERT(key != NULL);
56862 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
56863 			                     "coercion key is %!T, arr_idx %ld",
56864 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
56865 			pop_count = 1;
56866 		}
56867 
56868 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
56869 		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
56870 			duk_pop_n_unsafe(thr, pop_count);
56871 			duk_push_uint(thr, ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h))[arr_idx]);
56872 			DUK_STATS_INC(thr->heap, stats_getprop_bufferidx);
56873 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is an index inside buffer length "
56874 			                     "after coercion -> return byte as number)",
56875 			                     (duk_tval *) duk_get_tval(thr, -1)));
56876 			return 1;
56877 		}
56878 
56879 		if (pop_count == 0) {
56880 			/* This is a pretty awkward control flow, but we need to recheck the
56881 			 * key coercion here.
56882 			 */
56883 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
56884 			DUK_ASSERT(key != NULL);
56885 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
56886 			                     "coercion key is %!T, arr_idx %ld",
56887 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
56888 		}
56889 
56890 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
56891 			duk_pop_unsafe(thr);  /* [key] -> [] */
56892 			duk_push_uint(thr, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h));  /* [] -> [res] */
56893 			DUK_STATS_INC(thr->heap, stats_getprop_bufferlen);
56894 
56895 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'length' "
56896 			                     "after coercion -> return buffer length)",
56897 			                     (duk_tval *) duk_get_tval(thr, -1)));
56898 			return 1;
56899 		}
56900 
56901 		DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from Uint8Array prototype"));
56902 		curr = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
56903 		goto lookup;  /* avoid double coercion */
56904 	}
56905 
56906 	case DUK_TAG_POINTER: {
56907 		DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
56908 		curr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
56909 		break;
56910 	}
56911 
56912 	case DUK_TAG_LIGHTFUNC: {
56913 		/* Lightfuncs inherit getter .name and .length from %NativeFunctionPrototype%. */
56914 		DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
56915 		curr = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];
56916 		break;
56917 	}
56918 
56919 #if defined(DUK_USE_FASTINT)
56920 	case DUK_TAG_FASTINT:
56921 #endif
56922 	default: {
56923 		/* number */
56924 		DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
56925 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_obj));
56926 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_obj));
56927 		curr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];
56928 		break;
56929 	}
56930 	}
56931 
56932 	/* key coercion (unless already coerced above) */
56933 	DUK_ASSERT(key == NULL);
56934 	arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
56935 	DUK_ASSERT(key != NULL);
56936 	/*
56937 	 *  Property lookup
56938 	 */
56939 
56940  lookup:
56941 	/* [key] (coerced) */
56942 	DUK_ASSERT(curr != NULL);
56943 	DUK_ASSERT(key != NULL);
56944 
56945 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
56946 	do {
56947 		if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
56948 			goto next_in_chain;
56949 		}
56950 
56951 		if (desc.get != NULL) {
56952 			/* accessor with defined getter */
56953 			DUK_ASSERT((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0);
56954 
56955 			duk_pop_unsafe(thr);              /* [key undefined] -> [key] */
56956 			duk_push_hobject(thr, desc.get);
56957 			duk_push_tval(thr, tv_obj);       /* note: original, uncoerced base */
56958 #if defined(DUK_USE_NONSTD_GETTER_KEY_ARGUMENT)
56959 			duk_dup_m3(thr);
56960 			duk_call_method(thr, 1);          /* [key getter this key] -> [key retval] */
56961 #else
56962 			duk_call_method(thr, 0);          /* [key getter this] -> [key retval] */
56963 #endif
56964 		} else {
56965 			/* [key value] or [key undefined] */
56966 
56967 			/* data property or accessor without getter */
56968 			DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) ||
56969 			           (desc.get == NULL));
56970 
56971 			/* if accessor without getter, return value is undefined */
56972 			DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) ||
56973 			           duk_is_undefined(thr, -1));
56974 
56975 			/* Note: for an accessor without getter, falling through to
56976 			 * check for "caller" exotic behavior is unnecessary as
56977 			 * "undefined" will never activate the behavior.  But it does
56978 			 * no harm, so we'll do it anyway.
56979 			 */
56980 		}
56981 
56982 		goto found;  /* [key result] */
56983 
56984 	 next_in_chain:
56985 		/* XXX: option to pretend property doesn't exist if sanity limit is
56986 		 * hit might be useful.
56987 		 */
56988 		if (DUK_UNLIKELY(sanity-- == 0)) {
56989 			DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
56990 			DUK_WO_NORETURN(return 0;);
56991 		}
56992 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
56993 	} while (curr != NULL);
56994 
56995 	/*
56996 	 *  Not found
56997 	 */
56998 
56999 	duk_to_undefined(thr, -1);  /* [key] -> [undefined] (default value) */
57000 
57001 	DUK_DDD(DUK_DDDPRINT("-> %!T (not found)", (duk_tval *) duk_get_tval(thr, -1)));
57002 	return 0;
57003 
57004 	/*
57005 	 *  Found; post-processing (Function and arguments objects)
57006 	 */
57007 
57008  found:
57009 	/* [key result] */
57010 
57011 #if !defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
57012 	/* Special behavior for 'caller' property of (non-bound) function objects
57013 	 * and non-strict Arguments objects: if 'caller' -value- (!) is a strict
57014 	 * mode function, throw a TypeError (E5 Sections 15.3.5.4, 10.6).
57015 	 * Quite interestingly, a non-strict function with no formal arguments
57016 	 * will get an arguments object -without- special 'caller' behavior!
57017 	 *
57018 	 * The E5.1 spec is a bit ambiguous if this special behavior applies when
57019 	 * a bound function is the base value (not the 'caller' value): Section
57020 	 * 15.3.4.5 (describing bind()) states that [[Get]] for bound functions
57021 	 * matches that of Section 15.3.5.4 ([[Get]] for Function instances).
57022 	 * However, Section 13.3.5.4 has "NOTE: Function objects created using
57023 	 * Function.prototype.bind use the default [[Get]] internal method."
57024 	 * The current implementation assumes this means that bound functions
57025 	 * should not have the special [[Get]] behavior.
57026 	 *
57027 	 * The E5.1 spec is also a bit unclear if the TypeError throwing is
57028 	 * applied if the 'caller' value is a strict bound function.  The
57029 	 * current implementation will throw even for both strict non-bound
57030 	 * and strict bound functions.
57031 	 *
57032 	 * See test-dev-strict-func-as-caller-prop-value.js for quite extensive
57033 	 * tests.
57034 	 *
57035 	 * This exotic behavior is disabled when the non-standard 'caller' property
57036 	 * is enabled, as it conflicts with the free use of 'caller'.
57037 	 */
57038 	if (key == DUK_HTHREAD_STRING_CALLER(thr) &&
57039 	    DUK_TVAL_IS_OBJECT(tv_obj)) {
57040 		duk_hobject *orig = DUK_TVAL_GET_OBJECT(tv_obj);
57041 		DUK_ASSERT(orig != NULL);
57042 
57043 		if (DUK_HOBJECT_IS_NONBOUND_FUNCTION(orig) ||
57044 		    DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
57045 			duk_hobject *h;
57046 
57047 			/* XXX: The TypeError is currently not applied to bound
57048 			 * functions because the 'strict' flag is not copied by
57049 			 * bind().  This may or may not be correct, the specification
57050 			 * only refers to the value being a "strict mode Function
57051 			 * object" which is ambiguous.
57052 			 */
57053 			DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(orig));
57054 
57055 			h = duk_get_hobject(thr, -1);  /* NULL if not an object */
57056 			if (h &&
57057 			    DUK_HOBJECT_IS_FUNCTION(h) &&
57058 			    DUK_HOBJECT_HAS_STRICT(h)) {
57059 				/* XXX: sufficient to check 'strict', assert for 'is function' */
57060 				DUK_ERROR_TYPE(thr, DUK_STR_STRICT_CALLER_READ);
57061 				DUK_WO_NORETURN(return 0;);
57062 			}
57063 		}
57064 	}
57065 #endif   /* !DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
57066 
57067 	duk_remove_m2(thr);  /* [key result] -> [result] */
57068 
57069 	DUK_DDD(DUK_DDDPRINT("-> %!T (found)", (duk_tval *) duk_get_tval(thr, -1)));
57070 	return 1;
57071 }
57072 
57073 /*
57074  *  HASPROP: ECMAScript property existence check ("in" operator).
57075  *
57076  *  Interestingly, the 'in' operator does not do any coercion of
57077  *  the target object.
57078  */
57079 
57080 DUK_INTERNAL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
57081 	duk_tval tv_key_copy;
57082 	duk_hobject *obj;
57083 	duk_hstring *key;
57084 	duk_uint32_t arr_idx;
57085 	duk_bool_t rc;
57086 	duk_propdesc desc;
57087 
57088 	DUK_DDD(DUK_DDDPRINT("hasprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
57089 	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
57090 	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));
57091 
57092 	DUK_ASSERT(thr != NULL);
57093 	DUK_ASSERT(thr->heap != NULL);
57094 	DUK_ASSERT(tv_obj != NULL);
57095 	DUK_ASSERT(tv_key != NULL);
57096 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
57097 
57098 	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
57099 	tv_key = &tv_key_copy;
57100 
57101 	/*
57102 	 *  The 'in' operator requires an object as its right hand side,
57103 	 *  throwing a TypeError unconditionally if this is not the case.
57104 	 *
57105 	 *  However, lightfuncs need to behave like fully fledged objects
57106 	 *  here to be maximally transparent, so we need to handle them
57107 	 *  here.  Same goes for plain buffers which behave like ArrayBuffers.
57108 	 */
57109 
57110 	/* XXX: Refactor key coercion so that it's only called once.  It can't
57111 	 * be trivially lifted here because the object must be type checked
57112 	 * first.
57113 	 */
57114 
57115 	if (DUK_TVAL_IS_OBJECT(tv_obj)) {
57116 		obj = DUK_TVAL_GET_OBJECT(tv_obj);
57117 		DUK_ASSERT(obj != NULL);
57118 
57119 		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57120 	} else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
57121 		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57122 		if (duk__key_is_plain_buf_ownprop(thr, DUK_TVAL_GET_BUFFER(tv_obj), key, arr_idx)) {
57123 			rc = 1;
57124 			goto pop_and_return;
57125 		}
57126 		obj = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
57127 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
57128 		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57129 
57130 		/* If not found, resume existence check from %NativeFunctionPrototype%.
57131 		 * We can just substitute the value in this case; nothing will
57132 		 * need the original base value (as would be the case with e.g.
57133 		 * setters/getters.
57134 		 */
57135 		obj = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];
57136 	} else {
57137 		/* Note: unconditional throw */
57138 		DUK_DDD(DUK_DDDPRINT("base object is not an object -> reject"));
57139 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
57140 		DUK_WO_NORETURN(return 0;);
57141 	}
57142 
57143 	/* XXX: fast path for arrays? */
57144 
57145 	DUK_ASSERT(key != NULL);
57146 	DUK_ASSERT(obj != NULL);
57147 	DUK_UNREF(arr_idx);
57148 
57149 #if defined(DUK_USE_ES6_PROXY)
57150 	if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(obj))) {
57151 		duk_hobject *h_target;
57152 		duk_bool_t tmp_bool;
57153 
57154 		/* XXX: the key in 'key in obj' is string coerced before we're called
57155 		 * (which is the required behavior in E5/E5.1/E6) so the key is a string
57156 		 * here already.
57157 		 */
57158 
57159 		if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_HAS, tv_key, &h_target)) {
57160 			/* [ ... key trap handler ] */
57161 			DUK_DDD(DUK_DDDPRINT("-> proxy object 'has' for key %!T", (duk_tval *) tv_key));
57162 			duk_push_hobject(thr, h_target);  /* target */
57163 			duk_push_tval(thr, tv_key);       /* P */
57164 			duk_call_method(thr, 2 /*nargs*/);
57165 			tmp_bool = duk_to_boolean_top_pop(thr);
57166 			if (!tmp_bool) {
57167 				/* Target object must be checked for a conflicting
57168 				 * non-configurable property.
57169 				 */
57170 
57171 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
57172 					DUK_DDD(DUK_DDDPRINT("proxy 'has': target has matching property %!O, check for "
57173 					                     "conflicting property; desc.flags=0x%08lx, "
57174 					                     "desc.get=%p, desc.set=%p",
57175 					                     (duk_heaphdr *) key, (unsigned long) desc.flags,
57176 					                     (void *) desc.get, (void *) desc.set));
57177 					/* XXX: Extensibility check for target uses IsExtensible().  If we
57178 					 * implemented the isExtensible trap and didn't reject proxies as
57179 					 * proxy targets, it should be respected here.
57180 					 */
57181 					if (!((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&  /* property is configurable and */
57182 					      DUK_HOBJECT_HAS_EXTENSIBLE(h_target))) {          /* ... target is extensible */
57183 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
57184 						DUK_WO_NORETURN(return 0;);
57185 					}
57186 				}
57187 			}
57188 
57189 			duk_pop_unsafe(thr);  /* [ key ] -> [] */
57190 			return tmp_bool;
57191 		}
57192 
57193 		obj = h_target;  /* resume check from proxy target */
57194 	}
57195 #endif  /* DUK_USE_ES6_PROXY */
57196 
57197 	/* XXX: inline into a prototype walking loop? */
57198 
57199 	rc = duk__get_propdesc(thr, obj, key, &desc, 0 /*flags*/);  /* don't push value */
57200 	/* fall through */
57201 
57202  pop_and_return:
57203 	duk_pop_unsafe(thr);  /* [ key ] -> [] */
57204 	return rc;
57205 }
57206 
57207 /*
57208  *  HASPROP variant used internally.
57209  *
57210  *  This primitive must never throw an error, callers rely on this.
57211  *  In particular, don't throw an error for prototype loops; instead,
57212  *  pretend like the property doesn't exist if a prototype sanity limit
57213  *  is reached.
57214  *
57215  *  Does not implement proxy behavior: if applied to a proxy object,
57216  *  returns key existence on the proxy object itself.
57217  */
57218 
57219 DUK_INTERNAL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {
57220 	duk_propdesc dummy;
57221 
57222 	DUK_ASSERT(thr != NULL);
57223 	DUK_ASSERT(thr->heap != NULL);
57224 	DUK_ASSERT(obj != NULL);
57225 	DUK_ASSERT(key != NULL);
57226 
57227 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
57228 
57229 	return duk__get_propdesc(thr, obj, key, &dummy, DUK_GETDESC_FLAG_IGNORE_PROTOLOOP);  /* don't push value */
57230 }
57231 
57232 /*
57233  *  Helper: handle Array object 'length' write which automatically
57234  *  deletes properties, see E5 Section 15.4.5.1, step 3.  This is
57235  *  quite tricky to get right.
57236  *
57237  *  Used by duk_hobject_putprop().
57238  */
57239 
57240 /* Coerce a new .length candidate to a number and check that it's a valid
57241  * .length.
57242  */
57243 DUK_LOCAL duk_uint32_t duk__to_new_array_length_checked(duk_hthread *thr, duk_tval *tv) {
57244 	duk_uint32_t res;
57245 	duk_double_t d;
57246 
57247 #if !defined(DUK_USE_PREFER_SIZE)
57248 #if defined(DUK_USE_FASTINT)
57249 	/* When fastints are enabled, the most interesting case is assigning
57250 	 * a fastint to .length (e.g. arr.length = 0).
57251 	 */
57252 	if (DUK_TVAL_IS_FASTINT(tv)) {
57253 		/* Very common case. */
57254 		duk_int64_t fi;
57255 		fi = DUK_TVAL_GET_FASTINT(tv);
57256 		if (fi < 0 || fi > DUK_I64_CONSTANT(0xffffffff)) {
57257 			goto fail_range;
57258 		}
57259 		return (duk_uint32_t) fi;
57260 	}
57261 #else  /* DUK_USE_FASTINT */
57262 	/* When fastints are not enabled, the most interesting case is any
57263 	 * number.
57264 	 */
57265 	if (DUK_TVAL_IS_DOUBLE(tv)) {
57266 		d = DUK_TVAL_GET_NUMBER(tv);
57267 	}
57268 #endif  /* DUK_USE_FASTINT */
57269 	else
57270 #endif  /* !DUK_USE_PREFER_SIZE */
57271 	{
57272 		/* In all other cases, and when doing a size optimized build,
57273 		 * fall back to the comprehensive handler.
57274 		 */
57275 		d = duk_js_tonumber(thr, tv);
57276 	}
57277 
57278 	/* Refuse to update an Array's 'length' to a value outside the
57279 	 * 32-bit range.  Negative zero is accepted as zero.
57280 	 */
57281 	res = duk_double_to_uint32_t(d);
57282 	if ((duk_double_t) res != d) {
57283 		goto fail_range;
57284 	}
57285 
57286 	return res;
57287 
57288  fail_range:
57289 	DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARRAY_LENGTH);
57290 	DUK_WO_NORETURN(return 0;);
57291 }
57292 
57293 /* Delete elements required by a smaller length, taking into account
57294  * potentially non-configurable elements.  Returns non-zero if all
57295  * elements could be deleted, and zero if all or some elements could
57296  * not be deleted.  Also writes final "target length" to 'out_result_len'.
57297  * This is the length value that should go into the 'length' property
57298  * (must be set by the caller).  Never throws an error.
57299  */
57300 DUK_LOCAL
57301 duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
57302                                                 duk_hobject *obj,
57303                                                 duk_uint32_t old_len,
57304                                                 duk_uint32_t new_len,
57305                                                 duk_bool_t force_flag,
57306                                                 duk_uint32_t *out_result_len) {
57307 	duk_uint32_t target_len;
57308 	duk_uint_fast32_t i;
57309 	duk_uint32_t arr_idx;
57310 	duk_hstring *key;
57311 	duk_tval *tv;
57312 	duk_bool_t rc;
57313 
57314 	DUK_DDD(DUK_DDDPRINT("new array length smaller than old (%ld -> %ld), "
57315 	                     "probably need to remove elements",
57316 	                     (long) old_len, (long) new_len));
57317 
57318 	/*
57319 	 *  New length is smaller than old length, need to delete properties above
57320 	 *  the new length.
57321 	 *
57322 	 *  If array part exists, this is straightforward: array entries cannot
57323 	 *  be non-configurable so this is guaranteed to work.
57324 	 *
57325 	 *  If array part does not exist, array-indexed values are scattered
57326 	 *  in the entry part, and some may not be configurable (preventing length
57327 	 *  from becoming lower than their index + 1).  To handle the algorithm
57328 	 *  in E5 Section 15.4.5.1, step l correctly, we scan the entire property
57329 	 *  set twice.
57330 	 */
57331 
57332 	DUK_ASSERT(thr != NULL);
57333 	DUK_ASSERT(obj != NULL);
57334 	DUK_ASSERT(new_len < old_len);
57335 	DUK_ASSERT(out_result_len != NULL);
57336 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
57337 
57338 	DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));
57339 	DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(obj));
57340 
57341 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
57342 		/*
57343 		 *  All defined array-indexed properties are in the array part
57344 		 *  (we assume the array part is comprehensive), and all array
57345 		 *  entries are writable, configurable, and enumerable.  Thus,
57346 		 *  nothing can prevent array entries from being deleted.
57347 		 */
57348 
57349 		DUK_DDD(DUK_DDDPRINT("have array part, easy case"));
57350 
57351 		if (old_len < DUK_HOBJECT_GET_ASIZE(obj)) {
57352 			/* XXX: assertion that entries >= old_len are already unused */
57353 			i = old_len;
57354 		} else {
57355 			i = DUK_HOBJECT_GET_ASIZE(obj);
57356 		}
57357 		DUK_ASSERT(i <= DUK_HOBJECT_GET_ASIZE(obj));
57358 
57359 		while (i > new_len) {
57360 			i--;
57361 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
57362 			DUK_TVAL_SET_UNUSED_UPDREF(thr, tv);  /* side effects */
57363 		}
57364 
57365 		*out_result_len = new_len;
57366 		return 1;
57367 	} else {
57368 		/*
57369 		 *  Entries part is a bit more complex.
57370 		 */
57371 
57372 		/* Stage 1: find highest preventing non-configurable entry (if any).
57373 		 * When forcing, ignore non-configurability.
57374 		 */
57375 
57376 		DUK_DDD(DUK_DDDPRINT("no array part, slow case"));
57377 
57378 		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 1: find target_len "
57379 		                     "(highest preventing non-configurable entry (if any))"));
57380 
57381 		target_len = new_len;
57382 		if (force_flag) {
57383 			DUK_DDD(DUK_DDDPRINT("array length write, no array part; force flag -> skip stage 1"));
57384 			goto skip_stage1;
57385 		}
57386 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
57387 			key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
57388 			if (!key) {
57389 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
57390 				continue;
57391 			}
57392 			if (!DUK_HSTRING_HAS_ARRIDX(key)) {
57393 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
57394 				continue;
57395 			}
57396 
57397 			DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key));  /* XXX: macro checks for array index flag, which is unnecessary here */
57398 			arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
57399 			DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
57400 			DUK_ASSERT(arr_idx < old_len);  /* consistency requires this */
57401 
57402 			if (arr_idx < new_len) {
57403 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below new_len",
57404 				                     (long) i, (long) arr_idx));
57405 				continue;
57406 			}
57407 			if (DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i)) {
57408 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is a relevant array index %ld, but configurable",
57409 				                     (long) i, (long) arr_idx));
57410 				continue;
57411 			}
57412 
57413 			/* relevant array index is non-configurable, blocks write */
57414 			if (arr_idx >= target_len) {
57415 				DUK_DDD(DUK_DDDPRINT("entry at index %ld has arr_idx %ld, is not configurable, "
57416 				                     "update target_len %ld -> %ld",
57417 				                     (long) i, (long) arr_idx, (long) target_len,
57418 				                     (long) (arr_idx + 1)));
57419 				target_len = arr_idx + 1;
57420 			}
57421 		}
57422 	 skip_stage1:
57423 
57424 		/* stage 2: delete configurable entries above target length */
57425 
57426 		DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld, target_len=%ld",
57427 		                     (long) old_len, (long) new_len, (long) target_len));
57428 
57429 		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 2: remove "
57430 		                     "entries >= target_len"));
57431 
57432 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
57433 			key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
57434 			if (!key) {
57435 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
57436 				continue;
57437 			}
57438 			if (!DUK_HSTRING_HAS_ARRIDX(key)) {
57439 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
57440 				continue;
57441 			}
57442 
57443 			DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key));  /* XXX: macro checks for array index flag, which is unnecessary here */
57444 			arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
57445 			DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
57446 			DUK_ASSERT(arr_idx < old_len);  /* consistency requires this */
57447 
57448 			if (arr_idx < target_len) {
57449 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below target_len",
57450 				                     (long) i, (long) arr_idx));
57451 				continue;
57452 			}
57453 			DUK_ASSERT(force_flag || DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i));  /* stage 1 guarantees */
57454 
57455 			DUK_DDD(DUK_DDDPRINT("delete entry index %ld: key is array index %ld",
57456 			                     (long) i, (long) arr_idx));
57457 
57458 			/*
57459 			 *  Slow delete, but we don't care as we're already in a very slow path.
57460 			 *  The delete always succeeds: key has no exotic behavior, property
57461 			 *  is configurable, and no resize occurs.
57462 			 */
57463 			rc = duk_hobject_delprop_raw(thr, obj, key, force_flag ? DUK_DELPROP_FLAG_FORCE : 0);
57464 			DUK_UNREF(rc);
57465 			DUK_ASSERT(rc != 0);
57466 		}
57467 
57468 		/* stage 3: update length (done by caller), decide return code */
57469 
57470 		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 3: update length (done by caller)"));
57471 
57472 		*out_result_len = target_len;
57473 
57474 		if (target_len == new_len) {
57475 			DUK_DDD(DUK_DDDPRINT("target_len matches new_len, return success"));
57476 			return 1;
57477 		}
57478 		DUK_DDD(DUK_DDDPRINT("target_len does not match new_len (some entry prevented "
57479 		                     "full length adjustment), return error"));
57480 		return 0;
57481 	}
57482 
57483 	DUK_UNREACHABLE();
57484 }
57485 
57486 /* XXX: is valstack top best place for argument? */
57487 DUK_LOCAL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj) {
57488 	duk_harray *a;
57489 	duk_uint32_t old_len;
57490 	duk_uint32_t new_len;
57491 	duk_uint32_t result_len;
57492 	duk_bool_t rc;
57493 
57494 	DUK_DDD(DUK_DDDPRINT("handling a put operation to array 'length' exotic property, "
57495 	                     "new val: %!T",
57496 	                     (duk_tval *) duk_get_tval(thr, -1)));
57497 
57498 	DUK_ASSERT(thr != NULL);
57499 	DUK_ASSERT(obj != NULL);
57500 
57501 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
57502 
57503 	DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));
57504 	DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(obj));
57505 	a = (duk_harray *) obj;
57506 	DUK_ASSERT_HARRAY_VALID(a);
57507 
57508 	DUK_ASSERT(duk_is_valid_index(thr, -1));
57509 
57510 	/*
57511 	 *  Get old and new length
57512 	 */
57513 
57514 	old_len = a->length;
57515 	new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_NEGIDX(thr, -1));
57516 	DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) old_len, (long) new_len));
57517 
57518 	/*
57519 	 *  Writability check
57520 	 */
57521 
57522 	if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
57523 		DUK_DDD(DUK_DDDPRINT("length is not writable, fail"));
57524 		return 0;
57525 	}
57526 
57527 	/*
57528 	 *  New length not lower than old length => no changes needed
57529 	 *  (not even array allocation).
57530 	 */
57531 
57532 	if (new_len >= old_len) {
57533 		DUK_DDD(DUK_DDDPRINT("new length is same or higher than old length, just update length, no deletions"));
57534 		a->length = new_len;
57535 		return 1;
57536 	}
57537 
57538 	DUK_DDD(DUK_DDDPRINT("new length is lower than old length, probably must delete entries"));
57539 
57540 	/*
57541 	 *  New length lower than old length => delete elements, then
57542 	 *  update length.
57543 	 *
57544 	 *  Note: even though a bunch of elements have been deleted, the 'desc' is
57545 	 *  still valid as properties haven't been resized (and entries compacted).
57546 	 */
57547 
57548 	rc = duk__handle_put_array_length_smaller(thr, obj, old_len, new_len, 0 /*force_flag*/, &result_len);
57549 	DUK_ASSERT(result_len >= new_len && result_len <= old_len);
57550 
57551 	a->length = result_len;
57552 
57553 	/* XXX: shrink array allocation or entries compaction here? */
57554 
57555 	return rc;
57556 }
57557 
57558 /*
57559  *  PUTPROP: ECMAScript property write.
57560  *
57561  *  Unlike ECMAScript primitive which returns nothing, returns 1 to indicate
57562  *  success and 0 to indicate failure (assuming throw is not set).
57563  *
57564  *  This is an extremely tricky function.  Some examples:
57565  *
57566  *    * Currently a decref may trigger a GC, which may compact an object's
57567  *      property allocation.  Consequently, any entry indices (e_idx) will
57568  *      be potentially invalidated by a decref.
57569  *
57570  *    * Exotic behaviors (strings, arrays, arguments object) require,
57571  *      among other things:
57572  *
57573  *      - Preprocessing before and postprocessing after an actual property
57574  *        write.  For example, array index write requires pre-checking the
57575  *        array 'length' property for access control, and may require an
57576  *        array 'length' update after the actual write has succeeded (but
57577  *        not if it fails).
57578  *
57579  *      - Deletion of multiple entries, as a result of array 'length' write.
57580  *
57581  *    * Input values are taken as pointers which may point to the valstack.
57582  *      If valstack is resized because of the put (this may happen at least
57583  *      when the array part is abandoned), the pointers can be invalidated.
57584  *      (We currently make a copy of all of the input values to avoid issues.)
57585  */
57586 
57587 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) {
57588 	duk_tval tv_obj_copy;
57589 	duk_tval tv_key_copy;
57590 	duk_tval tv_val_copy;
57591 	duk_hobject *orig = NULL;  /* NULL if tv_obj is primitive */
57592 	duk_hobject *curr;
57593 	duk_hstring *key = NULL;
57594 	duk_propdesc desc;
57595 	duk_tval *tv;
57596 	duk_uint32_t arr_idx;
57597 	duk_bool_t rc;
57598 	duk_int_t e_idx;
57599 	duk_uint_t sanity;
57600 	duk_uint32_t new_array_length = 0;  /* 0 = no update */
57601 
57602 	DUK_DDD(DUK_DDDPRINT("putprop: thr=%p, obj=%p, key=%p, val=%p, throw=%ld "
57603 	                     "(obj -> %!T, key -> %!T, val -> %!T)",
57604 	                     (void *) thr, (void *) tv_obj, (void *) tv_key, (void *) tv_val,
57605 	                     (long) throw_flag, (duk_tval *) tv_obj, (duk_tval *) tv_key, (duk_tval *) tv_val));
57606 
57607 	DUK_ASSERT(thr != NULL);
57608 	DUK_ASSERT(thr->heap != NULL);
57609 	DUK_ASSERT(tv_obj != NULL);
57610 	DUK_ASSERT(tv_key != NULL);
57611 	DUK_ASSERT(tv_val != NULL);
57612 
57613 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
57614 
57615 	DUK_STATS_INC(thr->heap, stats_putprop_all);
57616 
57617 	/*
57618 	 *  Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
57619 	 *  them being invalidated by a valstack resize.
57620 	 *
57621 	 *  XXX: this is an overkill for some paths, so optimize this later
57622 	 *  (or maybe switch to a stack arguments model entirely).
57623 	 */
57624 
57625 	DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
57626 	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
57627 	DUK_TVAL_SET_TVAL(&tv_val_copy, tv_val);
57628 	tv_obj = &tv_obj_copy;
57629 	tv_key = &tv_key_copy;
57630 	tv_val = &tv_val_copy;
57631 
57632 	/*
57633 	 *  Coercion and fast path processing.
57634 	 */
57635 
57636 	switch (DUK_TVAL_GET_TAG(tv_obj)) {
57637 	case DUK_TAG_UNDEFINED:
57638 	case DUK_TAG_NULL: {
57639 		/* Note: unconditional throw */
57640 		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject (object=%!iT)",
57641 		                     (duk_tval *) tv_obj));
57642 #if defined(DUK_USE_PARANOID_ERRORS)
57643 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
57644 #else
57645 		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
57646 		               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
57647 #endif
57648 		DUK_WO_NORETURN(return 0;);
57649 		break;
57650 	}
57651 
57652 	case DUK_TAG_BOOLEAN: {
57653 		DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
57654 		curr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];
57655 		break;
57656 	}
57657 
57658 	case DUK_TAG_STRING: {
57659 		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
57660 
57661 		/*
57662 		 *  Note: currently no fast path for array index writes.
57663 		 *  They won't be possible anyway as strings are immutable.
57664 		 */
57665 
57666 		DUK_ASSERT(key == NULL);
57667 		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57668 		DUK_ASSERT(key != NULL);
57669 
57670 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
57671 			/* Symbols (ES2015 or hidden) don't have virtual properties. */
57672 			curr = thr->builtins[DUK_BIDX_SYMBOL_PROTOTYPE];
57673 			goto lookup;
57674 		}
57675 
57676 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
57677 			goto fail_not_writable;
57678 		}
57679 
57680 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
57681 		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
57682 			goto fail_not_writable;
57683 		}
57684 
57685 		DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
57686 		curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
57687 		goto lookup;  /* avoid double coercion */
57688 	}
57689 
57690 	case DUK_TAG_OBJECT: {
57691 		orig = DUK_TVAL_GET_OBJECT(tv_obj);
57692 		DUK_ASSERT(orig != NULL);
57693 
57694 #if defined(DUK_USE_ROM_OBJECTS)
57695 		/* With this check in place fast paths won't need read-only
57696 		 * object checks.  This is technically incorrect if there are
57697 		 * setters that cause no writes to ROM objects, but current
57698 		 * built-ins don't have such setters.
57699 		 */
57700 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
57701 			DUK_DD(DUK_DDPRINT("attempt to putprop on read-only target object"));
57702 			goto fail_not_writable_no_pop;  /* Must avoid duk_pop() in exit path */
57703 		}
57704 #endif
57705 
57706 		/* The fast path for array property put is not fully compliant:
57707 		 * If one places conflicting number-indexed properties into
57708 		 * Array.prototype (for example, a non-writable Array.prototype[7])
57709 		 * the fast path will incorrectly ignore them.
57710 		 *
57711 		 * This fast path could be made compliant by falling through
57712 		 * to the slow path if the previous value was UNUSED.  This would
57713 		 * also remove the need to check for extensibility.  Right now a
57714 		 * non-extensible array is slower than an extensible one as far
57715 		 * as writes are concerned.
57716 		 *
57717 		 * The fast path behavior is documented in more detail here:
57718 		 * tests/ecmascript/test-misc-array-fast-write.js
57719 		 */
57720 
57721 		/* XXX: array .length? */
57722 
57723 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
57724 		if (duk__putprop_shallow_fastpath_array_tval(thr, orig, tv_key, tv_val) != 0) {
57725 			DUK_DDD(DUK_DDDPRINT("array fast path success"));
57726 			DUK_STATS_INC(thr->heap, stats_putprop_arrayidx);
57727 			return 1;
57728 		}
57729 #endif
57730 
57731 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
57732 		if (duk__putprop_fastpath_bufobj_tval(thr, orig, tv_key, tv_val) != 0) {
57733 			DUK_DDD(DUK_DDDPRINT("base is bufobj, key is a number, bufobj fast path"));
57734 			DUK_STATS_INC(thr->heap, stats_putprop_bufobjidx);
57735 			return 1;
57736 		}
57737 #endif
57738 
57739 #if defined(DUK_USE_ES6_PROXY)
57740 		if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(orig))) {
57741 			duk_hobject *h_target;
57742 			duk_bool_t tmp_bool;
57743 
57744 			if (duk__proxy_check_prop(thr, orig, DUK_STRIDX_SET, tv_key, &h_target)) {
57745 				/* -> [ ... trap handler ] */
57746 				DUK_DDD(DUK_DDDPRINT("-> proxy object 'set' for key %!T", (duk_tval *) tv_key));
57747 				DUK_STATS_INC(thr->heap, stats_putprop_proxy);
57748 				duk_push_hobject(thr, h_target);  /* target */
57749 				duk_push_tval(thr, tv_key);       /* P */
57750 				duk_push_tval(thr, tv_val);       /* V */
57751 				duk_push_tval(thr, tv_obj);       /* Receiver: Proxy object */
57752 				duk_call_method(thr, 4 /*nargs*/);
57753 				tmp_bool = duk_to_boolean_top_pop(thr);
57754 				if (!tmp_bool) {
57755 					goto fail_proxy_rejected;
57756 				}
57757 
57758 				/* Target object must be checked for a conflicting
57759 				 * non-configurable property.
57760 				 */
57761 				arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57762 				DUK_ASSERT(key != NULL);
57763 
57764 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
57765 					duk_tval *tv_targ = duk_require_tval(thr, -1);
57766 					duk_bool_t datadesc_reject;
57767 					duk_bool_t accdesc_reject;
57768 
57769 					DUK_DDD(DUK_DDDPRINT("proxy 'set': target has matching property %!O, check for "
57770 					                     "conflicting property; tv_val=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
57771 					                     "desc.get=%p, desc.set=%p",
57772 					                     (duk_heaphdr *) key, (duk_tval *) tv_val, (duk_tval *) tv_targ,
57773 					                     (unsigned long) desc.flags,
57774 					                     (void *) desc.get, (void *) desc.set));
57775 
57776 					datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
57777 					                  !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
57778 					                  !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) &&
57779 					                  !duk_js_samevalue(tv_val, tv_targ);
57780 					accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
57781 					                 !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
57782 					                 (desc.set == NULL);
57783 					if (datadesc_reject || accdesc_reject) {
57784 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
57785 						DUK_WO_NORETURN(return 0;);
57786 					}
57787 
57788 					duk_pop_2_unsafe(thr);
57789 				} else {
57790 					duk_pop_unsafe(thr);
57791 				}
57792 				return 1;  /* success */
57793 			}
57794 
57795 			orig = h_target;  /* resume write to target */
57796 			DUK_TVAL_SET_OBJECT(tv_obj, orig);
57797 		}
57798 #endif  /* DUK_USE_ES6_PROXY */
57799 
57800 		curr = orig;
57801 		break;
57802 	}
57803 
57804 	case DUK_TAG_BUFFER: {
57805 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
57806 		duk_int_t pop_count = 0;
57807 
57808 		/*
57809 		 *  Because buffer values may be looped over and read/written
57810 		 *  from, an array index fast path is important.
57811 		 */
57812 
57813 #if defined(DUK_USE_FASTINT)
57814 		if (DUK_TVAL_IS_FASTINT(tv_key)) {
57815 			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
57816 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
57817 			pop_count = 0;
57818 		} else
57819 #endif
57820 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
57821 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
57822 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
57823 			pop_count = 0;
57824 		} else {
57825 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57826 			DUK_ASSERT(key != NULL);
57827 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
57828 			                     "coercion key is %!T, arr_idx %ld",
57829 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
57830 			pop_count = 1;
57831 		}
57832 
57833 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
57834 		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
57835 			duk_uint8_t *data;
57836 			DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
57837 			data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);
57838 
57839 			/* XXX: duk_to_int() ensures we'll get 8 lowest bits as
57840 			 * as input is within duk_int_t range (capped outside it).
57841 			 */
57842 #if defined(DUK_USE_FASTINT)
57843 			/* Buffer writes are often integers. */
57844 			if (DUK_TVAL_IS_FASTINT(tv_val)) {
57845 				data[arr_idx] = (duk_uint8_t) DUK_TVAL_GET_FASTINT_U32(tv_val);
57846 			}
57847 			else
57848 #endif
57849 			{
57850 				duk_push_tval(thr, tv_val);
57851 				data[arr_idx] = (duk_uint8_t) duk_to_uint32(thr, -1);
57852 				pop_count++;
57853 			}
57854 
57855 			duk_pop_n_unsafe(thr, pop_count);
57856 			DUK_DDD(DUK_DDDPRINT("result: success (buffer data write)"));
57857 			DUK_STATS_INC(thr->heap, stats_putprop_bufferidx);
57858 			return 1;
57859 		}
57860 
57861 		if (pop_count == 0) {
57862 			/* This is a pretty awkward control flow, but we need to recheck the
57863 			 * key coercion here.
57864 			 */
57865 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57866 			DUK_ASSERT(key != NULL);
57867 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
57868 			                     "coercion key is %!T, arr_idx %ld",
57869 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
57870 		}
57871 
57872 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
57873 			goto fail_not_writable;
57874 		}
57875 
57876 		DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from Uint8Array prototype"));
57877 		curr = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
57878 		goto lookup;  /* avoid double coercion */
57879 	}
57880 
57881 	case DUK_TAG_POINTER: {
57882 		DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
57883 		curr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
57884 		break;
57885 	}
57886 
57887 	case DUK_TAG_LIGHTFUNC: {
57888 		/* Lightfuncs have no own properties and are considered non-extensible.
57889 		 * However, the write may be captured by an inherited setter which
57890 		 * means we can't stop the lookup here.
57891 		 */
57892 		DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
57893 		curr = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];
57894 		break;
57895 	}
57896 
57897 #if defined(DUK_USE_FASTINT)
57898 	case DUK_TAG_FASTINT:
57899 #endif
57900 	default: {
57901 		/* number */
57902 		DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
57903 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_obj));
57904 		curr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];
57905 		break;
57906 	}
57907 	}
57908 
57909 	DUK_ASSERT(key == NULL);
57910 	arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57911 	DUK_ASSERT(key != NULL);
57912 
57913  lookup:
57914 
57915 	/*
57916 	 *  Check whether the property already exists in the prototype chain.
57917 	 *  Note that the actual write goes into the original base object
57918 	 *  (except if an accessor property captures the write).
57919 	 */
57920 
57921 	/* [key] */
57922 
57923 	DUK_ASSERT(curr != NULL);
57924 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
57925 	do {
57926 		if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
57927 			goto next_in_chain;
57928 		}
57929 
57930 		if (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
57931 			/*
57932 			 *  Found existing accessor property (own or inherited).
57933 			 *  Call setter with 'this' set to orig, and value as the only argument.
57934 			 *  Setter calls are OK even for ROM objects.
57935 			 *
57936 			 *  Note: no exotic arguments object behavior, because [[Put]] never
57937 			 *  calls [[DefineOwnProperty]] (E5 Section 8.12.5, step 5.b).
57938 			 */
57939 
57940 			duk_hobject *setter;
57941 
57942 			DUK_DD(DUK_DDPRINT("put to an own or inherited accessor, calling setter"));
57943 
57944 			setter = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, curr, desc.e_idx);
57945 			if (!setter) {
57946 				goto fail_no_setter;
57947 			}
57948 			duk_push_hobject(thr, setter);
57949 			duk_push_tval(thr, tv_obj);  /* note: original, uncoerced base */
57950 			duk_push_tval(thr, tv_val);  /* [key setter this val] */
57951 #if defined(DUK_USE_NONSTD_SETTER_KEY_ARGUMENT)
57952 			duk_dup_m4(thr);
57953 			duk_call_method(thr, 2);     /* [key setter this val key] -> [key retval] */
57954 #else
57955 			duk_call_method(thr, 1);     /* [key setter this val] -> [key retval] */
57956 #endif
57957 			duk_pop_unsafe(thr);         /* ignore retval -> [key] */
57958 			goto success_no_arguments_exotic;
57959 		}
57960 
57961 		if (orig == NULL) {
57962 			/*
57963 			 *  Found existing own or inherited plain property, but original
57964 			 *  base is a primitive value.
57965 			 */
57966 			DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
57967 			goto fail_base_primitive;
57968 		}
57969 
57970 		if (curr != orig) {
57971 			/*
57972 			 *  Found existing inherited plain property.
57973 			 *  Do an access control check, and if OK, write
57974 			 *  new property to 'orig'.
57975 			 */
57976 			if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
57977 				DUK_DD(DUK_DDPRINT("found existing inherited plain property, but original object is not extensible"));
57978 				goto fail_not_extensible;
57979 			}
57980 			if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
57981 				DUK_DD(DUK_DDPRINT("found existing inherited plain property, original object is extensible, but inherited property is not writable"));
57982 				goto fail_not_writable;
57983 			}
57984 			DUK_DD(DUK_DDPRINT("put to new property, object extensible, inherited property found and is writable"));
57985 			goto create_new;
57986 		} else {
57987 			/*
57988 			 *  Found existing own (non-inherited) plain property.
57989 			 *  Do an access control check and update in place.
57990 			 */
57991 
57992 			if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
57993 				DUK_DD(DUK_DDPRINT("found existing own (non-inherited) plain property, but property is not writable"));
57994 				goto fail_not_writable;
57995 			}
57996 			if (desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) {
57997 				DUK_DD(DUK_DDPRINT("found existing own (non-inherited) virtual property, property is writable"));
57998 
57999 				if (DUK_HOBJECT_IS_ARRAY(curr)) {
58000 					/*
58001 					 *  Write to 'length' of an array is a very complex case
58002 					 *  handled in a helper which updates both the array elements
58003 					 *  and writes the new 'length'.  The write may result in an
58004 					 *  unconditional RangeError or a partial write (indicated
58005 					 *  by a return code).
58006 					 *
58007 					 *  Note: the helper has an unnecessary writability check
58008 					 *  for 'length', we already know it is writable.
58009 					 */
58010 					DUK_ASSERT(key == DUK_HTHREAD_STRING_LENGTH(thr));  /* only virtual array property */
58011 
58012 					DUK_DDD(DUK_DDDPRINT("writing existing 'length' property to array exotic, invoke complex helper"));
58013 
58014 					/* XXX: the helper currently assumes stack top contains new
58015 					 * 'length' value and the whole calling convention is not very
58016 					 * compatible with what we need.
58017 					 */
58018 
58019 					duk_push_tval(thr, tv_val);  /* [key val] */
58020 					rc = duk__handle_put_array_length(thr, orig);
58021 					duk_pop_unsafe(thr);  /* [key val] -> [key] */
58022 					if (!rc) {
58023 						goto fail_array_length_partial;
58024 					}
58025 
58026 					/* key is 'length', cannot match argument exotic behavior */
58027 					goto success_no_arguments_exotic;
58028 				}
58029 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
58030 				else if (DUK_HOBJECT_IS_BUFOBJ(curr)) {
58031 					duk_hbufobj *h_bufobj;
58032 					duk_uint_t byte_off;
58033 					duk_small_uint_t elem_size;
58034 
58035 					h_bufobj = (duk_hbufobj *) curr;
58036 					DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
58037 
58038 					DUK_DD(DUK_DDPRINT("writable virtual property is in buffer object"));
58039 
58040 					/* Careful with wrapping: arr_idx upshift may easily wrap, whereas
58041 					 * length downshift won't.
58042 					 */
58043 					if (arr_idx < (h_bufobj->length >> h_bufobj->shift) && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
58044 						duk_uint8_t *data;
58045 						DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
58046 
58047 						DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);  /* index/length check guarantees */
58048 						byte_off = arr_idx << h_bufobj->shift;       /* no wrap assuming h_bufobj->length is valid */
58049 						elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
58050 
58051 						/* Coerce to number before validating pointers etc so that the
58052 						 * number coercions in duk_hbufobj_validated_write() are
58053 						 * guaranteed to be side effect free and not invalidate the
58054 						 * pointer checks we do here.
58055 						 */
58056 						duk_push_tval(thr, tv_val);
58057 						(void) duk_to_number_m1(thr);
58058 
58059 						if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
58060 							data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
58061 							duk_hbufobj_validated_write(thr, h_bufobj, data, elem_size);
58062 						} else {
58063 							DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (write skipped)"));
58064 						}
58065 						duk_pop_unsafe(thr);
58066 						goto success_no_arguments_exotic;
58067 					}
58068 				}
58069 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
58070 
58071 				DUK_D(DUK_DPRINT("should not happen, key %!O", key));
58072 				goto fail_internal;  /* should not happen */
58073 			}
58074 			DUK_DD(DUK_DDPRINT("put to existing own plain property, property is writable"));
58075 			goto update_old;
58076 		}
58077 		DUK_UNREACHABLE();
58078 
58079 	 next_in_chain:
58080 		/* XXX: option to pretend property doesn't exist if sanity limit is
58081 		 * hit might be useful.
58082 		 */
58083 		if (DUK_UNLIKELY(sanity-- == 0)) {
58084 			DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
58085 			DUK_WO_NORETURN(return 0;);
58086 		}
58087 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
58088 	} while (curr != NULL);
58089 
58090 	/*
58091 	 *  Property not found in prototype chain.
58092 	 */
58093 
58094 	DUK_DDD(DUK_DDDPRINT("property not found in prototype chain"));
58095 
58096 	if (orig == NULL) {
58097 		DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
58098 		goto fail_base_primitive;
58099 	}
58100 
58101 	if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
58102 		DUK_DD(DUK_DDPRINT("put to a new property (not found in prototype chain), but original object not extensible"));
58103 		goto fail_not_extensible;
58104 	}
58105 
58106 	goto create_new;
58107 
58108  update_old:
58109 
58110 	/*
58111 	 *  Update an existing property of the base object.
58112 	 */
58113 
58114 	/* [key] */
58115 
58116 	DUK_DDD(DUK_DDDPRINT("update an existing property of the original object"));
58117 
58118 	DUK_ASSERT(orig != NULL);
58119 #if defined(DUK_USE_ROM_OBJECTS)
58120 	/* This should not happen because DUK_TAG_OBJECT case checks
58121 	 * for this already, but check just in case.
58122 	 */
58123 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
58124 		goto fail_not_writable;
58125 	}
58126 #endif
58127 
58128 	/* Although there are writable virtual properties (e.g. plain buffer
58129 	 * and buffer object number indices), they are handled before we come
58130 	 * here.
58131 	 */
58132 	DUK_ASSERT((desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) == 0);
58133 	DUK_ASSERT(desc.a_idx >= 0 || desc.e_idx >= 0);
58134 
58135 	/* Array own property .length is handled above. */
58136 	DUK_ASSERT(!(DUK_HOBJECT_IS_ARRAY(orig) && key == DUK_HTHREAD_STRING_LENGTH(thr)));
58137 
58138 	if (desc.e_idx >= 0) {
58139 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, desc.e_idx);
58140 		DUK_DDD(DUK_DDDPRINT("previous entry value: %!iT", (duk_tval *) tv));
58141 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects; e_idx may be invalidated */
58142 		/* don't touch property attributes or hash part */
58143 		DUK_DD(DUK_DDPRINT("put to an existing entry at index %ld -> new value %!iT",
58144 		                   (long) desc.e_idx, (duk_tval *) tv));
58145 	} else {
58146 		/* Note: array entries are always writable, so the writability check
58147 		 * above is pointless for them.  The check could be avoided with some
58148 		 * refactoring but is probably not worth it.
58149 		 */
58150 
58151 		DUK_ASSERT(desc.a_idx >= 0);
58152 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, desc.a_idx);
58153 		DUK_DDD(DUK_DDDPRINT("previous array value: %!iT", (duk_tval *) tv));
58154 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects; a_idx may be invalidated */
58155 		DUK_DD(DUK_DDPRINT("put to an existing array entry at index %ld -> new value %!iT",
58156 		                   (long) desc.a_idx, (duk_tval *) tv));
58157 	}
58158 
58159 	/* Regardless of whether property is found in entry or array part,
58160 	 * it may have arguments exotic behavior (array indices may reside
58161 	 * in entry part for abandoned / non-existent array parts).
58162 	 */
58163 	goto success_with_arguments_exotic;
58164 
58165  create_new:
58166 
58167 	/*
58168 	 *  Create a new property in the original object.
58169 	 *
58170 	 *  Exotic properties need to be reconsidered here from a write
58171 	 *  perspective (not just property attributes perspective).
58172 	 *  However, the property does not exist in the object already,
58173 	 *  so this limits the kind of exotic properties that apply.
58174 	 */
58175 
58176 	/* [key] */
58177 
58178 	DUK_DDD(DUK_DDDPRINT("create new property to original object"));
58179 
58180 	DUK_ASSERT(orig != NULL);
58181 
58182 	/* Array own property .length is handled above. */
58183 	DUK_ASSERT(!(DUK_HOBJECT_IS_ARRAY(orig) && key == DUK_HTHREAD_STRING_LENGTH(thr)));
58184 
58185 #if defined(DUK_USE_ROM_OBJECTS)
58186 	/* This should not happen because DUK_TAG_OBJECT case checks
58187 	 * for this already, but check just in case.
58188 	 */
58189 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
58190 		goto fail_not_writable;
58191 	}
58192 #endif
58193 
58194 	/* Not possible because array object 'length' is present
58195 	 * from its creation and cannot be deleted, and is thus
58196 	 * caught as an existing property above.
58197 	 */
58198 	DUK_ASSERT(!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
58199 	             key == DUK_HTHREAD_STRING_LENGTH(thr)));
58200 
58201 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
58202 	    arr_idx != DUK__NO_ARRAY_INDEX) {
58203 		/* automatic length update */
58204 		duk_uint32_t old_len;
58205 		duk_harray *a;
58206 
58207 		a = (duk_harray *) orig;
58208 		DUK_ASSERT_HARRAY_VALID(a);
58209 
58210 		old_len = a->length;
58211 
58212 		if (arr_idx >= old_len) {
58213 			DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
58214 			                     "(arr_idx=%ld, old_len=%ld)",
58215 			                     (long) arr_idx, (long) old_len));
58216 
58217 			if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
58218 				DUK_DD(DUK_DDPRINT("attempt to extend array, but array 'length' is not writable"));
58219 				goto fail_not_writable;
58220 			}
58221 
58222 			/* Note: actual update happens once write has been completed
58223 			 * without error below.  The write should always succeed
58224 			 * from a specification viewpoint, but we may e.g. run out
58225 			 * of memory.  It's safer in this order.
58226 			 */
58227 
58228 			DUK_ASSERT(arr_idx != 0xffffffffUL);
58229 			new_array_length = arr_idx + 1;  /* flag for later write */
58230 		} else {
58231 			DUK_DDD(DUK_DDDPRINT("write new array entry does not require length update "
58232 			                     "(arr_idx=%ld, old_len=%ld)",
58233 			                     (long) arr_idx, (long) old_len));
58234 		}
58235 	}
58236 
58237  /* write_to_array_part: */
58238 
58239 	/*
58240 	 *  Write to array part?
58241 	 *
58242 	 *  Note: array abandonding requires a property resize which uses
58243 	 *  'rechecks' valstack for temporaries and may cause any existing
58244 	 *  valstack pointers to be invalidated.  To protect against this,
58245 	 *  tv_obj, tv_key, and tv_val are copies of the original inputs.
58246 	 */
58247 
58248 	if (arr_idx != DUK__NO_ARRAY_INDEX &&
58249 	    DUK_HOBJECT_HAS_ARRAY_PART(orig)) {
58250 		if (arr_idx < DUK_HOBJECT_GET_ASIZE(orig)) {
58251 			goto no_array_growth;
58252 		}
58253 
58254 		/*
58255 		 *  Array needs to grow, but we don't want it becoming too sparse.
58256 		 *  If it were to become sparse, abandon array part, moving all
58257 		 *  array entries into the entries part (for good).
58258 		 *
58259 		 *  Since we don't keep track of actual density (used vs. size) of
58260 		 *  the array part, we need to estimate somehow.  The check is made
58261 		 *  in two parts:
58262 		 *
58263 		 *    - Check whether the resize need is small compared to the
58264 		 *      current size (relatively); if so, resize without further
58265 		 *      checking (essentially we assume that the original part is
58266 		 *      "dense" so that the result would be dense enough).
58267 		 *
58268 		 *    - Otherwise, compute the resize using an actual density
58269 		 *      measurement based on counting the used array entries.
58270 		 */
58271 
58272 		DUK_DDD(DUK_DDDPRINT("write to new array requires array resize, decide whether to do a "
58273 		                     "fast resize without abandon check (arr_idx=%ld, old_size=%ld)",
58274 		                     (long) arr_idx, (long) DUK_HOBJECT_GET_ASIZE(orig)));
58275 
58276 		if (duk__abandon_array_slow_check_required(arr_idx, DUK_HOBJECT_GET_ASIZE(orig))) {
58277 			duk_uint32_t old_used;
58278 			duk_uint32_t old_size;
58279 
58280 			DUK_DDD(DUK_DDDPRINT("=> fast check is NOT OK, do slow check for array abandon"));
58281 
58282 			duk__compute_a_stats(thr, orig, &old_used, &old_size);
58283 
58284 			DUK_DDD(DUK_DDDPRINT("abandon check, array stats: old_used=%ld, old_size=%ld, arr_idx=%ld",
58285 			                     (long) old_used, (long) old_size, (long) arr_idx));
58286 
58287 			/* Note: intentionally use approximations to shave a few instructions:
58288 			 *   a_used = old_used  (accurate: old_used + 1)
58289 			 *   a_size = arr_idx   (accurate: arr_idx + 1)
58290 			 */
58291 			if (duk__abandon_array_density_check(old_used, arr_idx)) {
58292 				DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
58293 				                   "decided to abandon array part (would become too sparse)"));
58294 
58295 				/* abandoning requires a props allocation resize and
58296 				 * 'rechecks' the valstack, invalidating any existing
58297 				 * valstack value pointers!
58298 				 */
58299 				duk__abandon_array_checked(thr, orig);
58300 				DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(orig));
58301 
58302 				goto write_to_entry_part;
58303 			}
58304 
58305 			DUK_DDD(DUK_DDDPRINT("=> decided to keep array part"));
58306 		} else {
58307 			DUK_DDD(DUK_DDDPRINT("=> fast resize is OK"));
58308 		}
58309 
58310 		DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
58311 		                   "decided to extend current allocation"));
58312 
58313 		duk__grow_props_for_array_item(thr, orig, arr_idx);
58314 
58315 	 no_array_growth:
58316 
58317 		/* Note: assume array part is comprehensive, so that either
58318 		 * the write goes to the array part, or we've abandoned the
58319 		 * array above (and will not come here).
58320 		 */
58321 
58322 		DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(orig));
58323 		DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(orig));
58324 
58325 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, arr_idx);
58326 		/* prev value must be unused, no decref */
58327 		DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));
58328 		DUK_TVAL_SET_TVAL(tv, tv_val);
58329 		DUK_TVAL_INCREF(thr, tv);
58330 		DUK_DD(DUK_DDPRINT("put to new array entry: %ld -> %!T",
58331 		                   (long) arr_idx, (duk_tval *) tv));
58332 
58333 		/* Note: array part values are [[Writable]], [[Enumerable]],
58334 		 * and [[Configurable]] which matches the required attributes
58335 		 * here.
58336 		 */
58337 		goto entry_updated;
58338 	}
58339 
58340  write_to_entry_part:
58341 
58342 	/*
58343 	 *  Write to entry part
58344 	 */
58345 
58346 	/* entry allocation updates hash part and increases the key
58347 	 * refcount; may need a props allocation resize but doesn't
58348 	 * 'recheck' the valstack.
58349 	 */
58350 	e_idx = duk__hobject_alloc_entry_checked(thr, orig, key);
58351 	DUK_ASSERT(e_idx >= 0);
58352 
58353 	tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, e_idx);
58354 	/* prev value can be garbage, no decref */
58355 	DUK_TVAL_SET_TVAL(tv, tv_val);
58356 	DUK_TVAL_INCREF(thr, tv);
58357 	DUK_HOBJECT_E_SET_FLAGS(thr->heap, orig, e_idx, DUK_PROPDESC_FLAGS_WEC);
58358 	goto entry_updated;
58359 
58360  entry_updated:
58361 
58362 	/*
58363 	 *  Possible pending array length update, which must only be done
58364 	 *  if the actual entry write succeeded.
58365 	 */
58366 
58367 	if (new_array_length > 0) {
58368 		/* Note: zero works as a "no update" marker because the new length
58369 		 * can never be zero after a new property is written.
58370 		 */
58371 
58372 		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig));
58373 
58374 		DUK_DDD(DUK_DDDPRINT("write successful, pending array length update to: %ld",
58375 		                     (long) new_array_length));
58376 
58377 		((duk_harray *) orig)->length = new_array_length;
58378 	}
58379 
58380 	/*
58381 	 *  Arguments exotic behavior not possible for new properties: all
58382 	 *  magically bound properties are initially present in the arguments
58383 	 *  object, and if they are deleted, the binding is also removed from
58384 	 *  parameter map.
58385 	 */
58386 
58387 	goto success_no_arguments_exotic;
58388 
58389  success_with_arguments_exotic:
58390 
58391 	/*
58392 	 *  Arguments objects have exotic [[DefineOwnProperty]] which updates
58393 	 *  the internal 'map' of arguments for writes to currently mapped
58394 	 *  arguments.  More conretely, writes to mapped arguments generate
58395 	 *  a write to a bound variable.
58396 	 *
58397 	 *  The [[Put]] algorithm invokes [[DefineOwnProperty]] for existing
58398 	 *  data properties and new properties, but not for existing accessors.
58399 	 *  Hence, in E5 Section 10.6 ([[DefinedOwnProperty]] algorithm), we
58400 	 *  have a Desc with 'Value' (and possibly other properties too), and
58401 	 *  we end up in step 5.b.i.
58402 	 */
58403 
58404 	if (arr_idx != DUK__NO_ARRAY_INDEX &&
58405 	    DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
58406 		/* Note: only numbered indices are relevant, so arr_idx fast reject
58407 		 * is good (this is valid unless there are more than 4**32-1 arguments).
58408 		 */
58409 
58410 		DUK_DDD(DUK_DDDPRINT("putprop successful, arguments exotic behavior needed"));
58411 
58412 		/* Note: we can reuse 'desc' here */
58413 
58414 		/* XXX: top of stack must contain value, which helper doesn't touch,
58415 		 * rework to use tv_val directly?
58416 		 */
58417 
58418 		duk_push_tval(thr, tv_val);
58419 		(void) duk__check_arguments_map_for_put(thr, orig, key, &desc, throw_flag);
58420 		duk_pop_unsafe(thr);
58421 	}
58422 	/* fall thru */
58423 
58424  success_no_arguments_exotic:
58425 	/* shared exit path now */
58426 	DUK_DDD(DUK_DDDPRINT("result: success"));
58427 	duk_pop_unsafe(thr);  /* remove key */
58428 	return 1;
58429 
58430 #if defined(DUK_USE_ES6_PROXY)
58431  fail_proxy_rejected:
58432 	DUK_DDD(DUK_DDDPRINT("result: error, proxy rejects"));
58433 	if (throw_flag) {
58434 		DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
58435 		DUK_WO_NORETURN(return 0;);
58436 	}
58437 	/* Note: no key on stack */
58438 	return 0;
58439 #endif
58440 
58441  fail_base_primitive:
58442 	DUK_DDD(DUK_DDDPRINT("result: error, base primitive"));
58443 	if (throw_flag) {
58444 #if defined(DUK_USE_PARANOID_ERRORS)
58445 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
58446 #else
58447 		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
58448 		               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
58449 #endif
58450 		DUK_WO_NORETURN(return 0;);
58451 	}
58452 	duk_pop_unsafe(thr);  /* remove key */
58453 	return 0;
58454 
58455  fail_not_extensible:
58456 	DUK_DDD(DUK_DDDPRINT("result: error, not extensible"));
58457 	if (throw_flag) {
58458 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE);
58459 		DUK_WO_NORETURN(return 0;);
58460 	}
58461 	duk_pop_unsafe(thr);  /* remove key */
58462 	return 0;
58463 
58464  fail_not_writable:
58465 	DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
58466 	if (throw_flag) {
58467 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);
58468 		DUK_WO_NORETURN(return 0;);
58469 	}
58470 	duk_pop_unsafe(thr);  /* remove key */
58471 	return 0;
58472 
58473 #if defined(DUK_USE_ROM_OBJECTS)
58474  fail_not_writable_no_pop:
58475 	DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
58476 	if (throw_flag) {
58477 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);
58478 		DUK_WO_NORETURN(return 0;);
58479 	}
58480 	return 0;
58481 #endif
58482 
58483  fail_array_length_partial:
58484 	DUK_DD(DUK_DDPRINT("result: error, array length write only partially successful"));
58485 	if (throw_flag) {
58486 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
58487 		DUK_WO_NORETURN(return 0;);
58488 	}
58489 	duk_pop_unsafe(thr);  /* remove key */
58490 	return 0;
58491 
58492  fail_no_setter:
58493 	DUK_DDD(DUK_DDDPRINT("result: error, accessor property without setter"));
58494 	if (throw_flag) {
58495 		DUK_ERROR_TYPE(thr, DUK_STR_SETTER_UNDEFINED);
58496 		DUK_WO_NORETURN(return 0;);
58497 	}
58498 	duk_pop_unsafe(thr);  /* remove key */
58499 	return 0;
58500 
58501  fail_internal:
58502 	DUK_DDD(DUK_DDDPRINT("result: error, internal"));
58503 	if (throw_flag) {
58504 		DUK_ERROR_INTERNAL(thr);
58505 		DUK_WO_NORETURN(return 0;);
58506 	}
58507 	duk_pop_unsafe(thr);  /* remove key */
58508 	return 0;
58509 }
58510 
58511 /*
58512  *  ECMAScript compliant [[Delete]](P, Throw).
58513  */
58514 
58515 DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
58516 	duk_propdesc desc;
58517 	duk_tval *tv;
58518 	duk_uint32_t arr_idx;
58519 	duk_bool_t throw_flag;
58520 	duk_bool_t force_flag;
58521 
58522 	throw_flag = (flags & DUK_DELPROP_FLAG_THROW);
58523 	force_flag = (flags & DUK_DELPROP_FLAG_FORCE);
58524 
58525 	DUK_DDD(DUK_DDDPRINT("delprop_raw: thr=%p, obj=%p, key=%p, throw=%ld, force=%ld (obj -> %!O, key -> %!O)",
58526 	                     (void *) thr, (void *) obj, (void *) key, (long) throw_flag, (long) force_flag,
58527 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
58528 
58529 	DUK_ASSERT(thr != NULL);
58530 	DUK_ASSERT(thr->heap != NULL);
58531 	DUK_ASSERT(obj != NULL);
58532 	DUK_ASSERT(key != NULL);
58533 
58534 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
58535 
58536 	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
58537 
58538 	/* 0 = don't push current value */
58539 	if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
58540 		DUK_DDD(DUK_DDDPRINT("property not found, succeed always"));
58541 		goto success;
58542 	}
58543 
58544 #if defined(DUK_USE_ROM_OBJECTS)
58545 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
58546 		DUK_DD(DUK_DDPRINT("attempt to delprop on read-only target object"));
58547 		goto fail_not_configurable;
58548 	}
58549 #endif
58550 
58551 	if ((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) == 0 && !force_flag) {
58552 		goto fail_not_configurable;
58553 	}
58554 	if (desc.a_idx < 0 && desc.e_idx < 0) {
58555 		/* Currently there are no deletable virtual properties, but
58556 		 * with force_flag we might attempt to delete one.
58557 		 */
58558 		DUK_DD(DUK_DDPRINT("delete failed: property found, force flag, but virtual (and implicitly non-configurable)"));
58559 		goto fail_virtual;
58560 	}
58561 
58562 	if (desc.a_idx >= 0) {
58563 		DUK_ASSERT(desc.e_idx < 0);
58564 
58565 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
58566 		DUK_TVAL_SET_UNUSED_UPDREF(thr, tv);  /* side effects */
58567 		goto success;
58568 	} else {
58569 		DUK_ASSERT(desc.a_idx < 0);
58570 
58571 		/* remove hash entry (no decref) */
58572 #if defined(DUK_USE_HOBJECT_HASH_PART)
58573 		if (desc.h_idx >= 0) {
58574 			duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
58575 
58576 			DUK_DDD(DUK_DDDPRINT("removing hash entry at h_idx %ld", (long) desc.h_idx));
58577 			DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) > 0);
58578 			DUK_ASSERT((duk_uint32_t) desc.h_idx < DUK_HOBJECT_GET_HSIZE(obj));
58579 			h_base[desc.h_idx] = DUK__HASH_DELETED;
58580 		} else {
58581 			DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) == 0);
58582 		}
58583 #else
58584 		DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) == 0);
58585 #endif
58586 
58587 		/* Remove value.  This requires multiple writes so avoid side
58588 		 * effects via no-refzero macros so that e_idx is not
58589 		 * invalidated.
58590 		 */
58591 		DUK_DDD(DUK_DDDPRINT("before removing value, e_idx %ld, key %p, key at slot %p",
58592 		                     (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
58593 		DUK_DDD(DUK_DDDPRINT("removing value at e_idx %ld", (long) desc.e_idx));
58594 		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx)) {
58595 			duk_hobject *tmp;
58596 
58597 			tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, desc.e_idx);
58598 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, desc.e_idx, NULL);
58599 			DUK_UNREF(tmp);
58600 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
58601 
58602 			tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, desc.e_idx);
58603 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, desc.e_idx, NULL);
58604 			DUK_UNREF(tmp);
58605 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
58606 		} else {
58607 			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
58608 			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
58609 		}
58610 #if 0
58611 		/* Not strictly necessary because if key == NULL, flag MUST be ignored. */
58612 		DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, 0);
58613 #endif
58614 
58615 		/* Remove key. */
58616 		DUK_DDD(DUK_DDDPRINT("before removing key, e_idx %ld, key %p, key at slot %p",
58617 		                     (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
58618 		DUK_DDD(DUK_DDDPRINT("removing key at e_idx %ld", (long) desc.e_idx));
58619 		DUK_ASSERT(key == DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx));
58620 		DUK_HOBJECT_E_SET_KEY(thr->heap, obj, desc.e_idx, NULL);
58621 		DUK_HSTRING_DECREF_NORZ(thr, key);
58622 
58623 		/* Trigger refzero side effects only when we're done as a
58624 		 * finalizer might operate on the object and affect the
58625 		 * e_idx we're supposed to use.
58626 		 */
58627 		DUK_REFZERO_CHECK_SLOW(thr);
58628 		goto success;
58629 	}
58630 
58631 	DUK_UNREACHABLE();
58632 
58633  success:
58634 	/*
58635 	 *  Argument exotic [[Delete]] behavior (E5 Section 10.6) is
58636 	 *  a post-check, keeping arguments internal 'map' in sync with
58637 	 *  any successful deletes (note that property does not need to
58638 	 *  exist for delete to 'succeed').
58639 	 *
58640 	 *  Delete key from 'map'.  Since 'map' only contains array index
58641 	 *  keys, we can use arr_idx for a fast skip.
58642 	 */
58643 
58644 	DUK_DDD(DUK_DDDPRINT("delete successful, check for arguments exotic behavior"));
58645 
58646 	if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {
58647 		/* Note: only numbered indices are relevant, so arr_idx fast reject
58648 		 * is good (this is valid unless there are more than 4**32-1 arguments).
58649 		 */
58650 
58651 		DUK_DDD(DUK_DDDPRINT("delete successful, arguments exotic behavior needed"));
58652 
58653 		/* Note: we can reuse 'desc' here */
58654 		(void) duk__check_arguments_map_for_delete(thr, obj, key, &desc);
58655 	}
58656 
58657 	DUK_DDD(DUK_DDDPRINT("delete successful"));
58658 	return 1;
58659 
58660  fail_virtual:  /* just use the same "not configurable" error message */
58661  fail_not_configurable:
58662 	DUK_DDD(DUK_DDDPRINT("delete failed: property found, not configurable"));
58663 
58664 	if (throw_flag) {
58665 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
58666 		DUK_WO_NORETURN(return 0;);
58667 	}
58668 	return 0;
58669 }
58670 
58671 /*
58672  *  DELPROP: ECMAScript property deletion.
58673  */
58674 
58675 DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag) {
58676 	duk_hstring *key = NULL;
58677 #if defined(DUK_USE_ES6_PROXY)
58678 	duk_propdesc desc;
58679 #endif
58680 	duk_int_t entry_top;
58681 	duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
58682 	duk_bool_t rc;
58683 
58684 	DUK_DDD(DUK_DDDPRINT("delprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
58685 	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
58686 	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));
58687 
58688 	DUK_ASSERT(thr != NULL);
58689 	DUK_ASSERT(thr->heap != NULL);
58690 	DUK_ASSERT(tv_obj != NULL);
58691 	DUK_ASSERT(tv_key != NULL);
58692 
58693 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
58694 
58695 	/* Storing the entry top is cheaper here to ensure stack is correct at exit,
58696 	 * as there are several paths out.
58697 	 */
58698 	entry_top = duk_get_top(thr);
58699 
58700 	if (DUK_TVAL_IS_UNDEFINED(tv_obj) ||
58701 	    DUK_TVAL_IS_NULL(tv_obj)) {
58702 		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
58703 		goto fail_invalid_base_uncond;
58704 	}
58705 
58706 	duk_push_tval(thr, tv_obj);
58707 	duk_push_tval(thr, tv_key);
58708 
58709 	tv_obj = DUK_GET_TVAL_NEGIDX(thr, -2);
58710 	if (DUK_TVAL_IS_OBJECT(tv_obj)) {
58711 		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_obj);
58712 		DUK_ASSERT(obj != NULL);
58713 
58714 #if defined(DUK_USE_ES6_PROXY)
58715 		if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(obj))) {
58716 			duk_hobject *h_target;
58717 			duk_bool_t tmp_bool;
58718 
58719 			/* Note: proxy handling must happen before key is string coerced. */
58720 
58721 			if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_DELETE_PROPERTY, tv_key, &h_target)) {
58722 				/* -> [ ... obj key trap handler ] */
58723 				DUK_DDD(DUK_DDDPRINT("-> proxy object 'deleteProperty' for key %!T", (duk_tval *) tv_key));
58724 				duk_push_hobject(thr, h_target);  /* target */
58725 				duk_dup_m4(thr);  /* P */
58726 				duk_call_method(thr, 2 /*nargs*/);
58727 				tmp_bool = duk_to_boolean_top_pop(thr);
58728 				if (!tmp_bool) {
58729 					goto fail_proxy_rejected;  /* retval indicates delete failed */
58730 				}
58731 
58732 				/* Target object must be checked for a conflicting
58733 				 * non-configurable property.
58734 				 */
58735 				tv_key = DUK_GET_TVAL_NEGIDX(thr, -1);
58736 				arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
58737 				DUK_ASSERT(key != NULL);
58738 
58739 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
58740 					duk_small_int_t desc_reject;
58741 
58742 					DUK_DDD(DUK_DDDPRINT("proxy 'deleteProperty': target has matching property %!O, check for "
58743 					                     "conflicting property; desc.flags=0x%08lx, "
58744 					                     "desc.get=%p, desc.set=%p",
58745 					                     (duk_heaphdr *) key, (unsigned long) desc.flags,
58746 					                     (void *) desc.get, (void *) desc.set));
58747 
58748 					desc_reject = !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE);
58749 					if (desc_reject) {
58750 						/* unconditional */
58751 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
58752 						DUK_WO_NORETURN(return 0;);
58753 					}
58754 				}
58755 				rc = 1;  /* success */
58756 				goto done_rc;
58757 			}
58758 
58759 			obj = h_target;  /* resume delete to target */
58760 		}
58761 #endif  /* DUK_USE_ES6_PROXY */
58762 
58763 		arr_idx = duk__to_property_key(thr, -1, &key);
58764 		DUK_ASSERT(key != NULL);
58765 
58766 		rc = duk_hobject_delprop_raw(thr, obj, key, throw_flag ? DUK_DELPROP_FLAG_THROW : 0);
58767 		goto done_rc;
58768 	} else if (DUK_TVAL_IS_STRING(tv_obj)) {
58769 		/* String has .length and array index virtual properties
58770 		 * which can't be deleted.  No need for a symbol check;
58771 		 * no offending virtual symbols exist.
58772 		 */
58773 		/* XXX: unnecessary string coercion for array indices,
58774 		 * intentional to keep small.
58775 		 */
58776 		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
58777 		DUK_ASSERT(h != NULL);
58778 
58779 		arr_idx = duk__to_property_key(thr, -1, &key);
58780 		DUK_ASSERT(key != NULL);
58781 
58782 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
58783 			goto fail_not_configurable;
58784 		}
58785 
58786 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
58787 		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
58788 			goto fail_not_configurable;
58789 		}
58790 	} else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
58791 		/* XXX: unnecessary string coercion for array indices,
58792 		 * intentional to keep small; some overlap with string
58793 		 * handling.
58794 		 */
58795 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
58796 		DUK_ASSERT(h != NULL);
58797 
58798 		arr_idx = duk__to_property_key(thr, -1, &key);
58799 		DUK_ASSERT(key != NULL);
58800 
58801 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
58802 			goto fail_not_configurable;
58803 		}
58804 
58805 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
58806 		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
58807 			goto fail_not_configurable;
58808 		}
58809 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
58810 		/* Lightfunc has no virtual properties since Duktape 2.2
58811 		 * so success.  Still must coerce key for side effects.
58812 		 */
58813 
58814 		arr_idx = duk__to_property_key(thr, -1, &key);
58815 		DUK_ASSERT(key != NULL);
58816 		DUK_UNREF(key);
58817 	}
58818 
58819 	/* non-object base, no offending virtual property */
58820 	rc = 1;
58821 	goto done_rc;
58822 
58823  done_rc:
58824 	duk_set_top_unsafe(thr, entry_top);
58825 	return rc;
58826 
58827  fail_invalid_base_uncond:
58828 	/* Note: unconditional throw */
58829 	DUK_ASSERT(duk_get_top(thr) == entry_top);
58830 #if defined(DUK_USE_PARANOID_ERRORS)
58831 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
58832 #else
58833 	DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot delete property %s of %s",
58834 	               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
58835 #endif
58836 	DUK_WO_NORETURN(return 0;);
58837 
58838 #if defined(DUK_USE_ES6_PROXY)
58839  fail_proxy_rejected:
58840 	if (throw_flag) {
58841 		DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
58842 		DUK_WO_NORETURN(return 0;);
58843 	}
58844 	duk_set_top_unsafe(thr, entry_top);
58845 	return 0;
58846 #endif
58847 
58848  fail_not_configurable:
58849 	if (throw_flag) {
58850 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
58851 		DUK_WO_NORETURN(return 0;);
58852 	}
58853 	duk_set_top_unsafe(thr, entry_top);
58854 	return 0;
58855 }
58856 
58857 /*
58858  *  Internal helper to define a property with specific flags, ignoring
58859  *  normal semantics such as extensibility, write protection etc.
58860  *  Overwrites any existing value and attributes unless caller requests
58861  *  that value only be updated if it doesn't already exists.
58862  *
58863  *  Does not support:
58864  *    - virtual properties (error if write attempted)
58865  *    - getter/setter properties (error if write attempted)
58866  *    - non-default (!= WEC) attributes for array entries (error if attempted)
58867  *    - array abandoning: if array part exists, it is always extended
58868  *    - array 'length' updating
58869  *
58870  *  Stack: [... in_val] -> []
58871  *
58872  *  Used for e.g. built-in initialization and environment record
58873  *  operations.
58874  */
58875 
58876 DUK_INTERNAL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
58877 	duk_propdesc desc;
58878 	duk_uint32_t arr_idx;
58879 	duk_int_t e_idx;
58880 	duk_tval *tv1 = NULL;
58881 	duk_tval *tv2 = NULL;
58882 	duk_small_uint_t propflags = flags & DUK_PROPDESC_FLAGS_MASK;  /* mask out flags not actually stored */
58883 
58884 	DUK_DDD(DUK_DDDPRINT("define new property (internal): thr=%p, obj=%!O, key=%!O, flags=0x%02lx, val=%!T",
58885 	                     (void *) thr, (duk_heaphdr *) obj, (duk_heaphdr *) key,
58886 	                     (unsigned long) flags, (duk_tval *) duk_get_tval(thr, -1)));
58887 
58888 	DUK_ASSERT(thr != NULL);
58889 	DUK_ASSERT(thr->heap != NULL);
58890 	DUK_ASSERT(obj != NULL);
58891 	DUK_ASSERT(key != NULL);
58892 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
58893 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
58894 	DUK_ASSERT(duk_is_valid_index(thr, -1));  /* contains value */
58895 
58896 	arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
58897 
58898 	if (duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
58899 		if (desc.e_idx >= 0) {
58900 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
58901 				DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> skip as requested"));
58902 				goto pop_exit;
58903 			}
58904 			DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> update value and attributes"));
58905 			if (DUK_UNLIKELY(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx))) {
58906 				DUK_D(DUK_DPRINT("existing property is an accessor, not supported"));
58907 				goto error_internal;
58908 			}
58909 
58910 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, propflags);
58911 			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
58912 		} else if (desc.a_idx >= 0) {
58913 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
58914 				DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> skip as requested"));
58915 				goto pop_exit;
58916 			}
58917 			DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> update value (assert attributes)"));
58918 			if (propflags != DUK_PROPDESC_FLAGS_WEC) {
58919 				DUK_D(DUK_DPRINT("existing property in array part, but propflags not WEC (0x%02lx)",
58920 				                 (unsigned long) propflags));
58921 				goto error_internal;
58922 			}
58923 
58924 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
58925 		} else {
58926 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
58927 				DUK_DDD(DUK_DDDPRINT("property already exists but is virtual -> skip as requested"));
58928 				goto pop_exit;
58929 			}
58930 			if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
58931 				duk_uint32_t new_len;
58932 #if defined(DUK_USE_DEBUG)
58933 				duk_uint32_t prev_len;
58934 				prev_len = ((duk_harray *) obj)->length;
58935 #endif
58936 				new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_NEGIDX(thr, -1));
58937 				((duk_harray *) obj)->length = new_len;
58938 				DUK_D(DUK_DPRINT("internal define property for array .length: %ld -> %ld",
58939 				                 (long) prev_len, (long) ((duk_harray *) obj)->length));
58940 				goto pop_exit;
58941 			}
58942 			DUK_DD(DUK_DDPRINT("property already exists but is virtual -> failure"));
58943 			goto error_virtual;
58944 		}
58945 
58946 		goto write_value;
58947 	}
58948 
58949 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
58950 		if (arr_idx != DUK__NO_ARRAY_INDEX) {
58951 			DUK_DDD(DUK_DDDPRINT("property does not exist, object has array part -> possibly extend array part and write value (assert attributes)"));
58952 			DUK_ASSERT(propflags == DUK_PROPDESC_FLAGS_WEC);
58953 
58954 			/* always grow the array, no sparse / abandon support here */
58955 			if (arr_idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
58956 				duk__grow_props_for_array_item(thr, obj, arr_idx);
58957 			}
58958 
58959 			DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
58960 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
58961 			goto write_value;
58962 		}
58963 	}
58964 
58965 	DUK_DDD(DUK_DDDPRINT("property does not exist, object belongs in entry part -> allocate new entry and write value and attributes"));
58966 	e_idx = duk__hobject_alloc_entry_checked(thr, obj, key);  /* increases key refcount */
58967 	DUK_ASSERT(e_idx >= 0);
58968 	DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, propflags);
58969 	tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
58970 	/* new entry: previous value is garbage; set to undefined to share write_value */
58971 	DUK_TVAL_SET_UNDEFINED(tv1);
58972 	goto write_value;
58973 
58974  write_value:
58975 	/* tv1 points to value storage */
58976 
58977 	tv2 = duk_require_tval(thr, -1);  /* late lookup, avoid side effects */
58978 	DUK_DDD(DUK_DDDPRINT("writing/updating value: %!T -> %!T",
58979 	                     (duk_tval *) tv1, (duk_tval *) tv2));
58980 
58981 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
58982 	goto pop_exit;
58983 
58984  pop_exit:
58985 	duk_pop_unsafe(thr);  /* remove in_val */
58986 	return;
58987 
58988  error_virtual:  /* share error message */
58989  error_internal:
58990 	DUK_ERROR_INTERNAL(thr);
58991 	DUK_WO_NORETURN(return;);
58992 }
58993 
58994 /*
58995  *  Fast path for defining array indexed values without interning the key.
58996  *  This is used by e.g. code for Array prototype and traceback creation so
58997  *  must avoid interning.
58998  */
58999 
59000 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) {
59001 	duk_hstring *key;
59002 	duk_tval *tv1, *tv2;
59003 
59004 	DUK_DDD(DUK_DDDPRINT("define new property (internal) arr_idx fast path: thr=%p, obj=%!O, "
59005 	                     "arr_idx=%ld, flags=0x%02lx, val=%!T",
59006 	                     (void *) thr, obj, (long) arr_idx, (unsigned long) flags,
59007 	                     (duk_tval *) duk_get_tval(thr, -1)));
59008 
59009 	DUK_ASSERT(thr != NULL);
59010 	DUK_ASSERT(thr->heap != NULL);
59011 	DUK_ASSERT(obj != NULL);
59012 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
59013 
59014 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
59015 	    arr_idx != DUK__NO_ARRAY_INDEX &&
59016 	    flags == DUK_PROPDESC_FLAGS_WEC) {
59017 		DUK_ASSERT((flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) == 0);  /* covered by comparison */
59018 
59019 		DUK_DDD(DUK_DDDPRINT("define property to array part (property may or may not exist yet)"));
59020 
59021 		/* always grow the array, no sparse / abandon support here */
59022 		if (arr_idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
59023 			duk__grow_props_for_array_item(thr, obj, arr_idx);
59024 		}
59025 
59026 		DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
59027 		tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
59028 		tv2 = duk_require_tval(thr, -1);
59029 
59030 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
59031 
59032 		duk_pop_unsafe(thr);  /* [ ...val ] -> [ ... ] */
59033 		return;
59034 	}
59035 
59036 	DUK_DDD(DUK_DDDPRINT("define property fast path didn't work, use slow path"));
59037 
59038 	key = duk_push_uint_to_hstring(thr, (duk_uint_t) arr_idx);
59039 	DUK_ASSERT(key != NULL);
59040 	duk_insert(thr, -2);  /* [ ... val key ] -> [ ... key val ] */
59041 
59042 	duk_hobject_define_property_internal(thr, obj, key, flags);
59043 
59044 	duk_pop_unsafe(thr);  /* [ ... key ] -> [ ... ] */
59045 }
59046 
59047 /*
59048  *  Internal helpers for managing object 'length'
59049  */
59050 
59051 DUK_INTERNAL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj) {
59052 	duk_double_t val;
59053 
59054 	DUK_ASSERT_CTX_VALID(thr);
59055 	DUK_ASSERT(obj != NULL);
59056 
59057 	/* Fast path for Arrays. */
59058 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
59059 		return ((duk_harray *) obj)->length;
59060 	}
59061 
59062 	/* Slow path, .length can be e.g. accessor, obj can be a Proxy, etc. */
59063 	duk_push_hobject(thr, obj);
59064 	duk_push_hstring_stridx(thr, DUK_STRIDX_LENGTH);
59065 	(void) duk_hobject_getprop(thr,
59066 	                           DUK_GET_TVAL_NEGIDX(thr, -2),
59067 	                           DUK_GET_TVAL_NEGIDX(thr, -1));
59068 	val = duk_to_number_m1(thr);
59069 	duk_pop_3_unsafe(thr);
59070 
59071 	/* This isn't part of ECMAScript semantics; return a value within
59072 	 * duk_size_t range, or 0 otherwise.
59073 	 */
59074 	if (val >= 0.0 && val <= (duk_double_t) DUK_SIZE_MAX) {
59075 		return (duk_size_t) val;
59076 	}
59077 	return 0;
59078 }
59079 
59080 /*
59081  *  Fast finalizer check for an object.  Walks the prototype chain, checking
59082  *  for finalizer presence using DUK_HOBJECT_FLAG_HAVE_FINALIZER which is kept
59083  *  in sync with the actual property when setting/removing the finalizer.
59084  */
59085 
59086 #if defined(DUK_USE_HEAPPTR16)
59087 DUK_INTERNAL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_heap *heap, duk_hobject *obj) {
59088 #else
59089 DUK_INTERNAL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_hobject *obj) {
59090 #endif
59091 	duk_uint_t sanity;
59092 
59093 	DUK_ASSERT(obj != NULL);
59094 
59095 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
59096 	do {
59097 		if (DUK_UNLIKELY(DUK_HOBJECT_HAS_HAVE_FINALIZER(obj))) {
59098 			return 1;
59099 		}
59100 		if (DUK_UNLIKELY(sanity-- == 0)) {
59101 			DUK_D(DUK_DPRINT("prototype loop when checking for finalizer existence; returning false"));
59102 			return 0;
59103 		}
59104 #if defined(DUK_USE_HEAPPTR16)
59105 		DUK_ASSERT(heap != NULL);
59106 		obj = DUK_HOBJECT_GET_PROTOTYPE(heap, obj);
59107 #else
59108 		obj = DUK_HOBJECT_GET_PROTOTYPE(NULL, obj);  /* 'heap' arg ignored */
59109 #endif
59110 	} while (obj != NULL);
59111 
59112 	return 0;
59113 }
59114 
59115 /*
59116  *  Object.getOwnPropertyDescriptor()  (E5 Sections 15.2.3.3, 8.10.4)
59117  *
59118  *  [ ... key ] -> [ ... desc/undefined ]
59119  */
59120 
59121 DUK_INTERNAL void duk_hobject_object_get_own_property_descriptor(duk_hthread *thr, duk_idx_t obj_idx) {
59122 	duk_hobject *obj;
59123 	duk_hstring *key;
59124 	duk_propdesc pd;
59125 
59126 	DUK_ASSERT(thr != NULL);
59127 	DUK_ASSERT(thr->heap != NULL);
59128 
59129 	obj = duk_require_hobject_promote_mask(thr, obj_idx, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
59130 	key = duk_to_property_key_hstring(thr, -1);
59131 	DUK_ASSERT(key != NULL);
59132 
59133 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
59134 
59135 	if (!duk_hobject_get_own_propdesc(thr, obj, key, &pd, DUK_GETDESC_FLAG_PUSH_VALUE)) {
59136 		duk_push_undefined(thr);
59137 		duk_remove_m2(thr);
59138 		return;
59139 	}
59140 
59141 	duk_push_object(thr);
59142 
59143 	/* [ ... key value desc ] */
59144 
59145 	if (DUK_PROPDESC_IS_ACCESSOR(&pd)) {
59146 		/* If a setter/getter is missing (undefined), the descriptor must
59147 		 * still have the property present with the value 'undefined'.
59148 		 */
59149 		if (pd.get) {
59150 			duk_push_hobject(thr, pd.get);
59151 		} else {
59152 			duk_push_undefined(thr);
59153 		}
59154 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_GET);
59155 		if (pd.set) {
59156 			duk_push_hobject(thr, pd.set);
59157 		} else {
59158 			duk_push_undefined(thr);
59159 		}
59160 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_SET);
59161 	} else {
59162 		duk_dup_m2(thr);
59163 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_VALUE);
59164 		duk_push_boolean(thr, DUK_PROPDESC_IS_WRITABLE(&pd));
59165 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_WRITABLE);
59166 	}
59167 	duk_push_boolean(thr, DUK_PROPDESC_IS_ENUMERABLE(&pd));
59168 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_ENUMERABLE);
59169 	duk_push_boolean(thr, DUK_PROPDESC_IS_CONFIGURABLE(&pd));
59170 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_CONFIGURABLE);
59171 
59172 	/* [ ... key value desc ] */
59173 
59174 	duk_replace(thr, -3);
59175 	duk_pop_unsafe(thr);  /* -> [ ... desc ] */
59176 }
59177 
59178 /*
59179  *  NormalizePropertyDescriptor() related helper.
59180  *
59181  *  Internal helper which validates and normalizes a property descriptor
59182  *  represented as an ECMAScript object (e.g. argument to defineProperty()).
59183  *  The output of this conversion is a set of defprop_flags and possibly
59184  *  some values pushed on the value stack to (1) ensure borrowed pointers
59185  *  remain valid, and (2) avoid unnecessary pops for footprint reasons.
59186  *  Caller must manage stack top carefully because the number of values
59187  *  pushed depends on the input property descriptor.
59188  *
59189  *  The original descriptor object must not be altered in the process.
59190  */
59191 
59192 /* XXX: very basic optimization -> duk_get_prop_stridx_top */
59193 
59194 DUK_INTERNAL
59195 void duk_hobject_prepare_property_descriptor(duk_hthread *thr,
59196                                              duk_idx_t idx_in,
59197                                              duk_uint_t *out_defprop_flags,
59198                                              duk_idx_t *out_idx_value,
59199                                              duk_hobject **out_getter,
59200                                              duk_hobject **out_setter) {
59201 	duk_idx_t idx_value = -1;
59202 	duk_hobject *getter = NULL;
59203 	duk_hobject *setter = NULL;
59204 	duk_bool_t is_data_desc = 0;
59205 	duk_bool_t is_acc_desc = 0;
59206 	duk_uint_t defprop_flags = 0;
59207 
59208 	DUK_ASSERT(out_defprop_flags != NULL);
59209 	DUK_ASSERT(out_idx_value != NULL);
59210 	DUK_ASSERT(out_getter != NULL);
59211 	DUK_ASSERT(out_setter != NULL);
59212 	DUK_ASSERT(idx_in <= 0x7fffL);  /* short variants would be OK, but not used to avoid shifts */
59213 
59214 	/* Must be an object, otherwise TypeError (E5.1 Section 8.10.5, step 1). */
59215 	idx_in = duk_require_normalize_index(thr, idx_in);
59216 	(void) duk_require_hobject(thr, idx_in);
59217 
59218 	/* The coercion order must match the ToPropertyDescriptor() algorithm
59219 	 * so that side effects in coercion happen in the correct order.
59220 	 * (This order also happens to be compatible with duk_def_prop(),
59221 	 * although it doesn't matter in practice.)
59222 	 */
59223 
59224 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_VALUE)) {
59225 		is_data_desc = 1;
59226 		defprop_flags |= DUK_DEFPROP_HAVE_VALUE;
59227 		idx_value = duk_get_top_index(thr);
59228 	}
59229 
59230 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_WRITABLE)) {
59231 		is_data_desc = 1;
59232 		if (duk_to_boolean_top_pop(thr)) {
59233 			defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE;
59234 		} else {
59235 			defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE;
59236 		}
59237 	}
59238 
59239 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_GET)) {
59240 		duk_tval *tv = duk_require_tval(thr, -1);
59241 		duk_hobject *h_get;
59242 
59243 		if (DUK_TVAL_IS_UNDEFINED(tv)) {
59244 			/* undefined is accepted */
59245 			DUK_ASSERT(getter == NULL);
59246 		} else {
59247 			/* NOTE: lightfuncs are coerced to full functions because
59248 			 * lightfuncs don't fit into a property value slot.  This
59249 			 * has some side effects, see test-dev-lightfunc-accessor.js.
59250 			 */
59251 			h_get = duk_get_hobject_promote_lfunc(thr, -1);
59252 			if (h_get == NULL || !DUK_HOBJECT_IS_CALLABLE(h_get)) {
59253 				goto type_error;
59254 			}
59255 			getter = h_get;
59256 		}
59257 		is_acc_desc = 1;
59258 		defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
59259 	}
59260 
59261 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_SET)) {
59262 		duk_tval *tv = duk_require_tval(thr, -1);
59263 		duk_hobject *h_set;
59264 
59265 		if (DUK_TVAL_IS_UNDEFINED(tv)) {
59266 			/* undefined is accepted */
59267 			DUK_ASSERT(setter == NULL);
59268 		}  else {
59269 			/* NOTE: lightfuncs are coerced to full functions because
59270 			 * lightfuncs don't fit into a property value slot.  This
59271 			 * has some side effects, see test-dev-lightfunc-accessor.js.
59272 			 */
59273 			h_set = duk_get_hobject_promote_lfunc(thr, -1);
59274 			if (h_set == NULL || !DUK_HOBJECT_IS_CALLABLE(h_set)) {
59275 				goto type_error;
59276 			}
59277 			setter = h_set;
59278 		}
59279 		is_acc_desc = 1;
59280 		defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
59281 	}
59282 
59283 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_ENUMERABLE)) {
59284 		if (duk_to_boolean_top_pop(thr)) {
59285 			defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE;
59286 		} else {
59287 			defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE;
59288 		}
59289 	}
59290 
59291 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_CONFIGURABLE)) {
59292 		if (duk_to_boolean_top_pop(thr)) {
59293 			defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE;
59294 		} else {
59295 			defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE;
59296 		}
59297 	}
59298 
59299 	if (is_data_desc && is_acc_desc) {
59300 		goto type_error;
59301 	}
59302 
59303 	*out_defprop_flags = defprop_flags;
59304 	*out_idx_value = idx_value;
59305 	*out_getter = getter;
59306 	*out_setter = setter;
59307 
59308 	/* [ ... [multiple values] ] */
59309 	return;
59310 
59311  type_error:
59312 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);
59313 	DUK_WO_NORETURN(return;);
59314 }
59315 
59316 /*
59317  *  Object.defineProperty() related helper (E5 Section 15.2.3.6).
59318  *  Also handles ES2015 Reflect.defineProperty().
59319  *
59320  *  Inlines all [[DefineOwnProperty]] exotic behaviors.
59321  *
59322  *  Note: ECMAScript compliant [[DefineOwnProperty]](P, Desc, Throw) is not
59323  *  implemented directly, but Object.defineProperty() serves its purpose.
59324  *  We don't need the [[DefineOwnProperty]] internally and we don't have a
59325  *  property descriptor with 'missing values' so it's easier to avoid it
59326  *  entirely.
59327  *
59328  *  Note: this is only called for actual objects, not primitive values.
59329  *  This must support virtual properties for full objects (e.g. Strings)
59330  *  but not for plain values (e.g. strings).  Lightfuncs, even though
59331  *  primitive in a sense, are treated like objects and accepted as target
59332  *  values.
59333  */
59334 
59335 /* XXX: this is a major target for size optimization */
59336 DUK_INTERNAL
59337 duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
59338                                               duk_uint_t defprop_flags,
59339                                               duk_hobject *obj,
59340                                               duk_hstring *key,
59341                                               duk_idx_t idx_value,
59342                                               duk_hobject *get,
59343                                               duk_hobject *set,
59344                                               duk_bool_t throw_flag) {
59345 	duk_uint32_t arr_idx;
59346 	duk_tval tv;
59347 	duk_bool_t has_enumerable;
59348 	duk_bool_t has_configurable;
59349 	duk_bool_t has_writable;
59350 	duk_bool_t has_value;
59351 	duk_bool_t has_get;
59352 	duk_bool_t has_set;
59353 	duk_bool_t is_enumerable;
59354 	duk_bool_t is_configurable;
59355 	duk_bool_t is_writable;
59356 	duk_bool_t force_flag;
59357 	duk_small_uint_t new_flags;
59358 	duk_propdesc curr;
59359 	duk_uint32_t arridx_new_array_length;  /* != 0 => post-update for array 'length' (used when key is an array index) */
59360 	duk_uint32_t arrlen_old_len;
59361 	duk_uint32_t arrlen_new_len;
59362 	duk_bool_t pending_write_protect;
59363 
59364 	DUK_ASSERT(thr != NULL);
59365 	DUK_ASSERT(thr->heap != NULL);
59366 	DUK_ASSERT(obj != NULL);
59367 	DUK_ASSERT(key != NULL);
59368 	/* idx_value may be < 0 (no value), set and get may be NULL */
59369 
59370 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
59371 
59372 	/* All the flags fit in 16 bits, so will fit into duk_bool_t. */
59373 
59374 	has_writable = (defprop_flags & DUK_DEFPROP_HAVE_WRITABLE);
59375 	has_enumerable = (defprop_flags & DUK_DEFPROP_HAVE_ENUMERABLE);
59376 	has_configurable = (defprop_flags & DUK_DEFPROP_HAVE_CONFIGURABLE);
59377 	has_value = (defprop_flags & DUK_DEFPROP_HAVE_VALUE);
59378 	has_get = (defprop_flags & DUK_DEFPROP_HAVE_GETTER);
59379 	has_set = (defprop_flags & DUK_DEFPROP_HAVE_SETTER);
59380 	is_writable = (defprop_flags & DUK_DEFPROP_WRITABLE);
59381 	is_enumerable = (defprop_flags & DUK_DEFPROP_ENUMERABLE);
59382 	is_configurable = (defprop_flags & DUK_DEFPROP_CONFIGURABLE);
59383 	force_flag = (defprop_flags & DUK_DEFPROP_FORCE);
59384 
59385 	arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
59386 
59387 	arridx_new_array_length = 0;
59388 	pending_write_protect = 0;
59389 	arrlen_old_len = 0;
59390 	arrlen_new_len = 0;
59391 
59392 	DUK_DDD(DUK_DDDPRINT("has_enumerable=%ld is_enumerable=%ld "
59393 	                     "has_configurable=%ld is_configurable=%ld "
59394 	                     "has_writable=%ld is_writable=%ld "
59395 	                     "has_value=%ld value=%!T "
59396 	                     "has_get=%ld get=%p=%!O "
59397 	                     "has_set=%ld set=%p=%!O "
59398 	                     "arr_idx=%ld throw_flag=!%ld",
59399 	                     (long) has_enumerable, (long) is_enumerable,
59400 	                     (long) has_configurable, (long) is_configurable,
59401 	                     (long) has_writable, (long) is_writable,
59402 	                     (long) has_value, (duk_tval *) (idx_value >= 0 ? duk_get_tval(thr, idx_value) : NULL),
59403 	                     (long) has_get, (void *) get, (duk_heaphdr *) get,
59404 	                     (long) has_set, (void *) set, (duk_heaphdr *) set,
59405 	                     (long) arr_idx, (long) throw_flag));
59406 
59407 	/*
59408 	 *  Array exotic behaviors can be implemented at this point.  The local variables
59409 	 *  are essentially a 'value copy' of the input descriptor (Desc), which is modified
59410 	 *  by the Array [[DefineOwnProperty]] (E5 Section 15.4.5.1).
59411 	 */
59412 
59413 	if (!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
59414 		goto skip_array_exotic;
59415 	}
59416 
59417 	if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
59418 		duk_harray *a;
59419 
59420 		/* E5 Section 15.4.5.1, step 3, steps a - i are implemented here, j - n at the end */
59421 		if (!has_value) {
59422 			DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', but no value in descriptor -> normal behavior"));
59423 			goto skip_array_exotic;
59424 		}
59425 
59426 		DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', value present in descriptor -> exotic behavior"));
59427 
59428 		/*
59429 		 *  Get old and new length
59430 		 */
59431 
59432 		a = (duk_harray *) obj;
59433 		DUK_ASSERT_HARRAY_VALID(a);
59434 		arrlen_old_len = a->length;
59435 
59436 		DUK_ASSERT(idx_value >= 0);
59437 		arrlen_new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_POSIDX(thr, idx_value));
59438 		duk_push_u32(thr, arrlen_new_len);
59439 		duk_replace(thr, idx_value);  /* step 3.e: replace 'Desc.[[Value]]' */
59440 
59441 		DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) arrlen_old_len, (long) arrlen_new_len));
59442 
59443 		if (arrlen_new_len >= arrlen_old_len) {
59444 			/* standard behavior, step 3.f.i */
59445 			DUK_DDD(DUK_DDDPRINT("new length is same or higher as previous => standard behavior"));
59446 			goto skip_array_exotic;
59447 		}
59448 		DUK_DDD(DUK_DDDPRINT("new length is smaller than previous => exotic post behavior"));
59449 
59450 		/* XXX: consolidated algorithm step 15.f -> redundant? */
59451 		if (DUK_HARRAY_LENGTH_NONWRITABLE(a) && !force_flag) {
59452 			/* Array .length is always non-configurable; if it's also
59453 			 * non-writable, don't allow it to be written.
59454 			 */
59455 			goto fail_not_configurable;
59456 		}
59457 
59458 		/* steps 3.h and 3.i */
59459 		if (has_writable && !is_writable) {
59460 			DUK_DDD(DUK_DDDPRINT("desc writable is false, force it back to true, and flag pending write protect"));
59461 			is_writable = 1;
59462 			pending_write_protect = 1;
59463 		}
59464 
59465 		/* remaining actual steps are carried out if standard DefineOwnProperty succeeds */
59466 	} else if (arr_idx != DUK__NO_ARRAY_INDEX) {
59467 		/* XXX: any chance of unifying this with the 'length' key handling? */
59468 
59469 		/* E5 Section 15.4.5.1, step 4 */
59470 		duk_uint32_t old_len;
59471 		duk_harray *a;
59472 
59473 		a = (duk_harray *) obj;
59474 		DUK_ASSERT_HARRAY_VALID(a);
59475 
59476 		old_len = a->length;
59477 
59478 		if (arr_idx >= old_len) {
59479 			DUK_DDD(DUK_DDDPRINT("defineProperty requires array length update "
59480 			                     "(arr_idx=%ld, old_len=%ld)",
59481 			                     (long) arr_idx, (long) old_len));
59482 
59483 			if (DUK_HARRAY_LENGTH_NONWRITABLE(a) && !force_flag) {
59484 				/* Array .length is always non-configurable, so
59485 				 * if it's also non-writable, don't allow a value
59486 				 * write.  With force flag allow writing.
59487 				 */
59488 				goto fail_not_configurable;
59489 			}
59490 
59491 			/* actual update happens once write has been completed without
59492 			 * error below.
59493 			 */
59494 			DUK_ASSERT(arr_idx != 0xffffffffUL);
59495 			arridx_new_array_length = arr_idx + 1;
59496 		} else {
59497 			DUK_DDD(DUK_DDDPRINT("defineProperty does not require length update "
59498 			                     "(arr_idx=%ld, old_len=%ld) -> standard behavior",
59499 			                     (long) arr_idx, (long) old_len));
59500 		}
59501 	}
59502  skip_array_exotic:
59503 
59504 	/* XXX: There is currently no support for writing buffer object
59505 	 * indexed elements here.  Attempt to do so will succeed and
59506 	 * write a concrete property into the buffer object.  This should
59507 	 * be fixed at some point but because buffers are a custom feature
59508 	 * anyway, this is relatively unimportant.
59509 	 */
59510 
59511 	/*
59512 	 *  Actual Object.defineProperty() default algorithm.
59513 	 */
59514 
59515 	/*
59516 	 *  First check whether property exists; if not, simple case.  This covers
59517 	 *  steps 1-4.
59518 	 */
59519 
59520 	if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE)) {
59521 		DUK_DDD(DUK_DDDPRINT("property does not exist"));
59522 
59523 		if (!DUK_HOBJECT_HAS_EXTENSIBLE(obj) && !force_flag) {
59524 			goto fail_not_extensible;
59525 		}
59526 
59527 #if defined(DUK_USE_ROM_OBJECTS)
59528 		/* ROM objects are never extensible but force flag may
59529 		 * allow us to come here anyway.
59530 		 */
59531 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj) || !DUK_HOBJECT_HAS_EXTENSIBLE(obj));
59532 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
59533 			DUK_D(DUK_DPRINT("attempt to define property on a read-only target object"));
59534 			goto fail_not_configurable;
59535 		}
59536 #endif
59537 
59538 		/* XXX: share final setting code for value and flags?  difficult because
59539 		 * refcount code is different.  Share entry allocation?  But can't allocate
59540 		 * until array index checked.
59541 		 */
59542 
59543 		/* steps 4.a and 4.b are tricky */
59544 		if (has_set || has_get) {
59545 			duk_int_t e_idx;
59546 
59547 			DUK_DDD(DUK_DDDPRINT("create new accessor property"));
59548 
59549 			DUK_ASSERT(has_set || set == NULL);
59550 			DUK_ASSERT(has_get || get == NULL);
59551 			DUK_ASSERT(!has_value);
59552 			DUK_ASSERT(!has_writable);
59553 
59554 			new_flags = DUK_PROPDESC_FLAG_ACCESSOR;  /* defaults, E5 Section 8.6.1, Table 7 */
59555 			if (has_enumerable && is_enumerable) {
59556 				new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
59557 			}
59558 			if (has_configurable && is_configurable) {
59559 				new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
59560 			}
59561 
59562 			if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
59563 				DUK_DDD(DUK_DDDPRINT("accessor cannot go to array part, abandon array"));
59564 				duk__abandon_array_checked(thr, obj);
59565 			}
59566 
59567 			/* write to entry part */
59568 			e_idx = duk__hobject_alloc_entry_checked(thr, obj, key);
59569 			DUK_ASSERT(e_idx >= 0);
59570 
59571 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, e_idx, get);
59572 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, e_idx, set);
59573 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, get);
59574 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, set);
59575 
59576 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
59577 			goto success_exotics;
59578 		} else {
59579 			duk_int_t e_idx;
59580 			duk_tval *tv2;
59581 
59582 			DUK_DDD(DUK_DDDPRINT("create new data property"));
59583 
59584 			DUK_ASSERT(!has_set);
59585 			DUK_ASSERT(!has_get);
59586 
59587 			new_flags = 0;  /* defaults, E5 Section 8.6.1, Table 7 */
59588 			if (has_writable && is_writable) {
59589 				new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
59590 			}
59591 			if (has_enumerable && is_enumerable) {
59592 				new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
59593 			}
59594 			if (has_configurable && is_configurable) {
59595 				new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
59596 			}
59597 			if (has_value) {
59598 				duk_tval *tv_tmp = duk_require_tval(thr, idx_value);
59599 				DUK_TVAL_SET_TVAL(&tv, tv_tmp);
59600 			} else {
59601 				DUK_TVAL_SET_UNDEFINED(&tv);  /* default value */
59602 			}
59603 
59604 			if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
59605 				if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
59606 #if 0
59607 					DUK_DDD(DUK_DDDPRINT("new data property attributes match array defaults, attempt to write to array part"));
59608 					/* may become sparse...*/
59609 #endif
59610 					/* XXX: handling for array part missing now; this doesn't affect
59611 					 * compliance but causes array entry writes using defineProperty()
59612 					 * to always abandon array part.
59613 					 */
59614 				}
59615 				DUK_DDD(DUK_DDDPRINT("new data property cannot go to array part, abandon array"));
59616 				duk__abandon_array_checked(thr, obj);
59617 				/* fall through */
59618 			}
59619 
59620 			/* write to entry part */
59621 			e_idx = duk__hobject_alloc_entry_checked(thr, obj, key);
59622 			DUK_ASSERT(e_idx >= 0);
59623 			tv2 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
59624 			DUK_TVAL_SET_TVAL(tv2, &tv);
59625 			DUK_TVAL_INCREF(thr, tv2);
59626 
59627 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
59628 			goto success_exotics;
59629 		}
59630 		DUK_UNREACHABLE();
59631 	}
59632 
59633 	/* we currently assume virtual properties are not configurable (as none of them are) */
59634 	DUK_ASSERT((curr.e_idx >= 0 || curr.a_idx >= 0) || !(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE));
59635 
59636 	/* [obj key desc value get set curr_value] */
59637 
59638 	/*
59639 	 *  Property already exists.  Steps 5-6 detect whether any changes need
59640 	 *  to be made.
59641 	 */
59642 
59643 	if (has_enumerable) {
59644 		if (is_enumerable) {
59645 			if (!(curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE)) {
59646 				goto need_check;
59647 			}
59648 		} else {
59649 			if (curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE) {
59650 				goto need_check;
59651 			}
59652 		}
59653 	}
59654 	if (has_configurable) {
59655 		if (is_configurable) {
59656 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
59657 				goto need_check;
59658 			}
59659 		} else {
59660 			if (curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
59661 				goto need_check;
59662 			}
59663 		}
59664 	}
59665 	if (has_value) {
59666 		duk_tval *tmp1;
59667 		duk_tval *tmp2;
59668 
59669 		/* attempt to change from accessor to data property */
59670 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
59671 			goto need_check;
59672 		}
59673 
59674 		tmp1 = duk_require_tval(thr, -1);         /* curr value */
59675 		tmp2 = duk_require_tval(thr, idx_value);  /* new value */
59676 		if (!duk_js_samevalue(tmp1, tmp2)) {
59677 			goto need_check;
59678 		}
59679 	}
59680 	if (has_writable) {
59681 		/* attempt to change from accessor to data property */
59682 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
59683 			goto need_check;
59684 		}
59685 
59686 		if (is_writable) {
59687 			if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
59688 				goto need_check;
59689 			}
59690 		} else {
59691 			if (curr.flags & DUK_PROPDESC_FLAG_WRITABLE) {
59692 				goto need_check;
59693 			}
59694 		}
59695 	}
59696 	if (has_set) {
59697 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
59698 			if (set != curr.set) {
59699 				goto need_check;
59700 			}
59701 		} else {
59702 			goto need_check;
59703 		}
59704 	}
59705 	if (has_get) {
59706 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
59707 			if (get != curr.get) {
59708 				goto need_check;
59709 			}
59710 		} else {
59711 			goto need_check;
59712 		}
59713 	}
59714 
59715 	/* property exists, either 'desc' is empty, or all values
59716 	 * match (SameValue)
59717 	 */
59718 	goto success_no_exotics;
59719 
59720  need_check:
59721 
59722 	/*
59723 	 *  Some change(s) need to be made.  Steps 7-11.
59724 	 */
59725 
59726 	/* shared checks for all descriptor types */
59727 	if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
59728 		if (has_configurable && is_configurable) {
59729 			goto fail_not_configurable;
59730 		}
59731 		if (has_enumerable) {
59732 			if (curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE) {
59733 				if (!is_enumerable) {
59734 					goto fail_not_configurable;
59735 				}
59736 			} else {
59737 				if (is_enumerable) {
59738 					goto fail_not_configurable;
59739 				}
59740 			}
59741 		}
59742 	}
59743 
59744 	/* Virtual properties don't have backing so they can't mostly be
59745 	 * edited.  Some virtual properties are, however, writable: for
59746 	 * example, virtual index properties of buffer objects and Array
59747 	 * instance .length.  These are not configurable so the checks
59748 	 * above mostly cover attempts to change them, except when the
59749 	 * duk_def_prop() call is used with DUK_DEFPROP_FORCE; even in
59750 	 * that case we can't forcibly change the property attributes
59751 	 * because they don't have concrete backing.
59752 	 */
59753 
59754 	/* XXX: for ROM objects too it'd be best if value modify was
59755 	 * allowed if the value matches SameValue.
59756 	 */
59757 	/* Reject attempt to change a read-only object. */
59758 #if defined(DUK_USE_ROM_OBJECTS)
59759 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
59760 		DUK_DD(DUK_DDPRINT("attempt to define property on read-only target object"));
59761 		goto fail_not_configurable;
59762 	}
59763 #endif
59764 
59765 	/* descriptor type specific checks */
59766 	if (has_set || has_get) {
59767 		/* IsAccessorDescriptor(desc) == true */
59768 		DUK_ASSERT(!has_writable);
59769 		DUK_ASSERT(!has_value);
59770 
59771 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
59772 			/* curr and desc are accessors */
59773 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
59774 				if (has_set && set != curr.set) {
59775 					goto fail_not_configurable;
59776 				}
59777 				if (has_get && get != curr.get) {
59778 					goto fail_not_configurable;
59779 				}
59780 			}
59781 		} else {
59782 			duk_bool_t rc;
59783 			duk_tval *tv1;
59784 
59785 			/* curr is data, desc is accessor */
59786 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
59787 				goto fail_not_configurable;
59788 			}
59789 
59790 			DUK_DDD(DUK_DDDPRINT("convert property to accessor property"));
59791 			if (curr.a_idx >= 0) {
59792 				DUK_DDD(DUK_DDDPRINT("property to convert is stored in an array entry, abandon array and re-lookup"));
59793 				duk__abandon_array_checked(thr, obj);
59794 				duk_pop_unsafe(thr);  /* remove old value */
59795 				rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
59796 				DUK_UNREF(rc);
59797 				DUK_ASSERT(rc != 0);
59798 				DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
59799 			}
59800 			if (curr.e_idx < 0) {
59801 				DUK_ASSERT(curr.a_idx < 0 && curr.e_idx < 0);
59802 				goto fail_virtual;  /* safeguard for virtual property */
59803 			}
59804 
59805 			DUK_ASSERT(curr.e_idx >= 0);
59806 			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
59807 
59808 			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
59809 			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv1);  /* XXX: just decref */
59810 
59811 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
59812 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
59813 			DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);
59814 			DUK_HOBJECT_E_SLOT_SET_ACCESSOR(thr->heap, obj, curr.e_idx);
59815 
59816 			DUK_DDD(DUK_DDDPRINT("flags after data->accessor conversion: 0x%02lx",
59817 			                     (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
59818 			/* Update curr.flags; faster than a re-lookup. */
59819 			curr.flags &= ~DUK_PROPDESC_FLAG_WRITABLE;
59820 			curr.flags |= DUK_PROPDESC_FLAG_ACCESSOR;
59821 		}
59822 	} else if (has_value || has_writable) {
59823 		/* IsDataDescriptor(desc) == true */
59824 		DUK_ASSERT(!has_set);
59825 		DUK_ASSERT(!has_get);
59826 
59827 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
59828 			duk_hobject *tmp;
59829 
59830 			/* curr is accessor, desc is data */
59831 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
59832 				goto fail_not_configurable;
59833 			}
59834 
59835 			/* curr is accessor -> cannot be in array part. */
59836 			DUK_ASSERT(curr.a_idx < 0);
59837 			if (curr.e_idx < 0) {
59838 				goto fail_virtual;  /* safeguard; no virtual accessors now */
59839 			}
59840 
59841 			DUK_DDD(DUK_DDDPRINT("convert property to data property"));
59842 
59843 			DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
59844 			tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
59845 			DUK_UNREF(tmp);
59846 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
59847 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
59848 			tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
59849 			DUK_UNREF(tmp);
59850 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
59851 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
59852 
59853 			DUK_TVAL_SET_UNDEFINED(DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx));
59854 			DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);
59855 			DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(thr->heap, obj, curr.e_idx);
59856 
59857 			DUK_DDD(DUK_DDDPRINT("flags after accessor->data conversion: 0x%02lx",
59858 			                     (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
59859 
59860 			/* Update curr.flags; faster than a re-lookup. */
59861 			curr.flags &= ~(DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ACCESSOR);
59862 		} else {
59863 			/* curr and desc are data */
59864 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
59865 				if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_writable && is_writable) {
59866 					goto fail_not_configurable;
59867 				}
59868 				/* Note: changing from writable to non-writable is OK */
59869 				if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_value) {
59870 					duk_tval *tmp1 = duk_require_tval(thr, -1);         /* curr value */
59871 					duk_tval *tmp2 = duk_require_tval(thr, idx_value);  /* new value */
59872 					if (!duk_js_samevalue(tmp1, tmp2)) {
59873 						goto fail_not_configurable;
59874 					}
59875 				}
59876 			}
59877 		}
59878 	} else {
59879 		/* IsGenericDescriptor(desc) == true; this means in practice that 'desc'
59880 		 * only has [[Enumerable]] or [[Configurable]] flag updates, which are
59881 		 * allowed at this point.
59882 		 */
59883 
59884 		DUK_ASSERT(!has_value && !has_writable && !has_get && !has_set);
59885 	}
59886 
59887 	/*
59888 	 *  Start doing property attributes updates.  Steps 12-13.
59889 	 *
59890 	 *  Start by computing new attribute flags without writing yet.
59891 	 *  Property type conversion is done above if necessary.
59892 	 */
59893 
59894 	new_flags = curr.flags;
59895 
59896 	if (has_enumerable) {
59897 		if (is_enumerable) {
59898 			new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
59899 		} else {
59900 			new_flags &= ~DUK_PROPDESC_FLAG_ENUMERABLE;
59901 		}
59902 	}
59903 	if (has_configurable) {
59904 		if (is_configurable) {
59905 			new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
59906 		} else {
59907 			new_flags &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
59908 		}
59909 	}
59910 	if (has_writable) {
59911 		if (is_writable) {
59912 			new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
59913 		} else {
59914 			new_flags &= ~DUK_PROPDESC_FLAG_WRITABLE;
59915 		}
59916 	}
59917 
59918 	/* XXX: write protect after flag? -> any chance of handling it here? */
59919 
59920 	DUK_DDD(DUK_DDDPRINT("new flags that we want to write: 0x%02lx",
59921 	                     (unsigned long) new_flags));
59922 
59923 	/*
59924 	 *  Check whether we need to abandon an array part (if it exists)
59925 	 */
59926 
59927 	if (curr.a_idx >= 0) {
59928 		duk_bool_t rc;
59929 
59930 		DUK_ASSERT(curr.e_idx < 0);
59931 
59932 		if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
59933 			duk_tval *tv1, *tv2;
59934 
59935 			DUK_DDD(DUK_DDDPRINT("array index, new property attributes match array defaults, update in-place"));
59936 
59937 			DUK_ASSERT(curr.flags == DUK_PROPDESC_FLAGS_WEC);  /* must have been, since in array part */
59938 			DUK_ASSERT(!has_set);
59939 			DUK_ASSERT(!has_get);
59940 			DUK_ASSERT(idx_value >= 0);  /* must be: if attributes match and we get here the value must differ (otherwise no change) */
59941 
59942 			tv2 = duk_require_tval(thr, idx_value);
59943 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, curr.a_idx);
59944 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects; may invalidate a_idx */
59945 			goto success_exotics;
59946 		}
59947 
59948 		DUK_DDD(DUK_DDDPRINT("array index, new property attributes do not match array defaults, abandon array and re-lookup"));
59949 		duk__abandon_array_checked(thr, obj);
59950 		duk_pop_unsafe(thr);  /* remove old value */
59951 		rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
59952 		DUK_UNREF(rc);
59953 		DUK_ASSERT(rc != 0);
59954 		DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
59955 	}
59956 
59957 	DUK_DDD(DUK_DDDPRINT("updating existing property in entry part"));
59958 
59959 	/* Array case is handled comprehensively above: either in entry
59960 	 * part or a virtual property.
59961 	 */
59962 	DUK_ASSERT(curr.a_idx < 0);
59963 
59964 	DUK_DDD(DUK_DDDPRINT("update existing property attributes"));
59965 	if (curr.e_idx >= 0) {
59966 		DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, curr.e_idx, new_flags);
59967 	} else {
59968 		/* For Array .length the only allowed transition is for .length
59969 		 * to become non-writable.
59970 		 */
59971 		if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
59972 			duk_harray *a;
59973 			a = (duk_harray *) obj;
59974 			DUK_DD(DUK_DDPRINT("Object.defineProperty() attribute update for duk_harray .length -> %02lx", (unsigned long) new_flags));
59975 			DUK_ASSERT_HARRAY_VALID(a);
59976 			if ((new_flags & DUK_PROPDESC_FLAGS_EC) != (curr.flags & DUK_PROPDESC_FLAGS_EC)) {
59977 				DUK_D(DUK_DPRINT("Object.defineProperty() attempt to change virtual array .length enumerable or configurable attribute, fail"));
59978 				goto fail_virtual;
59979 			}
59980 			if (new_flags & DUK_PROPDESC_FLAG_WRITABLE) {
59981 				DUK_HARRAY_SET_LENGTH_WRITABLE(a);
59982 			} else {
59983 				DUK_HARRAY_SET_LENGTH_NONWRITABLE(a);
59984 			}
59985 		}
59986 	}
59987 
59988 	if (has_set) {
59989 		duk_hobject *tmp;
59990 
59991 		/* Virtual properties are non-configurable but with a 'force'
59992 		 * flag we might come here so check explicitly for virtual.
59993 		 */
59994 		if (curr.e_idx < 0) {
59995 			goto fail_virtual;
59996 		}
59997 
59998 		DUK_DDD(DUK_DDDPRINT("update existing property setter"));
59999 		DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
60000 
60001 		tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
60002 		DUK_UNREF(tmp);
60003 		DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, set);
60004 		DUK_HOBJECT_INCREF_ALLOWNULL(thr, set);
60005 		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects; may invalidate e_idx */
60006 	}
60007 	if (has_get) {
60008 		duk_hobject *tmp;
60009 
60010 		if (curr.e_idx < 0) {
60011 			goto fail_virtual;
60012 		}
60013 
60014 		DUK_DDD(DUK_DDDPRINT("update existing property getter"));
60015 		DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
60016 
60017 		tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
60018 		DUK_UNREF(tmp);
60019 		DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, get);
60020 		DUK_HOBJECT_INCREF_ALLOWNULL(thr, get);
60021 		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects; may invalidate e_idx */
60022 	}
60023 	if (has_value) {
60024 		duk_tval *tv1, *tv2;
60025 
60026 		DUK_DDD(DUK_DDDPRINT("update existing property value"));
60027 
60028 		if (curr.e_idx >= 0) {
60029 			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
60030 			tv2 = duk_require_tval(thr, idx_value);
60031 			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
60032 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects; may invalidate e_idx */
60033 		} else {
60034 			DUK_ASSERT(curr.a_idx < 0);  /* array part case handled comprehensively previously */
60035 
60036 			DUK_DD(DUK_DDPRINT("Object.defineProperty(), value update for virtual property"));
60037 			/* XXX: Uint8Array and other typed array virtual writes not currently
60038 			 * handled.
60039 			 */
60040 			if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
60041 				duk_harray *a;
60042 				a = (duk_harray *) obj;
60043 				DUK_DD(DUK_DDPRINT("Object.defineProperty() value update for duk_harray .length -> %ld", (long) arrlen_new_len));
60044 				DUK_ASSERT_HARRAY_VALID(a);
60045 				a->length = arrlen_new_len;
60046 			} else {
60047 				goto fail_virtual;  /* should not happen */
60048 			}
60049 		}
60050 	}
60051 
60052 	/*
60053 	 *  Standard algorithm succeeded without errors, check for exotic post-behaviors.
60054 	 *
60055 	 *  Arguments exotic behavior in E5 Section 10.6 occurs after the standard
60056 	 *  [[DefineOwnProperty]] has completed successfully.
60057 	 *
60058 	 *  Array exotic behavior in E5 Section 15.4.5.1 is implemented partly
60059 	 *  prior to the default [[DefineOwnProperty]], but:
60060 	 *    - for an array index key (e.g. "10") the final 'length' update occurs here
60061 	 *    - for 'length' key the element deletion and 'length' update occurs here
60062 	 */
60063 
60064  success_exotics:
60065 
60066 	/* curr.a_idx or curr.e_idx may have been invalidated by side effects
60067 	 * above.
60068 	 */
60069 
60070 	/* [obj key desc value get set curr_value] */
60071 
60072 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
60073 		duk_harray *a;
60074 
60075 		a = (duk_harray *) obj;
60076 		DUK_ASSERT_HARRAY_VALID(a);
60077 
60078 		if (arridx_new_array_length > 0) {
60079 			/*
60080 			 *  Note: zero works as a "no update" marker because the new length
60081 			 *  can never be zero after a new property is written.
60082 			 */
60083 
60084 			/* E5 Section 15.4.5.1, steps 4.e.i - 4.e.ii */
60085 
60086 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, pending array length update to: %ld",
60087 			                     (long) arridx_new_array_length));
60088 
60089 			a->length = arridx_new_array_length;
60090 		}
60091 
60092 		if (key == DUK_HTHREAD_STRING_LENGTH(thr) && arrlen_new_len < arrlen_old_len) {
60093 			/*
60094 			 *  E5 Section 15.4.5.1, steps 3.k - 3.n.  The order at the end combines
60095 			 *  the error case 3.l.iii and the success case 3.m-3.n.
60096 			 */
60097 
60098 			/* XXX: investigate whether write protect can be handled above, if we
60099 			 * just update length here while ignoring its protected status
60100 			 */
60101 
60102 			duk_uint32_t result_len;
60103 			duk_bool_t rc;
60104 
60105 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key is 'length', exotic array behavior, "
60106 			                     "doing array element deletion and length update"));
60107 
60108 			rc = duk__handle_put_array_length_smaller(thr, obj, arrlen_old_len, arrlen_new_len, force_flag, &result_len);
60109 
60110 			/* update length (curr points to length, and we assume it's still valid) */
60111 			DUK_ASSERT(result_len >= arrlen_new_len && result_len <= arrlen_old_len);
60112 
60113 			a->length = result_len;
60114 
60115 			if (pending_write_protect) {
60116 				DUK_DDD(DUK_DDDPRINT("setting array length non-writable (pending writability update)"));
60117 				DUK_HARRAY_SET_LENGTH_NONWRITABLE(a);
60118 			}
60119 
60120 			/* XXX: shrink array allocation or entries compaction here? */
60121 			if (!rc) {
60122 				DUK_DD(DUK_DDPRINT("array length write only partially successful"));
60123 				goto fail_not_configurable;
60124 			}
60125 		}
60126 	} else if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {
60127 		duk_hobject *map;
60128 		duk_hobject *varenv;
60129 
60130 		DUK_ASSERT(arridx_new_array_length == 0);
60131 		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));  /* traits are separate; in particular, arguments not an array */
60132 
60133 		map = NULL;
60134 		varenv = NULL;
60135 		if (!duk__lookup_arguments_map(thr, obj, key, &curr, &map, &varenv)) {
60136 			goto success_no_exotics;
60137 		}
60138 		DUK_ASSERT(map != NULL);
60139 		DUK_ASSERT(varenv != NULL);
60140 
60141 		/* [obj key desc value get set curr_value varname] */
60142 
60143 		if (has_set || has_get) {
60144 			/* = IsAccessorDescriptor(Desc) */
60145 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map' "
60146 			                     "changed to an accessor, delete arguments binding"));
60147 
60148 			(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
60149 		} else {
60150 			/* Note: this order matters (final value before deleting map entry must be done) */
60151 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
60152 			                     "check for value update / binding deletion"));
60153 
60154 			if (has_value) {
60155 				duk_hstring *varname;
60156 
60157 				DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
60158 				                     "update bound value (variable/argument)"));
60159 
60160 				varname = duk_require_hstring(thr, -1);
60161 				DUK_ASSERT(varname != NULL);
60162 
60163 				DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
60164 				                     "key=%!O, varname=%!O, value=%!T",
60165 				                     (duk_heaphdr *) key,
60166 				                     (duk_heaphdr *) varname,
60167 				                     (duk_tval *) duk_require_tval(thr, idx_value)));
60168 
60169 				/* strict flag for putvar comes from our caller (currently: fixed) */
60170 				duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(thr, idx_value), 1 /*throw_flag*/);
60171 			}
60172 			if (has_writable && !is_writable) {
60173 				DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
60174 				                     "changed to non-writable, delete arguments binding"));
60175 
60176 				(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
60177 			}
60178 		}
60179 
60180 		/* 'varname' is in stack in this else branch, leaving an unbalanced stack below,
60181 		 * but this doesn't matter now.
60182 		 */
60183 	}
60184 
60185  success_no_exotics:
60186 	/* Some code paths use NORZ macros for simplicity, ensure refzero
60187 	 * handling is completed.
60188 	 */
60189 	DUK_REFZERO_CHECK_SLOW(thr);
60190 	return 1;
60191 
60192  fail_not_extensible:
60193 	if (throw_flag) {
60194 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE);
60195 		DUK_WO_NORETURN(return 0;);
60196 	}
60197 	return 0;
60198 
60199  fail_virtual:  /* just use the same "not configurable" error message" */
60200  fail_not_configurable:
60201 	if (throw_flag) {
60202 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
60203 		DUK_WO_NORETURN(return 0;);
60204 	}
60205 	return 0;
60206 }
60207 
60208 /*
60209  *  Object.prototype.hasOwnProperty() and Object.prototype.propertyIsEnumerable().
60210  */
60211 
60212 DUK_INTERNAL duk_bool_t duk_hobject_object_ownprop_helper(duk_hthread *thr, duk_small_uint_t required_desc_flags) {
60213 	duk_hstring *h_v;
60214 	duk_hobject *h_obj;
60215 	duk_propdesc desc;
60216 	duk_bool_t ret;
60217 
60218 	/* coercion order matters */
60219 	h_v = duk_to_hstring_acceptsymbol(thr, 0);
60220 	DUK_ASSERT(h_v != NULL);
60221 
60222 	h_obj = duk_push_this_coercible_to_object(thr);
60223 	DUK_ASSERT(h_obj != NULL);
60224 
60225 	ret = duk_hobject_get_own_propdesc(thr, h_obj, h_v, &desc, 0 /*flags*/);  /* don't push value */
60226 
60227 	duk_push_boolean(thr, ret && ((desc.flags & required_desc_flags) == required_desc_flags));
60228 	return 1;
60229 }
60230 
60231 /*
60232  *  Object.seal() and Object.freeze()  (E5 Sections 15.2.3.8 and 15.2.3.9)
60233  *
60234  *  Since the algorithms are similar, a helper provides both functions.
60235  *  Freezing is essentially sealing + making plain properties non-writable.
60236  *
60237  *  Note: virtual (non-concrete) properties which are non-configurable but
60238  *  writable would pose some problems, but such properties do not currently
60239  *  exist (all virtual properties are non-configurable and non-writable).
60240  *  If they did exist, the non-configurability does NOT prevent them from
60241  *  becoming non-writable.  However, this change should be recorded somehow
60242  *  so that it would turn up (e.g. when getting the property descriptor),
60243  *  requiring some additional flags in the object.
60244  */
60245 
60246 DUK_INTERNAL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze) {
60247 	duk_uint_fast32_t i;
60248 
60249 	DUK_ASSERT(thr != NULL);
60250 	DUK_ASSERT(thr->heap != NULL);
60251 	DUK_ASSERT(obj != NULL);
60252 
60253 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
60254 
60255 #if defined(DUK_USE_ROM_OBJECTS)
60256 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
60257 		DUK_DD(DUK_DDPRINT("attempt to seal/freeze a readonly object, reject"));
60258 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
60259 		DUK_WO_NORETURN(return;);
60260 	}
60261 #endif
60262 
60263 	/*
60264 	 *  Abandon array part because all properties must become non-configurable.
60265 	 *  Note that this is now done regardless of whether this is always the case
60266 	 *  (skips check, but performance problem if caller would do this many times
60267 	 *  for the same object; not likely).
60268 	 */
60269 
60270 	duk__abandon_array_checked(thr, obj);
60271 	DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) == 0);
60272 
60273 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
60274 		duk_uint8_t *fp;
60275 
60276 		/* since duk__abandon_array_checked() causes a resize, there should be no gaps in keys */
60277 		DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != NULL);
60278 
60279 		/* avoid multiple computations of flags address; bypasses macros */
60280 		fp = DUK_HOBJECT_E_GET_FLAGS_PTR(thr->heap, obj, i);
60281 		if (is_freeze && !((*fp) & DUK_PROPDESC_FLAG_ACCESSOR)) {
60282 			*fp &= ~(DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE);
60283 		} else {
60284 			*fp &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
60285 		}
60286 	}
60287 
60288 	DUK_HOBJECT_CLEAR_EXTENSIBLE(obj);
60289 
60290 	/* no need to compact since we already did that in duk__abandon_array_checked()
60291 	 * (regardless of whether an array part existed or not.
60292 	 */
60293 
60294 	return;
60295 }
60296 
60297 /*
60298  *  Object.isSealed() and Object.isFrozen()  (E5 Sections 15.2.3.11, 15.2.3.13)
60299  *
60300  *  Since the algorithms are similar, a helper provides both functions.
60301  *  Freezing is essentially sealing + making plain properties non-writable.
60302  *
60303  *  Note: all virtual (non-concrete) properties are currently non-configurable
60304  *  and non-writable (and there are no accessor virtual properties), so they don't
60305  *  need to be considered here now.
60306  */
60307 
60308 DUK_INTERNAL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen) {
60309 	duk_uint_fast32_t i;
60310 
60311 	DUK_ASSERT(obj != NULL);
60312 	DUK_UNREF(thr);
60313 
60314 	/* Note: no allocation pressure, no need to check refcounts etc */
60315 
60316 	/* must not be extensible */
60317 	if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
60318 		return 0;
60319 	}
60320 
60321 	/* all virtual properties are non-configurable and non-writable */
60322 
60323 	/* entry part must not contain any configurable properties, or
60324 	 * writable properties (if is_frozen).
60325 	 */
60326 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
60327 		duk_small_uint_t flags;
60328 
60329 		if (!DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i)) {
60330 			continue;
60331 		}
60332 
60333 		/* avoid multiple computations of flags address; bypasses macros */
60334 		flags = (duk_small_uint_t) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
60335 
60336 		if (flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
60337 			return 0;
60338 		}
60339 		if (is_frozen &&
60340 		    !(flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
60341 		    (flags & DUK_PROPDESC_FLAG_WRITABLE)) {
60342 			return 0;
60343 		}
60344 	}
60345 
60346 	/* array part must not contain any non-unused properties, as they would
60347 	 * be configurable and writable.
60348 	 */
60349 	for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
60350 		duk_tval *tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
60351 		if (!DUK_TVAL_IS_UNUSED(tv)) {
60352 			return 0;
60353 		}
60354 	}
60355 
60356 	return 1;
60357 }
60358 
60359 /*
60360  *  Object.preventExtensions() and Object.isExtensible()  (E5 Sections 15.2.3.10, 15.2.3.13)
60361  *
60362  *  Not needed, implemented by macros DUK_HOBJECT_{HAS,CLEAR,SET}_EXTENSIBLE
60363  *  and the Object built-in bindings.
60364  */
60365 
60366 /* automatic undefs */
60367 #undef DUK__HASH_DELETED
60368 #undef DUK__HASH_UNUSED
60369 #undef DUK__NO_ARRAY_INDEX
60370 #undef DUK__VALSTACK_PROXY_LOOKUP
60371 #undef DUK__VALSTACK_SPACE
60372 #line 1 "duk_hstring_misc.c"
60373 /*
60374  *  Misc support functions
60375  */
60376 
60377 /* #include duk_internal.h -> already included */
60378 
60379 /*
60380  *  duk_hstring charCodeAt, with and without surrogate awareness
60381  */
60382 
60383 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) {
60384 	duk_uint32_t boff;
60385 	const duk_uint8_t *p, *p_start, *p_end;
60386 	duk_ucodepoint_t cp1;
60387 	duk_ucodepoint_t cp2;
60388 
60389 	/* Caller must check character offset to be inside the string. */
60390 	DUK_ASSERT(thr != NULL);
60391 	DUK_ASSERT(h != NULL);
60392 	DUK_ASSERT_DISABLE(pos >= 0);  /* unsigned */
60393 	DUK_ASSERT(pos < (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h));
60394 
60395 	boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint32_t) pos);
60396 	DUK_DDD(DUK_DDDPRINT("charCodeAt: pos=%ld -> boff=%ld, str=%!O",
60397 	                     (long) pos, (long) boff, (duk_heaphdr *) h));
60398 	DUK_ASSERT_DISABLE(boff >= 0);
60399 	DUK_ASSERT(boff < DUK_HSTRING_GET_BYTELEN(h));
60400 
60401 	p_start = DUK_HSTRING_GET_DATA(h);
60402 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
60403 	p = p_start + boff;
60404 	DUK_DDD(DUK_DDDPRINT("p_start=%p, p_end=%p, p=%p",
60405 	                     (const void *) p_start, (const void *) p_end,
60406 	                     (const void *) p));
60407 
60408 	/* For invalid UTF-8 (never happens for standard ECMAScript strings)
60409 	 * return U+FFFD replacement character.
60410 	 */
60411 	if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp1)) {
60412 		if (surrogate_aware && cp1 >= 0xd800UL && cp1 <= 0xdbffUL) {
60413 			/* The decode helper is memory safe even if 'cp1' was
60414 			 * decoded at the end of the string and 'p' is no longer
60415 			 * within string memory range.
60416 			 */
60417 			cp2 = 0;  /* If call fails, this is left untouched and won't match cp2 check. */
60418 			(void) duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp2);
60419 			if (cp2 >= 0xdc00UL && cp2 <= 0xdfffUL) {
60420 				cp1 = (duk_ucodepoint_t) (((cp1 - 0xd800UL) << 10) + (cp2 - 0xdc00UL) + 0x10000UL);
60421 			}
60422 		}
60423 	} else {
60424 		cp1 = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
60425 	}
60426 
60427 	return cp1;
60428 }
60429 
60430 /*
60431  *  duk_hstring charlen, when lazy charlen disabled
60432  */
60433 
60434 #if !defined(DUK_USE_HSTRING_LAZY_CLEN)
60435 #if !defined(DUK_USE_HSTRING_CLEN)
60436 #error non-lazy duk_hstring charlen but DUK_USE_HSTRING_CLEN not set
60437 #endif
60438 DUK_INTERNAL void duk_hstring_init_charlen(duk_hstring *h) {
60439 	duk_uint32_t clen;
60440 
60441 	DUK_ASSERT(h != NULL);
60442 	DUK_ASSERT(!DUK_HSTRING_HAS_ASCII(h));
60443 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));
60444 
60445 	clen = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
60446 #if defined(DUK_USE_STRLEN16)
60447 	DUK_ASSERT(clen <= 0xffffUL);  /* Bytelength checked during interning. */
60448 	h->clen16 = (duk_uint16_t) clen;
60449 #else
60450 	h->clen = (duk_uint32_t) clen;
60451 #endif
60452 	if (DUK_LIKELY(clen == DUK_HSTRING_GET_BYTELEN(h))) {
60453 		DUK_HSTRING_SET_ASCII(h);
60454 	}
60455 }
60456 
60457 DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
60458 #if defined(DUK_USE_STRLEN16)
60459 	return h->clen16;
60460 #else
60461 	return h->clen;
60462 #endif
60463 }
60464 #endif  /* !DUK_USE_HSTRING_LAZY_CLEN */
60465 
60466 /*
60467  *  duk_hstring charlen, when lazy charlen enabled
60468  */
60469 
60470 #if defined(DUK_USE_HSTRING_LAZY_CLEN)
60471 #if defined(DUK_USE_HSTRING_CLEN)
60472 DUK_LOCAL DUK_COLD duk_size_t duk__hstring_get_charlen_slowpath(duk_hstring *h) {
60473 	duk_size_t res;
60474 
60475 	DUK_ASSERT(h->clen == 0);  /* Checked by caller. */
60476 
60477 #if defined(DUK_USE_ROM_STRINGS)
60478 	/* ROM strings have precomputed clen, but if the computed clen is zero
60479 	 * we can still come here and can't write anything.
60480 	 */
60481 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) {
60482 		return 0;
60483 	}
60484 #endif
60485 
60486 	res = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
60487 #if defined(DUK_USE_STRLEN16)
60488 	DUK_ASSERT(res <= 0xffffUL);  /* Bytelength checked during interning. */
60489 	h->clen16 = (duk_uint16_t) res;
60490 #else
60491 	h->clen = (duk_uint32_t) res;
60492 #endif
60493 	if (DUK_LIKELY(res == DUK_HSTRING_GET_BYTELEN(h))) {
60494 		DUK_HSTRING_SET_ASCII(h);
60495 	}
60496 	return res;
60497 }
60498 #else  /* DUK_USE_HSTRING_CLEN */
60499 DUK_LOCAL duk_size_t duk__hstring_get_charlen_slowpath(duk_hstring *h) {
60500 	if (DUK_LIKELY(DUK_HSTRING_HAS_ASCII(h))) {
60501 		/* Most practical strings will go here. */
60502 		return DUK_HSTRING_GET_BYTELEN(h);
60503 	} else {
60504 		/* ASCII flag is lazy, so set it here. */
60505 		duk_size_t res;
60506 
60507 		/* XXX: here we could use the strcache to speed up the
60508 		 * computation (matters for 'i < str.length' loops).
60509 		 */
60510 
60511 		res = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
60512 
60513 #if defined(DUK_USE_ROM_STRINGS)
60514 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) {
60515 			/* For ROM strings, can't write anything; ASCII flag
60516 			 * is preset so we don't need to update it.
60517 			 */
60518 			return res;
60519 		}
60520 #endif
60521 		if (DUK_LIKELY(res == DUK_HSTRING_GET_BYTELEN(h))) {
60522 			DUK_HSTRING_SET_ASCII(h);
60523 		}
60524 		return res;
60525 	}
60526 }
60527 #endif  /* DUK_USE_HSTRING_CLEN */
60528 
60529 #if defined(DUK_USE_HSTRING_CLEN)
60530 DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
60531 #if defined(DUK_USE_STRLEN16)
60532 	if (DUK_LIKELY(h->clen16 != 0)) {
60533 		return h->clen16;
60534 	}
60535 #else
60536 	if (DUK_LIKELY(h->clen != 0)) {
60537 		return h->clen;
60538 	}
60539 #endif
60540 	return duk__hstring_get_charlen_slowpath(h);
60541 }
60542 #else  /* DUK_USE_HSTRING_CLEN */
60543 DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
60544 	/* Always use slow path. */
60545 	return duk__hstring_get_charlen_slowpath(h);
60546 }
60547 #endif  /* DUK_USE_HSTRING_CLEN */
60548 #endif  /* DUK_USE_HSTRING_LAZY_CLEN */
60549 
60550 /*
60551  *  Compare duk_hstring to an ASCII cstring.
60552  */
60553 
60554 DUK_INTERNAL duk_bool_t duk_hstring_equals_ascii_cstring(duk_hstring *h, const char *cstr) {
60555 	duk_size_t len;
60556 
60557 	DUK_ASSERT(h != NULL);
60558 	DUK_ASSERT(cstr != NULL);
60559 
60560 	len = DUK_STRLEN(cstr);
60561 	if (len != DUK_HSTRING_GET_BYTELEN(h)) {
60562 		return 0;
60563 	}
60564 	if (duk_memcmp((const void *) cstr, (const void *) DUK_HSTRING_GET_DATA(h), len) == 0) {
60565 		return 1;
60566 	}
60567 	return 0;
60568 }
60569 #line 1 "duk_hthread_alloc.c"
60570 /*
60571  *  duk_hthread allocation and freeing.
60572  */
60573 
60574 /* #include duk_internal.h -> already included */
60575 
60576 /*
60577  *  Allocate initial stacks for a thread.  Note that 'thr' must be reachable
60578  *  as a garbage collection may be triggered by the allocation attempts.
60579  *  Returns zero (without leaking memory) if init fails.
60580  */
60581 
60582 DUK_INTERNAL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr) {
60583 	duk_size_t alloc_size;
60584 	duk_size_t i;
60585 
60586 	DUK_ASSERT(heap != NULL);
60587 	DUK_ASSERT(thr != NULL);
60588 	DUK_ASSERT(thr->valstack == NULL);
60589 	DUK_ASSERT(thr->valstack_end == NULL);
60590 	DUK_ASSERT(thr->valstack_alloc_end == NULL);
60591 	DUK_ASSERT(thr->valstack_bottom == NULL);
60592 	DUK_ASSERT(thr->valstack_top == NULL);
60593 	DUK_ASSERT(thr->callstack_curr == NULL);
60594 
60595 	/* valstack */
60596 	DUK_ASSERT(DUK_VALSTACK_API_ENTRY_MINIMUM <= DUK_VALSTACK_INITIAL_SIZE);
60597 	alloc_size = sizeof(duk_tval) * DUK_VALSTACK_INITIAL_SIZE;
60598 	thr->valstack = (duk_tval *) DUK_ALLOC(heap, alloc_size);
60599 	if (!thr->valstack) {
60600 		goto fail;
60601 	}
60602 	duk_memzero(thr->valstack, alloc_size);
60603 	thr->valstack_end = thr->valstack + DUK_VALSTACK_API_ENTRY_MINIMUM;
60604 	thr->valstack_alloc_end = thr->valstack + DUK_VALSTACK_INITIAL_SIZE;
60605 	thr->valstack_bottom = thr->valstack;
60606 	thr->valstack_top = thr->valstack;
60607 
60608 	for (i = 0; i < DUK_VALSTACK_INITIAL_SIZE; i++) {
60609 		DUK_TVAL_SET_UNDEFINED(&thr->valstack[i]);
60610 	}
60611 
60612 	return 1;
60613 
60614  fail:
60615 	DUK_FREE(heap, thr->valstack);
60616 	DUK_ASSERT(thr->callstack_curr == NULL);
60617 
60618 	thr->valstack = NULL;
60619 	return 0;
60620 }
60621 
60622 /* For indirect allocs. */
60623 
60624 DUK_INTERNAL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud) {
60625 	duk_hthread *thr = (duk_hthread *) ud;
60626 	DUK_UNREF(heap);
60627 	return (void *) thr->valstack;
60628 }
60629 #line 1 "duk_hthread_builtins.c"
60630 /*
60631  *  Initialize built-in objects.  Current thread must have a valstack
60632  *  and initialization errors may longjmp, so a setjmp() catch point
60633  *  must exist.
60634  */
60635 
60636 /* #include duk_internal.h -> already included */
60637 
60638 /*
60639  *  Encoding constants, must match genbuiltins.py
60640  */
60641 
60642 #define DUK__PROP_FLAGS_BITS             3
60643 #define DUK__LENGTH_PROP_BITS            3
60644 #define DUK__NARGS_BITS                  3
60645 #define DUK__PROP_TYPE_BITS              3
60646 
60647 #define DUK__NARGS_VARARGS_MARKER        0x07
60648 
60649 #define DUK__PROP_TYPE_DOUBLE            0
60650 #define DUK__PROP_TYPE_STRING            1
60651 #define DUK__PROP_TYPE_STRIDX            2
60652 #define DUK__PROP_TYPE_BUILTIN           3
60653 #define DUK__PROP_TYPE_UNDEFINED         4
60654 #define DUK__PROP_TYPE_BOOLEAN_TRUE      5
60655 #define DUK__PROP_TYPE_BOOLEAN_FALSE     6
60656 #define DUK__PROP_TYPE_ACCESSOR          7
60657 
60658 /*
60659  *  Create built-in objects by parsing an init bitstream generated
60660  *  by genbuiltins.py.
60661  */
60662 
60663 #if defined(DUK_USE_ROM_OBJECTS)
60664 #if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
60665 DUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) {
60666 	duk_hobject *h_global;
60667 #if defined(DUK_USE_ROM_GLOBAL_CLONE)
60668 	duk_hobject *h_oldglobal;
60669 	duk_uint8_t *props;
60670 	duk_size_t alloc_size;
60671 #endif
60672 	duk_hobject *h_objenv;
60673 
60674 	/* XXX: refactor into internal helper, duk_clone_hobject() */
60675 
60676 #if defined(DUK_USE_ROM_GLOBAL_INHERIT)
60677 	/* Inherit from ROM-based global object: less RAM usage, less transparent. */
60678 	h_global = duk_push_object_helper(thr,
60679 	                                  DUK_HOBJECT_FLAG_EXTENSIBLE |
60680 	                                  DUK_HOBJECT_FLAG_FASTREFS |
60681 	                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),
60682 	                                  DUK_BIDX_GLOBAL);
60683 	DUK_ASSERT(h_global != NULL);
60684 #elif defined(DUK_USE_ROM_GLOBAL_CLONE)
60685 	/* Clone the properties of the ROM-based global object to create a
60686 	 * fully RAM-based global object.  Uses more memory than the inherit
60687 	 * model but more compliant.
60688 	 */
60689 	h_global = duk_push_object_helper(thr,
60690 	                                  DUK_HOBJECT_FLAG_EXTENSIBLE |
60691 	                                  DUK_HOBJECT_FLAG_FASTREFS |
60692 	                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),
60693 	                                  DUK_BIDX_OBJECT_PROTOTYPE);
60694 	DUK_ASSERT(h_global != NULL);
60695 	h_oldglobal = thr->builtins[DUK_BIDX_GLOBAL];
60696 	DUK_ASSERT(h_oldglobal != NULL);
60697 
60698 	/* Copy the property table verbatim; this handles attributes etc.
60699 	 * For ROM objects it's not necessary (or possible) to update
60700 	 * refcounts so leave them as is.
60701 	 */
60702 	alloc_size = DUK_HOBJECT_P_ALLOC_SIZE(h_oldglobal);
60703 	DUK_ASSERT(alloc_size > 0);
60704 	props = DUK_ALLOC_CHECKED(thr, alloc_size);
60705 	DUK_ASSERT(props != NULL);
60706 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal) != NULL);
60707 	duk_memcpy((void *) props, (const void *) DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal), alloc_size);
60708 
60709 	/* XXX: keep property attributes or tweak them here?
60710 	 * Properties will now be non-configurable even when they're
60711 	 * normally configurable for the global object.
60712 	 */
60713 
60714 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h_global) == NULL);
60715 	DUK_HOBJECT_SET_PROPS(thr->heap, h_global, props);
60716 	DUK_HOBJECT_SET_ESIZE(h_global, DUK_HOBJECT_GET_ESIZE(h_oldglobal));
60717 	DUK_HOBJECT_SET_ENEXT(h_global, DUK_HOBJECT_GET_ENEXT(h_oldglobal));
60718 	DUK_HOBJECT_SET_ASIZE(h_global, DUK_HOBJECT_GET_ASIZE(h_oldglobal));
60719 	DUK_HOBJECT_SET_HSIZE(h_global, DUK_HOBJECT_GET_HSIZE(h_oldglobal));
60720 #else
60721 #error internal error in config defines
60722 #endif
60723 
60724 	duk_hobject_compact_props(thr, h_global);
60725 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
60726 	DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL]));  /* no need to decref: ROM object */
60727 	thr->builtins[DUK_BIDX_GLOBAL] = h_global;
60728 	DUK_HOBJECT_INCREF(thr, h_global);
60729 	DUK_D(DUK_DPRINT("duplicated global object: %!O", h_global));
60730 
60731 	/* Create a fresh object environment for the global scope.  This is
60732 	 * needed so that the global scope points to the newly created RAM-based
60733 	 * global object.
60734 	 */
60735 	h_objenv = (duk_hobject *) duk_hobjenv_alloc(thr,
60736 	                                             DUK_HOBJECT_FLAG_EXTENSIBLE |
60737 	                                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
60738 	DUK_ASSERT(h_objenv != NULL);
60739 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_objenv) == NULL);
60740 	duk_push_hobject(thr, h_objenv);
60741 
60742 	DUK_ASSERT(h_global != NULL);
60743 	((duk_hobjenv *) h_objenv)->target = h_global;
60744 	DUK_HOBJECT_INCREF(thr, h_global);
60745 	DUK_ASSERT(((duk_hobjenv *) h_objenv)->has_this == 0);
60746 
60747 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL);
60748 	DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL_ENV]));  /* no need to decref: ROM object */
60749 	thr->builtins[DUK_BIDX_GLOBAL_ENV] = h_objenv;
60750 	DUK_HOBJECT_INCREF(thr, h_objenv);
60751 	DUK_D(DUK_DPRINT("duplicated global env: %!O", h_objenv));
60752 
60753 	DUK_ASSERT_HOBJENV_VALID((duk_hobjenv *) h_objenv);
60754 
60755 	duk_pop_2(thr);  /* Pop global object and global env. */
60756 }
60757 #endif  /* DUK_USE_ROM_GLOBAL_CLONE || DUK_USE_ROM_GLOBAL_INHERIT */
60758 
60759 DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
60760 	/* Setup builtins from ROM objects.  All heaps/threads will share
60761 	 * the same readonly objects.
60762 	 */
60763 	duk_small_uint_t i;
60764 
60765 	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
60766 		duk_hobject *h;
60767 		h = (duk_hobject *) DUK_LOSE_CONST(duk_rom_builtins_bidx[i]);
60768 		DUK_ASSERT(h != NULL);
60769 		thr->builtins[i] = h;
60770 	}
60771 
60772 #if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
60773 	/* By default the global object is read-only which is often much
60774 	 * more of an issue than having read-only built-in objects (like
60775 	 * RegExp, Date, etc).  Use a RAM-based copy of the global object
60776 	 * and the global environment object for convenience.
60777 	 */
60778 	duk__duplicate_ram_global_object(thr);
60779 #endif
60780 }
60781 #else  /* DUK_USE_ROM_OBJECTS */
60782 DUK_LOCAL void duk__push_stridx(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
60783 	duk_small_uint_t n;
60784 
60785 	n = (duk_small_uint_t) duk_bd_decode_varuint(bd);
60786 	DUK_ASSERT_DISABLE(n >= 0);  /* unsigned */
60787 	DUK_ASSERT(n < DUK_HEAP_NUM_STRINGS);
60788 	duk_push_hstring_stridx(thr, n);
60789 }
60790 DUK_LOCAL void duk__push_string(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
60791 	/* XXX: built-ins data could provide a maximum length that is
60792 	 * actually needed; bitpacked max length is now 256 bytes.
60793 	 */
60794 	duk_uint8_t tmp[DUK_BD_BITPACKED_STRING_MAXLEN];
60795 	duk_small_uint_t len;
60796 
60797 	len = duk_bd_decode_bitpacked_string(bd, tmp);
60798 	duk_push_lstring(thr, (const char *) tmp, (duk_size_t) len);
60799 }
60800 DUK_LOCAL void duk__push_stridx_or_string(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
60801 	duk_small_uint_t n;
60802 
60803 	n = (duk_small_uint_t) duk_bd_decode_varuint(bd);
60804 	if (n == 0) {
60805 		duk__push_string(thr, bd);
60806 	} else {
60807 		n--;
60808 		DUK_ASSERT(n < DUK_HEAP_NUM_STRINGS);
60809 		duk_push_hstring_stridx(thr, n);
60810 	}
60811 }
60812 DUK_LOCAL void duk__push_double(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
60813 	duk_double_union du;
60814 	duk_small_uint_t i;
60815 
60816 	for (i = 0; i < 8; i++) {
60817 		/* Encoding endianness must match target memory layout,
60818 		 * build scripts and genbuiltins.py must ensure this.
60819 		 */
60820 		du.uc[i] = (duk_uint8_t) duk_bd_decode(bd, 8);
60821 	}
60822 
60823 	duk_push_number(thr, du.d);  /* push operation normalizes NaNs */
60824 }
60825 
60826 DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
60827 	duk_bitdecoder_ctx bd_ctx;
60828 	duk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */
60829 	duk_hobject *h;
60830 	duk_small_uint_t i, j;
60831 
60832 	DUK_D(DUK_DPRINT("INITBUILTINS BEGIN: DUK_NUM_BUILTINS=%d, DUK_NUM_BUILTINS_ALL=%d", (int) DUK_NUM_BUILTINS, (int) DUK_NUM_ALL_BUILTINS));
60833 
60834 	duk_memzero(&bd_ctx, sizeof(bd_ctx));
60835 	bd->data = (const duk_uint8_t *) duk_builtins_data;
60836 	bd->length = (duk_size_t) DUK_BUILTINS_DATA_LENGTH;
60837 
60838 	/*
60839 	 *  First create all built-in bare objects on the empty valstack.
60840 	 *
60841 	 *  Built-ins in the index range [0,DUK_NUM_BUILTINS-1] have value
60842 	 *  stack indices matching their eventual thr->builtins[] index.
60843 	 *
60844 	 *  Built-ins in the index range [DUK_NUM_BUILTINS,DUK_NUM_ALL_BUILTINS]
60845 	 *  will exist on the value stack during init but won't be placed
60846 	 *  into thr->builtins[].  These are objects referenced in some way
60847 	 *  from thr->builtins[] roots but which don't need to be indexed by
60848 	 *  Duktape through thr->builtins[] (e.g. user custom objects).
60849 	 *
60850 	 *  Internal prototypes will be incorrect (NULL) at this stage.
60851 	 */
60852 
60853 	duk_require_stack(thr, DUK_NUM_ALL_BUILTINS);
60854 
60855 	DUK_DD(DUK_DDPRINT("create empty built-ins"));
60856 	DUK_ASSERT_TOP(thr, 0);
60857 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
60858 		duk_small_uint_t class_num;
60859 		duk_small_int_t len = -1;  /* must be signed */
60860 
60861 		class_num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
60862 		len = (duk_small_int_t) duk_bd_decode_flagged_signed(bd, DUK__LENGTH_PROP_BITS, (duk_int32_t) -1 /*def_value*/);
60863 
60864 		if (class_num == DUK_HOBJECT_CLASS_FUNCTION) {
60865 			duk_small_uint_t natidx;
60866 			duk_small_int_t c_nargs;  /* must hold DUK_VARARGS */
60867 			duk_c_function c_func;
60868 			duk_int16_t magic;
60869 
60870 			DUK_DDD(DUK_DDDPRINT("len=%ld", (long) len));
60871 			DUK_ASSERT(len >= 0);
60872 
60873 			natidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);
60874 			DUK_ASSERT(natidx != 0);
60875 			c_func = duk_bi_native_functions[natidx];
60876 			DUK_ASSERT(c_func != NULL);
60877 
60878 			c_nargs = (duk_small_int_t) duk_bd_decode_flagged_signed(bd, DUK__NARGS_BITS, len /*def_value*/);
60879 			if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
60880 				c_nargs = DUK_VARARGS;
60881 			}
60882 
60883 			/* XXX: set magic directly here? (it could share the c_nargs arg) */
60884 			(void) duk_push_c_function_builtin(thr, c_func, c_nargs);
60885 			h = duk_known_hobject(thr, -1);
60886 
60887 			/* Currently all built-in native functions are strict.
60888 			 * duk_push_c_function() now sets strict flag, so
60889 			 * assert for it.
60890 			 */
60891 			DUK_ASSERT(DUK_HOBJECT_HAS_STRICT(h));
60892 
60893 			/* XXX: function properties */
60894 
60895 			duk__push_stridx_or_string(thr, bd);
60896 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
60897 			duk_xdef_prop_stridx_short(thr,
60898 			                           -2,
60899 			                           DUK_STRIDX_NAME,
60900 			                           DUK_PROPDESC_FLAGS_C);
60901 #else
60902 			duk_pop(thr);  /* Not very ideal but good enough for now. */
60903 #endif
60904 
60905 			/* Almost all global level Function objects are constructable
60906 			 * but not all: Function.prototype is a non-constructable,
60907 			 * callable Function.
60908 			 */
60909 			if (duk_bd_decode_flag(bd)) {
60910 				DUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE(h));
60911 			} else {
60912 				DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h);
60913 			}
60914 
60915 			/* Cast converts magic to 16-bit signed value */
60916 			magic = (duk_int16_t) duk_bd_decode_varuint(bd);
60917 			((duk_hnatfunc *) h)->magic = magic;
60918 		} else if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
60919 			duk_push_array(thr);
60920 		} else if (class_num == DUK_HOBJECT_CLASS_OBJENV) {
60921 			duk_hobjenv *env;
60922 			duk_hobject *global;
60923 
60924 			DUK_ASSERT(i == DUK_BIDX_GLOBAL_ENV);
60925 			DUK_ASSERT(DUK_BIDX_GLOBAL_ENV > DUK_BIDX_GLOBAL);
60926 
60927 			env = duk_hobjenv_alloc(thr,
60928 	                                        DUK_HOBJECT_FLAG_EXTENSIBLE |
60929 	                                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
60930 			DUK_ASSERT(env->target == NULL);
60931 			duk_push_hobject(thr, (duk_hobject *) env);
60932 
60933 			global = duk_known_hobject(thr, DUK_BIDX_GLOBAL);
60934 			DUK_ASSERT(global != NULL);
60935 			env->target = global;
60936 			DUK_HOBJECT_INCREF(thr, global);
60937 			DUK_ASSERT(env->has_this == 0);
60938 
60939 			DUK_ASSERT_HOBJENV_VALID(env);
60940 		} else {
60941 			DUK_ASSERT(class_num != DUK_HOBJECT_CLASS_DECENV);
60942 
60943 			(void) duk_push_object_helper(thr,
60944 			                              DUK_HOBJECT_FLAG_FASTREFS |
60945 			                              DUK_HOBJECT_FLAG_EXTENSIBLE,
60946 			                              -1);  /* no prototype or class yet */
60947 
60948 		}
60949 
60950 		h = duk_known_hobject(thr, -1);
60951 		DUK_HOBJECT_SET_CLASS_NUMBER(h, class_num);
60952 
60953 		if (i < DUK_NUM_BUILTINS) {
60954 			thr->builtins[i] = h;
60955 			DUK_HOBJECT_INCREF(thr, &h->hdr);
60956 		}
60957 
60958 		if (len >= 0) {
60959 			/* In ES2015+ built-in function object .length property
60960 			 * has property attributes C (configurable only):
60961 			 * http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-standard-built-in-objects
60962 			 *
60963 			 * Array.prototype remains an Array instance in ES2015+
60964 			 * and its length has attributes W (writable only).
60965 			 * Because .length is now virtual for duk_harray, it is
60966 			 * not encoded explicitly in init data.
60967 			 */
60968 
60969 			DUK_ASSERT(class_num != DUK_HOBJECT_CLASS_ARRAY);  /* .length is virtual */
60970 			duk_push_int(thr, len);
60971 			duk_xdef_prop_stridx_short(thr,
60972 			                           -2,
60973 			                           DUK_STRIDX_LENGTH,
60974 			                           DUK_PROPDESC_FLAGS_C);
60975 		}
60976 
60977 		/* enable exotic behaviors last */
60978 
60979 		if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
60980 			DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h));  /* set by duk_push_array() */
60981 		}
60982 		if (class_num == DUK_HOBJECT_CLASS_STRING) {
60983 			DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h);
60984 		}
60985 
60986 		/* some assertions */
60987 
60988 		DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h));
60989 		/* DUK_HOBJECT_FLAG_CONSTRUCTABLE varies */
60990 		DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(h));
60991 		DUK_ASSERT(!DUK_HOBJECT_HAS_COMPFUNC(h));
60992 		/* DUK_HOBJECT_FLAG_NATFUNC varies */
60993 		DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(h));
60994 		DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(h) || class_num == DUK_HOBJECT_CLASS_ARRAY);
60995 		/* DUK_HOBJECT_FLAG_STRICT varies */
60996 		DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(h) ||  /* all native functions have NEWENV */
60997 		           DUK_HOBJECT_HAS_NEWENV(h));
60998 		DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(h));
60999 		DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(h));
61000 		/* DUK_HOBJECT_FLAG_EXOTIC_ARRAY varies */
61001 		/* DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ varies */
61002 		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h));
61003 
61004 		DUK_DDD(DUK_DDDPRINT("created built-in %ld, class=%ld, length=%ld", (long) i, (long) class_num, (long) len));
61005 	}
61006 
61007 	/*
61008 	 *  Then decode the builtins init data (see genbuiltins.py) to
61009 	 *  init objects.  Internal prototypes are set at this stage,
61010 	 *  with thr->builtins[] populated.
61011 	 */
61012 
61013 	DUK_DD(DUK_DDPRINT("initialize built-in object properties"));
61014 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
61015 		duk_small_uint_t t;
61016 		duk_small_uint_t num;
61017 
61018 		DUK_DDD(DUK_DDDPRINT("initializing built-in object at index %ld", (long) i));
61019 		h = duk_known_hobject(thr, (duk_idx_t) i);
61020 
61021 		t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61022 		if (t > 0) {
61023 			t--;
61024 			DUK_DDD(DUK_DDDPRINT("set internal prototype: built-in %ld", (long) t));
61025 			DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, duk_known_hobject(thr, (duk_idx_t) t));
61026 		} else if (DUK_HOBJECT_IS_NATFUNC(h)) {
61027 			/* Standard native built-ins cannot inherit from
61028 			 * %NativeFunctionPrototype%, they are required to
61029 			 * inherit from Function.prototype directly.
61030 			 */
61031 			DUK_ASSERT(thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE] != NULL);
61032 			DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
61033 		}
61034 
61035 		t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61036 		if (t > 0) {
61037 			/* 'prototype' property for all built-in objects (which have it) has attributes:
61038 			 *  [[Writable]] = false,
61039 			 *  [[Enumerable]] = false,
61040 			 *  [[Configurable]] = false
61041 			 */
61042 			t--;
61043 			DUK_DDD(DUK_DDDPRINT("set external prototype: built-in %ld", (long) t));
61044 			duk_dup(thr, (duk_idx_t) t);
61045 			duk_xdef_prop_stridx(thr, (duk_idx_t) i, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_NONE);
61046 		}
61047 
61048 		t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61049 		if (t > 0) {
61050 			/* 'constructor' property for all built-in objects (which have it) has attributes:
61051 			 *  [[Writable]] = true,
61052 			 *  [[Enumerable]] = false,
61053 			 *  [[Configurable]] = true
61054 			 */
61055 			t--;
61056 			DUK_DDD(DUK_DDDPRINT("set external constructor: built-in %ld", (long) t));
61057 			duk_dup(thr, (duk_idx_t) t);
61058 			duk_xdef_prop_stridx(thr, (duk_idx_t) i, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);
61059 		}
61060 
61061 		/* normal valued properties */
61062 		num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61063 		DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld normal valued properties", (long) i, (long) num));
61064 		for (j = 0; j < num; j++) {
61065 			duk_small_uint_t defprop_flags;
61066 
61067 			duk__push_stridx_or_string(thr, bd);
61068 
61069 			/*
61070 			 *  Property attribute defaults are defined in E5 Section 15 (first
61071 			 *  few pages); there is a default for all properties and a special
61072 			 *  default for 'length' properties.  Variation from the defaults is
61073 			 *  signaled using a single flag bit in the bitstream.
61074 			 */
61075 
61076 			defprop_flags = (duk_small_uint_t) duk_bd_decode_flagged(bd,
61077 			                                                         DUK__PROP_FLAGS_BITS,
61078 			                                                         (duk_uint32_t) DUK_PROPDESC_FLAGS_WC);
61079 			defprop_flags |= DUK_DEFPROP_FORCE |
61080 			                 DUK_DEFPROP_HAVE_VALUE |
61081 			                 DUK_DEFPROP_HAVE_WRITABLE |
61082 			                 DUK_DEFPROP_HAVE_ENUMERABLE |
61083 			                 DUK_DEFPROP_HAVE_CONFIGURABLE;  /* Defaults for data properties. */
61084 
61085 			/* The writable, enumerable, configurable flags in prop_flags
61086 			 * match both duk_def_prop() and internal property flags.
61087 			 */
61088 			DUK_ASSERT(DUK_PROPDESC_FLAG_WRITABLE == DUK_DEFPROP_WRITABLE);
61089 			DUK_ASSERT(DUK_PROPDESC_FLAG_ENUMERABLE == DUK_DEFPROP_ENUMERABLE);
61090 			DUK_ASSERT(DUK_PROPDESC_FLAG_CONFIGURABLE == DUK_DEFPROP_CONFIGURABLE);
61091 
61092 			t = (duk_small_uint_t) duk_bd_decode(bd, DUK__PROP_TYPE_BITS);
61093 
61094 			DUK_DDD(DUK_DDDPRINT("built-in %ld, normal-valued property %ld, key %!T, flags 0x%02lx, type %ld",
61095 			                     (long) i, (long) j, duk_get_tval(thr, -1), (unsigned long) defprop_flags, (long) t));
61096 
61097 			switch (t) {
61098 			case DUK__PROP_TYPE_DOUBLE: {
61099 				duk__push_double(thr, bd);
61100 				break;
61101 			}
61102 			case DUK__PROP_TYPE_STRING: {
61103 				duk__push_string(thr, bd);
61104 				break;
61105 			}
61106 			case DUK__PROP_TYPE_STRIDX: {
61107 				duk__push_stridx(thr, bd);
61108 				break;
61109 			}
61110 			case DUK__PROP_TYPE_BUILTIN: {
61111 				duk_small_uint_t bidx;
61112 
61113 				bidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61114 				duk_dup(thr, (duk_idx_t) bidx);
61115 				break;
61116 			}
61117 			case DUK__PROP_TYPE_UNDEFINED: {
61118 				duk_push_undefined(thr);
61119 				break;
61120 			}
61121 			case DUK__PROP_TYPE_BOOLEAN_TRUE: {
61122 				duk_push_true(thr);
61123 				break;
61124 			}
61125 			case DUK__PROP_TYPE_BOOLEAN_FALSE: {
61126 				duk_push_false(thr);
61127 				break;
61128 			}
61129 			case DUK__PROP_TYPE_ACCESSOR: {
61130 				duk_small_uint_t natidx_getter = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61131 				duk_small_uint_t natidx_setter = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61132 				duk_small_uint_t accessor_magic = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61133 				duk_c_function c_func_getter;
61134 				duk_c_function c_func_setter;
61135 
61136 				DUK_DDD(DUK_DDDPRINT("built-in accessor property: objidx=%ld, key=%!T, getteridx=%ld, setteridx=%ld, flags=0x%04lx",
61137 				                     (long) i, duk_get_tval(thr, -1), (long) natidx_getter, (long) natidx_setter, (unsigned long) defprop_flags));
61138 
61139 				c_func_getter = duk_bi_native_functions[natidx_getter];
61140 				if (c_func_getter != NULL) {
61141 					duk_push_c_function_builtin_noconstruct(thr, c_func_getter, 0);  /* always 0 args */
61142 					duk_set_magic(thr, -1, (duk_int_t) accessor_magic);
61143 					defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
61144 				}
61145 				c_func_setter = duk_bi_native_functions[natidx_setter];
61146 				if (c_func_setter != NULL) {
61147 					duk_push_c_function_builtin_noconstruct(thr, c_func_setter, 1);  /* always 1 arg */
61148 					duk_set_magic(thr, -1, (duk_int_t) accessor_magic);
61149 					defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
61150 				}
61151 
61152 				/* Writable flag doesn't make sense for an accessor. */
61153 				DUK_ASSERT((defprop_flags & DUK_PROPDESC_FLAG_WRITABLE) == 0);  /* genbuiltins.py ensures */
61154 
61155 				defprop_flags &= ~(DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);
61156 				defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_HAVE_CONFIGURABLE;
61157 				break;
61158 			}
61159 			default: {
61160 				/* exhaustive */
61161 				DUK_UNREACHABLE();
61162 			}
61163 			}
61164 
61165 			duk_def_prop(thr, (duk_idx_t) i, defprop_flags);
61166 			DUK_ASSERT_TOP(thr, DUK_NUM_ALL_BUILTINS);
61167 		}
61168 
61169 		/* native function properties */
61170 		num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61171 		DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld function valued properties", (long) i, (long) num));
61172 		for (j = 0; j < num; j++) {
61173 			duk_hstring *h_key;
61174 			duk_small_uint_t natidx;
61175 			duk_int_t c_nargs;  /* must hold DUK_VARARGS */
61176 			duk_small_uint_t c_length;
61177 			duk_int16_t magic;
61178 			duk_c_function c_func;
61179 			duk_hnatfunc *h_func;
61180 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
61181 			duk_small_int_t lightfunc_eligible;
61182 #endif
61183 			duk_small_uint_t defprop_flags;
61184 
61185 			duk__push_stridx_or_string(thr, bd);
61186 			h_key = duk_known_hstring(thr, -1);
61187 			DUK_UNREF(h_key);
61188 			natidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61189 
61190 			c_length = (duk_small_uint_t) duk_bd_decode(bd, DUK__LENGTH_PROP_BITS);
61191 			c_nargs = (duk_int_t) duk_bd_decode_flagged(bd, DUK__NARGS_BITS, (duk_uint32_t) c_length /*def_value*/);
61192 			if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
61193 				c_nargs = DUK_VARARGS;
61194 			}
61195 
61196 			c_func = duk_bi_native_functions[natidx];
61197 
61198 			DUK_DDD(DUK_DDDPRINT("built-in %ld, function-valued property %ld, key %!O, natidx %ld, length %ld, nargs %ld",
61199 			                     (long) i, (long) j, (duk_heaphdr *) h_key, (long) natidx, (long) c_length,
61200 			                     (c_nargs == DUK_VARARGS ? (long) -1 : (long) c_nargs)));
61201 
61202 			/* Cast converts magic to 16-bit signed value */
61203 			magic = (duk_int16_t) duk_bd_decode_varuint(bd);
61204 
61205 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
61206 			lightfunc_eligible =
61207 				((c_nargs >= DUK_LFUNC_NARGS_MIN && c_nargs <= DUK_LFUNC_NARGS_MAX) || (c_nargs == DUK_VARARGS)) &&
61208 				(c_length <= DUK_LFUNC_LENGTH_MAX) &&
61209 				(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX);
61210 
61211 			/* These functions have trouble working as lightfuncs.
61212 			 * Some of them have specific asserts and some may have
61213 		         * additional properties (e.g. 'require.id' may be written).
61214 			 */
61215 			if (c_func == duk_bi_global_object_eval) {
61216 				lightfunc_eligible = 0;
61217 			}
61218 #if defined(DUK_USE_COROUTINE_SUPPORT)
61219 			if (c_func == duk_bi_thread_yield ||
61220 			    c_func == duk_bi_thread_resume) {
61221 				lightfunc_eligible = 0;
61222 			}
61223 #endif
61224 			if (c_func == duk_bi_function_prototype_call ||
61225 			    c_func == duk_bi_function_prototype_apply ||
61226 			    c_func == duk_bi_reflect_apply ||
61227 			    c_func == duk_bi_reflect_construct) {
61228 				lightfunc_eligible = 0;
61229 			}
61230 
61231 			if (lightfunc_eligible) {
61232 				duk_tval tv_lfunc;
61233 				duk_small_uint_t lf_nargs = (duk_small_uint_t) (c_nargs == DUK_VARARGS ? DUK_LFUNC_NARGS_VARARGS : c_nargs);
61234 				duk_small_uint_t lf_flags = DUK_LFUNC_FLAGS_PACK(magic, c_length, lf_nargs);
61235 				DUK_TVAL_SET_LIGHTFUNC(&tv_lfunc, c_func, lf_flags);
61236 				duk_push_tval(thr, &tv_lfunc);
61237 				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)));
61238 				goto lightfunc_skip;
61239 			}
61240 
61241 			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));
61242 #endif  /* DUK_USE_LIGHTFUNC_BUILTINS */
61243 
61244 			/* [ (builtin objects) name ] */
61245 
61246 			duk_push_c_function_builtin_noconstruct(thr, c_func, c_nargs);
61247 			h_func = duk_known_hnatfunc(thr, -1);
61248 			DUK_UNREF(h_func);
61249 
61250 			/* XXX: add into init data? */
61251 
61252 			/* Special call handling, not described in init data. */
61253 			if (c_func == duk_bi_global_object_eval ||
61254 			    c_func == duk_bi_function_prototype_call ||
61255 			    c_func == duk_bi_function_prototype_apply ||
61256 			    c_func == duk_bi_reflect_apply ||
61257 			    c_func == duk_bi_reflect_construct) {
61258 				DUK_HOBJECT_SET_SPECIAL_CALL((duk_hobject *) h_func);
61259 			}
61260 
61261 			/* Currently all built-in native functions are strict.
61262 			 * This doesn't matter for many functions, but e.g.
61263 			 * String.prototype.charAt (and other string functions)
61264 			 * rely on being strict so that their 'this' binding is
61265 			 * not automatically coerced.
61266 			 */
61267 			DUK_HOBJECT_SET_STRICT((duk_hobject *) h_func);
61268 
61269 			/* No built-in functions are constructable except the top
61270 			 * level ones (Number, etc).
61271 			 */
61272 			DUK_ASSERT(!DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_func));
61273 
61274 			/* XXX: any way to avoid decoding magic bit; there are quite
61275 			 * many function properties and relatively few with magic values.
61276 			 */
61277 			h_func->magic = magic;
61278 
61279 			/* [ (builtin objects) name func ] */
61280 
61281 			duk_push_uint(thr, c_length);
61282 			duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
61283 
61284 			duk_dup_m2(thr);
61285 			duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
61286 
61287 			/* XXX: other properties of function instances; 'arguments', 'caller'. */
61288 
61289 			DUK_DD(DUK_DDPRINT("built-in object %ld, function property %ld -> %!T",
61290 			                   (long) i, (long) j, (duk_tval *) duk_get_tval(thr, -1)));
61291 
61292 			/* [ (builtin objects) name func ] */
61293 
61294 			/*
61295 			 *  The default property attributes are correct for all
61296 			 *  function valued properties of built-in objects now.
61297 			 */
61298 
61299 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
61300 		 lightfunc_skip:
61301 #endif
61302 
61303 			defprop_flags = (duk_small_uint_t) duk_bd_decode_flagged(bd,
61304 			                                                         DUK__PROP_FLAGS_BITS,
61305 			                                                         (duk_uint32_t) DUK_PROPDESC_FLAGS_WC);
61306 			defprop_flags |= DUK_DEFPROP_FORCE |
61307 			                 DUK_DEFPROP_HAVE_VALUE |
61308 			                 DUK_DEFPROP_HAVE_WRITABLE |
61309 			                 DUK_DEFPROP_HAVE_ENUMERABLE |
61310 			                 DUK_DEFPROP_HAVE_CONFIGURABLE;
61311 			DUK_ASSERT(DUK_PROPDESC_FLAG_WRITABLE == DUK_DEFPROP_WRITABLE);
61312 			DUK_ASSERT(DUK_PROPDESC_FLAG_ENUMERABLE == DUK_DEFPROP_ENUMERABLE);
61313 			DUK_ASSERT(DUK_PROPDESC_FLAG_CONFIGURABLE == DUK_DEFPROP_CONFIGURABLE);
61314 
61315 			duk_def_prop(thr, (duk_idx_t) i, defprop_flags);
61316 
61317 			/* [ (builtin objects) ] */
61318 		}
61319 	}
61320 
61321 	/*
61322 	 *  Special post-tweaks, for cases not covered by the init data format.
61323 	 *
61324 	 *  - Set Date.prototype.toGMTString to Date.prototype.toUTCString.
61325 	 *    toGMTString is required to have the same Function object as
61326 	 *    toUTCString in E5 Section B.2.6.  Note that while Smjs respects
61327 	 *    this, V8 does not (the Function objects are distinct).
61328 	 *
61329 	 *  - Make DoubleError non-extensible.
61330 	 *
61331 	 *  - Add info about most important effective compile options to Duktape.
61332 	 *
61333 	 *  - Possibly remove some properties (values or methods) which are not
61334 	 *    desirable with current feature options but are not currently
61335 	 *    conditional in init data.
61336 	 */
61337 
61338 #if defined(DUK_USE_DATE_BUILTIN)
61339 	duk_get_prop_stridx_short(thr, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_UTC_STRING);
61340 	duk_xdef_prop_stridx_short(thr, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_GMT_STRING, DUK_PROPDESC_FLAGS_WC);
61341 #endif
61342 
61343 	h = duk_known_hobject(thr, DUK_BIDX_DOUBLE_ERROR);
61344 	DUK_HOBJECT_CLEAR_EXTENSIBLE(h);
61345 
61346 #if !defined(DUK_USE_ES6_OBJECT_PROTO_PROPERTY)
61347 	DUK_DD(DUK_DDPRINT("delete Object.prototype.__proto__ built-in which is not enabled in features"));
61348 	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_PROTOTYPE], DUK_HTHREAD_STRING___PROTO__(thr), DUK_DELPROP_FLAG_THROW);
61349 #endif
61350 
61351 #if !defined(DUK_USE_ES6_OBJECT_SETPROTOTYPEOF)
61352 	DUK_DD(DUK_DDPRINT("delete Object.setPrototypeOf built-in which is not enabled in features"));
61353 	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_CONSTRUCTOR], DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr), DUK_DELPROP_FLAG_THROW);
61354 #endif
61355 
61356 	/* XXX: relocate */
61357 	duk_push_string(thr,
61358 			/* Endianness indicator */
61359 #if defined(DUK_USE_INTEGER_LE)
61360 	                "l"
61361 #elif defined(DUK_USE_INTEGER_BE)
61362 	                "b"
61363 #elif defined(DUK_USE_INTEGER_ME)  /* integer mixed endian not really used now */
61364 	                "m"
61365 #else
61366 	                "?"
61367 #endif
61368 #if defined(DUK_USE_DOUBLE_LE)
61369 	                "l"
61370 #elif defined(DUK_USE_DOUBLE_BE)
61371 	                "b"
61372 #elif defined(DUK_USE_DOUBLE_ME)
61373 	                "m"
61374 #else
61375 	                "?"
61376 #endif
61377 	                " "
61378 			/* Packed or unpacked tval */
61379 #if defined(DUK_USE_PACKED_TVAL)
61380 	                "p"
61381 #else
61382 	                "u"
61383 #endif
61384 #if defined(DUK_USE_FASTINT)
61385 			"f"
61386 #endif
61387 			" "
61388 			/* Low memory/performance options */
61389 #if defined(DUK_USE_STRTAB_PTRCOMP)
61390 			"s"
61391 #endif
61392 #if !defined(DUK_USE_HEAPPTR16) && !defined(DUK_DATAPTR16) && !defined(DUK_FUNCPTR16)
61393 			"n"
61394 #endif
61395 #if defined(DUK_USE_HEAPPTR16)
61396 			"h"
61397 #endif
61398 #if defined(DUK_USE_DATAPTR16)
61399 			"d"
61400 #endif
61401 #if defined(DUK_USE_FUNCPTR16)
61402 			"f"
61403 #endif
61404 #if defined(DUK_USE_REFCOUNT16)
61405 			"R"
61406 #endif
61407 #if defined(DUK_USE_STRHASH16)
61408 			"H"
61409 #endif
61410 #if defined(DUK_USE_STRLEN16)
61411 			"S"
61412 #endif
61413 #if defined(DUK_USE_BUFLEN16)
61414 			"B"
61415 #endif
61416 #if defined(DUK_USE_OBJSIZES16)
61417 			"O"
61418 #endif
61419 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
61420 			"L"
61421 #endif
61422 #if defined(DUK_USE_ROM_STRINGS) || defined(DUK_USE_ROM_OBJECTS)
61423 			/* XXX: This won't be shown in practice now
61424 			 * because this code is not run when builtins
61425 			 * are in ROM.
61426 			 */
61427 			"Z"
61428 #endif
61429 #if defined(DUK_USE_LITCACHE_SIZE)
61430 			"l"
61431 #endif
61432 	                " "
61433 			/* Object property allocation layout */
61434 #if defined(DUK_USE_HOBJECT_LAYOUT_1)
61435 			"p1"
61436 #elif defined(DUK_USE_HOBJECT_LAYOUT_2)
61437 			"p2"
61438 #elif defined(DUK_USE_HOBJECT_LAYOUT_3)
61439 			"p3"
61440 #else
61441 			"p?"
61442 #endif
61443 			" "
61444 			/* Alignment guarantee */
61445 #if (DUK_USE_ALIGN_BY == 4)
61446 			"a4"
61447 #elif (DUK_USE_ALIGN_BY == 8)
61448 			"a8"
61449 #elif (DUK_USE_ALIGN_BY == 1)
61450 			"a1"
61451 #else
61452 #error invalid DUK_USE_ALIGN_BY
61453 #endif
61454 			" "
61455 			/* Architecture, OS, and compiler strings */
61456 	                DUK_USE_ARCH_STRING
61457 			" "
61458 	                DUK_USE_OS_STRING
61459 			" "
61460 	                DUK_USE_COMPILER_STRING);
61461 	duk_xdef_prop_stridx_short(thr, DUK_BIDX_DUKTAPE, DUK_STRIDX_ENV, DUK_PROPDESC_FLAGS_WC);
61462 
61463 	/*
61464 	 *  Since built-ins are not often extended, compact them.
61465 	 */
61466 
61467 	DUK_DD(DUK_DDPRINT("compact built-ins"));
61468 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
61469 		duk_hobject_compact_props(thr, duk_known_hobject(thr, (duk_idx_t) i));
61470 	}
61471 
61472 	DUK_D(DUK_DPRINT("INITBUILTINS END"));
61473 
61474 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
61475 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
61476 		DUK_DD(DUK_DDPRINT("built-in object %ld after initialization and compacting: %!@iO",
61477 		                   (long) i, (duk_heaphdr *) duk_require_hobject(thr, i)));
61478 	}
61479 #endif
61480 
61481 	/*
61482 	 *  Pop built-ins from stack: they are now INCREF'd and
61483 	 *  reachable from the builtins[] array or indirectly
61484 	 *  through builtins[].
61485 	 */
61486 
61487 	duk_set_top(thr, 0);
61488 	DUK_ASSERT_TOP(thr, 0);
61489 }
61490 #endif  /* DUK_USE_ROM_OBJECTS */
61491 
61492 DUK_INTERNAL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to) {
61493 	duk_small_uint_t i;
61494 
61495 	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
61496 		thr_to->builtins[i] = thr_from->builtins[i];
61497 		DUK_HOBJECT_INCREF_ALLOWNULL(thr_to, thr_to->builtins[i]);  /* side effect free */
61498 	}
61499 }
61500 
61501 /* automatic undefs */
61502 #undef DUK__LENGTH_PROP_BITS
61503 #undef DUK__NARGS_BITS
61504 #undef DUK__NARGS_VARARGS_MARKER
61505 #undef DUK__PROP_FLAGS_BITS
61506 #undef DUK__PROP_TYPE_ACCESSOR
61507 #undef DUK__PROP_TYPE_BITS
61508 #undef DUK__PROP_TYPE_BOOLEAN_FALSE
61509 #undef DUK__PROP_TYPE_BOOLEAN_TRUE
61510 #undef DUK__PROP_TYPE_BUILTIN
61511 #undef DUK__PROP_TYPE_DOUBLE
61512 #undef DUK__PROP_TYPE_STRIDX
61513 #undef DUK__PROP_TYPE_STRING
61514 #undef DUK__PROP_TYPE_UNDEFINED
61515 #line 1 "duk_hthread_misc.c"
61516 /*
61517  *  Thread support.
61518  */
61519 
61520 /* #include duk_internal.h -> already included */
61521 
61522 DUK_INTERNAL void duk_hthread_terminate(duk_hthread *thr) {
61523 	DUK_ASSERT(thr != NULL);
61524 
61525 	while (thr->callstack_curr != NULL) {
61526 		duk_hthread_activation_unwind_norz(thr);
61527 	}
61528 
61529 	thr->valstack_bottom = thr->valstack;
61530 	duk_set_top(thr, 0);  /* unwinds valstack, updating refcounts */
61531 
61532 	thr->state = DUK_HTHREAD_STATE_TERMINATED;
61533 
61534 	/* Here we could remove references to built-ins, but it may not be
61535 	 * worth the effort because built-ins are quite likely to be shared
61536 	 * with another (unterminated) thread, and terminated threads are also
61537 	 * usually garbage collected quite quickly.
61538 	 *
61539 	 * We could also shrink the value stack here, but that also may not
61540 	 * be worth the effort for the same reason.
61541 	 */
61542 
61543 	DUK_REFZERO_CHECK_SLOW(thr);
61544 }
61545 
61546 #if defined(DUK_USE_DEBUGGER_SUPPORT)
61547 DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act) {
61548 	duk_instr_t *bcode;
61549 
61550 	DUK_ASSERT(thr != NULL);
61551 	DUK_ASSERT(act != NULL);
61552 	DUK_UNREF(thr);
61553 
61554 	/* XXX: store 'bcode' pointer to activation for faster lookup? */
61555 	if (act->func && DUK_HOBJECT_IS_COMPFUNC(act->func)) {
61556 		bcode = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) (act->func));
61557 		return (duk_uint_fast32_t) (act->curr_pc - bcode);
61558 	}
61559 	return 0;
61560 }
61561 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
61562 
61563 DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act) {
61564 	duk_instr_t *bcode;
61565 	duk_uint_fast32_t ret;
61566 
61567 	DUK_ASSERT(thr != NULL);
61568 	DUK_ASSERT(act != NULL);
61569 	DUK_UNREF(thr);
61570 
61571 	if (act->func && DUK_HOBJECT_IS_COMPFUNC(act->func)) {
61572 		bcode = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) (act->func));
61573 		ret = (duk_uint_fast32_t) (act->curr_pc - bcode);
61574 		if (ret > 0) {
61575 			ret--;
61576 		}
61577 		return ret;
61578 	}
61579 	return 0;
61580 }
61581 
61582 /* Write bytecode executor's curr_pc back to topmost activation (if any). */
61583 DUK_INTERNAL void duk_hthread_sync_currpc(duk_hthread *thr) {
61584 	duk_activation *act;
61585 
61586 	DUK_ASSERT(thr != NULL);
61587 
61588 	if (thr->ptr_curr_pc != NULL) {
61589 		/* ptr_curr_pc != NULL only when bytecode executor is active. */
61590 		DUK_ASSERT(thr->callstack_top > 0);
61591 		DUK_ASSERT(thr->callstack_curr != NULL);
61592 		act = thr->callstack_curr;
61593 		DUK_ASSERT(act != NULL);
61594 		act->curr_pc = *thr->ptr_curr_pc;
61595 	}
61596 }
61597 
61598 DUK_INTERNAL void duk_hthread_sync_and_null_currpc(duk_hthread *thr) {
61599 	duk_activation *act;
61600 
61601 	DUK_ASSERT(thr != NULL);
61602 
61603 	if (thr->ptr_curr_pc != NULL) {
61604 		/* ptr_curr_pc != NULL only when bytecode executor is active. */
61605 		DUK_ASSERT(thr->callstack_top > 0);
61606 		DUK_ASSERT(thr->callstack_curr != NULL);
61607 		act = thr->callstack_curr;
61608 		DUK_ASSERT(act != NULL);
61609 		act->curr_pc = *thr->ptr_curr_pc;
61610 		thr->ptr_curr_pc = NULL;
61611 	}
61612 }
61613 #line 1 "duk_hthread_stacks.c"
61614 /*
61615  *  Thread stack (mainly call stack) primitives: allocation of activations,
61616  *  unwinding catchers and activations, etc.
61617  *
61618  *  Value stack handling is a part of the API implementation.
61619  */
61620 
61621 /* #include duk_internal.h -> already included */
61622 
61623 /* Unwind the topmost catcher of the current activation (caller must check that
61624  * both exist) without side effects.
61625  */
61626 DUK_INTERNAL void duk_hthread_catcher_unwind_norz(duk_hthread *thr, duk_activation *act) {
61627 	duk_catcher *cat;
61628 
61629 	DUK_ASSERT(thr != NULL);
61630 	DUK_ASSERT(act != NULL);
61631 	DUK_ASSERT(act->cat != NULL);  /* caller must check */
61632 	cat = act->cat;
61633 	DUK_ASSERT(cat != NULL);
61634 
61635 	DUK_DDD(DUK_DDDPRINT("unwinding catch stack entry %p (lexenv check is done)", (void *) cat));
61636 
61637 	if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
61638 		duk_hobject *env;
61639 
61640 		env = act->lex_env;             /* current lex_env of the activation (created for catcher) */
61641 		DUK_ASSERT(env != NULL);        /* must be, since env was created when catcher was created */
61642 		act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);  /* prototype is lex_env before catcher created */
61643 		DUK_HOBJECT_INCREF(thr, act->lex_env);
61644 		DUK_HOBJECT_DECREF_NORZ(thr, env);
61645 
61646 		/* There is no need to decref anything else than 'env': if 'env'
61647 		 * becomes unreachable, refzero will handle decref'ing its prototype.
61648 		 */
61649 	}
61650 
61651 	act->cat = cat->parent;
61652 	duk_hthread_catcher_free(thr, cat);
61653 }
61654 
61655 /* Same as above, but caller is certain no catcher-related lexenv may exist. */
61656 DUK_INTERNAL void duk_hthread_catcher_unwind_nolexenv_norz(duk_hthread *thr, duk_activation *act) {
61657 	duk_catcher *cat;
61658 
61659 	DUK_ASSERT(thr != NULL);
61660 	DUK_ASSERT(act != NULL);
61661 	DUK_ASSERT(act->cat != NULL);  /* caller must check */
61662 	cat = act->cat;
61663 	DUK_ASSERT(cat != NULL);
61664 
61665 	DUK_DDD(DUK_DDDPRINT("unwinding catch stack entry %p (lexenv check is not done)", (void *) cat));
61666 
61667 	DUK_ASSERT(!DUK_CAT_HAS_LEXENV_ACTIVE(cat));
61668 
61669 	act->cat = cat->parent;
61670 	duk_hthread_catcher_free(thr, cat);
61671 }
61672 
61673 DUK_LOCAL
61674 #if defined(DUK_USE_CACHE_CATCHER)
61675 DUK_NOINLINE
61676 #endif
61677 duk_catcher *duk__hthread_catcher_alloc_slow(duk_hthread *thr) {
61678 	duk_catcher *cat;
61679 
61680 	cat = (duk_catcher *) DUK_ALLOC_CHECKED(thr, sizeof(duk_catcher));
61681 	DUK_ASSERT(cat != NULL);
61682 	return cat;
61683 }
61684 
61685 #if defined(DUK_USE_CACHE_CATCHER)
61686 DUK_INTERNAL DUK_INLINE duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr) {
61687 	duk_catcher *cat;
61688 
61689 	DUK_ASSERT(thr != NULL);
61690 
61691 	cat = thr->heap->catcher_free;
61692 	if (DUK_LIKELY(cat != NULL)) {
61693 		thr->heap->catcher_free = cat->parent;
61694 		return cat;
61695 	}
61696 
61697 	return duk__hthread_catcher_alloc_slow(thr);
61698 }
61699 #else  /* DUK_USE_CACHE_CATCHER */
61700 DUK_INTERNAL duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr) {
61701 	return duk__hthread_catcher_alloc_slow(thr);
61702 }
61703 #endif  /* DUK_USE_CACHE_CATCHER */
61704 
61705 DUK_INTERNAL void duk_hthread_catcher_free(duk_hthread *thr, duk_catcher *cat) {
61706 	DUK_ASSERT(thr != NULL);
61707 	DUK_ASSERT(cat != NULL);
61708 
61709 #if defined(DUK_USE_CACHE_CATCHER)
61710 	/* Unconditional caching for now; freed in mark-and-sweep. */
61711 	cat->parent = thr->heap->catcher_free;
61712 	thr->heap->catcher_free = cat;
61713 #else
61714 	DUK_FREE_CHECKED(thr, (void *) cat);
61715 #endif
61716 }
61717 
61718 DUK_LOCAL
61719 #if defined(DUK_USE_CACHE_ACTIVATION)
61720 DUK_NOINLINE
61721 #endif
61722 duk_activation *duk__hthread_activation_alloc_slow(duk_hthread *thr) {
61723 	duk_activation *act;
61724 
61725 	act = (duk_activation *) DUK_ALLOC_CHECKED(thr, sizeof(duk_activation));
61726 	DUK_ASSERT(act != NULL);
61727 	return act;
61728 }
61729 
61730 #if defined(DUK_USE_CACHE_ACTIVATION)
61731 DUK_INTERNAL DUK_INLINE duk_activation *duk_hthread_activation_alloc(duk_hthread *thr) {
61732 	duk_activation *act;
61733 
61734 	DUK_ASSERT(thr != NULL);
61735 
61736 	act = thr->heap->activation_free;
61737 	if (DUK_LIKELY(act != NULL)) {
61738 		thr->heap->activation_free = act->parent;
61739 		return act;
61740 	}
61741 
61742 	return duk__hthread_activation_alloc_slow(thr);
61743 }
61744 #else  /* DUK_USE_CACHE_ACTIVATION */
61745 DUK_INTERNAL duk_activation *duk_hthread_activation_alloc(duk_hthread *thr) {
61746 	return duk__hthread_activation_alloc_slow(thr);
61747 }
61748 #endif  /* DUK_USE_CACHE_ACTIVATION */
61749 
61750 
61751 DUK_INTERNAL void duk_hthread_activation_free(duk_hthread *thr, duk_activation *act) {
61752 	DUK_ASSERT(thr != NULL);
61753 	DUK_ASSERT(act != NULL);
61754 
61755 #if defined(DUK_USE_CACHE_ACTIVATION)
61756 	/* Unconditional caching for now; freed in mark-and-sweep. */
61757 	act->parent = thr->heap->activation_free;
61758 	thr->heap->activation_free = act;
61759 #else
61760 	DUK_FREE_CHECKED(thr, (void *) act);
61761 #endif
61762 }
61763 
61764 /* Internal helper: process the unwind for the topmost activation of a thread,
61765  * but leave the duk_activation in place for possible tailcall reuse.
61766  */
61767 DUK_LOCAL void duk__activation_unwind_nofree_norz(duk_hthread *thr) {
61768 #if defined(DUK_USE_DEBUGGER_SUPPORT)
61769 	duk_heap *heap;
61770 #endif
61771 	duk_activation *act;
61772 	duk_hobject *func;
61773 	duk_hobject *tmp;
61774 
61775 	DUK_ASSERT(thr != NULL);
61776 	DUK_ASSERT(thr->callstack_curr != NULL);  /* caller must check */
61777 	DUK_ASSERT(thr->callstack_top > 0);
61778 	act = thr->callstack_curr;
61779 	DUK_ASSERT(act != NULL);
61780 	/* With lightfuncs, act 'func' may be NULL. */
61781 
61782 	/* With duk_activation records allocated separately, 'act' is a stable
61783 	 * pointer and not affected by side effects.
61784 	 */
61785 
61786 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
61787 	/*
61788 	 *  Restore 'caller' property for non-strict callee functions.
61789 	 */
61790 
61791 	func = DUK_ACT_GET_FUNC(act);
61792 	if (func != NULL && !DUK_HOBJECT_HAS_STRICT(func)) {
61793 		duk_tval *tv_caller;
61794 		duk_tval tv_tmp;
61795 		duk_hobject *h_tmp;
61796 
61797 		tv_caller = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_CALLER(thr));
61798 
61799 		/* The act->prev_caller should only be set if the entry for 'caller'
61800 		 * exists (as it is only set in that case, and the property is not
61801 		 * configurable), but handle all the cases anyway.
61802 		 */
61803 
61804 		if (tv_caller) {
61805 			DUK_TVAL_SET_TVAL(&tv_tmp, tv_caller);
61806 			if (act->prev_caller) {
61807 				/* Just transfer the refcount from act->prev_caller to tv_caller,
61808 				 * so no need for a refcount update.  This is the expected case.
61809 				 */
61810 				DUK_TVAL_SET_OBJECT(tv_caller, act->prev_caller);
61811 				act->prev_caller = NULL;
61812 			} else {
61813 				DUK_TVAL_SET_NULL(tv_caller);   /* no incref needed */
61814 				DUK_ASSERT(act->prev_caller == NULL);
61815 			}
61816 			DUK_TVAL_DECREF_NORZ(thr, &tv_tmp);
61817 		} else {
61818 			h_tmp = act->prev_caller;
61819 			if (h_tmp) {
61820 				act->prev_caller = NULL;
61821 				DUK_HOBJECT_DECREF_NORZ(thr, h_tmp);
61822 			}
61823 		}
61824 		DUK_ASSERT(act->prev_caller == NULL);
61825 	}
61826 #endif
61827 
61828 	/*
61829 	 *  Unwind debugger state.  If we unwind while stepping
61830 	 *  (for any step type), pause execution.  This is the
61831 	 *  only place explicitly handling a step out.
61832 	 */
61833 
61834 #if defined(DUK_USE_DEBUGGER_SUPPORT)
61835 	heap = thr->heap;
61836 	if (heap->dbg_pause_act == thr->callstack_curr) {
61837 		if (heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_EXIT) {
61838 			DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function exit"));
61839 			duk_debug_set_paused(heap);
61840 		} else {
61841 			DUK_D(DUK_DPRINT("unwound past dbg_pause_act, set to NULL"));
61842 			heap->dbg_pause_act = NULL;  /* avoid stale pointers */
61843 		}
61844 		DUK_ASSERT(heap->dbg_pause_act == NULL);
61845 	}
61846 #endif
61847 
61848 	/*
61849 	 *  Unwind catchers.
61850 	 *
61851 	 *  Since there are no references in the catcher structure,
61852 	 *  unwinding is quite simple.  The only thing we need to
61853 	 *  look out for is popping a possible lexical environment
61854 	 *  established for an active catch clause.
61855 	 */
61856 
61857 	while (act->cat != NULL) {
61858 		duk_hthread_catcher_unwind_norz(thr, act);
61859 	}
61860 
61861 	/*
61862 	 *  Close environment record(s) if they exist.
61863 	 *
61864 	 *  Only variable environments are closed.  If lex_env != var_env, it
61865 	 *  cannot currently contain any register bound declarations.
61866 	 *
61867 	 *  Only environments created for a NEWENV function are closed.  If an
61868 	 *  environment is created for e.g. an eval call, it must not be closed.
61869 	 */
61870 
61871 	func = DUK_ACT_GET_FUNC(act);
61872 	if (func != NULL && !DUK_HOBJECT_HAS_NEWENV(func)) {
61873 		DUK_DDD(DUK_DDDPRINT("skip closing environments, envs not owned by this activation"));
61874 		goto skip_env_close;
61875 	}
61876 	/* func is NULL for lightfunc */
61877 
61878 	/* Catch sites are required to clean up their environments
61879 	 * in FINALLY part before propagating, so this should
61880 	 * always hold here.
61881 	 */
61882 	DUK_ASSERT(act->lex_env == act->var_env);
61883 
61884 	/* XXX: Closing the environment record copies values from registers
61885 	 * into the scope object.  It's side effect free as such, but may
61886 	 * currently run out of memory which causes an error throw.  This is
61887 	 * an actual sandboxing problem for error unwinds, and needs to be
61888 	 * fixed e.g. by preallocating the scope property slots.
61889 	 */
61890 	if (act->var_env != NULL) {
61891 		DUK_DDD(DUK_DDDPRINT("closing var_env record %p -> %!O",
61892 		                     (void *) act->var_env, (duk_heaphdr *) act->var_env));
61893 		duk_js_close_environment_record(thr, act->var_env);
61894 	}
61895 
61896  skip_env_close:
61897 
61898 	/*
61899 	 *  Update preventcount
61900 	 */
61901 
61902 	if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
61903 		DUK_ASSERT(thr->callstack_preventcount >= 1);
61904 		thr->callstack_preventcount--;
61905 	}
61906 
61907 	/*
61908 	 *  Reference count updates, using NORZ macros so we don't
61909 	 *  need to handle side effects.
61910 	 *
61911 	 *  duk_activation pointers like act->var_env are intentionally
61912 	 *  left as garbage and not NULLed.  Without side effects they
61913 	 *  can't be used when the values are dangling/garbage.
61914 	 */
61915 
61916 	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, act->var_env);
61917 	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, act->lex_env);
61918 	tmp = DUK_ACT_GET_FUNC(act);
61919 	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
61920 	DUK_UNREF(tmp);
61921 }
61922 
61923 /* Unwind topmost duk_activation of a thread, caller must ensure that an
61924  * activation exists.  The call is side effect free, except that scope
61925  * closure may currently throw an out-of-memory error.
61926  */
61927 DUK_INTERNAL void duk_hthread_activation_unwind_norz(duk_hthread *thr) {
61928 	duk_activation *act;
61929 
61930 	duk__activation_unwind_nofree_norz(thr);
61931 
61932 	DUK_ASSERT(thr->callstack_curr != NULL);
61933 	DUK_ASSERT(thr->callstack_top > 0);
61934 	act = thr->callstack_curr;
61935 	thr->callstack_curr = act->parent;
61936 	thr->callstack_top--;
61937 
61938 	/* Ideally we'd restore value stack reserve here to caller's value.
61939 	 * This doesn't work for current unwind call sites however, because
61940 	 * the current (unwound) value stack top may be above the reserve.
61941 	 * Thus value stack reserve is restored by the call sites.
61942 	 */
61943 
61944 	/* XXX: inline for performance builds? */
61945 	duk_hthread_activation_free(thr, act);
61946 
61947 	/* We could clear the book-keeping variables like retval_byteoff for
61948 	 * the topmost activation, but don't do so now as it's not necessary.
61949 	 */
61950 }
61951 
61952 DUK_INTERNAL void duk_hthread_activation_unwind_reuse_norz(duk_hthread *thr) {
61953 	duk__activation_unwind_nofree_norz(thr);
61954 }
61955 
61956 /* Get duk_activation for given callstack level or NULL if level is invalid
61957  * or deeper than the call stack.  Level -1 refers to current activation, -2
61958  * to its caller, etc.  Starting from Duktape 2.2 finding the activation is
61959  * a linked list scan which gets more expensive the deeper the lookup is.
61960  */
61961 DUK_INTERNAL duk_activation *duk_hthread_get_activation_for_level(duk_hthread *thr, duk_int_t level) {
61962 	duk_activation *act;
61963 
61964 	if (level >= 0) {
61965 		return NULL;
61966 	}
61967 	act = thr->callstack_curr;
61968 	for (;;) {
61969 		if (act == NULL) {
61970 			return act;
61971 		}
61972 		if (level == -1) {
61973 			return act;
61974 		}
61975 		level++;
61976 		act = act->parent;
61977 	}
61978 	/* never here */
61979 }
61980 
61981 #if defined(DUK_USE_FINALIZER_TORTURE)
61982 DUK_INTERNAL void duk_hthread_valstack_torture_realloc(duk_hthread *thr) {
61983 	duk_size_t alloc_size;
61984 	duk_tval *new_ptr;
61985 	duk_ptrdiff_t alloc_end_off;
61986 	duk_ptrdiff_t end_off;
61987 	duk_ptrdiff_t bottom_off;
61988 	duk_ptrdiff_t top_off;
61989 
61990 	if (thr->valstack == NULL) {
61991 		DUK_D(DUK_DPRINT("skip valstack torture realloc, valstack is NULL"));
61992 		return;
61993 	}
61994 
61995 	alloc_end_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_alloc_end - (duk_uint8_t *) thr->valstack);
61996 	end_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
61997 	bottom_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
61998 	top_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack);
61999 	alloc_size = (duk_size_t) alloc_end_off;
62000 	if (alloc_size == 0) {
62001 		DUK_D(DUK_DPRINT("skip valstack torture realloc, alloc_size is zero"));
62002 		return;
62003 	}
62004 
62005 	/* Use DUK_ALLOC_RAW() to avoid side effects. */
62006 	new_ptr = (duk_tval *) DUK_ALLOC_RAW(thr->heap, alloc_size);
62007 	if (new_ptr != NULL) {
62008 		duk_memcpy((void *) new_ptr, (const void *) thr->valstack, alloc_size);
62009 		duk_memset((void *) thr->valstack, 0x55, alloc_size);
62010 		DUK_FREE_CHECKED(thr, (void *) thr->valstack);
62011 		thr->valstack = new_ptr;
62012 		thr->valstack_alloc_end = (duk_tval *) ((duk_uint8_t *) new_ptr + alloc_end_off);
62013 		thr->valstack_end = (duk_tval *) ((duk_uint8_t *) new_ptr + end_off);
62014 		thr->valstack_bottom = (duk_tval *) ((duk_uint8_t *) new_ptr + bottom_off);
62015 		thr->valstack_top = (duk_tval *) ((duk_uint8_t *) new_ptr + top_off);
62016 	} else {
62017 		DUK_D(DUK_DPRINT("failed to realloc valstack for torture, ignore"));
62018 	}
62019 }
62020 #endif  /* DUK_USE_FINALIZER_TORTURE */
62021 #line 1 "duk_js_arith.c"
62022 /*
62023  *  Shared helpers for arithmetic operations
62024  */
62025 
62026 /* #include duk_internal.h -> already included */
62027 
62028 /* ECMAScript modulus ('%') does not match IEEE 754 "remainder" operation
62029  * (implemented by remainder() in C99) but does seem to match ANSI C fmod().
62030  * Compare E5 Section 11.5.3 and "man fmod".
62031  */
62032 DUK_INTERNAL double duk_js_arith_mod(double d1, double d2) {
62033 #if defined(DUK_USE_POW_WORKAROUNDS)
62034 	/* Specific fixes to common fmod() implementation issues:
62035 	 * - test-bug-mingw-math-issues.js
62036 	 */
62037 	if (DUK_ISINF(d2)) {
62038 		if (DUK_ISINF(d1)) {
62039 			return DUK_DOUBLE_NAN;
62040 		} else {
62041 			return d1;
62042 		}
62043 	} else if (d1 == 0.0) {
62044 		/* d1 +/-0 is returned as is (preserving sign) except when
62045 		 * d2 is zero or NaN.
62046 		 */
62047 		if (d2 == 0.0 || DUK_ISNAN(d2)) {
62048 			return DUK_DOUBLE_NAN;
62049 		} else {
62050 			return d1;
62051 		}
62052 	}
62053 #else
62054 	/* Some ISO C assumptions. */
62055 	DUK_ASSERT(DUK_FMOD(1.0, DUK_DOUBLE_INFINITY) == 1.0);
62056 	DUK_ASSERT(DUK_FMOD(-1.0, DUK_DOUBLE_INFINITY) == -1.0);
62057 	DUK_ASSERT(DUK_FMOD(1.0, -DUK_DOUBLE_INFINITY) == 1.0);
62058 	DUK_ASSERT(DUK_FMOD(-1.0, -DUK_DOUBLE_INFINITY) == -1.0);
62059 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY)));
62060 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY)));
62061 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY)));
62062 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY)));
62063 	DUK_ASSERT(DUK_FMOD(0.0, 1.0) == 0.0 && DUK_SIGNBIT(DUK_FMOD(0.0, 1.0)) == 0);
62064 	DUK_ASSERT(DUK_FMOD(-0.0, 1.0) == 0.0 && DUK_SIGNBIT(DUK_FMOD(-0.0, 1.0)) != 0);
62065 	DUK_ASSERT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY)) == 0);
62066 	DUK_ASSERT(DUK_FMOD(-0.0, DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(-0.0, DUK_DOUBLE_INFINITY)) != 0);
62067 	DUK_ASSERT(DUK_FMOD(0.0, -DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY)) == 0);
62068 	DUK_ASSERT(DUK_FMOD(-0.0, -DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(-0.0, -DUK_DOUBLE_INFINITY)) != 0);
62069 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, 0.0)));
62070 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, 0.0)));
62071 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, -0.0)));
62072 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, -0.0)));
62073 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, DUK_DOUBLE_NAN)));
62074 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, DUK_DOUBLE_NAN)));
62075 #endif
62076 
62077 	return (duk_double_t) DUK_FMOD((double) d1, (double) d2);
62078 }
62079 
62080 /* Shared helper for Math.pow() and exponentiation operator. */
62081 DUK_INTERNAL double duk_js_arith_pow(double x, double y) {
62082 	/* The ANSI C pow() semantics differ from ECMAScript.
62083 	 *
62084 	 * E.g. when x==1 and y is +/- infinite, the ECMAScript required
62085 	 * result is NaN, while at least Linux pow() returns 1.
62086 	 */
62087 
62088 	duk_small_int_t cx, cy, sx;
62089 
62090 	DUK_UNREF(cx);
62091 	DUK_UNREF(sx);
62092 	cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
62093 
62094 	if (cy == DUK_FP_NAN) {
62095 		goto ret_nan;
62096 	}
62097 	if (DUK_FABS(x) == 1.0 && cy == DUK_FP_INFINITE) {
62098 		goto ret_nan;
62099 	}
62100 
62101 #if defined(DUK_USE_POW_WORKAROUNDS)
62102 	/* Specific fixes to common pow() implementation issues:
62103 	 *   - test-bug-netbsd-math-pow.js: NetBSD 6.0 on x86 (at least)
62104 	 *   - test-bug-mingw-math-issues.js
62105 	 */
62106 	cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
62107 	if (cx == DUK_FP_ZERO && y < 0.0) {
62108 		sx = (duk_small_int_t) DUK_SIGNBIT(x);
62109 		if (sx == 0) {
62110 			/* Math.pow(+0,y) should be Infinity when y<0.  NetBSD pow()
62111 			 * returns -Infinity instead when y is <0 and finite.  The
62112 			 * if-clause also catches y == -Infinity (which works even
62113 			 * without the fix).
62114 			 */
62115 			return DUK_DOUBLE_INFINITY;
62116 		} else {
62117 			/* Math.pow(-0,y) where y<0 should be:
62118 			 *   - -Infinity if y<0 and an odd integer
62119 			 *   - Infinity if y<0 but not an odd integer
62120 			 * NetBSD pow() returns -Infinity for all finite y<0.  The
62121 			 * if-clause also catches y == -Infinity (which works even
62122 			 * without the fix).
62123 			 */
62124 
62125 			/* fmod() return value has same sign as input (negative) so
62126 			 * the result here will be in the range ]-2,0], -1 indicates
62127 			 * odd.  If x is -Infinity, NaN is returned and the odd check
62128 			 * always concludes "not odd" which results in desired outcome.
62129 			 */
62130 			double tmp = DUK_FMOD(y, 2);
62131 			if (tmp == -1.0) {
62132 				return -DUK_DOUBLE_INFINITY;
62133 			} else {
62134 				/* Not odd, or y == -Infinity */
62135 				return DUK_DOUBLE_INFINITY;
62136 			}
62137 		}
62138 	} else if (cx == DUK_FP_NAN) {
62139 		if (y == 0.0) {
62140 			/* NaN ** +/- 0 should always be 1, but is NaN on
62141 			 * at least some Cygwin/MinGW versions.
62142 			 */
62143 			return 1.0;
62144 		}
62145 	}
62146 #else
62147 	/* Some ISO C assumptions. */
62148 	DUK_ASSERT(DUK_POW(DUK_DOUBLE_NAN, 0.0) == 1.0);
62149 	DUK_ASSERT(DUK_ISINF(DUK_POW(0.0, -1.0)) && DUK_SIGNBIT(DUK_POW(0.0, -1.0)) == 0);
62150 	DUK_ASSERT(DUK_ISINF(DUK_POW(-0.0, -2.0)) && DUK_SIGNBIT(DUK_POW(-0.0, -2.0)) == 0);
62151 	DUK_ASSERT(DUK_ISINF(DUK_POW(-0.0, -3.0)) && DUK_SIGNBIT(DUK_POW(-0.0, -3.0)) != 0);
62152 #endif
62153 
62154 	return DUK_POW(x, y);
62155 
62156  ret_nan:
62157 	return DUK_DOUBLE_NAN;
62158 }
62159 #line 1 "duk_js_call.c"
62160 /*
62161  *  Call handling.
62162  *
62163  *  duk_handle_call_unprotected():
62164  *
62165  *    - Unprotected call to ECMAScript or Duktape/C function, from native
62166  *      code or bytecode executor.
62167  *
62168  *    - Also handles Ecma-to-Ecma calls which reuses a currently running
62169  *      executor instance to avoid native recursion.  Call setup is done
62170  *      normally, but just before calling the bytecode executor a special
62171  *      return code is used to indicate that a calling executor is reused.
62172  *
62173  *    - Also handles tailcalls, i.e. reuse of current duk_activation.
62174  *
62175  *    - Also handles setup for initial Duktape.Thread.resume().
62176  *
62177  *  duk_handle_safe_call():
62178  *
62179  *    - Protected C call within current activation.
62180  *
62181  *  setjmp() and local variables have a nasty interaction, see execution.rst;
62182  *  non-volatile locals modified after setjmp() call are not guaranteed to
62183  *  keep their value and can cause compiler or compiler version specific
62184  *  difficult to replicate issues.
62185  *
62186  *  See 'execution.rst'.
62187  */
62188 
62189 /* #include duk_internal.h -> already included */
62190 
62191 /* XXX: heap->error_not_allowed for success path too? */
62192 
62193 /*
62194  *  Limit check helpers.
62195  */
62196 
62197 /* Allow headroom for calls during error augmentation (see GH-191).
62198  * We allow space for 10 additional recursions, with one extra
62199  * for, e.g. a print() call at the deepest level, and an extra
62200  * +1 for protected call wrapping.
62201  */
62202 #define DUK__AUGMENT_CALL_RELAX_COUNT  (10 + 2)
62203 
62204 DUK_LOCAL DUK_NOINLINE void duk__call_c_recursion_limit_check_slowpath(duk_hthread *thr) {
62205 	/* When augmenting an error, the effective limit is a bit higher.
62206 	 * Check for it only if the fast path check fails.
62207 	 */
62208 #if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
62209 	if (thr->heap->augmenting_error) {
62210 		if (thr->heap->call_recursion_depth < thr->heap->call_recursion_limit + DUK__AUGMENT_CALL_RELAX_COUNT) {
62211 			DUK_D(DUK_DPRINT("C recursion limit reached but augmenting error and within relaxed limit"));
62212 			return;
62213 		}
62214 	}
62215 #endif
62216 
62217 	DUK_D(DUK_DPRINT("call prevented because C recursion limit reached"));
62218 	DUK_ERROR_RANGE(thr, DUK_STR_C_CALLSTACK_LIMIT);
62219 	DUK_WO_NORETURN(return;);
62220 }
62221 
62222 DUK_LOCAL DUK_ALWAYS_INLINE void duk__call_c_recursion_limit_check(duk_hthread *thr) {
62223 	DUK_ASSERT(thr->heap->call_recursion_depth >= 0);
62224 	DUK_ASSERT(thr->heap->call_recursion_depth <= thr->heap->call_recursion_limit);
62225 
62226 	/* This check is forcibly inlined because it's very cheap and almost
62227 	 * always passes.  The slow path is forcibly noinline.
62228 	 */
62229 	if (DUK_LIKELY(thr->heap->call_recursion_depth < thr->heap->call_recursion_limit)) {
62230 		return;
62231 	}
62232 
62233 	duk__call_c_recursion_limit_check_slowpath(thr);
62234 }
62235 
62236 DUK_LOCAL DUK_NOINLINE void duk__call_callstack_limit_check_slowpath(duk_hthread *thr) {
62237 	/* When augmenting an error, the effective limit is a bit higher.
62238 	 * Check for it only if the fast path check fails.
62239 	 */
62240 #if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
62241 	if (thr->heap->augmenting_error) {
62242 		if (thr->callstack_top < DUK_USE_CALLSTACK_LIMIT + DUK__AUGMENT_CALL_RELAX_COUNT) {
62243 			DUK_D(DUK_DPRINT("call stack limit reached but augmenting error and within relaxed limit"));
62244 			return;
62245 		}
62246 	}
62247 #endif
62248 
62249 	/* XXX: error message is a bit misleading: we reached a recursion
62250 	 * limit which is also essentially the same as a C callstack limit
62251 	 * (except perhaps with some relaxed threading assumptions).
62252 	 */
62253 	DUK_D(DUK_DPRINT("call prevented because call stack limit reached"));
62254 	DUK_ERROR_RANGE(thr, DUK_STR_CALLSTACK_LIMIT);
62255 	DUK_WO_NORETURN(return;);
62256 }
62257 
62258 DUK_LOCAL DUK_ALWAYS_INLINE void duk__call_callstack_limit_check(duk_hthread *thr) {
62259 	/* This check is forcibly inlined because it's very cheap and almost
62260 	 * always passes.  The slow path is forcibly noinline.
62261 	 */
62262 	if (DUK_LIKELY(thr->callstack_top < DUK_USE_CALLSTACK_LIMIT)) {
62263 		return;
62264 	}
62265 
62266 	duk__call_callstack_limit_check_slowpath(thr);
62267 }
62268 
62269 /*
62270  *  Interrupt counter fixup (for development only).
62271  */
62272 
62273 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
62274 DUK_LOCAL void duk__interrupt_fixup(duk_hthread *thr, duk_hthread *entry_curr_thread) {
62275 	/* Currently the bytecode executor and executor interrupt
62276 	 * instruction counts are off because we don't execute the
62277 	 * interrupt handler when we're about to exit from the initial
62278 	 * user call into Duktape.
62279 	 *
62280 	 * If we were to execute the interrupt handler here, the counts
62281 	 * would match.  You can enable this block manually to check
62282 	 * that this is the case.
62283 	 */
62284 
62285 	DUK_ASSERT(thr != NULL);
62286 	DUK_ASSERT(thr->heap != NULL);
62287 
62288 #if defined(DUK_USE_INTERRUPT_DEBUG_FIXUP)
62289 	if (entry_curr_thread == NULL) {
62290 		thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
62291 		thr->heap->inst_count_interrupt += thr->interrupt_init;
62292 		DUK_DD(DUK_DDPRINT("debug test: updated interrupt count on exit to "
62293 		                   "user code, instruction counts: executor=%ld, interrupt=%ld",
62294 		                   (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
62295 		DUK_ASSERT(thr->heap->inst_count_exec == thr->heap->inst_count_interrupt);
62296 	}
62297 #else
62298 	DUK_UNREF(thr);
62299 	DUK_UNREF(entry_curr_thread);
62300 #endif
62301 }
62302 #endif
62303 
62304 /*
62305  *  Arguments object creation.
62306  *
62307  *  Creating arguments objects involves many small details, see E5 Section
62308  *  10.6 for the specific requirements.  Much of the arguments object exotic
62309  *  behavior is implemented in duk_hobject_props.c, and is enabled by the
62310  *  object flag DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS.
62311  */
62312 
62313 DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
62314                                             duk_hobject *func,
62315                                             duk_hobject *varenv,
62316                                             duk_idx_t idx_args) {
62317 	duk_hobject *arg;          /* 'arguments' */
62318 	duk_hobject *formals;      /* formals for 'func' (may be NULL if func is a C function) */
62319 	duk_idx_t i_arg;
62320 	duk_idx_t i_map;
62321 	duk_idx_t i_mappednames;
62322 	duk_idx_t i_formals;
62323 	duk_idx_t i_argbase;
62324 	duk_idx_t n_formals;
62325 	duk_idx_t idx;
62326 	duk_idx_t num_stack_args;
62327 	duk_bool_t need_map;
62328 
62329 	DUK_ASSERT(thr != NULL);
62330 	DUK_ASSERT(func != NULL);
62331 	DUK_ASSERT(DUK_HOBJECT_IS_NONBOUND_FUNCTION(func));
62332 	DUK_ASSERT(varenv != NULL);
62333 
62334 	/* [ ... func this arg1(@idx_args) ... argN envobj ]
62335 	 * [ arg1(@idx_args) ... argN envobj ] (for tailcalls)
62336 	 */
62337 
62338 	need_map = 0;
62339 
62340 	i_argbase = idx_args;
62341 	num_stack_args = duk_get_top(thr) - i_argbase - 1;
62342 	DUK_ASSERT(i_argbase >= 0);
62343 	DUK_ASSERT(num_stack_args >= 0);
62344 
62345 	duk_push_hobject(thr, func);
62346 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_FORMALS);
62347 	formals = duk_get_hobject(thr, -1);
62348 	if (formals) {
62349 		n_formals = (duk_idx_t) duk_get_length(thr, -1);
62350 	} else {
62351 		/* This shouldn't happen without tampering of internal
62352 		 * properties: if a function accesses 'arguments', _Formals
62353 		 * is kept.  Check for the case anyway in case internal
62354 		 * properties have been modified manually.
62355 		 */
62356 		DUK_D(DUK_DPRINT("_Formals is undefined when creating arguments, use n_formals == 0"));
62357 		n_formals = 0;
62358 	}
62359 	duk_remove_m2(thr);  /* leave formals on stack for later use */
62360 	i_formals = duk_require_top_index(thr);
62361 
62362 	DUK_ASSERT(n_formals >= 0);
62363 	DUK_ASSERT(formals != NULL || n_formals == 0);
62364 
62365 	DUK_DDD(DUK_DDDPRINT("func=%!O, formals=%!O, n_formals=%ld",
62366 	                     (duk_heaphdr *) func, (duk_heaphdr *) formals,
62367 	                     (long) n_formals));
62368 
62369 	/* [ ... formals ] */
62370 
62371 	/*
62372 	 *  Create required objects:
62373 	 *    - 'arguments' object: array-like, but not an array
62374 	 *    - 'map' object: internal object, tied to 'arguments'
62375 	 *    - 'mappedNames' object: temporary value used during construction
62376 	 */
62377 
62378 	arg = duk_push_object_helper(thr,
62379 	                             DUK_HOBJECT_FLAG_EXTENSIBLE |
62380 	                             DUK_HOBJECT_FLAG_FASTREFS |
62381 	                             DUK_HOBJECT_FLAG_ARRAY_PART |
62382 	                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARGUMENTS),
62383 	                             DUK_BIDX_OBJECT_PROTOTYPE);
62384 	DUK_ASSERT(arg != NULL);
62385 	(void) duk_push_object_helper(thr,
62386 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
62387 	                              DUK_HOBJECT_FLAG_FASTREFS |
62388 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
62389 	                              -1);  /* no prototype */
62390 	(void) duk_push_object_helper(thr,
62391 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
62392 	                              DUK_HOBJECT_FLAG_FASTREFS |
62393 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
62394 	                              -1);  /* no prototype */
62395 	i_arg = duk_get_top(thr) - 3;
62396 	i_map = i_arg + 1;
62397 	i_mappednames = i_arg + 2;
62398 
62399 	/* [ ... formals arguments map mappedNames ] */
62400 
62401 	DUK_DDD(DUK_DDDPRINT("created arguments related objects: "
62402 	                     "arguments at index %ld -> %!O "
62403 	                     "map at index %ld -> %!O "
62404 	                     "mappednames at index %ld -> %!O",
62405 	                     (long) i_arg, (duk_heaphdr *) duk_get_hobject(thr, i_arg),
62406 	                     (long) i_map, (duk_heaphdr *) duk_get_hobject(thr, i_map),
62407 	                     (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(thr, i_mappednames)));
62408 
62409 	/*
62410 	 *  Init arguments properties, map, etc.
62411 	 */
62412 
62413 	duk_push_int(thr, num_stack_args);
62414 	duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_WC);
62415 
62416 	/*
62417 	 *  Init argument related properties.
62418 	 */
62419 
62420 	/* step 11 */
62421 	idx = num_stack_args - 1;
62422 	while (idx >= 0) {
62423 		DUK_DDD(DUK_DDDPRINT("arg idx %ld, argbase=%ld, argidx=%ld",
62424 		                     (long) idx, (long) i_argbase, (long) (i_argbase + idx)));
62425 
62426 		DUK_DDD(DUK_DDDPRINT("define arguments[%ld]=arg", (long) idx));
62427 		duk_dup(thr, i_argbase + idx);
62428 		duk_xdef_prop_index_wec(thr, i_arg, (duk_uarridx_t) idx);
62429 		DUK_DDD(DUK_DDDPRINT("defined arguments[%ld]=arg", (long) idx));
62430 
62431 		/* step 11.c is relevant only if non-strict (checked in 11.c.ii) */
62432 		if (!DUK_HOBJECT_HAS_STRICT(func) && idx < n_formals) {
62433 			DUK_ASSERT(formals != NULL);
62434 
62435 			DUK_DDD(DUK_DDDPRINT("strict function, index within formals (%ld < %ld)",
62436 			                     (long) idx, (long) n_formals));
62437 
62438 			duk_get_prop_index(thr, i_formals, (duk_uarridx_t) idx);
62439 			DUK_ASSERT(duk_is_string(thr, -1));
62440 
62441 			duk_dup_top(thr);  /* [ ... name name ] */
62442 
62443 			if (!duk_has_prop(thr, i_mappednames)) {
62444 				/* steps 11.c.ii.1 - 11.c.ii.4, but our internal book-keeping
62445 				 * differs from the reference model
62446 				 */
62447 
62448 				/* [ ... name ] */
62449 
62450 				need_map = 1;
62451 
62452 				DUK_DDD(DUK_DDDPRINT("set mappednames[%s]=%ld",
62453 				                     (const char *) duk_get_string(thr, -1),
62454 				                     (long) idx));
62455 				duk_dup_top(thr);                      /* name */
62456 				(void) duk_push_uint_to_hstring(thr, (duk_uint_t) idx);  /* index */
62457 				duk_xdef_prop_wec(thr, i_mappednames);  /* out of spec, must be configurable */
62458 
62459 				DUK_DDD(DUK_DDDPRINT("set map[%ld]=%s",
62460 				                     (long) idx,
62461 				                     duk_get_string(thr, -1)));
62462 				duk_dup_top(thr);         /* name */
62463 				duk_xdef_prop_index_wec(thr, i_map, (duk_uarridx_t) idx);  /* out of spec, must be configurable */
62464 			} else {
62465 				/* duk_has_prop() popped the second 'name' */
62466 			}
62467 
62468 			/* [ ... name ] */
62469 			duk_pop(thr);  /* pop 'name' */
62470 		}
62471 
62472 		idx--;
62473 	}
62474 
62475 	DUK_DDD(DUK_DDDPRINT("actual arguments processed"));
62476 
62477 	/* step 12 */
62478 	if (need_map) {
62479 		DUK_DDD(DUK_DDDPRINT("adding 'map' and 'varenv' to arguments object"));
62480 
62481 		/* should never happen for a strict callee */
62482 		DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(func));
62483 
62484 		duk_dup(thr, i_map);
62485 		duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_INT_MAP, DUK_PROPDESC_FLAGS_NONE);  /* out of spec, don't care */
62486 
62487 		/* The variable environment for magic variable bindings needs to be
62488 		 * given by the caller and recorded in the arguments object.
62489 		 *
62490 		 * See E5 Section 10.6, the creation of setters/getters.
62491 		 *
62492 		 * The variable environment also provides access to the callee, so
62493 		 * an explicit (internal) callee property is not needed.
62494 		 */
62495 
62496 		duk_push_hobject(thr, varenv);
62497 		duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_INT_VARENV, DUK_PROPDESC_FLAGS_NONE);  /* out of spec, don't care */
62498 	}
62499 
62500 	/* steps 13-14 */
62501 	if (DUK_HOBJECT_HAS_STRICT(func)) {
62502 		/* Callee/caller are throwers and are not deletable etc.  They
62503 		 * could be implemented as virtual properties, but currently
62504 		 * there is no support for virtual properties which are accessors
62505 		 * (only plain virtual properties).  This would not be difficult
62506 		 * to change in duk_hobject_props, but we can make the throwers
62507 		 * normal, concrete properties just as easily.
62508 		 *
62509 		 * Note that the specification requires that the *same* thrower
62510 		 * built-in object is used here!  See E5 Section 10.6 main
62511 		 * algoritm, step 14, and Section 13.2.3 which describes the
62512 		 * thrower.  See test case test-arguments-throwers.js.
62513 		 */
62514 
62515 		DUK_DDD(DUK_DDDPRINT("strict function, setting caller/callee to throwers"));
62516 
62517 		duk_xdef_prop_stridx_thrower(thr, i_arg, DUK_STRIDX_CALLER);
62518 		duk_xdef_prop_stridx_thrower(thr, i_arg, DUK_STRIDX_CALLEE);
62519 	} else {
62520 		DUK_DDD(DUK_DDDPRINT("non-strict function, setting callee to actual value"));
62521 		duk_push_hobject(thr, func);
62522 		duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_CALLEE, DUK_PROPDESC_FLAGS_WC);
62523 	}
62524 
62525 	/* set exotic behavior only after we're done */
62526 	if (need_map) {
62527 		/* Exotic behaviors are only enabled for arguments objects
62528 		 * which have a parameter map (see E5 Section 10.6 main
62529 		 * algorithm, step 12).
62530 		 *
62531 		 * In particular, a non-strict arguments object with no
62532 		 * mapped formals does *NOT* get exotic behavior, even
62533 		 * for e.g. "caller" property.  This seems counterintuitive
62534 		 * but seems to be the case.
62535 		 */
62536 
62537 		/* cannot be strict (never mapped variables) */
62538 		DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(func));
62539 
62540 		DUK_DDD(DUK_DDDPRINT("enabling exotic behavior for arguments object"));
62541 		DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(arg);
62542 	} else {
62543 		DUK_DDD(DUK_DDDPRINT("not enabling exotic behavior for arguments object"));
62544 	}
62545 
62546 	DUK_DDD(DUK_DDDPRINT("final arguments related objects: "
62547 	                     "arguments at index %ld -> %!O "
62548 	                     "map at index %ld -> %!O "
62549 	                     "mappednames at index %ld -> %!O",
62550 	                     (long) i_arg, (duk_heaphdr *) duk_get_hobject(thr, i_arg),
62551 	                     (long) i_map, (duk_heaphdr *) duk_get_hobject(thr, i_map),
62552 	                     (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(thr, i_mappednames)));
62553 
62554 	/* [ args(n) envobj formals arguments map mappednames ] */
62555 
62556 	duk_pop_2(thr);
62557 	duk_remove_m2(thr);
62558 
62559 	/* [ args(n) envobj arguments ] */
62560 }
62561 
62562 /* Helper for creating the arguments object and adding it to the env record
62563  * on top of the value stack.
62564  */
62565 DUK_LOCAL void duk__handle_createargs_for_call(duk_hthread *thr,
62566                                                duk_hobject *func,
62567                                                duk_hobject *env,
62568                                                duk_idx_t idx_args) {
62569 	DUK_DDD(DUK_DDDPRINT("creating arguments object for function call"));
62570 
62571 	DUK_ASSERT(thr != NULL);
62572 	DUK_ASSERT(func != NULL);
62573 	DUK_ASSERT(env != NULL);
62574 	DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
62575 
62576 	/* [ ... arg1 ... argN envobj ] */
62577 
62578 	duk__create_arguments_object(thr,
62579 	                             func,
62580 	                             env,
62581 	                             idx_args);
62582 
62583 	/* [ ... arg1 ... argN envobj argobj ] */
62584 
62585 	duk_xdef_prop_stridx_short(thr,
62586 	                           -2,
62587 	                           DUK_STRIDX_LC_ARGUMENTS,
62588 	                           DUK_HOBJECT_HAS_STRICT(func) ? DUK_PROPDESC_FLAGS_E :   /* strict: non-deletable, non-writable */
62589 	                                                          DUK_PROPDESC_FLAGS_WE);  /* non-strict: non-deletable, writable */
62590 	/* [ ... arg1 ... argN envobj ] */
62591 }
62592 
62593 /*
62594  *  Helpers for constructor call handling.
62595  *
62596  *  There are two [[Construct]] operations in the specification:
62597  *
62598  *    - E5 Section 13.2.2: for Function objects
62599  *    - E5 Section 15.3.4.5.2: for "bound" Function objects
62600  *
62601  *  The chain of bound functions is resolved in Section 15.3.4.5.2,
62602  *  with arguments "piling up" until the [[Construct]] internal
62603  *  method is called on the final, actual Function object.  Note
62604  *  that the "prototype" property is looked up *only* from the
62605  *  final object, *before* calling the constructor.
62606  *
62607  *  Since Duktape 2.2 bound functions are represented with the
62608  *  duk_hboundfunc internal type, and bound function chains are
62609  *  collapsed when a bound function is created.  As a result, the
62610  *  direct target of a duk_hboundfunc is always non-bound and the
62611  *  this/argument lists have been resolved.
62612  *
62613  *  When constructing new Array instances, an unnecessary object is
62614  *  created and discarded now: the standard [[Construct]] creates an
62615  *  object, and calls the Array constructor.  The Array constructor
62616  *  returns an Array instance, which is used as the result value for
62617  *  the "new" operation; the object created before the Array constructor
62618  *  call is discarded.
62619  *
62620  *  This would be easy to fix, e.g. by knowing that the Array constructor
62621  *  will always create a replacement object and skip creating the fallback
62622  *  object in that case.
62623  */
62624 
62625 /* Update default instance prototype for constructor call. */
62626 DUK_LOCAL void duk__update_default_instance_proto(duk_hthread *thr, duk_idx_t idx_func) {
62627 	duk_hobject *proto;
62628 	duk_hobject *fallback;
62629 
62630 	DUK_ASSERT(duk_is_constructable(thr, idx_func));
62631 
62632 	duk_get_prop_stridx_short(thr, idx_func, DUK_STRIDX_PROTOTYPE);
62633 	proto = duk_get_hobject(thr, -1);
62634 	if (proto == NULL) {
62635 		DUK_DDD(DUK_DDDPRINT("constructor has no 'prototype' property, or value not an object "
62636 		                     "-> leave standard Object prototype as fallback prototype"));
62637 	} else {
62638 		DUK_DDD(DUK_DDDPRINT("constructor has 'prototype' property with object value "
62639 		                     "-> set fallback prototype to that value: %!iO", (duk_heaphdr *) proto));
62640 		/* Original fallback (default instance) is untouched when
62641 		 * resolving bound functions etc.
62642 		 */
62643 		fallback = duk_known_hobject(thr, idx_func + 1);
62644 		DUK_ASSERT(fallback != NULL);
62645 		DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, fallback, proto);
62646 	}
62647 	duk_pop(thr);
62648 }
62649 
62650 /* Postprocess: return value special handling, error augmentation. */
62651 DUK_INTERNAL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uint_t proxy_invariant) {
62652 	/* Use either fallback (default instance) or retval depending
62653 	 * on retval type.  Needs to be called before unwind because
62654 	 * the default instance is read from the current (immutable)
62655 	 * 'this' binding.
62656 	 *
62657 	 * For Proxy 'construct' calls the return value must be an
62658 	 * Object (we accept object-like values like buffers and
62659 	 * lightfuncs too).  If not, TypeError.
62660 	 */
62661 	if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |
62662 	                                 DUK_TYPE_MASK_BUFFER |
62663 	                                 DUK_TYPE_MASK_LIGHTFUNC)) {
62664 		DUK_DDD(DUK_DDDPRINT("replacement value"));
62665 	} else {
62666 		if (DUK_UNLIKELY(proxy_invariant != 0U)) {
62667 			/* Proxy 'construct' return value invariant violated. */
62668 			DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr);
62669 			DUK_WO_NORETURN(return;);
62670 		}
62671 		/* XXX: direct value stack access */
62672 		duk_pop(thr);
62673 		duk_push_this(thr);
62674 	}
62675 
62676 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
62677 	/* Augment created errors upon creation, not when they are thrown or
62678 	 * rethrown.  __FILE__ and __LINE__ are not desirable here; the call
62679 	 * stack reflects the caller which is correct.  Skip topmost, unwound
62680 	 * activation when creating a traceback.  If thr->ptr_curr_pc was !=
62681 	 * NULL we'd need to sync the current PC so that the traceback comes
62682 	 * out right; however it is always synced here so just assert for it.
62683 	 */
62684 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
62685 	duk_err_augment_error_create(thr, thr, NULL, 0, DUK_AUGMENT_FLAG_NOBLAME_FILELINE |
62686 	                                                DUK_AUGMENT_FLAG_SKIP_ONE);
62687 #endif
62688 }
62689 
62690 /*
62691  *  Helper for handling a bound function when a call is being made.
62692  *
62693  *  Assumes that bound function chains have been "collapsed" so that either
62694  *  the target is non-bound or there is one bound function that points to a
62695  *  nonbound target.
62696  *
62697  *  Prepends the bound arguments to the value stack (at idx_func + 2).
62698  *  The 'this' binding is also updated if necessary (at idx_func + 1).
62699  *  Note that for constructor calls the 'this' binding is never updated by
62700  *  [[BoundThis]].
62701  */
62702 
62703 DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr,
62704                                                 duk_idx_t idx_func,
62705                                                 duk_bool_t is_constructor_call) {
62706 	duk_tval *tv_func;
62707 	duk_hobject *func;
62708 	duk_idx_t len;
62709 
62710 	DUK_ASSERT(thr != NULL);
62711 
62712 	/* On entry, item at idx_func is a bound, non-lightweight function,
62713 	 * but we don't rely on that below.
62714 	 */
62715 
62716 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
62717 
62718 	tv_func = duk_require_tval(thr, idx_func);
62719 	DUK_ASSERT(tv_func != NULL);
62720 
62721 	if (DUK_TVAL_IS_OBJECT(tv_func)) {
62722 		func = DUK_TVAL_GET_OBJECT(tv_func);
62723 
62724 		/* XXX: separate helper function, out of fast path? */
62725 		if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
62726 			duk_hboundfunc *h_bound;
62727 			duk_tval *tv_args;
62728 			duk_tval *tv_gap;
62729 
62730 			h_bound = (duk_hboundfunc *) (void *) func;
62731 			tv_args = h_bound->args;
62732 			len = h_bound->nargs;
62733 			DUK_ASSERT(len == 0 || tv_args != NULL);
62734 
62735 			DUK_DDD(DUK_DDDPRINT("bound function encountered, ptr=%p: %!T",
62736 			                     (void *) DUK_TVAL_GET_OBJECT(tv_func), tv_func));
62737 
62738 			/* [ ... func this arg1 ... argN ] */
62739 
62740 			if (is_constructor_call) {
62741 				/* See: tests/ecmascript/test-spec-bound-constructor.js */
62742 				DUK_DDD(DUK_DDDPRINT("constructor call: don't update this binding"));
62743 			} else {
62744 				/* XXX: duk_replace_tval */
62745 				duk_push_tval(thr, &h_bound->this_binding);
62746 				duk_replace(thr, idx_func + 1);  /* idx_this = idx_func + 1 */
62747 			}
62748 
62749 			/* [ ... func this arg1 ... argN ] */
62750 
62751 			duk_require_stack(thr, len);
62752 
62753 			tv_gap = duk_reserve_gap(thr, idx_func + 2, len);
62754 			duk_copy_tvals_incref(thr, tv_gap, tv_args, (duk_size_t) len);
62755 
62756 			/* [ ... func this <bound args> arg1 ... argN ] */
62757 
62758 			duk_push_tval(thr, &h_bound->target);
62759 			duk_replace(thr, idx_func);  /* replace in stack */
62760 
62761 			DUK_DDD(DUK_DDDPRINT("bound function handled, idx_func=%ld, curr func=%!T",
62762 			                     (long) idx_func, duk_get_tval(thr, idx_func)));
62763 		}
62764 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
62765 		/* Lightweight function: never bound, so terminate. */
62766 		;
62767 	} else {
62768 		/* Shouldn't happen, so ugly error is enough. */
62769 		DUK_ERROR_INTERNAL(thr);
62770 		DUK_WO_NORETURN(return;);
62771 	}
62772 
62773 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
62774 
62775 	DUK_DDD(DUK_DDDPRINT("final non-bound function is: %!T", duk_get_tval(thr, idx_func)));
62776 
62777 #if defined(DUK_USE_ASSERTIONS)
62778 	tv_func = duk_require_tval(thr, idx_func);
62779 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func) || DUK_TVAL_IS_OBJECT(tv_func));
62780 	if (DUK_TVAL_IS_OBJECT(tv_func)) {
62781 		func = DUK_TVAL_GET_OBJECT(tv_func);
62782 		DUK_ASSERT(func != NULL);
62783 		DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
62784 		DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func) ||
62785 		           DUK_HOBJECT_HAS_NATFUNC(func));
62786 	}
62787 #endif
62788 }
62789 
62790 /*
62791  *  Helper for inline handling of .call(), .apply(), and .construct().
62792  */
62793 
62794 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) {
62795 #if defined(DUK_USE_ASSERTIONS)
62796 	duk_c_function natfunc;
62797 #endif
62798 	duk_tval *tv_args;
62799 
62800 	DUK_ASSERT(func != NULL);
62801 	DUK_ASSERT((*call_flags & DUK_CALL_FLAG_CONSTRUCT) == 0);  /* Caller. */
62802 
62803 #if defined(DUK_USE_ASSERTIONS)
62804 	natfunc = ((duk_hnatfunc *) func)->func;
62805 	DUK_ASSERT(natfunc != NULL);
62806 #endif
62807 
62808 	/* On every round of function resolution at least target function and
62809 	 * 'this' binding are set.  We can assume that here, and must guarantee
62810 	 * it on exit.  Value stack reserve is extended for bound function and
62811 	 * .apply() unpacking so we don't need to extend it here when we need a
62812 	 * few slots.
62813 	 */
62814 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
62815 
62816 	/* Handle native 'eval' specially.  A direct eval check is only made
62817 	 * for the first resolution attempt; e.g. a bound eval call is -not-
62818 	 * a direct eval call.
62819 	 */
62820 	if (DUK_UNLIKELY(((duk_hnatfunc *) func)->magic == 15)) {
62821 		/* For now no special handling except for direct eval
62822 		 * detection.
62823 		 */
62824 		DUK_ASSERT(((duk_hnatfunc *) func)->func == duk_bi_global_object_eval);
62825 		if (first && (*call_flags & DUK_CALL_FLAG_CALLED_AS_EVAL)) {
62826 			*call_flags = (*call_flags & ~DUK_CALL_FLAG_CALLED_AS_EVAL) | DUK_CALL_FLAG_DIRECT_EVAL;
62827 		}
62828 		DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
62829 		return 1;  /* stop resolving */
62830 	}
62831 
62832 	/* Handle special functions based on the DUK_HOBJECT_FLAG_SPECIAL_CALL
62833 	 * flag; their magic value is used for switch-case.
62834 	 *
62835 	 * NOTE: duk_unpack_array_like() reserves value stack space
62836 	 * for the result values (unlike most other value stack calls).
62837 	 */
62838 	switch (((duk_hnatfunc *) func)->magic) {
62839 	case 0: {  /* 0=Function.prototype.call() */
62840 		/* Value stack:
62841 		 * idx_func + 0: Function.prototype.call()  [removed]
62842 		 * idx_func + 1: this binding for .call (target function)
62843 		 * idx_func + 2: 1st argument to .call, desired 'this' binding
62844 		 * idx_func + 3: 2nd argument to .call, desired 1st argument for ultimate target
62845 		 * ...
62846 		 *
62847 		 * Remove idx_func + 0 to get:
62848 		 * idx_func + 0: target function
62849 		 * idx_func + 1: this binding
62850 		 * idx_func + 2: call arguments
62851 		 * ...
62852 		 */
62853 		DUK_ASSERT(natfunc == duk_bi_function_prototype_call);
62854 		duk_remove_unsafe(thr, idx_func);
62855 		tv_args = thr->valstack_bottom + idx_func + 2;
62856 		if (thr->valstack_top < tv_args) {
62857 			DUK_ASSERT(tv_args <= thr->valstack_end);
62858 			thr->valstack_top = tv_args;  /* at least target function and 'this' binding present */
62859 		}
62860 		break;
62861 	}
62862 	case 1: {  /* 1=Function.prototype.apply() */
62863 		/* Value stack:
62864 		 * idx_func + 0: Function.prototype.apply()  [removed]
62865 		 * idx_func + 1: this binding for .apply (target function)
62866 		 * idx_func + 2: 1st argument to .apply, desired 'this' binding
62867 		 * idx_func + 3: 2nd argument to .apply, argArray
62868 		 * [anything after this MUST be ignored]
62869 		 *
62870 		 * Remove idx_func + 0 and unpack the argArray to get:
62871 		 * idx_func + 0: target function
62872 		 * idx_func + 1: this binding
62873 		 * idx_func + 2: call arguments
62874 		 * ...
62875 		 */
62876 		DUK_ASSERT(natfunc == duk_bi_function_prototype_apply);
62877 		duk_remove_unsafe(thr, idx_func);
62878 		goto apply_shared;
62879 	}
62880 #if defined(DUK_USE_REFLECT_BUILTIN)
62881 	case 2: {  /* 2=Reflect.apply() */
62882 		/* Value stack:
62883 		 * idx_func + 0: Reflect.apply()  [removed]
62884 		 * idx_func + 1: this binding for .apply (ignored, usually Reflect)  [removed]
62885 		 * idx_func + 2: 1st argument to .apply, target function
62886 		 * idx_func + 3: 2nd argument to .apply, desired 'this' binding
62887 		 * idx_func + 4: 3rd argument to .apply, argArray
62888 		 * [anything after this MUST be ignored]
62889 		 *
62890 		 * Remove idx_func + 0 and idx_func + 1, and unpack the argArray to get:
62891 		 * idx_func + 0: target function
62892 		 * idx_func + 1: this binding
62893 		 * idx_func + 2: call arguments
62894 		 * ...
62895 		 */
62896 		DUK_ASSERT(natfunc == duk_bi_reflect_apply);
62897 		duk_remove_n_unsafe(thr, idx_func, 2);
62898 		goto apply_shared;
62899 	}
62900 	case 3: {  /* 3=Reflect.construct() */
62901 		/* Value stack:
62902 		 * idx_func + 0: Reflect.construct()  [removed]
62903 		 * idx_func + 1: this binding for .construct (ignored, usually Reflect)  [removed]
62904 		 * idx_func + 2: 1st argument to .construct, target function
62905 		 * idx_func + 3: 2nd argument to .construct, argArray
62906 		 * idx_func + 4: 3rd argument to .construct, newTarget
62907 		 * [anything after this MUST be ignored]
62908 		 *
62909 		 * Remove idx_func + 0 and idx_func + 1, unpack the argArray,
62910 		 * and insert default instance (prototype not yet updated), to get:
62911 		 * idx_func + 0: target function
62912 		 * idx_func + 1: this binding (default instance)
62913 		 * idx_func + 2: constructor call arguments
62914 		 * ...
62915 		 *
62916 		 * Call flags must be updated to reflect the fact that we're
62917 		 * now dealing with a constructor call, and e.g. the 'this'
62918 		 * binding cannot be overwritten if the target is bound.
62919 		 *
62920 		 * newTarget is checked but not yet passed onwards.
62921 		 */
62922 
62923 		duk_idx_t top;
62924 
62925 		DUK_ASSERT(natfunc == duk_bi_reflect_construct);
62926 		*call_flags |= DUK_CALL_FLAG_CONSTRUCT;
62927 		duk_remove_n_unsafe(thr, idx_func, 2);
62928 		top = duk_get_top(thr);
62929 		if (!duk_is_constructable(thr, idx_func)) {
62930 			/* Target constructability must be checked before
62931 			 * unpacking argArray (which may cause side effects).
62932 			 * Just return; caller will throw the error.
62933 			 */
62934 			duk_set_top_unsafe(thr, idx_func + 2);  /* satisfy asserts */
62935 			break;
62936 		}
62937 		duk_push_object(thr);
62938 		duk_insert(thr, idx_func + 1);  /* default instance */
62939 
62940 		/* [ ... func default_instance argArray newTarget? ] */
62941 
62942 		top = duk_get_top(thr);
62943 		if (top < idx_func + 3) {
62944 			/* argArray is a mandatory argument for Reflect.construct(). */
62945 			DUK_ERROR_TYPE_INVALID_ARGS(thr);
62946 			DUK_WO_NORETURN(return 0;);
62947 		}
62948 		if (top > idx_func + 3) {
62949 			if (!duk_strict_equals(thr, idx_func, idx_func + 3)) {
62950 				/* XXX: [[Construct]] newTarget currently unsupported */
62951 				DUK_ERROR_UNSUPPORTED(thr);
62952 				DUK_WO_NORETURN(return 0;);
62953 			}
62954 			duk_set_top_unsafe(thr, idx_func + 3);  /* remove any args beyond argArray */
62955 		}
62956 		DUK_ASSERT(duk_get_top(thr) == idx_func + 3);
62957 		DUK_ASSERT(duk_is_valid_index(thr, idx_func + 2));
62958 		(void) duk_unpack_array_like(thr, idx_func + 2);  /* XXX: should also remove target to be symmetric with duk_pack()? */
62959 		duk_remove(thr, idx_func + 2);
62960 		DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
62961 		break;
62962 	}
62963 #endif  /* DUK_USE_REFLECT_BUILTIN */
62964 	default: {
62965 		DUK_ASSERT(0);
62966 		DUK_UNREACHABLE();
62967 	}
62968 	}
62969 
62970 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
62971 	return 0;  /* keep resolving */
62972 
62973  apply_shared:
62974 	tv_args = thr->valstack_bottom + idx_func + 2;
62975 	if (thr->valstack_top <= tv_args) {
62976 		DUK_ASSERT(tv_args <= thr->valstack_end);
62977 		thr->valstack_top = tv_args;  /* at least target func and 'this' binding present */
62978 		/* No need to check for argArray. */
62979 	} else {
62980 		DUK_ASSERT(duk_get_top(thr) >= idx_func + 3);  /* idx_func + 2 covered above */
62981 		if (thr->valstack_top > tv_args + 1) {
62982 			duk_set_top_unsafe(thr, idx_func + 3);  /* remove any args beyond argArray */
62983 		}
62984 		DUK_ASSERT(duk_is_valid_index(thr, idx_func + 2));
62985 		if (!duk_is_callable(thr, idx_func)) {
62986 			/* Avoid unpack side effects if the target isn't callable.
62987 			 * Calling code will throw the actual error.
62988 			 */
62989 		} else {
62990 			(void) duk_unpack_array_like(thr, idx_func + 2);
62991 			duk_remove(thr, idx_func + 2);
62992 		}
62993 	}
62994 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
62995 	return 0;  /* keep resolving */
62996 }
62997 
62998 /*
62999  *  Helper for Proxy handling.
63000  */
63001 
63002 #if defined(DUK_USE_ES6_PROXY)
63003 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) {
63004 	duk_bool_t rc;
63005 
63006 	/* Value stack:
63007 	 * idx_func + 0: Proxy object
63008 	 * idx_func + 1: this binding for call
63009 	 * idx_func + 2: 1st argument for call
63010 	 * idx_func + 3: 2nd argument for call
63011 	 * ...
63012 	 *
63013 	 * If Proxy doesn't have a trap for the call ('apply' or 'construct'),
63014 	 * replace Proxy object with target object.
63015 	 *
63016 	 * If we're dealing with a normal call and the Proxy has an 'apply'
63017 	 * trap, manipulate value stack to:
63018 	 *
63019 	 * idx_func + 0: trap
63020 	 * idx_func + 1: Proxy's handler
63021 	 * idx_func + 2: Proxy's target
63022 	 * idx_func + 3: this binding for call (from idx_func + 1)
63023 	 * idx_func + 4: call arguments packed to an array
63024 	 *
63025 	 * If we're dealing with a constructor call and the Proxy has a
63026 	 * 'construct' trap, manipulate value stack to:
63027 	 *
63028 	 * idx_func + 0: trap
63029 	 * idx_func + 1: Proxy's handler
63030 	 * idx_func + 2: Proxy's target
63031 	 * idx_func + 3: call arguments packed to an array
63032 	 * idx_func + 4: newTarget == Proxy object here
63033 	 *
63034 	 * As we don't yet have proper newTarget support, the newTarget at
63035 	 * idx_func + 3 is just the original constructor being called, i.e.
63036 	 * the Proxy object (not the target).  Note that the default instance
63037 	 * (original 'this' binding) is dropped and ignored.
63038 	 */
63039 
63040 	duk_push_hobject(thr, h_proxy->handler);
63041 	rc = duk_get_prop_stridx_short(thr, -1, (*call_flags & DUK_CALL_FLAG_CONSTRUCT) ? DUK_STRIDX_CONSTRUCT : DUK_STRIDX_APPLY);
63042 	if (rc == 0) {
63043 		/* Not found, continue to target.  If this is a construct
63044 		 * call, update default instance prototype using the Proxy,
63045 		 * not the target.
63046 		 */
63047 		if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
63048 			if (!(*call_flags & DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED)) {
63049 				*call_flags |= DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED;
63050 				duk__update_default_instance_proto(thr, idx_func);
63051 			}
63052 		}
63053 		duk_pop_2(thr);
63054 		duk_push_hobject(thr, h_proxy->target);
63055 		duk_replace(thr, idx_func);
63056 		return;
63057 	}
63058 
63059 	/* Here we must be careful not to replace idx_func while
63060 	 * h_proxy is still needed, otherwise h_proxy may become
63061 	 * dangling.  This could be improved e.g. using a
63062 	 * duk_pack_slice() with a freeform slice.
63063 	 */
63064 
63065 	/* Here:
63066 	 * idx_func + 0: Proxy object
63067 	 * idx_func + 1: this binding for call
63068 	 * idx_func + 2: 1st argument for call
63069 	 * idx_func + 3: 2nd argument for call
63070 	 * ...
63071 	 * idx_func + N: handler
63072 	 * idx_func + N + 1: trap
63073 	 */
63074 
63075 	duk_insert(thr, idx_func + 1);
63076 	duk_insert(thr, idx_func + 2);
63077 	duk_push_hobject(thr, h_proxy->target);
63078 	duk_insert(thr, idx_func + 3);
63079 	duk_pack(thr, duk_get_top(thr) - (idx_func + 5));
63080 
63081 	/* Here:
63082 	 * idx_func + 0: Proxy object
63083 	 * idx_func + 1: trap
63084 	 * idx_func + 2: Proxy's handler
63085 	 * idx_func + 3: Proxy's target
63086 	 * idx_func + 4: this binding for call
63087 	 * idx_func + 5: arguments array
63088 	 */
63089 	DUK_ASSERT(duk_get_top(thr) == idx_func + 6);
63090 
63091 	if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
63092 		*call_flags |= DUK_CALL_FLAG_CONSTRUCT_PROXY;  /* Enable 'construct' trap return invariant check. */
63093 		*call_flags &= ~(DUK_CALL_FLAG_CONSTRUCT);     /* Resume as non-constructor call to the trap. */
63094 
63095 		/* 'apply' args: target, thisArg, argArray
63096 		 * 'construct' args: target, argArray, newTarget
63097 		 */
63098 		duk_remove(thr, idx_func + 4);
63099 		duk_push_hobject(thr, (duk_hobject *) h_proxy);
63100 	}
63101 
63102 	/* Finalize value stack layout by removing Proxy reference. */
63103 	duk_remove(thr, idx_func);
63104 	h_proxy = NULL;  /* invalidated */
63105 	DUK_ASSERT(duk_get_top(thr) == idx_func + 5);
63106 }
63107 #endif  /* DUK_USE_ES6_PROXY */
63108 
63109 /*
63110  *  Helper for setting up var_env and lex_env of an activation,
63111  *  assuming it does NOT have the DUK_HOBJECT_FLAG_NEWENV flag.
63112  */
63113 
63114 DUK_LOCAL void duk__handle_oldenv_for_call(duk_hthread *thr,
63115                                            duk_hobject *func,
63116                                            duk_activation *act) {
63117 	duk_hcompfunc *f;
63118 	duk_hobject *h_lex;
63119 	duk_hobject *h_var;
63120 
63121 	DUK_ASSERT(thr != NULL);
63122 	DUK_ASSERT(func != NULL);
63123 	DUK_ASSERT(act != NULL);
63124 	DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV(func));
63125 	DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
63126 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(func));
63127 	DUK_UNREF(thr);
63128 
63129 	f = (duk_hcompfunc *) func;
63130 	h_lex = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
63131 	h_var = DUK_HCOMPFUNC_GET_VARENV(thr->heap, f);
63132 	DUK_ASSERT(h_lex != NULL);  /* Always true for closures (not for templates) */
63133 	DUK_ASSERT(h_var != NULL);
63134 	act->lex_env = h_lex;
63135 	act->var_env = h_var;
63136 	DUK_HOBJECT_INCREF(thr, h_lex);
63137 	DUK_HOBJECT_INCREF(thr, h_var);
63138 }
63139 
63140 /*
63141  *  Helper for updating callee 'caller' property.
63142  */
63143 
63144 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
63145 DUK_LOCAL void duk__update_func_caller_prop(duk_hthread *thr, duk_hobject *func) {
63146 	duk_tval *tv_caller;
63147 	duk_hobject *h_tmp;
63148 	duk_activation *act_callee;
63149 	duk_activation *act_caller;
63150 
63151 	DUK_ASSERT(thr != NULL);
63152 	DUK_ASSERT(func != NULL);
63153 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound chain resolved */
63154 	DUK_ASSERT(thr->callstack_top >= 1);
63155 
63156 	if (DUK_HOBJECT_HAS_STRICT(func)) {
63157 		/* Strict functions don't get their 'caller' updated. */
63158 		return;
63159 	}
63160 
63161 	DUK_ASSERT(thr->callstack_top > 0);
63162 	act_callee = thr->callstack_curr;
63163 	DUK_ASSERT(act_callee != NULL);
63164 	act_caller = (thr->callstack_top >= 2 ? act_callee->parent : NULL);
63165 
63166 	/* XXX: check .caller writability? */
63167 
63168 	/* Backup 'caller' property and update its value. */
63169 	tv_caller = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_CALLER(thr));
63170 	if (tv_caller) {
63171 		/* If caller is global/eval code, 'caller' should be set to
63172 		 * 'null'.
63173 		 *
63174 		 * XXX: there is no exotic flag to infer this correctly now.
63175 		 * The NEWENV flag is used now which works as intended for
63176 		 * everything (global code, non-strict eval code, and functions)
63177 		 * except strict eval code.  Bound functions are never an issue
63178 		 * because 'func' has been resolved to a non-bound function.
63179 		 */
63180 
63181 		if (act_caller != NULL) {
63182 			/* act_caller->func may be NULL in some finalization cases,
63183 			 * just treat like we don't know the caller.
63184 			 */
63185 			if (act_caller->func && !DUK_HOBJECT_HAS_NEWENV(act_caller->func)) {
63186 				/* Setting to NULL causes 'caller' to be set to
63187 				 * 'null' as desired.
63188 				 */
63189 				act_caller = NULL;
63190 			}
63191 		}
63192 
63193 		if (DUK_TVAL_IS_OBJECT(tv_caller)) {
63194 			h_tmp = DUK_TVAL_GET_OBJECT(tv_caller);
63195 			DUK_ASSERT(h_tmp != NULL);
63196 			act_callee->prev_caller = h_tmp;
63197 
63198 			/* Previous value doesn't need refcount changes because its ownership
63199 			 * is transferred to prev_caller.
63200 			 */
63201 
63202 			if (act_caller != NULL) {
63203 				DUK_ASSERT(act_caller->func != NULL);
63204 				DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
63205 				DUK_TVAL_INCREF(thr, tv_caller);
63206 			} else {
63207 				DUK_TVAL_SET_NULL(tv_caller);  /* no incref */
63208 			}
63209 		} else {
63210 			/* 'caller' must only take on 'null' or function value */
63211 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_caller));
63212 			DUK_ASSERT(act_callee->prev_caller == NULL);
63213 			if (act_caller != NULL && act_caller->func) {
63214 				/* Tolerate act_caller->func == NULL which happens in
63215 				 * some finalization cases; treat like unknown caller.
63216 				 */
63217 				DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
63218 				DUK_TVAL_INCREF(thr, tv_caller);
63219 			} else {
63220 				DUK_TVAL_SET_NULL(tv_caller);  /* no incref */
63221 			}
63222 		}
63223 	}
63224 }
63225 #endif  /* DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
63226 
63227 /*
63228  *  Shared helpers for resolving the final, non-bound target function of the
63229  *  call and the effective 'this' binding.  Resolves bound functions and
63230  *  applies .call(), .apply(), and .construct() inline.
63231  *
63232  *  Proxy traps are also handled inline so that if the target is a Proxy with
63233  *  a 'call' or 'construct' trap, the trap handler is called with a modified
63234  *  argument list.
63235  *
63236  *  Once the bound function / .call() / .apply() / .construct() sequence has
63237  *  been resolved, the value at idx_func + 1 may need coercion described in
63238  *  E5 Section 10.4.3.
63239  *
63240  *  A call that begins as a non-constructor call may be converted into a
63241  *  constructor call during the resolution process if Reflect.construct()
63242  *  is invoked.  This is handled by updating the caller's call_flags.
63243  *
63244  *  For global and eval code (E5 Sections 10.4.1 and 10.4.2), we assume
63245  *  that the caller has provided the correct 'this' binding explicitly
63246  *  when calling, i.e.:
63247  *
63248  *    - global code: this=global object
63249  *    - direct eval: this=copy from eval() caller's this binding
63250  *    - other eval:  this=global object
63251  *
63252  *  The 'this' coercion may cause a recursive function call with arbitrary
63253  *  side effects, because ToObject() may be called.
63254  */
63255 
63256 DUK_LOCAL DUK_INLINE void duk__coerce_nonstrict_this_binding(duk_hthread *thr, duk_idx_t idx_this) {
63257 	duk_tval *tv_this;
63258 	duk_hobject *obj_global;
63259 
63260 	tv_this = thr->valstack_bottom + idx_this;
63261 	switch (DUK_TVAL_GET_TAG(tv_this)) {
63262 	case DUK_TAG_OBJECT:
63263 		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, object -> use directly"));
63264 		break;
63265 	case DUK_TAG_UNDEFINED:
63266 	case DUK_TAG_NULL:
63267 		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, undefined/null -> use global object"));
63268 		obj_global = thr->builtins[DUK_BIDX_GLOBAL];
63269 		/* XXX: avoid this check somehow */
63270 		if (DUK_LIKELY(obj_global != NULL)) {
63271 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this));  /* no need to decref previous value */
63272 			DUK_TVAL_SET_OBJECT(tv_this, obj_global);
63273 			DUK_HOBJECT_INCREF(thr, obj_global);
63274 		} else {
63275 			/* This may only happen if built-ins are being "torn down".
63276 			 * This behavior is out of specification scope.
63277 			 */
63278 			DUK_D(DUK_DPRINT("this binding: wanted to use global object, but it is NULL -> using undefined instead"));
63279 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this));  /* no need to decref previous value */
63280 			DUK_TVAL_SET_UNDEFINED(tv_this);  /* nothing to incref */
63281 		}
63282 		break;
63283 	default:
63284 		/* Plain buffers and lightfuncs are object coerced.  Lightfuncs
63285 		 * very rarely come here however, because the call target would
63286 		 * need to be a non-strict non-lightfunc (lightfuncs are considered
63287 		 * strict) with an explicit lightfunc 'this' binding.
63288 		 */
63289 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_this));
63290 		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, not object/undefined/null -> use ToObject(value)"));
63291 		duk_to_object(thr, idx_this);  /* may have side effects */
63292 		break;
63293 	}
63294 }
63295 
63296 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) {
63297 #if defined(DUK_USE_PREFER_SIZE)
63298 	DUK_UNREF(thr);
63299 	DUK_UNREF(idx_func);
63300 	DUK_UNREF(out_func);
63301 	DUK_UNREF(call_flags);
63302 #else  /* DUK_USE_PREFER_SIZE */
63303 	duk_tval *tv_func;
63304 	duk_hobject *func;
63305 
63306 	if (DUK_UNLIKELY(call_flags & DUK_CALL_FLAG_CONSTRUCT)) {
63307 		return 0;
63308 	}
63309 
63310 	tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
63311 	DUK_ASSERT(tv_func != NULL);
63312 
63313 	if (DUK_LIKELY(DUK_TVAL_IS_OBJECT(tv_func))) {
63314 		func = DUK_TVAL_GET_OBJECT(tv_func);
63315 		if (DUK_HOBJECT_IS_CALLABLE(func) &&
63316 		    !DUK_HOBJECT_HAS_BOUNDFUNC(func) &&
63317 		    !DUK_HOBJECT_HAS_SPECIAL_CALL(func)) {
63318 			*out_func = func;
63319 
63320 			if (DUK_HOBJECT_HAS_STRICT(func)) {
63321 				/* Strict function: no 'this' coercion. */
63322 				return 1;
63323 			}
63324 
63325 			duk__coerce_nonstrict_this_binding(thr, idx_func + 1);
63326 			return 1;
63327 		}
63328 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
63329 		*out_func = NULL;
63330 
63331 		/* Lightfuncs are considered strict, so 'this' binding is
63332 		 * used as is.  They're never bound, always constructable,
63333 		 * and never special functions.
63334 		 */
63335 		return 1;
63336 	}
63337 #endif  /* DUK_USE_PREFER_SIZE */
63338 	return 0;  /* let slow path deal with it */
63339 }
63340 
63341 DUK_LOCAL duk_hobject *duk__resolve_target_func_and_this_binding(duk_hthread *thr,
63342                                                                  duk_idx_t idx_func,
63343                                                                  duk_small_uint_t *call_flags) {
63344 	duk_tval *tv_func;
63345 	duk_hobject *func;
63346 	duk_bool_t first;
63347 
63348 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
63349 
63350 	for (first = 1;; first = 0) {
63351 		DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
63352 
63353 		tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
63354 		DUK_ASSERT(tv_func != NULL);
63355 
63356 		if (DUK_TVAL_IS_OBJECT(tv_func)) {
63357 			func = DUK_TVAL_GET_OBJECT(tv_func);
63358 
63359 			if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
63360 				if (DUK_UNLIKELY(!DUK_HOBJECT_HAS_CONSTRUCTABLE(func))) {
63361 					goto not_constructable;
63362 				}
63363 			} else {
63364 				if (DUK_UNLIKELY(!DUK_HOBJECT_IS_CALLABLE(func))) {
63365 					goto not_callable;
63366 				}
63367 			}
63368 
63369 			if (DUK_LIKELY(!DUK_HOBJECT_HAS_BOUNDFUNC(func) &&
63370 			               !DUK_HOBJECT_HAS_SPECIAL_CALL(func) &&
63371 			               !DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(func))) {
63372 				/* Common case, so test for using a single bitfield test.
63373 				 * Break out to handle this coercion etc.
63374 				 */
63375 				break;
63376 			}
63377 
63378 			/* XXX: could set specialcall for boundfuncs too, simplify check above */
63379 
63380 			if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
63381 				DUK_ASSERT(!DUK_HOBJECT_HAS_SPECIAL_CALL(func));
63382 				DUK_ASSERT(!DUK_HOBJECT_IS_NATFUNC(func));
63383 
63384 				/* Callable/constructable flags are the same
63385 				 * for the bound function and its target, so
63386 				 * we don't need to check them here, we can
63387 				 * check them from the target only.
63388 				 */
63389 				duk__handle_bound_chain_for_call(thr, idx_func, *call_flags & DUK_CALL_FLAG_CONSTRUCT);
63390 
63391 				DUK_ASSERT(DUK_TVAL_IS_OBJECT(duk_require_tval(thr, idx_func)) ||
63392 				           DUK_TVAL_IS_LIGHTFUNC(duk_require_tval(thr, idx_func)));
63393 			} else {
63394 				DUK_ASSERT(DUK_HOBJECT_HAS_SPECIAL_CALL(func));
63395 
63396 #if defined(DUK_USE_ES6_PROXY)
63397 				if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(func)) {
63398 					/* If no trap, resume processing from Proxy trap.
63399 					 * If trap exists, helper converts call into a trap
63400 					 * call; this may change a constructor call into a
63401 					 * normal (non-constructor) trap call.  We must
63402 					 * continue processing even when a trap is found as
63403 					 * the trap may be bound.
63404 					 */
63405 					duk__handle_proxy_for_call(thr, idx_func, (duk_hproxy *) func, call_flags);
63406 				}
63407 				else
63408 #endif
63409 				{
63410 					DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(func));
63411 					DUK_ASSERT(DUK_HOBJECT_HAS_CALLABLE(func));
63412 					DUK_ASSERT(!DUK_HOBJECT_HAS_CONSTRUCTABLE(func));
63413 					/* Constructable check already done above. */
63414 
63415 					if (duk__handle_specialfuncs_for_call(thr, idx_func, func, call_flags, first) != 0) {
63416 						/* Encountered native eval call, normal call
63417 						 * context.  Break out, handle this coercion etc.
63418 						 */
63419 						break;
63420 					}
63421 				}
63422 			}
63423 			/* Retry loop. */
63424 		} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
63425 			/* Lightfuncs are:
63426 			 *   - Always strict, so no 'this' coercion.
63427 			 *   - Always callable.
63428 			 *   - Always constructable.
63429 			 *   - Never specialfuncs.
63430 			 */
63431 			func = NULL;
63432 			goto finished;
63433 		} else {
63434 			goto not_callable;
63435 		}
63436 	}
63437 
63438 	DUK_ASSERT(func != NULL);
63439 
63440 	if (!DUK_HOBJECT_HAS_STRICT(func)) {
63441 		/* Non-strict target needs 'this' coercion.
63442 		 * This has potential side effects invalidating
63443 		 * 'tv_func'.
63444 		 */
63445 		duk__coerce_nonstrict_this_binding(thr, idx_func + 1);
63446 	}
63447 	if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
63448 		if (!(*call_flags & DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED)) {
63449 			*call_flags |= DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED;
63450 			duk__update_default_instance_proto(thr, idx_func);
63451 		}
63452 	}
63453 
63454  finished:
63455 
63456 #if defined(DUK_USE_ASSERTIONS)
63457 	{
63458 		duk_tval *tv_tmp;
63459 
63460 		tv_tmp = duk_get_tval(thr, idx_func);
63461 		DUK_ASSERT(tv_tmp != NULL);
63462 
63463 		DUK_ASSERT((DUK_TVAL_IS_OBJECT(tv_tmp) && DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(tv_tmp))) ||
63464 		           DUK_TVAL_IS_LIGHTFUNC(tv_tmp));
63465 		DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
63466 		DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) ||
63467 		                            DUK_HOBJECT_IS_NATFUNC(func)));
63468 		DUK_ASSERT(func == NULL || (DUK_HOBJECT_HAS_CONSTRUCTABLE(func) ||
63469 		                            (*call_flags & DUK_CALL_FLAG_CONSTRUCT) == 0));
63470 	}
63471 #endif
63472 
63473 	return func;
63474 
63475  not_callable:
63476 	DUK_ASSERT(tv_func != NULL);
63477 
63478 #if defined(DUK_USE_VERBOSE_ERRORS)
63479 	/* GETPROPC delayed error handling: when target is not callable,
63480 	 * GETPROPC replaces idx_func+0 with an Error (non-callable) with
63481 	 * a hidden Symbol to signify it's to be thrown as is here.  The
63482 	 * hidden Symbol is only checked as an own property, not inherited
63483 	 * (which would be dangerous).
63484 	 */
63485 	if (DUK_TVAL_IS_OBJECT(tv_func)) {
63486 		if (duk_hobject_find_existing_entry_tval_ptr(thr->heap, DUK_TVAL_GET_OBJECT(tv_func), DUK_HTHREAD_STRING_INT_TARGET(thr)) != NULL) {
63487 			duk_push_tval(thr, tv_func);
63488 			(void) duk_throw(thr);
63489 			DUK_WO_NORETURN(return NULL;);
63490 		}
63491 	}
63492 #endif
63493 
63494 #if defined(DUK_USE_VERBOSE_ERRORS)
63495 #if defined(DUK_USE_PARANOID_ERRORS)
63496 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not callable", duk_get_type_name(thr, idx_func));
63497 #else
63498 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not callable", duk_push_string_tval_readable(thr, tv_func));
63499 #endif
63500 #else
63501 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
63502 #endif
63503 	DUK_WO_NORETURN(return NULL;);
63504 
63505  not_constructable:
63506 	/* For now GETPROPC delayed error not needed for constructor calls. */
63507 #if defined(DUK_USE_VERBOSE_ERRORS)
63508 #if defined(DUK_USE_PARANOID_ERRORS)
63509 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not constructable", duk_get_type_name(thr, idx_func));
63510 #else
63511 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not constructable", duk_push_string_tval_readable(thr, tv_func));
63512 #endif
63513 #else
63514 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONSTRUCTABLE);
63515 #endif
63516 	DUK_WO_NORETURN(return NULL;);
63517 }
63518 
63519 /*
63520  *  Manipulate value stack so that exactly 'num_stack_rets' return
63521  *  values are at 'idx_retbase' in every case, assuming there are
63522  *  'rc' return values on top of stack.
63523  *
63524  *  This is a bit tricky, because the called C function operates in
63525  *  the same activation record and may have e.g. popped the stack
63526  *  empty (below idx_retbase).
63527  */
63528 
63529 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) {
63530 	duk_idx_t idx_rcbase;
63531 
63532 	DUK_ASSERT(thr != NULL);
63533 	DUK_ASSERT(idx_retbase >= 0);
63534 	DUK_ASSERT(num_stack_rets >= 0);
63535 	DUK_ASSERT(num_actual_rets >= 0);
63536 
63537 	idx_rcbase = duk_get_top(thr) - num_actual_rets;  /* base of known return values */
63538 	if (DUK_UNLIKELY(idx_rcbase < 0)) {
63539 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_CFUNC_RC);
63540 		DUK_WO_NORETURN(return;);
63541 	}
63542 
63543 	DUK_DDD(DUK_DDDPRINT("adjust valstack after func call: "
63544 	                     "num_stack_rets=%ld, num_actual_rets=%ld, stack_top=%ld, idx_retbase=%ld, idx_rcbase=%ld",
63545 	                     (long) num_stack_rets, (long) num_actual_rets, (long) duk_get_top(thr),
63546 	                     (long) idx_retbase, (long) idx_rcbase));
63547 
63548 	DUK_ASSERT(idx_rcbase >= 0);  /* caller must check */
63549 
63550 	/* Space for num_stack_rets was reserved before the safe call.
63551 	 * Because value stack reserve cannot shrink except in call returns,
63552 	 * the reserve is still in place.  Adjust valstack, carefully
63553 	 * ensuring we don't overstep the reserve.
63554 	 */
63555 
63556 	/* Match idx_rcbase with idx_retbase so that the return values
63557 	 * start at the correct index.
63558 	 */
63559 	if (idx_rcbase > idx_retbase) {
63560 		duk_idx_t count = idx_rcbase - idx_retbase;
63561 
63562 		DUK_DDD(DUK_DDDPRINT("elements at/after idx_retbase have enough to cover func retvals "
63563 		                     "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
63564 
63565 		/* Remove values between irc_rcbase (start of intended return
63566 		 * values) and idx_retbase to lower return values to idx_retbase.
63567 		 */
63568 		DUK_ASSERT(count > 0);
63569 		duk_remove_n(thr, idx_retbase, count);  /* may be NORZ */
63570 	} else {
63571 		duk_idx_t count = idx_retbase - idx_rcbase;
63572 
63573 		DUK_DDD(DUK_DDDPRINT("not enough elements at/after idx_retbase to cover func retvals "
63574 		                     "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
63575 
63576 		/* Insert 'undefined' at idx_rcbase (start of intended return
63577 		 * values) to lift return values to idx_retbase.
63578 		 */
63579 		DUK_ASSERT(count >= 0);
63580 		DUK_ASSERT(thr->valstack_end - thr->valstack_top >= count);  /* reserve cannot shrink */
63581 		duk_insert_undefined_n(thr, idx_rcbase, count);
63582 	}
63583 
63584 	/* Chop extra retvals away / extend with undefined. */
63585 	duk_set_top_unsafe(thr, idx_retbase + num_stack_rets);
63586 }
63587 
63588 /*
63589  *  Activation setup for tailcalls and non-tailcalls.
63590  */
63591 
63592 #if defined(DUK_USE_TAILCALL)
63593 DUK_LOCAL duk_small_uint_t duk__call_setup_act_attempt_tailcall(duk_hthread *thr,
63594                                                                 duk_small_uint_t call_flags,
63595                                                                 duk_idx_t idx_func,
63596                                                                 duk_hobject *func,
63597                                                                 duk_size_t entry_valstack_bottom_byteoff,
63598                                                                 duk_size_t entry_valstack_end_byteoff,
63599                                                                 duk_idx_t *out_nargs,
63600                                                                 duk_idx_t *out_nregs,
63601                                                                 duk_size_t *out_vs_min_bytes,
63602                                                                 duk_activation **out_act) {
63603 	duk_activation *act;
63604 	duk_tval *tv1, *tv2;
63605 	duk_idx_t idx_args;
63606 	duk_small_uint_t flags1, flags2;
63607 #if defined(DUK_USE_DEBUGGER_SUPPORT)
63608 	duk_activation *prev_pause_act;
63609 #endif
63610 
63611 	DUK_UNREF(entry_valstack_end_byteoff);
63612 
63613 	/* Tailcall cannot be flagged to resume calls, and a
63614 	 * previous frame must exist.
63615 	 */
63616 	DUK_ASSERT(thr->callstack_top >= 1);
63617 
63618 	act = thr->callstack_curr;
63619 	DUK_ASSERT(act != NULL);
63620 	*out_act = act;
63621 
63622 	if (func == NULL || !DUK_HOBJECT_IS_COMPFUNC(func)) {
63623 		DUK_DDD(DUK_DDDPRINT("tail call prevented by target not being ecma function"));
63624 		return 0;
63625 	}
63626 	if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
63627 		DUK_DDD(DUK_DDDPRINT("tail call prevented by current activation having DUK_ACT_FLAG_PREVENT_YIELD"));
63628 		return 0;
63629 	}
63630 	/* Tailcall is only allowed if current and candidate
63631 	 * function have identical return value handling.  There
63632 	 * are three possible return value handling cases:
63633 	 *   1. Normal function call, no special return value handling.
63634 	 *   2. Constructor call, return value replacement object check.
63635 	 *   3. Proxy 'construct' trap call, return value invariant check.
63636 	 */
63637 	flags1 = (duk_small_uint_t) ((act->flags & DUK_ACT_FLAG_CONSTRUCT) ? 1 : 0)
63638 #if defined(DUK_USE_ES6_PROXY)
63639 	         | (duk_small_uint_t) ((act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) ? 2 : 0)
63640 #endif
63641 	         ;
63642 	flags2 = (duk_small_uint_t) ((call_flags & DUK_CALL_FLAG_CONSTRUCT) ? 1 : 0)
63643 #if defined(DUK_USE_ES6_PROXY)
63644 	         | (duk_small_uint_t) ((call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) ? 2 : 0);
63645 #endif
63646 	         ;
63647 	if (flags1 != flags2) {
63648 		DUK_DDD(DUK_DDDPRINT("tail call prevented by incompatible return value handling"));
63649 		return 0;
63650 	}
63651 	DUK_ASSERT(((act->flags & DUK_ACT_FLAG_CONSTRUCT) && (call_flags & DUK_CALL_FLAG_CONSTRUCT)) ||
63652 	           (!(act->flags & DUK_ACT_FLAG_CONSTRUCT) && !(call_flags & DUK_CALL_FLAG_CONSTRUCT)));
63653 	DUK_ASSERT(((act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) && (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY)) ||
63654 	           (!(act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) && !(call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY)));
63655 	if (DUK_HOBJECT_HAS_NOTAIL(func)) {
63656 		/* See: test-bug-tailcall-preventyield-assert.c. */
63657 		DUK_DDD(DUK_DDDPRINT("tail call prevented by function having a notail flag"));
63658 		return 0;
63659 	}
63660 
63661 	/*
63662 	 *  Tailcall handling
63663 	 *
63664 	 *  Although the callstack entry is reused, we need to explicitly unwind
63665 	 *  the current activation (or simulate an unwind).  In particular, the
63666 	 *  current activation must be closed, otherwise something like
63667 	 *  test-bug-reduce-judofyr.js results.  Also catchers need to be unwound
63668 	 *  because there may be non-error-catching label entries in valid tail calls.
63669 	 *
63670 	 *  Special attention is needed for debugger and pause behavior when
63671 	 *  reusing an activation.
63672 	 *    - Disable StepOut processing for the activation unwind because
63673 	 *      we reuse the activation, see:
63674 	 *      https://github.com/svaarala/duktape/issues/1684.
63675 	 *    - Disable line change pause flag permanently if act == dbg_pause_act
63676 	 *      (if set) because it would no longer be relevant, see:
63677 	 *      https://github.com/svaarala/duktape/issues/1726,
63678 	 *      https://github.com/svaarala/duktape/issues/1786.
63679 	 *    - Check for function entry (e.g. StepInto) pause flag here, because
63680 	 *      the executor pause check won't trigger due to shared activation, see:
63681 	 *      https://github.com/svaarala/duktape/issues/1726.
63682 	 */
63683 
63684 	DUK_DDD(DUK_DDDPRINT("is tail call, reusing activation at callstack top, at index %ld",
63685                              (long) (thr->callstack_top - 1)));
63686 
63687 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
63688 	DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(func));
63689 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
63690 	DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
63691 	DUK_ASSERT(call_flags & DUK_CALL_FLAG_ALLOW_ECMATOECMA);
63692 
63693 	/* Unwind the topmost callstack entry before reusing it.  This
63694 	 * also unwinds the catchers related to the topmost entry.
63695 	 */
63696 	DUK_ASSERT(thr->callstack_top > 0);
63697 	DUK_ASSERT(thr->callstack_curr != NULL);
63698 #if defined(DUK_USE_DEBUGGER_SUPPORT)
63699 	if (act == thr->heap->dbg_pause_act) {
63700 		thr->heap->dbg_pause_flags &= ~DUK_PAUSE_FLAG_LINE_CHANGE;
63701 	}
63702 
63703 	prev_pause_act = thr->heap->dbg_pause_act;
63704 	thr->heap->dbg_pause_act = NULL;
63705 	if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_ENTRY) {
63706 		DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function entry (tailcall)"));
63707 		duk_debug_set_paused(thr->heap);
63708 	}
63709 #endif
63710 	duk_hthread_activation_unwind_reuse_norz(thr);
63711 #if defined(DUK_USE_DEBUGGER_SUPPORT)
63712 	thr->heap->dbg_pause_act = prev_pause_act;
63713 #endif
63714 	DUK_ASSERT(act == thr->callstack_curr);
63715 
63716 	/* XXX: We could restore the caller's value stack reserve
63717 	 * here, as if we did an actual unwind-and-call.  Without
63718 	 * the restoration, value stack reserve may remain higher
63719 	 * than would otherwise be possible until we return to a
63720 	 * non-tailcall.
63721 	 */
63722 
63723 	/* Then reuse the unwound activation. */
63724 	act->cat = NULL;
63725 	act->var_env = NULL;
63726 	act->lex_env = NULL;
63727 	DUK_ASSERT(func != NULL);
63728 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
63729 	act->func = func;  /* don't want an intermediate exposed state with func == NULL */
63730 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
63731 	act->prev_caller = NULL;
63732 #endif
63733 	/* don't want an intermediate exposed state with invalid pc */
63734 	act->curr_pc = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) func);
63735 #if defined(DUK_USE_DEBUGGER_SUPPORT)
63736 	act->prev_line = 0;
63737 #endif
63738 	DUK_TVAL_SET_OBJECT(&act->tv_func, func);  /* borrowed, no refcount */
63739 	DUK_HOBJECT_INCREF(thr, func);
63740 
63741 	act->flags = DUK_ACT_FLAG_TAILCALLED;
63742 	if (DUK_HOBJECT_HAS_STRICT(func)) {
63743 		act->flags |= DUK_ACT_FLAG_STRICT;
63744 	}
63745 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
63746 		act->flags |= DUK_ACT_FLAG_CONSTRUCT;
63747 	}
63748 #if defined(DUK_USE_ES6_PROXY)
63749 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) {
63750 		act->flags |= DUK_ACT_FLAG_CONSTRUCT_PROXY;
63751 	}
63752 #endif
63753 
63754 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) == func);      /* already updated */
63755 	DUK_ASSERT(act->var_env == NULL);
63756 	DUK_ASSERT(act->lex_env == NULL);
63757 	act->bottom_byteoff = entry_valstack_bottom_byteoff;  /* tail call -> reuse current "frame" */
63758 #if 0
63759 	/* Topmost activation retval_byteoff is considered garbage, no need to init. */
63760 	act->retval_byteoff = 0;
63761 #endif
63762 	/* Filled in when final reserve is known, dummy value doesn't matter
63763 	 * even in error unwind because reserve_byteoff is only used when
63764 	 * returning to -this- activation.
63765 	 */
63766 	act->reserve_byteoff = 0;
63767 
63768 	/*
63769 	 *  Manipulate valstack so that args are on the current bottom and the
63770 	 *  previous caller's 'this' binding (which is the value preceding the
63771 	 *  current bottom) is replaced with the new 'this' binding:
63772 	 *
63773 	 *       [ ... this_old | (crud) func this_new arg1 ... argN ]
63774 	 *  -->  [ ... this_new | arg1 ... argN ]
63775 	 *
63776 	 *  For tail calling to work properly, the valstack bottom must not grow
63777 	 *  here; otherwise crud would accumulate on the valstack.
63778 	 */
63779 
63780 	tv1 = thr->valstack_bottom - 1;
63781 	tv2 = thr->valstack_bottom + idx_func + 1;
63782 	DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);  /* tv1 is -below- valstack_bottom */
63783 	DUK_ASSERT(tv2 >= thr->valstack_bottom && tv2 < thr->valstack_top);
63784 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
63785 
63786 	idx_args = idx_func + 2;
63787 	duk_remove_n(thr, 0, idx_args);  /* may be NORZ */
63788 
63789 	idx_func = 0; DUK_UNREF(idx_func);  /* really 'not applicable' anymore, should not be referenced after this */
63790 	idx_args = 0;
63791 
63792 	*out_nargs = ((duk_hcompfunc *) func)->nargs;
63793 	*out_nregs = ((duk_hcompfunc *) func)->nregs;
63794 	DUK_ASSERT(*out_nregs >= 0);
63795 	DUK_ASSERT(*out_nregs >= *out_nargs);
63796 	*out_vs_min_bytes = entry_valstack_bottom_byteoff + sizeof(duk_tval) * ((duk_size_t) *out_nregs + DUK_VALSTACK_INTERNAL_EXTRA);
63797 
63798 
63799 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
63800 #if defined(DUK_USE_TAILCALL)
63801 #error incorrect options: tail calls enabled with function caller property
63802 #endif
63803 	/* XXX: This doesn't actually work properly for tail calls, so
63804 	 * tail calls are disabled when DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
63805 	 * is in use.
63806 	 */
63807 	duk__update_func_caller_prop(thr, func);
63808 #endif
63809 
63810 	/* [ ... this_new | arg1 ... argN ] */
63811 
63812 	return 1;
63813 }
63814 #endif  /* DUK_USE_TAILCALL */
63815 
63816 DUK_LOCAL void duk__call_setup_act_not_tailcall(duk_hthread *thr,
63817                                                 duk_small_uint_t call_flags,
63818                                                 duk_idx_t idx_func,
63819                                                 duk_hobject *func,
63820                                                 duk_size_t entry_valstack_bottom_byteoff,
63821                                                 duk_size_t entry_valstack_end_byteoff,
63822                                                 duk_idx_t *out_nargs,
63823                                                 duk_idx_t *out_nregs,
63824                                                 duk_size_t *out_vs_min_bytes,
63825                                                 duk_activation **out_act) {
63826 	duk_activation *act;
63827 	duk_activation *new_act;
63828 
63829 	DUK_UNREF(entry_valstack_end_byteoff);
63830 
63831 	DUK_DDD(DUK_DDDPRINT("not a tail call, pushing a new activation to callstack, to index %ld",
63832 	                     (long) (thr->callstack_top)));
63833 
63834 	duk__call_callstack_limit_check(thr);
63835 	new_act = duk_hthread_activation_alloc(thr);
63836 	DUK_ASSERT(new_act != NULL);
63837 
63838 	act = thr->callstack_curr;
63839 	if (act != NULL) {
63840 		/*
63841 		 *  Update return value stack index of current activation (if any).
63842 		 *
63843 		 *  Although it might seem this is not necessary (bytecode executor
63844 		 *  does this for ECMAScript-to-ECMAScript calls; other calls are
63845 		 *  handled here), this turns out to be necessary for handling yield
63846 		 *  and resume.  For them, an ECMAScript-to-native call happens, and
63847 		 *  the ECMAScript call's retval_byteoff must be set for things to work.
63848 		 */
63849 
63850 		act->retval_byteoff = entry_valstack_bottom_byteoff + (duk_size_t) idx_func * sizeof(duk_tval);
63851 	}
63852 
63853 	new_act->parent = act;
63854 	thr->callstack_curr = new_act;
63855 	thr->callstack_top++;
63856 	act = new_act;
63857 	*out_act = act;
63858 
63859 	DUK_ASSERT(thr->valstack_top > thr->valstack_bottom);  /* at least effective 'this' */
63860 	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
63861 
63862 	act->cat = NULL;
63863 
63864 	act->flags = 0;
63865 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
63866 		act->flags |= DUK_ACT_FLAG_CONSTRUCT;
63867 	}
63868 #if defined(DUK_USE_ES6_PROXY)
63869 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) {
63870 		act->flags |= DUK_ACT_FLAG_CONSTRUCT_PROXY;
63871 	}
63872 #endif
63873 	if (call_flags & DUK_CALL_FLAG_DIRECT_EVAL) {
63874 		act->flags |= DUK_ACT_FLAG_DIRECT_EVAL;
63875 	}
63876 
63877 	/* start of arguments: idx_func + 2. */
63878 	act->func = func;  /* NULL for lightfunc */
63879 	if (DUK_LIKELY(func != NULL)) {
63880 		DUK_TVAL_SET_OBJECT(&act->tv_func, func);  /* borrowed, no refcount */
63881 		if (DUK_HOBJECT_HAS_STRICT(func)) {
63882 			act->flags |= DUK_ACT_FLAG_STRICT;
63883 		}
63884 		if (DUK_HOBJECT_IS_COMPFUNC(func)) {
63885 			*out_nargs = ((duk_hcompfunc *) func)->nargs;
63886 			*out_nregs = ((duk_hcompfunc *) func)->nregs;
63887 			DUK_ASSERT(*out_nregs >= 0);
63888 			DUK_ASSERT(*out_nregs >= *out_nargs);
63889 			*out_vs_min_bytes = entry_valstack_bottom_byteoff +
63890 				sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nregs + DUK_VALSTACK_INTERNAL_EXTRA);
63891 		} else {
63892 			/* True because of call target lookup checks. */
63893 			DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(func));
63894 
63895 			*out_nargs = ((duk_hnatfunc *) func)->nargs;
63896 			*out_nregs = *out_nargs;
63897 			if (*out_nargs >= 0) {
63898 				*out_vs_min_bytes = entry_valstack_bottom_byteoff +
63899 					sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nregs + DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
63900 			} else {
63901 				/* Vararg function. */
63902 				duk_size_t valstack_top_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - ((duk_uint8_t *) thr->valstack));
63903 				*out_vs_min_bytes = valstack_top_byteoff +
63904 					sizeof(duk_tval) * (DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
63905 			}
63906 		}
63907 	} else {
63908 		duk_small_uint_t lf_flags;
63909 		duk_tval *tv_func;
63910 
63911 		act->flags |= DUK_ACT_FLAG_STRICT;
63912 
63913 		tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
63914 		DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func));
63915 		DUK_TVAL_SET_TVAL(&act->tv_func, tv_func);  /* borrowed, no refcount */
63916 
63917 		lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv_func);
63918 		*out_nargs = DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
63919 		if (*out_nargs != DUK_LFUNC_NARGS_VARARGS) {
63920 			*out_vs_min_bytes = entry_valstack_bottom_byteoff +
63921 				sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nargs + DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
63922 		} else {
63923 			duk_size_t valstack_top_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - ((duk_uint8_t *) thr->valstack));
63924 			*out_vs_min_bytes = valstack_top_byteoff +
63925 				sizeof(duk_tval) * (DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
63926 			*out_nargs = -1;  /* vararg */
63927 		}
63928 		*out_nregs = *out_nargs;
63929 	}
63930 
63931 	act->var_env = NULL;
63932 	act->lex_env = NULL;
63933 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
63934 	act->prev_caller = NULL;
63935 #endif
63936 	act->curr_pc = NULL;
63937 #if defined(DUK_USE_DEBUGGER_SUPPORT)
63938 	act->prev_line = 0;
63939 #endif
63940 	act->bottom_byteoff = entry_valstack_bottom_byteoff + sizeof(duk_tval) * ((duk_size_t) idx_func + 2U);
63941 #if 0
63942 	act->retval_byteoff = 0;   /* topmost activation retval_byteoff is considered garbage, no need to init */
63943 #endif
63944 	/* Filled in when final reserve is known, dummy value doesn't matter
63945 	 * even in error unwind because reserve_byteoff is only used when
63946 	 * returning to -this- activation.
63947 	 */
63948 	act->reserve_byteoff = 0;  /* filled in by caller */
63949 
63950 	/* XXX: Is this INCREF necessary? 'func' is always a borrowed
63951 	 * reference reachable through the value stack?  If changed, stack
63952 	 * unwind code also needs to be fixed to match.
63953 	 */
63954 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, func);  /* act->func */
63955 
63956 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
63957 	if (func) {
63958 		duk__update_func_caller_prop(thr, func);
63959 	}
63960 #endif
63961 }
63962 
63963 /*
63964  *  Environment setup.
63965  */
63966 
63967 DUK_LOCAL void duk__call_env_setup(duk_hthread *thr, duk_hobject *func, duk_activation *act, duk_idx_t idx_args) {
63968 	duk_hobject *env;
63969 
63970 	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound function has already been resolved */
63971 
63972 	if (DUK_LIKELY(func != NULL)) {
63973 		if (DUK_LIKELY(DUK_HOBJECT_HAS_NEWENV(func))) {
63974 			if (DUK_LIKELY(!DUK_HOBJECT_HAS_CREATEARGS(func))) {
63975 				/* Use a new environment but there's no 'arguments' object;
63976 				 * delayed environment initialization.  This is the most
63977 				 * common case.
63978 				 */
63979 				DUK_ASSERT(act->lex_env == NULL);
63980 				DUK_ASSERT(act->var_env == NULL);
63981 			} else {
63982 				/* Use a new environment and there's an 'arguments' object.
63983 				 * We need to initialize it right now.
63984 				 */
63985 
63986 				/* third arg: absolute index (to entire valstack) of bottom_byteoff of new activation */
63987 				env = duk_create_activation_environment_record(thr, func, act->bottom_byteoff);
63988 				DUK_ASSERT(env != NULL);
63989 
63990 				/* [ ... func this arg1 ... argN envobj ] */
63991 
63992 				DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
63993 				duk__handle_createargs_for_call(thr, func, env, idx_args);
63994 
63995 				/* [ ... func this arg1 ... argN envobj ] */
63996 
63997 				act->lex_env = env;
63998 				act->var_env = env;
63999 				DUK_HOBJECT_INCREF(thr, env);
64000 				DUK_HOBJECT_INCREF(thr, env);  /* XXX: incref by count (2) directly */
64001 				duk_pop(thr);
64002 			}
64003 		} else {
64004 			/* Use existing env (e.g. for non-strict eval); cannot have
64005 			 * an own 'arguments' object (but can refer to an existing one).
64006 			 */
64007 
64008 			DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
64009 
64010 			duk__handle_oldenv_for_call(thr, func, act);
64011 
64012 			DUK_ASSERT(act->lex_env != NULL);
64013 			DUK_ASSERT(act->var_env != NULL);
64014 		}
64015 	} else {
64016 		/* Lightfuncs are always native functions and have "newenv". */
64017 		DUK_ASSERT(act->lex_env == NULL);
64018 		DUK_ASSERT(act->var_env == NULL);
64019 	}
64020 }
64021 
64022 /*
64023  *  Misc shared helpers.
64024  */
64025 
64026 /* Check thread state, update current thread. */
64027 DUK_LOCAL void duk__call_thread_state_update(duk_hthread *thr) {
64028 	DUK_ASSERT(thr != NULL);
64029 
64030 	if (DUK_LIKELY(thr == thr->heap->curr_thread)) {
64031 		if (DUK_UNLIKELY(thr->state != DUK_HTHREAD_STATE_RUNNING)) {
64032 			/* Should actually never happen, but check anyway. */
64033 			goto thread_state_error;
64034 		}
64035 	} else {
64036 		DUK_ASSERT(thr->heap->curr_thread == NULL ||
64037 		           thr->heap->curr_thread->state == DUK_HTHREAD_STATE_RUNNING);
64038 		if (DUK_UNLIKELY(thr->state != DUK_HTHREAD_STATE_INACTIVE)) {
64039 			goto thread_state_error;
64040 		}
64041 		DUK_HEAP_SWITCH_THREAD(thr->heap, thr);
64042 		thr->state = DUK_HTHREAD_STATE_RUNNING;
64043 
64044 		/* Multiple threads may be simultaneously in the RUNNING
64045 		 * state, but not in the same "resume chain".
64046 		 */
64047 	}
64048 	DUK_ASSERT(thr->heap->curr_thread == thr);
64049 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
64050 	return;
64051 
64052  thread_state_error:
64053 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "invalid thread state (%ld)", (long) thr->state);
64054 	DUK_WO_NORETURN(return;);
64055 }
64056 
64057 /*
64058  *  Main unprotected call handler, handles:
64059  *
64060  *    - All combinations of native/ECMAScript caller and native/ECMAScript
64061  *      target.
64062  *
64063  *    - Optimized ECMAScript-to-ECMAScript call where call handling only
64064  *      sets up a new duk_activation but reuses an existing bytecode executor
64065  *      (the caller) without native recursion.
64066  *
64067  *    - Tailcalls, where an activation is reused without increasing call
64068  *      stack (duk_activation) depth.
64069  *
64070  *    - Setup for an initial Duktape.Thread.resume().
64071  *
64072  *  The call handler doesn't provide any protection guarantees, protected calls
64073  *  must be implemented e.g. by wrapping the call in a duk_safe_call().
64074  *  Call setup may fail at any stage, even when the new activation is in
64075  *  place; the only guarantee is that the state is consistent for unwinding.
64076  */
64077 
64078 DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
64079                                          duk_idx_t idx_func,
64080                                          duk_small_uint_t call_flags) {
64081 #if defined(DUK_USE_ASSERTIONS)
64082 	duk_activation *entry_act;
64083 	duk_size_t entry_callstack_top;
64084 #endif
64085 	duk_size_t entry_valstack_bottom_byteoff;
64086 	duk_size_t entry_valstack_end_byteoff;
64087 	duk_int_t entry_call_recursion_depth;
64088 	duk_hthread *entry_curr_thread;
64089 	duk_uint_fast8_t entry_thread_state;
64090 	duk_instr_t **entry_ptr_curr_pc;
64091 	duk_idx_t idx_args;
64092 	duk_idx_t nargs;            /* # argument registers target function wants (< 0 => "as is") */
64093 	duk_idx_t nregs;            /* # total registers target function wants on entry (< 0 => "as is") */
64094 	duk_size_t vs_min_bytes;    /* minimum value stack size (bytes) for handling call */
64095 	duk_hobject *func;          /* 'func' on stack (borrowed reference) */
64096 	duk_activation *act;
64097 	duk_ret_t rc;
64098 	duk_small_uint_t use_tailcall;
64099 
64100 	DUK_ASSERT(thr != NULL);
64101 	DUK_ASSERT(thr->heap != NULL);
64102 	/* Asserts for heap->curr_thread omitted: it may be NULL, 'thr', or
64103 	 * any other thread (e.g. when heap thread is used to run finalizers).
64104 	 */
64105 	DUK_ASSERT_CTX_VALID(thr);
64106 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
64107 	DUK_ASSERT(idx_func >= 0);
64108 
64109 	DUK_STATS_INC(thr->heap, stats_call_all);
64110 
64111 	/* If a tail call:
64112 	 *   - an ECMAScript activation must be on top of the callstack
64113 	 *   - there cannot be any catch stack entries that would catch
64114 	 *     a return
64115 	 */
64116 #if defined(DUK_USE_ASSERTIONS)
64117 	if (call_flags & DUK_CALL_FLAG_TAILCALL) {
64118 		duk_activation *tmp_act;
64119 		duk_catcher *tmp_cat;
64120 
64121 		DUK_ASSERT(thr->callstack_top >= 1);
64122 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
64123 		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
64124 
64125 		/* No entry in the catch stack which would actually catch a
64126 		 * throw can refer to the callstack entry being reused.
64127 		 * There *can* be catch stack entries referring to the current
64128 		 * callstack entry as long as they don't catch (e.g. label sites).
64129 		 */
64130 
64131 		tmp_act = thr->callstack_curr;
64132 		for (tmp_cat = tmp_act->cat; tmp_cat != NULL; tmp_cat = tmp_cat->parent) {
64133 			DUK_ASSERT(DUK_CAT_GET_TYPE(tmp_cat) == DUK_CAT_TYPE_LABEL); /* a non-catching entry */
64134 		}
64135 	}
64136 #endif  /* DUK_USE_ASSERTIONS */
64137 
64138 	/*
64139 	 *  Store entry state.
64140 	 */
64141 
64142 #if defined(DUK_USE_ASSERTIONS)
64143 	entry_act = thr->callstack_curr;
64144 	entry_callstack_top = thr->callstack_top;
64145 #endif
64146 	entry_valstack_bottom_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
64147 	entry_valstack_end_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
64148 	entry_call_recursion_depth = thr->heap->call_recursion_depth;
64149 	entry_curr_thread = thr->heap->curr_thread;  /* may be NULL if first call */
64150 	entry_thread_state = thr->state;
64151 	entry_ptr_curr_pc = thr->ptr_curr_pc;  /* may be NULL */
64152 
64153 	/* If thr->ptr_curr_pc is set, sync curr_pc to act->pc.  Then NULL
64154 	 * thr->ptr_curr_pc so that it's not accidentally used with an incorrect
64155 	 * activation when side effects occur.
64156 	 */
64157 	duk_hthread_sync_and_null_currpc(thr);
64158 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
64159 
64160 	DUK_DD(DUK_DDPRINT("duk__handle_call_raw: thr=%p, idx_func=%ld, "
64161 	                   "call_flags=0x%08lx (constructor=%ld), "
64162 	                   "valstack_top=%ld, idx_func=%ld, idx_args=%ld, rec_depth=%ld/%ld, "
64163 	                   "entry_valstack_bottom_byteoff=%ld, entry_valstack_end_byteoff=%ld, "
64164 	                   "entry_call_recursion_depth=%ld, "
64165 	                   "entry_curr_thread=%p, entry_thread_state=%ld",
64166 	                   (void *) thr,
64167 	                   (long) idx_func,
64168 	                   (unsigned long) call_flags,
64169 	                   (long) ((call_flags & DUK_CALL_FLAG_CONSTRUCT) != 0 ? 1 : 0),
64170 	                   (long) duk_get_top(thr),
64171 	                   (long) idx_func,
64172 	                   (long) (idx_func + 2),
64173 	                   (long) thr->heap->call_recursion_depth,
64174 	                   (long) thr->heap->call_recursion_limit,
64175 	                   (long) entry_valstack_bottom_byteoff,
64176 	                   (long) entry_valstack_end_byteoff,
64177 	                   (long) entry_call_recursion_depth,
64178 	                   (void *) entry_curr_thread,
64179 	                   (long) entry_thread_state));
64180 
64181 	/*
64182 	 *  Thread state check and book-keeping.
64183 	 */
64184 
64185 	duk__call_thread_state_update(thr);
64186 
64187 	/*
64188 	 *  Resolve final target function; handle bound functions and special
64189 	 *  functions like .call() and .apply().  Also figure out the effective
64190 	 *  'this' binding, which replaces the current value at idx_func + 1.
64191 	 */
64192 
64193 	if (DUK_LIKELY(duk__resolve_target_fastpath_check(thr, idx_func, &func, call_flags) != 0U)) {
64194 		DUK_DDD(DUK_DDDPRINT("fast path target resolve"));
64195 	} else {
64196 		DUK_DDD(DUK_DDDPRINT("slow path target resolve"));
64197 		func = duk__resolve_target_func_and_this_binding(thr, idx_func, &call_flags);
64198 	}
64199 	DUK_ASSERT(duk_get_top(thr) - idx_func >= 2);  /* at least func and this present */
64200 
64201 	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
64202 	DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) ||
64203 	                            DUK_HOBJECT_IS_NATFUNC(func)));
64204 
64205 	/* [ ... func this arg1 ... argN ] */
64206 
64207 	/*
64208 	 *  Setup a preliminary activation and figure out nargs/nregs and
64209 	 *  value stack minimum size.
64210 	 *
64211 	 *  Don't touch valstack_bottom or valstack_top yet so that Duktape API
64212 	 *  calls work normally.
64213 	 *
64214 	 *  Because 'act' is not zeroed, all fields must be filled in.
64215 	 */
64216 
64217 	/* Should not be necessary, but initialize to silence warnings. */
64218 	act = NULL;
64219 	nargs = 0;
64220 	nregs = 0;
64221 	vs_min_bytes = 0;
64222 
64223 #if defined(DUK_USE_TAILCALL)
64224 	use_tailcall = (call_flags & DUK_CALL_FLAG_TAILCALL);
64225 	if (use_tailcall) {
64226 		use_tailcall = duk__call_setup_act_attempt_tailcall(thr,
64227 		                                                    call_flags,
64228 		                                                    idx_func,
64229 		                                                    func,
64230 		                                                    entry_valstack_bottom_byteoff,
64231 		                                                    entry_valstack_end_byteoff,
64232 		                                                    &nargs,
64233 		                                                    &nregs,
64234 		                                                    &vs_min_bytes,
64235 		                                                    &act);
64236 	}
64237 #else
64238 	DUK_ASSERT((call_flags & DUK_CALL_FLAG_TAILCALL) == 0);  /* compiler ensures this */
64239 	use_tailcall = 0;
64240 #endif
64241 
64242 	if (use_tailcall) {
64243 		idx_args = 0;
64244 		DUK_STATS_INC(thr->heap, stats_call_tailcall);
64245 	} else {
64246 		duk__call_setup_act_not_tailcall(thr,
64247 		                                 call_flags,
64248 		                                 idx_func,
64249 		                                 func,
64250 		                                 entry_valstack_bottom_byteoff,
64251 		                                 entry_valstack_end_byteoff,
64252 		                                 &nargs,
64253 		                                 &nregs,
64254 		                                 &vs_min_bytes,
64255 		                                 &act);
64256 		idx_args = idx_func + 2;
64257 	}
64258 	/* After this point idx_func is no longer valid for tailcalls. */
64259 
64260 	DUK_ASSERT(act != NULL);
64261 
64262 	/* [ ... func this arg1 ... argN ] */
64263 
64264 	/*
64265 	 *  Environment record creation and 'arguments' object creation.
64266 	 *  Named function expression name binding is handled by the
64267 	 *  compiler; the compiled function's parent env will contain
64268 	 *  the (immutable) binding already.
64269 	 *
64270 	 *  This handling is now identical for C and ECMAScript functions.
64271 	 *  C functions always have the 'NEWENV' flag set, so their
64272 	 *  environment record initialization is delayed (which is good).
64273 	 *
64274 	 *  Delayed creation (on demand) is handled in duk_js_var.c.
64275 	 */
64276 
64277 	duk__call_env_setup(thr, func, act, idx_args);
64278 
64279 	/* [ ... func this arg1 ... argN ] */
64280 
64281 	/*
64282 	 *  Setup value stack: clamp to 'nargs', fill up to 'nregs',
64283 	 *  ensure value stack size matches target requirements, and
64284 	 *  switch value stack bottom.  Valstack top is kept.
64285 	 *
64286 	 *  Value stack can only grow here.
64287 	 */
64288 
64289 	duk_valstack_grow_check_throw(thr, vs_min_bytes);
64290 	act->reserve_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
64291 
64292 	if (use_tailcall) {
64293 		DUK_ASSERT(nregs >= 0);
64294 		DUK_ASSERT(nregs >= nargs);
64295 		duk_set_top_and_wipe(thr, nregs, nargs);
64296 	} else {
64297 		if (nregs >= 0) {
64298 			DUK_ASSERT(nregs >= nargs);
64299 			duk_set_top_and_wipe(thr, idx_func + 2 + nregs, idx_func + 2 + nargs);
64300 		} else {
64301 			;
64302 		}
64303 		thr->valstack_bottom = thr->valstack_bottom + idx_func + 2;
64304 	}
64305 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
64306 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
64307 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
64308 
64309 	/*
64310 	 *  Make the actual call.  For Ecma-to-Ecma calls detect that
64311 	 *  setup is complete, then return with a status code that allows
64312 	 *  the caller to reuse the running executor.
64313 	 */
64314 
64315 	if (func != NULL && DUK_HOBJECT_IS_COMPFUNC(func)) {
64316 		/*
64317 		 *  ECMAScript call.
64318 		 */
64319 
64320 		DUK_ASSERT(func != NULL);
64321 		DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
64322 		act->curr_pc = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) func);
64323 
64324 		if (call_flags & DUK_CALL_FLAG_ALLOW_ECMATOECMA) {
64325 			DUK_DD(DUK_DDPRINT("avoid native call, use existing executor"));
64326 			DUK_STATS_INC(thr->heap, stats_call_ecmatoecma);
64327 			DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
64328 			DUK_REFZERO_CHECK_FAST(thr);
64329 			DUK_ASSERT(thr->ptr_curr_pc == NULL);
64330 			return 1;  /* 1=reuse executor */
64331 		}
64332 		DUK_ASSERT(use_tailcall == 0);
64333 
64334 		/* duk_hthread_activation_unwind_norz() will decrease this on unwind */
64335 		DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
64336 		act->flags |= DUK_ACT_FLAG_PREVENT_YIELD;
64337 		thr->callstack_preventcount++;
64338 
64339 		/* XXX: we could just do this on entry regardless of reuse, as long
64340 		 * as recursion depth is decreased for e2e case.
64341 		 */
64342 		duk__call_c_recursion_limit_check(thr);
64343 		thr->heap->call_recursion_depth++;
64344 
64345 		/* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
64346 
64347 		/*
64348 		 *  Bytecode executor call.
64349 		 *
64350 		 *  Execute bytecode, handling any recursive function calls and
64351 		 *  thread resumptions.  Returns when execution would return from
64352 		 *  the entry level activation.  When the executor returns, a
64353 		 *  single return value is left on the stack top.
64354 		 *
64355 		 *  The only possible longjmp() is an error (DUK_LJ_TYPE_THROW),
64356 		 *  other types are handled internally by the executor.
64357 		 */
64358 
64359 		/* thr->ptr_curr_pc is set by bytecode executor early on entry */
64360 		DUK_ASSERT(thr->ptr_curr_pc == NULL);
64361 		DUK_DDD(DUK_DDDPRINT("entering bytecode execution"));
64362 		duk_js_execute_bytecode(thr);
64363 		DUK_DDD(DUK_DDDPRINT("returned from bytecode execution"));
64364 	} else {
64365 		/*
64366 		 *  Native call.
64367 		 */
64368 
64369 		DUK_ASSERT(func == NULL || ((duk_hnatfunc *) func)->func != NULL);
64370 		DUK_ASSERT(use_tailcall == 0);
64371 
64372 		/* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
64373 
64374 		/* duk_hthread_activation_unwind_norz() will decrease this on unwind */
64375 		DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
64376 		act->flags |= DUK_ACT_FLAG_PREVENT_YIELD;
64377 		thr->callstack_preventcount++;
64378 
64379 		/* XXX: we could just do this on entry regardless of reuse, as long
64380 		 * as recursion depth is decreased for e2e case.
64381 		 */
64382 		duk__call_c_recursion_limit_check(thr);
64383 		thr->heap->call_recursion_depth++;
64384 
64385 		/* For native calls must be NULL so we don't sync back */
64386 		DUK_ASSERT(thr->ptr_curr_pc == NULL);
64387 
64388 		/* XXX: native funcptr could come out of call setup. */
64389 		if (func) {
64390 			rc = ((duk_hnatfunc *) func)->func(thr);
64391 		} else {
64392 			duk_tval *tv_func;
64393 			duk_c_function funcptr;
64394 
64395 			tv_func = &act->tv_func;
64396 			DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func));
64397 			funcptr = DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv_func);
64398 			rc = funcptr(thr);
64399 		}
64400 
64401 		/* Automatic error throwing, retval check. */
64402 
64403 		if (rc == 0) {
64404 			DUK_ASSERT(thr->valstack < thr->valstack_end);
64405 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
64406 			thr->valstack_top++;
64407 		} else if (rc == 1) {
64408 			;
64409 		} else if (rc < 0) {
64410 			duk_error_throw_from_negative_rc(thr, rc);
64411 			DUK_WO_NORETURN(return 0;);
64412 		} else {
64413 			DUK_ERROR_TYPE(thr, DUK_STR_INVALID_CFUNC_RC);
64414 			DUK_WO_NORETURN(return 0;);
64415 		}
64416 	}
64417 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
64418 	DUK_ASSERT(use_tailcall == 0);
64419 
64420 	/*
64421 	 *  Constructor call post processing.
64422 	 */
64423 
64424 #if defined(DUK_USE_ES6_PROXY)
64425 	if (call_flags & (DUK_CALL_FLAG_CONSTRUCT | DUK_CALL_FLAG_CONSTRUCT_PROXY)) {
64426 		duk_call_construct_postprocess(thr, call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY);
64427 	}
64428 #else
64429 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
64430 		duk_call_construct_postprocess(thr, 0);
64431 	}
64432 #endif
64433 
64434 	/*
64435 	 *  Unwind, restore valstack bottom and other book-keeping.
64436 	 */
64437 
64438 	DUK_ASSERT(thr->callstack_curr != NULL);
64439 	DUK_ASSERT(thr->callstack_curr->parent == entry_act);
64440 	DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
64441 	duk_hthread_activation_unwind_norz(thr);
64442 	DUK_ASSERT(thr->callstack_curr == entry_act);
64443 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
64444 
64445 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_bottom_byteoff);
64446 	/* keep current valstack_top */
64447 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
64448 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
64449 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
64450 	DUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= idx_func + 1);
64451 
64452 	/* Return value handling. */
64453 
64454 	/* [ ... func this (crud) retval ] */
64455 
64456 	{
64457 		duk_tval *tv_ret;
64458 		duk_tval *tv_funret;
64459 
64460 		tv_ret = thr->valstack_bottom + idx_func;
64461 		tv_funret = thr->valstack_top - 1;
64462 #if defined(DUK_USE_FASTINT)
64463 		/* Explicit check for fastint downgrade. */
64464 		DUK_TVAL_CHKFAST_INPLACE_FAST(tv_funret);
64465 #endif
64466 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret);  /* side effects */
64467 	}
64468 
64469 	duk_set_top_unsafe(thr, idx_func + 1);
64470 
64471 	/* [ ... retval ] */
64472 
64473 	/* Restore caller's value stack reserve (cannot fail). */
64474 	DUK_ASSERT((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff >= (duk_uint8_t *) thr->valstack_top);
64475 	DUK_ASSERT((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff <= (duk_uint8_t *) thr->valstack_alloc_end);
64476 	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff);
64477 
64478 	/* XXX: Trial value stack shrink would be OK here, but we'd need
64479 	 * to prevent side effects of the potential realloc.
64480 	 */
64481 
64482 	/* Restore entry thread executor curr_pc stack frame pointer. */
64483 	thr->ptr_curr_pc = entry_ptr_curr_pc;
64484 
64485 	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
64486 	thr->state = (duk_uint8_t) entry_thread_state;
64487 
64488 	/* Disabled assert: triggered with some torture tests. */
64489 #if 0
64490 	DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) ||  /* first call */
64491 	           (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) ||  /* other call */
64492 	           (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr));     /* current thread */
64493 #endif
64494 
64495 	thr->heap->call_recursion_depth = entry_call_recursion_depth;
64496 
64497 	/* If the debugger is active we need to force an interrupt so that
64498 	 * debugger breakpoints are rechecked.  This is important for function
64499 	 * calls caused by side effects (e.g. when doing a DUK_OP_GETPROP), see
64500 	 * GH-303.  Only needed for success path, error path always causes a
64501 	 * breakpoint recheck in the executor.  It would be enough to set this
64502 	 * only when returning to an ECMAScript activation, but setting the flag
64503 	 * on every return should have no ill effect.
64504 	 */
64505 #if defined(DUK_USE_DEBUGGER_SUPPORT)
64506 	if (duk_debug_is_attached(thr->heap)) {
64507 		DUK_DD(DUK_DDPRINT("returning with debugger enabled, force interrupt"));
64508 		DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
64509 		thr->interrupt_init -= thr->interrupt_counter;
64510 		thr->interrupt_counter = 0;
64511 		thr->heap->dbg_force_restart = 1;
64512 	}
64513 #endif
64514 
64515 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
64516 	duk__interrupt_fixup(thr, entry_curr_thread);
64517 #endif
64518 
64519 	/* Restored by success path. */
64520 	DUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);
64521 	DUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);
64522 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
64523 
64524 	DUK_REFZERO_CHECK_FAST(thr);
64525 
64526 	return 0;  /* 0=call handled inline */
64527 }
64528 
64529 DUK_INTERNAL duk_int_t duk_handle_call_unprotected_nargs(duk_hthread *thr,
64530                                                          duk_idx_t nargs,
64531                                                          duk_small_uint_t call_flags) {
64532 	duk_idx_t idx_func;
64533 	DUK_ASSERT(duk_get_top(thr) >= nargs + 2);
64534 	idx_func = duk_get_top(thr) - (nargs + 2);
64535 	DUK_ASSERT(idx_func >= 0);
64536 	return duk_handle_call_unprotected(thr, idx_func, call_flags);
64537 }
64538 
64539 DUK_INTERNAL duk_int_t duk_handle_call_unprotected(duk_hthread *thr,
64540                                                    duk_idx_t idx_func,
64541                                                    duk_small_uint_t call_flags) {
64542 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
64543 	DUK_ASSERT(idx_func >= 0);
64544 	return duk__handle_call_raw(thr, idx_func, call_flags);
64545 }
64546 
64547 /*
64548  *  duk_handle_safe_call(): make a "C protected call" within the
64549  *  current activation.
64550  *
64551  *  The allowed thread states for making a call are the same as for
64552  *  duk_handle_call_protected().
64553  *
64554  *  Even though this call is protected, errors are thrown for insane arguments
64555  *  and may result in a fatal error unless there's another protected call which
64556  *  catches such errors.
64557  *
64558  *  The error handling path should be error free, even for out-of-memory
64559  *  errors, to ensure safe sandboxing.  (As of Duktape 2.2.0 this is not
64560  *  yet the case for environment closing which may run out of memory, see
64561  *  XXX notes below.)
64562  */
64563 
64564 DUK_LOCAL void duk__handle_safe_call_inner(duk_hthread *thr,
64565                                            duk_safe_call_function func,
64566                                            void *udata,
64567 #if defined(DUK_USE_ASSERTIONS)
64568                                            duk_size_t entry_valstack_bottom_byteoff,
64569                                            duk_size_t entry_callstack_top,
64570 #endif
64571                                            duk_hthread *entry_curr_thread,
64572                                            duk_uint_fast8_t entry_thread_state,
64573                                            duk_idx_t idx_retbase,
64574                                            duk_idx_t num_stack_rets) {
64575 	duk_ret_t rc;
64576 
64577 	DUK_ASSERT(thr != NULL);
64578 	DUK_ASSERT_CTX_VALID(thr);
64579 
64580 	/*
64581 	 *  Thread state check and book-keeping.
64582 	 */
64583 
64584 	duk__call_thread_state_update(thr);
64585 
64586 	/*
64587 	 *  Recursion limit check.
64588 	 */
64589 
64590 	duk__call_c_recursion_limit_check(thr);
64591 	thr->heap->call_recursion_depth++;
64592 
64593 	/*
64594 	 *  Make the C call.
64595 	 */
64596 
64597 	rc = func(thr, udata);
64598 
64599 	DUK_DDD(DUK_DDDPRINT("safe_call, func rc=%ld", (long) rc));
64600 
64601 	/*
64602 	 *  Valstack manipulation for results.
64603 	 */
64604 
64605 	/* we're running inside the caller's activation, so no change in call/catch stack or valstack bottom */
64606 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
64607 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
64608 	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) == entry_valstack_bottom_byteoff);
64609 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
64610 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
64611 
64612 	if (DUK_UNLIKELY(rc < 0)) {
64613 		duk_error_throw_from_negative_rc(thr, rc);
64614 		DUK_WO_NORETURN(return;);
64615 	}
64616 	DUK_ASSERT(rc >= 0);
64617 
64618 	duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, rc);  /* throws for insane rc */
64619 
64620 	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
64621 	thr->state = (duk_uint8_t) entry_thread_state;
64622 }
64623 
64624 DUK_LOCAL void duk__handle_safe_call_error(duk_hthread *thr,
64625                                            duk_activation *entry_act,
64626 #if defined(DUK_USE_ASSERTIONS)
64627                                            duk_size_t entry_callstack_top,
64628 #endif
64629                                            duk_hthread *entry_curr_thread,
64630                                            duk_uint_fast8_t entry_thread_state,
64631                                            duk_idx_t idx_retbase,
64632                                            duk_idx_t num_stack_rets,
64633                                            duk_size_t entry_valstack_bottom_byteoff,
64634                                            duk_jmpbuf *old_jmpbuf_ptr) {
64635 	DUK_ASSERT(thr != NULL);
64636 	DUK_ASSERT_CTX_VALID(thr);
64637 
64638 	/*
64639 	 *  Error during call.  The error value is at heap->lj.value1.
64640 	 *
64641 	 *  The very first thing we do is restore the previous setjmp catcher.
64642 	 *  This means that any error in error handling will propagate outwards
64643 	 *  instead of causing a setjmp() re-entry above.
64644 	 */
64645 
64646 	DUK_DDD(DUK_DDDPRINT("error caught during protected duk_handle_safe_call()"));
64647 
64648 	/* Other longjmp types are handled by executor before propagating
64649 	 * the error here.
64650 	 */
64651 	DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);
64652 	DUK_ASSERT_LJSTATE_SET(thr->heap);
64653 
64654 	/* Either pointer may be NULL (at entry), so don't assert. */
64655 	thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
64656 
64657 	/* XXX: callstack unwind may now throw an error when closing
64658 	 * scopes; this is a sandboxing issue, described in:
64659 	 * https://github.com/svaarala/duktape/issues/476
64660 	 */
64661 	/* XXX: "unwind to" primitive? */
64662 
64663 	DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
64664 	while (thr->callstack_curr != entry_act) {
64665 		DUK_ASSERT(thr->callstack_curr != NULL);
64666 		duk_hthread_activation_unwind_norz(thr);
64667 	}
64668 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
64669 
64670 	/* Switch active thread before any side effects to avoid a
64671 	 * dangling curr_thread pointer.
64672 	 */
64673 	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
64674 	thr->state = (duk_uint8_t) entry_thread_state;
64675 
64676 	DUK_ASSERT(thr->heap->curr_thread == entry_curr_thread);
64677 	DUK_ASSERT(thr->state == entry_thread_state);
64678 
64679 	/* Restore valstack bottom. */
64680 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_bottom_byteoff);
64681 
64682 	/* [ ... | (crud) ] */
64683 
64684 	/* XXX: ensure space in valstack (now relies on internal reserve)? */
64685 	duk_push_tval(thr, &thr->heap->lj.value1);
64686 
64687 	/* [ ... | (crud) errobj ] */
64688 
64689 	DUK_ASSERT(duk_get_top(thr) >= 1);  /* at least errobj must be on stack */
64690 
64691 	duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, 1);  /* 1 = num actual 'return values' */
64692 
64693 	/* [ ... | ] or [ ... | errobj (M * undefined)] where M = num_stack_rets - 1 */
64694 
64695 	/* Reset longjmp state. */
64696 	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
64697 	thr->heap->lj.iserror = 0;
64698 	DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, &thr->heap->lj.value1);
64699 	DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, &thr->heap->lj.value2);
64700 
64701 	/* Error handling complete, remove side effect protections.  Caller
64702 	 * will process pending finalizers.
64703 	 */
64704 #if defined(DUK_USE_ASSERTIONS)
64705 	DUK_ASSERT(thr->heap->error_not_allowed == 1);
64706 	thr->heap->error_not_allowed = 0;
64707 #endif
64708 	DUK_ASSERT(thr->heap->pf_prevent_count > 0);
64709 	thr->heap->pf_prevent_count--;
64710 	DUK_DD(DUK_DDPRINT("safe call error handled, pf_prevent_count updated to %ld", (long) thr->heap->pf_prevent_count));
64711 
64712 	/* thr->ptr_curr_pc is restored by
64713 	 * duk__handle_safe_call_shared_unwind() which is also used for
64714 	 * success path.
64715 	 */
64716 }
64717 
64718 DUK_LOCAL void duk__handle_safe_call_shared_unwind(duk_hthread *thr,
64719                                                    duk_idx_t idx_retbase,
64720                                                    duk_idx_t num_stack_rets,
64721 #if defined(DUK_USE_ASSERTIONS)
64722                                                    duk_size_t entry_callstack_top,
64723 #endif
64724                                                    duk_int_t entry_call_recursion_depth,
64725                                                    duk_hthread *entry_curr_thread,
64726                                                    duk_instr_t **entry_ptr_curr_pc) {
64727 	DUK_ASSERT(thr != NULL);
64728 	DUK_ASSERT_CTX_VALID(thr);
64729 	DUK_UNREF(idx_retbase);
64730 	DUK_UNREF(num_stack_rets);
64731 	DUK_UNREF(entry_curr_thread);
64732 
64733 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
64734 
64735 	/* Restore entry thread executor curr_pc stack frame pointer.
64736 	 * XXX: would be enough to do in error path only, should nest
64737 	 * cleanly in success path.
64738 	 */
64739 	thr->ptr_curr_pc = entry_ptr_curr_pc;
64740 
64741 	thr->heap->call_recursion_depth = entry_call_recursion_depth;
64742 
64743 	/* stack discipline consistency check */
64744 	DUK_ASSERT(duk_get_top(thr) == idx_retbase + num_stack_rets);
64745 
64746 	/* A debugger forced interrupt check is not needed here, as
64747 	 * problematic safe calls are not caused by side effects.
64748 	 */
64749 
64750 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
64751 	duk__interrupt_fixup(thr, entry_curr_thread);
64752 #endif
64753 }
64754 
64755 DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr,
64756                                             duk_safe_call_function func,
64757                                             void *udata,
64758                                             duk_idx_t num_stack_args,
64759                                             duk_idx_t num_stack_rets) {
64760 	duk_activation *entry_act;
64761 	duk_size_t entry_valstack_bottom_byteoff;
64762 #if defined(DUK_USE_ASSERTIONS)
64763 	duk_size_t entry_valstack_end_byteoff;
64764 	duk_size_t entry_callstack_top;
64765 	duk_size_t entry_callstack_preventcount;
64766 #endif
64767 	duk_int_t entry_call_recursion_depth;
64768 	duk_hthread *entry_curr_thread;
64769 	duk_uint_fast8_t entry_thread_state;
64770 	duk_instr_t **entry_ptr_curr_pc;
64771 	duk_jmpbuf *old_jmpbuf_ptr = NULL;
64772 	duk_jmpbuf our_jmpbuf;
64773 	duk_idx_t idx_retbase;
64774 	duk_int_t retval;
64775 
64776 	DUK_ASSERT(thr != NULL);
64777 	DUK_ASSERT(duk_get_top(thr) >= num_stack_args);  /* Caller ensures. */
64778 
64779 	DUK_STATS_INC(thr->heap, stats_safecall_all);
64780 
64781 	/* Value stack reserve handling: safe call assumes caller has reserved
64782 	 * space for nrets (assuming optimal unwind processing).  Value stack
64783 	 * reserve is not stored/restored as for normal calls because a safe
64784 	 * call conceptually happens in the same activation.
64785 	 */
64786 
64787 	/* Careful with indices like '-x'; if 'x' is zero, it refers to bottom */
64788 	entry_act = thr->callstack_curr;
64789 	entry_valstack_bottom_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
64790 #if defined(DUK_USE_ASSERTIONS)
64791 	entry_valstack_end_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
64792 	entry_callstack_top = thr->callstack_top;
64793 	entry_callstack_preventcount = thr->callstack_preventcount;
64794 #endif
64795 	entry_call_recursion_depth = thr->heap->call_recursion_depth;
64796 	entry_curr_thread = thr->heap->curr_thread;  /* may be NULL if first call */
64797 	entry_thread_state = thr->state;
64798 	entry_ptr_curr_pc = thr->ptr_curr_pc;  /* may be NULL */
64799 	idx_retbase = duk_get_top(thr) - num_stack_args;  /* not a valid stack index if num_stack_args == 0 */
64800 	DUK_ASSERT(idx_retbase >= 0);
64801 
64802 	DUK_ASSERT((duk_idx_t) (thr->valstack_top - thr->valstack_bottom) >= num_stack_args);  /* Caller ensures. */
64803 	DUK_ASSERT((duk_idx_t) (thr->valstack_end - (thr->valstack_bottom + idx_retbase)) >= num_stack_rets);  /* Caller ensures. */
64804 
64805 	/* Cannot portably debug print a function pointer, hence 'func' not printed! */
64806 	DUK_DD(DUK_DDPRINT("duk_handle_safe_call: thr=%p, num_stack_args=%ld, num_stack_rets=%ld, "
64807 	                   "valstack_top=%ld, idx_retbase=%ld, rec_depth=%ld/%ld, "
64808 	                   "entry_act=%p, entry_valstack_bottom_byteoff=%ld, entry_call_recursion_depth=%ld, "
64809 	                   "entry_curr_thread=%p, entry_thread_state=%ld",
64810 	                   (void *) thr,
64811 	                   (long) num_stack_args,
64812 	                   (long) num_stack_rets,
64813 	                   (long) duk_get_top(thr),
64814 	                   (long) idx_retbase,
64815 	                   (long) thr->heap->call_recursion_depth,
64816 	                   (long) thr->heap->call_recursion_limit,
64817 	                   (void *) entry_act,
64818 	                   (long) entry_valstack_bottom_byteoff,
64819 	                   (long) entry_call_recursion_depth,
64820 	                   (void *) entry_curr_thread,
64821 	                   (long) entry_thread_state));
64822 
64823 	/* Setjmp catchpoint setup. */
64824 	old_jmpbuf_ptr = thr->heap->lj.jmpbuf_ptr;
64825 	thr->heap->lj.jmpbuf_ptr = &our_jmpbuf;
64826 
64827 	/* Prevent yields for the duration of the safe call.  This only
64828 	 * matters if the executor makes safe calls to functions that
64829 	 * yield, this doesn't currently happen.
64830 	 */
64831 	thr->callstack_preventcount++;
64832 
64833 #if defined(DUK_USE_CPP_EXCEPTIONS)
64834 	try {
64835 #else
64836 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == &our_jmpbuf);
64837 	if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
64838 		/* Success path. */
64839 #endif
64840 		DUK_DDD(DUK_DDDPRINT("safe_call setjmp catchpoint setup complete"));
64841 
64842 		duk__handle_safe_call_inner(thr,
64843 		                            func,
64844 		                            udata,
64845 #if defined(DUK_USE_ASSERTIONS)
64846 		                            entry_valstack_bottom_byteoff,
64847 		                            entry_callstack_top,
64848 #endif
64849 		                            entry_curr_thread,
64850 		                            entry_thread_state,
64851 		                            idx_retbase,
64852 		                            num_stack_rets);
64853 
64854 		DUK_STATS_INC(thr->heap, stats_safecall_nothrow);
64855 
64856 		/* Either pointer may be NULL (at entry), so don't assert */
64857 		thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
64858 
64859 		/* If calls happen inside the safe call, these are restored by
64860 		 * whatever calls are made.  Reserve cannot decrease.
64861 		 */
64862 		DUK_ASSERT(thr->callstack_curr == entry_act);
64863 		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
64864 
64865 		retval = DUK_EXEC_SUCCESS;
64866 #if defined(DUK_USE_CPP_EXCEPTIONS)
64867 	} catch (duk_internal_exception &exc) {
64868 		DUK_UNREF(exc);
64869 #else
64870 	} else {
64871 		/* Error path. */
64872 #endif
64873 		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
64874 
64875 		DUK_STATS_INC(thr->heap, stats_safecall_throw);
64876 
64877 		duk__handle_safe_call_error(thr,
64878 		                            entry_act,
64879 #if defined(DUK_USE_ASSERTIONS)
64880 		                            entry_callstack_top,
64881 #endif
64882 		                            entry_curr_thread,
64883 		                            entry_thread_state,
64884 		                            idx_retbase,
64885 		                            num_stack_rets,
64886 		                            entry_valstack_bottom_byteoff,
64887 		                            old_jmpbuf_ptr);
64888 
64889 		retval = DUK_EXEC_ERROR;
64890 	}
64891 #if defined(DUK_USE_CPP_EXCEPTIONS)
64892 	catch (duk_fatal_exception &exc) {
64893 		DUK_D(DUK_DPRINT("rethrow duk_fatal_exception"));
64894 		throw;
64895 	} catch (std::exception &exc) {
64896 		const char *what = exc.what();
64897 		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
64898 		DUK_STATS_INC(thr->heap, stats_safecall_throw);
64899 		if (!what) {
64900 			what = "unknown";
64901 		}
64902 		DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
64903 		try {
64904 			DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
64905 			DUK_WO_NORETURN(return 0;);
64906 		} catch (duk_internal_exception exc) {
64907 			DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
64908 			DUK_UNREF(exc);
64909 			duk__handle_safe_call_error(thr,
64910 			                            entry_act,
64911 #if defined(DUK_USE_ASSERTIONS)
64912 			                            entry_callstack_top,
64913 #endif
64914 			                            entry_curr_thread,
64915 			                            entry_thread_state,
64916 			                            idx_retbase,
64917 			                            num_stack_rets,
64918 			                            entry_valstack_bottom_byteoff,
64919 			                            old_jmpbuf_ptr);
64920 			retval = DUK_EXEC_ERROR;
64921 		}
64922 	} catch (...) {
64923 		DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
64924 		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
64925 		DUK_STATS_INC(thr->heap, stats_safecall_throw);
64926 		try {
64927 			DUK_ERROR_TYPE(thr, "caught invalid c++ exception (perhaps thrown by user code)");
64928 			DUK_WO_NORETURN(return 0;);
64929 		} catch (duk_internal_exception exc) {
64930 			DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
64931 			DUK_UNREF(exc);
64932 			duk__handle_safe_call_error(thr,
64933 			                            entry_act,
64934 #if defined(DUK_USE_ASSERTIONS)
64935 			                            entry_callstack_top,
64936 #endif
64937 			                            entry_curr_thread,
64938 			                            entry_thread_state,
64939 			                            idx_retbase,
64940 			                            num_stack_rets,
64941 			                            entry_valstack_bottom_byteoff,
64942 			                            old_jmpbuf_ptr);
64943 			retval = DUK_EXEC_ERROR;
64944 		}
64945 	}
64946 #endif
64947 
64948 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == old_jmpbuf_ptr);  /* success/error path both do this */
64949 
64950 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
64951 
64952 	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
64953 	duk__handle_safe_call_shared_unwind(thr,
64954 	                                    idx_retbase,
64955 	                                    num_stack_rets,
64956 #if defined(DUK_USE_ASSERTIONS)
64957 	                                    entry_callstack_top,
64958 #endif
64959 	                                    entry_call_recursion_depth,
64960 	                                    entry_curr_thread,
64961 	                                    entry_ptr_curr_pc);
64962 
64963 	/* Restore preventcount. */
64964 	thr->callstack_preventcount--;
64965 	DUK_ASSERT(thr->callstack_preventcount == entry_callstack_preventcount);
64966 
64967 	/* Final asserts. */
64968 	DUK_ASSERT(thr->callstack_curr == entry_act);
64969 	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) == entry_valstack_bottom_byteoff);
64970 	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
64971 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
64972 	DUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);
64973 	DUK_ASSERT(thr->heap->curr_thread == entry_curr_thread);
64974 	DUK_ASSERT(thr->state == entry_thread_state);
64975 	DUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);
64976 	DUK_ASSERT(duk_get_top(thr) == idx_retbase + num_stack_rets);
64977 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
64978 
64979 	/* Pending side effects. */
64980 	DUK_REFZERO_CHECK_FAST(thr);
64981 
64982 	return retval;
64983 }
64984 
64985 /*
64986  *  Property-based call (foo.noSuch()) error setup: replace target function
64987  *  on stack top with a specially tagged (hidden Symbol) error which gets
64988  *  thrown in call handling at the proper spot to follow ECMAScript semantics.
64989  */
64990 
64991 #if defined(DUK_USE_VERBOSE_ERRORS)
64992 DUK_INTERNAL DUK_NOINLINE DUK_COLD void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_targ, duk_tval *tv_base, duk_tval *tv_key) {
64993 	const char *str1, *str2, *str3;
64994 	duk_idx_t entry_top;
64995 
64996 	entry_top = duk_get_top(thr);
64997 
64998 	/* Must stabilize pointers first.  Argument convention is a bit awkward,
64999 	 * it comes from the executor call site where some arguments may not be
65000 	 * on the value stack (consts).
65001 	 */
65002 	duk_push_tval(thr, tv_base);
65003 	duk_push_tval(thr, tv_key);
65004 	duk_push_tval(thr, tv_targ);
65005 
65006 	DUK_GC_TORTURE(thr->heap);
65007 
65008 	/* We only push an error, replacing the call target (at idx_func)
65009 	 * with the error to ensure side effects come out correctly:
65010 	 * - Property read
65011 	 * - Call argument evaluation
65012 	 * - Callability check and error thrown.
65013 	 *
65014 	 * A hidden Symbol on the error object pushed here is used by
65015 	 * call handling to figure out the error is to be thrown as is.
65016 	 * It is CRITICAL that the hidden Symbol can never occur on a
65017 	 * user visible object that may get thrown.
65018 	 */
65019 
65020 #if defined(DUK_USE_PARANOID_ERRORS)
65021 	str1 = duk_get_type_name(thr, -1);
65022 	str2 = duk_get_type_name(thr, -2);
65023 	str3 = duk_get_type_name(thr, -3);
65024 	duk_push_error_object(thr, DUK_ERR_TYPE_ERROR | DUK_ERRCODE_FLAG_NOBLAME_FILELINE, "%s not callable (property %s of %s)", str1, str2, str3);
65025 #else
65026 	str1 = duk_push_string_readable(thr, -1);
65027 	str2 = duk_push_string_readable(thr, -3);
65028 	str3 = duk_push_string_readable(thr, -5);
65029 	duk_push_error_object(thr, DUK_ERR_TYPE_ERROR | DUK_ERRCODE_FLAG_NOBLAME_FILELINE, "%s not callable (property %s of %s)", str1, str2, str3);
65030 #endif
65031 
65032 	duk_push_true(thr);
65033 	duk_put_prop_stridx(thr, -2, DUK_STRIDX_INT_TARGET);  /* Marker property, reuse _Target. */
65034 
65035 	/* [ <nregs> propValue <variable> error ] */
65036 	duk_replace(thr, entry_top - 1);
65037 	duk_set_top(thr, entry_top);
65038 
65039 	DUK_ASSERT(!duk_is_callable(thr, -1));  /* Critical so that call handling will throw the error. */
65040 }
65041 #endif  /* DUK_USE_VERBOSE_ERRORS */
65042 
65043 /* automatic undefs */
65044 #undef DUK__AUGMENT_CALL_RELAX_COUNT
65045 #line 1 "duk_js_compiler.c"
65046 /*
65047  *  ECMAScript compiler.
65048  *
65049  *  Parses an input string and generates a function template result.
65050  *  Compilation may happen in multiple contexts (global code, eval
65051  *  code, function code).
65052  *
65053  *  The parser uses a traditional top-down recursive parsing for the
65054  *  statement level, and an operator precedence based top-down approach
65055  *  for the expression level.  The attempt is to minimize the C stack
65056  *  depth.  Bytecode is generated directly without an intermediate
65057  *  representation (tree), at the cost of needing two (and sometimes
65058  *  three) passes over each function.
65059  *
65060  *  The top-down recursive parser functions are named "duk__parse_XXX".
65061  *
65062  *  Recursion limits are in key functions to prevent arbitrary C recursion:
65063  *  function body parsing, statement parsing, and expression parsing.
65064  *
65065  *  See doc/compiler.rst for discussion on the design.
65066  *
65067  *  A few typing notes:
65068  *
65069  *    - duk_regconst_t: signed, highest bit set (< 0) means constant,
65070  *      some call sites use -1 for "none" (equivalent to constant 0x7fffffff)
65071  *    - PC values: duk_int_t, negative values used as markers
65072  */
65073 
65074 /* #include duk_internal.h -> already included */
65075 
65076 /* If highest bit of a register number is set, it refers to a constant instead.
65077  * When interpreted as a signed value, this means const values are always
65078  * negative (when interpreted as two's complement).  For example DUK__ISREG_TEMP()
65079  * uses this approach to avoid an explicit DUK__ISREG() check (the condition is
65080  * logically "'x' is a register AND 'x' >= temp_first").
65081  */
65082 #define DUK__CONST_MARKER                   DUK_REGCONST_CONST_MARKER
65083 #define DUK__REMOVECONST(x)                 ((x) & ~DUK__CONST_MARKER)
65084 #define DUK__ISREG(x)                       ((x) >= 0)
65085 #define DUK__ISCONST(x)                     ((x) < 0)
65086 #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. */
65087 #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. */
65088 #define DUK__GETTEMP(comp_ctx)              ((comp_ctx)->curr_func.temp_next)
65089 #define DUK__SETTEMP(comp_ctx,x)            ((comp_ctx)->curr_func.temp_next = (x))  /* dangerous: must only lower (temp_max not updated) */
65090 #define DUK__SETTEMP_CHECKMAX(comp_ctx,x)   duk__settemp_checkmax((comp_ctx),(x))
65091 #define DUK__ALLOCTEMP(comp_ctx)            duk__alloctemp((comp_ctx))
65092 #define DUK__ALLOCTEMPS(comp_ctx,count)     duk__alloctemps((comp_ctx),(count))
65093 
65094 /* Init value set size for array and object literals. */
65095 #define DUK__MAX_ARRAY_INIT_VALUES        20
65096 #define DUK__MAX_OBJECT_INIT_PAIRS        10
65097 
65098 /* XXX: hack, remove when const lookup is not O(n) */
65099 #define DUK__GETCONST_MAX_CONSTS_CHECK    256
65100 
65101 /* These limits are based on bytecode limits.  Max temps is limited
65102  * by duk_hcompfunc nargs/nregs fields being 16 bits.
65103  */
65104 #define DUK__MAX_CONSTS                   DUK_BC_BC_MAX
65105 #define DUK__MAX_FUNCS                    DUK_BC_BC_MAX
65106 #define DUK__MAX_TEMPS                    0xffffL
65107 
65108 /* Initial bytecode size allocation. */
65109 #if defined(DUK_USE_PREFER_SIZE)
65110 #define DUK__BC_INITIAL_INSTS             16
65111 #else
65112 #define DUK__BC_INITIAL_INSTS             256
65113 #endif
65114 
65115 #define DUK__RECURSION_INCREASE(comp_ctx,thr)  do { \
65116 		DUK_DDD(DUK_DDDPRINT("RECURSION INCREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
65117 		duk__comp_recursion_increase((comp_ctx)); \
65118 	} while (0)
65119 
65120 #define DUK__RECURSION_DECREASE(comp_ctx,thr)  do { \
65121 		DUK_DDD(DUK_DDDPRINT("RECURSION DECREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
65122 		duk__comp_recursion_decrease((comp_ctx)); \
65123 	} while (0)
65124 
65125 /* Value stack slot limits: these are quite approximate right now, and
65126  * because they overlap in control flow, some could be eliminated.
65127  */
65128 #define DUK__COMPILE_ENTRY_SLOTS          8
65129 #define DUK__FUNCTION_INIT_REQUIRE_SLOTS  16
65130 #define DUK__FUNCTION_BODY_REQUIRE_SLOTS  16
65131 #define DUK__PARSE_STATEMENTS_SLOTS       16
65132 #define DUK__PARSE_EXPR_SLOTS             16
65133 
65134 /* Temporary structure used to pass a stack allocated region through
65135  * duk_safe_call().
65136  */
65137 typedef struct {
65138 	duk_small_uint_t flags;
65139 	duk_compiler_ctx comp_ctx_alloc;
65140 	duk_lexer_point lex_pt_alloc;
65141 } duk__compiler_stkstate;
65142 
65143 /*
65144  *  Prototypes
65145  */
65146 
65147 /* lexing */
65148 DUK_LOCAL_DECL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);
65149 DUK_LOCAL_DECL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);
65150 DUK_LOCAL_DECL void duk__advance(duk_compiler_ctx *ctx);
65151 
65152 /* function helpers */
65153 DUK_LOCAL_DECL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx);
65154 DUK_LOCAL_DECL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx);
65155 DUK_LOCAL_DECL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_regconst_t *out_stmt_value_reg);
65156 DUK_LOCAL_DECL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx);
65157 DUK_LOCAL_DECL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx);
65158 
65159 /* code emission */
65160 DUK_LOCAL_DECL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx);
65161 DUK_LOCAL_DECL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc);
65162 DUK_LOCAL_DECL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins);
65163 DUK_LOCAL_DECL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op);
65164 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);
65165 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);
65166 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);
65167 #if 0  /* unused */
65168 DUK_LOCAL_DECL void duk__emit_a(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a);
65169 DUK_LOCAL_DECL void duk__emit_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b);
65170 #endif
65171 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);
65172 DUK_LOCAL_DECL void duk__emit_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t bc);
65173 DUK_LOCAL_DECL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc);
65174 DUK_LOCAL_DECL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val);
65175 DUK_LOCAL_DECL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val);
65176 DUK_LOCAL_DECL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc);
65177 DUK_LOCAL_DECL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx);
65178 DUK_LOCAL_DECL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
65179 DUK_LOCAL_DECL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc);
65180 DUK_LOCAL_DECL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
65181 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);
65182 DUK_LOCAL_DECL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
65183 DUK_LOCAL_DECL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
65184 DUK_LOCAL_DECL void duk__emit_invalid(duk_compiler_ctx *comp_ctx);
65185 
65186 /* ivalue/ispec helpers */
65187 DUK_LOCAL_DECL void duk__ivalue_regconst(duk_ivalue *x, duk_regconst_t regconst);
65188 DUK_LOCAL_DECL void duk__ivalue_plain_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65189 DUK_LOCAL_DECL void duk__ivalue_var_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65190 DUK_LOCAL_DECL void duk__ivalue_var_hstring(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_hstring *h);
65191 DUK_LOCAL_DECL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst);
65192 DUK_LOCAL_DECL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst);
65193 DUK_LOCAL_DECL duk_regconst_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num);
65194 DUK_LOCAL_DECL duk_regconst_t duk__alloctemp(duk_compiler_ctx *comp_ctx);
65195 DUK_LOCAL_DECL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_regconst_t temp_next);
65196 DUK_LOCAL_DECL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx);
65197 DUK_LOCAL_DECL
65198 duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
65199                                          duk_ispec *x,
65200                                          duk_regconst_t forced_reg,
65201                                          duk_small_uint_t flags);
65202 DUK_LOCAL_DECL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_regconst_t forced_reg);
65203 DUK_LOCAL_DECL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_regconst_t forced_reg);
65204 DUK_LOCAL_DECL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65205 DUK_LOCAL_DECL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65206 DUK_LOCAL_DECL
65207 duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
65208                                           duk_ivalue *x,
65209                                           duk_regconst_t forced_reg,
65210                                           duk_small_uint_t flags);
65211 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65212 #if 0  /* unused */
65213 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65214 #endif
65215 DUK_LOCAL_DECL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg);
65216 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65217 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65218 
65219 /* identifier handling */
65220 DUK_LOCAL_DECL duk_regconst_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx);
65221 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);
65222 
65223 /* label handling */
65224 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);
65225 DUK_LOCAL_DECL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags);
65226 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);
65227 DUK_LOCAL_DECL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_size_t len);
65228 
65229 /* top-down expression parser */
65230 DUK_LOCAL_DECL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65231 DUK_LOCAL_DECL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res);
65232 DUK_LOCAL_DECL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx);
65233 DUK_LOCAL_DECL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx);
65234 
65235 /* exprtop is the top level variant which resets nud/led counts */
65236 DUK_LOCAL_DECL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65237 DUK_LOCAL_DECL void duk__exprtop(duk_compiler_ctx *ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65238 
65239 /* convenience helpers */
65240 #if 0  /* unused */
65241 DUK_LOCAL_DECL duk_regconst_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65242 #endif
65243 #if 0  /* unused */
65244 DUK_LOCAL_DECL duk_regconst_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65245 #endif
65246 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);
65247 DUK_LOCAL_DECL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65248 #if 0  /* unused */
65249 DUK_LOCAL_DECL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65250 #endif
65251 DUK_LOCAL_DECL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65252 DUK_LOCAL_DECL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65253 DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65254 #if 0  /* unused */
65255 DUK_LOCAL_DECL duk_regconst_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65256 #endif
65257 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);
65258 DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65259 #if 0  /* unused */
65260 DUK_LOCAL_DECL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65261 #endif
65262 
65263 /* expression parsing helpers */
65264 DUK_LOCAL_DECL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65265 DUK_LOCAL_DECL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65266 DUK_LOCAL_DECL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65267 
65268 /* statement parsing */
65269 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);
65270 DUK_LOCAL_DECL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags);
65271 DUK_LOCAL_DECL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
65272 DUK_LOCAL_DECL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
65273 DUK_LOCAL_DECL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65274 DUK_LOCAL_DECL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
65275 DUK_LOCAL_DECL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
65276 DUK_LOCAL_DECL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65277 DUK_LOCAL_DECL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65278 DUK_LOCAL_DECL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65279 DUK_LOCAL_DECL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65280 DUK_LOCAL_DECL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65281 DUK_LOCAL_DECL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem);
65282 DUK_LOCAL_DECL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id);
65283 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);
65284 
65285 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);
65286 DUK_LOCAL_DECL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx);
65287 DUK_LOCAL_DECL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags);
65288 DUK_LOCAL_DECL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags);
65289 
65290 #define DUK__FUNC_FLAG_DECL            (1 << 0)   /* Parsing a function declaration. */
65291 #define DUK__FUNC_FLAG_GETSET          (1 << 1)   /* Parsing an object literal getter/setter. */
65292 #define DUK__FUNC_FLAG_METDEF          (1 << 2)   /* Parsing an object literal method definition shorthand. */
65293 #define DUK__FUNC_FLAG_PUSHNAME_PASS1  (1 << 3)   /* Push function name when creating template (first pass only). */
65294 #define DUK__FUNC_FLAG_USE_PREVTOKEN   (1 << 4)   /* Use prev_token to start function parsing (workaround for object literal). */
65295 
65296 /*
65297  *  Parser control values for tokens.  The token table is ordered by the
65298  *  DUK_TOK_XXX defines.
65299  *
65300  *  The binding powers are for lbp() use (i.e. for use in led() context).
65301  *  Binding powers are positive for typing convenience, and bits at the
65302  *  top should be reserved for flags.  Binding power step must be higher
65303  *  than 1 so that binding power "lbp - 1" can be used for right associative
65304  *  operators.  Currently a step of 2 is used (which frees one more bit for
65305  *  flags).
65306  */
65307 
65308 /* XXX: actually single step levels would work just fine, clean up */
65309 
65310 /* binding power "levels" (see doc/compiler.rst) */
65311 #define DUK__BP_INVALID                0             /* always terminates led() */
65312 #define DUK__BP_EOF                    2
65313 #define DUK__BP_CLOSING                4             /* token closes expression, e.g. ')', ']' */
65314 #define DUK__BP_FOR_EXPR               DUK__BP_CLOSING    /* bp to use when parsing a top level Expression */
65315 #define DUK__BP_COMMA                  6
65316 #define DUK__BP_ASSIGNMENT             8
65317 #define DUK__BP_CONDITIONAL            10
65318 #define DUK__BP_LOR                    12
65319 #define DUK__BP_LAND                   14
65320 #define DUK__BP_BOR                    16
65321 #define DUK__BP_BXOR                   18
65322 #define DUK__BP_BAND                   20
65323 #define DUK__BP_EQUALITY               22
65324 #define DUK__BP_RELATIONAL             24
65325 #define DUK__BP_SHIFT                  26
65326 #define DUK__BP_ADDITIVE               28
65327 #define DUK__BP_MULTIPLICATIVE         30
65328 #define DUK__BP_EXPONENTIATION         32
65329 #define DUK__BP_POSTFIX                34
65330 #define DUK__BP_CALL                   36
65331 #define DUK__BP_MEMBER                 38
65332 
65333 #define DUK__TOKEN_LBP_BP_MASK         0x1f
65334 #define DUK__TOKEN_LBP_FLAG_NO_REGEXP  (1 << 5)   /* regexp literal must not follow this token */
65335 #define DUK__TOKEN_LBP_FLAG_TERMINATES (1 << 6)   /* terminates expression; e.g. post-increment/-decrement */
65336 #define DUK__TOKEN_LBP_FLAG_UNUSED     (1 << 7)   /* unused */
65337 
65338 #define DUK__TOKEN_LBP_GET_BP(x)       ((duk_small_uint_t) (((x) & DUK__TOKEN_LBP_BP_MASK) * 2))
65339 
65340 #define DUK__MK_LBP(bp)                ((bp) >> 1)    /* bp is assumed to be even */
65341 #define DUK__MK_LBP_FLAGS(bp,flags)    (((bp) >> 1) | (flags))
65342 
65343 DUK_LOCAL const duk_uint8_t duk__token_lbp[] = {
65344 	DUK__MK_LBP(DUK__BP_EOF),                                 /* DUK_TOK_EOF */
65345 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_IDENTIFIER */
65346 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_BREAK */
65347 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CASE */
65348 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CATCH */
65349 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CONTINUE */
65350 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DEBUGGER */
65351 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DEFAULT */
65352 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DELETE */
65353 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DO */
65354 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_ELSE */
65355 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FINALLY */
65356 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FOR */
65357 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FUNCTION */
65358 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IF */
65359 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_IN */
65360 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_INSTANCEOF */
65361 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_NEW */
65362 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_RETURN */
65363 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SWITCH */
65364 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_THIS */
65365 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_THROW */
65366 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_TRY */
65367 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_TYPEOF */
65368 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_VAR */
65369 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CONST */
65370 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_VOID */
65371 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_WHILE */
65372 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_WITH */
65373 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CLASS */
65374 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_ENUM */
65375 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_EXPORT */
65376 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_EXTENDS */
65377 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IMPORT */
65378 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SUPER */
65379 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_NULL */
65380 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_TRUE */
65381 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_FALSE */
65382 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_GET */
65383 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SET */
65384 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IMPLEMENTS */
65385 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_INTERFACE */
65386 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LET */
65387 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PACKAGE */
65388 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PRIVATE */
65389 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PROTECTED */
65390 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PUBLIC */
65391 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_STATIC */
65392 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_YIELD */
65393 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LCURLY */
65394 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RCURLY */
65395 	DUK__MK_LBP(DUK__BP_MEMBER),                              /* DUK_TOK_LBRACKET */
65396 	DUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RBRACKET */
65397 	DUK__MK_LBP(DUK__BP_CALL),                                /* DUK_TOK_LPAREN */
65398 	DUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RPAREN */
65399 	DUK__MK_LBP(DUK__BP_MEMBER),                              /* DUK_TOK_PERIOD */
65400 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SEMICOLON */
65401 	DUK__MK_LBP(DUK__BP_COMMA),                               /* DUK_TOK_COMMA */
65402 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_LT */
65403 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_GT */
65404 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_LE */
65405 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_GE */
65406 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_EQ */
65407 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_NEQ */
65408 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_SEQ */
65409 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_SNEQ */
65410 	DUK__MK_LBP(DUK__BP_ADDITIVE),                            /* DUK_TOK_ADD */
65411 	DUK__MK_LBP(DUK__BP_ADDITIVE),                            /* DUK_TOK_SUB */
65412 	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_MUL */
65413 	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_DIV */
65414 	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_MOD */
65415 	DUK__MK_LBP(DUK__BP_EXPONENTIATION),                      /* DUK_TOK_EXP */
65416 	DUK__MK_LBP(DUK__BP_POSTFIX),                             /* DUK_TOK_INCREMENT */
65417 	DUK__MK_LBP(DUK__BP_POSTFIX),                             /* DUK_TOK_DECREMENT */
65418 	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_ALSHIFT */
65419 	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_ARSHIFT */
65420 	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_RSHIFT */
65421 	DUK__MK_LBP(DUK__BP_BAND),                                /* DUK_TOK_BAND */
65422 	DUK__MK_LBP(DUK__BP_BOR),                                 /* DUK_TOK_BOR */
65423 	DUK__MK_LBP(DUK__BP_BXOR),                                /* DUK_TOK_BXOR */
65424 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LNOT */
65425 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_BNOT */
65426 	DUK__MK_LBP(DUK__BP_LAND),                                /* DUK_TOK_LAND */
65427 	DUK__MK_LBP(DUK__BP_LOR),                                 /* DUK_TOK_LOR */
65428 	DUK__MK_LBP(DUK__BP_CONDITIONAL),                         /* DUK_TOK_QUESTION */
65429 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_COLON */
65430 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_EQUALSIGN */
65431 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ADD_EQ */
65432 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_SUB_EQ */
65433 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_MUL_EQ */
65434 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_DIV_EQ */
65435 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_MOD_EQ */
65436 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_EXP_EQ */
65437 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ALSHIFT_EQ */
65438 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ARSHIFT_EQ */
65439 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_RSHIFT_EQ */
65440 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BAND_EQ */
65441 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BOR_EQ */
65442 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BXOR_EQ */
65443 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_NUMBER */
65444 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_STRING */
65445 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_REGEXP */
65446 };
65447 
65448 /*
65449  *  Misc helpers
65450  */
65451 
65452 DUK_LOCAL void duk__comp_recursion_increase(duk_compiler_ctx *comp_ctx) {
65453 	DUK_ASSERT(comp_ctx != NULL);
65454 	DUK_ASSERT(comp_ctx->recursion_depth >= 0);
65455 	if (comp_ctx->recursion_depth >= comp_ctx->recursion_limit) {
65456 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_COMPILER_RECURSION_LIMIT);
65457 		DUK_WO_NORETURN(return;);
65458 	}
65459 	comp_ctx->recursion_depth++;
65460 }
65461 
65462 DUK_LOCAL void duk__comp_recursion_decrease(duk_compiler_ctx *comp_ctx) {
65463 	DUK_ASSERT(comp_ctx != NULL);
65464 	DUK_ASSERT(comp_ctx->recursion_depth > 0);
65465 	comp_ctx->recursion_depth--;
65466 }
65467 
65468 DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
65469 	DUK_UNREF(comp_ctx);
65470 	DUK_ASSERT(h != NULL);
65471 	return DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h);
65472 }
65473 
65474 DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments_in_strict_mode(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
65475 	DUK_ASSERT(h != NULL);
65476 	return (comp_ctx->curr_func.is_strict &&
65477 	        DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h));
65478 }
65479 
65480 /*
65481  *  Parser duk__advance() token eating functions
65482  */
65483 
65484 /* XXX: valstack handling is awkward.  Add a valstack helper which
65485  * avoids dup():ing; valstack_copy(src, dst)?
65486  */
65487 
65488 DUK_LOCAL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {
65489 	duk_hthread *thr = comp_ctx->thr;
65490 	duk_bool_t regexp;
65491 
65492 	DUK_ASSERT_DISABLE(comp_ctx->curr_token.t >= 0);  /* unsigned */
65493 	DUK_ASSERT(comp_ctx->curr_token.t <= DUK_TOK_MAXVAL);  /* MAXVAL is inclusive */
65494 
65495 	/*
65496 	 *  Use current token to decide whether a RegExp can follow.
65497 	 *
65498 	 *  We can use either 't' or 't_nores'; the latter would not
65499 	 *  recognize keywords.  Some keywords can be followed by a
65500 	 *  RegExp (e.g. "return"), so using 't' is better.  This is
65501 	 *  not trivial, see doc/compiler.rst.
65502 	 */
65503 
65504 	regexp = 1;
65505 	if (duk__token_lbp[comp_ctx->curr_token.t] & DUK__TOKEN_LBP_FLAG_NO_REGEXP) {
65506 		regexp = 0;
65507 	}
65508 	if (comp_ctx->curr_func.reject_regexp_in_adv) {
65509 		comp_ctx->curr_func.reject_regexp_in_adv = 0;
65510 		regexp = 0;
65511 	}
65512 	if (comp_ctx->curr_func.allow_regexp_in_adv) {
65513 		comp_ctx->curr_func.allow_regexp_in_adv = 0;
65514 		regexp = 1;
65515 	}
65516 
65517 	if (expect >= 0 && comp_ctx->curr_token.t != (duk_small_uint_t) expect) {
65518 		DUK_D(DUK_DPRINT("parse error: expect=%ld, got=%ld",
65519 		                 (long) expect, (long) comp_ctx->curr_token.t));
65520 		DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
65521 		DUK_WO_NORETURN(return;);
65522 	}
65523 
65524 	/* make current token the previous; need to fiddle with valstack "backing store" */
65525 	duk_memcpy(&comp_ctx->prev_token, &comp_ctx->curr_token, sizeof(duk_token));
65526 	duk_copy(thr, comp_ctx->tok11_idx, comp_ctx->tok21_idx);
65527 	duk_copy(thr, comp_ctx->tok12_idx, comp_ctx->tok22_idx);
65528 
65529 	/* parse new token */
65530 	duk_lexer_parse_js_input_element(&comp_ctx->lex,
65531 	                                 &comp_ctx->curr_token,
65532 	                                 comp_ctx->curr_func.is_strict,
65533 	                                 regexp);
65534 
65535 	DUK_DDD(DUK_DDDPRINT("advance: curr: tok=%ld/%ld,%ld,term=%ld,%!T,%!T "
65536 	                     "prev: tok=%ld/%ld,%ld,term=%ld,%!T,%!T",
65537 	                     (long) comp_ctx->curr_token.t,
65538 	                     (long) comp_ctx->curr_token.t_nores,
65539 	                     (long) comp_ctx->curr_token.start_line,
65540 	                     (long) comp_ctx->curr_token.lineterm,
65541 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok11_idx),
65542 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok12_idx),
65543 	                     (long) comp_ctx->prev_token.t,
65544 	                     (long) comp_ctx->prev_token.t_nores,
65545 	                     (long) comp_ctx->prev_token.start_line,
65546 	                     (long) comp_ctx->prev_token.lineterm,
65547 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok21_idx),
65548 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok22_idx)));
65549 }
65550 
65551 /* advance, expecting current token to be a specific token; parse next token in regexp context */
65552 DUK_LOCAL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {
65553 	duk__advance_helper(comp_ctx, expect);
65554 }
65555 
65556 /* advance, whatever the current token is; parse next token in regexp context */
65557 DUK_LOCAL void duk__advance(duk_compiler_ctx *comp_ctx) {
65558 	duk__advance_helper(comp_ctx, -1);
65559 }
65560 
65561 /*
65562  *  Helpers for duk_compiler_func.
65563  */
65564 
65565 /* init function state: inits valstack allocations */
65566 DUK_LOCAL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) {
65567 	duk_compiler_func *func = &comp_ctx->curr_func;
65568 	duk_hthread *thr = comp_ctx->thr;
65569 	duk_idx_t entry_top;
65570 
65571 	entry_top = duk_get_top(thr);
65572 
65573 	duk_memzero(func, sizeof(*func));  /* intentional overlap with earlier memzero */
65574 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
65575 	func->h_name = NULL;
65576 	func->h_consts = NULL;
65577 	func->h_funcs = NULL;
65578 	func->h_decls = NULL;
65579 	func->h_labelnames = NULL;
65580 	func->h_labelinfos = NULL;
65581 	func->h_argnames = NULL;
65582 	func->h_varmap = NULL;
65583 #endif
65584 
65585 	duk_require_stack(thr, DUK__FUNCTION_INIT_REQUIRE_SLOTS);
65586 
65587 	DUK_BW_INIT_PUSHBUF(thr, &func->bw_code, DUK__BC_INITIAL_INSTS * sizeof(duk_compiler_instr));
65588 	/* code_idx = entry_top + 0 */
65589 
65590 	duk_push_array(thr);
65591 	func->consts_idx = entry_top + 1;
65592 	func->h_consts = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 1);
65593 	DUK_ASSERT(func->h_consts != NULL);
65594 
65595 	duk_push_array(thr);
65596 	func->funcs_idx = entry_top + 2;
65597 	func->h_funcs = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 2);
65598 	DUK_ASSERT(func->h_funcs != NULL);
65599 	DUK_ASSERT(func->fnum_next == 0);
65600 
65601 	duk_push_array(thr);
65602 	func->decls_idx = entry_top + 3;
65603 	func->h_decls = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 3);
65604 	DUK_ASSERT(func->h_decls != NULL);
65605 
65606 	duk_push_array(thr);
65607 	func->labelnames_idx = entry_top + 4;
65608 	func->h_labelnames = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 4);
65609 	DUK_ASSERT(func->h_labelnames != NULL);
65610 
65611 	duk_push_dynamic_buffer(thr, 0);
65612 	func->labelinfos_idx = entry_top + 5;
65613 	func->h_labelinfos = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, entry_top + 5);
65614 	DUK_ASSERT(func->h_labelinfos != NULL);
65615 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(func->h_labelinfos) && !DUK_HBUFFER_HAS_EXTERNAL(func->h_labelinfos));
65616 
65617 	duk_push_array(thr);
65618 	func->argnames_idx = entry_top + 6;
65619 	func->h_argnames = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 6);
65620 	DUK_ASSERT(func->h_argnames != NULL);
65621 
65622 	duk_push_bare_object(thr);
65623 	func->varmap_idx = entry_top + 7;
65624 	func->h_varmap = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 7);
65625 	DUK_ASSERT(func->h_varmap != NULL);
65626 }
65627 
65628 /* reset function state (prepare for pass 2) */
65629 DUK_LOCAL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx) {
65630 	duk_compiler_func *func = &comp_ctx->curr_func;
65631 	duk_hthread *thr = comp_ctx->thr;
65632 
65633 	/* reset bytecode buffer but keep current size; pass 2 will
65634 	 * require same amount or more.
65635 	 */
65636 	DUK_BW_RESET_SIZE(thr, &func->bw_code);
65637 
65638 	duk_set_length(thr, func->consts_idx, 0);
65639 	/* keep func->h_funcs; inner functions are not reparsed to avoid O(depth^2) parsing */
65640 	func->fnum_next = 0;
65641 	/* duk_set_length(thr, func->funcs_idx, 0); */
65642 	duk_set_length(thr, func->labelnames_idx, 0);
65643 	duk_hbuffer_reset(thr, func->h_labelinfos);
65644 	/* keep func->h_argnames; it is fixed for all passes */
65645 
65646 	/* truncated in case pass 3 needed */
65647 	duk_push_bare_object(thr);
65648 	duk_replace(thr, func->varmap_idx);
65649 	func->h_varmap = DUK_GET_HOBJECT_POSIDX(thr, func->varmap_idx);
65650 	DUK_ASSERT(func->h_varmap != NULL);
65651 }
65652 
65653 /* cleanup varmap from any null entries, compact it, etc; returns number
65654  * of final entries after cleanup.
65655  */
65656 DUK_LOCAL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx) {
65657 	duk_hthread *thr = comp_ctx->thr;
65658 	duk_hobject *h_varmap;
65659 	duk_hstring *h_key;
65660 	duk_tval *tv;
65661 	duk_uint32_t i, e_next;
65662 	duk_int_t ret;
65663 
65664 	/* [ ... varmap ] */
65665 
65666 	h_varmap = DUK_GET_HOBJECT_NEGIDX(thr, -1);
65667 	DUK_ASSERT(h_varmap != NULL);
65668 
65669 	ret = 0;
65670 	e_next = DUK_HOBJECT_GET_ENEXT(h_varmap);
65671 	for (i = 0; i < e_next; i++) {
65672 		h_key = DUK_HOBJECT_E_GET_KEY(thr->heap, h_varmap, i);
65673 		if (!h_key) {
65674 			continue;
65675 		}
65676 
65677 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h_varmap, i));
65678 
65679 		/* The entries can either be register numbers or 'null' values.
65680 		 * Thus, no need to DECREF them and get side effects.  DECREF'ing
65681 		 * the keys (strings) can cause memory to be freed but no side
65682 		 * effects as strings don't have finalizers.  This is why we can
65683 		 * rely on the object properties not changing from underneath us.
65684 		 */
65685 
65686 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h_varmap, i);
65687 		if (!DUK_TVAL_IS_NUMBER(tv)) {
65688 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv));
65689 			DUK_HOBJECT_E_SET_KEY(thr->heap, h_varmap, i, NULL);
65690 			DUK_HSTRING_DECREF(thr, h_key);
65691 			/* when key is NULL, value is garbage so no need to set */
65692 		} else {
65693 			ret++;
65694 		}
65695 	}
65696 
65697 	duk_compact_m1(thr);
65698 
65699 	return ret;
65700 }
65701 
65702 /* Convert duk_compiler_func into a function template, leaving the result
65703  * on top of stack.
65704  */
65705 /* XXX: awkward and bloated asm -- use faster internal accesses */
65706 DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
65707 	duk_compiler_func *func = &comp_ctx->curr_func;
65708 	duk_hthread *thr = comp_ctx->thr;
65709 	duk_hcompfunc *h_res;
65710 	duk_hbuffer_fixed *h_data;
65711 	duk_size_t consts_count;
65712 	duk_size_t funcs_count;
65713 	duk_size_t code_count;
65714 	duk_size_t code_size;
65715 	duk_size_t data_size;
65716 	duk_size_t i;
65717 	duk_tval *p_const;
65718 	duk_hobject **p_func;
65719 	duk_instr_t *p_instr;
65720 	duk_compiler_instr *q_instr;
65721 	duk_tval *tv;
65722 	duk_bool_t keep_varmap;
65723 	duk_bool_t keep_formals;
65724 #if !defined(DUK_USE_DEBUGGER_SUPPORT)
65725 	duk_size_t formals_length;
65726 #endif
65727 
65728 	DUK_DDD(DUK_DDDPRINT("converting duk_compiler_func to function/template"));
65729 
65730 	/*
65731 	 *  Push result object and init its flags
65732 	 */
65733 
65734 	/* Valstack should suffice here, required on function valstack init */
65735 
65736 	h_res = duk_push_hcompfunc(thr);
65737 	DUK_ASSERT(h_res != NULL);
65738 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_res) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
65739 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) h_res, NULL);  /* Function templates are "bare objects". */
65740 
65741 	if (func->is_function) {
65742 		DUK_DDD(DUK_DDDPRINT("function -> set NEWENV"));
65743 		DUK_HOBJECT_SET_NEWENV((duk_hobject *) h_res);
65744 
65745 		if (!func->is_arguments_shadowed) {
65746 			/* arguments object would be accessible; note that shadowing
65747 			 * bindings are arguments or function declarations, neither
65748 			 * of which are deletable, so this is safe.
65749 			 */
65750 
65751 			if (func->id_access_arguments || func->may_direct_eval) {
65752 				DUK_DDD(DUK_DDDPRINT("function may access 'arguments' object directly or "
65753 				                     "indirectly -> set CREATEARGS"));
65754 				DUK_HOBJECT_SET_CREATEARGS((duk_hobject *) h_res);
65755 			}
65756 		}
65757 	} else if (func->is_eval && func->is_strict) {
65758 		DUK_DDD(DUK_DDDPRINT("strict eval code -> set NEWENV"));
65759 		DUK_HOBJECT_SET_NEWENV((duk_hobject *) h_res);
65760 	} else {
65761 		/* non-strict eval: env is caller's env or global env (direct vs. indirect call)
65762 		 * global code: env is is global env
65763 		 */
65764 		DUK_DDD(DUK_DDDPRINT("non-strict eval code or global code -> no NEWENV"));
65765 		DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV((duk_hobject *) h_res));
65766 	}
65767 
65768 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
65769 	if (func->is_function && func->is_namebinding && func->h_name != NULL) {
65770 		/* Object literal set/get functions have a name (property
65771 		 * name) but must not have a lexical name binding, see
65772 		 * test-bug-getset-func-name.js.
65773 		 */
65774 		DUK_DDD(DUK_DDDPRINT("function expression with a name -> set NAMEBINDING"));
65775 		DUK_HOBJECT_SET_NAMEBINDING((duk_hobject *) h_res);
65776 	}
65777 #endif
65778 
65779 	if (func->is_strict) {
65780 		DUK_DDD(DUK_DDDPRINT("function is strict -> set STRICT"));
65781 		DUK_HOBJECT_SET_STRICT((duk_hobject *) h_res);
65782 	}
65783 
65784 	if (func->is_notail) {
65785 		DUK_DDD(DUK_DDDPRINT("function is notail -> set NOTAIL"));
65786 		DUK_HOBJECT_SET_NOTAIL((duk_hobject *) h_res);
65787 	}
65788 
65789 	if (func->is_constructable) {
65790 		DUK_DDD(DUK_DDDPRINT("function is constructable -> set CONSTRUCTABLE"));
65791 		DUK_HOBJECT_SET_CONSTRUCTABLE((duk_hobject *) h_res);
65792 	}
65793 
65794 	/*
65795 	 *  Build function fixed size 'data' buffer, which contains bytecode,
65796 	 *  constants, and inner function references.
65797 	 *
65798 	 *  During the building phase 'data' is reachable but incomplete.
65799 	 *  Only incref's occur during building (no refzero or GC happens),
65800 	 *  so the building process is atomic.
65801 	 */
65802 
65803 	consts_count = duk_hobject_get_length(thr, func->h_consts);
65804 	funcs_count = duk_hobject_get_length(thr, func->h_funcs) / 3;
65805 	code_count = DUK_BW_GET_SIZE(thr, &func->bw_code) / sizeof(duk_compiler_instr);
65806 	code_size = code_count * sizeof(duk_instr_t);
65807 
65808 	data_size = consts_count * sizeof(duk_tval) +
65809 	            funcs_count * sizeof(duk_hobject *) +
65810 	            code_size;
65811 
65812 	DUK_DDD(DUK_DDDPRINT("consts_count=%ld, funcs_count=%ld, code_size=%ld -> "
65813 	                     "data_size=%ld*%ld + %ld*%ld + %ld = %ld",
65814 	                     (long) consts_count, (long) funcs_count, (long) code_size,
65815 	                     (long) consts_count, (long) sizeof(duk_tval),
65816 	                     (long) funcs_count, (long) sizeof(duk_hobject *),
65817 	                     (long) code_size, (long) data_size));
65818 
65819 	duk_push_fixed_buffer_nozero(thr, data_size);
65820 	h_data = (duk_hbuffer_fixed *) (void *) duk_known_hbuffer(thr, -1);
65821 
65822 	DUK_HCOMPFUNC_SET_DATA(thr->heap, h_res, (duk_hbuffer *) h_data);
65823 	DUK_HEAPHDR_INCREF(thr, h_data);
65824 
65825 	p_const = (duk_tval *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data);
65826 	for (i = 0; i < consts_count; i++) {
65827 		DUK_ASSERT(i <= DUK_UARRIDX_MAX);  /* const limits */
65828 		tv = duk_hobject_find_existing_array_entry_tval_ptr(thr->heap, func->h_consts, (duk_uarridx_t) i);
65829 		DUK_ASSERT(tv != NULL);
65830 		DUK_TVAL_SET_TVAL(p_const, tv);
65831 		p_const++;
65832 		DUK_TVAL_INCREF(thr, tv);  /* may be a string constant */
65833 
65834 		DUK_DDD(DUK_DDDPRINT("constant: %!T", (duk_tval *) tv));
65835 	}
65836 
65837 	p_func = (duk_hobject **) p_const;
65838 	DUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_res, p_func);
65839 	for (i = 0; i < funcs_count; i++) {
65840 		duk_hobject *h;
65841 		DUK_ASSERT(i * 3 <= DUK_UARRIDX_MAX);  /* func limits */
65842 		tv = duk_hobject_find_existing_array_entry_tval_ptr(thr->heap, func->h_funcs, (duk_uarridx_t) (i * 3));
65843 		DUK_ASSERT(tv != NULL);
65844 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
65845 		h = DUK_TVAL_GET_OBJECT(tv);
65846 		DUK_ASSERT(h != NULL);
65847 		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(h));
65848 		*p_func++ = h;
65849 		DUK_HOBJECT_INCREF(thr, h);
65850 
65851 		DUK_DDD(DUK_DDDPRINT("inner function: %p -> %!iO",
65852 		                     (void *) h, (duk_heaphdr *) h));
65853 	}
65854 
65855 	p_instr = (duk_instr_t *) p_func;
65856 	DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, h_res, p_instr);
65857 
65858 	/* copy bytecode instructions one at a time */
65859 	q_instr = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(thr, &func->bw_code);
65860 	for (i = 0; i < code_count; i++) {
65861 		p_instr[i] = q_instr[i].ins;
65862 	}
65863 	/* Note: 'q_instr' is still used below */
65864 
65865 	DUK_ASSERT((duk_uint8_t *) (p_instr + code_count) == DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data) + data_size);
65866 
65867 	duk_pop(thr);  /* 'data' (and everything in it) is reachable through h_res now */
65868 
65869 	/*
65870 	 *  Init non-property result fields
65871 	 *
65872 	 *  'nregs' controls how large a register frame is allocated.
65873 	 *
65874 	 *  'nargs' controls how many formal arguments are written to registers:
65875 	 *  r0, ... r(nargs-1).  The remaining registers are initialized to
65876 	 *  undefined.
65877 	 */
65878 
65879 	DUK_ASSERT(func->temp_max >= 0);
65880 	h_res->nregs = (duk_uint16_t) func->temp_max;
65881 	h_res->nargs = (duk_uint16_t) duk_hobject_get_length(thr, func->h_argnames);
65882 	DUK_ASSERT(h_res->nregs >= h_res->nargs);  /* pass2 allocation handles this */
65883 #if defined(DUK_USE_DEBUGGER_SUPPORT)
65884 	h_res->start_line = (duk_uint32_t) func->min_line;
65885 	h_res->end_line = (duk_uint32_t) func->max_line;
65886 #endif
65887 
65888 	/*
65889 	 *  Init object properties
65890 	 *
65891 	 *  Properties should be added in decreasing order of access frequency.
65892 	 *  (Not very critical for function templates.)
65893 	 */
65894 
65895 	DUK_DDD(DUK_DDDPRINT("init function properties"));
65896 
65897 	/* [ ... res ] */
65898 
65899 	/* _Varmap: omitted if function is guaranteed not to do a slow path
65900 	 * identifier access that might be caught by locally declared variables.
65901 	 * The varmap can also be omitted if it turns out empty of actual
65902 	 * register mappings after a cleanup.  When debugging is enabled, we
65903 	 * always need the varmap to be able to lookup variables at any point.
65904 	 */
65905 
65906 #if defined(DUK_USE_DEBUGGER_SUPPORT)
65907 	DUK_DD(DUK_DDPRINT("keeping _Varmap because debugger support is enabled"));
65908 	keep_varmap = 1;
65909 #else
65910 	if (func->id_access_slow_own ||   /* directly uses slow accesses that may match own variables */
65911 	    func->id_access_arguments ||  /* accesses 'arguments' directly */
65912 	    func->may_direct_eval ||      /* may indirectly slow access through a direct eval */
65913 	    funcs_count > 0) {            /* has inner functions which may slow access (XXX: this can be optimized by looking at the inner functions) */
65914 		DUK_DD(DUK_DDPRINT("keeping _Varmap because of direct eval, slow path access that may match local variables, or presence of inner functions"));
65915 		keep_varmap = 1;
65916 	} else {
65917 		DUK_DD(DUK_DDPRINT("dropping _Varmap"));
65918 		keep_varmap = 0;
65919 	}
65920 #endif
65921 
65922 	if (keep_varmap) {
65923 		duk_int_t num_used;
65924 		duk_dup(thr, func->varmap_idx);
65925 		num_used = duk__cleanup_varmap(comp_ctx);
65926 		DUK_DDD(DUK_DDDPRINT("cleaned up varmap: %!T (num_used=%ld)",
65927 		                     (duk_tval *) duk_get_tval(thr, -1), (long) num_used));
65928 
65929 		if (num_used > 0) {
65930 			duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);
65931 		} else {
65932 			DUK_DD(DUK_DDPRINT("varmap is empty after cleanup -> no need to add"));
65933 			duk_pop(thr);
65934 		}
65935 	}
65936 
65937 	/* _Formals: omitted if function is guaranteed not to need a (non-strict)
65938 	 * arguments object, and _Formals.length matches nargs exactly.
65939 	 *
65940 	 * Non-arrow functions can't see an outer function's 'argument' binding
65941 	 * (because they have their own), but arrow functions can.  When arrow
65942 	 * functions are added, this condition would need to be added:
65943 	 *     inner_arrow_funcs_count > 0   inner arrow functions may access 'arguments'
65944 	 */
65945 #if defined(DUK_USE_DEBUGGER_SUPPORT)
65946 	DUK_DD(DUK_DDPRINT("keeping _Formals because debugger support is enabled"));
65947 	keep_formals = 1;
65948 #else
65949 	formals_length = duk_get_length(thr, func->argnames_idx);
65950 	if (formals_length != (duk_size_t) h_res->nargs) {
65951 		/* Nargs not enough for closure .length: keep _Formals regardless
65952 		 * of its length.  Shouldn't happen in practice at the moment.
65953 		 */
65954 		DUK_DD(DUK_DDPRINT("keeping _Formals because _Formals.length != nargs"));
65955 		keep_formals = 1;
65956 	} else if ((func->id_access_arguments || func->may_direct_eval) &&
65957 	           (formals_length > 0)) {
65958 		/* Direct eval (may access 'arguments') or accesses 'arguments'
65959 		 * explicitly: keep _Formals unless it is zero length.
65960 		 */
65961 		DUK_DD(DUK_DDPRINT("keeping _Formals because of direct eval or explicit access to 'arguments', and _Formals.length != 0"));
65962 		keep_formals = 1;
65963 	} else {
65964 		DUK_DD(DUK_DDPRINT("omitting _Formals, nargs matches _Formals.length, so no properties added"));
65965 		keep_formals = 0;
65966 	}
65967 #endif
65968 
65969 	if (keep_formals) {
65970 		duk_dup(thr, func->argnames_idx);
65971 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);
65972 	}
65973 
65974 	/* name */
65975 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
65976 	if (func->h_name) {
65977 		duk_push_hstring(thr, func->h_name);
65978 		DUK_DD(DUK_DDPRINT("setting function template .name to %!T", duk_get_tval(thr, -1)));
65979 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
65980 	}
65981 #endif  /* DUK_USE_FUNC_NAME_PROPERTY */
65982 
65983 	/* _Source */
65984 #if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
65985 	if (0) {
65986 		/* XXX: Currently function source code is not stored, as it is not
65987 		 * required by the standard.  Source code should not be stored by
65988 		 * default (user should enable it explicitly), and the source should
65989 		 * probably be compressed with a trivial text compressor; average
65990 		 * compression of 20-30% is quite easy to achieve even with a trivial
65991 		 * compressor (RLE + backwards lookup).
65992 		 *
65993 		 * Debugging needs source code to be useful: sometimes input code is
65994 		 * not found in files as it may be generated and then eval()'d, given
65995 		 * by dynamic C code, etc.
65996 		 *
65997 		 * Other issues:
65998 		 *
65999 		 *   - Need tokenizer indices for start and end to substring
66000 		 *   - Always normalize function declaration part?
66001 		 *   - If we keep _Formals, only need to store body
66002 		 */
66003 
66004 		/*
66005 		 *  For global or eval code this is straightforward.  For functions
66006 		 *  created with the Function constructor we only get the source for
66007 		 *  the body and must manufacture the "function ..." part.
66008 		 *
66009 		 *  For instance, for constructed functions (v8):
66010 		 *
66011 		 *    > a = new Function("foo", "bar", "print(foo)");
66012 		 *    [Function]
66013 		 *    > a.toString()
66014 		 *    'function anonymous(foo,bar) {\nprint(foo)\n}'
66015 		 *
66016 		 *  Similarly for e.g. getters (v8):
66017 		 *
66018 		 *    > x = { get a(foo,bar) { print(foo); } }
66019 		 *    { a: [Getter] }
66020 		 *    > Object.getOwnPropertyDescriptor(x, 'a').get.toString()
66021 		 *    'function a(foo,bar) { print(foo); }'
66022 		 */
66023 
66024 #if 0
66025 		duk_push_literal(thr, "XXX");
66026 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE);
66027 #endif
66028 	}
66029 #endif  /* DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY */
66030 
66031 	/* _Pc2line */
66032 #if defined(DUK_USE_PC2LINE)
66033 	if (1) {
66034 		/*
66035 		 *  Size-optimized pc->line mapping.
66036 		 */
66037 
66038 		DUK_ASSERT(code_count <= DUK_COMPILER_MAX_BYTECODE_LENGTH);
66039 		duk_hobject_pc2line_pack(thr, q_instr, (duk_uint_fast32_t) code_count);  /* -> pushes fixed buffer */
66040 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_NONE);
66041 
66042 		/* XXX: if assertions enabled, walk through all valid PCs
66043 		 * and check line mapping.
66044 		 */
66045 	}
66046 #endif  /* DUK_USE_PC2LINE */
66047 
66048 	/* fileName */
66049 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
66050 	if (comp_ctx->h_filename) {
66051 		/*
66052 		 *  Source filename (or equivalent), for identifying thrown errors.
66053 		 */
66054 
66055 		duk_push_hstring(thr, comp_ctx->h_filename);
66056 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_NONE);
66057 	}
66058 #endif
66059 
66060 	DUK_DD(DUK_DDPRINT("converted function: %!ixT",
66061 	                   (duk_tval *) duk_get_tval(thr, -1)));
66062 
66063 	/*
66064 	 *  Compact the function template.
66065 	 */
66066 
66067 	duk_compact_m1(thr);
66068 
66069 	/*
66070 	 *  Debug dumping
66071 	 */
66072 
66073 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
66074 	{
66075 		duk_hcompfunc *h;
66076 		duk_instr_t *p, *p_start, *p_end;
66077 
66078 		h = (duk_hcompfunc *) duk_get_hobject(thr, -1);
66079 		p_start = (duk_instr_t *) DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, h);
66080 		p_end = (duk_instr_t *) DUK_HCOMPFUNC_GET_CODE_END(thr->heap, h);
66081 
66082 		p = p_start;
66083 		while (p < p_end) {
66084 			DUK_DDD(DUK_DDDPRINT("BC %04ld: %!I        ; 0x%08lx op=%ld (%!C) a=%ld b=%ld c=%ld",
66085 			                     (long) (p - p_start),
66086 			                     (duk_instr_t) (*p),
66087 			                     (unsigned long) (*p),
66088 			                     (long) DUK_DEC_OP(*p),
66089 			                     (long) DUK_DEC_OP(*p),
66090 			                     (long) DUK_DEC_A(*p),
66091 			                     (long) DUK_DEC_B(*p),
66092 			                     (long) DUK_DEC_C(*p)));
66093 			p++;
66094 		}
66095 	}
66096 #endif
66097 }
66098 
66099 /*
66100  *  Code emission helpers
66101  *
66102  *  Some emission helpers understand the range of target and source reg/const
66103  *  values and automatically emit shuffling code if necessary.  This is the
66104  *  case when the slot in question (A, B, C) is used in the standard way and
66105  *  for opcodes the emission helpers explicitly understand (like DUK_OP_MPUTOBJ).
66106  *
66107  *  The standard way is that:
66108  *    - slot A is a target register
66109  *    - slot B is a source register/constant
66110  *    - slot C is a source register/constant
66111  *
66112  *  If a slot is used in a non-standard way the caller must indicate this
66113  *  somehow.  If a slot is used as a target instead of a source (or vice
66114  *  versa), this can be indicated with a flag to trigger proper shuffling
66115  *  (e.g. DUK__EMIT_FLAG_B_IS_TARGET).  If the value in the slot is not
66116  *  register/const related at all, the caller must ensure that the raw value
66117  *  fits into the corresponding slot so as to not trigger shuffling.  The
66118  *  caller must set a "no shuffle" flag to ensure compilation fails if
66119  *  shuffling were to be triggered because of an internal error.
66120  *
66121  *  For slots B and C the raw slot size is 9 bits but one bit is reserved for
66122  *  the reg/const indicator.  To use the full 9-bit range for a raw value,
66123  *  shuffling must be disabled with the DUK__EMIT_FLAG_NO_SHUFFLE_{B,C} flag.
66124  *  Shuffling is only done for A, B, and C slots, not the larger BC or ABC slots.
66125  *
66126  *  There is call handling specific understanding in the A-B-C emitter to
66127  *  convert call setup and call instructions into indirect ones if necessary.
66128  */
66129 
66130 /* Code emission flags, passed in the 'opcode' field.  Opcode + flags
66131  * fit into 16 bits for now, so use duk_small_uint_t.
66132  */
66133 #define DUK__EMIT_FLAG_NO_SHUFFLE_A      (1 << 8)
66134 #define DUK__EMIT_FLAG_NO_SHUFFLE_B      (1 << 9)
66135 #define DUK__EMIT_FLAG_NO_SHUFFLE_C      (1 << 10)
66136 #define DUK__EMIT_FLAG_A_IS_SOURCE       (1 << 11)  /* slot A is a source (default: target) */
66137 #define DUK__EMIT_FLAG_B_IS_TARGET       (1 << 12)  /* slot B is a target (default: source) */
66138 #define DUK__EMIT_FLAG_C_IS_TARGET       (1 << 13)  /* slot C is a target (default: source) */
66139 #define DUK__EMIT_FLAG_BC_REGCONST       (1 << 14)  /* slots B and C are reg/const */
66140 #define DUK__EMIT_FLAG_RESERVE_JUMPSLOT  (1 << 15)  /* reserve a jumpslot after instr before target spilling, used for NEXTENUM */
66141 
66142 /* XXX: macro smaller than call? */
66143 DUK_LOCAL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx) {
66144 	duk_compiler_func *func;
66145 	func = &comp_ctx->curr_func;
66146 	return (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &func->bw_code) / sizeof(duk_compiler_instr));
66147 }
66148 
66149 DUK_LOCAL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc) {
66150 	DUK_ASSERT(pc >= 0);
66151 	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)));
66152 	return ((duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code)) + pc;
66153 }
66154 
66155 /* emit instruction; could return PC but that's not needed in the majority
66156  * of cases.
66157  */
66158 DUK_LOCAL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) {
66159 #if defined(DUK_USE_PC2LINE)
66160 	duk_int_t line;
66161 #endif
66162 	duk_compiler_instr *instr;
66163 
66164 	DUK_DDD(DUK_DDDPRINT("duk__emit: 0x%08lx curr_token.start_line=%ld prev_token.start_line=%ld pc=%ld --> %!I",
66165 	                     (unsigned long) ins,
66166 	                     (long) comp_ctx->curr_token.start_line,
66167 	                     (long) comp_ctx->prev_token.start_line,
66168 	                     (long) duk__get_current_pc(comp_ctx),
66169 	                     (duk_instr_t) ins));
66170 
66171 	instr = (duk_compiler_instr *) (void *) DUK_BW_ENSURE_GETPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
66172 	DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
66173 
66174 #if defined(DUK_USE_PC2LINE)
66175 	/* The line number tracking is a bit inconsistent right now, which
66176 	 * affects debugger accuracy.  Mostly call sites emit opcodes when
66177 	 * they have parsed a token (say a terminating semicolon) and called
66178 	 * duk__advance().  In this case the line number of the previous
66179 	 * token is the most accurate one (except in prologue where
66180 	 * prev_token.start_line is 0).  This is probably not 100% correct
66181 	 * right now.
66182 	 */
66183 	/* approximation, close enough */
66184 	line = comp_ctx->prev_token.start_line;
66185 	if (line == 0) {
66186 		line = comp_ctx->curr_token.start_line;
66187 	}
66188 #endif
66189 
66190 	instr->ins = ins;
66191 #if defined(DUK_USE_PC2LINE)
66192 	instr->line = (duk_uint32_t) line;
66193 #endif
66194 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66195 	if (line < comp_ctx->curr_func.min_line) {
66196 		comp_ctx->curr_func.min_line = line;
66197 	}
66198 	if (line > comp_ctx->curr_func.max_line) {
66199 		comp_ctx->curr_func.max_line = line;
66200 	}
66201 #endif
66202 
66203 	/* Limit checks for bytecode byte size and line number. */
66204 	if (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) {
66205 		goto fail_bc_limit;
66206 	}
66207 #if defined(DUK_USE_PC2LINE) && defined(DUK_USE_ESBC_LIMITS)
66208 #if defined(DUK_USE_BUFLEN16)
66209 	/* Buffer length is bounded to 0xffff automatically, avoid compile warning. */
66210 	if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) {
66211 		goto fail_bc_limit;
66212 	}
66213 #else
66214 	if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) {
66215 		goto fail_bc_limit;
66216 	}
66217 #endif
66218 #endif
66219 
66220 	return;
66221 
66222   fail_bc_limit:
66223 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT);
66224 	DUK_WO_NORETURN(return;);
66225 }
66226 
66227 /* Update function min/max line from current token.  Needed to improve
66228  * function line range information for debugging, so that e.g. opening
66229  * curly brace is covered by line range even when no opcodes are emitted
66230  * for the line containing the brace.
66231  */
66232 DUK_LOCAL void duk__update_lineinfo_currtoken(duk_compiler_ctx *comp_ctx) {
66233 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66234 	duk_int_t line;
66235 
66236 	line = comp_ctx->curr_token.start_line;
66237 	if (line == 0) {
66238 		return;
66239 	}
66240 	if (line < comp_ctx->curr_func.min_line) {
66241 		comp_ctx->curr_func.min_line = line;
66242 	}
66243 	if (line > comp_ctx->curr_func.max_line) {
66244 		comp_ctx->curr_func.max_line = line;
66245 	}
66246 #else
66247 	DUK_UNREF(comp_ctx);
66248 #endif
66249 }
66250 
66251 DUK_LOCAL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op) {
66252 	duk__emit(comp_ctx, DUK_ENC_OP_ABC(op, 0));
66253 }
66254 
66255 /* Important main primitive. */
66256 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) {
66257 	duk_instr_t ins = 0;
66258 	duk_int_t a_out = -1;
66259 	duk_int_t b_out = -1;
66260 	duk_int_t c_out = -1;
66261 	duk_int_t tmp;
66262 	duk_small_uint_t op = op_flags & 0xffU;
66263 
66264 	DUK_DDD(DUK_DDDPRINT("emit: op_flags=%04lx, a=%ld, b=%ld, c=%ld",
66265 	                     (unsigned long) op_flags, (long) a, (long) b, (long) c));
66266 
66267 	/* We could rely on max temp/const checks: if they don't exceed BC
66268 	 * limit, nothing here can either (just asserts would be enough).
66269 	 * Currently we check for the limits, which provides additional
66270 	 * protection against creating invalid bytecode due to compiler
66271 	 * bugs.
66272 	 */
66273 
66274 	DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN);  /* unsigned */
66275 	DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
66276 	DUK_ASSERT(DUK__ISREG(a));
66277 	DUK_ASSERT(b != -1);  /* Not 'none'. */
66278 	DUK_ASSERT(c != -1);  /* Not 'none'. */
66279 
66280 	/* Input shuffling happens before the actual operation, while output
66281 	 * shuffling happens afterwards.  Output shuffling decisions are still
66282 	 * made at the same time to reduce branch clutter; output shuffle decisions
66283 	 * are recorded into X_out variables.
66284 	 */
66285 
66286 	/* Slot A: currently no support for reg/const. */
66287 
66288 #if defined(DUK_USE_SHUFFLE_TORTURE)
66289 	if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
66290 #else
66291 	if (a <= DUK_BC_A_MAX) {
66292 #endif
66293 		;
66294 	} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
66295 		DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but shuffle prohibited, a: %ld", (long) a));
66296 		goto error_outofregs;
66297 	} else if (a <= DUK_BC_BC_MAX) {
66298 		comp_ctx->curr_func.needs_shuffle = 1;
66299 		tmp = comp_ctx->curr_func.shuffle1;
66300 		if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
66301 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
66302 		} else {
66303 			/* Output shuffle needed after main operation */
66304 			a_out = a;
66305 
66306 			/* The DUK_OP_CSVAR output shuffle assumes shuffle registers are
66307 			 * consecutive.
66308 			 */
66309 			DUK_ASSERT((comp_ctx->curr_func.shuffle1 == 0 && comp_ctx->curr_func.shuffle2 == 0) ||
66310 			           (comp_ctx->curr_func.shuffle2 == comp_ctx->curr_func.shuffle1 + 1));
66311 			if (op == DUK_OP_CSVAR) {
66312 				/* For CSVAR the limit is one smaller because output shuffle
66313 				 * must be able to express 'a + 1' in BC.
66314 				 */
66315 				if (a + 1 > DUK_BC_BC_MAX) {
66316 					goto error_outofregs;
66317 				}
66318 			}
66319 		}
66320 		a = tmp;
66321 	} else {
66322 		DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but does not fit into BC, a: %ld", (long) a));
66323 		goto error_outofregs;
66324 	}
66325 
66326 	/* Slot B: reg/const support, mapped to bit 0 of opcode. */
66327 
66328 	if ((b & DUK__CONST_MARKER) != 0) {
66329 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) == 0);
66330 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
66331 		b = b & ~DUK__CONST_MARKER;
66332 #if defined(DUK_USE_SHUFFLE_TORTURE)
66333 		if (0) {
66334 #else
66335 		if (b <= 0xff) {
66336 #endif
66337 			if (op_flags & DUK__EMIT_FLAG_BC_REGCONST) {
66338 				/* Opcode follows B/C reg/const convention. */
66339 				DUK_ASSERT((op & 0x01) == 0);
66340 				ins |= DUK_ENC_OP_A_B_C(0x01, 0, 0, 0);  /* const flag for B */
66341 			} else {
66342 				DUK_D(DUK_DPRINT("B is const, opcode is not B/C reg/const: %x", op_flags));
66343 			}
66344 		} else if (b <= DUK_BC_BC_MAX) {
66345 			comp_ctx->curr_func.needs_shuffle = 1;
66346 			tmp = comp_ctx->curr_func.shuffle2;
66347 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, b));
66348 			b = tmp;
66349 		} else {
66350 			DUK_D(DUK_DPRINT("out of regs: 'b' (const) needs shuffling but does not fit into BC, b: %ld", (long) b));
66351 			goto error_outofregs;
66352 		}
66353 	} else {
66354 #if defined(DUK_USE_SHUFFLE_TORTURE)
66355 		if (b <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B)) {
66356 #else
66357 		if (b <= 0xff) {
66358 #endif
66359 			;
66360 		} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) {
66361 			if (b > DUK_BC_B_MAX) {
66362 				/* Note: 0xff != DUK_BC_B_MAX */
66363 				DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but shuffle prohibited, b: %ld", (long) b));
66364 				goto error_outofregs;
66365 			}
66366 		} else if (b <= DUK_BC_BC_MAX) {
66367 			comp_ctx->curr_func.needs_shuffle = 1;
66368 			tmp = comp_ctx->curr_func.shuffle2;
66369 			if (op_flags & DUK__EMIT_FLAG_B_IS_TARGET) {
66370 				/* Output shuffle needed after main operation */
66371 				b_out = b;
66372 			}
66373 			if (!(op_flags & DUK__EMIT_FLAG_B_IS_TARGET)) {
66374 				if (op == DUK_OP_MPUTOBJ || op == DUK_OP_MPUTARR) {
66375 					/* Special handling for MPUTOBJ/MPUTARR shuffling.
66376 					 * For each, slot B identifies the first register of a range
66377 					 * of registers, so normal shuffling won't work.  Instead,
66378 					 * an indirect version of the opcode is used.
66379 					 */
66380 					DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
66381 					duk__emit_load_int32_noshuffle(comp_ctx, tmp, b);
66382 					DUK_ASSERT(DUK_OP_MPUTOBJI == DUK_OP_MPUTOBJ + 1);
66383 					DUK_ASSERT(DUK_OP_MPUTARRI == DUK_OP_MPUTARR + 1);
66384 					op_flags++;  /* indirect opcode follows direct */
66385 				} else {
66386 					duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, b));
66387 				}
66388 			}
66389 			b = tmp;
66390 		} else {
66391 			DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but does not fit into BC, b: %ld", (long) b));
66392 			goto error_outofregs;
66393 		}
66394 	}
66395 
66396 	/* Slot C: reg/const support, mapped to bit 1 of opcode. */
66397 
66398 	if ((c & DUK__CONST_MARKER) != 0) {
66399 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) == 0);
66400 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_C_IS_TARGET) == 0);
66401 		c = c & ~DUK__CONST_MARKER;
66402 #if defined(DUK_USE_SHUFFLE_TORTURE)
66403 		if (0) {
66404 #else
66405 		if (c <= 0xff) {
66406 #endif
66407 			if (op_flags & DUK__EMIT_FLAG_BC_REGCONST) {
66408 				/* Opcode follows B/C reg/const convention. */
66409 				DUK_ASSERT((op & 0x02) == 0);
66410 				ins |= DUK_ENC_OP_A_B_C(0x02, 0, 0, 0);  /* const flag for C */
66411 			} else {
66412 				DUK_D(DUK_DPRINT("C is const, opcode is not B/C reg/const: %x", op_flags));
66413 			}
66414 		} else if (c <= DUK_BC_BC_MAX) {
66415 			comp_ctx->curr_func.needs_shuffle = 1;
66416 			tmp = comp_ctx->curr_func.shuffle3;
66417 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, c));
66418 			c = tmp;
66419 		} else {
66420 			DUK_D(DUK_DPRINT("out of regs: 'c' (const) needs shuffling but does not fit into BC, c: %ld", (long) c));
66421 			goto error_outofregs;
66422 		}
66423 	} else {
66424 #if defined(DUK_USE_SHUFFLE_TORTURE)
66425 		if (c <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C)) {
66426 #else
66427 		if (c <= 0xff) {
66428 #endif
66429 			;
66430 		} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) {
66431 			if (c > DUK_BC_C_MAX) {
66432 				/* Note: 0xff != DUK_BC_C_MAX */
66433 				DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but shuffle prohibited, c: %ld", (long) c));
66434 				goto error_outofregs;
66435 			}
66436 		} else if (c <= DUK_BC_BC_MAX) {
66437 			comp_ctx->curr_func.needs_shuffle = 1;
66438 			tmp = comp_ctx->curr_func.shuffle3;
66439 			if (op_flags & DUK__EMIT_FLAG_C_IS_TARGET) {
66440 				/* Output shuffle needed after main operation */
66441 				c_out = c;
66442 			} else {
66443 				duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, c));
66444 			}
66445 			c = tmp;
66446 		} else {
66447 			DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but does not fit into BC, c: %ld", (long) c));
66448 			goto error_outofregs;
66449 		}
66450 	}
66451 
66452 	/* Main operation */
66453 
66454 	DUK_ASSERT(a >= DUK_BC_A_MIN);
66455 	DUK_ASSERT(a <= DUK_BC_A_MAX);
66456 	DUK_ASSERT(b >= DUK_BC_B_MIN);
66457 	DUK_ASSERT(b <= DUK_BC_B_MAX);
66458 	DUK_ASSERT(c >= DUK_BC_C_MIN);
66459 	DUK_ASSERT(c <= DUK_BC_C_MAX);
66460 
66461 	ins |= DUK_ENC_OP_A_B_C(op_flags & 0xff, a, b, c);
66462 	duk__emit(comp_ctx, ins);
66463 
66464 	/* NEXTENUM needs a jump slot right after the main instruction.
66465 	 * When the JUMP is taken, output spilling is not needed so this
66466 	 * workaround is possible.  The jump slot PC is exceptionally
66467 	 * plumbed through comp_ctx to minimize call sites.
66468 	 */
66469 	if (op_flags & DUK__EMIT_FLAG_RESERVE_JUMPSLOT) {
66470 		comp_ctx->emit_jumpslot_pc = duk__get_current_pc(comp_ctx);
66471 		duk__emit_abc(comp_ctx, DUK_OP_JUMP, 0);
66472 	}
66473 
66474 	/* Output shuffling: only one output register is realistically possible.
66475 	 *
66476 	 * (Zero would normally be an OK marker value: if the target register
66477 	 * was zero, it would never be shuffled.  But with DUK_USE_SHUFFLE_TORTURE
66478 	 * this is no longer true, so use -1 as a marker instead.)
66479 	 */
66480 
66481 	if (a_out >= 0) {
66482 		DUK_ASSERT(b_out < 0);
66483 		DUK_ASSERT(c_out < 0);
66484 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, a, a_out));
66485 
66486 		if (op == DUK_OP_CSVAR) {
66487 			/* Special handling for CSVAR shuffling.  The variable lookup
66488 			 * results in a <value, this binding> pair in successive
66489 			 * registers so use two shuffle registers and two output
66490 			 * loads.  (In practice this is dead code because temp/const
66491 			 * limit is reached first.)
66492 			 */
66493 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, a + 1, a_out + 1));
66494 		}
66495 	} else if (b_out >= 0) {
66496 		DUK_ASSERT(a_out < 0);
66497 		DUK_ASSERT(c_out < 0);
66498 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, b, b_out));
66499 	} else if (c_out >= 0) {
66500 		DUK_ASSERT(b_out < 0);
66501 		DUK_ASSERT(c_out < 0);
66502 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, c, c_out));
66503 	}
66504 
66505 	return;
66506 
66507  error_outofregs:
66508 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
66509 	DUK_WO_NORETURN(return;);
66510 }
66511 
66512 /* For many of the helpers below it'd be technically correct to add
66513  * "no shuffle" flags for parameters passed in as zero.  For example,
66514  * duk__emit_a_b() should call duk__emit_a_b_c() with C set to 0, and
66515  * DUK__EMIT_FLAG_NO_SHUFFLE_C added to op_flags.  However, since the
66516  * C value is 0, it'll never get shuffled so adding the flag is just
66517  * unnecessary additional code.  This is unfortunately not true for
66518  * "shuffle torture" mode which needs special handling.
66519  */
66520 
66521 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) {
66522 #if defined(DUK_USE_SHUFFLE_TORTURE)
66523 	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_C;
66524 #endif
66525 	duk__emit_a_b_c(comp_ctx, op_flags, a, b, 0);
66526 }
66527 
66528 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) {
66529 #if defined(DUK_USE_SHUFFLE_TORTURE)
66530 	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_A;
66531 #endif
66532 	duk__emit_a_b_c(comp_ctx, op_flags, 0, b, c);
66533 }
66534 
66535 #if 0  /* unused */
66536 DUK_LOCAL void duk__emit_a(duk_compiler_ctx *comp_ctx, int op_flags, int a) {
66537 #if defined(DUK_USE_SHUFFLE_TORTURE)
66538 	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_B | DUK__EMIT_FLAG_NO_SHUFFLE_C;
66539 #endif
66540 	duk__emit_a_b_c(comp_ctx, op_flags, a, 0, 0);
66541 }
66542 #endif
66543 
66544 #if 0  /* unused */
66545 DUK_LOCAL void duk__emit_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b) {
66546 #if defined(DUK_USE_SHUFFLE_TORTURE)
66547 	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_NO_SHUFFLE_C;
66548 #endif
66549 	duk__emit_a_b_c(comp_ctx, op_flags, 0, b, 0);
66550 }
66551 #endif
66552 
66553 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) {
66554 	duk_instr_t ins;
66555 	duk_int_t tmp;
66556 
66557 	/* allow caller to give a const number with the DUK__CONST_MARKER */
66558 	DUK_ASSERT(bc != -1);  /* Not 'none'. */
66559 	bc = bc & (~DUK__CONST_MARKER);
66560 
66561 	DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN);  /* unsigned */
66562 	DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
66563 	DUK_ASSERT(bc >= DUK_BC_BC_MIN);
66564 	DUK_ASSERT(bc <= DUK_BC_BC_MAX);
66565 	DUK_ASSERT((bc & DUK__CONST_MARKER) == 0);
66566 
66567 	if (bc <= DUK_BC_BC_MAX) {
66568 		;
66569 	} else {
66570 		/* No BC shuffling now. */
66571 		goto error_outofregs;
66572 	}
66573 
66574 #if defined(DUK_USE_SHUFFLE_TORTURE)
66575 	if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
66576 #else
66577 	if (a <= DUK_BC_A_MAX) {
66578 #endif
66579 		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, a, bc);
66580 		duk__emit(comp_ctx, ins);
66581 	} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
66582 		goto error_outofregs;
66583 	} else if ((op_flags & 0xf0U) == DUK_OP_CALL0) {
66584 		comp_ctx->curr_func.needs_shuffle = 1;
66585 		tmp = comp_ctx->curr_func.shuffle1;
66586 		duk__emit_load_int32_noshuffle(comp_ctx, tmp, a);
66587 		op_flags |= DUK_BC_CALL_FLAG_INDIRECT;
66588 		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, tmp, bc);
66589 		duk__emit(comp_ctx, ins);
66590 	} else if (a <= DUK_BC_BC_MAX) {
66591 		comp_ctx->curr_func.needs_shuffle = 1;
66592 		tmp = comp_ctx->curr_func.shuffle1;
66593 		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, tmp, bc);
66594 		if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
66595 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
66596 			duk__emit(comp_ctx, ins);
66597 		} else {
66598 			duk__emit(comp_ctx, ins);
66599 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, tmp, a));
66600 		}
66601 	} else {
66602 		goto error_outofregs;
66603 	}
66604 	return;
66605 
66606  error_outofregs:
66607 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
66608 	DUK_WO_NORETURN(return;);
66609 }
66610 
66611 DUK_LOCAL void duk__emit_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t bc) {
66612 #if defined(DUK_USE_SHUFFLE_TORTURE)
66613 	op |= DUK__EMIT_FLAG_NO_SHUFFLE_A;
66614 #endif
66615 	duk__emit_a_bc(comp_ctx, op, 0, bc);
66616 }
66617 
66618 DUK_LOCAL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc) {
66619 	duk_instr_t ins;
66620 
66621 	DUK_ASSERT_DISABLE(op >= DUK_BC_OP_MIN);  /* unsigned */
66622 	DUK_ASSERT(op <= DUK_BC_OP_MAX);
66623 	DUK_ASSERT_DISABLE(abc >= DUK_BC_ABC_MIN);  /* unsigned */
66624 	DUK_ASSERT(abc <= DUK_BC_ABC_MAX);
66625 	DUK_ASSERT((abc & DUK__CONST_MARKER) == 0);
66626 	DUK_ASSERT(abc != -1);  /* Not 'none'. */
66627 
66628 	if (abc <= DUK_BC_ABC_MAX) {
66629 		;
66630 	} else {
66631 		goto error_outofregs;
66632 	}
66633 	ins = DUK_ENC_OP_ABC(op, abc);
66634 	DUK_DDD(DUK_DDDPRINT("duk__emit_abc: 0x%08lx line=%ld pc=%ld op=%ld (%!C) abc=%ld (%!I)",
66635 	                     (unsigned long) ins, (long) comp_ctx->curr_token.start_line,
66636 	                     (long) duk__get_current_pc(comp_ctx), (long) op, (long) op,
66637 	                     (long) abc, (duk_instr_t) ins));
66638 	duk__emit(comp_ctx, ins);
66639 	return;
66640 
66641  error_outofregs:
66642 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
66643 	DUK_WO_NORETURN(return;);
66644 }
66645 
66646 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) {
66647 	/* XXX: Shuffling support could be implemented here so that LDINT+LDINTX
66648 	 * would only shuffle once (instead of twice).  The current code works
66649 	 * though, and has a smaller compiler footprint.
66650 	 */
66651 
66652 	if ((val >= (duk_int32_t) DUK_BC_BC_MIN - (duk_int32_t) DUK_BC_LDINT_BIAS) &&
66653 	    (val <= (duk_int32_t) DUK_BC_BC_MAX - (duk_int32_t) DUK_BC_LDINT_BIAS)) {
66654 		DUK_DDD(DUK_DDDPRINT("emit LDINT to reg %ld for %ld", (long) reg, (long) val));
66655 		duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (val + (duk_int32_t) DUK_BC_LDINT_BIAS));
66656 	} else {
66657 		duk_int32_t hi = val >> DUK_BC_LDINTX_SHIFT;
66658 		duk_int32_t lo = val & ((((duk_int32_t) 1) << DUK_BC_LDINTX_SHIFT) - 1);
66659 		DUK_ASSERT(lo >= 0);
66660 		DUK_DDD(DUK_DDDPRINT("emit LDINT+LDINTX to reg %ld for %ld -> hi %ld, lo %ld",
66661 		                     (long) reg, (long) val, (long) hi, (long) lo));
66662 		duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (hi + (duk_int32_t) DUK_BC_LDINT_BIAS));
66663 		duk__emit_a_bc(comp_ctx, DUK_OP_LDINTX | op_flags, reg, (duk_regconst_t) lo);
66664 	}
66665 }
66666 
66667 DUK_LOCAL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
66668 	duk__emit_load_int32_raw(comp_ctx, reg, val, 0 /*op_flags*/);
66669 }
66670 
66671 #if defined(DUK_USE_SHUFFLE_TORTURE)
66672 /* Used by duk__emit*() calls so that we don't shuffle the loadints that
66673  * are needed to handle indirect opcodes.
66674  */
66675 DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
66676 	duk__emit_load_int32_raw(comp_ctx, reg, val, DUK__EMIT_FLAG_NO_SHUFFLE_A /*op_flags*/);
66677 }
66678 #else
66679 DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
66680 	/* When torture not enabled, can just use the same helper because
66681 	 * 'reg' won't get spilled.
66682 	 */
66683 	DUK_ASSERT(reg <= DUK_BC_A_MAX);
66684 	duk__emit_load_int32(comp_ctx, reg, val);
66685 }
66686 #endif
66687 
66688 DUK_LOCAL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc) {
66689 	duk_int_t curr_pc;
66690 	duk_int_t offset;
66691 
66692 	curr_pc = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
66693 	offset = (duk_int_t) target_pc - (duk_int_t) curr_pc - 1;
66694 	DUK_ASSERT(offset + DUK_BC_JUMP_BIAS >= DUK_BC_ABC_MIN);
66695 	DUK_ASSERT(offset + DUK_BC_JUMP_BIAS <= DUK_BC_ABC_MAX);
66696 	duk__emit_abc(comp_ctx, DUK_OP_JUMP, (duk_regconst_t) (offset + DUK_BC_JUMP_BIAS));
66697 }
66698 
66699 DUK_LOCAL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx) {
66700 	duk_int_t ret;
66701 
66702 	ret = duk__get_current_pc(comp_ctx);  /* useful for patching jumps later */
66703 	duk__emit_op_only(comp_ctx, DUK_OP_JUMP);
66704 	return ret;
66705 }
66706 
66707 /* Insert an empty jump in the middle of code emitted earlier.  This is
66708  * currently needed for compiling for-in.
66709  */
66710 DUK_LOCAL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
66711 #if defined(DUK_USE_PC2LINE)
66712 	duk_int_t line;
66713 #endif
66714 	duk_compiler_instr *instr;
66715 	duk_size_t offset;
66716 
66717 	DUK_ASSERT(jump_pc >= 0);
66718 	offset = (duk_size_t) jump_pc * sizeof(duk_compiler_instr);
66719 	instr = (duk_compiler_instr *) (void *)
66720 	        DUK_BW_INSERT_ENSURE_AREA(comp_ctx->thr,
66721 	                                  &comp_ctx->curr_func.bw_code,
66722 	                                  offset,
66723 	                                  sizeof(duk_compiler_instr));
66724 
66725 #if defined(DUK_USE_PC2LINE)
66726 	line = comp_ctx->curr_token.start_line;  /* approximation, close enough */
66727 #endif
66728 	instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, 0);
66729 #if defined(DUK_USE_PC2LINE)
66730 	instr->line = (duk_uint32_t) line;
66731 #endif
66732 
66733 	DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
66734 	if (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) {
66735 		goto fail_bc_limit;
66736 	}
66737 	return;
66738 
66739   fail_bc_limit:
66740 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT);
66741 	DUK_WO_NORETURN(return;);
66742 }
66743 
66744 /* Does not assume that jump_pc contains a DUK_OP_JUMP previously; this is intentional
66745  * to allow e.g. an INVALID opcode be overwritten with a JUMP (label management uses this).
66746  */
66747 DUK_LOCAL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc) {
66748 	duk_compiler_instr *instr;
66749 	duk_int_t offset;
66750 
66751 	/* allow negative PCs, behave as a no-op */
66752 	if (jump_pc < 0) {
66753 		DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): nop call, jump_pc=%ld (<0), target_pc=%ld",
66754 		                     (long) jump_pc, (long) target_pc));
66755 		return;
66756 	}
66757 	DUK_ASSERT(jump_pc >= 0);
66758 
66759 	/* XXX: range assert */
66760 	instr = duk__get_instr_ptr(comp_ctx, jump_pc);
66761 	DUK_ASSERT(instr != NULL);
66762 
66763 	/* XXX: range assert */
66764 	offset = target_pc - jump_pc - 1;
66765 
66766 	instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, offset + DUK_BC_JUMP_BIAS);
66767 	DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): jump_pc=%ld, target_pc=%ld, offset=%ld",
66768 	                     (long) jump_pc, (long) target_pc, (long) offset));
66769 }
66770 
66771 DUK_LOCAL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
66772 	duk__patch_jump(comp_ctx, jump_pc, duk__get_current_pc(comp_ctx));
66773 }
66774 
66775 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) {
66776 	duk_compiler_instr *instr;
66777 
66778 	DUK_ASSERT(DUK__ISREG(reg_catch));
66779 
66780 	instr = duk__get_instr_ptr(comp_ctx, ldconst_pc);
66781 	DUK_ASSERT(DUK_DEC_OP(instr->ins) == DUK_OP_LDCONST);
66782 	DUK_ASSERT(instr != NULL);
66783 	if (const_varname & DUK__CONST_MARKER) {
66784 		/* Have a catch variable. */
66785 		const_varname = const_varname & (~DUK__CONST_MARKER);
66786 		if (reg_catch > DUK_BC_BC_MAX || const_varname > DUK_BC_BC_MAX) {
66787 			/* Catch attempts to use out-of-range reg/const.  Without this
66788 			 * check Duktape 0.12.0 could generate invalid code which caused
66789 			 * an assert failure on execution.  This error is triggered e.g.
66790 			 * for functions with a lot of constants and a try-catch statement.
66791 			 * Shuffling or opcode semantics change is needed to fix the issue.
66792 			 * See: test-bug-trycatch-many-constants.js.
66793 			 */
66794 			DUK_D(DUK_DPRINT("failed to patch trycatch: flags=%ld, reg_catch=%ld, const_varname=%ld (0x%08lx)",
66795 			                 (long) flags, (long) reg_catch, (long) const_varname, (long) const_varname));
66796 			DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
66797 			DUK_WO_NORETURN(return;);
66798 		}
66799 		instr->ins |= DUK_ENC_OP_A_BC(0, 0, const_varname);
66800 	} else {
66801 		/* No catch variable, e.g. a try-finally; replace LDCONST with
66802 		 * NOP to avoid a bogus LDCONST.
66803 		 */
66804 		instr->ins = DUK_ENC_OP(DUK_OP_NOP);
66805 	}
66806 
66807 	instr = duk__get_instr_ptr(comp_ctx, trycatch_pc);
66808 	DUK_ASSERT(instr != NULL);
66809 	DUK_ASSERT_DISABLE(flags >= DUK_BC_A_MIN);
66810 	DUK_ASSERT(flags <= DUK_BC_A_MAX);
66811 	instr->ins = DUK_ENC_OP_A_BC(DUK_OP_TRYCATCH, flags, reg_catch);
66812 }
66813 
66814 DUK_LOCAL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
66815 	duk_small_uint_t op;
66816 
66817 	op = DUK__ISREG(regconst) ? DUK_OP_IFFALSE_R : DUK_OP_IFFALSE_C;
66818 	duk__emit_bc(comp_ctx, op, regconst);  /* helper will remove const flag */
66819 }
66820 
66821 DUK_LOCAL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
66822 	duk_small_uint_t op;
66823 
66824 	op = DUK__ISREG(regconst) ? DUK_OP_IFTRUE_R : DUK_OP_IFTRUE_C;
66825 	duk__emit_bc(comp_ctx, op, regconst);  /* helper will remove const flag */
66826 }
66827 
66828 DUK_LOCAL void duk__emit_invalid(duk_compiler_ctx *comp_ctx) {
66829 	duk__emit_op_only(comp_ctx, DUK_OP_INVALID);
66830 }
66831 
66832 /*
66833  *  Peephole optimizer for finished bytecode.
66834  *
66835  *  Does not remove opcodes; currently only straightens out unconditional
66836  *  jump chains which are generated by several control structures.
66837  */
66838 
66839 DUK_LOCAL void duk__peephole_optimize_bytecode(duk_compiler_ctx *comp_ctx) {
66840 	duk_compiler_instr *bc;
66841 	duk_small_uint_t iter;
66842 	duk_int_t i, n;
66843 	duk_int_t count_opt;
66844 
66845 	bc = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code);
66846 #if defined(DUK_USE_BUFLEN16)
66847 	/* No need to assert, buffer size maximum is 0xffff. */
66848 #else
66849 	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 */
66850 #endif
66851 	n = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
66852 
66853 	for (iter = 0; iter < DUK_COMPILER_PEEPHOLE_MAXITER; iter++) {
66854 		count_opt = 0;
66855 
66856 		for (i = 0; i < n; i++) {
66857 			duk_instr_t ins;
66858 			duk_int_t target_pc1;
66859 			duk_int_t target_pc2;
66860 
66861 			ins = bc[i].ins;
66862 			if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
66863 				continue;
66864 			}
66865 
66866 			target_pc1 = i + 1 + (duk_int_t) DUK_DEC_ABC(ins) - (duk_int_t) DUK_BC_JUMP_BIAS;
66867 			DUK_DDD(DUK_DDDPRINT("consider jump at pc %ld; target_pc=%ld", (long) i, (long) target_pc1));
66868 			DUK_ASSERT(target_pc1 >= 0);
66869 			DUK_ASSERT(target_pc1 < n);
66870 
66871 			/* Note: if target_pc1 == i, we'll optimize a jump to itself.
66872 			 * This does not need to be checked for explicitly; the case
66873 			 * is rare and max iter breaks us out.
66874 			 */
66875 
66876 			ins = bc[target_pc1].ins;
66877 			if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
66878 				continue;
66879 			}
66880 
66881 			target_pc2 = target_pc1 + 1 + (duk_int_t) DUK_DEC_ABC(ins) - (duk_int_t) DUK_BC_JUMP_BIAS;
66882 
66883 			DUK_DDD(DUK_DDDPRINT("optimizing jump at pc %ld; old target is %ld -> new target is %ld",
66884 			                     (long) i, (long) target_pc1, (long) target_pc2));
66885 
66886 			bc[i].ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, target_pc2 - (i + 1) + DUK_BC_JUMP_BIAS);
66887 
66888 			count_opt++;
66889 		}
66890 
66891 		DUK_DD(DUK_DDPRINT("optimized %ld jumps on peephole round %ld", (long) count_opt, (long) (iter + 1)));
66892 
66893 		if (count_opt == 0) {
66894 			break;
66895 		}
66896 	}
66897 }
66898 
66899 /*
66900  *  Intermediate value helpers
66901  */
66902 
66903 /* Flags for intermediate value coercions.  A flag for using a forced reg
66904  * is not needed, the forced_reg argument suffices and generates better
66905  * code (it is checked as it is used).
66906  */
66907 /* XXX: DUK__IVAL_FLAG_REQUIRE_SHORT is passed but not currently implemented
66908  * by ispec/ivalue operations.
66909  */
66910 #define DUK__IVAL_FLAG_ALLOW_CONST          (1 << 0)  /* allow a constant to be returned */
66911 #define DUK__IVAL_FLAG_REQUIRE_TEMP         (1 << 1)  /* require a (mutable) temporary as a result (or a const if allowed) */
66912 #define DUK__IVAL_FLAG_REQUIRE_SHORT        (1 << 2)  /* require a short (8-bit) reg/const which fits into bytecode B/C slot */
66913 
66914 /* XXX: some code might benefit from DUK__SETTEMP_IFTEMP(thr,x) */
66915 
66916 #if 0  /* enable manually for dumping */
66917 #define DUK__DUMP_ISPEC(compctx,ispec) do { duk__dump_ispec((compctx), (ispec)); } while (0)
66918 #define DUK__DUMP_IVALUE(compctx,ivalue) do { duk__dump_ivalue((compctx), (ivalue)); } while (0)
66919 
66920 DUK_LOCAL void duk__dump_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *x) {
66921 	DUK_D(DUK_DPRINT("ispec dump: t=%ld regconst=0x%08lx, valstack_idx=%ld, value=%!T",
66922 	                 (long) x->t, (unsigned long) x->regconst, (long) x->valstack_idx,
66923 	                 duk_get_tval(comp_ctx->thr, x->valstack_idx)));
66924 }
66925 DUK_LOCAL void duk__dump_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
66926 	DUK_D(DUK_DPRINT("ivalue dump: t=%ld op=%ld "
66927 	                 "x1={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T} "
66928 	                 "x2={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T}",
66929 		         (long) x->t, (long) x->op,
66930 	                 (long) x->x1.t, (unsigned long) x->x1.regconst, (long) x->x1.valstack_idx,
66931 	                 duk_get_tval(comp_ctx->thr, x->x1.valstack_idx),
66932 	                 (long) x->x2.t, (unsigned long) x->x2.regconst, (long) x->x2.valstack_idx,
66933 	                 duk_get_tval(comp_ctx->thr, x->x2.valstack_idx)));
66934 }
66935 #else
66936 #define DUK__DUMP_ISPEC(comp_ctx,x) do {} while (0)
66937 #define DUK__DUMP_IVALUE(comp_ctx,x) do {} while (0)
66938 #endif
66939 
66940 DUK_LOCAL void duk__ivalue_regconst(duk_ivalue *x, duk_regconst_t regconst) {
66941 	x->t = DUK_IVAL_PLAIN;
66942 	x->x1.t = DUK_ISPEC_REGCONST;
66943 	x->x1.regconst = regconst;
66944 }
66945 
66946 DUK_LOCAL void duk__ivalue_plain_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
66947 	x->t = DUK_IVAL_PLAIN;
66948 	x->x1.t = DUK_ISPEC_VALUE;
66949 	duk_replace(comp_ctx->thr, x->x1.valstack_idx);
66950 }
66951 
66952 DUK_LOCAL void duk__ivalue_var_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
66953 	x->t = DUK_IVAL_VAR;
66954 	x->x1.t = DUK_ISPEC_VALUE;
66955 	duk_replace(comp_ctx->thr, x->x1.valstack_idx);
66956 }
66957 
66958 DUK_LOCAL_DECL void duk__ivalue_var_hstring(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_hstring *h) {
66959 	DUK_ASSERT(h != NULL);
66960 	duk_push_hstring(comp_ctx->thr, h);
66961 	duk__ivalue_var_fromstack(comp_ctx, x);
66962 }
66963 
66964 DUK_LOCAL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst) {
66965 	dst->t = src->t;
66966 	dst->regconst = src->regconst;
66967 	duk_copy(comp_ctx->thr, src->valstack_idx, dst->valstack_idx);
66968 }
66969 
66970 DUK_LOCAL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst) {
66971 	dst->t = src->t;
66972 	dst->op = src->op;
66973 	dst->x1.t = src->x1.t;
66974 	dst->x1.regconst = src->x1.regconst;
66975 	dst->x2.t = src->x2.t;
66976 	dst->x2.regconst = src->x2.regconst;
66977 	duk_copy(comp_ctx->thr, src->x1.valstack_idx, dst->x1.valstack_idx);
66978 	duk_copy(comp_ctx->thr, src->x2.valstack_idx, dst->x2.valstack_idx);
66979 }
66980 
66981 DUK_LOCAL duk_regconst_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num) {
66982 	duk_regconst_t res;
66983 
66984 	res = comp_ctx->curr_func.temp_next;
66985 	comp_ctx->curr_func.temp_next += num;
66986 
66987 	if (comp_ctx->curr_func.temp_next > DUK__MAX_TEMPS) {  /* == DUK__MAX_TEMPS is OK */
66988 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_TEMP_LIMIT);
66989 		DUK_WO_NORETURN(return 0;);
66990 	}
66991 
66992 	/* maintain highest 'used' temporary, needed to figure out nregs of function */
66993 	if (comp_ctx->curr_func.temp_next > comp_ctx->curr_func.temp_max) {
66994 		comp_ctx->curr_func.temp_max = comp_ctx->curr_func.temp_next;
66995 	}
66996 
66997 	return res;
66998 }
66999 
67000 DUK_LOCAL duk_regconst_t duk__alloctemp(duk_compiler_ctx *comp_ctx) {
67001 	return duk__alloctemps(comp_ctx, 1);
67002 }
67003 
67004 DUK_LOCAL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_regconst_t temp_next) {
67005 	comp_ctx->curr_func.temp_next = temp_next;
67006 	if (temp_next > comp_ctx->curr_func.temp_max) {
67007 		comp_ctx->curr_func.temp_max = temp_next;
67008 	}
67009 }
67010 
67011 /* get const for value at valstack top */
67012 DUK_LOCAL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx) {
67013 	duk_hthread *thr = comp_ctx->thr;
67014 	duk_compiler_func *f = &comp_ctx->curr_func;
67015 	duk_tval *tv1;
67016 	duk_int_t i, n, n_check;
67017 
67018 	n = (duk_int_t) duk_get_length(thr, f->consts_idx);
67019 
67020 	tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
67021 	DUK_ASSERT(tv1 != NULL);
67022 
67023 #if defined(DUK_USE_FASTINT)
67024 	/* Explicit check for fastint downgrade. */
67025 	DUK_TVAL_CHKFAST_INPLACE_SLOW(tv1);
67026 #endif
67027 
67028 	/* Sanity workaround for handling functions with a large number of
67029 	 * constants at least somewhat reasonably.  Otherwise checking whether
67030 	 * we already have the constant would grow very slow (as it is O(N^2)).
67031 	 */
67032 	n_check = (n > DUK__GETCONST_MAX_CONSTS_CHECK ? DUK__GETCONST_MAX_CONSTS_CHECK : n);
67033 	for (i = 0; i < n_check; i++) {
67034 		duk_tval *tv2 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, f->h_consts, i);
67035 
67036 		/* Strict equality is NOT enough, because we cannot use the same
67037 		 * constant for e.g. +0 and -0.
67038 		 */
67039 		if (duk_js_samevalue(tv1, tv2)) {
67040 			DUK_DDD(DUK_DDDPRINT("reused existing constant for %!T -> const index %ld",
67041 			                     (duk_tval *) tv1, (long) i));
67042 			duk_pop(thr);
67043 			return (duk_regconst_t) i | (duk_regconst_t) DUK__CONST_MARKER;
67044 		}
67045 	}
67046 
67047 	if (n > DUK__MAX_CONSTS) {
67048 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_CONST_LIMIT);
67049 		DUK_WO_NORETURN(return 0;);
67050 	}
67051 
67052 	DUK_DDD(DUK_DDDPRINT("allocating new constant for %!T -> const index %ld",
67053 	                     (duk_tval *) tv1, (long) n));
67054 	(void) duk_put_prop_index(thr, f->consts_idx, (duk_uarridx_t) n);  /* invalidates tv1, tv2 */
67055 	return (duk_regconst_t) n | (duk_regconst_t) DUK__CONST_MARKER;
67056 }
67057 
67058 DUK_LOCAL duk_bool_t duk__const_needs_refcount(duk_compiler_ctx *comp_ctx, duk_regconst_t rc) {
67059 #if defined(DUK_USE_REFERENCE_COUNTING)
67060 	duk_compiler_func *f = &comp_ctx->curr_func;
67061 	duk_bool_t ret;
67062 
67063 	DUK_ASSERT((rc & DUK__CONST_MARKER) == 0);  /* caller removes const marker */
67064 	(void) duk_get_prop_index(comp_ctx->thr, f->consts_idx, (duk_uarridx_t) rc);
67065 	ret = !duk_is_number(comp_ctx->thr, -1);  /* now only number/string, so conservative check */
67066 	duk_pop(comp_ctx->thr);
67067 	return ret;
67068 #else
67069 	DUK_UNREF(comp_ctx);
67070 	DUK_UNREF(rc);
67071 	DUK_ASSERT((rc & DUK__CONST_MARKER) == 0);  /* caller removes const marker */
67072 	return 0;
67073 #endif
67074 }
67075 
67076 /* Get the value represented by an duk_ispec to a register or constant.
67077  * The caller can control the result by indicating whether or not:
67078  *
67079  *   (1) a constant is allowed (sometimes the caller needs the result to
67080  *       be in a register)
67081  *
67082  *   (2) a temporary register is required (usually when caller requires
67083  *       the register to be safely mutable; normally either a bound
67084  *       register or a temporary register are both OK)
67085  *
67086  *   (3) a forced register target needs to be used
67087  *
67088  * Bytecode may be emitted to generate the necessary value.  The return
67089  * value is either a register or a constant.
67090  */
67091 
67092 DUK_LOCAL
67093 duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
67094                                          duk_ispec *x,
67095                                          duk_regconst_t forced_reg,
67096                                          duk_small_uint_t flags) {
67097 	duk_hthread *thr = comp_ctx->thr;
67098 
67099 	DUK_DDD(DUK_DDDPRINT("duk__ispec_toregconst_raw(): x={%ld:%ld:%!T}, "
67100 	                     "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
67101 	                     (long) x->t,
67102 	                     (long) x->regconst,
67103 	                     (duk_tval *) duk_get_tval(thr, x->valstack_idx),
67104 	                     (long) forced_reg,
67105 	                     (unsigned long) flags,
67106 	                     (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
67107 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
67108 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));
67109 
67110 	switch (x->t) {
67111 	case DUK_ISPEC_VALUE: {
67112 		duk_tval *tv;
67113 
67114 		tv = DUK_GET_TVAL_POSIDX(thr, x->valstack_idx);
67115 		DUK_ASSERT(tv != NULL);
67116 
67117 		switch (DUK_TVAL_GET_TAG(tv)) {
67118 		case DUK_TAG_UNDEFINED: {
67119 			/* Note: although there is no 'undefined' literal, undefined
67120 			 * values can occur during compilation as a result of e.g.
67121 			 * the 'void' operator.
67122 			 */
67123 			duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
67124 			duk__emit_bc(comp_ctx, DUK_OP_LDUNDEF, dest);
67125 			return dest;
67126 		}
67127 		case DUK_TAG_NULL: {
67128 			duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
67129 			duk__emit_bc(comp_ctx, DUK_OP_LDNULL, dest);
67130 			return dest;
67131 		}
67132 		case DUK_TAG_BOOLEAN: {
67133 			duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
67134 			duk__emit_bc(comp_ctx,
67135 			             (DUK_TVAL_GET_BOOLEAN(tv) ? DUK_OP_LDTRUE : DUK_OP_LDFALSE),
67136 			             dest);
67137 			return dest;
67138 		}
67139 		case DUK_TAG_POINTER: {
67140 			DUK_UNREACHABLE();
67141 			break;
67142 		}
67143 		case DUK_TAG_STRING: {
67144 			duk_hstring *h;
67145 			duk_regconst_t dest;
67146 			duk_regconst_t constidx;
67147 
67148 			h = DUK_TVAL_GET_STRING(tv);
67149 			DUK_UNREF(h);
67150 			DUK_ASSERT(h != NULL);
67151 
67152 #if 0  /* XXX: to be implemented? */
67153 			/* Use special opcodes to load short strings */
67154 			if (DUK_HSTRING_GET_BYTELEN(h) <= 2) {
67155 				/* Encode into a single opcode (18 bits can encode 1-2 bytes + length indicator) */
67156 			} else if (DUK_HSTRING_GET_BYTELEN(h) <= 6) {
67157 				/* Encode into a double constant (53 bits can encode 6*8 = 48 bits + 3-bit length */
67158 			}
67159 #endif
67160 			duk_dup(thr, x->valstack_idx);
67161 			constidx = duk__getconst(comp_ctx);
67162 
67163 			if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
67164 				return constidx;
67165 			}
67166 
67167 			dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
67168 			duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, constidx);
67169 			return dest;
67170 		}
67171 		case DUK_TAG_OBJECT: {
67172 			DUK_UNREACHABLE();
67173 			break;
67174 		}
67175 		case DUK_TAG_BUFFER: {
67176 			DUK_UNREACHABLE();
67177 			break;
67178 		}
67179 		case DUK_TAG_LIGHTFUNC: {
67180 			DUK_UNREACHABLE();
67181 			break;
67182 		}
67183 #if defined(DUK_USE_FASTINT)
67184 		case DUK_TAG_FASTINT:
67185 #endif
67186 		default: {
67187 			/* number */
67188 			duk_regconst_t dest;
67189 			duk_regconst_t constidx;
67190 			duk_double_t dval;
67191 			duk_int32_t ival;
67192 
67193 			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
67194 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
67195 			dval = DUK_TVAL_GET_NUMBER(tv);
67196 
67197 			if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
67198 				/* A number can be loaded either through a constant, using
67199 				 * LDINT, or using LDINT+LDINTX.  LDINT is always a size win,
67200 				 * LDINT+LDINTX is not if the constant is used multiple times.
67201 				 * Currently always prefer LDINT+LDINTX over a double constant.
67202 				 */
67203 
67204 				if (duk_is_whole_get_int32_nonegzero(dval, &ival)) {
67205 					dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
67206 					duk__emit_load_int32(comp_ctx, dest, ival);
67207 					return dest;
67208 				}
67209 			}
67210 
67211 			duk_dup(thr, x->valstack_idx);
67212 			constidx = duk__getconst(comp_ctx);
67213 
67214 			if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
67215 				return constidx;
67216 			} else {
67217 				dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
67218 				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, constidx);
67219 				return dest;
67220 			}
67221 		}
67222 		}  /* end switch */
67223 		goto fail_internal;  /* never here */
67224 	}
67225 	case DUK_ISPEC_REGCONST: {
67226 		if (forced_reg >= 0) {
67227 			if (DUK__ISCONST(x->regconst)) {
67228 				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, forced_reg, x->regconst);
67229 			} else if (x->regconst != forced_reg) {
67230 				duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, forced_reg, x->regconst);
67231 			} else {
67232 				; /* already in correct reg */
67233 			}
67234 			return forced_reg;
67235 		}
67236 
67237 		DUK_ASSERT(forced_reg < 0);
67238 		if (DUK__ISCONST(x->regconst)) {
67239 			if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
67240 				duk_regconst_t dest = DUK__ALLOCTEMP(comp_ctx);
67241 				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, x->regconst);
67242 				return dest;
67243 			}
67244 			return x->regconst;
67245 		}
67246 
67247 		DUK_ASSERT(forced_reg < 0 && !DUK__ISCONST(x->regconst));
67248 		if ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) && !DUK__ISREG_TEMP(comp_ctx, x->regconst)) {
67249 			duk_regconst_t dest = DUK__ALLOCTEMP(comp_ctx);
67250 			duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, dest, x->regconst);
67251 			return dest;
67252 		}
67253 		return x->regconst;
67254 	}
67255 	default: {
67256 		break;  /* never here */
67257 	}
67258 	}
67259 
67260  fail_internal:
67261 	DUK_ERROR_INTERNAL(thr);
67262 	DUK_WO_NORETURN(return 0;);
67263 }
67264 
67265 DUK_LOCAL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_regconst_t forced_reg) {
67266 	DUK_ASSERT(forced_reg >= 0);
67267 	(void) duk__ispec_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
67268 }
67269 
67270 /* Coerce an duk_ivalue to a 'plain' value by generating the necessary
67271  * arithmetic operations, property access, or variable access bytecode.
67272  * The duk_ivalue argument ('x') is converted into a plain value as a
67273  * side effect.
67274  */
67275 DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_regconst_t forced_reg) {
67276 	duk_hthread *thr = comp_ctx->thr;
67277 
67278 	DUK_DDD(DUK_DDDPRINT("duk__ivalue_toplain_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
67279 	                     "forced_reg=%ld",
67280 	                     (long) x->t, (long) x->op,
67281 	                     (long) x->x1.t, (long) x->x1.regconst,
67282 	                     (duk_tval *) duk_get_tval(thr, x->x1.valstack_idx),
67283 	                     (long) x->x2.t, (long) x->x2.regconst,
67284 	                     (duk_tval *) duk_get_tval(thr, x->x2.valstack_idx),
67285 	                     (long) forced_reg));
67286 
67287 	switch (x->t) {
67288 	case DUK_IVAL_PLAIN: {
67289 		return;
67290 	}
67291 	/* XXX: support unary arithmetic ivalues (useful?) */
67292 	case DUK_IVAL_ARITH: {
67293 		duk_regconst_t arg1;
67294 		duk_regconst_t arg2;
67295 		duk_regconst_t dest;
67296 		duk_tval *tv1;
67297 		duk_tval *tv2;
67298 
67299 		DUK_DDD(DUK_DDDPRINT("arith to plain conversion"));
67300 
67301 		/* inline arithmetic check for constant values */
67302 		/* XXX: use the exactly same arithmetic function here as in executor */
67303 		if (x->x1.t == DUK_ISPEC_VALUE && x->x2.t == DUK_ISPEC_VALUE && x->t == DUK_IVAL_ARITH) {
67304 			tv1 = DUK_GET_TVAL_POSIDX(thr, x->x1.valstack_idx);
67305 			tv2 = DUK_GET_TVAL_POSIDX(thr, x->x2.valstack_idx);
67306 			DUK_ASSERT(tv1 != NULL);
67307 			DUK_ASSERT(tv2 != NULL);
67308 
67309 			DUK_DDD(DUK_DDDPRINT("arith: tv1=%!T, tv2=%!T",
67310 			                     (duk_tval *) tv1,
67311 			                     (duk_tval *) tv2));
67312 
67313 			if (DUK_TVAL_IS_NUMBER(tv1) && DUK_TVAL_IS_NUMBER(tv2)) {
67314 				duk_double_t d1 = DUK_TVAL_GET_NUMBER(tv1);
67315 				duk_double_t d2 = DUK_TVAL_GET_NUMBER(tv2);
67316 				duk_double_t d3;
67317 				duk_bool_t accept_fold = 1;
67318 
67319 				DUK_DDD(DUK_DDDPRINT("arith inline check: d1=%lf, d2=%lf, op=%ld",
67320 				                     (double) d1, (double) d2, (long) x->op));
67321 				switch (x->op) {
67322 				case DUK_OP_ADD: {
67323 					d3 = d1 + d2;
67324 					break;
67325 				}
67326 				case DUK_OP_SUB: {
67327 					d3 = d1 - d2;
67328 					break;
67329 				}
67330 				case DUK_OP_MUL: {
67331 					d3 = d1 * d2;
67332 					break;
67333 				}
67334 				case DUK_OP_DIV: {
67335 					/* Division-by-zero is undefined
67336 					 * behavior, so rely on a helper.
67337 					 */
67338 					d3 = duk_double_div(d1, d2);
67339 					break;
67340 				}
67341 				case DUK_OP_EXP: {
67342 					d3 = (duk_double_t) duk_js_arith_pow((double) d1, (double) d2);
67343 					break;
67344 				}
67345 				default: {
67346 					d3 = 0.0;  /* Won't be used, but silence MSVC /W4 warning. */
67347 					accept_fold = 0;
67348 					break;
67349 				}
67350 				}
67351 
67352 				if (accept_fold) {
67353 					duk_double_union du;
67354 					du.d = d3;
67355 					DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
67356 					d3 = du.d;
67357 
67358 					x->t = DUK_IVAL_PLAIN;
67359 					DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
67360 					DUK_TVAL_SET_NUMBER(tv1, d3);  /* old value is number: no refcount */
67361 					return;
67362 				}
67363 			} else if (x->op == DUK_OP_ADD && DUK_TVAL_IS_STRING(tv1) && DUK_TVAL_IS_STRING(tv2)) {
67364 				/* Inline string concatenation.  No need to check for
67365 				 * symbols, as all inputs are valid ECMAScript strings.
67366 				 */
67367 				duk_dup(thr, x->x1.valstack_idx);
67368 				duk_dup(thr, x->x2.valstack_idx);
67369 				duk_concat(thr, 2);
67370 				duk_replace(thr, x->x1.valstack_idx);
67371 				x->t = DUK_IVAL_PLAIN;
67372 				DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
67373 				return;
67374 			}
67375 		}
67376 
67377 		arg1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
67378 		arg2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
67379 
67380 		/* If forced reg, use it as destination.  Otherwise try to
67381 		 * use either coerced ispec if it is a temporary.
67382 		 */
67383 		if (forced_reg >= 0) {
67384 			dest = forced_reg;
67385 		} else if (DUK__ISREG_TEMP(comp_ctx, arg1)) {
67386 			dest = arg1;
67387 		} else if (DUK__ISREG_TEMP(comp_ctx, arg2)) {
67388 			dest = arg2;
67389 		} else {
67390 			dest = DUK__ALLOCTEMP(comp_ctx);
67391 		}
67392 
67393 		DUK_ASSERT(DUK__ISREG(dest));
67394 		duk__emit_a_b_c(comp_ctx, x->op | DUK__EMIT_FLAG_BC_REGCONST, dest, arg1, arg2);
67395 
67396 		duk__ivalue_regconst(x, dest);
67397 		return;
67398 	}
67399 	case DUK_IVAL_PROP: {
67400 		/* XXX: very similar to DUK_IVAL_ARITH - merge? */
67401 		duk_regconst_t arg1;
67402 		duk_regconst_t arg2;
67403 		duk_regconst_t dest;
67404 
67405 		/* Need a short reg/const, does not have to be a mutable temp. */
67406 		arg1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
67407 		arg2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
67408 
67409 		/* Pick a destination register.  If either base value or key
67410 		 * happens to be a temp value, reuse it as the destination.
67411 		 *
67412 		 * XXX: The temp must be a "mutable" one, i.e. such that no
67413 		 * other expression is using it anymore.  Here this should be
67414 		 * the case because the value of a property access expression
67415 		 * is neither the base nor the key, but the lookup result.
67416 		 */
67417 
67418 		if (forced_reg >= 0) {
67419 			dest = forced_reg;
67420 		} else if (DUK__ISREG_TEMP(comp_ctx, arg1)) {
67421 			dest = arg1;
67422 		} else if (DUK__ISREG_TEMP(comp_ctx, arg2)) {
67423 			dest = arg2;
67424 		} else {
67425 			dest = DUK__ALLOCTEMP(comp_ctx);
67426 		}
67427 
67428 		duk__emit_a_b_c(comp_ctx,
67429 		                DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST,
67430 		                dest,
67431 		                arg1,
67432 		                arg2);
67433 
67434 		duk__ivalue_regconst(x, dest);
67435 		return;
67436 	}
67437 	case DUK_IVAL_VAR: {
67438 		/* x1 must be a string */
67439 		duk_regconst_t dest;
67440 		duk_regconst_t reg_varbind;
67441 		duk_regconst_t rc_varname;
67442 
67443 		DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
67444 
67445 		duk_dup(thr, x->x1.valstack_idx);
67446 		if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
67447 			duk__ivalue_regconst(x, reg_varbind);
67448 		} else {
67449 			dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
67450 			duk__emit_a_bc(comp_ctx, DUK_OP_GETVAR, dest, rc_varname);
67451 			duk__ivalue_regconst(x, dest);
67452 		}
67453 		return;
67454 	}
67455 	case DUK_IVAL_NONE:
67456 	default: {
67457 		DUK_D(DUK_DPRINT("invalid ivalue type: %ld", (long) x->t));
67458 		break;
67459 	}
67460 	}
67461 
67462 	DUK_ERROR_INTERNAL(thr);
67463 	DUK_WO_NORETURN(return;);
67464 }
67465 
67466 /* evaluate to plain value, no forced register (temp/bound reg both ok) */
67467 DUK_LOCAL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
67468 	duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
67469 }
67470 
67471 /* evaluate to final form (e.g. coerce GETPROP to code), throw away temp */
67472 DUK_LOCAL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
67473 	duk_regconst_t temp;
67474 
67475 	/* If duk__ivalue_toplain_raw() allocates a temp, forget it and
67476 	 * restore next temp state.
67477 	 */
67478 	temp = DUK__GETTEMP(comp_ctx);
67479 	duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
67480 	DUK__SETTEMP(comp_ctx, temp);
67481 }
67482 
67483 /* Coerce an duk_ivalue to a register or constant; result register may
67484  * be a temp or a bound register.
67485  *
67486  * The duk_ivalue argument ('x') is converted into a regconst as a
67487  * side effect.
67488  */
67489 DUK_LOCAL
67490 duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
67491                                           duk_ivalue *x,
67492                                           duk_regconst_t forced_reg,
67493                                           duk_small_uint_t flags) {
67494 	duk_hthread *thr = comp_ctx->thr;
67495 	duk_regconst_t reg;
67496 	DUK_UNREF(thr);
67497 
67498 	DUK_DDD(DUK_DDDPRINT("duk__ivalue_toregconst_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
67499 	                     "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
67500 	                     (long) x->t, (long) x->op,
67501 	                     (long) x->x1.t, (long) x->x1.regconst,
67502 	                     (duk_tval *) duk_get_tval(thr, x->x1.valstack_idx),
67503 	                     (long) x->x2.t, (long) x->x2.regconst,
67504 	                     (duk_tval *) duk_get_tval(thr, x->x2.valstack_idx),
67505 	                     (long) forced_reg,
67506 	                     (unsigned long) flags,
67507 	                     (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
67508 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
67509 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));
67510 
67511 	/* first coerce to a plain value */
67512 	duk__ivalue_toplain_raw(comp_ctx, x, forced_reg);
67513 	DUK_ASSERT(x->t == DUK_IVAL_PLAIN);
67514 
67515 	/* then to a register */
67516 	reg = duk__ispec_toregconst_raw(comp_ctx, &x->x1, forced_reg, flags);
67517 	duk__ivalue_regconst(x, reg);
67518 
67519 	return reg;
67520 }
67521 
67522 DUK_LOCAL duk_regconst_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
67523 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, 0 /*flags*/);
67524 }
67525 
67526 #if 0  /* unused */
67527 DUK_LOCAL duk_regconst_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
67528 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
67529 }
67530 #endif
67531 
67532 DUK_LOCAL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg) {
67533 	DUK_ASSERT(forced_reg >= 0);
67534 	(void) duk__ivalue_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
67535 }
67536 
67537 DUK_LOCAL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
67538 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
67539 }
67540 
67541 DUK_LOCAL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
67542 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
67543 }
67544 
67545 /* The issues below can be solved with better flags */
67546 
67547 /* XXX: many operations actually want toforcedtemp() -- brand new temp? */
67548 /* XXX: need a toplain_ignore() which will only coerce a value to a temp
67549  * register if it might have a side effect.  Side-effect free values do not
67550  * need to be coerced.
67551  */
67552 
67553 /*
67554  *  Identifier handling
67555  */
67556 
67557 DUK_LOCAL duk_regconst_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx) {
67558 	duk_hthread *thr = comp_ctx->thr;
67559 	duk_hstring *h_varname;
67560 	duk_regconst_t ret;
67561 
67562 	DUK_DDD(DUK_DDDPRINT("resolving identifier reference to '%!T'",
67563 	                     (duk_tval *) duk_get_tval(thr, -1)));
67564 
67565 	/*
67566 	 *  Special name handling
67567 	 */
67568 
67569 	h_varname = duk_known_hstring(thr, -1);
67570 
67571 	if (h_varname == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)) {
67572 		DUK_DDD(DUK_DDDPRINT("flagging function as accessing 'arguments'"));
67573 		comp_ctx->curr_func.id_access_arguments = 1;
67574 	}
67575 
67576 	/*
67577 	 *  Inside one or more 'with' statements fall back to slow path always.
67578 	 *  (See e.g. test-stmt-with.js.)
67579 	 */
67580 
67581 	if (comp_ctx->curr_func.with_depth > 0) {
67582 		DUK_DDD(DUK_DDDPRINT("identifier lookup inside a 'with' -> fall back to slow path"));
67583 		goto slow_path_own;
67584 	}
67585 
67586 	/*
67587 	 *  Any catch bindings ("catch (e)") also affect identifier binding.
67588 	 *
67589 	 *  Currently, the varmap is modified for the duration of the catch
67590 	 *  clause to ensure any identifier accesses with the catch variable
67591 	 *  name will use slow path.
67592 	 */
67593 
67594 	duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
67595 	if (duk_is_number(thr, -1)) {
67596 		ret = duk_to_int(thr, -1);
67597 		duk_pop(thr);
67598 	} else {
67599 		duk_pop(thr);
67600 		if (comp_ctx->curr_func.catch_depth > 0 || comp_ctx->curr_func.with_depth > 0) {
67601 			DUK_DDD(DUK_DDDPRINT("slow path access from inside a try-catch or with needs _Varmap"));
67602 			goto slow_path_own;
67603 		} else {
67604 			/* In this case we're doing a variable lookup that doesn't
67605 			 * match our own variables, so _Varmap won't be needed at
67606 			 * run time.
67607 			 */
67608 			DUK_DDD(DUK_DDDPRINT("slow path access outside of try-catch and with, no need for _Varmap"));
67609 			goto slow_path_notown;
67610 		}
67611 	}
67612 
67613 	DUK_DDD(DUK_DDDPRINT("identifier lookup -> reg %ld", (long) ret));
67614 	return ret;
67615 
67616  slow_path_notown:
67617 	DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path, not own variable"));
67618 
67619 	comp_ctx->curr_func.id_access_slow = 1;
67620 	return (duk_regconst_t) -1;
67621 
67622  slow_path_own:
67623 	DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path, may be own variable"));
67624 
67625 	comp_ctx->curr_func.id_access_slow = 1;
67626 	comp_ctx->curr_func.id_access_slow_own = 1;
67627 	return (duk_regconst_t) -1;
67628 }
67629 
67630 /* Lookup an identifier name in the current varmap, indicating whether the
67631  * identifier is register-bound and if not, allocating a constant for the
67632  * identifier name.  Returns 1 if register-bound, 0 otherwise.  Caller can
67633  * also check (out_reg_varbind >= 0) to check whether or not identifier is
67634  * register bound.  The caller must NOT use out_rc_varname at all unless
67635  * return code is 0 or out_reg_varbind is < 0; this is becuase out_rc_varname
67636  * is unsigned and doesn't have a "unused" / none value.
67637  */
67638 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) {
67639 	duk_hthread *thr = comp_ctx->thr;
67640 	duk_regconst_t reg_varbind;
67641 	duk_regconst_t rc_varname;
67642 
67643 	/* [ ... varname ] */
67644 
67645 	duk_dup_top(thr);
67646 	reg_varbind = duk__lookup_active_register_binding(comp_ctx);
67647 
67648 	if (reg_varbind >= 0) {
67649 		*out_reg_varbind = reg_varbind;
67650 		*out_rc_varname = 0;  /* duk_regconst_t is unsigned, so use 0 as dummy value (ignored by caller) */
67651 		duk_pop(thr);
67652 		return 1;
67653 	} else {
67654 		rc_varname = duk__getconst(comp_ctx);
67655 		*out_reg_varbind = -1;
67656 		*out_rc_varname = rc_varname;
67657 		return 0;
67658 	}
67659 }
67660 
67661 /*
67662  *  Label handling
67663  *
67664  *  Labels are initially added with flags prohibiting both break and continue.
67665  *  When the statement type is finally uncovered (after potentially multiple
67666  *  labels), all the labels are updated to allow/prohibit break and continue.
67667  */
67668 
67669 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) {
67670 	duk_hthread *thr = comp_ctx->thr;
67671 	duk_size_t n;
67672 	duk_size_t new_size;
67673 	duk_uint8_t *p;
67674 	duk_labelinfo *li_start, *li;
67675 
67676 	/* Duplicate (shadowing) labels are not allowed, except for the empty
67677 	 * labels (which are used as default labels for switch and iteration
67678 	 * statements).
67679 	 *
67680 	 * We could also allow shadowing of non-empty pending labels without any
67681 	 * other issues than breaking the required label shadowing requirements
67682 	 * of the E5 specification, see Section 12.12.
67683 	 */
67684 
67685 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
67686 	li_start = (duk_labelinfo *) (void *) p;
67687 	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
67688 	n = (duk_size_t) (li - li_start);
67689 
67690 	while (li > li_start) {
67691 		li--;
67692 
67693 		if (li->h_label == h_label && h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
67694 			DUK_ERROR_SYNTAX(thr, DUK_STR_DUPLICATE_LABEL);
67695 			DUK_WO_NORETURN(return;);
67696 		}
67697 	}
67698 
67699 	duk_push_hstring(thr, h_label);
67700 	DUK_ASSERT(n <= DUK_UARRIDX_MAX);  /* label limits */
67701 	(void) duk_put_prop_index(thr, comp_ctx->curr_func.labelnames_idx, (duk_uarridx_t) n);
67702 
67703 	new_size = (n + 1) * sizeof(duk_labelinfo);
67704 	duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size);
67705 	/* XXX: slack handling, slow now */
67706 
67707 	/* relookup after possible realloc */
67708 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
67709 	li_start = (duk_labelinfo *) (void *) p;
67710 	DUK_UNREF(li_start);  /* silence scan-build warning */
67711 	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
67712 	li--;
67713 
67714 	/* Labels can be used for iteration statements but also for other statements,
67715 	 * in particular a label can be used for a block statement.  All cases of a
67716 	 * named label accept a 'break' so that flag is set here.  Iteration statements
67717 	 * also allow 'continue', so that flag is updated when we figure out the
67718 	 * statement type.
67719 	 */
67720 
67721 	li->flags = DUK_LABEL_FLAG_ALLOW_BREAK;
67722 	li->label_id = label_id;
67723 	li->h_label = h_label;
67724 	li->catch_depth = comp_ctx->curr_func.catch_depth;   /* catch depth from current func */
67725 	li->pc_label = pc_label;
67726 
67727 	DUK_DDD(DUK_DDDPRINT("registered label: flags=0x%08lx, id=%ld, name=%!O, catch_depth=%ld, pc_label=%ld",
67728 	                     (unsigned long) li->flags, (long) li->label_id, (duk_heaphdr *) li->h_label,
67729 	                     (long) li->catch_depth, (long) li->pc_label));
67730 }
67731 
67732 /* Update all labels with matching label_id. */
67733 DUK_LOCAL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags) {
67734 	duk_uint8_t *p;
67735 	duk_labelinfo *li_start, *li;
67736 
67737 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(comp_ctx->thr->heap, comp_ctx->curr_func.h_labelinfos);
67738 	li_start = (duk_labelinfo *) (void *) p;
67739 	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
67740 
67741 	/* Match labels starting from latest; once label_id no longer matches, we can
67742 	 * safely exit without checking the rest of the labels (only the topmost labels
67743 	 * are ever updated).
67744 	 */
67745 	while (li > li_start) {
67746 		li--;
67747 
67748 		if (li->label_id != label_id) {
67749 			break;
67750 		}
67751 
67752 		DUK_DDD(DUK_DDDPRINT("updating (overwriting) label flags for li=%p, label_id=%ld, flags=%ld",
67753 		                     (void *) li, (long) label_id, (long) flags));
67754 
67755 		li->flags = flags;
67756 	}
67757 }
67758 
67759 /* Lookup active label information.  Break/continue distinction is necessary to handle switch
67760  * statement related labels correctly: a switch will only catch a 'break', not a 'continue'.
67761  *
67762  * An explicit label cannot appear multiple times in the active set, but empty labels (unlabelled
67763  * iteration and switch statements) can.  A break will match the closest unlabelled or labelled
67764  * statement.  A continue will match the closest unlabelled or labelled iteration statement.  It is
67765  * a syntax error if a continue matches a labelled switch statement; because an explicit label cannot
67766  * be duplicated, the continue cannot match any valid label outside the switch.
67767  *
67768  * A side effect of these rules is that a LABEL statement related to a switch should never actually
67769  * catch a continue abrupt completion at run-time.  Hence an INVALID opcode can be placed in the
67770  * continue slot of the switch's LABEL statement.
67771  */
67772 
67773 /* XXX: awkward, especially the bunch of separate output values -> output struct? */
67774 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) {
67775 	duk_hthread *thr = comp_ctx->thr;
67776 	duk_uint8_t *p;
67777 	duk_labelinfo *li_start, *li_end, *li;
67778 	duk_bool_t match = 0;
67779 
67780 	DUK_DDD(DUK_DDDPRINT("looking up active label: label='%!O', is_break=%ld",
67781 	                     (duk_heaphdr *) h_label, (long) is_break));
67782 
67783 	DUK_UNREF(thr);
67784 
67785 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
67786 	li_start = (duk_labelinfo *) (void *) p;
67787 	li_end = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
67788 	li = li_end;
67789 
67790 	/* Match labels starting from latest label because there can be duplicate empty
67791 	 * labels in the label set.
67792 	 */
67793 	while (li > li_start) {
67794 		li--;
67795 
67796 		if (li->h_label != h_label) {
67797 			DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] ->'%!O' != %!O",
67798 			                     (long) (li - li_start),
67799 			                     (duk_heaphdr *) li->h_label,
67800 			                     (duk_heaphdr *) h_label));
67801 			continue;
67802 		}
67803 
67804 		DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] -> '%!O' label name matches (still need to check type)",
67805 		                     (long) (li - li_start), (duk_heaphdr *) h_label));
67806 
67807 		/* currently all labels accept a break, so no explicit check for it now */
67808 		DUK_ASSERT(li->flags & DUK_LABEL_FLAG_ALLOW_BREAK);
67809 
67810 		if (is_break) {
67811 			/* break matches always */
67812 			match = 1;
67813 			break;
67814 		} else if (li->flags & DUK_LABEL_FLAG_ALLOW_CONTINUE) {
67815 			/* iteration statements allow continue */
67816 			match = 1;
67817 			break;
67818 		} else {
67819 			/* continue matched this label -- we can only continue if this is the empty
67820 			 * label, for which duplication is allowed, and thus there is hope of
67821 			 * finding a match deeper in the label stack.
67822 			 */
67823 			if (h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
67824 				DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL);
67825 				DUK_WO_NORETURN(return;);
67826 			} else {
67827 				DUK_DDD(DUK_DDDPRINT("continue matched an empty label which does not "
67828 				                     "allow a continue -> continue lookup deeper in label stack"));
67829 			}
67830 		}
67831 	}
67832 	/* XXX: match flag is awkward, rework */
67833 	if (!match) {
67834 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL);
67835 		DUK_WO_NORETURN(return;);
67836 	}
67837 
67838 	DUK_DDD(DUK_DDDPRINT("label match: %!O -> label_id %ld, catch_depth=%ld, pc_label=%ld",
67839 	                     (duk_heaphdr *) h_label, (long) li->label_id,
67840 	                     (long) li->catch_depth, (long) li->pc_label));
67841 
67842 	*out_label_id = li->label_id;
67843 	*out_label_catch_depth = li->catch_depth;
67844 	*out_label_pc = li->pc_label;
67845 	*out_is_closest = (li == li_end - 1);
67846 }
67847 
67848 DUK_LOCAL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_size_t len) {
67849 	duk_hthread *thr = comp_ctx->thr;
67850 
67851 	duk_set_length(thr, comp_ctx->curr_func.labelnames_idx, len);
67852 	duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, sizeof(duk_labelinfo) * len);
67853 }
67854 
67855 /*
67856  *  Expression parsing: duk__expr_nud(), duk__expr_led(), duk__expr_lbp(), and helpers.
67857  *
67858  *  - duk__expr_nud(): ("null denotation"): process prev_token as a "start" of an expression (e.g. literal)
67859  *  - duk__expr_led(): ("left denotation"): process prev_token in the "middle" of an expression (e.g. operator)
67860  *  - duk__expr_lbp(): ("left-binding power"): return left-binding power of curr_token
67861  */
67862 
67863 /* object literal key tracking flags */
67864 #define DUK__OBJ_LIT_KEY_PLAIN  (1 << 0)  /* key encountered as a plain property */
67865 #define DUK__OBJ_LIT_KEY_GET    (1 << 1)  /* key encountered as a getter */
67866 #define DUK__OBJ_LIT_KEY_SET    (1 << 2)  /* key encountered as a setter */
67867 
67868 DUK_LOCAL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
67869 	duk_hthread *thr = comp_ctx->thr;
67870 	duk_regconst_t reg_obj;                 /* result reg */
67871 	duk_regconst_t reg_temp;                /* temp reg */
67872 	duk_regconst_t temp_start;              /* temp reg value for start of loop */
67873 	duk_small_uint_t max_init_values;  /* max # of values initialized in one MPUTARR set */
67874 	duk_small_uint_t num_values;       /* number of values in current MPUTARR set */
67875 	duk_uarridx_t curr_idx;            /* current (next) array index */
67876 	duk_uarridx_t start_idx;           /* start array index of current MPUTARR set */
67877 	duk_uarridx_t init_idx;            /* last array index explicitly initialized, +1 */
67878 	duk_bool_t require_comma;          /* next loop requires a comma */
67879 #if !defined(DUK_USE_PREFER_SIZE)
67880 	duk_int_t pc_newarr;
67881 	duk_compiler_instr *instr;
67882 #endif
67883 
67884 	/* DUK_TOK_LBRACKET already eaten, current token is right after that */
67885 	DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LBRACKET);
67886 
67887 	max_init_values = DUK__MAX_ARRAY_INIT_VALUES;  /* XXX: depend on available temps? */
67888 
67889 	reg_obj = DUK__ALLOCTEMP(comp_ctx);
67890 #if !defined(DUK_USE_PREFER_SIZE)
67891 	pc_newarr = duk__get_current_pc(comp_ctx);
67892 #endif
67893 	duk__emit_bc(comp_ctx, DUK_OP_NEWARR, reg_obj);  /* XXX: patch initial size hint afterwards? */
67894 	temp_start = DUK__GETTEMP(comp_ctx);
67895 
67896 	/*
67897 	 *  Emit initializers in sets of maximum max_init_values.
67898 	 *  Corner cases such as single value initializers do not have
67899 	 *  special handling now.
67900 	 *
67901 	 *  Elided elements must not be emitted as 'undefined' values,
67902 	 *  because such values would be enumerable (which is incorrect).
67903 	 *  Also note that trailing elisions must be reflected in the
67904 	 *  length of the final array but cause no elements to be actually
67905 	 *  inserted.
67906 	 */
67907 
67908 	curr_idx = 0;
67909 	init_idx = 0;         /* tracks maximum initialized index + 1 */
67910 	start_idx = 0;
67911 	require_comma = 0;
67912 
67913 	for (;;) {
67914 		num_values = 0;
67915 		DUK__SETTEMP(comp_ctx, temp_start);
67916 
67917 		if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
67918 			break;
67919 		}
67920 
67921 		for (;;) {
67922 			if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
67923 				/* the outer loop will recheck and exit */
67924 				break;
67925 			}
67926 
67927 			/* comma check */
67928 			if (require_comma) {
67929 				if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
67930 					/* comma after a value, expected */
67931 					duk__advance(comp_ctx);
67932 					require_comma = 0;
67933 					continue;
67934 				} else {
67935 					goto syntax_error;
67936 				}
67937 			} else {
67938 				if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
67939 					/* elision - flush */
67940 					curr_idx++;
67941 					duk__advance(comp_ctx);
67942 					/* if num_values > 0, MPUTARR emitted by outer loop after break */
67943 					break;
67944 				}
67945 			}
67946 			/* else an array initializer element */
67947 
67948 			/* initial index */
67949 			if (num_values == 0) {
67950 				start_idx = curr_idx;
67951 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
67952 				duk__emit_load_int32(comp_ctx, reg_temp, (duk_int32_t) start_idx);
67953 			}
67954 
67955 			reg_temp = DUK__ALLOCTEMP(comp_ctx);   /* alloc temp just in case, to update max temp */
67956 			DUK__SETTEMP(comp_ctx, reg_temp);
67957 			duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);
67958 			DUK__SETTEMP(comp_ctx, reg_temp + 1);
67959 
67960 			num_values++;
67961 			curr_idx++;
67962 			require_comma = 1;
67963 
67964 			if (num_values >= max_init_values) {
67965 				/* MPUTARR emitted by outer loop */
67966 				break;
67967 			}
67968 		}
67969 
67970 		if (num_values > 0) {
67971 			/* - A is a source register (it's not a write target, but used
67972 			 *   to identify the target object) but can be shuffled.
67973 			 * - B cannot be shuffled normally because it identifies a range
67974 			 *   of registers, the emitter has special handling for this
67975 			 *   (the "no shuffle" flag must not be set).
67976 			 * - C is a non-register number and cannot be shuffled, but
67977 			 *   never needs to be.
67978 			 */
67979 			duk__emit_a_b_c(comp_ctx,
67980 			                DUK_OP_MPUTARR |
67981 			                    DUK__EMIT_FLAG_NO_SHUFFLE_C |
67982 			                    DUK__EMIT_FLAG_A_IS_SOURCE,
67983 			                reg_obj,
67984 			                temp_start,
67985 			                (duk_regconst_t) (num_values + 1));
67986 			init_idx = start_idx + num_values;
67987 
67988 			/* num_values and temp_start reset at top of outer loop */
67989 		}
67990 	}
67991 
67992 	/* Update initil size for NEWARR, doesn't need to be exact and is
67993 	 * capped at A field limit.
67994 	 */
67995 #if !defined(DUK_USE_PREFER_SIZE)
67996 	instr = duk__get_instr_ptr(comp_ctx, pc_newarr);
67997 	instr->ins |= DUK_ENC_OP_A(0, curr_idx > DUK_BC_A_MAX ? DUK_BC_A_MAX : curr_idx);
67998 #endif
67999 
68000 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RBRACKET);
68001 	duk__advance(comp_ctx);
68002 
68003 	DUK_DDD(DUK_DDDPRINT("array literal done, curridx=%ld, initidx=%ld",
68004 	                     (long) curr_idx, (long) init_idx));
68005 
68006 	/* trailing elisions? */
68007 	if (curr_idx > init_idx) {
68008 		/* yes, must set array length explicitly */
68009 		DUK_DDD(DUK_DDDPRINT("array literal has trailing elisions which affect its length"));
68010 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
68011 		duk__emit_load_int32(comp_ctx, reg_temp, (duk_int_t) curr_idx);
68012 		duk__emit_a_bc(comp_ctx,
68013 		               DUK_OP_SETALEN | DUK__EMIT_FLAG_A_IS_SOURCE,
68014 		               reg_obj,
68015 		               reg_temp);
68016 	}
68017 
68018 	DUK__SETTEMP(comp_ctx, temp_start);
68019 
68020 	duk__ivalue_regconst(res, reg_obj);
68021 	return;
68022 
68023  syntax_error:
68024 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARRAY_LITERAL);
68025 	DUK_WO_NORETURN(return;);
68026 }
68027 
68028 typedef struct {
68029 	duk_regconst_t reg_obj;
68030 	duk_regconst_t temp_start;
68031 	duk_small_uint_t num_pairs;
68032 	duk_small_uint_t num_total_pairs;
68033 } duk__objlit_state;
68034 
68035 DUK_LOCAL void duk__objlit_flush_keys(duk_compiler_ctx *comp_ctx, duk__objlit_state *st) {
68036 	if (st->num_pairs > 0) {
68037 		/* - A is a source register (it's not a write target, but used
68038 		 *   to identify the target object) but can be shuffled.
68039 		 * - B cannot be shuffled normally because it identifies a range
68040 		 *   of registers, the emitter has special handling for this
68041 		 *   (the "no shuffle" flag must not be set).
68042 		 * - C is a non-register number and cannot be shuffled, but
68043 		 *   never needs to be.
68044 		 */
68045 		DUK_ASSERT(st->num_pairs > 0);
68046 		duk__emit_a_b_c(comp_ctx,
68047 		                DUK_OP_MPUTOBJ |
68048 		                    DUK__EMIT_FLAG_NO_SHUFFLE_C |
68049 		                    DUK__EMIT_FLAG_A_IS_SOURCE,
68050 		                st->reg_obj,
68051 		                st->temp_start,
68052 		                (duk_regconst_t) (st->num_pairs * 2));
68053 		st->num_total_pairs += st->num_pairs;
68054 		st->num_pairs = 0;
68055 	}
68056 	DUK__SETTEMP(comp_ctx, st->temp_start);
68057 }
68058 
68059 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) {
68060 	if (tok->t_nores == DUK_TOK_IDENTIFIER || tok->t_nores == DUK_TOK_STRING) {
68061 		/* same handling for identifiers and strings */
68062 		DUK_ASSERT(tok->str1 != NULL);
68063 		duk_push_hstring(comp_ctx->thr, tok->str1);
68064 	} else if (tok->t == DUK_TOK_NUMBER) {
68065 		/* numbers can be loaded as numbers and coerced on the fly */
68066 		duk_push_number(comp_ctx->thr, tok->num);
68067 	} else {
68068 		return 1;  /* error */
68069 	}
68070 
68071 	duk__ivalue_plain_fromstack(comp_ctx, res);
68072 	DUK__SETTEMP(comp_ctx, reg_temp + 1);
68073 	duk__ivalue_toforcedreg(comp_ctx, res, reg_temp);
68074 	DUK__SETTEMP(comp_ctx, reg_temp + 1);
68075 	return 0;
68076 }
68077 
68078 DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
68079 	duk_hthread *thr = comp_ctx->thr;
68080 	duk__objlit_state st;
68081 	duk_regconst_t reg_temp;          /* temp reg */
68082 	duk_small_uint_t max_init_pairs;  /* max # of key-value pairs initialized in one MPUTOBJ set */
68083 	duk_bool_t first;                 /* first value: comma must not precede the value */
68084 	duk_bool_t is_set, is_get;        /* temps */
68085 #if !defined(DUK_USE_PREFER_SIZE)
68086 	duk_int_t pc_newobj;
68087 	duk_compiler_instr *instr;
68088 #endif
68089 
68090 	DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LCURLY);
68091 
68092 	max_init_pairs = DUK__MAX_OBJECT_INIT_PAIRS;  /* XXX: depend on available temps? */
68093 
68094 	st.reg_obj = DUK__ALLOCTEMP(comp_ctx);    /* target object */
68095 	st.temp_start = DUK__GETTEMP(comp_ctx);   /* start of MPUTOBJ argument list */
68096 	st.num_pairs = 0;                         /* number of key/value pairs emitted for current MPUTOBJ set */
68097 	st.num_total_pairs = 0;                   /* number of key/value pairs emitted overall */
68098 
68099 #if !defined(DUK_USE_PREFER_SIZE)
68100 	pc_newobj = duk__get_current_pc(comp_ctx);
68101 #endif
68102 	duk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, st.reg_obj);
68103 
68104 	/*
68105 	 *  Emit initializers in sets of maximum max_init_pairs keys.
68106 	 *  Setter/getter is handled separately and terminates the
68107 	 *  current set of initializer values.  Corner cases such as
68108 	 *  single value initializers do not have special handling now.
68109 	 */
68110 
68111 	first = 1;
68112 	for (;;) {
68113 		/*
68114 		 *  ES5 and ES2015+ provide a lot of different PropertyDefinition
68115 		 *  formats, see http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer.
68116 		 *
68117 		 *  PropertyName can be IdentifierName (includes reserved words), a string
68118 		 *  literal, or a number literal.  Note that IdentifierName allows 'get' and
68119 		 *  'set' too, so we need to look ahead to the next token to distinguish:
68120 		 *
68121 		 *     { get : 1 }
68122 		 *
68123 		 *  and
68124 		 *
68125 		 *     { get foo() { return 1 } }
68126 		 *     { get get() { return 1 } }    // 'get' as getter propertyname
68127 		 *
68128 		 *  Finally, a trailing comma is allowed.
68129 		 *
68130 		 *  Key name is coerced to string at compile time (and ends up as a
68131 		 *  a string constant) even for numeric keys (e.g. "{1:'foo'}").
68132 		 *  These could be emitted using e.g. LDINT, but that seems hardly
68133 		 *  worth the effort and would increase code size.
68134 		 */
68135 
68136 		DUK_DDD(DUK_DDDPRINT("object literal loop, curr_token->t = %ld",
68137 		                     (long) comp_ctx->curr_token.t));
68138 
68139 		if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
68140 			break;
68141 		}
68142 
68143 		if (first) {
68144 			first = 0;
68145 		} else {
68146 			if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
68147 				goto syntax_error;
68148 			}
68149 			duk__advance(comp_ctx);
68150 			if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
68151 				/* trailing comma followed by rcurly */
68152 				break;
68153 			}
68154 		}
68155 
68156 		/* Advance to get one step of lookup. */
68157 		duk__advance(comp_ctx);
68158 
68159 		/* Flush current MPUTOBJ if enough many pairs gathered. */
68160 		if (st.num_pairs >= max_init_pairs) {
68161 			duk__objlit_flush_keys(comp_ctx, &st);
68162 			DUK_ASSERT(st.num_pairs == 0);
68163 		}
68164 
68165 		/* Reset temp register state and reserve reg_temp and
68166 		 * reg_temp + 1 for handling the current property.
68167 		 */
68168 		DUK__SETTEMP(comp_ctx, st.temp_start + 2 * (duk_regconst_t) st.num_pairs);
68169 		reg_temp = DUK__ALLOCTEMPS(comp_ctx, 2);
68170 
68171 		/* NOTE: "get" and "set" are not officially ReservedWords and the lexer
68172 		 * currently treats them always like ordinary identifiers (DUK_TOK_GET
68173 		 * and DUK_TOK_SET are unused).  They need to be detected based on the
68174 		 * identifier string content.
68175 		 */
68176 
68177 		is_get = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
68178 		          comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_GET(thr));
68179 		is_set = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
68180 		          comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_SET(thr));
68181 		if ((is_get || is_set) && comp_ctx->curr_token.t != DUK_TOK_COLON) {
68182 			/* getter/setter */
68183 			duk_int_t fnum;
68184 
68185 			duk__objlit_flush_keys(comp_ctx, &st);
68186 			DUK_ASSERT(DUK__GETTEMP(comp_ctx) == st.temp_start);  /* 2 regs are guaranteed to be allocated w.r.t. temp_max */
68187 			reg_temp = DUK__ALLOCTEMPS(comp_ctx, 2);
68188 
68189 			if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->curr_token, reg_temp) != 0) {
68190 				goto syntax_error;
68191 			}
68192 
68193 			/* curr_token = get/set name */
68194 			fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_GETSET);
68195 
68196 			duk__emit_a_bc(comp_ctx,
68197 			               DUK_OP_CLOSURE,
68198 			               st.temp_start + 1,
68199 			               (duk_regconst_t) fnum);
68200 
68201 			/* Slot C is used in a non-standard fashion (range of regs),
68202 			 * emitter code has special handling for it (must not set the
68203 			 * "no shuffle" flag).
68204 			 */
68205 			duk__emit_a_bc(comp_ctx,
68206 			              (is_get ? DUK_OP_INITGET : DUK_OP_INITSET) | DUK__EMIT_FLAG_A_IS_SOURCE,
68207 			              st.reg_obj,
68208 			              st.temp_start);   /* temp_start+0 = key, temp_start+1 = closure */
68209 
68210 			DUK_ASSERT(st.num_pairs == 0);  /* temp state is reset on next loop */
68211 #if defined(DUK_USE_ES6)
68212 		} else if (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
68213 		           (comp_ctx->curr_token.t == DUK_TOK_COMMA || comp_ctx->curr_token.t == DUK_TOK_RCURLY)) {
68214 			duk_bool_t load_rc;
68215 
68216 			load_rc = duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp);
68217 			DUK_UNREF(load_rc);
68218 			DUK_ASSERT(load_rc == 0);  /* always succeeds because token is identifier */
68219 
68220 			duk__ivalue_var_hstring(comp_ctx, res, comp_ctx->prev_token.str1);
68221 			DUK_ASSERT(DUK__GETTEMP(comp_ctx) == reg_temp + 1);
68222 			duk__ivalue_toforcedreg(comp_ctx, res, reg_temp + 1);
68223 
68224 			st.num_pairs++;
68225 		} else if ((comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER ||
68226 		            comp_ctx->prev_token.t == DUK_TOK_STRING ||
68227 		            comp_ctx->prev_token.t == DUK_TOK_NUMBER) &&
68228 		           comp_ctx->curr_token.t == DUK_TOK_LPAREN) {
68229 			duk_int_t fnum;
68230 
68231 			/* Parsing-wise there's a small hickup here: the token parsing
68232 			 * state is one step too advanced for the function parse helper
68233 			 * compared to other cases.  The current solution is an extra
68234 			 * flag to indicate whether function parsing should use the
68235 			 * current or the previous token to starting parsing from.
68236 			 */
68237 
68238 			if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp) != 0) {
68239 				goto syntax_error;
68240 			}
68241 
68242 			fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_USE_PREVTOKEN | DUK__FUNC_FLAG_METDEF);
68243 
68244 			duk__emit_a_bc(comp_ctx,
68245 			               DUK_OP_CLOSURE,
68246 			               reg_temp + 1,
68247 			               (duk_regconst_t) fnum);
68248 
68249 			st.num_pairs++;
68250 #endif  /* DUK_USE_ES6 */
68251 		} else {
68252 #if defined(DUK_USE_ES6)
68253 			if (comp_ctx->prev_token.t == DUK_TOK_LBRACKET) {
68254 				/* ES2015 computed property name.  Executor ToPropertyKey()
68255 				 * coerces the key at runtime.
68256 				 */
68257 				DUK__SETTEMP(comp_ctx, reg_temp);
68258 				duk__expr_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR, reg_temp);
68259 				duk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);
68260 
68261 				/* XXX: If next token is '(' we're dealing with
68262 				 * the method shorthand with a computed name,
68263 				 * e.g. { [Symbol.for('foo')](a,b) {} }.  This
68264 				 * form is not yet supported and causes a
68265 				 * SyntaxError on the DUK_TOK_COLON check below.
68266 				 */
68267 			}
68268 			else
68269 #endif  /* DUK_USE_ES6 */
68270 			{
68271 				if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp) != 0) {
68272 					goto syntax_error;
68273 				}
68274 			}
68275 
68276 			duk__advance_expect(comp_ctx, DUK_TOK_COLON);
68277 
68278 			DUK__SETTEMP(comp_ctx, reg_temp + 1);
68279 			duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp + 1 /*forced_reg*/);
68280 
68281 			st.num_pairs++;
68282 		}
68283 	}  /* property loop */
68284 
68285 	/* Flush remaining properties. */
68286 	duk__objlit_flush_keys(comp_ctx, &st);
68287 	DUK_ASSERT(st.num_pairs == 0);
68288 	DUK_ASSERT(DUK__GETTEMP(comp_ctx) == st.temp_start);
68289 
68290 	/* Update initial size for NEWOBJ.  The init size doesn't need to be
68291 	 * exact as the purpose is just to avoid object resizes in common
68292 	 * cases.  The size is capped to field A limit, and will be too high
68293 	 * if the object literal contains duplicate keys (this is harmless but
68294 	 * increases memory traffic if the object is compacted later on).
68295 	 */
68296 #if !defined(DUK_USE_PREFER_SIZE)
68297 	instr = duk__get_instr_ptr(comp_ctx, pc_newobj);
68298 	instr->ins |= DUK_ENC_OP_A(0, st.num_total_pairs > DUK_BC_A_MAX ? DUK_BC_A_MAX : st.num_total_pairs);
68299 #endif
68300 
68301 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
68302 	duk__advance(comp_ctx);  /* No RegExp after object literal. */
68303 
68304 	duk__ivalue_regconst(res, st.reg_obj);
68305 	return;
68306 
68307  syntax_error:
68308 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_OBJECT_LITERAL);
68309 	DUK_WO_NORETURN(return;);
68310 }
68311 
68312 /* Parse argument list.  Arguments are written to temps starting from
68313  * "next temp".  Returns number of arguments parsed.  Expects left paren
68314  * to be already eaten, and eats the right paren before returning.
68315  */
68316 DUK_LOCAL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
68317 	duk_int_t nargs = 0;
68318 	duk_regconst_t reg_temp;
68319 
68320 	/* Note: expect that caller has already eaten the left paren */
68321 
68322 	DUK_DDD(DUK_DDDPRINT("start parsing arguments, prev_token.t=%ld, curr_token.t=%ld",
68323 	                     (long) comp_ctx->prev_token.t, (long) comp_ctx->curr_token.t));
68324 
68325 	for (;;) {
68326 		if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
68327 			break;
68328 		}
68329 		if (nargs > 0) {
68330 			duk__advance_expect(comp_ctx, DUK_TOK_COMMA);
68331 		}
68332 
68333 		/* We want the argument expression value to go to "next temp"
68334 		 * without additional moves.  That should almost always be the
68335 		 * case, but we double check after expression parsing.
68336 		 *
68337 		 * This is not the cleanest possible approach.
68338 		 */
68339 
68340 		reg_temp = DUK__ALLOCTEMP(comp_ctx);  /* bump up "allocated" reg count, just in case */
68341 		DUK__SETTEMP(comp_ctx, reg_temp);
68342 
68343 		/* binding power must be high enough to NOT allow comma expressions directly */
68344 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp);  /* always allow 'in', coerce to 'tr' just in case */
68345 
68346 		DUK__SETTEMP(comp_ctx, reg_temp + 1);
68347 		nargs++;
68348 
68349 		DUK_DDD(DUK_DDDPRINT("argument #%ld written into reg %ld", (long) nargs, (long) reg_temp));
68350 	}
68351 
68352 	/* eat the right paren */
68353 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* RegExp mode does not matter. */
68354 
68355 	DUK_DDD(DUK_DDDPRINT("end parsing arguments"));
68356 
68357 	return nargs;
68358 }
68359 
68360 DUK_LOCAL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx) {
68361 	/* empty expressions can be detected conveniently with nud/led counts */
68362 	return (comp_ctx->curr_func.nud_count == 0) &&
68363 	       (comp_ctx->curr_func.led_count == 0);
68364 }
68365 
68366 DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
68367 	duk_hthread *thr = comp_ctx->thr;
68368 	duk_token *tk;
68369 	duk_regconst_t temp_at_entry;
68370 	duk_small_uint_t tok;
68371 	duk_uint32_t args;  /* temp variable to pass constants and flags to shared code */
68372 
68373 	/*
68374 	 *  ctx->prev_token     token to process with duk__expr_nud()
68375 	 *  ctx->curr_token     updated by caller
68376 	 *
68377 	 *  Note: the token in the switch below has already been eaten.
68378 	 */
68379 
68380 	temp_at_entry = DUK__GETTEMP(comp_ctx);
68381 
68382 	comp_ctx->curr_func.nud_count++;
68383 
68384 	tk = &comp_ctx->prev_token;
68385 	tok = tk->t;
68386 	res->t = DUK_IVAL_NONE;
68387 
68388 	DUK_DDD(DUK_DDDPRINT("duk__expr_nud(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
68389 	                     (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));
68390 
68391 	switch (tok) {
68392 
68393 	/* PRIMARY EXPRESSIONS */
68394 
68395 	case DUK_TOK_THIS: {
68396 		duk_regconst_t reg_temp;
68397 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
68398 		duk__emit_bc(comp_ctx,
68399 		             DUK_OP_LDTHIS,
68400 		             reg_temp);
68401 		duk__ivalue_regconst(res, reg_temp);
68402 		return;
68403 	}
68404 	case DUK_TOK_IDENTIFIER: {
68405 		duk__ivalue_var_hstring(comp_ctx, res, tk->str1);
68406 		return;
68407 	}
68408 	case DUK_TOK_NULL: {
68409 		duk_push_null(thr);
68410 		goto plain_value;
68411 	}
68412 	case DUK_TOK_TRUE: {
68413 		duk_push_true(thr);
68414 		goto plain_value;
68415 	}
68416 	case DUK_TOK_FALSE: {
68417 		duk_push_false(thr);
68418 		goto plain_value;
68419 	}
68420 	case DUK_TOK_NUMBER: {
68421 		duk_push_number(thr, tk->num);
68422 		goto plain_value;
68423 	}
68424 	case DUK_TOK_STRING: {
68425 		DUK_ASSERT(tk->str1 != NULL);
68426 		duk_push_hstring(thr, tk->str1);
68427 		goto plain_value;
68428 	}
68429 	case DUK_TOK_REGEXP: {
68430 #if defined(DUK_USE_REGEXP_SUPPORT)
68431 		duk_regconst_t reg_temp;
68432 		duk_regconst_t rc_re_bytecode;  /* const */
68433 		duk_regconst_t rc_re_source;    /* const */
68434 
68435 		DUK_ASSERT(tk->str1 != NULL);
68436 		DUK_ASSERT(tk->str2 != NULL);
68437 
68438 		DUK_DDD(DUK_DDDPRINT("emitting regexp op, str1=%!O, str2=%!O",
68439 		                     (duk_heaphdr *) tk->str1,
68440 		                     (duk_heaphdr *) tk->str2));
68441 
68442 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
68443 		duk_push_hstring(thr, tk->str1);
68444 		duk_push_hstring(thr, tk->str2);
68445 
68446 		/* [ ... pattern flags ] */
68447 
68448 		duk_regexp_compile(thr);
68449 
68450 		/* [ ... escaped_source bytecode ] */
68451 
68452 		rc_re_bytecode = duk__getconst(comp_ctx);
68453 		rc_re_source = duk__getconst(comp_ctx);
68454 
68455 		duk__emit_a_b_c(comp_ctx,
68456 		                DUK_OP_REGEXP | DUK__EMIT_FLAG_BC_REGCONST,
68457 		                reg_temp /*a*/,
68458 		                rc_re_bytecode /*b*/,
68459 		                rc_re_source /*c*/);
68460 
68461 		duk__ivalue_regconst(res, reg_temp);
68462 		return;
68463 #else  /* DUK_USE_REGEXP_SUPPORT */
68464 		goto syntax_error;
68465 #endif  /* DUK_USE_REGEXP_SUPPORT */
68466 	}
68467 	case DUK_TOK_LBRACKET: {
68468 		DUK_DDD(DUK_DDDPRINT("parsing array literal"));
68469 		duk__nud_array_literal(comp_ctx, res);
68470 		return;
68471 	}
68472 	case DUK_TOK_LCURLY: {
68473 		DUK_DDD(DUK_DDDPRINT("parsing object literal"));
68474 		duk__nud_object_literal(comp_ctx, res);
68475 		return;
68476 	}
68477 	case DUK_TOK_LPAREN: {
68478 		duk_bool_t prev_allow_in;
68479 
68480 		comp_ctx->curr_func.paren_level++;
68481 		prev_allow_in = comp_ctx->curr_func.allow_in;
68482 		comp_ctx->curr_func.allow_in = 1; /* reset 'allow_in' for parenthesized expression */
68483 
68484 		duk__expr(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression, terminates at a ')' */
68485 
68486 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* No RegExp after parenthesized expression. */
68487 		comp_ctx->curr_func.allow_in = prev_allow_in;
68488 		comp_ctx->curr_func.paren_level--;
68489 		return;
68490 	}
68491 
68492 	/* MEMBER/NEW/CALL EXPRESSIONS */
68493 
68494 	case DUK_TOK_NEW: {
68495 		/*
68496 		 *  Parsing an expression starting with 'new' is tricky because
68497 		 *  there are multiple possible productions deriving from
68498 		 *  LeftHandSideExpression which begin with 'new'.
68499 		 *
68500 		 *  We currently resort to one-token lookahead to distinguish the
68501 		 *  cases.  Hopefully this is correct.  The binding power must be
68502 		 *  such that parsing ends at an LPAREN (CallExpression) but not at
68503 		 *  a PERIOD or LBRACKET (MemberExpression).
68504 		 *
68505 		 *  See doc/compiler.rst for discussion on the parsing approach,
68506 		 *  and testcases/test-dev-new.js for a bunch of documented tests.
68507 		 */
68508 
68509 		duk_regconst_t reg_target;
68510 		duk_int_t nargs;
68511 
68512 		DUK_DDD(DUK_DDDPRINT("begin parsing new expression"));
68513 
68514 		reg_target = DUK__ALLOCTEMPS(comp_ctx, 2);
68515 
68516 #if defined(DUK_USE_ES6)
68517 		if (comp_ctx->curr_token.t == DUK_TOK_PERIOD) {
68518 			/* new.target */
68519 			DUK_DDD(DUK_DDDPRINT("new.target"));
68520 			duk__advance(comp_ctx);
68521 			if (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER ||
68522 			    !duk_hstring_equals_ascii_cstring(comp_ctx->curr_token.str1, "target")) {
68523 				goto syntax_error_newtarget;
68524 			}
68525 			if (comp_ctx->curr_func.is_global) {
68526 				goto syntax_error_newtarget;
68527 			}
68528 			duk__advance(comp_ctx);
68529 			duk__emit_bc(comp_ctx,
68530 			             DUK_OP_NEWTARGET,
68531 			             reg_target);
68532 			duk__ivalue_regconst(res, reg_target);
68533 			return;
68534 		}
68535 #endif  /* DUK_USE_ES6 */
68536 
68537 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_CALL /*rbp_flags*/, reg_target /*forced_reg*/);
68538 		duk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, reg_target + 1);  /* default instance */
68539 		DUK__SETTEMP(comp_ctx, reg_target + 2);
68540 
68541 		/* XXX: 'new obj.noSuch()' doesn't use GETPROPC now which
68542 		 * makes the error message worse than for obj.noSuch().
68543 		 */
68544 
68545 		if (comp_ctx->curr_token.t == DUK_TOK_LPAREN) {
68546 			/* 'new' MemberExpression Arguments */
68547 			DUK_DDD(DUK_DDDPRINT("new expression has argument list"));
68548 			duk__advance(comp_ctx);
68549 			nargs = duk__parse_arguments(comp_ctx, res);  /* parse args starting from "next temp", reg_target + 1 */
68550 			/* right paren eaten */
68551 		} else {
68552 			/* 'new' MemberExpression */
68553 			DUK_DDD(DUK_DDDPRINT("new expression has no argument list"));
68554 			nargs = 0;
68555 		}
68556 
68557 		duk__emit_a_bc(comp_ctx,
68558 		              DUK_OP_CALL0 | DUK_BC_CALL_FLAG_CONSTRUCT,
68559 		              nargs /*num_args*/,
68560 		              reg_target /*target*/);
68561 
68562 		DUK_DDD(DUK_DDDPRINT("end parsing new expression"));
68563 
68564 		duk__ivalue_regconst(res, reg_target);
68565 		return;
68566 	}
68567 
68568 	/* FUNCTION EXPRESSIONS */
68569 
68570 	case DUK_TOK_FUNCTION: {
68571 		/* Function expression.  Note that any statement beginning with 'function'
68572 		 * is handled by the statement parser as a function declaration, or a
68573 		 * non-standard function expression/statement (or a SyntaxError).  We only
68574 		 * handle actual function expressions (occurring inside an expression) here.
68575 		 *
68576 		 * O(depth^2) parse count for inner functions is handled by recording a
68577 		 * lexer offset on the first compilation pass, so that the function can
68578 		 * be efficiently skipped on the second pass.  This is encapsulated into
68579 		 * duk__parse_func_like_fnum().
68580 		 */
68581 
68582 		duk_regconst_t reg_temp;
68583 		duk_int_t fnum;
68584 
68585 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
68586 
68587 		/* curr_token follows 'function' */
68588 		fnum = duk__parse_func_like_fnum(comp_ctx, 0 /*flags*/);
68589 		DUK_DDD(DUK_DDDPRINT("parsed inner function -> fnum %ld", (long) fnum));
68590 
68591 		duk__emit_a_bc(comp_ctx,
68592 		               DUK_OP_CLOSURE,
68593 		               reg_temp /*a*/,
68594 		               (duk_regconst_t) fnum /*bc*/);
68595 
68596 		duk__ivalue_regconst(res, reg_temp);
68597 		return;
68598 	}
68599 
68600 	/* UNARY EXPRESSIONS */
68601 
68602 	case DUK_TOK_DELETE: {
68603 		/* Delete semantics are a bit tricky.  The description in E5 specification
68604 		 * is kind of confusing, because it distinguishes between resolvability of
68605 		 * a reference (which is only known at runtime) seemingly at compile time
68606 		 * (= SyntaxError throwing).
68607 		 */
68608 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
68609 		if (res->t == DUK_IVAL_VAR) {
68610 			/* not allowed in strict mode, regardless of whether resolves;
68611 			 * in non-strict mode DELVAR handles both non-resolving and
68612 			 * resolving cases (the specification description is a bit confusing).
68613 			 */
68614 
68615 			duk_regconst_t reg_temp;
68616 			duk_regconst_t reg_varbind;
68617 			duk_regconst_t rc_varname;
68618 
68619 			if (comp_ctx->curr_func.is_strict) {
68620 				DUK_ERROR_SYNTAX(thr, DUK_STR_CANNOT_DELETE_IDENTIFIER);
68621 				DUK_WO_NORETURN(return;);
68622 			}
68623 
68624 			DUK__SETTEMP(comp_ctx, temp_at_entry);
68625 			reg_temp = DUK__ALLOCTEMP(comp_ctx);
68626 
68627 			duk_dup(thr, res->x1.valstack_idx);
68628 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
68629 				/* register bound variables are non-configurable -> always false */
68630 				duk__emit_bc(comp_ctx,
68631 				             DUK_OP_LDFALSE,
68632 				             reg_temp);
68633 			} else {
68634 				duk_dup(thr, res->x1.valstack_idx);
68635 				rc_varname = duk__getconst(comp_ctx);
68636 				duk__emit_a_bc(comp_ctx,
68637 				               DUK_OP_DELVAR,
68638 				               reg_temp,
68639 				               rc_varname);
68640 			}
68641 			duk__ivalue_regconst(res, reg_temp);
68642 		} else if (res->t == DUK_IVAL_PROP) {
68643 			duk_regconst_t reg_temp;
68644 			duk_regconst_t reg_obj;
68645 			duk_regconst_t rc_key;
68646 
68647 			DUK__SETTEMP(comp_ctx, temp_at_entry);
68648 			reg_temp = DUK__ALLOCTEMP(comp_ctx);
68649 			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
68650 			rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
68651 			duk__emit_a_b_c(comp_ctx,
68652 			                DUK_OP_DELPROP | DUK__EMIT_FLAG_BC_REGCONST,
68653 			                reg_temp,
68654 			                reg_obj,
68655 			                rc_key);
68656 
68657 			duk__ivalue_regconst(res, reg_temp);
68658 		} else {
68659 			/* non-Reference deletion is always 'true', even in strict mode */
68660 			duk_push_true(thr);
68661 			goto plain_value;
68662 		}
68663 		return;
68664 	}
68665 	case DUK_TOK_VOID: {
68666 		duk__expr_toplain_ignore(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
68667 		duk_push_undefined(thr);
68668 		goto plain_value;
68669 	}
68670 	case DUK_TOK_TYPEOF: {
68671 		/* 'typeof' must handle unresolvable references without throwing
68672 		 * a ReferenceError (E5 Section 11.4.3).  Register mapped values
68673 		 * will never be unresolvable so special handling is only required
68674 		 * when an identifier is a "slow path" one.
68675 		 */
68676 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
68677 
68678 		if (res->t == DUK_IVAL_VAR) {
68679 			duk_regconst_t reg_varbind;
68680 			duk_regconst_t rc_varname;
68681 			duk_regconst_t reg_temp;
68682 
68683 			duk_dup(thr, res->x1.valstack_idx);
68684 			if (!duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
68685 				DUK_DDD(DUK_DDDPRINT("typeof for an identifier name which could not be resolved "
68686 				                     "at compile time, need to use special run-time handling"));
68687 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
68688 				duk__emit_a_bc(comp_ctx,
68689 				               DUK_OP_TYPEOFID,
68690 				               reg_temp,
68691 				               rc_varname);
68692 				duk__ivalue_regconst(res, reg_temp);
68693 				return;
68694 			}
68695 		}
68696 
68697 		args = DUK_OP_TYPEOF;
68698 		goto unary;
68699 	}
68700 	case DUK_TOK_INCREMENT: {
68701 		args = (DUK_OP_PREINCP << 8) + DUK_OP_PREINCR;
68702 		goto preincdec;
68703 	}
68704 	case DUK_TOK_DECREMENT: {
68705 		args = (DUK_OP_PREDECP << 8) + DUK_OP_PREDECR;
68706 		goto preincdec;
68707 	}
68708 	case DUK_TOK_ADD: {
68709 		/* unary plus */
68710 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
68711 		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
68712 		    duk_is_number(thr, res->x1.valstack_idx)) {
68713 			/* unary plus of a number is identity */
68714 			return;
68715 		}
68716 		args = DUK_OP_UNP;
68717 		goto unary;
68718 	}
68719 	case DUK_TOK_SUB: {
68720 		/* unary minus */
68721 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
68722 		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
68723 		    duk_is_number(thr, res->x1.valstack_idx)) {
68724 			/* this optimization is important to handle negative literals
68725 			 * (which are not directly provided by the lexical grammar)
68726 			 */
68727 			duk_tval *tv_num;
68728 			duk_double_union du;
68729 
68730 			tv_num = DUK_GET_TVAL_POSIDX(thr, res->x1.valstack_idx);
68731 			DUK_ASSERT(tv_num != NULL);
68732 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_num));
68733 			du.d = DUK_TVAL_GET_NUMBER(tv_num);
68734 			du.d = -du.d;
68735 			DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
68736 			DUK_TVAL_SET_NUMBER(tv_num, du.d);
68737 			return;
68738 		}
68739 		args = DUK_OP_UNM;
68740 		goto unary;
68741 	}
68742 	case DUK_TOK_BNOT: {
68743 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
68744 		args = DUK_OP_BNOT;
68745 		goto unary;
68746 	}
68747 	case DUK_TOK_LNOT: {
68748 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
68749 		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE) {
68750 			/* Very minimal inlining to handle common idioms '!0' and '!1',
68751 			 * and also boolean arguments like '!false' and '!true'.
68752 			 */
68753 			duk_tval *tv_val;
68754 
68755 			tv_val = DUK_GET_TVAL_POSIDX(thr, res->x1.valstack_idx);
68756 			DUK_ASSERT(tv_val != NULL);
68757 			if (DUK_TVAL_IS_NUMBER(tv_val)) {
68758 				duk_double_t d;
68759 				d = DUK_TVAL_GET_NUMBER(tv_val);
68760 				if (d == 0.0) {
68761 					/* Matches both +0 and -0 on purpose. */
68762 					DUK_DDD(DUK_DDDPRINT("inlined lnot: !0 -> true"));
68763 					DUK_TVAL_SET_BOOLEAN_TRUE(tv_val);
68764 					return;
68765 				} else if (d == 1.0) {
68766 					DUK_DDD(DUK_DDDPRINT("inlined lnot: !1 -> false"));
68767 					DUK_TVAL_SET_BOOLEAN_FALSE(tv_val);
68768 					return;
68769 				}
68770 			} else if (DUK_TVAL_IS_BOOLEAN(tv_val)) {
68771 				duk_small_uint_t v;
68772 				v = DUK_TVAL_GET_BOOLEAN(tv_val);
68773 				DUK_DDD(DUK_DDDPRINT("inlined lnot boolean: %ld", (long) v));
68774 				DUK_ASSERT(v == 0 || v == 1);
68775 				DUK_TVAL_SET_BOOLEAN(tv_val, v ^ 0x01);
68776 				return;
68777 			}
68778 		}
68779 		args = DUK_OP_LNOT;
68780 		goto unary;
68781 	}
68782 
68783 	}  /* end switch */
68784 
68785 	DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
68786 	DUK_WO_NORETURN(return;);
68787 
68788  unary:
68789 	{
68790 		/* Unary opcodes use just the 'BC' register source because it
68791 		 * matches current shuffle limits, and maps cleanly to 16 high
68792 		 * bits of the opcode.
68793 		 */
68794 
68795 		duk_regconst_t reg_src, reg_res;
68796 
68797 		reg_src = duk__ivalue_toregconst_raw(comp_ctx, res, -1 /*forced_reg*/, 0 /*flags*/);
68798 		if (DUK__ISREG_TEMP(comp_ctx, reg_src)) {
68799 			reg_res = reg_src;
68800 		} else {
68801 			reg_res = DUK__ALLOCTEMP(comp_ctx);
68802 		}
68803 		duk__emit_a_bc(comp_ctx,
68804 		             args,
68805 		             reg_res,
68806 		             reg_src);
68807 		duk__ivalue_regconst(res, reg_res);
68808 		return;
68809 	}
68810 
68811  preincdec:
68812 	{
68813 		/* preincrement and predecrement */
68814 		duk_regconst_t reg_res;
68815 		duk_small_uint_t args_op1 = args & 0xff;  /* DUK_OP_PREINCR/DUK_OP_PREDECR */
68816 		duk_small_uint_t args_op2 = args >> 8;    /* DUK_OP_PREINCP_RR/DUK_OP_PREDECP_RR */
68817 
68818 		/* Specific assumptions for opcode numbering. */
68819 		DUK_ASSERT(DUK_OP_PREINCR + 4 == DUK_OP_PREINCV);
68820 		DUK_ASSERT(DUK_OP_PREDECR + 4 == DUK_OP_PREDECV);
68821 
68822 		reg_res = DUK__ALLOCTEMP(comp_ctx);
68823 
68824 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
68825 		if (res->t == DUK_IVAL_VAR) {
68826 			duk_hstring *h_varname;
68827 			duk_regconst_t reg_varbind;
68828 			duk_regconst_t rc_varname;
68829 
68830 			h_varname = duk_known_hstring(thr, res->x1.valstack_idx);
68831 
68832 			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
68833 				goto syntax_error;
68834 			}
68835 
68836 			duk_dup(thr, res->x1.valstack_idx);
68837 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
68838 				duk__emit_a_bc(comp_ctx,
68839 				               args_op1,  /* e.g. DUK_OP_PREINCR */
68840 				               reg_res,
68841 				               reg_varbind);
68842 			} else {
68843 				duk__emit_a_bc(comp_ctx,
68844 				                args_op1 + 4,  /* e.g. DUK_OP_PREINCV */
68845 				                reg_res,
68846 				                rc_varname);
68847 			}
68848 
68849 			DUK_DDD(DUK_DDDPRINT("preincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
68850 			                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
68851 		} else if (res->t == DUK_IVAL_PROP) {
68852 			duk_regconst_t reg_obj;  /* allocate to reg only (not const) */
68853 			duk_regconst_t rc_key;
68854 			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
68855 			rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
68856 			duk__emit_a_b_c(comp_ctx,
68857 			                args_op2 | DUK__EMIT_FLAG_BC_REGCONST,  /* e.g. DUK_OP_PREINCP */
68858 			                reg_res,
68859 			                reg_obj,
68860 			                rc_key);
68861 		} else {
68862 			/* Technically return value is not needed because INVLHS will
68863 			 * unconditially throw a ReferenceError.  Coercion is necessary
68864 			 * for proper semantics (consider ToNumber() called for an object).
68865 			 * Use DUK_OP_UNP with a dummy register to get ToNumber().
68866 			 */
68867 
68868 			duk__ivalue_toforcedreg(comp_ctx, res, reg_res);
68869 			duk__emit_bc(comp_ctx,
68870 			             DUK_OP_UNP,
68871 			             reg_res);  /* for side effects, result ignored */
68872 			duk__emit_op_only(comp_ctx,
68873 			                  DUK_OP_INVLHS);
68874 		}
68875 		DUK__SETTEMP(comp_ctx, reg_res + 1);
68876 		duk__ivalue_regconst(res, reg_res);
68877 		return;
68878 	}
68879 
68880  plain_value:
68881 	{
68882 		/* Stack top contains plain value */
68883 		duk__ivalue_plain_fromstack(comp_ctx, res);
68884 		return;
68885 	}
68886 
68887 #if defined(DUK_USE_ES6)
68888  syntax_error_newtarget:
68889 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_NEWTARGET);
68890 	DUK_WO_NORETURN(return;);
68891 #endif
68892 
68893  syntax_error:
68894 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);
68895 	DUK_WO_NORETURN(return;);
68896 }
68897 
68898 /* XXX: add flag to indicate whether caller cares about return value; this
68899  * affects e.g. handling of assignment expressions.  This change needs API
68900  * changes elsewhere too.
68901  */
68902 DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res) {
68903 	duk_hthread *thr = comp_ctx->thr;
68904 	duk_token *tk;
68905 	duk_small_uint_t tok;
68906 	duk_uint32_t args;  /* temp variable to pass constants and flags to shared code */
68907 
68908 	/*
68909 	 *  ctx->prev_token     token to process with duk__expr_led()
68910 	 *  ctx->curr_token     updated by caller
68911 	 */
68912 
68913 	comp_ctx->curr_func.led_count++;
68914 
68915 	/* The token in the switch has already been eaten here */
68916 	tk = &comp_ctx->prev_token;
68917 	tok = tk->t;
68918 
68919 	DUK_DDD(DUK_DDDPRINT("duk__expr_led(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
68920 	                     (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));
68921 
68922 	/* XXX: default priority for infix operators is duk__expr_lbp(tok) -> get it here? */
68923 
68924 	switch (tok) {
68925 
68926 	/* PRIMARY EXPRESSIONS */
68927 
68928 	case DUK_TOK_PERIOD: {
68929 		/* Property access expressions are critical for correct LHS ordering,
68930 		 * see comments in duk__expr()!
68931 		 *
68932 		 * A conservative approach would be to use duk__ivalue_totempconst()
68933 		 * for 'left'.  However, allowing a reg-bound variable seems safe here
68934 		 * and is nice because "foo.bar" is a common expression.  If the ivalue
68935 		 * is used in an expression a GETPROP will occur before any changes to
68936 		 * the base value can occur.  If the ivalue is used as an assignment
68937 		 * LHS, the assignment code will ensure the base value is safe from
68938 		 * RHS mutation.
68939 		 */
68940 
68941 		/* XXX: This now coerces an identifier into a GETVAR to a temp, which
68942 		 * causes an extra LDREG in call setup.  It's sufficient to coerce to a
68943 		 * unary ivalue?
68944 		 */
68945 		duk__ivalue_toplain(comp_ctx, left);
68946 
68947 		/* NB: must accept reserved words as property name */
68948 		if (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER) {
68949 			DUK_ERROR_SYNTAX(thr, DUK_STR_EXPECTED_IDENTIFIER);
68950 			DUK_WO_NORETURN(return;);
68951 		}
68952 
68953 		res->t = DUK_IVAL_PROP;
68954 		duk__copy_ispec(comp_ctx, &left->x1, &res->x1);  /* left.x1 -> res.x1 */
68955 		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
68956 		duk_push_hstring(thr, comp_ctx->curr_token.str1);
68957 		duk_replace(thr, res->x2.valstack_idx);
68958 		res->x2.t = DUK_ISPEC_VALUE;
68959 
68960 		/* special RegExp literal handling after IdentifierName */
68961 		comp_ctx->curr_func.reject_regexp_in_adv = 1;
68962 
68963 		duk__advance(comp_ctx);
68964 		return;
68965 	}
68966 	case DUK_TOK_LBRACKET: {
68967 		/* Property access expressions are critical for correct LHS ordering,
68968 		 * see comments in duk__expr()!
68969 		 */
68970 
68971 		/* XXX: optimize temp reg use */
68972 		/* XXX: similar coercion issue as in DUK_TOK_PERIOD */
68973 		/* XXX: coerce to regs? it might be better for enumeration use, where the
68974 		 * same PROP ivalue is used multiple times.  Or perhaps coerce PROP further
68975 		 * there?
68976 		 */
68977 		/* XXX: for simple cases like x['y'] an unnecessary LDREG is
68978 		 * emitted for the base value; could avoid it if we knew that
68979 		 * the key expression is safe (e.g. just a single literal).
68980 		 */
68981 
68982 		/* The 'left' value must not be a register bound variable
68983 		 * because it may be mutated during the rest of the expression
68984 		 * and E5.1 Section 11.2.1 specifies the order of evaluation
68985 		 * so that the base value is evaluated first.
68986 		 * See: test-bug-nested-prop-mutate.js.
68987 		 */
68988 		duk__ivalue_totempconst(comp_ctx, left);
68989 		duk__expr_toplain(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression, ']' terminates */
68990 		duk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);
68991 
68992 		res->t = DUK_IVAL_PROP;
68993 		duk__copy_ispec(comp_ctx, &res->x1, &res->x2);   /* res.x1 -> res.x2 */
68994 		duk__copy_ispec(comp_ctx, &left->x1, &res->x1);  /* left.x1 -> res.x1 */
68995 		return;
68996 	}
68997 	case DUK_TOK_LPAREN: {
68998 		/* function call */
68999 		duk_regconst_t reg_cs = DUK__ALLOCTEMPS(comp_ctx, 2);
69000 		duk_int_t nargs;
69001 		duk_small_uint_t call_op = DUK_OP_CALL0;
69002 
69003 		/* XXX: attempt to get the call result to "next temp" whenever
69004 		 * possible to avoid unnecessary register shuffles.
69005 		 */
69006 
69007 		/*
69008 		 *  Setup call: target and 'this' binding.  Three cases:
69009 		 *
69010 		 *    1. Identifier base (e.g. "foo()")
69011 		 *    2. Property base (e.g. "foo.bar()")
69012 		 *    3. Register base (e.g. "foo()()"; i.e. when a return value is a function)
69013 		 */
69014 
69015 		if (left->t == DUK_IVAL_VAR) {
69016 			duk_hstring *h_varname;
69017 			duk_regconst_t reg_varbind;
69018 			duk_regconst_t rc_varname;
69019 
69020 			DUK_DDD(DUK_DDDPRINT("function call with identifier base"));
69021 
69022 			h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
69023 			if (h_varname == DUK_HTHREAD_STRING_EVAL(thr)) {
69024 				/* Potential direct eval call detected, flag the CALL
69025 				 * so that a run-time "direct eval" check is made and
69026 				 * special behavior may be triggered.  Note that this
69027 				 * does not prevent 'eval' from being register bound.
69028 				 */
69029 				DUK_DDD(DUK_DDDPRINT("function call with identifier 'eval' "
69030 				                     "-> using EVALCALL, marking function "
69031 				                     "as may_direct_eval"));
69032 				call_op |= DUK_BC_CALL_FLAG_CALLED_AS_EVAL;
69033 				comp_ctx->curr_func.may_direct_eval = 1;
69034 			}
69035 
69036 			duk_dup(thr, left->x1.valstack_idx);
69037 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
69038 				duk__emit_a_bc(comp_ctx,
69039 				              DUK_OP_CSREG | DUK__EMIT_FLAG_A_IS_SOURCE,
69040 				              reg_varbind,
69041 				              reg_cs + 0);
69042 			} else {
69043 				/* XXX: expand target register or constant field to
69044 				 * reduce shuffling.
69045 				 */
69046 				DUK_ASSERT(DUK__ISCONST(rc_varname));
69047 				duk__emit_a_b(comp_ctx,
69048 				              DUK_OP_CSVAR | DUK__EMIT_FLAG_BC_REGCONST,
69049 				              reg_cs + 0,
69050 				              rc_varname);
69051 			}
69052 		} else if (left->t == DUK_IVAL_PROP) {
69053 			/* Call through a property lookup, E5 Section 11.2.3, step 6.a.i,
69054 			 * E5 Section 10.4.3.  There used to be a separate CSPROP opcode
69055 			 * but a typical call setup took 3 opcodes (e.g. LDREG, LDCONST,
69056 			 * CSPROP) and the same can be achieved with ordinary loads.
69057 			 */
69058 #if defined(DUK_USE_VERBOSE_ERRORS)
69059 			duk_regconst_t reg_key;
69060 #endif
69061 
69062 			DUK_DDD(DUK_DDDPRINT("function call with property base"));
69063 
69064 			/* XXX: For Math.sin() this generates: LDCONST + LDREG +
69065 			 * GETPROPC + call.  The LDREG is unnecessary because LDCONST
69066 			 * could be loaded directly into reg_cs + 1.  This doesn't
69067 			 * happen now because a variable cannot be in left->x1 of a
69068 			 * DUK_IVAL_PROP.  We could notice that left->x1 is a temp
69069 			 * and reuse, but it would still be in the wrong position
69070 			 * (reg_cs + 0 rather than reg_cs + 1).
69071 			 */
69072 			duk__ispec_toforcedreg(comp_ctx, &left->x1, reg_cs + 1);  /* base */
69073 #if defined(DUK_USE_VERBOSE_ERRORS)
69074 			reg_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
69075 			duk__emit_a_b_c(comp_ctx,
69076 			                DUK_OP_GETPROPC | DUK__EMIT_FLAG_BC_REGCONST,
69077 			                reg_cs + 0,
69078 			                reg_cs + 1,
69079 			                reg_key);
69080 #else
69081 			duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0);  /* base[key] */
69082 #endif
69083 		} else {
69084 			DUK_DDD(DUK_DDDPRINT("function call with register base"));
69085 
69086 			duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0);
69087 #if 0
69088 			duk__emit_a_bc(comp_ctx,
69089 			               DUK_OP_CSREG | DUK__EMIT_FLAG_A_IS_SOURCE,
69090 			               reg_cs + 0,
69091 			               reg_cs + 0);  /* in-place setup */
69092 #endif
69093 			/* Because of in-place setup, REGCS is equivalent to
69094 			 * just this LDUNDEF.
69095 			 */
69096 			duk__emit_bc(comp_ctx, DUK_OP_LDUNDEF, reg_cs + 1);
69097 		}
69098 
69099 		DUK__SETTEMP(comp_ctx, reg_cs + 2);
69100 		nargs = duk__parse_arguments(comp_ctx, res);  /* parse args starting from "next temp" */
69101 
69102 		/* Tailcalls are handled by back-patching the already emitted opcode
69103 		 * later in return statement parser.
69104 		 */
69105 
69106 		duk__emit_a_bc(comp_ctx,
69107 		               call_op,
69108 		               (duk_regconst_t) nargs /*numargs*/,
69109 		               reg_cs /*basereg*/);
69110 		DUK__SETTEMP(comp_ctx, reg_cs + 1);    /* result in csreg */
69111 
69112 		duk__ivalue_regconst(res, reg_cs);
69113 		return;
69114 	}
69115 
69116 	/* POSTFIX EXPRESSION */
69117 
69118 	case DUK_TOK_INCREMENT: {
69119 		args = (DUK_OP_POSTINCP_RR << 16) + (DUK_OP_POSTINCR << 8) + 0;
69120 		goto postincdec;
69121 	}
69122 	case DUK_TOK_DECREMENT: {
69123 		args = (DUK_OP_POSTDECP_RR << 16) + (DUK_OP_POSTDECR << 8) + 0;
69124 		goto postincdec;
69125 	}
69126 
69127 	/* EXPONENTIATION EXPRESSION */
69128 
69129 #if defined(DUK_USE_ES7_EXP_OPERATOR)
69130 	case DUK_TOK_EXP: {
69131 		args = (DUK_OP_EXP << 8) + DUK__BP_EXPONENTIATION - 1;  /* UnaryExpression */
69132 		goto binary;
69133 	}
69134 #endif
69135 
69136 	/* MULTIPLICATIVE EXPRESSION */
69137 
69138 	case DUK_TOK_MUL: {
69139 		args = (DUK_OP_MUL << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */
69140 		goto binary;
69141 	}
69142 	case DUK_TOK_DIV: {
69143 		args = (DUK_OP_DIV << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */
69144 		goto binary;
69145 	}
69146 	case DUK_TOK_MOD: {
69147 		args = (DUK_OP_MOD << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */
69148 		goto binary;
69149 	}
69150 
69151 	/* ADDITIVE EXPRESSION */
69152 
69153 	case DUK_TOK_ADD: {
69154 		args = (DUK_OP_ADD << 8) + DUK__BP_ADDITIVE;  /* MultiplicativeExpression */
69155 		goto binary;
69156 	}
69157 	case DUK_TOK_SUB: {
69158 		args = (DUK_OP_SUB << 8) + DUK__BP_ADDITIVE;  /* MultiplicativeExpression */
69159 		goto binary;
69160 	}
69161 
69162 	/* SHIFT EXPRESSION */
69163 
69164 	case DUK_TOK_ALSHIFT: {
69165 		/* << */
69166 		args = (DUK_OP_BASL << 8) + DUK__BP_SHIFT;
69167 		goto binary;
69168 	}
69169 	case DUK_TOK_ARSHIFT: {
69170 		/* >> */
69171 		args = (DUK_OP_BASR << 8) + DUK__BP_SHIFT;
69172 		goto binary;
69173 	}
69174 	case DUK_TOK_RSHIFT: {
69175 		/* >>> */
69176 		args = (DUK_OP_BLSR << 8) + DUK__BP_SHIFT;
69177 		goto binary;
69178 	}
69179 
69180 	/* RELATIONAL EXPRESSION */
69181 
69182 	case DUK_TOK_LT: {
69183 		/* < */
69184 		args = (DUK_OP_LT << 8) + DUK__BP_RELATIONAL;
69185 		goto binary;
69186 	}
69187 	case DUK_TOK_GT: {
69188 		args = (DUK_OP_GT << 8) + DUK__BP_RELATIONAL;
69189 		goto binary;
69190 	}
69191 	case DUK_TOK_LE: {
69192 		args = (DUK_OP_LE << 8) + DUK__BP_RELATIONAL;
69193 		goto binary;
69194 	}
69195 	case DUK_TOK_GE: {
69196 		args = (DUK_OP_GE << 8) + DUK__BP_RELATIONAL;
69197 		goto binary;
69198 	}
69199 	case DUK_TOK_INSTANCEOF: {
69200 		args = (DUK_OP_INSTOF << 8) + DUK__BP_RELATIONAL;
69201 		goto binary;
69202 	}
69203 	case DUK_TOK_IN: {
69204 		args = (DUK_OP_IN << 8) + DUK__BP_RELATIONAL;
69205 		goto binary;
69206 	}
69207 
69208 	/* EQUALITY EXPRESSION */
69209 
69210 	case DUK_TOK_EQ: {
69211 		args = (DUK_OP_EQ << 8) + DUK__BP_EQUALITY;
69212 		goto binary;
69213 	}
69214 	case DUK_TOK_NEQ: {
69215 		args = (DUK_OP_NEQ << 8) + DUK__BP_EQUALITY;
69216 		goto binary;
69217 	}
69218 	case DUK_TOK_SEQ: {
69219 		args = (DUK_OP_SEQ << 8) + DUK__BP_EQUALITY;
69220 		goto binary;
69221 	}
69222 	case DUK_TOK_SNEQ: {
69223 		args = (DUK_OP_SNEQ << 8) + DUK__BP_EQUALITY;
69224 		goto binary;
69225 	}
69226 
69227 	/* BITWISE EXPRESSIONS */
69228 
69229 	case DUK_TOK_BAND: {
69230 		args = (DUK_OP_BAND << 8) + DUK__BP_BAND;
69231 		goto binary;
69232 	}
69233 	case DUK_TOK_BXOR: {
69234 		args = (DUK_OP_BXOR << 8) + DUK__BP_BXOR;
69235 		goto binary;
69236 	}
69237 	case DUK_TOK_BOR: {
69238 		args = (DUK_OP_BOR << 8) + DUK__BP_BOR;
69239 		goto binary;
69240 	}
69241 
69242 	/* LOGICAL EXPRESSIONS */
69243 
69244 	case DUK_TOK_LAND: {
69245 		/* syntactically left-associative but parsed as right-associative */
69246 		args = (1 << 8) + DUK__BP_LAND - 1;
69247 		goto binary_logical;
69248 	}
69249 	case DUK_TOK_LOR: {
69250 		/* syntactically left-associative but parsed as right-associative */
69251 		args = (0 << 8) + DUK__BP_LOR - 1;
69252 		goto binary_logical;
69253 	}
69254 
69255 	/* CONDITIONAL EXPRESSION */
69256 
69257 	case DUK_TOK_QUESTION: {
69258 		/* XXX: common reg allocation need is to reuse a sub-expression's temp reg,
69259 		 * but only if it really is a temp.  Nothing fancy here now.
69260 		 */
69261 		duk_regconst_t reg_temp;
69262 		duk_int_t pc_jump1;
69263 		duk_int_t pc_jump2;
69264 
69265 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
69266 		duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
69267 		duk__emit_if_true_skip(comp_ctx, reg_temp);
69268 		pc_jump1 = duk__emit_jump_empty(comp_ctx);  /* jump to false */
69269 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);  /* AssignmentExpression */
69270 		duk__advance_expect(comp_ctx, DUK_TOK_COLON);
69271 		pc_jump2 = duk__emit_jump_empty(comp_ctx);  /* jump to end */
69272 		duk__patch_jump_here(comp_ctx, pc_jump1);
69273 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);  /* AssignmentExpression */
69274 		duk__patch_jump_here(comp_ctx, pc_jump2);
69275 
69276 		DUK__SETTEMP(comp_ctx, reg_temp + 1);
69277 		duk__ivalue_regconst(res, reg_temp);
69278 		return;
69279 	}
69280 
69281 	/* ASSIGNMENT EXPRESSION */
69282 
69283 	case DUK_TOK_EQUALSIGN: {
69284 		/*
69285 		 *  Assignments are right associative, allows e.g.
69286 		 *    a = 5;
69287 		 *    a += b = 9;   // same as a += (b = 9)
69288 		 *  -> expression value 14, a = 14, b = 9
69289 		 *
69290 		 *  Right associativiness is reflected in the BP for recursion,
69291 		 *  "-1" ensures assignment operations are allowed.
69292 		 *
69293 		 *  XXX: just use DUK__BP_COMMA (i.e. no need for 2-step bp levels)?
69294 		 */
69295 		args = (DUK_OP_NONE << 8) + DUK__BP_ASSIGNMENT - 1;   /* DUK_OP_NONE marks a 'plain' assignment */
69296 		goto assign;
69297 	}
69298 	case DUK_TOK_ADD_EQ: {
69299 		/* right associative */
69300 		args = (DUK_OP_ADD << 8) + DUK__BP_ASSIGNMENT - 1;
69301 		goto assign;
69302 	}
69303 	case DUK_TOK_SUB_EQ: {
69304 		/* right associative */
69305 		args = (DUK_OP_SUB << 8) + DUK__BP_ASSIGNMENT - 1;
69306 		goto assign;
69307 	}
69308 	case DUK_TOK_MUL_EQ: {
69309 		/* right associative */
69310 		args = (DUK_OP_MUL << 8) + DUK__BP_ASSIGNMENT - 1;
69311 		goto assign;
69312 	}
69313 	case DUK_TOK_DIV_EQ: {
69314 		/* right associative */
69315 		args = (DUK_OP_DIV << 8) + DUK__BP_ASSIGNMENT - 1;
69316 		goto assign;
69317 	}
69318 	case DUK_TOK_MOD_EQ: {
69319 		/* right associative */
69320 		args = (DUK_OP_MOD << 8) + DUK__BP_ASSIGNMENT - 1;
69321 		goto assign;
69322 	}
69323 #if defined(DUK_USE_ES7_EXP_OPERATOR)
69324 	case DUK_TOK_EXP_EQ: {
69325 		/* right associative */
69326 		args = (DUK_OP_EXP << 8) + DUK__BP_ASSIGNMENT - 1;
69327 		goto assign;
69328 	}
69329 #endif
69330 	case DUK_TOK_ALSHIFT_EQ: {
69331 		/* right associative */
69332 		args = (DUK_OP_BASL << 8) + DUK__BP_ASSIGNMENT - 1;
69333 		goto assign;
69334 	}
69335 	case DUK_TOK_ARSHIFT_EQ: {
69336 		/* right associative */
69337 		args = (DUK_OP_BASR << 8) + DUK__BP_ASSIGNMENT - 1;
69338 		goto assign;
69339 	}
69340 	case DUK_TOK_RSHIFT_EQ: {
69341 		/* right associative */
69342 		args = (DUK_OP_BLSR << 8) + DUK__BP_ASSIGNMENT - 1;
69343 		goto assign;
69344 	}
69345 	case DUK_TOK_BAND_EQ: {
69346 		/* right associative */
69347 		args = (DUK_OP_BAND << 8) + DUK__BP_ASSIGNMENT - 1;
69348 		goto assign;
69349 	}
69350 	case DUK_TOK_BOR_EQ: {
69351 		/* right associative */
69352 		args = (DUK_OP_BOR << 8) + DUK__BP_ASSIGNMENT - 1;
69353 		goto assign;
69354 	}
69355 	case DUK_TOK_BXOR_EQ: {
69356 		/* right associative */
69357 		args = (DUK_OP_BXOR << 8) + DUK__BP_ASSIGNMENT - 1;
69358 		goto assign;
69359 	}
69360 
69361 	/* COMMA */
69362 
69363 	case DUK_TOK_COMMA: {
69364 		/* right associative */
69365 
69366 		duk__ivalue_toplain_ignore(comp_ctx, left);  /* need side effects, not value */
69367 		duk__expr_toplain(comp_ctx, res, DUK__BP_COMMA - 1 /*rbp_flags*/);
69368 
69369 		/* return 'res' (of right part) as our result */
69370 		return;
69371 	}
69372 
69373 	default: {
69374 		break;
69375 	}
69376 	}
69377 
69378 	DUK_D(DUK_DPRINT("parse error: unexpected token: %ld", (long) tok));
69379 	DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
69380 	DUK_WO_NORETURN(return;);
69381 
69382 #if 0
69383 	/* XXX: shared handling for 'duk__expr_lhs'? */
69384 	if (comp_ctx->curr_func.paren_level == 0 && XXX) {
69385 		comp_ctx->curr_func.duk__expr_lhs = 0;
69386 	}
69387 #endif
69388 
69389  binary:
69390 	/*
69391 	 *  Shared handling of binary operations
69392 	 *
69393 	 *  args = (opcode << 8) + rbp
69394 	 */
69395 	{
69396 		duk__ivalue_toplain(comp_ctx, left);
69397 		duk__expr_toplain(comp_ctx, res, args & 0xff /*rbp_flags*/);
69398 
69399 		/* combine left->x1 and res->x1 (right->x1, really) -> (left->x1 OP res->x1) */
69400 		DUK_ASSERT(left->t == DUK_IVAL_PLAIN);
69401 		DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
69402 
69403 		res->t = DUK_IVAL_ARITH;
69404 		res->op = (args >> 8) & 0xff;
69405 
69406 		res->x2.t = res->x1.t;
69407 		res->x2.regconst = res->x1.regconst;
69408 		duk_copy(thr, res->x1.valstack_idx, res->x2.valstack_idx);
69409 
69410 		res->x1.t = left->x1.t;
69411 		res->x1.regconst = left->x1.regconst;
69412 		duk_copy(thr, left->x1.valstack_idx, res->x1.valstack_idx);
69413 
69414 		DUK_DDD(DUK_DDDPRINT("binary op, res: t=%ld, x1.t=%ld, x1.regconst=0x%08lx, x2.t=%ld, x2.regconst=0x%08lx",
69415 		                     (long) res->t, (long) res->x1.t, (unsigned long) res->x1.regconst, (long) res->x2.t, (unsigned long) res->x2.regconst));
69416 		return;
69417 	}
69418 
69419  binary_logical:
69420 	/*
69421 	 *  Shared handling for logical AND and logical OR.
69422 	 *
69423 	 *  args = (truthval << 8) + rbp
69424 	 *
69425 	 *  Truthval determines when to skip right-hand-side.
69426 	 *  For logical AND truthval=1, for logical OR truthval=0.
69427 	 *
69428 	 *  See doc/compiler.rst for discussion on compiling logical
69429 	 *  AND and OR expressions.  The approach here is very simplistic,
69430 	 *  generating extra jumps and multiple evaluations of truth values,
69431 	 *  but generates code on-the-fly with only local back-patching.
69432 	 *
69433 	 *  Both logical AND and OR are syntactically left-associated.
69434 	 *  However, logical ANDs are compiled as right associative
69435 	 *  expressions, i.e. "A && B && C" as "A && (B && C)", to allow
69436 	 *  skip jumps to skip over the entire tail.  Similarly for logical OR.
69437 	 */
69438 
69439 	{
69440 		duk_regconst_t reg_temp;
69441 		duk_int_t pc_jump;
69442 		duk_small_uint_t args_truthval = args >> 8;
69443 		duk_small_uint_t args_rbp = args & 0xff;
69444 
69445 		/* XXX: unoptimal use of temps, resetting */
69446 
69447 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
69448 
69449 		duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
69450 		DUK_ASSERT(DUK__ISREG(reg_temp));
69451 		duk__emit_bc(comp_ctx,
69452 		            (args_truthval ? DUK_OP_IFTRUE_R : DUK_OP_IFFALSE_R),
69453 		            reg_temp);  /* skip jump conditionally */
69454 		pc_jump = duk__emit_jump_empty(comp_ctx);
69455 		duk__expr_toforcedreg(comp_ctx, res, args_rbp /*rbp_flags*/, reg_temp /*forced_reg*/);
69456 		duk__patch_jump_here(comp_ctx, pc_jump);
69457 
69458 		duk__ivalue_regconst(res, reg_temp);
69459 		return;
69460 	}
69461 
69462  assign:
69463 	/*
69464 	 *  Shared assignment expression handling
69465 	 *
69466 	 *  args = (opcode << 8) + rbp
69467 	 *
69468 	 *  If 'opcode' is DUK_OP_NONE, plain assignment without arithmetic.
69469 	 *  Syntactically valid left-hand-side forms which are not accepted as
69470 	 *  left-hand-side values (e.g. as in "f() = 1") must NOT cause a
69471 	 *  SyntaxError, but rather a run-time ReferenceError.
69472 	 *
69473 	 *  When evaluating X <op>= Y, the LHS (X) is conceptually evaluated
69474 	 *  to a temporary first.  The RHS is then evaluated.  Finally, the
69475 	 *  <op> is applied to the initial value of RHS (not the value after
69476 	 *  RHS evaluation), and written to X.  Doing so concretely generates
69477 	 *  inefficient code so we'd like to avoid the temporary when possible.
69478 	 *  See: https://github.com/svaarala/duktape/pull/992.
69479 	 *
69480 	 *  The expression value (final LHS value, written to RHS) is
69481 	 *  conceptually copied into a fresh temporary so that it won't
69482 	 *  change even if the LHS/RHS values change in outer expressions.
69483 	 *  For example, it'd be generally incorrect for the expression value
69484 	 *  to be the RHS register binding, unless there's a guarantee that it
69485 	 *  won't change during further expression evaluation.  Using the
69486 	 *  temporary concretely produces inefficient bytecode, so we try to
69487 	 *  avoid the extra temporary for some known-to-be-safe cases.
69488 	 *  Currently the only safe case we detect is a "top level assignment",
69489 	 *  for example "x = y + z;", where the assignment expression value is
69490 	 *  ignored.
69491 	 *  See: test-dev-assign-expr.js and test-bug-assign-mutate-gh381.js.
69492 	 */
69493 
69494 	{
69495 		duk_small_uint_t args_op = args >> 8;
69496 		duk_small_uint_t args_rbp = args & 0xff;
69497 		duk_bool_t toplevel_assign;
69498 
69499 		/* XXX: here we need to know if 'left' is left-hand-side compatible.
69500 		 * That information is no longer available from current expr parsing
69501 		 * state; it would need to be carried into the 'left' ivalue or by
69502 		 * some other means.
69503 		 */
69504 
69505 		/* A top-level assignment is e.g. "x = y;".  For these it's safe
69506 		 * to use the RHS as-is as the expression value, even if the RHS
69507 		 * is a reg-bound identifier.  The RHS ('res') is right associative
69508 		 * so it has consumed all other assignment level operations; the
69509 		 * only relevant lower binding power construct is comma operator
69510 		 * which will ignore the expression value provided here.  Usually
69511 		 * the top level assignment expression value is ignored, but it
69512 		 * is relevant for e.g. eval code.
69513 		 */
69514 		toplevel_assign = (comp_ctx->curr_func.nud_count == 1 && /* one token before */
69515 		                   comp_ctx->curr_func.led_count == 1);  /* one operator (= assign) */
69516 		DUK_DDD(DUK_DDDPRINT("assignment: nud_count=%ld, led_count=%ld, toplevel_assign=%ld",
69517 		                     (long) comp_ctx->curr_func.nud_count,
69518 		                     (long) comp_ctx->curr_func.led_count,
69519 		                     (long) toplevel_assign));
69520 
69521 		if (left->t == DUK_IVAL_VAR) {
69522 			duk_hstring *h_varname;
69523 			duk_regconst_t reg_varbind;
69524 			duk_regconst_t rc_varname;
69525 
69526 			DUK_ASSERT(left->x1.t == DUK_ISPEC_VALUE);  /* LHS is already side effect free */
69527 
69528 			h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
69529 			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
69530 				/* E5 Section 11.13.1 (and others for other assignments), step 4. */
69531 				goto syntax_error_lvalue;
69532 			}
69533 			duk_dup(thr, left->x1.valstack_idx);
69534 			(void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
69535 
69536 			if (args_op == DUK_OP_NONE) {
69537 				duk__expr(comp_ctx, res, args_rbp /*rbp_flags*/);
69538 				if (toplevel_assign) {
69539 					/* Any 'res' will do. */
69540 					DUK_DDD(DUK_DDDPRINT("plain assignment, toplevel assign, use as is"));
69541 				} else {
69542 					/* 'res' must be a plain ivalue, and not register-bound variable. */
69543 					DUK_DDD(DUK_DDDPRINT("plain assignment, not toplevel assign, ensure not a reg-bound identifier"));
69544 					if (res->t != DUK_IVAL_PLAIN || (res->x1.t == DUK_ISPEC_REGCONST &&
69545 					                                 DUK__ISREG_NOTTEMP(comp_ctx, res->x1.regconst))) {
69546 						duk__ivalue_totempconst(comp_ctx, res);
69547 					}
69548 				}
69549 			} else {
69550 				/* For X <op>= Y we need to evaluate the pre-op
69551 				 * value of X before evaluating the RHS: the RHS
69552 				 * can change X, but when we do <op> we must use
69553 				 * the pre-op value.
69554 				 */
69555 				duk_regconst_t reg_temp;
69556 
69557 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
69558 
69559 				if (reg_varbind >= 0) {
69560 					duk_regconst_t reg_res;
69561 					duk_regconst_t reg_src;
69562 					duk_int_t pc_temp_load;
69563 					duk_int_t pc_before_rhs;
69564 					duk_int_t pc_after_rhs;
69565 
69566 					if (toplevel_assign) {
69567 						/* 'reg_varbind' is the operation result and can also
69568 						 * become the expression value for top level assignments
69569 						 * such as: "var x; x += y;".
69570 						 */
69571 						DUK_DD(DUK_DDPRINT("<op>= expression is top level, write directly to reg_varbind"));
69572 						reg_res = reg_varbind;
69573 					} else {
69574 						/* Not safe to use 'reg_varbind' as assignment expression
69575 						 * value, so go through a temp.
69576 						 */
69577 						DUK_DD(DUK_DDPRINT("<op>= expression is not top level, write to reg_temp"));
69578 						reg_res = reg_temp;  /* reg_res should be smallest possible */
69579 						reg_temp = DUK__ALLOCTEMP(comp_ctx);
69580 					}
69581 
69582 					/* Try to optimize X <op>= Y for reg-bound
69583 					 * variables.  Detect side-effect free RHS
69584 					 * narrowly by seeing whether it emits code.
69585 					 * If not, rewind the code emitter and overwrite
69586 					 * the unnecessary temp reg load.
69587 					 */
69588 
69589 					pc_temp_load = duk__get_current_pc(comp_ctx);
69590 					duk__emit_a_bc(comp_ctx,
69591 					               DUK_OP_LDREG,
69592 					               reg_temp,
69593 					               reg_varbind);
69594 
69595 					pc_before_rhs = duk__get_current_pc(comp_ctx);
69596 					duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
69597 					DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
69598 					pc_after_rhs = duk__get_current_pc(comp_ctx);
69599 
69600 					DUK_DD(DUK_DDPRINT("pc_temp_load=%ld, pc_before_rhs=%ld, pc_after_rhs=%ld",
69601 					                   (long) pc_temp_load, (long) pc_before_rhs,
69602 					                   (long) pc_after_rhs));
69603 
69604 					if (pc_after_rhs == pc_before_rhs) {
69605 						/* Note: if the reg_temp load generated shuffling
69606 						 * instructions, we may need to rewind more than
69607 						 * one instruction, so use explicit PC computation.
69608 						 */
69609 						DUK_DD(DUK_DDPRINT("rhs is side effect free, rewind and avoid unnecessary temp for reg-based <op>="));
69610 						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));
69611 						reg_src = reg_varbind;
69612 					} else {
69613 						DUK_DD(DUK_DDPRINT("rhs evaluation emitted code, not sure if rhs is side effect free; use temp reg for LHS"));
69614 						reg_src = reg_temp;
69615 					}
69616 
69617 					duk__emit_a_b_c(comp_ctx,
69618 					                args_op | DUK__EMIT_FLAG_BC_REGCONST,
69619 					                reg_res,
69620 					                reg_src,
69621 					                res->x1.regconst);
69622 
69623 					res->x1.regconst = reg_res;
69624 
69625 					/* Ensure compact use of temps. */
69626 					if (DUK__ISREG_TEMP(comp_ctx, reg_res)) {
69627 						DUK__SETTEMP(comp_ctx, reg_res + 1);
69628 					}
69629 				} else {
69630 					/* When LHS is not register bound, always go through a
69631 					 * temporary.  No optimization for top level assignment.
69632 					 */
69633 
69634 					duk__emit_a_bc(comp_ctx,
69635 					               DUK_OP_GETVAR,
69636 					               reg_temp,
69637 					               rc_varname);
69638 
69639 					duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
69640 					DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
69641 
69642 					duk__emit_a_b_c(comp_ctx,
69643 					                args_op | DUK__EMIT_FLAG_BC_REGCONST,
69644 					                reg_temp,
69645 					                reg_temp,
69646 					                res->x1.regconst);
69647 					res->x1.regconst = reg_temp;
69648 				}
69649 
69650 				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
69651 			}
69652 
69653 			/* At this point 'res' holds the potential expression value.
69654 			 * It can be basically any ivalue here, including a reg-bound
69655 			 * identifier (if code above deems it safe) or a unary/binary
69656 			 * operation.  Operations must be resolved to a side effect free
69657 			 * plain value, and the side effects must happen exactly once.
69658 			 */
69659 
69660 			if (reg_varbind >= 0) {
69661 				if (res->t != DUK_IVAL_PLAIN) {
69662 					/* Resolve 'res' directly into the LHS binding, and use
69663 					 * that as the expression value if safe.  If not safe,
69664 					 * resolve to a temp/const and copy to LHS.
69665 					 */
69666 					if (toplevel_assign) {
69667 						duk__ivalue_toforcedreg(comp_ctx, res, (duk_int_t) reg_varbind);
69668 					} else {
69669 						duk__ivalue_totempconst(comp_ctx, res);
69670 						duk__copy_ivalue(comp_ctx, res, left);  /* use 'left' as a temp */
69671 						duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
69672 					}
69673 				} else {
69674 					/* Use 'res' as the expression value (it's side effect
69675 					 * free and may be a plain value, a register, or a
69676 					 * constant) and write it to the LHS binding too.
69677 					 */
69678 					duk__copy_ivalue(comp_ctx, res, left);  /* use 'left' as a temp */
69679 					duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
69680 				}
69681 			} else {
69682 				/* Only a reg fits into 'A' so coerce 'res' into a register
69683 				 * for PUTVAR.
69684 				 *
69685 				 * XXX: here the current A/B/C split is suboptimal: we could
69686 				 * just use 9 bits for reg_res (and support constants) and 17
69687 				 * instead of 18 bits for the varname const index.
69688 				 */
69689 
69690 				duk__ivalue_toreg(comp_ctx, res);
69691 				duk__emit_a_bc(comp_ctx,
69692 				               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
69693 				               res->x1.regconst,
69694 				               rc_varname);
69695 			}
69696 
69697 			/* 'res' contains expression value */
69698 		} else if (left->t == DUK_IVAL_PROP) {
69699 			/* E5 Section 11.13.1 (and others) step 4 never matches for prop writes -> no check */
69700 			duk_regconst_t reg_obj;
69701 			duk_regconst_t rc_key;
69702 			duk_regconst_t rc_res;
69703 			duk_regconst_t reg_temp;
69704 
69705 			/* Property access expressions ('a[b]') are critical to correct
69706 			 * LHS evaluation ordering, see test-dev-assign-eval-order*.js.
69707 			 * We must make sure that the LHS target slot (base object and
69708 			 * key) don't change during RHS evaluation.  The only concrete
69709 			 * problem is a register reference to a variable-bound register
69710 			 * (i.e., non-temp).  Require temp regs for both key and base.
69711 			 *
69712 			 * Don't allow a constant for the object (even for a number
69713 			 * etc), as it goes into the 'A' field of the opcode.
69714 			 */
69715 
69716 			reg_obj = duk__ispec_toregconst_raw(comp_ctx,
69717 			                                    &left->x1,
69718 			                                    -1 /*forced_reg*/,
69719 			                                    DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
69720 
69721 			rc_key = duk__ispec_toregconst_raw(comp_ctx,
69722 			                                   &left->x2,
69723 			                                   -1 /*forced_reg*/,
69724 			                                   DUK__IVAL_FLAG_REQUIRE_TEMP | DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
69725 
69726 			/* Evaluate RHS only when LHS is safe. */
69727 
69728 			if (args_op == DUK_OP_NONE) {
69729 				duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
69730 				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
69731 				rc_res = res->x1.regconst;
69732 			} else {
69733 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
69734 				duk__emit_a_b_c(comp_ctx,
69735 				                DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST,
69736 				                reg_temp,
69737 				                reg_obj,
69738 				                rc_key);
69739 
69740 				duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
69741 				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
69742 
69743 				duk__emit_a_b_c(comp_ctx,
69744 				                args_op | DUK__EMIT_FLAG_BC_REGCONST,
69745 				                reg_temp,
69746 				                reg_temp,
69747 				                res->x1.regconst);
69748 				rc_res = reg_temp;
69749 			}
69750 
69751 			duk__emit_a_b_c(comp_ctx,
69752 			                DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE | DUK__EMIT_FLAG_BC_REGCONST,
69753 			                reg_obj,
69754 			                rc_key,
69755 			                rc_res);
69756 
69757 			duk__ivalue_regconst(res, rc_res);
69758 		} else {
69759 			/* No support for lvalues returned from new or function call expressions.
69760 			 * However, these must NOT cause compile-time SyntaxErrors, but run-time
69761 			 * ReferenceErrors.  Both left and right sides of the assignment must be
69762 			 * evaluated before throwing a ReferenceError.  For instance:
69763 			 *
69764 			 *     f() = g();
69765 			 *
69766 			 * must result in f() being evaluated, then g() being evaluated, and
69767 			 * finally, a ReferenceError being thrown.  See E5 Section 11.13.1.
69768 			 */
69769 
69770 			duk_regconst_t rc_res;
69771 
69772 			/* First evaluate LHS fully to ensure all side effects are out. */
69773 			duk__ivalue_toplain_ignore(comp_ctx, left);
69774 
69775 			/* Then evaluate RHS fully (its value becomes the expression value too).
69776 			 * Technically we'd need the side effect safety check here too, but because
69777 			 * we always throw using INVLHS the result doesn't matter.
69778 			 */
69779 			rc_res = duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
69780 
69781 			duk__emit_op_only(comp_ctx, DUK_OP_INVLHS);
69782 
69783 			duk__ivalue_regconst(res, rc_res);
69784 		}
69785 
69786 		return;
69787 	}
69788 
69789  postincdec:
69790 	{
69791 		/*
69792 		 *  Post-increment/decrement will return the original value as its
69793 		 *  result value.  However, even that value will be coerced using
69794 		 *  ToNumber() which is quite awkward.  Specific bytecode opcodes
69795 		 *  are used to handle these semantics.
69796 		 *
69797 		 *  Note that post increment/decrement has a "no LineTerminator here"
69798 		 *  restriction.  This is handled by duk__expr_lbp(), which forcibly terminates
69799 		 *  the previous expression if a LineTerminator occurs before '++'/'--'.
69800 		 */
69801 
69802 		duk_regconst_t reg_res;
69803 		duk_small_uint_t args_op1 = (args >> 8) & 0xff;  /* DUK_OP_POSTINCR/DUK_OP_POSTDECR */
69804 		duk_small_uint_t args_op2 = args >> 16;          /* DUK_OP_POSTINCP_RR/DUK_OP_POSTDECP_RR */
69805 
69806 		/* Specific assumptions for opcode numbering. */
69807 		DUK_ASSERT(DUK_OP_POSTINCR + 4 == DUK_OP_POSTINCV);
69808 		DUK_ASSERT(DUK_OP_POSTDECR + 4 == DUK_OP_POSTDECV);
69809 
69810 		reg_res = DUK__ALLOCTEMP(comp_ctx);
69811 
69812 		if (left->t == DUK_IVAL_VAR) {
69813 			duk_hstring *h_varname;
69814 			duk_regconst_t reg_varbind;
69815 			duk_regconst_t rc_varname;
69816 
69817 			h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
69818 
69819 			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
69820 				goto syntax_error;
69821 			}
69822 
69823 			duk_dup(thr, left->x1.valstack_idx);
69824 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
69825 				duk__emit_a_bc(comp_ctx,
69826 				               args_op1,  /* e.g. DUK_OP_POSTINCR */
69827 				               reg_res,
69828 				               reg_varbind);
69829 			} else {
69830 				duk__emit_a_bc(comp_ctx,
69831 				               args_op1 + 4,  /* e.g. DUK_OP_POSTINCV */
69832 				               reg_res,
69833 				               rc_varname);
69834 			}
69835 
69836 			DUK_DDD(DUK_DDDPRINT("postincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
69837 			                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
69838 		} else if (left->t == DUK_IVAL_PROP) {
69839 			duk_regconst_t reg_obj;  /* allocate to reg only (not const) */
69840 			duk_regconst_t rc_key;
69841 
69842 			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &left->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
69843 			rc_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
69844 			duk__emit_a_b_c(comp_ctx,
69845 			                args_op2 | DUK__EMIT_FLAG_BC_REGCONST,  /* e.g. DUK_OP_POSTINCP */
69846 			                reg_res,
69847 			                reg_obj,
69848 			                rc_key);
69849 		} else {
69850 			/* Technically return value is not needed because INVLHS will
69851 			 * unconditially throw a ReferenceError.  Coercion is necessary
69852 			 * for proper semantics (consider ToNumber() called for an object).
69853 			 * Use DUK_OP_UNP with a dummy register to get ToNumber().
69854 			 */
69855 			duk__ivalue_toforcedreg(comp_ctx, left, reg_res);
69856 			duk__emit_bc(comp_ctx,
69857 			             DUK_OP_UNP,
69858 			             reg_res);  /* for side effects, result ignored */
69859 			duk__emit_op_only(comp_ctx,
69860 			                  DUK_OP_INVLHS);
69861 		}
69862 
69863 		DUK__SETTEMP(comp_ctx, reg_res + 1);
69864 		duk__ivalue_regconst(res, reg_res);
69865 		return;
69866 	}
69867 
69868  syntax_error:
69869 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);
69870 	DUK_WO_NORETURN(return;);
69871 
69872  syntax_error_lvalue:
69873 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LVALUE);
69874 	DUK_WO_NORETURN(return;);
69875 }
69876 
69877 DUK_LOCAL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx) {
69878 	duk_small_uint_t tok = comp_ctx->curr_token.t;
69879 
69880 	DUK_ASSERT_DISABLE(tok >= DUK_TOK_MINVAL);  /* unsigned */
69881 	DUK_ASSERT(tok <= DUK_TOK_MAXVAL);
69882 	DUK_ASSERT(sizeof(duk__token_lbp) == DUK_TOK_MAXVAL + 1);
69883 
69884 	/* XXX: integrate support for this into led() instead?
69885 	 * Similar issue as post-increment/post-decrement.
69886 	 */
69887 
69888 	/* prevent duk__expr_led() by using a binding power less than anything valid */
69889 	if (tok == DUK_TOK_IN && !comp_ctx->curr_func.allow_in) {
69890 		return 0;
69891 	}
69892 
69893 	if ((tok == DUK_TOK_DECREMENT || tok == DUK_TOK_INCREMENT) &&
69894 	    (comp_ctx->curr_token.lineterm)) {
69895 		/* '++' or '--' in a post-increment/decrement position,
69896 		 * and a LineTerminator occurs between the operator and
69897 		 * the preceding expression.  Force the previous expr
69898 		 * to terminate, in effect treating e.g. "a,b\n++" as
69899 		 * "a,b;++" (= SyntaxError).
69900 		 */
69901 		return 0;
69902 	}
69903 
69904 	return DUK__TOKEN_LBP_GET_BP(duk__token_lbp[tok]);  /* format is bit packed */
69905 }
69906 
69907 /*
69908  *  Expression parsing.
69909  *
69910  *  Upon entry to 'expr' and its variants, 'curr_tok' is assumed to be the
69911  *  first token of the expression.  Upon exit, 'curr_tok' will be the first
69912  *  token not part of the expression (e.g. semicolon terminating an expression
69913  *  statement).
69914  */
69915 
69916 #define DUK__EXPR_RBP_MASK           0xff
69917 #define DUK__EXPR_FLAG_REJECT_IN     (1 << 8)   /* reject 'in' token (used for for-in) */
69918 #define DUK__EXPR_FLAG_ALLOW_EMPTY   (1 << 9)   /* allow empty expression */
69919 #define DUK__EXPR_FLAG_REQUIRE_INIT  (1 << 10)  /* require initializer for var/const */
69920 
69921 /* main expression parser function */
69922 DUK_LOCAL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
69923 	duk_hthread *thr = comp_ctx->thr;
69924 	duk_ivalue tmp_alloc;   /* 'res' is used for "left", and 'tmp' for "right" */
69925 	duk_ivalue *tmp = &tmp_alloc;
69926 	duk_small_uint_t rbp;
69927 
69928 	DUK__RECURSION_INCREASE(comp_ctx, thr);
69929 
69930 	duk_require_stack(thr, DUK__PARSE_EXPR_SLOTS);
69931 
69932 	/* filter out flags from exprtop rbp_flags here to save space */
69933 	rbp = rbp_flags & DUK__EXPR_RBP_MASK;
69934 
69935 	DUK_DDD(DUK_DDDPRINT("duk__expr(), rbp_flags=%ld, rbp=%ld, allow_in=%ld, paren_level=%ld",
69936 	                     (long) rbp_flags, (long) rbp, (long) comp_ctx->curr_func.allow_in,
69937 	                     (long) comp_ctx->curr_func.paren_level));
69938 
69939 	duk_memzero(&tmp_alloc, sizeof(tmp_alloc));
69940 	tmp->x1.valstack_idx = duk_get_top(thr);
69941 	tmp->x2.valstack_idx = tmp->x1.valstack_idx + 1;
69942 	duk_push_undefined(thr);
69943 	duk_push_undefined(thr);
69944 
69945 	/* XXX: where to release temp regs in intermediate expressions?
69946 	 * e.g. 1+2+3 -> don't inflate temp register count when parsing this.
69947 	 * that particular expression temp regs can be forced here.
69948 	 */
69949 
69950 	/* XXX: increase ctx->expr_tokens here for every consumed token
69951 	 * (this would be a nice statistic)?
69952 	 */
69953 
69954 	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
69955 		/* XXX: possibly incorrect handling of empty expression */
69956 		DUK_DDD(DUK_DDDPRINT("empty expression"));
69957 		if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY)) {
69958 			DUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED);
69959 			DUK_WO_NORETURN(return;);
69960 		}
69961 		duk_push_undefined(thr);
69962 		duk__ivalue_plain_fromstack(comp_ctx, res);
69963 		goto cleanup;
69964 	}
69965 
69966 	duk__advance(comp_ctx);
69967 	duk__expr_nud(comp_ctx, res);  /* reuse 'res' as 'left' */
69968 	while (rbp < duk__expr_lbp(comp_ctx)) {
69969 		duk__advance(comp_ctx);
69970 		duk__expr_led(comp_ctx, res, tmp);
69971 		duk__copy_ivalue(comp_ctx, tmp, res);  /* tmp -> res */
69972 	}
69973 
69974  cleanup:
69975 	/* final result is already in 'res' */
69976 
69977 	duk_pop_2(thr);
69978 
69979 	DUK__RECURSION_DECREASE(comp_ctx, thr);
69980 }
69981 
69982 DUK_LOCAL void duk__exprtop(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
69983 	duk_hthread *thr = comp_ctx->thr;
69984 
69985 	/* Note: these variables must reside in 'curr_func' instead of the global
69986 	 * context: when parsing function expressions, expression parsing is nested.
69987 	 */
69988 	comp_ctx->curr_func.nud_count = 0;
69989 	comp_ctx->curr_func.led_count = 0;
69990 	comp_ctx->curr_func.paren_level = 0;
69991 	comp_ctx->curr_func.expr_lhs = 1;
69992 	comp_ctx->curr_func.allow_in = (rbp_flags & DUK__EXPR_FLAG_REJECT_IN ? 0 : 1);
69993 
69994 	duk__expr(comp_ctx, res, rbp_flags);
69995 
69996 	if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY) && duk__expr_is_empty(comp_ctx)) {
69997 		DUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED);
69998 		DUK_WO_NORETURN(return;);
69999 	}
70000 }
70001 
70002 /* A bunch of helpers (for size optimization) that combine duk__expr()/duk__exprtop()
70003  * and result conversions.
70004  *
70005  * Each helper needs at least 2-3 calls to make it worth while to wrap.
70006  */
70007 
70008 #if 0  /* unused */
70009 DUK_LOCAL duk_regconst_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70010 	duk__expr(comp_ctx, res, rbp_flags);
70011 	return duk__ivalue_toreg(comp_ctx, res);
70012 }
70013 #endif
70014 
70015 #if 0  /* unused */
70016 DUK_LOCAL duk_regconst_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70017 	duk__expr(comp_ctx, res, rbp_flags);
70018 	return duk__ivalue_totemp(comp_ctx, res);
70019 }
70020 #endif
70021 
70022 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) {
70023 	DUK_ASSERT(forced_reg >= 0);
70024 	duk__expr(comp_ctx, res, rbp_flags);
70025 	duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
70026 }
70027 
70028 DUK_LOCAL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70029 	duk__expr(comp_ctx, res, rbp_flags);
70030 	return duk__ivalue_toregconst(comp_ctx, res);
70031 }
70032 
70033 #if 0  /* unused */
70034 DUK_LOCAL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70035 	duk__expr(comp_ctx, res, rbp_flags);
70036 	return duk__ivalue_totempconst(comp_ctx, res);
70037 }
70038 #endif
70039 
70040 DUK_LOCAL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70041 	duk__expr(comp_ctx, res, rbp_flags);
70042 	duk__ivalue_toplain(comp_ctx, res);
70043 }
70044 
70045 DUK_LOCAL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70046 	duk__expr(comp_ctx, res, rbp_flags);
70047 	duk__ivalue_toplain_ignore(comp_ctx, res);
70048 }
70049 
70050 DUK_LOCAL duk_regconst_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70051 	duk__exprtop(comp_ctx, res, rbp_flags);
70052 	return duk__ivalue_toreg(comp_ctx, res);
70053 }
70054 
70055 #if 0  /* unused */
70056 DUK_LOCAL duk_regconst_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70057 	duk__exprtop(comp_ctx, res, rbp_flags);
70058 	return duk__ivalue_totemp(comp_ctx, res);
70059 }
70060 #endif
70061 
70062 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) {
70063 	DUK_ASSERT(forced_reg >= 0);
70064 	duk__exprtop(comp_ctx, res, rbp_flags);
70065 	duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
70066 }
70067 
70068 DUK_LOCAL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70069 	duk__exprtop(comp_ctx, res, rbp_flags);
70070 	return duk__ivalue_toregconst(comp_ctx, res);
70071 }
70072 
70073 #if 0  /* unused */
70074 DUK_LOCAL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, int rbp_flags) {
70075 	duk__exprtop(comp_ctx, res, rbp_flags);
70076 	duk__ivalue_toplain_ignore(comp_ctx, res);
70077 }
70078 #endif
70079 
70080 /*
70081  *  Parse an individual source element (top level statement) or a statement.
70082  *
70083  *  Handles labeled statements automatically (peeling away labels before
70084  *  parsing an expression that follows the label(s)).
70085  *
70086  *  Upon entry, 'curr_tok' contains the first token of the statement (parsed
70087  *  in "allow regexp literal" mode).  Upon exit, 'curr_tok' contains the first
70088  *  token following the statement (if the statement has a terminator, this is
70089  *  the token after the terminator).
70090  */
70091 
70092 #define DUK__HAS_VAL                  (1 << 0)  /* stmt has non-empty value */
70093 #define DUK__HAS_TERM                 (1 << 1)  /* stmt has explicit/implicit semicolon terminator */
70094 #define DUK__ALLOW_AUTO_SEMI_ALWAYS   (1 << 2)  /* allow automatic semicolon even without lineterm (compatibility) */
70095 #define DUK__STILL_PROLOGUE           (1 << 3)  /* statement does not terminate directive prologue */
70096 #define DUK__IS_TERMINAL              (1 << 4)  /* statement is guaranteed to be terminal (control doesn't flow to next statement) */
70097 
70098 /* Parse a single variable declaration (e.g. "i" or "i=10").  A leading 'var'
70099  * has already been eaten.  These is no return value in 'res', it is used only
70100  * as a temporary.
70101  *
70102  * When called from 'for-in' statement parser, the initializer expression must
70103  * not allow the 'in' token.  The caller supply additional expression parsing
70104  * flags (like DUK__EXPR_FLAG_REJECT_IN) in 'expr_flags'.
70105  *
70106  * Finally, out_rc_varname and out_reg_varbind are updated to reflect where
70107  * the identifier is bound:
70108  *
70109  *    If register bound:      out_reg_varbind >= 0, out_rc_varname == 0 (ignore)
70110  *    If not register bound:  out_reg_varbind < 0, out_rc_varname >= 0
70111  *
70112  * These allow the caller to use the variable for further assignment, e.g.
70113  * as is done in 'for-in' parsing.
70114  */
70115 
70116 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) {
70117 	duk_hthread *thr = comp_ctx->thr;
70118 	duk_hstring *h_varname;
70119 	duk_regconst_t reg_varbind;
70120 	duk_regconst_t rc_varname;
70121 
70122 	/* assume 'var' has been eaten */
70123 
70124 	/* Note: Identifier rejects reserved words */
70125 	if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
70126 		goto syntax_error;
70127 	}
70128 	h_varname = comp_ctx->curr_token.str1;
70129 
70130 	DUK_ASSERT(h_varname != NULL);
70131 
70132 	/* strict mode restrictions (E5 Section 12.2.1) */
70133 	if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
70134 		goto syntax_error;
70135 	}
70136 
70137 	/* register declarations in first pass */
70138 	if (comp_ctx->curr_func.in_scanning) {
70139 		duk_uarridx_t n;
70140 		DUK_DDD(DUK_DDDPRINT("register variable declaration %!O in pass 1",
70141 		                     (duk_heaphdr *) h_varname));
70142 		n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
70143 		duk_push_hstring(thr, h_varname);
70144 		duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n);
70145 		duk_push_int(thr, DUK_DECL_TYPE_VAR + (0 << 8));
70146 		duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n + 1);
70147 	}
70148 
70149 	duk_push_hstring(thr, h_varname);  /* push before advancing to keep reachable */
70150 
70151 	/* register binding lookup is based on varmap (even in first pass) */
70152 	duk_dup_top(thr);
70153 	(void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
70154 
70155 	duk__advance(comp_ctx);  /* eat identifier */
70156 
70157 	if (comp_ctx->curr_token.t == DUK_TOK_EQUALSIGN) {
70158 		duk__advance(comp_ctx);
70159 
70160 		DUK_DDD(DUK_DDDPRINT("vardecl, assign to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
70161 		                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
70162 
70163 		duk__exprtop(comp_ctx, res, DUK__BP_COMMA | expr_flags /*rbp_flags*/);  /* AssignmentExpression */
70164 
70165 		if (reg_varbind >= 0) {
70166 			duk__ivalue_toforcedreg(comp_ctx, res, reg_varbind);
70167 		} else {
70168 			duk_regconst_t reg_val;
70169 			reg_val = duk__ivalue_toreg(comp_ctx, res);
70170 			duk__emit_a_bc(comp_ctx,
70171 			               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
70172 			               reg_val,
70173 			               rc_varname);
70174 		}
70175 	} else {
70176 		if (expr_flags & DUK__EXPR_FLAG_REQUIRE_INIT) {
70177 			/* Used for minimal 'const': initializer required. */
70178 			goto syntax_error;
70179 		}
70180 	}
70181 
70182 	duk_pop(thr);  /* pop varname */
70183 
70184 	*out_rc_varname = rc_varname;
70185 	*out_reg_varbind = reg_varbind;
70186 
70187 	return;
70188 
70189  syntax_error:
70190 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_VAR_DECLARATION);
70191 	DUK_WO_NORETURN(return;);
70192 }
70193 
70194 DUK_LOCAL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags) {
70195 	duk_regconst_t reg_varbind;
70196 	duk_regconst_t rc_varname;
70197 
70198 	duk__advance(comp_ctx);  /* eat 'var' */
70199 
70200 	for (;;) {
70201 		/* rc_varname and reg_varbind are ignored here */
70202 		duk__parse_var_decl(comp_ctx, res, 0 | expr_flags, &reg_varbind, &rc_varname);
70203 
70204 		if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
70205 			break;
70206 		}
70207 		duk__advance(comp_ctx);
70208 	}
70209 }
70210 
70211 DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
70212 	duk_hthread *thr = comp_ctx->thr;
70213 	duk_int_t pc_v34_lhs;         /* start variant 3/4 left-hand-side code (L1 in doc/compiler.rst example) */
70214 	duk_regconst_t temp_reset;    /* knock back "next temp" to this whenever possible */
70215 	duk_regconst_t reg_temps;     /* preallocated temporaries (2) for variants 3 and 4 */
70216 
70217 	DUK_DDD(DUK_DDDPRINT("start parsing a for/for-in statement"));
70218 
70219 	/* Two temporaries are preallocated here for variants 3 and 4 which need
70220 	 * registers which are never clobbered by expressions in the loop
70221 	 * (concretely: for the enumerator object and the next enumerated value).
70222 	 * Variants 1 and 2 "release" these temps.
70223 	 */
70224 
70225 	reg_temps = DUK__ALLOCTEMPS(comp_ctx, 2);
70226 
70227 	temp_reset = DUK__GETTEMP(comp_ctx);
70228 
70229 	/*
70230 	 *  For/for-in main variants are:
70231 	 *
70232 	 *    1. for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement
70233 	 *    2. for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement
70234 	 *    3. for (LeftHandSideExpression in Expression) Statement
70235 	 *    4. for (var VariableDeclarationNoIn in Expression) Statement
70236 	 *
70237 	 *  Parsing these without arbitrary lookahead or backtracking is relatively
70238 	 *  tricky but we manage to do so for now.
70239 	 *
70240 	 *  See doc/compiler.rst for a detailed discussion of control flow
70241 	 *  issues, evaluation order issues, etc.
70242 	 */
70243 
70244 	duk__advance(comp_ctx);  /* eat 'for' */
70245 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
70246 
70247 	DUK_DDD(DUK_DDDPRINT("detecting for/for-in loop variant, pc=%ld", (long) duk__get_current_pc(comp_ctx)));
70248 
70249 	/* a label site has been emitted by duk__parse_stmt() automatically
70250 	 * (it will also emit the ENDLABEL).
70251 	 */
70252 
70253 	if (comp_ctx->curr_token.t == DUK_TOK_VAR) {
70254 		/*
70255 		 *  Variant 2 or 4
70256 		 */
70257 
70258 		duk_regconst_t reg_varbind;  /* variable binding register if register-bound (otherwise < 0) */
70259 		duk_regconst_t rc_varname;   /* variable name reg/const, if variable not register-bound */
70260 
70261 		duk__advance(comp_ctx);  /* eat 'var' */
70262 		duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
70263 		DUK__SETTEMP(comp_ctx, temp_reset);
70264 
70265 		if (comp_ctx->curr_token.t == DUK_TOK_IN) {
70266 			/*
70267 			 *  Variant 4
70268 			 */
70269 
70270 			DUK_DDD(DUK_DDDPRINT("detected for variant 4: for (var VariableDeclarationNoIn in Expression) Statement"));
70271 			pc_v34_lhs = duk__get_current_pc(comp_ctx);  /* jump is inserted here */
70272 			if (reg_varbind >= 0) {
70273 				duk__emit_a_bc(comp_ctx,
70274 				               DUK_OP_LDREG,
70275 				               reg_varbind,
70276 				               reg_temps + 0);
70277 			} else {
70278 				duk__emit_a_bc(comp_ctx,
70279 				               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
70280 				               reg_temps + 0,
70281 				               rc_varname);
70282 			}
70283 			goto parse_3_or_4;
70284 		} else {
70285 			/*
70286 			 *  Variant 2
70287 			 */
70288 
70289 			DUK_DDD(DUK_DDDPRINT("detected for variant 2: for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement"));
70290 			for (;;) {
70291 				/* more initializers */
70292 				if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
70293 					break;
70294 				}
70295 				DUK_DDD(DUK_DDDPRINT("variant 2 has another variable initializer"));
70296 
70297 				duk__advance(comp_ctx);  /* eat comma */
70298 				duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
70299 			}
70300 			goto parse_1_or_2;
70301 		}
70302 	} else {
70303 		/*
70304 		 *  Variant 1 or 3
70305 		 */
70306 
70307 		pc_v34_lhs = duk__get_current_pc(comp_ctx);  /* jump is inserted here (variant 3) */
70308 
70309 		/* Note that duk__exprtop() here can clobber any reg above current temp_next,
70310 		 * so any loop variables (e.g. enumerator) must be "preallocated".
70311 		 */
70312 
70313 		/* don't coerce yet to a plain value (variant 3 needs special handling) */
70314 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_REJECT_IN | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression */
70315 		if (comp_ctx->curr_token.t == DUK_TOK_IN) {
70316 			/*
70317 			 *  Variant 3
70318 			 */
70319 
70320 			/* XXX: need to determine LHS type, and check that it is LHS compatible */
70321 			DUK_DDD(DUK_DDDPRINT("detected for variant 3: for (LeftHandSideExpression in Expression) Statement"));
70322 			if (duk__expr_is_empty(comp_ctx)) {
70323 				goto syntax_error;  /* LeftHandSideExpression does not allow empty expression */
70324 			}
70325 
70326 			if (res->t == DUK_IVAL_VAR) {
70327 				duk_regconst_t reg_varbind;
70328 				duk_regconst_t rc_varname;
70329 
70330 				duk_dup(thr, res->x1.valstack_idx);
70331 				if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
70332 					duk__emit_a_bc(comp_ctx,
70333 					               DUK_OP_LDREG,
70334 					               reg_varbind,
70335 					               reg_temps + 0);
70336 				} else {
70337 					duk__emit_a_bc(comp_ctx,
70338 					               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
70339 					               reg_temps + 0,
70340 					               rc_varname);
70341 				}
70342 			} else if (res->t == DUK_IVAL_PROP) {
70343 				/* Don't allow a constant for the object (even for a number etc), as
70344 				 * it goes into the 'A' field of the opcode.
70345 				 */
70346 				duk_regconst_t reg_obj;
70347 				duk_regconst_t rc_key;
70348 				reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
70349 				rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
70350 				duk__emit_a_b_c(comp_ctx,
70351 				                DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE | DUK__EMIT_FLAG_BC_REGCONST,
70352 				                reg_obj,
70353 				                rc_key,
70354 				                reg_temps + 0);
70355 			} else {
70356 				duk__ivalue_toplain_ignore(comp_ctx, res);  /* just in case */
70357 				duk__emit_op_only(comp_ctx,
70358 				                  DUK_OP_INVLHS);
70359 			}
70360 			goto parse_3_or_4;
70361 		} else {
70362 			/*
70363 			 *  Variant 1
70364 			 */
70365 
70366 			DUK_DDD(DUK_DDDPRINT("detected for variant 1: for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement"));
70367 			duk__ivalue_toplain_ignore(comp_ctx, res);
70368 			goto parse_1_or_2;
70369 		}
70370 	}
70371 
70372  parse_1_or_2:
70373 	/*
70374 	 *  Parse variant 1 or 2.  The first part expression (which differs
70375 	 *  in the variants) has already been parsed and its code emitted.
70376 	 *
70377 	 *  reg_temps + 0: unused
70378 	 *  reg_temps + 1: unused
70379 	 */
70380 	{
70381 		duk_regconst_t rc_cond;
70382 		duk_int_t pc_l1, pc_l2, pc_l3, pc_l4;
70383 		duk_int_t pc_jumpto_l3, pc_jumpto_l4;
70384 		duk_bool_t expr_c_empty;
70385 
70386 		DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 1 and 2"));
70387 
70388 		/* "release" preallocated temps since we won't need them */
70389 		temp_reset = reg_temps + 0;
70390 		DUK__SETTEMP(comp_ctx, temp_reset);
70391 
70392 		duk__advance_expect(comp_ctx, DUK_TOK_SEMICOLON);
70393 
70394 		pc_l1 = duk__get_current_pc(comp_ctx);
70395 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression_opt */
70396 		if (duk__expr_is_empty(comp_ctx)) {
70397 			/* no need to coerce */
70398 			pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* to body */
70399 			pc_jumpto_l4 = -1;  /* omitted */
70400 		} else {
70401 			rc_cond = duk__ivalue_toregconst(comp_ctx, res);
70402 			duk__emit_if_false_skip(comp_ctx, rc_cond);
70403 			pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* to body */
70404 			pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);  /* to exit */
70405 		}
70406 		DUK__SETTEMP(comp_ctx, temp_reset);
70407 
70408 		duk__advance_expect(comp_ctx, DUK_TOK_SEMICOLON);
70409 
70410 		pc_l2 = duk__get_current_pc(comp_ctx);
70411 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression_opt */
70412 		if (duk__expr_is_empty(comp_ctx)) {
70413 			/* no need to coerce */
70414 			expr_c_empty = 1;
70415 			/* JUMP L1 omitted */
70416 		} else {
70417 			duk__ivalue_toplain_ignore(comp_ctx, res);
70418 			expr_c_empty = 0;
70419 			duk__emit_jump(comp_ctx, pc_l1);
70420 		}
70421 		DUK__SETTEMP(comp_ctx, temp_reset);
70422 
70423 		comp_ctx->curr_func.allow_regexp_in_adv = 1;
70424 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
70425 
70426 		pc_l3 = duk__get_current_pc(comp_ctx);
70427 		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
70428 		if (expr_c_empty) {
70429 			duk__emit_jump(comp_ctx, pc_l1);
70430 		} else {
70431 			duk__emit_jump(comp_ctx, pc_l2);
70432 		}
70433 		/* temp reset is not necessary after duk__parse_stmt(), which already does it */
70434 
70435 		pc_l4 = duk__get_current_pc(comp_ctx);
70436 
70437 		DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l3: %ld->%ld, jumpto_l4: %ld->%ld, "
70438 		                     "break: %ld->%ld, continue: %ld->%ld",
70439 			             (long) pc_jumpto_l3, (long) pc_l3, (long) pc_jumpto_l4, (long) pc_l4,
70440 		                     (long) (pc_label_site + 1), (long) pc_l4, (long) (pc_label_site + 2), (long) pc_l2));
70441 
70442 		duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
70443 		duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
70444 		duk__patch_jump(comp_ctx,
70445 		                pc_label_site + 1,
70446 		                pc_l4);                         /* break jump */
70447 		duk__patch_jump(comp_ctx,
70448 		                pc_label_site + 2,
70449 		                expr_c_empty ? pc_l1 : pc_l2);  /* continue jump */
70450 	}
70451 	goto finished;
70452 
70453  parse_3_or_4:
70454 	/*
70455 	 *  Parse variant 3 or 4.
70456 	 *
70457 	 *  For variant 3 (e.g. "for (A in C) D;") the code for A (except the
70458 	 *  final property/variable write) has already been emitted.  The first
70459 	 *  instruction of that code is at pc_v34_lhs; a JUMP needs to be inserted
70460 	 *  there to satisfy control flow needs.
70461 	 *
70462 	 *  For variant 4, if the variable declaration had an initializer
70463 	 *  (e.g. "for (var A = B in C) D;") the code for the assignment
70464 	 *  (B) has already been emitted.
70465 	 *
70466 	 *  Variables set before entering here:
70467 	 *
70468 	 *    pc_v34_lhs:    insert a "JUMP L2" here (see doc/compiler.rst example).
70469 	 *    reg_temps + 0: iteration target value (written to LHS)
70470 	 *    reg_temps + 1: enumerator object
70471 	 */
70472 	{
70473 		duk_int_t pc_l1, pc_l2, pc_l3, pc_l4, pc_l5;
70474 		duk_int_t pc_jumpto_l2, pc_jumpto_l3, pc_jumpto_l4, pc_jumpto_l5;
70475 		duk_regconst_t reg_target;
70476 
70477 		DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 3 and 4, pc_v34_lhs=%ld", (long) pc_v34_lhs));
70478 
70479 		DUK__SETTEMP(comp_ctx, temp_reset);
70480 
70481 		/* First we need to insert a jump in the middle of previously
70482 		 * emitted code to get the control flow right.  No jumps can
70483 		 * cross the position where the jump is inserted.  See doc/compiler.rst
70484 		 * for discussion on the intricacies of control flow and side effects
70485 		 * for variants 3 and 4.
70486 		 */
70487 
70488 		duk__insert_jump_entry(comp_ctx, pc_v34_lhs);
70489 		pc_jumpto_l2 = pc_v34_lhs;  /* inserted jump */
70490 		pc_l1 = pc_v34_lhs + 1;     /* +1, right after inserted jump */
70491 
70492 		/* The code for writing reg_temps + 0 to the left hand side has already
70493 		 * been emitted.
70494 		 */
70495 
70496 		pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* -> loop body */
70497 
70498 		duk__advance(comp_ctx);  /* eat 'in' */
70499 
70500 		/* Parse enumeration target and initialize enumerator.  For 'null' and 'undefined',
70501 		 * INITENUM will creates a 'null' enumerator which works like an empty enumerator
70502 		 * (E5 Section 12.6.4, step 3).  Note that INITENUM requires the value to be in a
70503 		 * register (constant not allowed).
70504 		 */
70505 
70506 		pc_l2 = duk__get_current_pc(comp_ctx);
70507 		reg_target = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression */
70508 		duk__emit_b_c(comp_ctx,
70509 		              DUK_OP_INITENUM | DUK__EMIT_FLAG_B_IS_TARGET,
70510 		              reg_temps + 1,
70511 		              reg_target);
70512 		pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);
70513 		DUK__SETTEMP(comp_ctx, temp_reset);
70514 
70515 		comp_ctx->curr_func.allow_regexp_in_adv = 1;
70516 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
70517 
70518 		pc_l3 = duk__get_current_pc(comp_ctx);
70519 		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
70520 		/* temp reset is not necessary after duk__parse_stmt(), which already does it */
70521 
70522 		/* NEXTENUM needs a jump slot right after the main opcode.
70523 		 * We need the code emitter to reserve the slot: if there's
70524 		 * target shuffling, the target shuffle opcodes must happen
70525 		 * after the jump slot (for NEXTENUM the shuffle opcodes are
70526 		 * not needed if the enum is finished).
70527 		 */
70528 		pc_l4 = duk__get_current_pc(comp_ctx);
70529 		duk__emit_b_c(comp_ctx,
70530 		              DUK_OP_NEXTENUM | DUK__EMIT_FLAG_B_IS_TARGET | DUK__EMIT_FLAG_RESERVE_JUMPSLOT,
70531 		              reg_temps + 0,
70532 		              reg_temps + 1);
70533 		pc_jumpto_l5 = comp_ctx->emit_jumpslot_pc;  /* NEXTENUM jump slot: executed when enum finished */
70534 		duk__emit_jump(comp_ctx, pc_l1);  /* jump to next loop, using reg_v34_iter as iterated value */
70535 
70536 		pc_l5 = duk__get_current_pc(comp_ctx);
70537 
70538 		/* XXX: since the enumerator may be a memory expensive object,
70539 		 * perhaps clear it explicitly here?  If so, break jump must
70540 		 * go through this clearing operation.
70541 		 */
70542 
70543 		DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l2: %ld->%ld, jumpto_l3: %ld->%ld, "
70544 		                     "jumpto_l4: %ld->%ld, jumpto_l5: %ld->%ld, "
70545 		                     "break: %ld->%ld, continue: %ld->%ld",
70546 			             (long) pc_jumpto_l2, (long) pc_l2, (long) pc_jumpto_l3, (long) pc_l3,
70547 			             (long) pc_jumpto_l4, (long) pc_l4, (long) pc_jumpto_l5, (long) pc_l5,
70548 		                     (long) (pc_label_site + 1), (long) pc_l5, (long) (pc_label_site + 2), (long) pc_l4));
70549 
70550 		duk__patch_jump(comp_ctx, pc_jumpto_l2, pc_l2);
70551 		duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
70552 		duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
70553 		duk__patch_jump(comp_ctx, pc_jumpto_l5, pc_l5);
70554 		duk__patch_jump(comp_ctx, pc_label_site + 1, pc_l5);  /* break jump */
70555 		duk__patch_jump(comp_ctx, pc_label_site + 2, pc_l4);  /* continue jump */
70556 	}
70557 	goto finished;
70558 
70559  finished:
70560 	DUK_DDD(DUK_DDDPRINT("end parsing a for/for-in statement"));
70561 	return;
70562 
70563  syntax_error:
70564 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FOR);
70565 	DUK_WO_NORETURN(return;);
70566 }
70567 
70568 DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
70569 	duk_hthread *thr = comp_ctx->thr;
70570 	duk_regconst_t temp_at_loop;
70571 	duk_regconst_t rc_switch;    /* reg/const for switch value */
70572 	duk_regconst_t rc_case;      /* reg/const for case value */
70573 	duk_regconst_t reg_temp;     /* general temp register */
70574 	duk_int_t pc_prevcase = -1;
70575 	duk_int_t pc_prevstmt = -1;
70576 	duk_int_t pc_default = -1;   /* -1 == not set, -2 == pending (next statement list) */
70577 
70578 	/* Note: negative pc values are ignored when patching jumps, so no explicit checks needed */
70579 
70580 	/*
70581 	 *  Switch is pretty complicated because of several conflicting concerns:
70582 	 *
70583 	 *    - Want to generate code without an intermediate representation,
70584 	 *      i.e., in one go
70585 	 *
70586 	 *    - Case selectors are expressions, not values, and may thus e.g. throw
70587 	 *      exceptions (which causes evaluation order concerns)
70588 	 *
70589 	 *    - Evaluation semantics of case selectors and default clause need to be
70590 	 *      carefully implemented to provide correct behavior even with case value
70591 	 *      side effects
70592 	 *
70593 	 *    - Fall through case and default clauses; avoiding dead JUMPs if case
70594 	 *      ends with an unconditional jump (a break or a continue)
70595 	 *
70596 	 *    - The same case value may occur multiple times, but evaluation rules
70597 	 *      only process the first match before switching to a "propagation" mode
70598 	 *      where case values are no longer evaluated
70599 	 *
70600 	 *  See E5 Section 12.11.  Also see doc/compiler.rst for compilation
70601 	 *  discussion.
70602 	 */
70603 
70604 	duk__advance(comp_ctx);
70605 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
70606 	rc_switch = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
70607 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* RegExp mode does not matter. */
70608 	duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
70609 
70610 	DUK_DDD(DUK_DDDPRINT("switch value in register %ld", (long) rc_switch));
70611 
70612 	temp_at_loop = DUK__GETTEMP(comp_ctx);
70613 
70614 	for (;;) {
70615 		duk_int_t num_stmts;
70616 		duk_small_uint_t tok;
70617 
70618 		/* sufficient for keeping temp reg numbers in check */
70619 		DUK__SETTEMP(comp_ctx, temp_at_loop);
70620 
70621 		if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
70622 			break;
70623 		}
70624 
70625 		/*
70626 		 *  Parse a case or default clause.
70627 		 */
70628 
70629 		if (comp_ctx->curr_token.t == DUK_TOK_CASE) {
70630 			/*
70631 			 *  Case clause.
70632 			 *
70633 			 *  Note: cannot use reg_case as a temp register (for SEQ target)
70634 			 *  because it may be a constant.
70635 			 */
70636 
70637 			duk__patch_jump_here(comp_ctx, pc_prevcase);  /* chain jumps for case
70638 			                                               * evaluation and checking
70639 			                                               */
70640 
70641 			duk__advance(comp_ctx);
70642 			rc_case = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
70643 			duk__advance_expect(comp_ctx, DUK_TOK_COLON);
70644 
70645 			reg_temp = DUK__ALLOCTEMP(comp_ctx);
70646 			duk__emit_a_b_c(comp_ctx,
70647 			                DUK_OP_SEQ | DUK__EMIT_FLAG_BC_REGCONST,
70648 			                reg_temp,
70649 			                rc_switch,
70650 			                rc_case);
70651 			duk__emit_if_true_skip(comp_ctx, reg_temp);
70652 
70653 			/* jump to next case clause */
70654 			pc_prevcase = duk__emit_jump_empty(comp_ctx);  /* no match, next case */
70655 
70656 			/* statements go here (if any) on next loop */
70657 		} else if (comp_ctx->curr_token.t == DUK_TOK_DEFAULT) {
70658 			/*
70659 			 *  Default clause.
70660 			 */
70661 
70662 			if (pc_default >= 0) {
70663 				goto syntax_error;
70664 			}
70665 			duk__advance(comp_ctx);
70666 			duk__advance_expect(comp_ctx, DUK_TOK_COLON);
70667 
70668 			/* Fix for https://github.com/svaarala/duktape/issues/155:
70669 			 * If 'default' is first clause (detected by pc_prevcase < 0)
70670 			 * we need to ensure we stay in the matching chain.
70671 			 */
70672 			if (pc_prevcase < 0) {
70673 				DUK_DD(DUK_DDPRINT("default clause is first, emit prevcase jump"));
70674 				pc_prevcase = duk__emit_jump_empty(comp_ctx);
70675 			}
70676 
70677 			/* default clause matches next statement list (if any) */
70678 			pc_default = -2;
70679 		} else {
70680 			/* Code is not accepted before the first case/default clause */
70681 			goto syntax_error;
70682 		}
70683 
70684 		/*
70685 		 *  Parse code after the clause.  Possible terminators are
70686 		 *  'case', 'default', and '}'.
70687 		 *
70688 		 *  Note that there may be no code at all, not even an empty statement,
70689 		 *  between case clauses.  This must be handled just like an empty statement
70690 		 *  (omitting seemingly pointless JUMPs), to avoid situations like
70691 		 *  test-bug-case-fallthrough.js.
70692 		 */
70693 
70694 		num_stmts = 0;
70695 		if (pc_default == -2) {
70696 			pc_default = duk__get_current_pc(comp_ctx);
70697 		}
70698 
70699 		/* Note: this is correct even for default clause statements:
70700 		 * they participate in 'fall-through' behavior even if the
70701 		 * default clause is in the middle.
70702 		 */
70703 		duk__patch_jump_here(comp_ctx, pc_prevstmt);  /* chain jumps for 'fall-through'
70704 		                                               * after a case matches.
70705 		                                               */
70706 
70707 		for (;;) {
70708 			tok = comp_ctx->curr_token.t;
70709 			if (tok == DUK_TOK_CASE || tok == DUK_TOK_DEFAULT ||
70710 			    tok == DUK_TOK_RCURLY) {
70711 				break;
70712 			}
70713 			num_stmts++;
70714 			duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
70715 		}
70716 
70717 		/* fall-through jump to next code of next case (backpatched) */
70718 		pc_prevstmt = duk__emit_jump_empty(comp_ctx);
70719 
70720 		/* XXX: would be nice to omit this jump when the jump is not
70721 		 * reachable, at least in the obvious cases (such as the case
70722 		 * ending with a 'break'.
70723 		 *
70724 		 * Perhaps duk__parse_stmt() could provide some info on whether
70725 		 * the statement is a "dead end"?
70726 		 *
70727 		 * If implemented, just set pc_prevstmt to -1 when not needed.
70728 		 */
70729 	}
70730 
70731 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
70732 	comp_ctx->curr_func.allow_regexp_in_adv = 1;
70733 	duk__advance(comp_ctx);  /* Allow RegExp as part of next stmt. */
70734 
70735 	/* default case control flow patchup; note that if pc_prevcase < 0
70736 	 * (i.e. no case clauses), control enters default case automatically.
70737 	 */
70738 	if (pc_default >= 0) {
70739 		/* default case exists: go there if no case matches */
70740 		duk__patch_jump(comp_ctx, pc_prevcase, pc_default);
70741 	} else {
70742 		/* default case does not exist, or no statements present
70743 		 * after default case: finish case evaluation
70744 		 */
70745 		duk__patch_jump_here(comp_ctx, pc_prevcase);
70746 	}
70747 
70748 	/* fall-through control flow patchup; note that pc_prevstmt may be
70749 	 * < 0 (i.e. no case clauses), in which case this is a no-op.
70750 	 */
70751 	duk__patch_jump_here(comp_ctx, pc_prevstmt);
70752 
70753 	/* continue jump not patched, an INVALID opcode remains there */
70754 	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */
70755 
70756 	/* Note: 'fast' breaks will jump to pc_label_site + 1, which will
70757 	 * then jump here.  The double jump will be eliminated by a
70758 	 * peephole pass, resulting in an optimal jump here.  The label
70759 	 * site jumps will remain in bytecode and will waste code size.
70760 	 */
70761 
70762 	return;
70763 
70764  syntax_error:
70765 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_SWITCH);
70766 	DUK_WO_NORETURN(return;);
70767 }
70768 
70769 DUK_LOCAL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
70770 	duk_regconst_t temp_reset;
70771 	duk_regconst_t rc_cond;
70772 	duk_int_t pc_jump_false;
70773 
70774 	DUK_DDD(DUK_DDDPRINT("begin parsing if statement"));
70775 
70776 	temp_reset = DUK__GETTEMP(comp_ctx);
70777 
70778 	duk__advance(comp_ctx);  /* eat 'if' */
70779 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
70780 
70781 	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
70782 	duk__emit_if_true_skip(comp_ctx, rc_cond);
70783 	pc_jump_false = duk__emit_jump_empty(comp_ctx);  /* jump to end or else part */
70784 	DUK__SETTEMP(comp_ctx, temp_reset);
70785 
70786 	comp_ctx->curr_func.allow_regexp_in_adv = 1;
70787 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
70788 
70789 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
70790 
70791 	/* The 'else' ambiguity is resolved by 'else' binding to the innermost
70792 	 * construct, so greedy matching is correct here.
70793 	 */
70794 
70795 	if (comp_ctx->curr_token.t == DUK_TOK_ELSE) {
70796 		duk_int_t pc_jump_end;
70797 
70798 		DUK_DDD(DUK_DDDPRINT("if has else part"));
70799 
70800 		duk__advance(comp_ctx);
70801 
70802 		pc_jump_end = duk__emit_jump_empty(comp_ctx);  /* jump from true part to end */
70803 		duk__patch_jump_here(comp_ctx, pc_jump_false);
70804 
70805 		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
70806 
70807 		duk__patch_jump_here(comp_ctx, pc_jump_end);
70808 	} else {
70809 		DUK_DDD(DUK_DDDPRINT("if does not have else part"));
70810 
70811 		duk__patch_jump_here(comp_ctx, pc_jump_false);
70812 	}
70813 
70814 	DUK_DDD(DUK_DDDPRINT("end parsing if statement"));
70815 }
70816 
70817 DUK_LOCAL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
70818 	duk_regconst_t rc_cond;
70819 	duk_int_t pc_start;
70820 
70821 	DUK_DDD(DUK_DDDPRINT("begin parsing do statement"));
70822 
70823 	duk__advance(comp_ctx);  /* Eat 'do'; allow RegExp as part of next stmt. */
70824 
70825 	pc_start = duk__get_current_pc(comp_ctx);
70826 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
70827 	duk__patch_jump_here(comp_ctx, pc_label_site + 2);  /* continue jump */
70828 
70829 	duk__advance_expect(comp_ctx, DUK_TOK_WHILE);
70830 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
70831 
70832 	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
70833 	duk__emit_if_false_skip(comp_ctx, rc_cond);
70834 	duk__emit_jump(comp_ctx, pc_start);
70835 	/* no need to reset temps, as we're finished emitting code */
70836 
70837 	comp_ctx->curr_func.allow_regexp_in_adv = 1;  /* Allow RegExp as part of next stmt. */
70838 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
70839 
70840 	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */
70841 
70842 	DUK_DDD(DUK_DDDPRINT("end parsing do statement"));
70843 }
70844 
70845 DUK_LOCAL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
70846 	duk_regconst_t temp_reset;
70847 	duk_regconst_t rc_cond;
70848 	duk_int_t pc_start;
70849 	duk_int_t pc_jump_false;
70850 
70851 	DUK_DDD(DUK_DDDPRINT("begin parsing while statement"));
70852 
70853 	temp_reset = DUK__GETTEMP(comp_ctx);
70854 
70855 	duk__advance(comp_ctx);  /* eat 'while' */
70856 
70857 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
70858 
70859 	pc_start = duk__get_current_pc(comp_ctx);
70860 	duk__patch_jump_here(comp_ctx, pc_label_site + 2);  /* continue jump */
70861 
70862 	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
70863 	duk__emit_if_true_skip(comp_ctx, rc_cond);
70864 	pc_jump_false = duk__emit_jump_empty(comp_ctx);
70865 	DUK__SETTEMP(comp_ctx, temp_reset);
70866 
70867 	comp_ctx->curr_func.allow_regexp_in_adv = 1;
70868 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
70869 
70870 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
70871 	duk__emit_jump(comp_ctx, pc_start);
70872 
70873 	duk__patch_jump_here(comp_ctx, pc_jump_false);
70874 	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */
70875 
70876 	DUK_DDD(DUK_DDDPRINT("end parsing while statement"));
70877 }
70878 
70879 DUK_LOCAL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
70880 	duk_hthread *thr = comp_ctx->thr;
70881 	duk_bool_t is_break = (comp_ctx->curr_token.t == DUK_TOK_BREAK);
70882 	duk_int_t label_id;
70883 	duk_int_t label_catch_depth;
70884 	duk_int_t label_pc;  /* points to LABEL; pc+1 = jump site for break; pc+2 = jump site for continue */
70885 	duk_bool_t label_is_closest;
70886 
70887 	DUK_UNREF(res);
70888 
70889 	duk__advance(comp_ctx);  /* eat 'break' or 'continue' */
70890 
70891 	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON ||  /* explicit semi follows */
70892 	    comp_ctx->curr_token.lineterm ||                /* automatic semi will be inserted */
70893 	    comp_ctx->curr_token.allow_auto_semi) {         /* automatic semi will be inserted */
70894 		/* break/continue without label */
70895 
70896 		duk__lookup_active_label(comp_ctx, DUK_HTHREAD_STRING_EMPTY_STRING(thr), is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
70897 	} else if (comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER) {
70898 		/* break/continue with label (label cannot be a reserved word, production is 'Identifier' */
70899 		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
70900 		duk__lookup_active_label(comp_ctx, comp_ctx->curr_token.str1, is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
70901 		duk__advance(comp_ctx);
70902 	} else {
70903 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BREAK_CONT_LABEL);
70904 		DUK_WO_NORETURN(return;);
70905 	}
70906 
70907 	/* Use a fast break/continue when possible.  A fast break/continue is
70908 	 * just a jump to the LABEL break/continue jump slot, which then jumps
70909 	 * to an appropriate place (for break, going through ENDLABEL correctly).
70910 	 * The peephole optimizer will optimize the jump to a direct one.
70911 	 */
70912 
70913 	if (label_catch_depth == comp_ctx->curr_func.catch_depth &&
70914 	    label_is_closest) {
70915 		DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
70916 		                     "label_catch_depth=%ld, catch_depth=%ld "
70917 		                     "-> use fast variant (direct jump)",
70918 		                     (long) is_break, (long) label_id, (long) label_is_closest,
70919 		                     (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
70920 
70921 		duk__emit_jump(comp_ctx, label_pc + (is_break ? 1 : 2));
70922 	} else {
70923 		DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
70924 		                     "label_catch_depth=%ld, catch_depth=%ld "
70925 		                     "-> use slow variant (longjmp)",
70926 		                     (long) is_break, (long) label_id, (long) label_is_closest,
70927 		                     (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
70928 
70929 		duk__emit_bc(comp_ctx,
70930 		             is_break ? DUK_OP_BREAK : DUK_OP_CONTINUE,
70931 		             (duk_regconst_t) label_id);
70932 	}
70933 }
70934 
70935 DUK_LOCAL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
70936 	duk_hthread *thr = comp_ctx->thr;
70937 	duk_regconst_t rc_val;
70938 
70939 	duk__advance(comp_ctx);  /* eat 'return' */
70940 
70941 	/* A 'return' statement is only allowed inside an actual function body,
70942 	 * not as part of eval or global code.
70943 	 */
70944 	if (!comp_ctx->curr_func.is_function) {
70945 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_RETURN);
70946 		DUK_WO_NORETURN(return;);
70947 	}
70948 
70949 	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON ||  /* explicit semi follows */
70950 	    comp_ctx->curr_token.lineterm ||                /* automatic semi will be inserted */
70951 	    comp_ctx->curr_token.allow_auto_semi) {         /* automatic semi will be inserted */
70952 		DUK_DDD(DUK_DDDPRINT("empty return value -> undefined"));
70953 		duk__emit_op_only(comp_ctx, DUK_OP_RETUNDEF);
70954 	} else {
70955 		duk_int_t pc_before_expr;
70956 		duk_int_t pc_after_expr;
70957 
70958 		DUK_DDD(DUK_DDDPRINT("return with a value"));
70959 
70960 		DUK_UNREF(pc_before_expr);
70961 		DUK_UNREF(pc_after_expr);
70962 
70963 		pc_before_expr = duk__get_current_pc(comp_ctx);
70964 		rc_val = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
70965 		pc_after_expr = duk__get_current_pc(comp_ctx);
70966 
70967 		/* Tail call check: if last opcode emitted was CALL, and
70968 		 * the context allows it, add a tailcall flag to the CALL.
70969 		 * This doesn't guarantee that a tail call will be allowed at
70970 		 * runtime, so the RETURN must still be emitted.  (Duktape
70971 		 * 0.10.0 avoided this and simulated a RETURN if a tail call
70972 		 * couldn't be used at runtime; but this didn't work
70973 		 * correctly with a thread yield/resume, see
70974 		 * test-bug-tailcall-thread-yield-resume.js for discussion.)
70975 		 *
70976 		 * In addition to the last opcode being CALL, we also need to
70977 		 * be sure that 'rc_val' is the result register of the CALL.
70978 		 * For instance, for the expression 'return 0, (function ()
70979 		 * { return 1; }), 2' the last opcode emitted is CALL (no
70980 		 * bytecode is emitted for '2') but 'rc_val' indicates
70981 		 * constant '2'.  Similarly if '2' is replaced by a register
70982 		 * bound variable, no opcodes are emitted but tail call would
70983 		 * be incorrect.
70984 		 *
70985 		 * This is tricky and easy to get wrong.  It would be best to
70986 		 * track enough expression metadata to check that 'rc_val' came
70987 		 * from that last CALL instruction.  We don't have that metadata
70988 		 * now, so we check that 'rc_val' is a temporary register result
70989 		 * (not a constant or a register bound variable).  There should
70990 		 * be no way currently for 'rc_val' to be a temporary for an
70991 		 * expression following the CALL instruction without emitting
70992 		 * some opcodes following the CALL.  This proxy check is used
70993 		 * below.
70994 		 *
70995 		 * See: test-bug-comma-expr-gh131.js.
70996 		 *
70997 		 * The non-standard 'caller' property disables tail calls
70998 		 * because they pose some special cases which haven't been
70999 		 * fixed yet.
71000 		 */
71001 
71002 #if defined(DUK_USE_TAILCALL)
71003 		if (comp_ctx->curr_func.catch_depth == 0 &&   /* no catchers */
71004 		    pc_after_expr > pc_before_expr) {         /* at least one opcode emitted */
71005 			duk_compiler_instr *instr;
71006 			duk_instr_t ins;
71007 			duk_small_uint_t op;
71008 
71009 			instr = duk__get_instr_ptr(comp_ctx, pc_after_expr - 1);
71010 			DUK_ASSERT(instr != NULL);
71011 
71012 			ins = instr->ins;
71013 			op = (duk_small_uint_t) DUK_DEC_OP(ins);
71014 			if ((op & ~0x0fU) == DUK_OP_CALL0 &&
71015 			    DUK__ISREG_TEMP(comp_ctx, rc_val) /* see above */) {
71016 				DUK_DDD(DUK_DDDPRINT("return statement detected a tail call opportunity: "
71017 				                     "catch depth is 0, duk__exprtop() emitted >= 1 instructions, "
71018 				                     "and last instruction is a CALL "
71019 				                     "-> change to TAILCALL"));
71020 				ins |= DUK_ENC_OP(DUK_BC_CALL_FLAG_TAILCALL);
71021 				instr->ins = ins;
71022 			}
71023 		}
71024 #endif  /* DUK_USE_TAILCALL */
71025 
71026 		if (DUK__ISREG(rc_val)) {
71027 			duk__emit_bc(comp_ctx, DUK_OP_RETREG, rc_val);
71028 		} else {
71029 			rc_val = DUK__REMOVECONST(rc_val);
71030 			if (duk__const_needs_refcount(comp_ctx, rc_val)) {
71031 				duk__emit_bc(comp_ctx, DUK_OP_RETCONST, rc_val);
71032 			} else {
71033 				duk__emit_bc(comp_ctx, DUK_OP_RETCONSTN, rc_val);
71034 			}
71035 		}
71036 	}
71037 }
71038 
71039 DUK_LOCAL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
71040 	duk_regconst_t reg_val;
71041 
71042 	duk__advance(comp_ctx);  /* eat 'throw' */
71043 
71044 	/* Unlike break/continue, throw statement does not allow an empty value. */
71045 
71046 	if (comp_ctx->curr_token.lineterm) {
71047 		DUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_INVALID_THROW);
71048 		DUK_WO_NORETURN(return;);
71049 	}
71050 
71051 	reg_val = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
71052 	duk__emit_bc(comp_ctx,
71053 	             DUK_OP_THROW,
71054 	             reg_val);
71055 }
71056 
71057 DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
71058 	duk_hthread *thr = comp_ctx->thr;
71059 	duk_regconst_t reg_catch;      /* reg_catch+0 and reg_catch+1 are reserved for TRYCATCH */
71060 	duk_regconst_t rc_varname = 0;
71061 	duk_small_uint_t trycatch_flags = 0;
71062 	duk_int_t pc_ldconst = -1;
71063 	duk_int_t pc_trycatch = -1;
71064 	duk_int_t pc_catch = -1;
71065 	duk_int_t pc_finally = -1;
71066 
71067 	DUK_UNREF(res);
71068 
71069 	/*
71070 	 *  See the following documentation for discussion:
71071 	 *
71072 	 *    doc/execution.rst: control flow details
71073 	 *
71074 	 *  Try, catch, and finally "parts" are Blocks, not Statements, so
71075 	 *  they must always be delimited by curly braces.  This is unlike e.g.
71076 	 *  the if statement, which accepts any Statement.  This eliminates any
71077 	 *  questions of matching parts of nested try statements.  The Block
71078 	 *  parsing is implemented inline here (instead of calling out).
71079 	 *
71080 	 *  Finally part has a 'let scoped' variable, which requires a few kinks
71081 	 *  here.
71082 	 */
71083 
71084 	comp_ctx->curr_func.catch_depth++;
71085 
71086 	duk__advance(comp_ctx);  /* eat 'try' */
71087 
71088 	reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
71089 
71090 	/* The target for this LDCONST may need output shuffling, but we assume
71091 	 * that 'pc_ldconst' will be the LDCONST that we can patch later.  This
71092 	 * should be the case because there's no input shuffling.  (If there's
71093 	 * no catch clause, this LDCONST will be replaced with a NOP.)
71094 	 */
71095 	pc_ldconst = duk__get_current_pc(comp_ctx);
71096 	duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, reg_catch, 0 /*patched later*/);
71097 
71098 	pc_trycatch = duk__get_current_pc(comp_ctx);
71099 	duk__emit_invalid(comp_ctx);  /* TRYCATCH, cannot emit now (not enough info) */
71100 	duk__emit_invalid(comp_ctx);  /* jump for 'catch' case */
71101 	duk__emit_invalid(comp_ctx);  /* jump for 'finally' case or end (if no finally) */
71102 
71103 	/* try part */
71104 	duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
71105 	duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
71106 	/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
71107 	duk__emit_op_only(comp_ctx, DUK_OP_ENDTRY);
71108 
71109 	if (comp_ctx->curr_token.t == DUK_TOK_CATCH) {
71110 		/*
71111 		 *  The catch variable must be updated to reflect the new allocated
71112 		 *  register for the duration of the catch clause.  We need to store
71113 		 *  and restore the original value for the varmap entry (if any).
71114 		 */
71115 
71116 		/*
71117 		 *  Note: currently register bindings must be fixed for the entire
71118 		 *  function.  So, even though the catch variable is in a register
71119 		 *  we know, we must use an explicit environment record and slow path
71120 		 *  accesses to read/write the catch binding to make closures created
71121 		 *  within the catch clause work correctly.  This restriction should
71122 		 *  be fixable (at least in common cases) later.
71123 		 *
71124 		 *  See: test-bug-catch-binding-2.js.
71125 		 *
71126 		 *  XXX: improve to get fast path access to most catch clauses.
71127 		 */
71128 
71129 		duk_hstring *h_var;
71130 		duk_int_t varmap_value;  /* for storing/restoring the varmap binding for catch variable */
71131 
71132 		DUK_DDD(DUK_DDDPRINT("stack top at start of catch clause: %ld", (long) duk_get_top(thr)));
71133 
71134 		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_CATCH;
71135 
71136 		pc_catch = duk__get_current_pc(comp_ctx);
71137 
71138 		duk__advance(comp_ctx);
71139 		duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
71140 
71141 		if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
71142 			/* Identifier, i.e. don't allow reserved words */
71143 			goto syntax_error;
71144 		}
71145 		h_var = comp_ctx->curr_token.str1;
71146 		DUK_ASSERT(h_var != NULL);
71147 
71148 		duk_push_hstring(thr, h_var);  /* keep in on valstack, use borrowed ref below */
71149 
71150 		if (comp_ctx->curr_func.is_strict &&
71151 		    ((h_var == DUK_HTHREAD_STRING_EVAL(thr)) ||
71152 		     (h_var == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)))) {
71153 			DUK_DDD(DUK_DDDPRINT("catch identifier 'eval' or 'arguments' in strict mode -> SyntaxError"));
71154 			goto syntax_error;
71155 		}
71156 
71157 		duk_dup_top(thr);
71158 		rc_varname = duk__getconst(comp_ctx);
71159 		DUK_DDD(DUK_DDDPRINT("catch clause, rc_varname=0x%08lx (%ld)",
71160 		                     (unsigned long) rc_varname, (long) rc_varname));
71161 
71162 		duk__advance(comp_ctx);
71163 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
71164 
71165 		duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
71166 
71167 		DUK_DDD(DUK_DDDPRINT("varmap before modifying for catch clause: %!iT",
71168 		                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
71169 
71170 		duk_dup_top(thr);
71171 		duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
71172 		if (duk_is_undefined(thr, -1)) {
71173 			varmap_value = -2;
71174 		} else if (duk_is_null(thr, -1)) {
71175 			varmap_value = -1;
71176 		} else {
71177 			DUK_ASSERT(duk_is_number(thr, -1));
71178 			varmap_value = duk_get_int(thr, -1);
71179 			DUK_ASSERT(varmap_value >= 0);
71180 		}
71181 		duk_pop(thr);
71182 
71183 #if 0
71184 		/* It'd be nice to do something like this - but it doesn't
71185 		 * work for closures created inside the catch clause.
71186 		 */
71187 		duk_dup_top(thr);
71188 		duk_push_int(thr, (duk_int_t) (reg_catch + 0));
71189 		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);
71190 #endif
71191 		duk_dup_top(thr);
71192 		duk_push_null(thr);
71193 		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);
71194 
71195 		duk__emit_a_bc(comp_ctx,
71196 		               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
71197 		               reg_catch + 0 /*value*/,
71198 		               rc_varname /*varname*/);
71199 
71200 		DUK_DDD(DUK_DDDPRINT("varmap before parsing catch clause: %!iT",
71201 		                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
71202 
71203 		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
71204 		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
71205 
71206 		if (varmap_value == -2) {
71207 			/* not present */
71208 			duk_del_prop(thr, comp_ctx->curr_func.varmap_idx);
71209 		} else {
71210 			if (varmap_value == -1) {
71211 				duk_push_null(thr);
71212 			} else {
71213 				DUK_ASSERT(varmap_value >= 0);
71214 				duk_push_int(thr, varmap_value);
71215 			}
71216 			duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);
71217 		}
71218 		/* varname is popped by above code */
71219 
71220 		DUK_DDD(DUK_DDDPRINT("varmap after restore catch clause: %!iT",
71221 		                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
71222 
71223 		duk__emit_op_only(comp_ctx,
71224 		                  DUK_OP_ENDCATCH);
71225 
71226 		/*
71227 		 *  XXX: for now, indicate that an expensive catch binding
71228 		 *  declarative environment is always needed.  If we don't
71229 		 *  need it, we don't need the const_varname either.
71230 		 */
71231 
71232 		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_CATCH_BINDING;
71233 
71234 		DUK_DDD(DUK_DDDPRINT("stack top at end of catch clause: %ld", (long) duk_get_top(thr)));
71235 	}
71236 
71237 	if (comp_ctx->curr_token.t == DUK_TOK_FINALLY) {
71238 		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY;
71239 
71240 		pc_finally = duk__get_current_pc(comp_ctx);
71241 
71242 		duk__advance(comp_ctx);
71243 
71244 		duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
71245 		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
71246 		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
71247 		duk__emit_abc(comp_ctx,
71248 		              DUK_OP_ENDFIN,
71249 		              reg_catch);  /* rethrow */
71250 	}
71251 
71252 	if (!(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) &&
71253 	    !(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY)) {
71254 		/* must have catch and/or finally */
71255 		goto syntax_error;
71256 	}
71257 
71258 	/* If there's no catch block, rc_varname will be 0 and duk__patch_trycatch()
71259 	 * will replace the LDCONST with a NOP.  For any actual constant (including
71260 	 * constant 0) the DUK__CONST_MARKER flag will be set in rc_varname.
71261 	 */
71262 
71263 	duk__patch_trycatch(comp_ctx,
71264 	                    pc_ldconst,
71265 	                    pc_trycatch,
71266 	                    reg_catch,
71267 	                    rc_varname,
71268 	                    trycatch_flags);
71269 
71270 	if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {
71271 		DUK_ASSERT(pc_catch >= 0);
71272 		duk__patch_jump(comp_ctx, pc_trycatch + 1, pc_catch);
71273 	}
71274 
71275 	if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {
71276 		DUK_ASSERT(pc_finally >= 0);
71277 		duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finally);
71278 	} else {
71279 		/* without finally, the second jump slot is used to jump to end of stmt */
71280 		duk__patch_jump_here(comp_ctx, pc_trycatch + 2);
71281 	}
71282 
71283 	comp_ctx->curr_func.catch_depth--;
71284 	return;
71285 
71286  syntax_error:
71287 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_TRY);
71288 	DUK_WO_NORETURN(return;);
71289 }
71290 
71291 DUK_LOCAL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
71292 	duk_int_t pc_trycatch;
71293 	duk_int_t pc_finished;
71294 	duk_regconst_t reg_catch;
71295 	duk_small_uint_t trycatch_flags;
71296 
71297 	if (comp_ctx->curr_func.is_strict) {
71298 		DUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_WITH_IN_STRICT_MODE);
71299 		DUK_WO_NORETURN(return;);
71300 	}
71301 
71302 	comp_ctx->curr_func.catch_depth++;
71303 
71304 	duk__advance(comp_ctx);  /* eat 'with' */
71305 
71306 	reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
71307 
71308 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
71309 	duk__exprtop_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/, reg_catch);
71310 	comp_ctx->curr_func.allow_regexp_in_adv = 1;
71311 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
71312 
71313 	pc_trycatch = duk__get_current_pc(comp_ctx);
71314 	trycatch_flags = DUK_BC_TRYCATCH_FLAG_WITH_BINDING;
71315 	duk__emit_a_bc(comp_ctx,
71316 	                DUK_OP_TRYCATCH | DUK__EMIT_FLAG_NO_SHUFFLE_A,
71317 	                (duk_regconst_t) trycatch_flags /*a*/,
71318 	                reg_catch /*bc*/);
71319 	duk__emit_invalid(comp_ctx);  /* catch jump */
71320 	duk__emit_invalid(comp_ctx);  /* finished jump */
71321 
71322 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
71323 	duk__emit_op_only(comp_ctx, DUK_OP_ENDTRY);
71324 
71325 	pc_finished = duk__get_current_pc(comp_ctx);
71326 
71327 	duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finished);
71328 
71329 	comp_ctx->curr_func.catch_depth--;
71330 }
71331 
71332 DUK_LOCAL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id) {
71333 	/* if a site already exists, nop: max one label site per statement */
71334 	if (label_id >= 0) {
71335 		return label_id;
71336 	}
71337 
71338 	label_id = comp_ctx->curr_func.label_next++;
71339 	DUK_DDD(DUK_DDDPRINT("allocated new label id for label site: %ld", (long) label_id));
71340 
71341 	duk__emit_bc(comp_ctx,
71342 	             DUK_OP_LABEL,
71343 	             (duk_regconst_t) label_id);
71344 	duk__emit_invalid(comp_ctx);
71345 	duk__emit_invalid(comp_ctx);
71346 
71347 	return label_id;
71348 }
71349 
71350 /* Parse a single statement.
71351  *
71352  * Creates a label site (with an empty label) automatically for iteration
71353  * statements.  Also "peels off" any label statements for explicit labels.
71354  */
71355 DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem) {
71356 	duk_hthread *thr = comp_ctx->thr;
71357 	duk_bool_t dir_prol_at_entry;    /* directive prologue status at entry */
71358 	duk_regconst_t temp_at_entry;
71359 	duk_size_t labels_len_at_entry;
71360 	duk_int_t pc_at_entry;           /* assumed to also be PC of "LABEL" */
71361 	duk_int_t stmt_id;
71362 	duk_small_uint_t stmt_flags = 0;
71363 	duk_int_t label_id = -1;
71364 	duk_small_uint_t tok;
71365 	duk_bool_t test_func_decl;
71366 
71367 	DUK__RECURSION_INCREASE(comp_ctx, thr);
71368 
71369 	temp_at_entry = DUK__GETTEMP(comp_ctx);
71370 	pc_at_entry = duk__get_current_pc(comp_ctx);
71371 	labels_len_at_entry = duk_get_length(thr, comp_ctx->curr_func.labelnames_idx);
71372 	stmt_id = comp_ctx->curr_func.stmt_next++;
71373 	dir_prol_at_entry = comp_ctx->curr_func.in_directive_prologue;
71374 
71375 	DUK_UNREF(stmt_id);
71376 
71377 	DUK_DDD(DUK_DDDPRINT("parsing a statement, stmt_id=%ld, temp_at_entry=%ld, labels_len_at_entry=%ld, "
71378 	                     "is_strict=%ld, in_directive_prologue=%ld, catch_depth=%ld",
71379 	                     (long) stmt_id, (long) temp_at_entry, (long) labels_len_at_entry,
71380 	                     (long) comp_ctx->curr_func.is_strict, (long) comp_ctx->curr_func.in_directive_prologue,
71381 	                     (long) comp_ctx->curr_func.catch_depth));
71382 
71383 	/* The directive prologue flag is cleared by default so that it is
71384 	 * unset for any recursive statement parsing.  It is only "revived"
71385 	 * if a directive is detected.  (We could also make directives only
71386 	 * allowed if 'allow_source_elem' was true.)
71387 	 */
71388 	comp_ctx->curr_func.in_directive_prologue = 0;
71389 
71390  retry_parse:
71391 
71392 	DUK_DDD(DUK_DDDPRINT("try stmt parse, stmt_id=%ld, label_id=%ld, allow_source_elem=%ld, catch_depth=%ld",
71393 	                     (long) stmt_id, (long) label_id, (long) allow_source_elem,
71394 	                     (long) comp_ctx->curr_func.catch_depth));
71395 
71396 	/*
71397 	 *  Detect iteration statements; if encountered, establish an
71398 	 *  empty label.
71399 	 */
71400 
71401 	tok = comp_ctx->curr_token.t;
71402 	if (tok == DUK_TOK_FOR || tok == DUK_TOK_DO || tok == DUK_TOK_WHILE ||
71403 	    tok == DUK_TOK_SWITCH) {
71404 		DUK_DDD(DUK_DDDPRINT("iteration/switch statement -> add empty label"));
71405 
71406 		label_id = duk__stmt_label_site(comp_ctx, label_id);
71407 		duk__add_label(comp_ctx,
71408 		               DUK_HTHREAD_STRING_EMPTY_STRING(thr),
71409 		               pc_at_entry /*pc_label*/,
71410 		               label_id);
71411 	}
71412 
71413 	/*
71414 	 *  Main switch for statement / source element type.
71415 	 */
71416 
71417 	switch (comp_ctx->curr_token.t) {
71418 	case DUK_TOK_FUNCTION: {
71419 		/*
71420 		 *  Function declaration, function expression, or (non-standard)
71421 		 *  function statement.
71422 		 *
71423 		 *  The E5 specification only allows function declarations at
71424 		 *  the top level (in "source elements").  An ExpressionStatement
71425 		 *  is explicitly not allowed to begin with a "function" keyword
71426 		 *  (E5 Section 12.4).  Hence any non-error semantics for such
71427 		 *  non-top-level statements are non-standard.  Duktape semantics
71428 		 *  for function statements are modelled after V8, see
71429 		 *  test-dev-func-decl-outside-top.js.
71430 		 */
71431 		test_func_decl = allow_source_elem;
71432 #if defined(DUK_USE_NONSTD_FUNC_STMT)
71433 		/* Lenient: allow function declarations outside top level in
71434 		 * non-strict mode but reject them in strict mode.
71435 		 */
71436 		test_func_decl = test_func_decl || !comp_ctx->curr_func.is_strict;
71437 #endif  /* DUK_USE_NONSTD_FUNC_STMT */
71438 		/* Strict: never allow function declarations outside top level. */
71439 		if (test_func_decl) {
71440 			/* FunctionDeclaration: not strictly a statement but handled as such.
71441 			 *
71442 			 * O(depth^2) parse count for inner functions is handled by recording a
71443 			 * lexer offset on the first compilation pass, so that the function can
71444 			 * be efficiently skipped on the second pass.  This is encapsulated into
71445 			 * duk__parse_func_like_fnum().
71446 			 */
71447 
71448 			duk_int_t fnum;
71449 #if defined(DUK_USE_ASSERTIONS)
71450 			duk_idx_t top_before;
71451 #endif
71452 
71453 			DUK_DDD(DUK_DDDPRINT("function declaration statement"));
71454 
71455 #if defined(DUK_USE_ASSERTIONS)
71456 			top_before = duk_get_top(thr);
71457 #endif
71458 
71459 			duk__advance(comp_ctx);  /* eat 'function' */
71460 			fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_DECL | DUK__FUNC_FLAG_PUSHNAME_PASS1);
71461 
71462 			/* The value stack convention here is a bit odd: the function
71463 			 * name is only pushed on pass 1 (in_scanning), and is needed
71464 			 * to process function declarations.
71465 			 */
71466 			if (comp_ctx->curr_func.in_scanning) {
71467 				duk_uarridx_t n;
71468 
71469 #if defined(DUK_USE_ASSERTIONS)
71470 				DUK_ASSERT(duk_get_top(thr) == top_before + 1);
71471 #endif
71472 				DUK_DDD(DUK_DDDPRINT("register function declaration %!T in pass 1, fnum %ld",
71473 				                     duk_get_tval(thr, -1), (long) fnum));
71474 				n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
71475 				/* funcname is at index -1 */
71476 				duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n);
71477 				duk_push_int(thr, (duk_int_t) (DUK_DECL_TYPE_FUNC + (fnum << 8)));
71478 				duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n + 1);
71479 			} else {
71480 #if defined(DUK_USE_ASSERTIONS)
71481 				DUK_ASSERT(duk_get_top(thr) == top_before);
71482 #endif
71483 			}
71484 
71485 			/* no statement value (unlike function expression) */
71486 			stmt_flags = 0;
71487 			break;
71488 		} else {
71489 			DUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_STMT_NOT_ALLOWED);
71490 			DUK_WO_NORETURN(return;);
71491 		}
71492 		break;
71493 	}
71494 	case DUK_TOK_LCURLY: {
71495 		DUK_DDD(DUK_DDDPRINT("block statement"));
71496 		duk__advance(comp_ctx);
71497 		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
71498 		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
71499 		if (label_id >= 0) {
71500 			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
71501 		}
71502 		stmt_flags = 0;
71503 		break;
71504 	}
71505 	case DUK_TOK_CONST: {
71506 		DUK_DDD(DUK_DDDPRINT("constant declaration statement"));
71507 		duk__parse_var_stmt(comp_ctx, res, DUK__EXPR_FLAG_REQUIRE_INIT /*expr_flags*/);
71508 		stmt_flags = DUK__HAS_TERM;
71509 		break;
71510 	}
71511 	case DUK_TOK_VAR: {
71512 		DUK_DDD(DUK_DDDPRINT("variable declaration statement"));
71513 		duk__parse_var_stmt(comp_ctx, res, 0 /*expr_flags*/);
71514 		stmt_flags = DUK__HAS_TERM;
71515 		break;
71516 	}
71517 	case DUK_TOK_SEMICOLON: {
71518 		/* empty statement with an explicit semicolon */
71519 		DUK_DDD(DUK_DDDPRINT("empty statement"));
71520 		stmt_flags = DUK__HAS_TERM;
71521 		break;
71522 	}
71523 	case DUK_TOK_IF: {
71524 		DUK_DDD(DUK_DDDPRINT("if statement"));
71525 		duk__parse_if_stmt(comp_ctx, res);
71526 		if (label_id >= 0) {
71527 			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
71528 		}
71529 		stmt_flags = 0;
71530 		break;
71531 	}
71532 	case DUK_TOK_DO: {
71533 		/*
71534 		 *  Do-while statement is mostly trivial, but there is special
71535 		 *  handling for automatic semicolon handling (triggered by the
71536 		 *  DUK__ALLOW_AUTO_SEMI_ALWAYS) flag related to a bug filed at:
71537 		 *
71538 		 *    https://bugs.ecmascript.org/show_bug.cgi?id=8
71539 		 *
71540 		 *  See doc/compiler.rst for details.
71541 		 */
71542 		DUK_DDD(DUK_DDDPRINT("do statement"));
71543 		DUK_ASSERT(label_id >= 0);
71544 		duk__update_label_flags(comp_ctx,
71545 		                        label_id,
71546 		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
71547 		duk__parse_do_stmt(comp_ctx, res, pc_at_entry);
71548 		stmt_flags = DUK__HAS_TERM | DUK__ALLOW_AUTO_SEMI_ALWAYS;  /* DUK__ALLOW_AUTO_SEMI_ALWAYS workaround */
71549 		break;
71550 	}
71551 	case DUK_TOK_WHILE: {
71552 		DUK_DDD(DUK_DDDPRINT("while statement"));
71553 		DUK_ASSERT(label_id >= 0);
71554 		duk__update_label_flags(comp_ctx,
71555 		                        label_id,
71556 		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
71557 		duk__parse_while_stmt(comp_ctx, res, pc_at_entry);
71558 		stmt_flags = 0;
71559 		break;
71560 	}
71561 	case DUK_TOK_FOR: {
71562 		/*
71563 		 *  For/for-in statement is complicated to parse because
71564 		 *  determining the statement type (three-part for vs. a
71565 		 *  for-in) requires potential backtracking.
71566 		 *
71567 		 *  See the helper for the messy stuff.
71568 		 */
71569 		DUK_DDD(DUK_DDDPRINT("for/for-in statement"));
71570 		DUK_ASSERT(label_id >= 0);
71571 		duk__update_label_flags(comp_ctx,
71572 		                        label_id,
71573 		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
71574 		duk__parse_for_stmt(comp_ctx, res, pc_at_entry);
71575 		stmt_flags = 0;
71576 		break;
71577 	}
71578 	case DUK_TOK_CONTINUE:
71579 	case DUK_TOK_BREAK: {
71580 		DUK_DDD(DUK_DDDPRINT("break/continue statement"));
71581 		duk__parse_break_or_continue_stmt(comp_ctx, res);
71582 		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
71583 		break;
71584 	}
71585 	case DUK_TOK_RETURN: {
71586 		DUK_DDD(DUK_DDDPRINT("return statement"));
71587 		duk__parse_return_stmt(comp_ctx, res);
71588 		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
71589 		break;
71590 	}
71591 	case DUK_TOK_WITH: {
71592 		DUK_DDD(DUK_DDDPRINT("with statement"));
71593 		comp_ctx->curr_func.with_depth++;
71594 		duk__parse_with_stmt(comp_ctx, res);
71595 		if (label_id >= 0) {
71596 			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
71597 		}
71598 		comp_ctx->curr_func.with_depth--;
71599 		stmt_flags = 0;
71600 		break;
71601 	}
71602 	case DUK_TOK_SWITCH: {
71603 		/*
71604 		 *  The switch statement is pretty messy to compile.
71605 		 *  See the helper for details.
71606 		 */
71607 		DUK_DDD(DUK_DDDPRINT("switch statement"));
71608 		DUK_ASSERT(label_id >= 0);
71609 		duk__update_label_flags(comp_ctx,
71610 		                        label_id,
71611 		                        DUK_LABEL_FLAG_ALLOW_BREAK);  /* don't allow continue */
71612 		duk__parse_switch_stmt(comp_ctx, res, pc_at_entry);
71613 		stmt_flags = 0;
71614 		break;
71615 	}
71616 	case DUK_TOK_THROW: {
71617 		DUK_DDD(DUK_DDDPRINT("throw statement"));
71618 		duk__parse_throw_stmt(comp_ctx, res);
71619 		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
71620 		break;
71621 	}
71622 	case DUK_TOK_TRY: {
71623 		DUK_DDD(DUK_DDDPRINT("try statement"));
71624 		duk__parse_try_stmt(comp_ctx, res);
71625 		stmt_flags = 0;
71626 		break;
71627 	}
71628 	case DUK_TOK_DEBUGGER: {
71629 		duk__advance(comp_ctx);
71630 #if defined(DUK_USE_DEBUGGER_SUPPORT)
71631 		DUK_DDD(DUK_DDDPRINT("debugger statement: debugging enabled, emit debugger opcode"));
71632 		duk__emit_op_only(comp_ctx, DUK_OP_DEBUGGER);
71633 #else
71634 		DUK_DDD(DUK_DDDPRINT("debugger statement: ignored"));
71635 #endif
71636 		stmt_flags = DUK__HAS_TERM;
71637 		break;
71638 	}
71639 	default: {
71640 		/*
71641 		 *  Else, must be one of:
71642 		 *    - ExpressionStatement, possibly a directive (String)
71643 		 *    - LabelledStatement (Identifier followed by ':')
71644 		 *
71645 		 *  Expressions beginning with 'function' keyword are covered by a case
71646 		 *  above (such expressions are not allowed in standard E5 anyway).
71647 		 *  Also expressions starting with '{' are interpreted as block
71648 		 *  statements.  See E5 Section 12.4.
71649 		 *
71650 		 *  Directive detection is tricky; see E5 Section 14.1 on directive
71651 		 *  prologue.  A directive is an expression statement with a single
71652 		 *  string literal and an explicit or automatic semicolon.  Escape
71653 		 *  characters are significant and no parens etc are allowed:
71654 		 *
71655 		 *    'use strict';          // valid 'use strict' directive
71656 		 *    'use\u0020strict';     // valid directive, not a 'use strict' directive
71657 		 *    ('use strict');        // not a valid directive
71658 		 *
71659 		 *  The expression is determined to consist of a single string literal
71660 		 *  based on duk__expr_nud() and duk__expr_led() call counts.  The string literal
71661 		 *  of a 'use strict' directive is determined to lack any escapes based
71662 		 *  num_escapes count from the lexer.  Note that other directives may be
71663 		 *  allowed to contain escapes, so a directive with escapes does not
71664 		 *  terminate a directive prologue.
71665 		 *
71666 		 *  We rely on the fact that the expression parser will not emit any
71667 		 *  code for a single token expression.  However, it will generate an
71668 		 *  intermediate value which we will then successfully ignore.
71669 		 *
71670 		 *  A similar approach is used for labels.
71671 		 */
71672 
71673 		duk_bool_t single_token;
71674 
71675 		DUK_DDD(DUK_DDDPRINT("expression statement"));
71676 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
71677 
71678 		single_token = (comp_ctx->curr_func.nud_count == 1 &&  /* one token */
71679 		                comp_ctx->curr_func.led_count == 0);   /* no operators */
71680 
71681 		if (single_token &&
71682 		    comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
71683 		    comp_ctx->curr_token.t == DUK_TOK_COLON) {
71684 			/*
71685 			 *  Detected label
71686 			 */
71687 
71688 			duk_hstring *h_lab;
71689 
71690 			/* expected ival */
71691 			DUK_ASSERT(res->t == DUK_IVAL_VAR);
71692 			DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
71693 			DUK_ASSERT(DUK_TVAL_IS_STRING(duk_get_tval(thr, res->x1.valstack_idx)));
71694 			h_lab = comp_ctx->prev_token.str1;
71695 			DUK_ASSERT(h_lab != NULL);
71696 
71697 			DUK_DDD(DUK_DDDPRINT("explicit label site for label '%!O'",
71698 			                     (duk_heaphdr *) h_lab));
71699 
71700 			duk__advance(comp_ctx);  /* eat colon */
71701 
71702 			label_id = duk__stmt_label_site(comp_ctx, label_id);
71703 
71704 			duk__add_label(comp_ctx,
71705 			               h_lab,
71706 			               pc_at_entry /*pc_label*/,
71707 			               label_id);
71708 
71709 			/* a statement following a label cannot be a source element
71710 			 * (a function declaration).
71711 			 */
71712 			allow_source_elem = 0;
71713 
71714 			DUK_DDD(DUK_DDDPRINT("label handled, retry statement parsing"));
71715 			goto retry_parse;
71716 		}
71717 
71718 		stmt_flags = 0;
71719 
71720 		if (dir_prol_at_entry &&                           /* still in prologue */
71721 		    single_token &&                                /* single string token */
71722 		    comp_ctx->prev_token.t == DUK_TOK_STRING) {
71723 			/*
71724 			 *  Detected a directive
71725 			 */
71726 			duk_hstring *h_dir;
71727 
71728 			/* expected ival */
71729 			DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
71730 			DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
71731 			DUK_ASSERT(DUK_TVAL_IS_STRING(duk_get_tval(thr, res->x1.valstack_idx)));
71732 			h_dir = comp_ctx->prev_token.str1;
71733 			DUK_ASSERT(h_dir != NULL);
71734 
71735 			DUK_DDD(DUK_DDDPRINT("potential directive: %!O", h_dir));
71736 
71737 			stmt_flags |= DUK__STILL_PROLOGUE;
71738 
71739 			/* Note: escaped characters differentiate directives */
71740 
71741 			if (comp_ctx->prev_token.num_escapes > 0) {
71742 				DUK_DDD(DUK_DDDPRINT("directive contains escapes: valid directive "
71743 				                     "but we ignore such directives"));
71744 			} else {
71745 				/*
71746 				 * The length comparisons are present to handle
71747 				 * strings like "use strict\u0000foo" as required.
71748 				 */
71749 
71750 				if (DUK_HSTRING_GET_BYTELEN(h_dir) == 10 &&
71751 				    DUK_STRCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use strict") == 0) {
71752 #if defined(DUK_USE_STRICT_DECL)
71753 					DUK_DDD(DUK_DDDPRINT("use strict directive detected: strict flag %ld -> %ld",
71754 					                     (long) comp_ctx->curr_func.is_strict, (long) 1));
71755 					comp_ctx->curr_func.is_strict = 1;
71756 #else
71757 					DUK_DDD(DUK_DDDPRINT("use strict detected but strict declarations disabled, ignoring"));
71758 #endif
71759 				} else if (DUK_HSTRING_GET_BYTELEN(h_dir) == 14 &&
71760 				           DUK_STRCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use duk notail") == 0) {
71761 					DUK_DDD(DUK_DDDPRINT("use duk notail directive detected: notail flag %ld -> %ld",
71762 					                     (long) comp_ctx->curr_func.is_notail, (long) 1));
71763 					comp_ctx->curr_func.is_notail = 1;
71764 				} else {
71765 					DUK_DD(DUK_DDPRINT("unknown directive: '%!O', ignoring but not terminating "
71766 					                   "directive prologue", (duk_hobject *) h_dir));
71767 				}
71768 			}
71769 		} else {
71770 			DUK_DDD(DUK_DDDPRINT("non-directive expression statement or no longer in prologue; "
71771 			                     "prologue terminated if still active"));
71772                 }
71773 
71774 		stmt_flags |= DUK__HAS_VAL | DUK__HAS_TERM;
71775 	}
71776 	}  /* end switch (tok) */
71777 
71778 	/*
71779 	 *  Statement value handling.
71780 	 *
71781 	 *  Global code and eval code has an implicit return value
71782 	 *  which comes from the last statement with a value
71783 	 *  (technically a non-"empty" continuation, which is
71784 	 *  different from an empty statement).
71785 	 *
71786 	 *  Since we don't know whether a later statement will
71787 	 *  override the value of the current statement, we need
71788 	 *  to coerce the statement value to a register allocated
71789 	 *  for implicit return values.  In other cases we need
71790 	 *  to coerce the statement value to a plain value to get
71791 	 *  any side effects out (consider e.g. "foo.bar;").
71792 	 */
71793 
71794 	/* XXX: what about statements which leave a half-cooked value in 'res'
71795 	 * but have no stmt value?  Any such statements?
71796 	 */
71797 
71798 	if (stmt_flags & DUK__HAS_VAL) {
71799 		duk_regconst_t reg_stmt_value = comp_ctx->curr_func.reg_stmt_value;
71800 		if (reg_stmt_value >= 0) {
71801 			duk__ivalue_toforcedreg(comp_ctx, res, reg_stmt_value);
71802 		} else {
71803 			duk__ivalue_toplain_ignore(comp_ctx, res);
71804 		}
71805 	} else {
71806 		;
71807 	}
71808 
71809 	/*
71810 	 *  Statement terminator check, including automatic semicolon
71811 	 *  handling.  After this step, 'curr_tok' should be the first
71812 	 *  token after a possible statement terminator.
71813 	 */
71814 
71815 	if (stmt_flags & DUK__HAS_TERM) {
71816 		if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON) {
71817 			DUK_DDD(DUK_DDDPRINT("explicit semicolon terminates statement"));
71818 			duk__advance(comp_ctx);
71819 		} else {
71820 			if (comp_ctx->curr_token.allow_auto_semi) {
71821 				DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement"));
71822 			} else if (stmt_flags & DUK__ALLOW_AUTO_SEMI_ALWAYS) {
71823 				/* XXX: make this lenience dependent on flags or strictness? */
71824 				DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement (allowed for compatibility "
71825 				                     "even though no lineterm present before next token)"));
71826 			} else {
71827 				DUK_ERROR_SYNTAX(thr, DUK_STR_UNTERMINATED_STMT);
71828 				DUK_WO_NORETURN(return;);
71829 			}
71830 		}
71831 	} else {
71832 		DUK_DDD(DUK_DDDPRINT("statement has no terminator"));
71833 	}
71834 
71835 	/*
71836 	 *  Directive prologue tracking.
71837 	 */
71838 
71839 	if (stmt_flags & DUK__STILL_PROLOGUE) {
71840 		DUK_DDD(DUK_DDDPRINT("setting in_directive_prologue"));
71841 		comp_ctx->curr_func.in_directive_prologue = 1;
71842 	}
71843 
71844 	/*
71845 	 *  Cleanups (all statement parsing flows through here).
71846 	 *
71847 	 *  Pop label site and reset labels.  Reset 'next temp' to value at
71848 	 *  entry to reuse temps.
71849 	 */
71850 
71851 	if (label_id >= 0) {
71852 		duk__emit_bc(comp_ctx,
71853 		             DUK_OP_ENDLABEL,
71854 		             (duk_regconst_t) label_id);
71855 	}
71856 
71857 	DUK__SETTEMP(comp_ctx, temp_at_entry);
71858 
71859 	duk__reset_labels_to_length(comp_ctx, labels_len_at_entry);
71860 
71861 	/* XXX: return indication of "terminalness" (e.g. a 'throw' is terminal) */
71862 
71863 	DUK__RECURSION_DECREASE(comp_ctx, thr);
71864 }
71865 
71866 /*
71867  *  Parse a statement list.
71868  *
71869  *  Handles automatic semicolon insertion and implicit return value.
71870  *
71871  *  Upon entry, 'curr_tok' should contain the first token of the first
71872  *  statement (parsed in the "allow regexp literal" mode).  Upon exit,
71873  *  'curr_tok' contains the token following the statement list terminator
71874  *  (EOF or closing brace).
71875  */
71876 
71877 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) {
71878 	duk_hthread *thr = comp_ctx->thr;
71879 	duk_ivalue res_alloc;
71880 	duk_ivalue *res = &res_alloc;
71881 
71882 	/* Setup state.  Initial ivalue is 'undefined'. */
71883 
71884 	duk_require_stack(thr, DUK__PARSE_STATEMENTS_SLOTS);
71885 
71886 	/* XXX: 'res' setup can be moved to function body level; in fact, two 'res'
71887 	 * intermediate values suffice for parsing of each function.  Nesting is needed
71888 	 * for nested functions (which may occur inside expressions).
71889 	 */
71890 
71891 	duk_memzero(&res_alloc, sizeof(res_alloc));
71892 	res->t = DUK_IVAL_PLAIN;
71893 	res->x1.t = DUK_ISPEC_VALUE;
71894 	res->x1.valstack_idx = duk_get_top(thr);
71895 	res->x2.valstack_idx = res->x1.valstack_idx + 1;
71896 	duk_push_undefined(thr);
71897 	duk_push_undefined(thr);
71898 
71899 	/* Parse statements until a closing token (EOF or '}') is found. */
71900 
71901 	for (;;) {
71902 		/* Check whether statement list ends. */
71903 
71904 		if (expect_eof) {
71905 			if (comp_ctx->curr_token.t == DUK_TOK_EOF) {
71906 				break;
71907 			}
71908 		} else {
71909 			if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
71910 				break;
71911 			}
71912 		}
71913 
71914 		/* Check statement type based on the first token type.
71915 		 *
71916 		 * Note: expression parsing helpers expect 'curr_tok' to
71917 		 * contain the first token of the expression upon entry.
71918 		 */
71919 
71920 		DUK_DDD(DUK_DDDPRINT("TOKEN %ld (non-whitespace, non-comment)", (long) comp_ctx->curr_token.t));
71921 
71922 		duk__parse_stmt(comp_ctx, res, allow_source_elem);
71923 	}
71924 
71925 	/* RegExp is allowed / not allowed depending on context.  For function
71926 	 * declarations RegExp is allowed because it follows a function
71927 	 * declaration statement and may appear as part of the next statement.
71928 	 * For function expressions RegExp is not allowed, and it's possible
71929 	 * to do something like '(function () {} / 123)'.
71930 	 */
71931 	if (regexp_after) {
71932 		comp_ctx->curr_func.allow_regexp_in_adv = 1;
71933 	}
71934 	duk__advance(comp_ctx);
71935 
71936 	/* Tear down state. */
71937 
71938 	duk_pop_2(thr);
71939 }
71940 
71941 /*
71942  *  Declaration binding instantiation conceptually happens when calling a
71943  *  function; for us it essentially means that function prologue.  The
71944  *  conceptual process is described in E5 Section 10.5.
71945  *
71946  *  We need to keep track of all encountered identifiers to (1) create an
71947  *  identifier-to-register map ("varmap"); and (2) detect duplicate
71948  *  declarations.  Identifiers which are not bound to registers still need
71949  *  to be tracked for detecting duplicates.  Currently such identifiers
71950  *  are put into the varmap with a 'null' value, which is later cleaned up.
71951  *
71952  *  To support functions with a large number of variable and function
71953  *  declarations, registers are not allocated beyond a certain limit;
71954  *  after that limit, variables and functions need slow path access.
71955  *  Arguments are currently always register bound, which imposes a hard
71956  *  (and relatively small) argument count limit.
71957  *
71958  *  Some bindings in E5 are not configurable (= deletable) and almost all
71959  *  are mutable (writable).  Exceptions are:
71960  *
71961  *    - The 'arguments' binding, established only if no shadowing argument
71962  *      or function declaration exists.  We handle 'arguments' creation
71963  *      and binding through an explicit slow path environment record.
71964  *
71965  *    - The "name" binding for a named function expression.  This is also
71966  *      handled through an explicit slow path environment record.
71967  */
71968 
71969 /* XXX: add support for variables to not be register bound always, to
71970  * handle cases with a very large number of variables?
71971  */
71972 
71973 DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_regconst_t *out_stmt_value_reg) {
71974 	duk_hthread *thr = comp_ctx->thr;
71975 	duk_hstring *h_name;
71976 	duk_bool_t configurable_bindings;
71977 	duk_uarridx_t num_args;
71978 	duk_uarridx_t num_decls;
71979 	duk_regconst_t rc_name;
71980 	duk_small_uint_t declvar_flags;
71981 	duk_uarridx_t i;
71982 #if defined(DUK_USE_ASSERTIONS)
71983 	duk_idx_t entry_top;
71984 #endif
71985 
71986 #if defined(DUK_USE_ASSERTIONS)
71987 	entry_top = duk_get_top(thr);
71988 #endif
71989 
71990 	/*
71991 	 *  Preliminaries
71992 	 */
71993 
71994 	configurable_bindings = comp_ctx->curr_func.is_eval;
71995 	DUK_DDD(DUK_DDDPRINT("configurable_bindings=%ld", (long) configurable_bindings));
71996 
71997 	/* varmap is already in comp_ctx->curr_func.varmap_idx */
71998 
71999 	/*
72000 	 *  Function formal arguments, always bound to registers
72001 	 *  (there's no support for shuffling them now).
72002 	 */
72003 
72004 	num_args = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.argnames_idx);
72005 	DUK_DDD(DUK_DDDPRINT("num_args=%ld", (long) num_args));
72006 	/* XXX: check num_args */
72007 
72008 	for (i = 0; i < num_args; i++) {
72009 		duk_get_prop_index(thr, comp_ctx->curr_func.argnames_idx, i);
72010 		h_name = duk_known_hstring(thr, -1);
72011 
72012 		if (comp_ctx->curr_func.is_strict) {
72013 			if (duk__hstring_is_eval_or_arguments(comp_ctx, h_name)) {
72014 				DUK_DDD(DUK_DDDPRINT("arg named 'eval' or 'arguments' in strict mode -> SyntaxError"));
72015 				goto error_argname;
72016 			}
72017 			duk_dup_top(thr);
72018 			if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
72019 				DUK_DDD(DUK_DDDPRINT("duplicate arg name in strict mode -> SyntaxError"));
72020 				goto error_argname;
72021 			}
72022 
72023 			/* Ensure argument name is not a reserved word in current
72024 			 * (final) strictness.  Formal argument parsing may not
72025 			 * catch reserved names if strictness changes during
72026 			 * parsing.
72027 			 *
72028 			 * We only need to do this in strict mode because non-strict
72029 			 * keyword are always detected in formal argument parsing.
72030 			 */
72031 
72032 			if (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(h_name)) {
72033 				goto error_argname;
72034 			}
72035 		}
72036 
72037 		/* overwrite any previous binding of the same name; the effect is
72038 		 * that last argument of a certain name wins.
72039 		 */
72040 
72041 		/* only functions can have arguments */
72042 		DUK_ASSERT(comp_ctx->curr_func.is_function);
72043 		duk_push_uarridx(thr, i);  /* -> [ ... name index ] */
72044 		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx); /* -> [ ... ] */
72045 
72046 		/* no code needs to be emitted, the regs already have values */
72047 	}
72048 
72049 	/* use temp_next for tracking register allocations */
72050 	DUK__SETTEMP_CHECKMAX(comp_ctx, (duk_regconst_t) num_args);
72051 
72052 	/*
72053 	 *  After arguments, allocate special registers (like shuffling temps)
72054 	 */
72055 
72056 	if (out_stmt_value_reg) {
72057 		*out_stmt_value_reg = DUK__ALLOCTEMP(comp_ctx);
72058 	}
72059 	if (comp_ctx->curr_func.needs_shuffle) {
72060 		duk_regconst_t shuffle_base = DUK__ALLOCTEMPS(comp_ctx, 3);
72061 		comp_ctx->curr_func.shuffle1 = shuffle_base;
72062 		comp_ctx->curr_func.shuffle2 = shuffle_base + 1;
72063 		comp_ctx->curr_func.shuffle3 = shuffle_base + 2;
72064 		DUK_D(DUK_DPRINT("shuffle registers needed by function, allocated: %ld %ld %ld",
72065 		                 (long) comp_ctx->curr_func.shuffle1,
72066 		                 (long) comp_ctx->curr_func.shuffle2,
72067 		                 (long) comp_ctx->curr_func.shuffle3));
72068 	}
72069 	if (comp_ctx->curr_func.temp_next > 0x100) {
72070 		DUK_D(DUK_DPRINT("not enough 8-bit regs: temp_next=%ld", (long) comp_ctx->curr_func.temp_next));
72071 		goto error_outofregs;
72072 	}
72073 
72074 	/*
72075 	 *  Function declarations
72076 	 */
72077 
72078 	num_decls = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
72079 	DUK_DDD(DUK_DDDPRINT("num_decls=%ld -> %!T",
72080 	                     (long) num_decls,
72081 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.decls_idx)));
72082 	for (i = 0; i < num_decls; i += 2) {
72083 		duk_int_t decl_type;
72084 		duk_int_t fnum;
72085 
72086 		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i + 1);  /* decl type */
72087 		decl_type = duk_to_int(thr, -1);
72088 		fnum = decl_type >> 8;  /* XXX: macros */
72089 		decl_type = decl_type & 0xff;
72090 		duk_pop(thr);
72091 
72092 		if (decl_type != DUK_DECL_TYPE_FUNC) {
72093 			continue;
72094 		}
72095 
72096 		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */
72097 
72098 		/* XXX: spilling */
72099 		if (comp_ctx->curr_func.is_function) {
72100 			duk_regconst_t reg_bind;
72101 			duk_dup_top(thr);
72102 			if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
72103 				/* shadowed; update value */
72104 				duk_dup_top(thr);
72105 				duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
72106 				reg_bind = duk_to_int(thr, -1);  /* [ ... name reg_bind ] */
72107 				duk__emit_a_bc(comp_ctx,
72108 				               DUK_OP_CLOSURE,
72109 				               reg_bind,
72110 				               (duk_regconst_t) fnum);
72111 			} else {
72112 				/* function: always register bound */
72113 				reg_bind = DUK__ALLOCTEMP(comp_ctx);
72114 				duk__emit_a_bc(comp_ctx,
72115 				               DUK_OP_CLOSURE,
72116 				               reg_bind,
72117 				               (duk_regconst_t) fnum);
72118 				duk_push_int(thr, (duk_int_t) reg_bind);
72119 			}
72120 		} else {
72121 			/* Function declaration for global/eval code is emitted even
72122 			 * for duplicates, because of E5 Section 10.5, step 5.e of
72123 			 * E5.1 (special behavior for variable bound to global object).
72124 			 *
72125 			 * DECLVAR will not re-declare a variable as such, but will
72126 			 * update the binding value.
72127 			 */
72128 
72129 			duk_regconst_t reg_temp = DUK__ALLOCTEMP(comp_ctx);
72130 			duk_dup_top(thr);
72131 			rc_name = duk__getconst(comp_ctx);
72132 			duk_push_null(thr);
72133 
72134 			duk__emit_a_bc(comp_ctx,
72135 			               DUK_OP_CLOSURE,
72136 			               reg_temp,
72137 			               (duk_regconst_t) fnum);
72138 
72139 			declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
72140 			                DUK_PROPDESC_FLAG_ENUMERABLE |
72141 			                DUK_BC_DECLVAR_FLAG_FUNC_DECL;
72142 
72143 			if (configurable_bindings) {
72144 				declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
72145 			}
72146 
72147 			duk__emit_a_b_c(comp_ctx,
72148 			                DUK_OP_DECLVAR | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_BC_REGCONST,
72149 			                (duk_regconst_t) declvar_flags /*flags*/,
72150 			                rc_name /*name*/,
72151 			                reg_temp /*value*/);
72152 
72153 			DUK__SETTEMP(comp_ctx, reg_temp);  /* forget temp */
72154 		}
72155 
72156 		DUK_DDD(DUK_DDDPRINT("function declaration to varmap: %!T -> %!T",
72157 		                     (duk_tval *) duk_get_tval(thr, -2),
72158 		                     (duk_tval *) duk_get_tval(thr, -1)));
72159 
72160 #if defined(DUK_USE_FASTINT)
72161 		DUK_ASSERT(DUK_TVAL_IS_NULL(duk_get_tval(thr, -1)) || DUK_TVAL_IS_FASTINT(duk_get_tval(thr, -1)));
72162 #endif
72163 		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);  /* [ ... name reg/null ] -> [ ... ] */
72164 	}
72165 
72166 	/*
72167 	 *  'arguments' binding is special; if a shadowing argument or
72168 	 *  function declaration exists, an arguments object will
72169 	 *  definitely not be needed, regardless of whether the identifier
72170 	 *  'arguments' is referenced inside the function body.
72171 	 */
72172 
72173 	if (duk_has_prop_stridx(thr, comp_ctx->curr_func.varmap_idx, DUK_STRIDX_LC_ARGUMENTS)) {
72174 		DUK_DDD(DUK_DDDPRINT("'arguments' is shadowed by argument or function declaration "
72175 		                     "-> arguments object creation can be skipped"));
72176 		comp_ctx->curr_func.is_arguments_shadowed = 1;
72177 	}
72178 
72179 	/*
72180 	 *  Variable declarations.
72181 	 *
72182 	 *  Unlike function declarations, variable declaration values don't get
72183 	 *  assigned on entry.  If a binding of the same name already exists, just
72184 	 *  ignore it silently.
72185 	 */
72186 
72187 	for (i = 0; i < num_decls; i += 2) {
72188 		duk_int_t decl_type;
72189 
72190 		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i + 1);  /* decl type */
72191 		decl_type = duk_to_int(thr, -1);
72192 		decl_type = decl_type & 0xff;
72193 		duk_pop(thr);
72194 
72195 		if (decl_type != DUK_DECL_TYPE_VAR) {
72196 			continue;
72197 		}
72198 
72199 		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */
72200 
72201 		if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
72202 			/* shadowed, ignore */
72203 		} else {
72204 			duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */
72205 			h_name = duk_known_hstring(thr, -1);
72206 
72207 			if (h_name == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr) &&
72208 			    !comp_ctx->curr_func.is_arguments_shadowed) {
72209 				/* E5 Section steps 7-8 */
72210 				DUK_DDD(DUK_DDDPRINT("'arguments' not shadowed by a function declaration, "
72211 				                     "but appears as a variable declaration -> treat as "
72212 				                     "a no-op for variable declaration purposes"));
72213 				duk_pop(thr);
72214 				continue;
72215 			}
72216 
72217 			/* XXX: spilling */
72218 			if (comp_ctx->curr_func.is_function) {
72219 				duk_regconst_t reg_bind = DUK__ALLOCTEMP(comp_ctx);
72220 				/* no need to init reg, it will be undefined on entry */
72221 				duk_push_int(thr, (duk_int_t) reg_bind);
72222 			} else {
72223 				duk_dup_top(thr);
72224 				rc_name = duk__getconst(comp_ctx);
72225 				duk_push_null(thr);
72226 
72227 				declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
72228 			                        DUK_PROPDESC_FLAG_ENUMERABLE;
72229 				if (configurable_bindings) {
72230 					declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
72231 				}
72232 
72233 				duk__emit_a_b_c(comp_ctx,
72234 				                DUK_OP_DECLVAR | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_BC_REGCONST,
72235 				                (duk_regconst_t) declvar_flags /*flags*/,
72236 				                rc_name /*name*/,
72237 				                0 /*value*/);
72238 			}
72239 
72240 			duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);  /* [ ... name reg/null ] -> [ ... ] */
72241 		}
72242 	}
72243 
72244 	/*
72245 	 *  Wrap up
72246 	 */
72247 
72248 	DUK_DDD(DUK_DDDPRINT("varmap: %!T, is_arguments_shadowed=%ld",
72249 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx),
72250 	                     (long) comp_ctx->curr_func.is_arguments_shadowed));
72251 
72252 	DUK_ASSERT_TOP(thr, entry_top);
72253 	return;
72254 
72255  error_outofregs:
72256 	DUK_ERROR_RANGE(thr, DUK_STR_REG_LIMIT);
72257 	DUK_WO_NORETURN(return;);
72258 
72259  error_argname:
72260 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARG_NAME);
72261 	DUK_WO_NORETURN(return;);
72262 }
72263 
72264 /*
72265  *  Parse a function-body-like expression (FunctionBody or Program
72266  *  in E5 grammar) using a two-pass parse.  The productions appear
72267  *  in the following contexts:
72268  *
72269  *    - function expression
72270  *    - function statement
72271  *    - function declaration
72272  *    - getter in object literal
72273  *    - setter in object literal
72274  *    - global code
72275  *    - eval code
72276  *    - Function constructor body
72277  *
72278  *  This function only parses the statement list of the body; the argument
72279  *  list and possible function name must be initialized by the caller.
72280  *  For instance, for Function constructor, the argument names are originally
72281  *  on the value stack.  The parsing of statements ends either at an EOF or
72282  *  a closing brace; this is controlled by an input flag.
72283  *
72284  *  Note that there are many differences affecting parsing and even code
72285  *  generation:
72286  *
72287  *    - Global and eval code have an implicit return value generated
72288  *      by the last statement; function code does not
72289  *
72290  *    - Global code, eval code, and Function constructor body end in
72291  *      an EOF, other bodies in a closing brace ('}')
72292  *
72293  *  Upon entry, 'curr_tok' is ignored and the function will pull in the
72294  *  first token on its own.  Upon exit, 'curr_tok' is the terminating
72295  *  token (EOF or closing brace).
72296  */
72297 
72298 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) {
72299 	duk_compiler_func *func;
72300 	duk_hthread *thr;
72301 	duk_regconst_t reg_stmt_value = -1;
72302 	duk_lexer_point lex_pt;
72303 	duk_regconst_t temp_first;
72304 	duk_small_int_t compile_round = 1;
72305 
72306 	DUK_ASSERT(comp_ctx != NULL);
72307 
72308 	thr = comp_ctx->thr;
72309 	DUK_ASSERT(thr != NULL);
72310 
72311 	func = &comp_ctx->curr_func;
72312 	DUK_ASSERT(func != NULL);
72313 
72314 	DUK__RECURSION_INCREASE(comp_ctx, thr);
72315 
72316 	duk_require_stack(thr, DUK__FUNCTION_BODY_REQUIRE_SLOTS);
72317 
72318 	/*
72319 	 *  Store lexer position for a later rewind
72320 	 */
72321 
72322 	DUK_LEXER_GETPOINT(&comp_ctx->lex, &lex_pt);
72323 
72324 	/*
72325 	 *  Program code (global and eval code) has an implicit return value
72326 	 *  from the last statement value (e.g. eval("1; 2+3;") returns 3).
72327 	 *  This is not the case with functions.  If implicit statement return
72328 	 *  value is requested, all statements are coerced to a register
72329 	 *  allocated here, and used in the implicit return statement below.
72330 	 */
72331 
72332 	/* XXX: this is pointless here because pass 1 is throw-away */
72333 	if (implicit_return_value) {
72334 		reg_stmt_value = DUK__ALLOCTEMP(comp_ctx);
72335 
72336 		/* If an implicit return value is needed by caller, it must be
72337 		 * initialized to 'undefined' because we don't know whether any
72338 		 * non-empty (where "empty" is a continuation type, and different
72339 		 * from an empty statement) statements will be executed.
72340 		 *
72341 		 * However, since 1st pass is a throwaway one, no need to emit
72342 		 * it here.
72343 		 */
72344 #if 0
72345 		duk__emit_bc(comp_ctx,
72346 		             DUK_OP_LDUNDEF,
72347 		             0);
72348 #endif
72349 	}
72350 
72351 	/*
72352 	 *  First pass.
72353 	 *
72354 	 *  Gather variable/function declarations needed for second pass.
72355 	 *  Code generated is dummy and discarded.
72356 	 */
72357 
72358 	func->in_directive_prologue = 1;
72359 	func->in_scanning = 1;
72360 	func->may_direct_eval = 0;
72361 	func->id_access_arguments = 0;
72362 	func->id_access_slow = 0;
72363 	func->id_access_slow_own = 0;
72364 	func->reg_stmt_value = reg_stmt_value;
72365 #if defined(DUK_USE_DEBUGGER_SUPPORT)
72366 	func->min_line = DUK_INT_MAX;
72367 	func->max_line = 0;
72368 #endif
72369 
72370 	/* duk__parse_stmts() expects curr_tok to be set; parse in "allow
72371 	 * regexp literal" mode with current strictness.
72372 	 */
72373 	if (expect_token >= 0) {
72374 		/* Eating a left curly; regexp mode is allowed by left curly
72375 		 * based on duk__token_lbp[] automatically.
72376 		 */
72377 		DUK_ASSERT(expect_token == DUK_TOK_LCURLY);
72378 		duk__update_lineinfo_currtoken(comp_ctx);
72379 		duk__advance_expect(comp_ctx, expect_token);
72380 	} else {
72381 		/* Need to set curr_token.t because lexing regexp mode depends on current
72382 		 * token type.  Zero value causes "allow regexp" mode.
72383 		 */
72384 		comp_ctx->curr_token.t = 0;
72385 		duk__advance(comp_ctx);
72386 	}
72387 
72388 	DUK_DDD(DUK_DDDPRINT("begin 1st pass"));
72389 	duk__parse_stmts(comp_ctx,
72390 	                 1,             /* allow source elements */
72391 	                 expect_eof,    /* expect EOF instead of } */
72392 	                 regexp_after); /* regexp after */
72393 	DUK_DDD(DUK_DDDPRINT("end 1st pass"));
72394 
72395 	/*
72396 	 *  Second (and possibly third) pass.
72397 	 *
72398 	 *  Generate actual code.  In most cases the need for shuffle
72399 	 *  registers is detected during pass 1, but in some corner cases
72400 	 *  we'll only detect it during pass 2 and a third pass is then
72401 	 *  needed (see GH-115).
72402 	 */
72403 
72404 	for (;;) {
72405 		duk_bool_t needs_shuffle_before = comp_ctx->curr_func.needs_shuffle;
72406 		compile_round++;
72407 
72408 		/*
72409 		 *  Rewind lexer.
72410 		 *
72411 		 *  duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp
72412 		 *  literal" mode with current strictness.
72413 		 *
72414 		 *  curr_token line number info should be initialized for pass 2 before
72415 		 *  generating prologue, to ensure prologue bytecode gets nice line numbers.
72416 		 */
72417 
72418 		DUK_DDD(DUK_DDDPRINT("rewind lexer"));
72419 		DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
72420 		comp_ctx->curr_token.t = 0;  /* this is needed for regexp mode */
72421 		comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
72422 		duk__advance(comp_ctx);
72423 
72424 		/*
72425 		 *  Reset function state and perform register allocation, which creates
72426 		 *  'varmap' for second pass.  Function prologue for variable declarations,
72427 		 *  binding value initializations etc is emitted as a by-product.
72428 		 *
72429 		 *  Strict mode restrictions for duplicate and invalid argument
72430 		 *  names are checked here now that we know whether the function
72431 		 *  is actually strict.  See: test-dev-strict-mode-boundary.js.
72432 		 *
72433 		 *  Inner functions are compiled during pass 1 and are not reset.
72434 		 */
72435 
72436 		duk__reset_func_for_pass2(comp_ctx);
72437 		func->in_directive_prologue = 1;
72438 		func->in_scanning = 0;
72439 
72440 		/* must be able to emit code, alloc consts, etc. */
72441 
72442 		duk__init_varmap_and_prologue_for_pass2(comp_ctx,
72443 		                                        (implicit_return_value ? &reg_stmt_value : NULL));
72444 		func->reg_stmt_value = reg_stmt_value;
72445 
72446 		temp_first = DUK__GETTEMP(comp_ctx);
72447 
72448 		func->temp_first = temp_first;
72449 		func->temp_next = temp_first;
72450 		func->stmt_next = 0;
72451 		func->label_next = 0;
72452 
72453 		/* XXX: init or assert catch depth etc -- all values */
72454 		func->id_access_arguments = 0;
72455 		func->id_access_slow = 0;
72456 		func->id_access_slow_own = 0;
72457 
72458 		/*
72459 		 *  Check function name validity now that we know strictness.
72460 		 *  This only applies to function declarations and expressions,
72461 		 *  not setter/getter name.
72462 		 *
72463 		 *  See: test-dev-strict-mode-boundary.js
72464 		 */
72465 
72466 		if (func->is_function && !func->is_setget && func->h_name != NULL) {
72467 			if (func->is_strict) {
72468 				if (duk__hstring_is_eval_or_arguments(comp_ctx, func->h_name)) {
72469 					DUK_DDD(DUK_DDDPRINT("func name is 'eval' or 'arguments' in strict mode"));
72470 					goto error_funcname;
72471 				}
72472 				if (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {
72473 					DUK_DDD(DUK_DDDPRINT("func name is a reserved word in strict mode"));
72474 					goto error_funcname;
72475 				}
72476 			} else {
72477 				if (DUK_HSTRING_HAS_RESERVED_WORD(func->h_name) &&
72478 				    !DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {
72479 					DUK_DDD(DUK_DDDPRINT("func name is a reserved word in non-strict mode"));
72480 					goto error_funcname;
72481 				}
72482 			}
72483 		}
72484 
72485 		/*
72486 		 *  Second pass parsing.
72487 		 */
72488 
72489 		if (implicit_return_value) {
72490 			/* Default implicit return value. */
72491 			duk__emit_bc(comp_ctx,
72492 			             DUK_OP_LDUNDEF,
72493 			             0);
72494 		}
72495 
72496 		DUK_DDD(DUK_DDDPRINT("begin 2nd pass"));
72497 		duk__parse_stmts(comp_ctx,
72498 		                 1,             /* allow source elements */
72499 		                 expect_eof,    /* expect EOF instead of } */
72500 		                 regexp_after); /* regexp after */
72501 		DUK_DDD(DUK_DDDPRINT("end 2nd pass"));
72502 
72503 		duk__update_lineinfo_currtoken(comp_ctx);
72504 
72505 		if (needs_shuffle_before == comp_ctx->curr_func.needs_shuffle) {
72506 			/* Shuffle decision not changed. */
72507 			break;
72508 		}
72509 		if (compile_round >= 3) {
72510 			/* Should never happen but avoid infinite loop just in case. */
72511 			DUK_D(DUK_DPRINT("more than 3 compile passes needed, should never happen"));
72512 			DUK_ERROR_INTERNAL(thr);
72513 			DUK_WO_NORETURN(return;);
72514 		}
72515 		DUK_D(DUK_DPRINT("need additional round to compile function, round now %d", (int) compile_round));
72516 	}
72517 
72518 	/*
72519 	 *  Emit a final RETURN.
72520 	 *
72521 	 *  It would be nice to avoid emitting an unnecessary "return" opcode
72522 	 *  if the current PC is not reachable.  However, this cannot be reliably
72523 	 *  detected; even if the previous instruction is an unconditional jump,
72524 	 *  there may be a previous jump which jumps to current PC (which is the
72525 	 *  case for iteration and conditional statements, for instance).
72526 	 */
72527 
72528 	/* XXX: request a "last statement is terminal" from duk__parse_stmt() and duk__parse_stmts();
72529 	 * we could avoid the last RETURN if we could ensure there is no way to get here
72530 	 * (directly or via a jump)
72531 	 */
72532 
72533 	DUK_ASSERT(comp_ctx->curr_func.catch_depth == 0);
72534 	if (reg_stmt_value >= 0) {
72535 		DUK_ASSERT(DUK__ISREG(reg_stmt_value));
72536 		duk__emit_bc(comp_ctx, DUK_OP_RETREG, reg_stmt_value /*reg*/);
72537 	} else {
72538 		duk__emit_op_only(comp_ctx, DUK_OP_RETUNDEF);
72539 	}
72540 
72541 	/*
72542 	 *  Peephole optimize JUMP chains.
72543 	 */
72544 
72545 	duk__peephole_optimize_bytecode(comp_ctx);
72546 
72547 	/*
72548 	 *  comp_ctx->curr_func is now ready to be converted into an actual
72549 	 *  function template.
72550 	 */
72551 
72552 	DUK__RECURSION_DECREASE(comp_ctx, thr);
72553 	return;
72554 
72555  error_funcname:
72556 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FUNC_NAME);
72557 	DUK_WO_NORETURN(return;);
72558 }
72559 
72560 /*
72561  *  Parse a function-like expression:
72562  *
72563  *    - function expression
72564  *    - function declaration
72565  *    - function statement (non-standard)
72566  *    - setter/getter
72567  *
72568  *  Adds the function to comp_ctx->curr_func function table and returns the
72569  *  function number.
72570  *
72571  *  On entry, curr_token points to:
72572  *
72573  *    - the token after 'function' for function expression/declaration/statement
72574  *    - the token after 'set' or 'get' for setter/getter
72575  */
72576 
72577 /* Parse formals. */
72578 DUK_LOCAL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx) {
72579 	duk_hthread *thr = comp_ctx->thr;
72580 	duk_bool_t first = 1;
72581 	duk_uarridx_t n;
72582 
72583 	for (;;) {
72584 		if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
72585 			break;
72586 		}
72587 
72588 		if (first) {
72589 			/* no comma */
72590 			first = 0;
72591 		} else {
72592 			duk__advance_expect(comp_ctx, DUK_TOK_COMMA);
72593 		}
72594 
72595 		/* Note: when parsing a formal list in non-strict context, e.g.
72596 		 * "implements" is parsed as an identifier.  When the function is
72597 		 * later detected to be strict, the argument list must be rechecked
72598 		 * against a larger set of reserved words (that of strict mode).
72599 		 * This is handled by duk__parse_func_body().  Here we recognize
72600 		 * whatever tokens are considered reserved in current strictness
72601 		 * (which is not always enough).
72602 		 */
72603 
72604 		if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
72605 			DUK_ERROR_SYNTAX(thr, DUK_STR_EXPECTED_IDENTIFIER);
72606 			DUK_WO_NORETURN(return;);
72607 		}
72608 		DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER);
72609 		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
72610 		DUK_DDD(DUK_DDDPRINT("formal argument: %!O",
72611 		                     (duk_heaphdr *) comp_ctx->curr_token.str1));
72612 
72613 		/* XXX: append primitive */
72614 		duk_push_hstring(thr, comp_ctx->curr_token.str1);
72615 		n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.argnames_idx);
72616 		duk_put_prop_index(thr, comp_ctx->curr_func.argnames_idx, n);
72617 
72618 		duk__advance(comp_ctx);  /* eat identifier */
72619 	}
72620 }
72621 
72622 /* Parse a function-like expression, assuming that 'comp_ctx->curr_func' is
72623  * correctly set up.  Assumes that curr_token is just after 'function' (or
72624  * 'set'/'get' etc).
72625  */
72626 DUK_LOCAL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags) {
72627 	duk_hthread *thr = comp_ctx->thr;
72628 	duk_token *tok;
72629 	duk_bool_t no_advance;
72630 
72631 	DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
72632 	DUK_ASSERT(comp_ctx->curr_func.is_function == 1);
72633 	DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
72634 	DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
72635 	DUK_ASSERT(comp_ctx->curr_func.is_setget == ((flags & DUK__FUNC_FLAG_GETSET) != 0));
72636 
72637 	duk__update_lineinfo_currtoken(comp_ctx);
72638 
72639 	/*
72640 	 *  Function name (if any)
72641 	 *
72642 	 *  We don't check for prohibited names here, because we don't
72643 	 *  yet know whether the function will be strict.  Function body
72644 	 *  parsing handles this retroactively.
72645 	 *
72646 	 *  For function expressions and declarations function name must
72647 	 *  be an Identifer (excludes reserved words).  For setter/getter
72648 	 *  it is a PropertyName which allows reserved words and also
72649 	 *  strings and numbers (e.g. "{ get 1() { ... } }").
72650 	 *
72651 	 *  Function parsing may start either from prev_token or curr_token
72652 	 *  (object literal method definition uses prev_token for example).
72653 	 *  This is dealt with for the initial token.
72654 	 */
72655 
72656 	no_advance = (flags & DUK__FUNC_FLAG_USE_PREVTOKEN);
72657 	if (no_advance) {
72658 		tok = &comp_ctx->prev_token;
72659 	} else {
72660 		tok = &comp_ctx->curr_token;
72661 	}
72662 
72663 	if (flags & DUK__FUNC_FLAG_GETSET) {
72664 		/* PropertyName -> IdentifierName | StringLiteral | NumericLiteral */
72665 		if (tok->t_nores == DUK_TOK_IDENTIFIER || tok->t == DUK_TOK_STRING) {
72666 			duk_push_hstring(thr, tok->str1);       /* keep in valstack */
72667 		} else if (tok->t == DUK_TOK_NUMBER) {
72668 			duk_push_number(thr, tok->num);
72669 			duk_to_string(thr, -1);
72670 		} else {
72671 			DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_GETSET_NAME);
72672 			DUK_WO_NORETURN(return;);
72673 		}
72674 		comp_ctx->curr_func.h_name = duk_known_hstring(thr, -1);  /* borrowed reference */
72675 	} else {
72676 		/* Function name is an Identifier (not IdentifierName), but we get
72677 		 * the raw name (not recognizing keywords) here and perform the name
72678 		 * checks only after pass 1.
72679 		 */
72680 		if (tok->t_nores == DUK_TOK_IDENTIFIER) {
72681 			duk_push_hstring(thr, tok->str1);       /* keep in valstack */
72682 			comp_ctx->curr_func.h_name = duk_known_hstring(thr, -1);  /* borrowed reference */
72683 		} else {
72684 			/* valstack will be unbalanced, which is OK */
72685 			DUK_ASSERT((flags & DUK__FUNC_FLAG_GETSET) == 0);
72686 			DUK_ASSERT(comp_ctx->curr_func.h_name == NULL);
72687 			no_advance = 1;
72688 			if (flags & DUK__FUNC_FLAG_DECL) {
72689 				DUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_NAME_REQUIRED);
72690 				DUK_WO_NORETURN(return;);
72691 			}
72692 		}
72693 	}
72694 
72695 	DUK_DD(DUK_DDPRINT("function name: %!O",
72696 	                   (duk_heaphdr *) comp_ctx->curr_func.h_name));
72697 
72698 	if (!no_advance) {
72699 		duk__advance(comp_ctx);
72700 	}
72701 
72702 	/*
72703 	 *  Formal argument list
72704 	 *
72705 	 *  We don't check for prohibited names or for duplicate argument
72706 	 *  names here, becase we don't yet know whether the function will
72707 	 *  be strict.  Function body parsing handles this retroactively.
72708 	 */
72709 
72710 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
72711 
72712 	duk__parse_func_formals(comp_ctx);
72713 
72714 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RPAREN);
72715 	duk__advance(comp_ctx);
72716 
72717 	/*
72718 	 *  Parse function body
72719 	 */
72720 
72721 	duk__parse_func_body(comp_ctx,
72722 	                     0,   /* expect_eof */
72723 	                     0,   /* implicit_return_value */
72724 	                     flags & DUK__FUNC_FLAG_DECL, /* regexp_after */
72725 	                     DUK_TOK_LCURLY);  /* expect_token */
72726 
72727 	/*
72728 	 *  Convert duk_compiler_func to a function template and add it
72729 	 *  to the parent function table.
72730 	 */
72731 
72732 	duk__convert_to_func_template(comp_ctx);  /* -> [ ... func ] */
72733 }
72734 
72735 /* Parse an inner function, adding the function template to the current function's
72736  * function table.  Return a function number to be used by the outer function.
72737  *
72738  * Avoiding O(depth^2) inner function parsing is handled here.  On the first pass,
72739  * compile and register the function normally into the 'funcs' array, also recording
72740  * a lexer point (offset/line) to the closing brace of the function.  On the second
72741  * pass, skip the function and return the same 'fnum' as on the first pass by using
72742  * a running counter.
72743  *
72744  * An unfortunate side effect of this is that when parsing the inner function, almost
72745  * nothing is known of the outer function, i.e. the inner function's scope.  We don't
72746  * need that information at the moment, but it would allow some optimizations if it
72747  * were used.
72748  */
72749 DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags) {
72750 	duk_hthread *thr = comp_ctx->thr;
72751 	duk_compiler_func old_func;
72752 	duk_idx_t entry_top;
72753 	duk_int_t fnum;
72754 
72755 	/*
72756 	 *  On second pass, skip the function.
72757 	 */
72758 
72759 	if (!comp_ctx->curr_func.in_scanning) {
72760 		duk_lexer_point lex_pt;
72761 
72762 		fnum = comp_ctx->curr_func.fnum_next++;
72763 		duk_get_prop_index(thr, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
72764 		lex_pt.offset = (duk_size_t) duk_to_uint(thr, -1);
72765 		duk_pop(thr);
72766 		duk_get_prop_index(thr, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
72767 		lex_pt.line = duk_to_int(thr, -1);
72768 		duk_pop(thr);
72769 
72770 		DUK_DDD(DUK_DDDPRINT("second pass of an inner func, skip the function, reparse closing brace; lex offset=%ld, line=%ld",
72771 		                     (long) lex_pt.offset, (long) lex_pt.line));
72772 
72773 		DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
72774 		comp_ctx->curr_token.t = 0;  /* this is needed for regexp mode */
72775 		comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
72776 		duk__advance(comp_ctx);
72777 
72778 		/* RegExp is not allowed after a function expression, e.g. in
72779 		 * (function () {} / 123).  A RegExp *is* allowed after a
72780 		 * function declaration!
72781 		 */
72782 		if (flags & DUK__FUNC_FLAG_DECL) {
72783 			comp_ctx->curr_func.allow_regexp_in_adv = 1;
72784 		}
72785 		duk__advance_expect(comp_ctx, DUK_TOK_RCURLY);
72786 
72787 		return fnum;
72788 	}
72789 
72790 	/*
72791 	 *  On first pass, perform actual parsing.  Remember valstack top on entry
72792 	 *  to restore it later, and switch to using a new function in comp_ctx.
72793 	 */
72794 
72795 	entry_top = duk_get_top(thr);
72796 	DUK_DDD(DUK_DDDPRINT("before func: entry_top=%ld, curr_tok.start_offset=%ld",
72797 	                     (long) entry_top, (long) comp_ctx->curr_token.start_offset));
72798 
72799 	duk_memcpy(&old_func, &comp_ctx->curr_func, sizeof(duk_compiler_func));
72800 
72801 	duk_memzero(&comp_ctx->curr_func, sizeof(duk_compiler_func));
72802 	duk__init_func_valstack_slots(comp_ctx);
72803 	DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
72804 
72805 	/* inherit initial strictness from parent */
72806 	comp_ctx->curr_func.is_strict = old_func.is_strict;
72807 
72808 	/* XXX: It might be better to just store the flags into the curr_func
72809 	 * struct and use them as is without this flag interpretation step
72810 	 * here.
72811 	 */
72812 	DUK_ASSERT(comp_ctx->curr_func.is_notail == 0);
72813 	comp_ctx->curr_func.is_function = 1;
72814 	DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
72815 	DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
72816 	comp_ctx->curr_func.is_setget = ((flags & DUK__FUNC_FLAG_GETSET) != 0);
72817 	comp_ctx->curr_func.is_namebinding = !(flags & (DUK__FUNC_FLAG_GETSET |
72818 	                                                DUK__FUNC_FLAG_METDEF |
72819 	                                                DUK__FUNC_FLAG_DECL));  /* no name binding for: declarations, objlit getset, objlit method def */
72820 	comp_ctx->curr_func.is_constructable = !(flags & (DUK__FUNC_FLAG_GETSET |
72821 	                                                  DUK__FUNC_FLAG_METDEF));  /* not constructable: objlit getset, objlit method def */
72822 
72823 	/*
72824 	 *  Parse inner function
72825 	 */
72826 
72827 	duk__parse_func_like_raw(comp_ctx, flags);  /* pushes function template */
72828 
72829 	/* prev_token.start_offset points to the closing brace here; when skipping
72830 	 * we're going to reparse the closing brace to ensure semicolon insertion
72831 	 * etc work as expected.
72832 	 */
72833 	DUK_DDD(DUK_DDDPRINT("after func: prev_tok.start_offset=%ld, curr_tok.start_offset=%ld",
72834 	                     (long) comp_ctx->prev_token.start_offset, (long) comp_ctx->curr_token.start_offset));
72835 	DUK_ASSERT(comp_ctx->lex.input[comp_ctx->prev_token.start_offset] == (duk_uint8_t) DUK_ASC_RCURLY);
72836 
72837 	/* XXX: append primitive */
72838 	DUK_ASSERT(duk_get_length(thr, old_func.funcs_idx) == (duk_size_t) (old_func.fnum_next * 3));
72839 	fnum = old_func.fnum_next++;
72840 
72841 	if (fnum > DUK__MAX_FUNCS) {
72842 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_FUNC_LIMIT);
72843 		DUK_WO_NORETURN(return 0;);
72844 	}
72845 
72846 	/* array writes autoincrement length */
72847 	(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3));
72848 	duk_push_size_t(thr, comp_ctx->prev_token.start_offset);
72849 	(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
72850 	duk_push_int(thr, comp_ctx->prev_token.start_line);
72851 	(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
72852 
72853 	/*
72854 	 *  Cleanup: restore original function, restore valstack state.
72855 	 *
72856 	 *  Function declaration handling needs the function name to be pushed
72857 	 *  on the value stack.
72858 	 */
72859 
72860 	if (flags & DUK__FUNC_FLAG_PUSHNAME_PASS1) {
72861 		DUK_ASSERT(comp_ctx->curr_func.h_name != NULL);
72862 		duk_push_hstring(thr, comp_ctx->curr_func.h_name);
72863 		duk_replace(thr, entry_top);
72864 		duk_set_top(thr, entry_top + 1);
72865 	} else {
72866 		duk_set_top(thr, entry_top);
72867 	}
72868 	duk_memcpy((void *) &comp_ctx->curr_func, (void *) &old_func, sizeof(duk_compiler_func));
72869 
72870 	return fnum;
72871 }
72872 
72873 /*
72874  *  Compile input string into an executable function template without
72875  *  arguments.
72876  *
72877  *  The string is parsed as the "Program" production of ECMAScript E5.
72878  *  Compilation context can be either global code or eval code (see E5
72879  *  Sections 14 and 15.1.2.1).
72880  *
72881  *  Input stack:  [ ... filename ]
72882  *  Output stack: [ ... func_template ]
72883  */
72884 
72885 /* XXX: source code property */
72886 
72887 DUK_LOCAL duk_ret_t duk__js_compile_raw(duk_hthread *thr, void *udata) {
72888 	duk_hstring *h_filename;
72889 	duk__compiler_stkstate *comp_stk;
72890 	duk_compiler_ctx *comp_ctx;
72891 	duk_lexer_point *lex_pt;
72892 	duk_compiler_func *func;
72893 	duk_idx_t entry_top;
72894 	duk_bool_t is_strict;
72895 	duk_bool_t is_eval;
72896 	duk_bool_t is_funcexpr;
72897 	duk_small_uint_t flags;
72898 
72899 	DUK_ASSERT(thr != NULL);
72900 	DUK_ASSERT(udata != NULL);
72901 
72902 	/*
72903 	 *  Arguments check
72904 	 */
72905 
72906 	entry_top = duk_get_top(thr);
72907 	DUK_ASSERT(entry_top >= 1);
72908 
72909 	comp_stk = (duk__compiler_stkstate *) udata;
72910 	comp_ctx = &comp_stk->comp_ctx_alloc;
72911 	lex_pt = &comp_stk->lex_pt_alloc;
72912 	DUK_ASSERT(comp_ctx != NULL);
72913 	DUK_ASSERT(lex_pt != NULL);
72914 
72915 	flags = comp_stk->flags;
72916 	is_eval = (flags & DUK_COMPILE_EVAL ? 1 : 0);
72917 	is_strict = (flags & DUK_COMPILE_STRICT ? 1 : 0);
72918 	is_funcexpr = (flags & DUK_COMPILE_FUNCEXPR ? 1 : 0);
72919 
72920 	h_filename = duk_get_hstring(thr, -1);  /* may be undefined */
72921 
72922 	/*
72923 	 *  Init compiler and lexer contexts
72924 	 */
72925 
72926 	func = &comp_ctx->curr_func;
72927 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
72928 	comp_ctx->thr = NULL;
72929 	comp_ctx->h_filename = NULL;
72930 	comp_ctx->prev_token.str1 = NULL;
72931 	comp_ctx->prev_token.str2 = NULL;
72932 	comp_ctx->curr_token.str1 = NULL;
72933 	comp_ctx->curr_token.str2 = NULL;
72934 #endif
72935 
72936 	duk_require_stack(thr, DUK__COMPILE_ENTRY_SLOTS);
72937 
72938 	duk_push_dynamic_buffer(thr, 0);       /* entry_top + 0 */
72939 	duk_push_undefined(thr);               /* entry_top + 1 */
72940 	duk_push_undefined(thr);               /* entry_top + 2 */
72941 	duk_push_undefined(thr);               /* entry_top + 3 */
72942 	duk_push_undefined(thr);               /* entry_top + 4 */
72943 
72944 	comp_ctx->thr = thr;
72945 	comp_ctx->h_filename = h_filename;
72946 	comp_ctx->tok11_idx = entry_top + 1;
72947 	comp_ctx->tok12_idx = entry_top + 2;
72948 	comp_ctx->tok21_idx = entry_top + 3;
72949 	comp_ctx->tok22_idx = entry_top + 4;
72950 	comp_ctx->recursion_limit = DUK_USE_COMPILER_RECLIMIT;
72951 
72952 	/* comp_ctx->lex has been pre-initialized by caller: it has been
72953 	 * zeroed and input/input_length has been set.
72954 	 */
72955 	comp_ctx->lex.thr = thr;
72956 	/* comp_ctx->lex.input and comp_ctx->lex.input_length filled by caller */
72957 	comp_ctx->lex.slot1_idx = comp_ctx->tok11_idx;
72958 	comp_ctx->lex.slot2_idx = comp_ctx->tok12_idx;
72959 	comp_ctx->lex.buf_idx = entry_top + 0;
72960 	comp_ctx->lex.buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, entry_top + 0);
72961 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(comp_ctx->lex.buf) && !DUK_HBUFFER_HAS_EXTERNAL(comp_ctx->lex.buf));
72962 	comp_ctx->lex.token_limit = DUK_COMPILER_TOKEN_LIMIT;
72963 
72964 	lex_pt->offset = 0;
72965 	lex_pt->line = 1;
72966 	DUK_LEXER_SETPOINT(&comp_ctx->lex, lex_pt);    /* fills window */
72967 	comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
72968 
72969 	/*
72970 	 *  Initialize function state for a zero-argument function
72971 	 */
72972 
72973 	duk__init_func_valstack_slots(comp_ctx);
72974 	DUK_ASSERT(func->num_formals == 0);
72975 
72976 	if (is_funcexpr) {
72977 		/* Name will be filled from function expression, not by caller.
72978 		 * This case is used by Function constructor and duk_compile()
72979 		 * API with the DUK_COMPILE_FUNCTION option.
72980 		 */
72981 		DUK_ASSERT(func->h_name == NULL);
72982 	} else {
72983 		duk_push_hstring_stridx(thr, (is_eval ? DUK_STRIDX_EVAL :
72984 		                                        DUK_STRIDX_GLOBAL));
72985 		func->h_name = duk_get_hstring(thr, -1);
72986 	}
72987 
72988 	/*
72989 	 *  Parse a function body or a function-like expression, depending
72990 	 *  on flags.
72991 	 */
72992 
72993 	DUK_ASSERT(func->is_setget == 0);
72994 	func->is_strict = (duk_uint8_t) is_strict;
72995 	DUK_ASSERT(func->is_notail == 0);
72996 
72997 	if (is_funcexpr) {
72998 		func->is_function = 1;
72999 		DUK_ASSERT(func->is_eval == 0);
73000 		DUK_ASSERT(func->is_global == 0);
73001 		func->is_namebinding = 1;
73002 		func->is_constructable = 1;
73003 
73004 		duk__advance(comp_ctx);  /* init 'curr_token' */
73005 		duk__advance_expect(comp_ctx, DUK_TOK_FUNCTION);
73006 		(void) duk__parse_func_like_raw(comp_ctx, 0 /*flags*/);
73007 	} else {
73008 		DUK_ASSERT(func->is_function == 0);
73009 		DUK_ASSERT(is_eval == 0 || is_eval == 1);
73010 		func->is_eval = (duk_uint8_t) is_eval;
73011 		func->is_global = (duk_uint8_t) !is_eval;
73012 		DUK_ASSERT(func->is_namebinding == 0);
73013 		DUK_ASSERT(func->is_constructable == 0);
73014 
73015 		duk__parse_func_body(comp_ctx,
73016 		                     1,             /* expect_eof */
73017 		                     1,             /* implicit_return_value */
73018 		                     1,             /* regexp_after (does not matter) */
73019 		                     -1);           /* expect_token */
73020 	}
73021 
73022 	/*
73023 	 *  Convert duk_compiler_func to a function template
73024 	 */
73025 
73026 	duk__convert_to_func_template(comp_ctx);
73027 
73028 	/*
73029 	 *  Wrapping duk_safe_call() will mangle the stack, just return stack top
73030 	 */
73031 
73032 	/* [ ... filename (temps) func ] */
73033 
73034 	return 1;
73035 }
73036 
73037 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) {
73038 	duk__compiler_stkstate comp_stk;
73039 	duk_compiler_ctx *prev_ctx;
73040 	duk_ret_t safe_rc;
73041 
73042 	DUK_ASSERT(thr != NULL);
73043 	DUK_ASSERT(src_buffer != NULL);
73044 
73045 	/* preinitialize lexer state partially */
73046 	duk_memzero(&comp_stk, sizeof(comp_stk));
73047 	comp_stk.flags = flags;
73048 	DUK_LEXER_INITCTX(&comp_stk.comp_ctx_alloc.lex);
73049 	comp_stk.comp_ctx_alloc.lex.input = src_buffer;
73050 	comp_stk.comp_ctx_alloc.lex.input_length = src_length;
73051 	comp_stk.comp_ctx_alloc.lex.flags = flags;  /* Forward flags directly for now. */
73052 
73053 	/* [ ... filename ] */
73054 
73055 	prev_ctx = thr->compile_ctx;
73056 	thr->compile_ctx = &comp_stk.comp_ctx_alloc;  /* for duk_error_augment.c */
73057 	safe_rc = duk_safe_call(thr, duk__js_compile_raw, (void *) &comp_stk /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
73058 	thr->compile_ctx = prev_ctx;  /* must restore reliably before returning */
73059 
73060 	if (safe_rc != DUK_EXEC_SUCCESS) {
73061 		DUK_D(DUK_DPRINT("compilation failed: %!T", duk_get_tval(thr, -1)));
73062 		(void) duk_throw(thr);
73063 		DUK_WO_NORETURN(return;);
73064 	}
73065 
73066 	/* [ ... template ] */
73067 }
73068 
73069 /* automatic undefs */
73070 #undef DUK__ALLOCTEMP
73071 #undef DUK__ALLOCTEMPS
73072 #undef DUK__ALLOW_AUTO_SEMI_ALWAYS
73073 #undef DUK__BC_INITIAL_INSTS
73074 #undef DUK__BP_ADDITIVE
73075 #undef DUK__BP_ASSIGNMENT
73076 #undef DUK__BP_BAND
73077 #undef DUK__BP_BOR
73078 #undef DUK__BP_BXOR
73079 #undef DUK__BP_CALL
73080 #undef DUK__BP_CLOSING
73081 #undef DUK__BP_COMMA
73082 #undef DUK__BP_CONDITIONAL
73083 #undef DUK__BP_EOF
73084 #undef DUK__BP_EQUALITY
73085 #undef DUK__BP_EXPONENTIATION
73086 #undef DUK__BP_FOR_EXPR
73087 #undef DUK__BP_INVALID
73088 #undef DUK__BP_LAND
73089 #undef DUK__BP_LOR
73090 #undef DUK__BP_MEMBER
73091 #undef DUK__BP_MULTIPLICATIVE
73092 #undef DUK__BP_POSTFIX
73093 #undef DUK__BP_RELATIONAL
73094 #undef DUK__BP_SHIFT
73095 #undef DUK__COMPILE_ENTRY_SLOTS
73096 #undef DUK__CONST_MARKER
73097 #undef DUK__DUMP_ISPEC
73098 #undef DUK__DUMP_IVALUE
73099 #undef DUK__EMIT_FLAG_A_IS_SOURCE
73100 #undef DUK__EMIT_FLAG_BC_REGCONST
73101 #undef DUK__EMIT_FLAG_B_IS_TARGET
73102 #undef DUK__EMIT_FLAG_C_IS_TARGET
73103 #undef DUK__EMIT_FLAG_NO_SHUFFLE_A
73104 #undef DUK__EMIT_FLAG_NO_SHUFFLE_B
73105 #undef DUK__EMIT_FLAG_NO_SHUFFLE_C
73106 #undef DUK__EMIT_FLAG_RESERVE_JUMPSLOT
73107 #undef DUK__EXPR_FLAG_ALLOW_EMPTY
73108 #undef DUK__EXPR_FLAG_REJECT_IN
73109 #undef DUK__EXPR_FLAG_REQUIRE_INIT
73110 #undef DUK__EXPR_RBP_MASK
73111 #undef DUK__FUNCTION_BODY_REQUIRE_SLOTS
73112 #undef DUK__FUNCTION_INIT_REQUIRE_SLOTS
73113 #undef DUK__FUNC_FLAG_DECL
73114 #undef DUK__FUNC_FLAG_GETSET
73115 #undef DUK__FUNC_FLAG_METDEF
73116 #undef DUK__FUNC_FLAG_PUSHNAME_PASS1
73117 #undef DUK__FUNC_FLAG_USE_PREVTOKEN
73118 #undef DUK__GETCONST_MAX_CONSTS_CHECK
73119 #undef DUK__GETTEMP
73120 #undef DUK__HAS_TERM
73121 #undef DUK__HAS_VAL
73122 #undef DUK__ISCONST
73123 #undef DUK__ISREG
73124 #undef DUK__ISREG_NOTTEMP
73125 #undef DUK__ISREG_TEMP
73126 #undef DUK__IS_TERMINAL
73127 #undef DUK__IVAL_FLAG_ALLOW_CONST
73128 #undef DUK__IVAL_FLAG_REQUIRE_SHORT
73129 #undef DUK__IVAL_FLAG_REQUIRE_TEMP
73130 #undef DUK__MAX_ARRAY_INIT_VALUES
73131 #undef DUK__MAX_CONSTS
73132 #undef DUK__MAX_FUNCS
73133 #undef DUK__MAX_OBJECT_INIT_PAIRS
73134 #undef DUK__MAX_TEMPS
73135 #undef DUK__MK_LBP
73136 #undef DUK__MK_LBP_FLAGS
73137 #undef DUK__OBJ_LIT_KEY_GET
73138 #undef DUK__OBJ_LIT_KEY_PLAIN
73139 #undef DUK__OBJ_LIT_KEY_SET
73140 #undef DUK__PARSE_EXPR_SLOTS
73141 #undef DUK__PARSE_STATEMENTS_SLOTS
73142 #undef DUK__RECURSION_DECREASE
73143 #undef DUK__RECURSION_INCREASE
73144 #undef DUK__REMOVECONST
73145 #undef DUK__SETTEMP
73146 #undef DUK__SETTEMP_CHECKMAX
73147 #undef DUK__STILL_PROLOGUE
73148 #undef DUK__TOKEN_LBP_BP_MASK
73149 #undef DUK__TOKEN_LBP_FLAG_NO_REGEXP
73150 #undef DUK__TOKEN_LBP_FLAG_TERMINATES
73151 #undef DUK__TOKEN_LBP_FLAG_UNUSED
73152 #undef DUK__TOKEN_LBP_GET_BP
73153 #line 1 "duk_js_executor.c"
73154 /*
73155  *  ECMAScript bytecode executor.
73156  */
73157 
73158 /* #include duk_internal.h -> already included */
73159 
73160 /*
73161  *  Local declarations.
73162  */
73163 
73164 DUK_LOCAL_DECL void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_activation *entry_act);
73165 
73166 /*
73167  *  Misc helpers.
73168  */
73169 
73170 /* Forced inline declaration, only applied for performance oriented build. */
73171 #if defined(DUK_USE_EXEC_PREFER_SIZE)
73172 #define DUK__INLINE_PERF
73173 #define DUK__NOINLINE_PERF
73174 #else
73175 #define DUK__INLINE_PERF DUK_ALWAYS_INLINE
73176 #define DUK__NOINLINE_PERF DUK_NOINLINE
73177 #endif
73178 
73179 /* Replace value stack top to value at 'tv_ptr'.  Optimize for
73180  * performance by only applying the net refcount change.
73181  */
73182 #define DUK__REPLACE_TO_TVPTR(thr,tv_ptr) do { \
73183 		duk_hthread *duk__thr; \
73184 		duk_tval *duk__tvsrc; \
73185 		duk_tval *duk__tvdst; \
73186 		duk_tval duk__tvtmp; \
73187 		duk__thr = (thr); \
73188 		duk__tvsrc = DUK_GET_TVAL_NEGIDX(duk__thr, -1); \
73189 		duk__tvdst = (tv_ptr); \
73190 		DUK_TVAL_SET_TVAL(&duk__tvtmp, duk__tvdst); \
73191 		DUK_TVAL_SET_TVAL(duk__tvdst, duk__tvsrc); \
73192 		DUK_TVAL_SET_UNDEFINED(duk__tvsrc);  /* value stack init policy */ \
73193 		duk__thr->valstack_top = duk__tvsrc; \
73194 		DUK_TVAL_DECREF(duk__thr, &duk__tvtmp); \
73195 	} while (0)
73196 
73197 /* XXX: candidate of being an internal shared API call */
73198 #if 0  /* unused */
73199 DUK_LOCAL void duk__push_tvals_incref_only(duk_hthread *thr, duk_tval *tv_src, duk_small_uint_fast_t count) {
73200 	duk_tval *tv_dst;
73201 	duk_size_t copy_size;
73202 	duk_size_t i;
73203 
73204 	tv_dst = thr->valstack_top;
73205 	copy_size = sizeof(duk_tval) * count;
73206 	duk_memcpy((void *) tv_dst, (const void *) tv_src, copy_size);
73207 	for (i = 0; i < count; i++) {
73208 		DUK_TVAL_INCREF(thr, tv_dst);
73209 		tv_dst++;
73210 	}
73211 	thr->valstack_top = tv_dst;
73212 }
73213 #endif
73214 
73215 /*
73216  *  Arithmetic, binary, and logical helpers.
73217  *
73218  *  Note: there is no opcode for logical AND or logical OR; this is on
73219  *  purpose, because the evalution order semantics for them make such
73220  *  opcodes pretty pointless: short circuiting means they are most
73221  *  comfortably implemented as jumps.  However, a logical NOT opcode
73222  *  is useful.
73223  *
73224  *  Note: careful with duk_tval pointers here: they are potentially
73225  *  invalidated by any DECREF and almost any API call.  It's still
73226  *  preferable to work without making a copy but that's not always
73227  *  possible.
73228  */
73229 
73230 DUK_LOCAL DUK__INLINE_PERF duk_double_t duk__compute_mod(duk_double_t d1, duk_double_t d2) {
73231 	return (duk_double_t) duk_js_arith_mod((double) d1, (double) d2);
73232 }
73233 
73234 #if defined(DUK_USE_ES7_EXP_OPERATOR)
73235 DUK_LOCAL DUK__INLINE_PERF duk_double_t duk__compute_exp(duk_double_t d1, duk_double_t d2) {
73236 	return (duk_double_t) duk_js_arith_pow((double) d1, (double) d2);
73237 }
73238 #endif
73239 
73240 DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z) {
73241 	/*
73242 	 *  Addition operator is different from other arithmetic
73243 	 *  operations in that it also provides string concatenation.
73244 	 *  Hence it is implemented separately.
73245 	 *
73246 	 *  There is a fast path for number addition.  Other cases go
73247 	 *  through potentially multiple coercions as described in the
73248 	 *  E5 specification.  It may be possible to reduce the number
73249 	 *  of coercions, but this must be done carefully to preserve
73250 	 *  the exact semantics.
73251 	 *
73252 	 *  E5 Section 11.6.1.
73253 	 *
73254 	 *  Custom types also have special behavior implemented here.
73255 	 */
73256 
73257 	duk_double_union du;
73258 
73259 	DUK_ASSERT(thr != NULL);
73260 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
73261 	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
73262 	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
73263 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
73264 
73265 	/*
73266 	 *  Fast paths
73267 	 */
73268 
73269 #if defined(DUK_USE_FASTINT)
73270 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
73271 		duk_int64_t v1, v2, v3;
73272 		duk_int32_t v3_hi;
73273 		duk_tval *tv_z;
73274 
73275 		/* Input values are signed 48-bit so we can detect overflow
73276 		 * reliably from high bits or just a comparison.
73277 		 */
73278 
73279 		v1 = DUK_TVAL_GET_FASTINT(tv_x);
73280 		v2 = DUK_TVAL_GET_FASTINT(tv_y);
73281 		v3 = v1 + v2;
73282 		v3_hi = (duk_int32_t) (v3 >> 32);
73283 		if (DUK_LIKELY(v3_hi >= DUK_I64_CONSTANT(-0x8000) && v3_hi <= DUK_I64_CONSTANT(0x7fff))) {
73284 			tv_z = thr->valstack_bottom + idx_z;
73285 			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3);  /* side effects */
73286 			return;
73287 		} else {
73288 			/* overflow, fall through */
73289 			;
73290 		}
73291 	}
73292 #endif  /* DUK_USE_FASTINT */
73293 
73294 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
73295 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
73296 		duk_tval *tv_z;
73297 #endif
73298 
73299 		du.d = DUK_TVAL_GET_NUMBER(tv_x) + DUK_TVAL_GET_NUMBER(tv_y);
73300 #if defined(DUK_USE_EXEC_PREFER_SIZE)
73301 		duk_push_number(thr, du.d);  /* will NaN normalize result */
73302 		duk_replace(thr, (duk_idx_t) idx_z);
73303 #else  /* DUK_USE_EXEC_PREFER_SIZE */
73304 		DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
73305 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
73306 		tv_z = thr->valstack_bottom + idx_z;
73307 		DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d);  /* side effects */
73308 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
73309 		return;
73310 	}
73311 
73312 	/*
73313 	 *  Slow path: potentially requires function calls for coercion
73314 	 */
73315 
73316 	duk_push_tval(thr, tv_x);
73317 	duk_push_tval(thr, tv_y);
73318 	duk_to_primitive(thr, -2, DUK_HINT_NONE);  /* side effects -> don't use tv_x, tv_y after */
73319 	duk_to_primitive(thr, -1, DUK_HINT_NONE);
73320 
73321 	/* Since Duktape 2.x plain buffers are treated like ArrayBuffer. */
73322 	if (duk_is_string(thr, -2) || duk_is_string(thr, -1)) {
73323 		/* Symbols shouldn't technically be handled here, but should
73324 		 * go into the default ToNumber() coercion path instead and
73325 		 * fail there with a TypeError.  However, there's a ToString()
73326 		 * in duk_concat_2() which also fails with TypeError so no
73327 		 * explicit check is needed.
73328 		 */
73329 		duk_concat_2(thr);  /* [... s1 s2] -> [... s1+s2] */
73330 	} else {
73331 		duk_double_t d1, d2;
73332 
73333 		d1 = duk_to_number_m2(thr);
73334 		d2 = duk_to_number_m1(thr);
73335 		DUK_ASSERT(duk_is_number(thr, -2));
73336 		DUK_ASSERT(duk_is_number(thr, -1));
73337 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d1);
73338 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d2);
73339 
73340 		du.d = d1 + d2;
73341 		duk_pop_2_unsafe(thr);
73342 		duk_push_number(thr, du.d);  /* will NaN normalize result */
73343 	}
73344 	duk_replace(thr, (duk_idx_t) idx_z);  /* side effects */
73345 }
73346 
73347 DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_uint_fast_t idx_z, duk_small_uint_fast_t opcode) {
73348 	/*
73349 	 *  Arithmetic operations other than '+' have number-only semantics
73350 	 *  and are implemented here.  The separate switch-case here means a
73351 	 *  "double dispatch" of the arithmetic opcode, but saves code space.
73352 	 *
73353 	 *  E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
73354 	 */
73355 
73356 	duk_double_t d1, d2;
73357 	duk_double_union du;
73358 	duk_small_uint_fast_t opcode_shifted;
73359 #if defined(DUK_USE_FASTINT) || !defined(DUK_USE_EXEC_PREFER_SIZE)
73360 	duk_tval *tv_z;
73361 #endif
73362 
73363 	DUK_ASSERT(thr != NULL);
73364 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
73365 	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
73366 	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
73367 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
73368 
73369 	opcode_shifted = opcode >> 2;  /* Get base opcode without reg/const modifiers. */
73370 
73371 #if defined(DUK_USE_FASTINT)
73372 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
73373 		duk_int64_t v1, v2, v3;
73374 		duk_int32_t v3_hi;
73375 
73376 		v1 = DUK_TVAL_GET_FASTINT(tv_x);
73377 		v2 = DUK_TVAL_GET_FASTINT(tv_y);
73378 
73379 		switch (opcode_shifted) {
73380 		case DUK_OP_SUB >> 2: {
73381 			v3 = v1 - v2;
73382 			break;
73383 		}
73384 		case DUK_OP_MUL >> 2: {
73385 			/* Must ensure result is 64-bit (no overflow); a
73386 			 * simple and sufficient fast path is to allow only
73387 			 * 32-bit inputs.  Avoid zero inputs to avoid
73388 			 * negative zero issues (-1 * 0 = -0, for instance).
73389 			 */
73390 			if (v1 >= DUK_I64_CONSTANT(-0x80000000) && v1 <= DUK_I64_CONSTANT(0x7fffffff) && v1 != 0 &&
73391 			    v2 >= DUK_I64_CONSTANT(-0x80000000) && v2 <= DUK_I64_CONSTANT(0x7fffffff) && v2 != 0) {
73392 				v3 = v1 * v2;
73393 			} else {
73394 				goto skip_fastint;
73395 			}
73396 			break;
73397 		}
73398 		case DUK_OP_DIV >> 2: {
73399 			/* Don't allow a zero divisor.  Fast path check by
73400 			 * "verifying" with multiplication.  Also avoid zero
73401 			 * dividend to avoid negative zero issues (0 / -1 = -0
73402 			 * for instance).
73403 			 */
73404 			if (v1 == 0 || v2 == 0) {
73405 				goto skip_fastint;
73406 			}
73407 			v3 = v1 / v2;
73408 			if (v3 * v2 != v1) {
73409 				goto skip_fastint;
73410 			}
73411 			break;
73412 		}
73413 		case DUK_OP_MOD >> 2: {
73414 			/* Don't allow a zero divisor.  Restrict both v1 and
73415 			 * v2 to positive values to avoid compiler specific
73416 			 * behavior.
73417 			 */
73418 			if (v1 < 1 || v2 < 1) {
73419 				goto skip_fastint;
73420 			}
73421 			v3 = v1 % v2;
73422 			DUK_ASSERT(v3 >= 0);
73423 			DUK_ASSERT(v3 < v2);
73424 			DUK_ASSERT(v1 - (v1 / v2) * v2 == v3);
73425 			break;
73426 		}
73427 		default: {
73428 			/* Possible with DUK_OP_EXP. */
73429 			goto skip_fastint;
73430 		}
73431 		}
73432 
73433 		v3_hi = (duk_int32_t) (v3 >> 32);
73434 		if (DUK_LIKELY(v3_hi >= DUK_I64_CONSTANT(-0x8000) && v3_hi <= DUK_I64_CONSTANT(0x7fff))) {
73435 			tv_z = thr->valstack_bottom + idx_z;
73436 			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3);  /* side effects */
73437 			return;
73438 		}
73439 		/* fall through if overflow etc */
73440 	}
73441  skip_fastint:
73442 #endif  /* DUK_USE_FASTINT */
73443 
73444 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
73445 		/* fast path */
73446 		d1 = DUK_TVAL_GET_NUMBER(tv_x);
73447 		d2 = DUK_TVAL_GET_NUMBER(tv_y);
73448 	} else {
73449 		duk_push_tval(thr, tv_x);
73450 		duk_push_tval(thr, tv_y);
73451 		d1 = duk_to_number_m2(thr);  /* side effects */
73452 		d2 = duk_to_number_m1(thr);
73453 		DUK_ASSERT(duk_is_number(thr, -2));
73454 		DUK_ASSERT(duk_is_number(thr, -1));
73455 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d1);
73456 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d2);
73457 		duk_pop_2_unsafe(thr);
73458 	}
73459 
73460 	switch (opcode_shifted) {
73461 	case DUK_OP_SUB >> 2: {
73462 		du.d = d1 - d2;
73463 		break;
73464 	}
73465 	case DUK_OP_MUL >> 2: {
73466 		du.d = d1 * d2;
73467 		break;
73468 	}
73469 	case DUK_OP_DIV >> 2: {
73470 		/* Division-by-zero is undefined behavior, so
73471 		 * rely on a helper.
73472 		 */
73473 		du.d = duk_double_div(d1, d2);
73474 		break;
73475 	}
73476 	case DUK_OP_MOD >> 2: {
73477 		du.d = duk__compute_mod(d1, d2);
73478 		break;
73479 	}
73480 #if defined(DUK_USE_ES7_EXP_OPERATOR)
73481 	case DUK_OP_EXP >> 2: {
73482 		du.d = duk__compute_exp(d1, d2);
73483 		break;
73484 	}
73485 #endif
73486 	default: {
73487 		DUK_UNREACHABLE();
73488 		du.d = DUK_DOUBLE_NAN;  /* should not happen */
73489 		break;
73490 	}
73491 	}
73492 
73493 #if defined(DUK_USE_EXEC_PREFER_SIZE)
73494 	duk_push_number(thr, du.d);  /* will NaN normalize result */
73495 	duk_replace(thr, (duk_idx_t) idx_z);
73496 #else  /* DUK_USE_EXEC_PREFER_SIZE */
73497 	/* important to use normalized NaN with 8-byte tagged types */
73498 	DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
73499 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
73500 	tv_z = thr->valstack_bottom + idx_z;
73501 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d);  /* side effects */
73502 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
73503 }
73504 
73505 DUK_LOCAL DUK__INLINE_PERF void duk__vm_bitwise_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z, duk_small_uint_fast_t opcode) {
73506 	/*
73507 	 *  Binary bitwise operations use different coercions (ToInt32, ToUint32)
73508 	 *  depending on the operation.  We coerce the arguments first using
73509 	 *  ToInt32(), and then cast to an 32-bit value if necessary.  Note that
73510 	 *  such casts must be correct even if there is no native 32-bit type
73511 	 *  (e.g., duk_int32_t and duk_uint32_t are 64-bit).
73512 	 *
73513 	 *  E5 Sections 11.10, 11.7.1, 11.7.2, 11.7.3
73514 	 */
73515 
73516 	duk_int32_t i1, i2, i3;
73517 	duk_uint32_t u1, u2, u3;
73518 #if defined(DUK_USE_FASTINT)
73519 	duk_int64_t fi3;
73520 #else
73521 	duk_double_t d3;
73522 #endif
73523 	duk_small_uint_fast_t opcode_shifted;
73524 #if defined(DUK_USE_FASTINT) || !defined(DUK_USE_EXEC_PREFER_SIZE)
73525 	duk_tval *tv_z;
73526 #endif
73527 
73528 	DUK_ASSERT(thr != NULL);
73529 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
73530 	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
73531 	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
73532 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
73533 
73534 	opcode_shifted = opcode >> 2;  /* Get base opcode without reg/const modifiers. */
73535 
73536 #if defined(DUK_USE_FASTINT)
73537 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
73538 		i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_x);
73539 		i2 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_y);
73540 	}
73541 	else
73542 #endif  /* DUK_USE_FASTINT */
73543 	{
73544 		duk_push_tval(thr, tv_x);
73545 		duk_push_tval(thr, tv_y);
73546 		i1 = duk_to_int32(thr, -2);
73547 		i2 = duk_to_int32(thr, -1);
73548 		duk_pop_2_unsafe(thr);
73549 	}
73550 
73551 	switch (opcode_shifted) {
73552 	case DUK_OP_BAND >> 2: {
73553 		i3 = i1 & i2;
73554 		break;
73555 	}
73556 	case DUK_OP_BOR >> 2: {
73557 		i3 = i1 | i2;
73558 		break;
73559 	}
73560 	case DUK_OP_BXOR >> 2: {
73561 		i3 = i1 ^ i2;
73562 		break;
73563 	}
73564 	case DUK_OP_BASL >> 2: {
73565 		/* Signed shift, named "arithmetic" (asl) because the result
73566 		 * is signed, e.g. 4294967295 << 1 -> -2.  Note that result
73567 		 * must be masked.
73568 		 */
73569 
73570 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
73571 		i3 = (duk_int32_t) (((duk_uint32_t) i1) << (u2 & 0x1fUL));  /* E5 Section 11.7.1, steps 7 and 8 */
73572 		i3 = i3 & ((duk_int32_t) 0xffffffffUL);                     /* Note: left shift, should mask */
73573 		break;
73574 	}
73575 	case DUK_OP_BASR >> 2: {
73576 		/* signed shift */
73577 
73578 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
73579 		i3 = i1 >> (u2 & 0x1fUL);                      /* E5 Section 11.7.2, steps 7 and 8 */
73580 		break;
73581 	}
73582 	case DUK_OP_BLSR >> 2: {
73583 		/* unsigned shift */
73584 
73585 		u1 = ((duk_uint32_t) i1) & 0xffffffffUL;
73586 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
73587 
73588 		/* special result value handling */
73589 		u3 = u1 >> (u2 & 0x1fUL);     /* E5 Section 11.7.2, steps 7 and 8 */
73590 #if defined(DUK_USE_FASTINT)
73591 		fi3 = (duk_int64_t) u3;
73592 		goto fastint_result_set;
73593 #else
73594 		d3 = (duk_double_t) u3;
73595 		goto result_set;
73596 #endif
73597 	}
73598 	default: {
73599 		DUK_UNREACHABLE();
73600 		i3 = 0;  /* should not happen */
73601 		break;
73602 	}
73603 	}
73604 
73605 #if defined(DUK_USE_FASTINT)
73606 	/* Result is always fastint compatible. */
73607 	/* XXX: Set 32-bit result (but must then handle signed and
73608 	 * unsigned results separately).
73609 	 */
73610 	fi3 = (duk_int64_t) i3;
73611 
73612  fastint_result_set:
73613 	tv_z = thr->valstack_bottom + idx_z;
73614 	DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, fi3);  /* side effects */
73615 #else  /* DUK_USE_FASTINT */
73616 	d3 = (duk_double_t) i3;
73617 
73618  result_set:
73619 	DUK_ASSERT(!DUK_ISNAN(d3));            /* 'd3' is never NaN, so no need to normalize */
73620 	DUK_ASSERT_DOUBLE_IS_NORMALIZED(d3);   /* always normalized */
73621 
73622 #if defined(DUK_USE_EXEC_PREFER_SIZE)
73623 	duk_push_number(thr, d3);  /* would NaN normalize result, but unnecessary */
73624 	duk_replace(thr, (duk_idx_t) idx_z);
73625 #else  /* DUK_USE_EXEC_PREFER_SIZE */
73626 	tv_z = thr->valstack_bottom + idx_z;
73627 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, d3);  /* side effects */
73628 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
73629 #endif  /* DUK_USE_FASTINT */
73630 }
73631 
73632 /* In-place unary operation. */
73633 DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_unary_op(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst, duk_small_uint_fast_t opcode) {
73634 	/*
73635 	 *  Arithmetic operations other than '+' have number-only semantics
73636 	 *  and are implemented here.  The separate switch-case here means a
73637 	 *  "double dispatch" of the arithmetic opcode, but saves code space.
73638 	 *
73639 	 *  E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
73640 	 */
73641 
73642 	duk_tval *tv;
73643 	duk_double_t d1;
73644 	duk_double_union du;
73645 
73646 	DUK_ASSERT(thr != NULL);
73647 	DUK_ASSERT(opcode == DUK_OP_UNM || opcode == DUK_OP_UNP);
73648 	DUK_ASSERT_DISABLE(idx_src >= 0);
73649 	DUK_ASSERT_DISABLE(idx_dst >= 0);
73650 
73651 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);
73652 
73653 #if defined(DUK_USE_FASTINT)
73654 	if (DUK_TVAL_IS_FASTINT(tv)) {
73655 		duk_int64_t v1, v2;
73656 
73657 		v1 = DUK_TVAL_GET_FASTINT(tv);
73658 		if (opcode == DUK_OP_UNM) {
73659 			/* The smallest fastint is no longer 48-bit when
73660 			 * negated.  Positive zero becames negative zero
73661 			 * (cannot be represented) when negated.
73662 			 */
73663 			if (DUK_LIKELY(v1 != DUK_FASTINT_MIN && v1 != 0)) {
73664 				v2 = -v1;
73665 				tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
73666 				DUK_TVAL_SET_FASTINT_UPDREF(thr, tv, v2);
73667 				return;
73668 			}
73669 		} else {
73670 			/* ToNumber() for a fastint is a no-op. */
73671 			DUK_ASSERT(opcode == DUK_OP_UNP);
73672 			v2 = v1;
73673 			tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
73674 			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv, v2);
73675 			return;
73676 		}
73677 		/* fall through if overflow etc */
73678 	}
73679 #endif  /* DUK_USE_FASTINT */
73680 
73681 	if (DUK_TVAL_IS_NUMBER(tv)) {
73682 		d1 = DUK_TVAL_GET_NUMBER(tv);
73683 	} else {
73684 		d1 = duk_to_number_tval(thr, tv);  /* side effects */
73685 	}
73686 
73687 	if (opcode == DUK_OP_UNP) {
73688 		/* ToNumber() for a double is a no-op, but unary plus is
73689 		 * used to force a fastint check so do that here.
73690 		 */
73691 		du.d = d1;
73692 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
73693 #if defined(DUK_USE_FASTINT)
73694 		tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
73695 		DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF(thr, tv, du.d);  /* always 'fast', i.e. inlined */
73696 		return;
73697 #endif
73698 	} else {
73699 		DUK_ASSERT(opcode == DUK_OP_UNM);
73700 		du.d = -d1;
73701 		DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);  /* mandatory if du.d is a NaN */
73702 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
73703 	}
73704 
73705 	/* XXX: size optimize: push+replace? */
73706 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
73707 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, du.d);
73708 }
73709 
73710 DUK_LOCAL DUK__INLINE_PERF void duk__vm_bitwise_not(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst) {
73711 	/*
73712 	 *  E5 Section 11.4.8
73713 	 */
73714 
73715 	duk_tval *tv;
73716 	duk_int32_t i1, i2;
73717 
73718 	DUK_ASSERT(thr != NULL);
73719 	DUK_ASSERT_DISABLE(idx_src >= 0);
73720 	DUK_ASSERT_DISABLE(idx_dst >= 0);
73721 	DUK_ASSERT((duk_uint_t) idx_src < (duk_uint_t) duk_get_top(thr));
73722 	DUK_ASSERT((duk_uint_t) idx_dst < (duk_uint_t) duk_get_top(thr));
73723 
73724 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);
73725 
73726 #if defined(DUK_USE_FASTINT)
73727 	if (DUK_TVAL_IS_FASTINT(tv)) {
73728 		i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv);
73729 	}
73730 	else
73731 #endif  /* DUK_USE_FASTINT */
73732 	{
73733 		duk_push_tval(thr, tv);
73734 		i1 = duk_to_int32(thr, -1);  /* side effects */
73735 		duk_pop_unsafe(thr);
73736 	}
73737 
73738 	/* Result is always fastint compatible. */
73739 	i2 = ~i1;
73740 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
73741 	DUK_TVAL_SET_I32_UPDREF(thr, tv, i2);  /* side effects */
73742 }
73743 
73744 DUK_LOCAL DUK__INLINE_PERF void duk__vm_logical_not(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst) {
73745 	/*
73746 	 *  E5 Section 11.4.9
73747 	 */
73748 
73749 	duk_tval *tv;
73750 	duk_bool_t res;
73751 
73752 	DUK_ASSERT(thr != NULL);
73753 	DUK_ASSERT_DISABLE(idx_src >= 0);
73754 	DUK_ASSERT_DISABLE(idx_dst >= 0);
73755 	DUK_ASSERT((duk_uint_t) idx_src < (duk_uint_t) duk_get_top(thr));
73756 	DUK_ASSERT((duk_uint_t) idx_dst < (duk_uint_t) duk_get_top(thr));
73757 
73758 	/* ToBoolean() does not require any operations with side effects so
73759 	 * we can do it efficiently.  For footprint it would be better to use
73760 	 * duk_js_toboolean() and then push+replace to the result slot.
73761 	 */
73762 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);
73763 	res = duk_js_toboolean(tv);  /* does not modify 'tv' */
73764 	DUK_ASSERT(res == 0 || res == 1);
73765 	res ^= 1;
73766 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
73767 	/* XXX: size optimize: push+replace? */
73768 	DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, res);  /* side effects */
73769 }
73770 
73771 /* XXX: size optimized variant */
73772 DUK_LOCAL DUK__INLINE_PERF void duk__prepost_incdec_reg_helper(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_small_uint_t op) {
73773 	duk_double_t x, y, z;
73774 
73775 	/* Two lowest bits of opcode are used to distinguish
73776 	 * variants.  Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
73777 	 */
73778 	DUK_ASSERT((DUK_OP_PREINCR & 0x03) == 0x00);
73779 	DUK_ASSERT((DUK_OP_PREDECR & 0x03) == 0x01);
73780 	DUK_ASSERT((DUK_OP_POSTINCR & 0x03) == 0x02);
73781 	DUK_ASSERT((DUK_OP_POSTDECR & 0x03) == 0x03);
73782 
73783 #if defined(DUK_USE_FASTINT)
73784 	if (DUK_TVAL_IS_FASTINT(tv_src)) {
73785 		duk_int64_t x_fi, y_fi, z_fi;
73786 		x_fi = DUK_TVAL_GET_FASTINT(tv_src);
73787 		if (op & 0x01) {
73788 			if (DUK_UNLIKELY(x_fi == DUK_FASTINT_MIN)) {
73789 				goto skip_fastint;
73790 			}
73791 			y_fi = x_fi - 1;
73792 		} else {
73793 			if (DUK_UNLIKELY(x_fi == DUK_FASTINT_MAX)) {
73794 				goto skip_fastint;
73795 			}
73796 			y_fi = x_fi + 1;
73797 		}
73798 
73799 		DUK_TVAL_SET_FASTINT(tv_src, y_fi);  /* no need for refcount update */
73800 
73801 		z_fi = (op & 0x02) ? x_fi : y_fi;
73802 		DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_dst, z_fi);  /* side effects */
73803 		return;
73804 	}
73805  skip_fastint:
73806 #endif
73807 	if (DUK_TVAL_IS_NUMBER(tv_src)) {
73808 		/* Fast path for the case where the register
73809 		 * is a number (e.g. loop counter).
73810 		 */
73811 
73812 		x = DUK_TVAL_GET_NUMBER(tv_src);
73813 		if (op & 0x01) {
73814 			y = x - 1.0;
73815 		} else {
73816 			y = x + 1.0;
73817 		}
73818 
73819 		DUK_TVAL_SET_NUMBER(tv_src, y);  /* no need for refcount update */
73820 	} else {
73821 		/* Preserve duk_tval pointer(s) across a potential valstack
73822 		 * resize by converting them into offsets temporarily.
73823 		 */
73824 		duk_idx_t bc;
73825 		duk_size_t off_dst;
73826 
73827 		off_dst = (duk_size_t) ((duk_uint8_t *) tv_dst - (duk_uint8_t *) thr->valstack_bottom);
73828 		bc = (duk_idx_t) (tv_src - thr->valstack_bottom);  /* XXX: pass index explicitly? */
73829 		tv_src = NULL;  /* no longer referenced */
73830 
73831 		x = duk_to_number(thr, bc);
73832 		if (op & 0x01) {
73833 			y = x - 1.0;
73834 		} else {
73835 			y = x + 1.0;
73836 		}
73837 
73838 		duk_push_number(thr, y);
73839 		duk_replace(thr, bc);
73840 
73841 		tv_dst = (duk_tval *) (void *) (((duk_uint8_t *) thr->valstack_bottom) + off_dst);
73842 	}
73843 
73844 	z = (op & 0x02) ? x : y;
73845 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_dst, z);  /* side effects */
73846 }
73847 
73848 DUK_LOCAL DUK__INLINE_PERF void duk__prepost_incdec_var_helper(duk_hthread *thr, duk_small_uint_t idx_dst, duk_tval *tv_id, duk_small_uint_t op, duk_small_uint_t is_strict) {
73849 	duk_activation *act;
73850 	duk_double_t x, y;
73851 	duk_hstring *name;
73852 
73853 	/* XXX: The pre/post inc/dec for an identifier lookup is
73854 	 * missing the important fast path where the identifier
73855 	 * has a storage location e.g. in a scope object so that
73856 	 * it can be updated in-place.  In particular, the case
73857 	 * where the identifier has a storage location AND the
73858 	 * previous value is a number should be optimized because
73859 	 * it's side effect free.
73860 	 */
73861 
73862 	/* Two lowest bits of opcode are used to distinguish
73863 	 * variants.  Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
73864 	 */
73865 	DUK_ASSERT((DUK_OP_PREINCV & 0x03) == 0x00);
73866 	DUK_ASSERT((DUK_OP_PREDECV & 0x03) == 0x01);
73867 	DUK_ASSERT((DUK_OP_POSTINCV & 0x03) == 0x02);
73868 	DUK_ASSERT((DUK_OP_POSTDECV & 0x03) == 0x03);
73869 
73870 	DUK_ASSERT(DUK_TVAL_IS_STRING(tv_id));
73871 	name = DUK_TVAL_GET_STRING(tv_id);
73872 	DUK_ASSERT(name != NULL);
73873 	act = thr->callstack_curr;
73874 	(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [ ... val this ] */
73875 
73876 	/* XXX: Fastint fast path would be useful here.  Also fastints
73877 	 * now lose their fastint status in current handling which is
73878 	 * not intuitive.
73879 	 */
73880 
73881 	x = duk_to_number_m2(thr);
73882 	if (op & 0x01) {
73883 		y = x - 1.0;
73884 	} else {
73885 		y = x + 1.0;
73886 	}
73887 
73888 	/* [... x this] */
73889 
73890 	if (op & 0x02) {
73891 		duk_push_number(thr, y);  /* -> [ ... x this y ] */
73892 		DUK_ASSERT(act == thr->callstack_curr);
73893 		duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(thr, -1), is_strict);
73894 		duk_pop_2_unsafe(thr);  /* -> [ ... x ] */
73895 	} else {
73896 		duk_pop_2_unsafe(thr);  /* -> [ ... ] */
73897 		duk_push_number(thr, y);  /* -> [ ... y ] */
73898 		DUK_ASSERT(act == thr->callstack_curr);
73899 		duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(thr, -1), is_strict);
73900 	}
73901 
73902 #if defined(DUK_USE_EXEC_PREFER_SIZE)
73903 	duk_replace(thr, (duk_idx_t) idx_dst);
73904 #else  /* DUK_USE_EXEC_PREFER_SIZE */
73905 	DUK__REPLACE_TO_TVPTR(thr, DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst));
73906 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
73907 }
73908 
73909 /*
73910  *  Longjmp and other control flow transfer for the bytecode executor.
73911  *
73912  *  The longjmp handler can handle all longjmp types: error, yield, and
73913  *  resume (pseudotypes are never actually thrown).
73914  *
73915  *  Error policy for longjmp: should not ordinarily throw errors; if errors
73916  *  occur (e.g. due to out-of-memory) they bubble outwards rather than being
73917  *  handled recursively.
73918  */
73919 
73920 #define DUK__LONGJMP_RESTART   0  /* state updated, restart bytecode execution */
73921 #define DUK__LONGJMP_RETHROW   1  /* exit bytecode executor by rethrowing an error to caller */
73922 
73923 #define DUK__RETHAND_RESTART   0  /* state updated, restart bytecode execution */
73924 #define DUK__RETHAND_FINISHED  1  /* exit bytecode execution with return value */
73925 
73926 /* XXX: optimize reconfig valstack operations so that resize, clamp, and setting
73927  * top are combined into one pass.
73928  */
73929 
73930 /* Reconfigure value stack for return to an ECMAScript function at
73931  * callstack top (caller unwinds).
73932  */
73933 DUK_LOCAL void duk__reconfig_valstack_ecma_return(duk_hthread *thr) {
73934 	duk_activation *act;
73935 	duk_hcompfunc *h_func;
73936 	duk_idx_t clamp_top;
73937 
73938 	DUK_ASSERT(thr != NULL);
73939 	act = thr->callstack_curr;
73940 	DUK_ASSERT(act != NULL);
73941 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
73942 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act)));
73943 
73944 	/* Clamp so that values at 'clamp_top' and above are wiped and won't
73945 	 * retain reachable garbage.  Then extend to 'nregs' because we're
73946 	 * returning to an ECMAScript function.
73947 	 */
73948 
73949 	h_func = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
73950 
73951 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
73952 	DUK_ASSERT(act->retval_byteoff >= act->bottom_byteoff);
73953 	clamp_top = (duk_idx_t) ((act->retval_byteoff - act->bottom_byteoff + sizeof(duk_tval)) / sizeof(duk_tval));  /* +1 = one retval */
73954 	duk_set_top_and_wipe(thr, h_func->nregs, clamp_top);
73955 
73956 	DUK_ASSERT((duk_uint8_t *) thr->valstack_end >= (duk_uint8_t *) thr->valstack + act->reserve_byteoff);
73957 	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->reserve_byteoff);
73958 
73959 	/* XXX: a best effort shrink check would be OK here */
73960 }
73961 
73962 /* Reconfigure value stack for an ECMAScript catcher.  Use topmost catcher
73963  * in 'act'.
73964  */
73965 DUK_LOCAL void duk__reconfig_valstack_ecma_catcher(duk_hthread *thr, duk_activation *act) {
73966 	duk_catcher *cat;
73967 	duk_hcompfunc *h_func;
73968 	duk_size_t idx_bottom;
73969 	duk_idx_t clamp_top;
73970 
73971 	DUK_ASSERT(thr != NULL);
73972 	DUK_ASSERT(act != NULL);
73973 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
73974 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act)));
73975 	cat = act->cat;
73976 	DUK_ASSERT(cat != NULL);
73977 
73978 	h_func = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
73979 
73980 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
73981 	idx_bottom = (duk_size_t) (thr->valstack_bottom - thr->valstack);
73982 	DUK_ASSERT(cat->idx_base >= idx_bottom);
73983 	clamp_top = (duk_idx_t) (cat->idx_base - idx_bottom + 2);  /* +2 = catcher value, catcher lj_type */
73984 	duk_set_top_and_wipe(thr, h_func->nregs, clamp_top);
73985 
73986 	DUK_ASSERT((duk_uint8_t *) thr->valstack_end >= (duk_uint8_t *) thr->valstack + act->reserve_byteoff);
73987 	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->reserve_byteoff);
73988 
73989 	/* XXX: a best effort shrink check would be OK here */
73990 }
73991 
73992 /* Set catcher regs: idx_base+0 = value, idx_base+1 = lj_type.
73993  * No side effects.
73994  */
73995 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) {
73996 	duk_tval *tv1;
73997 
73998 	DUK_ASSERT(thr != NULL);
73999 	DUK_ASSERT(tv_val_unstable != NULL);
74000 
74001 	tv1 = thr->valstack + cat->idx_base;
74002 	DUK_ASSERT(tv1 < thr->valstack_top);
74003 	DUK_TVAL_SET_TVAL_UPDREF_NORZ(thr, tv1, tv_val_unstable);
74004 
74005 	tv1++;
74006 	DUK_ASSERT(tv1 == thr->valstack + cat->idx_base + 1);
74007 	DUK_ASSERT(tv1 < thr->valstack_top);
74008 	DUK_TVAL_SET_U32_UPDREF_NORZ(thr, tv1, (duk_uint32_t) lj_type);
74009 }
74010 
74011 DUK_LOCAL void duk__handle_catch(duk_hthread *thr, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
74012 	duk_activation *act;
74013 	duk_catcher *cat;
74014 
74015 	DUK_ASSERT(thr != NULL);
74016 	DUK_ASSERT(tv_val_unstable != NULL);
74017 
74018 	act = thr->callstack_curr;
74019 	DUK_ASSERT(act != NULL);
74020 	DUK_ASSERT(act->cat != NULL);
74021 	DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);
74022 
74023 	duk__set_catcher_regs_norz(thr, act->cat, tv_val_unstable, lj_type);
74024 
74025 	DUK_ASSERT(thr->callstack_top >= 1);
74026 	DUK_ASSERT(thr->callstack_curr != NULL);
74027 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
74028 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
74029 
74030 	DUK_ASSERT(thr->callstack_top >= 1);
74031 	DUK_ASSERT(act == thr->callstack_curr);
74032 	DUK_ASSERT(act != NULL);
74033 	duk__reconfig_valstack_ecma_catcher(thr, act);
74034 
74035 	DUK_ASSERT(thr->callstack_top >= 1);
74036 	DUK_ASSERT(act == thr->callstack_curr);
74037 	DUK_ASSERT(act != NULL);
74038 	cat = act->cat;
74039 	DUK_ASSERT(cat != NULL);
74040 
74041 	act->curr_pc = cat->pc_base + 0;  /* +0 = catch */
74042 
74043 	/*
74044 	 *  If entering a 'catch' block which requires an automatic
74045 	 *  catch variable binding, create the lexical environment.
74046 	 *
74047 	 *  The binding is mutable (= writable) but not deletable.
74048 	 *  Step 4 for the catch production in E5 Section 12.14;
74049 	 *  no value is given for CreateMutableBinding 'D' argument,
74050 	 *  which implies the binding is not deletable.
74051 	 */
74052 
74053 	if (DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat)) {
74054 		duk_hdecenv *new_env;
74055 
74056 		DUK_DDD(DUK_DDDPRINT("catcher has an automatic catch binding"));
74057 
74058 		DUK_ASSERT(thr->callstack_top >= 1);
74059 		DUK_ASSERT(act == thr->callstack_curr);
74060 		DUK_ASSERT(act != NULL);
74061 
74062 		if (act->lex_env == NULL) {
74063 			DUK_ASSERT(act->var_env == NULL);
74064 			DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
74065 
74066 			duk_js_init_activation_environment_records_delayed(thr, act);
74067 			DUK_ASSERT(act == thr->callstack_curr);
74068 			DUK_ASSERT(act != NULL);
74069 		}
74070 		DUK_ASSERT(act->lex_env != NULL);
74071 		DUK_ASSERT(act->var_env != NULL);
74072 		DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
74073 
74074 		/* XXX: If an out-of-memory happens here, longjmp state asserts
74075 		 * will be triggered at present and a try-catch fails to catch.
74076 		 * That's not sandboxing fatal (C API protected calls are what
74077 		 * matters), and script catch code can immediately throw anyway
74078 		 * for almost any operation.
74079 		 */
74080 		new_env = duk_hdecenv_alloc(thr,
74081 		                            DUK_HOBJECT_FLAG_EXTENSIBLE |
74082 		                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
74083 		DUK_ASSERT(new_env != NULL);
74084 		duk_push_hobject(thr, (duk_hobject *) new_env);
74085 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
74086 		DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));
74087 
74088 		/* Note: currently the catch binding is handled without a register
74089 		 * binding because we don't support dynamic register bindings (they
74090 		 * must be fixed for an entire function).  So, there is no need to
74091 		 * record regbases etc.
74092 		 */
74093 
74094 		/* XXX: duk_xdef_prop() may cause an out-of-memory, see above. */
74095 		DUK_ASSERT(cat->h_varname != NULL);
74096 		duk_push_hstring(thr, cat->h_varname);
74097 		duk_push_tval(thr, thr->valstack + cat->idx_base);
74098 		duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_W);  /* writable, not configurable */
74099 
74100 		DUK_ASSERT(act == thr->callstack_curr);
74101 		DUK_ASSERT(act != NULL);
74102 		DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, act->lex_env);
74103 		act->lex_env = (duk_hobject *) new_env;
74104 		DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);  /* reachable through activation */
74105 		/* Net refcount change to act->lex_env is 0: incref for new_env's
74106 		 * prototype, decref for act->lex_env overwrite.
74107 		 */
74108 
74109 		DUK_CAT_SET_LEXENV_ACTIVE(cat);
74110 
74111 		duk_pop_unsafe(thr);
74112 
74113 		DUK_DDD(DUK_DDDPRINT("new_env finished: %!iO", (duk_heaphdr *) new_env));
74114 	}
74115 
74116 	DUK_CAT_CLEAR_CATCH_ENABLED(cat);
74117 }
74118 
74119 DUK_LOCAL void duk__handle_finally(duk_hthread *thr, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
74120 	duk_activation *act;
74121 	duk_catcher *cat;
74122 
74123 	DUK_ASSERT(thr != NULL);
74124 	DUK_ASSERT(tv_val_unstable != NULL);
74125 
74126 	act = thr->callstack_curr;
74127 	DUK_ASSERT(act != NULL);
74128 	DUK_ASSERT(act->cat != NULL);
74129 	DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);
74130 
74131 	duk__set_catcher_regs_norz(thr, act->cat, tv_val_unstable, lj_type);
74132 
74133 	DUK_ASSERT(thr->callstack_top >= 1);
74134 	DUK_ASSERT(thr->callstack_curr != NULL);
74135 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
74136 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
74137 
74138 	DUK_ASSERT(thr->callstack_top >= 1);
74139 	DUK_ASSERT(act == thr->callstack_curr);
74140 	DUK_ASSERT(act != NULL);
74141 	duk__reconfig_valstack_ecma_catcher(thr, act);
74142 
74143 	DUK_ASSERT(thr->callstack_top >= 1);
74144 	DUK_ASSERT(act == thr->callstack_curr);
74145 	DUK_ASSERT(act != NULL);
74146 	cat = act->cat;
74147 	DUK_ASSERT(cat != NULL);
74148 
74149 	act->curr_pc = cat->pc_base + 1;  /* +1 = finally */
74150 
74151 	DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
74152 }
74153 
74154 DUK_LOCAL void duk__handle_label(duk_hthread *thr, duk_small_uint_t lj_type) {
74155 	duk_activation *act;
74156 	duk_catcher *cat;
74157 
74158 	DUK_ASSERT(thr != NULL);
74159 
74160 	DUK_ASSERT(thr->callstack_top >= 1);
74161 	act = thr->callstack_curr;
74162 	DUK_ASSERT(act != NULL);
74163 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
74164 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(DUK_ACT_GET_FUNC(act)));
74165 
74166 	/* +0 = break, +1 = continue */
74167 	cat = act->cat;
74168 	DUK_ASSERT(cat != NULL);
74169 	DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL);
74170 
74171 	act->curr_pc = cat->pc_base + (lj_type == DUK_LJ_TYPE_CONTINUE ? 1 : 0);
74172 
74173 	/* valstack should not need changes */
74174 #if defined(DUK_USE_ASSERTIONS)
74175 	DUK_ASSERT(thr->callstack_top >= 1);
74176 	DUK_ASSERT(act == thr->callstack_curr);
74177 	DUK_ASSERT(act != NULL);
74178 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) ==
74179 	           (duk_size_t) ((duk_hcompfunc *) DUK_ACT_GET_FUNC(act))->nregs);
74180 #endif
74181 }
74182 
74183 /* Called for handling both a longjmp() with type DUK_LJ_TYPE_YIELD and
74184  * when a RETURN opcode terminates a thread and yields to the resumer.
74185  * Caller unwinds so that top of callstack is the activation we return to.
74186  */
74187 #if defined(DUK_USE_COROUTINE_SUPPORT)
74188 DUK_LOCAL void duk__handle_yield(duk_hthread *thr, duk_hthread *resumer, duk_tval *tv_val_unstable) {
74189 	duk_activation *act_resumer;
74190 	duk_tval *tv1;
74191 
74192 	DUK_ASSERT(thr != NULL);
74193 	DUK_ASSERT(resumer != NULL);
74194 	DUK_ASSERT(tv_val_unstable != NULL);
74195 	act_resumer = resumer->callstack_curr;
74196 	DUK_ASSERT(act_resumer != NULL);
74197 	DUK_ASSERT(DUK_ACT_GET_FUNC(act_resumer) != NULL);
74198 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act_resumer)));  /* resume caller must be an ECMAScript func */
74199 
74200 	tv1 = (duk_tval *) (void *) ((duk_uint8_t *) resumer->valstack + act_resumer->retval_byteoff);  /* return value from Duktape.Thread.resume() */
74201 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable);  /* side effects */  /* XXX: avoid side effects */
74202 
74203 	duk__reconfig_valstack_ecma_return(resumer);
74204 
74205 	/* caller must change active thread, and set thr->resumer to NULL */
74206 }
74207 #endif  /* DUK_USE_COROUTINE_SUPPORT */
74208 
74209 DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation *entry_act) {
74210 	duk_small_uint_t retval = DUK__LONGJMP_RESTART;
74211 
74212 	DUK_ASSERT(thr != NULL);
74213 	DUK_ASSERT(entry_act != NULL);
74214 
74215 	/* 'thr' is the current thread, as no-one resumes except us and we
74216 	 * switch 'thr' in that case.
74217 	 */
74218 	DUK_ASSERT(thr == thr->heap->curr_thread);
74219 
74220 	/*
74221 	 *  (Re)try handling the longjmp.
74222 	 *
74223 	 *  A longjmp handler may convert the longjmp to a different type and
74224 	 *  "virtually" rethrow by goto'ing to 'check_longjmp'.  Before the goto,
74225 	 *  the following must be updated:
74226 	 *    - the heap 'lj' state
74227 	 *    - 'thr' must reflect the "throwing" thread
74228 	 */
74229 
74230  check_longjmp:
74231 
74232 	DUK_DD(DUK_DDPRINT("handling longjmp: type=%ld, value1=%!T, value2=%!T, iserror=%ld",
74233 	                   (long) thr->heap->lj.type,
74234 	                   (duk_tval *) &thr->heap->lj.value1,
74235 	                   (duk_tval *) &thr->heap->lj.value2,
74236 	                   (long) thr->heap->lj.iserror));
74237 
74238 	switch (thr->heap->lj.type) {
74239 
74240 #if defined(DUK_USE_COROUTINE_SUPPORT)
74241 	case DUK_LJ_TYPE_RESUME: {
74242 		/*
74243 		 *  Note: lj.value1 is 'value', lj.value2 is 'resumee'.
74244 		 *  This differs from YIELD.
74245 		 */
74246 
74247 		duk_tval *tv;
74248 		duk_tval *tv2;
74249 		duk_hthread *resumee;
74250 
74251 		/* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
74252 
74253 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);                                                         /* unchanged by Duktape.Thread.resume() */
74254 		DUK_ASSERT(thr->callstack_top >= 2);                                                                         /* ECMAScript activation + Duktape.Thread.resume() activation */
74255 		DUK_ASSERT(thr->callstack_curr != NULL);
74256 		DUK_ASSERT(thr->callstack_curr->parent != NULL);
74257 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL &&
74258 		           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)) &&
74259 		           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->callstack_curr))->func == duk_bi_thread_resume);
74260 
74261 		tv = &thr->heap->lj.value2;  /* resumee */
74262 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
74263 		DUK_ASSERT(DUK_TVAL_GET_OBJECT(tv) != NULL);
74264 		DUK_ASSERT(DUK_HOBJECT_IS_THREAD(DUK_TVAL_GET_OBJECT(tv)));
74265 		resumee = (duk_hthread *) DUK_TVAL_GET_OBJECT(tv);
74266 
74267 		DUK_ASSERT(resumee != NULL);
74268 		DUK_ASSERT(resumee->resumer == NULL);
74269 		DUK_ASSERT(resumee->state == DUK_HTHREAD_STATE_INACTIVE ||
74270 		           resumee->state == DUK_HTHREAD_STATE_YIELDED);                                                     /* checked by Duktape.Thread.resume() */
74271 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
74272 		           resumee->callstack_top >= 2);                                                                     /* YIELDED: ECMAScript activation + Duktape.Thread.yield() activation */
74273 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
74274 		           (DUK_ACT_GET_FUNC(resumee->callstack_curr) != NULL &&
74275 		            DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(resumee->callstack_curr)) &&
74276 		            ((duk_hnatfunc *) DUK_ACT_GET_FUNC(resumee->callstack_curr))->func == duk_bi_thread_yield));
74277 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_INACTIVE ||
74278 		           resumee->callstack_top == 0);                                                                     /* INACTIVE: no activation, single function value on valstack */
74279 
74280 		if (thr->heap->lj.iserror) {
74281 			/*
74282 			 *  Throw the error in the resumed thread's context; the
74283 			 *  error value is pushed onto the resumee valstack.
74284 			 *
74285 			 *  Note: the callstack of the target may empty in this case
74286 			 *  too (i.e. the target thread has never been resumed).  The
74287 			 *  value stack will contain the initial function in that case,
74288 			 *  which we simply ignore.
74289 			 */
74290 
74291 			DUK_ASSERT(resumee->resumer == NULL);
74292 			resumee->resumer = thr;
74293 			DUK_HTHREAD_INCREF(thr, thr);
74294 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
74295 			thr->state = DUK_HTHREAD_STATE_RESUMED;
74296 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
74297 			thr = resumee;
74298 
74299 			thr->heap->lj.type = DUK_LJ_TYPE_THROW;
74300 
74301 			/* thr->heap->lj.value1 is already the value to throw */
74302 			/* thr->heap->lj.value2 is 'thread', will be wiped out at the end */
74303 
74304 			DUK_ASSERT(thr->heap->lj.iserror);  /* already set */
74305 
74306 			DUK_DD(DUK_DDPRINT("-> resume with an error, converted to a throw in the resumee, propagate"));
74307 			goto check_longjmp;
74308 		} else if (resumee->state == DUK_HTHREAD_STATE_YIELDED) {
74309 			/* Unwind previous Duktape.Thread.yield() call.  The
74310 			 * activation remaining must always be an ECMAScript
74311 			 * call now (yield() accepts calls from ECMAScript
74312 			 * only).
74313 			 */
74314 			duk_activation *act_resumee;
74315 
74316 			DUK_ASSERT(resumee->callstack_top >= 2);
74317 			act_resumee = resumee->callstack_curr;  /* Duktape.Thread.yield() */
74318 			DUK_ASSERT(act_resumee != NULL);
74319 			act_resumee = act_resumee->parent;      /* ECMAScript call site for yield() */
74320 			DUK_ASSERT(act_resumee != NULL);
74321 
74322 			tv = (duk_tval *) (void *) ((duk_uint8_t *) resumee->valstack + act_resumee->retval_byteoff);  /* return value from Duktape.Thread.yield() */
74323 			DUK_ASSERT(tv >= resumee->valstack && tv < resumee->valstack_top);
74324 			tv2 = &thr->heap->lj.value1;
74325 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv2);  /* side effects */  /* XXX: avoid side effects */
74326 
74327 			duk_hthread_activation_unwind_norz(resumee);  /* unwind to 'yield' caller */
74328 			/* no need to unwind catch stack */
74329 
74330 			duk__reconfig_valstack_ecma_return(resumee);
74331 
74332 			DUK_ASSERT(resumee->resumer == NULL);
74333 			resumee->resumer = thr;
74334 			DUK_HTHREAD_INCREF(thr, thr);
74335 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
74336 			thr->state = DUK_HTHREAD_STATE_RESUMED;
74337 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
74338 #if 0
74339 			thr = resumee;  /* not needed, as we exit right away */
74340 #endif
74341 			DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
74342 			retval = DUK__LONGJMP_RESTART;
74343 			goto wipe_and_return;
74344 		} else {
74345 			/* Initial resume call. */
74346 			duk_small_uint_t call_flags;
74347 			duk_int_t setup_rc;
74348 
74349 			/* resumee: [... initial_func]  (currently actually: [initial_func]) */
74350 
74351 			duk_push_undefined(resumee);
74352 			tv = &thr->heap->lj.value1;
74353 			duk_push_tval(resumee, tv);
74354 
74355 			/* resumee: [... initial_func undefined(= this) resume_value ] */
74356 
74357 			call_flags = DUK_CALL_FLAG_ALLOW_ECMATOECMA;  /* not tailcall, ecma-to-ecma (assumed to succeed) */
74358 
74359 			setup_rc = duk_handle_call_unprotected_nargs(resumee, 1 /*nargs*/, call_flags);
74360 			if (setup_rc == 0) {
74361 				/* This shouldn't happen; Duktape.Thread.resume()
74362 				 * should make sure of that.  If it does happen
74363 				 * this internal error will propagate out of the
74364 				 * executor which can be quite misleading.
74365 				 */
74366 				DUK_ERROR_INTERNAL(thr);
74367 				DUK_WO_NORETURN(return 0;);
74368 			}
74369 
74370 			DUK_ASSERT(resumee->resumer == NULL);
74371 			resumee->resumer = thr;
74372 			DUK_HTHREAD_INCREF(thr, thr);
74373 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
74374 			thr->state = DUK_HTHREAD_STATE_RESUMED;
74375 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
74376 #if 0
74377 			thr = resumee;  /* not needed, as we exit right away */
74378 #endif
74379 			DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
74380 			retval = DUK__LONGJMP_RESTART;
74381 			goto wipe_and_return;
74382 		}
74383 		DUK_UNREACHABLE();
74384 		break;  /* never here */
74385 	}
74386 
74387 	case DUK_LJ_TYPE_YIELD: {
74388 		/*
74389 		 *  Currently only allowed only if yielding thread has only
74390 		 *  ECMAScript activations (except for the Duktape.Thread.yield()
74391 		 *  call at the callstack top) and none of them constructor
74392 		 *  calls.
74393 		 *
74394 		 *  This excludes the 'entry' thread which will always have
74395 		 *  a preventcount > 0.
74396 		 */
74397 
74398 		duk_hthread *resumer;
74399 
74400 		/* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
74401 
74402 #if 0  /* entry_thread not available for assert */
74403 		DUK_ASSERT(thr != entry_thread);                                                                             /* Duktape.Thread.yield() should prevent */
74404 #endif
74405 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);                                                         /* unchanged from Duktape.Thread.yield() */
74406 		DUK_ASSERT(thr->callstack_top >= 2);                                                                         /* ECMAScript activation + Duktape.Thread.yield() activation */
74407 		DUK_ASSERT(thr->callstack_curr != NULL);
74408 		DUK_ASSERT(thr->callstack_curr->parent != NULL);
74409 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL &&
74410 		           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)) &&
74411 		           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->callstack_curr))->func == duk_bi_thread_yield);
74412 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL &&
74413 		           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent)));                              /* an ECMAScript function */
74414 
74415 		resumer = thr->resumer;
74416 
74417 		DUK_ASSERT(resumer != NULL);
74418 		DUK_ASSERT(resumer->state == DUK_HTHREAD_STATE_RESUMED);                                                     /* written by a previous RESUME handling */
74419 		DUK_ASSERT(resumer->callstack_top >= 2);                                                                     /* ECMAScript activation + Duktape.Thread.resume() activation */
74420 		DUK_ASSERT(resumer->callstack_curr != NULL);
74421 		DUK_ASSERT(resumer->callstack_curr->parent != NULL);
74422 		DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack_curr) != NULL &&
74423 		           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr)) &&
74424 		           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(resumer->callstack_curr))->func == duk_bi_thread_resume);
74425 		DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent) != NULL &&
74426 		           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent)));                            /* an ECMAScript function */
74427 
74428 		if (thr->heap->lj.iserror) {
74429 			thr->state = DUK_HTHREAD_STATE_YIELDED;
74430 			thr->resumer = NULL;
74431 			DUK_HTHREAD_DECREF_NORZ(thr, resumer);
74432 			resumer->state = DUK_HTHREAD_STATE_RUNNING;
74433 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
74434 			thr = resumer;
74435 
74436 			thr->heap->lj.type = DUK_LJ_TYPE_THROW;
74437 			/* lj.value1 is already set */
74438 			DUK_ASSERT(thr->heap->lj.iserror);  /* already set */
74439 
74440 			DUK_DD(DUK_DDPRINT("-> yield an error, converted to a throw in the resumer, propagate"));
74441 			goto check_longjmp;
74442 		} else {
74443 			duk_hthread_activation_unwind_norz(resumer);
74444 			duk__handle_yield(thr, resumer, &thr->heap->lj.value1);
74445 
74446 			thr->state = DUK_HTHREAD_STATE_YIELDED;
74447 			thr->resumer = NULL;
74448 			DUK_HTHREAD_DECREF_NORZ(thr, resumer);
74449 			resumer->state = DUK_HTHREAD_STATE_RUNNING;
74450 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
74451 #if 0
74452 			thr = resumer;  /* not needed, as we exit right away */
74453 #endif
74454 
74455 			DUK_DD(DUK_DDPRINT("-> yield a value, restart execution in resumer"));
74456 			retval = DUK__LONGJMP_RESTART;
74457 			goto wipe_and_return;
74458 		}
74459 		DUK_UNREACHABLE();
74460 		break;  /* never here */
74461 	}
74462 #endif  /* DUK_USE_COROUTINE_SUPPORT */
74463 
74464 	case DUK_LJ_TYPE_THROW: {
74465 		/*
74466 		 *  Three possible outcomes:
74467 		 *    * A try or finally catcher is found => resume there.
74468 		 *      (or)
74469 		 *    * The error propagates to the bytecode executor entry
74470 		 *      level (and we're in the entry thread) => rethrow
74471 		 *      with a new longjmp(), after restoring the previous
74472 		 *      catchpoint.
74473 		 *    * The error is not caught in the current thread, so
74474 		 *      the thread finishes with an error.  This works like
74475 		 *      a yielded error, except that the thread is finished
74476 		 *      and can no longer be resumed.  (There is always a
74477 		 *      resumer in this case.)
74478 		 *
74479 		 *  Note: until we hit the entry level, there can only be
74480 		 *  ECMAScript activations.
74481 		 */
74482 
74483 		duk_activation *act;
74484 		duk_catcher *cat;
74485 		duk_hthread *resumer;
74486 
74487 		for (;;) {
74488 			act = thr->callstack_curr;
74489 			if (act == NULL) {
74490 				break;
74491 			}
74492 
74493 			for (;;) {
74494 				cat = act->cat;
74495 				if (cat == NULL) {
74496 					break;
74497 				}
74498 
74499 				if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
74500 					DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
74501 
74502 					duk__handle_catch(thr,
74503 					                  &thr->heap->lj.value1,
74504 					                  DUK_LJ_TYPE_THROW);
74505 
74506 					DUK_DD(DUK_DDPRINT("-> throw caught by a 'catch' clause, restart execution"));
74507 					retval = DUK__LONGJMP_RESTART;
74508 					goto wipe_and_return;
74509 				}
74510 
74511 				if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
74512 					DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
74513 					DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat));
74514 
74515 					duk__handle_finally(thr,
74516 					                    &thr->heap->lj.value1,
74517 					                    DUK_LJ_TYPE_THROW);
74518 
74519 					DUK_DD(DUK_DDPRINT("-> throw caught by a 'finally' clause, restart execution"));
74520 					retval = DUK__LONGJMP_RESTART;
74521 					goto wipe_and_return;
74522 				}
74523 
74524 				duk_hthread_catcher_unwind_norz(thr, act);
74525 			}
74526 
74527 			if (act == entry_act) {
74528 				/* Not caught by anything before entry level; rethrow and let the
74529 				 * final catcher finish unwinding (esp. value stack).
74530 				 */
74531 				DUK_D(DUK_DPRINT("-> throw propagated up to entry level, rethrow and exit bytecode executor"));
74532 				retval = DUK__LONGJMP_RETHROW;
74533 				goto just_return;
74534 			}
74535 
74536 			duk_hthread_activation_unwind_norz(thr);
74537 		}
74538 
74539 		DUK_DD(DUK_DDPRINT("-> throw not caught by current thread, yield error to resumer and recheck longjmp"));
74540 
74541 		/* Not caught by current thread, thread terminates (yield error to resumer);
74542 		 * note that this may cause a cascade if the resumer terminates with an uncaught
74543 		 * exception etc (this is OK, but needs careful testing).
74544 		 */
74545 
74546 		DUK_ASSERT(thr->resumer != NULL);
74547 		DUK_ASSERT(thr->resumer->callstack_top >= 2);  /* ECMAScript activation + Duktape.Thread.resume() activation */
74548 		DUK_ASSERT(thr->resumer->callstack_curr != NULL);
74549 		DUK_ASSERT(thr->resumer->callstack_curr->parent != NULL);
74550 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent) != NULL &&
74551 		           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent)));  /* an ECMAScript function */
74552 
74553 		resumer = thr->resumer;
74554 
74555 		/* reset longjmp */
74556 
74557 		DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);  /* already set */
74558 		/* lj.value1 already set */
74559 
74560 		duk_hthread_terminate(thr);  /* updates thread state, minimizes its allocations */
74561 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
74562 
74563 		thr->resumer = NULL;
74564 		DUK_HTHREAD_DECREF_NORZ(thr, resumer);
74565 		resumer->state = DUK_HTHREAD_STATE_RUNNING;
74566 		DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
74567 		thr = resumer;
74568 		goto check_longjmp;
74569 	}
74570 
74571 	case DUK_LJ_TYPE_BREAK:  /* pseudotypes, not used in actual longjmps */
74572 	case DUK_LJ_TYPE_CONTINUE:
74573 	case DUK_LJ_TYPE_RETURN:
74574 	case DUK_LJ_TYPE_NORMAL:
74575 	default: {
74576 		/* should never happen, but be robust */
74577 		DUK_D(DUK_DPRINT("caught unknown longjmp type %ld, treat as internal error", (long) thr->heap->lj.type));
74578 		goto convert_to_internal_error;
74579 	}
74580 
74581 	}  /* end switch */
74582 
74583 	DUK_UNREACHABLE();
74584 
74585  wipe_and_return:
74586 	/* this is not strictly necessary, but helps debugging */
74587 	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
74588 	thr->heap->lj.iserror = 0;
74589 
74590 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1);  /* side effects */
74591 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2);  /* side effects */
74592 
74593 	DUK_GC_TORTURE(thr->heap);
74594 
74595  just_return:
74596 	return retval;
74597 
74598  convert_to_internal_error:
74599 	/* This could also be thrown internally (set the error, goto check_longjmp),
74600 	 * but it's better for internal errors to bubble outwards so that we won't
74601 	 * infinite loop in this catchpoint.
74602 	 */
74603 	DUK_ERROR_INTERNAL(thr);
74604 	DUK_WO_NORETURN(return 0;);
74605 }
74606 
74607 /* Handle a BREAK/CONTINUE opcode.  Avoid using longjmp() for BREAK/CONTINUE
74608  * handling because it has a measurable performance impact in ordinary
74609  * environments and an extreme impact in Emscripten (GH-342).
74610  */
74611 DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_break_or_continue(duk_hthread *thr,
74612                                                                 duk_uint_t label_id,
74613                                                                 duk_small_uint_t lj_type) {
74614 	duk_activation *act;
74615 	duk_catcher *cat;
74616 
74617 	DUK_ASSERT(thr != NULL);
74618 
74619 	/* Find a matching label catcher or 'finally' catcher in
74620 	 * the same function, unwinding catchers as we go.
74621 	 *
74622 	 * A label catcher must always exist and will match unless
74623 	 * a 'finally' captures the break/continue first.  It is the
74624 	 * compiler's responsibility to ensure that labels are used
74625 	 * correctly.
74626 	 */
74627 
74628 	act = thr->callstack_curr;
74629 	DUK_ASSERT(act != NULL);
74630 
74631 	for (;;) {
74632 		cat = act->cat;
74633 		if (cat == NULL) {
74634 			break;
74635 		}
74636 
74637 		DUK_DDD(DUK_DDDPRINT("considering catcher %p: type=%ld label=%ld",
74638 		                     (void *) cat,
74639 		                     (long) DUK_CAT_GET_TYPE(cat),
74640 		                     (long) DUK_CAT_GET_LABEL(cat)));
74641 
74642 		/* XXX: bit mask test; FINALLY <-> TCF, single bit mask would suffice? */
74643 
74644 		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
74645 		    DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
74646 			duk_tval tv_tmp;
74647 
74648 			DUK_TVAL_SET_U32(&tv_tmp, (duk_uint32_t) label_id);
74649 			duk__handle_finally(thr, &tv_tmp, lj_type);
74650 
74651 			DUK_DD(DUK_DDPRINT("-> break/continue caught by 'finally', restart execution"));
74652 			return;
74653 		}
74654 		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL &&
74655 		    (duk_uint_t) DUK_CAT_GET_LABEL(cat) == label_id) {
74656 			duk__handle_label(thr, lj_type);
74657 
74658 			DUK_DD(DUK_DDPRINT("-> break/continue caught by a label catcher (in the same function), restart execution"));
74659 			return;
74660 		}
74661 
74662 		duk_hthread_catcher_unwind_norz(thr, act);
74663 	}
74664 
74665 	/* Should never happen, but be robust. */
74666 	DUK_D(DUK_DPRINT("-> break/continue not caught by anything in the current function (should never happen), throw internal error"));
74667 	DUK_ERROR_INTERNAL(thr);
74668 	DUK_WO_NORETURN(return;);
74669 }
74670 
74671 /* Handle a RETURN opcode.  Avoid using longjmp() for return handling because
74672  * it has a measurable performance impact in ordinary environments and an extreme
74673  * impact in Emscripten (GH-342).  Return value is on value stack top.
74674  */
74675 DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr, duk_activation *entry_act) {
74676 	duk_tval *tv1;
74677 	duk_tval *tv2;
74678 #if defined(DUK_USE_COROUTINE_SUPPORT)
74679 	duk_hthread *resumer;
74680 #endif
74681 	duk_activation *act;
74682 	duk_catcher *cat;
74683 
74684 	/* We can directly access value stack here. */
74685 
74686 	DUK_ASSERT(thr != NULL);
74687 	DUK_ASSERT(entry_act != NULL);
74688 	DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
74689 	tv1 = thr->valstack_top - 1;
74690 	DUK_TVAL_CHKFAST_INPLACE_FAST(tv1);  /* fastint downgrade check for return values */
74691 
74692 	/*
74693 	 *  Four possible outcomes:
74694 	 *
74695 	 *    1. A 'finally' in the same function catches the 'return'.
74696 	 *       It may continue to propagate when 'finally' is finished,
74697 	 *       or it may be neutralized by 'finally' (both handled by
74698 	 *       ENDFIN).
74699 	 *
74700 	 *    2. The return happens at the entry level of the bytecode
74701 	 *       executor, so return from the executor (in C stack).
74702 	 *
74703 	 *    3. There is a calling (ECMAScript) activation in the call
74704 	 *       stack => return to it, in the same executor instance.
74705 	 *
74706 	 *    4. There is no calling activation, and the thread is
74707 	 *       terminated.  There is always a resumer in this case,
74708 	 *       which gets the return value similarly to a 'yield'
74709 	 *       (except that the current thread can no longer be
74710 	 *       resumed).
74711 	 */
74712 
74713 	DUK_ASSERT(thr != NULL);
74714 	DUK_ASSERT(thr->callstack_top >= 1);
74715 
74716 	act = thr->callstack_curr;
74717 	DUK_ASSERT(act != NULL);
74718 
74719 	for (;;) {
74720 		cat = act->cat;
74721 		if (cat == NULL) {
74722 			break;
74723 		}
74724 
74725 		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
74726 		    DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
74727 			DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
74728 			duk__handle_finally(thr, thr->valstack_top - 1, DUK_LJ_TYPE_RETURN);
74729 
74730 			DUK_DD(DUK_DDPRINT("-> return caught by 'finally', restart execution"));
74731 			return DUK__RETHAND_RESTART;
74732 		}
74733 
74734 		duk_hthread_catcher_unwind_norz(thr, act);
74735 	}
74736 
74737 	if (act == entry_act) {
74738 		/* Return to the bytecode executor caller who will unwind stacks
74739 		 * and handle constructor post-processing.
74740 		 * Return value is already on the stack top: [ ... retval ].
74741 		 */
74742 
74743 		DUK_DDD(DUK_DDDPRINT("-> return propagated up to entry level, exit bytecode executor"));
74744 		return DUK__RETHAND_FINISHED;
74745 	}
74746 
74747 	if (thr->callstack_top >= 2) {
74748 		/* There is a caller; it MUST be an ECMAScript caller (otherwise it would
74749 		 * match entry_act check).
74750 		 */
74751 		DUK_DDD(DUK_DDDPRINT("return to ECMAScript caller, retval_byteoff=%ld, lj_value1=%!T",
74752 		                     (long) (thr->callstack_curr->parent->retval_byteoff),
74753 		                     (duk_tval *) &thr->heap->lj.value1));
74754 
74755 		DUK_ASSERT(thr->callstack_curr != NULL);
74756 		DUK_ASSERT(thr->callstack_curr->parent != NULL);
74757 		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent)));   /* must be ECMAScript */
74758 
74759 #if defined(DUK_USE_ES6_PROXY)
74760 		if (thr->callstack_curr->flags & (DUK_ACT_FLAG_CONSTRUCT | DUK_ACT_FLAG_CONSTRUCT_PROXY)) {
74761 			duk_call_construct_postprocess(thr, thr->callstack_curr->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY);  /* side effects */
74762 		}
74763 #else
74764 		if (thr->callstack_curr->flags & DUK_ACT_FLAG_CONSTRUCT) {
74765 			duk_call_construct_postprocess(thr, 0);  /* side effects */
74766 		}
74767 #endif
74768 
74769 		tv1 = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + thr->callstack_curr->parent->retval_byteoff);
74770 		DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
74771 		tv2 = thr->valstack_top - 1;
74772 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
74773 
74774 		/* Catch stack unwind happens inline in callstack unwind. */
74775 		duk_hthread_activation_unwind_norz(thr);
74776 
74777 		duk__reconfig_valstack_ecma_return(thr);
74778 
74779 		DUK_DD(DUK_DDPRINT("-> return not intercepted, restart execution in caller"));
74780 		return DUK__RETHAND_RESTART;
74781 	}
74782 
74783 #if defined(DUK_USE_COROUTINE_SUPPORT)
74784 	DUK_DD(DUK_DDPRINT("no calling activation, thread finishes (similar to yield)"));
74785 
74786 	DUK_ASSERT(thr->resumer != NULL);
74787 	DUK_ASSERT(thr->resumer->callstack_top >= 2);  /* ECMAScript activation + Duktape.Thread.resume() activation */
74788 	DUK_ASSERT(thr->resumer->callstack_curr != NULL);
74789 	DUK_ASSERT(thr->resumer->callstack_curr->parent != NULL);
74790 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr) != NULL &&
74791 			DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr)) &&
74792 			((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->resumer->callstack_curr))->func == duk_bi_thread_resume);  /* Duktape.Thread.resume() */
74793 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent) != NULL &&
74794 			DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent)));  /* an ECMAScript function */
74795 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
74796 	DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);
74797 
74798 	resumer = thr->resumer;
74799 
74800 	/* Share yield longjmp handler.
74801 	 *
74802 	 * This sequence of steps is a bit fragile (see GH-1845):
74803 	 * - We need the return value from 'thr' (resumed thread) value stack.
74804 	 *   The termination unwinds its value stack, losing the value.
74805 	 * - We need a refcounted reference for 'thr', which may only exist
74806 	 *   in the caller value stack.  We can't unwind or reconfigure the
74807 	 *   caller's value stack without potentially freeing 'thr'.
74808 	 *
74809 	 * Current approach is to capture the 'thr' return value and store
74810 	 * a reference to 'thr' in the caller value stack temporarily.  This
74811 	 * keeps 'thr' reachable until final yield/return handling which
74812 	 * removes the references atomatically.
74813 	 */
74814 
74815 	DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
74816 	duk_hthread_activation_unwind_norz(resumer);  /* May remove last reference to 'thr', but is NORZ. */
74817 	duk_push_tval(resumer, thr->valstack_top - 1);  /* Capture return value, side effect free. */
74818 	duk_push_hthread(resumer, thr);  /* Make 'thr' reachable again, before side effects. */
74819 
74820 	duk_hthread_terminate(thr);  /* Updates thread state, minimizes its allocations. */
74821 	thr->resumer = NULL;
74822 	DUK_HTHREAD_DECREF(thr, resumer);
74823 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
74824 
74825 	resumer->state = DUK_HTHREAD_STATE_RUNNING;
74826 	DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
74827 
74828 	DUK_ASSERT(resumer->valstack_top - 2 >= resumer->valstack_bottom);
74829 	duk__handle_yield(thr, resumer, resumer->valstack_top - 2);
74830 	thr = NULL;  /* 'thr' invalidated by call */
74831 
74832 #if 0
74833 	thr = resumer;  /* not needed */
74834 #endif
74835 
74836 	DUK_DD(DUK_DDPRINT("-> return not caught, thread terminated; handle like yield, restart execution in resumer"));
74837 	return DUK__RETHAND_RESTART;
74838 #else
74839 	/* Without coroutine support this case should never happen. */
74840 	DUK_ERROR_INTERNAL(thr);
74841 	DUK_WO_NORETURN(return 0;);
74842 #endif
74843 }
74844 
74845 /*
74846  *  Executor interrupt handling
74847  *
74848  *  The handler is called whenever the interrupt countdown reaches zero
74849  *  (or below).  The handler must perform whatever checks are activated,
74850  *  e.g. check for cumulative step count to impose an execution step
74851  *  limit or check for breakpoints or other debugger interaction.
74852  *
74853  *  When the actions are done, the handler must reinit the interrupt
74854  *  init and counter values.  The 'init' value must indicate how many
74855  *  bytecode instructions are executed before the next interrupt.  The
74856  *  counter must interface with the bytecode executor loop.  Concretely,
74857  *  the new init value is normally one higher than the new counter value.
74858  *  For instance, to execute exactly one bytecode instruction the init
74859  *  value is set to 1 and the counter to 0.  If an error is thrown by the
74860  *  interrupt handler, the counters are set to the same value (e.g. both
74861  *  to 0 to cause an interrupt when the next bytecode instruction is about
74862  *  to be executed after error handling).
74863  *
74864  *  Maintaining the init/counter value properly is important for accurate
74865  *  behavior.  For instance, executor step limit needs a cumulative step
74866  *  count which is simply computed as a sum of 'init' values.  This must
74867  *  work accurately even when single stepping.
74868  */
74869 
74870 #if defined(DUK_USE_INTERRUPT_COUNTER)
74871 
74872 #define DUK__INT_NOACTION    0    /* no specific action, resume normal execution */
74873 #define DUK__INT_RESTART     1    /* must "goto restart_execution", e.g. breakpoints changed */
74874 
74875 #if defined(DUK_USE_DEBUGGER_SUPPORT)
74876 DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_immediate, duk_small_uint_t *out_interrupt_retval) {
74877 	duk_activation *act;
74878 	duk_breakpoint *bp;
74879 	duk_breakpoint **bp_active;
74880 	duk_uint_fast32_t line = 0;
74881 	duk_bool_t process_messages;
74882 	duk_bool_t processed_messages = 0;
74883 
74884 	DUK_ASSERT(thr->heap->dbg_processing == 0);  /* don't re-enter e.g. during Eval */
74885 
74886 	act = thr->callstack_curr;
74887 	DUK_ASSERT(act != NULL);
74888 
74889 	/* It might seem that replacing 'thr->heap' with just 'heap' below
74890 	 * might be a good idea, but it increases code size slightly
74891 	 * (probably due to unnecessary spilling) at least on x64.
74892 	 */
74893 
74894 	/*
74895 	 *  Single opcode step check
74896 	 */
74897 
74898 	if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE) {
74899 		DUK_D(DUK_DPRINT("PAUSE TRIGGERED by one opcode step"));
74900 		duk_debug_set_paused(thr->heap);
74901 	}
74902 
74903 	/*
74904 	 *  Breakpoint and step state checks
74905 	 */
74906 
74907 	if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||
74908 	    (thr->heap->dbg_pause_act == thr->callstack_curr)) {
74909 		line = duk_debug_curr_line(thr);
74910 
74911 		if (act->prev_line != line) {
74912 			/* Stepped?  Step out is handled by callstack unwind. */
74913 			if ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
74914 			    (thr->heap->dbg_pause_act == thr->callstack_curr) &&
74915 			    (line != thr->heap->dbg_pause_startline)) {
74916 				DUK_D(DUK_DPRINT("PAUSE TRIGGERED by line change, at line %ld",
74917 				                 (long) line));
74918 				duk_debug_set_paused(thr->heap);
74919 			}
74920 
74921 			/* Check for breakpoints only on line transition.
74922 			 * Breakpoint is triggered when we enter the target
74923 			 * line from a different line, and the previous line
74924 			 * was within the same function.
74925 			 *
74926 			 * This condition is tricky: the condition used to be
74927 			 * that transition to -or across- the breakpoint line
74928 			 * triggered the breakpoint.  This seems intuitively
74929 			 * better because it handles breakpoints on lines with
74930 			 * no emitted opcodes; but this leads to the issue
74931 			 * described in: https://github.com/svaarala/duktape/issues/263.
74932 			 */
74933 			bp_active = thr->heap->dbg_breakpoints_active;
74934 			for (;;) {
74935 				bp = *bp_active++;
74936 				if (bp == NULL) {
74937 					break;
74938 				}
74939 
74940 				DUK_ASSERT(bp->filename != NULL);
74941 				if (act->prev_line != bp->line && line == bp->line) {
74942 					DUK_D(DUK_DPRINT("PAUSE TRIGGERED by breakpoint at %!O:%ld",
74943 					                 (duk_heaphdr *) bp->filename, (long) bp->line));
74944 					duk_debug_set_paused(thr->heap);
74945 				}
74946 			}
74947 		} else {
74948 			;
74949 		}
74950 
74951 		act->prev_line = (duk_uint32_t) line;
74952 	}
74953 
74954 	/*
74955 	 *  Rate limit check for sending status update or peeking into
74956 	 *  the debug transport.  Both can be expensive operations that
74957 	 *  we don't want to do on every opcode.
74958 	 *
74959 	 *  Making sure the interval remains reasonable on a wide variety
74960 	 *  of targets and bytecode is difficult without a timestamp, so
74961 	 *  we use a Date-provided timestamp for the rate limit check.
74962 	 *  But since it's also expensive to get a timestamp, a bytecode
74963 	 *  counter is used to rate limit getting timestamps.
74964 	 */
74965 
74966 	process_messages = 0;
74967 	if (thr->heap->dbg_state_dirty || DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || thr->heap->dbg_detaching) {
74968 		/* Enter message processing loop for sending Status notifys and
74969 		 * to finish a pending detach.
74970 		 */
74971 		process_messages = 1;
74972 	}
74973 
74974 	/* XXX: remove heap->dbg_exec_counter, use heap->inst_count_interrupt instead? */
74975 	DUK_ASSERT(thr->interrupt_init >= 0);
74976 	thr->heap->dbg_exec_counter += (duk_uint_t) thr->interrupt_init;
74977 	if (thr->heap->dbg_exec_counter - thr->heap->dbg_last_counter >= DUK_HEAP_DBG_RATELIMIT_OPCODES) {
74978 		/* Overflow of the execution counter is fine and doesn't break
74979 		 * anything here.
74980 		 */
74981 
74982 		duk_double_t now, diff_last;
74983 
74984 		thr->heap->dbg_last_counter = thr->heap->dbg_exec_counter;
74985 		now = duk_time_get_monotonic_time(thr);
74986 
74987 		diff_last = now - thr->heap->dbg_last_time;
74988 		if (diff_last < 0.0 || diff_last >= (duk_double_t) DUK_HEAP_DBG_RATELIMIT_MILLISECS) {
74989 			/* Monotonic time should not experience time jumps,
74990 			 * but the provider may be missing and we're actually
74991 			 * using ECMAScript time.  So, tolerate negative values
74992 			 * so that a time jump works reasonably.
74993 			 *
74994 			 * Same interval is now used for status sending and
74995 			 * peeking.
74996 			 */
74997 
74998 			thr->heap->dbg_last_time = now;
74999 			thr->heap->dbg_state_dirty = 1;
75000 			process_messages = 1;
75001 		}
75002 	}
75003 
75004 	/*
75005 	 *  Process messages and send status if necessary.
75006 	 *
75007 	 *  If we're paused, we'll block for new messages.  If we're not
75008 	 *  paused, we'll process anything we can peek but won't block
75009 	 *  for more.  Detach (and re-attach) handling is all localized
75010 	 *  to duk_debug_process_messages() too.
75011 	 *
75012 	 *  Debugger writes outside the message loop may cause debugger
75013 	 *  detach1 phase to run, after which dbg_read_cb == NULL and
75014 	 *  dbg_detaching != 0.  The message loop will finish the detach
75015 	 *  by running detach2 phase, so enter the message loop also when
75016 	 *  detaching.
75017 	 */
75018 
75019 	if (process_messages) {
75020 		DUK_ASSERT(thr->heap->dbg_processing == 0);
75021 		processed_messages = duk_debug_process_messages(thr, 0 /*no_block*/);
75022 		DUK_ASSERT(thr->heap->dbg_processing == 0);
75023 	}
75024 
75025 	/* Continue checked execution if there are breakpoints or we're stepping.
75026 	 * Also use checked execution if paused flag is active - it shouldn't be
75027 	 * because the debug message loop shouldn't terminate if it was.  Step out
75028 	 * is handled by callstack unwind and doesn't need checked execution.
75029 	 * Note that debugger may have detached due to error or explicit request
75030 	 * above, so we must recheck attach status.
75031 	 */
75032 
75033 	if (duk_debug_is_attached(thr->heap)) {
75034 		DUK_ASSERT(act == thr->callstack_curr);
75035 		DUK_ASSERT(act != NULL);
75036 		if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||
75037 		    (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE) ||
75038 		    ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
75039 		     thr->heap->dbg_pause_act == thr->callstack_curr) ||
75040 		     DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap)) {
75041 			*out_immediate = 1;
75042 		}
75043 
75044 		/* If we processed any debug messages breakpoints may have
75045 		 * changed; restart execution to re-check active breakpoints.
75046 		 */
75047 		if (processed_messages) {
75048 			DUK_D(DUK_DPRINT("processed debug messages, restart execution to recheck possibly changed breakpoints"));
75049 			*out_interrupt_retval = DUK__INT_RESTART;
75050 		} else {
75051 			if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE) {
75052 				/* Set 'pause after one opcode' active only when we're
75053 				 * actually just about to execute code.
75054 				 */
75055 				thr->heap->dbg_pause_flags |= DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE;
75056 			}
75057 		}
75058 	} else {
75059 		DUK_D(DUK_DPRINT("debugger became detached, resume normal execution"));
75060 	}
75061 }
75062 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
75063 
75064 DUK_LOCAL DUK__NOINLINE_PERF DUK_COLD duk_small_uint_t duk__executor_interrupt(duk_hthread *thr) {
75065 	duk_int_t ctr;
75066 	duk_activation *act;
75067 	duk_hcompfunc *fun;
75068 	duk_bool_t immediate = 0;
75069 	duk_small_uint_t retval;
75070 
75071 	DUK_ASSERT(thr != NULL);
75072 	DUK_ASSERT(thr->heap != NULL);
75073 	DUK_ASSERT(thr->callstack_top > 0);
75074 
75075 #if defined(DUK_USE_DEBUG)
75076 	thr->heap->inst_count_interrupt += thr->interrupt_init;
75077 	DUK_DD(DUK_DDPRINT("execution interrupt, counter=%ld, init=%ld, "
75078 	                   "instruction counts: executor=%ld, interrupt=%ld",
75079 	                   (long) thr->interrupt_counter, (long) thr->interrupt_init,
75080 	                   (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
75081 #endif
75082 
75083 	retval = DUK__INT_NOACTION;
75084 	ctr = DUK_HTHREAD_INTCTR_DEFAULT;
75085 
75086 	/*
75087 	 *  Avoid nested calls.  Concretely this happens during debugging, e.g.
75088 	 *  when we eval() an expression.
75089 	 *
75090 	 *  Also don't interrupt if we're currently doing debug processing
75091 	 *  (which can be initiated outside the bytecode executor) as this
75092 	 *  may cause the debugger to be called recursively.  Check required
75093 	 *  for correct operation of throw intercept and other "exotic" halting
75094 	 * scenarios.
75095 	 */
75096 
75097 #if defined(DUK_USE_DEBUGGER_SUPPORT)
75098 	if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap) || thr->heap->dbg_processing) {
75099 #else
75100 	if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap)) {
75101 #endif
75102 		DUK_DD(DUK_DDPRINT("nested executor interrupt, ignoring"));
75103 
75104 		/* Set a high interrupt counter; the original executor
75105 		 * interrupt invocation will rewrite before exiting.
75106 		 */
75107 		thr->interrupt_init = ctr;
75108 		thr->interrupt_counter = ctr - 1;
75109 		return DUK__INT_NOACTION;
75110 	}
75111 	DUK_HEAP_SET_INTERRUPT_RUNNING(thr->heap);
75112 
75113 	act = thr->callstack_curr;
75114 	DUK_ASSERT(act != NULL);
75115 
75116 	fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
75117 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC((duk_hobject *) fun));
75118 
75119 	DUK_UNREF(fun);
75120 
75121 #if defined(DUK_USE_EXEC_TIMEOUT_CHECK)
75122 	/*
75123 	 *  Execution timeout check
75124 	 */
75125 
75126 	if (DUK_USE_EXEC_TIMEOUT_CHECK(thr->heap->heap_udata)) {
75127 		/* Keep throwing an error whenever we get here.  The unusual values
75128 		 * are set this way because no instruction is ever executed, we just
75129 		 * throw an error until all try/catch/finally and other catchpoints
75130 		 * have been exhausted.  Duktape/C code gets control at each protected
75131 		 * call but whenever it enters back into Duktape the RangeError gets
75132 		 * raised.  User exec timeout check must consistently indicate a timeout
75133 		 * until we've fully bubbled out of Duktape.
75134 		 */
75135 		DUK_D(DUK_DPRINT("execution timeout, throwing a RangeError"));
75136 		thr->interrupt_init = 0;
75137 		thr->interrupt_counter = 0;
75138 		DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);
75139 		DUK_ERROR_RANGE(thr, "execution timeout");
75140 		DUK_WO_NORETURN(return 0;);
75141 	}
75142 #endif  /* DUK_USE_EXEC_TIMEOUT_CHECK */
75143 
75144 #if defined(DUK_USE_DEBUGGER_SUPPORT)
75145 	if (!thr->heap->dbg_processing &&
75146 	    (thr->heap->dbg_read_cb != NULL || thr->heap->dbg_detaching)) {
75147 		/* Avoid recursive re-entry; enter when we're attached or
75148 		 * detaching (to finish off the pending detach).
75149 		 */
75150 		duk__interrupt_handle_debugger(thr, &immediate, &retval);
75151 		DUK_ASSERT(act == thr->callstack_curr);
75152 	}
75153 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
75154 
75155 	/*
75156 	 *  Update the interrupt counter
75157 	 */
75158 
75159 	if (immediate) {
75160 		/* Cause an interrupt after executing one instruction. */
75161 		ctr = 1;
75162 	}
75163 
75164 	/* The counter value is one less than the init value: init value should
75165 	 * indicate how many instructions are executed before interrupt.  To
75166 	 * execute 1 instruction (after interrupt handler return), counter must
75167 	 * be 0.
75168 	 */
75169 	DUK_ASSERT(ctr >= 1);
75170 	thr->interrupt_init = ctr;
75171 	thr->interrupt_counter = ctr - 1;
75172 	DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);
75173 
75174 	return retval;
75175 }
75176 #endif  /* DUK_USE_INTERRUPT_COUNTER */
75177 
75178 /*
75179  *  Debugger handling for executor restart
75180  *
75181  *  Check for breakpoints, stepping, etc, and figure out if we should execute
75182  *  in checked or normal mode.  Note that we can't do this when an activation
75183  *  is created, because breakpoint status (and stepping status) may change
75184  *  later, so we must recheck every time we're executing an activation.
75185  *  This primitive should be side effect free to avoid changes during check.
75186  */
75187 
75188 #if defined(DUK_USE_DEBUGGER_SUPPORT)
75189 DUK_LOCAL void duk__executor_recheck_debugger(duk_hthread *thr, duk_activation *act, duk_hcompfunc *fun) {
75190 	duk_heap *heap;
75191 	duk_tval *tv_tmp;
75192 	duk_hstring *filename;
75193 	duk_small_uint_t bp_idx;
75194 	duk_breakpoint **bp_active;
75195 
75196 	DUK_ASSERT(thr != NULL);
75197 	DUK_ASSERT(act != NULL);
75198 	DUK_ASSERT(fun != NULL);
75199 
75200 	heap = thr->heap;
75201 	bp_active = heap->dbg_breakpoints_active;
75202 	act->flags &= ~DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
75203 
75204 	tv_tmp = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) fun, DUK_HTHREAD_STRING_FILE_NAME(thr));
75205 	if (tv_tmp && DUK_TVAL_IS_STRING(tv_tmp)) {
75206 		filename = DUK_TVAL_GET_STRING(tv_tmp);
75207 
75208 		/* Figure out all active breakpoints.  A breakpoint is
75209 		 * considered active if the current function's fileName
75210 		 * matches the breakpoint's fileName, AND there is no
75211 		 * inner function that has matching line numbers
75212 		 * (otherwise a breakpoint would be triggered both
75213 		 * inside and outside of the inner function which would
75214 		 * be confusing).  Example:
75215 		 *
75216 		 *     function foo() {
75217 		 *         print('foo');
75218 		 *         function bar() {    <-.  breakpoints in these
75219 		 *             print('bar');     |  lines should not affect
75220 		 *         }                   <-'  foo() execution
75221 		 *         bar();
75222 		 *     }
75223 		 *
75224 		 * We need a few things that are only available when
75225 		 * debugger support is enabled: (1) a line range for
75226 		 * each function, and (2) access to the function
75227 		 * template to access the inner functions (and their
75228 		 * line ranges).
75229 		 *
75230 		 * It's important to have a narrow match for active
75231 		 * breakpoints so that we don't enter checked execution
75232 		 * when that's not necessary.  For instance, if we're
75233 		 * running inside a certain function and there's
75234 		 * breakpoint outside in (after the call site), we
75235 		 * don't want to slow down execution of the function.
75236 		 */
75237 
75238 		for (bp_idx = 0; bp_idx < heap->dbg_breakpoint_count; bp_idx++) {
75239 			duk_breakpoint *bp = heap->dbg_breakpoints + bp_idx;
75240 			duk_hobject **funcs, **funcs_end;
75241 			duk_hcompfunc *inner_fun;
75242 			duk_bool_t bp_match;
75243 
75244 			if (bp->filename == filename &&
75245 			    bp->line >= fun->start_line && bp->line <= fun->end_line) {
75246 				bp_match = 1;
75247 				DUK_DD(DUK_DDPRINT("breakpoint filename and line match: "
75248 				                   "%s:%ld vs. %s (line %ld vs. %ld-%ld)",
75249 				                   DUK_HSTRING_GET_DATA(bp->filename),
75250 				                   (long) bp->line,
75251 				                   DUK_HSTRING_GET_DATA(filename),
75252 				                   (long) bp->line,
75253 				                   (long) fun->start_line,
75254 				                   (long) fun->end_line));
75255 
75256 				funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, fun);
75257 				funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, fun);
75258 				while (funcs != funcs_end) {
75259 					inner_fun = (duk_hcompfunc *) *funcs;
75260 					DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) inner_fun));
75261 					if (bp->line >= inner_fun->start_line && bp->line <= inner_fun->end_line) {
75262 						DUK_DD(DUK_DDPRINT("inner function masks ('captures') breakpoint"));
75263 						bp_match = 0;
75264 						break;
75265 					}
75266 					funcs++;
75267 				}
75268 
75269 				if (bp_match) {
75270 					/* No need to check for size of bp_active list,
75271 					 * it's always larger than maximum number of
75272 					 * breakpoints.
75273 					 */
75274 					act->flags |= DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
75275 					*bp_active = heap->dbg_breakpoints + bp_idx;
75276 					bp_active++;
75277 				}
75278 			}
75279 		}
75280 	}
75281 
75282 	*bp_active = NULL;  /* terminate */
75283 
75284 	DUK_DD(DUK_DDPRINT("ACTIVE BREAKPOINTS: %ld", (long) (bp_active - thr->heap->dbg_breakpoints_active)));
75285 
75286 	/* Force pause if we were doing "step into" in another activation. */
75287 	if ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_ENTRY) &&
75288 	    thr->heap->dbg_pause_act != thr->callstack_curr) {
75289 		DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function entry"));
75290 		duk_debug_set_paused(thr->heap);
75291 	}
75292 
75293 	/* Force interrupt right away if we're paused or in "checked mode".
75294 	 * Step out is handled by callstack unwind.
75295 	 */
75296 	if ((act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE) ||
75297 	    DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) ||
75298 	    ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
75299 	     thr->heap->dbg_pause_act == thr->callstack_curr)) {
75300 		/* We'll need to interrupt early so recompute the init
75301 		 * counter to reflect the number of bytecode instructions
75302 		 * executed so that step counts for e.g. debugger rate
75303 		 * limiting are accurate.
75304 		 */
75305 		DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
75306 		thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
75307 		thr->interrupt_counter = 0;
75308 	}
75309 }
75310 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
75311 
75312 /*
75313  *  Opcode handlers for opcodes with a lot of code and which are relatively
75314  *  rare; NOINLINE to reduce amount of code in main bytecode dispatcher.
75315  */
75316 
75317 DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_initset_initget(duk_hthread *thr, duk_uint_fast32_t ins) {
75318 	duk_bool_t is_set = (DUK_DEC_OP(ins) == DUK_OP_INITSET);
75319 	duk_uint_fast_t idx;
75320 	duk_uint_t defprop_flags;
75321 
75322 	/* A -> object register (acts as a source)
75323 	 * BC -> BC+0 contains key, BC+1 closure (value)
75324 	 */
75325 
75326 	/* INITSET/INITGET are only used to initialize object literal keys.
75327 	 * There may be a previous propery in ES2015 because duplicate property
75328 	 * names are allowed.
75329 	 */
75330 
75331 	/* This could be made more optimal by accessing internals directly. */
75332 
75333 	idx = (duk_uint_fast_t) DUK_DEC_BC(ins);
75334 	duk_dup(thr, (duk_idx_t) (idx + 0));  /* key */
75335 	duk_dup(thr, (duk_idx_t) (idx + 1));  /* getter/setter */
75336 	if (is_set) {
75337 	        defprop_flags = DUK_DEFPROP_HAVE_SETTER |
75338 	                        DUK_DEFPROP_FORCE |
75339 	                        DUK_DEFPROP_SET_ENUMERABLE |
75340 	                        DUK_DEFPROP_SET_CONFIGURABLE;
75341 	} else {
75342 	        defprop_flags = DUK_DEFPROP_HAVE_GETTER |
75343 	                        DUK_DEFPROP_FORCE |
75344 	                        DUK_DEFPROP_SET_ENUMERABLE |
75345 	                        DUK_DEFPROP_SET_CONFIGURABLE;
75346 	}
75347 	duk_def_prop(thr, (duk_idx_t) DUK_DEC_A(ins), defprop_flags);
75348 }
75349 
75350 DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_trycatch(duk_hthread *thr, duk_uint_fast32_t ins, duk_instr_t *curr_pc) {
75351 	duk_activation *act;
75352 	duk_catcher *cat;
75353 	duk_tval *tv1;
75354 	duk_small_uint_fast_t a;
75355 	duk_small_uint_fast_t bc;
75356 
75357 	/* A -> flags
75358 	 * BC -> reg_catch; base register for two registers used both during
75359 	 *       trycatch setup and when catch is triggered
75360 	 *
75361 	 *      If DUK_BC_TRYCATCH_FLAG_CATCH_BINDING set:
75362 	 *          reg_catch + 0: catch binding variable name (string).
75363 	 *          Automatic declarative environment is established for
75364 	 *          the duration of the 'catch' clause.
75365 	 *
75366 	 *      If DUK_BC_TRYCATCH_FLAG_WITH_BINDING set:
75367 	 *          reg_catch + 0: with 'target value', which is coerced to
75368 	 *          an object and then used as a bindind object for an
75369 	 *          environment record.  The binding is initialized here, for
75370 	 *          the 'try' clause.
75371 	 *
75372 	 * Note that a TRYCATCH generated for a 'with' statement has no
75373 	 * catch or finally parts.
75374 	 */
75375 
75376 	/* XXX: TRYCATCH handling should be reworked to avoid creating
75377 	 * an explicit scope unless it is actually needed (e.g. function
75378 	 * instances or eval is executed inside the catch block).  This
75379 	 * rework is not trivial because the compiler doesn't have an
75380 	 * intermediate representation.  When the rework is done, the
75381 	 * opcode format can also be made more straightforward.
75382 	 */
75383 
75384 	/* XXX: side effect handling is quite awkward here */
75385 
75386 	DUK_DDD(DUK_DDDPRINT("TRYCATCH: reg_catch=%ld, have_catch=%ld, "
75387 	                     "have_finally=%ld, catch_binding=%ld, with_binding=%ld (flags=0x%02lx)",
75388 	                     (long) DUK_DEC_BC(ins),
75389 	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH ? 1 : 0),
75390 	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY ? 1 : 0),
75391 	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING ? 1 : 0),
75392 	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_WITH_BINDING ? 1 : 0),
75393 	                     (unsigned long) DUK_DEC_A(ins)));
75394 
75395 	a = DUK_DEC_A(ins);
75396 	bc = DUK_DEC_BC(ins);
75397 
75398 	/* Registers 'bc' and 'bc + 1' are written in longjmp handling
75399 	 * and if their previous values (which are temporaries) become
75400 	 * unreachable -and- have a finalizer, there'll be a function
75401 	 * call during error handling which is not supported now (GH-287).
75402 	 * Ensure that both 'bc' and 'bc + 1' have primitive values to
75403 	 * guarantee no finalizer calls in error handling.  Scrubbing also
75404 	 * ensures finalizers for the previous values run here rather than
75405 	 * later.  Error handling related values are also written to 'bc'
75406 	 * and 'bc + 1' but those values never become unreachable during
75407 	 * error handling, so there's no side effect problem even if the
75408 	 * error value has a finalizer.
75409 	 */
75410 	duk_dup(thr, (duk_idx_t) bc);  /* Stabilize value. */
75411 	duk_to_undefined(thr, (duk_idx_t) bc);
75412 	duk_to_undefined(thr, (duk_idx_t) (bc + 1));
75413 
75414 	/* Allocate catcher and populate it.  Doesn't have to
75415 	 * be fully atomic, but the catcher must be in a
75416 	 * consistent state if side effects (such as finalizer
75417 	 * calls) occur.
75418 	 */
75419 
75420 	cat = duk_hthread_catcher_alloc(thr);
75421 	DUK_ASSERT(cat != NULL);
75422 
75423 	cat->flags = DUK_CAT_TYPE_TCF;
75424 	cat->h_varname = NULL;
75425 	cat->pc_base = (duk_instr_t *) curr_pc;  /* pre-incremented, points to first jump slot */
75426 	cat->idx_base = (duk_size_t) (thr->valstack_bottom - thr->valstack) + bc;
75427 
75428 	act = thr->callstack_curr;
75429 	DUK_ASSERT(act != NULL);
75430 	cat->parent = act->cat;
75431 	act->cat = cat;
75432 
75433 	if (a & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {
75434 		cat->flags |= DUK_CAT_FLAG_CATCH_ENABLED;
75435 	}
75436 	if (a & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {
75437 		cat->flags |= DUK_CAT_FLAG_FINALLY_ENABLED;
75438 	}
75439 	if (a & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING) {
75440 		DUK_DDD(DUK_DDDPRINT("catch binding flag set to catcher"));
75441 		cat->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED;
75442 		tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
75443 		DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
75444 
75445 		/* borrowed reference; although 'tv1' comes from a register,
75446 		 * its value was loaded using LDCONST so the constant will
75447 		 * also exist and be reachable.
75448 		 */
75449 		cat->h_varname = DUK_TVAL_GET_STRING(tv1);
75450 	} else if (a & DUK_BC_TRYCATCH_FLAG_WITH_BINDING) {
75451 		duk_hobjenv *env;
75452 		duk_hobject *target;
75453 
75454 		/* Delayed env initialization for activation (if needed). */
75455 		DUK_ASSERT(thr->callstack_top >= 1);
75456 		DUK_ASSERT(act == thr->callstack_curr);
75457 		DUK_ASSERT(act != NULL);
75458 		if (act->lex_env == NULL) {
75459 			DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
75460 			DUK_ASSERT(act->var_env == NULL);
75461 
75462 			duk_js_init_activation_environment_records_delayed(thr, act);
75463 			DUK_ASSERT(act == thr->callstack_curr);
75464 			DUK_UNREF(act);  /* 'act' is no longer accessed, scanbuild fix */
75465 		}
75466 		DUK_ASSERT(act->lex_env != NULL);
75467 		DUK_ASSERT(act->var_env != NULL);
75468 
75469 		/* Coerce 'with' target. */
75470 		target = duk_to_hobject(thr, -1);
75471 		DUK_ASSERT(target != NULL);
75472 
75473 		/* Create an object environment; it is not pushed
75474 		 * so avoid side effects very carefully until it is
75475 		 * referenced.
75476 		 */
75477 		env = duk_hobjenv_alloc(thr,
75478 		                        DUK_HOBJECT_FLAG_EXTENSIBLE |
75479 		                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
75480 		DUK_ASSERT(env != NULL);
75481 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
75482 		env->target = target;  /* always provideThis=true */
75483 		DUK_HOBJECT_INCREF(thr, target);
75484 		env->has_this = 1;
75485 		DUK_ASSERT_HOBJENV_VALID(env);
75486 		DUK_DDD(DUK_DDDPRINT("environment for with binding: %!iO", env));
75487 
75488 		DUK_ASSERT(act == thr->callstack_curr);
75489 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
75490 		DUK_ASSERT(act->lex_env != NULL);
75491 		DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) env, act->lex_env);
75492 		act->lex_env = (duk_hobject *) env;  /* Now reachable. */
75493 		DUK_HOBJECT_INCREF(thr, (duk_hobject *) env);
75494 		/* Net refcount change to act->lex_env is 0: incref for env's
75495 		 * prototype, decref for act->lex_env overwrite.
75496 		 */
75497 
75498 		/* Set catcher lex_env active (affects unwind)
75499 		 * only when the whole setup is complete.
75500 		 */
75501 		cat = act->cat;  /* XXX: better to relookup? not mandatory because 'cat' is stable */
75502 		cat->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE;
75503 	} else {
75504 		;
75505 	}
75506 
75507 	DUK_DDD(DUK_DDDPRINT("TRYCATCH catcher: flags=0x%08lx, pc_base=%ld, "
75508 	                     "idx_base=%ld, h_varname=%!O",
75509 	                     (unsigned long) cat->flags,
75510 	                     (long) cat->pc_base, (long) cat->idx_base, (duk_heaphdr *) cat->h_varname));
75511 
75512 	duk_pop_unsafe(thr);
75513 }
75514 
75515 DUK_LOCAL DUK__NOINLINE_PERF duk_instr_t *duk__handle_op_endtry(duk_hthread *thr, duk_uint_fast32_t ins) {
75516 	duk_activation *act;
75517 	duk_catcher *cat;
75518 	duk_tval *tv1;
75519 	duk_instr_t *pc_base;
75520 
75521 	DUK_UNREF(ins);
75522 
75523 	DUK_ASSERT(thr->callstack_top >= 1);
75524 	act = thr->callstack_curr;
75525 	DUK_ASSERT(act != NULL);
75526 	cat = act->cat;
75527 	DUK_ASSERT(cat != NULL);
75528 	DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);
75529 
75530 	DUK_DDD(DUK_DDDPRINT("ENDTRY: clearing catch active flag (regardless of whether it was set or not)"));
75531 	DUK_CAT_CLEAR_CATCH_ENABLED(cat);
75532 
75533 	pc_base = cat->pc_base;
75534 
75535 	if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
75536 		DUK_DDD(DUK_DDDPRINT("ENDTRY: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
75537 
75538 		tv1 = thr->valstack + cat->idx_base;
75539 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
75540 		DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
75541 		tv1 = NULL;
75542 
75543 		tv1 = thr->valstack + cat->idx_base + 1;
75544 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
75545 		DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL);  /* side effects */
75546 		tv1 = NULL;
75547 
75548 		DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
75549 	} else {
75550 		DUK_DDD(DUK_DDDPRINT("ENDTRY: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
75551 
75552 		duk_hthread_catcher_unwind_norz(thr, act);  /* lexenv may be set for 'with' binding */
75553 		/* no need to unwind callstack */
75554 	}
75555 
75556 	return pc_base + 1;  /* new curr_pc value */
75557 }
75558 
75559 DUK_LOCAL DUK__NOINLINE_PERF duk_instr_t *duk__handle_op_endcatch(duk_hthread *thr, duk_uint_fast32_t ins) {
75560 	duk_activation *act;
75561 	duk_catcher *cat;
75562 	duk_tval *tv1;
75563 	duk_instr_t *pc_base;
75564 
75565 	DUK_UNREF(ins);
75566 
75567 	DUK_ASSERT(thr->callstack_top >= 1);
75568 	act = thr->callstack_curr;
75569 	DUK_ASSERT(act != NULL);
75570 	cat = act->cat;
75571 	DUK_ASSERT(cat != NULL);
75572 	DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat));  /* cleared before entering catch part */
75573 
75574 	if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
75575 		duk_hobject *prev_env;
75576 
75577 		/* 'with' binding has no catch clause, so can't be here unless a normal try-catch */
75578 		DUK_ASSERT(DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat));
75579 		DUK_ASSERT(act->lex_env != NULL);
75580 
75581 		DUK_DDD(DUK_DDDPRINT("ENDCATCH: popping catcher part lexical environment"));
75582 
75583 		prev_env = act->lex_env;
75584 		DUK_ASSERT(prev_env != NULL);
75585 		act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, prev_env);
75586 		DUK_CAT_CLEAR_LEXENV_ACTIVE(cat);
75587 		DUK_HOBJECT_INCREF(thr, act->lex_env);
75588 		DUK_HOBJECT_DECREF(thr, prev_env);  /* side effects */
75589 
75590 		DUK_ASSERT(act == thr->callstack_curr);
75591 		DUK_ASSERT(act != NULL);
75592 	}
75593 
75594 	pc_base = cat->pc_base;
75595 
75596 	if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
75597 		DUK_DDD(DUK_DDDPRINT("ENDCATCH: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
75598 
75599 		tv1 = thr->valstack + cat->idx_base;
75600 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
75601 		DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
75602 		tv1 = NULL;
75603 
75604 		tv1 = thr->valstack + cat->idx_base + 1;
75605 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
75606 		DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL);  /* side effects */
75607 		tv1 = NULL;
75608 
75609 		DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
75610 	} else {
75611 		DUK_DDD(DUK_DDDPRINT("ENDCATCH: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
75612 
75613 		duk_hthread_catcher_unwind_norz(thr, act);
75614 		/* no need to unwind callstack */
75615 	}
75616 
75617 	return pc_base + 1;  /* new curr_pc value */
75618 }
75619 
75620 DUK_LOCAL DUK__NOINLINE_PERF duk_small_uint_t duk__handle_op_endfin(duk_hthread *thr, duk_uint_fast32_t ins, duk_activation *entry_act) {
75621 	duk_activation *act;
75622 	duk_tval *tv1;
75623 	duk_uint_t reg_catch;
75624 	duk_small_uint_t cont_type;
75625 	duk_small_uint_t ret_result;
75626 
75627 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
75628 	DUK_ASSERT(thr->callstack_top >= 1);
75629 	act = thr->callstack_curr;
75630 	DUK_ASSERT(act != NULL);
75631 	reg_catch = DUK_DEC_ABC(ins);
75632 
75633 	/* CATCH flag may be enabled or disabled here; it may be enabled if
75634 	 * the statement has a catch block but the try block does not throw
75635 	 * an error.
75636 	 */
75637 
75638 	DUK_DDD(DUK_DDDPRINT("ENDFIN: completion value=%!T, type=%!T",
75639 	                     (duk_tval *) (thr->valstack_bottom + reg_catch + 0),
75640 	                     (duk_tval *) (thr->valstack_bottom + reg_catch + 1)));
75641 
75642 	tv1 = thr->valstack_bottom + reg_catch + 1;  /* type */
75643 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
75644 #if defined(DUK_USE_FASTINT)
75645 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
75646 	cont_type = (duk_small_uint_t) DUK_TVAL_GET_FASTINT_U32(tv1);
75647 #else
75648 	cont_type = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
75649 #endif
75650 
75651 	tv1--;  /* value */
75652 
75653 	switch (cont_type) {
75654 	case DUK_LJ_TYPE_NORMAL: {
75655 		DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'normal' (non-abrupt) completion -> "
75656 		                     "dismantle catcher, resume execution after ENDFIN"));
75657 
75658 		duk_hthread_catcher_unwind_norz(thr, act);
75659 		/* no need to unwind callstack */
75660 		return 0;  /* restart execution */
75661 	}
75662 	case DUK_LJ_TYPE_RETURN: {
75663 		DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'return' complation -> dismantle "
75664 		                     "catcher, handle return, lj.value1=%!T", tv1));
75665 
75666 		/* Not necessary to unwind catch stack: return handling will
75667 		 * do it.  The finally flag of 'cat' is no longer set.  The
75668 		 * catch flag may be set, but it's not checked by return handling.
75669 		 */
75670 
75671 		duk_push_tval(thr, tv1);
75672 		ret_result = duk__handle_return(thr, entry_act);
75673 		if (ret_result == DUK__RETHAND_RESTART) {
75674 			return 0;  /* restart execution */
75675 		}
75676 		DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED);
75677 
75678 		DUK_DDD(DUK_DDDPRINT("exiting executor after ENDFIN and RETURN (pseudo) longjmp type"));
75679 		return 1;  /* exit executor */
75680 	}
75681 	case DUK_LJ_TYPE_BREAK:
75682 	case DUK_LJ_TYPE_CONTINUE: {
75683 		duk_uint_t label_id;
75684 		duk_small_uint_t lj_type;
75685 
75686 		/* Not necessary to unwind catch stack: break/continue
75687 		 * handling will do it.  The finally flag of 'cat' is
75688 		 * no longer set.  The catch flag may be set, but it's
75689 		 * not checked by break/continue handling.
75690 		 */
75691 
75692 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
75693 #if defined(DUK_USE_FASTINT)
75694 		DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
75695 		label_id = (duk_small_uint_t) DUK_TVAL_GET_FASTINT_U32(tv1);
75696 #else
75697 		label_id = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
75698 #endif
75699 		lj_type = cont_type;
75700 		duk__handle_break_or_continue(thr, label_id, lj_type);
75701 		return 0;  /* restart execution */
75702 	}
75703 	default: {
75704 		DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with abrupt completion, lj_type=%ld -> "
75705 		                     "dismantle catcher, re-throw error",
75706 		                     (long) cont_type));
75707 
75708 		duk_err_setup_ljstate1(thr, (duk_small_uint_t) cont_type, tv1);
75709 		/* No debugger Throw notify check on purpose (rethrow). */
75710 
75711 		DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* always in executor */
75712 		duk_err_longjmp(thr);
75713 		DUK_UNREACHABLE();
75714 	}
75715 	}
75716 
75717 	DUK_UNREACHABLE();
75718 	return 0;
75719 }
75720 
75721 DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_initenum(duk_hthread *thr, duk_uint_fast32_t ins) {
75722 	duk_small_uint_t b;
75723 	duk_small_uint_t c;
75724 
75725 	/*
75726 	 *  Enumeration semantics come from for-in statement, E5 Section 12.6.4.
75727 	 *  If called with 'null' or 'undefined', this opcode returns 'null' as
75728 	 *  the enumerator, which is special cased in NEXTENUM.  This simplifies
75729 	 *  the compiler part
75730 	 */
75731 
75732 	/* B -> register for writing enumerator object
75733 	 * C -> value to be enumerated (register)
75734 	 */
75735 	b = DUK_DEC_B(ins);
75736 	c = DUK_DEC_C(ins);
75737 
75738 	if (duk_is_null_or_undefined(thr, (duk_idx_t) c)) {
75739 		duk_push_null(thr);
75740 		duk_replace(thr, (duk_idx_t) b);
75741 	} else {
75742 		duk_dup(thr, (duk_idx_t) c);
75743 		duk_to_object(thr, -1);
75744 		duk_hobject_enumerator_create(thr, 0 /*enum_flags*/);  /* [ ... val ] --> [ ... enum ] */
75745 		duk_replace(thr, (duk_idx_t) b);
75746 	}
75747 }
75748 
75749 DUK_LOCAL DUK__NOINLINE_PERF duk_small_uint_t duk__handle_op_nextenum(duk_hthread *thr, duk_uint_fast32_t ins) {
75750 	duk_small_uint_t b;
75751 	duk_small_uint_t c;
75752 	duk_small_uint_t pc_skip = 0;
75753 
75754 	/*
75755 	 *  NEXTENUM checks whether the enumerator still has unenumerated
75756 	 *  keys.  If so, the next key is loaded to the target register
75757 	 *  and the next instruction is skipped.  Otherwise the next instruction
75758 	 *  will be executed, jumping out of the enumeration loop.
75759 	 */
75760 
75761 	/* B -> target register for next key
75762 	 * C -> enum register
75763 	 */
75764 	b = DUK_DEC_B(ins);
75765 	c = DUK_DEC_C(ins);
75766 
75767 	DUK_DDD(DUK_DDDPRINT("NEXTENUM: b->%!T, c->%!T",
75768 	                     (duk_tval *) duk_get_tval(thr, (duk_idx_t) b),
75769 	                     (duk_tval *) duk_get_tval(thr, (duk_idx_t) c)));
75770 
75771 	if (duk_is_object(thr, (duk_idx_t) c)) {
75772 		/* XXX: assert 'c' is an enumerator */
75773 		duk_dup(thr, (duk_idx_t) c);
75774 		if (duk_hobject_enumerator_next(thr, 0 /*get_value*/)) {
75775 			/* [ ... enum ] -> [ ... next_key ] */
75776 			DUK_DDD(DUK_DDDPRINT("enum active, next key is %!T, skip jump slot ",
75777 			                     (duk_tval *) duk_get_tval(thr, -1)));
75778 			pc_skip = 1;
75779 		} else {
75780 			/* [ ... enum ] -> [ ... ] */
75781 			DUK_DDD(DUK_DDDPRINT("enum finished, execute jump slot"));
75782 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */
75783 			thr->valstack_top++;
75784 		}
75785 		duk_replace(thr, (duk_idx_t) b);
75786 	} else {
75787 		/* 'null' enumerator case -> behave as with an empty enumerator */
75788 		DUK_ASSERT(duk_is_null(thr, (duk_idx_t) c));
75789 		DUK_DDD(DUK_DDDPRINT("enum is null, execute jump slot"));
75790 	}
75791 
75792 	return pc_skip;
75793 }
75794 
75795 /*
75796  *  Call handling helpers.
75797  */
75798 
75799 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) {
75800 	duk_bool_t rc;
75801 
75802 	duk_set_top_unsafe(thr, (duk_idx_t) (idx + nargs + 2));   /* [ ... func this arg1 ... argN ] */
75803 
75804 	/* Attempt an Ecma-to-Ecma call setup.  If the call
75805 	 * target is (directly or indirectly) Reflect.construct(),
75806 	 * the call may change into a constructor call on the fly.
75807 	 */
75808 	rc = (duk_bool_t) duk_handle_call_unprotected(thr, idx, call_flags);
75809 	if (rc != 0) {
75810 		/* Ecma-to-ecma call possible, may or may not
75811 		 * be a tail call.  Avoid C recursion by
75812 		 * reusing current executor instance.
75813 		 */
75814 		DUK_DDD(DUK_DDDPRINT("ecma-to-ecma call setup possible, restart execution"));
75815 		/* curr_pc synced by duk_handle_call_unprotected() */
75816 		DUK_ASSERT(thr->ptr_curr_pc == NULL);
75817 		return rc;
75818 	} else {
75819 		/* Call was handled inline. */
75820 	}
75821 	DUK_ASSERT(thr->ptr_curr_pc != NULL);
75822 	return rc;
75823 }
75824 
75825 /*
75826  *  ECMAScript bytecode executor.
75827  *
75828  *  Resume execution for the current thread from its current activation.
75829  *  Returns when execution would return from the entry level activation,
75830  *  leaving a single return value on top of the stack.  Function calls
75831  *  and thread resumptions are handled internally.  If an error occurs,
75832  *  a longjmp() with type DUK_LJ_TYPE_THROW is called on the entry level
75833  *  setjmp() jmpbuf.
75834  *
75835  *  ECMAScript function calls and coroutine resumptions are handled
75836  *  internally (by the outer executor function) without recursive C calls.
75837  *  Other function calls are handled using duk_handle_call(), increasing
75838  *  C recursion depth.
75839  *
75840  *  Abrupt completions (= long control tranfers) are handled either
75841  *  directly by reconfiguring relevant stacks and restarting execution,
75842  *  or via a longjmp.  Longjmp-free handling is preferable for performance
75843  *  (especially Emscripten performance), and is used for: break, continue,
75844  *  and return.
75845  *
75846  *  For more detailed notes, see doc/execution.rst.
75847  *
75848  *  Also see doc/code-issues.rst for discussion of setjmp(), longjmp(),
75849  *  and volatile.
75850  */
75851 
75852 /* Presence of 'fun' is config based, there's a marginal performance
75853  * difference and the best option is architecture dependent.
75854  */
75855 #if defined(DUK_USE_EXEC_FUN_LOCAL)
75856 #define DUK__FUN()          fun
75857 #else
75858 #define DUK__FUN()          ((duk_hcompfunc *) DUK_ACT_GET_FUNC((thr)->callstack_curr))
75859 #endif
75860 
75861 /* Strict flag. */
75862 #define DUK__STRICT()       ((duk_small_uint_t) DUK_HOBJECT_HAS_STRICT((duk_hobject *) DUK__FUN()))
75863 
75864 /* Reg/const access macros: these are very footprint and performance sensitive
75865  * so modify with care.  Arguments are sometimes evaluated multiple times which
75866  * is not ideal.
75867  */
75868 #define DUK__REG(x)         (*(thr->valstack_bottom + (x)))
75869 #define DUK__REGP(x)        (thr->valstack_bottom + (x))
75870 #define DUK__CONST(x)       (*(consts + (x)))
75871 #define DUK__CONSTP(x)      (consts + (x))
75872 
75873 /* Reg/const access macros which take the 32-bit instruction and avoid an
75874  * explicit field decoding step by using shifts and masks.  These must be
75875  * kept in sync with duk_js_bytecode.h.  The shift/mask values are chosen
75876  * so that 'ins' can be shifted and masked and used as a -byte- offset
75877  * instead of a duk_tval offset which needs further shifting (which is an
75878  * issue on some, but not all, CPUs).
75879  */
75880 #define DUK__RCBIT_B           DUK_BC_REGCONST_B
75881 #define DUK__RCBIT_C           DUK_BC_REGCONST_C
75882 #if defined(DUK_USE_EXEC_REGCONST_OPTIMIZE)
75883 #if defined(DUK_USE_PACKED_TVAL)
75884 #define DUK__TVAL_SHIFT        3  /* sizeof(duk_tval) == 8 */
75885 #else
75886 #define DUK__TVAL_SHIFT        4  /* sizeof(duk_tval) == 16; not always the case so also asserted for */
75887 #endif
75888 #define DUK__SHIFT_A           (DUK_BC_SHIFT_A - DUK__TVAL_SHIFT)
75889 #define DUK__SHIFT_B           (DUK_BC_SHIFT_B - DUK__TVAL_SHIFT)
75890 #define DUK__SHIFT_C           (DUK_BC_SHIFT_C - DUK__TVAL_SHIFT)
75891 #define DUK__SHIFT_BC          (DUK_BC_SHIFT_BC - DUK__TVAL_SHIFT)
75892 #define DUK__MASK_A            (DUK_BC_UNSHIFTED_MASK_A << DUK__TVAL_SHIFT)
75893 #define DUK__MASK_B            (DUK_BC_UNSHIFTED_MASK_B << DUK__TVAL_SHIFT)
75894 #define DUK__MASK_C            (DUK_BC_UNSHIFTED_MASK_C << DUK__TVAL_SHIFT)
75895 #define DUK__MASK_BC           (DUK_BC_UNSHIFTED_MASK_BC << DUK__TVAL_SHIFT)
75896 #define DUK__BYTEOFF_A(ins)    (((ins) >> DUK__SHIFT_A) & DUK__MASK_A)
75897 #define DUK__BYTEOFF_B(ins)    (((ins) >> DUK__SHIFT_B) & DUK__MASK_B)
75898 #define DUK__BYTEOFF_C(ins)    (((ins) >> DUK__SHIFT_C) & DUK__MASK_C)
75899 #define DUK__BYTEOFF_BC(ins)   (((ins) >> DUK__SHIFT_BC) & DUK__MASK_BC)
75900 
75901 #define DUK__REGP_A(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_A((ins))))
75902 #define DUK__REGP_B(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_B((ins))))
75903 #define DUK__REGP_C(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_C((ins))))
75904 #define DUK__REGP_BC(ins)      ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_BC((ins))))
75905 #define DUK__CONSTP_A(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_A((ins))))
75906 #define DUK__CONSTP_B(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_B((ins))))
75907 #define DUK__CONSTP_C(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_C((ins))))
75908 #define DUK__CONSTP_BC(ins)    ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_BC((ins))))
75909 #define DUK__REGCONSTP_B(ins)  ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) & DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_B((ins))))
75910 #define DUK__REGCONSTP_C(ins)  ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) & DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_C((ins))))
75911 #else  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
75912 /* Safe alternatives, no assumption about duk_tval size. */
75913 #define DUK__REGP_A(ins)       DUK__REGP(DUK_DEC_A((ins)))
75914 #define DUK__REGP_B(ins)       DUK__REGP(DUK_DEC_B((ins)))
75915 #define DUK__REGP_C(ins)       DUK__REGP(DUK_DEC_C((ins)))
75916 #define DUK__REGP_BC(ins)      DUK__REGP(DUK_DEC_BC((ins)))
75917 #define DUK__CONSTP_A(ins)     DUK__CONSTP(DUK_DEC_A((ins)))
75918 #define DUK__CONSTP_B(ins)     DUK__CONSTP(DUK_DEC_B((ins)))
75919 #define DUK__CONSTP_C(ins)     DUK__CONSTP(DUK_DEC_C((ins)))
75920 #define DUK__CONSTP_BC(ins)    DUK__CONSTP(DUK_DEC_BC((ins)))
75921 #define DUK__REGCONSTP_B(ins)  ((((ins) & DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK_DEC_B((ins)))
75922 #define DUK__REGCONSTP_C(ins)  ((((ins) & DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK_DEC_C((ins)))
75923 #endif  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
75924 
75925 #if defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS)
75926 #define DUK__INTERNAL_ERROR(msg)  do { \
75927 		DUK_ERROR_ERROR(thr, (msg)); \
75928 		DUK_WO_NORETURN(return;); \
75929 	} while (0)
75930 #else
75931 #define DUK__INTERNAL_ERROR(msg)  do { \
75932 		goto internal_error; \
75933 	} while (0)
75934 #endif
75935 
75936 #define DUK__SYNC_CURR_PC()  do { \
75937 		duk_activation *duk__act; \
75938 		duk__act = thr->callstack_curr; \
75939 		duk__act->curr_pc = curr_pc; \
75940 	} while (0)
75941 #define DUK__SYNC_AND_NULL_CURR_PC()  do { \
75942 		duk_activation *duk__act; \
75943 		duk__act = thr->callstack_curr; \
75944 		duk__act->curr_pc = curr_pc; \
75945 		thr->ptr_curr_pc = NULL; \
75946 	} while (0)
75947 
75948 #if defined(DUK_USE_EXEC_PREFER_SIZE)
75949 #define DUK__LOOKUP_INDIRECT(idx) do { \
75950 		(idx) = (duk_uint_fast_t) duk_get_uint(thr, (duk_idx_t) (idx)); \
75951 	} while (0)
75952 #elif defined(DUK_USE_FASTINT)
75953 #define DUK__LOOKUP_INDIRECT(idx) do { \
75954 		duk_tval *tv_ind; \
75955 		tv_ind = DUK__REGP((idx)); \
75956 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind)); \
75957 		DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_ind));  /* compiler guarantees */ \
75958 		(idx) = (duk_uint_fast_t) DUK_TVAL_GET_FASTINT_U32(tv_ind); \
75959 	} while (0)
75960 #else
75961 #define DUK__LOOKUP_INDIRECT(idx) do { \
75962 		duk_tval *tv_ind; \
75963 		tv_ind = DUK__REGP(idx); \
75964 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind)); \
75965 		idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind); \
75966 	} while (0)
75967 #endif
75968 
75969 DUK_LOCAL void duk__handle_executor_error(duk_heap *heap,
75970                                           duk_activation *entry_act,
75971                                           duk_int_t entry_call_recursion_depth,
75972                                           duk_jmpbuf *entry_jmpbuf_ptr) {
75973 	duk_small_uint_t lj_ret;
75974 
75975 	/* Longjmp callers are required to sync-and-null thr->ptr_curr_pc
75976 	 * before longjmp.
75977 	 */
75978 	DUK_ASSERT(heap->curr_thread != NULL);
75979 	DUK_ASSERT(heap->curr_thread->ptr_curr_pc == NULL);
75980 
75981 	/* XXX: signalling the need to shrink check (only if unwound) */
75982 
75983 	/* Must be restored here to handle e.g. yields properly. */
75984 	heap->call_recursion_depth = entry_call_recursion_depth;
75985 
75986 	/* Switch to caller's setjmp() catcher so that if an error occurs
75987 	 * during error handling, it is always propagated outwards instead
75988 	 * of causing an infinite loop in our own handler.
75989 	 */
75990 	heap->lj.jmpbuf_ptr = (duk_jmpbuf *) entry_jmpbuf_ptr;
75991 
75992 	lj_ret = duk__handle_longjmp(heap->curr_thread, entry_act);
75993 
75994 	/* Error handling complete, remove side effect protections.
75995 	 */
75996 #if defined(DUK_USE_ASSERTIONS)
75997 	DUK_ASSERT(heap->error_not_allowed == 1);
75998 	heap->error_not_allowed = 0;
75999 #endif
76000 	DUK_ASSERT(heap->pf_prevent_count > 0);
76001 	heap->pf_prevent_count--;
76002 	DUK_DD(DUK_DDPRINT("executor error handled, pf_prevent_count updated to %ld", (long) heap->pf_prevent_count));
76003 
76004 	if (lj_ret == DUK__LONGJMP_RESTART) {
76005 		/* Restart bytecode execution, possibly with a changed thread. */
76006 		DUK_REFZERO_CHECK_SLOW(heap->curr_thread);
76007 	} else {
76008 		/* If an error is propagated, don't run refzero checks here.
76009 		 * The next catcher will deal with that.  Pf_prevent_count
76010 		 * will be re-bumped by the longjmp.
76011 		 */
76012 
76013 		DUK_ASSERT(lj_ret == DUK__LONGJMP_RETHROW);  /* Rethrow error to calling state. */
76014 		DUK_ASSERT(heap->lj.jmpbuf_ptr == entry_jmpbuf_ptr);  /* Longjmp handling has restored jmpbuf_ptr. */
76015 
76016 		/* Thread may have changed, e.g. YIELD converted to THROW. */
76017 		duk_err_longjmp(heap->curr_thread);
76018 		DUK_UNREACHABLE();
76019 	}
76020 }
76021 
76022 /* Outer executor with setjmp/longjmp handling. */
76023 DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) {
76024 	/* Entry level info. */
76025 	duk_hthread *entry_thread;
76026 	duk_activation *entry_act;
76027 	duk_int_t entry_call_recursion_depth;
76028 	duk_jmpbuf *entry_jmpbuf_ptr;
76029 	duk_jmpbuf our_jmpbuf;
76030 	duk_heap *heap;
76031 
76032 	DUK_ASSERT(exec_thr != NULL);
76033 	DUK_ASSERT(exec_thr->heap != NULL);
76034 	DUK_ASSERT(exec_thr->heap->curr_thread != NULL);
76035 	DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR((duk_heaphdr *) exec_thr);
76036 	DUK_ASSERT(exec_thr->callstack_top >= 1);  /* at least one activation, ours */
76037 	DUK_ASSERT(exec_thr->callstack_curr != NULL);
76038 	DUK_ASSERT(DUK_ACT_GET_FUNC(exec_thr->callstack_curr) != NULL);
76039 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(exec_thr->callstack_curr)));
76040 
76041 	DUK_GC_TORTURE(exec_thr->heap);
76042 
76043 	entry_thread = exec_thr;
76044 	heap = entry_thread->heap;
76045 	entry_act = entry_thread->callstack_curr;
76046 	DUK_ASSERT(entry_act != NULL);
76047 	entry_call_recursion_depth = entry_thread->heap->call_recursion_depth;
76048 	entry_jmpbuf_ptr = entry_thread->heap->lj.jmpbuf_ptr;
76049 
76050 	/*
76051 	 *  Note: we currently assume that the setjmp() catchpoint is
76052 	 *  not re-entrant (longjmp() cannot be called more than once
76053 	 *  for a single setjmp()).
76054 	 *
76055 	 *  See doc/code-issues.rst for notes on variable assignment
76056 	 *  before and after setjmp().
76057 	 */
76058 
76059 	for (;;) {
76060 		heap->lj.jmpbuf_ptr = &our_jmpbuf;
76061 		DUK_ASSERT(heap->lj.jmpbuf_ptr != NULL);
76062 
76063 #if defined(DUK_USE_CPP_EXCEPTIONS)
76064 		try {
76065 #else
76066 		DUK_ASSERT(heap->lj.jmpbuf_ptr == &our_jmpbuf);
76067 		if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
76068 #endif
76069 			/* Execute bytecode until returned or longjmp(). */
76070 			duk__js_execute_bytecode_inner(entry_thread, entry_act);
76071 
76072 			/* Successful return: restore jmpbuf and return to caller. */
76073 			heap->lj.jmpbuf_ptr = entry_jmpbuf_ptr;
76074 
76075 			return;
76076 #if defined(DUK_USE_CPP_EXCEPTIONS)
76077 		} catch (duk_internal_exception &exc) {
76078 #else
76079 		} else {
76080 #endif
76081 #if defined(DUK_USE_CPP_EXCEPTIONS)
76082 			DUK_UNREF(exc);
76083 #endif
76084 			DUK_DDD(DUK_DDDPRINT("longjmp caught by bytecode executor"));
76085 			DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
76086 
76087 			duk__handle_executor_error(heap,
76088 			                           entry_act,
76089 			                           entry_call_recursion_depth,
76090 			                           entry_jmpbuf_ptr);
76091 		}
76092 #if defined(DUK_USE_CPP_EXCEPTIONS)
76093 		catch (duk_fatal_exception &exc) {
76094 			DUK_D(DUK_DPRINT("rethrow duk_fatal_exception"));
76095 			throw;
76096 		} catch (std::exception &exc) {
76097 			const char *what = exc.what();
76098 			if (!what) {
76099 				what = "unknown";
76100 			}
76101 			DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
76102 			DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
76103 			try {
76104 				DUK_ASSERT(heap->curr_thread != NULL);
76105 				DUK_ERROR_FMT1(heap->curr_thread, DUK_ERR_TYPE_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
76106 				DUK_WO_NORETURN(return;);
76107 			} catch (duk_internal_exception exc) {
76108 				DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
76109 				DUK_UNREF(exc);
76110 				duk__handle_executor_error(heap,
76111 				                           entry_act,
76112 				                           entry_call_recursion_depth,
76113 				                           entry_jmpbuf_ptr);
76114 			}
76115 		} catch (...) {
76116 			DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
76117 			DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
76118 			try {
76119 				DUK_ASSERT(heap->curr_thread != NULL);
76120 				DUK_ERROR_TYPE(heap->curr_thread, "caught invalid c++ exception (perhaps thrown by user code)");
76121 				DUK_WO_NORETURN(return;);
76122 			} catch (duk_internal_exception exc) {
76123 				DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
76124 				DUK_UNREF(exc);
76125 				duk__handle_executor_error(heap,
76126 				                           entry_act,
76127 				                           entry_call_recursion_depth,
76128 				                           entry_jmpbuf_ptr);
76129 			}
76130 		}
76131 #endif
76132 	}
76133 
76134 	DUK_WO_NORETURN(return;);
76135 }
76136 
76137 /* Inner executor, performance critical. */
76138 DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_activation *entry_act) {
76139 	/* Current PC, accessed by other functions through thr->ptr_to_curr_pc.
76140 	 * Critical for performance.  It would be safest to make this volatile,
76141 	 * but that eliminates performance benefits; aliasing guarantees
76142 	 * should be enough though.
76143 	 */
76144 	duk_instr_t *curr_pc;         /* bytecode has a stable pointer */
76145 
76146 	/* Hot variables for interpretation.  Critical for performance,
76147 	 * but must add sparingly to minimize register shuffling.
76148 	 */
76149 	duk_hthread *thr;             /* stable */
76150 	duk_tval *consts;             /* stable */
76151 	duk_uint_fast32_t ins;
76152 	/* 'funcs' is quite rarely used, so no local for it */
76153 #if defined(DUK_USE_EXEC_FUN_LOCAL)
76154 	duk_hcompfunc *fun;
76155 #else
76156 	/* 'fun' is quite rarely used, so no local for it */
76157 #endif
76158 
76159 #if defined(DUK_USE_INTERRUPT_COUNTER)
76160 	duk_int_t int_ctr;
76161 #endif
76162 
76163 #if defined(DUK_USE_ASSERTIONS)
76164 	duk_size_t valstack_top_base;    /* valstack top, should match before interpreting each op (no leftovers) */
76165 #endif
76166 
76167 	/* Optimized reg/const access macros assume sizeof(duk_tval) to be
76168 	 * either 8 or 16.  Heap allocation checks this even without asserts
76169 	 * enabled now because it can't be autodetected in duk_config.h.
76170 	 */
76171 #if 1
76172 #if defined(DUK_USE_PACKED_TVAL)
76173 	DUK_ASSERT(sizeof(duk_tval) == 8);
76174 #else
76175 	DUK_ASSERT(sizeof(duk_tval) == 16);
76176 #endif
76177 #endif
76178 
76179 	DUK_GC_TORTURE(entry_thread->heap);
76180 
76181 	/*
76182 	 *  Restart execution by reloading thread state.
76183 	 *
76184 	 *  Note that 'thr' and any thread configuration may have changed,
76185 	 *  so all local variables are suspect and we need to reinitialize.
76186 	 *
76187 	 *  The number of local variables should be kept to a minimum: if
76188 	 *  the variables are spilled, they will need to be loaded from
76189 	 *  memory anyway.
76190 	 *
76191 	 *  Any 'goto restart_execution;' code path in opcode dispatch must
76192 	 *  ensure 'curr_pc' is synced back to act->curr_pc before the goto
76193 	 *  takes place.
76194 	 *
76195 	 *  The interpreter must be very careful with memory pointers, as
76196 	 *  many pointers are not guaranteed to be 'stable' and may be
76197 	 *  reallocated and relocated on-the-fly quite easily (e.g. by a
76198 	 *  memory allocation or a property access).
76199 	 *
76200 	 *  The following are assumed to have stable pointers:
76201 	 *    - the current thread
76202 	 *    - the current function
76203 	 *    - the bytecode, constant table, inner function table of the
76204 	 *      current function (as they are a part of the function allocation)
76205 	 *
76206 	 *  The following are assumed to have semi-stable pointers:
76207 	 *    - the current activation entry: stable as long as callstack
76208 	 *      is not changed (reallocated by growing or shrinking), or
76209 	 *      by any garbage collection invocation (through finalizers)
76210 	 *    - Note in particular that ANY DECREF can invalidate the
76211 	 *      activation pointer, so for the most part a fresh lookup
76212 	 *      is required
76213 	 *
76214 	 *  The following are not assumed to have stable pointers at all:
76215 	 *    - the value stack (registers) of the current thread
76216 	 *
76217 	 *  See execution.rst for discussion.
76218 	 */
76219 
76220  restart_execution:
76221 
76222 	/* Lookup current thread; use the stable 'entry_thread' for this to
76223 	 * avoid clobber warnings.  Any valid, reachable 'thr' value would be
76224 	 * fine for this, so using 'entry_thread' is just to silence warnings.
76225 	 */
76226 	thr = entry_thread->heap->curr_thread;
76227 	DUK_ASSERT(thr != NULL);
76228 	DUK_ASSERT(thr->callstack_top >= 1);
76229 	DUK_ASSERT(thr->callstack_curr != NULL);
76230 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
76231 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
76232 
76233 	DUK_GC_TORTURE(thr->heap);
76234 
76235 	thr->ptr_curr_pc = &curr_pc;
76236 
76237 	/* Relookup and initialize dispatch loop variables.  Debugger check. */
76238 	{
76239 		duk_activation *act;
76240 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
76241 		duk_hcompfunc *fun;
76242 #endif
76243 
76244 		/* Assume interrupt init/counter are properly initialized here. */
76245 		/* Assume that thr->valstack_bottom has been set-up before getting here. */
76246 
76247 		act = thr->callstack_curr;
76248 		DUK_ASSERT(act != NULL);
76249 		fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
76250 		DUK_ASSERT(fun != NULL);
76251 		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == fun->nregs);
76252 		consts = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, fun);
76253 		DUK_ASSERT(consts != NULL);
76254 
76255 #if defined(DUK_USE_DEBUGGER_SUPPORT)
76256 		if (DUK_UNLIKELY(duk_debug_is_attached(thr->heap) && !thr->heap->dbg_processing)) {
76257 			duk__executor_recheck_debugger(thr, act, fun);
76258 			DUK_ASSERT(act == thr->callstack_curr);
76259 			DUK_ASSERT(act != NULL);
76260 		}
76261 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
76262 
76263 #if defined(DUK_USE_ASSERTIONS)
76264 		valstack_top_base = (duk_size_t) (thr->valstack_top - thr->valstack);
76265 #endif
76266 
76267 		/* Set up curr_pc for opcode dispatch. */
76268 		curr_pc = act->curr_pc;
76269 	}
76270 
76271 	DUK_DD(DUK_DDPRINT("restarting execution, thr %p, act idx %ld, fun %p,"
76272 	                   "consts %p, funcs %p, lev %ld, regbot %ld, regtop %ld, "
76273 	                   "preventcount=%ld",
76274 	                   (void *) thr,
76275 	                   (long) (thr->callstack_top - 1),
76276 	                   (void *) DUK__FUN(),
76277 	                   (void *) DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, DUK__FUN()),
76278 	                   (void *) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, DUK__FUN()),
76279 	                   (long) (thr->callstack_top - 1),
76280 	                   (long) (thr->valstack_bottom - thr->valstack),
76281 	                   (long) (thr->valstack_top - thr->valstack),
76282 	                   (long) thr->callstack_preventcount));
76283 
76284 	/* Dispatch loop. */
76285 
76286 	for (;;) {
76287 		duk_uint8_t op;
76288 
76289 		DUK_ASSERT(thr->callstack_top >= 1);
76290 		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == DUK__FUN()->nregs);
76291 		DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) == valstack_top_base);
76292 
76293 		/* Executor interrupt counter check, used to implement breakpoints,
76294 		 * debugging interface, execution timeouts, etc.  The counter is heap
76295 		 * specific but is maintained in the current thread to make the check
76296 		 * as fast as possible.  The counter is copied back to the heap struct
76297 		 * whenever a thread switch occurs by the DUK_HEAP_SWITCH_THREAD() macro.
76298 		 */
76299 #if defined(DUK_USE_INTERRUPT_COUNTER)
76300 		int_ctr = thr->interrupt_counter;
76301 		if (DUK_LIKELY(int_ctr > 0)) {
76302 			thr->interrupt_counter = int_ctr - 1;
76303 		} else {
76304 			/* Trigger at zero or below */
76305 			duk_small_uint_t exec_int_ret;
76306 
76307 			DUK_STATS_INC(thr->heap, stats_exec_interrupt);
76308 
76309 			/* Write curr_pc back for the debugger. */
76310 			{
76311 				duk_activation *act;
76312 				DUK_ASSERT(thr->callstack_top > 0);
76313 				act = thr->callstack_curr;
76314 				DUK_ASSERT(act != NULL);
76315 				act->curr_pc = (duk_instr_t *) curr_pc;
76316 			}
76317 
76318 			/* Forced restart caused by a function return; must recheck
76319 			 * debugger breakpoints before checking line transitions,
76320 			 * see GH-303.  Restart and then handle interrupt_counter
76321 			 * zero again.
76322 			 */
76323 #if defined(DUK_USE_DEBUGGER_SUPPORT)
76324 			if (thr->heap->dbg_force_restart) {
76325 				DUK_DD(DUK_DDPRINT("dbg_force_restart flag forced restart execution"));  /* GH-303 */
76326 				thr->heap->dbg_force_restart = 0;
76327 				goto restart_execution;
76328 			}
76329 #endif
76330 
76331 			exec_int_ret = duk__executor_interrupt(thr);
76332 			if (exec_int_ret == DUK__INT_RESTART) {
76333 				/* curr_pc synced back above */
76334 				goto restart_execution;
76335 			}
76336 		}
76337 #endif  /* DUK_USE_INTERRUPT_COUNTER */
76338 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
76339 		/* For cross-checking during development: ensure dispatch count
76340 		 * matches cumulative interrupt counter init value sums.
76341 		 */
76342 		thr->heap->inst_count_exec++;
76343 #endif
76344 
76345 #if defined(DUK_USE_ASSERTIONS) || defined(DUK_USE_DEBUG)
76346 		{
76347 			duk_activation *act;
76348 			act = thr->callstack_curr;
76349 			DUK_ASSERT(curr_pc >= DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN()));
76350 			DUK_ASSERT(curr_pc < DUK_HCOMPFUNC_GET_CODE_END(thr->heap, DUK__FUN()));
76351 			DUK_UNREF(act);  /* if debugging disabled */
76352 
76353 			DUK_DDD(DUK_DDDPRINT("executing bytecode: pc=%ld, ins=0x%08lx, op=%ld, valstack_top=%ld/%ld, nregs=%ld  -->  %!I",
76354 			                     (long) (curr_pc - DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN())),
76355 			                     (unsigned long) *curr_pc,
76356 			                     (long) DUK_DEC_OP(*curr_pc),
76357 			                     (long) (thr->valstack_top - thr->valstack),
76358 			                     (long) (thr->valstack_end - thr->valstack),
76359 			                     (long) (DUK__FUN() ? DUK__FUN()->nregs : -1),
76360 			                     (duk_instr_t) *curr_pc));
76361 		}
76362 #endif
76363 
76364 #if defined(DUK_USE_ASSERTIONS)
76365 		/* Quite heavy assert: check valstack policy.  Improper
76366 		 * shuffle instructions can write beyond valstack_top/end
76367 		 * so this check catches them in the act.
76368 		 */
76369 		{
76370 			duk_tval *tv;
76371 			tv = thr->valstack_top;
76372 			while (tv != thr->valstack_end) {
76373 				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
76374 				tv++;
76375 			}
76376 		}
76377 #endif
76378 
76379 		ins = *curr_pc++;
76380 		DUK_STATS_INC(thr->heap, stats_exec_opcodes);
76381 
76382 		/* Typing: use duk_small_(u)int_fast_t when decoding small
76383 		 * opcode fields (op, A, B, C, BC) which fit into 16 bits
76384 		 * and duk_(u)int_fast_t when decoding larger fields (e.g.
76385 		 * ABC).  Use unsigned variant by default, signed when the
76386 		 * value is used in signed arithmetic.  Using variable names
76387 		 * such as 'a', 'b', 'c', 'bc', etc makes it easier to spot
76388 		 * typing mismatches.
76389 		 */
76390 
76391 		/* Switch based on opcode.  Cast to 8-bit unsigned value and
76392 		 * use a fully populated case clauses so that the compiler
76393 		 * will (at least usually) omit a bounds check.
76394 		 */
76395 		op = (duk_uint8_t) DUK_DEC_OP(ins);
76396 		switch (op) {
76397 
76398 		/* Some useful macros.  These access inner executor variables
76399 		 * directly so they only apply within the executor.
76400 		 */
76401 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76402 #define DUK__REPLACE_TOP_A_BREAK() { goto replace_top_a; }
76403 #define DUK__REPLACE_TOP_BC_BREAK() { goto replace_top_bc; }
76404 #define DUK__REPLACE_BOOL_A_BREAK(bval) { \
76405 		duk_bool_t duk__bval; \
76406 		duk__bval = (bval); \
76407 		DUK_ASSERT(duk__bval == 0 || duk__bval == 1); \
76408 		duk_push_boolean(thr, duk__bval); \
76409 		DUK__REPLACE_TOP_A_BREAK(); \
76410 	}
76411 #else
76412 #define DUK__REPLACE_TOP_A_BREAK() { DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_A(ins)); break; }
76413 #define DUK__REPLACE_TOP_BC_BREAK() { DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_BC(ins)); break; }
76414 #define DUK__REPLACE_BOOL_A_BREAK(bval) { \
76415 		duk_bool_t duk__bval; \
76416 		duk_tval *duk__tvdst; \
76417 		duk__bval = (bval); \
76418 		DUK_ASSERT(duk__bval == 0 || duk__bval == 1); \
76419 		duk__tvdst = DUK__REGP_A(ins); \
76420 		DUK_TVAL_SET_BOOLEAN_UPDREF(thr, duk__tvdst, duk__bval); \
76421 		break; \
76422 	}
76423 #endif
76424 
76425 		/* XXX: 12 + 12 bit variant might make sense too, for both reg and
76426 		 * const loads.
76427 		 */
76428 
76429 		/* For LDREG, STREG, LDCONST footprint optimized variants would just
76430 		 * duk_dup() + duk_replace(), but because they're used quite a lot
76431 		 * they're currently intentionally not size optimized.
76432 		 */
76433 		case DUK_OP_LDREG: {
76434 			duk_tval *tv1, *tv2;
76435 
76436 			tv1 = DUK__REGP_A(ins);
76437 			tv2 = DUK__REGP_BC(ins);
76438 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
76439 			break;
76440 		}
76441 
76442 		case DUK_OP_STREG: {
76443 			duk_tval *tv1, *tv2;
76444 
76445 			tv1 = DUK__REGP_A(ins);
76446 			tv2 = DUK__REGP_BC(ins);
76447 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv2, tv1);  /* side effects */
76448 			break;
76449 		}
76450 
76451 		case DUK_OP_LDCONST: {
76452 			duk_tval *tv1, *tv2;
76453 
76454 			tv1 = DUK__REGP_A(ins);
76455 			tv2 = DUK__CONSTP_BC(ins);
76456 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
76457 			break;
76458 		}
76459 
76460 		/* LDINT and LDINTX are intended to load an arbitrary signed
76461 		 * 32-bit value.  Only an LDINT+LDINTX sequence is supported.
76462 		 * This also guarantees all values remain fastints.
76463 		 */
76464 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76465 		case DUK_OP_LDINT: {
76466 			duk_int32_t val;
76467 
76468 			val = (duk_int32_t) DUK_DEC_BC(ins) - (duk_int32_t) DUK_BC_LDINT_BIAS;
76469 			duk_push_int(thr, val);
76470 			DUK__REPLACE_TOP_A_BREAK();
76471 		}
76472 		case DUK_OP_LDINTX: {
76473 			duk_int32_t val;
76474 
76475 			val = (duk_int32_t) duk_get_int(thr, DUK_DEC_A(ins));
76476 			val = (val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins);  /* no bias */
76477 			duk_push_int(thr, val);
76478 			DUK__REPLACE_TOP_A_BREAK();
76479 		}
76480 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76481 		case DUK_OP_LDINT: {
76482 			duk_tval *tv1;
76483 			duk_int32_t val;
76484 
76485 			val = (duk_int32_t) DUK_DEC_BC(ins) - (duk_int32_t) DUK_BC_LDINT_BIAS;
76486 			tv1 = DUK__REGP_A(ins);
76487 			DUK_TVAL_SET_I32_UPDREF(thr, tv1, val);  /* side effects */
76488 			break;
76489 		}
76490 		case DUK_OP_LDINTX: {
76491 			duk_tval *tv1;
76492 			duk_int32_t val;
76493 
76494 			tv1 = DUK__REGP_A(ins);
76495 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
76496 #if defined(DUK_USE_FASTINT)
76497 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
76498 			val = DUK_TVAL_GET_FASTINT_I32(tv1);
76499 #else
76500 			/* XXX: fast double-to-int conversion, we know number is integer in [-0x80000000,0xffffffff]. */
76501 			val = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv1);
76502 #endif
76503 			val = (duk_int32_t) ((duk_uint32_t) val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins);  /* no bias */
76504 			DUK_TVAL_SET_I32_UPDREF(thr, tv1, val);  /* side effects */
76505 			break;
76506 		}
76507 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76508 
76509 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76510 		case DUK_OP_LDTHIS: {
76511 			duk_push_this(thr);
76512 			DUK__REPLACE_TOP_BC_BREAK();
76513 		}
76514 		case DUK_OP_LDUNDEF: {
76515 			duk_to_undefined(thr, (duk_idx_t) DUK_DEC_BC(ins));
76516 			break;
76517 		}
76518 		case DUK_OP_LDNULL: {
76519 			duk_to_null(thr, (duk_idx_t) DUK_DEC_BC(ins));
76520 			break;
76521 		}
76522 		case DUK_OP_LDTRUE: {
76523 			duk_push_true(thr);
76524 			DUK__REPLACE_TOP_BC_BREAK();
76525 		}
76526 		case DUK_OP_LDFALSE: {
76527 			duk_push_false(thr);
76528 			DUK__REPLACE_TOP_BC_BREAK();
76529 		}
76530 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76531 		case DUK_OP_LDTHIS: {
76532 			/* Note: 'this' may be bound to any value, not just an object */
76533 			duk_tval *tv1, *tv2;
76534 
76535 			tv1 = DUK__REGP_BC(ins);
76536 			tv2 = thr->valstack_bottom - 1;  /* 'this binding' is just under bottom */
76537 			DUK_ASSERT(tv2 >= thr->valstack);
76538 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
76539 			break;
76540 		}
76541 		case DUK_OP_LDUNDEF: {
76542 			duk_tval *tv1;
76543 
76544 			tv1 = DUK__REGP_BC(ins);
76545 			DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
76546 			break;
76547 		}
76548 		case DUK_OP_LDNULL: {
76549 			duk_tval *tv1;
76550 
76551 			tv1 = DUK__REGP_BC(ins);
76552 			DUK_TVAL_SET_NULL_UPDREF(thr, tv1);  /* side effects */
76553 			break;
76554 		}
76555 		case DUK_OP_LDTRUE: {
76556 			duk_tval *tv1;
76557 
76558 			tv1 = DUK__REGP_BC(ins);
76559 			DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 1);  /* side effects */
76560 			break;
76561 		}
76562 		case DUK_OP_LDFALSE: {
76563 			duk_tval *tv1;
76564 
76565 			tv1 = DUK__REGP_BC(ins);
76566 			DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 0);  /* side effects */
76567 			break;
76568 		}
76569 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76570 
76571 		case DUK_OP_BNOT: {
76572 			duk__vm_bitwise_not(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins));
76573 			break;
76574 		}
76575 
76576 		case DUK_OP_LNOT: {
76577 			duk__vm_logical_not(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins));
76578 			break;
76579 		}
76580 
76581 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76582 		case DUK_OP_UNM:
76583 		case DUK_OP_UNP: {
76584 			duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), op);
76585 			break;
76586 		}
76587 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76588 		case DUK_OP_UNM: {
76589 			duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), DUK_OP_UNM);
76590 			break;
76591 		}
76592 		case DUK_OP_UNP: {
76593 			duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), DUK_OP_UNP);
76594 			break;
76595 		}
76596 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76597 
76598 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76599 		case DUK_OP_TYPEOF: {
76600 			duk_small_uint_t stridx;
76601 
76602 			stridx = duk_js_typeof_stridx(DUK__REGP_BC(ins));
76603 			DUK_ASSERT_STRIDX_VALID(stridx);
76604 			duk_push_hstring_stridx(thr, stridx);
76605 			DUK__REPLACE_TOP_A_BREAK();
76606 		}
76607 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76608 		case DUK_OP_TYPEOF: {
76609 			duk_tval *tv;
76610 			duk_small_uint_t stridx;
76611 			duk_hstring *h_str;
76612 
76613 			tv = DUK__REGP_BC(ins);
76614 			stridx = duk_js_typeof_stridx(tv);
76615 			DUK_ASSERT_STRIDX_VALID(stridx);
76616 			h_str = DUK_HTHREAD_GET_STRING(thr, stridx);
76617 			tv = DUK__REGP_A(ins);
76618 			DUK_TVAL_SET_STRING_UPDREF(thr, tv, h_str);
76619 			break;
76620 		}
76621 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76622 
76623 		case DUK_OP_TYPEOFID: {
76624 			duk_small_uint_t stridx;
76625 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
76626 			duk_hstring *h_str;
76627 #endif
76628 			duk_activation *act;
76629 			duk_hstring *name;
76630 			duk_tval *tv;
76631 
76632 			/* A -> target register
76633 			 * BC -> constant index of identifier name
76634 			 */
76635 
76636 			tv = DUK__CONSTP_BC(ins);
76637 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv));
76638 			name = DUK_TVAL_GET_STRING(tv);
76639 			tv = NULL;  /* lookup has side effects */
76640 			act = thr->callstack_curr;
76641 			if (duk_js_getvar_activation(thr, act, name, 0 /*throw*/)) {
76642 				/* -> [... val this] */
76643 				tv = DUK_GET_TVAL_NEGIDX(thr, -2);
76644 				stridx = duk_js_typeof_stridx(tv);
76645 				tv = NULL;  /* no longer needed */
76646 				duk_pop_2_unsafe(thr);
76647 			} else {
76648 				/* unresolvable, no stack changes */
76649 				stridx = DUK_STRIDX_LC_UNDEFINED;
76650 			}
76651 			DUK_ASSERT_STRIDX_VALID(stridx);
76652 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76653 			duk_push_hstring_stridx(thr, stridx);
76654 			DUK__REPLACE_TOP_A_BREAK();
76655 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76656 			h_str = DUK_HTHREAD_GET_STRING(thr, stridx);
76657 			tv = DUK__REGP_A(ins);
76658 			DUK_TVAL_SET_STRING_UPDREF(thr, tv, h_str);
76659 			break;
76660 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76661 		}
76662 
76663 		/* Equality: E5 Sections 11.9.1, 11.9.3 */
76664 
76665 #define DUK__EQ_BODY(barg,carg) { \
76666 		duk_bool_t tmp; \
76667 		tmp = duk_js_equals(thr, (barg), (carg)); \
76668 		DUK_ASSERT(tmp == 0 || tmp == 1); \
76669 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
76670 	}
76671 #define DUK__NEQ_BODY(barg,carg) { \
76672 		duk_bool_t tmp; \
76673 		tmp = duk_js_equals(thr, (barg), (carg)); \
76674 		DUK_ASSERT(tmp == 0 || tmp == 1); \
76675 		tmp ^= 1; \
76676 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
76677 	}
76678 #define DUK__SEQ_BODY(barg,carg) { \
76679 		duk_bool_t tmp; \
76680 		tmp = duk_js_strict_equals((barg), (carg)); \
76681 		DUK_ASSERT(tmp == 0 || tmp == 1); \
76682 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
76683 	}
76684 #define DUK__SNEQ_BODY(barg,carg) { \
76685 		duk_bool_t tmp; \
76686 		tmp = duk_js_strict_equals((barg), (carg)); \
76687 		DUK_ASSERT(tmp == 0 || tmp == 1); \
76688 		tmp ^= 1; \
76689 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
76690 	}
76691 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76692 		case DUK_OP_EQ_RR:
76693 		case DUK_OP_EQ_CR:
76694 		case DUK_OP_EQ_RC:
76695 		case DUK_OP_EQ_CC:
76696 			DUK__EQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
76697 		case DUK_OP_NEQ_RR:
76698 		case DUK_OP_NEQ_CR:
76699 		case DUK_OP_NEQ_RC:
76700 		case DUK_OP_NEQ_CC:
76701 			DUK__NEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
76702 		case DUK_OP_SEQ_RR:
76703 		case DUK_OP_SEQ_CR:
76704 		case DUK_OP_SEQ_RC:
76705 		case DUK_OP_SEQ_CC:
76706 			DUK__SEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
76707 		case DUK_OP_SNEQ_RR:
76708 		case DUK_OP_SNEQ_CR:
76709 		case DUK_OP_SNEQ_RC:
76710 		case DUK_OP_SNEQ_CC:
76711 			DUK__SNEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
76712 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76713 		case DUK_OP_EQ_RR:
76714 			DUK__EQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
76715 		case DUK_OP_EQ_CR:
76716 			DUK__EQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
76717 		case DUK_OP_EQ_RC:
76718 			DUK__EQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
76719 		case DUK_OP_EQ_CC:
76720 			DUK__EQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
76721 		case DUK_OP_NEQ_RR:
76722 			DUK__NEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
76723 		case DUK_OP_NEQ_CR:
76724 			DUK__NEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
76725 		case DUK_OP_NEQ_RC:
76726 			DUK__NEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
76727 		case DUK_OP_NEQ_CC:
76728 			DUK__NEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
76729 		case DUK_OP_SEQ_RR:
76730 			DUK__SEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
76731 		case DUK_OP_SEQ_CR:
76732 			DUK__SEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
76733 		case DUK_OP_SEQ_RC:
76734 			DUK__SEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
76735 		case DUK_OP_SEQ_CC:
76736 			DUK__SEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
76737 		case DUK_OP_SNEQ_RR:
76738 			DUK__SNEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
76739 		case DUK_OP_SNEQ_CR:
76740 			DUK__SNEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
76741 		case DUK_OP_SNEQ_RC:
76742 			DUK__SNEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
76743 		case DUK_OP_SNEQ_CC:
76744 			DUK__SNEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
76745 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76746 
76747 #define DUK__COMPARE_BODY(arg1,arg2,flags) { \
76748 		duk_bool_t tmp; \
76749 		tmp = duk_js_compare_helper(thr, (arg1), (arg2), (flags)); \
76750 		DUK_ASSERT(tmp == 0 || tmp == 1); \
76751 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
76752 	}
76753 #define DUK__GT_BODY(barg,carg) DUK__COMPARE_BODY((carg), (barg), 0)
76754 #define DUK__GE_BODY(barg,carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
76755 #define DUK__LT_BODY(barg,carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
76756 #define DUK__LE_BODY(barg,carg) DUK__COMPARE_BODY((carg), (barg), DUK_COMPARE_FLAG_NEGATE)
76757 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76758 		case DUK_OP_GT_RR:
76759 		case DUK_OP_GT_CR:
76760 		case DUK_OP_GT_RC:
76761 		case DUK_OP_GT_CC:
76762 			DUK__GT_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
76763 		case DUK_OP_GE_RR:
76764 		case DUK_OP_GE_CR:
76765 		case DUK_OP_GE_RC:
76766 		case DUK_OP_GE_CC:
76767 			DUK__GE_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
76768 		case DUK_OP_LT_RR:
76769 		case DUK_OP_LT_CR:
76770 		case DUK_OP_LT_RC:
76771 		case DUK_OP_LT_CC:
76772 			DUK__LT_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
76773 		case DUK_OP_LE_RR:
76774 		case DUK_OP_LE_CR:
76775 		case DUK_OP_LE_RC:
76776 		case DUK_OP_LE_CC:
76777 			DUK__LE_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
76778 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76779 		case DUK_OP_GT_RR:
76780 			DUK__GT_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
76781 		case DUK_OP_GT_CR:
76782 			DUK__GT_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
76783 		case DUK_OP_GT_RC:
76784 			DUK__GT_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
76785 		case DUK_OP_GT_CC:
76786 			DUK__GT_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
76787 		case DUK_OP_GE_RR:
76788 			DUK__GE_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
76789 		case DUK_OP_GE_CR:
76790 			DUK__GE_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
76791 		case DUK_OP_GE_RC:
76792 			DUK__GE_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
76793 		case DUK_OP_GE_CC:
76794 			DUK__GE_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
76795 		case DUK_OP_LT_RR:
76796 			DUK__LT_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
76797 		case DUK_OP_LT_CR:
76798 			DUK__LT_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
76799 		case DUK_OP_LT_RC:
76800 			DUK__LT_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
76801 		case DUK_OP_LT_CC:
76802 			DUK__LT_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
76803 		case DUK_OP_LE_RR:
76804 			DUK__LE_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
76805 		case DUK_OP_LE_CR:
76806 			DUK__LE_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
76807 		case DUK_OP_LE_RC:
76808 			DUK__LE_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
76809 		case DUK_OP_LE_CC:
76810 			DUK__LE_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
76811 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76812 
76813 		/* No size optimized variant at present for IF. */
76814 		case DUK_OP_IFTRUE_R: {
76815 			if (duk_js_toboolean(DUK__REGP_BC(ins)) != 0) {
76816 				curr_pc++;
76817 			}
76818 			break;
76819 		}
76820 		case DUK_OP_IFTRUE_C: {
76821 			if (duk_js_toboolean(DUK__CONSTP_BC(ins)) != 0) {
76822 				curr_pc++;
76823 			}
76824 			break;
76825 		}
76826 		case DUK_OP_IFFALSE_R: {
76827 			if (duk_js_toboolean(DUK__REGP_BC(ins)) == 0) {
76828 				curr_pc++;
76829 			}
76830 			break;
76831 		}
76832 		case DUK_OP_IFFALSE_C: {
76833 			if (duk_js_toboolean(DUK__CONSTP_BC(ins)) == 0) {
76834 				curr_pc++;
76835 			}
76836 			break;
76837 		}
76838 
76839 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76840 		case DUK_OP_ADD_RR:
76841 		case DUK_OP_ADD_CR:
76842 		case DUK_OP_ADD_RC:
76843 		case DUK_OP_ADD_CC: {
76844 			/* XXX: could leave value on stack top and goto replace_top_a; */
76845 			duk__vm_arith_add(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins));
76846 			break;
76847 		}
76848 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76849 		case DUK_OP_ADD_RR: {
76850 			duk__vm_arith_add(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins));
76851 			break;
76852 		}
76853 		case DUK_OP_ADD_CR: {
76854 			duk__vm_arith_add(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins));
76855 			break;
76856 		}
76857 		case DUK_OP_ADD_RC: {
76858 			duk__vm_arith_add(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins));
76859 			break;
76860 		}
76861 		case DUK_OP_ADD_CC: {
76862 			duk__vm_arith_add(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins));
76863 			break;
76864 		}
76865 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76866 
76867 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76868 		case DUK_OP_SUB_RR:
76869 		case DUK_OP_SUB_CR:
76870 		case DUK_OP_SUB_RC:
76871 		case DUK_OP_SUB_CC:
76872 		case DUK_OP_MUL_RR:
76873 		case DUK_OP_MUL_CR:
76874 		case DUK_OP_MUL_RC:
76875 		case DUK_OP_MUL_CC:
76876 		case DUK_OP_DIV_RR:
76877 		case DUK_OP_DIV_CR:
76878 		case DUK_OP_DIV_RC:
76879 		case DUK_OP_DIV_CC:
76880 		case DUK_OP_MOD_RR:
76881 		case DUK_OP_MOD_CR:
76882 		case DUK_OP_MOD_RC:
76883 		case DUK_OP_MOD_CC:
76884 #if defined(DUK_USE_ES7_EXP_OPERATOR)
76885 		case DUK_OP_EXP_RR:
76886 		case DUK_OP_EXP_CR:
76887 		case DUK_OP_EXP_RC:
76888 		case DUK_OP_EXP_CC:
76889 #endif  /* DUK_USE_ES7_EXP_OPERATOR */
76890 		{
76891 			/* XXX: could leave value on stack top and goto replace_top_a; */
76892 			duk__vm_arith_binary_op(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins), op);
76893 			break;
76894 		}
76895 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76896 		case DUK_OP_SUB_RR: {
76897 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
76898 			break;
76899 		}
76900 		case DUK_OP_SUB_CR: {
76901 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
76902 			break;
76903 		}
76904 		case DUK_OP_SUB_RC: {
76905 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
76906 			break;
76907 		}
76908 		case DUK_OP_SUB_CC: {
76909 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
76910 			break;
76911 		}
76912 		case DUK_OP_MUL_RR: {
76913 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
76914 			break;
76915 		}
76916 		case DUK_OP_MUL_CR: {
76917 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
76918 			break;
76919 		}
76920 		case DUK_OP_MUL_RC: {
76921 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
76922 			break;
76923 		}
76924 		case DUK_OP_MUL_CC: {
76925 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
76926 			break;
76927 		}
76928 		case DUK_OP_DIV_RR: {
76929 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
76930 			break;
76931 		}
76932 		case DUK_OP_DIV_CR: {
76933 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
76934 			break;
76935 		}
76936 		case DUK_OP_DIV_RC: {
76937 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
76938 			break;
76939 		}
76940 		case DUK_OP_DIV_CC: {
76941 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
76942 			break;
76943 		}
76944 		case DUK_OP_MOD_RR: {
76945 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
76946 			break;
76947 		}
76948 		case DUK_OP_MOD_CR: {
76949 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
76950 			break;
76951 		}
76952 		case DUK_OP_MOD_RC: {
76953 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
76954 			break;
76955 		}
76956 		case DUK_OP_MOD_CC: {
76957 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
76958 			break;
76959 		}
76960 #if defined(DUK_USE_ES7_EXP_OPERATOR)
76961 		case DUK_OP_EXP_RR: {
76962 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
76963 			break;
76964 		}
76965 		case DUK_OP_EXP_CR: {
76966 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
76967 			break;
76968 		}
76969 		case DUK_OP_EXP_RC: {
76970 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
76971 			break;
76972 		}
76973 		case DUK_OP_EXP_CC: {
76974 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
76975 			break;
76976 		}
76977 #endif  /* DUK_USE_ES7_EXP_OPERATOR */
76978 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76979 
76980 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76981 		case DUK_OP_BAND_RR:
76982 		case DUK_OP_BAND_CR:
76983 		case DUK_OP_BAND_RC:
76984 		case DUK_OP_BAND_CC:
76985 		case DUK_OP_BOR_RR:
76986 		case DUK_OP_BOR_CR:
76987 		case DUK_OP_BOR_RC:
76988 		case DUK_OP_BOR_CC:
76989 		case DUK_OP_BXOR_RR:
76990 		case DUK_OP_BXOR_CR:
76991 		case DUK_OP_BXOR_RC:
76992 		case DUK_OP_BXOR_CC:
76993 		case DUK_OP_BASL_RR:
76994 		case DUK_OP_BASL_CR:
76995 		case DUK_OP_BASL_RC:
76996 		case DUK_OP_BASL_CC:
76997 		case DUK_OP_BLSR_RR:
76998 		case DUK_OP_BLSR_CR:
76999 		case DUK_OP_BLSR_RC:
77000 		case DUK_OP_BLSR_CC:
77001 		case DUK_OP_BASR_RR:
77002 		case DUK_OP_BASR_CR:
77003 		case DUK_OP_BASR_RC:
77004 		case DUK_OP_BASR_CC: {
77005 			/* XXX: could leave value on stack top and goto replace_top_a; */
77006 			duk__vm_bitwise_binary_op(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins), op);
77007 			break;
77008 		}
77009 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77010 		case DUK_OP_BAND_RR: {
77011 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
77012 			break;
77013 		}
77014 		case DUK_OP_BAND_CR: {
77015 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
77016 			break;
77017 		}
77018 		case DUK_OP_BAND_RC: {
77019 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
77020 			break;
77021 		}
77022 		case DUK_OP_BAND_CC: {
77023 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
77024 			break;
77025 		}
77026 		case DUK_OP_BOR_RR: {
77027 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
77028 			break;
77029 		}
77030 		case DUK_OP_BOR_CR: {
77031 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
77032 			break;
77033 		}
77034 		case DUK_OP_BOR_RC: {
77035 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
77036 			break;
77037 		}
77038 		case DUK_OP_BOR_CC: {
77039 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
77040 			break;
77041 		}
77042 		case DUK_OP_BXOR_RR: {
77043 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
77044 			break;
77045 		}
77046 		case DUK_OP_BXOR_CR: {
77047 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
77048 			break;
77049 		}
77050 		case DUK_OP_BXOR_RC: {
77051 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
77052 			break;
77053 		}
77054 		case DUK_OP_BXOR_CC: {
77055 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
77056 			break;
77057 		}
77058 		case DUK_OP_BASL_RR: {
77059 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
77060 			break;
77061 		}
77062 		case DUK_OP_BASL_CR: {
77063 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
77064 			break;
77065 		}
77066 		case DUK_OP_BASL_RC: {
77067 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
77068 			break;
77069 		}
77070 		case DUK_OP_BASL_CC: {
77071 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
77072 			break;
77073 		}
77074 		case DUK_OP_BLSR_RR: {
77075 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
77076 			break;
77077 		}
77078 		case DUK_OP_BLSR_CR: {
77079 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
77080 			break;
77081 		}
77082 		case DUK_OP_BLSR_RC: {
77083 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
77084 			break;
77085 		}
77086 		case DUK_OP_BLSR_CC: {
77087 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
77088 			break;
77089 		}
77090 		case DUK_OP_BASR_RR: {
77091 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
77092 			break;
77093 		}
77094 		case DUK_OP_BASR_CR: {
77095 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
77096 			break;
77097 		}
77098 		case DUK_OP_BASR_RC: {
77099 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
77100 			break;
77101 		}
77102 		case DUK_OP_BASR_CC: {
77103 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
77104 			break;
77105 		}
77106 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77107 
77108 		/* For INSTOF and IN, B is always a register. */
77109 #define DUK__INSTOF_BODY(barg,carg) { \
77110 		duk_bool_t tmp; \
77111 		tmp = duk_js_instanceof(thr, (barg), (carg)); \
77112 		DUK_ASSERT(tmp == 0 || tmp == 1); \
77113 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
77114 	}
77115 #define DUK__IN_BODY(barg,carg) { \
77116 		duk_bool_t tmp; \
77117 		tmp = duk_js_in(thr, (barg), (carg)); \
77118 		DUK_ASSERT(tmp == 0 || tmp == 1); \
77119 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
77120 	}
77121 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77122 		case DUK_OP_INSTOF_RR:
77123 		case DUK_OP_INSTOF_CR:
77124 		case DUK_OP_INSTOF_RC:
77125 		case DUK_OP_INSTOF_CC:
77126 			DUK__INSTOF_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
77127 		case DUK_OP_IN_RR:
77128 		case DUK_OP_IN_CR:
77129 		case DUK_OP_IN_RC:
77130 		case DUK_OP_IN_CC:
77131 			DUK__IN_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
77132 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77133 		case DUK_OP_INSTOF_RR:
77134 			DUK__INSTOF_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
77135 		case DUK_OP_INSTOF_CR:
77136 			DUK__INSTOF_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
77137 		case DUK_OP_INSTOF_RC:
77138 			DUK__INSTOF_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77139 		case DUK_OP_INSTOF_CC:
77140 			DUK__INSTOF_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
77141 		case DUK_OP_IN_RR:
77142 			DUK__IN_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
77143 		case DUK_OP_IN_CR:
77144 			DUK__IN_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
77145 		case DUK_OP_IN_RC:
77146 			DUK__IN_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77147 		case DUK_OP_IN_CC:
77148 			DUK__IN_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
77149 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77150 
77151 		/* Pre/post inc/dec for register variables, important for loops. */
77152 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77153 		case DUK_OP_PREINCR:
77154 		case DUK_OP_PREDECR:
77155 		case DUK_OP_POSTINCR:
77156 		case DUK_OP_POSTDECR: {
77157 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), op);
77158 			break;
77159 		}
77160 		case DUK_OP_PREINCV:
77161 		case DUK_OP_PREDECV:
77162 		case DUK_OP_POSTINCV:
77163 		case DUK_OP_POSTDECV: {
77164 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), op, DUK__STRICT());
77165 			break;
77166 		}
77167 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77168 		case DUK_OP_PREINCR: {
77169 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_PREINCR);
77170 			break;
77171 		}
77172 		case DUK_OP_PREDECR: {
77173 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_PREDECR);
77174 			break;
77175 		}
77176 		case DUK_OP_POSTINCR: {
77177 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_POSTINCR);
77178 			break;
77179 		}
77180 		case DUK_OP_POSTDECR: {
77181 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_POSTDECR);
77182 			break;
77183 		}
77184 		case DUK_OP_PREINCV: {
77185 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_PREINCV, DUK__STRICT());
77186 			break;
77187 		}
77188 		case DUK_OP_PREDECV: {
77189 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_PREDECV, DUK__STRICT());
77190 			break;
77191 		}
77192 		case DUK_OP_POSTINCV: {
77193 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_POSTINCV, DUK__STRICT());
77194 			break;
77195 		}
77196 		case DUK_OP_POSTDECV: {
77197 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_POSTDECV, DUK__STRICT());
77198 			break;
77199 		}
77200 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77201 
77202 		/* XXX: Move to separate helper, optimize for perf/size separately. */
77203 		/* Preinc/predec for object properties. */
77204 		case DUK_OP_PREINCP_RR:
77205 		case DUK_OP_PREINCP_CR:
77206 		case DUK_OP_PREINCP_RC:
77207 		case DUK_OP_PREINCP_CC:
77208 		case DUK_OP_PREDECP_RR:
77209 		case DUK_OP_PREDECP_CR:
77210 		case DUK_OP_PREDECP_RC:
77211 		case DUK_OP_PREDECP_CC:
77212 		case DUK_OP_POSTINCP_RR:
77213 		case DUK_OP_POSTINCP_CR:
77214 		case DUK_OP_POSTINCP_RC:
77215 		case DUK_OP_POSTINCP_CC:
77216 		case DUK_OP_POSTDECP_RR:
77217 		case DUK_OP_POSTDECP_CR:
77218 		case DUK_OP_POSTDECP_RC:
77219 		case DUK_OP_POSTDECP_CC: {
77220 			duk_tval *tv_obj;
77221 			duk_tval *tv_key;
77222 			duk_tval *tv_val;
77223 			duk_bool_t rc;
77224 			duk_double_t x, y, z;
77225 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
77226 			duk_tval *tv_dst;
77227 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77228 
77229 			/* A -> target reg
77230 			 * B -> object reg/const (may be const e.g. in "'foo'[1]")
77231 			 * C -> key reg/const
77232 			 */
77233 
77234 			/* Opcode bits 0-1 are used to distinguish reg/const variants.
77235 			 * Opcode bits 2-3 are used to distinguish inc/dec variants:
77236 			 * Bit 2 = inc(0)/dec(1), bit 3 = pre(0)/post(1).
77237 			 */
77238 			DUK_ASSERT((DUK_OP_PREINCP_RR & 0x0c) == 0x00);
77239 			DUK_ASSERT((DUK_OP_PREDECP_RR & 0x0c) == 0x04);
77240 			DUK_ASSERT((DUK_OP_POSTINCP_RR & 0x0c) == 0x08);
77241 			DUK_ASSERT((DUK_OP_POSTDECP_RR & 0x0c) == 0x0c);
77242 
77243 			tv_obj = DUK__REGCONSTP_B(ins);
77244 			tv_key = DUK__REGCONSTP_C(ins);
77245 			rc = duk_hobject_getprop(thr, tv_obj, tv_key);  /* -> [val] */
77246 			DUK_UNREF(rc);  /* ignore */
77247 			tv_obj = NULL;  /* invalidated */
77248 			tv_key = NULL;  /* invalidated */
77249 
77250 			/* XXX: Fastint fast path would be useful here.  Also fastints
77251 			 * now lose their fastint status in current handling which is
77252 			 * not intuitive.
77253 			 */
77254 
77255 			x = duk_to_number_m1(thr);
77256 			duk_pop_unsafe(thr);
77257 			if (ins & DUK_BC_INCDECP_FLAG_DEC) {
77258 				y = x - 1.0;
77259 			} else {
77260 				y = x + 1.0;
77261 			}
77262 
77263 			duk_push_number(thr, y);
77264 			tv_val = DUK_GET_TVAL_NEGIDX(thr, -1);
77265 			DUK_ASSERT(tv_val != NULL);
77266 			tv_obj = DUK__REGCONSTP_B(ins);
77267 			tv_key = DUK__REGCONSTP_C(ins);
77268 			rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, DUK__STRICT());
77269 			DUK_UNREF(rc);  /* ignore */
77270 			tv_obj = NULL;  /* invalidated */
77271 			tv_key = NULL;  /* invalidated */
77272 			duk_pop_unsafe(thr);
77273 
77274 			z = (ins & DUK_BC_INCDECP_FLAG_POST) ? x : y;
77275 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77276 			duk_push_number(thr, z);
77277 			DUK__REPLACE_TOP_A_BREAK();
77278 #else
77279 			tv_dst = DUK__REGP_A(ins);
77280 			DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_dst, z);
77281 			break;
77282 #endif
77283 		}
77284 
77285 		/* XXX: GETPROP where object is 'this', GETPROPT?
77286 		 * Occurs relatively often in object oriented code.
77287 		 */
77288 
77289 #define DUK__GETPROP_BODY(barg,carg) { \
77290 		/* A -> target reg \
77291 		 * B -> object reg/const (may be const e.g. in "'foo'[1]") \
77292 		 * C -> key reg/const \
77293 		 */ \
77294 		(void) duk_hobject_getprop(thr, (barg), (carg)); \
77295 		DUK__REPLACE_TOP_A_BREAK(); \
77296 	}
77297 #define DUK__GETPROPC_BODY(barg,carg) { \
77298 		/* Same as GETPROP but callability check for property-based calls. */ \
77299 		duk_tval *tv__targ; \
77300 		(void) duk_hobject_getprop(thr, (barg), (carg)); \
77301 		DUK_GC_TORTURE(thr->heap); \
77302 		tv__targ = DUK_GET_TVAL_NEGIDX(thr, -1); \
77303 		if (DUK_UNLIKELY(!duk_is_callable_tval(thr, tv__targ))) { \
77304 			/* Here we intentionally re-evaluate the macro \
77305 			 * arguments to deal with potentially changed \
77306 			 * valstack base pointer! \
77307 			 */ \
77308 			duk_call_setup_propcall_error(thr, tv__targ, (barg), (carg)); \
77309 		} \
77310 		DUK__REPLACE_TOP_A_BREAK(); \
77311 	}
77312 #define DUK__PUTPROP_BODY(aarg,barg,carg) { \
77313 		/* A -> object reg \
77314 		 * B -> key reg/const \
77315 		 * C -> value reg/const \
77316 		 * \
77317 		 * Note: intentional difference to register arrangement \
77318 		 * of e.g. GETPROP; 'A' must contain a register-only value. \
77319 		 */ \
77320 		(void) duk_hobject_putprop(thr, (aarg), (barg), (carg), DUK__STRICT()); \
77321 		break; \
77322 	}
77323 #define DUK__DELPROP_BODY(barg,carg) { \
77324 		/* A -> result reg \
77325 		 * B -> object reg \
77326 		 * C -> key reg/const \
77327 		 */ \
77328 		duk_bool_t rc; \
77329 		rc = duk_hobject_delprop(thr, (barg), (carg), DUK__STRICT()); \
77330 		DUK_ASSERT(rc == 0 || rc == 1); \
77331 		DUK__REPLACE_BOOL_A_BREAK(rc); \
77332 	}
77333 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77334 		case DUK_OP_GETPROP_RR:
77335 		case DUK_OP_GETPROP_CR:
77336 		case DUK_OP_GETPROP_RC:
77337 		case DUK_OP_GETPROP_CC:
77338 			DUK__GETPROP_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
77339 #if defined(DUK_USE_VERBOSE_ERRORS)
77340 		case DUK_OP_GETPROPC_RR:
77341 		case DUK_OP_GETPROPC_CR:
77342 		case DUK_OP_GETPROPC_RC:
77343 		case DUK_OP_GETPROPC_CC:
77344 			DUK__GETPROPC_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
77345 #endif
77346 		case DUK_OP_PUTPROP_RR:
77347 		case DUK_OP_PUTPROP_CR:
77348 		case DUK_OP_PUTPROP_RC:
77349 		case DUK_OP_PUTPROP_CC:
77350 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
77351 		case DUK_OP_DELPROP_RR:
77352 		case DUK_OP_DELPROP_RC:  /* B is always reg */
77353 			DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__REGCONSTP_C(ins));
77354 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77355 		case DUK_OP_GETPROP_RR:
77356 			DUK__GETPROP_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
77357 		case DUK_OP_GETPROP_CR:
77358 			DUK__GETPROP_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
77359 		case DUK_OP_GETPROP_RC:
77360 			DUK__GETPROP_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77361 		case DUK_OP_GETPROP_CC:
77362 			DUK__GETPROP_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
77363 #if defined(DUK_USE_VERBOSE_ERRORS)
77364 		case DUK_OP_GETPROPC_RR:
77365 			DUK__GETPROPC_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
77366 		case DUK_OP_GETPROPC_CR:
77367 			DUK__GETPROPC_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
77368 		case DUK_OP_GETPROPC_RC:
77369 			DUK__GETPROPC_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77370 		case DUK_OP_GETPROPC_CC:
77371 			DUK__GETPROPC_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
77372 #endif
77373 		case DUK_OP_PUTPROP_RR:
77374 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGP_B(ins), DUK__REGP_C(ins));
77375 		case DUK_OP_PUTPROP_CR:
77376 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__CONSTP_B(ins), DUK__REGP_C(ins));
77377 		case DUK_OP_PUTPROP_RC:
77378 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77379 		case DUK_OP_PUTPROP_CC:
77380 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
77381 		case DUK_OP_DELPROP_RR:  /* B is always reg */
77382 			DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
77383 		case DUK_OP_DELPROP_RC:
77384 			DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77385 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77386 
77387 		/* No fast path for DECLVAR now, it's quite a rare instruction. */
77388 		case DUK_OP_DECLVAR_RR:
77389 		case DUK_OP_DECLVAR_CR:
77390 		case DUK_OP_DECLVAR_RC:
77391 		case DUK_OP_DECLVAR_CC: {
77392 			duk_activation *act;
77393 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
77394 			duk_tval *tv1;
77395 			duk_hstring *name;
77396 			duk_small_uint_t prop_flags;
77397 			duk_bool_t is_func_decl;
77398 
77399 			tv1 = DUK__REGCONSTP_B(ins);
77400 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
77401 			name = DUK_TVAL_GET_STRING(tv1);
77402 			DUK_ASSERT(name != NULL);
77403 
77404 			is_func_decl = ((a & DUK_BC_DECLVAR_FLAG_FUNC_DECL) != 0);
77405 
77406 			/* XXX: declvar takes an duk_tval pointer, which is awkward and
77407 			 * should be reworked.
77408 			 */
77409 
77410 			/* Compiler is responsible for selecting property flags (configurability,
77411 			 * writability, etc).
77412 			 */
77413 			prop_flags = a & DUK_PROPDESC_FLAGS_MASK;
77414 
77415 			if (is_func_decl) {
77416 				duk_push_tval(thr, DUK__REGCONSTP_C(ins));
77417 			} else {
77418 				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */
77419 				thr->valstack_top++;
77420 			}
77421 			tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
77422 
77423 			act = thr->callstack_curr;
77424 			if (duk_js_declvar_activation(thr, act, name, tv1, prop_flags, is_func_decl)) {
77425 				if (is_func_decl) {
77426 					/* Already declared, update value. */
77427 					tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
77428 					duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
77429 				} else {
77430 					/* Already declared but no initializer value
77431 					 * (e.g. 'var xyz;'), no-op.
77432 					 */
77433 				}
77434 			}
77435 
77436 			duk_pop_unsafe(thr);
77437 			break;
77438 		}
77439 
77440 #if defined(DUK_USE_REGEXP_SUPPORT)
77441 		/* The compiler should never emit DUK_OP_REGEXP if there is no
77442 		 * regexp support.
77443 		 */
77444 		case DUK_OP_REGEXP_RR:
77445 		case DUK_OP_REGEXP_CR:
77446 		case DUK_OP_REGEXP_RC:
77447 		case DUK_OP_REGEXP_CC: {
77448 			/* A -> target register
77449 			 * B -> bytecode (also contains flags)
77450 			 * C -> escaped source
77451 			 */
77452 
77453 			duk_push_tval(thr, DUK__REGCONSTP_C(ins));
77454 			duk_push_tval(thr, DUK__REGCONSTP_B(ins));  /* -> [ ... escaped_source bytecode ] */
77455 			duk_regexp_create_instance(thr);   /* -> [ ... regexp_instance ] */
77456 			DUK__REPLACE_TOP_A_BREAK();
77457 		}
77458 #endif  /* DUK_USE_REGEXP_SUPPORT */
77459 
77460 		/* XXX: 'c' is unused, use whole BC, etc. */
77461 		case DUK_OP_CSVAR_RR:
77462 		case DUK_OP_CSVAR_CR:
77463 		case DUK_OP_CSVAR_RC:
77464 		case DUK_OP_CSVAR_CC: {
77465 			/* The speciality of calling through a variable binding is that the
77466 			 * 'this' value may be provided by the variable lookup: E5 Section 6.b.i.
77467 			 *
77468 			 * The only (standard) case where the 'this' binding is non-null is when
77469 			 *   (1) the variable is found in an object environment record, and
77470 			 *   (2) that object environment record is a 'with' block.
77471 			 */
77472 
77473 			duk_activation *act;
77474 			duk_uint_fast_t idx;
77475 			duk_tval *tv1;
77476 			duk_hstring *name;
77477 
77478 			/* A -> target registers (A, A + 1) for call setup
77479 			 * B -> identifier name, usually constant but can be a register due to shuffling
77480 			 */
77481 
77482 			tv1 = DUK__REGCONSTP_B(ins);
77483 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
77484 			name = DUK_TVAL_GET_STRING(tv1);
77485 			DUK_ASSERT(name != NULL);
77486 			act = thr->callstack_curr;
77487 			(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [... val this] */
77488 
77489 			idx = (duk_uint_fast_t) DUK_DEC_A(ins);
77490 
77491 			/* Could add direct value stack handling. */
77492 			duk_replace(thr, (duk_idx_t) (idx + 1));  /* 'this' binding */
77493 			duk_replace(thr, (duk_idx_t) idx);        /* variable value (function, we hope, not checked here) */
77494 			break;
77495 		}
77496 
77497 		case DUK_OP_CLOSURE: {
77498 			duk_activation *act;
77499 			duk_hcompfunc *fun_act;
77500 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
77501 			duk_hobject *fun_temp;
77502 
77503 			/* A -> target reg
77504 			 * BC -> inner function index
77505 			 */
77506 
77507 			DUK_DDD(DUK_DDDPRINT("CLOSURE to target register %ld, fnum %ld (count %ld)",
77508 			                     (long) DUK_DEC_A(ins), (long) DUK_DEC_BC(ins), (long) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, DUK__FUN())));
77509 
77510 			DUK_ASSERT_DISABLE(bc >= 0); /* unsigned */
77511 			DUK_ASSERT((duk_uint_t) bc < (duk_uint_t) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, DUK__FUN()));
77512 
77513 			act = thr->callstack_curr;
77514 			fun_act = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
77515 			fun_temp = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, fun_act)[bc];
77516 			DUK_ASSERT(fun_temp != NULL);
77517 			DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(fun_temp));
77518 
77519 			DUK_DDD(DUK_DDDPRINT("CLOSURE: function template is: %p -> %!O",
77520 			                     (void *) fun_temp, (duk_heaphdr *) fun_temp));
77521 
77522 			if (act->lex_env == NULL) {
77523 				DUK_ASSERT(act->var_env == NULL);
77524 				duk_js_init_activation_environment_records_delayed(thr, act);
77525 				act = thr->callstack_curr;
77526 			}
77527 			DUK_ASSERT(act->lex_env != NULL);
77528 			DUK_ASSERT(act->var_env != NULL);
77529 
77530 			/* functions always have a NEWENV flag, i.e. they get a
77531 			 * new variable declaration environment, so only lex_env
77532 			 * matters here.
77533 			 */
77534 			duk_js_push_closure(thr,
77535 			                    (duk_hcompfunc *) fun_temp,
77536 			                    act->var_env,
77537 			                    act->lex_env,
77538 			                    1 /*add_auto_proto*/);
77539 			DUK__REPLACE_TOP_A_BREAK();
77540 		}
77541 
77542 		case DUK_OP_GETVAR: {
77543 			duk_activation *act;
77544 			duk_tval *tv1;
77545 			duk_hstring *name;
77546 
77547 			tv1 = DUK__CONSTP_BC(ins);
77548 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
77549 			name = DUK_TVAL_GET_STRING(tv1);
77550 			DUK_ASSERT(name != NULL);
77551 			act = thr->callstack_curr;
77552 			DUK_ASSERT(act != NULL);
77553 			(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [... val this] */
77554 			duk_pop_unsafe(thr);  /* 'this' binding is not needed here */
77555 			DUK__REPLACE_TOP_A_BREAK();
77556 		}
77557 
77558 		case DUK_OP_PUTVAR: {
77559 			duk_activation *act;
77560 			duk_tval *tv1;
77561 			duk_hstring *name;
77562 
77563 			tv1 = DUK__CONSTP_BC(ins);
77564 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
77565 			name = DUK_TVAL_GET_STRING(tv1);
77566 			DUK_ASSERT(name != NULL);
77567 
77568 			/* XXX: putvar takes a duk_tval pointer, which is awkward and
77569 			 * should be reworked.
77570 			 */
77571 
77572 			tv1 = DUK__REGP_A(ins);  /* val */
77573 			act = thr->callstack_curr;
77574 			duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
77575 			break;
77576 		}
77577 
77578 		case DUK_OP_DELVAR: {
77579 			duk_activation *act;
77580 			duk_tval *tv1;
77581 			duk_hstring *name;
77582 			duk_bool_t rc;
77583 
77584 			tv1 = DUK__CONSTP_BC(ins);
77585 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
77586 			name = DUK_TVAL_GET_STRING(tv1);
77587 			DUK_ASSERT(name != NULL);
77588 			act = thr->callstack_curr;
77589 			rc = duk_js_delvar_activation(thr, act, name);
77590 			DUK__REPLACE_BOOL_A_BREAK(rc);
77591 		}
77592 
77593 		case DUK_OP_JUMP: {
77594 			/* Note: without explicit cast to signed, MSVC will
77595 			 * apparently generate a large positive jump when the
77596 			 * bias-corrected value would normally be negative.
77597 			 */
77598 			curr_pc += (duk_int_fast_t) DUK_DEC_ABC(ins) - (duk_int_fast_t) DUK_BC_JUMP_BIAS;
77599 			break;
77600 		}
77601 
77602 #define DUK__RETURN_SHARED() do { \
77603 		duk_small_uint_t ret_result; \
77604 		/* duk__handle_return() is guaranteed never to throw, except \
77605 		 * for potential out-of-memory situations which will then \
77606 		 * propagate out of the executor longjmp handler. \
77607 		 */ \
77608 		DUK_ASSERT(thr->ptr_curr_pc == NULL); \
77609 		ret_result = duk__handle_return(thr, entry_act); \
77610 		if (ret_result == DUK__RETHAND_RESTART) { \
77611 			goto restart_execution; \
77612 		} \
77613 		DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED); \
77614 		return; \
77615 	} while (0)
77616 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77617 		case DUK_OP_RETREG:
77618 		case DUK_OP_RETCONST:
77619 		case DUK_OP_RETCONSTN:
77620 		case DUK_OP_RETUNDEF: {
77621 			 /* BC -> return value reg/const */
77622 
77623 			DUK__SYNC_AND_NULL_CURR_PC();
77624 
77625 			if (op == DUK_OP_RETREG) {
77626 				duk_push_tval(thr, DUK__REGP_BC(ins));
77627 			} else if (op == DUK_OP_RETUNDEF) {
77628 				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */
77629 				thr->valstack_top++;
77630 			} else {
77631 				DUK_ASSERT(op == DUK_OP_RETCONST || op == DUK_OP_RETCONSTN);
77632 				duk_push_tval(thr, DUK__CONSTP_BC(ins));
77633 			}
77634 
77635 			DUK__RETURN_SHARED();
77636 		}
77637 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77638 		case DUK_OP_RETREG: {
77639 			duk_tval *tv;
77640 
77641 			DUK__SYNC_AND_NULL_CURR_PC();
77642 			tv = DUK__REGP_BC(ins);
77643 			DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
77644 			DUK_TVAL_INCREF(thr, tv);
77645 			thr->valstack_top++;
77646 			DUK__RETURN_SHARED();
77647 		}
77648 		/* This will be unused without refcounting. */
77649 		case DUK_OP_RETCONST: {
77650 			duk_tval *tv;
77651 
77652 			DUK__SYNC_AND_NULL_CURR_PC();
77653 			tv = DUK__CONSTP_BC(ins);
77654 			DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
77655 			DUK_TVAL_INCREF(thr, tv);
77656 			thr->valstack_top++;
77657 			DUK__RETURN_SHARED();
77658 		}
77659 		case DUK_OP_RETCONSTN: {
77660 			duk_tval *tv;
77661 
77662 			DUK__SYNC_AND_NULL_CURR_PC();
77663 			tv = DUK__CONSTP_BC(ins);
77664 			DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
77665 #if defined(DUK_USE_REFERENCE_COUNTING)
77666 			/* Without refcounting only RETCONSTN is used. */
77667 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv));  /* no INCREF for this constant */
77668 #endif
77669 			thr->valstack_top++;
77670 			DUK__RETURN_SHARED();
77671 		}
77672 		case DUK_OP_RETUNDEF: {
77673 			DUK__SYNC_AND_NULL_CURR_PC();
77674 			thr->valstack_top++;  /* value at valstack top is already undefined by valstack policy */
77675 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
77676 			DUK__RETURN_SHARED();
77677 		}
77678 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77679 
77680 		case DUK_OP_LABEL: {
77681 			duk_activation *act;
77682 			duk_catcher *cat;
77683 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
77684 
77685 			/* Allocate catcher and populate it (must be atomic). */
77686 
77687 			cat = duk_hthread_catcher_alloc(thr);
77688 			DUK_ASSERT(cat != NULL);
77689 
77690 			cat->flags = (duk_uint32_t) (DUK_CAT_TYPE_LABEL | (bc << DUK_CAT_LABEL_SHIFT));
77691 			cat->pc_base = (duk_instr_t *) curr_pc;  /* pre-incremented, points to first jump slot */
77692 			cat->idx_base = 0;  /* unused for label */
77693 			cat->h_varname = NULL;
77694 
77695 			act = thr->callstack_curr;
77696 			DUK_ASSERT(act != NULL);
77697 			cat->parent = act->cat;
77698 			act->cat = cat;
77699 
77700 			DUK_DDD(DUK_DDDPRINT("LABEL catcher: flags=0x%08lx, pc_base=%ld, "
77701 			                     "idx_base=%ld, h_varname=%!O, label_id=%ld",
77702 			                     (long) cat->flags, (long) cat->pc_base,
77703 			                     (long) cat->idx_base, (duk_heaphdr *) cat->h_varname, (long) DUK_CAT_GET_LABEL(cat)));
77704 
77705 			curr_pc += 2;  /* skip jump slots */
77706 			break;
77707 		}
77708 
77709 		case DUK_OP_ENDLABEL: {
77710 			duk_activation *act;
77711 #if (defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)) || defined(DUK_USE_ASSERTIONS)
77712 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
77713 #endif
77714 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
77715 			DUK_DDD(DUK_DDDPRINT("ENDLABEL %ld", (long) bc));
77716 #endif
77717 
77718 			act = thr->callstack_curr;
77719 			DUK_ASSERT(act->cat != NULL);
77720 			DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_LABEL);
77721 			DUK_ASSERT((duk_uint_fast_t) DUK_CAT_GET_LABEL(act->cat) == bc);
77722 			duk_hthread_catcher_unwind_nolexenv_norz(thr, act);
77723 
77724 			/* no need to unwind callstack */
77725 			break;
77726 		}
77727 
77728 		case DUK_OP_BREAK: {
77729 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
77730 
77731 			DUK__SYNC_AND_NULL_CURR_PC();
77732 			duk__handle_break_or_continue(thr, (duk_uint_t) bc, DUK_LJ_TYPE_BREAK);
77733 			goto restart_execution;
77734 		}
77735 
77736 		case DUK_OP_CONTINUE: {
77737 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
77738 
77739 			DUK__SYNC_AND_NULL_CURR_PC();
77740 			duk__handle_break_or_continue(thr, (duk_uint_t) bc, DUK_LJ_TYPE_CONTINUE);
77741 			goto restart_execution;
77742 		}
77743 
77744 		/* XXX: move to helper, too large to be inline here */
77745 		case DUK_OP_TRYCATCH: {
77746 			duk__handle_op_trycatch(thr, ins, curr_pc);
77747 			curr_pc += 2;  /* skip jump slots */
77748 			break;
77749 		}
77750 
77751 		case DUK_OP_ENDTRY: {
77752 			curr_pc = duk__handle_op_endtry(thr, ins);
77753 			break;
77754 		}
77755 
77756 		case DUK_OP_ENDCATCH: {
77757 			duk__handle_op_endcatch(thr, ins);
77758 			break;
77759 		}
77760 
77761 		case DUK_OP_ENDFIN: {
77762 			/* Sync and NULL early. */
77763 			DUK__SYNC_AND_NULL_CURR_PC();
77764 
77765 			if (duk__handle_op_endfin(thr, ins, entry_act) != 0) {
77766 				return;
77767 			}
77768 
77769 			/* Must restart because we NULLed out curr_pc. */
77770 			goto restart_execution;
77771 		}
77772 
77773 		case DUK_OP_THROW: {
77774 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
77775 
77776 			/* Note: errors are augmented when they are created, not
77777 			 * when they are thrown.  So, don't augment here, it would
77778 			 * break re-throwing for instance.
77779 			 */
77780 
77781 			/* Sync so that augmentation sees up-to-date activations, NULL
77782 			 * thr->ptr_curr_pc so that it's not used if side effects occur
77783 			 * in augmentation or longjmp handling.
77784 			 */
77785 			DUK__SYNC_AND_NULL_CURR_PC();
77786 
77787 			duk_dup(thr, (duk_idx_t) bc);
77788 			DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (before throw augment)",
77789 			                     (duk_tval *) duk_get_tval(thr, -1)));
77790 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
77791 			duk_err_augment_error_throw(thr);
77792 			DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (after throw augment)",
77793 			                     (duk_tval *) duk_get_tval(thr, -1)));
77794 #endif
77795 
77796 			duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, DUK_GET_TVAL_NEGIDX(thr, -1));
77797 #if defined(DUK_USE_DEBUGGER_SUPPORT)
77798 			duk_err_check_debugger_integration(thr);
77799 #endif
77800 
77801 			DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* always in executor */
77802 			duk_err_longjmp(thr);
77803 			DUK_UNREACHABLE();
77804 			break;
77805 		}
77806 
77807 		case DUK_OP_CSREG: {
77808 			/*
77809 			 *  Assuming a register binds to a variable declared within this
77810 			 *  function (a declarative binding), the 'this' for the call
77811 			 *  setup is always 'undefined'.  E5 Section 10.2.1.1.6.
77812 			 */
77813 
77814 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
77815 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
77816 
77817 			/* A -> register containing target function (not type checked here)
77818 			 * BC -> target registers (BC, BC + 1) for call setup
77819 			 */
77820 
77821 #if defined(DUK_USE_PREFER_SIZE)
77822 			duk_dup(thr, (duk_idx_t) a);
77823 			duk_replace(thr, (duk_idx_t) bc);
77824 			duk_to_undefined(thr, (duk_idx_t) (bc + 1));
77825 #else
77826 			duk_tval *tv1;
77827 			duk_tval *tv2;
77828 			duk_tval *tv3;
77829 			duk_tval tv_tmp1;
77830 			duk_tval tv_tmp2;
77831 
77832 			tv1 = DUK__REGP(bc);
77833 			tv2 = tv1 + 1;
77834 			DUK_TVAL_SET_TVAL(&tv_tmp1, tv1);
77835 			DUK_TVAL_SET_TVAL(&tv_tmp2, tv2);
77836 			tv3 = DUK__REGP(a);
77837 			DUK_TVAL_SET_TVAL(tv1, tv3);
77838 			DUK_TVAL_INCREF(thr, tv1);  /* no side effects */
77839 			DUK_TVAL_SET_UNDEFINED(tv2);  /* no need for incref */
77840 			DUK_TVAL_DECREF(thr, &tv_tmp1);
77841 			DUK_TVAL_DECREF(thr, &tv_tmp2);
77842 #endif
77843 			break;
77844 		}
77845 
77846 
77847 		/* XXX: in some cases it's faster NOT to reuse the value
77848 		 * stack but rather copy the arguments on top of the stack
77849 		 * (mainly when the calling value stack is large and the value
77850 		 * stack resize would be large).
77851 		 */
77852 
77853 		case DUK_OP_CALL0:
77854 		case DUK_OP_CALL1:
77855 		case DUK_OP_CALL2:
77856 		case DUK_OP_CALL3:
77857 		case DUK_OP_CALL4:
77858 		case DUK_OP_CALL5:
77859 		case DUK_OP_CALL6:
77860 		case DUK_OP_CALL7: {
77861 			/* Opcode packs 4 flag bits: 1 for indirect, 3 map
77862 			 * 1:1 to three lowest call handling flags.
77863 			 *
77864 			 * A -> nargs or register with nargs (indirect)
77865 			 * BC -> base register for call (base -> func, base+1 -> this, base+2 -> arg1 ... base+2+N-1 -> argN)
77866 			 */
77867 
77868 			duk_idx_t nargs;
77869 			duk_idx_t idx;
77870 			duk_small_uint_t call_flags;
77871 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
77872 			duk_hcompfunc *fun;
77873 #endif
77874 
77875 			DUK_ASSERT((DUK_OP_CALL0 & 0x0fU) == 0);
77876 			DUK_ASSERT((ins & DUK_BC_CALL_FLAG_INDIRECT) == 0);
77877 
77878 			nargs = (duk_idx_t) DUK_DEC_A(ins);
77879 			call_flags = (ins & 0x07U) | DUK_CALL_FLAG_ALLOW_ECMATOECMA;
77880 			idx = (duk_idx_t) DUK_DEC_BC(ins);
77881 
77882 			if (duk__executor_handle_call(thr, idx, nargs, call_flags)) {
77883 				/* curr_pc synced by duk_handle_call_unprotected() */
77884 				DUK_ASSERT(thr->ptr_curr_pc == NULL);
77885 				goto restart_execution;
77886 			}
77887 			DUK_ASSERT(thr->ptr_curr_pc != NULL);
77888 
77889 			/* duk_js_call.c is required to restore the stack reserve
77890 			 * so we only need to reset the top.
77891 			 */
77892 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
77893 			fun = DUK__FUN();
77894 #endif
77895 			duk_set_top_unsafe(thr, (duk_idx_t) fun->nregs);
77896 
77897 			/* No need to reinit setjmp() catchpoint, as call handling
77898 			 * will store and restore our state.
77899 			 *
77900 			 * When debugger is enabled, we need to recheck the activation
77901 			 * status after returning.  This is now handled by call handling
77902 			 * and heap->dbg_force_restart.
77903 			 */
77904 			break;
77905 		}
77906 
77907 		case DUK_OP_CALL8:
77908 		case DUK_OP_CALL9:
77909 		case DUK_OP_CALL10:
77910 		case DUK_OP_CALL11:
77911 		case DUK_OP_CALL12:
77912 		case DUK_OP_CALL13:
77913 		case DUK_OP_CALL14:
77914 		case DUK_OP_CALL15: {
77915 			/* Indirect variant. */
77916 			duk_uint_fast_t nargs;
77917 			duk_idx_t idx;
77918 			duk_small_uint_t call_flags;
77919 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
77920 			duk_hcompfunc *fun;
77921 #endif
77922 
77923 			DUK_ASSERT((DUK_OP_CALL0 & 0x0fU) == 0);
77924 			DUK_ASSERT((ins & DUK_BC_CALL_FLAG_INDIRECT) != 0);
77925 
77926 			nargs = (duk_uint_fast_t) DUK_DEC_A(ins);
77927 			DUK__LOOKUP_INDIRECT(nargs);
77928 			call_flags = (ins & 0x07U) | DUK_CALL_FLAG_ALLOW_ECMATOECMA;
77929 			idx = (duk_idx_t) DUK_DEC_BC(ins);
77930 
77931 			if (duk__executor_handle_call(thr, idx, (duk_idx_t) nargs, call_flags)) {
77932 				DUK_ASSERT(thr->ptr_curr_pc == NULL);
77933 				goto restart_execution;
77934 			}
77935 			DUK_ASSERT(thr->ptr_curr_pc != NULL);
77936 
77937 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
77938 			fun = DUK__FUN();
77939 #endif
77940 			duk_set_top_unsafe(thr, (duk_idx_t) fun->nregs);
77941 			break;
77942 		}
77943 
77944 		case DUK_OP_NEWOBJ: {
77945 			duk_push_object(thr);
77946 #if defined(DUK_USE_ASSERTIONS)
77947 			{
77948 				duk_hobject *h;
77949 				h = duk_require_hobject(thr, -1);
77950 				DUK_ASSERT(DUK_HOBJECT_GET_ESIZE(h) == 0);
77951 				DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(h) == 0);
77952 				DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0);
77953 				DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(h) == 0);
77954 			}
77955 #endif
77956 #if !defined(DUK_USE_PREFER_SIZE)
77957 			/* XXX: could do a direct props realloc, but need hash size */
77958 			duk_hobject_resize_entrypart(thr, duk_known_hobject(thr, -1), DUK_DEC_A(ins));
77959 #endif
77960 			DUK__REPLACE_TOP_BC_BREAK();
77961 		}
77962 
77963 		case DUK_OP_NEWARR: {
77964 			duk_push_array(thr);
77965 #if defined(DUK_USE_ASSERTIONS)
77966 			{
77967 				duk_hobject *h;
77968 				h = duk_require_hobject(thr, -1);
77969 				DUK_ASSERT(DUK_HOBJECT_GET_ESIZE(h) == 0);
77970 				DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(h) == 0);
77971 				DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0);
77972 				DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(h) == 0);
77973 				DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(h));
77974 			}
77975 #endif
77976 #if !defined(DUK_USE_PREFER_SIZE)
77977 			duk_hobject_realloc_props(thr,
77978 			                          duk_known_hobject(thr, -1),
77979 			                          0 /*new_e_size*/,
77980 			                          DUK_DEC_A(ins) /*new_a_size*/,
77981 			                          0 /*new_h_size*/,
77982 			                          0 /*abandon_array*/);
77983 #if 0
77984 			duk_hobject_resize_arraypart(thr, duk_known_hobject(thr, -1), DUK_DEC_A(ins));
77985 #endif
77986 #endif
77987 			DUK__REPLACE_TOP_BC_BREAK();
77988 		}
77989 
77990 		case DUK_OP_MPUTOBJ:
77991 		case DUK_OP_MPUTOBJI: {
77992 			duk_idx_t obj_idx;
77993 			duk_uint_fast_t idx, idx_end;
77994 			duk_small_uint_fast_t count;
77995 
77996 			/* A -> register of target object
77997 			 * B -> first register of key/value pair list
77998 			 *      or register containing first register number if indirect
77999 			 * C -> number of key/value pairs * 2
78000 			 *      (= number of value stack indices used starting from 'B')
78001 			 */
78002 
78003 			obj_idx = DUK_DEC_A(ins);
78004 			DUK_ASSERT(duk_is_object(thr, obj_idx));
78005 
78006 			idx = (duk_uint_fast_t) DUK_DEC_B(ins);
78007 			if (DUK_DEC_OP(ins) == DUK_OP_MPUTOBJI) {
78008 				DUK__LOOKUP_INDIRECT(idx);
78009 			}
78010 
78011 			count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
78012 			DUK_ASSERT(count > 0);  /* compiler guarantees */
78013 			idx_end = idx + count;
78014 
78015 #if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
78016 			if (DUK_UNLIKELY(idx_end > (duk_uint_fast_t) duk_get_top(thr))) {
78017 				/* XXX: use duk_is_valid_index() instead? */
78018 				/* XXX: improve check; check against nregs, not against top */
78019 				DUK__INTERNAL_ERROR("MPUTOBJ out of bounds");
78020 			}
78021 #endif
78022 
78023 			/* Use 'force' flag to duk_def_prop() to ensure that any
78024 			 * inherited properties don't prevent the operation.
78025 			 * With ES2015 duplicate properties are allowed, so that we
78026 			 * must overwrite any previous data or accessor property.
78027 			 *
78028 			 * With ES2015 computed property names the literal keys
78029 			 * may be arbitrary values and need to be ToPropertyKey()
78030 			 * coerced at runtime.
78031 			 */
78032 			do {
78033 				/* XXX: faster initialization (direct access or better primitives) */
78034 				duk_dup(thr, (duk_idx_t) idx);
78035 				duk_dup(thr, (duk_idx_t) (idx + 1));
78036 				duk_def_prop(thr, obj_idx, DUK_DEFPROP_HAVE_VALUE |
78037 				                           DUK_DEFPROP_FORCE |
78038 				                           DUK_DEFPROP_SET_WRITABLE |
78039 				                           DUK_DEFPROP_SET_ENUMERABLE |
78040 				                           DUK_DEFPROP_SET_CONFIGURABLE);
78041 				idx += 2;
78042 			} while (idx < idx_end);
78043 			break;
78044 		}
78045 
78046 		case DUK_OP_INITSET:
78047 		case DUK_OP_INITGET: {
78048 			duk__handle_op_initset_initget(thr, ins);
78049 			break;
78050 		}
78051 
78052 		case DUK_OP_MPUTARR:
78053 		case DUK_OP_MPUTARRI: {
78054 			duk_idx_t obj_idx;
78055 			duk_uint_fast_t idx, idx_end;
78056 			duk_small_uint_fast_t count;
78057 			duk_tval *tv1;
78058 			duk_uint32_t arr_idx;
78059 
78060 			/* A -> register of target object
78061 			 * B -> first register of value data (start_index, value1, value2, ..., valueN)
78062 			 *      or register containing first register number if indirect
78063 			 * C -> number of key/value pairs (N)
78064 			 */
78065 
78066 			obj_idx = DUK_DEC_A(ins);
78067 			DUK_ASSERT(duk_is_object(thr, obj_idx));
78068 
78069 			idx = (duk_uint_fast_t) DUK_DEC_B(ins);
78070 			if (DUK_DEC_OP(ins) == DUK_OP_MPUTARRI) {
78071 				DUK__LOOKUP_INDIRECT(idx);
78072 			}
78073 
78074 			count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
78075 			DUK_ASSERT(count > 0 + 1);  /* compiler guarantees */
78076 			idx_end = idx + count;
78077 
78078 #if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
78079 			if (idx_end > (duk_uint_fast_t) duk_get_top(thr)) {
78080 				/* XXX: use duk_is_valid_index() instead? */
78081 				/* XXX: improve check; check against nregs, not against top */
78082 				DUK__INTERNAL_ERROR("MPUTARR out of bounds");
78083 			}
78084 #endif
78085 
78086 			tv1 = DUK__REGP(idx);
78087 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
78088 #if defined(DUK_USE_FASTINT)
78089 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
78090 			arr_idx = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv1);
78091 #else
78092 			arr_idx = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
78093 #endif
78094 			idx++;
78095 
78096 			do {
78097 				/* duk_xdef_prop() will define an own property without any array
78098 				 * special behaviors.  We'll need to set the array length explicitly
78099 				 * in the end.  For arrays with elisions, the compiler will emit an
78100 				 * explicit SETALEN which will update the length.
78101 				 */
78102 
78103 				/* XXX: because we're dealing with 'own' properties of a fresh array,
78104 				 * the array initializer should just ensure that the array has a large
78105 				 * enough array part and write the values directly into array part,
78106 				 * and finally set 'length' manually in the end (as already happens now).
78107 				 */
78108 
78109 				duk_dup(thr, (duk_idx_t) idx);
78110 				duk_xdef_prop_index_wec(thr, obj_idx, arr_idx);
78111 
78112 				idx++;
78113 				arr_idx++;
78114 			} while (idx < idx_end);
78115 
78116 			/* XXX: E5.1 Section 11.1.4 coerces the final length through
78117 			 * ToUint32() which is odd but happens now as a side effect of
78118 			 * 'arr_idx' type.
78119 			 */
78120 			duk_set_length(thr, obj_idx, (duk_size_t) (duk_uarridx_t) arr_idx);
78121 			break;
78122 		}
78123 
78124 		case DUK_OP_SETALEN: {
78125 			duk_tval *tv1;
78126 			duk_hobject *h;
78127 			duk_uint32_t len;
78128 
78129 			tv1 = DUK__REGP_A(ins);
78130 			DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
78131 			h = DUK_TVAL_GET_OBJECT(tv1);
78132 			DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(h));
78133 
78134 			tv1 = DUK__REGP_BC(ins);
78135 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
78136 #if defined(DUK_USE_FASTINT)
78137 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
78138 			len = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv1);
78139 #else
78140 			len = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
78141 #endif
78142 			((duk_harray *) h)->length = len;
78143 			break;
78144 		}
78145 
78146 		case DUK_OP_INITENUM: {
78147 			duk__handle_op_initenum(thr, ins);
78148 			break;
78149 		}
78150 
78151 		case DUK_OP_NEXTENUM: {
78152 			curr_pc += duk__handle_op_nextenum(thr, ins);
78153 			break;
78154 		}
78155 
78156 		case DUK_OP_INVLHS: {
78157 			DUK_ERROR_REFERENCE(thr, DUK_STR_INVALID_LVALUE);
78158 			DUK_WO_NORETURN(return;);
78159 			break;
78160 		}
78161 
78162 		case DUK_OP_DEBUGGER: {
78163 			/* Opcode only emitted by compiler when debugger
78164 			 * support is enabled.  Ignore it silently without
78165 			 * debugger support, in case it has been loaded
78166 			 * from precompiled bytecode.
78167 			 */
78168 #if defined(DUK_USE_DEBUGGER_SUPPORT)
78169 			if (duk_debug_is_attached(thr->heap)) {
78170 				DUK_D(DUK_DPRINT("DEBUGGER statement encountered, halt execution"));
78171 				DUK__SYNC_AND_NULL_CURR_PC();
78172 				duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
78173 				DUK_D(DUK_DPRINT("DEBUGGER statement finished, resume execution"));
78174 				goto restart_execution;
78175 			} else {
78176 				DUK_D(DUK_DPRINT("DEBUGGER statement ignored, debugger not attached"));
78177 			}
78178 #else
78179 			DUK_D(DUK_DPRINT("DEBUGGER statement ignored, no debugger support"));
78180 #endif
78181 			break;
78182 		}
78183 
78184 		case DUK_OP_NOP: {
78185 			/* Nop, ignored, but ABC fields may carry a value e.g.
78186 			 * for indirect opcode handling.
78187 			 */
78188 			break;
78189 		}
78190 
78191 		case DUK_OP_INVALID: {
78192 			DUK_ERROR_FMT1(thr, DUK_ERR_ERROR, "INVALID opcode (%ld)", (long) DUK_DEC_ABC(ins));
78193 			DUK_WO_NORETURN(return;);
78194 			break;
78195 		}
78196 
78197 #if defined(DUK_USE_ES6)
78198 		case DUK_OP_NEWTARGET: {
78199 			duk_push_new_target(thr);
78200 			DUK__REPLACE_TOP_BC_BREAK();
78201 		}
78202 #endif  /* DUK_USE_ES6 */
78203 
78204 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
78205 #if !defined(DUK_USE_ES7_EXP_OPERATOR)
78206 		case DUK_OP_EXP_RR:
78207 		case DUK_OP_EXP_CR:
78208 		case DUK_OP_EXP_RC:
78209 		case DUK_OP_EXP_CC:
78210 #endif
78211 #if !defined(DUK_USE_ES6)
78212 		case DUK_OP_NEWTARGET:
78213 #endif
78214 #if !defined(DUK_USE_VERBOSE_ERRORS)
78215 		case DUK_OP_GETPROPC_RR:
78216 		case DUK_OP_GETPROPC_CR:
78217 		case DUK_OP_GETPROPC_RC:
78218 		case DUK_OP_GETPROPC_CC:
78219 #endif
78220 		case DUK_OP_UNUSED207:
78221 		case DUK_OP_UNUSED212:
78222 		case DUK_OP_UNUSED213:
78223 		case DUK_OP_UNUSED214:
78224 		case DUK_OP_UNUSED215:
78225 		case DUK_OP_UNUSED216:
78226 		case DUK_OP_UNUSED217:
78227 		case DUK_OP_UNUSED218:
78228 		case DUK_OP_UNUSED219:
78229 		case DUK_OP_UNUSED220:
78230 		case DUK_OP_UNUSED221:
78231 		case DUK_OP_UNUSED222:
78232 		case DUK_OP_UNUSED223:
78233 		case DUK_OP_UNUSED224:
78234 		case DUK_OP_UNUSED225:
78235 		case DUK_OP_UNUSED226:
78236 		case DUK_OP_UNUSED227:
78237 		case DUK_OP_UNUSED228:
78238 		case DUK_OP_UNUSED229:
78239 		case DUK_OP_UNUSED230:
78240 		case DUK_OP_UNUSED231:
78241 		case DUK_OP_UNUSED232:
78242 		case DUK_OP_UNUSED233:
78243 		case DUK_OP_UNUSED234:
78244 		case DUK_OP_UNUSED235:
78245 		case DUK_OP_UNUSED236:
78246 		case DUK_OP_UNUSED237:
78247 		case DUK_OP_UNUSED238:
78248 		case DUK_OP_UNUSED239:
78249 		case DUK_OP_UNUSED240:
78250 		case DUK_OP_UNUSED241:
78251 		case DUK_OP_UNUSED242:
78252 		case DUK_OP_UNUSED243:
78253 		case DUK_OP_UNUSED244:
78254 		case DUK_OP_UNUSED245:
78255 		case DUK_OP_UNUSED246:
78256 		case DUK_OP_UNUSED247:
78257 		case DUK_OP_UNUSED248:
78258 		case DUK_OP_UNUSED249:
78259 		case DUK_OP_UNUSED250:
78260 		case DUK_OP_UNUSED251:
78261 		case DUK_OP_UNUSED252:
78262 		case DUK_OP_UNUSED253:
78263 		case DUK_OP_UNUSED254:
78264 		case DUK_OP_UNUSED255:
78265 		/* Force all case clauses to map to an actual handler
78266 		 * so that the compiler can emit a jump without a bounds
78267 		 * check: the switch argument is a duk_uint8_t so that
78268 		 * the compiler may be able to figure it out.  This is
78269 		 * a small detail and obviously compiler dependent.
78270 		 */
78271 		/* default: clause omitted on purpose */
78272 #else  /* DUK_USE_EXEC_PREFER_SIZE */
78273 		default:
78274 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
78275 		{
78276 			/* Default case catches invalid/unsupported opcodes. */
78277 			DUK_D(DUK_DPRINT("invalid opcode: %ld - %!I", (long) op, ins));
78278 			DUK__INTERNAL_ERROR("invalid opcode");
78279 			break;
78280 		}
78281 
78282 		}  /* end switch */
78283 
78284 		continue;
78285 
78286 		/* Some shared exit paths for opcode handling below.  These
78287 		 * are mostly useful to reduce code footprint when multiple
78288 		 * opcodes have a similar epilogue (like replacing stack top
78289 		 * with index 'a').
78290 		 */
78291 
78292 #if defined(DUK_USE_EXEC_PREFER_SIZE)
78293 	 replace_top_a:
78294 		DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_A(ins));
78295 		continue;
78296 	 replace_top_bc:
78297 		DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_BC(ins));
78298 		continue;
78299 #endif
78300 	}
78301 	DUK_WO_NORETURN(return;);
78302 
78303 #if !defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS)
78304  internal_error:
78305 	DUK_ERROR_INTERNAL(thr);
78306 	DUK_WO_NORETURN(return;);
78307 #endif
78308 }
78309 
78310 /* automatic undefs */
78311 #undef DUK__BYTEOFF_A
78312 #undef DUK__BYTEOFF_B
78313 #undef DUK__BYTEOFF_BC
78314 #undef DUK__BYTEOFF_C
78315 #undef DUK__COMPARE_BODY
78316 #undef DUK__CONST
78317 #undef DUK__CONSTP
78318 #undef DUK__CONSTP_A
78319 #undef DUK__CONSTP_B
78320 #undef DUK__CONSTP_BC
78321 #undef DUK__CONSTP_C
78322 #undef DUK__DELPROP_BODY
78323 #undef DUK__EQ_BODY
78324 #undef DUK__FUN
78325 #undef DUK__GETPROPC_BODY
78326 #undef DUK__GETPROP_BODY
78327 #undef DUK__GE_BODY
78328 #undef DUK__GT_BODY
78329 #undef DUK__INLINE_PERF
78330 #undef DUK__INSTOF_BODY
78331 #undef DUK__INTERNAL_ERROR
78332 #undef DUK__INT_NOACTION
78333 #undef DUK__INT_RESTART
78334 #undef DUK__IN_BODY
78335 #undef DUK__LE_BODY
78336 #undef DUK__LONGJMP_RESTART
78337 #undef DUK__LONGJMP_RETHROW
78338 #undef DUK__LOOKUP_INDIRECT
78339 #undef DUK__LT_BODY
78340 #undef DUK__MASK_A
78341 #undef DUK__MASK_B
78342 #undef DUK__MASK_BC
78343 #undef DUK__MASK_C
78344 #undef DUK__NEQ_BODY
78345 #undef DUK__NOINLINE_PERF
78346 #undef DUK__PUTPROP_BODY
78347 #undef DUK__RCBIT_B
78348 #undef DUK__RCBIT_C
78349 #undef DUK__REG
78350 #undef DUK__REGCONSTP_B
78351 #undef DUK__REGCONSTP_C
78352 #undef DUK__REGP
78353 #undef DUK__REGP_A
78354 #undef DUK__REGP_B
78355 #undef DUK__REGP_BC
78356 #undef DUK__REGP_C
78357 #undef DUK__REPLACE_BOOL_A_BREAK
78358 #undef DUK__REPLACE_TOP_A_BREAK
78359 #undef DUK__REPLACE_TOP_BC_BREAK
78360 #undef DUK__REPLACE_TO_TVPTR
78361 #undef DUK__RETHAND_FINISHED
78362 #undef DUK__RETHAND_RESTART
78363 #undef DUK__RETURN_SHARED
78364 #undef DUK__SEQ_BODY
78365 #undef DUK__SHIFT_A
78366 #undef DUK__SHIFT_B
78367 #undef DUK__SHIFT_BC
78368 #undef DUK__SHIFT_C
78369 #undef DUK__SNEQ_BODY
78370 #undef DUK__STRICT
78371 #undef DUK__SYNC_AND_NULL_CURR_PC
78372 #undef DUK__SYNC_CURR_PC
78373 #undef DUK__TVAL_SHIFT
78374 #line 1 "duk_js_ops.c"
78375 /*
78376  *  ECMAScript specification algorithm and conversion helpers.
78377  *
78378  *  These helpers encapsulate the primitive ECMAScript operation semantics,
78379  *  and are used by the bytecode executor and the API (among other places).
78380  *  Some primitives are only implemented as part of the API and have no
78381  *  "internal" helper.  This is the case when an internal helper would not
78382  *  really be useful; e.g. the operation is rare, uses value stack heavily,
78383  *  etc.
78384  *
78385  *  The operation arguments depend on what is required to implement
78386  *  the operation:
78387  *
78388  *    - If an operation is simple and stateless, and has no side
78389  *      effects, it won't take an duk_hthread argument and its
78390  *      arguments may be duk_tval pointers (which are safe as long
78391  *      as no side effects take place).
78392  *
78393  *    - If complex coercions are required (e.g. a "ToNumber" coercion)
78394  *      or errors may be thrown, the operation takes an duk_hthread
78395  *      argument.  This also implies that the operation may have
78396  *      arbitrary side effects, invalidating any duk_tval pointers.
78397  *
78398  *    - For operations with potential side effects, arguments can be
78399  *      taken in several ways:
78400  *
78401  *      a) as duk_tval pointers, which makes sense if the "common case"
78402  *         can be resolved without side effects (e.g. coercion); the
78403  *         arguments are pushed to the valstack for coercion if
78404  *         necessary
78405  *
78406  *      b) as duk_tval values
78407  *
78408  *      c) implicitly on value stack top
78409  *
78410  *      d) as indices to the value stack
78411  *
78412  *  Future work:
78413  *
78414  *     - Argument styles may not be the most sensible in every case now.
78415  *
78416  *     - In-place coercions might be useful for several operations, if
78417  *       in-place coercion is OK for the bytecode executor and the API.
78418  */
78419 
78420 /* #include duk_internal.h -> already included */
78421 
78422 /*
78423  *  ToPrimitive()  (E5 Section 9.1)
78424  *
78425  *  ==> implemented in the API.
78426  */
78427 
78428 /*
78429  *  ToBoolean()  (E5 Section 9.2)
78430  */
78431 
78432 DUK_INTERNAL duk_bool_t duk_js_toboolean(duk_tval *tv) {
78433 	switch (DUK_TVAL_GET_TAG(tv)) {
78434 	case DUK_TAG_UNDEFINED:
78435 	case DUK_TAG_NULL:
78436 		return 0;
78437 	case DUK_TAG_BOOLEAN:
78438 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 || DUK_TVAL_GET_BOOLEAN(tv) == 1);
78439 		return DUK_TVAL_GET_BOOLEAN(tv);
78440 	case DUK_TAG_STRING: {
78441 		/* Symbols ToBoolean() coerce to true, regardless of their
78442 		 * description.  This happens with no explicit check because
78443 		 * of the symbol representation byte prefix.
78444 		 */
78445 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
78446 		DUK_ASSERT(h != NULL);
78447 		return (DUK_HSTRING_GET_BYTELEN(h) > 0 ? 1 : 0);
78448 	}
78449 	case DUK_TAG_OBJECT: {
78450 		return 1;
78451 	}
78452 	case DUK_TAG_BUFFER: {
78453 		/* Mimic Uint8Array semantics: objects coerce true, regardless
78454 		 * of buffer length (zero or not) or context.
78455 		 */
78456 		return 1;
78457 	}
78458 	case DUK_TAG_POINTER: {
78459 		void *p = DUK_TVAL_GET_POINTER(tv);
78460 		return (p != NULL ? 1 : 0);
78461 	}
78462 	case DUK_TAG_LIGHTFUNC: {
78463 		return 1;
78464 	}
78465 #if defined(DUK_USE_FASTINT)
78466 	case DUK_TAG_FASTINT:
78467 		if (DUK_TVAL_GET_FASTINT(tv) != 0) {
78468 			return 1;
78469 		} else {
78470 			return 0;
78471 		}
78472 #endif
78473 	default: {
78474 		/* number */
78475 		duk_double_t d;
78476 #if defined(DUK_USE_PREFER_SIZE)
78477 		int c;
78478 #endif
78479 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
78480 		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
78481 		d = DUK_TVAL_GET_DOUBLE(tv);
78482 #if defined(DUK_USE_PREFER_SIZE)
78483 		c = DUK_FPCLASSIFY((double) d);
78484 		if (c == DUK_FP_ZERO || c == DUK_FP_NAN) {
78485 			return 0;
78486 		} else {
78487 			return 1;
78488 		}
78489 #else
78490 		DUK_ASSERT(duk_double_is_nan_or_zero(d) == 0 || duk_double_is_nan_or_zero(d) == 1);
78491 		return duk_double_is_nan_or_zero(d) ^ 1;
78492 #endif
78493 	}
78494 	}
78495 	DUK_UNREACHABLE();
78496 }
78497 
78498 /*
78499  *  ToNumber()  (E5 Section 9.3)
78500  *
78501  *  Value to convert must be on stack top, and is popped before exit.
78502  *
78503  *  See: http://www.cs.indiana.edu/~burger/FP-Printing-PLDI96.pdf
78504  *       http://www.cs.indiana.edu/~burger/fp/index.html
78505  *
78506  *  Notes on the conversion:
78507  *
78508  *    - There are specific requirements on the accuracy of the conversion
78509  *      through a "Mathematical Value" (MV), so this conversion is not
78510  *      trivial.
78511  *
78512  *    - Quick rejects (e.g. based on first char) are difficult because
78513  *      the grammar allows leading and trailing white space.
78514  *
78515  *    - Quick reject based on string length is difficult even after
78516  *      accounting for white space; there may be arbitrarily many
78517  *      decimal digits.
78518  *
78519  *    - Standard grammar allows decimal values ("123"), hex values
78520  *      ("0x123") and infinities
78521  *
78522  *    - Unlike source code literals, ToNumber() coerces empty strings
78523  *      and strings with only whitespace to zero (not NaN).
78524  */
78525 
78526 /* E5 Section 9.3.1 */
78527 DUK_LOCAL duk_double_t duk__tonumber_string_raw(duk_hthread *thr) {
78528 	duk_small_uint_t s2n_flags;
78529 	duk_double_t d;
78530 
78531 	DUK_ASSERT(duk_is_string(thr, -1));
78532 
78533 	/* Quite lenient, e.g. allow empty as zero, but don't allow trailing
78534 	 * garbage.
78535 	 */
78536 	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
78537 	            DUK_S2N_FLAG_ALLOW_EXP |
78538 	            DUK_S2N_FLAG_ALLOW_PLUS |
78539 	            DUK_S2N_FLAG_ALLOW_MINUS |
78540 	            DUK_S2N_FLAG_ALLOW_INF |
78541 	            DUK_S2N_FLAG_ALLOW_FRAC |
78542 	            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
78543 	            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
78544 	            DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO |
78545 	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
78546 	            DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT |
78547 	            DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT |
78548 	            DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT;
78549 
78550 	duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
78551 
78552 #if defined(DUK_USE_PREFER_SIZE)
78553 	d = duk_get_number(thr, -1);
78554 	duk_pop_unsafe(thr);
78555 #else
78556 	thr->valstack_top--;
78557 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(thr->valstack_top));
78558 	DUK_ASSERT(DUK_TVAL_IS_DOUBLE(thr->valstack_top));  /* no fastint conversion in numconv now */
78559 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(thr->valstack_top));
78560 	d = DUK_TVAL_GET_DOUBLE(thr->valstack_top);  /* assumes not a fastint */
78561 	DUK_TVAL_SET_UNDEFINED(thr->valstack_top);
78562 #endif
78563 
78564 	return d;
78565 }
78566 
78567 DUK_INTERNAL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv) {
78568 	DUK_ASSERT(thr != NULL);
78569 	DUK_ASSERT(tv != NULL);
78570 
78571 	switch (DUK_TVAL_GET_TAG(tv)) {
78572 	case DUK_TAG_UNDEFINED: {
78573 		/* return a specific NaN (although not strictly necessary) */
78574 		duk_double_union du;
78575 		DUK_DBLUNION_SET_NAN(&du);
78576 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
78577 		return du.d;
78578 	}
78579 	case DUK_TAG_NULL: {
78580 		/* +0.0 */
78581 		return 0.0;
78582 	}
78583 	case DUK_TAG_BOOLEAN: {
78584 		if (DUK_TVAL_IS_BOOLEAN_TRUE(tv)) {
78585 			return 1.0;
78586 		}
78587 		return 0.0;
78588 	}
78589 	case DUK_TAG_STRING: {
78590 		/* For Symbols ToNumber() is always a TypeError. */
78591 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
78592 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
78593 			DUK_ERROR_TYPE(thr, DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL);
78594 			DUK_WO_NORETURN(return 0.0;);
78595 		}
78596 		duk_push_hstring(thr, h);
78597 		return duk__tonumber_string_raw(thr);
78598 	}
78599 	case DUK_TAG_BUFFER:  /* plain buffer treated like object */
78600 	case DUK_TAG_OBJECT: {
78601 		duk_double_t d;
78602 		duk_push_tval(thr, tv);
78603 		duk_to_primitive(thr, -1, DUK_HINT_NUMBER);  /* 'tv' becomes invalid */
78604 
78605 		/* recursive call for a primitive value (guaranteed not to cause second
78606 		 * recursion).
78607 		 */
78608 		DUK_ASSERT(duk_get_tval(thr, -1) != NULL);
78609 		d = duk_js_tonumber(thr, duk_get_tval(thr, -1));
78610 
78611 		duk_pop_unsafe(thr);
78612 		return d;
78613 	}
78614 	case DUK_TAG_POINTER: {
78615 		/* Coerce like boolean */
78616 		void *p = DUK_TVAL_GET_POINTER(tv);
78617 		return (p != NULL ? 1.0 : 0.0);
78618 	}
78619 	case DUK_TAG_LIGHTFUNC: {
78620 		/* +(function(){}) -> NaN */
78621 		return DUK_DOUBLE_NAN;
78622 	}
78623 #if defined(DUK_USE_FASTINT)
78624 	case DUK_TAG_FASTINT:
78625 		return (duk_double_t) DUK_TVAL_GET_FASTINT(tv);
78626 #endif
78627 	default: {
78628 		/* number */
78629 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
78630 		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
78631 		return DUK_TVAL_GET_DOUBLE(tv);
78632 	}
78633 	}
78634 
78635 	DUK_UNREACHABLE();
78636 }
78637 
78638 /*
78639  *  ToInteger()  (E5 Section 9.4)
78640  */
78641 
78642 /* exposed, used by e.g. duk_bi_date.c */
78643 DUK_INTERNAL duk_double_t duk_js_tointeger_number(duk_double_t x) {
78644 #if defined(DUK_USE_PREFER_SIZE)
78645 	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
78646 
78647 	if (DUK_UNLIKELY(c == DUK_FP_NAN)) {
78648 		return 0.0;
78649 	} else if (DUK_UNLIKELY(c == DUK_FP_INFINITE)) {
78650 		return x;
78651 	} else {
78652 		/* Finite, including neg/pos zero.  Neg zero sign must be
78653 		 * preserved.
78654 		 */
78655 		return duk_double_trunc_towards_zero(x);
78656 	}
78657 #else  /* DUK_USE_PREFER_SIZE */
78658 	/* NaN and Infinity have the same exponent so it's a cheap
78659 	 * initial check for the rare path.
78660 	 */
78661 	if (DUK_UNLIKELY(duk_double_is_nan_or_inf(x) != 0U)) {
78662 		if (duk_double_is_nan(x)) {
78663 			return 0.0;
78664 		} else {
78665 			return x;
78666 		}
78667 	} else {
78668 		return duk_double_trunc_towards_zero(x);
78669 	}
78670 #endif  /* DUK_USE_PREFER_SIZE */
78671 }
78672 
78673 DUK_INTERNAL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv) {
78674 	/* XXX: fastint */
78675 	duk_double_t d = duk_js_tonumber(thr, tv);  /* invalidates tv */
78676 	return duk_js_tointeger_number(d);
78677 }
78678 
78679 /*
78680  *  ToInt32(), ToUint32(), ToUint16()  (E5 Sections 9.5, 9.6, 9.7)
78681  */
78682 
78683 /* combined algorithm matching E5 Sections 9.5 and 9.6 */
78684 DUK_LOCAL duk_double_t duk__toint32_touint32_helper(duk_double_t x, duk_bool_t is_toint32) {
78685 #if defined (DUK_USE_PREFER_SIZE)
78686 	duk_small_int_t c;
78687 #endif
78688 
78689 #if defined (DUK_USE_PREFER_SIZE)
78690 	c = (duk_small_int_t) DUK_FPCLASSIFY(x);
78691 	if (c == DUK_FP_NAN || c == DUK_FP_ZERO || c == DUK_FP_INFINITE) {
78692 		return 0.0;
78693 	}
78694 #else
78695 	if (duk_double_is_nan_zero_inf(x)) {
78696 		return 0.0;
78697 	}
78698 #endif
78699 
78700 	/* x = sign(x) * floor(abs(x)), i.e. truncate towards zero, keep sign */
78701 	x = duk_double_trunc_towards_zero(x);
78702 
78703 	/* NOTE: fmod(x) result sign is same as sign of x, which
78704 	 * differs from what Javascript wants (see Section 9.6).
78705 	 */
78706 
78707 	x = DUK_FMOD(x, DUK_DOUBLE_2TO32);    /* -> x in ]-2**32, 2**32[ */
78708 
78709 	if (x < 0.0) {
78710 		x += DUK_DOUBLE_2TO32;
78711 	}
78712 	DUK_ASSERT(x >= 0 && x < DUK_DOUBLE_2TO32);  /* -> x in [0, 2**32[ */
78713 
78714 	if (is_toint32) {
78715 		if (x >= DUK_DOUBLE_2TO31) {
78716 			/* x in [2**31, 2**32[ */
78717 
78718 			x -= DUK_DOUBLE_2TO32;  /* -> x in [-2**31,2**31[ */
78719 		}
78720 	}
78721 
78722 	return x;
78723 }
78724 
78725 DUK_INTERNAL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv) {
78726 	duk_double_t d;
78727 
78728 #if defined(DUK_USE_FASTINT)
78729 	if (DUK_TVAL_IS_FASTINT(tv)) {
78730 		return DUK_TVAL_GET_FASTINT_I32(tv);
78731 	}
78732 #endif
78733 
78734 	d = duk_js_tonumber(thr, tv);  /* invalidates tv */
78735 	d = duk__toint32_touint32_helper(d, 1);
78736 	DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);
78737 	DUK_ASSERT(d >= -2147483648.0 && d <= 2147483647.0);  /* [-0x80000000,0x7fffffff] */
78738 	DUK_ASSERT(d == ((duk_double_t) ((duk_int32_t) d)));  /* whole, won't clip */
78739 	return (duk_int32_t) d;
78740 }
78741 
78742 
78743 DUK_INTERNAL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv) {
78744 	duk_double_t d;
78745 
78746 #if defined(DUK_USE_FASTINT)
78747 	if (DUK_TVAL_IS_FASTINT(tv)) {
78748 		return DUK_TVAL_GET_FASTINT_U32(tv);
78749 	}
78750 #endif
78751 
78752 	d = duk_js_tonumber(thr, tv);  /* invalidates tv */
78753 	d = duk__toint32_touint32_helper(d, 0);
78754 	DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);
78755 	DUK_ASSERT(d >= 0.0 && d <= 4294967295.0);  /* [0x00000000, 0xffffffff] */
78756 	DUK_ASSERT(d == ((duk_double_t) ((duk_uint32_t) d)));  /* whole, won't clip */
78757 	return (duk_uint32_t) d;
78758 
78759 }
78760 
78761 DUK_INTERNAL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv) {
78762 	/* should be a safe way to compute this */
78763 	return (duk_uint16_t) (duk_js_touint32(thr, tv) & 0x0000ffffU);
78764 }
78765 
78766 /*
78767  *  ToString()  (E5 Section 9.8)
78768  *  ToObject()  (E5 Section 9.9)
78769  *  CheckObjectCoercible()  (E5 Section 9.10)
78770  *  IsCallable()  (E5 Section 9.11)
78771  *
78772  *  ==> implemented in the API.
78773  */
78774 
78775 /*
78776  *  Loose equality, strict equality, and SameValue (E5 Sections 11.9.1, 11.9.4,
78777  *  9.12).  These have much in common so they can share some helpers.
78778  *
78779  *  Future work notes:
78780  *
78781  *    - Current implementation (and spec definition) has recursion; this should
78782  *      be fixed if possible.
78783  *
78784  *    - String-to-number coercion should be possible without going through the
78785  *      value stack (and be more compact) if a shared helper is invoked.
78786  */
78787 
78788 /* Note that this is the same operation for strict and loose equality:
78789  *  - E5 Section 11.9.3, step 1.c (loose)
78790  *  - E5 Section 11.9.6, step 4 (strict)
78791  */
78792 
78793 DUK_LOCAL duk_bool_t duk__js_equals_number(duk_double_t x, duk_double_t y) {
78794 #if defined(DUK_USE_PARANOID_MATH)
78795 	/* Straightforward algorithm, makes fewer compiler assumptions. */
78796 	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
78797 	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
78798 	if (cx == DUK_FP_NAN || cy == DUK_FP_NAN) {
78799 		return 0;
78800 	}
78801 	if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
78802 		return 1;
78803 	}
78804 	if (x == y) {
78805 		return 1;
78806 	}
78807 	return 0;
78808 #else  /* DUK_USE_PARANOID_MATH */
78809 	/* Better equivalent algorithm.  If the compiler is compliant, C and
78810 	 * ECMAScript semantics are identical for this particular comparison.
78811 	 * In particular, NaNs must never compare equal and zeroes must compare
78812 	 * equal regardless of sign.  Could also use a macro, but this inlines
78813 	 * already nicely (no difference on gcc, for instance).
78814 	 */
78815 	if (x == y) {
78816 		/* IEEE requires that NaNs compare false */
78817 		DUK_ASSERT(DUK_FPCLASSIFY(x) != DUK_FP_NAN);
78818 		DUK_ASSERT(DUK_FPCLASSIFY(y) != DUK_FP_NAN);
78819 		return 1;
78820 	} else {
78821 		/* IEEE requires that zeros compare the same regardless
78822 		 * of their signed, so if both x and y are zeroes, they
78823 		 * are caught above.
78824 		 */
78825 		DUK_ASSERT(!(DUK_FPCLASSIFY(x) == DUK_FP_ZERO && DUK_FPCLASSIFY(y) == DUK_FP_ZERO));
78826 		return 0;
78827 	}
78828 #endif  /* DUK_USE_PARANOID_MATH */
78829 }
78830 
78831 DUK_LOCAL duk_bool_t duk__js_samevalue_number(duk_double_t x, duk_double_t y) {
78832 #if defined(DUK_USE_PARANOID_MATH)
78833 	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
78834 	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
78835 
78836 	if (cx == DUK_FP_NAN && cy == DUK_FP_NAN) {
78837 		/* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
78838 		return 1;
78839 	}
78840 	if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
78841 		/* Note: cannot assume that a non-zero return value of signbit() would
78842 		 * always be the same -- hence cannot (portably) use something like:
78843 		 *
78844 		 *     signbit(x) == signbit(y)
78845 		 */
78846 		duk_small_int_t sx = DUK_SIGNBIT(x) ? 1 : 0;
78847 		duk_small_int_t sy = DUK_SIGNBIT(y) ? 1 : 0;
78848 		return (sx == sy);
78849 	}
78850 
78851 	/* normal comparison; known:
78852 	 *   - both x and y are not NaNs (but one of them can be)
78853 	 *   - both x and y are not zero (but one of them can be)
78854 	 *   - x and y may be denormal or infinite
78855 	 */
78856 
78857 	return (x == y);
78858 #else  /* DUK_USE_PARANOID_MATH */
78859 	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
78860 	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
78861 
78862 	if (x == y) {
78863 		/* IEEE requires that NaNs compare false */
78864 		DUK_ASSERT(DUK_FPCLASSIFY(x) != DUK_FP_NAN);
78865 		DUK_ASSERT(DUK_FPCLASSIFY(y) != DUK_FP_NAN);
78866 
78867 		/* Using classification has smaller footprint than direct comparison. */
78868 		if (DUK_UNLIKELY(cx == DUK_FP_ZERO && cy == DUK_FP_ZERO)) {
78869 			/* Note: cannot assume that a non-zero return value of signbit() would
78870 			 * always be the same -- hence cannot (portably) use something like:
78871 			 *
78872 			 *     signbit(x) == signbit(y)
78873 			 */
78874 			return duk_double_same_sign(x, y);
78875 		}
78876 		return 1;
78877 	} else {
78878 		/* IEEE requires that zeros compare the same regardless
78879 		 * of their sign, so if both x and y are zeroes, they
78880 		 * are caught above.
78881 		 */
78882 		DUK_ASSERT(!(DUK_FPCLASSIFY(x) == DUK_FP_ZERO && DUK_FPCLASSIFY(y) == DUK_FP_ZERO));
78883 
78884 		/* Difference to non-strict/strict comparison is that NaNs compare
78885 		 * equal and signed zero signs matter.
78886 		 */
78887 		if (DUK_UNLIKELY(cx == DUK_FP_NAN && cy == DUK_FP_NAN)) {
78888 			/* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
78889 			return 1;
78890 		}
78891 		return 0;
78892 	}
78893 #endif  /* DUK_USE_PARANOID_MATH */
78894 }
78895 
78896 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) {
78897 	duk_uint_t type_mask_x;
78898 	duk_uint_t type_mask_y;
78899 
78900 	/* If flags != 0 (strict or SameValue), thr can be NULL.  For loose
78901 	 * equals comparison it must be != NULL.
78902 	 */
78903 	DUK_ASSERT(flags != 0 || thr != NULL);
78904 
78905 	/*
78906 	 *  Same type?
78907 	 *
78908 	 *  Note: since number values have no explicit tag in the 8-byte
78909 	 *  representation, need the awkward if + switch.
78910 	 */
78911 
78912 #if defined(DUK_USE_FASTINT)
78913 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
78914 		if (DUK_TVAL_GET_FASTINT(tv_x) == DUK_TVAL_GET_FASTINT(tv_y)) {
78915 			return 1;
78916 		} else {
78917 			return 0;
78918 		}
78919 	}
78920 	else
78921 #endif
78922 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
78923 		duk_double_t d1, d2;
78924 
78925 		/* Catches both doubles and cases where only one argument is
78926 		 * a fastint so can't assume a double.
78927 		 */
78928 		d1 = DUK_TVAL_GET_NUMBER(tv_x);
78929 		d2 = DUK_TVAL_GET_NUMBER(tv_y);
78930 		if (DUK_UNLIKELY((flags & DUK_EQUALS_FLAG_SAMEVALUE) != 0)) {
78931 			/* SameValue */
78932 			return duk__js_samevalue_number(d1, d2);
78933 		} else {
78934 			/* equals and strict equals */
78935 			return duk__js_equals_number(d1, d2);
78936 		}
78937 	} else if (DUK_TVAL_GET_TAG(tv_x) == DUK_TVAL_GET_TAG(tv_y)) {
78938 		switch (DUK_TVAL_GET_TAG(tv_x)) {
78939 		case DUK_TAG_UNDEFINED:
78940 		case DUK_TAG_NULL: {
78941 			return 1;
78942 		}
78943 		case DUK_TAG_BOOLEAN: {
78944 			return DUK_TVAL_GET_BOOLEAN(tv_x) == DUK_TVAL_GET_BOOLEAN(tv_y);
78945 		}
78946 		case DUK_TAG_POINTER: {
78947 			return DUK_TVAL_GET_POINTER(tv_x) == DUK_TVAL_GET_POINTER(tv_y);
78948 		}
78949 		case DUK_TAG_STRING:
78950 		case DUK_TAG_OBJECT: {
78951 			/* Heap pointer comparison suffices for strings and objects.
78952 			 * Symbols compare equal if they have the same internal
78953 			 * representation; again heap pointer comparison suffices.
78954 			 */
78955 			return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
78956 		}
78957 		case DUK_TAG_BUFFER: {
78958 			/* In Duktape 2.x plain buffers mimic Uint8Array objects
78959 			 * so always compare by heap pointer.  In Duktape 1.x
78960 			 * strict comparison would compare heap pointers and
78961 			 * non-strict would compare contents.
78962 			 */
78963 			return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
78964 		}
78965 		case DUK_TAG_LIGHTFUNC: {
78966 			/* At least 'magic' has a significant impact on function
78967 			 * identity.
78968 			 */
78969 			duk_small_uint_t lf_flags_x;
78970 			duk_small_uint_t lf_flags_y;
78971 			duk_c_function func_x;
78972 			duk_c_function func_y;
78973 
78974 			DUK_TVAL_GET_LIGHTFUNC(tv_x, func_x, lf_flags_x);
78975 			DUK_TVAL_GET_LIGHTFUNC(tv_y, func_y, lf_flags_y);
78976 			return ((func_x == func_y) && (lf_flags_x == lf_flags_y)) ? 1 : 0;
78977 		}
78978 #if defined(DUK_USE_FASTINT)
78979 		case DUK_TAG_FASTINT:
78980 #endif
78981 		default: {
78982 			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_x));
78983 			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_y));
78984 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
78985 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_y));
78986 			DUK_UNREACHABLE();
78987 			return 0;
78988 		}
78989 		}
78990 	}
78991 
78992 	if ((flags & (DUK_EQUALS_FLAG_STRICT | DUK_EQUALS_FLAG_SAMEVALUE)) != 0) {
78993 		return 0;
78994 	}
78995 
78996 	DUK_ASSERT(flags == 0);  /* non-strict equality from here on */
78997 
78998 	/*
78999 	 *  Types are different; various cases for non-strict comparison
79000 	 *
79001 	 *  Since comparison is symmetric, we use a "swap trick" to reduce
79002 	 *  code size.
79003 	 */
79004 
79005 	type_mask_x = duk_get_type_mask_tval(tv_x);
79006 	type_mask_y = duk_get_type_mask_tval(tv_y);
79007 
79008 	/* Undefined/null are considered equal (e.g. "null == undefined" -> true). */
79009 	if ((type_mask_x & (DUK_TYPE_MASK_UNDEFINED | DUK_TYPE_MASK_NULL)) &&
79010 	    (type_mask_y & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED))) {
79011 		return 1;
79012 	}
79013 
79014 	/* Number/string -> coerce string to number (e.g. "'1.5' == 1.5" -> true). */
79015 	if ((type_mask_x & DUK_TYPE_MASK_NUMBER) && (type_mask_y & DUK_TYPE_MASK_STRING)) {
79016 		if (!DUK_TVAL_STRING_IS_SYMBOL(tv_y)) {
79017 			duk_double_t d1, d2;
79018 			d1 = DUK_TVAL_GET_NUMBER(tv_x);
79019 			d2 = duk_to_number_tval(thr, tv_y);
79020 			return duk__js_equals_number(d1, d2);
79021 		}
79022 	}
79023 	if ((type_mask_x & DUK_TYPE_MASK_STRING) && (type_mask_y & DUK_TYPE_MASK_NUMBER)) {
79024 		if (!DUK_TVAL_STRING_IS_SYMBOL(tv_x)) {
79025 			duk_double_t d1, d2;
79026 			d1 = DUK_TVAL_GET_NUMBER(tv_y);
79027 			d2 = duk_to_number_tval(thr, tv_x);
79028 			return duk__js_equals_number(d1, d2);
79029 		}
79030 	}
79031 
79032 	/* Boolean/any -> coerce boolean to number and try again.  If boolean is
79033 	 * compared to a pointer, the final comparison after coercion now always
79034 	 * yields false (as pointer vs. number compares to false), but this is
79035 	 * not special cased.
79036 	 *
79037 	 * ToNumber(bool) is +1.0 or 0.0.  Tagged boolean value is always 0 or 1.
79038 	 */
79039 	if (type_mask_x & DUK_TYPE_MASK_BOOLEAN) {
79040 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_x) == 0 || DUK_TVAL_GET_BOOLEAN(tv_x) == 1);
79041 		duk_push_uint(thr, DUK_TVAL_GET_BOOLEAN(tv_x));
79042 		duk_push_tval(thr, tv_y);
79043 		goto recursive_call;
79044 	}
79045 	if (type_mask_y & DUK_TYPE_MASK_BOOLEAN) {
79046 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_y) == 0 || DUK_TVAL_GET_BOOLEAN(tv_y) == 1);
79047 		duk_push_tval(thr, tv_x);
79048 		duk_push_uint(thr, DUK_TVAL_GET_BOOLEAN(tv_y));
79049 		goto recursive_call;
79050 	}
79051 
79052 	/* String-number-symbol/object -> coerce object to primitive (apparently without hint), then try again. */
79053 	if ((type_mask_x & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER)) &&
79054 	    (type_mask_y & DUK_TYPE_MASK_OBJECT)) {
79055 		/* No symbol check needed because symbols and strings are accepted. */
79056 		duk_push_tval(thr, tv_x);
79057 		duk_push_tval(thr, tv_y);
79058 		duk_to_primitive(thr, -1, DUK_HINT_NONE);  /* apparently no hint? */
79059 		goto recursive_call;
79060 	}
79061 	if ((type_mask_x & DUK_TYPE_MASK_OBJECT) &&
79062 	    (type_mask_y & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER))) {
79063 		/* No symbol check needed because symbols and strings are accepted. */
79064 		duk_push_tval(thr, tv_x);
79065 		duk_push_tval(thr, tv_y);
79066 		duk_to_primitive(thr, -2, DUK_HINT_NONE);  /* apparently no hint? */
79067 		goto recursive_call;
79068 	}
79069 
79070 	/* Nothing worked -> not equal. */
79071 	return 0;
79072 
79073  recursive_call:
79074 	/* Shared code path to call the helper again with arguments on stack top. */
79075 	{
79076 		duk_bool_t rc;
79077 		rc = duk_js_equals_helper(thr,
79078 		                          DUK_GET_TVAL_NEGIDX(thr, -2),
79079 		                          DUK_GET_TVAL_NEGIDX(thr, -1),
79080 		                          0 /*flags:nonstrict*/);
79081 		duk_pop_2_unsafe(thr);
79082 		return rc;
79083 	}
79084 }
79085 
79086 /*
79087  *  Comparisons (x >= y, x > y, x <= y, x < y)
79088  *
79089  *  E5 Section 11.8.5: implement 'x < y' and then use negate and eval_left_first
79090  *  flags to get the rest.
79091  */
79092 
79093 /* XXX: this should probably just operate on the stack top, because it
79094  * needs to push stuff on the stack anyway...
79095  */
79096 
79097 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) {
79098 	duk_size_t prefix_len;
79099 	duk_small_int_t rc;
79100 
79101 	prefix_len = (len1 <= len2 ? len1 : len2);
79102 
79103 	/* duk_memcmp() is guaranteed to return zero (equal) for zero length
79104 	 * inputs.
79105 	 */
79106 	rc = duk_memcmp_unsafe((const void *) buf1,
79107 	                       (const void *) buf2,
79108 	                       (size_t) prefix_len);
79109 
79110 	if (rc < 0) {
79111 		return -1;
79112 	} else if (rc > 0) {
79113 		return 1;
79114 	}
79115 
79116 	/* prefix matches, lengths matter now */
79117 	if (len1 < len2) {
79118 		/* e.g. "x" < "xx" */
79119 		return -1;
79120 	} else if (len1 > len2) {
79121 		return 1;
79122 	}
79123 
79124 	return 0;
79125 }
79126 
79127 DUK_INTERNAL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2) {
79128 	/*
79129 	 *  String comparison (E5 Section 11.8.5, step 4), which
79130 	 *  needs to compare codepoint by codepoint.
79131 	 *
79132 	 *  However, UTF-8 allows us to use strcmp directly: the shared
79133 	 *  prefix will be encoded identically (UTF-8 has unique encoding)
79134 	 *  and the first differing character can be compared with a simple
79135 	 *  unsigned byte comparison (which strcmp does).
79136 	 *
79137 	 *  This will not work properly for non-xutf-8 strings, but this
79138 	 *  is not an issue for compliance.
79139 	 */
79140 
79141 	DUK_ASSERT(h1 != NULL);
79142 	DUK_ASSERT(h2 != NULL);
79143 
79144 	return duk_js_data_compare((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h1),
79145 	                           (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h2),
79146 	                           (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1),
79147 	                           (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2));
79148 }
79149 
79150 #if 0  /* unused */
79151 DUK_INTERNAL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2) {
79152 	/* Similar to String comparison. */
79153 
79154 	DUK_ASSERT(h1 != NULL);
79155 	DUK_ASSERT(h2 != NULL);
79156 	DUK_UNREF(heap);
79157 
79158 	return duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h1),
79159 	                           (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h2),
79160 	                           (duk_size_t) DUK_HBUFFER_GET_SIZE(h1),
79161 	                           (duk_size_t) DUK_HBUFFER_GET_SIZE(h2));
79162 }
79163 #endif
79164 
79165 #if defined(DUK_USE_FASTINT)
79166 DUK_LOCAL duk_bool_t duk__compare_fastint(duk_bool_t retval, duk_int64_t v1, duk_int64_t v2) {
79167 	DUK_ASSERT(retval == 0 || retval == 1);
79168 	if (v1 < v2) {
79169 		return retval ^ 1;
79170 	} else {
79171 		return retval;
79172 	}
79173 }
79174 #endif
79175 
79176 #if defined(DUK_USE_PARANOID_MATH)
79177 DUK_LOCAL duk_bool_t duk__compare_number(duk_bool_t retval, duk_double_t d1, duk_double_t d2) {
79178 	duk_small_int_t c1, s1, c2, s2;
79179 
79180 	DUK_ASSERT(retval == 0 || retval == 1);
79181 	c1 = (duk_small_int_t) DUK_FPCLASSIFY(d1);
79182 	s1 = (duk_small_int_t) DUK_SIGNBIT(d1);
79183 	c2 = (duk_small_int_t) DUK_FPCLASSIFY(d2);
79184 	s2 = (duk_small_int_t) DUK_SIGNBIT(d2);
79185 
79186 	if (c1 == DUK_FP_NAN || c2 == DUK_FP_NAN) {
79187 		return 0;  /* Always false, regardless of negation. */
79188 	}
79189 
79190 	if (c1 == DUK_FP_ZERO && c2 == DUK_FP_ZERO) {
79191 		/* For all combinations: +0 < +0, +0 < -0, -0 < +0, -0 < -0,
79192 		 * steps e, f, and g.
79193 		 */
79194 		return retval;  /* false */
79195 	}
79196 
79197 	if (d1 == d2) {
79198 		return retval;  /* false */
79199 	}
79200 
79201 	if (c1 == DUK_FP_INFINITE && s1 == 0) {
79202 		/* x == +Infinity */
79203 		return retval;  /* false */
79204 	}
79205 
79206 	if (c2 == DUK_FP_INFINITE && s2 == 0) {
79207 		/* y == +Infinity */
79208 		return retval ^ 1;  /* true */
79209 	}
79210 
79211 	if (c2 == DUK_FP_INFINITE && s2 != 0) {
79212 		/* y == -Infinity */
79213 		return retval;  /* false */
79214 	}
79215 
79216 	if (c1 == DUK_FP_INFINITE && s1 != 0) {
79217 		/* x == -Infinity */
79218 		return retval ^ 1;  /* true */
79219 	}
79220 
79221 	if (d1 < d2) {
79222 		return retval ^ 1;  /* true */
79223 	}
79224 
79225 	return retval;  /* false */
79226 }
79227 #else  /* DUK_USE_PARANOID_MATH */
79228 DUK_LOCAL duk_bool_t duk__compare_number(duk_bool_t retval, duk_double_t d1, duk_double_t d2) {
79229 	/* This comparison tree relies doesn't match the exact steps in
79230 	 * E5 Section 11.8.5 but should produce the same results.  The
79231 	 * steps rely on exact IEEE semantics for NaNs, etc.
79232 	 */
79233 
79234 	DUK_ASSERT(retval == 0 || retval == 1);
79235 	if (d1 < d2) {
79236 		/* In no case should both (d1 < d2) and (d2 < d1) be true.
79237 		 * It's possible that neither is true though, and that's
79238 		 * handled below.
79239 		 */
79240 		DUK_ASSERT(!(d2 < d1));
79241 
79242 		/* - d1 < d2, both d1/d2 are normals (not Infinity, not NaN)
79243 		 * - d2 is +Infinity, d1 != +Infinity and NaN
79244 		 * - d1 is -Infinity, d2 != -Infinity and NaN
79245 		 */
79246 		return retval ^ 1;
79247 	} else {
79248 		if (d2 < d1) {
79249 			/* - !(d1 < d2), both d1/d2 are normals (not Infinity, not NaN)
79250 			 * - d1 is +Infinity, d2 != +Infinity and NaN
79251 			 * - d2 is -Infinity, d1 != -Infinity and NaN
79252 			 */
79253 			return retval;
79254 		} else {
79255 			/* - d1 and/or d2 is NaN
79256 			 * - d1 and d2 are both +/- 0
79257 			 * - d1 == d2 (including infinities)
79258 			 */
79259 			if (duk_double_is_nan(d1) || duk_double_is_nan(d2)) {
79260 				/* Note: undefined from Section 11.8.5 always
79261 				 * results in false return (see e.g. Section
79262 				 * 11.8.3) - hence special treatment here.
79263 				 */
79264 				return 0;  /* zero regardless of negation */
79265 			} else {
79266 				return retval;
79267 			}
79268 		}
79269 	}
79270 }
79271 #endif  /* DUK_USE_PARANOID_MATH */
79272 
79273 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) {
79274 	duk_double_t d1, d2;
79275 	duk_small_int_t rc;
79276 	duk_bool_t retval;
79277 
79278 	DUK_ASSERT(DUK_COMPARE_FLAG_NEGATE == 1);  /* Rely on this flag being lowest. */
79279 	retval = flags & DUK_COMPARE_FLAG_NEGATE;
79280 	DUK_ASSERT(retval == 0 || retval == 1);
79281 
79282 	/* Fast path for fastints */
79283 #if defined(DUK_USE_FASTINT)
79284 	if (DUK_LIKELY(DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y))) {
79285 		return duk__compare_fastint(retval,
79286 		                            DUK_TVAL_GET_FASTINT(tv_x),
79287 		                            DUK_TVAL_GET_FASTINT(tv_y));
79288 	}
79289 #endif  /* DUK_USE_FASTINT */
79290 
79291 	/* Fast path for numbers (one of which may be a fastint) */
79292 #if !defined(DUK_USE_PREFER_SIZE)
79293 	if (DUK_LIKELY(DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y))) {
79294 		return duk__compare_number(retval,
79295 		                           DUK_TVAL_GET_NUMBER(tv_x),
79296 		                           DUK_TVAL_GET_NUMBER(tv_y));
79297 	}
79298 #endif
79299 
79300 	/* Slow path */
79301 
79302 	duk_push_tval(thr, tv_x);
79303 	duk_push_tval(thr, tv_y);
79304 
79305 	if (flags & DUK_COMPARE_FLAG_EVAL_LEFT_FIRST) {
79306 		duk_to_primitive(thr, -2, DUK_HINT_NUMBER);
79307 		duk_to_primitive(thr, -1, DUK_HINT_NUMBER);
79308 	} else {
79309 		duk_to_primitive(thr, -1, DUK_HINT_NUMBER);
79310 		duk_to_primitive(thr, -2, DUK_HINT_NUMBER);
79311 	}
79312 
79313 	/* Note: reuse variables */
79314 	tv_x = DUK_GET_TVAL_NEGIDX(thr, -2);
79315 	tv_y = DUK_GET_TVAL_NEGIDX(thr, -1);
79316 
79317 	if (DUK_TVAL_IS_STRING(tv_x) && DUK_TVAL_IS_STRING(tv_y)) {
79318 		duk_hstring *h1 = DUK_TVAL_GET_STRING(tv_x);
79319 		duk_hstring *h2 = DUK_TVAL_GET_STRING(tv_y);
79320 		DUK_ASSERT(h1 != NULL);
79321 		DUK_ASSERT(h2 != NULL);
79322 
79323 		if (DUK_LIKELY(!DUK_HSTRING_HAS_SYMBOL(h1) && !DUK_HSTRING_HAS_SYMBOL(h2))) {
79324 			rc = duk_js_string_compare(h1, h2);
79325 			duk_pop_2_unsafe(thr);
79326 			if (rc < 0) {
79327 				return retval ^ 1;
79328 			} else {
79329 				return retval;
79330 			}
79331 		}
79332 
79333 		/* One or both are Symbols: fall through to handle in the
79334 		 * generic path.  Concretely, ToNumber() will fail.
79335 		 */
79336 	}
79337 
79338 	/* Ordering should not matter (E5 Section 11.8.5, step 3.a). */
79339 #if 0
79340 	if (flags & DUK_COMPARE_FLAG_EVAL_LEFT_FIRST) {
79341 		d1 = duk_to_number_m2(thr);
79342 		d2 = duk_to_number_m1(thr);
79343 	} else {
79344 		d2 = duk_to_number_m1(thr);
79345 		d1 = duk_to_number_m2(thr);
79346 	}
79347 #endif
79348 	d1 = duk_to_number_m2(thr);
79349 	d2 = duk_to_number_m1(thr);
79350 
79351 	/* We want to duk_pop_2_unsafe(thr); because the values are numbers
79352 	 * no decref check is needed.
79353 	 */
79354 #if defined(DUK_USE_PREFER_SIZE)
79355 	duk_pop_2_nodecref_unsafe(thr);
79356 #else
79357 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk_get_tval(thr, -2)));
79358 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk_get_tval(thr, -1)));
79359 	DUK_ASSERT(duk_get_top(thr) >= 2);
79360 	thr->valstack_top -= 2;
79361 	tv_x = thr->valstack_top;
79362 	tv_y = tv_x + 1;
79363 	DUK_TVAL_SET_UNDEFINED(tv_x);  /* Value stack policy */
79364 	DUK_TVAL_SET_UNDEFINED(tv_y);
79365 #endif
79366 
79367 	return duk__compare_number(retval, d1, d2);
79368 }
79369 
79370 /*
79371  *  instanceof
79372  */
79373 
79374 /*
79375  *  ES2015 Section 7.3.19 describes the OrdinaryHasInstance() algorithm
79376  *  which covers both bound and non-bound functions; in effect the algorithm
79377  *  includes E5 Sections 11.8.6, 15.3.5.3, and 15.3.4.5.3.
79378  *
79379  *  ES2015 Section 12.9.4 describes the instanceof operator which first
79380  *  checks @@hasInstance well-known symbol and falls back to
79381  *  OrdinaryHasInstance().
79382  *
79383  *  Limited Proxy support: don't support 'getPrototypeOf' trap but
79384  *  continue lookup in Proxy target if the value is a Proxy.
79385  */
79386 
79387 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) {
79388 	duk_hobject *func;
79389 	duk_hobject *val;
79390 	duk_hobject *proto;
79391 	duk_tval *tv;
79392 	duk_bool_t skip_first;
79393 	duk_uint_t sanity;
79394 
79395 	/*
79396 	 *  Get the values onto the stack first.  It would be possible to cover
79397 	 *  some normal cases without resorting to the value stack.
79398 	 *
79399 	 *  The right hand side could be a light function (as they generally
79400 	 *  behave like objects).  Light functions never have a 'prototype'
79401 	 *  property so E5.1 Section 15.3.5.3 step 3 always throws a TypeError.
79402 	 *  Using duk_require_hobject() is thus correct (except for error msg).
79403 	 */
79404 
79405 	duk_push_tval(thr, tv_x);
79406 	duk_push_tval(thr, tv_y);
79407 	func = duk_require_hobject(thr, -1);
79408 	DUK_ASSERT(func != NULL);
79409 
79410 #if defined(DUK_USE_SYMBOL_BUILTIN)
79411 	/*
79412 	 *  @@hasInstance check, ES2015 Section 12.9.4, Steps 2-4.
79413 	 */
79414 	if (!skip_sym_check) {
79415 		if (duk_get_method_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)) {
79416 			/* [ ... lhs rhs func ] */
79417 			duk_insert(thr, -3);    /* -> [ ... func lhs rhs ] */
79418 			duk_swap_top(thr, -2);  /* -> [ ... func rhs(this) lhs ] */
79419 			duk_call_method(thr, 1);
79420 			return duk_to_boolean_top_pop(thr);
79421 		}
79422 	}
79423 #else
79424 	DUK_UNREF(skip_sym_check);
79425 #endif
79426 
79427 	/*
79428 	 *  For bound objects, [[HasInstance]] just calls the target function
79429 	 *  [[HasInstance]].  If that is again a bound object, repeat until
79430 	 *  we find a non-bound Function object.
79431 	 *
79432 	 *  The bound function chain is now "collapsed" so there can be only
79433 	 *  one bound function in the chain.
79434 	 */
79435 
79436 	if (!DUK_HOBJECT_IS_CALLABLE(func)) {
79437 		/*
79438 		 *  Note: of native ECMAScript objects, only Function instances
79439 		 *  have a [[HasInstance]] internal property.  Custom objects might
79440 		 *  also have it, but not in current implementation.
79441 		 *
79442 		 *  XXX: add a separate flag, DUK_HOBJECT_FLAG_ALLOW_INSTANCEOF?
79443 		 */
79444 		goto error_invalid_rval;
79445 	}
79446 
79447 	if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
79448 		duk_push_tval(thr, &((duk_hboundfunc *) (void *) func)->target);
79449 		duk_replace(thr, -2);
79450 		func = duk_require_hobject(thr, -1);  /* lightfunc throws */
79451 
79452 		/* Rely on Function.prototype.bind() never creating bound
79453 		 * functions whose target is not proper.
79454 		 */
79455 		DUK_ASSERT(func != NULL);
79456 		DUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(func));
79457 	}
79458 
79459 	/*
79460 	 *  'func' is now a non-bound object which supports [[HasInstance]]
79461 	 *  (which here just means DUK_HOBJECT_FLAG_CALLABLE).  Move on
79462 	 *  to execute E5 Section 15.3.5.3.
79463 	 */
79464 
79465 	DUK_ASSERT(func != NULL);
79466 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
79467 	DUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(func));
79468 
79469 	/* [ ... lval rval(func) ] */
79470 
79471 	/* For lightfuncs, buffers, and pointers start the comparison directly
79472 	 * from the virtual prototype object.
79473 	 */
79474 	skip_first = 0;
79475 	tv = DUK_GET_TVAL_NEGIDX(thr, -2);
79476 	switch (DUK_TVAL_GET_TAG(tv)) {
79477 	case DUK_TAG_LIGHTFUNC:
79478 		val = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
79479 		DUK_ASSERT(val != NULL);
79480 		break;
79481 	case DUK_TAG_BUFFER:
79482 		val = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
79483 		DUK_ASSERT(val != NULL);
79484 		break;
79485 	case DUK_TAG_POINTER:
79486 		val = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
79487 		DUK_ASSERT(val != NULL);
79488 		break;
79489 	case DUK_TAG_OBJECT:
79490 		skip_first = 1;  /* Ignore object itself on first round. */
79491 		val = DUK_TVAL_GET_OBJECT(tv);
79492 		DUK_ASSERT(val != NULL);
79493 		break;
79494 	default:
79495 		goto pop2_and_false;
79496 	}
79497 	DUK_ASSERT(val != NULL);  /* Loop doesn't actually rely on this. */
79498 
79499 	/* Look up .prototype of rval.  Leave it on the value stack in case it
79500 	 * has been virtualized (e.g. getter, Proxy trap).
79501 	 */
79502 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_PROTOTYPE);  /* -> [ ... lval rval rval.prototype ] */
79503 #if defined(DUK_USE_VERBOSE_ERRORS)
79504 	proto = duk_get_hobject(thr, -1);
79505 	if (proto == NULL) {
79506 		goto error_invalid_rval_noproto;
79507 	}
79508 #else
79509 	proto = duk_require_hobject(thr, -1);
79510 #endif
79511 
79512 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
79513 	do {
79514 		/*
79515 		 *  Note: prototype chain is followed BEFORE first comparison.  This
79516 		 *  means that the instanceof lval is never itself compared to the
79517 		 *  rval.prototype property.  This is apparently intentional, see E5
79518 		 *  Section 15.3.5.3, step 4.a.
79519 		 *
79520 		 *  Also note:
79521 		 *
79522 		 *      js> (function() {}) instanceof Function
79523 		 *      true
79524 		 *      js> Function instanceof Function
79525 		 *      true
79526 		 *
79527 		 *  For the latter, h_proto will be Function.prototype, which is the
79528 		 *  built-in Function prototype.  Because Function.[[Prototype]] is
79529 		 *  also the built-in Function prototype, the result is true.
79530 		 */
79531 
79532 		if (!val) {
79533 			goto pop3_and_false;
79534 		}
79535 
79536 		DUK_ASSERT(val != NULL);
79537 #if defined(DUK_USE_ES6_PROXY)
79538 		val = duk_hobject_resolve_proxy_target(val);
79539 #endif
79540 
79541 		if (skip_first) {
79542 			skip_first = 0;
79543 		} else if (val == proto) {
79544 			goto pop3_and_true;
79545 		}
79546 
79547 		DUK_ASSERT(val != NULL);
79548 		val = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, val);
79549 	} while (--sanity > 0);
79550 
79551 	if (DUK_UNLIKELY(sanity == 0)) {
79552 		DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
79553 		DUK_WO_NORETURN(return 0;);
79554 	}
79555 	DUK_UNREACHABLE();
79556 
79557  pop2_and_false:
79558 	duk_pop_2_unsafe(thr);
79559 	return 0;
79560 
79561  pop3_and_false:
79562 	duk_pop_3_unsafe(thr);
79563 	return 0;
79564 
79565  pop3_and_true:
79566 	duk_pop_3_unsafe(thr);
79567 	return 1;
79568 
79569  error_invalid_rval:
79570 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_INSTANCEOF_RVAL);
79571 	DUK_WO_NORETURN(return 0;);
79572 
79573 #if defined(DUK_USE_VERBOSE_ERRORS)
79574  error_invalid_rval_noproto:
79575 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO);
79576 	DUK_WO_NORETURN(return 0;);
79577 #endif
79578 }
79579 
79580 #if defined(DUK_USE_SYMBOL_BUILTIN)
79581 DUK_INTERNAL duk_bool_t duk_js_instanceof_ordinary(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
79582 	return duk__js_instanceof_helper(thr, tv_x, tv_y, 1 /*skip_sym_check*/);
79583 }
79584 #endif
79585 
79586 DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
79587 	return duk__js_instanceof_helper(thr, tv_x, tv_y, 0 /*skip_sym_check*/);
79588 }
79589 
79590 /*
79591  *  in
79592  */
79593 
79594 /*
79595  *  E5 Sections 11.8.7, 8.12.6.
79596  *
79597  *  Basically just a property existence check using [[HasProperty]].
79598  */
79599 
79600 DUK_INTERNAL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
79601 	duk_bool_t retval;
79602 
79603 	/*
79604 	 *  Get the values onto the stack first.  It would be possible to cover
79605 	 *  some normal cases without resorting to the value stack (e.g. if
79606 	 *  lval is already a string).
79607 	 */
79608 
79609 	/* XXX: The ES5/5.1/6 specifications require that the key in 'key in obj'
79610 	 * must be string coerced before the internal HasProperty() algorithm is
79611 	 * invoked.  A fast path skipping coercion could be safely implemented for
79612 	 * numbers (as number-to-string coercion has no side effects).  For ES2015
79613 	 * proxy behavior, the trap 'key' argument must be in a string coerced
79614 	 * form (which is a shame).
79615 	 */
79616 
79617 	/* TypeError if rval is not an object or object like (e.g. lightfunc
79618 	 * or plain buffer).
79619 	 */
79620 	duk_push_tval(thr, tv_x);
79621 	duk_push_tval(thr, tv_y);
79622 	duk_require_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT | DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
79623 
79624 	(void) duk_to_property_key_hstring(thr, -2);
79625 
79626 	retval = duk_hobject_hasprop(thr,
79627 	                             DUK_GET_TVAL_NEGIDX(thr, -1),
79628 	                             DUK_GET_TVAL_NEGIDX(thr, -2));
79629 
79630 	duk_pop_2_unsafe(thr);
79631 	return retval;
79632 }
79633 
79634 /*
79635  *  typeof
79636  *
79637  *  E5 Section 11.4.3.
79638  *
79639  *  Very straightforward.  The only question is what to return for our
79640  *  non-standard tag / object types.
79641  *
79642  *  There is an unfortunate string constant define naming problem with
79643  *  typeof return values for e.g. "Object" and "object"; careful with
79644  *  the built-in string defines.  The LC_XXX defines are used for the
79645  *  lowercase variants now.
79646  */
79647 
79648 DUK_INTERNAL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x) {
79649 	duk_small_uint_t stridx = 0;
79650 
79651 	switch (DUK_TVAL_GET_TAG(tv_x)) {
79652 	case DUK_TAG_UNDEFINED: {
79653 		stridx = DUK_STRIDX_LC_UNDEFINED;
79654 		break;
79655 	}
79656 	case DUK_TAG_NULL: {
79657 		/* Note: not a typo, "object" is returned for a null value. */
79658 		stridx = DUK_STRIDX_LC_OBJECT;
79659 		break;
79660 	}
79661 	case DUK_TAG_BOOLEAN: {
79662 		stridx = DUK_STRIDX_LC_BOOLEAN;
79663 		break;
79664 	}
79665 	case DUK_TAG_POINTER: {
79666 		/* Implementation specific. */
79667 		stridx = DUK_STRIDX_LC_POINTER;
79668 		break;
79669 	}
79670 	case DUK_TAG_STRING: {
79671 		duk_hstring *str;
79672 
79673 		/* All internal keys are identified as Symbols. */
79674 		str = DUK_TVAL_GET_STRING(tv_x);
79675 		DUK_ASSERT(str != NULL);
79676 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(str))) {
79677 			stridx = DUK_STRIDX_LC_SYMBOL;
79678 		} else {
79679 			stridx = DUK_STRIDX_LC_STRING;
79680 		}
79681 		break;
79682 	}
79683 	case DUK_TAG_OBJECT: {
79684 		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_x);
79685 		DUK_ASSERT(obj != NULL);
79686 		if (DUK_HOBJECT_IS_CALLABLE(obj)) {
79687 			stridx = DUK_STRIDX_LC_FUNCTION;
79688 		} else {
79689 			stridx = DUK_STRIDX_LC_OBJECT;
79690 		}
79691 		break;
79692 	}
79693 	case DUK_TAG_BUFFER: {
79694 		/* Implementation specific.  In Duktape 1.x this would be
79695 		 * 'buffer', in Duktape 2.x changed to 'object' because plain
79696 		 * buffers now mimic Uint8Array objects.
79697 		 */
79698 		stridx = DUK_STRIDX_LC_OBJECT;
79699 		break;
79700 	}
79701 	case DUK_TAG_LIGHTFUNC: {
79702 		stridx = DUK_STRIDX_LC_FUNCTION;
79703 		break;
79704 	}
79705 #if defined(DUK_USE_FASTINT)
79706 	case DUK_TAG_FASTINT:
79707 #endif
79708 	default: {
79709 		/* number */
79710 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_x));
79711 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
79712 		stridx = DUK_STRIDX_LC_NUMBER;
79713 		break;
79714 	}
79715 	}
79716 
79717 	DUK_ASSERT_STRIDX_VALID(stridx);
79718 	return stridx;
79719 }
79720 
79721 /*
79722  *  Array index and length
79723  *
79724  *  Array index: E5 Section 15.4
79725  *  Array length: E5 Section 15.4.5.1 steps 3.c - 3.d (array length write)
79726  */
79727 
79728 /* Compure array index from string context, or return a "not array index"
79729  * indicator.
79730  */
79731 DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_string(const duk_uint8_t *str, duk_uint32_t blen) {
79732 	duk_uarridx_t res;
79733 
79734 	/* Only strings with byte length 1-10 can be 32-bit array indices.
79735 	 * Leading zeroes (except '0' alone), plus/minus signs are not allowed.
79736 	 * We could do a lot of prechecks here, but since most strings won't
79737 	 * start with any digits, it's simpler to just parse the number and
79738 	 * fail quickly.
79739 	 */
79740 
79741 	res = 0;
79742 	if (blen == 0) {
79743 		goto parse_fail;
79744 	}
79745 	do {
79746 		duk_uarridx_t dig;
79747 		dig = (duk_uarridx_t) (*str++) - DUK_ASC_0;
79748 
79749 		if (dig <= 9U) {
79750 			/* Careful overflow handling.  When multiplying by 10:
79751 			 * - 0x19999998 x 10 = 0xfffffff0: no overflow, and adding
79752 			 *   0...9 is safe.
79753 			 * - 0x19999999 x 10 = 0xfffffffa: no overflow, adding
79754 			 *   0...5 is safe, 6...9 overflows.
79755 			 * - 0x1999999a x 10 = 0x100000004: always overflow.
79756 			 */
79757 			if (DUK_UNLIKELY(res >= 0x19999999UL)) {
79758 				if (res >= 0x1999999aUL) {
79759 					/* Always overflow. */
79760 					goto parse_fail;
79761 				}
79762 				DUK_ASSERT(res == 0x19999999UL);
79763 				if (dig >= 6U) {
79764 					goto parse_fail;
79765 				}
79766 				res = 0xfffffffaUL + dig;
79767 				DUK_ASSERT(res >= 0xfffffffaUL);
79768 				DUK_ASSERT_DISABLE(res <= 0xffffffffUL);  /* range */
79769 			} else {
79770 				res = res * 10U + dig;
79771 				if (DUK_UNLIKELY(res == 0)) {
79772 					/* If 'res' is 0, previous 'res' must
79773 					 * have been 0 and we scanned in a zero.
79774 					 * This is only allowed if blen == 1,
79775 					 * i.e. the exact string '0'.
79776 					 */
79777 					if (blen == (duk_uint32_t) 1) {
79778 						return 0;
79779 					}
79780 					goto parse_fail;
79781 				}
79782 			}
79783 		} else {
79784 			/* Because 'dig' is unsigned, catches both values
79785 			 * above '9' and below '0'.
79786 			 */
79787 			goto parse_fail;
79788 		}
79789 	} while (--blen > 0);
79790 
79791 	return res;
79792 
79793  parse_fail:
79794 	return DUK_HSTRING_NO_ARRAY_INDEX;
79795 }
79796 
79797 #if !defined(DUK_USE_HSTRING_ARRIDX)
79798 /* Get array index for a string which is known to be an array index.  This helper
79799  * is needed when duk_hstring doesn't concretely store the array index, but strings
79800  * are flagged as array indices at intern time.
79801  */
79802 DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_hstring_fast_known(duk_hstring *h) {
79803 	const duk_uint8_t *p;
79804 	duk_uarridx_t res;
79805 	duk_uint8_t t;
79806 
79807 	DUK_ASSERT(h != NULL);
79808 	DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(h));
79809 
79810 	p = DUK_HSTRING_GET_DATA(h);
79811 	res = 0;
79812 	for (;;) {
79813 		t = *p++;
79814 		if (DUK_UNLIKELY(t == 0)) {
79815 			/* Scanning to NUL is always safe for interned strings. */
79816 			break;
79817 		}
79818 		DUK_ASSERT(t >= (duk_uint8_t) DUK_ASC_0 && t <= (duk_uint8_t) DUK_ASC_9);
79819 		res = res * 10U + (duk_uarridx_t) t - (duk_uarridx_t) DUK_ASC_0;
79820 	}
79821 	return res;
79822 }
79823 
79824 DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h) {
79825 	DUK_ASSERT(h != NULL);
79826 	if (!DUK_HSTRING_HAS_ARRIDX(h)) {
79827 		return DUK_HSTRING_NO_ARRAY_INDEX;
79828 	}
79829 	return duk_js_to_arrayindex_hstring_fast_known(h);
79830 }
79831 #endif  /* DUK_USE_HSTRING_ARRIDX */
79832 #line 1 "duk_js_var.c"
79833 /*
79834  *  Identifier access and function closure handling.
79835  *
79836  *  Provides the primitives for slow path identifier accesses: GETVAR,
79837  *  PUTVAR, DELVAR, etc.  The fast path, direct register accesses, should
79838  *  be used for most identifier accesses.  Consequently, these slow path
79839  *  primitives should be optimized for maximum compactness.
79840  *
79841  *  ECMAScript environment records (declarative and object) are represented
79842  *  as internal objects with control keys.  Environment records have a
79843  *  parent record ("outer environment reference") which is represented by
79844  *  the implicit prototype for technical reasons (in other words, it is a
79845  *  convenient field).  The prototype chain is not followed in the ordinary
79846  *  sense for variable lookups.
79847  *
79848  *  See identifier-handling.rst for more details on the identifier algorithms
79849  *  and the internal representation.  See function-objects.rst for details on
79850  *  what function templates and instances are expected to look like.
79851  *
79852  *  Care must be taken to avoid duk_tval pointer invalidation caused by
79853  *  e.g. value stack or object resizing.
79854  *
79855  *  TODO: properties for function instances could be initialized much more
79856  *  efficiently by creating a property allocation for a certain size and
79857  *  filling in keys and values directly (and INCREFing both with "bulk incref"
79858  *  primitives.
79859  *
79860  *  XXX: duk_hobject_getprop() and duk_hobject_putprop() calls are a bit
79861  *  awkward (especially because they follow the prototype chain); rework
79862  *  if "raw" own property helpers are added.
79863  */
79864 
79865 /* #include duk_internal.h -> already included */
79866 
79867 /*
79868  *  Local result type for duk__get_identifier_reference() lookup.
79869  */
79870 
79871 typedef struct {
79872 	duk_hobject *env;
79873 	duk_hobject *holder;      /* for object-bound identifiers */
79874 	duk_tval *value;          /* for register-bound and declarative env identifiers */
79875 	duk_uint_t attrs;         /* property attributes for identifier (relevant if value != NULL) */
79876 	duk_bool_t has_this;      /* for object-bound identifiers: provide 'this' binding */
79877 } duk__id_lookup_result;
79878 
79879 /*
79880  *  Create a new function object based on a "template function" which contains
79881  *  compiled bytecode, constants, etc, but lacks a lexical environment.
79882  *
79883  *  ECMAScript requires that each created closure is a separate object, with
79884  *  its own set of editable properties.  However, structured property values
79885  *  (such as the formal arguments list and the variable map) are shared.
79886  *  Also the bytecode, constants, and inner functions are shared.
79887  *
79888  *  See E5 Section 13.2 for detailed requirements on the function objects;
79889  *  there are no similar requirements for function "templates" which are an
79890  *  implementation dependent internal feature.  Also see function-objects.rst
79891  *  for a discussion on the function instance properties provided by this
79892  *  implementation.
79893  *
79894  *  Notes:
79895  *
79896  *   * Order of internal properties should match frequency of use, since the
79897  *     properties will be linearly scanned on lookup (functions usually don't
79898  *     have enough properties to warrant a hash part).
79899  *
79900  *   * The created closure is independent of its template; they do share the
79901  *     same 'data' buffer object, but the template object itself can be freed
79902  *     even if the closure object remains reachable.
79903  */
79904 
79905 DUK_LOCAL void duk__inc_data_inner_refcounts(duk_hthread *thr, duk_hcompfunc *f) {
79906 	duk_tval *tv, *tv_end;
79907 	duk_hobject **funcs, **funcs_end;
79908 
79909 	DUK_UNREF(thr);
79910 
79911 	/* If function creation fails due to out-of-memory, the data buffer
79912 	 * pointer may be NULL in some cases.  That's actually possible for
79913 	 * GC code, but shouldn't be possible here because the incomplete
79914 	 * function will be unwound from the value stack and never instantiated.
79915 	 */
79916 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, f) != NULL);
79917 
79918 	tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, f);
79919 	tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, f);
79920 	while (tv < tv_end) {
79921 		DUK_TVAL_INCREF(thr, tv);
79922 		tv++;
79923 	}
79924 
79925 	funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, f);
79926 	funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, f);
79927 	while (funcs < funcs_end) {
79928 		DUK_HEAPHDR_INCREF(thr, (duk_heaphdr *) *funcs);
79929 		funcs++;
79930 	}
79931 }
79932 
79933 /* Push a new closure on the stack.
79934  *
79935  * Note: if fun_temp has NEWENV, i.e. a new lexical and variable declaration
79936  * is created when the function is called, only outer_lex_env matters
79937  * (outer_var_env is ignored and may or may not be same as outer_lex_env).
79938  */
79939 
79940 DUK_LOCAL const duk_uint16_t duk__closure_copy_proplist[] = {
79941 	/* order: most frequent to least frequent */
79942 	DUK_STRIDX_INT_VARMAP,
79943 	DUK_STRIDX_INT_FORMALS,
79944 #if defined(DUK_USE_PC2LINE)
79945 	DUK_STRIDX_INT_PC2LINE,
79946 #endif
79947 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
79948 	DUK_STRIDX_FILE_NAME,
79949 #endif
79950 #if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
79951 	DUK_STRIDX_INT_SOURCE
79952 #endif
79953 };
79954 
79955 DUK_INTERNAL
79956 void duk_js_push_closure(duk_hthread *thr,
79957                          duk_hcompfunc *fun_temp,
79958                          duk_hobject *outer_var_env,
79959                          duk_hobject *outer_lex_env,
79960                          duk_bool_t add_auto_proto) {
79961 	duk_hcompfunc *fun_clos;
79962 	duk_small_uint_t i;
79963 	duk_uint_t len_value;
79964 
79965 	DUK_ASSERT(fun_temp != NULL);
79966 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_temp) != NULL);
79967 	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_temp) != NULL);
79968 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_temp) != NULL);
79969 	DUK_ASSERT(outer_var_env != NULL);
79970 	DUK_ASSERT(outer_lex_env != NULL);
79971 	DUK_UNREF(len_value);
79972 
79973 	fun_clos = duk_push_hcompfunc(thr);
79974 	DUK_ASSERT(fun_clos != NULL);
79975 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) fun_clos) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
79976 
79977 	duk_push_hobject(thr, &fun_temp->obj);  /* -> [ ... closure template ] */
79978 
79979 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun_clos));
79980 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos) == NULL);
79981 	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_clos) == NULL);
79982 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_clos) == NULL);
79983 
79984 	DUK_HCOMPFUNC_SET_DATA(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_temp));
79985 	DUK_HCOMPFUNC_SET_FUNCS(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_temp));
79986 	DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_temp));
79987 
79988 	/* Note: all references inside 'data' need to get their refcounts
79989 	 * upped too.  This is the case because refcounts are decreased
79990 	 * through every function referencing 'data' independently.
79991 	 */
79992 
79993 	DUK_HBUFFER_INCREF(thr, DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos));
79994 	duk__inc_data_inner_refcounts(thr, fun_temp);
79995 
79996 	fun_clos->nregs = fun_temp->nregs;
79997 	fun_clos->nargs = fun_temp->nargs;
79998 #if defined(DUK_USE_DEBUGGER_SUPPORT)
79999 	fun_clos->start_line = fun_temp->start_line;
80000 	fun_clos->end_line = fun_temp->end_line;
80001 #endif
80002 
80003 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos) != NULL);
80004 	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_clos) != NULL);
80005 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_clos) != NULL);
80006 
80007 	/* XXX: Could also copy from template, but there's no way to have any
80008 	 * other value here now (used code has no access to the template).
80009 	 * Prototype is set by duk_push_hcompfunc().
80010 	 */
80011 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, &fun_clos->obj) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
80012 #if 0
80013 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &fun_clos->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
80014 #endif
80015 
80016 	/* Copy duk_hobject flags as is from the template using a mask.
80017 	 * Leave out duk_heaphdr owned flags just in case (e.g. if there's
80018 	 * some GC flag or similar).  Some flags can then be adjusted
80019 	 * separately if necessary.
80020 	 */
80021 
80022 	/* DUK_HEAPHDR_SET_FLAGS() masks changes to non-duk_heaphdr flags only. */
80023 	DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) fun_clos, DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_temp));
80024 	DUK_DD(DUK_DDPRINT("fun_temp heaphdr flags: 0x%08lx, fun_clos heaphdr flags: 0x%08lx",
80025 	                   (unsigned long) DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_temp),
80026 	                   (unsigned long) DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_clos)));
80027 
80028 	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));
80029 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&fun_clos->obj));
80030 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(&fun_clos->obj));
80031 	DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(&fun_clos->obj));
80032 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(&fun_clos->obj));
80033 	/* DUK_HOBJECT_FLAG_ARRAY_PART: don't care */
80034 	/* DUK_HOBJECT_FLAG_NEWENV: handled below */
80035 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&fun_clos->obj));
80036 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&fun_clos->obj));
80037 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&fun_clos->obj));
80038 
80039 	if (!DUK_HOBJECT_HAS_CONSTRUCTABLE(&fun_clos->obj)) {
80040 		/* If the template is not constructable don't add an automatic
80041 		 * .prototype property.  This is the case for e.g. ES2015 object
80042 		 * literal getters/setters and method definitions.
80043 		 */
80044 		add_auto_proto = 0;
80045 	}
80046 
80047 	/*
80048 	 *  Setup environment record properties based on the template and
80049 	 *  its flags.
80050 	 *
80051 	 *  If DUK_HOBJECT_HAS_NEWENV(fun_temp) is true, the environment
80052 	 *  records represent identifiers "outside" the function; the
80053 	 *  "inner" environment records are created on demand.  Otherwise,
80054 	 *  the environment records are those that will be directly used
80055 	 *  (e.g. for declarations).
80056 	 *
80057 	 *  _Lexenv is always set; _Varenv defaults to _Lexenv if missing,
80058 	 *  so _Varenv is only set if _Lexenv != _Varenv.
80059 	 *
80060 	 *  This is relatively complex, see doc/identifier-handling.rst.
80061 	 */
80062 
80063 	if (DUK_HOBJECT_HAS_NEWENV(&fun_clos->obj)) {
80064 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
80065 		if (DUK_HOBJECT_HAS_NAMEBINDING(&fun_clos->obj)) {
80066 			duk_hobject *proto;
80067 			duk_hdecenv *new_env;
80068 
80069 			/*
80070 			 *  Named function expression, name needs to be bound
80071 			 *  in an intermediate environment record.  The "outer"
80072 			 *  lexical/variable environment will thus be:
80073 			 *
80074 			 *  a) { funcname: <func>, __prototype: outer_lex_env }
80075 			 *  b) { funcname: <func>, __prototype:  <globalenv> }  (if outer_lex_env missing)
80076 			 */
80077 
80078 			if (outer_lex_env) {
80079 				proto = outer_lex_env;
80080 			} else {
80081 				proto = thr->builtins[DUK_BIDX_GLOBAL_ENV];
80082 			}
80083 
80084 			/* -> [ ... closure template env ] */
80085 			new_env = duk_hdecenv_alloc(thr,
80086 			                            DUK_HOBJECT_FLAG_EXTENSIBLE |
80087 			                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
80088 			DUK_ASSERT(new_env != NULL);
80089 			duk_push_hobject(thr, (duk_hobject *) new_env);
80090 
80091 			DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
80092 			DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, proto);
80093 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, proto);
80094 
80095 			DUK_ASSERT(new_env->thread == NULL);  /* Closed. */
80096 			DUK_ASSERT(new_env->varmap == NULL);
80097 
80098 			/* It's important that duk_xdef_prop() is a 'raw define' so that any
80099 			 * properties in an ancestor are never an issue (they should never be
80100 			 * e.g. non-writable, but just in case).
80101 			 *
80102 			 * Because template objects are not visible to user code, the case
80103 			 * where .name is missing shouldn't happen in practice.  It it does,
80104 			 * the name 'undefined' gets bound and maps to the closure (which is
80105 			 * a bit odd, but safe).
80106 			 */
80107 			(void) duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);
80108 			/* -> [ ... closure template env funcname ] */
80109 			duk_dup_m4(thr);                                           /* -> [ ... closure template env funcname closure ] */
80110 			duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_NONE);           /* -> [ ... closure template env ] */
80111 			/* env[funcname] = closure */
80112 
80113 			/* [ ... closure template env ] */
80114 
80115 			DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, (duk_hobject *) new_env);
80116 			DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, (duk_hobject *) new_env);
80117 			DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);
80118 			DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);
80119 			duk_pop_unsafe(thr);
80120 
80121 			/* [ ... closure template ] */
80122 		}
80123 		else
80124 #endif  /* DUK_USE_FUNC_NAME_PROPERTY */
80125 		{
80126 			/*
80127 			 *  Other cases (function declaration, anonymous function expression,
80128 			 *  strict direct eval code).  The "outer" environment will be whatever
80129 			 *  the caller gave us.
80130 			 */
80131 
80132 			DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, outer_lex_env);
80133 			DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, outer_lex_env);
80134 			DUK_HOBJECT_INCREF(thr, outer_lex_env);
80135 			DUK_HOBJECT_INCREF(thr, outer_lex_env);
80136 
80137 			/* [ ... closure template ] */
80138 		}
80139 	} else {
80140 		/*
80141 		 *  Function gets no new environment when called.  This is the
80142 		 *  case for global code, indirect eval code, and non-strict
80143 		 *  direct eval code.  There is no direct correspondence to the
80144 		 *  E5 specification, as global/eval code is not exposed as a
80145 		 *  function.
80146 		 */
80147 
80148 		DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(&fun_temp->obj));
80149 
80150 		DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, outer_lex_env);
80151 		DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, outer_var_env);
80152 		DUK_HOBJECT_INCREF(thr, outer_lex_env);  /* NULLs not allowed; asserted on entry */
80153 		DUK_HOBJECT_INCREF(thr, outer_var_env);
80154 	}
80155 	DUK_DDD(DUK_DDDPRINT("closure varenv -> %!ipO, lexenv -> %!ipO",
80156 	                     (duk_heaphdr *) fun_clos->var_env,
80157 	                     (duk_heaphdr *) fun_clos->lex_env));
80158 
80159 	/* Call handling assumes this for all callable closures. */
80160 	DUK_ASSERT(DUK_HCOMPFUNC_GET_LEXENV(thr->heap, fun_clos) != NULL);
80161 	DUK_ASSERT(DUK_HCOMPFUNC_GET_VARENV(thr->heap, fun_clos) != NULL);
80162 
80163 	/*
80164 	 *  Copy some internal properties directly
80165 	 *
80166 	 *  The properties will be non-writable and non-enumerable, but
80167 	 *  configurable.
80168 	 */
80169 
80170 	/* [ ... closure template ] */
80171 
80172 	DUK_DDD(DUK_DDDPRINT("copying properties: closure=%!iT, template=%!iT",
80173 	                     (duk_tval *) duk_get_tval(thr, -2),
80174 	                     (duk_tval *) duk_get_tval(thr, -1)));
80175 
80176 	for (i = 0; i < (duk_small_uint_t) (sizeof(duk__closure_copy_proplist) / sizeof(duk_uint16_t)); i++) {
80177 		duk_small_int_t stridx = (duk_small_int_t) duk__closure_copy_proplist[i];
80178 		if (duk_get_prop_stridx_short(thr, -1, stridx)) {
80179 			/* [ ... closure template val ] */
80180 			DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> found", (long) stridx));
80181 			duk_xdef_prop_stridx_short(thr, -3, stridx, DUK_PROPDESC_FLAGS_C);
80182 		} else {
80183 			DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> not found", (long) stridx));
80184 			duk_pop_unsafe(thr);
80185 		}
80186 	}
80187 
80188 	/*
80189 	 *  "length" maps to number of formals (E5 Section 13.2) for function
80190 	 *  declarations/expressions (non-bound functions).  Note that 'nargs'
80191 	 *  is NOT necessarily equal to the number of arguments.  Use length
80192 	 *  of _Formals; if missing, assume nargs matches .length.
80193 	 */
80194 
80195 	/* [ ... closure template ] */
80196 
80197 	/* XXX: these lookups should be just own property lookups instead of
80198 	 * looking up the inheritance chain.
80199 	 */
80200 	if (duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_FORMALS)) {
80201 		/* [ ... closure template formals ] */
80202 		len_value = (duk_uint_t) duk_get_length(thr, -1);  /* could access duk_harray directly, not important */
80203 		DUK_DD(DUK_DDPRINT("closure length from _Formals -> %ld", (long) len_value));
80204 	} else {
80205 		len_value = fun_temp->nargs;
80206 		DUK_DD(DUK_DDPRINT("closure length defaulted from nargs -> %ld", (long) len_value));
80207 	}
80208 	duk_pop_unsafe(thr);
80209 
80210 	duk_push_uint(thr, len_value);  /* [ ... closure template len_value ] */
80211 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
80212 
80213 	/*
80214 	 *  "prototype" is, by default, a fresh object with the "constructor"
80215 	 *  property.
80216 	 *
80217 	 *  Note that this creates a circular reference for every function
80218 	 *  instance (closure) which prevents refcount-based collection of
80219 	 *  function instances.
80220 	 *
80221 	 *  XXX: Try to avoid creating the default prototype object, because
80222 	 *  many functions are not used as constructors and the default
80223 	 *  prototype is unnecessary.  Perhaps it could be created on-demand
80224 	 *  when it is first accessed?
80225 	 */
80226 
80227 	/* [ ... closure template ] */
80228 
80229 	if (add_auto_proto) {
80230 		duk_push_object(thr);  /* -> [ ... closure template newobj ] */
80231 		duk_dup_m3(thr);       /* -> [ ... closure template newobj closure ] */
80232 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);  /* -> [ ... closure template newobj ] */
80233 		duk_compact(thr, -1);  /* compact the prototype */
80234 		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);     /* -> [ ... closure template ] */
80235 	}
80236 
80237 	/*
80238 	 *  "arguments" and "caller" must be mapped to throwers for strict
80239 	 *  mode and bound functions (E5 Section 15.3.5).
80240 	 *
80241 	 *  XXX: This is expensive to have for every strict function instance.
80242 	 *  Try to implement as virtual properties or on-demand created properties.
80243 	 */
80244 
80245 	/* [ ... closure template ] */
80246 
80247 	if (DUK_HOBJECT_HAS_STRICT(&fun_clos->obj)) {
80248 		duk_xdef_prop_stridx_thrower(thr, -2, DUK_STRIDX_CALLER);
80249 		duk_xdef_prop_stridx_thrower(thr, -2, DUK_STRIDX_LC_ARGUMENTS);
80250 	} else {
80251 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
80252 		DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property in use, add initial 'null' value"));
80253 		duk_push_null(thr);
80254 		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE);
80255 #else
80256 		DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property not used"));
80257 #endif
80258 	}
80259 
80260 	/*
80261 	 *  "name" used to be non-standard but is now defined by ES2015.
80262 	 *  In ES2015/ES2016 the .name property is configurable.
80263 	 */
80264 
80265 	/* [ ... closure template ] */
80266 
80267 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
80268 	/* XXX: Look for own property only; doesn't matter much because
80269 	 * templates are bare objects.
80270 	 */
80271 	if (duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME)) {
80272 		/* [ ... closure template name ] */
80273 		DUK_ASSERT(duk_is_string(thr, -1));
80274 		DUK_DD(DUK_DDPRINT("setting function instance name to %!T", duk_get_tval(thr, -1)));
80275 		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);  /* -> [ ... closure template ] */
80276 	} else {
80277 		/* Anonymous functions don't have a .name in ES2015, so don't set
80278 		 * it on the instance either.  The instance will then inherit
80279 		 * it from Function.prototype.name.
80280 		 */
80281 		DUK_DD(DUK_DDPRINT("not setting function instance .name"));
80282 		duk_pop_unsafe(thr);
80283 	}
80284 #endif
80285 
80286 	/*
80287 	 *  Compact the closure, in most cases no properties will be added later.
80288 	 *  Also, without this the closures end up having unused property slots
80289 	 *  (e.g. in Duktape 0.9.0, 8 slots would be allocated and only 7 used).
80290 	 *  A better future solution would be to allocate the closure directly
80291 	 *  to correct size (and setup the properties directly without going
80292 	 *  through the API).
80293 	 */
80294 
80295 	duk_compact(thr, -2);
80296 
80297 	/*
80298 	 *  Some assertions (E5 Section 13.2).
80299 	 */
80300 
80301 	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(&fun_clos->obj) == DUK_HOBJECT_CLASS_FUNCTION);
80302 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, &fun_clos->obj) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
80303 	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));
80304 	DUK_ASSERT(duk_has_prop_stridx(thr, -2, DUK_STRIDX_LENGTH) != 0);
80305 	DUK_ASSERT(add_auto_proto == 0 || duk_has_prop_stridx(thr, -2, DUK_STRIDX_PROTOTYPE) != 0);
80306 	/* May be missing .name */
80307 	DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
80308 	           duk_has_prop_stridx(thr, -2, DUK_STRIDX_CALLER) != 0);
80309 	DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
80310 	           duk_has_prop_stridx(thr, -2, DUK_STRIDX_LC_ARGUMENTS) != 0);
80311 
80312 	/*
80313 	 *  Finish
80314 	 */
80315 
80316 	/* [ ... closure template ] */
80317 
80318 	DUK_DDD(DUK_DDDPRINT("created function instance: template=%!iT -> closure=%!iT",
80319 	                     (duk_tval *) duk_get_tval(thr, -1),
80320 	                     (duk_tval *) duk_get_tval(thr, -2)));
80321 
80322 	duk_pop_unsafe(thr);
80323 
80324 	/* [ ... closure ] */
80325 }
80326 
80327 /*
80328  *  Delayed activation environment record initialization (for functions
80329  *  with NEWENV).
80330  *
80331  *  The non-delayed initialization is handled by duk_handle_call().
80332  */
80333 
80334 /* shared helper */
80335 DUK_INTERNAL
80336 duk_hobject *duk_create_activation_environment_record(duk_hthread *thr,
80337                                                       duk_hobject *func,
80338                                                       duk_size_t bottom_byteoff) {
80339 	duk_hdecenv *env;
80340 	duk_hobject *parent;
80341 	duk_hcompfunc *f;
80342 
80343 	DUK_ASSERT(thr != NULL);
80344 	DUK_ASSERT(func != NULL);
80345 
80346 	f = (duk_hcompfunc *) func;
80347 	parent = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
80348 	if (!parent) {
80349 		parent = thr->builtins[DUK_BIDX_GLOBAL_ENV];
80350 	}
80351 
80352 	env = duk_hdecenv_alloc(thr,
80353 	                        DUK_HOBJECT_FLAG_EXTENSIBLE |
80354 	                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
80355 	DUK_ASSERT(env != NULL);
80356 	duk_push_hobject(thr, (duk_hobject *) env);
80357 
80358 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
80359 	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) env, parent);
80360 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, parent);  /* parent env is the prototype */
80361 
80362 	/* open scope information, for compiled functions only */
80363 
80364 	DUK_ASSERT(env->thread == NULL);
80365 	DUK_ASSERT(env->varmap == NULL);
80366 	DUK_ASSERT(env->regbase_byteoff == 0);
80367 	if (DUK_HOBJECT_IS_COMPFUNC(func)) {
80368 		duk_hobject *varmap;
80369 		duk_tval *tv;
80370 
80371 		tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
80372 		if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
80373 			DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
80374 			varmap = DUK_TVAL_GET_OBJECT(tv);
80375 			DUK_ASSERT(varmap != NULL);
80376 			env->varmap = varmap;
80377 			DUK_HOBJECT_INCREF(thr, varmap);
80378 			env->thread = thr;
80379 			DUK_HTHREAD_INCREF(thr, thr);
80380 			env->regbase_byteoff = bottom_byteoff;
80381 		} else {
80382 			/* If function has no _Varmap, leave the environment closed. */
80383 			DUK_ASSERT(env->thread == NULL);
80384 			DUK_ASSERT(env->varmap == NULL);
80385 			DUK_ASSERT(env->regbase_byteoff == 0);
80386 		}
80387 	}
80388 
80389 	return (duk_hobject *) env;
80390 }
80391 
80392 DUK_INTERNAL
80393 void duk_js_init_activation_environment_records_delayed(duk_hthread *thr,
80394                                                         duk_activation *act) {
80395 	duk_hobject *func;
80396 	duk_hobject *env;
80397 
80398 	DUK_ASSERT(thr != NULL);
80399 	func = DUK_ACT_GET_FUNC(act);
80400 	DUK_ASSERT(func != NULL);
80401 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound functions are never in act 'func' */
80402 
80403 	/*
80404 	 *  Delayed initialization only occurs for 'NEWENV' functions.
80405 	 */
80406 
80407 	DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
80408 	DUK_ASSERT(act->lex_env == NULL);
80409 	DUK_ASSERT(act->var_env == NULL);
80410 
80411 	env = duk_create_activation_environment_record(thr, func, act->bottom_byteoff);
80412 	DUK_ASSERT(env != NULL);
80413 	/* 'act' is a stable pointer, so still OK. */
80414 
80415 	DUK_DDD(DUK_DDDPRINT("created delayed fresh env: %!ipO", (duk_heaphdr *) env));
80416 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
80417 	{
80418 		duk_hobject *p = env;
80419 		while (p) {
80420 			DUK_DDD(DUK_DDDPRINT("  -> %!ipO", (duk_heaphdr *) p));
80421 			p = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, p);
80422 		}
80423 	}
80424 #endif
80425 
80426 	act->lex_env = env;
80427 	act->var_env = env;
80428 	DUK_HOBJECT_INCREF(thr, env);  /* XXX: incref by count (here 2 times) */
80429 	DUK_HOBJECT_INCREF(thr, env);
80430 
80431 	duk_pop_unsafe(thr);
80432 }
80433 
80434 /*
80435  *  Closing environment records.
80436  *
80437  *  The environment record MUST be closed with the thread where its activation
80438  *  is; i.e. if 'env' is open, 'thr' must match env->thread, and the regbase
80439  *  and varmap must still be valid.  On entry, 'env' must be reachable.
80440  */
80441 
80442 DUK_INTERNAL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env) {
80443 	duk_uint_fast32_t i;
80444 	duk_hobject *varmap;
80445 	duk_hstring *key;
80446 	duk_tval *tv;
80447 	duk_uint_t regnum;
80448 
80449 	DUK_ASSERT(thr != NULL);
80450 	DUK_ASSERT(env != NULL);
80451 
80452 	if (DUK_UNLIKELY(!DUK_HOBJECT_IS_DECENV(env))) {
80453 		DUK_DDD(DUK_DDDPRINT("env not a declarative record: %!iO", (duk_heaphdr *) env));
80454 		return;
80455 	}
80456 
80457 	varmap = ((duk_hdecenv *) env)->varmap;
80458 	if (varmap == NULL) {
80459 		DUK_DDD(DUK_DDDPRINT("env already closed: %!iO", (duk_heaphdr *) env));
80460 
80461 		return;
80462 	}
80463 	DUK_ASSERT(((duk_hdecenv *) env)->thread != NULL);
80464 	DUK_ASSERT_HDECENV_VALID((duk_hdecenv *) env);
80465 
80466 	DUK_DDD(DUK_DDDPRINT("closing env: %!iO", (duk_heaphdr *) env));
80467 	DUK_DDD(DUK_DDDPRINT("varmap: %!O", (duk_heaphdr *) varmap));
80468 
80469 	/* Env must be closed in the same thread as where it runs. */
80470 	DUK_ASSERT(((duk_hdecenv *) env)->thread == thr);
80471 
80472 	/* XXX: additional conditions when to close variables? we don't want to do it
80473 	 * unless the environment may have "escaped" (referenced in a function closure).
80474 	 * With delayed environments, the existence is probably good enough of a check.
80475 	 */
80476 
80477 	/* Note: we rely on the _Varmap having a bunch of nice properties, like:
80478 	 *  - being compacted and unmodified during this process
80479 	 *  - not containing an array part
80480 	 *  - having correct value types
80481 	 */
80482 
80483 	DUK_DDD(DUK_DDDPRINT("copying bound register values, %ld bound regs", (long) DUK_HOBJECT_GET_ENEXT(varmap)));
80484 
80485 	/* Copy over current variable values from value stack to the
80486 	 * environment record.  The scope object is empty but may
80487 	 * inherit from another scope which has conflicting names.
80488 	 */
80489 
80490 	/* XXX: Do this using a once allocated entry area, no side effects.
80491 	 * Hash part would need special treatment however (maybe copy, and
80492 	 * then realloc with hash part if large enough).
80493 	 */
80494 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(varmap); i++) {
80495 		duk_size_t regbase_byteoff;
80496 
80497 		key = DUK_HOBJECT_E_GET_KEY(thr->heap, varmap, i);
80498 		DUK_ASSERT(key != NULL);   /* assume keys are compact in _Varmap */
80499 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i));  /* assume plain values */
80500 
80501 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, varmap, i);
80502 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
80503 		DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (duk_double_t) DUK_UINT32_MAX);  /* limits */
80504 #if defined(DUK_USE_FASTINT)
80505 		DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
80506 		regnum = (duk_uint_t) DUK_TVAL_GET_FASTINT_U32(tv);
80507 #else
80508 		regnum = (duk_uint_t) DUK_TVAL_GET_NUMBER(tv);
80509 #endif
80510 
80511 		regbase_byteoff = ((duk_hdecenv *) env)->regbase_byteoff;
80512 		DUK_ASSERT((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum >= (duk_uint8_t *) thr->valstack);
80513 		DUK_ASSERT((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum < (duk_uint8_t *) thr->valstack_top);
80514 
80515 		/* If property already exists, overwrites silently.
80516 		 * Property is writable, but not deletable (not configurable
80517 		 * in terms of property attributes).
80518 		 */
80519 		duk_push_tval(thr, (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum));
80520 		DUK_DDD(DUK_DDDPRINT("closing identifier %!O -> reg %ld, value %!T",
80521 		                     (duk_heaphdr *) key,
80522 		                     (long) regnum,
80523 		                     (duk_tval *) duk_get_tval(thr, -1)));
80524 		duk_hobject_define_property_internal(thr, env, key, DUK_PROPDESC_FLAGS_WE);
80525 	}
80526 
80527 	/* NULL atomically to avoid inconsistent state + side effects. */
80528 	DUK_HOBJECT_DECREF_NORZ(thr, ((duk_hdecenv *) env)->thread);
80529 	DUK_HOBJECT_DECREF_NORZ(thr, ((duk_hdecenv *) env)->varmap);
80530 	((duk_hdecenv *) env)->thread = NULL;
80531 	((duk_hdecenv *) env)->varmap = NULL;
80532 
80533 	DUK_DDD(DUK_DDDPRINT("env after closing: %!O", (duk_heaphdr *) env));
80534 }
80535 
80536 /*
80537  *  GETIDREF: a GetIdentifierReference-like helper.
80538  *
80539  *  Provides a parent traversing lookup and a single level lookup
80540  *  (for HasBinding).
80541  *
80542  *  Instead of returning the value, returns a bunch of values allowing
80543  *  the caller to read, write, or delete the binding.  Value pointers
80544  *  are duk_tval pointers which can be mutated directly as long as
80545  *  refcounts are properly updated.  Note that any operation which may
80546  *  reallocate valstacks or compact objects may invalidate the returned
80547  *  duk_tval (but not object) pointers, so caller must be very careful.
80548  *
80549  *  If starting environment record 'env' is given, 'act' is ignored.
80550  *  However, if 'env' is NULL, the caller may identify, in 'act', an
80551  *  activation which hasn't had its declarative environment initialized
80552  *  yet.  The activation registers are then looked up, and its parent
80553  *  traversed normally.
80554  *
80555  *  The 'out' structure values are only valid if the function returns
80556  *  success (non-zero).
80557  */
80558 
80559 /* lookup name from an open declarative record's registers */
80560 DUK_LOCAL
80561 duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,
80562                                          duk_hstring *name,
80563                                          duk_hdecenv *env,
80564                                          duk__id_lookup_result *out) {
80565 	duk_tval *tv;
80566 	duk_size_t reg_rel;
80567 
80568 	DUK_ASSERT(thr != NULL);
80569 	DUK_ASSERT(name != NULL);
80570 	DUK_ASSERT(env != NULL);
80571 	DUK_ASSERT(out != NULL);
80572 
80573 	DUK_ASSERT(DUK_HOBJECT_IS_DECENV((duk_hobject *) env));
80574 	DUK_ASSERT_HDECENV_VALID(env);
80575 
80576 	if (env->thread == NULL) {
80577 		/* already closed */
80578 		return 0;
80579 	}
80580 	DUK_ASSERT(env->varmap != NULL);
80581 
80582 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env->varmap, name);
80583 	if (DUK_UNLIKELY(tv == NULL)) {
80584 		return 0;
80585 	}
80586 
80587 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
80588 	DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (duk_double_t) DUK_UINT32_MAX);  /* limits */
80589 #if defined(DUK_USE_FASTINT)
80590 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
80591 	reg_rel = (duk_size_t) DUK_TVAL_GET_FASTINT_U32(tv);
80592 #else
80593 	reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
80594 #endif
80595 	DUK_ASSERT_DISABLE(reg_rel >= 0);  /* unsigned */
80596 
80597 	tv = (duk_tval *) (void *) ((duk_uint8_t *) env->thread->valstack + env->regbase_byteoff + sizeof(duk_tval) * reg_rel);
80598 	DUK_ASSERT(tv >= env->thread->valstack && tv < env->thread->valstack_end);  /* XXX: more accurate? */
80599 
80600 	out->value = tv;
80601 	out->attrs = DUK_PROPDESC_FLAGS_W;  /* registers are mutable, non-deletable */
80602 	out->env = (duk_hobject *) env;
80603 	out->holder = NULL;
80604 	out->has_this = 0;
80605 	return 1;
80606 }
80607 
80608 /* lookup name from current activation record's functions' registers */
80609 DUK_LOCAL
80610 duk_bool_t duk__getid_activation_regs(duk_hthread *thr,
80611                                       duk_hstring *name,
80612                                       duk_activation *act,
80613                                       duk__id_lookup_result *out) {
80614 	duk_tval *tv;
80615 	duk_hobject *func;
80616 	duk_hobject *varmap;
80617 	duk_size_t reg_rel;
80618 
80619 	DUK_ASSERT(thr != NULL);
80620 	DUK_ASSERT(name != NULL);
80621 	DUK_ASSERT(act != NULL);
80622 	DUK_ASSERT(out != NULL);
80623 
80624 	func = DUK_ACT_GET_FUNC(act);
80625 	DUK_ASSERT(func != NULL);
80626 	DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
80627 
80628 	if (!DUK_HOBJECT_IS_COMPFUNC(func)) {
80629 		return 0;
80630 	}
80631 
80632 	/* XXX: move varmap to duk_hcompfunc struct field. */
80633 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
80634 	if (!tv) {
80635 		return 0;
80636 	}
80637 	DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
80638 	varmap = DUK_TVAL_GET_OBJECT(tv);
80639 	DUK_ASSERT(varmap != NULL);
80640 
80641 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, varmap, name);
80642 	if (!tv) {
80643 		return 0;
80644 	}
80645 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
80646 	reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
80647 	DUK_ASSERT_DISABLE(reg_rel >= 0);
80648 	DUK_ASSERT(reg_rel < ((duk_hcompfunc *) func)->nregs);
80649 
80650 	tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
80651 	tv += reg_rel;
80652 
80653 	out->value = tv;
80654 	out->attrs = DUK_PROPDESC_FLAGS_W;  /* registers are mutable, non-deletable */
80655 	out->env = NULL;
80656 	out->holder = NULL;
80657 	out->has_this = 0;
80658 	return 1;
80659 }
80660 
80661 DUK_LOCAL
80662 duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
80663                                          duk_hobject *env,
80664                                          duk_hstring *name,
80665                                          duk_activation *act,
80666                                          duk_bool_t parents,
80667                                          duk__id_lookup_result *out) {
80668 	duk_tval *tv;
80669 	duk_uint_t sanity;
80670 
80671 	DUK_ASSERT(thr != NULL);
80672 	DUK_ASSERT(env != NULL || act != NULL);
80673 	DUK_ASSERT(name != NULL);
80674 	DUK_ASSERT(out != NULL);
80675 
80676 	DUK_ASSERT(!env || DUK_HOBJECT_IS_ENV(env));
80677 	DUK_ASSERT(!env || !DUK_HOBJECT_HAS_ARRAY_PART(env));
80678 
80679 	/*
80680 	 *  Conceptually, we look for the identifier binding by starting from
80681 	 *  'env' and following to chain of environment records (represented
80682 	 *  by the prototype chain).
80683 	 *
80684 	 *  If 'env' is NULL, the current activation does not yet have an
80685 	 *  allocated declarative environment record; this should be treated
80686 	 *  exactly as if the environment record existed but had no bindings
80687 	 *  other than register bindings.
80688 	 *
80689 	 *  Note: we assume that with the DUK_HOBJECT_FLAG_NEWENV cleared
80690 	 *  the environment will always be initialized immediately; hence
80691 	 *  a NULL 'env' should only happen with the flag set.  This is the
80692 	 *  case for: (1) function calls, and (2) strict, direct eval calls.
80693 	 */
80694 
80695 	if (env == NULL && act != NULL) {
80696 		duk_hobject *func;
80697 		duk_hcompfunc *f;
80698 
80699 		DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference: env is NULL, activation is non-NULL -> "
80700 		                     "delayed env case, look up activation regs first"));
80701 
80702 		/*
80703 		 *  Try registers
80704 		 */
80705 
80706 		if (duk__getid_activation_regs(thr, name, act, out)) {
80707 			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
80708 			                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
80709 			                     "(found from register bindings when env=NULL)",
80710 			                     (duk_heaphdr *) name, (duk_tval *) out->value,
80711 			                     (long) out->attrs, (long) out->has_this,
80712 			                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
80713 			return 1;
80714 		}
80715 
80716 		DUK_DDD(DUK_DDDPRINT("not found in current activation regs"));
80717 
80718 		/*
80719 		 *  Not found in registers, proceed to the parent record.
80720 		 *  Here we need to determine what the parent would be,
80721 		 *  if 'env' was not NULL (i.e. same logic as when initializing
80722 		 *  the record).
80723 		 *
80724 		 *  Note that environment initialization is only deferred when
80725 		 *  DUK_HOBJECT_HAS_NEWENV is set, and this only happens for:
80726 		 *    - Function code
80727 		 *    - Strict eval code
80728 		 *
80729 		 *  We only need to check _Lexenv here; _Varenv exists only if it
80730 		 *  differs from _Lexenv (and thus _Lexenv will also be present).
80731 		 */
80732 
80733 		if (!parents) {
80734 			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
80735 			                     "(not found from register bindings when env=NULL)"));
80736 			goto fail_not_found;
80737 		}
80738 
80739 		func = DUK_ACT_GET_FUNC(act);
80740 		DUK_ASSERT(func != NULL);
80741 		DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
80742 		f = (duk_hcompfunc *) func;
80743 
80744 		env = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
80745 		if (!env) {
80746 			env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
80747 		}
80748 
80749 		DUK_DDD(DUK_DDDPRINT("continue lookup from env: %!iO",
80750 		                     (duk_heaphdr *) env));
80751 	}
80752 
80753 	/*
80754 	 *  Prototype walking starting from 'env'.
80755 	 *
80756 	 *  ('act' is not needed anywhere here.)
80757 	 */
80758 
80759 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
80760 	while (env != NULL) {
80761 		duk_small_uint_t cl;
80762 		duk_uint_t attrs;
80763 
80764 		DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference, name=%!O, considering env=%p -> %!iO",
80765 		                     (duk_heaphdr *) name,
80766 		                     (void *) env,
80767 		                     (duk_heaphdr *) env));
80768 
80769 		DUK_ASSERT(env != NULL);
80770 		DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
80771 		DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(env));
80772 
80773 		cl = DUK_HOBJECT_GET_CLASS_NUMBER(env);
80774 		DUK_ASSERT(cl == DUK_HOBJECT_CLASS_OBJENV || cl == DUK_HOBJECT_CLASS_DECENV);
80775 		if (cl == DUK_HOBJECT_CLASS_DECENV) {
80776 			/*
80777 			 *  Declarative environment record.
80778 			 *
80779 			 *  Identifiers can never be stored in ancestors and are
80780 			 *  always plain values, so we can use an internal helper
80781 			 *  and access the value directly with an duk_tval ptr.
80782 			 *
80783 			 *  A closed environment is only indicated by it missing
80784 			 *  the "book-keeping" properties required for accessing
80785 			 *  register-bound variables.
80786 			 */
80787 
80788 			DUK_ASSERT_HDECENV_VALID((duk_hdecenv *) env);
80789 			if (duk__getid_open_decl_env_regs(thr, name, (duk_hdecenv *) env, out)) {
80790 				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
80791 				                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
80792 				                     "(declarative environment record, scope open, found in regs)",
80793 				                     (duk_heaphdr *) name, (duk_tval *) out->value,
80794 				                     (long) out->attrs, (long) out->has_this,
80795 				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
80796 				return 1;
80797 			}
80798 
80799 			tv = duk_hobject_find_existing_entry_tval_ptr_and_attrs(thr->heap, env, name, &attrs);
80800 			if (tv) {
80801 				out->value = tv;
80802 				out->attrs = attrs;
80803 				out->env = env;
80804 				out->holder = env;
80805 				out->has_this = 0;
80806 
80807 				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
80808 				                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
80809 				                     "(declarative environment record, found in properties)",
80810 				                     (duk_heaphdr *) name, (duk_tval *) out->value,
80811 				                     (long) out->attrs, (long) out->has_this,
80812 				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
80813 				return 1;
80814 			}
80815 		} else {
80816 			/*
80817 			 *  Object environment record.
80818 			 *
80819 			 *  Binding (target) object is an external, uncontrolled object.
80820 			 *  Identifier may be bound in an ancestor property, and may be
80821 			 *  an accessor.  Target can also be a Proxy which we must support
80822 			 *  here.
80823 			 */
80824 
80825 			/* XXX: we could save space by using _Target OR _This.  If _Target, assume
80826 			 * this binding is undefined.  If _This, assumes this binding is _This, and
80827 			 * target is also _This.  One property would then be enough.
80828 			 */
80829 
80830 			duk_hobject *target;
80831 			duk_bool_t found;
80832 
80833 			DUK_ASSERT(cl == DUK_HOBJECT_CLASS_OBJENV);
80834 			DUK_ASSERT_HOBJENV_VALID((duk_hobjenv *) env);
80835 
80836 			target = ((duk_hobjenv *) env)->target;
80837 			DUK_ASSERT(target != NULL);
80838 
80839 			/* Target may be a Proxy or property may be an accessor, so we must
80840 			 * use an actual, Proxy-aware hasprop check here.
80841 			 *
80842 			 * out->holder is NOT set to the actual duk_hobject where the
80843 			 * property is found, but rather the object binding target object.
80844 			 */
80845 
80846 #if defined(DUK_USE_ES6_PROXY)
80847 			if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(target))) {
80848 				duk_tval tv_name;
80849 				duk_tval tv_target_tmp;
80850 
80851 				DUK_ASSERT(name != NULL);
80852 				DUK_TVAL_SET_STRING(&tv_name, name);
80853 				DUK_TVAL_SET_OBJECT(&tv_target_tmp, target);
80854 
80855 				found = duk_hobject_hasprop(thr, &tv_target_tmp, &tv_name);
80856 			} else
80857 #endif  /* DUK_USE_ES6_PROXY */
80858 			{
80859 				/* XXX: duk_hobject_hasprop() would be correct for
80860 				 * non-Proxy objects too, but it is about ~20-25%
80861 				 * slower at present so separate code paths for
80862 				 * Proxy and non-Proxy now.
80863 				 */
80864 				found = duk_hobject_hasprop_raw(thr, target, name);
80865 			}
80866 
80867 			if (found) {
80868 				out->value = NULL;  /* can't get value, may be accessor */
80869 				out->attrs = 0;     /* irrelevant when out->value == NULL */
80870 				out->env = env;
80871 				out->holder = target;
80872 				out->has_this = ((duk_hobjenv *) env)->has_this;
80873 
80874 				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
80875 				                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
80876 				                     "(object environment record)",
80877 				                     (duk_heaphdr *) name, (duk_tval *) out->value,
80878 				                     (long) out->attrs, (long) out->has_this,
80879 				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
80880 				return 1;
80881 			}
80882 		}
80883 
80884 		if (!parents) {
80885 			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
80886 			                     "(not found from first traversed env)"));
80887 			goto fail_not_found;
80888 		}
80889 
80890                 if (DUK_UNLIKELY(sanity-- == 0)) {
80891                         DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
80892 			DUK_WO_NORETURN(return 0;);
80893                 }
80894 		env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);
80895 	}
80896 
80897 	/*
80898 	 *  Not found (even in global object)
80899 	 */
80900 
80901  fail_not_found:
80902 	return 0;
80903 }
80904 
80905 /*
80906  *  HASVAR: check identifier binding from a given environment record
80907  *  without traversing its parents.
80908  *
80909  *  This primitive is not exposed to user code as such, but is used
80910  *  internally for e.g. declaration binding instantiation.
80911  *
80912  *  See E5 Sections:
80913  *    10.2.1.1.1 HasBinding(N)
80914  *    10.2.1.2.1 HasBinding(N)
80915  *
80916  *  Note: strictness has no bearing on this check.  Hence we don't take
80917  *  a 'strict' parameter.
80918  */
80919 
80920 #if 0  /*unused*/
80921 DUK_INTERNAL
80922 duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr,
80923                                 duk_hobject *env,
80924                                 duk_hstring *name) {
80925 	duk__id_lookup_result ref;
80926 	duk_bool_t parents;
80927 
80928 	DUK_DDD(DUK_DDDPRINT("hasvar: thr=%p, env=%p, name=%!O "
80929 	                     "(env -> %!dO)",
80930 	                     (void *) thr, (void *) env, (duk_heaphdr *) name,
80931 	                     (duk_heaphdr *) env));
80932 
80933 	DUK_ASSERT(thr != NULL);
80934 	DUK_ASSERT(env != NULL);
80935 	DUK_ASSERT(name != NULL);
80936 
80937         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
80938         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
80939 
80940 	DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
80941 	DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(env));
80942 
80943 	/* lookup results is ignored */
80944 	parents = 0;
80945 	return duk__get_identifier_reference(thr, env, name, NULL, parents, &ref);
80946 }
80947 #endif
80948 
80949 /*
80950  *  GETVAR
80951  *
80952  *  See E5 Sections:
80953  *    11.1.2 Identifier Reference
80954  *    10.3.1 Identifier Resolution
80955  *    11.13.1 Simple Assignment  [example of where the Reference is GetValue'd]
80956  *    8.7.1 GetValue (V)
80957  *    8.12.1 [[GetOwnProperty]] (P)
80958  *    8.12.2 [[GetProperty]] (P)
80959  *    8.12.3 [[Get]] (P)
80960  *
80961  *  If 'throw' is true, always leaves two values on top of stack: [val this].
80962  *
80963  *  If 'throw' is false, returns 0 if identifier cannot be resolved, and the
80964  *  stack will be unaffected in this case.  If identifier is resolved, returns
80965  *  1 and leaves [val this] on top of stack.
80966  *
80967  *  Note: the 'strict' flag of a reference returned by GetIdentifierReference
80968  *  is ignored by GetValue.  Hence we don't take a 'strict' parameter.
80969  *
80970  *  The 'throw' flag is needed for implementing 'typeof' for an unreferenced
80971  *  identifier.  An unreference identifier in other contexts generates a
80972  *  ReferenceError.
80973  */
80974 
80975 DUK_LOCAL
80976 duk_bool_t duk__getvar_helper(duk_hthread *thr,
80977                               duk_hobject *env,
80978                               duk_activation *act,
80979                               duk_hstring *name,
80980                               duk_bool_t throw_flag) {
80981 	duk__id_lookup_result ref;
80982 	duk_tval tv_tmp_obj;
80983 	duk_tval tv_tmp_key;
80984 	duk_bool_t parents;
80985 
80986 	DUK_DDD(DUK_DDDPRINT("getvar: thr=%p, env=%p, act=%p, name=%!O "
80987 	                     "(env -> %!dO)",
80988 	                     (void *) thr, (void *) env, (void *) act,
80989 	                     (duk_heaphdr *) name, (duk_heaphdr *) env));
80990 
80991 	DUK_ASSERT(thr != NULL);
80992 	DUK_ASSERT(name != NULL);
80993 	/* env and act may be NULL */
80994 
80995 	DUK_STATS_INC(thr->heap, stats_getvar_all);
80996 
80997         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
80998         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
80999 
81000 	parents = 1;     /* follow parent chain */
81001 	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
81002 		if (ref.value) {
81003 			duk_push_tval(thr, ref.value);
81004 			duk_push_undefined(thr);
81005 		} else {
81006 			DUK_ASSERT(ref.holder != NULL);
81007 
81008 			/* ref.holder is safe across the getprop call (even
81009 			 * with side effects) because 'env' is reachable and
81010 			 * ref.holder is a direct heap pointer.
81011 			 */
81012 
81013 			DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
81014 			DUK_TVAL_SET_STRING(&tv_tmp_key, name);
81015 			(void) duk_hobject_getprop(thr, &tv_tmp_obj, &tv_tmp_key);  /* [value] */
81016 
81017 			if (ref.has_this) {
81018 				duk_push_hobject(thr, ref.holder);
81019 			} else {
81020 				duk_push_undefined(thr);
81021 			}
81022 
81023 			/* [value this] */
81024 		}
81025 
81026 		return 1;
81027 	} else {
81028 		if (throw_flag) {
81029 			DUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR,
81030 			               "identifier '%s' undefined",
81031 			               (const char *) DUK_HSTRING_GET_DATA(name));
81032 			DUK_WO_NORETURN(return 0;);
81033 		}
81034 
81035 		return 0;
81036 	}
81037 }
81038 
81039 DUK_INTERNAL
81040 duk_bool_t duk_js_getvar_envrec(duk_hthread *thr,
81041                                 duk_hobject *env,
81042                                 duk_hstring *name,
81043                                 duk_bool_t throw_flag) {
81044 	return duk__getvar_helper(thr, env, NULL, name, throw_flag);
81045 }
81046 
81047 DUK_INTERNAL
81048 duk_bool_t duk_js_getvar_activation(duk_hthread *thr,
81049                                     duk_activation *act,
81050                                     duk_hstring *name,
81051                                     duk_bool_t throw_flag) {
81052 	DUK_ASSERT(act != NULL);
81053 	return duk__getvar_helper(thr, act->lex_env, act, name, throw_flag);
81054 }
81055 
81056 /*
81057  *  PUTVAR
81058  *
81059  *  See E5 Sections:
81060  *    11.1.2 Identifier Reference
81061  *    10.3.1 Identifier Resolution
81062  *    11.13.1 Simple Assignment  [example of where the Reference is PutValue'd]
81063  *    8.7.2 PutValue (V,W)  [see especially step 3.b, undefined -> automatic global in non-strict mode]
81064  *    8.12.4 [[CanPut]] (P)
81065  *    8.12.5 [[Put]] (P)
81066  *
81067  *  Note: may invalidate any valstack (or object) duk_tval pointers because
81068  *  putting a value may reallocate any object or any valstack.  Caller beware.
81069  */
81070 
81071 DUK_LOCAL
81072 void duk__putvar_helper(duk_hthread *thr,
81073                         duk_hobject *env,
81074                         duk_activation *act,
81075                         duk_hstring *name,
81076                         duk_tval *val,
81077                         duk_bool_t strict) {
81078 	duk__id_lookup_result ref;
81079 	duk_tval tv_tmp_obj;
81080 	duk_tval tv_tmp_key;
81081 	duk_bool_t parents;
81082 
81083 	DUK_STATS_INC(thr->heap, stats_putvar_all);
81084 
81085 	DUK_DDD(DUK_DDDPRINT("putvar: thr=%p, env=%p, act=%p, name=%!O, val=%p, strict=%ld "
81086 	                     "(env -> %!dO, val -> %!T)",
81087 	                     (void *) thr, (void *) env, (void *) act,
81088 	                     (duk_heaphdr *) name, (void *) val, (long) strict,
81089 	                     (duk_heaphdr *) env, (duk_tval *) val));
81090 
81091 	DUK_ASSERT(thr != NULL);
81092 	DUK_ASSERT(name != NULL);
81093 	DUK_ASSERT(val != NULL);
81094 	/* env and act may be NULL */
81095 
81096         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
81097         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
81098 	DUK_ASSERT_REFCOUNT_NONZERO_TVAL(val);
81099 
81100 	/*
81101 	 *  In strict mode E5 protects 'eval' and 'arguments' from being
81102 	 *  assigned to (or even declared anywhere).  Attempt to do so
81103 	 *  should result in a compile time SyntaxError.  See the internal
81104 	 *  design documentation for details.
81105 	 *
81106 	 *  Thus, we should never come here, run-time, for strict code,
81107 	 *  and name 'eval' or 'arguments'.
81108 	 */
81109 
81110 	DUK_ASSERT(!strict ||
81111 	           (name != DUK_HTHREAD_STRING_EVAL(thr) &&
81112 	            name != DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)));
81113 
81114 	/*
81115 	 *  Lookup variable and update in-place if found.
81116 	 */
81117 
81118 	parents = 1;     /* follow parent chain */
81119 
81120 	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
81121 		if (ref.value && (ref.attrs & DUK_PROPDESC_FLAG_WRITABLE)) {
81122 			/* Update duk_tval in-place if pointer provided and the
81123 			 * property is writable.  If the property is not writable
81124 			 * (immutable binding), use duk_hobject_putprop() which
81125 			 * will respect mutability.
81126 			 */
81127 			duk_tval *tv_val;
81128 
81129 			tv_val = ref.value;
81130 			DUK_ASSERT(tv_val != NULL);
81131 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv_val, val);  /* side effects */
81132 
81133 			/* ref.value invalidated here */
81134 		} else {
81135 			DUK_ASSERT(ref.holder != NULL);
81136 
81137 			DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
81138 			DUK_TVAL_SET_STRING(&tv_tmp_key, name);
81139 			(void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, strict);
81140 
81141 			/* ref.value invalidated here */
81142 		}
81143 
81144 		return;
81145 	}
81146 
81147 	/*
81148 	 *  Not found: write to global object (non-strict) or ReferenceError
81149 	 *  (strict); see E5 Section 8.7.2, step 3.
81150 	 */
81151 
81152 	if (strict) {
81153 		DUK_DDD(DUK_DDDPRINT("identifier binding not found, strict => reference error"));
81154 		DUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR,
81155 		               "identifier '%s' undefined",
81156 		               (const char *) DUK_HSTRING_GET_DATA(name));
81157 		DUK_WO_NORETURN(return;);
81158 	}
81159 
81160 	DUK_DDD(DUK_DDDPRINT("identifier binding not found, not strict => set to global"));
81161 
81162 	DUK_TVAL_SET_OBJECT(&tv_tmp_obj, thr->builtins[DUK_BIDX_GLOBAL]);
81163 	DUK_TVAL_SET_STRING(&tv_tmp_key, name);
81164 	(void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, 0);  /* 0 = no throw */
81165 
81166 	/* NB: 'val' may be invalidated here because put_value may realloc valstack,
81167 	 * caller beware.
81168 	 */
81169 }
81170 
81171 DUK_INTERNAL
81172 void duk_js_putvar_envrec(duk_hthread *thr,
81173                           duk_hobject *env,
81174                           duk_hstring *name,
81175                           duk_tval *val,
81176                           duk_bool_t strict) {
81177 	duk__putvar_helper(thr, env, NULL, name, val, strict);
81178 }
81179 
81180 DUK_INTERNAL
81181 void duk_js_putvar_activation(duk_hthread *thr,
81182                               duk_activation *act,
81183                               duk_hstring *name,
81184                               duk_tval *val,
81185                               duk_bool_t strict) {
81186 	DUK_ASSERT(act != NULL);
81187 	duk__putvar_helper(thr, act->lex_env, act, name, val, strict);
81188 }
81189 
81190 /*
81191  *  DELVAR
81192  *
81193  *  See E5 Sections:
81194  *    11.4.1 The delete operator
81195  *    10.2.1.1.5 DeleteBinding (N)  [declarative environment record]
81196  *    10.2.1.2.5 DeleteBinding (N)  [object environment record]
81197  *
81198  *  Variable bindings established inside eval() are deletable (configurable),
81199  *  other bindings are not, including variables declared in global level.
81200  *  Registers are always non-deletable, and the deletion of other bindings
81201  *  is controlled by the configurable flag.
81202  *
81203  *  For strict mode code, the 'delete' operator should fail with a compile
81204  *  time SyntaxError if applied to identifiers.  Hence, no strict mode
81205  *  run-time deletion of identifiers should ever happen.  This function
81206  *  should never be called from strict mode code!
81207  */
81208 
81209 DUK_LOCAL
81210 duk_bool_t duk__delvar_helper(duk_hthread *thr,
81211                               duk_hobject *env,
81212                               duk_activation *act,
81213                               duk_hstring *name) {
81214 	duk__id_lookup_result ref;
81215 	duk_bool_t parents;
81216 
81217 	DUK_DDD(DUK_DDDPRINT("delvar: thr=%p, env=%p, act=%p, name=%!O "
81218 	                     "(env -> %!dO)",
81219 	                     (void *) thr, (void *) env, (void *) act,
81220 	                     (duk_heaphdr *) name, (duk_heaphdr *) env));
81221 
81222 	DUK_ASSERT(thr != NULL);
81223 	DUK_ASSERT(name != NULL);
81224 	/* env and act may be NULL */
81225 
81226         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
81227 
81228 	parents = 1;     /* follow parent chain */
81229 
81230 	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
81231 		if (ref.value && !(ref.attrs & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
81232 			/* Identifier found in registers (always non-deletable)
81233 			 * or declarative environment record and non-configurable.
81234 			 */
81235 			return 0;
81236 		}
81237 		DUK_ASSERT(ref.holder != NULL);
81238 
81239 		return duk_hobject_delprop_raw(thr, ref.holder, name, 0);
81240 	}
81241 
81242 	/*
81243 	 *  Not found (even in global object).
81244 	 *
81245 	 *  In non-strict mode this is a silent SUCCESS (!), see E5 Section 11.4.1,
81246 	 *  step 3.b.  In strict mode this case is a compile time SyntaxError so
81247 	 *  we should not come here.
81248 	 */
81249 
81250 	DUK_DDD(DUK_DDDPRINT("identifier to be deleted not found: name=%!O "
81251 	                     "(treated as silent success)",
81252 	                     (duk_heaphdr *) name));
81253 	return 1;
81254 }
81255 
81256 #if 0  /*unused*/
81257 DUK_INTERNAL
81258 duk_bool_t duk_js_delvar_envrec(duk_hthread *thr,
81259                                 duk_hobject *env,
81260                                 duk_hstring *name) {
81261 	return duk__delvar_helper(thr, env, NULL, name);
81262 }
81263 #endif
81264 
81265 DUK_INTERNAL
81266 duk_bool_t duk_js_delvar_activation(duk_hthread *thr,
81267                                     duk_activation *act,
81268                                     duk_hstring *name) {
81269 	DUK_ASSERT(act != NULL);
81270 	return duk__delvar_helper(thr, act->lex_env, act, name);
81271 }
81272 
81273 /*
81274  *  DECLVAR
81275  *
81276  *  See E5 Sections:
81277  *    10.4.3 Entering Function Code
81278  *    10.5 Declaration Binding Instantion
81279  *    12.2 Variable Statement
81280  *    11.1.2 Identifier Reference
81281  *    10.3.1 Identifier Resolution
81282  *
81283  *  Variable declaration behavior is mainly discussed in Section 10.5,
81284  *  and is not discussed in the execution semantics (Sections 11-13).
81285  *
81286  *  Conceptually declarations happen when code (global, eval, function)
81287  *  is entered, before any user code is executed.  In practice, register-
81288  *  bound identifiers are 'declared' automatically (by virtue of being
81289  *  allocated to registers with the initial value 'undefined').  Other
81290  *  identifiers are declared in the function prologue with this primitive.
81291  *
81292  *  Since non-register bindings eventually back to an internal object's
81293  *  properties, the 'prop_flags' argument is used to specify binding
81294  *  type:
81295  *
81296  *    - Immutable binding: set DUK_PROPDESC_FLAG_WRITABLE to false
81297  *    - Non-deletable binding: set DUK_PROPDESC_FLAG_CONFIGURABLE to false
81298  *    - The flag DUK_PROPDESC_FLAG_ENUMERABLE should be set, although it
81299  *      doesn't really matter for internal objects
81300  *
81301  *  All bindings are non-deletable mutable bindings except:
81302  *
81303  *    - Declarations in eval code (mutable, deletable)
81304  *    - 'arguments' binding in strict function code (immutable)
81305  *    - Function name binding of a function expression (immutable)
81306  *
81307  *  Declarations may go to declarative environment records (always
81308  *  so for functions), but may also go to object environment records
81309  *  (e.g. global code).  The global object environment has special
81310  *  behavior when re-declaring a function (but not a variable); see
81311  *  E5.1 specification, Section 10.5, step 5.e.
81312  *
81313  *  Declarations always go to the 'top-most' environment record, i.e.
81314  *  we never check the record chain.  It's not an error even if a
81315  *  property (even an immutable or non-deletable one) of the same name
81316  *  already exists.
81317  *
81318  *  If a declared variable already exists, its value needs to be updated
81319  *  (if possible).  Returns 1 if a PUTVAR needs to be done by the caller;
81320  *  otherwise returns 0.
81321  */
81322 
81323 DUK_LOCAL
81324 duk_bool_t duk__declvar_helper(duk_hthread *thr,
81325                                duk_hobject *env,
81326                                duk_hstring *name,
81327                                duk_tval *val,
81328                                duk_small_uint_t prop_flags,
81329                                duk_bool_t is_func_decl) {
81330 	duk_hobject *holder;
81331 	duk_bool_t parents;
81332 	duk__id_lookup_result ref;
81333 	duk_tval *tv;
81334 
81335 	DUK_DDD(DUK_DDDPRINT("declvar: thr=%p, env=%p, name=%!O, val=%!T, prop_flags=0x%08lx, is_func_decl=%ld "
81336 	                     "(env -> %!iO)",
81337 	                     (void *) thr, (void *) env, (duk_heaphdr *) name,
81338 	                     (duk_tval *) val, (unsigned long) prop_flags,
81339 	                     (unsigned int) is_func_decl, (duk_heaphdr *) env));
81340 
81341 	DUK_ASSERT(thr != NULL);
81342 	DUK_ASSERT(env != NULL);
81343 	DUK_ASSERT(name != NULL);
81344 	DUK_ASSERT(val != NULL);
81345 
81346 	/* Note: in strict mode the compiler should reject explicit
81347 	 * declaration of 'eval' or 'arguments'.  However, internal
81348 	 * bytecode may declare 'arguments' in the function prologue.
81349 	 * We don't bother checking (or asserting) for these now.
81350 	 */
81351 
81352 	/* Note: val is a stable duk_tval pointer.  The caller makes
81353 	 * a value copy into its stack frame, so 'tv_val' is not subject
81354 	 * to side effects here.
81355 	 */
81356 
81357 	/*
81358 	 *  Check whether already declared.
81359 	 *
81360 	 *  We need to check whether the binding exists in the environment
81361 	 *  without walking its parents.  However, we still need to check
81362 	 *  register-bound identifiers and the prototype chain of an object
81363 	 *  environment target object.
81364 	 */
81365 
81366 	parents = 0;  /* just check 'env' */
81367 	if (duk__get_identifier_reference(thr, env, name, NULL, parents, &ref)) {
81368 		duk_int_t e_idx;
81369 		duk_int_t h_idx;
81370 		duk_small_uint_t flags;
81371 
81372 		/*
81373 		 *  Variable already declared, ignore re-declaration.
81374 		 *  The only exception is the updated behavior of E5.1 for
81375 		 *  global function declarations, E5.1 Section 10.5, step 5.e.
81376 		 *  This behavior does not apply to global variable declarations.
81377 		 */
81378 
81379 		if (!(is_func_decl && env == thr->builtins[DUK_BIDX_GLOBAL_ENV])) {
81380 			DUK_DDD(DUK_DDDPRINT("re-declare a binding, ignoring"));
81381 			return 1;  /* 1 -> needs a PUTVAR */
81382 		}
81383 
81384 		/*
81385 		 *  Special behavior in E5.1.
81386 		 *
81387 		 *  Note that even though parents == 0, the conflicting property
81388 		 *  may be an inherited property (currently our global object's
81389 		 *  prototype is Object.prototype).  Step 5.e first operates on
81390 		 *  the existing property (which is potentially in an ancestor)
81391 		 *  and then defines a new property in the global object (and
81392 		 *  never modifies the ancestor).
81393 		 *
81394 		 *  Also note that this logic would become even more complicated
81395 		 *  if the conflicting property might be a virtual one.  Object
81396 		 *  prototype has no virtual properties, though.
81397 		 *
81398 		 *  XXX: this is now very awkward, rework.
81399 		 */
81400 
81401 		DUK_DDD(DUK_DDDPRINT("re-declare a function binding in global object, "
81402 		                     "updated E5.1 processing"));
81403 
81404 		DUK_ASSERT(ref.holder != NULL);
81405 		holder = ref.holder;
81406 
81407 		/* holder will be set to the target object, not the actual object
81408 		 * where the property was found (see duk__get_identifier_reference()).
81409 		 */
81410 		DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(holder) == DUK_HOBJECT_CLASS_GLOBAL);
81411 		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(holder));  /* global object doesn't have array part */
81412 
81413 		/* XXX: use a helper for prototype traversal; no loop check here */
81414 		/* must be found: was found earlier, and cannot be inherited */
81415 		for (;;) {
81416 			DUK_ASSERT(holder != NULL);
81417 			if (duk_hobject_find_existing_entry(thr->heap, holder, name, &e_idx, &h_idx)) {
81418 				DUK_ASSERT(e_idx >= 0);
81419 				break;
81420 			}
81421 			/* SCANBUILD: NULL pointer dereference, doesn't actually trigger,
81422 			 * asserted above.
81423 			 */
81424 			holder = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, holder);
81425 		}
81426 		DUK_ASSERT(holder != NULL);
81427 		DUK_ASSERT(e_idx >= 0);
81428 		/* SCANBUILD: scan-build produces a NULL pointer dereference warning
81429 		 * below; it never actually triggers because holder is actually never
81430 		 * NULL.
81431 		 */
81432 
81433 		/* ref.holder is global object, holder is the object with the
81434 		 * conflicting property.
81435 		 */
81436 
81437 		flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, holder, e_idx);
81438 		if (!(flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
81439 			if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
81440 				DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
81441 				                     "accessor -> reject"));
81442 				goto fail_existing_attributes;
81443 			}
81444 			if (!((flags & DUK_PROPDESC_FLAG_WRITABLE) &&
81445 			      (flags & DUK_PROPDESC_FLAG_ENUMERABLE))) {
81446 				DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
81447 				                     "plain property which is not writable and "
81448 				                     "enumerable -> reject"));
81449 				goto fail_existing_attributes;
81450 			}
81451 
81452 			DUK_DDD(DUK_DDDPRINT("existing property is not configurable but "
81453 			                     "is plain, enumerable, and writable -> "
81454 			                     "allow redeclaration"));
81455 		}
81456 
81457 		if (holder == ref.holder) {
81458 			/* XXX: if duk_hobject_define_property_internal() was updated
81459 			 * to handle a pre-existing accessor property, this would be
81460 			 * a simple call (like for the ancestor case).
81461 			 */
81462 			DUK_DDD(DUK_DDDPRINT("redefine, offending property in global object itself"));
81463 
81464 			if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
81465 				duk_hobject *tmp;
81466 
81467 				tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, holder, e_idx);
81468 				DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, holder, e_idx, NULL);
81469 				DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
81470 				DUK_UNREF(tmp);
81471 				tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, holder, e_idx);
81472 				DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, holder, e_idx, NULL);
81473 				DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
81474 				DUK_UNREF(tmp);
81475 			} else {
81476 				tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
81477 				DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);
81478 			}
81479 
81480 			/* Here val would be potentially invalid if we didn't make
81481 			 * a value copy at the caller.
81482 			 */
81483 
81484 			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
81485 			DUK_TVAL_SET_TVAL(tv, val);
81486 			DUK_TVAL_INCREF(thr, tv);
81487 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, holder, e_idx, prop_flags);
81488 
81489 			DUK_DDD(DUK_DDDPRINT("updated global binding, final result: "
81490 			                     "value -> %!T, prop_flags=0x%08lx",
81491 			                     (duk_tval *) DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx),
81492 			                     (unsigned long) prop_flags));
81493 		} else {
81494 			DUK_DDD(DUK_DDDPRINT("redefine, offending property in ancestor"));
81495 
81496 			DUK_ASSERT(ref.holder == thr->builtins[DUK_BIDX_GLOBAL]);
81497 			duk_push_tval(thr, val);
81498 			duk_hobject_define_property_internal(thr, ref.holder, name, prop_flags);
81499 		}
81500 
81501 		return 0;
81502 	}
81503 
81504 	/*
81505 	 *  Not found (in registers or record objects).  Declare
81506 	 *  to current variable environment.
81507 	 */
81508 
81509 	/*
81510 	 *  Get holder object
81511 	 */
81512 
81513 	if (DUK_HOBJECT_IS_DECENV(env)) {
81514 		DUK_ASSERT_HDECENV_VALID((duk_hdecenv *) env);
81515 		holder = env;
81516 	} else {
81517 		DUK_ASSERT_HOBJENV_VALID((duk_hobjenv *) env);
81518 		holder = ((duk_hobjenv *) env)->target;
81519 		DUK_ASSERT(holder != NULL);
81520 	}
81521 
81522 	/*
81523 	 *  Define new property
81524 	 *
81525 	 *  Note: this may fail if the holder is not extensible.
81526 	 */
81527 
81528 	/* XXX: this is awkward as we use an internal method which doesn't handle
81529 	 * extensibility etc correctly.  Basically we'd want to do a [[DefineOwnProperty]]
81530 	 * or Object.defineProperty() here.
81531 	 */
81532 
81533 	if (!DUK_HOBJECT_HAS_EXTENSIBLE(holder)) {
81534 		goto fail_not_extensible;
81535 	}
81536 
81537 	duk_push_hobject(thr, holder);
81538 	duk_push_hstring(thr, name);
81539 	duk_push_tval(thr, val);
81540 	duk_xdef_prop(thr, -3, prop_flags);  /* [holder name val] -> [holder] */
81541 	duk_pop_unsafe(thr);
81542 
81543 	return 0;
81544 
81545  fail_existing_attributes:
81546  fail_not_extensible:
81547 	DUK_ERROR_TYPE(thr, "declaration failed");
81548 	DUK_WO_NORETURN(return 0;);
81549 }
81550 
81551 DUK_INTERNAL
81552 duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
81553                                      duk_activation *act,
81554                                      duk_hstring *name,
81555                                      duk_tval *val,
81556                                      duk_small_uint_t prop_flags,
81557                                      duk_bool_t is_func_decl) {
81558 	duk_hobject *env;
81559 	duk_tval tv_val_copy;
81560 
81561 	DUK_ASSERT(act != NULL);
81562 
81563 	/*
81564 	 *  Make a value copy of the input val.  This ensures that
81565 	 *  side effects cannot invalidate the pointer.
81566 	 */
81567 
81568 	DUK_TVAL_SET_TVAL(&tv_val_copy, val);
81569 	val = &tv_val_copy;
81570 
81571 	/*
81572 	 *  Delayed env creation check
81573 	 */
81574 
81575 	if (!act->var_env) {
81576 		DUK_ASSERT(act->lex_env == NULL);
81577 		duk_js_init_activation_environment_records_delayed(thr, act);
81578 		/* 'act' is a stable pointer, so still OK. */
81579 	}
81580 	DUK_ASSERT(act->lex_env != NULL);
81581 	DUK_ASSERT(act->var_env != NULL);
81582 
81583 	env = act->var_env;
81584 	DUK_ASSERT(env != NULL);
81585 	DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
81586 
81587 	return duk__declvar_helper(thr, env, name, val, prop_flags, is_func_decl);
81588 }
81589 #line 1 "duk_lexer.c"
81590 /*
81591  *  Lexer for source files, ToNumber() string conversions, RegExp expressions,
81592  *  and JSON.
81593  *
81594  *  Provides a stream of ECMAScript tokens from an UTF-8/CESU-8 buffer.  The
81595  *  caller can also rewind the token stream into a certain position which is
81596  *  needed by the compiler part for multi-pass scanning.  Tokens are
81597  *  represented as duk_token structures, and contain line number information.
81598  *  Token types are identified with DUK_TOK_* defines.
81599  *
81600  *  Characters are decoded into a fixed size lookup window consisting of
81601  *  decoded Unicode code points, with window positions past the end of the
81602  *  input filled with an invalid codepoint (-1).  The tokenizer can thus
81603  *  perform multiple character lookups efficiently and with few sanity
81604  *  checks (such as access outside the end of the input), which keeps the
81605  *  tokenization code small at the cost of performance.
81606  *
81607  *  Character data in tokens, such as identifier names and string literals,
81608  *  is encoded into CESU-8 format on-the-fly while parsing the token in
81609  *  question.  The string data is made reachable to garbage collection by
81610  *  placing the token-related values in value stack entries allocated for
81611  *  this purpose by the caller.  The characters exist in Unicode code point
81612  *  form only in the fixed size lookup window, which keeps character data
81613  *  expansion (of especially ASCII data) low.
81614  *
81615  *  Token parsing supports the full range of Unicode characters as described
81616  *  in the E5 specification.  Parsing has been optimized for ASCII characters
81617  *  because ordinary ECMAScript code consists almost entirely of ASCII
81618  *  characters.  Matching of complex Unicode codepoint sets (such as in the
81619  *  IdentifierStart and IdentifierPart productions) is optimized for size,
81620  *  and is done using a linear scan of a bit-packed list of ranges.  This is
81621  *  very slow, but should never be entered unless the source code actually
81622  *  contains Unicode characters.
81623  *
81624  *  ECMAScript tokenization is partially context sensitive.  First,
81625  *  additional future reserved words are recognized in strict mode (see E5
81626  *  Section 7.6.1.2).  Second, a forward slash character ('/') can be
81627  *  recognized either as starting a RegExp literal or as a division operator,
81628  *  depending on context.  The caller must provide necessary context flags
81629  *  when requesting a new token.
81630  *
81631  *  Future work:
81632  *
81633  *    * Make line number tracking optional, as it consumes space.
81634  *
81635  *    * Add a feature flag for disabling UTF-8 decoding of input, as most
81636  *      source code is ASCII.  Because of Unicode escapes written in ASCII,
81637  *      this does not allow Unicode support to be removed from e.g.
81638  *      duk_unicode_is_identifier_start() nor does it allow removal of CESU-8
81639  *      encoding of e.g. string literals.
81640  *
81641  *    * Add a feature flag for disabling Unicode compliance of e.g. identifier
81642  *      names.  This allows for a build more than a kilobyte smaller, because
81643  *      Unicode ranges needed by duk_unicode_is_identifier_start() and
81644  *      duk_unicode_is_identifier_part() can be dropped.  String literals
81645  *      should still be allowed to contain escaped Unicode, so this still does
81646  *      not allow removal of CESU-8 encoding of e.g. string literals.
81647  *
81648  *    * Character lookup tables for codepoints above BMP could be stripped.
81649  *
81650  *    * Strictly speaking, E5 specification requires that source code consists
81651  *      of 16-bit code units, and if not, must be conceptually converted to
81652  *      that format first.  The current lexer processes Unicode code points
81653  *      and allows characters outside the BMP.  These should be converted to
81654  *      surrogate pairs while reading the source characters into the window,
81655  *      not after tokens have been formed (as is done now).  However, the fix
81656  *      is not trivial because two characters are decoded from one codepoint.
81657  *
81658  *    * Optimize for speed as well as size.  Large if-else ladders are (at
81659  *      least potentially) slow.
81660  */
81661 
81662 /* #include duk_internal.h -> already included */
81663 
81664 /*
81665  *  Various defines and file specific helper macros
81666  */
81667 
81668 #define DUK__MAX_RE_DECESC_DIGITS     9
81669 #define DUK__MAX_RE_QUANT_DIGITS      9   /* Does not allow e.g. 2**31-1, but one more would allow overflows of u32. */
81670 
81671 /* whether to use macros or helper function depends on call count */
81672 #define DUK__ISDIGIT(x)          ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_9)
81673 #define DUK__ISHEXDIGIT(x)       duk__is_hex_digit((x))
81674 #define DUK__ISOCTDIGIT(x)       ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_7)
81675 #define DUK__ISDIGIT03(x)        ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_3)
81676 #define DUK__ISDIGIT47(x)        ((x) >= DUK_ASC_4 && (x) <= DUK_ASC_7)
81677 
81678 /* lexer character window helpers */
81679 #define DUK__LOOKUP(lex_ctx,idx)            ((lex_ctx)->window[(idx)].codepoint)
81680 #define DUK__ADVANCECHARS(lex_ctx,count)    duk__advance_chars((lex_ctx), (count))
81681 #define DUK__ADVANCEBYTES(lex_ctx,count)    duk__advance_bytes((lex_ctx), (count))
81682 #define DUK__INITBUFFER(lex_ctx)            duk__initbuffer((lex_ctx))
81683 #define DUK__APPENDBUFFER(lex_ctx,x)        duk__appendbuffer((lex_ctx), (duk_codepoint_t) (x))
81684 #define DUK__APPENDBUFFER_ASCII(lex_ctx,x)  duk__appendbuffer_ascii((lex_ctx), (duk_codepoint_t) (x))
81685 
81686 /* lookup shorthands (note: assume context variable is named 'lex_ctx') */
81687 #define DUK__L0()  DUK__LOOKUP(lex_ctx, 0)
81688 #define DUK__L1()  DUK__LOOKUP(lex_ctx, 1)
81689 #define DUK__L2()  DUK__LOOKUP(lex_ctx, 2)
81690 #define DUK__L3()  DUK__LOOKUP(lex_ctx, 3)
81691 #define DUK__L4()  DUK__LOOKUP(lex_ctx, 4)
81692 #define DUK__L5()  DUK__LOOKUP(lex_ctx, 5)
81693 
81694 /* packed advance/token number macro used by multiple functions */
81695 #define DUK__ADVTOK(advbytes,tok)  ((((advbytes) * sizeof(duk_lexer_codepoint)) << 8) + (tok))
81696 
81697 /*
81698  *  Advance lookup window by N characters, filling in new characters as
81699  *  necessary.  After returning caller is guaranteed a character window of
81700  *  at least DUK_LEXER_WINDOW_SIZE characters.
81701  *
81702  *  The main function duk__advance_bytes() is called at least once per every
81703  *  token so it has a major lexer/compiler performance impact.  There are two
81704  *  variants for the main duk__advance_bytes() algorithm: a sliding window
81705  *  approach which is slightly faster at the cost of larger code footprint,
81706  *  and a simple copying one.
81707  *
81708  *  Decoding directly from the source string would be another lexing option.
81709  *  But the lookup window based approach has the advantage of hiding the
81710  *  source string and its encoding effectively which gives more flexibility
81711  *  going forward to e.g. support chunked streaming of source from flash.
81712  *
81713  *  Decodes UTF-8/CESU-8 leniently with support for code points from U+0000 to
81714  *  U+10FFFF, causing an error if the input is unparseable.  Leniency means:
81715  *
81716  *    * Unicode code point validation is intentionally not performed,
81717  *      except to check that the codepoint does not exceed 0x10ffff.
81718  *
81719  *    * In particular, surrogate pairs are allowed and not combined, which
81720  *      allows source files to represent all SourceCharacters with CESU-8.
81721  *      Broken surrogate pairs are allowed, as ECMAScript does not mandate
81722  *      their validation.
81723  *
81724  *    * Allow non-shortest UTF-8 encodings.
81725  *
81726  *  Leniency here causes few security concerns because all character data is
81727  *  decoded into Unicode codepoints before lexer processing, and is then
81728  *  re-encoded into CESU-8.  The source can be parsed as strict UTF-8 with
81729  *  a compiler option.  However, ECMAScript source characters include -all-
81730  *  16-bit unsigned integer codepoints, so leniency seems to be appropriate.
81731  *
81732  *  Note that codepoints above the BMP are not strictly SourceCharacters,
81733  *  but the lexer still accepts them as such.  Before ending up in a string
81734  *  or an identifier name, codepoints above BMP are converted into surrogate
81735  *  pairs and then CESU-8 encoded, resulting in 16-bit Unicode data as
81736  *  expected by ECMAScript.
81737  *
81738  *  An alternative approach to dealing with invalid or partial sequences
81739  *  would be to skip them and replace them with e.g. the Unicode replacement
81740  *  character U+FFFD.  This has limited utility because a replacement character
81741  *  will most likely cause a parse error, unless it occurs inside a string.
81742  *  Further, ECMAScript source is typically pure ASCII.
81743  *
81744  *  See:
81745  *
81746  *     http://en.wikipedia.org/wiki/UTF-8
81747  *     http://en.wikipedia.org/wiki/CESU-8
81748  *     http://tools.ietf.org/html/rfc3629
81749  *     http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
81750  *
81751  *  Future work:
81752  *
81753  *    * Reject other invalid Unicode sequences (see Wikipedia entry for examples)
81754  *      in strict UTF-8 mode.
81755  *
81756  *    * Size optimize.  An attempt to use a 16-byte lookup table for the first
81757  *      byte resulted in a code increase though.
81758  *
81759  *    * Is checking against maximum 0x10ffff really useful?  4-byte encoding
81760  *      imposes a certain limit anyway.
81761  *
81762  *    * Support chunked streaming of source code.  Can be implemented either
81763  *      by streaming chunks of bytes or chunks of codepoints.
81764  */
81765 
81766 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
81767 DUK_LOCAL void duk__fill_lexer_buffer(duk_lexer_ctx *lex_ctx, duk_small_uint_t start_offset_bytes) {
81768 	duk_lexer_codepoint *cp, *cp_end;
81769 	duk_ucodepoint_t x;
81770 	duk_small_uint_t contlen;
81771 	const duk_uint8_t *p, *p_end;
81772 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
81773 	duk_ucodepoint_t mincp;
81774 #endif
81775 	duk_int_t input_line;
81776 
81777 	/* Use temporaries and update lex_ctx only when finished. */
81778 	input_line = lex_ctx->input_line;
81779 	p = lex_ctx->input + lex_ctx->input_offset;
81780 	p_end = lex_ctx->input + lex_ctx->input_length;
81781 
81782 	cp = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->buffer + start_offset_bytes);
81783 	cp_end = lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE;
81784 
81785 	for (; cp != cp_end; cp++) {
81786 		cp->offset = (duk_size_t) (p - lex_ctx->input);
81787 		cp->line = input_line;
81788 
81789 		/* XXX: potential issue with signed pointers, p_end < p. */
81790 		if (DUK_UNLIKELY(p >= p_end)) {
81791 			/* If input_offset were assigned a negative value, it would
81792 			 * result in a large positive value.  Most likely it would be
81793 			 * larger than input_length and be caught here.  In any case
81794 			 * no memory unsafe behavior would happen.
81795 			 */
81796 			cp->codepoint = -1;
81797 			continue;
81798 		}
81799 
81800 		x = (duk_ucodepoint_t) (*p++);
81801 
81802 		/* Fast path. */
81803 
81804 		if (DUK_LIKELY(x < 0x80UL)) {
81805 			DUK_ASSERT(x != 0x2028UL && x != 0x2029UL);  /* not LS/PS */
81806 			if (DUK_UNLIKELY(x <= 0x000dUL)) {
81807 				if ((x == 0x000aUL) ||
81808 				    ((x == 0x000dUL) && (p >= p_end || *p != 0x000aUL))) {
81809 					/* lookup for 0x000a above assumes shortest encoding now */
81810 
81811 					/* E5 Section 7.3, treat the following as newlines:
81812 					 *   LF
81813 					 *   CR [not followed by LF]
81814 					 *   LS
81815 					 *   PS
81816 					 *
81817 					 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
81818 					 * the line number.
81819 					 */
81820 					input_line++;
81821 				}
81822 			}
81823 
81824 			cp->codepoint = (duk_codepoint_t) x;
81825 			continue;
81826 		}
81827 
81828 		/* Slow path. */
81829 
81830 		if (x < 0xc0UL) {
81831 			/* 10xx xxxx -> invalid */
81832 			goto error_encoding;
81833 		} else if (x < 0xe0UL) {
81834 			/* 110x xxxx   10xx xxxx  */
81835 			contlen = 1;
81836 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
81837 			mincp = 0x80UL;
81838 #endif
81839 			x = x & 0x1fUL;
81840 		} else if (x < 0xf0UL) {
81841 			/* 1110 xxxx   10xx xxxx   10xx xxxx */
81842 			contlen = 2;
81843 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
81844 			mincp = 0x800UL;
81845 #endif
81846 			x = x & 0x0fUL;
81847 		} else if (x < 0xf8UL) {
81848 			/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx */
81849 			contlen = 3;
81850 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
81851 			mincp = 0x10000UL;
81852 #endif
81853 			x = x & 0x07UL;
81854 		} else {
81855 			/* no point in supporting encodings of 5 or more bytes */
81856 			goto error_encoding;
81857 		}
81858 
81859 		DUK_ASSERT(p_end >= p);
81860 		if ((duk_size_t) contlen > (duk_size_t) (p_end - p)) {
81861 			goto error_clipped;
81862 		}
81863 
81864 		while (contlen > 0) {
81865 			duk_small_uint_t y;
81866 			y = *p++;
81867 			if ((y & 0xc0U) != 0x80U) {
81868 				/* check that byte has the form 10xx xxxx */
81869 				goto error_encoding;
81870 			}
81871 			x = x << 6;
81872 			x += y & 0x3fUL;
81873 			contlen--;
81874 		}
81875 
81876 		/* check final character validity */
81877 
81878 		if (x > 0x10ffffUL) {
81879 			goto error_encoding;
81880 		}
81881 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
81882 		if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
81883 			goto error_encoding;
81884 		}
81885 #endif
81886 
81887 		DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
81888 		if ((x == 0x2028UL) || (x == 0x2029UL)) {
81889 			input_line++;
81890 		}
81891 
81892 		cp->codepoint = (duk_codepoint_t) x;
81893 	}
81894 
81895 	lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
81896 	lex_ctx->input_line = input_line;
81897 	return;
81898 
81899  error_clipped:   /* clipped codepoint */
81900  error_encoding:  /* invalid codepoint encoding or codepoint */
81901 	lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
81902 	lex_ctx->input_line = input_line;
81903 
81904 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_SOURCE_DECODE_FAILED);
81905 	DUK_WO_NORETURN(return;);
81906 }
81907 
81908 DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
81909 	duk_small_uint_t used_bytes, avail_bytes;
81910 
81911 	DUK_ASSERT_DISABLE(count_bytes >= 0);  /* unsigned */
81912 	DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));
81913 	DUK_ASSERT(lex_ctx->window >= lex_ctx->buffer);
81914 	DUK_ASSERT(lex_ctx->window < lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE);
81915 	DUK_ASSERT((duk_uint8_t *) lex_ctx->window + count_bytes <= (duk_uint8_t *) lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint));
81916 
81917 	/* Zero 'count' is also allowed to make call sites easier.
81918 	 * Arithmetic in bytes generates better code in GCC.
81919 	 */
81920 
81921 	lex_ctx->window = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->window + count_bytes);  /* avoid multiply */
81922 	used_bytes = (duk_small_uint_t) ((duk_uint8_t *) lex_ctx->window - (duk_uint8_t *) lex_ctx->buffer);
81923 	avail_bytes = DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint) - used_bytes;
81924 	if (avail_bytes < (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint))) {
81925 		/* Not enough data to provide a full window, so "scroll" window to
81926 		 * start of buffer and fill up the rest.
81927 		 */
81928 		duk_memmove((void *) lex_ctx->buffer,
81929 		            (const void *) lex_ctx->window,
81930 		            (size_t) avail_bytes);
81931 		lex_ctx->window = lex_ctx->buffer;
81932 		duk__fill_lexer_buffer(lex_ctx, avail_bytes);
81933 	}
81934 }
81935 
81936 DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {
81937 	lex_ctx->window = lex_ctx->buffer;
81938 	duk__fill_lexer_buffer(lex_ctx, 0);
81939 }
81940 #else  /* DUK_USE_LEXER_SLIDING_WINDOW */
81941 DUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) {
81942 	duk_ucodepoint_t x;
81943 	duk_small_uint_t len;
81944 	duk_small_uint_t i;
81945 	const duk_uint8_t *p;
81946 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
81947 	duk_ucodepoint_t mincp;
81948 #endif
81949 	duk_size_t input_offset;
81950 
81951 	input_offset = lex_ctx->input_offset;
81952 	if (DUK_UNLIKELY(input_offset >= lex_ctx->input_length)) {
81953 		/* If input_offset were assigned a negative value, it would
81954 		 * result in a large positive value.  Most likely it would be
81955 		 * larger than input_length and be caught here.  In any case
81956 		 * no memory unsafe behavior would happen.
81957 		 */
81958 		return -1;
81959 	}
81960 
81961 	p = lex_ctx->input + input_offset;
81962 	x = (duk_ucodepoint_t) (*p);
81963 
81964 	if (DUK_LIKELY(x < 0x80UL)) {
81965 		/* 0xxx xxxx -> fast path */
81966 
81967 		/* input offset tracking */
81968 		lex_ctx->input_offset++;
81969 
81970 		DUK_ASSERT(x != 0x2028UL && x != 0x2029UL);  /* not LS/PS */
81971 		if (DUK_UNLIKELY(x <= 0x000dUL)) {
81972 			if ((x == 0x000aUL) ||
81973 			    ((x == 0x000dUL) && (lex_ctx->input_offset >= lex_ctx->input_length ||
81974 			                         lex_ctx->input[lex_ctx->input_offset] != 0x000aUL))) {
81975 				/* lookup for 0x000a above assumes shortest encoding now */
81976 
81977 				/* E5 Section 7.3, treat the following as newlines:
81978 				 *   LF
81979 				 *   CR [not followed by LF]
81980 				 *   LS
81981 				 *   PS
81982 				 *
81983 				 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
81984 				 * the line number.
81985 				 */
81986 				lex_ctx->input_line++;
81987 			}
81988 		}
81989 
81990 		return (duk_codepoint_t) x;
81991 	}
81992 
81993 	/* Slow path. */
81994 
81995 	if (x < 0xc0UL) {
81996 		/* 10xx xxxx -> invalid */
81997 		goto error_encoding;
81998 	} else if (x < 0xe0UL) {
81999 		/* 110x xxxx   10xx xxxx  */
82000 		len = 2;
82001 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
82002 		mincp = 0x80UL;
82003 #endif
82004 		x = x & 0x1fUL;
82005 	} else if (x < 0xf0UL) {
82006 		/* 1110 xxxx   10xx xxxx   10xx xxxx */
82007 		len = 3;
82008 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
82009 		mincp = 0x800UL;
82010 #endif
82011 		x = x & 0x0fUL;
82012 	} else if (x < 0xf8UL) {
82013 		/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx */
82014 		len = 4;
82015 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
82016 		mincp = 0x10000UL;
82017 #endif
82018 		x = x & 0x07UL;
82019 	} else {
82020 		/* no point in supporting encodings of 5 or more bytes */
82021 		goto error_encoding;
82022 	}
82023 
82024 	DUK_ASSERT(lex_ctx->input_length >= lex_ctx->input_offset);
82025 	if ((duk_size_t) len > (duk_size_t) (lex_ctx->input_length - lex_ctx->input_offset)) {
82026 		goto error_clipped;
82027 	}
82028 
82029 	p++;
82030 	for (i = 1; i < len; i++) {
82031 		duk_small_uint_t y;
82032 		y = *p++;
82033 		if ((y & 0xc0U) != 0x80U) {
82034 			/* check that byte has the form 10xx xxxx */
82035 			goto error_encoding;
82036 		}
82037 		x = x << 6;
82038 		x += y & 0x3fUL;
82039 	}
82040 
82041 	/* check final character validity */
82042 
82043 	if (x > 0x10ffffUL) {
82044 		goto error_encoding;
82045 	}
82046 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
82047 	if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
82048 		goto error_encoding;
82049 	}
82050 #endif
82051 
82052 	/* input offset tracking */
82053 	lex_ctx->input_offset += len;
82054 
82055 	/* line tracking */
82056 	DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
82057 	if ((x == 0x2028UL) || (x == 0x2029UL)) {
82058 		lex_ctx->input_line++;
82059 	}
82060 
82061 	return (duk_codepoint_t) x;
82062 
82063  error_clipped:   /* clipped codepoint */
82064  error_encoding:  /* invalid codepoint encoding or codepoint */
82065 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_SOURCE_DECODE_FAILED);
82066 	DUK_WO_NORETURN(return 0;);
82067 }
82068 
82069 DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
82070 	duk_small_uint_t keep_bytes;
82071 	duk_lexer_codepoint *cp, *cp_end;
82072 
82073 	DUK_ASSERT_DISABLE(count_bytes >= 0);  /* unsigned */
82074 	DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));
82075 
82076 	/* Zero 'count' is also allowed to make call sites easier. */
82077 
82078 	keep_bytes = DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint) - count_bytes;
82079 	duk_memmove((void *) lex_ctx->window,
82080 	            (const void *) ((duk_uint8_t *) lex_ctx->window + count_bytes),
82081 	            (size_t) keep_bytes);
82082 
82083 	cp = (duk_lexer_codepoint *) ((duk_uint8_t *) lex_ctx->window + keep_bytes);
82084 	cp_end = lex_ctx->window + DUK_LEXER_WINDOW_SIZE;
82085 	for (; cp != cp_end; cp++) {
82086 		cp->offset = lex_ctx->input_offset;
82087 		cp->line = lex_ctx->input_line;
82088 		cp->codepoint = duk__read_char(lex_ctx);
82089 	}
82090 }
82091 
82092 DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {
82093 	/* Call with count == DUK_LEXER_WINDOW_SIZE to fill buffer initially. */
82094 	duk__advance_bytes(lex_ctx, DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint));  /* fill window */
82095 }
82096 #endif  /* DUK_USE_LEXER_SLIDING_WINDOW */
82097 
82098 DUK_LOCAL void duk__advance_chars(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_chars) {
82099 	duk__advance_bytes(lex_ctx, count_chars * sizeof(duk_lexer_codepoint));
82100 }
82101 
82102 /*
82103  *  (Re)initialize the temporary byte buffer.  May be called extra times
82104  *  with little impact.
82105  */
82106 
82107 DUK_LOCAL void duk__initbuffer(duk_lexer_ctx *lex_ctx) {
82108 	/* Reuse buffer as is unless buffer has grown large. */
82109 	if (DUK_HBUFFER_DYNAMIC_GET_SIZE(lex_ctx->buf) < DUK_LEXER_TEMP_BUF_LIMIT) {
82110 		/* Keep current size */
82111 	} else {
82112 		duk_hbuffer_resize(lex_ctx->thr, lex_ctx->buf, DUK_LEXER_TEMP_BUF_LIMIT);
82113 	}
82114 
82115 	DUK_BW_INIT_WITHBUF(lex_ctx->thr, &lex_ctx->bw, lex_ctx->buf);
82116 }
82117 
82118 /*
82119  *  Append a Unicode codepoint to the temporary byte buffer.  Performs
82120  *  CESU-8 surrogate pair encoding for codepoints above the BMP.
82121  *  Existing surrogate pairs are allowed and also encoded into CESU-8.
82122  */
82123 
82124 DUK_LOCAL void duk__appendbuffer(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
82125 	/*
82126 	 *  Since character data is only generated by decoding the source or by
82127 	 *  the compiler itself, we rely on the input codepoints being correct
82128 	 *  and avoid a check here.
82129 	 *
82130 	 *  Character data can also come here through decoding of Unicode
82131 	 *  escapes ("\udead\ubeef") so all 16-but unsigned values can be
82132 	 *  present, even when the source file itself is strict UTF-8.
82133 	 */
82134 	DUK_ASSERT(x >= 0 && x <= 0x10ffffL);
82135 
82136 	DUK_BW_WRITE_ENSURE_CESU8(lex_ctx->thr, &lex_ctx->bw, (duk_ucodepoint_t) x);
82137 }
82138 
82139 DUK_LOCAL void duk__appendbuffer_ascii(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
82140 	/* ASCII characters can be emitted as a single byte without encoding
82141 	 * which matters for some fast paths.
82142 	 */
82143 	DUK_ASSERT(x >= 0 && x <= 0x7f);
82144 
82145 	DUK_BW_WRITE_ENSURE_U8(lex_ctx->thr, &lex_ctx->bw, (duk_uint8_t) x);
82146 }
82147 
82148 /*
82149  *  Intern the temporary byte buffer into a valstack slot
82150  *  (in practice, slot1 or slot2).
82151  */
82152 
82153 DUK_LOCAL duk_hstring *duk__internbuffer(duk_lexer_ctx *lex_ctx, duk_idx_t valstack_idx) {
82154 	DUK_ASSERT(valstack_idx == lex_ctx->slot1_idx || valstack_idx == lex_ctx->slot2_idx);
82155 
82156 	DUK_BW_PUSH_AS_STRING(lex_ctx->thr, &lex_ctx->bw);
82157 	duk_replace(lex_ctx->thr, valstack_idx);
82158 	return duk_known_hstring(lex_ctx->thr, valstack_idx);
82159 }
82160 
82161 /*
82162  *  Init lexer context
82163  */
82164 
82165 DUK_INTERNAL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx) {
82166 	DUK_ASSERT(lex_ctx != NULL);
82167 
82168 	duk_memzero(lex_ctx, sizeof(*lex_ctx));
82169 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
82170 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
82171 	lex_ctx->window = NULL;
82172 #endif
82173 	lex_ctx->thr = NULL;
82174 	lex_ctx->input = NULL;
82175 	lex_ctx->buf = NULL;
82176 #endif
82177 }
82178 
82179 /*
82180  *  Set lexer input position and reinitialize lookup window.
82181  */
82182 
82183 DUK_INTERNAL void duk_lexer_getpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {
82184 	pt->offset = lex_ctx->window[0].offset;
82185 	pt->line = lex_ctx->window[0].line;
82186 }
82187 
82188 DUK_INTERNAL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {
82189 	DUK_ASSERT_DISABLE(pt->offset >= 0);  /* unsigned */
82190 	DUK_ASSERT(pt->line >= 1);
82191 	lex_ctx->input_offset = pt->offset;
82192 	lex_ctx->input_line = pt->line;
82193 	duk__init_lexer_window(lex_ctx);
82194 }
82195 
82196 /*
82197  *  Lexing helpers
82198  */
82199 
82200 /* Numeric value of a hex digit (also covers octal and decimal digits) or
82201  * -1 if not a valid hex digit.
82202  */
82203 DUK_LOCAL duk_codepoint_t duk__hexval_validate(duk_codepoint_t x) {
82204 	duk_small_int_t t;
82205 
82206 	/* Here 'x' is a Unicode codepoint */
82207 	if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
82208 		t = duk_hex_dectab[x];
82209 		if (DUK_LIKELY(t >= 0)) {
82210 			return t;
82211 		}
82212 	}
82213 
82214 	return -1;
82215 }
82216 
82217 /* Just a wrapper for call sites where 'x' is known to be valid so
82218  * we assert for it before decoding.
82219  */
82220 DUK_LOCAL duk_codepoint_t duk__hexval(duk_codepoint_t x) {
82221 	duk_codepoint_t ret;
82222 
82223 	DUK_ASSERT((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
82224 	           (x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_F) ||
82225 	           (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_F));
82226 	ret = duk__hexval_validate(x);
82227 	DUK_ASSERT(ret >= 0 && ret <= 15);
82228 	return ret;
82229 }
82230 
82231 /* having this as a separate function provided a size benefit */
82232 DUK_LOCAL duk_bool_t duk__is_hex_digit(duk_codepoint_t x) {
82233 	if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
82234 		return (duk_hex_dectab[x] >= 0);
82235 	}
82236 	return 0;
82237 }
82238 
82239 /* Parse a Unicode escape of the form \xHH, \uHHHH, or \u{H+}.  Shared by
82240  * source and RegExp parsing.
82241  */
82242 DUK_LOCAL duk_codepoint_t duk__lexer_parse_escape(duk_lexer_ctx *lex_ctx, duk_bool_t allow_es6) {
82243 	duk_small_int_t digits;  /* Initial value 2 or 4 for fixed length escapes, 0 for ES2015 \u{H+}. */
82244 	duk_codepoint_t escval;
82245 	duk_codepoint_t x;
82246 	duk_small_uint_t adv;
82247 
82248 	DUK_ASSERT(DUK__L0() == DUK_ASC_BACKSLASH);  /* caller responsibilities */
82249 	DUK_ASSERT(DUK__L1() == DUK_ASC_LC_X || DUK__L1() == DUK_ASC_LC_U);
82250 	DUK_UNREF(allow_es6);
82251 
82252 	adv = 2;
82253 	digits = 2;
82254 	if (DUK__L1() == DUK_ASC_LC_U) {
82255 		digits = 4;
82256 #if defined(DUK_USE_ES6_UNICODE_ESCAPE)
82257 		if (DUK__L2() == DUK_ASC_LCURLY && allow_es6) {
82258 			digits = 0;
82259 			adv = 3;
82260 		}
82261 #endif
82262 	}
82263 	DUK__ADVANCECHARS(lex_ctx, adv);
82264 
82265 	escval = 0;
82266 	for (;;) {
82267 		/* One of the escape forms: \xHH, \uHHHH, \u{H+}.
82268 		 * The 'digits' variable tracks parsing state and is
82269 		 * initialized to:
82270 		 *
82271 		 *   \xHH     2
82272 		 *   \uHH     4
82273 		 *   \u{H+}   0 first time, updated to -1 to indicate
82274 		 *            at least one digit has been parsed
82275 		 *
82276 		 * Octal parsing is handled separately because it can be
82277 		 * done with fixed lookahead and also has validation
82278 		 * rules which depend on the escape length (which is
82279 		 * variable).
82280 		 *
82281 		 * We don't need a specific check for x < 0 (end of
82282 		 * input) or duk_unicode_is_line_terminator(x)
82283 		 * because the 'dig' decode will fail and lead to a
82284 		 * SyntaxError.
82285 		 */
82286 		duk_codepoint_t dig;
82287 
82288 		x = DUK__L0();
82289 		DUK__ADVANCECHARS(lex_ctx, 1);
82290 
82291 		dig = duk__hexval_validate(x);
82292 		if (digits > 0) {
82293 			digits--;
82294 			if (dig < 0) {
82295 				goto fail_escape;
82296 			}
82297 			DUK_ASSERT(dig >= 0x00 && dig <= 0x0f);
82298 			escval = (escval << 4) + dig;
82299 			if (digits == 0) {
82300 				DUK_ASSERT(escval >= 0 && escval <= 0xffffL);
82301 				break;
82302 			}
82303 		} else {
82304 #if defined(DUK_USE_ES6_UNICODE_ESCAPE)
82305 			DUK_ASSERT(digits == 0 /* first time */ || digits == -1 /* others */);
82306 			if (dig >= 0) {
82307 				DUK_ASSERT(dig >= 0x00 && dig <= 0x0f);
82308 				escval = (escval << 4) + dig;
82309 				if (escval > 0x10ffffL) {
82310 					goto fail_escape;
82311 				}
82312 			} else if (x == DUK_ASC_RCURLY) {
82313 				if (digits == 0) {
82314 					/* Empty escape, \u{}. */
82315 					goto fail_escape;
82316 				}
82317 				DUK_ASSERT(escval >= 0 && escval <= 0x10ffffL);
82318 				break;
82319 			} else {
82320 				goto fail_escape;
82321 			}
82322 			digits = -1;  /* Indicate we have at least one digit. */
82323 #else  /* DUK_USE_ES6_UNICODE_ESCAPE */
82324 			DUK_ASSERT(0);  /* Never happens if \u{H+} support disabled. */
82325 #endif  /* DUK_USE_ES6_UNICODE_ESCAPE */
82326 		}
82327 	}
82328 
82329 	return escval;
82330 
82331  fail_escape:
82332 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
82333 	DUK_WO_NORETURN(return 0;);
82334 }
82335 
82336 /* Parse legacy octal escape of the form \N{1,3}, e.g. \0, \5, \0377.  Maximum
82337  * allowed value is \0377 (U+00FF), longest match is used.  Used for both string
82338  * RegExp octal escape parsing.  Window[0] must be the slash '\' and the first
82339  * digit must already be validated to be in [0-9] by the caller.
82340  */
82341 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) {
82342 	duk_codepoint_t cp;
82343 	duk_small_uint_t lookup_idx;
82344 	duk_small_uint_t adv;
82345 	duk_codepoint_t tmp;
82346 
82347 	DUK_ASSERT(out_adv != NULL);
82348 	DUK_ASSERT(DUK__LOOKUP(lex_ctx, 0) == DUK_ASC_BACKSLASH);
82349 	DUK_ASSERT(DUK__LOOKUP(lex_ctx, 1) >= DUK_ASC_0 && DUK__LOOKUP(lex_ctx, 1) <= DUK_ASC_9);
82350 
82351 	cp = 0;
82352 	tmp = 0;
82353 	for (lookup_idx = 1; lookup_idx <= 3; lookup_idx++) {
82354 		DUK_DDD(DUK_DDDPRINT("lookup_idx=%ld, cp=%ld", (long) lookup_idx, (long) cp));
82355 		tmp = DUK__LOOKUP(lex_ctx, lookup_idx);
82356 		if (tmp < DUK_ASC_0 || tmp > DUK_ASC_7) {
82357 			/* No more valid digits. */
82358 			break;
82359 		}
82360 		tmp = (cp << 3) + (tmp - DUK_ASC_0);
82361 		if (tmp > 0xff) {
82362 			/* Three digit octal escapes above \377 (= 0xff)
82363 			 * are not allowed.
82364 			 */
82365 			break;
82366 		}
82367 		cp = tmp;
82368 	}
82369 	DUK_DDD(DUK_DDDPRINT("final lookup_idx=%ld, cp=%ld", (long) lookup_idx, (long) cp));
82370 
82371 	adv = lookup_idx;
82372 	if (lookup_idx == 1) {
82373 		DUK_DDD(DUK_DDDPRINT("\\8 or \\9 -> treat as literal, accept in strict mode too"));
82374 		DUK_ASSERT(tmp == DUK_ASC_8 || tmp == DUK_ASC_9);
82375 		cp = tmp;
82376 		adv++;  /* correction to above, eat offending character */
82377 	} else if (lookup_idx == 2 && cp == 0) {
82378 		/* Note: 'foo\0bar' is OK in strict mode, but 'foo\00bar' is not.
82379 		 * It won't be interpreted as 'foo\u{0}0bar' but as a SyntaxError.
82380 		 */
82381 		DUK_DDD(DUK_DDDPRINT("\\0 -> accept in strict mode too"));
82382 	} else {
82383 		/* This clause also handles non-shortest zero, e.g. \00. */
82384 		if (reject_annex_b) {
82385 			DUK_DDD(DUK_DDDPRINT("non-zero octal literal %ld -> reject in strict-mode", (long) cp));
82386 			cp = -1;
82387 		} else {
82388 			DUK_DDD(DUK_DDDPRINT("non-zero octal literal %ld -> accepted", (long) cp));
82389 			DUK_ASSERT(cp >= 0 && cp <= 0xff);
82390 		}
82391 	}
82392 
82393 	*out_adv = adv;
82394 
82395 	DUK_ASSERT((cp >= 0 && cp <= 0xff) || (cp == -1 && reject_annex_b));
82396 	return cp;
82397 }
82398 
82399 /* XXX: move strict mode to lex_ctx? */
82400 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) {
82401 	duk_small_uint_t adv;
82402 
82403 	for (adv = 1 /* initial quote */ ;;) {
82404 		duk_codepoint_t x;
82405 
82406 		DUK__ADVANCECHARS(lex_ctx, adv);  /* eat opening quote on first loop */
82407 		x = DUK__L0();
82408 
82409 		adv = 1;
82410 		if (x == quote) {
82411 			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat closing quote */
82412 			break;
82413 		} else if (x == '\\') {
82414 			/* DUK__L0        -> '\' char
82415 			 * DUK__L1 ... DUK__L5 -> more lookup
82416 			 */
82417 			duk_small_int_t emitcp = -1;
82418 
82419 			x = DUK__L1();
82420 
82421 			/* How much to advance before next loop. */
82422 			adv = 2;  /* note: long live range */
82423 
82424 			switch (x) {
82425 			case '\'':
82426 				emitcp = 0x0027;
82427 				break;
82428 			case '"':
82429 				emitcp = 0x0022;
82430 				break;
82431 			case '\\':
82432 				emitcp = 0x005c;
82433 				break;
82434 			case 'b':
82435 				emitcp = 0x0008;
82436 				break;
82437 			case 'f':
82438 				emitcp = 0x000c;
82439 				break;
82440 			case 'n':
82441 				emitcp = 0x000a;
82442 				break;
82443 			case 'r':
82444 				emitcp = 0x000d;
82445 				break;
82446 			case 't':
82447 				emitcp = 0x0009;
82448 				break;
82449 			case 'v':
82450 				emitcp = 0x000b;
82451 				break;
82452 			case 'x':
82453 			case 'u': {
82454 				duk_codepoint_t esc_cp;
82455 				esc_cp = duk__lexer_parse_escape(lex_ctx, 1 /*allow_es6*/);
82456 				DUK__APPENDBUFFER(lex_ctx, esc_cp);
82457 				adv = 0;
82458 				break;
82459 			}
82460 			default: {
82461 				if (duk_unicode_is_line_terminator(x)) {
82462 					/* line continuation */
82463 					if (x == 0x000d && DUK__L2() == 0x000a) {
82464 						/* CR LF again a special case */
82465 						adv = 3;  /* line terminator, CR, LF */
82466 					}
82467 				} else if (DUK__ISDIGIT(x)) {
82468 					/*
82469 					 *  Octal escape or zero escape:
82470 					 *    \0                                     (lookahead not OctalDigit)
82471 					 *    \1 ... \7                              (lookahead not OctalDigit)
82472 					 *    \ZeroToThree OctalDigit                (lookahead not OctalDigit)
82473 					 *    \FourToSeven OctalDigit                (no lookahead restrictions)
82474 					 *    \ZeroToThree OctalDigit OctalDigit     (no lookahead restrictions)
82475 					 *
82476 					 *  Zero escape is part of the standard syntax.  Octal escapes are
82477 					 *  defined in E5 Section B.1.2, and are only allowed in non-strict mode.
82478 					 *  Any other productions starting with a decimal digit are invalid
82479 					 *  but are in practice treated like identity escapes.
82480 					 *
82481 					 *  Parse octal (up to 3 digits) from the lookup window.
82482 					 */
82483 
82484 					emitcp = duk__lexer_parse_legacy_octal(lex_ctx, &adv, strict_mode /*reject_annex_b*/);
82485 					if (emitcp < 0) {
82486 						goto fail_escape;
82487 					}
82488 				} else if (x < 0) {
82489 					goto fail_unterminated;
82490 				} else {
82491 					/* escaped NonEscapeCharacter */
82492 					DUK__APPENDBUFFER(lex_ctx, x);
82493 				}
82494 			}  /* end default clause */
82495 			}  /* end switch */
82496 
82497 			/* Shared handling for single codepoint escapes. */
82498 			if (emitcp >= 0) {
82499 				DUK__APPENDBUFFER(lex_ctx, emitcp);
82500 			}
82501 
82502 			/* Track number of escapes; count not really needed but directive
82503 			 * prologues need to detect whether there were any escapes or line
82504 			 * continuations or not.
82505 			 */
82506 			out_token->num_escapes++;
82507 		} else if (x >= 0x20 && x <= 0x7f) {
82508 			/* Fast path for ASCII case, avoids line terminator
82509 			 * check and CESU-8 encoding.
82510 			 */
82511 			DUK_ASSERT(x >= 0);
82512 			DUK_ASSERT(!duk_unicode_is_line_terminator(x));
82513 			DUK_ASSERT(x != quote);
82514 			DUK_ASSERT(x != DUK_ASC_BACKSLASH);
82515 			DUK__APPENDBUFFER_ASCII(lex_ctx, x);
82516 		} else if (x < 0 || duk_unicode_is_line_terminator(x)) {
82517 			goto fail_unterminated;
82518 		} else {
82519 			/* Character which is part of the string but wasn't handled
82520 			 * by the fast path.
82521 			 */
82522 			DUK__APPENDBUFFER(lex_ctx, x);
82523 		}
82524 	} /* string parse loop */
82525 
82526 	return;
82527 
82528  fail_escape:
82529 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
82530 	DUK_WO_NORETURN(return;);
82531 
82532  fail_unterminated:
82533 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_STRING);
82534 	DUK_WO_NORETURN(return;);
82535 }
82536 
82537 /* Skip to end-of-line (or end-of-file), used for single line comments. */
82538 DUK_LOCAL void duk__lexer_skip_to_endofline(duk_lexer_ctx *lex_ctx) {
82539 	for (;;) {
82540 		duk_codepoint_t x;
82541 
82542 		x = DUK__L0();
82543 		if (x < 0 || duk_unicode_is_line_terminator(x)) {
82544 			break;
82545 		}
82546 		DUK__ADVANCECHARS(lex_ctx, 1);
82547 	}
82548 }
82549 
82550 /*
82551  *  Parse ECMAScript source InputElementDiv or InputElementRegExp
82552  *  (E5 Section 7), skipping whitespace, comments, and line terminators.
82553  *
82554  *  Possible results are:
82555  *    (1) a token
82556  *    (2) a line terminator (skipped)
82557  *    (3) a comment (skipped)
82558  *    (4) EOF
82559  *
82560  *  White space is automatically skipped from the current position (but
82561  *  not after the input element).  If input has already ended, returns
82562  *  DUK_TOK_EOF indefinitely.  If a parse error occurs, uses an DUK_ERROR()
82563  *  macro call (and hence a longjmp through current heap longjmp context).
82564  *  Comments and line terminator tokens are automatically skipped.
82565  *
82566  *  The input element being matched is determined by regexp_mode; if set,
82567  *  parses a InputElementRegExp, otherwise a InputElementDiv.  The
82568  *  difference between these are handling of productions starting with a
82569  *  forward slash.
82570  *
82571  *  If strict_mode is set, recognizes additional future reserved words
82572  *  specific to strict mode, and refuses to parse octal literals.
82573  *
82574  *  The matching strategy below is to (currently) use a six character
82575  *  lookup window to quickly determine which production is the -longest-
82576  *  matching one, and then parse that.  The top-level if-else clauses
82577  *  match the first character, and the code blocks for each clause
82578  *  handle -all- alternatives for that first character.  ECMAScript
82579  *  specification uses the "longest match wins" semantics, so the order
82580  *  of the if-clauses matters.
82581  *
82582  *  Misc notes:
82583  *
82584  *    * ECMAScript numeric literals do not accept a sign character.
82585  *      Consequently e.g. "-1.0" is parsed as two tokens: a negative
82586  *      sign and a positive numeric literal.  The compiler performs
82587  *      the negation during compilation, so this has no adverse impact.
82588  *
82589  *    * There is no token for "undefined": it is just a value available
82590  *      from the global object (or simply established by doing a reference
82591  *      to an undefined value).
82592  *
82593  *    * Some contexts want Identifier tokens, which are IdentifierNames
82594  *      excluding reserved words, while some contexts want IdentifierNames
82595  *      directly.  In the latter case e.g. "while" is interpreted as an
82596  *      identifier name, not a DUK_TOK_WHILE token.  The solution here is
82597  *      to provide both token types: DUK_TOK_WHILE goes to 't' while
82598  *      DUK_TOK_IDENTIFIER goes to 't_nores', and 'slot1' always contains
82599  *      the identifier / keyword name.
82600  *
82601  *    * Directive prologue needs to identify string literals such as
82602  *      "use strict" and 'use strict', which are sensitive to line
82603  *      continuations and escape sequences.  For instance, "use\u0020strict"
82604  *      is a valid directive but is distinct from "use strict".  The solution
82605  *      here is to decode escapes while tokenizing, but to keep track of the
82606  *      number of escapes.  Directive detection can then check that the
82607  *      number of escapes is zero.
82608  *
82609  *    * Multi-line comments with one or more internal LineTerminator are
82610  *      treated like a line terminator to comply with automatic semicolon
82611  *      insertion.
82612  */
82613 
82614 DUK_INTERNAL
82615 void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
82616                                       duk_token *out_token,
82617                                       duk_bool_t strict_mode,
82618                                       duk_bool_t regexp_mode) {
82619 	duk_codepoint_t x;           /* temporary, must be signed and 32-bit to hold Unicode code points */
82620 	duk_small_uint_t advtok = 0; /* (advance << 8) + token_type, updated at function end,
82621 	                              * init is unnecessary but suppresses "may be used uninitialized" warnings.
82622 	                              */
82623 	duk_bool_t got_lineterm = 0;  /* got lineterm preceding non-whitespace, non-lineterm token */
82624 
82625 	if (++lex_ctx->token_count >= lex_ctx->token_limit) {
82626 		goto fail_token_limit;
82627 	}
82628 
82629 	out_token->t = DUK_TOK_EOF;
82630 	out_token->t_nores = DUK_TOK_INVALID;  /* marker: copy t if not changed */
82631 #if 0  /* not necessary to init, disabled for faster parsing */
82632 	out_token->num = DUK_DOUBLE_NAN;
82633 	out_token->str1 = NULL;
82634 	out_token->str2 = NULL;
82635 #endif
82636 	out_token->num_escapes = 0;
82637 	/* out_token->lineterm set by caller */
82638 
82639 	/* This would be nice, but parsing is faster without resetting the
82640 	 * value slots.  The only side effect is that references to temporary
82641 	 * string values may linger until lexing is finished; they're then
82642 	 * freed normally.
82643 	 */
82644 #if 0
82645 	duk_to_undefined(lex_ctx->thr, lex_ctx->slot1_idx);
82646 	duk_to_undefined(lex_ctx->thr, lex_ctx->slot2_idx);
82647 #endif
82648 
82649 	/* 'advtok' indicates how much to advance and which token id to assign
82650 	 * at the end.  This shared functionality minimizes code size.  All
82651 	 * code paths are required to set 'advtok' to some value, so no default
82652 	 * init value is used.  Code paths calling DUK_ERROR() never return so
82653 	 * they don't need to set advtok.
82654 	 */
82655 
82656 	/*
82657 	 *  Matching order:
82658 	 *
82659 	 *    Punctuator first chars, also covers comments, regexps
82660 	 *    LineTerminator
82661 	 *    Identifier or reserved word, also covers null/true/false literals
82662 	 *    NumericLiteral
82663 	 *    StringLiteral
82664 	 *    EOF
82665 	 *
82666 	 *  The order does not matter as long as the longest match is
82667 	 *  always correctly identified.  There are order dependencies
82668 	 *  in the clauses, so it's not trivial to convert to a switch.
82669 	 */
82670 
82671  restart_lineupdate:
82672 	out_token->start_line = lex_ctx->window[0].line;
82673 
82674  restart:
82675 	out_token->start_offset = lex_ctx->window[0].offset;
82676 
82677 	x = DUK__L0();
82678 
82679 	switch (x) {
82680 	case DUK_ASC_SPACE:
82681 	case DUK_ASC_HT:  /* fast paths for space and tab */
82682 		DUK__ADVANCECHARS(lex_ctx, 1);
82683 		goto restart;
82684 	case DUK_ASC_LF:  /* LF line terminator; CR LF and Unicode lineterms are handled in slow path */
82685 		DUK__ADVANCECHARS(lex_ctx, 1);
82686 		got_lineterm = 1;
82687 		goto restart_lineupdate;
82688 #if defined(DUK_USE_SHEBANG_COMMENTS)
82689 	case DUK_ASC_HASH:  /* '#' */
82690 		if (DUK__L1() == DUK_ASC_EXCLAMATION && lex_ctx->window[0].offset == 0 &&
82691 		    (lex_ctx->flags & DUK_COMPILE_SHEBANG)) {
82692 			/* "Shebang" comment ('#! ...') on first line. */
82693 			/* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but not necessary */
82694 			duk__lexer_skip_to_endofline(lex_ctx);
82695 			goto restart;  /* line terminator will be handled on next round */
82696 		}
82697 		goto fail_token;
82698 #endif  /* DUK_USE_SHEBANG_COMMENTS */
82699 	case DUK_ASC_SLASH:  /* '/' */
82700 		if (DUK__L1() == DUK_ASC_SLASH) {
82701 			/*
82702 			 *  E5 Section 7.4, allow SourceCharacter (which is any 16-bit
82703 			 *  code point).
82704 			 */
82705 
82706 			/* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but not necessary */
82707 			duk__lexer_skip_to_endofline(lex_ctx);
82708 			goto restart;  /* line terminator will be handled on next round */
82709 		} else if (DUK__L1() == DUK_ASC_STAR) {
82710 			/*
82711 			 *  E5 Section 7.4.  If the multi-line comment contains a newline,
82712 			 *  it is treated like a single line terminator for automatic
82713 			 *  semicolon insertion.
82714 			 */
82715 
82716 			duk_bool_t last_asterisk = 0;
82717 			DUK__ADVANCECHARS(lex_ctx, 2);
82718 			for (;;) {
82719 				x = DUK__L0();
82720 				if (x < 0) {
82721 					goto fail_unterm_comment;
82722 				}
82723 				DUK__ADVANCECHARS(lex_ctx, 1);
82724 				if (last_asterisk && x == DUK_ASC_SLASH) {
82725 					break;
82726 				}
82727 				if (duk_unicode_is_line_terminator(x)) {
82728 					got_lineterm = 1;
82729 				}
82730 				last_asterisk = (x == DUK_ASC_STAR);
82731 			}
82732 			goto restart_lineupdate;
82733 		} else if (regexp_mode) {
82734 #if defined(DUK_USE_REGEXP_SUPPORT)
82735 			/*
82736 			 *  "/" followed by something in regexp mode.  See E5 Section 7.8.5.
82737 			 *
82738 			 *  RegExp parsing is a bit complex.  First, the regexp body is delimited
82739 			 *  by forward slashes, but the body may also contain forward slashes as
82740 			 *  part of an escape sequence or inside a character class (delimited by
82741 			 *  square brackets).  A mini state machine is used to implement these.
82742 			 *
82743 			 *  Further, an early (parse time) error must be thrown if the regexp
82744 			 *  would cause a run-time error when used in the expression new RegExp(...).
82745 			 *  Parsing here simply extracts the (candidate) regexp, and also accepts
82746 			 *  invalid regular expressions (which are delimited properly).  The caller
82747 			 *  (compiler) must perform final validation and regexp compilation.
82748 			 *
82749 			 *  RegExp first char may not be '/' (single line comment) or '*' (multi-
82750 			 *  line comment).  These have already been checked above, so there is no
82751 			 *  need below for special handling of the first regexp character as in
82752 			 *  the E5 productions.
82753 			 *
82754 			 *  About unicode escapes within regexp literals:
82755 			 *
82756 			 *      E5 Section 7.8.5 grammar does NOT accept \uHHHH escapes.
82757 			 *      However, Section 6 states that regexps accept the escapes,
82758 			 *      see paragraph starting with "In string literals...".
82759 			 *      The regexp grammar, which sees the decoded regexp literal
82760 			 *      (after lexical parsing) DOES have a \uHHHH unicode escape.
82761 			 *      So, for instance:
82762 			 *
82763 			 *          /\u1234/
82764 			 *
82765 			 *      should first be parsed by the lexical grammar as:
82766 			 *
82767 			 *          '\' 'u'      RegularExpressionBackslashSequence
82768 			 *          '1'          RegularExpressionNonTerminator
82769 			 *          '2'          RegularExpressionNonTerminator
82770 			 *          '3'          RegularExpressionNonTerminator
82771 			 *          '4'          RegularExpressionNonTerminator
82772 			 *
82773 			 *      and the escape itself is then parsed by the regexp engine.
82774 			 *      This is the current implementation.
82775 			 *
82776 			 *  Minor spec inconsistency:
82777 			 *
82778 			 *      E5 Section 7.8.5 RegularExpressionBackslashSequence is:
82779 			 *
82780 			 *         \ RegularExpressionNonTerminator
82781 			 *
82782 			 *      while Section A.1 RegularExpressionBackslashSequence is:
82783 			 *
82784 			 *         \ NonTerminator
82785 			 *
82786 			 *      The latter is not normative and a typo.
82787 			 *
82788 			 */
82789 
82790 			/* first, parse regexp body roughly */
82791 
82792 			duk_small_int_t state = 0;  /* 0=base, 1=esc, 2=class, 3=class+esc */
82793 
82794 			DUK__INITBUFFER(lex_ctx);
82795 			for (;;) {
82796 				DUK__ADVANCECHARS(lex_ctx, 1);  /* skip opening slash on first loop */
82797 				x = DUK__L0();
82798 				if (x < 0 || duk_unicode_is_line_terminator(x)) {
82799 					goto fail_unterm_regexp;
82800 				}
82801 				x = DUK__L0();  /* re-read to avoid spill / fetch */
82802 				if (state == 0) {
82803 					if (x == DUK_ASC_SLASH) {
82804 						DUK__ADVANCECHARS(lex_ctx, 1);  /* eat closing slash */
82805 						break;
82806 					} else if (x == DUK_ASC_BACKSLASH) {
82807 						state = 1;
82808 					} else if (x == DUK_ASC_LBRACKET) {
82809 						state = 2;
82810 					}
82811 				} else if (state == 1) {
82812 					state = 0;
82813 				} else if (state == 2) {
82814 					if (x == DUK_ASC_RBRACKET) {
82815 						state = 0;
82816 					} else if (x == DUK_ASC_BACKSLASH) {
82817 						state = 3;
82818 					}
82819 				} else { /* state == 3 */
82820 					state = 2;
82821 				}
82822 				DUK__APPENDBUFFER(lex_ctx, x);
82823 			}
82824 			out_token->str1 = duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
82825 
82826 			/* second, parse flags */
82827 
82828 			DUK__INITBUFFER(lex_ctx);
82829 			for (;;) {
82830 				x = DUK__L0();
82831 				if (!duk_unicode_is_identifier_part(x)) {
82832 					break;
82833 				}
82834 				x = DUK__L0();  /* re-read to avoid spill / fetch */
82835 				DUK__APPENDBUFFER(lex_ctx, x);
82836 				DUK__ADVANCECHARS(lex_ctx, 1);
82837 			}
82838 			out_token->str2 = duk__internbuffer(lex_ctx, lex_ctx->slot2_idx);
82839 
82840 			DUK__INITBUFFER(lex_ctx);  /* free some memory */
82841 
82842 			/* validation of the regexp is caller's responsibility */
82843 
82844 			advtok = DUK__ADVTOK(0, DUK_TOK_REGEXP);
82845 #else  /* DUK_USE_REGEXP_SUPPORT */
82846 			goto fail_regexp_support;
82847 #endif  /* DUK_USE_REGEXP_SUPPORT */
82848 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
82849 			/* "/=" and not in regexp mode */
82850 			advtok = DUK__ADVTOK(2, DUK_TOK_DIV_EQ);
82851 		} else {
82852 			/* "/" and not in regexp mode */
82853 			advtok = DUK__ADVTOK(1, DUK_TOK_DIV);
82854 		}
82855 		break;
82856 	case DUK_ASC_LCURLY:  /* '{' */
82857 		advtok = DUK__ADVTOK(1, DUK_TOK_LCURLY);
82858 		break;
82859 	case DUK_ASC_RCURLY:  /* '}' */
82860 		advtok = DUK__ADVTOK(1, DUK_TOK_RCURLY);
82861 		break;
82862 	case DUK_ASC_LPAREN:  /* '(' */
82863 		advtok = DUK__ADVTOK(1, DUK_TOK_LPAREN);
82864 		break;
82865 	case DUK_ASC_RPAREN:  /* ')' */
82866 		advtok = DUK__ADVTOK(1, DUK_TOK_RPAREN);
82867 		break;
82868 	case DUK_ASC_LBRACKET:  /* '[' */
82869 		advtok = DUK__ADVTOK(1, DUK_TOK_LBRACKET);
82870 		break;
82871 	case DUK_ASC_RBRACKET:  /* ']' */
82872 		advtok = DUK__ADVTOK(1, DUK_TOK_RBRACKET);
82873 		break;
82874 	case DUK_ASC_PERIOD:  /* '.' */
82875 		if (DUK__ISDIGIT(DUK__L1())) {
82876 			/* Period followed by a digit can only start DecimalLiteral
82877 			 * (handled in slow path).  We could jump straight into the
82878 			 * DecimalLiteral handling but should avoid goto to inside
82879 			 * a block.
82880 			 */
82881 			goto slow_path;
82882 		}
82883 		advtok = DUK__ADVTOK(1, DUK_TOK_PERIOD);
82884 		break;
82885 	case DUK_ASC_SEMICOLON:  /* ';' */
82886 		advtok = DUK__ADVTOK(1, DUK_TOK_SEMICOLON);
82887 		break;
82888 	case DUK_ASC_COMMA:  /* ',' */
82889 		advtok = DUK__ADVTOK(1, DUK_TOK_COMMA);
82890 		break;
82891 	case DUK_ASC_LANGLE:  /* '<' */
82892 #if defined(DUK_USE_HTML_COMMENTS)
82893 		if (DUK__L1() == DUK_ASC_EXCLAMATION && DUK__L2() == DUK_ASC_MINUS && DUK__L3() == DUK_ASC_MINUS) {
82894 			/*
82895 			 *  ES2015: B.1.3, handle "<!--" SingleLineHTMLOpenComment
82896 			 */
82897 
82898 			/* DUK__ADVANCECHARS(lex_ctx, 4) would be correct here, but not necessary */
82899 			duk__lexer_skip_to_endofline(lex_ctx);
82900 			goto restart;  /* line terminator will be handled on next round */
82901 		}
82902 		else
82903 #endif  /* DUK_USE_HTML_COMMENTS */
82904 		if (DUK__L1() == DUK_ASC_LANGLE && DUK__L2() == DUK_ASC_EQUALS) {
82905 			advtok = DUK__ADVTOK(3, DUK_TOK_ALSHIFT_EQ);
82906 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
82907 			advtok = DUK__ADVTOK(2, DUK_TOK_LE);
82908 		} else if (DUK__L1() == DUK_ASC_LANGLE) {
82909 			advtok = DUK__ADVTOK(2, DUK_TOK_ALSHIFT);
82910 		} else {
82911 			advtok = DUK__ADVTOK(1, DUK_TOK_LT);
82912 		}
82913 		break;
82914 	case DUK_ASC_RANGLE:  /* '>' */
82915 		if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_RANGLE && DUK__L3() == DUK_ASC_EQUALS) {
82916 			advtok = DUK__ADVTOK(4, DUK_TOK_RSHIFT_EQ);
82917 		} else if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_RANGLE) {
82918 			advtok = DUK__ADVTOK(3, DUK_TOK_RSHIFT);
82919 		} else if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_EQUALS) {
82920 			advtok = DUK__ADVTOK(3, DUK_TOK_ARSHIFT_EQ);
82921 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
82922 			advtok = DUK__ADVTOK(2, DUK_TOK_GE);
82923 		} else if (DUK__L1() == DUK_ASC_RANGLE) {
82924 			advtok = DUK__ADVTOK(2, DUK_TOK_ARSHIFT);
82925 		} else {
82926 			advtok = DUK__ADVTOK(1, DUK_TOK_GT);
82927 		}
82928 		break;
82929 	case DUK_ASC_EQUALS:  /* '=' */
82930 		if (DUK__L1() == DUK_ASC_EQUALS && DUK__L2() == DUK_ASC_EQUALS) {
82931 			advtok = DUK__ADVTOK(3, DUK_TOK_SEQ);
82932 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
82933 			advtok = DUK__ADVTOK(2, DUK_TOK_EQ);
82934 		} else {
82935 			advtok = DUK__ADVTOK(1, DUK_TOK_EQUALSIGN);
82936 		}
82937 		break;
82938 	case DUK_ASC_EXCLAMATION:  /* '!' */
82939 		if (DUK__L1() == DUK_ASC_EQUALS && DUK__L2() == DUK_ASC_EQUALS) {
82940 			advtok = DUK__ADVTOK(3, DUK_TOK_SNEQ);
82941 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
82942 			advtok = DUK__ADVTOK(2, DUK_TOK_NEQ);
82943 		} else {
82944 			advtok = DUK__ADVTOK(1, DUK_TOK_LNOT);
82945 		}
82946 		break;
82947 	case DUK_ASC_PLUS:  /* '+' */
82948 		if (DUK__L1() == DUK_ASC_PLUS) {
82949 			advtok = DUK__ADVTOK(2, DUK_TOK_INCREMENT);
82950 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
82951 			advtok = DUK__ADVTOK(2, DUK_TOK_ADD_EQ);
82952 		} else {
82953 			advtok = DUK__ADVTOK(1, DUK_TOK_ADD);
82954 		}
82955 		break;
82956 	case DUK_ASC_MINUS:  /* '-' */
82957 #if defined(DUK_USE_HTML_COMMENTS)
82958 		if (got_lineterm && DUK__L1() == DUK_ASC_MINUS && DUK__L2() == DUK_ASC_RANGLE) {
82959 			/*
82960 			 *  ES2015: B.1.3, handle "-->" SingleLineHTMLCloseComment
82961 			 *  Only allowed:
82962 			 *  - on new line
82963 			 *  - preceded only by whitespace
82964 			 *  - preceded by end of multiline comment and optional whitespace
82965 			 *
82966 			 * Since whitespace generates no tokens, and multiline comments
82967 			 * are treated as a line ending, consulting `got_lineterm` is
82968 			 * sufficient to test for these three options.
82969 			 */
82970 
82971 			/* DUK__ADVANCECHARS(lex_ctx, 3) would be correct here, but not necessary */
82972 			duk__lexer_skip_to_endofline(lex_ctx);
82973 			goto restart;  /* line terminator will be handled on next round */
82974 		} else
82975 #endif  /* DUK_USE_HTML_COMMENTS */
82976 		if (DUK__L1() == DUK_ASC_MINUS) {
82977 			advtok = DUK__ADVTOK(2, DUK_TOK_DECREMENT);
82978 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
82979 			advtok = DUK__ADVTOK(2, DUK_TOK_SUB_EQ);
82980 		} else {
82981 			advtok = DUK__ADVTOK(1, DUK_TOK_SUB);
82982 		}
82983 		break;
82984 	case DUK_ASC_STAR:  /* '*' */
82985 #if defined(DUK_USE_ES7_EXP_OPERATOR)
82986 		if (DUK__L1() == DUK_ASC_STAR && DUK__L2() == DUK_ASC_EQUALS) {
82987 			advtok = DUK__ADVTOK(3, DUK_TOK_EXP_EQ);
82988 		} else if (DUK__L1() == DUK_ASC_STAR) {
82989 			advtok = DUK__ADVTOK(2, DUK_TOK_EXP);
82990 		} else
82991 #endif
82992 		if (DUK__L1() == DUK_ASC_EQUALS) {
82993 			advtok = DUK__ADVTOK(2, DUK_TOK_MUL_EQ);
82994 		} else {
82995 			advtok = DUK__ADVTOK(1, DUK_TOK_MUL);
82996 		}
82997 		break;
82998 	case DUK_ASC_PERCENT:  /* '%' */
82999 		if (DUK__L1() == DUK_ASC_EQUALS) {
83000 			advtok = DUK__ADVTOK(2, DUK_TOK_MOD_EQ);
83001 		} else {
83002 			advtok = DUK__ADVTOK(1, DUK_TOK_MOD);
83003 		}
83004 		break;
83005 	case DUK_ASC_AMP:  /* '&' */
83006 		if (DUK__L1() == DUK_ASC_AMP) {
83007 			advtok = DUK__ADVTOK(2, DUK_TOK_LAND);
83008 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
83009 			advtok = DUK__ADVTOK(2, DUK_TOK_BAND_EQ);
83010 		} else {
83011 			advtok = DUK__ADVTOK(1, DUK_TOK_BAND);
83012 		}
83013 		break;
83014 	case DUK_ASC_PIPE:  /* '|' */
83015 		if (DUK__L1() == DUK_ASC_PIPE) {
83016 			advtok = DUK__ADVTOK(2, DUK_TOK_LOR);
83017 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
83018 			advtok = DUK__ADVTOK(2, DUK_TOK_BOR_EQ);
83019 		} else {
83020 			advtok = DUK__ADVTOK(1, DUK_TOK_BOR);
83021 		}
83022 		break;
83023 	case DUK_ASC_CARET:  /* '^' */
83024 		if (DUK__L1() == DUK_ASC_EQUALS) {
83025 			advtok = DUK__ADVTOK(2, DUK_TOK_BXOR_EQ);
83026 		} else {
83027 			advtok = DUK__ADVTOK(1, DUK_TOK_BXOR);
83028 		}
83029 		break;
83030 	case DUK_ASC_TILDE:  /* '~' */
83031 		advtok = DUK__ADVTOK(1, DUK_TOK_BNOT);
83032 		break;
83033 	case DUK_ASC_QUESTION:  /* '?' */
83034 		advtok = DUK__ADVTOK(1, DUK_TOK_QUESTION);
83035 		break;
83036 	case DUK_ASC_COLON:  /* ':' */
83037 		advtok = DUK__ADVTOK(1, DUK_TOK_COLON);
83038 		break;
83039 	case DUK_ASC_DOUBLEQUOTE:    /* '"' */
83040 	case DUK_ASC_SINGLEQUOTE: {  /* '\'' */
83041 		DUK__INITBUFFER(lex_ctx);
83042 		duk__lexer_parse_string_literal(lex_ctx, out_token, x /*quote*/, strict_mode);
83043 		duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
83044 		out_token->str1 = duk_known_hstring(lex_ctx->thr, lex_ctx->slot1_idx);
83045 
83046 		DUK__INITBUFFER(lex_ctx);  /* free some memory */
83047 
83048 		advtok = DUK__ADVTOK(0, DUK_TOK_STRING);
83049 		break;
83050 	}
83051 	default:
83052 		goto slow_path;
83053 	}  /* switch */
83054 
83055 	goto skip_slow_path;
83056 
83057  slow_path:
83058 	if (duk_unicode_is_line_terminator(x)) {
83059 		if (x == 0x000d && DUK__L1() == 0x000a) {
83060 			/*
83061 			 *  E5 Section 7.3: CR LF is detected as a single line terminator for
83062 			 *  line numbers.  Here we also detect it as a single line terminator
83063 			 *  token.
83064 			 */
83065 			DUK__ADVANCECHARS(lex_ctx, 2);
83066 		} else {
83067 			DUK__ADVANCECHARS(lex_ctx, 1);
83068 		}
83069 		got_lineterm = 1;
83070 		goto restart_lineupdate;
83071 	} else if (duk_unicode_is_identifier_start(x) || x == DUK_ASC_BACKSLASH) {
83072 		/*
83073 		 *  Parse an identifier and then check whether it is:
83074 		 *    - reserved word (keyword or other reserved word)
83075 		 *    - "null"  (NullLiteral)
83076 		 *    - "true"  (BooleanLiteral)
83077 		 *    - "false" (BooleanLiteral)
83078 		 *    - anything else => identifier
83079 		 *
83080 		 *  This does not follow the E5 productions cleanly, but is
83081 		 *  useful and compact.
83082 		 *
83083 		 *  Note that identifiers may contain Unicode escapes,
83084 		 *  see E5 Sections 6 and 7.6.  They must be decoded first,
83085 		 *  and the result checked against allowed characters.
83086 		 *  The above if-clause accepts an identifier start and an
83087 		 *  '\' character -- no other token can begin with a '\'.
83088 		 *
83089 		 *  Note that "get" and "set" are not reserved words in E5
83090 		 *  specification so they are recognized as plain identifiers
83091 		 *  (the tokens DUK_TOK_GET and DUK_TOK_SET are actually not
83092 		 *  used now).  The compiler needs to work around this.
83093 		 *
83094 		 *  Strictly speaking, following ECMAScript longest match
83095 		 *  specification, an invalid escape for the first character
83096 		 *  should cause a syntax error.  However, an invalid escape
83097 		 *  for IdentifierParts should just terminate the identifier
83098 		 *  early (longest match), and let the next tokenization
83099 		 *  fail.  For instance Rhino croaks with 'foo\z' when
83100 		 *  parsing the identifier.  This has little practical impact.
83101 		 */
83102 
83103 		duk_small_uint_t i, i_end;
83104 		duk_bool_t first = 1;
83105 		duk_hstring *str;
83106 
83107 		DUK__INITBUFFER(lex_ctx);
83108 		for (;;) {
83109 			/* re-lookup first char on first loop */
83110 			if (DUK__L0() == DUK_ASC_BACKSLASH) {
83111 				duk_codepoint_t esc_cp;
83112 				if (DUK__L1() != DUK_ASC_LC_U) {
83113 					goto fail_escape;
83114 				}
83115 				esc_cp = duk__lexer_parse_escape(lex_ctx, 1 /*allow_es6*/);
83116 				DUK__APPENDBUFFER(lex_ctx, esc_cp);
83117 
83118 				/* IdentifierStart is stricter than IdentifierPart, so if the first
83119 				 * character is escaped, must have a stricter check here.
83120 				 */
83121 				if (!(first ? duk_unicode_is_identifier_start(esc_cp) : duk_unicode_is_identifier_part(esc_cp))) {
83122 					goto fail_escape;
83123 				}
83124 
83125 				/* Track number of escapes: necessary for proper keyword
83126 				 * detection.
83127 				 */
83128 				out_token->num_escapes++;
83129 			} else {
83130 				/* Note: first character is checked against this.  But because
83131 				 * IdentifierPart includes all IdentifierStart characters, and
83132 				 * the first character (if unescaped) has already been checked
83133 				 * in the if condition, this is OK.
83134 				 */
83135 				if (!duk_unicode_is_identifier_part(DUK__L0())) {
83136 					break;
83137 				}
83138 				DUK__APPENDBUFFER(lex_ctx, DUK__L0());
83139 				DUK__ADVANCECHARS(lex_ctx, 1);
83140 			}
83141 			first = 0;
83142 		}
83143 
83144 		out_token->str1 = duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
83145 		str = out_token->str1;
83146 		out_token->t_nores = DUK_TOK_IDENTIFIER;
83147 
83148 		DUK__INITBUFFER(lex_ctx);  /* free some memory */
83149 
83150 		/*
83151 		 *  Interned identifier is compared against reserved words, which are
83152 		 *  currently interned into the heap context.  See genbuiltins.py.
83153 		 *
83154 		 *  Note that an escape in the identifier disables recognition of
83155 		 *  keywords; e.g. "\u0069f = 1;" is a valid statement (assigns to
83156 		 *  identifier named "if").  This is not necessarily compliant,
83157 		 *  see test-dec-escaped-char-in-keyword.js.
83158 		 *
83159 		 *  Note: "get" and "set" are awkward.  They are not officially
83160 		 *  ReservedWords (and indeed e.g. "var set = 1;" is valid), and
83161 		 *  must come out as DUK_TOK_IDENTIFIER.  The compiler needs to
83162 		 *  work around this a bit.
83163 		 */
83164 
83165 		/* XXX: optimize by adding the token numbers directly into the
83166 		 * always interned duk_hstring objects (there should be enough
83167 		 * flag bits free for that)?
83168 		 */
83169 
83170 		i_end = (strict_mode ? DUK_STRIDX_END_RESERVED : DUK_STRIDX_START_STRICT_RESERVED);
83171 
83172 		advtok = DUK__ADVTOK(0, DUK_TOK_IDENTIFIER);
83173 		if (out_token->num_escapes == 0) {
83174 			for (i = DUK_STRIDX_START_RESERVED; i < i_end; i++) {
83175 				DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
83176 				DUK_ASSERT(i < DUK_HEAP_NUM_STRINGS);
83177 				if (DUK_HTHREAD_GET_STRING(lex_ctx->thr, i) == str) {
83178 					advtok = DUK__ADVTOK(0, DUK_STRIDX_TO_TOK(i));
83179 					break;
83180 				}
83181 			}
83182 		}
83183 	} else if (DUK__ISDIGIT(x) || (x == DUK_ASC_PERIOD)) {
83184 		/* Note: decimal number may start with a period, but must be followed by a digit */
83185 
83186 		/*
83187 		 *  Pre-parsing for decimal, hex, octal (both legacy and ES2015),
83188 		 *  and binary literals, followed by an actual parser step
83189 		 *  provided by numconv.
83190 		 *
83191 		 *  Note: the leading sign character ('+' or '-') is -not- part of
83192 		 *  the production in E5 grammar, and that the a DecimalLiteral
83193 		 *  starting with a '0' must be followed by a non-digit.
83194 		 *
83195 		 *  XXX: the two step parsing process is quite awkward, it would
83196 		 *  be more straightforward to allow numconv to parse the longest
83197 		 *  valid prefix (it already does that, it only needs to indicate
83198 		 *  where the input ended).  However, the lexer decodes characters
83199 		 *  using a limited lookup window, so this is not a trivial change.
83200 		 */
83201 
83202 		/* XXX: because of the final check below (that the literal is not
83203 		 * followed by a digit), this could maybe be simplified, if we bail
83204 		 * out early from a leading zero (and if there are no periods etc).
83205 		 * Maybe too complex.
83206 		 */
83207 
83208 		duk_double_t val;
83209 		duk_bool_t legacy_oct = 0;
83210 		duk_small_int_t state;  /* 0=before period/exp,
83211 		                         * 1=after period, before exp
83212 		                         * 2=after exp, allow '+' or '-'
83213 		                         * 3=after exp and exp sign
83214 		                         */
83215 		duk_small_uint_t s2n_flags;
83216 		duk_codepoint_t y, z;
83217 		duk_small_int_t s2n_radix = 10;
83218 		duk_small_uint_t pre_adv = 0;
83219 
83220 		DUK__INITBUFFER(lex_ctx);
83221 		y = DUK__L1();
83222 
83223 		if (x == DUK_ASC_0) {
83224 			z = DUK_LOWERCASE_CHAR_ASCII(y);
83225 
83226 			pre_adv = 2;  /* default for 0xNNN, 0oNNN, 0bNNN. */
83227 			if (z == DUK_ASC_LC_X) {
83228 				s2n_radix = 16;
83229 			} else if (z == DUK_ASC_LC_O) {
83230 				s2n_radix = 8;
83231 			} else if (z == DUK_ASC_LC_B) {
83232 				s2n_radix = 2;
83233 			} else {
83234 				pre_adv = 0;
83235 				if (DUK__ISDIGIT(y)) {
83236 					if (strict_mode) {
83237 						/* Reject octal like \07 but also octal-lookalike
83238 						 * decimal like \08 in strict mode.
83239 						 */
83240 						goto fail_number_literal;
83241 					} else {
83242 						/* Legacy OctalIntegerLiteral or octal-lookalice
83243 						 * decimal.  Deciding between the two happens below
83244 						 * in digit scanning.
83245 						 */
83246 						DUK__APPENDBUFFER(lex_ctx, x);
83247 						pre_adv = 1;
83248 						legacy_oct = 1;
83249 						s2n_radix = 8;  /* tentative unless conflicting digits found */
83250 					}
83251 				}
83252 			}
83253 		}
83254 
83255 		DUK__ADVANCECHARS(lex_ctx, pre_adv);
83256 
83257 		/* XXX: we could parse integers here directly, and fall back
83258 		 * to numconv only when encountering a fractional expression
83259 		 * or when an octal literal turned out to be decimal (0778 etc).
83260 		 */
83261 		state = 0;
83262 		for (;;) {
83263 			x = DUK__L0();  /* re-lookup curr char on first round */
83264 			if (DUK__ISDIGIT(x)) {
83265 				/* Note: intentionally allow leading zeroes here, as the
83266 				 * actual parser will check for them.
83267 				 */
83268 				if (state == 0 && legacy_oct && (x == DUK_ASC_8 || x == DUK_ASC_9)) {
83269 					/* Started out as an octal-lookalike
83270 					 * but interpreted as decimal, e.g.
83271 					 * '0779' -> 779.  This also means
83272 					 * that fractions are allowed, e.g.
83273 					 * '0779.123' is allowed but '0777.123'
83274 					 * is not!
83275 					 */
83276 					s2n_radix = 10;
83277 				}
83278 				if (state == 2) {
83279 					state = 3;
83280 				}
83281 			} else if (s2n_radix == 16 && DUK__ISHEXDIGIT(x)) {
83282 				/* Note: 'e' and 'E' are also accepted here. */
83283 				;
83284 			} else if (x == DUK_ASC_PERIOD) {
83285 				if (state >= 1 || s2n_radix != 10) {
83286 					break;
83287 				} else {
83288 					state = 1;
83289 				}
83290 			} else if (x == DUK_ASC_LC_E || x == DUK_ASC_UC_E) {
83291 				if (state >= 2 || s2n_radix != 10) {
83292 					break;
83293 				} else {
83294 					state = 2;
83295 				}
83296 			} else if (x == DUK_ASC_MINUS || x == DUK_ASC_PLUS) {
83297 				if (state != 2) {
83298 					break;
83299 				} else {
83300 					state = 3;
83301 				}
83302 			} else {
83303 				break;
83304 			}
83305 			DUK__APPENDBUFFER(lex_ctx, x);
83306 			DUK__ADVANCECHARS(lex_ctx, 1);
83307 		}
83308 
83309 		/* XXX: better coercion */
83310 		(void) duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
83311 
83312 		if (s2n_radix != 10) {
83313 			/* For bases other than 10, integer only. */
83314 			s2n_flags = DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
83315 		} else {
83316 			s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
83317 			            DUK_S2N_FLAG_ALLOW_FRAC |
83318 			            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
83319 			            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
83320 			            DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
83321 		}
83322 
83323 		duk_dup(lex_ctx->thr, lex_ctx->slot1_idx);
83324 		duk_numconv_parse(lex_ctx->thr, s2n_radix, s2n_flags);
83325 		val = duk_to_number_m1(lex_ctx->thr);
83326 		if (DUK_ISNAN(val)) {
83327 			goto fail_number_literal;
83328 		}
83329 		duk_replace(lex_ctx->thr, lex_ctx->slot1_idx);  /* could also just pop? */
83330 
83331 		DUK__INITBUFFER(lex_ctx);  /* free some memory */
83332 
83333 		/* Section 7.8.3 (note): NumericLiteral must be followed by something other than
83334 		 * IdentifierStart or DecimalDigit.
83335 		 */
83336 
83337 		if (DUK__ISDIGIT(DUK__L0()) || duk_unicode_is_identifier_start(DUK__L0())) {
83338 			goto fail_number_literal;
83339 		}
83340 
83341 		out_token->num = val;
83342 		advtok = DUK__ADVTOK(0, DUK_TOK_NUMBER);
83343 	} else if (duk_unicode_is_whitespace(DUK__LOOKUP(lex_ctx, 0))) {
83344 		DUK__ADVANCECHARS(lex_ctx, 1);
83345 		goto restart;
83346 	} else if (x < 0) {
83347 		advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
83348 	} else {
83349 		goto fail_token;
83350 	}
83351  skip_slow_path:
83352 
83353 	/*
83354 	 *  Shared exit path
83355 	 */
83356 
83357 	DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
83358 	out_token->t = advtok & 0xff;
83359 	if (out_token->t_nores == DUK_TOK_INVALID) {
83360 		out_token->t_nores = out_token->t;
83361 	}
83362 	out_token->lineterm = got_lineterm;
83363 
83364 	/* Automatic semicolon insertion is allowed if a token is preceded
83365 	 * by line terminator(s), or terminates a statement list (right curly
83366 	 * or EOF).
83367 	 */
83368 	if (got_lineterm || out_token->t == DUK_TOK_RCURLY || out_token->t == DUK_TOK_EOF) {
83369 		out_token->allow_auto_semi = 1;
83370 	} else {
83371 		out_token->allow_auto_semi = 0;
83372 	}
83373 
83374 	return;
83375 
83376  fail_token_limit:
83377 	DUK_ERROR_RANGE(lex_ctx->thr, DUK_STR_TOKEN_LIMIT);
83378 	DUK_WO_NORETURN(return;);
83379 
83380  fail_token:
83381 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_TOKEN);
83382 	DUK_WO_NORETURN(return;);
83383 
83384  fail_number_literal:
83385 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_NUMBER_LITERAL);
83386 	DUK_WO_NORETURN(return;);
83387 
83388  fail_escape:
83389 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
83390 	DUK_WO_NORETURN(return;);
83391 
83392  fail_unterm_regexp:
83393 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_REGEXP);
83394 	DUK_WO_NORETURN(return;);
83395 
83396  fail_unterm_comment:
83397 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_COMMENT);
83398 	DUK_WO_NORETURN(return;);
83399 
83400 #if !defined(DUK_USE_REGEXP_SUPPORT)
83401  fail_regexp_support:
83402 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_REGEXP_SUPPORT_DISABLED);
83403 	DUK_WO_NORETURN(return;);
83404 #endif
83405 }
83406 
83407 #if defined(DUK_USE_REGEXP_SUPPORT)
83408 
83409 /*
83410  *  Parse a RegExp token.  The grammar is described in E5 Section 15.10.
83411  *  Terminal constructions (such as quantifiers) are parsed directly here.
83412  *
83413  *  0xffffffffU is used as a marker for "infinity" in quantifiers.  Further,
83414  *  DUK__MAX_RE_QUANT_DIGITS limits the maximum number of digits that
83415  *  will be accepted for a quantifier.
83416  */
83417 
83418 DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token) {
83419 	duk_small_uint_t advtok = 0;  /* init is unnecessary but suppresses "may be used uninitialized" warnings */
83420 	duk_codepoint_t x, y;
83421 
83422 	if (++lex_ctx->token_count >= lex_ctx->token_limit) {
83423 		goto fail_token_limit;
83424 	}
83425 
83426 	duk_memzero(out_token, sizeof(*out_token));
83427 
83428 	x = DUK__L0();
83429 	y = DUK__L1();
83430 
83431 	DUK_DDD(DUK_DDDPRINT("parsing regexp token, L0=%ld, L1=%ld", (long) x, (long) y));
83432 
83433 	switch (x) {
83434 	case DUK_ASC_PIPE: {
83435 		advtok = DUK__ADVTOK(1, DUK_RETOK_DISJUNCTION);
83436 		break;
83437 	}
83438 	case DUK_ASC_CARET: {
83439 		advtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_START);
83440 		break;
83441 	}
83442 	case DUK_ASC_DOLLAR: {
83443 		advtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_END);
83444 		break;
83445 	}
83446 	case DUK_ASC_QUESTION: {
83447 		out_token->qmin = 0;
83448 		out_token->qmax = 1;
83449 		if (y == DUK_ASC_QUESTION) {
83450 			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
83451 			out_token->greedy = 0;
83452 		} else {
83453 			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
83454 			out_token->greedy = 1;
83455 		}
83456 		break;
83457 	}
83458 	case DUK_ASC_STAR: {
83459 		out_token->qmin = 0;
83460 		out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
83461 		if (y == DUK_ASC_QUESTION) {
83462 			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
83463 			out_token->greedy = 0;
83464 		} else {
83465 			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
83466 			out_token->greedy = 1;
83467 		}
83468 		break;
83469 	}
83470 	case DUK_ASC_PLUS: {
83471 		out_token->qmin = 1;
83472 		out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
83473 		if (y == DUK_ASC_QUESTION) {
83474 			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
83475 			out_token->greedy = 0;
83476 		} else {
83477 			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
83478 			out_token->greedy = 1;
83479 		}
83480 		break;
83481 	}
83482 	case DUK_ASC_LCURLY: {
83483 		/* Production allows 'DecimalDigits', including leading zeroes */
83484 		duk_uint32_t val1 = 0;
83485 		duk_uint32_t val2 = DUK_RE_QUANTIFIER_INFINITE;
83486 		duk_small_int_t digits = 0;
83487 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
83488 		duk_lexer_point lex_pt;
83489 #endif
83490 
83491 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
83492 		/* Store lexer position, restoring if quantifier is invalid. */
83493 		DUK_LEXER_GETPOINT(lex_ctx, &lex_pt);
83494 #endif
83495 
83496 		for (;;) {
83497 			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat '{' on entry */
83498 			x = DUK__L0();
83499 			if (DUK__ISDIGIT(x)) {
83500 				digits++;
83501 				val1 = val1 * 10 + (duk_uint32_t) duk__hexval(x);
83502 			} else if (x == DUK_ASC_COMMA) {
83503 				if (digits > DUK__MAX_RE_QUANT_DIGITS) {
83504 					goto invalid_quantifier;
83505 				}
83506 				if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
83507 					goto invalid_quantifier;
83508 				}
83509 				if (DUK__L1() == DUK_ASC_RCURLY) {
83510 					/* form: { DecimalDigits , }, val1 = min count */
83511 					if (digits == 0) {
83512 						goto invalid_quantifier;
83513 					}
83514 					out_token->qmin = val1;
83515 					out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
83516 					DUK__ADVANCECHARS(lex_ctx, 2);
83517 					break;
83518 				}
83519 				val2 = val1;
83520 				val1 = 0;
83521 				digits = 0;  /* not strictly necessary because of lookahead '}' above */
83522 			} else if (x == DUK_ASC_RCURLY) {
83523 				if (digits > DUK__MAX_RE_QUANT_DIGITS) {
83524 					goto invalid_quantifier;
83525 				}
83526 				if (digits == 0) {
83527 					goto invalid_quantifier;
83528 				}
83529 				if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
83530 					/* val2 = min count, val1 = max count */
83531 					out_token->qmin = val2;
83532 					out_token->qmax = val1;
83533 				} else {
83534 					/* val1 = count */
83535 					out_token->qmin = val1;
83536 					out_token->qmax = val1;
83537 				}
83538 				DUK__ADVANCECHARS(lex_ctx, 1);
83539 				break;
83540 			} else {
83541 				goto invalid_quantifier;
83542 			}
83543 		}
83544 		if (DUK__L0() == DUK_ASC_QUESTION) {
83545 			out_token->greedy = 0;
83546 			DUK__ADVANCECHARS(lex_ctx, 1);
83547 		} else {
83548 			out_token->greedy = 1;
83549 		}
83550 		advtok = DUK__ADVTOK(0, DUK_RETOK_QUANTIFIER);
83551 		break;
83552  invalid_quantifier:
83553 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
83554 		/* Failed to match the quantifier, restore lexer and parse
83555 		 * opening brace as a literal.
83556 		 */
83557 		DUK_LEXER_SETPOINT(lex_ctx, &lex_pt);
83558 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
83559 		out_token->num = DUK_ASC_LCURLY;
83560 #else
83561 		goto fail_quantifier;
83562 #endif
83563 		break;
83564 	}
83565 	case DUK_ASC_PERIOD: {
83566 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_PERIOD);
83567 		break;
83568 	}
83569 	case DUK_ASC_BACKSLASH: {
83570 		/* The E5.1 specification does not seem to allow IdentifierPart characters
83571 		 * to be used as identity escapes.  Unfortunately this includes '$', which
83572 		 * cannot be escaped as '\$'; it needs to be escaped e.g. as '\u0024'.
83573 		 * Many other implementations (including V8 and Rhino, for instance) do
83574 		 * accept '\$' as a valid identity escape, which is quite pragmatic, and
83575 		 * ES2015 Annex B relaxes the rules to allow these (and other) real world forms.
83576 		 */
83577 
83578 		advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);  /* default: char escape (two chars) */
83579 		if (y == DUK_ASC_LC_B) {
83580 			advtok = DUK__ADVTOK(2, DUK_RETOK_ASSERT_WORD_BOUNDARY);
83581 		} else if (y == DUK_ASC_UC_B) {
83582 			advtok = DUK__ADVTOK(2, DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY);
83583 		} else if (y == DUK_ASC_LC_F) {
83584 			out_token->num = 0x000c;
83585 		} else if (y == DUK_ASC_LC_N) {
83586 			out_token->num = 0x000a;
83587 		} else if (y == DUK_ASC_LC_T) {
83588 			out_token->num = 0x0009;
83589 		} else if (y == DUK_ASC_LC_R) {
83590 			out_token->num = 0x000d;
83591 		} else if (y == DUK_ASC_LC_V) {
83592 			out_token->num = 0x000b;
83593 		} else if (y == DUK_ASC_LC_C) {
83594 			x = DUK__L2();
83595 			if ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) ||
83596 			    (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {
83597 				out_token->num = (duk_uint32_t) (x % 32);
83598 				advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_CHAR);
83599 			} else {
83600 				goto fail_escape;
83601 			}
83602 		} else if (y == DUK_ASC_LC_X || y == DUK_ASC_LC_U) {
83603 			/* The token value is the Unicode codepoint without
83604 			 * it being decode into surrogate pair characters
83605 			 * here.  The \u{H+} is only allowed in Unicode mode
83606 			 * which we don't support yet.
83607 			 */
83608 			out_token->num = (duk_uint32_t) duk__lexer_parse_escape(lex_ctx, 0 /*allow_es6*/);
83609 			advtok = DUK__ADVTOK(0, DUK_RETOK_ATOM_CHAR);
83610 		} else if (y == DUK_ASC_LC_D) {
83611 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_DIGIT);
83612 		} else if (y == DUK_ASC_UC_D) {
83613 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_DIGIT);
83614 		} else if (y == DUK_ASC_LC_S) {
83615 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WHITE);
83616 		} else if (y == DUK_ASC_UC_S) {
83617 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_WHITE);
83618 		} else if (y == DUK_ASC_LC_W) {
83619 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WORD_CHAR);
83620 		} else if (y == DUK_ASC_UC_W) {
83621 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_WORD_CHAR);
83622 		} else if (DUK__ISDIGIT(y)) {
83623 			/* E5 Section 15.10.2.11 */
83624 			if (y == DUK_ASC_0) {
83625 				if (DUK__ISDIGIT(DUK__L2())) {
83626 					goto fail_escape;
83627 				}
83628 				out_token->num = 0x0000;
83629 				advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);
83630 			} else {
83631 				/* XXX: shared parsing? */
83632 				duk_uint32_t val = 0;
83633 				duk_small_int_t i;
83634 				for (i = 0; ; i++) {
83635 					if (i >= DUK__MAX_RE_DECESC_DIGITS) {
83636 						goto fail_escape;
83637 					}
83638 					DUK__ADVANCECHARS(lex_ctx, 1);  /* eat backslash on entry */
83639 					x = DUK__L0();
83640 					if (!DUK__ISDIGIT(x)) {
83641 						break;
83642 					}
83643 					val = val * 10 + (duk_uint32_t) duk__hexval(x);
83644 				}
83645 				/* DUK__L0() cannot be a digit, because the loop doesn't terminate if it is */
83646 				advtok = DUK__ADVTOK(0, DUK_RETOK_ATOM_BACKREFERENCE);
83647 				out_token->num = val;
83648 			}
83649 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
83650 		} else if (y >= 0) {
83651 			/* For ES2015 Annex B, accept any source character as identity
83652 			 * escape except 'c' which is used for control characters.
83653 			 * http://www.ecma-international.org/ecma-262/6.0/#sec-regular-expressions-patterns
83654 			 * Careful not to match end-of-buffer (<0) here.
83655 			 * This is not yet full ES2015 Annex B because cases above
83656 			 * (like hex escape) won't backtrack.
83657 			 */
83658 			DUK_ASSERT(y != DUK_ASC_LC_C);  /* covered above */
83659 #else  /* DUK_USE_ES6_REGEXP_SYNTAX */
83660 		} else if ((y >= 0 && !duk_unicode_is_identifier_part(y)) ||
83661 		           y == DUK_UNICODE_CP_ZWNJ ||
83662 		           y == DUK_UNICODE_CP_ZWJ) {
83663 			/* For ES5.1 identity escapes are not allowed for identifier
83664 			 * parts.  This conflicts with a lot of real world code as this
83665 			 * doesn't e.g. allow escaping a dollar sign as /\$/, see
83666 			 * test-regexp-identity-escape-dollar.js.
83667 			 */
83668 #endif  /* DUK_USE_ES6_REGEXP_SYNTAX */
83669 			out_token->num = (duk_uint32_t) y;
83670 		} else {
83671 			goto fail_escape;
83672 		}
83673 		break;
83674 	}
83675 	case DUK_ASC_LPAREN: {
83676 		/* XXX: naming is inconsistent: ATOM_END_GROUP ends an ASSERT_START_LOOKAHEAD */
83677 
83678 		if (y == DUK_ASC_QUESTION) {
83679 			if (DUK__L2() == DUK_ASC_EQUALS) {
83680 				/* (?= */
83681 				advtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_POS_LOOKAHEAD);
83682 			} else if (DUK__L2() == DUK_ASC_EXCLAMATION) {
83683 				/* (?! */
83684 				advtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD);
83685 			} else if (DUK__L2() == DUK_ASC_COLON) {
83686 				/* (?: */
83687 				advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_START_NONCAPTURE_GROUP);
83688 			} else {
83689 				goto fail_group;
83690 			}
83691 		} else {
83692 			/* ( */
83693 			advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CAPTURE_GROUP);
83694 		}
83695 		break;
83696 	}
83697 	case DUK_ASC_RPAREN: {
83698 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_END_GROUP);
83699 		break;
83700 	}
83701 	case DUK_ASC_LBRACKET: {
83702 		/*
83703 		 *  To avoid creating a heavy intermediate value for the list of ranges,
83704 		 *  only the start token ('[' or '[^') is parsed here.  The regexp
83705 		 *  compiler parses the ranges itself.
83706 		 */
83707 
83708 		/* XXX: with DUK_USE_ES6_REGEXP_SYNTAX we should allow left bracket
83709 		 * literal too, but it's not easy to parse without backtracking.
83710 		 */
83711 
83712 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CHARCLASS);
83713 		if (y == DUK_ASC_CARET) {
83714 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_START_CHARCLASS_INVERTED);
83715 		}
83716 		break;
83717 	}
83718 #if !defined(DUK_USE_ES6_REGEXP_SYNTAX)
83719 	case DUK_ASC_RCURLY:
83720 	case DUK_ASC_RBRACKET: {
83721 		/* Although these could be parsed as PatternCharacters unambiguously (here),
83722 		 * E5 Section 15.10.1 grammar explicitly forbids these as PatternCharacters.
83723 		 */
83724 		goto fail_invalid_char;
83725 		break;
83726 	}
83727 #endif
83728 	case -1: {
83729 		/* EOF */
83730 		advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
83731 		break;
83732 	}
83733 	default: {
83734 		/* PatternCharacter, all excluded characters are matched by cases above */
83735 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
83736 		out_token->num = (duk_uint32_t) x;
83737 		break;
83738 	}
83739 	}
83740 
83741 	/*
83742 	 *  Shared exit path
83743 	 */
83744 
83745 	DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
83746 	out_token->t = advtok & 0xff;
83747 	return;
83748 
83749  fail_token_limit:
83750 	DUK_ERROR_RANGE(lex_ctx->thr, DUK_STR_TOKEN_LIMIT);
83751 	DUK_WO_NORETURN(return;);
83752 
83753  fail_escape:
83754 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_ESCAPE);
83755 	DUK_WO_NORETURN(return;);
83756 
83757  fail_group:
83758 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_GROUP);
83759 	DUK_WO_NORETURN(return;);
83760 
83761 #if !defined(DUK_USE_ES6_REGEXP_SYNTAX)
83762  fail_invalid_char:
83763 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_CHARACTER);
83764 	DUK_WO_NORETURN(return;);
83765 
83766  fail_quantifier:
83767 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_QUANTIFIER);
83768 	DUK_WO_NORETURN(return;);
83769 #endif
83770 }
83771 
83772 /*
83773  *  Special parser for character classes; calls callback for every
83774  *  range parsed and returns the number of ranges present.
83775  */
83776 
83777 /* XXX: this duplicates functionality in duk_regexp.c where a similar loop is
83778  * required anyway.  We could use that BUT we need to update the regexp compiler
83779  * 'nranges' too.  Work this out a bit more cleanly to save space.
83780  */
83781 
83782 /* XXX: the handling of character range detection is a bit convoluted.
83783  * Try to simplify and make smaller.
83784  */
83785 
83786 /* XXX: logic for handling character ranges is now incorrect, it will accept
83787  * e.g. [\d-z] whereas it should croak from it?  SMJS accepts this too, though.
83788  *
83789  * Needs a read through and a lot of additional tests.
83790  */
83791 
83792 DUK_LOCAL
83793 void duk__emit_u16_direct_ranges(duk_lexer_ctx *lex_ctx,
83794                                  duk_re_range_callback gen_range,
83795                                  void *userdata,
83796                                  const duk_uint16_t *ranges,
83797                                  duk_small_int_t num) {
83798 	const duk_uint16_t *ranges_end;
83799 
83800 	DUK_UNREF(lex_ctx);
83801 
83802 	ranges_end = ranges + num;
83803 	while (ranges < ranges_end) {
83804 		/* mark range 'direct', bypass canonicalization (see Wiki) */
83805 		gen_range(userdata, (duk_codepoint_t) ranges[0], (duk_codepoint_t) ranges[1], 1);
83806 		ranges += 2;
83807 	}
83808 }
83809 
83810 DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata) {
83811 	duk_codepoint_t start = -1;
83812 	duk_codepoint_t ch;
83813 	duk_codepoint_t x;
83814 	duk_bool_t dash = 0;
83815 	duk_small_uint_t adv = 0;
83816 
83817 	DUK_DD(DUK_DDPRINT("parsing regexp ranges"));
83818 
83819 	for (;;) {
83820 		DUK__ADVANCECHARS(lex_ctx, adv);
83821 		adv = 1;
83822 
83823 		x = DUK__L0();
83824 
83825 		ch = -1;  /* not strictly necessary, but avoids "uninitialized variable" warnings */
83826 		DUK_UNREF(ch);
83827 
83828 		if (x < 0) {
83829 			goto fail_unterm_charclass;
83830 		} else if (x == DUK_ASC_RBRACKET) {
83831 			if (start >= 0) {
83832 				gen_range(userdata, start, start, 0);
83833 			}
83834 			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat ']' before finishing */
83835 			break;
83836 		} else if (x == DUK_ASC_MINUS) {
83837 			if (start >= 0 && !dash && DUK__L1() != DUK_ASC_RBRACKET) {
83838 				/* '-' as a range indicator */
83839 				dash = 1;
83840 				continue;
83841 			} else {
83842 				/* '-' verbatim */
83843 				ch = x;
83844 			}
83845 		} else if (x == DUK_ASC_BACKSLASH) {
83846 			/*
83847 			 *  The escapes are same as outside a character class, except that \b has a
83848 			 *  different meaning, and \B and backreferences are prohibited (see E5
83849 			 *  Section 15.10.2.19).  However, it's difficult to share code because we
83850 			 *  handle e.g. "\n" very differently: here we generate a single character
83851 			 *  range for it.
83852 			 */
83853 
83854 			/* XXX: ES2015 surrogate pair handling. */
83855 
83856 			x = DUK__L1();
83857 
83858 			adv = 2;
83859 
83860 			if (x == DUK_ASC_LC_B) {
83861 				/* Note: '\b' in char class is different than outside (assertion),
83862 				 * '\B' is not allowed and is caught by the duk_unicode_is_identifier_part()
83863 				 * check below.
83864 				 */
83865 				ch = 0x0008;
83866 			} else if (x == DUK_ASC_LC_F) {
83867 				ch = 0x000c;
83868 			} else if (x == DUK_ASC_LC_N) {
83869 				ch = 0x000a;
83870 			} else if (x == DUK_ASC_LC_T) {
83871 				ch = 0x0009;
83872 			} else if (x == DUK_ASC_LC_R) {
83873 				ch = 0x000d;
83874 			} else if (x == DUK_ASC_LC_V) {
83875 				ch = 0x000b;
83876 			} else if (x == DUK_ASC_LC_C) {
83877 				x = DUK__L2();
83878 				adv = 3;
83879 				if ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) ||
83880 				    (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {
83881 					ch = (x % 32);
83882 				} else {
83883 					goto fail_escape;
83884 				}
83885 			} else if (x == DUK_ASC_LC_X || x == DUK_ASC_LC_U) {
83886 				/* The \u{H+} form is only allowed in Unicode mode which
83887 				 * we don't support yet.
83888 				 */
83889 				ch = duk__lexer_parse_escape(lex_ctx, 0 /*allow_es6*/);
83890 				adv = 0;
83891 			} else if (x == DUK_ASC_LC_D) {
83892 				duk__emit_u16_direct_ranges(lex_ctx,
83893 				                            gen_range,
83894 				                            userdata,
83895 				                            duk_unicode_re_ranges_digit,
83896 				                            sizeof(duk_unicode_re_ranges_digit) / sizeof(duk_uint16_t));
83897 				ch = -1;
83898 			} else if (x == DUK_ASC_UC_D) {
83899 				duk__emit_u16_direct_ranges(lex_ctx,
83900 				                            gen_range,
83901 				                            userdata,
83902 				                            duk_unicode_re_ranges_not_digit,
83903 				                            sizeof(duk_unicode_re_ranges_not_digit) / sizeof(duk_uint16_t));
83904 				ch = -1;
83905 			} else if (x == DUK_ASC_LC_S) {
83906 				duk__emit_u16_direct_ranges(lex_ctx,
83907 				                            gen_range,
83908 				                            userdata,
83909 				                            duk_unicode_re_ranges_white,
83910 				                            sizeof(duk_unicode_re_ranges_white) / sizeof(duk_uint16_t));
83911 				ch = -1;
83912 			} else if (x == DUK_ASC_UC_S) {
83913 				duk__emit_u16_direct_ranges(lex_ctx,
83914 				                            gen_range,
83915 				                            userdata,
83916 				                            duk_unicode_re_ranges_not_white,
83917 				                            sizeof(duk_unicode_re_ranges_not_white) / sizeof(duk_uint16_t));
83918 				ch = -1;
83919 			} else if (x == DUK_ASC_LC_W) {
83920 				duk__emit_u16_direct_ranges(lex_ctx,
83921 				                            gen_range,
83922 				                            userdata,
83923 				                            duk_unicode_re_ranges_wordchar,
83924 				                            sizeof(duk_unicode_re_ranges_wordchar) / sizeof(duk_uint16_t));
83925 				ch = -1;
83926 			} else if (x == DUK_ASC_UC_W) {
83927 				duk__emit_u16_direct_ranges(lex_ctx,
83928 				                            gen_range,
83929 				                            userdata,
83930 				                            duk_unicode_re_ranges_not_wordchar,
83931 				                            sizeof(duk_unicode_re_ranges_not_wordchar) / sizeof(duk_uint16_t));
83932 				ch = -1;
83933 			} else if (DUK__ISDIGIT(x)) {
83934 				/* DecimalEscape, only \0 is allowed, no leading
83935 				 * zeroes are allowed.
83936 				 *
83937 				 * ES2015 Annex B also allows (maximal match) legacy
83938 				 * octal escapes up to \377 and \8 and \9 are
83939 				 * accepted as literal '8' and '9', also in strict mode.
83940 				 */
83941 
83942 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
83943 				ch = duk__lexer_parse_legacy_octal(lex_ctx, &adv, 0 /*reject_annex_b*/);
83944 				DUK_ASSERT(ch >= 0);  /* no rejections */
83945 #else
83946 				if (x == DUK_ASC_0 && !DUK__ISDIGIT(DUK__L2())) {
83947 					ch = 0x0000;
83948 				} else {
83949 					goto fail_escape;
83950 				}
83951 #endif
83952 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
83953 			} else if (x >= 0) {
83954 				/* IdentityEscape: ES2015 Annex B allows almost all
83955 				 * source characters here.  Match anything except
83956 				 * EOF here.
83957 				 */
83958 				ch = x;
83959 #else  /* DUK_USE_ES6_REGEXP_SYNTAX */
83960 			} else if (!duk_unicode_is_identifier_part(x)) {
83961 				/* IdentityEscape: ES5.1 doesn't allow identity escape
83962 				 * for identifier part characters, which conflicts with
83963 				 * some real world code.  For example, it doesn't allow
83964 				 * /[\$]/ which is awkward.
83965 				 */
83966 				ch = x;
83967 #endif  /* DUK_USE_ES6_REGEXP_SYNTAX */
83968 			} else {
83969 				goto fail_escape;
83970 			}
83971 		} else {
83972 			/* character represents itself */
83973 			ch = x;
83974 		}
83975 
83976 		/* ch is a literal character here or -1 if parsed entity was
83977 		 * an escape such as "\s".
83978 		 */
83979 
83980 		if (ch < 0) {
83981 			/* multi-character sets not allowed as part of ranges, see
83982 			 * E5 Section 15.10.2.15, abstract operation CharacterRange.
83983 			 */
83984 			if (start >= 0) {
83985 				if (dash) {
83986 					goto fail_range;
83987 				} else {
83988 					gen_range(userdata, start, start, 0);
83989 					start = -1;
83990 					/* dash is already 0 */
83991 				}
83992 			}
83993 		} else {
83994 			if (start >= 0) {
83995 				if (dash) {
83996 					if (start > ch) {
83997 						goto fail_range;
83998 					}
83999 					gen_range(userdata, start, ch, 0);
84000 					start = -1;
84001 					dash = 0;
84002 				} else {
84003 					gen_range(userdata, start, start, 0);
84004 					start = ch;
84005 					/* dash is already 0 */
84006 				}
84007 			} else {
84008 				start = ch;
84009 			}
84010 		}
84011 	}
84012 
84013 	return;
84014 
84015  fail_escape:
84016 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_ESCAPE);
84017 	DUK_WO_NORETURN(return;);
84018 
84019  fail_range:
84020 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_RANGE);
84021 	DUK_WO_NORETURN(return;);
84022 
84023  fail_unterm_charclass:
84024 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_CHARCLASS);
84025 	DUK_WO_NORETURN(return;);
84026 }
84027 
84028 #endif  /* DUK_USE_REGEXP_SUPPORT */
84029 
84030 /* automatic undefs */
84031 #undef DUK__ADVANCEBYTES
84032 #undef DUK__ADVANCECHARS
84033 #undef DUK__ADVTOK
84034 #undef DUK__APPENDBUFFER
84035 #undef DUK__APPENDBUFFER_ASCII
84036 #undef DUK__INITBUFFER
84037 #undef DUK__ISDIGIT
84038 #undef DUK__ISDIGIT03
84039 #undef DUK__ISDIGIT47
84040 #undef DUK__ISHEXDIGIT
84041 #undef DUK__ISOCTDIGIT
84042 #undef DUK__L0
84043 #undef DUK__L1
84044 #undef DUK__L2
84045 #undef DUK__L3
84046 #undef DUK__L4
84047 #undef DUK__L5
84048 #undef DUK__LOOKUP
84049 #undef DUK__MAX_RE_DECESC_DIGITS
84050 #undef DUK__MAX_RE_QUANT_DIGITS
84051 #line 1 "duk_numconv.c"
84052 /*
84053  *  Number-to-string and string-to-number conversions.
84054  *
84055  *  Slow path number-to-string and string-to-number conversion is based on
84056  *  a Dragon4 variant, with fast paths for small integers.  Big integer
84057  *  arithmetic is needed for guaranteeing that the conversion is correct
84058  *  and uses a minimum number of digits.  The big number arithmetic has a
84059  *  fixed maximum size and does not require dynamic allocations.
84060  *
84061  *  See: doc/number-conversion.rst.
84062  */
84063 
84064 /* #include duk_internal.h -> already included */
84065 
84066 #define DUK__IEEE_DOUBLE_EXP_BIAS  1023
84067 #define DUK__IEEE_DOUBLE_EXP_MIN   (-1022)   /* biased exp == 0 -> denormal, exp -1022 */
84068 
84069 #define DUK__DIGITCHAR(x)  duk_lc_digits[(x)]
84070 
84071 /*
84072  *  Tables generated with util/gennumdigits.py.
84073  *
84074  *  duk__str2num_digits_for_radix indicates, for each radix, how many input
84075  *  digits should be considered significant for string-to-number conversion.
84076  *  The input is also padded to this many digits to give the Dragon4
84077  *  conversion enough (apparent) precision to work with.
84078  *
84079  *  duk__str2num_exp_limits indicates, for each radix, the radix-specific
84080  *  minimum/maximum exponent values (for a Dragon4 integer mantissa)
84081  *  below and above which the number is guaranteed to underflow to zero
84082  *  or overflow to Infinity.  This allows parsing to keep bigint values
84083  *  bounded.
84084  */
84085 
84086 DUK_LOCAL const duk_uint8_t duk__str2num_digits_for_radix[] = {
84087 	69, 44, 35, 30, 27, 25, 23, 22, 20, 20,    /* 2 to 11 */
84088 	20, 19, 19, 18, 18, 17, 17, 17, 16, 16,    /* 12 to 21 */
84089 	16, 16, 16, 15, 15, 15, 15, 15, 15, 14,    /* 22 to 31 */
84090 	14, 14, 14, 14, 14                         /* 31 to 36 */
84091 };
84092 
84093 typedef struct {
84094 	duk_int16_t upper;
84095 	duk_int16_t lower;
84096 } duk__exp_limits;
84097 
84098 DUK_LOCAL const duk__exp_limits duk__str2num_exp_limits[] = {
84099 	{ 957, -1147 }, { 605, -725 },  { 479, -575 },  { 414, -496 },
84100 	{ 372, -446 },  { 342, -411 },  { 321, -384 },  { 304, -364 },
84101 	{ 291, -346 },  { 279, -334 },  { 268, -323 },  { 260, -312 },
84102 	{ 252, -304 },  { 247, -296 },  { 240, -289 },  { 236, -283 },
84103 	{ 231, -278 },  { 227, -273 },  { 223, -267 },  { 220, -263 },
84104 	{ 216, -260 },  { 213, -256 },  { 210, -253 },  { 208, -249 },
84105 	{ 205, -246 },  { 203, -244 },  { 201, -241 },  { 198, -239 },
84106 	{ 196, -237 },  { 195, -234 },  { 193, -232 },  { 191, -230 },
84107 	{ 190, -228 },  { 188, -226 },  { 187, -225 },
84108 };
84109 
84110 /*
84111  *  Limited functionality bigint implementation.
84112  *
84113  *  Restricted to non-negative numbers with less than 32 * DUK__BI_MAX_PARTS bits,
84114  *  with the caller responsible for ensuring this is never exceeded.  No memory
84115  *  allocation (except stack) is needed for bigint computation.  Operations
84116  *  have been tailored for number conversion needs.
84117  *
84118  *  Argument order is "assignment order", i.e. target first, then arguments:
84119  *  x <- y * z  -->  duk__bi_mul(x, y, z);
84120  */
84121 
84122 /* This upper value has been experimentally determined; debug build will check
84123  * bigint size with assertions.
84124  */
84125 #define DUK__BI_MAX_PARTS  37  /* 37x32 = 1184 bits */
84126 
84127 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
84128 #define DUK__BI_PRINT(name,x)  duk__bi_print((name),(x))
84129 #else
84130 #define DUK__BI_PRINT(name,x)
84131 #endif
84132 
84133 /* Current size is about 152 bytes. */
84134 typedef struct {
84135 	duk_small_int_t n;
84136 	duk_uint32_t v[DUK__BI_MAX_PARTS];  /* low to high */
84137 } duk__bigint;
84138 
84139 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
84140 DUK_LOCAL void duk__bi_print(const char *name, duk__bigint *x) {
84141 	/* Overestimate required size; debug code so not critical to be tight. */
84142 	char buf[DUK__BI_MAX_PARTS * 9 + 64];
84143 	char *p = buf;
84144 	duk_small_int_t i;
84145 
84146 	/* No NUL term checks in this debug code. */
84147 	p += DUK_SPRINTF(p, "%p n=%ld", (void *) x, (long) x->n);
84148 	if (x->n == 0) {
84149 		p += DUK_SPRINTF(p, " 0");
84150 	}
84151 	for (i = x->n - 1; i >= 0; i--) {
84152 		p += DUK_SPRINTF(p, " %08lx", (unsigned long) x->v[i]);
84153 	}
84154 
84155 	DUK_DDD(DUK_DDDPRINT("%s: %s", (const char *) name, (const char *) buf));
84156 }
84157 #endif
84158 
84159 #if defined(DUK_USE_ASSERTIONS)
84160 DUK_LOCAL duk_small_int_t duk__bi_is_valid(duk__bigint *x) {
84161 	return (duk_small_int_t)
84162 	       ( ((x->n >= 0) && (x->n <= DUK__BI_MAX_PARTS)) /* is valid size */ &&
84163 	         ((x->n == 0) || (x->v[x->n - 1] != 0)) /* is normalized */ );
84164 }
84165 #endif
84166 
84167 DUK_LOCAL void duk__bi_normalize(duk__bigint *x) {
84168 	duk_small_int_t i;
84169 
84170 	for (i = x->n - 1; i >= 0; i--) {
84171 		if (x->v[i] != 0) {
84172 			break;
84173 		}
84174 	}
84175 
84176 	/* Note: if 'x' is zero, x->n becomes 0 here */
84177 	x->n = i + 1;
84178 	DUK_ASSERT(duk__bi_is_valid(x));
84179 }
84180 
84181 /* x <- y */
84182 DUK_LOCAL void duk__bi_copy(duk__bigint *x, duk__bigint *y) {
84183 	duk_small_int_t n;
84184 
84185 	n = y->n;
84186 	x->n = n;
84187 	/* No need to special case n == 0. */
84188 	duk_memcpy((void *) x->v, (const void *) y->v, (size_t) (sizeof(duk_uint32_t) * (size_t) n));
84189 }
84190 
84191 DUK_LOCAL void duk__bi_set_small(duk__bigint *x, duk_uint32_t v) {
84192 	if (v == 0U) {
84193 		x->n = 0;
84194 	} else {
84195 		x->n = 1;
84196 		x->v[0] = v;
84197 	}
84198 	DUK_ASSERT(duk__bi_is_valid(x));
84199 }
84200 
84201 /* Return value: <0  <=>  x < y
84202  *                0  <=>  x == y
84203  *               >0  <=>  x > y
84204  */
84205 DUK_LOCAL int duk__bi_compare(duk__bigint *x, duk__bigint *y) {
84206 	duk_small_int_t i, nx, ny;
84207 	duk_uint32_t tx, ty;
84208 
84209 	DUK_ASSERT(duk__bi_is_valid(x));
84210 	DUK_ASSERT(duk__bi_is_valid(y));
84211 
84212 	nx = x->n;
84213 	ny = y->n;
84214 	if (nx > ny) {
84215 		goto ret_gt;
84216 	}
84217 	if (nx < ny) {
84218 		goto ret_lt;
84219 	}
84220 	for (i = nx - 1; i >= 0; i--) {
84221 		tx = x->v[i];
84222 		ty = y->v[i];
84223 
84224 		if (tx > ty) {
84225 			goto ret_gt;
84226 		}
84227 		if (tx < ty) {
84228 			goto ret_lt;
84229 		}
84230 	}
84231 
84232 	return 0;
84233 
84234  ret_gt:
84235 	return 1;
84236 
84237  ret_lt:
84238 	return -1;
84239 }
84240 
84241 /* x <- y + z */
84242 #if defined(DUK_USE_64BIT_OPS)
84243 DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
84244 	duk_uint64_t tmp;
84245 	duk_small_int_t i, ny, nz;
84246 
84247 	DUK_ASSERT(duk__bi_is_valid(y));
84248 	DUK_ASSERT(duk__bi_is_valid(z));
84249 
84250 	if (z->n > y->n) {
84251 		duk__bigint *t;
84252 		t = y; y = z; z = t;
84253 	}
84254 	DUK_ASSERT(y->n >= z->n);
84255 
84256 	ny = y->n; nz = z->n;
84257 	tmp = 0U;
84258 	for (i = 0; i < ny; i++) {
84259 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
84260 		tmp += y->v[i];
84261 		if (i < nz) {
84262 			tmp += z->v[i];
84263 		}
84264 		x->v[i] = (duk_uint32_t) (tmp & 0xffffffffUL);
84265 		tmp = tmp >> 32;
84266 	}
84267 	if (tmp != 0U) {
84268 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
84269 		x->v[i++] = (duk_uint32_t) tmp;
84270 	}
84271 	x->n = i;
84272 	DUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);
84273 
84274 	/* no need to normalize */
84275 	DUK_ASSERT(duk__bi_is_valid(x));
84276 }
84277 #else  /* DUK_USE_64BIT_OPS */
84278 DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
84279 	duk_uint32_t carry, tmp1, tmp2;
84280 	duk_small_int_t i, ny, nz;
84281 
84282 	DUK_ASSERT(duk__bi_is_valid(y));
84283 	DUK_ASSERT(duk__bi_is_valid(z));
84284 
84285 	if (z->n > y->n) {
84286 		duk__bigint *t;
84287 		t = y; y = z; z = t;
84288 	}
84289 	DUK_ASSERT(y->n >= z->n);
84290 
84291 	ny = y->n; nz = z->n;
84292 	carry = 0U;
84293 	for (i = 0; i < ny; i++) {
84294 		/* Carry is detected based on wrapping which relies on exact 32-bit
84295 		 * types.
84296 		 */
84297 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
84298 		tmp1 = y->v[i];
84299 		tmp2 = tmp1;
84300 		if (i < nz) {
84301 			tmp2 += z->v[i];
84302 		}
84303 
84304 		/* Careful with carry condition:
84305 		 *  - If carry not added: 0x12345678 + 0 + 0xffffffff = 0x12345677 (< 0x12345678)
84306 		 *  - If carry added:     0x12345678 + 1 + 0xffffffff = 0x12345678 (== 0x12345678)
84307 		 */
84308 		if (carry) {
84309 			tmp2++;
84310 			carry = (tmp2 <= tmp1 ? 1U : 0U);
84311 		} else {
84312 			carry = (tmp2 < tmp1 ? 1U : 0U);
84313 		}
84314 
84315 		x->v[i] = tmp2;
84316 	}
84317 	if (carry) {
84318 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
84319 		DUK_ASSERT(carry == 1U);
84320 		x->v[i++] = carry;
84321 	}
84322 	x->n = i;
84323 	DUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);
84324 
84325 	/* no need to normalize */
84326 	DUK_ASSERT(duk__bi_is_valid(x));
84327 }
84328 #endif  /* DUK_USE_64BIT_OPS */
84329 
84330 /* x <- y + z */
84331 DUK_LOCAL void duk__bi_add_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
84332 	duk__bigint tmp;
84333 
84334 	DUK_ASSERT(duk__bi_is_valid(y));
84335 
84336 	/* XXX: this could be optimized; there is only one call site now though */
84337 	duk__bi_set_small(&tmp, z);
84338 	duk__bi_add(x, y, &tmp);
84339 
84340 	DUK_ASSERT(duk__bi_is_valid(x));
84341 }
84342 
84343 #if 0  /* unused */
84344 /* x <- x + y, use t as temp */
84345 DUK_LOCAL void duk__bi_add_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
84346 	duk__bi_add(t, x, y);
84347 	duk__bi_copy(x, t);
84348 }
84349 #endif
84350 
84351 /* x <- y - z, require x >= y => z >= 0, i.e. y >= z */
84352 #if defined(DUK_USE_64BIT_OPS)
84353 DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
84354 	duk_small_int_t i, ny, nz;
84355 	duk_uint32_t ty, tz;
84356 	duk_int64_t tmp;
84357 
84358 	DUK_ASSERT(duk__bi_is_valid(y));
84359 	DUK_ASSERT(duk__bi_is_valid(z));
84360 	DUK_ASSERT(duk__bi_compare(y, z) >= 0);
84361 	DUK_ASSERT(y->n >= z->n);
84362 
84363 	ny = y->n; nz = z->n;
84364 	tmp = 0;
84365 	for (i = 0; i < ny; i++) {
84366 		ty = y->v[i];
84367 		if (i < nz) {
84368 			tz = z->v[i];
84369 		} else {
84370 			tz = 0;
84371 		}
84372 		tmp = (duk_int64_t) ty - (duk_int64_t) tz + tmp;
84373 		x->v[i] = (duk_uint32_t) ((duk_uint64_t) tmp & 0xffffffffUL);
84374 		tmp = tmp >> 32;  /* 0 or -1 */
84375 	}
84376 	DUK_ASSERT(tmp == 0);
84377 
84378 	x->n = i;
84379 	duk__bi_normalize(x);  /* need to normalize, may even cancel to 0 */
84380 	DUK_ASSERT(duk__bi_is_valid(x));
84381 }
84382 #else
84383 DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
84384 	duk_small_int_t i, ny, nz;
84385 	duk_uint32_t tmp1, tmp2, borrow;
84386 
84387 	DUK_ASSERT(duk__bi_is_valid(y));
84388 	DUK_ASSERT(duk__bi_is_valid(z));
84389 	DUK_ASSERT(duk__bi_compare(y, z) >= 0);
84390 	DUK_ASSERT(y->n >= z->n);
84391 
84392 	ny = y->n; nz = z->n;
84393 	borrow = 0U;
84394 	for (i = 0; i < ny; i++) {
84395 		/* Borrow is detected based on wrapping which relies on exact 32-bit
84396 		 * types.
84397 		 */
84398 		tmp1 = y->v[i];
84399 		tmp2 = tmp1;
84400 		if (i < nz) {
84401 			tmp2 -= z->v[i];
84402 		}
84403 
84404 		/* Careful with borrow condition:
84405 		 *  - If borrow not subtracted: 0x12345678 - 0 - 0xffffffff = 0x12345679 (> 0x12345678)
84406 		 *  - If borrow subtracted:     0x12345678 - 1 - 0xffffffff = 0x12345678 (== 0x12345678)
84407 		 */
84408 		if (borrow) {
84409 			tmp2--;
84410 			borrow = (tmp2 >= tmp1 ? 1U : 0U);
84411 		} else {
84412 			borrow = (tmp2 > tmp1 ? 1U : 0U);
84413 		}
84414 
84415 		x->v[i] = tmp2;
84416 	}
84417 	DUK_ASSERT(borrow == 0U);
84418 
84419 	x->n = i;
84420 	duk__bi_normalize(x);  /* need to normalize, may even cancel to 0 */
84421 	DUK_ASSERT(duk__bi_is_valid(x));
84422 }
84423 #endif
84424 
84425 #if 0  /* unused */
84426 /* x <- y - z */
84427 DUK_LOCAL void duk__bi_sub_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
84428 	duk__bigint tmp;
84429 
84430 	DUK_ASSERT(duk__bi_is_valid(y));
84431 
84432 	/* XXX: this could be optimized */
84433 	duk__bi_set_small(&tmp, z);
84434 	duk__bi_sub(x, y, &tmp);
84435 
84436 	DUK_ASSERT(duk__bi_is_valid(x));
84437 }
84438 #endif
84439 
84440 /* x <- x - y, use t as temp */
84441 DUK_LOCAL void duk__bi_sub_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
84442 	duk__bi_sub(t, x, y);
84443 	duk__bi_copy(x, t);
84444 }
84445 
84446 /* x <- y * z */
84447 DUK_LOCAL void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
84448 	duk_small_int_t i, j, nx, nz;
84449 
84450 	DUK_ASSERT(duk__bi_is_valid(y));
84451 	DUK_ASSERT(duk__bi_is_valid(z));
84452 
84453 	nx = y->n + z->n;  /* max possible */
84454 	DUK_ASSERT(nx <= DUK__BI_MAX_PARTS);
84455 
84456 	if (nx == 0) {
84457 		/* Both inputs are zero; cases where only one is zero can go
84458 		 * through main algorithm.
84459 		 */
84460 		x->n = 0;
84461 		return;
84462 	}
84463 
84464 	duk_memzero((void *) x->v, (size_t) (sizeof(duk_uint32_t) * (size_t) nx));
84465 	x->n = nx;
84466 
84467 	nz = z->n;
84468 	for (i = 0; i < y->n; i++) {
84469 #if defined(DUK_USE_64BIT_OPS)
84470 		duk_uint64_t tmp = 0U;
84471 		for (j = 0; j < nz; j++) {
84472 			tmp += (duk_uint64_t) y->v[i] * (duk_uint64_t) z->v[j] + x->v[i+j];
84473 			x->v[i+j] = (duk_uint32_t) (tmp & 0xffffffffUL);
84474 			tmp = tmp >> 32;
84475 		}
84476 		if (tmp > 0) {
84477 			DUK_ASSERT(i + j < nx);
84478 			DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
84479 			DUK_ASSERT(x->v[i+j] == 0U);
84480 			x->v[i+j] = (duk_uint32_t) tmp;
84481 		}
84482 #else
84483 		/*
84484 		 *  Multiply + add + carry for 32-bit components using only 16x16->32
84485 		 *  multiplies and carry detection based on unsigned overflow.
84486 		 *
84487 		 *    1st mult, 32-bit: (A*2^16 + B)
84488 		 *    2nd mult, 32-bit: (C*2^16 + D)
84489 		 *    3rd add, 32-bit: E
84490 		 *    4th add, 32-bit: F
84491 		 *
84492 		 *      (AC*2^16 + B) * (C*2^16 + D) + E + F
84493 		 *    = AC*2^32 + AD*2^16 + BC*2^16 + BD + E + F
84494 		 *    = AC*2^32 + (AD + BC)*2^16 + (BD + E + F)
84495 		 *    = AC*2^32 + AD*2^16 + BC*2^16 + (BD + E + F)
84496 		 */
84497 		duk_uint32_t a, b, c, d, e, f;
84498 		duk_uint32_t r, s, t;
84499 
84500 		a = y->v[i]; b = a & 0xffffUL; a = a >> 16;
84501 
84502 		f = 0;
84503 		for (j = 0; j < nz; j++) {
84504 			c = z->v[j]; d = c & 0xffffUL; c = c >> 16;
84505 			e = x->v[i+j];
84506 
84507 			/* build result as: (r << 32) + s: start with (BD + E + F) */
84508 			r = 0;
84509 			s = b * d;
84510 
84511 			/* add E */
84512 			t = s + e;
84513 			if (t < s) { r++; }  /* carry */
84514 			s = t;
84515 
84516 			/* add F */
84517 			t = s + f;
84518 			if (t < s) { r++; }  /* carry */
84519 			s = t;
84520 
84521 			/* add BC*2^16 */
84522 			t = b * c;
84523 			r += (t >> 16);
84524 			t = s + ((t & 0xffffUL) << 16);
84525 			if (t < s) { r++; }  /* carry */
84526 			s = t;
84527 
84528 			/* add AD*2^16 */
84529 			t = a * d;
84530 			r += (t >> 16);
84531 			t = s + ((t & 0xffffUL) << 16);
84532 			if (t < s) { r++; }  /* carry */
84533 			s = t;
84534 
84535 			/* add AC*2^32 */
84536 			t = a * c;
84537 			r += t;
84538 
84539 			DUK_DDD(DUK_DDDPRINT("ab=%08lx cd=%08lx ef=%08lx -> rs=%08lx %08lx",
84540 			                     (unsigned long) y->v[i], (unsigned long) z->v[j],
84541 			                     (unsigned long) x->v[i+j], (unsigned long) r,
84542 			                     (unsigned long) s));
84543 
84544 			x->v[i+j] = s;
84545 			f = r;
84546 		}
84547 		if (f > 0U) {
84548 			DUK_ASSERT(i + j < nx);
84549 			DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
84550 			DUK_ASSERT(x->v[i+j] == 0U);
84551 			x->v[i+j] = (duk_uint32_t) f;
84552 		}
84553 #endif  /* DUK_USE_64BIT_OPS */
84554 	}
84555 
84556 	duk__bi_normalize(x);
84557 	DUK_ASSERT(duk__bi_is_valid(x));
84558 }
84559 
84560 /* x <- y * z */
84561 DUK_LOCAL void duk__bi_mul_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
84562 	duk__bigint tmp;
84563 
84564 	DUK_ASSERT(duk__bi_is_valid(y));
84565 
84566 	/* XXX: this could be optimized */
84567 	duk__bi_set_small(&tmp, z);
84568 	duk__bi_mul(x, y, &tmp);
84569 
84570 	DUK_ASSERT(duk__bi_is_valid(x));
84571 }
84572 
84573 /* x <- x * y, use t as temp */
84574 DUK_LOCAL void duk__bi_mul_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
84575 	duk__bi_mul(t, x, y);
84576 	duk__bi_copy(x, t);
84577 }
84578 
84579 /* x <- x * y, use t as temp */
84580 DUK_LOCAL void duk__bi_mul_small_copy(duk__bigint *x, duk_uint32_t y, duk__bigint *t) {
84581 	duk__bi_mul_small(t, x, y);
84582 	duk__bi_copy(x, t);
84583 }
84584 
84585 DUK_LOCAL int duk__bi_is_even(duk__bigint *x) {
84586 	DUK_ASSERT(duk__bi_is_valid(x));
84587 	return (x->n == 0) || ((x->v[0] & 0x01) == 0);
84588 }
84589 
84590 DUK_LOCAL int duk__bi_is_zero(duk__bigint *x) {
84591 	DUK_ASSERT(duk__bi_is_valid(x));
84592 	return (x->n == 0);  /* this is the case for normalized numbers */
84593 }
84594 
84595 /* Bigint is 2^52.  Used to detect normalized IEEE double mantissa values
84596  * which are at the lowest edge (next floating point value downwards has
84597  * a different exponent).  The lowest mantissa has the form:
84598  *
84599  *     1000........000    (52 zeroes; only "hidden bit" is set)
84600  */
84601 DUK_LOCAL duk_small_int_t duk__bi_is_2to52(duk__bigint *x) {
84602 	DUK_ASSERT(duk__bi_is_valid(x));
84603 	return (duk_small_int_t)
84604 	        (x->n == 2) && (x->v[0] == 0U) && (x->v[1] == (1U << (52-32)));
84605 }
84606 
84607 /* x <- (1<<y) */
84608 DUK_LOCAL void duk__bi_twoexp(duk__bigint *x, duk_small_int_t y) {
84609 	duk_small_int_t n, r;
84610 
84611 	n = (y / 32) + 1;
84612 	DUK_ASSERT(n > 0);
84613 	r = y % 32;
84614 	duk_memzero((void *) x->v, sizeof(duk_uint32_t) * (size_t) n);
84615 	x->n = n;
84616 	x->v[n - 1] = (((duk_uint32_t) 1) << r);
84617 }
84618 
84619 /* x <- b^y; use t1 and t2 as temps */
84620 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) {
84621 	/* Fast path the binary case */
84622 
84623 	DUK_ASSERT(x != t1 && x != t2 && t1 != t2);  /* distinct bignums, easy mistake to make */
84624 	DUK_ASSERT(b >= 0);
84625 	DUK_ASSERT(y >= 0);
84626 
84627 	if (b == 2) {
84628 		duk__bi_twoexp(x, y);
84629 		return;
84630 	}
84631 
84632 	/* http://en.wikipedia.org/wiki/Exponentiation_by_squaring */
84633 
84634 	DUK_DDD(DUK_DDDPRINT("exp_small: b=%ld, y=%ld", (long) b, (long) y));
84635 
84636 	duk__bi_set_small(x, 1);
84637 	duk__bi_set_small(t1, (duk_uint32_t) b);
84638 	for (;;) {
84639 		/* Loop structure ensures that we don't compute t1^2 unnecessarily
84640 		 * on the final round, as that might create a bignum exceeding the
84641 		 * current DUK__BI_MAX_PARTS limit.
84642 		 */
84643 		if (y & 0x01) {
84644 			duk__bi_mul_copy(x, t1, t2);
84645 		}
84646 		y = y >> 1;
84647 		if (y == 0) {
84648 			break;
84649 		}
84650 		duk__bi_mul_copy(t1, t1, t2);
84651 	}
84652 
84653 	DUK__BI_PRINT("exp_small result", x);
84654 }
84655 
84656 /*
84657  *  A Dragon4 number-to-string variant, based on:
84658  *
84659  *    Guy L. Steele Jr., Jon L. White: "How to Print Floating-Point Numbers
84660  *    Accurately"
84661  *
84662  *    Robert G. Burger, R. Kent Dybvig: "Printing Floating-Point Numbers
84663  *    Quickly and Accurately"
84664  *
84665  *  The current algorithm is based on Figure 1 of the Burger-Dybvig paper,
84666  *  i.e. the base implementation without logarithm estimation speedups
84667  *  (these would increase code footprint considerably).  Fixed-format output
84668  *  does not follow the suggestions in the paper; instead, we generate an
84669  *  extra digit and round-with-carry.
84670  *
84671  *  The same algorithm is used for number parsing (with b=10 and B=2)
84672  *  by generating one extra digit and doing rounding manually.
84673  *
84674  *  See doc/number-conversion.rst for limitations.
84675  */
84676 
84677 /* Maximum number of digits generated. */
84678 #define DUK__MAX_OUTPUT_DIGITS          1040  /* (Number.MAX_VALUE).toString(2).length == 1024, + slack */
84679 
84680 /* Maximum number of characters in formatted value. */
84681 #define DUK__MAX_FORMATTED_LENGTH       1040  /* (-Number.MAX_VALUE).toString(2).length == 1025, + slack */
84682 
84683 /* Number and (minimum) size of bigints in the nc_ctx structure. */
84684 #define DUK__NUMCONV_CTX_NUM_BIGINTS    7
84685 #define DUK__NUMCONV_CTX_BIGINTS_SIZE   (sizeof(duk__bigint) * DUK__NUMCONV_CTX_NUM_BIGINTS)
84686 
84687 typedef struct {
84688 	/* Currently about 7*152 = 1064 bytes.  The space for these
84689 	 * duk__bigints is used also as a temporary buffer for generating
84690 	 * the final string.  This is a bit awkard; a union would be
84691 	 * more correct.
84692 	 */
84693 	duk__bigint f, r, s, mp, mm, t1, t2;
84694 
84695 	duk_small_int_t is_s2n;        /* if 1, doing a string-to-number; else doing a number-to-string */
84696 	duk_small_int_t is_fixed;      /* if 1, doing a fixed format output (not free format) */
84697 	duk_small_int_t req_digits;    /* requested number of output digits; 0 = free-format */
84698 	duk_small_int_t abs_pos;       /* digit position is absolute, not relative */
84699 	duk_small_int_t e;             /* exponent for 'f' */
84700 	duk_small_int_t b;             /* input radix */
84701 	duk_small_int_t B;             /* output radix */
84702 	duk_small_int_t k;             /* see algorithm */
84703 	duk_small_int_t low_ok;        /* see algorithm */
84704 	duk_small_int_t high_ok;       /* see algorithm */
84705 	duk_small_int_t unequal_gaps;  /* m+ != m- (very rarely) */
84706 
84707 	/* Buffer used for generated digits, values are in the range [0,B-1]. */
84708 	duk_uint8_t digits[DUK__MAX_OUTPUT_DIGITS];
84709 	duk_small_int_t count;  /* digit count */
84710 } duk__numconv_stringify_ctx;
84711 
84712 /* Note: computes with 'idx' in assertions, so caller beware.
84713  * 'idx' is preincremented, i.e. '1' on first call, because it
84714  * is more convenient for the caller.
84715  */
84716 #define DUK__DRAGON4_OUTPUT_PREINC(nc_ctx,preinc_idx,x)  do { \
84717 		DUK_ASSERT((preinc_idx) - 1 >= 0); \
84718 		DUK_ASSERT((preinc_idx) - 1 < DUK__MAX_OUTPUT_DIGITS); \
84719 		((nc_ctx)->digits[(preinc_idx) - 1]) = (duk_uint8_t) (x); \
84720 	} while (0)
84721 
84722 DUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x, duk_small_int_t radix) {
84723 	duk_uint8_t *p;
84724 	duk_size_t len;
84725 	duk_small_int_t dig;
84726 	duk_uint32_t t;
84727 
84728 	DUK_ASSERT(buf != NULL);
84729 	DUK_ASSERT(radix >= 2 && radix <= 36);
84730 
84731 	/* A 32-bit unsigned integer formats to at most 32 digits (the
84732 	 * worst case happens with radix == 2).  Output the digits backwards,
84733 	 * and use a memmove() to get them in the right place.
84734 	 */
84735 
84736 	p = buf + 32;
84737 	for (;;) {
84738 		t = x / (duk_uint32_t) radix;
84739 		dig = (duk_small_int_t) (x - t * (duk_uint32_t) radix);
84740 		x = t;
84741 
84742 		DUK_ASSERT(dig >= 0 && dig < 36);
84743 		*(--p) = DUK__DIGITCHAR(dig);
84744 
84745 		if (x == 0) {
84746 			break;
84747 		}
84748 	}
84749 	len = (duk_size_t) ((buf + 32) - p);
84750 
84751 	duk_memmove((void *) buf, (const void *) p, (size_t) len);
84752 
84753 	return len;
84754 }
84755 
84756 DUK_LOCAL void duk__dragon4_prepare(duk__numconv_stringify_ctx *nc_ctx) {
84757 	duk_small_int_t lowest_mantissa;
84758 
84759 #if 1
84760 	/* Assume IEEE round-to-even, so that shorter encoding can be used
84761 	 * when round-to-even would produce correct result.  By removing
84762 	 * this check (and having low_ok == high_ok == 0) the results would
84763 	 * still be accurate but in some cases longer than necessary.
84764 	 */
84765 	if (duk__bi_is_even(&nc_ctx->f)) {
84766 		DUK_DDD(DUK_DDDPRINT("f is even"));
84767 		nc_ctx->low_ok = 1;
84768 		nc_ctx->high_ok = 1;
84769 	} else {
84770 		DUK_DDD(DUK_DDDPRINT("f is odd"));
84771 		nc_ctx->low_ok = 0;
84772 		nc_ctx->high_ok = 0;
84773 	}
84774 #else
84775 	/* Note: not honoring round-to-even should work but now generates incorrect
84776 	 * results.  For instance, 1e23 serializes to "a000...", i.e. the first digit
84777 	 * equals the radix (10).  Scaling stops one step too early in this case.
84778 	 * Don't know why this is the case, but since this code path is unused, it
84779 	 * doesn't matter.
84780 	 */
84781 	nc_ctx->low_ok = 0;
84782 	nc_ctx->high_ok = 0;
84783 #endif
84784 
84785 	/* For string-to-number, pretend we never have the lowest mantissa as there
84786 	 * is no natural "precision" for inputs.  Having lowest_mantissa == 0, we'll
84787 	 * fall into the base cases for both e >= 0 and e < 0.
84788 	 */
84789 	if (nc_ctx->is_s2n) {
84790 		lowest_mantissa = 0;
84791 	} else {
84792 		lowest_mantissa = duk__bi_is_2to52(&nc_ctx->f);
84793 	}
84794 
84795 	nc_ctx->unequal_gaps = 0;
84796 	if (nc_ctx->e >= 0) {
84797 		/* exponent non-negative (and thus not minimum exponent) */
84798 
84799 		if (lowest_mantissa) {
84800 			/* (>= e 0) AND (= f (expt b (- p 1)))
84801 			 *
84802 			 * be <- (expt b e) == b^e
84803 			 * be1 <- (* be b) == (expt b (+ e 1)) == b^(e+1)
84804 			 * r <- (* f be1 2) == 2 * f * b^(e+1)    [if b==2 -> f * b^(e+2)]
84805 			 * s <- (* b 2)                           [if b==2 -> 4]
84806 			 * m+ <- be1 == b^(e+1)
84807 			 * m- <- be == b^e
84808 			 * k <- 0
84809 			 * B <- B
84810 			 * low_ok <- round
84811 			 * high_ok <- round
84812 			 */
84813 
84814 			DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
84815 			                     "lowest mantissa value for this exponent -> "
84816 			                     "unequal gaps"));
84817 
84818 			duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2);  /* mm <- b^e */
84819 			duk__bi_mul_small(&nc_ctx->mp, &nc_ctx->mm, (duk_uint32_t) nc_ctx->b);           /* mp <- b^(e+1) */
84820 			duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
84821 			duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp);              /* r <- (2 * f) * b^(e+1) */
84822 			duk__bi_set_small(&nc_ctx->s, (duk_uint32_t) (nc_ctx->b * 2));  /* s <- 2 * b */
84823 			nc_ctx->unequal_gaps = 1;
84824 		} else {
84825 			/* (>= e 0) AND (not (= f (expt b (- p 1))))
84826 			 *
84827 			 * be <- (expt b e) == b^e
84828 			 * r <- (* f be 2) == 2 * f * b^e    [if b==2 -> f * b^(e+1)]
84829 			 * s <- 2
84830 			 * m+ <- be == b^e
84831 			 * m- <- be == b^e
84832 			 * k <- 0
84833 			 * B <- B
84834 			 * low_ok <- round
84835 			 * high_ok <- round
84836 			 */
84837 
84838 			DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
84839 			                     "not lowest mantissa for this exponent -> "
84840 			                     "equal gaps"));
84841 
84842 			duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2);  /* mm <- b^e */
84843 			duk__bi_copy(&nc_ctx->mp, &nc_ctx->mm);                /* mp <- b^e */
84844 			duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
84845 			duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp);     /* r <- (2 * f) * b^e */
84846 			duk__bi_set_small(&nc_ctx->s, 2);                      /* s <- 2 */
84847 		}
84848 	} else {
84849 		/* When doing string-to-number, lowest_mantissa is always 0 so
84850 		 * the exponent check, while incorrect, won't matter.
84851 		 */
84852 		if (nc_ctx->e > DUK__IEEE_DOUBLE_EXP_MIN /*not minimum exponent*/ &&
84853 		    lowest_mantissa /* lowest mantissa for this exponent*/) {
84854 			/* r <- (* f b 2)                                [if b==2 -> (* f 4)]
84855 			 * s <- (* (expt b (- 1 e)) 2) == b^(1-e) * 2    [if b==2 -> b^(2-e)]
84856 			 * m+ <- b == 2
84857 			 * m- <- 1
84858 			 * k <- 0
84859 			 * B <- B
84860 			 * low_ok <- round
84861 			 * high_ok <- round
84862 			 */
84863 
84864 			DUK_DDD(DUK_DDDPRINT("negative exponent; not minimum exponent and "
84865 			                     "lowest mantissa for this exponent -> "
84866 			                     "unequal gaps"));
84867 
84868 			duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, (duk_uint32_t) (nc_ctx->b * 2));  /* r <- (2 * b) * f */
84869 			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 */
84870 			duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2);             /* s <- b^(1-e) * 2 */
84871 			duk__bi_set_small(&nc_ctx->mp, 2);
84872 			duk__bi_set_small(&nc_ctx->mm, 1);
84873 			nc_ctx->unequal_gaps = 1;
84874 		} else {
84875 			/* r <- (* f 2)
84876 			 * s <- (* (expt b (- e)) 2) == b^(-e) * 2    [if b==2 -> b^(1-e)]
84877 			 * m+ <- 1
84878 			 * m- <- 1
84879 			 * k <- 0
84880 			 * B <- B
84881 			 * low_ok <- round
84882 			 * high_ok <- round
84883 			 */
84884 
84885 			DUK_DDD(DUK_DDDPRINT("negative exponent; minimum exponent or not "
84886 			                     "lowest mantissa for this exponent -> "
84887 			                     "equal gaps"));
84888 
84889 			duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, 2);            /* r <- 2 * f */
84890 			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 */
84891 			duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2);           /* s <- b^(-e) * 2 */
84892 			duk__bi_set_small(&nc_ctx->mp, 1);
84893 			duk__bi_set_small(&nc_ctx->mm, 1);
84894 		}
84895 	}
84896 }
84897 
84898 DUK_LOCAL void duk__dragon4_scale(duk__numconv_stringify_ctx *nc_ctx) {
84899 	duk_small_int_t k = 0;
84900 
84901 	/* This is essentially the 'scale' algorithm, with recursion removed.
84902 	 * Note that 'k' is either correct immediately, or will move in one
84903 	 * direction in the loop.  There's no need to do the low/high checks
84904 	 * on every round (like the Scheme algorithm does).
84905 	 *
84906 	 * The scheme algorithm finds 'k' and updates 's' simultaneously,
84907 	 * while the logical algorithm finds 'k' with 's' having its initial
84908 	 * value, after which 's' is updated separately (see the Burger-Dybvig
84909 	 * paper, Section 3.1, steps 2 and 3).
84910 	 *
84911 	 * The case where m+ == m- (almost always) is optimized for, because
84912 	 * it reduces the bigint operations considerably and almost always
84913 	 * applies.  The scale loop only needs to work with m+, so this works.
84914 	 */
84915 
84916 	/* XXX: this algorithm could be optimized quite a lot by using e.g.
84917 	 * a logarithm based estimator for 'k' and performing B^n multiplication
84918 	 * using a lookup table or using some bit-representation based exp
84919 	 * algorithm.  Currently we just loop, with significant performance
84920 	 * impact for very large and very small numbers.
84921 	 */
84922 
84923 	DUK_DDD(DUK_DDDPRINT("scale: B=%ld, low_ok=%ld, high_ok=%ld",
84924 	                     (long) nc_ctx->B, (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
84925 	DUK__BI_PRINT("r(init)", &nc_ctx->r);
84926 	DUK__BI_PRINT("s(init)", &nc_ctx->s);
84927 	DUK__BI_PRINT("mp(init)", &nc_ctx->mp);
84928 	DUK__BI_PRINT("mm(init)", &nc_ctx->mm);
84929 
84930 	for (;;) {
84931 		DUK_DDD(DUK_DDDPRINT("scale loop (inc k), k=%ld", (long) k));
84932 		DUK__BI_PRINT("r", &nc_ctx->r);
84933 		DUK__BI_PRINT("s", &nc_ctx->s);
84934 		DUK__BI_PRINT("m+", &nc_ctx->mp);
84935 		DUK__BI_PRINT("m-", &nc_ctx->mm);
84936 
84937 		duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 = (+ r m+) */
84938 		if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1)) {
84939 			DUK_DDD(DUK_DDDPRINT("k is too low"));
84940 			/* r <- r
84941 			 * s <- (* s B)
84942 			 * m+ <- m+
84943 			 * m- <- m-
84944 			 * k <- (+ k 1)
84945 			 */
84946 
84947 			duk__bi_mul_small_copy(&nc_ctx->s, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
84948 			k++;
84949 		} else {
84950 			break;
84951 		}
84952 	}
84953 
84954 	/* k > 0 -> k was too low, and cannot be too high */
84955 	if (k > 0) {
84956 		goto skip_dec_k;
84957 	}
84958 
84959 	for (;;) {
84960 		DUK_DDD(DUK_DDDPRINT("scale loop (dec k), k=%ld", (long) k));
84961 		DUK__BI_PRINT("r", &nc_ctx->r);
84962 		DUK__BI_PRINT("s", &nc_ctx->s);
84963 		DUK__BI_PRINT("m+", &nc_ctx->mp);
84964 		DUK__BI_PRINT("m-", &nc_ctx->mm);
84965 
84966 		duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 = (+ r m+) */
84967 		duk__bi_mul_small(&nc_ctx->t2, &nc_ctx->t1, (duk_uint32_t) nc_ctx->B);   /* t2 = (* (+ r m+) B) */
84968 		if (duk__bi_compare(&nc_ctx->t2, &nc_ctx->s) <= (nc_ctx->high_ok ? -1 : 0)) {
84969 			DUK_DDD(DUK_DDDPRINT("k is too high"));
84970 			/* r <- (* r B)
84971 			 * s <- s
84972 			 * m+ <- (* m+ B)
84973 			 * m- <- (* m- B)
84974 			 * k <- (- k 1)
84975 			 */
84976 			duk__bi_mul_small_copy(&nc_ctx->r, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
84977 			duk__bi_mul_small_copy(&nc_ctx->mp, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
84978 			if (nc_ctx->unequal_gaps) {
84979 				DUK_DDD(DUK_DDDPRINT("m+ != m- -> need to update m- too"));
84980 				duk__bi_mul_small_copy(&nc_ctx->mm, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
84981 			}
84982 			k--;
84983 		} else {
84984 			break;
84985 		}
84986 	}
84987 
84988  skip_dec_k:
84989 
84990 	if (!nc_ctx->unequal_gaps) {
84991 		DUK_DDD(DUK_DDDPRINT("equal gaps, copy m- from m+"));
84992 		duk__bi_copy(&nc_ctx->mm, &nc_ctx->mp);  /* mm <- mp */
84993 	}
84994 	nc_ctx->k = k;
84995 
84996 	DUK_DDD(DUK_DDDPRINT("final k: %ld", (long) k));
84997 	DUK__BI_PRINT("r(final)", &nc_ctx->r);
84998 	DUK__BI_PRINT("s(final)", &nc_ctx->s);
84999 	DUK__BI_PRINT("mp(final)", &nc_ctx->mp);
85000 	DUK__BI_PRINT("mm(final)", &nc_ctx->mm);
85001 }
85002 
85003 DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) {
85004 	duk_small_int_t tc1, tc2;    /* terminating conditions */
85005 	duk_small_int_t d;           /* current digit */
85006 	duk_small_int_t count = 0;   /* digit count */
85007 
85008 	/*
85009 	 *  Digit generation loop.
85010 	 *
85011 	 *  Different termination conditions:
85012 	 *
85013 	 *    1. Free format output.  Terminate when shortest accurate
85014 	 *       representation found.
85015 	 *
85016 	 *    2. Fixed format output, with specific number of digits.
85017 	 *       Ignore termination conditions, terminate when digits
85018 	 *       generated.  Caller requests an extra digit and rounds.
85019 	 *
85020 	 *    3. Fixed format output, with a specific absolute cut-off
85021 	 *       position (e.g. 10 digits after decimal point).  Note
85022 	 *       that we always generate at least one digit, even if
85023 	 *       the digit is below the cut-off point already.
85024 	 */
85025 
85026 	for (;;) {
85027 		DUK_DDD(DUK_DDDPRINT("generate loop, count=%ld, k=%ld, B=%ld, low_ok=%ld, high_ok=%ld",
85028 		                     (long) count, (long) nc_ctx->k, (long) nc_ctx->B,
85029 		                     (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
85030 		DUK__BI_PRINT("r", &nc_ctx->r);
85031 		DUK__BI_PRINT("s", &nc_ctx->s);
85032 		DUK__BI_PRINT("m+", &nc_ctx->mp);
85033 		DUK__BI_PRINT("m-", &nc_ctx->mm);
85034 
85035 		/* (quotient-remainder (* r B) s) using a dummy subtraction loop */
85036 		duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, (duk_uint32_t) nc_ctx->B);       /* t1 <- (* r B) */
85037 		d = 0;
85038 		for (;;) {
85039 			if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {
85040 				break;
85041 			}
85042 			duk__bi_sub_copy(&nc_ctx->t1, &nc_ctx->s, &nc_ctx->t2);  /* t1 <- t1 - s */
85043 			d++;
85044 		}
85045 		duk__bi_copy(&nc_ctx->r, &nc_ctx->t1);  /* r <- (remainder (* r B) s) */
85046 		                                        /* d <- (quotient (* r B) s)   (in range 0...B-1) */
85047 		DUK_DDD(DUK_DDDPRINT("-> d(quot)=%ld", (long) d));
85048 		DUK__BI_PRINT("r(rem)", &nc_ctx->r);
85049 
85050 		duk__bi_mul_small_copy(&nc_ctx->mp, (duk_uint32_t) nc_ctx->B, &nc_ctx->t2); /* m+ <- (* m+ B) */
85051 		duk__bi_mul_small_copy(&nc_ctx->mm, (duk_uint32_t) nc_ctx->B, &nc_ctx->t2); /* m- <- (* m- B) */
85052 		DUK__BI_PRINT("mp(upd)", &nc_ctx->mp);
85053 		DUK__BI_PRINT("mm(upd)", &nc_ctx->mm);
85054 
85055 		/* Terminating conditions.  For fixed width output, we just ignore the
85056 		 * terminating conditions (and pretend that tc1 == tc2 == false).  The
85057 		 * the current shortcut for fixed-format output is to generate a few
85058 		 * extra digits and use rounding (with carry) to finish the output.
85059 		 */
85060 
85061 		if (nc_ctx->is_fixed == 0) {
85062 			/* free-form */
85063 			tc1 = (duk__bi_compare(&nc_ctx->r, &nc_ctx->mm) <= (nc_ctx->low_ok ? 0 : -1));
85064 
85065 			duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 <- (+ r m+) */
85066 			tc2 = (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1));
85067 
85068 			DUK_DDD(DUK_DDDPRINT("tc1=%ld, tc2=%ld", (long) tc1, (long) tc2));
85069 		} else {
85070 			/* fixed-format */
85071 			tc1 = 0;
85072 			tc2 = 0;
85073 		}
85074 
85075 		/* Count is incremented before DUK__DRAGON4_OUTPUT_PREINC() call
85076 		 * on purpose, which is taken into account by the macro.
85077 		 */
85078 		count++;
85079 
85080 		if (tc1) {
85081 			if (tc2) {
85082 				/* tc1 = true, tc2 = true */
85083 				duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, 2);
85084 				if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {  /* (< (* r 2) s) */
85085 					DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r > s: output d --> %ld (k=%ld)",
85086 					                     (long) d, (long) nc_ctx->k));
85087 					DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
85088 				} else {
85089 					DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r <= s: output d+1 --> %ld (k=%ld)",
85090 					                     (long) (d + 1), (long) nc_ctx->k));
85091 					DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
85092 				}
85093 				break;
85094 			} else {
85095 				/* tc1 = true, tc2 = false */
85096 				DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=false: output d --> %ld (k=%ld)",
85097 				                     (long) d, (long) nc_ctx->k));
85098 				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
85099 				break;
85100 			}
85101 		} else {
85102 			if (tc2) {
85103 				/* tc1 = false, tc2 = true */
85104 				DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=true: output d+1 --> %ld (k=%ld)",
85105 				                     (long) (d + 1), (long) nc_ctx->k));
85106 				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
85107 				break;
85108 			} else {
85109 				/* tc1 = false, tc2 = false */
85110 				DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=false: output d --> %ld (k=%ld)",
85111 				                     (long) d, (long) nc_ctx->k));
85112 				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
85113 
85114 				/* r <- r    (updated above: r <- (remainder (* r B) s)
85115 				 * s <- s
85116 				 * m+ <- m+  (updated above: m+ <- (* m+ B)
85117 				 * m- <- m-  (updated above: m- <- (* m- B)
85118 				 * B, low_ok, high_ok are fixed
85119 				 */
85120 
85121 				/* fall through and continue for-loop */
85122 			}
85123 		}
85124 
85125 		/* fixed-format termination conditions */
85126 		if (nc_ctx->is_fixed) {
85127 			if (nc_ctx->abs_pos) {
85128 				int pos = nc_ctx->k - count + 1;  /* count is already incremented, take into account */
85129 				DUK_DDD(DUK_DDDPRINT("fixed format, absolute: abs pos=%ld, k=%ld, count=%ld, req=%ld",
85130 				                     (long) pos, (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
85131 				if (pos <= nc_ctx->req_digits) {
85132 					DUK_DDD(DUK_DDDPRINT("digit position reached req_digits, end generate loop"));
85133 					break;
85134 				}
85135 			} else {
85136 				DUK_DDD(DUK_DDDPRINT("fixed format, relative: k=%ld, count=%ld, req=%ld",
85137 				                     (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
85138 				if (count >= nc_ctx->req_digits) {
85139 					DUK_DDD(DUK_DDDPRINT("digit count reached req_digits, end generate loop"));
85140 					break;
85141 				}
85142 			}
85143 		}
85144 	}  /* for */
85145 
85146 	nc_ctx->count = count;
85147 
85148 	DUK_DDD(DUK_DDDPRINT("generate finished"));
85149 
85150 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
85151 	{
85152 		duk_uint8_t buf[2048];
85153 		duk_small_int_t i, t;
85154 		duk_memzero(buf, sizeof(buf));
85155 		for (i = 0; i < nc_ctx->count; i++) {
85156 			t = nc_ctx->digits[i];
85157 			if (t < 0 || t > 36) {
85158 				buf[i] = (duk_uint8_t) '?';
85159 			} else {
85160 				buf[i] = (duk_uint8_t) DUK__DIGITCHAR(t);
85161 			}
85162 		}
85163 		DUK_DDD(DUK_DDDPRINT("-> generated digits; k=%ld, digits='%s'",
85164 		                     (long) nc_ctx->k, (const char *) buf));
85165 	}
85166 #endif
85167 }
85168 
85169 /* Round up digits to a given position.  If position is out-of-bounds,
85170  * does nothing.  If carry propagates over the first digit, a '1' is
85171  * prepended to digits and 'k' will be updated.  Return value indicates
85172  * whether carry propagated over the first digit.
85173  *
85174  * Note that nc_ctx->count is NOT updated based on the rounding position
85175  * (it is updated only if carry overflows over the first digit and an
85176  * extra digit is prepended).
85177  */
85178 DUK_LOCAL duk_small_int_t duk__dragon4_fixed_format_round(duk__numconv_stringify_ctx *nc_ctx, duk_small_int_t round_idx) {
85179 	duk_small_int_t t;
85180 	duk_uint8_t *p;
85181 	duk_uint8_t roundup_limit;
85182 	duk_small_int_t ret = 0;
85183 
85184 	/*
85185 	 *  round_idx points to the digit which is considered for rounding; the
85186 	 *  digit to its left is the final digit of the rounded value.  If round_idx
85187 	 *  is zero, rounding will be performed; the result will either be an empty
85188 	 *  rounded value or if carry happens a '1' digit is generated.
85189 	 */
85190 
85191 	if (round_idx >= nc_ctx->count) {
85192 		DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld >= %ld (count)) -> no rounding",
85193 		                     (long) round_idx, (long) nc_ctx->count));
85194 		return 0;
85195 	} else if (round_idx < 0) {
85196 		DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld < 0) -> no rounding",
85197 		                     (long) round_idx));
85198 		return 0;
85199 	}
85200 
85201 	/*
85202 	 *  Round-up limit.
85203 	 *
85204 	 *  For even values, divides evenly, e.g. 10 -> roundup_limit=5.
85205 	 *
85206 	 *  For odd values, rounds up, e.g. 3 -> roundup_limit=2.
85207 	 *  If radix is 3, 0/3 -> down, 1/3 -> down, 2/3 -> up.
85208 	 */
85209 	roundup_limit = (duk_uint8_t) ((nc_ctx->B + 1) / 2);
85210 
85211 	p = &nc_ctx->digits[round_idx];
85212 	if (*p >= roundup_limit) {
85213 		DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry required"));
85214 		/* carry */
85215 		for (;;) {
85216 			*p = 0;
85217 			if (p == &nc_ctx->digits[0]) {
85218 				DUK_DDD(DUK_DDDPRINT("carry propagated to first digit -> special case handling"));
85219 				duk_memmove((void *) (&nc_ctx->digits[1]),
85220 				            (const void *) (&nc_ctx->digits[0]),
85221 				            (size_t) (sizeof(char) * (size_t) nc_ctx->count));
85222 				nc_ctx->digits[0] = 1;  /* don't increase 'count' */
85223 				nc_ctx->k++;  /* position of highest digit changed */
85224 				nc_ctx->count++;  /* number of digits changed */
85225 				ret = 1;
85226 				break;
85227 			}
85228 
85229 			DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry: B=%ld, roundup_limit=%ld, p=%p, digits=%p",
85230 			                     (long) nc_ctx->B, (long) roundup_limit, (void *) p, (void *) nc_ctx->digits));
85231 			p--;
85232 			t = *p;
85233 			DUK_DDD(DUK_DDDPRINT("digit before carry: %ld", (long) t));
85234 			if (++t < nc_ctx->B) {
85235 				DUK_DDD(DUK_DDDPRINT("rounding carry terminated"));
85236 				*p = (duk_uint8_t) t;
85237 				break;
85238 			}
85239 
85240 			DUK_DDD(DUK_DDDPRINT("wraps, carry to next digit"));
85241 		}
85242 	}
85243 
85244 	return ret;
85245 }
85246 
85247 #define DUK__NO_EXP  (65536)  /* arbitrary marker, outside valid exp range */
85248 
85249 DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx,
85250                                              duk_hthread *thr,
85251                                              duk_small_int_t radix,
85252                                              duk_small_int_t digits,
85253                                              duk_small_uint_t flags,
85254                                              duk_small_int_t neg) {
85255 	duk_small_int_t k;
85256 	duk_small_int_t pos, pos_end;
85257 	duk_small_int_t expt;
85258 	duk_small_int_t dig;
85259 	duk_uint8_t *q;
85260 	duk_uint8_t *buf;
85261 
85262 	/*
85263 	 *  The string conversion here incorporates all the necessary ECMAScript
85264 	 *  semantics without attempting to be generic.  nc_ctx->digits contains
85265 	 *  nc_ctx->count digits (>= 1), with the topmost digit's 'position'
85266 	 *  indicated by nc_ctx->k as follows:
85267 	 *
85268 	 *    digits="123" count=3 k=0   -->   0.123
85269 	 *    digits="123" count=3 k=1   -->   1.23
85270 	 *    digits="123" count=3 k=5   -->   12300
85271 	 *    digits="123" count=3 k=-1  -->   0.0123
85272 	 *
85273 	 *  Note that the identifier names used for format selection are different
85274 	 *  in Burger-Dybvig paper and ECMAScript specification (quite confusingly
85275 	 *  so, because e.g. 'k' has a totally different meaning in each).  See
85276 	 *  documentation for discussion.
85277 	 *
85278 	 *  ECMAScript doesn't specify any specific behavior for format selection
85279 	 *  (e.g. when to use exponent notation) for non-base-10 numbers.
85280 	 *
85281 	 *  The bigint space in the context is reused for string output, as there
85282 	 *  is more than enough space for that (>1kB at the moment), and we avoid
85283 	 *  allocating even more stack.
85284 	 */
85285 
85286 	DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= DUK__MAX_FORMATTED_LENGTH);
85287 	DUK_ASSERT(nc_ctx->count >= 1);
85288 
85289 	k = nc_ctx->k;
85290 	buf = (duk_uint8_t *) &nc_ctx->f;  /* XXX: union would be more correct */
85291 	q = buf;
85292 
85293 	/* Exponent handling: if exponent format is used, record exponent value and
85294 	 * fake k such that one leading digit is generated (e.g. digits=123 -> "1.23").
85295 	 *
85296 	 * toFixed() prevents exponent use; otherwise apply a set of criteria to
85297 	 * match the other API calls (toString(), toPrecision, etc).
85298 	 */
85299 
85300 	expt = DUK__NO_EXP;
85301 	if (!nc_ctx->abs_pos /* toFixed() */) {
85302 		if ((flags & DUK_N2S_FLAG_FORCE_EXP) ||             /* exponential notation forced */
85303 		    ((flags & DUK_N2S_FLAG_NO_ZERO_PAD) &&          /* fixed precision and zero padding would be required */
85304 	             (k - digits >= 1)) ||                          /* (e.g. k=3, digits=2 -> "12X") */
85305 		    ((k > 21 || k <= -6) && (radix == 10))) {       /* toString() conditions */
85306 			DUK_DDD(DUK_DDDPRINT("use exponential notation: k=%ld -> expt=%ld",
85307 			                     (long) k, (long) (k - 1)));
85308 			expt = k - 1;  /* e.g. 12.3 -> digits="123" k=2 -> 1.23e1 */
85309 			k = 1;  /* generate mantissa with a single leading whole number digit */
85310 		}
85311 	}
85312 
85313 	if (neg) {
85314 		*q++ = '-';
85315 	}
85316 
85317 	/* Start position (inclusive) and end position (exclusive) */
85318 	pos = (k >= 1 ? k : 1);
85319 	if (nc_ctx->is_fixed) {
85320 		if (nc_ctx->abs_pos) {
85321 			/* toFixed() */
85322 			pos_end = -digits;
85323 		} else {
85324 			pos_end = k - digits;
85325 		}
85326 	} else {
85327 		pos_end = k - nc_ctx->count;
85328 	}
85329 	if (pos_end > 0) {
85330 		pos_end = 0;
85331 	}
85332 
85333 	DUK_DDD(DUK_DDDPRINT("expt=%ld, k=%ld, count=%ld, pos=%ld, pos_end=%ld, is_fixed=%ld, "
85334 	                     "digits=%ld, abs_pos=%ld",
85335 	                     (long) expt, (long) k, (long) nc_ctx->count, (long) pos, (long) pos_end,
85336 	                     (long) nc_ctx->is_fixed, (long) digits, (long) nc_ctx->abs_pos));
85337 
85338 	/* Digit generation */
85339 	while (pos > pos_end) {
85340 		DUK_DDD(DUK_DDDPRINT("digit generation: pos=%ld, pos_end=%ld",
85341 		                     (long) pos, (long) pos_end));
85342 		if (pos == 0) {
85343 			*q++ = (duk_uint8_t) '.';
85344 		}
85345 		if (pos > k) {
85346 			*q++ = (duk_uint8_t) '0';
85347 		} else if (pos <= k - nc_ctx->count) {
85348 			*q++ = (duk_uint8_t) '0';
85349 		} else {
85350 			dig = nc_ctx->digits[k - pos];
85351 			DUK_ASSERT(dig >= 0 && dig < nc_ctx->B);
85352 			*q++ = (duk_uint8_t) DUK__DIGITCHAR(dig);
85353 		}
85354 
85355 		pos--;
85356 	}
85357 	DUK_ASSERT(pos <= 1);
85358 
85359 	/* Exponent */
85360 	if (expt != DUK__NO_EXP) {
85361 		/*
85362 		 *  Exponent notation for non-base-10 numbers isn't specified in ECMAScript
85363 		 *  specification, as it never explicitly turns up: non-decimal numbers can
85364 		 *  only be formatted with Number.prototype.toString([radix]) and for that,
85365 		 *  behavior is not explicitly specified.
85366 		 *
85367 		 *  Logical choices include formatting the exponent as decimal (e.g. binary
85368 		 *  100000 as 1e+5) or in current radix (e.g. binary 100000 as 1e+101).
85369 		 *  The Dragon4 algorithm (in the original paper) prints the exponent value
85370 		 *  in the target radix B.  However, for radix values 15 and above, the
85371 		 *  exponent separator 'e' is no longer easily parseable.  Consider, for
85372 		 *  instance, the number "1.faecee+1c".
85373 		 */
85374 
85375 		duk_size_t len;
85376 		char expt_sign;
85377 
85378 		*q++ = 'e';
85379 		if (expt >= 0) {
85380 			expt_sign = '+';
85381 		} else {
85382 			expt_sign = '-';
85383 			expt = -expt;
85384 		}
85385 		*q++ = (duk_uint8_t) expt_sign;
85386 		len = duk__dragon4_format_uint32(q, (duk_uint32_t) expt, radix);
85387 		q += len;
85388 	}
85389 
85390 	duk_push_lstring(thr, (const char *) buf, (size_t) (q - buf));
85391 }
85392 
85393 /*
85394  *  Conversion helpers
85395  */
85396 
85397 DUK_LOCAL void duk__dragon4_double_to_ctx(duk__numconv_stringify_ctx *nc_ctx, duk_double_t x) {
85398 	duk_double_union u;
85399 	duk_uint32_t tmp;
85400 	duk_small_int_t expt;
85401 
85402 	/*
85403 	 *    seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
85404 	 *       A        B        C        D        E        F        G        H
85405 	 *
85406 	 *    s       sign bit
85407 	 *    eee...  exponent field
85408 	 *    fff...  fraction
85409 	 *
85410 	 *    ieee value = 1.ffff... * 2^(e - 1023)  (normal)
85411 	 *               = 0.ffff... * 2^(-1022)     (denormal)
85412 	 *
85413 	 *    algorithm v = f * b^e
85414 	 */
85415 
85416 	DUK_DBLUNION_SET_DOUBLE(&u, x);
85417 
85418 	nc_ctx->f.n = 2;
85419 
85420 	tmp = DUK_DBLUNION_GET_LOW32(&u);
85421 	nc_ctx->f.v[0] = tmp;
85422 	tmp = DUK_DBLUNION_GET_HIGH32(&u);
85423 	nc_ctx->f.v[1] = tmp & 0x000fffffUL;
85424 	expt = (duk_small_int_t) ((tmp >> 20) & 0x07ffUL);
85425 
85426 	if (expt == 0) {
85427 		/* denormal */
85428 		expt = DUK__IEEE_DOUBLE_EXP_MIN - 52;
85429 		duk__bi_normalize(&nc_ctx->f);
85430 	} else {
85431 		/* normal: implicit leading 1-bit */
85432 		nc_ctx->f.v[1] |= 0x00100000UL;
85433 		expt = expt - DUK__IEEE_DOUBLE_EXP_BIAS - 52;
85434 		DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));  /* true, because v[1] has at least one bit set */
85435 	}
85436 
85437 	DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));
85438 
85439 	nc_ctx->e = expt;
85440 }
85441 
85442 DUK_LOCAL void duk__dragon4_ctx_to_double(duk__numconv_stringify_ctx *nc_ctx, duk_double_t *x) {
85443 	duk_double_union u;
85444 	duk_small_int_t expt;
85445 	duk_small_int_t i;
85446 	duk_small_int_t bitstart;
85447 	duk_small_int_t bitround;
85448 	duk_small_int_t bitidx;
85449 	duk_small_int_t skip_round;
85450 	duk_uint32_t t, v;
85451 
85452 	DUK_ASSERT(nc_ctx->count == 53 + 1);
85453 
85454 	/* Sometimes this assert is not true right now; it will be true after
85455 	 * rounding.  See: test-bug-numconv-mantissa-assert.js.
85456 	 */
85457 	DUK_ASSERT_DISABLE(nc_ctx->digits[0] == 1);  /* zero handled by caller */
85458 
85459 	/* Should not be required because the code below always sets both high
85460 	 * and low parts, but at least gcc-4.4.5 fails to deduce this correctly
85461 	 * (perhaps because the low part is set (seemingly) conditionally in a
85462 	 * loop), so this is here to avoid the bogus warning.
85463 	 */
85464 	duk_memzero((void *) &u, sizeof(u));
85465 
85466 	/*
85467 	 *  Figure out how generated digits match up with the mantissa,
85468 	 *  and then perform rounding.  If mantissa overflows, need to
85469 	 *  recompute the exponent (it is bumped and may overflow to
85470 	 *  infinity).
85471 	 *
85472 	 *  For normal numbers the leading '1' is hidden and ignored,
85473 	 *  and the last bit is used for rounding:
85474 	 *
85475 	 *                          rounding pt
85476 	 *       <--------52------->|
85477 	 *     1 x x x x ... x x x x|y  ==>  x x x x ... x x x x
85478 	 *
85479 	 *  For denormals, the leading '1' is included in the number,
85480 	 *  and the rounding point is different:
85481 	 *
85482 	 *                      rounding pt
85483 	 *     <--52 or less--->|
85484 	 *     1 x x x x ... x x|x x y  ==>  0 0 ... 1 x x ... x x
85485 	 *
85486 	 *  The largest denormals will have a mantissa beginning with
85487 	 *  a '1' (the explicit leading bit); smaller denormals will
85488 	 *  have leading zero bits.
85489 	 *
85490 	 *  If the exponent would become too high, the result becomes
85491 	 *  Infinity.  If the exponent is so small that the entire
85492 	 *  mantissa becomes zero, the result becomes zero.
85493 	 *
85494 	 *  Note: the Dragon4 'k' is off-by-one with respect to the IEEE
85495 	 *  exponent.  For instance, k==0 indicates that the leading '1'
85496 	 *  digit is at the first binary fraction position (0.1xxx...);
85497 	 *  the corresponding IEEE exponent would be -1.
85498 	 */
85499 
85500 	skip_round = 0;
85501 
85502  recheck_exp:
85503 
85504 	expt = nc_ctx->k - 1;   /* IEEE exp without bias */
85505 	if (expt > 1023) {
85506 		/* Infinity */
85507 		bitstart = -255;  /* needed for inf: causes mantissa to become zero,
85508 		                   * and rounding to be skipped.
85509 		                   */
85510 		expt = 2047;
85511 	} else if (expt >= -1022) {
85512 		/* normal */
85513 		bitstart = 1;  /* skip leading digit */
85514 		expt += DUK__IEEE_DOUBLE_EXP_BIAS;
85515 		DUK_ASSERT(expt >= 1 && expt <= 2046);
85516 	} else {
85517 		/* denormal or zero */
85518 		bitstart = 1023 + expt;  /* expt==-1023 -> bitstart=0 (leading 1);
85519 		                          * expt==-1024 -> bitstart=-1 (one left of leading 1), etc
85520 		                          */
85521 		expt = 0;
85522 	}
85523 	bitround = bitstart + 52;
85524 
85525 	DUK_DDD(DUK_DDDPRINT("ieee expt=%ld, bitstart=%ld, bitround=%ld",
85526 	                     (long) expt, (long) bitstart, (long) bitround));
85527 
85528 	if (!skip_round) {
85529 		if (duk__dragon4_fixed_format_round(nc_ctx, bitround)) {
85530 			/* Corner case: see test-numconv-parse-mant-carry.js.  We could
85531 			 * just bump the exponent and update bitstart, but it's more robust
85532 			 * to recompute (but avoid rounding twice).
85533 			 */
85534 			DUK_DDD(DUK_DDDPRINT("rounding caused exponent to be bumped, recheck exponent"));
85535 			skip_round = 1;
85536 			goto recheck_exp;
85537 		}
85538 	}
85539 
85540 	/*
85541 	 *  Create mantissa
85542 	 */
85543 
85544 	t = 0;
85545 	for (i = 0; i < 52; i++) {
85546 		bitidx = bitstart + 52 - 1 - i;
85547 		if (bitidx >= nc_ctx->count) {
85548 			v = 0;
85549 		} else if (bitidx < 0) {
85550 			v = 0;
85551 		} else {
85552 			v = nc_ctx->digits[bitidx];
85553 		}
85554 		DUK_ASSERT(v == 0 || v == 1);
85555 		t += v << (i % 32);
85556 		if (i == 31) {
85557 			/* low 32 bits is complete */
85558 			DUK_DBLUNION_SET_LOW32(&u, t);
85559 			t = 0;
85560 		}
85561 	}
85562 	/* t has high mantissa */
85563 
85564 	DUK_DDD(DUK_DDDPRINT("mantissa is complete: %08lx %08lx",
85565 	                     (unsigned long) t,
85566 	                     (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
85567 
85568 	DUK_ASSERT(expt >= 0 && expt <= 0x7ffL);
85569 	t += ((duk_uint32_t) expt) << 20;
85570 #if 0  /* caller handles sign change */
85571 	if (negative) {
85572 		t |= 0x80000000U;
85573 	}
85574 #endif
85575 	DUK_DBLUNION_SET_HIGH32(&u, t);
85576 
85577 	DUK_DDD(DUK_DDDPRINT("number is complete: %08lx %08lx",
85578 	                     (unsigned long) DUK_DBLUNION_GET_HIGH32(&u),
85579 	                     (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
85580 
85581 	*x = DUK_DBLUNION_GET_DOUBLE(&u);
85582 }
85583 
85584 /*
85585  *  Exposed number-to-string API
85586  *
85587  *  Input: [ number ]
85588  *  Output: [ string ]
85589  */
85590 
85591 DUK_INTERNAL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags) {
85592 	duk_double_t x;
85593 	duk_small_int_t c;
85594 	duk_small_int_t neg;
85595 	duk_uint32_t uval;
85596 	duk__numconv_stringify_ctx nc_ctx_alloc;  /* large context; around 2kB now */
85597 	duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
85598 
85599 	x = (duk_double_t) duk_require_number(thr, -1);
85600 	duk_pop(thr);
85601 
85602 	/*
85603 	 *  Handle special cases (NaN, infinity, zero).
85604 	 */
85605 
85606 	c = (duk_small_int_t) DUK_FPCLASSIFY(x);
85607 	if (DUK_SIGNBIT((double) x)) {
85608 		x = -x;
85609 		neg = 1;
85610 	} else {
85611 		neg = 0;
85612 	}
85613 
85614 	/* NaN sign bit is platform specific with unpacked, un-normalized NaNs */
85615 	DUK_ASSERT(c == DUK_FP_NAN || DUK_SIGNBIT((double) x) == 0);
85616 
85617 	if (c == DUK_FP_NAN) {
85618 		duk_push_hstring_stridx(thr, DUK_STRIDX_NAN);
85619 		return;
85620 	} else if (c == DUK_FP_INFINITE) {
85621 		if (neg) {
85622 			/* -Infinity */
85623 			duk_push_hstring_stridx(thr, DUK_STRIDX_MINUS_INFINITY);
85624 		} else {
85625 			/* Infinity */
85626 			duk_push_hstring_stridx(thr, DUK_STRIDX_INFINITY);
85627 		}
85628 		return;
85629 	} else if (c == DUK_FP_ZERO) {
85630 		/* We can't shortcut zero here if it goes through special formatting
85631 		 * (such as forced exponential notation).
85632 		 */
85633 		;
85634 	}
85635 
85636 	/*
85637 	 *  Handle integers in 32-bit range (that is, [-(2**32-1),2**32-1])
85638 	 *  specially, as they're very likely for embedded programs.  This
85639 	 *  is now done for all radix values.  We must be careful not to use
85640 	 *  the fast path when special formatting (e.g. forced exponential)
85641 	 *  is in force.
85642 	 *
85643 	 *  XXX: could save space by supporting radix 10 only and using
85644 	 *  sprintf "%lu" for the fast path and for exponent formatting.
85645 	 */
85646 
85647 	uval = duk_double_to_uint32_t(x);
85648 	if (((double) uval) == x &&  /* integer number in range */
85649 	    flags == 0) {            /* no special formatting */
85650 		/* use bigint area as a temp */
85651 		duk_uint8_t *buf = (duk_uint8_t *) (&nc_ctx->f);
85652 		duk_uint8_t *p = buf;
85653 
85654 		DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= 32 + 1);  /* max size: radix=2 + sign */
85655 		if (neg && uval != 0) {
85656 			/* no negative sign for zero */
85657 			*p++ = (duk_uint8_t) '-';
85658 		}
85659 		p += duk__dragon4_format_uint32(p, uval, radix);
85660 		duk_push_lstring(thr, (const char *) buf, (duk_size_t) (p - buf));
85661 		return;
85662 	}
85663 
85664 	/*
85665 	 *  Dragon4 setup.
85666 	 *
85667 	 *  Convert double from IEEE representation for conversion;
85668 	 *  normal finite values have an implicit leading 1-bit.  The
85669 	 *  slow path algorithm doesn't handle zero, so zero is special
85670 	 *  cased here but still creates a valid nc_ctx, and goes
85671 	 *  through normal formatting in case special formatting has
85672 	 *  been requested (e.g. forced exponential format: 0 -> "0e+0").
85673 	 */
85674 
85675 	/* Would be nice to bulk clear the allocation, but the context
85676 	 * is 1-2 kilobytes and nothing should rely on it being zeroed.
85677 	 */
85678 #if 0
85679 	duk_memzero((void *) nc_ctx, sizeof(*nc_ctx));  /* slow init, do only for slow path cases */
85680 #endif
85681 
85682 	nc_ctx->is_s2n = 0;
85683 	nc_ctx->b = 2;
85684 	nc_ctx->B = radix;
85685 	nc_ctx->abs_pos = 0;
85686 	if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
85687 		nc_ctx->is_fixed = 1;
85688 		if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
85689 			/* absolute req_digits; e.g. digits = 1 -> last digit is 0,
85690 			 * but add an extra digit for rounding.
85691 			 */
85692 			nc_ctx->abs_pos = 1;
85693 			nc_ctx->req_digits = (-digits + 1) - 1;
85694 		} else {
85695 			nc_ctx->req_digits = digits + 1;
85696 		}
85697 	} else {
85698 		nc_ctx->is_fixed = 0;
85699 		nc_ctx->req_digits = 0;
85700 	}
85701 
85702 	if (c == DUK_FP_ZERO) {
85703 		/* Zero special case: fake requested number of zero digits; ensure
85704 		 * no sign bit is printed.  Relative and absolute fixed format
85705 		 * require separate handling.
85706 		 */
85707 		duk_small_int_t count;
85708 		if (nc_ctx->is_fixed) {
85709 			if (nc_ctx->abs_pos) {
85710 				count = digits + 2;  /* lead zero + 'digits' fractions + 1 for rounding */
85711 			} else {
85712 				count = digits + 1;  /* + 1 for rounding */
85713 			}
85714 		} else {
85715 			count = 1;
85716 		}
85717 		DUK_DDD(DUK_DDDPRINT("count=%ld", (long) count));
85718 		DUK_ASSERT(count >= 1);
85719 		duk_memzero((void *) nc_ctx->digits, (size_t) count);
85720 		nc_ctx->count = count;
85721 		nc_ctx->k = 1;  /* 0.000... */
85722 		neg = 0;
85723 		goto zero_skip;
85724 	}
85725 
85726 	duk__dragon4_double_to_ctx(nc_ctx, x);   /* -> sets 'f' and 'e' */
85727 	DUK__BI_PRINT("f", &nc_ctx->f);
85728 	DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
85729 
85730 	/*
85731 	 *  Dragon4 slow path digit generation.
85732 	 */
85733 
85734 	duk__dragon4_prepare(nc_ctx);  /* setup many variables in nc_ctx */
85735 
85736 	DUK_DDD(DUK_DDDPRINT("after prepare:"));
85737 	DUK__BI_PRINT("r", &nc_ctx->r);
85738 	DUK__BI_PRINT("s", &nc_ctx->s);
85739 	DUK__BI_PRINT("mp", &nc_ctx->mp);
85740 	DUK__BI_PRINT("mm", &nc_ctx->mm);
85741 
85742 	duk__dragon4_scale(nc_ctx);
85743 
85744 	DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
85745 	DUK__BI_PRINT("r", &nc_ctx->r);
85746 	DUK__BI_PRINT("s", &nc_ctx->s);
85747 	DUK__BI_PRINT("mp", &nc_ctx->mp);
85748 	DUK__BI_PRINT("mm", &nc_ctx->mm);
85749 
85750 	duk__dragon4_generate(nc_ctx);
85751 
85752 	/*
85753 	 *  Convert and push final string.
85754 	 */
85755 
85756  zero_skip:
85757 
85758 	if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
85759 		/* Perform fixed-format rounding. */
85760 		duk_small_int_t roundpos;
85761 		if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
85762 			/* 'roundpos' is relative to nc_ctx->k and increases to the right
85763 			 * (opposite of how 'k' changes).
85764 			 */
85765 			roundpos = -digits;  /* absolute position for digit considered for rounding */
85766 			roundpos = nc_ctx->k - roundpos;
85767 		} else {
85768 			roundpos = digits;
85769 		}
85770 		DUK_DDD(DUK_DDDPRINT("rounding: k=%ld, count=%ld, digits=%ld, roundpos=%ld",
85771 		                     (long) nc_ctx->k, (long) nc_ctx->count, (long) digits, (long) roundpos));
85772 		(void) duk__dragon4_fixed_format_round(nc_ctx, roundpos);
85773 
85774 		/* Note: 'count' is currently not adjusted by rounding (i.e. the
85775 		 * digits are not "chopped off".  That shouldn't matter because
85776 		 * the digit position (absolute or relative) is passed on to the
85777 		 * convert-and-push function.
85778 		 */
85779 	}
85780 
85781 	duk__dragon4_convert_and_push(nc_ctx, thr, radix, digits, flags, neg);
85782 }
85783 
85784 /*
85785  *  Exposed string-to-number API
85786  *
85787  *  Input: [ string ]
85788  *  Output: [ number ]
85789  *
85790  *  If number parsing fails, a NaN is pushed as the result.  If number parsing
85791  *  fails due to an internal error, an InternalError is thrown.
85792  */
85793 
85794 DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags) {
85795 	duk__numconv_stringify_ctx nc_ctx_alloc;  /* large context; around 2kB now */
85796 	duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
85797 	duk_double_t res;
85798 	duk_hstring *h_str;
85799 	duk_int_t expt;
85800 	duk_bool_t expt_neg;
85801 	duk_small_int_t expt_adj;
85802 	duk_small_int_t neg;
85803 	duk_small_int_t dig;
85804 	duk_small_int_t dig_whole;
85805 	duk_small_int_t dig_lzero;
85806 	duk_small_int_t dig_frac;
85807 	duk_small_int_t dig_expt;
85808 	duk_small_int_t dig_prec;
85809 	const duk__exp_limits *explim;
85810 	const duk_uint8_t *p;
85811 	duk_small_int_t ch;
85812 
85813 	DUK_DDD(DUK_DDDPRINT("parse number: %!T, radix=%ld, flags=0x%08lx",
85814 	                     (duk_tval *) duk_get_tval(thr, -1),
85815 	                     (long) radix, (unsigned long) flags));
85816 
85817 	DUK_ASSERT(radix >= 2 && radix <= 36);
85818 	DUK_ASSERT(radix - 2 < (duk_small_int_t) sizeof(duk__str2num_digits_for_radix));
85819 
85820 	/*
85821 	 *  Preliminaries: trim, sign, Infinity check
85822 	 *
85823 	 *  We rely on the interned string having a NUL terminator, which will
85824 	 *  cause a parse failure wherever it is encountered.  As a result, we
85825 	 *  don't need separate pointer checks.
85826 	 *
85827 	 *  There is no special parsing for 'NaN' in the specification although
85828 	 *  'Infinity' (with an optional sign) is allowed in some contexts.
85829 	 *  Some contexts allow plus/minus sign, while others only allow the
85830 	 *  minus sign (like JSON.parse()).
85831 	 *
85832 	 *  Automatic hex number detection (leading '0x' or '0X') and octal
85833 	 *  number detection (leading '0' followed by at least one octal digit)
85834 	 *  is done here too.
85835 	 *
85836 	 *  Symbols are not explicitly rejected here (that's up to the caller).
85837 	 *  If a symbol were passed here, it should ultimately safely fail
85838 	 *  parsing due to a syntax error.
85839 	 */
85840 
85841 	if (flags & DUK_S2N_FLAG_TRIM_WHITE) {
85842 		/* Leading / trailing whitespace is sometimes accepted and
85843 		 * sometimes not.  After white space trimming, all valid input
85844 		 * characters are pure ASCII.
85845 		 */
85846 		duk_trim(thr, -1);
85847 	}
85848 	h_str = duk_require_hstring(thr, -1);
85849 	DUK_ASSERT(h_str != NULL);
85850 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_str);
85851 
85852 	neg = 0;
85853 	ch = *p;
85854 	if (ch == (duk_small_int_t) '+') {
85855 		if ((flags & DUK_S2N_FLAG_ALLOW_PLUS) == 0) {
85856 			DUK_DDD(DUK_DDDPRINT("parse failed: leading plus sign not allowed"));
85857 			goto parse_fail;
85858 		}
85859 		p++;
85860 	} else if (ch == (duk_small_int_t) '-') {
85861 		if ((flags & DUK_S2N_FLAG_ALLOW_MINUS) == 0) {
85862 			DUK_DDD(DUK_DDDPRINT("parse failed: leading minus sign not allowed"));
85863 			goto parse_fail;
85864 		}
85865 		p++;
85866 		neg = 1;
85867 	}
85868 
85869 	if ((flags & DUK_S2N_FLAG_ALLOW_INF) && DUK_STRNCMP((const char *) p, "Infinity", 8) == 0) {
85870 		/* Don't check for Infinity unless the context allows it.
85871 		 * 'Infinity' is a valid integer literal in e.g. base-36:
85872 		 *
85873 		 *   parseInt('Infinity', 36)
85874 		 *   1461559270678
85875 		 */
85876 
85877 		if ((flags & DUK_S2N_FLAG_ALLOW_GARBAGE) == 0 && p[8] != DUK_ASC_NUL) {
85878 			DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage after matching 'Infinity' not allowed"));
85879 			goto parse_fail;
85880 		} else {
85881 			res = DUK_DOUBLE_INFINITY;
85882 			goto negcheck_and_ret;
85883 		}
85884 	}
85885 	ch = *p;
85886 	if (ch == (duk_small_int_t) '0') {
85887 		duk_small_int_t detect_radix = 0;
85888 		ch = DUK_LOWERCASE_CHAR_ASCII(p[1]);  /* 'x' or 'X' -> 'x' */
85889 		if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT) && ch == DUK_ASC_LC_X) {
85890 			DUK_DDD(DUK_DDDPRINT("detected 0x/0X hex prefix, changing radix and preventing fractions and exponent"));
85891 			detect_radix = 16;
85892 #if 0
85893 		} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT) &&
85894 		           (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9')) {
85895 			DUK_DDD(DUK_DDDPRINT("detected 0n oct prefix, changing radix and preventing fractions and exponent"));
85896 			detect_radix = 8;
85897 
85898 			/* NOTE: if this legacy octal case is added back, it has
85899 			 * different flags and 'p' advance so this needs to be
85900 			 * reworked.
85901 			 */
85902 			flags |= DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO;  /* interpret e.g. '09' as '0', not NaN */
85903 			p += 1;
85904 #endif
85905 		} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT) && ch == DUK_ASC_LC_O) {
85906 			DUK_DDD(DUK_DDDPRINT("detected 0o oct prefix, changing radix and preventing fractions and exponent"));
85907 			detect_radix = 8;
85908 		} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT) && ch == DUK_ASC_LC_B) {
85909 			DUK_DDD(DUK_DDDPRINT("detected 0b bin prefix, changing radix and preventing fractions and exponent"));
85910 			detect_radix = 2;
85911 		}
85912 		if (detect_radix > 0) {
85913 			radix = detect_radix;
85914 			/* Clear empty as zero flag: interpret e.g. '0x' and '0xg' as a NaN (= parse error) */
85915 			flags &= ~(DUK_S2N_FLAG_ALLOW_EXP | DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
85916 			           DUK_S2N_FLAG_ALLOW_FRAC | DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
85917 			           DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO);
85918 			flags |= DUK_S2N_FLAG_ALLOW_LEADING_ZERO;  /* allow e.g. '0x0009' and '0b00010001' */
85919 			p += 2;
85920 		}
85921 	}
85922 
85923 	/*
85924 	 *  Scan number and setup for Dragon4.
85925 	 *
85926 	 *  The fast path case is detected during setup: an integer which
85927 	 *  can be converted without rounding, no net exponent.  The fast
85928 	 *  path could be implemented as a separate scan, but may not really
85929 	 *  be worth it: the multiplications for building 'f' are not
85930 	 *  expensive when 'f' is small.
85931 	 *
85932 	 *  The significand ('f') must contain enough bits of (apparent)
85933 	 *  accuracy, so that Dragon4 will generate enough binary output digits.
85934 	 *  For decimal numbers, this means generating a 20-digit significand,
85935 	 *  which should yield enough practical accuracy to parse IEEE doubles.
85936 	 *  In fact, the ECMAScript specification explicitly allows an
85937 	 *  implementation to treat digits beyond 20 as zeroes (and even
85938 	 *  to round the 20th digit upwards).  For non-decimal numbers, the
85939 	 *  appropriate number of digits has been precomputed for comparable
85940 	 *  accuracy.
85941 	 *
85942 	 *  Digit counts:
85943 	 *
85944 	 *    [ dig_lzero ]
85945 	 *      |
85946 	 *     .+-..---[ dig_prec ]----.
85947 	 *     |  ||                   |
85948 	 *     0000123.456789012345678901234567890e+123456
85949 	 *     |     | |                         |  |    |
85950 	 *     `--+--' `------[ dig_frac ]-------'  `-+--'
85951 	 *        |                                   |
85952 	 *    [ dig_whole ]                       [ dig_expt ]
85953 	 *
85954 	 *    dig_frac and dig_expt are -1 if not present
85955 	 *    dig_lzero is only computed for whole number part
85956 	 *
85957 	 *  Parsing state
85958 	 *
85959 	 *     Parsing whole part      dig_frac < 0 AND dig_expt < 0
85960 	 *     Parsing fraction part   dig_frac >= 0 AND dig_expt < 0
85961 	 *     Parsing exponent part   dig_expt >= 0   (dig_frac may be < 0 or >= 0)
85962 	 *
85963 	 *  Note: in case we hit an implementation limit (like exponent range),
85964 	 *  we should throw an error, NOT return NaN or Infinity.  Even with
85965 	 *  very large exponent (or significand) values the final result may be
85966 	 *  finite, so NaN/Infinity would be incorrect.
85967 	 */
85968 
85969 	duk__bi_set_small(&nc_ctx->f, 0);
85970 	dig_prec = 0;
85971 	dig_lzero = 0;
85972 	dig_whole = 0;
85973 	dig_frac = -1;
85974 	dig_expt = -1;
85975 	expt = 0;
85976 	expt_adj = 0;  /* essentially tracks digit position of lowest 'f' digit */
85977 	expt_neg = 0;
85978 	for (;;) {
85979 		ch = *p++;
85980 
85981 		DUK_DDD(DUK_DDDPRINT("parse digits: p=%p, ch='%c' (%ld), expt=%ld, expt_adj=%ld, "
85982 		                     "dig_whole=%ld, dig_frac=%ld, dig_expt=%ld, dig_lzero=%ld, dig_prec=%ld",
85983 		                     (const void *) p, (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : '?'), (long) ch,
85984 		                     (long) expt, (long) expt_adj, (long) dig_whole, (long) dig_frac,
85985 		                     (long) dig_expt, (long) dig_lzero, (long) dig_prec));
85986 		DUK__BI_PRINT("f", &nc_ctx->f);
85987 
85988 		/* Most common cases first. */
85989 		if (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9') {
85990 			dig = (duk_small_int_t) ch - '0' + 0;
85991 		} else if (ch == (duk_small_int_t) '.') {
85992 			/* A leading digit is not required in some cases, e.g. accept ".123".
85993 			 * In other cases (JSON.parse()) a leading digit is required.  This
85994 			 * is checked for after the loop.
85995 			 */
85996 			if (dig_frac >= 0 || dig_expt >= 0) {
85997 				if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
85998 					DUK_DDD(DUK_DDDPRINT("garbage termination (invalid period)"));
85999 					break;
86000 				} else {
86001 					DUK_DDD(DUK_DDDPRINT("parse failed: period not allowed"));
86002 					goto parse_fail;
86003 				}
86004 			}
86005 
86006 			if ((flags & DUK_S2N_FLAG_ALLOW_FRAC) == 0) {
86007 				/* Some contexts don't allow fractions at all; this can't be a
86008 				 * post-check because the state ('f' and expt) would be incorrect.
86009 				 */
86010 				if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
86011 					DUK_DDD(DUK_DDDPRINT("garbage termination (invalid first period)"));
86012 					break;
86013 				} else {
86014 					DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed"));
86015 				}
86016 			}
86017 
86018 			DUK_DDD(DUK_DDDPRINT("start fraction part"));
86019 			dig_frac = 0;
86020 			continue;
86021 		} else if (ch == (duk_small_int_t) 0) {
86022 			DUK_DDD(DUK_DDDPRINT("NUL termination"));
86023 			break;
86024 		} else if ((flags & DUK_S2N_FLAG_ALLOW_EXP) &&
86025 		           dig_expt < 0 && (ch == (duk_small_int_t) 'e' || ch == (duk_small_int_t) 'E')) {
86026 			/* Note: we don't parse back exponent notation for anything else
86027 			 * than radix 10, so this is not an ambiguous check (e.g. hex
86028 			 * exponent values may have 'e' either as a significand digit
86029 			 * or as an exponent separator).
86030 			 *
86031 			 * If the exponent separator occurs twice, 'e' will be interpreted
86032 			 * as a digit (= 14) and will be rejected as an invalid decimal
86033 			 * digit.
86034 			 */
86035 
86036 			DUK_DDD(DUK_DDDPRINT("start exponent part"));
86037 
86038 			/* Exponent without a sign or with a +/- sign is accepted
86039 			 * by all call sites (even JSON.parse()).
86040 			 */
86041 			ch = *p;
86042 			if (ch == (duk_small_int_t) '-') {
86043 				expt_neg = 1;
86044 				p++;
86045 			} else if (ch == (duk_small_int_t) '+') {
86046 				p++;
86047 			}
86048 			dig_expt = 0;
86049 			continue;
86050 		} else if (ch >= (duk_small_int_t) 'a' && ch <= (duk_small_int_t) 'z') {
86051 			dig = (duk_small_int_t) (ch - (duk_small_int_t) 'a' + 0x0a);
86052 		} else if (ch >= (duk_small_int_t) 'A' && ch <= (duk_small_int_t) 'Z') {
86053 			dig = (duk_small_int_t) (ch - (duk_small_int_t) 'A' + 0x0a);
86054 		} else {
86055 			dig = 255;  /* triggers garbage digit check below */
86056 		}
86057 		DUK_ASSERT((dig >= 0 && dig <= 35) || dig == 255);
86058 
86059 		if (dig >= radix) {
86060 			if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
86061 				DUK_DDD(DUK_DDDPRINT("garbage termination"));
86062 				break;
86063 			} else {
86064 				DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage or invalid digit"));
86065 				goto parse_fail;
86066 			}
86067 		}
86068 
86069 		if (dig_expt < 0) {
86070 			/* whole or fraction digit */
86071 
86072 			if (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
86073 				/* significant from precision perspective */
86074 
86075 				duk_small_int_t f_zero = duk__bi_is_zero(&nc_ctx->f);
86076 				if (f_zero && dig == 0) {
86077 					/* Leading zero is not counted towards precision digits; not
86078 					 * in the integer part, nor in the fraction part.
86079 					 */
86080 					if (dig_frac < 0) {
86081 						dig_lzero++;
86082 					}
86083 				} else {
86084 					/* XXX: join these ops (multiply-accumulate), but only if
86085 					 * code footprint decreases.
86086 					 */
86087 					duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, (duk_uint32_t) radix);
86088 					duk__bi_add_small(&nc_ctx->f, &nc_ctx->t1, (duk_uint32_t) dig);
86089 					dig_prec++;
86090 				}
86091 			} else {
86092 				/* Ignore digits beyond a radix-specific limit, but note them
86093 				 * in expt_adj.
86094 				 */
86095 				expt_adj++;
86096 			}
86097 
86098 			if (dig_frac >= 0) {
86099 				dig_frac++;
86100 				expt_adj--;
86101 			} else {
86102 				dig_whole++;
86103 			}
86104 		} else {
86105 			/* exponent digit */
86106 
86107 			DUK_ASSERT(radix == 10);
86108 			expt = expt * radix + dig;
86109 			if (expt > DUK_S2N_MAX_EXPONENT) {
86110 				/* Impose a reasonable exponent limit, so that exp
86111 				 * doesn't need to get tracked using a bigint.
86112 				 */
86113 				DUK_DDD(DUK_DDDPRINT("parse failed: exponent too large"));
86114 				goto parse_explimit_error;
86115 			}
86116 			dig_expt++;
86117 		}
86118 	}
86119 
86120 	/* Leading zero. */
86121 
86122 	if (dig_lzero > 0 && dig_whole > 1) {
86123 		if ((flags & DUK_S2N_FLAG_ALLOW_LEADING_ZERO) == 0) {
86124 			DUK_DDD(DUK_DDDPRINT("parse failed: leading zeroes not allowed in integer part"));
86125 			goto parse_fail;
86126 		}
86127 	}
86128 
86129 	/* Validity checks for various fraction formats ("0.1", ".1", "1.", "."). */
86130 
86131 	if (dig_whole == 0) {
86132 		if (dig_frac == 0) {
86133 			/* "." is not accepted in any format */
86134 			DUK_DDD(DUK_DDDPRINT("parse failed: plain period without leading or trailing digits"));
86135 			goto parse_fail;
86136 		} else if (dig_frac > 0) {
86137 			/* ".123" */
86138 			if ((flags & DUK_S2N_FLAG_ALLOW_NAKED_FRAC) == 0) {
86139 				DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed without "
86140 				                     "leading integer digit(s)"));
86141 				goto parse_fail;
86142 			}
86143 		} else {
86144 			/* empty ("") is allowed in some formats (e.g. Number(''), as zero */
86145 			if ((flags & DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO) == 0) {
86146 				DUK_DDD(DUK_DDDPRINT("parse failed: empty string not allowed (as zero)"));
86147 				goto parse_fail;
86148 			}
86149 		}
86150 	} else {
86151 		if (dig_frac == 0) {
86152 			/* "123." is allowed in some formats */
86153 			if ((flags & DUK_S2N_FLAG_ALLOW_EMPTY_FRAC) == 0) {
86154 				DUK_DDD(DUK_DDDPRINT("parse failed: empty fractions"));
86155 				goto parse_fail;
86156 			}
86157 		} else if (dig_frac > 0) {
86158 			/* "123.456" */
86159 			;
86160 		} else {
86161 			/* "123" */
86162 			;
86163 		}
86164 	}
86165 
86166 	/* Exponent without digits (e.g. "1e" or "1e+").  If trailing garbage is
86167 	 * allowed, ignore exponent part as garbage (= parse as "1", i.e. exp 0).
86168 	 */
86169 
86170 	if (dig_expt == 0) {
86171 		if ((flags & DUK_S2N_FLAG_ALLOW_GARBAGE) == 0) {
86172 			DUK_DDD(DUK_DDDPRINT("parse failed: empty exponent"));
86173 			goto parse_fail;
86174 		}
86175 		DUK_ASSERT(expt == 0);
86176 	}
86177 
86178 	if (expt_neg) {
86179 		expt = -expt;
86180 	}
86181 	DUK_DDD(DUK_DDDPRINT("expt=%ld, expt_adj=%ld, net exponent -> %ld",
86182 	                     (long) expt, (long) expt_adj, (long) (expt + expt_adj)));
86183 	expt += expt_adj;
86184 
86185 	/* Fast path check. */
86186 
86187 	if (nc_ctx->f.n <= 1 &&   /* 32-bit value */
86188 	    expt == 0    /* no net exponent */) {
86189 		/* Fast path is triggered for no exponent and also for balanced exponent
86190 		 * and fraction parts, e.g. for "1.23e2" == "123".  Remember to respect
86191 		 * zero sign.
86192 		 */
86193 
86194 		/* XXX: could accept numbers larger than 32 bits, e.g. up to 53 bits? */
86195 		DUK_DDD(DUK_DDDPRINT("fast path number parse"));
86196 		if (nc_ctx->f.n == 1) {
86197 			res = (double) nc_ctx->f.v[0];
86198 		} else {
86199 			res = 0.0;
86200 		}
86201 		goto negcheck_and_ret;
86202 	}
86203 
86204 	/* Significand ('f') padding. */
86205 
86206 	while (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
86207 		/* Pad significand with "virtual" zero digits so that Dragon4 will
86208 		 * have enough (apparent) precision to work with.
86209 		 */
86210 		DUK_DDD(DUK_DDDPRINT("dig_prec=%ld, pad significand with zero", (long) dig_prec));
86211 		duk__bi_mul_small_copy(&nc_ctx->f, (duk_uint32_t) radix, &nc_ctx->t1);
86212 		DUK__BI_PRINT("f", &nc_ctx->f);
86213 		expt--;
86214 		dig_prec++;
86215 	}
86216 
86217 	DUK_DDD(DUK_DDDPRINT("final exponent: %ld", (long) expt));
86218 
86219 	/* Detect zero special case. */
86220 
86221 	if (nc_ctx->f.n == 0) {
86222 		/* This may happen even after the fast path check, if exponent is
86223 		 * not balanced (e.g. "0e1").  Remember to respect zero sign.
86224 		 */
86225 		DUK_DDD(DUK_DDDPRINT("significand is zero"));
86226 		res = 0.0;
86227 		goto negcheck_and_ret;
86228 	}
86229 
86230 
86231 	/* Quick reject of too large or too small exponents.  This check
86232 	 * would be incorrect for zero (e.g. "0e1000" is zero, not Infinity)
86233 	 * so zero check must be above.
86234 	 */
86235 
86236 	explim = &duk__str2num_exp_limits[radix - 2];
86237 	if (expt > explim->upper) {
86238 		DUK_DDD(DUK_DDDPRINT("exponent too large -> infinite"));
86239 		res = (duk_double_t) DUK_DOUBLE_INFINITY;
86240 		goto negcheck_and_ret;
86241 	} else if (expt < explim->lower) {
86242 		DUK_DDD(DUK_DDDPRINT("exponent too small -> zero"));
86243 		res = (duk_double_t) 0.0;
86244 		goto negcheck_and_ret;
86245 	}
86246 
86247 	nc_ctx->is_s2n = 1;
86248 	nc_ctx->e = expt;
86249 	nc_ctx->b = radix;
86250 	nc_ctx->B = 2;
86251 	nc_ctx->is_fixed = 1;
86252 	nc_ctx->abs_pos = 0;
86253 	nc_ctx->req_digits = 53 + 1;
86254 
86255 	DUK__BI_PRINT("f", &nc_ctx->f);
86256 	DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
86257 
86258 	/*
86259 	 *  Dragon4 slow path (binary) digit generation.
86260 	 *  An extra digit is generated for rounding.
86261 	 */
86262 
86263 	duk__dragon4_prepare(nc_ctx);  /* setup many variables in nc_ctx */
86264 
86265 	DUK_DDD(DUK_DDDPRINT("after prepare:"));
86266 	DUK__BI_PRINT("r", &nc_ctx->r);
86267 	DUK__BI_PRINT("s", &nc_ctx->s);
86268 	DUK__BI_PRINT("mp", &nc_ctx->mp);
86269 	DUK__BI_PRINT("mm", &nc_ctx->mm);
86270 
86271 	duk__dragon4_scale(nc_ctx);
86272 
86273 	DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
86274 	DUK__BI_PRINT("r", &nc_ctx->r);
86275 	DUK__BI_PRINT("s", &nc_ctx->s);
86276 	DUK__BI_PRINT("mp", &nc_ctx->mp);
86277 	DUK__BI_PRINT("mm", &nc_ctx->mm);
86278 
86279 	duk__dragon4_generate(nc_ctx);
86280 
86281 	DUK_ASSERT(nc_ctx->count == 53 + 1);
86282 
86283 	/*
86284 	 *  Convert binary digits into an IEEE double.  Need to handle
86285 	 *  denormals and rounding correctly.
86286 	 *
86287 	 *  Some call sites currently assume the result is always a
86288 	 *  non-fastint double.  If this is changed, check all call
86289 	 *  sites.
86290 	 */
86291 
86292 	duk__dragon4_ctx_to_double(nc_ctx, &res);
86293 	goto negcheck_and_ret;
86294 
86295  negcheck_and_ret:
86296 	if (neg) {
86297 		res = -res;
86298 	}
86299 	duk_pop(thr);
86300 	duk_push_number(thr, (double) res);
86301 	DUK_DDD(DUK_DDDPRINT("result: %!T", (duk_tval *) duk_get_tval(thr, -1)));
86302 	return;
86303 
86304  parse_fail:
86305 	DUK_DDD(DUK_DDDPRINT("parse failed"));
86306 	duk_pop(thr);
86307 	duk_push_nan(thr);
86308 	return;
86309 
86310  parse_explimit_error:
86311 	DUK_DDD(DUK_DDDPRINT("parse failed, internal error, can't return a value"));
86312 	DUK_ERROR_RANGE(thr, "exponent too large");
86313 	DUK_WO_NORETURN(return;);
86314 }
86315 
86316 /* automatic undefs */
86317 #undef DUK__BI_MAX_PARTS
86318 #undef DUK__BI_PRINT
86319 #undef DUK__DIGITCHAR
86320 #undef DUK__DRAGON4_OUTPUT_PREINC
86321 #undef DUK__IEEE_DOUBLE_EXP_BIAS
86322 #undef DUK__IEEE_DOUBLE_EXP_MIN
86323 #undef DUK__MAX_FORMATTED_LENGTH
86324 #undef DUK__MAX_OUTPUT_DIGITS
86325 #undef DUK__NO_EXP
86326 #undef DUK__NUMCONV_CTX_BIGINTS_SIZE
86327 #undef DUK__NUMCONV_CTX_NUM_BIGINTS
86328 #line 1 "duk_regexp_compiler.c"
86329 /*
86330  *  Regexp compilation.
86331  *
86332  *  See doc/regexp.rst for a discussion of the compilation approach and
86333  *  current limitations.
86334  *
86335  *  Regexp bytecode assumes jumps can be expressed with signed 32-bit
86336  *  integers.  Consequently the bytecode size must not exceed 0x7fffffffL.
86337  *  The implementation casts duk_size_t (buffer size) to duk_(u)int32_t
86338  *  in many places.  Although this could be changed, the bytecode format
86339  *  limit would still prevent regexps exceeding the signed 32-bit limit
86340  *  from working.
86341  *
86342  *  XXX: The implementation does not prevent bytecode from exceeding the
86343  *  maximum supported size.  This could be done by limiting the maximum
86344  *  input string size (assuming an upper bound can be computed for number
86345  *  of bytecode bytes emitted per input byte) or checking buffer maximum
86346  *  size when emitting bytecode (slower).
86347  */
86348 
86349 /* #include duk_internal.h -> already included */
86350 
86351 #if defined(DUK_USE_REGEXP_SUPPORT)
86352 
86353 /*
86354  *  Helper macros
86355  */
86356 
86357 #define DUK__RE_INITIAL_BUFSIZE 64
86358 
86359 #define DUK__RE_BUFLEN(re_ctx) \
86360 	DUK_BW_GET_SIZE(re_ctx->thr, &re_ctx->bw)
86361 
86362 /*
86363  *  Disjunction struct: result of parsing a disjunction
86364  */
86365 
86366 typedef struct {
86367 	/* Number of characters that the atom matches (e.g. 3 for 'abc'),
86368 	 * -1 if atom is complex and number of matched characters either
86369 	 * varies or is not known.
86370 	 */
86371 	duk_int32_t charlen;
86372 
86373 #if 0
86374 	/* These are not needed to implement quantifier capture handling,
86375 	 * but might be needed at some point.
86376 	 */
86377 
86378 	/* re_ctx->captures at start and end of atom parsing.
86379 	 * Since 'captures' indicates highest capture number emitted
86380 	 * so far in a DUK_REOP_SAVE, the captures numbers saved by
86381 	 * the atom are: ]start_captures,end_captures].
86382 	 */
86383 	duk_uint32_t start_captures;
86384 	duk_uint32_t end_captures;
86385 #endif
86386 } duk__re_disjunction_info;
86387 
86388 /*
86389  *  Encoding helpers
86390  *
86391  *  Some of the typing is bytecode based, e.g. slice sizes are unsigned 32-bit
86392  *  even though the buffer operations will use duk_size_t.
86393  */
86394 
86395 /* XXX: the insert helpers should ensure that the bytecode result is not
86396  * larger than expected (or at least assert for it).  Many things in the
86397  * bytecode, like skip offsets, won't work correctly if the bytecode is
86398  * larger than say 2G.
86399  */
86400 
86401 DUK_LOCAL duk_uint32_t duk__encode_i32(duk_int32_t x) {
86402 	if (x < 0) {
86403 		return ((duk_uint32_t) (-x)) * 2 + 1;
86404 	} else {
86405 		return ((duk_uint32_t) x) * 2;
86406 	}
86407 }
86408 
86409 /* XXX: return type should probably be duk_size_t, or explicit checks are needed for
86410  * maximum size.
86411  */
86412 DUK_LOCAL duk_uint32_t duk__insert_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t x) {
86413 	duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
86414 	duk_small_int_t len;
86415 
86416 	len = duk_unicode_encode_xutf8((duk_ucodepoint_t) x, buf);
86417 	DUK_ASSERT(len >= 0);
86418 	DUK_BW_INSERT_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, offset, buf, (duk_size_t) len);
86419 	return (duk_uint32_t) len;
86420 }
86421 
86422 DUK_LOCAL void duk__append_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
86423 	DUK_BW_WRITE_ENSURE_XUTF8(re_ctx->thr, &re_ctx->bw, x);
86424 }
86425 
86426 DUK_LOCAL void duk__append_7bit(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
86427 #if defined(DUK_USE_PREFER_SIZE)
86428 	duk__append_u32(re_ctx, x);
86429 #else
86430 	DUK_ASSERT(x <= 0x7fU);
86431 	DUK_BW_WRITE_ENSURE_U8(re_ctx->thr, &re_ctx->bw, (duk_uint8_t) x);
86432 #endif
86433 }
86434 
86435 #if 0
86436 DUK_LOCAL void duk__append_2bytes(duk_re_compiler_ctx *re_ctx, duk_uint8_t x, duk_uint8_t y) {
86437 	DUK_BW_WRITE_ENSURE_U8_2(re_ctx->thr, &re_ctx->bw, x, y);
86438 }
86439 #endif
86440 
86441 DUK_LOCAL duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x) {
86442 	return duk__insert_u32(re_ctx, offset, duk__encode_i32(x));
86443 }
86444 
86445 DUK_LOCAL void duk__append_reop(duk_re_compiler_ctx *re_ctx, duk_uint32_t reop) {
86446 	DUK_ASSERT(reop <= 0x7fU);
86447 	(void) duk__append_7bit(re_ctx, reop);
86448 }
86449 
86450 #if 0  /* unused */
86451 DUK_LOCAL void duk__append_i32(duk_re_compiler_ctx *re_ctx, duk_int32_t x) {
86452 	duk__append_u32(re_ctx, duk__encode_i32(x));
86453 }
86454 #endif
86455 
86456 /* special helper for emitting u16 lists (used for character ranges for built-in char classes) */
86457 DUK_LOCAL void duk__append_u16_list(duk_re_compiler_ctx *re_ctx, const duk_uint16_t *values, duk_uint32_t count) {
86458 	/* Call sites don't need the result length so it's not accumulated. */
86459 	while (count-- > 0) {
86460 		duk__append_u32(re_ctx, (duk_uint32_t) (*values++));
86461 	}
86462 }
86463 
86464 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) {
86465 	DUK_BW_INSERT_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, offset, data_offset, data_length);
86466 }
86467 
86468 DUK_LOCAL void duk__append_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
86469 	DUK_BW_WRITE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
86470 }
86471 
86472 DUK_LOCAL void duk__remove_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
86473 	DUK_BW_REMOVE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
86474 }
86475 
86476 /*
86477  *  Insert a jump offset at 'offset' to complete an instruction
86478  *  (the jump offset is always the last component of an instruction).
86479  *  The 'skip' argument must be computed relative to 'offset',
86480  *  -without- taking into account the skip field being inserted.
86481  *
86482  *       ... A B C ins X Y Z ...   (ins may be a JUMP, SPLIT1/SPLIT2, etc)
86483  *   =>  ... A B C ins SKIP X Y Z
86484  *
86485  *  Computing the final (adjusted) skip value, which is relative to the
86486  *  first byte of the next instruction, is a bit tricky because of the
86487  *  variable length UTF-8 encoding.  See doc/regexp.rst for discussion.
86488  */
86489 DUK_LOCAL duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t skip) {
86490 #if 0
86491 	/* Iterative solution. */
86492 	if (skip < 0) {
86493 		duk_small_int_t len;
86494 		/* two encoding attempts suffices */
86495 		len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip));
86496 		len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip - (duk_int32_t) len));
86497 		DUK_ASSERT(duk_unicode_get_xutf8_length(duk__encode_i32(skip - (duk_int32_t) len)) == len);  /* no change */
86498 		skip -= (duk_int32_t) len;
86499 	}
86500 #endif
86501 
86502 #if defined(DUK_USE_PREFER_SIZE)
86503 	/* Closed form solution, this produces smallest code.
86504 	 * See re_neg_jump_offset (closed2).
86505 	 */
86506 	if (skip < 0) {
86507 		skip--;
86508 		if (skip < -0x3fL) {
86509 			skip--;
86510 		}
86511 		if (skip < -0x3ffL) {
86512 			skip--;
86513 		}
86514 		if (skip < -0x7fffL) {
86515 			skip--;
86516 		}
86517 		if (skip < -0xfffffL) {
86518 			skip--;
86519 		}
86520 		if (skip < -0x1ffffffL) {
86521 			skip--;
86522 		}
86523 		if (skip < -0x3fffffffL) {
86524 			skip--;
86525 		}
86526 	}
86527 #else  /* DUK_USE_PREFER_SIZE */
86528 	/* Closed form solution, this produces fastest code.
86529 	 * See re_neg_jump_offset (closed1).
86530 	 */
86531 	if (skip < 0) {
86532 		if (skip >= -0x3eL) {
86533 			skip -= 1;
86534 		} else if (skip >= -0x3fdL) {
86535 			skip -= 2;
86536 		} else if (skip >= -0x7ffcL) {
86537 			skip -= 3;
86538 		} else if (skip >= -0xffffbL) {
86539 			skip -= 4;
86540 		} else if (skip >= -0x1fffffaL) {
86541 			skip -= 5;
86542 		} else if (skip >= -0x3ffffff9L) {
86543 			skip -= 6;
86544 		} else {
86545 			skip -= 7;
86546 		}
86547 	}
86548 #endif  /* DUK_USE_PREFER_SIZE */
86549 
86550 	return duk__insert_i32(re_ctx, offset, skip);
86551 }
86552 
86553 DUK_LOCAL duk_uint32_t duk__append_jump_offset(duk_re_compiler_ctx *re_ctx, duk_int32_t skip) {
86554 	return (duk_uint32_t) duk__insert_jump_offset(re_ctx, (duk_uint32_t) DUK__RE_BUFLEN(re_ctx), skip);
86555 }
86556 
86557 /*
86558  *  duk_re_range_callback for generating character class ranges.
86559  *
86560  *  When ignoreCase is false, the range is simply emitted as is.  We don't,
86561  *  for instance, eliminate duplicates or overlapping ranges in a character
86562  *  class.
86563  *
86564  *  When ignoreCase is true but the 'direct' flag is set, the caller knows
86565  *  that the range canonicalizes to itself for case insensitive matching,
86566  *  so the range is emitted as is.  This is mainly useful for built-in ranges
86567  *  like \W.
86568  *
86569  *  Otherwise, when ignoreCase is true, the range needs to be normalized
86570  *  through canonicalization.  Unfortunately a canonicalized version of a
86571  *  continuous range is not necessarily continuous (e.g. [x-{] is continuous
86572  *  but [X-{] is not).  As a result, a single input range may expand to a lot
86573  *  of output ranges.  The current algorithm creates the canonicalized ranges
86574  *  footprint efficiently at the cost of compile time execution time; see
86575  *  doc/regexp.rst for discussion, and some more details below.
86576  *
86577  *  Note that the ctx->nranges is a context-wide temporary value.  This is OK
86578  *  because there cannot be multiple character classes being parsed
86579  *  simultaneously.
86580  *
86581  *  More detail on canonicalization:
86582  *
86583  *  Conceptually, a range is canonicalized by scanning the entire range,
86584  *  normalizing each codepoint by converting it to uppercase, and generating
86585  *  a set of result ranges.
86586  *
86587  *  Ideally a minimal set of output ranges would be emitted by merging all
86588  *  possible ranges even if they're emitted out of sequence.  Because the
86589  *  input string is also case normalized during matching, some codepoints
86590  *  never occur at runtime; these "don't care" codepoints can be included or
86591  *  excluded from ranges when merging/optimizing ranges.
86592  *
86593  *  The current algorithm does not do optimal range merging.  Rather, output
86594  *  codepoints are generated in sequence, and when the output codepoints are
86595  *  continuous (CP, CP+1, CP+2, ...), they are merged locally into as large a
86596  *  range as possible.  A small canonicalization bitmap is used to reduce
86597  *  actual codepoint canonicalizations which are quite slow at present.  The
86598  *  bitmap provides a "codepoint block is continuous with respect to
86599  *  canonicalization" for N-codepoint blocks.  This allows blocks to be
86600  *  skipped quickly.
86601  *
86602  *  There are a number of shortcomings and future work here:
86603  *
86604  *    - Individual codepoint normalizations are slow because they involve
86605  *      walking bit-packed rules without a lookup index.
86606  *
86607  *    - The conceptual algorithm needs to canonicalize every codepoint in the
86608  *      input range to figure out the output range(s).  Even with the small
86609  *      canonicalization bitmap the algorithm runs quite slowly for worst case
86610  *      inputs.  There are many data structure alternatives to improve this.
86611  *
86612  *    - While the current algorithm generates maximal output ranges when the
86613  *      output codepoints are emitted linearly, output ranges are not sorted or
86614  *      merged otherwise.  In the worst case a lot of ranges are emitted when
86615  *      most of the ranges could be merged.  In this process one could take
86616  *      advantage of "don't care" codepoints, which are never matched against at
86617  *      runtime due to canonicalization of input codepoints before comparison,
86618  *      to merge otherwise discontinuous output ranges.
86619  *
86620  *    - The runtime data structure is just a linear list of ranges to match
86621  *      against.  This can be quite slow if there are a lot of output ranges.
86622  *      There are various ways to make matching against the ranges faster,
86623  *      e.g. sorting the ranges and using a binary search; skip lists; tree
86624  *      based representations; full or approximate codepoint bitmaps, etc.
86625  *
86626  *    - Only BMP is supported, codepoints above BMP are assumed to canonicalize
86627  *      to themselves.  For now this is one place where we don't want to
86628  *      support chars outside the BMP, because the exhaustive search would be
86629  *      massively larger.  It would be possible to support non-BMP with a
86630  *      different algorithm, or perhaps doing case normalization only at match
86631  *      time.
86632  */
86633 
86634 DUK_LOCAL void duk__regexp_emit_range(duk_re_compiler_ctx *re_ctx, duk_codepoint_t r1, duk_codepoint_t r2) {
86635 	DUK_ASSERT(r2 >= r1);
86636 	duk__append_u32(re_ctx, (duk_uint32_t) r1);
86637 	duk__append_u32(re_ctx, (duk_uint32_t) r2);
86638 	re_ctx->nranges++;
86639 }
86640 
86641 #if defined(DUK_USE_REGEXP_CANON_BITMAP)
86642 /* Find next canonicalization discontinuity (conservative estimate) starting
86643  * from 'start', not exceeding 'end'.  If continuity is fine up to 'end'
86644  * inclusive, returns end.  Minimum possible return value is start.
86645  */
86646 DUK_LOCAL duk_codepoint_t duk__re_canon_next_discontinuity(duk_codepoint_t start, duk_codepoint_t end) {
86647 	duk_uint_t start_blk;
86648 	duk_uint_t end_blk;
86649 	duk_uint_t blk;
86650 	duk_uint_t offset;
86651 	duk_uint8_t mask;
86652 
86653 	/* Inclusive block range. */
86654 	DUK_ASSERT(start >= 0);
86655 	DUK_ASSERT(end >= 0);
86656 	DUK_ASSERT(end >= start);
86657 	start_blk = (duk_uint_t) (start >> DUK_CANON_BITMAP_BLKSHIFT);
86658 	end_blk = (duk_uint_t) (end >> DUK_CANON_BITMAP_BLKSHIFT);
86659 
86660 	for (blk = start_blk; blk <= end_blk; blk++) {
86661 		offset = blk >> 3;
86662 		mask = 1U << (blk & 0x07);
86663 		if (offset >= sizeof(duk_unicode_re_canon_bitmap)) {
86664 			/* Reached non-BMP range which is assumed continuous. */
86665 			return end;
86666 		}
86667 		DUK_ASSERT(offset < sizeof(duk_unicode_re_canon_bitmap));
86668 		if ((duk_unicode_re_canon_bitmap[offset] & mask) == 0) {
86669 			/* Block is discontinuous, continuity is guaranteed
86670 			 * only up to end of previous block (+1 for exclusive
86671 			 * return value => start of current block).  Start
86672 			 * block requires special handling.
86673 			 */
86674 			if (blk > start_blk) {
86675 				return (duk_codepoint_t) (blk << DUK_CANON_BITMAP_BLKSHIFT);
86676 			} else {
86677 				return start;
86678 			}
86679 		}
86680 	}
86681 	DUK_ASSERT(blk == end_blk + 1);  /* Reached end block which is continuous. */
86682 	return end;
86683 }
86684 #else  /* DUK_USE_REGEXP_CANON_BITMAP */
86685 DUK_LOCAL duk_codepoint_t duk__re_canon_next_discontinuity(duk_codepoint_t start, duk_codepoint_t end) {
86686 	DUK_ASSERT(start >= 0);
86687 	DUK_ASSERT(end >= 0);
86688 	DUK_ASSERT(end >= start);
86689 	if (start >= 0x10000) {
86690 		/* Even without the bitmap, treat non-BMP as continuous. */
86691 		return end;
86692 	}
86693 	return start;
86694 }
86695 #endif  /* DUK_USE_REGEXP_CANON_BITMAP */
86696 
86697 DUK_LOCAL void duk__regexp_generate_ranges(void *userdata, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct) {
86698 	duk_re_compiler_ctx *re_ctx = (duk_re_compiler_ctx *) userdata;
86699 	duk_codepoint_t r_start;
86700 	duk_codepoint_t r_end;
86701 	duk_codepoint_t i;
86702 	duk_codepoint_t t;
86703 	duk_codepoint_t r_disc;
86704 
86705 	DUK_DD(DUK_DDPRINT("duk__regexp_generate_ranges(): re_ctx=%p, range=[%ld,%ld] direct=%ld",
86706 	                   (void *) re_ctx, (long) r1, (long) r2, (long) direct));
86707 
86708 	DUK_ASSERT(r2 >= r1);  /* SyntaxError for out of order range. */
86709 
86710 	if (direct || (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) == 0) {
86711 		DUK_DD(DUK_DDPRINT("direct or not case sensitive, emit range: [%ld,%ld]", (long) r1, (long) r2));
86712 		duk__regexp_emit_range(re_ctx, r1, r2);
86713 		return;
86714 	}
86715 
86716 	DUK_DD(DUK_DDPRINT("case sensitive, process range: [%ld,%ld]", (long) r1, (long) r2));
86717 
86718 	r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
86719 	r_end = r_start;
86720 
86721 	for (i = r1 + 1; i <= r2;) {
86722 		/* Input codepoint space processed up to i-1, and
86723 		 * current range in r_{start,end} is up-to-date
86724 		 * (inclusive) and may either break or continue.
86725 		 */
86726 		r_disc = duk__re_canon_next_discontinuity(i, r2);
86727 		DUK_ASSERT(r_disc >= i);
86728 		DUK_ASSERT(r_disc <= r2);
86729 
86730 		r_end += r_disc - i;  /* May be zero. */
86731 		t = duk_unicode_re_canonicalize_char(re_ctx->thr, r_disc);
86732 		if (t == r_end + 1) {
86733 			/* Not actually a discontinuity, continue range
86734 			 * to r_disc and recheck.
86735 			 */
86736 			r_end = t;
86737 		} else {
86738 			duk__regexp_emit_range(re_ctx, r_start, r_end);
86739 			r_start = t;
86740 			r_end = t;
86741 		}
86742 		i = r_disc + 1;  /* Guarantees progress. */
86743 	}
86744 	duk__regexp_emit_range(re_ctx, r_start, r_end);
86745 
86746 #if 0  /* Exhaustive search, very slow. */
86747 	r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
86748 	r_end = r_start;
86749 	for (i = r1 + 1; i <= r2; i++) {
86750 		t = duk_unicode_re_canonicalize_char(re_ctx->thr, i);
86751 		if (t == r_end + 1) {
86752 			r_end = t;
86753 		} else {
86754 			DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
86755 			duk__append_u32(re_ctx, (duk_uint32_t) r_start);
86756 			duk__append_u32(re_ctx, (duk_uint32_t) r_end);
86757 			re_ctx->nranges++;
86758 			r_start = t;
86759 			r_end = t;
86760 		}
86761 	}
86762 	DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
86763 	duk__append_u32(re_ctx, (duk_uint32_t) r_start);
86764 	duk__append_u32(re_ctx, (duk_uint32_t) r_end);
86765 	re_ctx->nranges++;
86766 #endif
86767 }
86768 
86769 /*
86770  *  Parse regexp Disjunction.  Most of regexp compilation happens here.
86771  *
86772  *  Handles Disjunction, Alternative, and Term productions directly without
86773  *  recursion.  The only constructs requiring recursion are positive/negative
86774  *  lookaheads, capturing parentheses, and non-capturing parentheses.
86775  *
86776  *  The function determines whether the entire disjunction is a 'simple atom'
86777  *  (see doc/regexp.rst discussion on 'simple quantifiers') and if so,
86778  *  returns the atom character length which is needed by the caller to keep
86779  *  track of its own atom character length.  A disjunction with more than one
86780  *  alternative is never considered a simple atom (although in some cases
86781  *  that might be the case).
86782  *
86783  *  Return value: simple atom character length or < 0 if not a simple atom.
86784  *  Appends the bytecode for the disjunction matcher to the end of the temp
86785  *  buffer.
86786  *
86787  *  Regexp top level structure is:
86788  *
86789  *    Disjunction = Term*
86790  *                | Term* | Disjunction
86791  *
86792  *    Term = Assertion
86793  *         | Atom
86794  *         | Atom Quantifier
86795  *
86796  *  An empty Term sequence is a valid disjunction alternative (e.g. /|||c||/).
86797  *
86798  *  Notes:
86799  *
86800  *    * Tracking of the 'simple-ness' of the current atom vs. the entire
86801  *      disjunction are separate matters.  For instance, the disjunction
86802  *      may be complex, but individual atoms may be simple.  Furthermore,
86803  *      simple quantifiers are used whenever possible, even if the
86804  *      disjunction as a whole is complex.
86805  *
86806  *    * The estimate of whether an atom is simple is conservative now,
86807  *      and it would be possible to expand it.  For instance, captures
86808  *      cause the disjunction to be marked complex, even though captures
86809  *      -can- be handled by simple quantifiers with some minor modifications.
86810  *
86811  *    * Disjunction 'tainting' as 'complex' is handled at the end of the
86812  *      main for loop collectively for atoms.  Assertions, quantifiers,
86813  *      and '|' tokens need to taint the result manually if necessary.
86814  *      Assertions cannot add to result char length, only atoms (and
86815  *      quantifiers) can; currently quantifiers will taint the result
86816  *      as complex though.
86817  */
86818 
86819 DUK_LOCAL const duk_uint16_t * const duk__re_range_lookup1[3] = {
86820 	duk_unicode_re_ranges_digit,
86821 	duk_unicode_re_ranges_white,
86822 	duk_unicode_re_ranges_wordchar
86823 };
86824 DUK_LOCAL const duk_uint8_t duk__re_range_lookup2[3] = {
86825 	sizeof(duk_unicode_re_ranges_digit) / (2 * sizeof(duk_uint16_t)),
86826 	sizeof(duk_unicode_re_ranges_white) / (2 * sizeof(duk_uint16_t)),
86827 	sizeof(duk_unicode_re_ranges_wordchar) / (2 * sizeof(duk_uint16_t))
86828 };
86829 
86830 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) {
86831 #if 0
86832 	DUK_ASSERT(re_op <= 0x7fUL);
86833 	DUK_ASSERT(count <= 0x7fUL);
86834 	duk__append_2bytes(re_ctx, (duk_uint8_t) re_op, (duk_uint8_t) count);
86835 #endif
86836 	duk__append_reop(re_ctx, re_op);
86837 	duk__append_7bit(re_ctx, count);
86838 	duk__append_u16_list(re_ctx, ranges, count * 2);
86839 }
86840 
86841 DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t expect_eof, duk__re_disjunction_info *out_atom_info) {
86842 	duk_int32_t atom_start_offset = -1;                   /* negative -> no atom matched on previous round */
86843 	duk_int32_t atom_char_length = 0;                     /* negative -> complex atom */
86844 	duk_uint32_t atom_start_captures = re_ctx->captures;  /* value of re_ctx->captures at start of atom */
86845 	duk_int32_t unpatched_disjunction_split = -1;
86846 	duk_int32_t unpatched_disjunction_jump = -1;
86847 	duk_uint32_t entry_offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
86848 	duk_int32_t res_charlen = 0;  /* -1 if disjunction is complex, char length if simple */
86849 	duk__re_disjunction_info tmp_disj;
86850 
86851 	DUK_ASSERT(out_atom_info != NULL);
86852 
86853 	if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
86854 		DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT);
86855 		DUK_WO_NORETURN(return;);
86856 	}
86857 	re_ctx->recursion_depth++;
86858 
86859 #if 0
86860 	out_atom_info->start_captures = re_ctx->captures;
86861 #endif
86862 
86863 	for (;;) {
86864 		/* atom_char_length, atom_start_offset, atom_start_offset reflect the
86865 		 * atom matched on the previous loop.  If a quantifier is encountered
86866 		 * on this loop, these are needed to handle the quantifier correctly.
86867 		 * new_atom_char_length etc are for the atom parsed on this round;
86868 		 * they're written to atom_char_length etc at the end of the round.
86869 		 */
86870 		duk_int32_t new_atom_char_length;   /* char length of the atom parsed in this loop */
86871 		duk_int32_t new_atom_start_offset;  /* bytecode start offset of the atom parsed in this loop
86872 		                                     * (allows quantifiers to copy the atom bytecode)
86873 		                                     */
86874 		duk_uint32_t new_atom_start_captures;  /* re_ctx->captures at the start of the atom parsed in this loop */
86875 
86876 		duk_lexer_parse_re_token(&re_ctx->lex, &re_ctx->curr_token);
86877 
86878 		DUK_DD(DUK_DDPRINT("re token: %ld (num=%ld, char=%c)",
86879 		                   (long) re_ctx->curr_token.t,
86880 		                   (long) re_ctx->curr_token.num,
86881 		                   (re_ctx->curr_token.num >= 0x20 && re_ctx->curr_token.num <= 0x7e) ?
86882 		                   (int) re_ctx->curr_token.num : (int) '?'));
86883 
86884 		/* set by atom case clauses */
86885 		new_atom_start_offset = -1;
86886 		new_atom_char_length = -1;
86887 		new_atom_start_captures = re_ctx->captures;
86888 
86889 		switch (re_ctx->curr_token.t) {
86890 		case DUK_RETOK_DISJUNCTION: {
86891 			/*
86892 			 *  The handling here is a bit tricky.  If a previous '|' has been processed,
86893 			 *  we have a pending split1 and a pending jump (for a previous match).  These
86894 			 *  need to be back-patched carefully.  See docs for a detailed example.
86895 			 */
86896 
86897 			/* patch pending jump and split */
86898 			if (unpatched_disjunction_jump >= 0) {
86899 				duk_uint32_t offset;
86900 
86901 				DUK_ASSERT(unpatched_disjunction_split >= 0);
86902 				offset = (duk_uint32_t) unpatched_disjunction_jump;
86903 				offset += duk__insert_jump_offset(re_ctx,
86904 				                                  offset,
86905 				                                  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
86906 				/* offset is now target of the pending split (right after jump) */
86907 				duk__insert_jump_offset(re_ctx,
86908 				                        (duk_uint32_t) unpatched_disjunction_split,
86909 				                        (duk_int32_t) offset - unpatched_disjunction_split);
86910 			}
86911 
86912 			/* add a new pending split to the beginning of the entire disjunction */
86913 			(void) duk__insert_u32(re_ctx,
86914 			                       entry_offset,
86915 			                       DUK_REOP_SPLIT1);   /* prefer direct execution */
86916 			unpatched_disjunction_split = (duk_int32_t) (entry_offset + 1);   /* +1 for opcode */
86917 
86918 			/* add a new pending match jump for latest finished alternative */
86919 			duk__append_reop(re_ctx, DUK_REOP_JUMP);
86920 			unpatched_disjunction_jump = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
86921 
86922 			/* 'taint' result as complex */
86923 			res_charlen = -1;
86924 			break;
86925 		}
86926 		case DUK_RETOK_QUANTIFIER: {
86927 			if (atom_start_offset < 0) {
86928 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_NO_ATOM);
86929 				DUK_WO_NORETURN(return;);
86930 			}
86931 			if (re_ctx->curr_token.qmin > re_ctx->curr_token.qmax) {
86932 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_VALUES);
86933 				DUK_WO_NORETURN(return;);
86934 			}
86935 			if (atom_char_length >= 0) {
86936 				/*
86937 				 *  Simple atom
86938 				 *
86939 				 *  If atom_char_length is zero, we'll have unbounded execution time for e.g.
86940 				 *  /()*x/.exec('x').  We can't just skip the match because it might have some
86941 				 *  side effects (for instance, if we allowed captures in simple atoms, the
86942 				 *  capture needs to happen).  The simple solution below is to force the
86943 				 *  quantifier to match at most once, since the additional matches have no effect.
86944 				 *
86945 				 *  With a simple atom there can be no capture groups, so no captures need
86946 				 *  to be reset.
86947 				 */
86948 				duk_int32_t atom_code_length;
86949 				duk_uint32_t offset;
86950 				duk_uint32_t qmin, qmax;
86951 
86952 				qmin = re_ctx->curr_token.qmin;
86953 				qmax = re_ctx->curr_token.qmax;
86954 				if (atom_char_length == 0) {
86955 					/* qmin and qmax will be 0 or 1 */
86956 					if (qmin > 1) {
86957 						qmin = 1;
86958 					}
86959 					if (qmax > 1) {
86960 						qmax = 1;
86961 					}
86962 				}
86963 
86964 				duk__append_reop(re_ctx, DUK_REOP_MATCH);   /* complete 'sub atom' */
86965 				atom_code_length = (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (duk_size_t) atom_start_offset);
86966 
86967 				offset = (duk_uint32_t) atom_start_offset;
86968 				if (re_ctx->curr_token.greedy) {
86969 					offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQGREEDY);
86970 					offset += duk__insert_u32(re_ctx, offset, qmin);
86971 					offset += duk__insert_u32(re_ctx, offset, qmax);
86972 					offset += duk__insert_u32(re_ctx, offset, (duk_uint32_t) atom_char_length);
86973 					offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
86974 				} else {
86975 					offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQMINIMAL);
86976 					offset += duk__insert_u32(re_ctx, offset, qmin);
86977 					offset += duk__insert_u32(re_ctx, offset, qmax);
86978 					offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
86979 				}
86980 				DUK_UNREF(offset);  /* silence scan-build warning */
86981 			} else {
86982 				/*
86983 				 *  Complex atom
86984 				 *
86985 				 *  The original code is used as a template, and removed at the end
86986 				 *  (this differs from the handling of simple quantifiers).
86987 				 *
86988 				 *  NOTE: there is no current solution for empty atoms in complex
86989 				 *  quantifiers.  This would need some sort of a 'progress' instruction.
86990 				 *
86991 				 *  XXX: impose limit on maximum result size, i.e. atom_code_len * atom_copies?
86992 				 */
86993 				duk_int32_t atom_code_length;
86994 				duk_uint32_t atom_copies;
86995 				duk_uint32_t tmp_qmin, tmp_qmax;
86996 
86997 				/* pre-check how many atom copies we're willing to make (atom_copies not needed below) */
86998 				atom_copies = (re_ctx->curr_token.qmax == DUK_RE_QUANTIFIER_INFINITE) ?
86999 				              re_ctx->curr_token.qmin : re_ctx->curr_token.qmax;
87000 				if (atom_copies > DUK_RE_MAX_ATOM_COPIES) {
87001 					DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_QUANTIFIER_TOO_MANY_COPIES);
87002 					DUK_WO_NORETURN(return;);
87003 				}
87004 
87005 				/* wipe the capture range made by the atom (if any) */
87006 				DUK_ASSERT(atom_start_captures <= re_ctx->captures);
87007 				if (atom_start_captures != re_ctx->captures) {
87008 					DUK_ASSERT(atom_start_captures < re_ctx->captures);
87009 					DUK_DDD(DUK_DDDPRINT("must wipe ]atom_start_captures,re_ctx->captures]: ]%ld,%ld]",
87010 					                     (long) atom_start_captures, (long) re_ctx->captures));
87011 
87012 					/* insert (DUK_REOP_WIPERANGE, start, count) in reverse order so the order ends up right */
87013 					duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, (re_ctx->captures - atom_start_captures) * 2U);
87014 					duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, (atom_start_captures + 1) * 2);
87015 					duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, DUK_REOP_WIPERANGE);
87016 				} else {
87017 					DUK_DDD(DUK_DDDPRINT("no need to wipe captures: atom_start_captures == re_ctx->captures == %ld",
87018 					                     (long) atom_start_captures));
87019 				}
87020 
87021 				atom_code_length = (duk_int32_t) DUK__RE_BUFLEN(re_ctx) - atom_start_offset;
87022 
87023 				/* insert the required matches (qmin) by copying the atom */
87024 				tmp_qmin = re_ctx->curr_token.qmin;
87025 				tmp_qmax = re_ctx->curr_token.qmax;
87026 				while (tmp_qmin > 0) {
87027 					duk__append_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
87028 					tmp_qmin--;
87029 					if (tmp_qmax != DUK_RE_QUANTIFIER_INFINITE) {
87030 						tmp_qmax--;
87031 					}
87032 				}
87033 				DUK_ASSERT(tmp_qmin == 0);
87034 
87035 				/* insert code for matching the remainder - infinite or finite */
87036 				if (tmp_qmax == DUK_RE_QUANTIFIER_INFINITE) {
87037 					/* reuse last emitted atom for remaining 'infinite' quantifier */
87038 
87039 					if (re_ctx->curr_token.qmin == 0) {
87040 						/* Special case: original qmin was zero so there is nothing
87041 						 * to repeat.  Emit an atom copy but jump over it here.
87042 						 */
87043 						duk__append_reop(re_ctx, DUK_REOP_JUMP);
87044 						duk__append_jump_offset(re_ctx, atom_code_length);
87045 						duk__append_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
87046 					}
87047 					if (re_ctx->curr_token.greedy) {
87048 						duk__append_reop(re_ctx, DUK_REOP_SPLIT2);   /* prefer jump */
87049 					} else {
87050 						duk__append_reop(re_ctx, DUK_REOP_SPLIT1);   /* prefer direct */
87051 					}
87052 					duk__append_jump_offset(re_ctx, -atom_code_length - 1);  /* -1 for opcode */
87053 				} else {
87054 					/*
87055 					 *  The remaining matches are emitted as sequence of SPLITs and atom
87056 					 *  copies; the SPLITs skip the remaining copies and match the sequel.
87057 					 *  This sequence needs to be emitted starting from the last copy
87058 					 *  because the SPLITs are variable length due to the variable length
87059 					 *  skip offset.  This causes a lot of memory copying now.
87060 					 *
87061 					 *  Example structure (greedy, match maximum # atoms):
87062 					 *
87063 					 *      SPLIT1 LSEQ
87064 					 *      (atom)
87065 					 *      SPLIT1 LSEQ    ; <- the byte length of this instruction is needed
87066 					 *      (atom)         ; to encode the above SPLIT1 correctly
87067 					 *      ...
87068 					 *   LSEQ:
87069 					 */
87070 					duk_uint32_t offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
87071 					while (tmp_qmax > 0) {
87072 						duk__insert_slice(re_ctx, offset, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
87073 						if (re_ctx->curr_token.greedy) {
87074 							duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT1);   /* prefer direct */
87075 						} else {
87076 							duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT2);   /* prefer jump */
87077 						}
87078 						duk__insert_jump_offset(re_ctx,
87079 						                        offset + 1,   /* +1 for opcode */
87080 						                        (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
87081 						tmp_qmax--;
87082 					}
87083 				}
87084 
87085 				/* remove the original 'template' atom */
87086 				duk__remove_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
87087 			}
87088 
87089 			/* 'taint' result as complex */
87090 			res_charlen = -1;
87091 			break;
87092 		}
87093 		case DUK_RETOK_ASSERT_START: {
87094 			duk__append_reop(re_ctx, DUK_REOP_ASSERT_START);
87095 			break;
87096 		}
87097 		case DUK_RETOK_ASSERT_END: {
87098 			duk__append_reop(re_ctx, DUK_REOP_ASSERT_END);
87099 			break;
87100 		}
87101 		case DUK_RETOK_ASSERT_WORD_BOUNDARY: {
87102 			duk__append_reop(re_ctx, DUK_REOP_ASSERT_WORD_BOUNDARY);
87103 			break;
87104 		}
87105 		case DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY: {
87106 			duk__append_reop(re_ctx, DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);
87107 			break;
87108 		}
87109 		case DUK_RETOK_ASSERT_START_POS_LOOKAHEAD:
87110 		case DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD: {
87111 			duk_uint32_t offset;
87112 			duk_uint32_t opcode = (re_ctx->curr_token.t == DUK_RETOK_ASSERT_START_POS_LOOKAHEAD) ?
87113 			                      DUK_REOP_LOOKPOS : DUK_REOP_LOOKNEG;
87114 
87115 			offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
87116 			duk__parse_disjunction(re_ctx, 0, &tmp_disj);
87117 			duk__append_reop(re_ctx, DUK_REOP_MATCH);
87118 
87119 			(void) duk__insert_u32(re_ctx, offset, opcode);
87120 			(void) duk__insert_jump_offset(re_ctx,
87121 			                               offset + 1,   /* +1 for opcode */
87122 			                               (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
87123 
87124 			/* 'taint' result as complex -- this is conservative,
87125 			 * as lookaheads do not backtrack.
87126 			 */
87127 			res_charlen = -1;
87128 			break;
87129 		}
87130 		case DUK_RETOK_ATOM_PERIOD: {
87131 			new_atom_char_length = 1;
87132 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87133 			duk__append_reop(re_ctx, DUK_REOP_PERIOD);
87134 			break;
87135 		}
87136 		case DUK_RETOK_ATOM_CHAR: {
87137 			/* Note: successive characters could be joined into string matches
87138 			 * but this is not trivial (consider e.g. '/xyz+/); see docs for
87139 			 * more discussion.
87140 			 *
87141 			 * No support for \u{H+} yet.  While only BMP Unicode escapes are
87142 			 * supported for RegExps at present, 'ch' may still be a non-BMP
87143 			 * codepoint if it is decoded straight from source text UTF-8.
87144 			 * There's no non-BMP support yet so this is handled simply by
87145 			 * matching the non-BMP character (which is custom behavior).
87146 			 */
87147 			duk_uint32_t ch;
87148 
87149 			new_atom_char_length = 1;
87150 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87151 			duk__append_reop(re_ctx, DUK_REOP_CHAR);
87152 			ch = re_ctx->curr_token.num;
87153 			if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
87154 				ch = (duk_uint32_t) duk_unicode_re_canonicalize_char(re_ctx->thr, (duk_codepoint_t) ch);
87155 			}
87156 			duk__append_u32(re_ctx, ch);
87157 			break;
87158 		}
87159 		case DUK_RETOK_ATOM_DIGIT:
87160 		case DUK_RETOK_ATOM_NOT_DIGIT:
87161 		case DUK_RETOK_ATOM_WHITE:
87162 		case DUK_RETOK_ATOM_NOT_WHITE:
87163 		case DUK_RETOK_ATOM_WORD_CHAR:
87164 		case DUK_RETOK_ATOM_NOT_WORD_CHAR: {
87165 			duk_small_uint_t re_op;
87166 			duk_small_uint_t idx;
87167 
87168 			new_atom_char_length = 1;
87169 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87170 
87171 			DUK_ASSERT((DUK_RETOK_ATOM_DIGIT & 0x01) != 0);
87172 			DUK_ASSERT((DUK_RETOK_ATOM_WHITE & 0x01) != 0);
87173 			DUK_ASSERT((DUK_RETOK_ATOM_WORD_CHAR & 0x01) != 0);
87174 			DUK_ASSERT((DUK_RETOK_ATOM_NOT_DIGIT & 0x01) == 0);
87175 			DUK_ASSERT((DUK_RETOK_ATOM_NOT_WHITE & 0x01) == 0);
87176 			DUK_ASSERT((DUK_RETOK_ATOM_NOT_WORD_CHAR & 0x01) == 0);
87177 			re_op = (re_ctx->curr_token.t & 0x01) ? DUK_REOP_RANGES : DUK_REOP_INVRANGES;
87178 
87179 			DUK_ASSERT(DUK_RETOK_ATOM_WHITE == DUK_RETOK_ATOM_DIGIT + 2);
87180 			DUK_ASSERT(DUK_RETOK_ATOM_WORD_CHAR == DUK_RETOK_ATOM_DIGIT + 4);
87181 			idx = (duk_small_uint_t) ((re_ctx->curr_token.t - DUK_RETOK_ATOM_DIGIT) >> 1U);
87182 			DUK_ASSERT(idx <= 2U);  /* Assume continuous token numbers; also checks negative underflow. */
87183 
87184 			duk__append_range_atom_matcher(re_ctx, re_op, duk__re_range_lookup1[idx], duk__re_range_lookup2[idx]);
87185 			break;
87186 		}
87187 		case DUK_RETOK_ATOM_BACKREFERENCE: {
87188 			duk_uint32_t backref = (duk_uint32_t) re_ctx->curr_token.num;
87189 			if (backref > re_ctx->highest_backref) {
87190 				re_ctx->highest_backref = backref;
87191 			}
87192 			new_atom_char_length = -1;   /* mark as complex */
87193 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87194 			duk__append_reop(re_ctx, DUK_REOP_BACKREFERENCE);
87195 			duk__append_u32(re_ctx, backref);
87196 			break;
87197 		}
87198 		case DUK_RETOK_ATOM_START_CAPTURE_GROUP: {
87199 			duk_uint32_t cap;
87200 
87201 			new_atom_char_length = -1;   /* mark as complex (capture handling) */
87202 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87203 			cap = ++re_ctx->captures;
87204 			duk__append_reop(re_ctx, DUK_REOP_SAVE);
87205 			duk__append_u32(re_ctx, cap * 2);
87206 			duk__parse_disjunction(re_ctx, 0, &tmp_disj);  /* retval (sub-atom char length) unused, tainted as complex above */
87207 			duk__append_reop(re_ctx, DUK_REOP_SAVE);
87208 			duk__append_u32(re_ctx, cap * 2 + 1);
87209 			break;
87210 		}
87211 		case DUK_RETOK_ATOM_START_NONCAPTURE_GROUP: {
87212 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87213 			duk__parse_disjunction(re_ctx, 0, &tmp_disj);
87214 			new_atom_char_length = tmp_disj.charlen;
87215 			break;
87216 		}
87217 		case DUK_RETOK_ATOM_START_CHARCLASS:
87218 		case DUK_RETOK_ATOM_START_CHARCLASS_INVERTED: {
87219 			/*
87220 			 *  Range parsing is done with a special lexer function which calls
87221 			 *  us for every range parsed.  This is different from how rest of
87222 			 *  the parsing works, but avoids a heavy, arbitrary size intermediate
87223 			 *  value type to hold the ranges.
87224 			 *
87225 			 *  Another complication is the handling of character ranges when
87226 			 *  case insensitive matching is used (see docs for discussion).
87227 			 *  The range handler callback given to the lexer takes care of this
87228 			 *  as well.
87229 			 *
87230 			 *  Note that duplicate ranges are not eliminated when parsing character
87231 			 *  classes, so that canonicalization of
87232 			 *
87233 			 *    [0-9a-fA-Fx-{]
87234 			 *
87235 			 *  creates the result (note the duplicate ranges):
87236 			 *
87237 			 *    [0-9A-FA-FX-Z{-{]
87238 			 *
87239 			 *  where [x-{] is split as a result of canonicalization.  The duplicate
87240 			 *  ranges are not a semantics issue: they work correctly.
87241 			 */
87242 
87243 			duk_uint32_t offset;
87244 
87245 			DUK_DD(DUK_DDPRINT("character class"));
87246 
87247 			/* insert ranges instruction, range count patched in later */
87248 			new_atom_char_length = 1;
87249 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87250 			duk__append_reop(re_ctx,
87251 			                 (re_ctx->curr_token.t == DUK_RETOK_ATOM_START_CHARCLASS) ?
87252 			                 DUK_REOP_RANGES : DUK_REOP_INVRANGES);
87253 			offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);    /* patch in range count later */
87254 
87255 			/* parse ranges until character class ends */
87256 			re_ctx->nranges = 0;    /* note: ctx-wide temporary */
87257 			duk_lexer_parse_re_ranges(&re_ctx->lex, duk__regexp_generate_ranges, (void *) re_ctx);
87258 
87259 			/* insert range count */
87260 			duk__insert_u32(re_ctx, offset, re_ctx->nranges);
87261 			break;
87262 		}
87263 		case DUK_RETOK_ATOM_END_GROUP: {
87264 			if (expect_eof) {
87265 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_CLOSING_PAREN);
87266 				DUK_WO_NORETURN(return;);
87267 			}
87268 			goto done;
87269 		}
87270 		case DUK_RETOK_EOF: {
87271 			if (!expect_eof) {
87272 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_END_OF_PATTERN);
87273 				DUK_WO_NORETURN(return;);
87274 			}
87275 			goto done;
87276 		}
87277 		default: {
87278 			DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_REGEXP_TOKEN);
87279 			DUK_WO_NORETURN(return;);
87280 		}
87281 		}
87282 
87283 		/* a complex (new) atom taints the result */
87284 		if (new_atom_start_offset >= 0) {
87285 			if (new_atom_char_length < 0) {
87286 				res_charlen = -1;
87287 			} else if (res_charlen >= 0) {
87288 				/* only advance if not tainted */
87289 				res_charlen += new_atom_char_length;
87290 			}
87291 		}
87292 
87293 		/* record previous atom info in case next token is a quantifier */
87294 		atom_start_offset = new_atom_start_offset;
87295 		atom_char_length = new_atom_char_length;
87296 		atom_start_captures = new_atom_start_captures;
87297 	}
87298 
87299  done:
87300 
87301 	/* finish up pending jump and split for last alternative */
87302 	if (unpatched_disjunction_jump >= 0) {
87303 		duk_uint32_t offset;
87304 
87305 		DUK_ASSERT(unpatched_disjunction_split >= 0);
87306 		offset = (duk_uint32_t) unpatched_disjunction_jump;
87307 		offset += duk__insert_jump_offset(re_ctx,
87308 		                                  offset,
87309 		                                  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
87310 		/* offset is now target of the pending split (right after jump) */
87311 		duk__insert_jump_offset(re_ctx,
87312 		                        (duk_uint32_t) unpatched_disjunction_split,
87313 		                        (duk_int32_t) offset - unpatched_disjunction_split);
87314 	}
87315 
87316 #if 0
87317 	out_atom_info->end_captures = re_ctx->captures;
87318 #endif
87319 	out_atom_info->charlen = res_charlen;
87320 	DUK_DDD(DUK_DDDPRINT("parse disjunction finished: charlen=%ld",
87321 	                     (long) out_atom_info->charlen));
87322 
87323 	re_ctx->recursion_depth--;
87324 }
87325 
87326 /*
87327  *  Flags parsing (see E5 Section 15.10.4.1).
87328  */
87329 
87330 DUK_LOCAL duk_uint32_t duk__parse_regexp_flags(duk_hthread *thr, duk_hstring *h) {
87331 	const duk_uint8_t *p;
87332 	const duk_uint8_t *p_end;
87333 	duk_uint32_t flags = 0;
87334 
87335 	p = DUK_HSTRING_GET_DATA(h);
87336 	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
87337 
87338 	/* Note: can be safely scanned as bytes (undecoded) */
87339 
87340 	while (p < p_end) {
87341 		duk_uint8_t c = *p++;
87342 		switch (c) {
87343 		case (duk_uint8_t) 'g': {
87344 			if (flags & DUK_RE_FLAG_GLOBAL) {
87345 				goto flags_error;
87346 			}
87347 			flags |= DUK_RE_FLAG_GLOBAL;
87348 			break;
87349 		}
87350 		case (duk_uint8_t) 'i': {
87351 			if (flags & DUK_RE_FLAG_IGNORE_CASE) {
87352 				goto flags_error;
87353 			}
87354 			flags |= DUK_RE_FLAG_IGNORE_CASE;
87355 			break;
87356 		}
87357 		case (duk_uint8_t) 'm': {
87358 			if (flags & DUK_RE_FLAG_MULTILINE) {
87359 				goto flags_error;
87360 			}
87361 			flags |= DUK_RE_FLAG_MULTILINE;
87362 			break;
87363 		}
87364 		default: {
87365 			goto flags_error;
87366 		}
87367 		}
87368 	}
87369 
87370 	return flags;
87371 
87372  flags_error:
87373 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_REGEXP_FLAGS);
87374 	DUK_WO_NORETURN(return 0U;);
87375 }
87376 
87377 /*
87378  *  Create escaped RegExp source (E5 Section 15.10.3).
87379  *
87380  *  The current approach is to special case the empty RegExp
87381  *  ('' -> '(?:)') and otherwise replace unescaped '/' characters
87382  *  with '\/' regardless of where they occur in the regexp.
87383  *
87384  *  Note that normalization does not seem to be necessary for
87385  *  RegExp literals (e.g. '/foo/') because to be acceptable as
87386  *  a RegExp literal, the text between forward slashes must
87387  *  already match the escaping requirements (e.g. must not contain
87388  *  unescaped forward slashes or be empty).  Escaping IS needed
87389  *  for expressions like 'new Regexp("...", "")' however.
87390  *  Currently, we re-escape in either case.
87391  *
87392  *  Also note that we process the source here in UTF-8 encoded
87393  *  form.  This is correct, because any non-ASCII characters are
87394  *  passed through without change.
87395  */
87396 
87397 DUK_LOCAL void duk__create_escaped_source(duk_hthread *thr, int idx_pattern) {
87398 	duk_hstring *h;
87399 	const duk_uint8_t *p;
87400 	duk_bufwriter_ctx bw_alloc;
87401 	duk_bufwriter_ctx *bw;
87402 	duk_uint8_t *q;
87403 	duk_size_t i, n;
87404 	duk_uint_fast8_t c_prev, c;
87405 
87406 	h = duk_known_hstring(thr, idx_pattern);
87407 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
87408 	n = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
87409 
87410 	if (n == 0) {
87411 		duk_push_literal(thr, "(?:)");
87412 		return;
87413 	}
87414 
87415 	bw = &bw_alloc;
87416 	DUK_BW_INIT_PUSHBUF(thr, bw, n);
87417 	q = DUK_BW_GET_PTR(thr, bw);
87418 
87419 	c_prev = (duk_uint_fast8_t) 0;
87420 
87421 	for (i = 0; i < n; i++) {
87422 		c = p[i];
87423 
87424 		q = DUK_BW_ENSURE_RAW(thr, bw, 2, q);
87425 
87426 		if (c == (duk_uint_fast8_t) '/' && c_prev != (duk_uint_fast8_t) '\\') {
87427 			/* Unescaped '/' ANYWHERE in the regexp (in disjunction,
87428 			 * inside a character class, ...) => same escape works.
87429 			 */
87430 			*q++ = DUK_ASC_BACKSLASH;
87431 		}
87432 		*q++ = (duk_uint8_t) c;
87433 
87434 		c_prev = c;
87435 	}
87436 
87437 	DUK_BW_SETPTR_AND_COMPACT(thr, bw, q);
87438 	(void) duk_buffer_to_string(thr, -1);  /* Safe if input is safe. */
87439 
87440 	/* [ ... escaped_source ] */
87441 }
87442 
87443 /*
87444  *  Exposed regexp compilation primitive.
87445  *
87446  *  Sets up a regexp compilation context, and calls duk__parse_disjunction() to do the
87447  *  actual parsing.  Handles generation of the compiled regexp header and the
87448  *  "boilerplate" capture of the matching substring (save 0 and 1).  Also does some
87449  *  global level regexp checks after recursive compilation has finished.
87450  *
87451  *  An escaped version of the regexp source, suitable for use as a RegExp instance
87452  *  'source' property (see E5 Section 15.10.3), is also left on the stack.
87453  *
87454  *  Input stack:  [ pattern flags ]
87455  *  Output stack: [ bytecode escaped_source ]  (both as strings)
87456  */
87457 
87458 DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) {
87459 	duk_re_compiler_ctx re_ctx;
87460 	duk_lexer_point lex_point;
87461 	duk_hstring *h_pattern;
87462 	duk_hstring *h_flags;
87463 	duk__re_disjunction_info ign_disj;
87464 
87465 	DUK_ASSERT(thr != NULL);
87466 
87467 	/*
87468 	 *  Args validation
87469 	 */
87470 
87471 	/* TypeError if fails */
87472 	h_pattern = duk_require_hstring_notsymbol(thr, -2);
87473 	h_flags = duk_require_hstring_notsymbol(thr, -1);
87474 
87475 	/*
87476 	 *  Create normalized 'source' property (E5 Section 15.10.3).
87477 	 */
87478 
87479 	/* [ ... pattern flags ] */
87480 
87481 	duk__create_escaped_source(thr, -2);
87482 
87483 	/* [ ... pattern flags escaped_source ] */
87484 
87485 	/*
87486 	 *  Init compilation context
87487 	 */
87488 
87489 	/* [ ... pattern flags escaped_source buffer ] */
87490 
87491 	duk_memzero(&re_ctx, sizeof(re_ctx));
87492 	DUK_LEXER_INITCTX(&re_ctx.lex);  /* duplicate zeroing, expect for (possible) NULL inits */
87493 	re_ctx.thr = thr;
87494 	re_ctx.lex.thr = thr;
87495 	re_ctx.lex.input = DUK_HSTRING_GET_DATA(h_pattern);
87496 	re_ctx.lex.input_length = DUK_HSTRING_GET_BYTELEN(h_pattern);
87497 	re_ctx.lex.token_limit = DUK_RE_COMPILE_TOKEN_LIMIT;
87498 	re_ctx.recursion_limit = DUK_USE_REGEXP_COMPILER_RECLIMIT;
87499 	re_ctx.re_flags = duk__parse_regexp_flags(thr, h_flags);
87500 
87501 	DUK_BW_INIT_PUSHBUF(thr, &re_ctx.bw, DUK__RE_INITIAL_BUFSIZE);
87502 
87503 	DUK_DD(DUK_DDPRINT("regexp compiler ctx initialized, flags=0x%08lx, recursion_limit=%ld",
87504 	                   (unsigned long) re_ctx.re_flags, (long) re_ctx.recursion_limit));
87505 
87506 	/*
87507 	 *  Init lexer
87508 	 */
87509 
87510 	lex_point.offset = 0;  /* expensive init, just want to fill window */
87511 	lex_point.line = 1;
87512 	DUK_LEXER_SETPOINT(&re_ctx.lex, &lex_point);
87513 
87514 	/*
87515 	 *  Compilation
87516 	 */
87517 
87518 	DUK_DD(DUK_DDPRINT("starting regexp compilation"));
87519 
87520 	duk__append_reop(&re_ctx, DUK_REOP_SAVE);
87521 	duk__append_7bit(&re_ctx, 0);
87522 	duk__parse_disjunction(&re_ctx, 1 /*expect_eof*/, &ign_disj);
87523 	duk__append_reop(&re_ctx, DUK_REOP_SAVE);
87524 	duk__append_7bit(&re_ctx, 1);
87525 	duk__append_reop(&re_ctx, DUK_REOP_MATCH);
87526 
87527 	/*
87528 	 *  Check for invalid backreferences; note that it is NOT an error
87529 	 *  to back-reference a capture group which has not yet been introduced
87530 	 *  in the pattern (as in /\1(foo)/); in fact, the backreference will
87531 	 *  always match!  It IS an error to back-reference a capture group
87532 	 *  which will never be introduced in the pattern.  Thus, we can check
87533 	 *  for such references only after parsing is complete.
87534 	 */
87535 
87536 	if (re_ctx.highest_backref > re_ctx.captures) {
87537 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BACKREFS);
87538 		DUK_WO_NORETURN(return;);
87539 	}
87540 
87541 	/*
87542 	 *  Emit compiled regexp header: flags, ncaptures
87543 	 *  (insertion order inverted on purpose)
87544 	 */
87545 
87546 	duk__insert_u32(&re_ctx, 0, (re_ctx.captures + 1) * 2);
87547 	duk__insert_u32(&re_ctx, 0, re_ctx.re_flags);
87548 
87549 	/* [ ... pattern flags escaped_source buffer ] */
87550 
87551 	DUK_BW_COMPACT(thr, &re_ctx.bw);
87552 	(void) duk_buffer_to_string(thr, -1);  /* Safe because flags is at most 7 bit. */
87553 
87554 	/* [ ... pattern flags escaped_source bytecode ] */
87555 
87556 	/*
87557 	 *  Finalize stack
87558 	 */
87559 
87560 	duk_remove(thr, -4);     /* -> [ ... flags escaped_source bytecode ] */
87561 	duk_remove(thr, -3);     /* -> [ ... escaped_source bytecode ] */
87562 
87563 	DUK_DD(DUK_DDPRINT("regexp compilation successful, bytecode: %!T, escaped source: %!T",
87564 	                   (duk_tval *) duk_get_tval(thr, -1), (duk_tval *) duk_get_tval(thr, -2)));
87565 }
87566 
87567 /*
87568  *  Create a RegExp instance (E5 Section 15.10.7).
87569  *
87570  *  Note: the output stack left by duk_regexp_compile() is directly compatible
87571  *  with the input here.
87572  *
87573  *  Input stack:  [ escaped_source bytecode ]  (both as strings)
87574  *  Output stack: [ RegExp ]
87575  */
87576 
87577 DUK_INTERNAL void duk_regexp_create_instance(duk_hthread *thr) {
87578 	duk_hobject *h;
87579 
87580 	/* [ ... escaped_source bytecode ] */
87581 
87582 	duk_push_object(thr);
87583 	h = duk_known_hobject(thr, -1);
87584 	duk_insert(thr, -3);
87585 
87586 	/* [ ... regexp_object escaped_source bytecode ] */
87587 
87588 	DUK_HOBJECT_SET_CLASS_NUMBER(h, DUK_HOBJECT_CLASS_REGEXP);
87589 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]);
87590 
87591 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_BYTECODE, DUK_PROPDESC_FLAGS_NONE);
87592 
87593 	/* [ ... regexp_object escaped_source ] */
87594 
87595 	/* In ES2015 .source, and the .global, .multiline, etc flags are
87596 	 * inherited getters.  Store the escaped source as an internal
87597 	 * property for the getter.
87598 	 */
87599 
87600 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE);
87601 
87602 	/* [ ... regexp_object ] */
87603 
87604 	duk_push_int(thr, 0);
87605 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LAST_INDEX, DUK_PROPDESC_FLAGS_W);
87606 
87607 	/* [ ... regexp_object ] */
87608 }
87609 
87610 #else  /* DUK_USE_REGEXP_SUPPORT */
87611 
87612 /* regexp support disabled */
87613 
87614 #endif  /* DUK_USE_REGEXP_SUPPORT */
87615 
87616 /* automatic undefs */
87617 #undef DUK__RE_BUFLEN
87618 #undef DUK__RE_INITIAL_BUFSIZE
87619 #line 1 "duk_regexp_executor.c"
87620 /*
87621  *  Regexp executor.
87622  *
87623  *  Safety: the ECMAScript executor should prevent user from reading and
87624  *  replacing regexp bytecode.  Even so, the executor must validate all
87625  *  memory accesses etc.  When an invalid access is detected (e.g. a 'save'
87626  *  opcode to invalid, unallocated index) it should fail with an internal
87627  *  error but not cause a segmentation fault.
87628  *
87629  *  Notes:
87630  *
87631  *    - Backtrack counts are limited to unsigned 32 bits but should
87632  *      technically be duk_size_t for strings longer than 4G chars.
87633  *      This also requires a regexp bytecode change.
87634  */
87635 
87636 /* #include duk_internal.h -> already included */
87637 
87638 #if defined(DUK_USE_REGEXP_SUPPORT)
87639 
87640 /*
87641  *  Helpers for UTF-8 handling
87642  *
87643  *  For bytecode readers the duk_uint32_t and duk_int32_t types are correct
87644  *  because they're used for more than just codepoints.
87645  */
87646 
87647 DUK_LOCAL duk_uint32_t duk__bc_get_u32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
87648 	return (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
87649 }
87650 
87651 DUK_LOCAL duk_int32_t duk__bc_get_i32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
87652 	duk_uint32_t t;
87653 
87654 	/* signed integer encoding needed to work with UTF-8 */
87655 	t = (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
87656 	if (t & 1) {
87657 		return -((duk_int32_t) (t >> 1));
87658 	} else {
87659 		return (duk_int32_t) (t >> 1);
87660 	}
87661 }
87662 
87663 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) {
87664 	const duk_uint8_t *p;
87665 
87666 	/* Note: allow backtracking from p == ptr_end */
87667 	p = *ptr;
87668 	if (p < ptr_start || p > ptr_end) {
87669 		goto fail;
87670 	}
87671 
87672 	while (count > 0) {
87673 		for (;;) {
87674 			p--;
87675 			if (p < ptr_start) {
87676 				goto fail;
87677 			}
87678 			if ((*p & 0xc0) != 0x80) {
87679 				/* utf-8 continuation bytes have the form 10xx xxxx */
87680 				break;
87681 			}
87682 		}
87683 		count--;
87684 	}
87685 	*ptr = p;
87686 	return p;
87687 
87688  fail:
87689 	DUK_ERROR_INTERNAL(thr);
87690 	DUK_WO_NORETURN(return NULL;);
87691 }
87692 
87693 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) {
87694 	const duk_uint8_t *p;
87695 
87696 	p = *ptr;
87697 	if (p < ptr_start || p >= ptr_end) {
87698 		goto fail;
87699 	}
87700 
87701 	while (count > 0) {
87702 		for (;;) {
87703 			p++;
87704 
87705 			/* Note: if encoding ends by hitting end of input, we don't check that
87706 			 * the encoding is valid, we just assume it is.
87707 			 */
87708 			if (p >= ptr_end || ((*p & 0xc0) != 0x80)) {
87709 				/* utf-8 continuation bytes have the form 10xx xxxx */
87710 				break;
87711 			}
87712 		}
87713 		count--;
87714 	}
87715 
87716 	*ptr = p;
87717 	return p;
87718 
87719  fail:
87720 	DUK_ERROR_INTERNAL(thr);
87721 	DUK_WO_NORETURN(return NULL;);
87722 }
87723 
87724 /*
87725  *  Helpers for dealing with the input string
87726  */
87727 
87728 /* Get a (possibly canonicalized) input character from current sp.  The input
87729  * itself is never modified, and captures always record non-canonicalized
87730  * characters even in case-insensitive matching.  Return <0 if out of input.
87731  */
87732 DUK_LOCAL duk_codepoint_t duk__inp_get_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp) {
87733 	duk_codepoint_t res;
87734 
87735 	if (*sp >= re_ctx->input_end) {
87736 		return -1;
87737 	}
87738 	res = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end);
87739 	if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
87740 		res = duk_unicode_re_canonicalize_char(re_ctx->thr, res);
87741 	}
87742 	return res;
87743 }
87744 
87745 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) {
87746 	return duk__utf8_backtrack(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end, count);
87747 }
87748 
87749 /* Backtrack utf-8 input and return a (possibly canonicalized) input character. */
87750 DUK_LOCAL duk_codepoint_t duk__inp_get_prev_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *sp) {
87751 	/* note: caller 'sp' is intentionally not updated here */
87752 	(void) duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) 1);
87753 	return duk__inp_get_cp(re_ctx, &sp);
87754 }
87755 
87756 /*
87757  *  Regexp recursive matching function.
87758  *
87759  *  Returns 'sp' on successful match (points to character after last matched one),
87760  *  NULL otherwise.
87761  *
87762  *  The C recursion depth limit check is only performed in this function, this
87763  *  suffices because the function is present in all true recursion required by
87764  *  regexp execution.
87765  */
87766 
87767 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) {
87768 	if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
87769 		DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT);
87770 		DUK_WO_NORETURN(return NULL;);
87771 	}
87772 	re_ctx->recursion_depth++;
87773 
87774 	for (;;) {
87775 		duk_small_int_t op;
87776 
87777 		if (re_ctx->steps_count >= re_ctx->steps_limit) {
87778 			DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT);
87779 			DUK_WO_NORETURN(return NULL;);
87780 		}
87781 		re_ctx->steps_count++;
87782 
87783 		/* Opcodes are at most 7 bits now so they encode to one byte.  If this
87784 		 * were not the case or 'pc' is invalid here (due to a bug etc) we'll
87785 		 * still fail safely through the switch default case.
87786 		 */
87787 		DUK_ASSERT(pc[0] <= 0x7fU);
87788 #if 0
87789 		op = (duk_small_int_t) duk__bc_get_u32(re_ctx, &pc);
87790 #endif
87791 		op = *pc++;
87792 
87793 		DUK_DDD(DUK_DDDPRINT("match: rec=%ld, steps=%ld, pc (after op)=%ld, sp=%ld, op=%ld",
87794 		                     (long) re_ctx->recursion_depth,
87795 		                     (long) re_ctx->steps_count,
87796 		                     (long) (pc - re_ctx->bytecode),
87797 		                     (long) (sp - re_ctx->input),
87798 		                     (long) op));
87799 
87800 		switch (op) {
87801 		case DUK_REOP_MATCH: {
87802 			goto match;
87803 		}
87804 		case DUK_REOP_CHAR: {
87805 			/*
87806 			 *  Byte-based matching would be possible for case-sensitive
87807 			 *  matching but not for case-insensitive matching.  So, we
87808 			 *  match by decoding the input and bytecode character normally.
87809 			 *
87810 			 *  Bytecode characters are assumed to be already canonicalized.
87811 			 *  Input characters are canonicalized automatically by
87812 			 *  duk__inp_get_cp() if necessary.
87813 			 *
87814 			 *  There is no opcode for matching multiple characters.  The
87815 			 *  regexp compiler has trouble joining strings efficiently
87816 			 *  during compilation.  See doc/regexp.rst for more discussion.
87817 			 */
87818 			duk_codepoint_t c1, c2;
87819 
87820 			c1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
87821 			DUK_ASSERT(!(re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) ||
87822 			           c1 == duk_unicode_re_canonicalize_char(re_ctx->thr, c1));  /* canonicalized by compiler */
87823 			c2 = duk__inp_get_cp(re_ctx, &sp);
87824 			/* No need to check for c2 < 0 (end of input): because c1 >= 0, it
87825 			 * will fail the match below automatically and cause goto fail.
87826 			 */
87827 #if 0
87828 			if (c2 < 0) {
87829 				goto fail;
87830 			}
87831 #endif
87832 			DUK_ASSERT(c1 >= 0);
87833 
87834 			DUK_DDD(DUK_DDDPRINT("char match, c1=%ld, c2=%ld", (long) c1, (long) c2));
87835 			if (c1 != c2) {
87836 				goto fail;
87837 			}
87838 			break;
87839 		}
87840 		case DUK_REOP_PERIOD: {
87841 			duk_codepoint_t c;
87842 
87843 			c = duk__inp_get_cp(re_ctx, &sp);
87844 			if (c < 0 || duk_unicode_is_line_terminator(c)) {
87845 				/* E5 Sections 15.10.2.8, 7.3 */
87846 				goto fail;
87847 			}
87848 			break;
87849 		}
87850 		case DUK_REOP_RANGES:
87851 		case DUK_REOP_INVRANGES: {
87852 			duk_uint32_t n;
87853 			duk_codepoint_t c;
87854 			duk_small_int_t match;
87855 
87856 			n = duk__bc_get_u32(re_ctx, &pc);
87857 			c = duk__inp_get_cp(re_ctx, &sp);
87858 			if (c < 0) {
87859 				goto fail;
87860 			}
87861 
87862 			match = 0;
87863 			while (n) {
87864 				duk_codepoint_t r1, r2;
87865 				r1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
87866 				r2 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
87867 				DUK_DDD(DUK_DDDPRINT("matching ranges/invranges, n=%ld, r1=%ld, r2=%ld, c=%ld",
87868 				                     (long) n, (long) r1, (long) r2, (long) c));
87869 				if (c >= r1 && c <= r2) {
87870 					/* Note: don't bail out early, we must read all the ranges from
87871 					 * bytecode.  Another option is to skip them efficiently after
87872 					 * breaking out of here.  Prefer smallest code.
87873 					 */
87874 					match = 1;
87875 				}
87876 				n--;
87877 			}
87878 
87879 			if (op == DUK_REOP_RANGES) {
87880 				if (!match) {
87881 					goto fail;
87882 				}
87883 			} else {
87884 				DUK_ASSERT(op == DUK_REOP_INVRANGES);
87885 				if (match) {
87886 					goto fail;
87887 				}
87888 			}
87889 			break;
87890 		}
87891 		case DUK_REOP_ASSERT_START: {
87892 			duk_codepoint_t c;
87893 
87894 			if (sp <= re_ctx->input) {
87895 				break;
87896 			}
87897 			if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
87898 				goto fail;
87899 			}
87900 			c = duk__inp_get_prev_cp(re_ctx, sp);
87901 			if (duk_unicode_is_line_terminator(c)) {
87902 				/* E5 Sections 15.10.2.8, 7.3 */
87903 				break;
87904 			}
87905 			goto fail;
87906 		}
87907 		case DUK_REOP_ASSERT_END: {
87908 			duk_codepoint_t c;
87909 			const duk_uint8_t *tmp_sp;
87910 
87911 			tmp_sp = sp;
87912 			c = duk__inp_get_cp(re_ctx, &tmp_sp);
87913 			if (c < 0) {
87914 				break;
87915 			}
87916 			if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
87917 				goto fail;
87918 			}
87919 			if (duk_unicode_is_line_terminator(c)) {
87920 				/* E5 Sections 15.10.2.8, 7.3 */
87921 				break;
87922 			}
87923 			goto fail;
87924 		}
87925 		case DUK_REOP_ASSERT_WORD_BOUNDARY:
87926 		case DUK_REOP_ASSERT_NOT_WORD_BOUNDARY: {
87927 			/*
87928 			 *  E5 Section 15.10.2.6.  The previous and current character
87929 			 *  should -not- be canonicalized as they are now.  However,
87930 			 *  canonicalization does not affect the result of IsWordChar()
87931 			 *  (which depends on Unicode characters never canonicalizing
87932 			 *  into ASCII characters) so this does not matter.
87933 			 */
87934 			duk_small_int_t w1, w2;
87935 
87936 			if (sp <= re_ctx->input) {
87937 				w1 = 0;  /* not a wordchar */
87938 			} else {
87939 				duk_codepoint_t c;
87940 				c = duk__inp_get_prev_cp(re_ctx, sp);
87941 				w1 = duk_unicode_re_is_wordchar(c);
87942 			}
87943 			if (sp >= re_ctx->input_end) {
87944 				w2 = 0;  /* not a wordchar */
87945 			} else {
87946 				const duk_uint8_t *tmp_sp = sp;  /* dummy so sp won't get updated */
87947 				duk_codepoint_t c;
87948 				c = duk__inp_get_cp(re_ctx, &tmp_sp);
87949 				w2 = duk_unicode_re_is_wordchar(c);
87950 			}
87951 
87952 			if (op == DUK_REOP_ASSERT_WORD_BOUNDARY) {
87953 				if (w1 == w2) {
87954 					goto fail;
87955 				}
87956 			} else {
87957 				DUK_ASSERT(op == DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);
87958 				if (w1 != w2) {
87959 					goto fail;
87960 				}
87961 			}
87962 			break;
87963 		}
87964 		case DUK_REOP_JUMP: {
87965 			duk_int32_t skip;
87966 
87967 			skip = duk__bc_get_i32(re_ctx, &pc);
87968 			pc += skip;
87969 			break;
87970 		}
87971 		case DUK_REOP_SPLIT1: {
87972 			/* split1: prefer direct execution (no jump) */
87973 			const duk_uint8_t *sub_sp;
87974 			duk_int32_t skip;
87975 
87976 			skip = duk__bc_get_i32(re_ctx, &pc);
87977 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
87978 			if (sub_sp) {
87979 				sp = sub_sp;
87980 				goto match;
87981 			}
87982 			pc += skip;
87983 			break;
87984 		}
87985 		case DUK_REOP_SPLIT2: {
87986 			/* split2: prefer jump execution (not direct) */
87987 			const duk_uint8_t *sub_sp;
87988 			duk_int32_t skip;
87989 
87990 			skip = duk__bc_get_i32(re_ctx, &pc);
87991 			sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
87992 			if (sub_sp) {
87993 				sp = sub_sp;
87994 				goto match;
87995 			}
87996 			break;
87997 		}
87998 		case DUK_REOP_SQMINIMAL: {
87999 			duk_uint32_t q, qmin, qmax;
88000 			duk_int32_t skip;
88001 			const duk_uint8_t *sub_sp;
88002 
88003 			qmin = duk__bc_get_u32(re_ctx, &pc);
88004 			qmax = duk__bc_get_u32(re_ctx, &pc);
88005 			skip = duk__bc_get_i32(re_ctx, &pc);
88006 			DUK_DDD(DUK_DDDPRINT("minimal quantifier, qmin=%lu, qmax=%lu, skip=%ld",
88007 			                     (unsigned long) qmin, (unsigned long) qmax, (long) skip));
88008 
88009 			q = 0;
88010 			while (q <= qmax) {
88011 				if (q >= qmin) {
88012 					sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
88013 					if (sub_sp) {
88014 						sp = sub_sp;
88015 						goto match;
88016 					}
88017 				}
88018 				sub_sp = duk__match_regexp(re_ctx, pc, sp);
88019 				if (!sub_sp) {
88020 					break;
88021 				}
88022 				sp = sub_sp;
88023 				q++;
88024 			}
88025 			goto fail;
88026 		}
88027 		case DUK_REOP_SQGREEDY: {
88028 			duk_uint32_t q, qmin, qmax, atomlen;
88029 			duk_int32_t skip;
88030 			const duk_uint8_t *sub_sp;
88031 
88032 			qmin = duk__bc_get_u32(re_ctx, &pc);
88033 			qmax = duk__bc_get_u32(re_ctx, &pc);
88034 			atomlen = duk__bc_get_u32(re_ctx, &pc);
88035 			skip = duk__bc_get_i32(re_ctx, &pc);
88036 			DUK_DDD(DUK_DDDPRINT("greedy quantifier, qmin=%lu, qmax=%lu, atomlen=%lu, skip=%ld",
88037 			                     (unsigned long) qmin, (unsigned long) qmax, (unsigned long) atomlen, (long) skip));
88038 
88039 			q = 0;
88040 			while (q < qmax) {
88041 				sub_sp = duk__match_regexp(re_ctx, pc, sp);
88042 				if (!sub_sp) {
88043 					break;
88044 				}
88045 				sp = sub_sp;
88046 				q++;
88047 			}
88048 			while (q >= qmin) {
88049 				sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
88050 				if (sub_sp) {
88051 					sp = sub_sp;
88052 					goto match;
88053 				}
88054 				if (q == qmin) {
88055 					break;
88056 				}
88057 
88058 				/* Note: if atom were to contain e.g. captures, we would need to
88059 				 * re-match the atom to get correct captures.  Simply quantifiers
88060 				 * do not allow captures in their atom now, so this is not an issue.
88061 				 */
88062 
88063 				DUK_DDD(DUK_DDDPRINT("greedy quantifier, backtrack %ld characters (atomlen)",
88064 				                     (long) atomlen));
88065 				sp = duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) atomlen);
88066 				q--;
88067 			}
88068 			goto fail;
88069 		}
88070 		case DUK_REOP_SAVE: {
88071 			duk_uint32_t idx;
88072 			const duk_uint8_t *old;
88073 			const duk_uint8_t *sub_sp;
88074 
88075 			idx = duk__bc_get_u32(re_ctx, &pc);
88076 			if (idx >= re_ctx->nsaved) {
88077 				/* idx is unsigned, < 0 check is not necessary */
88078 				DUK_D(DUK_DPRINT("internal error, regexp save index insane: idx=%ld", (long) idx));
88079 				goto internal_error;
88080 			}
88081 			old = re_ctx->saved[idx];
88082 			re_ctx->saved[idx] = sp;
88083 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
88084 			if (sub_sp) {
88085 				sp = sub_sp;
88086 				goto match;
88087 			}
88088 			re_ctx->saved[idx] = old;
88089 			goto fail;
88090 		}
88091 		case DUK_REOP_WIPERANGE: {
88092 			/* Wipe capture range and save old values for backtracking.
88093 			 *
88094 			 * XXX: this typically happens with a relatively small idx_count.
88095 			 * It might be useful to handle cases where the count is small
88096 			 * (say <= 8) by saving the values in stack instead.  This would
88097 			 * reduce memory churn and improve performance, at the cost of a
88098 			 * slightly higher code footprint.
88099 			 */
88100 			duk_uint32_t idx_start, idx_count;
88101 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
88102 			duk_uint32_t idx_end, idx;
88103 #endif
88104 			duk_uint8_t **range_save;
88105 			const duk_uint8_t *sub_sp;
88106 
88107 			idx_start = duk__bc_get_u32(re_ctx, &pc);
88108 			idx_count = duk__bc_get_u32(re_ctx, &pc);
88109 			DUK_DDD(DUK_DDDPRINT("wipe saved range: start=%ld, count=%ld -> [%ld,%ld] (captures [%ld,%ld])",
88110 			                     (long) idx_start, (long) idx_count,
88111 			                     (long) idx_start, (long) (idx_start + idx_count - 1),
88112 			                     (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
88113 			if (idx_start + idx_count > re_ctx->nsaved || idx_count == 0) {
88114 				/* idx is unsigned, < 0 check is not necessary */
88115 				DUK_D(DUK_DPRINT("internal error, regexp wipe indices insane: idx_start=%ld, idx_count=%ld",
88116 				                 (long) idx_start, (long) idx_count));
88117 				goto internal_error;
88118 			}
88119 			DUK_ASSERT(idx_count > 0);
88120 
88121 			duk_require_stack(re_ctx->thr, 1);
88122 			range_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr,
88123 			                                                           sizeof(duk_uint8_t *) * idx_count);
88124 			DUK_ASSERT(range_save != NULL);
88125 			duk_memcpy(range_save, re_ctx->saved + idx_start, sizeof(duk_uint8_t *) * idx_count);
88126 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
88127 			idx_end = idx_start + idx_count;
88128 			for (idx = idx_start; idx < idx_end; idx++) {
88129 				re_ctx->saved[idx] = NULL;
88130 			}
88131 #else
88132 			duk_memzero((void *) (re_ctx->saved + idx_start), sizeof(duk_uint8_t *) * idx_count);
88133 #endif
88134 
88135 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
88136 			if (sub_sp) {
88137 				/* match: keep wiped/resaved values */
88138 				DUK_DDD(DUK_DDDPRINT("match: keep wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
88139 				                     (long) idx_start, (long) (idx_start + idx_count - 1),
88140 			                             (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
88141 				duk_pop_unsafe(re_ctx->thr);
88142 				sp = sub_sp;
88143 				goto match;
88144 			}
88145 
88146 			/* fail: restore saves */
88147 			DUK_DDD(DUK_DDDPRINT("fail: restore wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
88148 			                     (long) idx_start, (long) (idx_start + idx_count - 1),
88149 			                     (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
88150 			duk_memcpy((void *) (re_ctx->saved + idx_start),
88151 			           (const void *) range_save,
88152 			           sizeof(duk_uint8_t *) * idx_count);
88153 			duk_pop_unsafe(re_ctx->thr);
88154 			goto fail;
88155 		}
88156 		case DUK_REOP_LOOKPOS:
88157 		case DUK_REOP_LOOKNEG: {
88158 			/*
88159 			 *  Needs a save of multiple saved[] entries depending on what range
88160 			 *  may be overwritten.  Because the regexp parser does no such analysis,
88161 			 *  we currently save the entire saved array here.  Lookaheads are thus
88162 			 *  a bit expensive.  Note that the saved array is not needed for just
88163 			 *  the lookahead sub-match, but for the matching of the entire sequel.
88164 			 *
88165 			 *  The temporary save buffer is pushed on to the valstack to handle
88166 			 *  errors correctly.  Each lookahead causes a C recursion and pushes
88167 			 *  more stuff on the value stack.  If the C recursion limit is less
88168 			 *  than the value stack slack, there is no need to check the stack.
88169 			 *  We do so regardless, just in case.
88170 			 */
88171 
88172 			duk_int32_t skip;
88173 			duk_uint8_t **full_save;
88174 			const duk_uint8_t *sub_sp;
88175 
88176 			DUK_ASSERT(re_ctx->nsaved > 0);
88177 
88178 			duk_require_stack(re_ctx->thr, 1);
88179 			full_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr,
88180 			                                                          sizeof(duk_uint8_t *) * re_ctx->nsaved);
88181 			DUK_ASSERT(full_save != NULL);
88182 			duk_memcpy(full_save, re_ctx->saved, sizeof(duk_uint8_t *) * re_ctx->nsaved);
88183 
88184 			skip = duk__bc_get_i32(re_ctx, &pc);
88185 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
88186 			if (op == DUK_REOP_LOOKPOS) {
88187 				if (!sub_sp) {
88188 					goto lookahead_fail;
88189 				}
88190 			} else {
88191 				if (sub_sp) {
88192 					goto lookahead_fail;
88193 				}
88194 			}
88195 			sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
88196 			if (sub_sp) {
88197 				/* match: keep saves */
88198 				duk_pop_unsafe(re_ctx->thr);
88199 				sp = sub_sp;
88200 				goto match;
88201 			}
88202 
88203 			/* fall through */
88204 
88205 		 lookahead_fail:
88206 			/* fail: restore saves */
88207 			duk_memcpy((void *) re_ctx->saved,
88208 			           (const void *) full_save,
88209 			           sizeof(duk_uint8_t *) * re_ctx->nsaved);
88210 			duk_pop_unsafe(re_ctx->thr);
88211 			goto fail;
88212 		}
88213 		case DUK_REOP_BACKREFERENCE: {
88214 			/*
88215 			 *  Byte matching for back-references would be OK in case-
88216 			 *  sensitive matching.  In case-insensitive matching we need
88217 			 *  to canonicalize characters, so back-reference matching needs
88218 			 *  to be done with codepoints instead.  So, we just decode
88219 			 *  everything normally here, too.
88220 			 *
88221 			 *  Note: back-reference index which is 0 or higher than
88222 			 *  NCapturingParens (= number of capturing parens in the
88223 			 *  -entire- regexp) is a compile time error.  However, a
88224 			 *  backreference referring to a valid capture which has
88225 			 *  not matched anything always succeeds!  See E5 Section
88226 			 *  15.10.2.9, step 5, sub-step 3.
88227 			 */
88228 			duk_uint32_t idx;
88229 			const duk_uint8_t *p;
88230 
88231 			idx = duk__bc_get_u32(re_ctx, &pc);
88232 			idx = idx << 1;  /* backref n -> saved indices [n*2, n*2+1] */
88233 			if (idx < 2 || idx + 1 >= re_ctx->nsaved) {
88234 				/* regexp compiler should catch these */
88235 				DUK_D(DUK_DPRINT("internal error, backreference index insane"));
88236 				goto internal_error;
88237 			}
88238 			if (!re_ctx->saved[idx] || !re_ctx->saved[idx+1]) {
88239 				/* capture is 'undefined', always matches! */
88240 				DUK_DDD(DUK_DDDPRINT("backreference: saved[%ld,%ld] not complete, always match",
88241 				                     (long) idx, (long) (idx + 1)));
88242 				break;
88243 			}
88244 			DUK_DDD(DUK_DDDPRINT("backreference: match saved[%ld,%ld]", (long) idx, (long) (idx + 1)));
88245 
88246 			p = re_ctx->saved[idx];
88247 			while (p < re_ctx->saved[idx+1]) {
88248 				duk_codepoint_t c1, c2;
88249 
88250 				/* Note: not necessary to check p against re_ctx->input_end:
88251 				 * the memory access is checked by duk__inp_get_cp(), while
88252 				 * valid compiled regexps cannot write a saved[] entry
88253 				 * which points to outside the string.
88254 				 */
88255 				c1 = duk__inp_get_cp(re_ctx, &p);
88256 				DUK_ASSERT(c1 >= 0);
88257 				c2 = duk__inp_get_cp(re_ctx, &sp);
88258 				/* No need for an explicit c2 < 0 check: because c1 >= 0,
88259 				 * the comparison will always fail if c2 < 0.
88260 				 */
88261 #if 0
88262 				if (c2 < 0) {
88263 					goto fail;
88264 				}
88265 #endif
88266 				if (c1 != c2) {
88267 					goto fail;
88268 				}
88269 			}
88270 			break;
88271 		}
88272 		default: {
88273 			DUK_D(DUK_DPRINT("internal error, regexp opcode error: %ld", (long) op));
88274 			goto internal_error;
88275 		}
88276 		}
88277 	}
88278 
88279  match:
88280 	re_ctx->recursion_depth--;
88281 	return sp;
88282 
88283  fail:
88284 	re_ctx->recursion_depth--;
88285 	return NULL;
88286 
88287  internal_error:
88288 	DUK_ERROR_INTERNAL(re_ctx->thr);
88289 	DUK_WO_NORETURN(return NULL;);
88290 }
88291 
88292 /*
88293  *  Exposed matcher function which provides the semantics of RegExp.prototype.exec().
88294  *
88295  *  RegExp.prototype.test() has the same semantics as exec() but does not return the
88296  *  result object (which contains the matching string and capture groups).  Currently
88297  *  there is no separate test() helper, so a temporary result object is created and
88298  *  discarded if test() is needed.  This is intentional, to save code space.
88299  *
88300  *  Input stack:  [ ... re_obj input ]
88301  *  Output stack: [ ... result ]
88302  */
88303 
88304 DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_global) {
88305 	duk_re_matcher_ctx re_ctx;
88306 	duk_hobject *h_regexp;
88307 	duk_hstring *h_bytecode;
88308 	duk_hstring *h_input;
88309 	duk_uint8_t *p_buf;
88310 	const duk_uint8_t *pc;
88311 	const duk_uint8_t *sp;
88312 	duk_small_int_t match = 0;
88313 	duk_small_int_t global;
88314 	duk_uint_fast32_t i;
88315 	double d;
88316 	duk_uint32_t char_offset;
88317 
88318 	DUK_ASSERT(thr != NULL);
88319 
88320 	DUK_DD(DUK_DDPRINT("regexp match: regexp=%!T, input=%!T",
88321 	                   (duk_tval *) duk_get_tval(thr, -2),
88322 	                   (duk_tval *) duk_get_tval(thr, -1)));
88323 
88324 	/*
88325 	 *  Regexp instance check, bytecode check, input coercion.
88326 	 *
88327 	 *  See E5 Section 15.10.6.
88328 	 */
88329 
88330 	/* TypeError if wrong; class check, see E5 Section 15.10.6 */
88331 	h_regexp = duk_require_hobject_with_class(thr, -2, DUK_HOBJECT_CLASS_REGEXP);
88332 	DUK_ASSERT(h_regexp != NULL);
88333 	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_regexp) == DUK_HOBJECT_CLASS_REGEXP);
88334 	DUK_UNREF(h_regexp);
88335 
88336 	h_input = duk_to_hstring(thr, -1);
88337 	DUK_ASSERT(h_input != NULL);
88338 
88339 	duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_INT_BYTECODE);  /* [ ... re_obj input ] -> [ ... re_obj input bc ] */
88340 	h_bytecode = duk_require_hstring(thr, -1);  /* no regexp instance should exist without a non-configurable bytecode property */
88341 	DUK_ASSERT(h_bytecode != NULL);
88342 
88343 	/*
88344 	 *  Basic context initialization.
88345 	 *
88346 	 *  Some init values are read from the bytecode header
88347 	 *  whose format is (UTF-8 codepoints):
88348 	 *
88349 	 *    uint   flags
88350 	 *    uint   nsaved (even, 2n+2 where n = num captures)
88351 	 */
88352 
88353 	/* [ ... re_obj input bc ] */
88354 
88355 	duk_memzero(&re_ctx, sizeof(re_ctx));
88356 
88357 	re_ctx.thr = thr;
88358 	re_ctx.input = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
88359 	re_ctx.input_end = re_ctx.input + DUK_HSTRING_GET_BYTELEN(h_input);
88360 	re_ctx.bytecode = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_bytecode);
88361 	re_ctx.bytecode_end = re_ctx.bytecode + DUK_HSTRING_GET_BYTELEN(h_bytecode);
88362 	re_ctx.saved = NULL;
88363 	re_ctx.recursion_limit = DUK_USE_REGEXP_EXECUTOR_RECLIMIT;
88364 	re_ctx.steps_limit = DUK_RE_EXECUTE_STEPS_LIMIT;
88365 
88366 	/* read header */
88367 	pc = re_ctx.bytecode;
88368 	re_ctx.re_flags = duk__bc_get_u32(&re_ctx, &pc);
88369 	re_ctx.nsaved = duk__bc_get_u32(&re_ctx, &pc);
88370 	re_ctx.bytecode = pc;
88371 
88372 	DUK_ASSERT(DUK_RE_FLAG_GLOBAL < 0x10000UL);  /* must fit into duk_small_int_t */
88373 	global = (duk_small_int_t) (force_global | (duk_small_int_t) (re_ctx.re_flags & DUK_RE_FLAG_GLOBAL));
88374 
88375 	DUK_ASSERT(re_ctx.nsaved >= 2);
88376 	DUK_ASSERT((re_ctx.nsaved % 2) == 0);
88377 
88378 	p_buf = (duk_uint8_t *) duk_push_fixed_buffer(thr, sizeof(duk_uint8_t *) * re_ctx.nsaved);  /* rely on zeroing */
88379 	DUK_UNREF(p_buf);
88380 	re_ctx.saved = (const duk_uint8_t **) duk_get_buffer(thr, -1, NULL);
88381 	DUK_ASSERT(re_ctx.saved != NULL);
88382 
88383 	/* [ ... re_obj input bc saved_buf ] */
88384 
88385 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
88386 	for (i = 0; i < re_ctx.nsaved; i++) {
88387 		re_ctx.saved[i] = (duk_uint8_t *) NULL;
88388 	}
88389 #elif defined(DUK_USE_ZERO_BUFFER_DATA)
88390 	/* buffer is automatically zeroed */
88391 #else
88392 	duk_memzero((void *) p_buf, sizeof(duk_uint8_t *) * re_ctx.nsaved);
88393 #endif
88394 
88395 	DUK_DDD(DUK_DDDPRINT("regexp ctx initialized, flags=0x%08lx, nsaved=%ld, recursion_limit=%ld, steps_limit=%ld",
88396 	                     (unsigned long) re_ctx.re_flags, (long) re_ctx.nsaved, (long) re_ctx.recursion_limit,
88397 	                     (long) re_ctx.steps_limit));
88398 
88399 	/*
88400 	 *  Get starting character offset for match, and initialize 'sp' based on it.
88401 	 *
88402 	 *  Note: lastIndex is non-configurable so it must be present (we check the
88403 	 *  internal class of the object above, so we know it is).  User code can set
88404 	 *  its value to an arbitrary (garbage) value though; E5 requires that lastIndex
88405 	 *  be coerced to a number before using.  The code below works even if the
88406 	 *  property is missing: the value will then be coerced to zero.
88407 	 *
88408 	 *  Note: lastIndex may be outside Uint32 range even after ToInteger() coercion.
88409 	 *  For instance, ToInteger(+Infinity) = +Infinity.  We track the match offset
88410 	 *  as an integer, but pre-check it to be inside the 32-bit range before the loop.
88411 	 *  If not, the check in E5 Section 15.10.6.2, step 9.a applies.
88412 	 */
88413 
88414 	/* XXX: lastIndex handling produces a lot of asm */
88415 
88416 	/* [ ... re_obj input bc saved_buf ] */
88417 
88418 	duk_get_prop_stridx_short(thr, -4, DUK_STRIDX_LAST_INDEX);  /* -> [ ... re_obj input bc saved_buf lastIndex ] */
88419 	(void) duk_to_int(thr, -1);  /* ToInteger(lastIndex) */
88420 	d = duk_get_number(thr, -1);  /* integer, but may be +/- Infinite, +/- zero (not NaN, though) */
88421 	duk_pop_nodecref_unsafe(thr);
88422 
88423 	if (global) {
88424 		if (d < 0.0 || d > (double) DUK_HSTRING_GET_CHARLEN(h_input)) {
88425 			/* match fail */
88426 			char_offset = 0;   /* not really necessary */
88427 			DUK_ASSERT(match == 0);
88428 			goto match_over;
88429 		}
88430 		char_offset = (duk_uint32_t) d;
88431 	} else {
88432 		/* lastIndex must be ignored for non-global regexps, but get the
88433 		 * value for (theoretical) side effects.  No side effects can
88434 		 * really occur, because lastIndex is a normal property and is
88435 		 * always non-configurable for RegExp instances.
88436 		 */
88437 		char_offset = (duk_uint32_t) 0;
88438 	}
88439 
88440 	DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));
88441 	sp = re_ctx.input + duk_heap_strcache_offset_char2byte(thr, h_input, char_offset);
88442 
88443 	/*
88444 	 *  Match loop.
88445 	 *
88446 	 *  Try matching at different offsets until match found or input exhausted.
88447 	 */
88448 
88449 	/* [ ... re_obj input bc saved_buf ] */
88450 
88451 	DUK_ASSERT(match == 0);
88452 
88453 	for (;;) {
88454 		/* char offset in [0, h_input->clen] (both ends inclusive), checked before entry */
88455 		DUK_ASSERT_DISABLE(char_offset >= 0);
88456 		DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));
88457 
88458 		/* Note: re_ctx.steps is intentionally not reset, it applies to the entire unanchored match */
88459 		DUK_ASSERT(re_ctx.recursion_depth == 0);
88460 
88461 		DUK_DDD(DUK_DDDPRINT("attempt match at char offset %ld; %p [%p,%p]",
88462 		                     (long) char_offset, (const void *) sp,
88463 		                     (const void *) re_ctx.input, (const void *) re_ctx.input_end));
88464 
88465 		/*
88466 		 *  Note:
88467 		 *
88468 		 *    - duk__match_regexp() is required not to longjmp() in ordinary "non-match"
88469 		 *      conditions; a longjmp() will terminate the entire matching process.
88470 		 *
88471 		 *    - Clearing saved[] is not necessary because backtracking does it
88472 		 *
88473 		 *    - Backtracking also rewinds re_ctx.recursion back to zero, unless an
88474 		 *      internal/limit error occurs (which causes a longjmp())
88475 		 *
88476 		 *    - If we supported anchored matches, we would break out here
88477 		 *      unconditionally; however, ECMAScript regexps don't have anchored
88478 		 *      matches.  It might make sense to implement a fast bail-out if
88479 		 *      the regexp begins with '^' and sp is not 0: currently we'll just
88480 		 *      run through the entire input string, trivially failing the match
88481 		 *      at every non-zero offset.
88482 		 */
88483 
88484 		if (duk__match_regexp(&re_ctx, re_ctx.bytecode, sp) != NULL) {
88485 			DUK_DDD(DUK_DDDPRINT("match at offset %ld", (long) char_offset));
88486 			match = 1;
88487 			break;
88488 		}
88489 
88490 		/* advance by one character (code point) and one char_offset */
88491 		char_offset++;
88492 		if (char_offset > DUK_HSTRING_GET_CHARLEN(h_input)) {
88493 			/*
88494 			 *  Note:
88495 			 *
88496 			 *    - Intentionally attempt (empty) match at char_offset == k_input->clen
88497 			 *
88498 			 *    - Negative char_offsets have been eliminated and char_offset is duk_uint32_t
88499 			 *      -> no need or use for a negative check
88500 			 */
88501 
88502 			DUK_DDD(DUK_DDDPRINT("no match after trying all sp offsets"));
88503 			break;
88504 		}
88505 
88506 		/* avoid calling at end of input, will DUK_ERROR (above check suffices to avoid this) */
88507 		(void) duk__utf8_advance(thr, &sp, re_ctx.input, re_ctx.input_end, (duk_uint_fast32_t) 1);
88508 	}
88509 
88510  match_over:
88511 
88512 	/*
88513 	 *  Matching complete, create result array or return a 'null'.  Update lastIndex
88514 	 *  if necessary.  See E5 Section 15.10.6.2.
88515 	 *
88516 	 *  Because lastIndex is a character (not byte) offset, we need the character
88517 	 *  length of the match which we conveniently get as a side effect of interning
88518 	 *  the matching substring (0th index of result array).
88519 	 *
88520 	 *  saved[0]         start pointer (~ byte offset) of current match
88521 	 *  saved[1]         end pointer (~ byte offset) of current match (exclusive)
88522 	 *  char_offset      start character offset of current match (-> .index of result)
88523 	 *  char_end_offset  end character offset (computed below)
88524 	 */
88525 
88526 	/* [ ... re_obj input bc saved_buf ] */
88527 
88528 	if (match) {
88529 #if defined(DUK_USE_ASSERTIONS)
88530 		duk_hobject *h_res;
88531 #endif
88532 		duk_uint32_t char_end_offset = 0;
88533 
88534 		DUK_DDD(DUK_DDDPRINT("regexp matches at char_offset %ld", (long) char_offset));
88535 
88536 		DUK_ASSERT(re_ctx.nsaved >= 2);        /* must have start and end */
88537 		DUK_ASSERT((re_ctx.nsaved % 2) == 0);  /* and even number */
88538 
88539 		/* XXX: Array size is known before and (2 * re_ctx.nsaved) but not taken
88540 		 * advantage of now.  The array is not compacted either, as regexp match
88541 		 * objects are usually short lived.
88542 		 */
88543 
88544 		duk_push_array(thr);
88545 
88546 #if defined(DUK_USE_ASSERTIONS)
88547 		h_res = duk_require_hobject(thr, -1);
88548 		DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_res));
88549 		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h_res));
88550 		DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_res) == DUK_HOBJECT_CLASS_ARRAY);
88551 #endif
88552 
88553 		/* [ ... re_obj input bc saved_buf res_obj ] */
88554 
88555 		duk_push_u32(thr, char_offset);
88556 		duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INDEX);
88557 
88558 		duk_dup_m4(thr);
88559 		duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INPUT);
88560 
88561 		for (i = 0; i < re_ctx.nsaved; i += 2) {
88562 			/* Captures which are undefined have NULL pointers and are returned
88563 			 * as 'undefined'.  The same is done when saved[] pointers are insane
88564 			 * (this should, of course, never happen in practice).
88565 			 */
88566 			if (re_ctx.saved[i] && re_ctx.saved[i + 1] && re_ctx.saved[i + 1] >= re_ctx.saved[i]) {
88567 				duk_push_lstring(thr,
88568 				                 (const char *) re_ctx.saved[i],
88569 				                 (duk_size_t) (re_ctx.saved[i+1] - re_ctx.saved[i]));
88570 				if (i == 0) {
88571 					/* Assumes that saved[0] and saved[1] are always
88572 					 * set by regexp bytecode (if not, char_end_offset
88573 					 * will be zero).  Also assumes clen reflects the
88574 					 * correct char length.
88575 					 */
88576 					char_end_offset = char_offset + (duk_uint32_t) duk_get_length(thr, -1);  /* add charlen */
88577 				}
88578 			} else {
88579 				duk_push_undefined(thr);
88580 			}
88581 
88582 			/* [ ... re_obj input bc saved_buf res_obj val ] */
88583 			duk_put_prop_index(thr, -2, (duk_uarridx_t) (i / 2));
88584 		}
88585 
88586 		/* [ ... re_obj input bc saved_buf res_obj ] */
88587 
88588 		/* NB: 'length' property is automatically updated by the array setup loop */
88589 
88590 		if (global) {
88591 			/* global regexp: lastIndex updated on match */
88592 			duk_push_u32(thr, char_end_offset);
88593 			duk_put_prop_stridx_short(thr, -6, DUK_STRIDX_LAST_INDEX);
88594 		} else {
88595 			/* non-global regexp: lastIndex never updated on match */
88596 			;
88597 		}
88598 	} else {
88599 		/*
88600 		 *  No match, E5 Section 15.10.6.2, step 9.a.i - 9.a.ii apply, regardless
88601 		 *  of 'global' flag of the RegExp.  In particular, if lastIndex is invalid
88602 		 *  initially, it is reset to zero.
88603 		 */
88604 
88605 		DUK_DDD(DUK_DDDPRINT("regexp does not match"));
88606 
88607 		duk_push_null(thr);
88608 
88609 		/* [ ... re_obj input bc saved_buf res_obj ] */
88610 
88611 		duk_push_int(thr, 0);
88612 		duk_put_prop_stridx_short(thr, -6, DUK_STRIDX_LAST_INDEX);
88613 	}
88614 
88615 	/* [ ... re_obj input bc saved_buf res_obj ] */
88616 
88617 	duk_insert(thr, -5);
88618 
88619 	/* [ ... res_obj re_obj input bc saved_buf ] */
88620 
88621 	duk_pop_n_unsafe(thr, 4);
88622 
88623 	/* [ ... res_obj ] */
88624 
88625 	/* XXX: these last tricks are unnecessary if the function is made
88626 	 * a genuine native function.
88627 	 */
88628 }
88629 
88630 DUK_INTERNAL void duk_regexp_match(duk_hthread *thr) {
88631 	duk__regexp_match_helper(thr, 0 /*force_global*/);
88632 }
88633 
88634 /* This variant is needed by String.prototype.split(); it needs to perform
88635  * global-style matching on a cloned RegExp which is potentially non-global.
88636  */
88637 DUK_INTERNAL void duk_regexp_match_force_global(duk_hthread *thr) {
88638 	duk__regexp_match_helper(thr, 1 /*force_global*/);
88639 }
88640 
88641 #else  /* DUK_USE_REGEXP_SUPPORT */
88642 
88643 /* regexp support disabled */
88644 
88645 #endif  /* DUK_USE_REGEXP_SUPPORT */
88646 #line 1 "duk_selftest.c"
88647 /*
88648  *  Self tests to ensure execution environment is sane.  Intended to catch
88649  *  compiler/platform problems which cannot be detected at compile time.
88650  */
88651 
88652 /* #include duk_internal.h -> already included */
88653 
88654 #if defined(DUK_USE_SELF_TESTS)
88655 
88656 /*
88657  *  Unions and structs for self tests
88658  */
88659 
88660 typedef union {
88661 	double d;
88662 	duk_uint8_t x[8];
88663 } duk__test_double_union;
88664 
88665 /* Self test failed.  Expects a local variable 'error_count' to exist. */
88666 #define DUK__FAILED(msg)  do { \
88667 		DUK_D(DUK_DPRINT("self test failed: " #msg " at " DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO))); \
88668 		error_count++; \
88669 	} while (0)
88670 
88671 #define DUK__DBLUNION_CMP_TRUE(a,b)  do { \
88672 		if (duk_memcmp((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) != 0) { \
88673 			DUK__FAILED("double union compares false (expected true)"); \
88674 		} \
88675 	} while (0)
88676 
88677 #define DUK__DBLUNION_CMP_FALSE(a,b)  do { \
88678 		if (duk_memcmp((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) == 0) { \
88679 			DUK__FAILED("double union compares true (expected false)"); \
88680 		} \
88681 	} while (0)
88682 
88683 typedef union {
88684 	duk_uint32_t i;
88685 	duk_uint8_t x[8];
88686 } duk__test_u32_union;
88687 
88688 #if defined(DUK_USE_INTEGER_LE)
88689 #define DUK__U32_INIT(u, a, b, c, d) do { \
88690 		(u)->x[0] = (d); (u)->x[1] = (c); (u)->x[2] = (b); (u)->x[3] = (a); \
88691 	} while (0)
88692 #elif defined(DUK_USE_INTEGER_ME)
88693 #error integer mixed endian not supported now
88694 #elif defined(DUK_USE_INTEGER_BE)
88695 #define DUK__U32_INIT(u, a, b, c, d) do { \
88696 		(u)->x[0] = (a); (u)->x[1] = (b); (u)->x[2] = (c); (u)->x[3] = (d); \
88697 	} while (0)
88698 #else
88699 #error unknown integer endianness
88700 #endif
88701 
88702 #if defined(DUK_USE_DOUBLE_LE)
88703 #define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
88704 		(u)->x[0] = (h); (u)->x[1] = (g); (u)->x[2] = (f); (u)->x[3] = (e); \
88705 		(u)->x[4] = (d); (u)->x[5] = (c); (u)->x[6] = (b); (u)->x[7] = (a); \
88706 	} while (0)
88707 #define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
88708 	((u)->x[0] == (h) && (u)->x[1] == (g) && (u)->x[2] == (f) && (u)->x[3] == (e) && \
88709 	 (u)->x[4] == (d) && (u)->x[5] == (c) && (u)->x[6] == (b) && (u)->x[7] == (a))
88710 #elif defined(DUK_USE_DOUBLE_ME)
88711 #define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
88712 		(u)->x[0] = (d); (u)->x[1] = (c); (u)->x[2] = (b); (u)->x[3] = (a); \
88713 		(u)->x[4] = (h); (u)->x[5] = (g); (u)->x[6] = (f); (u)->x[7] = (e); \
88714 	} while (0)
88715 #define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
88716 	((u)->x[0] == (d) && (u)->x[1] == (c) && (u)->x[2] == (b) && (u)->x[3] == (a) && \
88717 	 (u)->x[4] == (h) && (u)->x[5] == (g) && (u)->x[6] == (f) && (u)->x[7] == (e))
88718 #elif defined(DUK_USE_DOUBLE_BE)
88719 #define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
88720 		(u)->x[0] = (a); (u)->x[1] = (b); (u)->x[2] = (c); (u)->x[3] = (d); \
88721 		(u)->x[4] = (e); (u)->x[5] = (f); (u)->x[6] = (g); (u)->x[7] = (h); \
88722 	} while (0)
88723 #define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
88724 	((u)->x[0] == (a) && (u)->x[1] == (b) && (u)->x[2] == (c) && (u)->x[3] == (d) && \
88725 	 (u)->x[4] == (e) && (u)->x[5] == (f) && (u)->x[6] == (g) && (u)->x[7] == (h))
88726 #else
88727 #error unknown double endianness
88728 #endif
88729 
88730 /*
88731  *  Various sanity checks for typing
88732  */
88733 
88734 DUK_LOCAL duk_uint_t duk__selftest_types(void) {
88735 	duk_uint_t error_count = 0;
88736 
88737 	if (!(sizeof(duk_int8_t) == 1 &&
88738 	      sizeof(duk_uint8_t) == 1 &&
88739 	      sizeof(duk_int16_t) == 2 &&
88740 	      sizeof(duk_uint16_t) == 2 &&
88741 	      sizeof(duk_int32_t) == 4 &&
88742 	      sizeof(duk_uint32_t) == 4)) {
88743 		DUK__FAILED("duk_(u)int{8,16,32}_t size");
88744 	}
88745 #if defined(DUK_USE_64BIT_OPS)
88746 	if (!(sizeof(duk_int64_t) == 8 &&
88747 	      sizeof(duk_uint64_t) == 8)) {
88748 		DUK__FAILED("duk_(u)int64_t size");
88749 	}
88750 #endif
88751 
88752 	if (!(sizeof(duk_size_t) >= sizeof(duk_uint_t))) {
88753 		/* Some internal code now assumes that all duk_uint_t values
88754 		 * can be expressed with a duk_size_t.
88755 		 */
88756 		DUK__FAILED("duk_size_t is smaller than duk_uint_t");
88757 	}
88758 	if (!(sizeof(duk_int_t) >= 4)) {
88759 		DUK__FAILED("duk_int_t is not 32 bits");
88760 	}
88761 
88762 	return error_count;
88763 }
88764 
88765 /*
88766  *  Packed tval sanity
88767  */
88768 
88769 DUK_LOCAL duk_uint_t duk__selftest_packed_tval(void) {
88770 	duk_uint_t error_count = 0;
88771 
88772 #if defined(DUK_USE_PACKED_TVAL)
88773 	if (sizeof(void *) > 4) {
88774 		DUK__FAILED("packed duk_tval in use but sizeof(void *) > 4");
88775 	}
88776 #endif
88777 
88778 	return error_count;
88779 }
88780 
88781 /*
88782  *  Two's complement arithmetic.
88783  */
88784 
88785 DUK_LOCAL duk_uint_t duk__selftest_twos_complement(void) {
88786 	duk_uint_t error_count = 0;
88787 	volatile int test;
88788 	test = -1;
88789 
88790 	/* Note that byte order doesn't affect this test: all bytes in
88791 	 * 'test' will be 0xFF for two's complement.
88792 	 */
88793 	if (((volatile duk_uint8_t *) &test)[0] != (duk_uint8_t) 0xff) {
88794 		DUK__FAILED("two's complement arithmetic");
88795 	}
88796 
88797 	return error_count;
88798 }
88799 
88800 /*
88801  *  Byte order.  Important to self check, because on some exotic platforms
88802  *  there is no actual detection but rather assumption based on platform
88803  *  defines.
88804  */
88805 
88806 DUK_LOCAL duk_uint_t duk__selftest_byte_order(void) {
88807 	duk_uint_t error_count = 0;
88808 	duk__test_u32_union u1;
88809 	duk__test_double_union u2;
88810 
88811 	/*
88812 	 *  >>> struct.pack('>d', 102030405060).encode('hex')
88813 	 *  '4237c17c6dc40000'
88814 	 */
88815 
88816 	DUK__U32_INIT(&u1, 0xde, 0xad, 0xbe, 0xef);
88817 	DUK__DOUBLE_INIT(&u2, 0x42, 0x37, 0xc1, 0x7c, 0x6d, 0xc4, 0x00, 0x00);
88818 
88819 	if (u1.i != (duk_uint32_t) 0xdeadbeefUL) {
88820 		DUK__FAILED("duk_uint32_t byte order");
88821 	}
88822 
88823 	if (u2.d != (double) 102030405060.0) {
88824 		DUK__FAILED("double byte order");
88825 	}
88826 
88827 	return error_count;
88828 }
88829 
88830 /*
88831  *  DUK_BSWAP macros
88832  */
88833 
88834 DUK_LOCAL duk_uint_t duk__selftest_bswap_macros(void) {
88835 	duk_uint_t error_count = 0;
88836 	duk_uint32_t x32;
88837 	duk_uint16_t x16;
88838 	duk_double_union du;
88839 	duk_double_t du_diff;
88840 
88841 	x16 = 0xbeefUL;
88842 	x16 = DUK_BSWAP16(x16);
88843 	if (x16 != (duk_uint16_t) 0xefbeUL) {
88844 		DUK__FAILED("DUK_BSWAP16");
88845 	}
88846 
88847 	x32 = 0xdeadbeefUL;
88848 	x32 = DUK_BSWAP32(x32);
88849 	if (x32 != (duk_uint32_t) 0xefbeaddeUL) {
88850 		DUK__FAILED("DUK_BSWAP32");
88851 	}
88852 
88853 	/* >>> struct.unpack('>d', '4000112233445566'.decode('hex'))
88854 	 * (2.008366013071895,)
88855 	 */
88856 
88857 	du.uc[0] = 0x40; du.uc[1] = 0x00; du.uc[2] = 0x11; du.uc[3] = 0x22;
88858 	du.uc[4] = 0x33; du.uc[5] = 0x44; du.uc[6] = 0x55; du.uc[7] = 0x66;
88859 	DUK_DBLUNION_DOUBLE_NTOH(&du);
88860 	du_diff = du.d - 2.008366013071895;
88861 #if 0
88862 	DUK_D(DUK_DPRINT("du_diff: %lg\n", (double) du_diff));
88863 #endif
88864 	if (du_diff > 1e-15) {
88865 		/* Allow very small lenience because some compilers won't parse
88866 		 * exact IEEE double constants (happened in matrix testing with
88867 		 * Linux gcc-4.8 -m32 at least).
88868 		 */
88869 #if 0
88870 		DUK_D(DUK_DPRINT("Result of DUK_DBLUNION_DOUBLE_NTOH: %02x %02x %02x %02x %02x %02x %02x %02x\n",
88871 		            (unsigned int) du.uc[0], (unsigned int) du.uc[1],
88872 		            (unsigned int) du.uc[2], (unsigned int) du.uc[3],
88873 		            (unsigned int) du.uc[4], (unsigned int) du.uc[5],
88874 		            (unsigned int) du.uc[6], (unsigned int) du.uc[7]));
88875 #endif
88876 		DUK__FAILED("DUK_DBLUNION_DOUBLE_NTOH");
88877 	}
88878 
88879 	return error_count;
88880 }
88881 
88882 /*
88883  *  Basic double / byte union memory layout.
88884  */
88885 
88886 DUK_LOCAL duk_uint_t duk__selftest_double_union_size(void) {
88887 	duk_uint_t error_count = 0;
88888 
88889 	if (sizeof(duk__test_double_union) != 8) {
88890 		DUK__FAILED("invalid union size");
88891 	}
88892 
88893 	return error_count;
88894 }
88895 
88896 /*
88897  *  Union aliasing, see misc/clang_aliasing.c.
88898  */
88899 
88900 DUK_LOCAL duk_uint_t duk__selftest_double_aliasing(void) {
88901 	/* This testcase fails when Emscripten-generated code runs on Firefox.
88902 	 * It's not an issue because the failure should only affect packed
88903 	 * duk_tval representation, which is not used with Emscripten.
88904 	 */
88905 #if defined(DUK_USE_PACKED_TVAL)
88906 	duk_uint_t error_count = 0;
88907 	duk__test_double_union a, b;
88908 
88909 	/* Test signaling NaN and alias assignment in all endianness combinations.
88910 	 */
88911 
88912 	/* little endian */
88913 	a.x[0] = 0x11; a.x[1] = 0x22; a.x[2] = 0x33; a.x[3] = 0x44;
88914 	a.x[4] = 0x00; a.x[5] = 0x00; a.x[6] = 0xf1; a.x[7] = 0xff;
88915 	b = a;
88916 	DUK__DBLUNION_CMP_TRUE(&a, &b);
88917 
88918 	/* big endian */
88919 	a.x[0] = 0xff; a.x[1] = 0xf1; a.x[2] = 0x00; a.x[3] = 0x00;
88920 	a.x[4] = 0x44; a.x[5] = 0x33; a.x[6] = 0x22; a.x[7] = 0x11;
88921 	b = a;
88922 	DUK__DBLUNION_CMP_TRUE(&a, &b);
88923 
88924 	/* mixed endian */
88925 	a.x[0] = 0x00; a.x[1] = 0x00; a.x[2] = 0xf1; a.x[3] = 0xff;
88926 	a.x[4] = 0x11; a.x[5] = 0x22; a.x[6] = 0x33; a.x[7] = 0x44;
88927 	b = a;
88928 	DUK__DBLUNION_CMP_TRUE(&a, &b);
88929 
88930 	return error_count;
88931 #else
88932 	DUK_D(DUK_DPRINT("skip double aliasing self test when duk_tval is not packed"));
88933 	return 0;
88934 #endif
88935 }
88936 
88937 /*
88938  *  Zero sign, see misc/tcc_zerosign2.c.
88939  */
88940 
88941 DUK_LOCAL duk_uint_t duk__selftest_double_zero_sign(void) {
88942 	duk_uint_t error_count = 0;
88943 	duk__test_double_union a, b;
88944 
88945 	a.d = 0.0;
88946 	b.d = -a.d;
88947 	DUK__DBLUNION_CMP_FALSE(&a, &b);
88948 
88949 	return error_count;
88950 }
88951 
88952 /*
88953  *  Rounding mode: Duktape assumes round-to-nearest, check that this is true.
88954  *  If we had C99 fenv.h we could check that fegetround() == FE_TONEAREST,
88955  *  but we don't want to rely on that header; and even if we did, it's good
88956  *  to ensure the rounding actually works.
88957  */
88958 
88959 DUK_LOCAL duk_uint_t duk__selftest_double_rounding(void) {
88960 	duk_uint_t error_count = 0;
88961 	duk__test_double_union a, b, c;
88962 
88963 #if 0
88964 	/* Include <fenv.h> and test manually; these trigger failures: */
88965 	fesetround(FE_UPWARD);
88966 	fesetround(FE_DOWNWARD);
88967 	fesetround(FE_TOWARDZERO);
88968 
88969 	/* This is the default and passes. */
88970 	fesetround(FE_TONEAREST);
88971 #endif
88972 
88973 	/* Rounding tests check that none of the other modes (round to
88974 	 * +Inf, round to -Inf, round to zero) can be active:
88975 	 * http://www.gnu.org/software/libc/manual/html_node/Rounding.html
88976 	 */
88977 
88978 	/* 1.0 + 2^(-53): result is midway between 1.0 and 1.0 + ulp.
88979 	 * Round to nearest: 1.0
88980 	 * Round to +Inf:    1.0 + ulp
88981 	 * Round to -Inf:    1.0
88982 	 * Round to zero:    1.0
88983 	 * => Correct result eliminates round to +Inf.
88984 	 */
88985 	DUK__DOUBLE_INIT(&a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
88986 	DUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
88987 	duk_memset((void *) &c, 0, sizeof(c));
88988 	c.d = a.d + b.d;
88989 	if (!DUK__DOUBLE_COMPARE(&c, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)) {
88990 		DUK_D(DUK_DPRINT("broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x",
88991 		                 (unsigned int) c.x[0], (unsigned int) c.x[1],
88992 		                 (unsigned int) c.x[2], (unsigned int) c.x[3],
88993 		                 (unsigned int) c.x[4], (unsigned int) c.x[5],
88994 		                 (unsigned int) c.x[6], (unsigned int) c.x[7]));
88995 		DUK__FAILED("invalid result from 1.0 + 0.5ulp");
88996 	}
88997 
88998 	/* (1.0 + ulp) + 2^(-53): result is midway between 1.0 + ulp and 1.0 + 2*ulp.
88999 	 * Round to nearest: 1.0 + 2*ulp (round to even mantissa)
89000 	 * Round to +Inf:    1.0 + 2*ulp
89001 	 * Round to -Inf:    1.0 + ulp
89002 	 * Round to zero:    1.0 + ulp
89003 	 * => Correct result eliminates round to -Inf and round to zero.
89004 	 */
89005 	DUK__DOUBLE_INIT(&a, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
89006 	DUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
89007 	duk_memset((void *) &c, 0, sizeof(c));
89008 	c.d = a.d + b.d;
89009 	if (!DUK__DOUBLE_COMPARE(&c, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02)) {
89010 		DUK_D(DUK_DPRINT("broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x",
89011 		                 (unsigned int) c.x[0], (unsigned int) c.x[1],
89012 		                 (unsigned int) c.x[2], (unsigned int) c.x[3],
89013 		                 (unsigned int) c.x[4], (unsigned int) c.x[5],
89014 		                 (unsigned int) c.x[6], (unsigned int) c.x[7]));
89015 		DUK__FAILED("invalid result from (1.0 + ulp) + 0.5ulp");
89016 	}
89017 
89018 	/* Could do negative number testing too, but the tests above should
89019 	 * differentiate between IEEE 754 rounding modes.
89020 	 */
89021 	return error_count;
89022 }
89023 
89024 /*
89025  *  fmod(): often a portability issue in embedded or bare platform targets.
89026  *  Check for at least minimally correct behavior.  Unlike some other math
89027  *  functions (like cos()) Duktape relies on fmod() internally too.
89028  */
89029 
89030 DUK_LOCAL duk_uint_t duk__selftest_fmod(void) {
89031 	duk_uint_t error_count = 0;
89032 	duk__test_double_union u1, u2;
89033 	volatile duk_double_t t1, t2, t3;
89034 
89035 	/* fmod() with integer argument and exponent 2^32 is used by e.g.
89036 	 * ToUint32() and some Duktape internals.
89037 	 */
89038 	u1.d = DUK_FMOD(10.0, 4294967296.0);
89039 	u2.d = 10.0;
89040 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89041 
89042 	u1.d = DUK_FMOD(4294967306.0, 4294967296.0);
89043 	u2.d = 10.0;
89044 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89045 
89046 	u1.d = DUK_FMOD(73014444042.0, 4294967296.0);
89047 	u2.d = 10.0;
89048 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89049 
89050 	/* 52-bit integer split into two parts:
89051 	 * >>> 0x1fedcba9876543
89052 	 * 8987183256397123
89053 	 * >>> float(0x1fedcba9876543) / float(2**53)
89054 	 * 0.9977777777777778
89055 	 */
89056 	u1.d = DUK_FMOD(8987183256397123.0, 4294967296.0);
89057 	u2.d = (duk_double_t) 0xa9876543UL;
89058 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89059 	t1 = 8987183256397123.0;
89060 	t2 = 4294967296.0;
89061 	t3 = t1 / t2;
89062 	u1.d = DUK_FLOOR(t3);
89063 	u2.d = (duk_double_t) 0x1fedcbUL;
89064 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89065 
89066 	/* C99 behavior is for fmod() result sign to mathc argument sign. */
89067 	u1.d = DUK_FMOD(-10.0, 4294967296.0);
89068 	u2.d = -10.0;
89069 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89070 
89071 	u1.d = DUK_FMOD(-4294967306.0, 4294967296.0);
89072 	u2.d = -10.0;
89073 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89074 
89075 	u1.d = DUK_FMOD(-73014444042.0, 4294967296.0);
89076 	u2.d = -10.0;
89077 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89078 
89079 	return error_count;
89080 }
89081 
89082 /*
89083  *  Struct size/alignment if platform requires it
89084  *
89085  *  There are some compiler specific struct padding pragmas etc in use, this
89086  *  selftest ensures they're correctly detected and used.
89087  */
89088 
89089 DUK_LOCAL duk_uint_t duk__selftest_struct_align(void) {
89090 	duk_uint_t error_count = 0;
89091 
89092 #if (DUK_USE_ALIGN_BY == 4)
89093 	if ((sizeof(duk_hbuffer_fixed) % 4) != 0) {
89094 		DUK__FAILED("sizeof(duk_hbuffer_fixed) not aligned to 4");
89095 	}
89096 #elif (DUK_USE_ALIGN_BY == 8)
89097 	if ((sizeof(duk_hbuffer_fixed) % 8) != 0) {
89098 		DUK__FAILED("sizeof(duk_hbuffer_fixed) not aligned to 8");
89099 	}
89100 #elif (DUK_USE_ALIGN_BY == 1)
89101 	/* no check */
89102 #else
89103 #error invalid DUK_USE_ALIGN_BY
89104 #endif
89105 	return error_count;
89106 }
89107 
89108 /*
89109  *  64-bit arithmetic
89110  *
89111  *  There are some platforms/compilers where 64-bit types are available
89112  *  but don't work correctly.  Test for known cases.
89113  */
89114 
89115 DUK_LOCAL duk_uint_t duk__selftest_64bit_arithmetic(void) {
89116 	duk_uint_t error_count = 0;
89117 #if defined(DUK_USE_64BIT_OPS)
89118 	volatile duk_int64_t i;
89119 	volatile duk_double_t d;
89120 
89121 	/* Catch a double-to-int64 cast issue encountered in practice. */
89122 	d = 2147483648.0;
89123 	i = (duk_int64_t) d;
89124 	if (i != DUK_I64_CONSTANT(0x80000000)) {
89125 		DUK__FAILED("casting 2147483648.0 to duk_int64_t failed");
89126 	}
89127 #else
89128 	/* nop */
89129 #endif
89130 	return error_count;
89131 }
89132 
89133 /*
89134  *  Casting
89135  */
89136 
89137 DUK_LOCAL duk_uint_t duk__selftest_cast_double_to_small_uint(void) {
89138 	/*
89139 	 *  https://github.com/svaarala/duktape/issues/127#issuecomment-77863473
89140 	 */
89141 
89142 	duk_uint_t error_count = 0;
89143 
89144 	duk_double_t d1, d2;
89145 	duk_small_uint_t u;
89146 
89147 	duk_double_t d1v, d2v;
89148 	duk_small_uint_t uv;
89149 
89150 	/* Test without volatiles */
89151 
89152 	d1 = 1.0;
89153 	u = (duk_small_uint_t) d1;
89154 	d2 = (duk_double_t) u;
89155 
89156 	if (!(d1 == 1.0 && u == 1 && d2 == 1.0 && d1 == d2)) {
89157 		DUK__FAILED("double to duk_small_uint_t cast failed");
89158 	}
89159 
89160 	/* Same test with volatiles */
89161 
89162 	d1v = 1.0;
89163 	uv = (duk_small_uint_t) d1v;
89164 	d2v = (duk_double_t) uv;
89165 
89166 	if (!(d1v == 1.0 && uv == 1 && d2v == 1.0 && d1v == d2v)) {
89167 		DUK__FAILED("double to duk_small_uint_t cast failed");
89168 	}
89169 
89170 	return error_count;
89171 }
89172 
89173 DUK_LOCAL duk_uint_t duk__selftest_cast_double_to_uint32(void) {
89174 	/*
89175 	 *  This test fails on an exotic ARM target; double-to-uint
89176 	 *  cast is incorrectly clamped to -signed- int highest value.
89177 	 *
89178 	 *  https://github.com/svaarala/duktape/issues/336
89179 	 */
89180 
89181 	duk_uint_t error_count = 0;
89182 	duk_double_t dv;
89183 	duk_uint32_t uv;
89184 
89185 	dv = 3735928559.0;  /* 0xdeadbeef in decimal */
89186 	uv = (duk_uint32_t) dv;
89187 
89188 	if (uv != 0xdeadbeefUL) {
89189 		DUK__FAILED("double to duk_uint32_t cast failed");
89190 	}
89191 
89192 	return error_count;
89193 }
89194 
89195 /*
89196  *  Minimal test of user supplied allocation functions
89197  *
89198  *    - Basic alloc + realloc + free cycle
89199  *
89200  *    - Realloc to significantly larger size to (hopefully) trigger a
89201  *      relocation and check that relocation copying works
89202  */
89203 
89204 DUK_LOCAL duk_uint_t duk__selftest_alloc_funcs(duk_alloc_function alloc_func,
89205                                                duk_realloc_function realloc_func,
89206                                                duk_free_function free_func,
89207                                                void *udata) {
89208 	duk_uint_t error_count = 0;
89209 	void *ptr;
89210 	void *new_ptr;
89211 	duk_small_int_t i, j;
89212 	unsigned char x;
89213 
89214 	if (alloc_func == NULL || realloc_func == NULL || free_func == NULL) {
89215 		return 0;
89216 	}
89217 
89218 	for (i = 1; i <= 256; i++) {
89219 		ptr = alloc_func(udata, (duk_size_t) i);
89220 		if (ptr == NULL) {
89221 			DUK_D(DUK_DPRINT("alloc failed, ignore"));
89222 			continue;  /* alloc failed, ignore */
89223 		}
89224 		for (j = 0; j < i; j++) {
89225 			((unsigned char *) ptr)[j] = (unsigned char) (0x80 + j);
89226 		}
89227 		new_ptr = realloc_func(udata, ptr, 1024);
89228 		if (new_ptr == NULL) {
89229 			DUK_D(DUK_DPRINT("realloc failed, ignore"));
89230 			free_func(udata, ptr);
89231 			continue;  /* realloc failed, ignore */
89232 		}
89233 		ptr = new_ptr;
89234 		for (j = 0; j < i; j++) {
89235 			x = ((unsigned char *) ptr)[j];
89236 			if (x != (unsigned char) (0x80 + j)) {
89237 				DUK_D(DUK_DPRINT("byte at index %ld doesn't match after realloc: %02lx",
89238 				                 (long) j, (unsigned long) x));
89239 				DUK__FAILED("byte compare after realloc");
89240 				break;
89241 			}
89242 		}
89243 		free_func(udata, ptr);
89244 	}
89245 
89246 	return error_count;
89247 }
89248 
89249 /*
89250  *  Self test main
89251  */
89252 
89253 DUK_INTERNAL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_func,
89254                                                duk_realloc_function realloc_func,
89255                                                duk_free_function free_func,
89256                                                void *udata) {
89257 	duk_uint_t error_count = 0;
89258 
89259 	DUK_D(DUK_DPRINT("self test starting"));
89260 
89261 	error_count += duk__selftest_types();
89262 	error_count += duk__selftest_packed_tval();
89263 	error_count += duk__selftest_twos_complement();
89264 	error_count += duk__selftest_byte_order();
89265 	error_count += duk__selftest_bswap_macros();
89266 	error_count += duk__selftest_double_union_size();
89267 	error_count += duk__selftest_double_aliasing();
89268 	error_count += duk__selftest_double_zero_sign();
89269 	error_count += duk__selftest_double_rounding();
89270 	error_count += duk__selftest_fmod();
89271 	error_count += duk__selftest_struct_align();
89272 	error_count += duk__selftest_64bit_arithmetic();
89273 	error_count += duk__selftest_cast_double_to_small_uint();
89274 	error_count += duk__selftest_cast_double_to_uint32();
89275 	error_count += duk__selftest_alloc_funcs(alloc_func, realloc_func, free_func, udata);
89276 
89277 	DUK_D(DUK_DPRINT("self test complete, total error count: %ld", (long) error_count));
89278 
89279 	return error_count;
89280 }
89281 
89282 #endif  /* DUK_USE_SELF_TESTS */
89283 
89284 /* automatic undefs */
89285 #undef DUK__DBLUNION_CMP_FALSE
89286 #undef DUK__DBLUNION_CMP_TRUE
89287 #undef DUK__DOUBLE_COMPARE
89288 #undef DUK__DOUBLE_INIT
89289 #undef DUK__FAILED
89290 #undef DUK__U32_INIT
89291 /* #include duk_internal.h -> already included */
89292 #line 2 "duk_tval.c"
89293 
89294 #if defined(DUK_USE_FASTINT)
89295 
89296 /*
89297  *  Manually optimized double-to-fastint downgrade check.
89298  *
89299  *  This check has a large impact on performance, especially for fastint
89300  *  slow paths, so must be changed carefully.  The code should probably be
89301  *  optimized for the case where the result does not fit into a fastint,
89302  *  to minimize the penalty for "slow path code" dealing with fractions etc.
89303  *
89304  *  At least on one tested soft float ARM platform double-to-int64 coercion
89305  *  is very slow (and sometimes produces incorrect results, see self tests).
89306  *  This algorithm combines a fastint compatibility check and extracting the
89307  *  integer value from an IEEE double for setting the tagged fastint.  For
89308  *  other platforms a more naive approach might be better.
89309  *
89310  *  See doc/fastint.rst for details.
89311  */
89312 
89313 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x) {
89314 	duk_double_union du;
89315 	duk_int64_t i;
89316 	duk_small_int_t expt;
89317 	duk_small_int_t shift;
89318 
89319 	/* XXX: optimize for packed duk_tval directly? */
89320 
89321 	du.d = x;
89322 	i = (duk_int64_t) DUK_DBLUNION_GET_INT64(&du);
89323 	expt = (duk_small_int_t) ((i >> 52) & 0x07ff);
89324 	shift = expt - 1023;
89325 
89326 	if (shift >= 0 && shift <= 46) {  /* exponents 1023 to 1069 */
89327 		duk_int64_t t;
89328 
89329 		if (((DUK_I64_CONSTANT(0x000fffffffffffff) >> shift) & i) == 0) {
89330 			t = i | DUK_I64_CONSTANT(0x0010000000000000);  /* implicit leading one */
89331 			t = t & DUK_I64_CONSTANT(0x001fffffffffffff);
89332 			t = t >> (52 - shift);
89333 			if (i < 0) {
89334 				t = -t;
89335 			}
89336 			DUK_TVAL_SET_FASTINT(tv, t);
89337 			return;
89338 		}
89339 	} else if (shift == -1023) {  /* exponent 0 */
89340 		if (i >= 0 && (i & DUK_I64_CONSTANT(0x000fffffffffffff)) == 0) {
89341 			/* Note: reject negative zero. */
89342 			DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) 0);
89343 			return;
89344 		}
89345 	} else if (shift == 47) {  /* exponent 1070 */
89346 		if (i < 0 && (i & DUK_I64_CONSTANT(0x000fffffffffffff)) == 0) {
89347 			DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) DUK_FASTINT_MIN);
89348 			return;
89349 		}
89350 	}
89351 
89352 	DUK_TVAL_SET_DOUBLE(tv, x);
89353 	return;
89354 }
89355 
89356 DUK_INTERNAL DUK_NOINLINE void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x) {
89357 	duk_tval_set_number_chkfast_fast(tv, x);
89358 }
89359 
89360 /*
89361  *  Manually optimized number-to-double conversion
89362  */
89363 
89364 #if defined(DUK_USE_FASTINT) && defined(DUK_USE_PACKED_TVAL)
89365 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_packed(duk_tval *tv) {
89366 	duk_double_union du;
89367 	duk_uint64_t t;
89368 
89369 	t = (duk_uint64_t) DUK_DBLUNION_GET_UINT64(tv);
89370 	if ((t >> 48) != DUK_TAG_FASTINT) {
89371 		return tv->d;
89372 	} else if (t & DUK_U64_CONSTANT(0x0000800000000000)) {
89373 		t = (duk_uint64_t) (-((duk_int64_t) t));  /* avoid unary minus on unsigned */
89374 		t = t & DUK_U64_CONSTANT(0x0000ffffffffffff);  /* negative */
89375 		t |= DUK_U64_CONSTANT(0xc330000000000000);
89376 		DUK_DBLUNION_SET_UINT64(&du, t);
89377 		return du.d + 4503599627370496.0;  /* 1 << 52 */
89378 	} else if (t != 0) {
89379 		t &= DUK_U64_CONSTANT(0x0000ffffffffffff);  /* positive */
89380 		t |= DUK_U64_CONSTANT(0x4330000000000000);
89381 		DUK_DBLUNION_SET_UINT64(&du, t);
89382 		return du.d - 4503599627370496.0;  /* 1 << 52 */
89383 	} else {
89384 		return 0.0;  /* zero */
89385 	}
89386 }
89387 #endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
89388 
89389 #if 0  /* unused */
89390 #if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
89391 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked(duk_tval *tv) {
89392 	duk_double_union du;
89393 	duk_uint64_t t;
89394 
89395 	DUK_ASSERT(tv->t == DUK_TAG_NUMBER || tv->t == DUK_TAG_FASTINT);
89396 
89397 	if (tv->t == DUK_TAG_FASTINT) {
89398 		if (tv->v.fi >= 0) {
89399 			t = DUK_U64_CONSTANT(0x4330000000000000) | (duk_uint64_t) tv->v.fi;
89400 			DUK_DBLUNION_SET_UINT64(&du, t);
89401 			return du.d - 4503599627370496.0;  /* 1 << 52 */
89402 		} else {
89403 			t = DUK_U64_CONSTANT(0xc330000000000000) | (duk_uint64_t) (-tv->v.fi);
89404 			DUK_DBLUNION_SET_UINT64(&du, t);
89405 			return du.d + 4503599627370496.0;  /* 1 << 52 */
89406 		}
89407 	} else {
89408 		return tv->v.d;
89409 	}
89410 }
89411 #endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
89412 #endif  /* 0 */
89413 
89414 #if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
89415 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv) {
89416 	duk_double_union du;
89417 	duk_uint64_t t;
89418 
89419 	DUK_ASSERT(tv->t == DUK_TAG_FASTINT);
89420 
89421 	if (tv->v.fi >= 0) {
89422 		t = DUK_U64_CONSTANT(0x4330000000000000) | (duk_uint64_t) tv->v.fi;
89423 		DUK_DBLUNION_SET_UINT64(&du, t);
89424 		return du.d - 4503599627370496.0;  /* 1 << 52 */
89425 	} else {
89426 		t = DUK_U64_CONSTANT(0xc330000000000000) | (duk_uint64_t) (-tv->v.fi);
89427 		DUK_DBLUNION_SET_UINT64(&du, t);
89428 		return du.d + 4503599627370496.0;  /* 1 << 52 */
89429 	}
89430 }
89431 #endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
89432 
89433 #endif  /* DUK_USE_FASTINT */
89434 #line 1 "duk_unicode_tables.c"
89435 /*
89436  *  Unicode support tables automatically generated during build.
89437  */
89438 
89439 /* #include duk_internal.h -> already included */
89440 
89441 /*
89442  *  Unicode tables containing ranges of Unicode characters in a
89443  *  packed format.  These tables are used to match non-ASCII
89444  *  characters of complex productions by resorting to a linear
89445  *  range-by-range comparison.  This is very slow, but is expected
89446  *  to be very rare in practical ECMAScript source code, and thus
89447  *  compactness is most important.
89448  *
89449  *  The tables are matched using uni_range_match() and the format
89450  *  is described in tools/extract_chars.py.
89451  */
89452 
89453 #if defined(DUK_USE_SOURCE_NONBMP)
89454 /* IdentifierStart production with ASCII excluded */
89455 /* duk_unicode_ids_noa[] */
89456 /*
89457  *  Automatically generated by extract_chars.py, do not edit!
89458  */
89459 
89460 const duk_uint8_t duk_unicode_ids_noa[1063] = {
89461 249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34,
89462 2,240,66,244,50,247,185,249,98,241,99,8,241,127,58,240,182,47,31,241,191,
89463 21,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
89464 101,10,4,15,9,240,152,175,39,240,82,127,56,242,100,15,4,8,159,1,240,5,115,
89465 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,
89466 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,
89467 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,
89468 12,38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,
89469 6,41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,3,18,3,7,50,
89470 98,34,2,3,18,50,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,
89471 2,85,52,4,24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,
89472 35,63,17,35,54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,
89473 227,240,18,240,166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,
89474 21,5,15,53,244,137,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,
89475 175,40,240,122,242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,
89476 79,27,43,241,67,143,82,50,52,26,251,15,50,255,224,8,53,63,22,53,55,32,32,
89477 32,47,15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,
89478 32,68,112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,
89479 87,52,29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,
89480 254,12,146,240,184,132,52,95,70,114,47,74,35,111,26,63,78,240,63,11,242,
89481 127,0,255,224,244,255,240,0,138,143,60,255,240,4,13,223,7,255,227,127,243,
89482 95,30,63,253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,20,39,
89483 243,26,34,35,47,7,240,255,36,240,15,34,243,5,64,32,223,12,191,7,240,191,13,
89484 143,31,240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,
89485 48,32,240,162,58,130,213,53,53,166,38,47,27,41,191,99,240,255,255,0,26,150,
89486 223,7,95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,
89487 18,245,207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,
89488 127,10,207,73,69,53,53,50,241,91,47,10,47,3,33,46,61,241,79,107,243,127,37,
89489 255,223,13,79,33,242,31,16,239,14,111,22,191,14,63,20,87,36,241,207,142,
89490 240,79,20,95,20,95,24,159,36,248,239,254,2,154,240,107,127,138,83,2,241,
89491 194,20,3,240,123,240,122,240,255,51,240,50,27,240,107,240,175,56,242,135,
89492 31,50,15,1,50,34,240,191,30,240,212,240,223,21,114,240,207,13,242,107,240,
89493 107,240,62,240,47,96,243,159,41,242,62,242,63,254,32,79,37,243,223,29,241,
89494 47,9,240,207,20,241,191,19,64,223,32,240,3,240,112,32,241,95,2,47,9,244,
89495 102,32,35,46,41,143,31,241,135,49,63,6,38,33,36,64,240,64,212,249,15,37,
89496 240,67,242,127,32,240,97,32,250,175,31,241,179,241,111,32,240,96,242,223,
89497 27,244,127,10,255,224,122,243,15,17,15,242,11,241,136,15,7,12,241,131,63,
89498 40,242,159,249,130,241,95,3,15,35,240,239,98,98,18,241,111,7,15,254,26,223,
89499 254,40,207,88,245,255,3,251,79,254,155,15,254,50,31,254,236,95,254,19,159,
89500 255,0,16,173,255,225,43,143,15,246,63,14,240,79,32,240,35,241,31,5,111,3,
89501 255,226,100,243,92,15,52,207,50,31,16,255,240,0,109,255,5,255,225,229,255,
89502 240,1,64,31,254,1,31,67,255,224,126,255,231,248,245,182,196,136,159,255,0,
89503 6,90,244,82,243,114,19,3,19,50,178,2,98,243,18,51,114,98,240,194,50,66,4,
89504 98,255,224,70,63,9,47,9,47,15,47,9,47,15,47,9,47,15,47,9,47,15,47,9,39,255,
89505 239,40,251,95,45,243,79,254,59,3,47,11,33,32,48,41,35,32,32,112,80,32,32,
89506 34,33,32,48,32,32,32,32,33,32,51,38,35,35,32,41,47,1,98,36,47,1,255,240,0,
89507 3,143,255,0,149,201,241,191,254,242,124,252,227,255,240,0,87,79,0,255,240,
89508 0,194,63,254,177,63,254,17,0,
89509 };
89510 #else
89511 /* IdentifierStart production with ASCII and non-BMP excluded */
89512 /* duk_unicode_ids_noabmp[] */
89513 /*
89514  *  Automatically generated by extract_chars.py, do not edit!
89515  */
89516 
89517 const duk_uint8_t duk_unicode_ids_noabmp[626] = {
89518 249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34,
89519 2,240,66,244,50,247,185,249,98,241,99,8,241,127,58,240,182,47,31,241,191,
89520 21,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
89521 101,10,4,15,9,240,152,175,39,240,82,127,56,242,100,15,4,8,159,1,240,5,115,
89522 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,
89523 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,
89524 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,
89525 12,38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,
89526 6,41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,3,18,3,7,50,
89527 98,34,2,3,18,50,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,
89528 2,85,52,4,24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,
89529 35,63,17,35,54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,
89530 227,240,18,240,166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,
89531 21,5,15,53,244,137,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,
89532 175,40,240,122,242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,
89533 79,27,43,241,67,143,82,50,52,26,251,15,50,255,224,8,53,63,22,53,55,32,32,
89534 32,47,15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,
89535 32,68,112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,
89536 87,52,29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,
89537 254,12,146,240,184,132,52,95,70,114,47,74,35,111,26,63,78,240,63,11,242,
89538 127,0,255,224,244,255,240,0,138,143,60,255,240,4,13,223,7,255,227,127,243,
89539 95,30,63,253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,20,39,
89540 243,26,34,35,47,7,240,255,36,240,15,34,243,5,64,32,223,12,191,7,240,191,13,
89541 143,31,240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,
89542 48,32,240,162,58,130,213,53,53,166,38,47,27,41,191,99,240,255,255,0,26,150,
89543 223,7,95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,
89544 18,245,207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,
89545 127,10,207,73,69,53,53,50,0,
89546 };
89547 #endif
89548 
89549 #if defined(DUK_USE_SOURCE_NONBMP)
89550 /* IdentifierStart production with Letter and ASCII excluded */
89551 /* duk_unicode_ids_m_let_noa[] */
89552 /*
89553  *  Automatically generated by extract_chars.py, do not edit!
89554  */
89555 
89556 const duk_uint8_t duk_unicode_ids_m_let_noa[42] = {
89557 255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
89558 249,255,240,4,148,79,37,255,224,192,9,15,120,79,255,0,15,30,245,240,
89559 };
89560 #else
89561 /* IdentifierStart production with Letter, ASCII, and non-BMP excluded */
89562 /* duk_unicode_ids_m_let_noabmp[] */
89563 /*
89564  *  Automatically generated by extract_chars.py, do not edit!
89565  */
89566 
89567 const duk_uint8_t duk_unicode_ids_m_let_noabmp[24] = {
89568 255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
89569 249,0,
89570 };
89571 #endif
89572 
89573 #if defined(DUK_USE_SOURCE_NONBMP)
89574 /* IdentifierPart production with IdentifierStart and ASCII excluded */
89575 /* duk_unicode_idp_m_ids_noa[] */
89576 /*
89577  *  Automatically generated by extract_chars.py, do not edit!
89578  */
89579 
89580 const duk_uint8_t duk_unicode_idp_m_ids_noa[549] = {
89581 255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
89582 245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,241,67,40,34,
89583 36,241,210,246,173,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,
89584 160,177,57,240,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,240,
89585 97,57,181,34,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,9,
89586 240,35,242,198,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,35,
89587 242,145,38,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,215,
89588 41,244,144,53,33,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,
89589 245,111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,
89590 241,241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,
89591 242,244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,
89592 57,241,237,242,47,4,153,121,246,130,47,5,80,82,50,251,143,42,36,255,225,0,
89593 31,35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,
89594 31,255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,
89595 242,79,2,185,127,2,240,9,240,231,240,188,241,227,242,29,240,25,192,185,242,
89596 29,208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,
89597 225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,15,254,27,16,253,64,
89598 248,116,255,224,25,159,254,68,178,33,99,241,162,80,249,113,255,228,13,47,
89599 39,239,17,159,1,63,31,175,39,151,47,22,210,159,37,13,47,34,218,36,159,68,
89600 183,15,146,182,151,63,42,2,99,19,42,11,19,100,79,178,240,42,159,72,240,77,
89601 159,199,99,143,13,31,68,240,31,1,159,67,201,159,69,229,159,254,9,169,255,
89602 224,11,159,26,98,57,10,175,32,240,15,254,8,151,39,240,41,242,175,6,45,246,
89603 197,64,33,38,32,153,255,240,3,191,169,247,132,242,214,240,185,255,226,235,
89604 241,239,2,63,255,0,59,254,31,255,0,3,186,68,89,115,111,16,63,134,47,254,71,
89605 223,34,255,224,244,242,117,242,41,15,0,15,8,66,239,254,68,70,47,1,54,33,36,
89606 255,231,153,111,95,102,159,255,12,6,154,254,0,
89607 };
89608 #else
89609 /* IdentifierPart production with IdentifierStart, ASCII, and non-BMP excluded */
89610 /* duk_unicode_idp_m_ids_noabmp[] */
89611 /*
89612  *  Automatically generated by extract_chars.py, do not edit!
89613  */
89614 
89615 const duk_uint8_t duk_unicode_idp_m_ids_noabmp[358] = {
89616 255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
89617 245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,241,67,40,34,
89618 36,241,210,246,173,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,
89619 160,177,57,240,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,240,
89620 97,57,181,34,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,9,
89621 240,35,242,198,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,35,
89622 242,145,38,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,215,
89623 41,244,144,53,33,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,
89624 245,111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,
89625 241,241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,
89626 242,244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,
89627 57,241,237,242,47,4,153,121,246,130,47,5,80,82,50,251,143,42,36,255,225,0,
89628 31,35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,
89629 31,255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,
89630 242,79,2,185,127,2,240,9,240,231,240,188,241,227,242,29,240,25,192,185,242,
89631 29,208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,
89632 225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,0,
89633 };
89634 #endif
89635 
89636 /*
89637  *  Case conversion tables generated using tools/extract_caseconv.py.
89638  */
89639 
89640 /* duk_unicode_caseconv_uc[] */
89641 /* duk_unicode_caseconv_lc[] */
89642 
89643 /*
89644  *  Automatically generated by extract_caseconv.py, do not edit!
89645  */
89646 
89647 const duk_uint8_t duk_unicode_caseconv_uc[1386] = {
89648 144,3,128,3,0,184,7,192,6,192,112,35,242,199,224,64,74,192,49,32,128,162,
89649 128,108,65,1,189,129,254,131,3,173,3,136,6,7,98,7,34,68,15,12,14,140,72,30,
89650 104,28,112,32,67,0,65,4,0,138,0,128,4,1,88,65,76,83,9,252,9,248,6,28,131,4,
89651 33,4,62,0,62,16,32,124,64,124,96,48,249,0,249,64,129,243,1,243,129,3,232,3,
89652 233,1,135,216,7,218,4,15,184,15,221,2,31,114,31,200,8,62,236,63,180,8,125,
89653 224,127,224,16,251,208,255,80,33,247,193,255,160,67,246,3,247,0,135,244,7,
89654 246,1,15,240,15,244,2,33,112,33,96,32,73,160,73,108,104,176,192,176,1,121,
89655 104,0,133,2,106,183,1,58,10,31,232,63,228,38,162,1,1,1,0,48,2,102,2,100,12,
89656 4,232,4,228,64,10,88,10,81,112,23,160,23,144,96,48,96,48,64,128,104,64,104,
89657 1,128,218,0,217,130,1,206,1,205,16,3,190,3,188,36,7,228,7,224,160,17,24,17,
89658 16,144,36,112,36,96,160,110,32,110,0,128,246,64,246,6,2,48,130,48,17,4,139,
89659 4,138,54,9,132,9,130,28,19,68,19,65,128,240,8,240,4,177,234,17,234,6,3,234,
89660 35,235,33,11,26,11,25,193,150,64,150,64,50,44,236,44,235,5,76,131,76,128,
89661 94,154,6,154,0,117,57,29,57,16,122,115,58,115,35,244,239,84,239,32,169,223,
89662 233,223,130,211,200,211,200,2,167,151,167,150,21,79,107,79,104,8,112,26,
89663 208,26,192,64,56,160,56,128,192,113,128,113,1,128,249,0,248,130,2,128,1,
89664 166,4,7,240,7,238,8,177,204,177,200,16,96,49,0,48,224,128,110,64,110,1,1,
89665 51,83,213,2,0,48,35,192,35,176,64,77,32,50,192,139,73,196,49,193,127,48,2,
89666 212,14,112,3,252,5,224,4,196,1,36,5,252,1,76,6,0,9,12,6,72,6,68,6,84,7,216,
89667 6,100,6,96,6,104,8,244,6,120,8,128,6,160,6,156,6,252,7,220,7,116,6,56,7,
89668 204,7,196,9,64,177,188,9,68,177,180,9,72,177,192,9,76,6,4,9,80,6,24,9,100,
89669 6,60,9,108,6,64,9,114,158,172,9,128,6,76,9,134,158,176,9,140,6,80,9,150,
89670 158,52,9,160,6,92,9,172,177,136,9,178,158,180,9,196,177,184,9,200,6,116,9,
89671 212,6,124,9,244,177,144,10,30,158,196,10,32,6,184,10,36,9,16,10,48,9,20,10,
89672 72,6,220,10,118,158,200,10,122,158,192,13,20,14,100,13,220,13,216,14,176,
89673 14,24,15,8,14,140,15,48,14,48,15,64,14,72,15,68,14,96,15,84,14,152,15,88,
89674 14,128,15,92,15,60,15,192,14,104,15,196,14,132,15,200,15,228,15,204,13,252,
89675 15,212,14,84,19,60,19,0,114,0,16,72,114,4,16,80,114,8,16,120,114,20,16,136,
89676 114,24,16,168,114,28,17,136,114,34,153,40,117,230,157,244,117,244,177,140,
89677 122,108,121,128,126,248,14,100,127,148,127,176,133,56,132,200,134,16,134,
89678 12,177,132,177,128,177,148,8,232,177,152,8,248,179,204,179,202,158,50,158,
89679 46,173,78,158,207,48,6,252,0,166,0,166,2,147,1,94,0,39,0,248,64,9,64,97,
89680 128,114,24,28,200,24,64,24,8,29,134,7,74,6,16,6,2,11,15,2,154,130,169,15,
89681 75,64,9,0,102,35,210,240,2,160,24,64,244,196,0,174,6,20,61,51,0,44,129,133,
89682 15,77,64,8,32,87,195,234,16,29,40,24,152,250,150,7,74,6,38,6,0,62,169,129,
89683 210,129,137,129,128,143,171,96,116,160,98,96,104,67,240,16,248,64,28,200,
89684 252,12,62,18,7,50,63,5,15,133,1,204,143,193,195,225,96,115,35,240,144,248,
89685 96,28,200,252,44,62,26,7,50,63,13,15,135,1,204,143,195,195,225,224,115,35,
89686 241,16,248,64,28,200,252,76,62,18,7,50,63,21,15,133,1,204,143,197,195,225,
89687 96,115,35,241,144,248,96,28,200,252,108,62,26,7,50,63,29,15,135,1,204,143,
89688 199,195,225,224,115,35,242,16,249,64,28,200,252,140,62,82,7,50,63,37,15,
89689 149,1,204,143,201,195,229,96,115,35,242,144,249,96,28,200,252,172,62,90,7,
89690 50,63,45,15,151,1,204,143,203,195,229,224,115,35,243,16,249,64,28,200,252,
89691 204,62,82,7,50,63,53,15,149,1,204,143,205,195,229,96,115,35,243,144,249,96,
89692 28,200,252,236,62,90,7,50,63,61,15,151,1,204,143,207,195,229,224,115,35,
89693 244,16,251,64,28,200,253,12,62,210,7,50,63,69,15,181,1,204,143,209,195,237,
89694 96,115,35,244,144,251,96,28,200,253,44,62,218,7,50,63,77,15,183,1,204,143,
89695 211,195,237,224,115,35,245,16,251,64,28,200,253,76,62,210,7,50,63,85,15,
89696 181,1,204,143,213,195,237,96,115,35,245,144,251,96,28,200,253,108,62,218,7,
89697 50,63,93,15,183,1,204,143,215,195,237,224,115,35,246,80,253,208,28,200,253,
89698 156,7,34,7,50,63,105,1,195,1,204,143,219,64,114,32,104,67,246,248,28,136,
89699 26,16,28,200,253,228,7,34,7,50,63,133,15,229,1,204,143,225,192,114,224,115,
89700 35,248,144,28,72,28,200,254,52,7,46,6,132,63,143,129,203,129,161,1,204,143,
89701 230,64,114,224,115,35,250,88,28,200,24,64,24,0,254,158,7,50,6,16,6,2,63,
89702 173,1,204,129,161,15,235,224,115,32,97,0,104,67,252,88,29,40,24,64,24,0,
89703 255,30,7,74,6,16,6,2,63,201,1,208,129,137,143,243,64,116,160,104,67,252,
89704 248,29,40,24,64,26,16,255,148,63,244,7,50,63,231,1,212,129,204,143,250,64,
89705 113,224,115,35,254,208,29,72,26,16,255,190,7,82,6,132,7,50,63,249,1,212,
89706 129,204,253,128,64,8,192,8,223,96,48,2,48,2,79,216,20,0,140,0,153,246,7,
89707 128,35,0,35,0,36,253,130,96,8,192,8,192,9,159,96,176,2,152,2,167,216,52,0,
89708 166,0,169,246,39,2,162,2,163,125,138,64,168,128,166,191,98,176,42,32,41,
89709 223,216,180,10,156,10,141,246,47,2,162,2,158,128,
89710 };
89711 const duk_uint8_t duk_unicode_caseconv_lc[680] = {
89712 152,3,0,3,128,184,6,192,7,192,112,24,144,37,96,64,54,32,81,64,128,226,0,
89713 235,65,129,199,1,230,130,3,145,3,177,34,7,70,7,134,36,15,244,13,236,24,32,
89714 0,34,129,0,65,0,67,4,0,166,32,172,41,132,40,11,64,19,9,208,85,184,80,19,
89715 240,19,248,12,62,16,62,0,32,124,96,124,64,48,249,64,249,0,129,243,129,243,
89716 1,3,233,3,232,1,135,218,7,216,4,15,196,15,192,8,31,152,31,144,16,63,80,63,
89717 64,32,126,224,126,192,16,253,208,251,128,33,252,129,247,32,131,251,3,250,0,
89718 135,246,135,221,129,15,244,15,240,2,31,234,31,122,4,63,240,62,240,8,127,
89719 232,125,240,17,11,1,11,129,2,75,98,77,3,69,128,5,134,11,203,31,128,143,193,
89720 127,144,255,160,154,140,4,0,4,4,192,9,144,9,152,48,19,144,19,161,0,41,64,
89721 41,101,192,94,64,94,129,128,193,0,193,130,1,160,1,161,6,3,102,3,104,8,7,44,
89722 7,48,72,14,240,14,248,144,31,32,31,48,64,63,0,63,37,0,136,128,136,196,129,
89723 35,1,35,133,3,112,3,113,4,7,176,7,178,48,17,128,17,132,136,36,80,36,89,176,
89724 76,16,76,32,224,154,0,154,44,7,128,7,128,101,143,80,15,80,176,31,89,31,81,
89725 8,88,206,88,208,12,178,0,178,5,145,103,89,103,96,42,100,10,100,18,244,208,
89726 20,208,35,169,200,169,200,195,211,153,83,153,159,167,121,167,122,5,78,253,
89727 78,254,22,158,66,158,68,21,60,181,60,184,170,123,74,123,80,67,0,211,1,64,2,
89728 1,172,1,173,4,3,136,3,140,12,7,20,7,24,16,31,184,31,192,34,199,34,199,48,
89729 65,128,195,128,196,2,1,184,1,185,5,79,84,4,204,8,0,192,101,128,154,65,1,29,
89730 129,30,2,16,199,45,39,5,251,240,23,128,15,240,24,16,37,48,24,96,37,64,24,
89731 224,29,208,24,240,37,144,25,0,37,176,25,16,25,32,25,48,38,0,25,64,38,48,25,
89732 112,38,128,25,128,25,144,25,208,39,32,25,240,39,80,26,112,26,128,26,224,40,
89733 128,27,112,41,32,31,16,31,48,31,96,25,80,31,112,27,240,34,0,25,224,35,162,
89734 198,80,35,208,25,160,35,226,198,96,36,48,24,0,36,64,40,144,36,80,40,192,55,
89735 96,55,112,55,240,63,48,56,96,58,192,56,192,60,192,60,240,61,112,63,64,59,
89736 128,63,144,63,32,76,0,76,241,233,224,13,241,251,193,251,49,252,193,252,49,
89737 254,193,254,81,255,193,255,50,18,96,60,146,18,160,6,178,18,176,14,82,19,34,
89738 20,226,24,50,24,66,198,2,198,18,198,32,38,178,198,49,215,210,198,64,39,210,
89739 198,208,37,18,198,224,39,18,198,240,37,2,199,0,37,34,207,34,207,58,119,209,
89740 215,154,120,186,120,202,120,208,38,90,122,176,37,202,122,192,38,26,122,208,
89741 38,202,123,0,41,234,123,16,40,122,123,32,41,218,123,58,181,48,32,38,16,3,
89742 72,24,56,
89743 };
89744 
89745 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
89746 /*
89747  *  Automatically generated by extract_caseconv.py, do not edit!
89748  */
89749 
89750 const duk_uint16_t duk_unicode_re_canon_lookup[65536] = {
89751 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,
89752 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,
89753 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,
89754 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,
89755 71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,123,124,125,
89756 126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
89757 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
89758 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
89759 180,924,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
89760 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
89761 216,217,218,219,220,221,222,223,192,193,194,195,196,197,198,199,200,201,
89762 202,203,204,205,206,207,208,209,210,211,212,213,214,247,216,217,218,219,
89763 220,221,222,376,256,256,258,258,260,260,262,262,264,264,266,266,268,268,
89764 270,270,272,272,274,274,276,276,278,278,280,280,282,282,284,284,286,286,
89765 288,288,290,290,292,292,294,294,296,296,298,298,300,300,302,302,304,305,
89766 306,306,308,308,310,310,312,313,313,315,315,317,317,319,319,321,321,323,
89767 323,325,325,327,327,329,330,330,332,332,334,334,336,336,338,338,340,340,
89768 342,342,344,344,346,346,348,348,350,350,352,352,354,354,356,356,358,358,
89769 360,360,362,362,364,364,366,366,368,368,370,370,372,372,374,374,376,377,
89770 377,379,379,381,381,383,579,385,386,386,388,388,390,391,391,393,394,395,
89771 395,397,398,399,400,401,401,403,404,502,406,407,408,408,573,411,412,413,
89772 544,415,416,416,418,418,420,420,422,423,423,425,426,427,428,428,430,431,
89773 431,433,434,435,435,437,437,439,440,440,442,443,444,444,446,503,448,449,
89774 450,451,452,452,452,455,455,455,458,458,458,461,461,463,463,465,465,467,
89775 467,469,469,471,471,473,473,475,475,398,478,478,480,480,482,482,484,484,
89776 486,486,488,488,490,490,492,492,494,494,496,497,497,497,500,500,502,503,
89777 504,504,506,506,508,508,510,510,512,512,514,514,516,516,518,518,520,520,
89778 522,522,524,524,526,526,528,528,530,530,532,532,534,534,536,536,538,538,
89779 540,540,542,542,544,545,546,546,548,548,550,550,552,552,554,554,556,556,
89780 558,558,560,560,562,562,564,565,566,567,568,569,570,571,571,573,574,11390,
89781 11391,577,577,579,580,581,582,582,584,584,586,586,588,588,590,590,11375,
89782 11373,11376,385,390,597,393,394,600,399,602,400,42923L,605,606,607,403,
89783 42924L,610,404,612,42893L,42922L,615,407,406,42926L,11362,42925L,621,622,
89784 412,624,11374,413,627,628,415,630,631,632,633,634,635,636,11364,638,639,
89785 422,641,642,425,644,645,646,42929L,430,580,433,434,581,653,654,655,656,657,
89786 439,659,660,661,662,663,664,665,666,667,668,42930L,42928L,671,672,673,674,
89787 675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,
89788 693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,
89789 711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,
89790 729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,
89791 747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,
89792 765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,
89793 783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,
89794 801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,
89795 819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,
89796 921,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,
89797 855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,
89798 873,874,875,876,877,878,879,880,880,882,882,884,885,886,886,888,889,890,
89799 1021,1022,1023,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,
89800 909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,
89801 927,928,929,930,931,932,933,934,935,936,937,938,939,902,904,905,906,944,
89802 913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,
89803 931,932,933,934,935,936,937,938,939,908,910,911,975,914,920,978,979,980,
89804 934,928,975,984,984,986,986,988,988,990,990,992,992,994,994,996,996,998,
89805 998,1000,1000,1002,1002,1004,1004,1006,1006,922,929,1017,895,1012,917,1014,
89806 1015,1015,1017,1018,1018,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,
89807 1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,
89808 1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,
89809 1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1040,1041,1042,
89810 1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,
89811 1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1024,
89812 1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,
89813 1120,1120,1122,1122,1124,1124,1126,1126,1128,1128,1130,1130,1132,1132,1134,
89814 1134,1136,1136,1138,1138,1140,1140,1142,1142,1144,1144,1146,1146,1148,1148,
89815 1150,1150,1152,1152,1154,1155,1156,1157,1158,1159,1160,1161,1162,1162,1164,
89816 1164,1166,1166,1168,1168,1170,1170,1172,1172,1174,1174,1176,1176,1178,1178,
89817 1180,1180,1182,1182,1184,1184,1186,1186,1188,1188,1190,1190,1192,1192,1194,
89818 1194,1196,1196,1198,1198,1200,1200,1202,1202,1204,1204,1206,1206,1208,1208,
89819 1210,1210,1212,1212,1214,1214,1216,1217,1217,1219,1219,1221,1221,1223,1223,
89820 1225,1225,1227,1227,1229,1229,1216,1232,1232,1234,1234,1236,1236,1238,1238,
89821 1240,1240,1242,1242,1244,1244,1246,1246,1248,1248,1250,1250,1252,1252,1254,
89822 1254,1256,1256,1258,1258,1260,1260,1262,1262,1264,1264,1266,1266,1268,1268,
89823 1270,1270,1272,1272,1274,1274,1276,1276,1278,1278,1280,1280,1282,1282,1284,
89824 1284,1286,1286,1288,1288,1290,1290,1292,1292,1294,1294,1296,1296,1298,1298,
89825 1300,1300,1302,1302,1304,1304,1306,1306,1308,1308,1310,1310,1312,1312,1314,
89826 1314,1316,1316,1318,1318,1320,1320,1322,1322,1324,1324,1326,1326,1328,1329,
89827 1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,
89828 1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,
89829 1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,
89830 1375,1376,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,
89831 1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,
89832 1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1415,1416,1417,1418,1419,
89833 1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,
89834 1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,
89835 1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,
89836 1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,
89837 1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,
89838 1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,
89839 1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,
89840 1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,
89841 1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,
89842 1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,
89843 1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,
89844 1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,
89845 1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,
89846 1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,
89847 1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,
89848 1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,
89849 1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,
89850 1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,
89851 1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,
89852 1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,
89853 1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,
89854 1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,
89855 1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,
89856 1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,
89857 1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,
89858 1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,
89859 1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,
89860 1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,
89861 1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,
89862 1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,
89863 1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,
89864 1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,
89865 1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,
89866 1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,
89867 1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,
89868 1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,
89869 1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,
89870 1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,
89871 1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,
89872 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,
89873 2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,
89874 2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,
89875 2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,
89876 2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,
89877 2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,
89878 2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,
89879 2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,
89880 2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,
89881 2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,
89882 2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,
89883 2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,
89884 2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,
89885 2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,
89886 2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,
89887 2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,
89888 2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,
89889 2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,
89890 2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,
89891 2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,2304,
89892 2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,
89893 2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,2334,
89894 2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,
89895 2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,
89896 2365,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,
89897 2380,2381,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,
89898 2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,
89899 2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,2424,
89900 2425,2426,2427,2428,2429,2430,2431,2432,2433,2434,2435,2436,2437,2438,2439,
89901 2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,
89902 2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,
89903 2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2480,2481,2482,2483,2484,
89904 2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,2499,
89905 2500,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,2514,
89906 2515,2516,2517,2518,2519,2520,2521,2522,2523,2524,2525,2526,2527,2528,2529,
89907 2530,2531,2532,2533,2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,2544,
89908 2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,2559,
89909 2560,2561,2562,2563,2564,2565,2566,2567,2568,2569,2570,2571,2572,2573,2574,
89910 2575,2576,2577,2578,2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,2589,
89911 2590,2591,2592,2593,2594,2595,2596,2597,2598,2599,2600,2601,2602,2603,2604,
89912 2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,
89913 2620,2621,2622,2623,2624,2625,2626,2627,2628,2629,2630,2631,2632,2633,2634,
89914 2635,2636,2637,2638,2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,2649,
89915 2650,2651,2652,2653,2654,2655,2656,2657,2658,2659,2660,2661,2662,2663,2664,
89916 2665,2666,2667,2668,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,2679,
89917 2680,2681,2682,2683,2684,2685,2686,2687,2688,2689,2690,2691,2692,2693,2694,
89918 2695,2696,2697,2698,2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,2709,
89919 2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,2724,
89920 2725,2726,2727,2728,2729,2730,2731,2732,2733,2734,2735,2736,2737,2738,2739,
89921 2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,2751,2752,2753,2754,
89922 2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,2769,
89923 2770,2771,2772,2773,2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,2784,
89924 2785,2786,2787,2788,2789,2790,2791,2792,2793,2794,2795,2796,2797,2798,2799,
89925 2800,2801,2802,2803,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,
89926 2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,
89927 2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840,2841,2842,2843,2844,
89928 2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859,
89929 2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2874,
89930 2875,2876,2877,2878,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,
89931 2890,2891,2892,2893,2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,
89932 2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,2919,
89933 2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,2931,2932,2933,2934,
89934 2935,2936,2937,2938,2939,2940,2941,2942,2943,2944,2945,2946,2947,2948,2949,
89935 2950,2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961,2962,2963,2964,
89936 2965,2966,2967,2968,2969,2970,2971,2972,2973,2974,2975,2976,2977,2978,2979,
89937 2980,2981,2982,2983,2984,2985,2986,2987,2988,2989,2990,2991,2992,2993,2994,
89938 2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3005,3006,3007,3008,3009,
89939 3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,3024,
89940 3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037,3038,3039,
89941 3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,3054,
89942 3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066,3067,3068,3069,
89943 3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,
89944 3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,
89945 3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3113,3114,
89946 3115,3116,3117,3118,3119,3120,3121,3122,3123,3124,3125,3126,3127,3128,3129,
89947 3130,3131,3132,3133,3134,3135,3136,3137,3138,3139,3140,3141,3142,3143,3144,
89948 3145,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,3159,
89949 3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,3174,
89950 3175,3176,3177,3178,3179,3180,3181,3182,3183,3184,3185,3186,3187,3188,3189,
89951 3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,3200,3201,3202,3203,3204,
89952 3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3217,3218,3219,
89953 3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,3234,
89954 3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,3249,
89955 3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,3264,
89956 3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,3278,3279,
89957 3280,3281,3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,3294,
89958 3295,3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,
89959 3310,3311,3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,3324,
89960 3325,3326,3327,3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,3339,
89961 3340,3341,3342,3343,3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,3354,
89962 3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,3369,
89963 3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,
89964 3385,3386,3387,3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,
89965 3400,3401,3402,3403,3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,3414,
89966 3415,3416,3417,3418,3419,3420,3421,3422,3423,3424,3425,3426,3427,3428,3429,
89967 3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,3444,
89968 3445,3446,3447,3448,3449,3450,3451,3452,3453,3454,3455,3456,3457,3458,3459,
89969 3460,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,
89970 3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,3489,
89971 3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,
89972 3505,3506,3507,3508,3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,3519,
89973 3520,3521,3522,3523,3524,3525,3526,3527,3528,3529,3530,3531,3532,3533,3534,
89974 3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,3549,
89975 3550,3551,3552,3553,3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,3564,
89976 3565,3566,3567,3568,3569,3570,3571,3572,3573,3574,3575,3576,3577,3578,3579,
89977 3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,
89978 3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,
89979 3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,
89980 3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,
89981 3640,3641,3642,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,
89982 3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,
89983 3670,3671,3672,3673,3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,3684,
89984 3685,3686,3687,3688,3689,3690,3691,3692,3693,3694,3695,3696,3697,3698,3699,
89985 3700,3701,3702,3703,3704,3705,3706,3707,3708,3709,3710,3711,3712,3713,3714,
89986 3715,3716,3717,3718,3719,3720,3721,3722,3723,3724,3725,3726,3727,3728,3729,
89987 3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,3744,
89988 3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,
89989 3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3774,
89990 3775,3776,3777,3778,3779,3780,3781,3782,3783,3784,3785,3786,3787,3788,3789,
89991 3790,3791,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3802,3803,3804,
89992 3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815,3816,3817,3818,3819,
89993 3820,3821,3822,3823,3824,3825,3826,3827,3828,3829,3830,3831,3832,3833,3834,
89994 3835,3836,3837,3838,3839,3840,3841,3842,3843,3844,3845,3846,3847,3848,3849,
89995 3850,3851,3852,3853,3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,3864,
89996 3865,3866,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,3879,
89997 3880,3881,3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,3892,3893,3894,
89998 3895,3896,3897,3898,3899,3900,3901,3902,3903,3904,3905,3906,3907,3908,3909,
89999 3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3924,
90000 3925,3926,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,
90001 3940,3941,3942,3943,3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,3954,
90002 3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,
90003 3970,3971,3972,3973,3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,3984,
90004 3985,3986,3987,3988,3989,3990,3991,3992,3993,3994,3995,3996,3997,3998,3999,
90005 4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,
90006 4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4029,
90007 4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,
90008 4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,4059,
90009 4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,4074,
90010 4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,
90011 4090,4091,4092,4093,4094,4095,4096,4097,4098,4099,4100,4101,4102,4103,4104,
90012 4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,4119,
90013 4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,4134,
90014 4135,4136,4137,4138,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,4149,
90015 4150,4151,4152,4153,4154,4155,4156,4157,4158,4159,4160,4161,4162,4163,4164,
90016 4165,4166,4167,4168,4169,4170,4171,4172,4173,4174,4175,4176,4177,4178,4179,
90017 4180,4181,4182,4183,4184,4185,4186,4187,4188,4189,4190,4191,4192,4193,4194,
90018 4195,4196,4197,4198,4199,4200,4201,4202,4203,4204,4205,4206,4207,4208,4209,
90019 4210,4211,4212,4213,4214,4215,4216,4217,4218,4219,4220,4221,4222,4223,4224,
90020 4225,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4238,4239,
90021 4240,4241,4242,4243,4244,4245,4246,4247,4248,4249,4250,4251,4252,4253,4254,
90022 4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,
90023 4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,
90024 4285,4286,4287,4288,4289,4290,4291,4292,4293,4294,4295,4296,4297,4298,4299,
90025 4300,4301,4302,4303,4304,4305,4306,4307,4308,4309,4310,4311,4312,4313,4314,
90026 4315,4316,4317,4318,4319,4320,4321,4322,4323,4324,4325,4326,4327,4328,4329,
90027 4330,4331,4332,4333,4334,4335,4336,4337,4338,4339,4340,4341,4342,4343,4344,
90028 4345,4346,4347,4348,4349,4350,4351,4352,4353,4354,4355,4356,4357,4358,4359,
90029 4360,4361,4362,4363,4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,4374,
90030 4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,4389,
90031 4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401,4402,4403,4404,
90032 4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416,4417,4418,4419,
90033 4420,4421,4422,4423,4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,4434,
90034 4435,4436,4437,4438,4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,4449,
90035 4450,4451,4452,4453,4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,4464,
90036 4465,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,4479,
90037 4480,4481,4482,4483,4484,4485,4486,4487,4488,4489,4490,4491,4492,4493,4494,
90038 4495,4496,4497,4498,4499,4500,4501,4502,4503,4504,4505,4506,4507,4508,4509,
90039 4510,4511,4512,4513,4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,4524,
90040 4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,4539,
90041 4540,4541,4542,4543,4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,4554,
90042 4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,4569,
90043 4570,4571,4572,4573,4574,4575,4576,4577,4578,4579,4580,4581,4582,4583,4584,
90044 4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,4599,
90045 4600,4601,4602,4603,4604,4605,4606,4607,4608,4609,4610,4611,4612,4613,4614,
90046 4615,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,4629,
90047 4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,4644,
90048 4645,4646,4647,4648,4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,4659,
90049 4660,4661,4662,4663,4664,4665,4666,4667,4668,4669,4670,4671,4672,4673,4674,
90050 4675,4676,4677,4678,4679,4680,4681,4682,4683,4684,4685,4686,4687,4688,4689,
90051 4690,4691,4692,4693,4694,4695,4696,4697,4698,4699,4700,4701,4702,4703,4704,
90052 4705,4706,4707,4708,4709,4710,4711,4712,4713,4714,4715,4716,4717,4718,4719,
90053 4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,4734,
90054 4735,4736,4737,4738,4739,4740,4741,4742,4743,4744,4745,4746,4747,4748,4749,
90055 4750,4751,4752,4753,4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,4764,
90056 4765,4766,4767,4768,4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,4779,
90057 4780,4781,4782,4783,4784,4785,4786,4787,4788,4789,4790,4791,4792,4793,4794,
90058 4795,4796,4797,4798,4799,4800,4801,4802,4803,4804,4805,4806,4807,4808,4809,
90059 4810,4811,4812,4813,4814,4815,4816,4817,4818,4819,4820,4821,4822,4823,4824,
90060 4825,4826,4827,4828,4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,4839,
90061 4840,4841,4842,4843,4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,4854,
90062 4855,4856,4857,4858,4859,4860,4861,4862,4863,4864,4865,4866,4867,4868,4869,
90063 4870,4871,4872,4873,4874,4875,4876,4877,4878,4879,4880,4881,4882,4883,4884,
90064 4885,4886,4887,4888,4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,4899,
90065 4900,4901,4902,4903,4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,4914,
90066 4915,4916,4917,4918,4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,4929,
90067 4930,4931,4932,4933,4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,4944,
90068 4945,4946,4947,4948,4949,4950,4951,4952,4953,4954,4955,4956,4957,4958,4959,
90069 4960,4961,4962,4963,4964,4965,4966,4967,4968,4969,4970,4971,4972,4973,4974,
90070 4975,4976,4977,4978,4979,4980,4981,4982,4983,4984,4985,4986,4987,4988,4989,
90071 4990,4991,4992,4993,4994,4995,4996,4997,4998,4999,5000,5001,5002,5003,5004,
90072 5005,5006,5007,5008,5009,5010,5011,5012,5013,5014,5015,5016,5017,5018,5019,
90073 5020,5021,5022,5023,5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,
90074 5035,5036,5037,5038,5039,5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,
90075 5050,5051,5052,5053,5054,5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,
90076 5065,5066,5067,5068,5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,
90077 5080,5081,5082,5083,5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,
90078 5095,5096,5097,5098,5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,5109,
90079 5110,5111,5104,5105,5106,5107,5108,5109,5118,5119,5120,5121,5122,5123,5124,
90080 5125,5126,5127,5128,5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,5139,
90081 5140,5141,5142,5143,5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,5154,
90082 5155,5156,5157,5158,5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,5169,
90083 5170,5171,5172,5173,5174,5175,5176,5177,5178,5179,5180,5181,5182,5183,5184,
90084 5185,5186,5187,5188,5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,5199,
90085 5200,5201,5202,5203,5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,5214,
90086 5215,5216,5217,5218,5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,5229,
90087 5230,5231,5232,5233,5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,
90088 5245,5246,5247,5248,5249,5250,5251,5252,5253,5254,5255,5256,5257,5258,5259,
90089 5260,5261,5262,5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,5274,
90090 5275,5276,5277,5278,5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,5289,
90091 5290,5291,5292,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,
90092 5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,
90093 5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,5334,
90094 5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,5349,
90095 5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,5364,
90096 5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379,
90097 5380,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,5394,
90098 5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,
90099 5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424,
90100 5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,
90101 5440,5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,
90102 5455,5456,5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,
90103 5470,5471,5472,5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,
90104 5485,5486,5487,5488,5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,
90105 5500,5501,5502,5503,5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,
90106 5515,5516,5517,5518,5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,5529,
90107 5530,5531,5532,5533,5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,5544,
90108 5545,5546,5547,5548,5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,5559,
90109 5560,5561,5562,5563,5564,5565,5566,5567,5568,5569,5570,5571,5572,5573,5574,
90110 5575,5576,5577,5578,5579,5580,5581,5582,5583,5584,5585,5586,5587,5588,5589,
90111 5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600,5601,5602,5603,5604,
90112 5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616,5617,5618,5619,
90113 5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632,5633,5634,
90114 5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648,5649,
90115 5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664,
90116 5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,
90117 5680,5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,
90118 5695,5696,5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,
90119 5710,5711,5712,5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,
90120 5725,5726,5727,5728,5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,
90121 5740,5741,5742,5743,5744,5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,
90122 5755,5756,5757,5758,5759,5760,5761,5762,5763,5764,5765,5766,5767,5768,5769,
90123 5770,5771,5772,5773,5774,5775,5776,5777,5778,5779,5780,5781,5782,5783,5784,
90124 5785,5786,5787,5788,5789,5790,5791,5792,5793,5794,5795,5796,5797,5798,5799,
90125 5800,5801,5802,5803,5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,5814,
90126 5815,5816,5817,5818,5819,5820,5821,5822,5823,5824,5825,5826,5827,5828,5829,
90127 5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,5844,
90128 5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,5859,
90129 5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872,5873,5874,
90130 5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888,5889,
90131 5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904,
90132 5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,
90133 5920,5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,
90134 5935,5936,5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,
90135 5950,5951,5952,5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,
90136 5965,5966,5967,5968,5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,
90137 5980,5981,5982,5983,5984,5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,
90138 5995,5996,5997,5998,5999,6000,6001,6002,6003,6004,6005,6006,6007,6008,6009,
90139 6010,6011,6012,6013,6014,6015,6016,6017,6018,6019,6020,6021,6022,6023,6024,
90140 6025,6026,6027,6028,6029,6030,6031,6032,6033,6034,6035,6036,6037,6038,6039,
90141 6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,6054,
90142 6055,6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6068,6069,
90143 6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084,
90144 6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,
90145 6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,6114,
90146 6115,6116,6117,6118,6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,6129,
90147 6130,6131,6132,6133,6134,6135,6136,6137,6138,6139,6140,6141,6142,6143,6144,
90148 6145,6146,6147,6148,6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,6159,
90149 6160,6161,6162,6163,6164,6165,6166,6167,6168,6169,6170,6171,6172,6173,6174,
90150 6175,6176,6177,6178,6179,6180,6181,6182,6183,6184,6185,6186,6187,6188,6189,
90151 6190,6191,6192,6193,6194,6195,6196,6197,6198,6199,6200,6201,6202,6203,6204,
90152 6205,6206,6207,6208,6209,6210,6211,6212,6213,6214,6215,6216,6217,6218,6219,
90153 6220,6221,6222,6223,6224,6225,6226,6227,6228,6229,6230,6231,6232,6233,6234,
90154 6235,6236,6237,6238,6239,6240,6241,6242,6243,6244,6245,6246,6247,6248,6249,
90155 6250,6251,6252,6253,6254,6255,6256,6257,6258,6259,6260,6261,6262,6263,6264,
90156 6265,6266,6267,6268,6269,6270,6271,6272,6273,6274,6275,6276,6277,6278,6279,
90157 6280,6281,6282,6283,6284,6285,6286,6287,6288,6289,6290,6291,6292,6293,6294,
90158 6295,6296,6297,6298,6299,6300,6301,6302,6303,6304,6305,6306,6307,6308,6309,
90159 6310,6311,6312,6313,6314,6315,6316,6317,6318,6319,6320,6321,6322,6323,6324,
90160 6325,6326,6327,6328,6329,6330,6331,6332,6333,6334,6335,6336,6337,6338,6339,
90161 6340,6341,6342,6343,6344,6345,6346,6347,6348,6349,6350,6351,6352,6353,6354,
90162 6355,6356,6357,6358,6359,6360,6361,6362,6363,6364,6365,6366,6367,6368,6369,
90163 6370,6371,6372,6373,6374,6375,6376,6377,6378,6379,6380,6381,6382,6383,6384,
90164 6385,6386,6387,6388,6389,6390,6391,6392,6393,6394,6395,6396,6397,6398,6399,
90165 6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,6411,6412,6413,6414,
90166 6415,6416,6417,6418,6419,6420,6421,6422,6423,6424,6425,6426,6427,6428,6429,
90167 6430,6431,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443,6444,
90168 6445,6446,6447,6448,6449,6450,6451,6452,6453,6454,6455,6456,6457,6458,6459,
90169 6460,6461,6462,6463,6464,6465,6466,6467,6468,6469,6470,6471,6472,6473,6474,
90170 6475,6476,6477,6478,6479,6480,6481,6482,6483,6484,6485,6486,6487,6488,6489,
90171 6490,6491,6492,6493,6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,6504,
90172 6505,6506,6507,6508,6509,6510,6511,6512,6513,6514,6515,6516,6517,6518,6519,
90173 6520,6521,6522,6523,6524,6525,6526,6527,6528,6529,6530,6531,6532,6533,6534,
90174 6535,6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,6549,
90175 6550,6551,6552,6553,6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,6564,
90176 6565,6566,6567,6568,6569,6570,6571,6572,6573,6574,6575,6576,6577,6578,6579,
90177 6580,6581,6582,6583,6584,6585,6586,6587,6588,6589,6590,6591,6592,6593,6594,
90178 6595,6596,6597,6598,6599,6600,6601,6602,6603,6604,6605,6606,6607,6608,6609,
90179 6610,6611,6612,6613,6614,6615,6616,6617,6618,6619,6620,6621,6622,6623,6624,
90180 6625,6626,6627,6628,6629,6630,6631,6632,6633,6634,6635,6636,6637,6638,6639,
90181 6640,6641,6642,6643,6644,6645,6646,6647,6648,6649,6650,6651,6652,6653,6654,
90182 6655,6656,6657,6658,6659,6660,6661,6662,6663,6664,6665,6666,6667,6668,6669,
90183 6670,6671,6672,6673,6674,6675,6676,6677,6678,6679,6680,6681,6682,6683,6684,
90184 6685,6686,6687,6688,6689,6690,6691,6692,6693,6694,6695,6696,6697,6698,6699,
90185 6700,6701,6702,6703,6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,6714,
90186 6715,6716,6717,6718,6719,6720,6721,6722,6723,6724,6725,6726,6727,6728,6729,
90187 6730,6731,6732,6733,6734,6735,6736,6737,6738,6739,6740,6741,6742,6743,6744,
90188 6745,6746,6747,6748,6749,6750,6751,6752,6753,6754,6755,6756,6757,6758,6759,
90189 6760,6761,6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,
90190 6775,6776,6777,6778,6779,6780,6781,6782,6783,6784,6785,6786,6787,6788,6789,
90191 6790,6791,6792,6793,6794,6795,6796,6797,6798,6799,6800,6801,6802,6803,6804,
90192 6805,6806,6807,6808,6809,6810,6811,6812,6813,6814,6815,6816,6817,6818,6819,
90193 6820,6821,6822,6823,6824,6825,6826,6827,6828,6829,6830,6831,6832,6833,6834,
90194 6835,6836,6837,6838,6839,6840,6841,6842,6843,6844,6845,6846,6847,6848,6849,
90195 6850,6851,6852,6853,6854,6855,6856,6857,6858,6859,6860,6861,6862,6863,6864,
90196 6865,6866,6867,6868,6869,6870,6871,6872,6873,6874,6875,6876,6877,6878,6879,
90197 6880,6881,6882,6883,6884,6885,6886,6887,6888,6889,6890,6891,6892,6893,6894,
90198 6895,6896,6897,6898,6899,6900,6901,6902,6903,6904,6905,6906,6907,6908,6909,
90199 6910,6911,6912,6913,6914,6915,6916,6917,6918,6919,6920,6921,6922,6923,6924,
90200 6925,6926,6927,6928,6929,6930,6931,6932,6933,6934,6935,6936,6937,6938,6939,
90201 6940,6941,6942,6943,6944,6945,6946,6947,6948,6949,6950,6951,6952,6953,6954,
90202 6955,6956,6957,6958,6959,6960,6961,6962,6963,6964,6965,6966,6967,6968,6969,
90203 6970,6971,6972,6973,6974,6975,6976,6977,6978,6979,6980,6981,6982,6983,6984,
90204 6985,6986,6987,6988,6989,6990,6991,6992,6993,6994,6995,6996,6997,6998,6999,
90205 7000,7001,7002,7003,7004,7005,7006,7007,7008,7009,7010,7011,7012,7013,7014,
90206 7015,7016,7017,7018,7019,7020,7021,7022,7023,7024,7025,7026,7027,7028,7029,
90207 7030,7031,7032,7033,7034,7035,7036,7037,7038,7039,7040,7041,7042,7043,7044,
90208 7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,7059,
90209 7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,7071,7072,7073,7074,
90210 7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7086,7087,7088,7089,
90211 7090,7091,7092,7093,7094,7095,7096,7097,7098,7099,7100,7101,7102,7103,7104,
90212 7105,7106,7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,7119,
90213 7120,7121,7122,7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,7134,
90214 7135,7136,7137,7138,7139,7140,7141,7142,7143,7144,7145,7146,7147,7148,7149,
90215 7150,7151,7152,7153,7154,7155,7156,7157,7158,7159,7160,7161,7162,7163,7164,
90216 7165,7166,7167,7168,7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,7179,
90217 7180,7181,7182,7183,7184,7185,7186,7187,7188,7189,7190,7191,7192,7193,7194,
90218 7195,7196,7197,7198,7199,7200,7201,7202,7203,7204,7205,7206,7207,7208,7209,
90219 7210,7211,7212,7213,7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,7224,
90220 7225,7226,7227,7228,7229,7230,7231,7232,7233,7234,7235,7236,7237,7238,7239,
90221 7240,7241,7242,7243,7244,7245,7246,7247,7248,7249,7250,7251,7252,7253,7254,
90222 7255,7256,7257,7258,7259,7260,7261,7262,7263,7264,7265,7266,7267,7268,7269,
90223 7270,7271,7272,7273,7274,7275,7276,7277,7278,7279,7280,7281,7282,7283,7284,
90224 7285,7286,7287,7288,7289,7290,7291,7292,7293,7294,7295,1042,1044,1054,1057,
90225 1058,1058,1066,1122,42570L,7305,7306,7307,7308,7309,7310,7311,7312,7313,
90226 7314,7315,7316,7317,7318,7319,7320,7321,7322,7323,7324,7325,7326,7327,7328,
90227 7329,7330,7331,7332,7333,7334,7335,7336,7337,7338,7339,7340,7341,7342,7343,
90228 7344,7345,7346,7347,7348,7349,7350,7351,7352,7353,7354,7355,7356,7357,7358,
90229 7359,7360,7361,7362,7363,7364,7365,7366,7367,7368,7369,7370,7371,7372,7373,
90230 7374,7375,7376,7377,7378,7379,7380,7381,7382,7383,7384,7385,7386,7387,7388,
90231 7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400,7401,7402,7403,
90232 7404,7405,7406,7407,7408,7409,7410,7411,7412,7413,7414,7415,7416,7417,7418,
90233 7419,7420,7421,7422,7423,7424,7425,7426,7427,7428,7429,7430,7431,7432,7433,
90234 7434,7435,7436,7437,7438,7439,7440,7441,7442,7443,7444,7445,7446,7447,7448,
90235 7449,7450,7451,7452,7453,7454,7455,7456,7457,7458,7459,7460,7461,7462,7463,
90236 7464,7465,7466,7467,7468,7469,7470,7471,7472,7473,7474,7475,7476,7477,7478,
90237 7479,7480,7481,7482,7483,7484,7485,7486,7487,7488,7489,7490,7491,7492,7493,
90238 7494,7495,7496,7497,7498,7499,7500,7501,7502,7503,7504,7505,7506,7507,7508,
90239 7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519,7520,7521,7522,7523,
90240 7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535,7536,7537,7538,
90241 7539,7540,7541,7542,7543,7544,42877L,7546,7547,7548,11363,7550,7551,7552,
90242 7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,7566,7567,
90243 7568,7569,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,7580,7581,7582,
90244 7583,7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,7595,7596,7597,
90245 7598,7599,7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,7610,7611,7612,
90246 7613,7614,7615,7616,7617,7618,7619,7620,7621,7622,7623,7624,7625,7626,7627,
90247 7628,7629,7630,7631,7632,7633,7634,7635,7636,7637,7638,7639,7640,7641,7642,
90248 7643,7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,7655,7656,7657,
90249 7658,7659,7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,7670,7671,7672,
90250 7673,7674,7675,7676,7677,7678,7679,7680,7680,7682,7682,7684,7684,7686,7686,
90251 7688,7688,7690,7690,7692,7692,7694,7694,7696,7696,7698,7698,7700,7700,7702,
90252 7702,7704,7704,7706,7706,7708,7708,7710,7710,7712,7712,7714,7714,7716,7716,
90253 7718,7718,7720,7720,7722,7722,7724,7724,7726,7726,7728,7728,7730,7730,7732,
90254 7732,7734,7734,7736,7736,7738,7738,7740,7740,7742,7742,7744,7744,7746,7746,
90255 7748,7748,7750,7750,7752,7752,7754,7754,7756,7756,7758,7758,7760,7760,7762,
90256 7762,7764,7764,7766,7766,7768,7768,7770,7770,7772,7772,7774,7774,7776,7776,
90257 7778,7778,7780,7780,7782,7782,7784,7784,7786,7786,7788,7788,7790,7790,7792,
90258 7792,7794,7794,7796,7796,7798,7798,7800,7800,7802,7802,7804,7804,7806,7806,
90259 7808,7808,7810,7810,7812,7812,7814,7814,7816,7816,7818,7818,7820,7820,7822,
90260 7822,7824,7824,7826,7826,7828,7828,7830,7831,7832,7833,7834,7776,7836,7837,
90261 7838,7839,7840,7840,7842,7842,7844,7844,7846,7846,7848,7848,7850,7850,7852,
90262 7852,7854,7854,7856,7856,7858,7858,7860,7860,7862,7862,7864,7864,7866,7866,
90263 7868,7868,7870,7870,7872,7872,7874,7874,7876,7876,7878,7878,7880,7880,7882,
90264 7882,7884,7884,7886,7886,7888,7888,7890,7890,7892,7892,7894,7894,7896,7896,
90265 7898,7898,7900,7900,7902,7902,7904,7904,7906,7906,7908,7908,7910,7910,7912,
90266 7912,7914,7914,7916,7916,7918,7918,7920,7920,7922,7922,7924,7924,7926,7926,
90267 7928,7928,7930,7930,7932,7932,7934,7934,7944,7945,7946,7947,7948,7949,7950,
90268 7951,7944,7945,7946,7947,7948,7949,7950,7951,7960,7961,7962,7963,7964,7965,
90269 7958,7959,7960,7961,7962,7963,7964,7965,7966,7967,7976,7977,7978,7979,7980,
90270 7981,7982,7983,7976,7977,7978,7979,7980,7981,7982,7983,7992,7993,7994,7995,
90271 7996,7997,7998,7999,7992,7993,7994,7995,7996,7997,7998,7999,8008,8009,8010,
90272 8011,8012,8013,8006,8007,8008,8009,8010,8011,8012,8013,8014,8015,8016,8025,
90273 8018,8027,8020,8029,8022,8031,8024,8025,8026,8027,8028,8029,8030,8031,8040,
90274 8041,8042,8043,8044,8045,8046,8047,8040,8041,8042,8043,8044,8045,8046,8047,
90275 8122,8123,8136,8137,8138,8139,8154,8155,8184,8185,8170,8171,8186,8187,8062,
90276 8063,8064,8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,8075,8076,8077,
90277 8078,8079,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,
90278 8093,8094,8095,8096,8097,8098,8099,8100,8101,8102,8103,8104,8105,8106,8107,
90279 8108,8109,8110,8111,8120,8121,8114,8115,8116,8117,8118,8119,8120,8121,8122,
90280 8123,8124,8125,921,8127,8128,8129,8130,8131,8132,8133,8134,8135,8136,8137,
90281 8138,8139,8140,8141,8142,8143,8152,8153,8146,8147,8148,8149,8150,8151,8152,
90282 8153,8154,8155,8156,8157,8158,8159,8168,8169,8162,8163,8164,8172,8166,8167,
90283 8168,8169,8170,8171,8172,8173,8174,8175,8176,8177,8178,8179,8180,8181,8182,
90284 8183,8184,8185,8186,8187,8188,8189,8190,8191,8192,8193,8194,8195,8196,8197,
90285 8198,8199,8200,8201,8202,8203,8204,8205,8206,8207,8208,8209,8210,8211,8212,
90286 8213,8214,8215,8216,8217,8218,8219,8220,8221,8222,8223,8224,8225,8226,8227,
90287 8228,8229,8230,8231,8232,8233,8234,8235,8236,8237,8238,8239,8240,8241,8242,
90288 8243,8244,8245,8246,8247,8248,8249,8250,8251,8252,8253,8254,8255,8256,8257,
90289 8258,8259,8260,8261,8262,8263,8264,8265,8266,8267,8268,8269,8270,8271,8272,
90290 8273,8274,8275,8276,8277,8278,8279,8280,8281,8282,8283,8284,8285,8286,8287,
90291 8288,8289,8290,8291,8292,8293,8294,8295,8296,8297,8298,8299,8300,8301,8302,
90292 8303,8304,8305,8306,8307,8308,8309,8310,8311,8312,8313,8314,8315,8316,8317,
90293 8318,8319,8320,8321,8322,8323,8324,8325,8326,8327,8328,8329,8330,8331,8332,
90294 8333,8334,8335,8336,8337,8338,8339,8340,8341,8342,8343,8344,8345,8346,8347,
90295 8348,8349,8350,8351,8352,8353,8354,8355,8356,8357,8358,8359,8360,8361,8362,
90296 8363,8364,8365,8366,8367,8368,8369,8370,8371,8372,8373,8374,8375,8376,8377,
90297 8378,8379,8380,8381,8382,8383,8384,8385,8386,8387,8388,8389,8390,8391,8392,
90298 8393,8394,8395,8396,8397,8398,8399,8400,8401,8402,8403,8404,8405,8406,8407,
90299 8408,8409,8410,8411,8412,8413,8414,8415,8416,8417,8418,8419,8420,8421,8422,
90300 8423,8424,8425,8426,8427,8428,8429,8430,8431,8432,8433,8434,8435,8436,8437,
90301 8438,8439,8440,8441,8442,8443,8444,8445,8446,8447,8448,8449,8450,8451,8452,
90302 8453,8454,8455,8456,8457,8458,8459,8460,8461,8462,8463,8464,8465,8466,8467,
90303 8468,8469,8470,8471,8472,8473,8474,8475,8476,8477,8478,8479,8480,8481,8482,
90304 8483,8484,8485,8486,8487,8488,8489,8490,8491,8492,8493,8494,8495,8496,8497,
90305 8498,8499,8500,8501,8502,8503,8504,8505,8506,8507,8508,8509,8510,8511,8512,
90306 8513,8514,8515,8516,8517,8518,8519,8520,8521,8522,8523,8524,8525,8498,8527,
90307 8528,8529,8530,8531,8532,8533,8534,8535,8536,8537,8538,8539,8540,8541,8542,
90308 8543,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,8556,8557,
90309 8558,8559,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,8556,
90310 8557,8558,8559,8576,8577,8578,8579,8579,8581,8582,8583,8584,8585,8586,8587,
90311 8588,8589,8590,8591,8592,8593,8594,8595,8596,8597,8598,8599,8600,8601,8602,
90312 8603,8604,8605,8606,8607,8608,8609,8610,8611,8612,8613,8614,8615,8616,8617,
90313 8618,8619,8620,8621,8622,8623,8624,8625,8626,8627,8628,8629,8630,8631,8632,
90314 8633,8634,8635,8636,8637,8638,8639,8640,8641,8642,8643,8644,8645,8646,8647,
90315 8648,8649,8650,8651,8652,8653,8654,8655,8656,8657,8658,8659,8660,8661,8662,
90316 8663,8664,8665,8666,8667,8668,8669,8670,8671,8672,8673,8674,8675,8676,8677,
90317 8678,8679,8680,8681,8682,8683,8684,8685,8686,8687,8688,8689,8690,8691,8692,
90318 8693,8694,8695,8696,8697,8698,8699,8700,8701,8702,8703,8704,8705,8706,8707,
90319 8708,8709,8710,8711,8712,8713,8714,8715,8716,8717,8718,8719,8720,8721,8722,
90320 8723,8724,8725,8726,8727,8728,8729,8730,8731,8732,8733,8734,8735,8736,8737,
90321 8738,8739,8740,8741,8742,8743,8744,8745,8746,8747,8748,8749,8750,8751,8752,
90322 8753,8754,8755,8756,8757,8758,8759,8760,8761,8762,8763,8764,8765,8766,8767,
90323 8768,8769,8770,8771,8772,8773,8774,8775,8776,8777,8778,8779,8780,8781,8782,
90324 8783,8784,8785,8786,8787,8788,8789,8790,8791,8792,8793,8794,8795,8796,8797,
90325 8798,8799,8800,8801,8802,8803,8804,8805,8806,8807,8808,8809,8810,8811,8812,
90326 8813,8814,8815,8816,8817,8818,8819,8820,8821,8822,8823,8824,8825,8826,8827,
90327 8828,8829,8830,8831,8832,8833,8834,8835,8836,8837,8838,8839,8840,8841,8842,
90328 8843,8844,8845,8846,8847,8848,8849,8850,8851,8852,8853,8854,8855,8856,8857,
90329 8858,8859,8860,8861,8862,8863,8864,8865,8866,8867,8868,8869,8870,8871,8872,
90330 8873,8874,8875,8876,8877,8878,8879,8880,8881,8882,8883,8884,8885,8886,8887,
90331 8888,8889,8890,8891,8892,8893,8894,8895,8896,8897,8898,8899,8900,8901,8902,
90332 8903,8904,8905,8906,8907,8908,8909,8910,8911,8912,8913,8914,8915,8916,8917,
90333 8918,8919,8920,8921,8922,8923,8924,8925,8926,8927,8928,8929,8930,8931,8932,
90334 8933,8934,8935,8936,8937,8938,8939,8940,8941,8942,8943,8944,8945,8946,8947,
90335 8948,8949,8950,8951,8952,8953,8954,8955,8956,8957,8958,8959,8960,8961,8962,
90336 8963,8964,8965,8966,8967,8968,8969,8970,8971,8972,8973,8974,8975,8976,8977,
90337 8978,8979,8980,8981,8982,8983,8984,8985,8986,8987,8988,8989,8990,8991,8992,
90338 8993,8994,8995,8996,8997,8998,8999,9000,9001,9002,9003,9004,9005,9006,9007,
90339 9008,9009,9010,9011,9012,9013,9014,9015,9016,9017,9018,9019,9020,9021,9022,
90340 9023,9024,9025,9026,9027,9028,9029,9030,9031,9032,9033,9034,9035,9036,9037,
90341 9038,9039,9040,9041,9042,9043,9044,9045,9046,9047,9048,9049,9050,9051,9052,
90342 9053,9054,9055,9056,9057,9058,9059,9060,9061,9062,9063,9064,9065,9066,9067,
90343 9068,9069,9070,9071,9072,9073,9074,9075,9076,9077,9078,9079,9080,9081,9082,
90344 9083,9084,9085,9086,9087,9088,9089,9090,9091,9092,9093,9094,9095,9096,9097,
90345 9098,9099,9100,9101,9102,9103,9104,9105,9106,9107,9108,9109,9110,9111,9112,
90346 9113,9114,9115,9116,9117,9118,9119,9120,9121,9122,9123,9124,9125,9126,9127,
90347 9128,9129,9130,9131,9132,9133,9134,9135,9136,9137,9138,9139,9140,9141,9142,
90348 9143,9144,9145,9146,9147,9148,9149,9150,9151,9152,9153,9154,9155,9156,9157,
90349 9158,9159,9160,9161,9162,9163,9164,9165,9166,9167,9168,9169,9170,9171,9172,
90350 9173,9174,9175,9176,9177,9178,9179,9180,9181,9182,9183,9184,9185,9186,9187,
90351 9188,9189,9190,9191,9192,9193,9194,9195,9196,9197,9198,9199,9200,9201,9202,
90352 9203,9204,9205,9206,9207,9208,9209,9210,9211,9212,9213,9214,9215,9216,9217,
90353 9218,9219,9220,9221,9222,9223,9224,9225,9226,9227,9228,9229,9230,9231,9232,
90354 9233,9234,9235,9236,9237,9238,9239,9240,9241,9242,9243,9244,9245,9246,9247,
90355 9248,9249,9250,9251,9252,9253,9254,9255,9256,9257,9258,9259,9260,9261,9262,
90356 9263,9264,9265,9266,9267,9268,9269,9270,9271,9272,9273,9274,9275,9276,9277,
90357 9278,9279,9280,9281,9282,9283,9284,9285,9286,9287,9288,9289,9290,9291,9292,
90358 9293,9294,9295,9296,9297,9298,9299,9300,9301,9302,9303,9304,9305,9306,9307,
90359 9308,9309,9310,9311,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9322,
90360 9323,9324,9325,9326,9327,9328,9329,9330,9331,9332,9333,9334,9335,9336,9337,
90361 9338,9339,9340,9341,9342,9343,9344,9345,9346,9347,9348,9349,9350,9351,9352,
90362 9353,9354,9355,9356,9357,9358,9359,9360,9361,9362,9363,9364,9365,9366,9367,
90363 9368,9369,9370,9371,9372,9373,9374,9375,9376,9377,9378,9379,9380,9381,9382,
90364 9383,9384,9385,9386,9387,9388,9389,9390,9391,9392,9393,9394,9395,9396,9397,
90365 9398,9399,9400,9401,9402,9403,9404,9405,9406,9407,9408,9409,9410,9411,9412,
90366 9413,9414,9415,9416,9417,9418,9419,9420,9421,9422,9423,9398,9399,9400,9401,
90367 9402,9403,9404,9405,9406,9407,9408,9409,9410,9411,9412,9413,9414,9415,9416,
90368 9417,9418,9419,9420,9421,9422,9423,9450,9451,9452,9453,9454,9455,9456,9457,
90369 9458,9459,9460,9461,9462,9463,9464,9465,9466,9467,9468,9469,9470,9471,9472,
90370 9473,9474,9475,9476,9477,9478,9479,9480,9481,9482,9483,9484,9485,9486,9487,
90371 9488,9489,9490,9491,9492,9493,9494,9495,9496,9497,9498,9499,9500,9501,9502,
90372 9503,9504,9505,9506,9507,9508,9509,9510,9511,9512,9513,9514,9515,9516,9517,
90373 9518,9519,9520,9521,9522,9523,9524,9525,9526,9527,9528,9529,9530,9531,9532,
90374 9533,9534,9535,9536,9537,9538,9539,9540,9541,9542,9543,9544,9545,9546,9547,
90375 9548,9549,9550,9551,9552,9553,9554,9555,9556,9557,9558,9559,9560,9561,9562,
90376 9563,9564,9565,9566,9567,9568,9569,9570,9571,9572,9573,9574,9575,9576,9577,
90377 9578,9579,9580,9581,9582,9583,9584,9585,9586,9587,9588,9589,9590,9591,9592,
90378 9593,9594,9595,9596,9597,9598,9599,9600,9601,9602,9603,9604,9605,9606,9607,
90379 9608,9609,9610,9611,9612,9613,9614,9615,9616,9617,9618,9619,9620,9621,9622,
90380 9623,9624,9625,9626,9627,9628,9629,9630,9631,9632,9633,9634,9635,9636,9637,
90381 9638,9639,9640,9641,9642,9643,9644,9645,9646,9647,9648,9649,9650,9651,9652,
90382 9653,9654,9655,9656,9657,9658,9659,9660,9661,9662,9663,9664,9665,9666,9667,
90383 9668,9669,9670,9671,9672,9673,9674,9675,9676,9677,9678,9679,9680,9681,9682,
90384 9683,9684,9685,9686,9687,9688,9689,9690,9691,9692,9693,9694,9695,9696,9697,
90385 9698,9699,9700,9701,9702,9703,9704,9705,9706,9707,9708,9709,9710,9711,9712,
90386 9713,9714,9715,9716,9717,9718,9719,9720,9721,9722,9723,9724,9725,9726,9727,
90387 9728,9729,9730,9731,9732,9733,9734,9735,9736,9737,9738,9739,9740,9741,9742,
90388 9743,9744,9745,9746,9747,9748,9749,9750,9751,9752,9753,9754,9755,9756,9757,
90389 9758,9759,9760,9761,9762,9763,9764,9765,9766,9767,9768,9769,9770,9771,9772,
90390 9773,9774,9775,9776,9777,9778,9779,9780,9781,9782,9783,9784,9785,9786,9787,
90391 9788,9789,9790,9791,9792,9793,9794,9795,9796,9797,9798,9799,9800,9801,9802,
90392 9803,9804,9805,9806,9807,9808,9809,9810,9811,9812,9813,9814,9815,9816,9817,
90393 9818,9819,9820,9821,9822,9823,9824,9825,9826,9827,9828,9829,9830,9831,9832,
90394 9833,9834,9835,9836,9837,9838,9839,9840,9841,9842,9843,9844,9845,9846,9847,
90395 9848,9849,9850,9851,9852,9853,9854,9855,9856,9857,9858,9859,9860,9861,9862,
90396 9863,9864,9865,9866,9867,9868,9869,9870,9871,9872,9873,9874,9875,9876,9877,
90397 9878,9879,9880,9881,9882,9883,9884,9885,9886,9887,9888,9889,9890,9891,9892,
90398 9893,9894,9895,9896,9897,9898,9899,9900,9901,9902,9903,9904,9905,9906,9907,
90399 9908,9909,9910,9911,9912,9913,9914,9915,9916,9917,9918,9919,9920,9921,9922,
90400 9923,9924,9925,9926,9927,9928,9929,9930,9931,9932,9933,9934,9935,9936,9937,
90401 9938,9939,9940,9941,9942,9943,9944,9945,9946,9947,9948,9949,9950,9951,9952,
90402 9953,9954,9955,9956,9957,9958,9959,9960,9961,9962,9963,9964,9965,9966,9967,
90403 9968,9969,9970,9971,9972,9973,9974,9975,9976,9977,9978,9979,9980,9981,9982,
90404 9983,9984,9985,9986,9987,9988,9989,9990,9991,9992,9993,9994,9995,9996,9997,
90405 9998,9999,10000,10001,10002,10003,10004,10005,10006,10007,10008,10009,
90406 10010,10011,10012,10013,10014,10015,10016,10017,10018,10019,10020,10021,
90407 10022,10023,10024,10025,10026,10027,10028,10029,10030,10031,10032,10033,
90408 10034,10035,10036,10037,10038,10039,10040,10041,10042,10043,10044,10045,
90409 10046,10047,10048,10049,10050,10051,10052,10053,10054,10055,10056,10057,
90410 10058,10059,10060,10061,10062,10063,10064,10065,10066,10067,10068,10069,
90411 10070,10071,10072,10073,10074,10075,10076,10077,10078,10079,10080,10081,
90412 10082,10083,10084,10085,10086,10087,10088,10089,10090,10091,10092,10093,
90413 10094,10095,10096,10097,10098,10099,10100,10101,10102,10103,10104,10105,
90414 10106,10107,10108,10109,10110,10111,10112,10113,10114,10115,10116,10117,
90415 10118,10119,10120,10121,10122,10123,10124,10125,10126,10127,10128,10129,
90416 10130,10131,10132,10133,10134,10135,10136,10137,10138,10139,10140,10141,
90417 10142,10143,10144,10145,10146,10147,10148,10149,10150,10151,10152,10153,
90418 10154,10155,10156,10157,10158,10159,10160,10161,10162,10163,10164,10165,
90419 10166,10167,10168,10169,10170,10171,10172,10173,10174,10175,10176,10177,
90420 10178,10179,10180,10181,10182,10183,10184,10185,10186,10187,10188,10189,
90421 10190,10191,10192,10193,10194,10195,10196,10197,10198,10199,10200,10201,
90422 10202,10203,10204,10205,10206,10207,10208,10209,10210,10211,10212,10213,
90423 10214,10215,10216,10217,10218,10219,10220,10221,10222,10223,10224,10225,
90424 10226,10227,10228,10229,10230,10231,10232,10233,10234,10235,10236,10237,
90425 10238,10239,10240,10241,10242,10243,10244,10245,10246,10247,10248,10249,
90426 10250,10251,10252,10253,10254,10255,10256,10257,10258,10259,10260,10261,
90427 10262,10263,10264,10265,10266,10267,10268,10269,10270,10271,10272,10273,
90428 10274,10275,10276,10277,10278,10279,10280,10281,10282,10283,10284,10285,
90429 10286,10287,10288,10289,10290,10291,10292,10293,10294,10295,10296,10297,
90430 10298,10299,10300,10301,10302,10303,10304,10305,10306,10307,10308,10309,
90431 10310,10311,10312,10313,10314,10315,10316,10317,10318,10319,10320,10321,
90432 10322,10323,10324,10325,10326,10327,10328,10329,10330,10331,10332,10333,
90433 10334,10335,10336,10337,10338,10339,10340,10341,10342,10343,10344,10345,
90434 10346,10347,10348,10349,10350,10351,10352,10353,10354,10355,10356,10357,
90435 10358,10359,10360,10361,10362,10363,10364,10365,10366,10367,10368,10369,
90436 10370,10371,10372,10373,10374,10375,10376,10377,10378,10379,10380,10381,
90437 10382,10383,10384,10385,10386,10387,10388,10389,10390,10391,10392,10393,
90438 10394,10395,10396,10397,10398,10399,10400,10401,10402,10403,10404,10405,
90439 10406,10407,10408,10409,10410,10411,10412,10413,10414,10415,10416,10417,
90440 10418,10419,10420,10421,10422,10423,10424,10425,10426,10427,10428,10429,
90441 10430,10431,10432,10433,10434,10435,10436,10437,10438,10439,10440,10441,
90442 10442,10443,10444,10445,10446,10447,10448,10449,10450,10451,10452,10453,
90443 10454,10455,10456,10457,10458,10459,10460,10461,10462,10463,10464,10465,
90444 10466,10467,10468,10469,10470,10471,10472,10473,10474,10475,10476,10477,
90445 10478,10479,10480,10481,10482,10483,10484,10485,10486,10487,10488,10489,
90446 10490,10491,10492,10493,10494,10495,10496,10497,10498,10499,10500,10501,
90447 10502,10503,10504,10505,10506,10507,10508,10509,10510,10511,10512,10513,
90448 10514,10515,10516,10517,10518,10519,10520,10521,10522,10523,10524,10525,
90449 10526,10527,10528,10529,10530,10531,10532,10533,10534,10535,10536,10537,
90450 10538,10539,10540,10541,10542,10543,10544,10545,10546,10547,10548,10549,
90451 10550,10551,10552,10553,10554,10555,10556,10557,10558,10559,10560,10561,
90452 10562,10563,10564,10565,10566,10567,10568,10569,10570,10571,10572,10573,
90453 10574,10575,10576,10577,10578,10579,10580,10581,10582,10583,10584,10585,
90454 10586,10587,10588,10589,10590,10591,10592,10593,10594,10595,10596,10597,
90455 10598,10599,10600,10601,10602,10603,10604,10605,10606,10607,10608,10609,
90456 10610,10611,10612,10613,10614,10615,10616,10617,10618,10619,10620,10621,
90457 10622,10623,10624,10625,10626,10627,10628,10629,10630,10631,10632,10633,
90458 10634,10635,10636,10637,10638,10639,10640,10641,10642,10643,10644,10645,
90459 10646,10647,10648,10649,10650,10651,10652,10653,10654,10655,10656,10657,
90460 10658,10659,10660,10661,10662,10663,10664,10665,10666,10667,10668,10669,
90461 10670,10671,10672,10673,10674,10675,10676,10677,10678,10679,10680,10681,
90462 10682,10683,10684,10685,10686,10687,10688,10689,10690,10691,10692,10693,
90463 10694,10695,10696,10697,10698,10699,10700,10701,10702,10703,10704,10705,
90464 10706,10707,10708,10709,10710,10711,10712,10713,10714,10715,10716,10717,
90465 10718,10719,10720,10721,10722,10723,10724,10725,10726,10727,10728,10729,
90466 10730,10731,10732,10733,10734,10735,10736,10737,10738,10739,10740,10741,
90467 10742,10743,10744,10745,10746,10747,10748,10749,10750,10751,10752,10753,
90468 10754,10755,10756,10757,10758,10759,10760,10761,10762,10763,10764,10765,
90469 10766,10767,10768,10769,10770,10771,10772,10773,10774,10775,10776,10777,
90470 10778,10779,10780,10781,10782,10783,10784,10785,10786,10787,10788,10789,
90471 10790,10791,10792,10793,10794,10795,10796,10797,10798,10799,10800,10801,
90472 10802,10803,10804,10805,10806,10807,10808,10809,10810,10811,10812,10813,
90473 10814,10815,10816,10817,10818,10819,10820,10821,10822,10823,10824,10825,
90474 10826,10827,10828,10829,10830,10831,10832,10833,10834,10835,10836,10837,
90475 10838,10839,10840,10841,10842,10843,10844,10845,10846,10847,10848,10849,
90476 10850,10851,10852,10853,10854,10855,10856,10857,10858,10859,10860,10861,
90477 10862,10863,10864,10865,10866,10867,10868,10869,10870,10871,10872,10873,
90478 10874,10875,10876,10877,10878,10879,10880,10881,10882,10883,10884,10885,
90479 10886,10887,10888,10889,10890,10891,10892,10893,10894,10895,10896,10897,
90480 10898,10899,10900,10901,10902,10903,10904,10905,10906,10907,10908,10909,
90481 10910,10911,10912,10913,10914,10915,10916,10917,10918,10919,10920,10921,
90482 10922,10923,10924,10925,10926,10927,10928,10929,10930,10931,10932,10933,
90483 10934,10935,10936,10937,10938,10939,10940,10941,10942,10943,10944,10945,
90484 10946,10947,10948,10949,10950,10951,10952,10953,10954,10955,10956,10957,
90485 10958,10959,10960,10961,10962,10963,10964,10965,10966,10967,10968,10969,
90486 10970,10971,10972,10973,10974,10975,10976,10977,10978,10979,10980,10981,
90487 10982,10983,10984,10985,10986,10987,10988,10989,10990,10991,10992,10993,
90488 10994,10995,10996,10997,10998,10999,11000,11001,11002,11003,11004,11005,
90489 11006,11007,11008,11009,11010,11011,11012,11013,11014,11015,11016,11017,
90490 11018,11019,11020,11021,11022,11023,11024,11025,11026,11027,11028,11029,
90491 11030,11031,11032,11033,11034,11035,11036,11037,11038,11039,11040,11041,
90492 11042,11043,11044,11045,11046,11047,11048,11049,11050,11051,11052,11053,
90493 11054,11055,11056,11057,11058,11059,11060,11061,11062,11063,11064,11065,
90494 11066,11067,11068,11069,11070,11071,11072,11073,11074,11075,11076,11077,
90495 11078,11079,11080,11081,11082,11083,11084,11085,11086,11087,11088,11089,
90496 11090,11091,11092,11093,11094,11095,11096,11097,11098,11099,11100,11101,
90497 11102,11103,11104,11105,11106,11107,11108,11109,11110,11111,11112,11113,
90498 11114,11115,11116,11117,11118,11119,11120,11121,11122,11123,11124,11125,
90499 11126,11127,11128,11129,11130,11131,11132,11133,11134,11135,11136,11137,
90500 11138,11139,11140,11141,11142,11143,11144,11145,11146,11147,11148,11149,
90501 11150,11151,11152,11153,11154,11155,11156,11157,11158,11159,11160,11161,
90502 11162,11163,11164,11165,11166,11167,11168,11169,11170,11171,11172,11173,
90503 11174,11175,11176,11177,11178,11179,11180,11181,11182,11183,11184,11185,
90504 11186,11187,11188,11189,11190,11191,11192,11193,11194,11195,11196,11197,
90505 11198,11199,11200,11201,11202,11203,11204,11205,11206,11207,11208,11209,
90506 11210,11211,11212,11213,11214,11215,11216,11217,11218,11219,11220,11221,
90507 11222,11223,11224,11225,11226,11227,11228,11229,11230,11231,11232,11233,
90508 11234,11235,11236,11237,11238,11239,11240,11241,11242,11243,11244,11245,
90509 11246,11247,11248,11249,11250,11251,11252,11253,11254,11255,11256,11257,
90510 11258,11259,11260,11261,11262,11263,11264,11265,11266,11267,11268,11269,
90511 11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,11280,11281,
90512 11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,11292,11293,
90513 11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,11304,11305,
90514 11306,11307,11308,11309,11310,11311,11264,11265,11266,11267,11268,11269,
90515 11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,11280,11281,
90516 11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,11292,11293,
90517 11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,11304,11305,
90518 11306,11307,11308,11309,11310,11359,11360,11360,11362,11363,11364,570,574,
90519 11367,11367,11369,11369,11371,11371,11373,11374,11375,11376,11377,11378,
90520 11378,11380,11381,11381,11383,11384,11385,11386,11387,11388,11389,11390,
90521 11391,11392,11392,11394,11394,11396,11396,11398,11398,11400,11400,11402,
90522 11402,11404,11404,11406,11406,11408,11408,11410,11410,11412,11412,11414,
90523 11414,11416,11416,11418,11418,11420,11420,11422,11422,11424,11424,11426,
90524 11426,11428,11428,11430,11430,11432,11432,11434,11434,11436,11436,11438,
90525 11438,11440,11440,11442,11442,11444,11444,11446,11446,11448,11448,11450,
90526 11450,11452,11452,11454,11454,11456,11456,11458,11458,11460,11460,11462,
90527 11462,11464,11464,11466,11466,11468,11468,11470,11470,11472,11472,11474,
90528 11474,11476,11476,11478,11478,11480,11480,11482,11482,11484,11484,11486,
90529 11486,11488,11488,11490,11490,11492,11493,11494,11495,11496,11497,11498,
90530 11499,11499,11501,11501,11503,11504,11505,11506,11506,11508,11509,11510,
90531 11511,11512,11513,11514,11515,11516,11517,11518,11519,4256,4257,4258,4259,
90532 4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,4272,4273,4274,
90533 4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,4287,4288,4289,
90534 4290,4291,4292,4293,11558,4295,11560,11561,11562,11563,11564,4301,11566,
90535 11567,11568,11569,11570,11571,11572,11573,11574,11575,11576,11577,11578,
90536 11579,11580,11581,11582,11583,11584,11585,11586,11587,11588,11589,11590,
90537 11591,11592,11593,11594,11595,11596,11597,11598,11599,11600,11601,11602,
90538 11603,11604,11605,11606,11607,11608,11609,11610,11611,11612,11613,11614,
90539 11615,11616,11617,11618,11619,11620,11621,11622,11623,11624,11625,11626,
90540 11627,11628,11629,11630,11631,11632,11633,11634,11635,11636,11637,11638,
90541 11639,11640,11641,11642,11643,11644,11645,11646,11647,11648,11649,11650,
90542 11651,11652,11653,11654,11655,11656,11657,11658,11659,11660,11661,11662,
90543 11663,11664,11665,11666,11667,11668,11669,11670,11671,11672,11673,11674,
90544 11675,11676,11677,11678,11679,11680,11681,11682,11683,11684,11685,11686,
90545 11687,11688,11689,11690,11691,11692,11693,11694,11695,11696,11697,11698,
90546 11699,11700,11701,11702,11703,11704,11705,11706,11707,11708,11709,11710,
90547 11711,11712,11713,11714,11715,11716,11717,11718,11719,11720,11721,11722,
90548 11723,11724,11725,11726,11727,11728,11729,11730,11731,11732,11733,11734,
90549 11735,11736,11737,11738,11739,11740,11741,11742,11743,11744,11745,11746,
90550 11747,11748,11749,11750,11751,11752,11753,11754,11755,11756,11757,11758,
90551 11759,11760,11761,11762,11763,11764,11765,11766,11767,11768,11769,11770,
90552 11771,11772,11773,11774,11775,11776,11777,11778,11779,11780,11781,11782,
90553 11783,11784,11785,11786,11787,11788,11789,11790,11791,11792,11793,11794,
90554 11795,11796,11797,11798,11799,11800,11801,11802,11803,11804,11805,11806,
90555 11807,11808,11809,11810,11811,11812,11813,11814,11815,11816,11817,11818,
90556 11819,11820,11821,11822,11823,11824,11825,11826,11827,11828,11829,11830,
90557 11831,11832,11833,11834,11835,11836,11837,11838,11839,11840,11841,11842,
90558 11843,11844,11845,11846,11847,11848,11849,11850,11851,11852,11853,11854,
90559 11855,11856,11857,11858,11859,11860,11861,11862,11863,11864,11865,11866,
90560 11867,11868,11869,11870,11871,11872,11873,11874,11875,11876,11877,11878,
90561 11879,11880,11881,11882,11883,11884,11885,11886,11887,11888,11889,11890,
90562 11891,11892,11893,11894,11895,11896,11897,11898,11899,11900,11901,11902,
90563 11903,11904,11905,11906,11907,11908,11909,11910,11911,11912,11913,11914,
90564 11915,11916,11917,11918,11919,11920,11921,11922,11923,11924,11925,11926,
90565 11927,11928,11929,11930,11931,11932,11933,11934,11935,11936,11937,11938,
90566 11939,11940,11941,11942,11943,11944,11945,11946,11947,11948,11949,11950,
90567 11951,11952,11953,11954,11955,11956,11957,11958,11959,11960,11961,11962,
90568 11963,11964,11965,11966,11967,11968,11969,11970,11971,11972,11973,11974,
90569 11975,11976,11977,11978,11979,11980,11981,11982,11983,11984,11985,11986,
90570 11987,11988,11989,11990,11991,11992,11993,11994,11995,11996,11997,11998,
90571 11999,12000,12001,12002,12003,12004,12005,12006,12007,12008,12009,12010,
90572 12011,12012,12013,12014,12015,12016,12017,12018,12019,12020,12021,12022,
90573 12023,12024,12025,12026,12027,12028,12029,12030,12031,12032,12033,12034,
90574 12035,12036,12037,12038,12039,12040,12041,12042,12043,12044,12045,12046,
90575 12047,12048,12049,12050,12051,12052,12053,12054,12055,12056,12057,12058,
90576 12059,12060,12061,12062,12063,12064,12065,12066,12067,12068,12069,12070,
90577 12071,12072,12073,12074,12075,12076,12077,12078,12079,12080,12081,12082,
90578 12083,12084,12085,12086,12087,12088,12089,12090,12091,12092,12093,12094,
90579 12095,12096,12097,12098,12099,12100,12101,12102,12103,12104,12105,12106,
90580 12107,12108,12109,12110,12111,12112,12113,12114,12115,12116,12117,12118,
90581 12119,12120,12121,12122,12123,12124,12125,12126,12127,12128,12129,12130,
90582 12131,12132,12133,12134,12135,12136,12137,12138,12139,12140,12141,12142,
90583 12143,12144,12145,12146,12147,12148,12149,12150,12151,12152,12153,12154,
90584 12155,12156,12157,12158,12159,12160,12161,12162,12163,12164,12165,12166,
90585 12167,12168,12169,12170,12171,12172,12173,12174,12175,12176,12177,12178,
90586 12179,12180,12181,12182,12183,12184,12185,12186,12187,12188,12189,12190,
90587 12191,12192,12193,12194,12195,12196,12197,12198,12199,12200,12201,12202,
90588 12203,12204,12205,12206,12207,12208,12209,12210,12211,12212,12213,12214,
90589 12215,12216,12217,12218,12219,12220,12221,12222,12223,12224,12225,12226,
90590 12227,12228,12229,12230,12231,12232,12233,12234,12235,12236,12237,12238,
90591 12239,12240,12241,12242,12243,12244,12245,12246,12247,12248,12249,12250,
90592 12251,12252,12253,12254,12255,12256,12257,12258,12259,12260,12261,12262,
90593 12263,12264,12265,12266,12267,12268,12269,12270,12271,12272,12273,12274,
90594 12275,12276,12277,12278,12279,12280,12281,12282,12283,12284,12285,12286,
90595 12287,12288,12289,12290,12291,12292,12293,12294,12295,12296,12297,12298,
90596 12299,12300,12301,12302,12303,12304,12305,12306,12307,12308,12309,12310,
90597 12311,12312,12313,12314,12315,12316,12317,12318,12319,12320,12321,12322,
90598 12323,12324,12325,12326,12327,12328,12329,12330,12331,12332,12333,12334,
90599 12335,12336,12337,12338,12339,12340,12341,12342,12343,12344,12345,12346,
90600 12347,12348,12349,12350,12351,12352,12353,12354,12355,12356,12357,12358,
90601 12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,
90602 12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,
90603 12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,
90604 12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,
90605 12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,
90606 12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,
90607 12431,12432,12433,12434,12435,12436,12437,12438,12439,12440,12441,12442,
90608 12443,12444,12445,12446,12447,12448,12449,12450,12451,12452,12453,12454,
90609 12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,
90610 12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,
90611 12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,
90612 12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,
90613 12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,
90614 12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,
90615 12527,12528,12529,12530,12531,12532,12533,12534,12535,12536,12537,12538,
90616 12539,12540,12541,12542,12543,12544,12545,12546,12547,12548,12549,12550,
90617 12551,12552,12553,12554,12555,12556,12557,12558,12559,12560,12561,12562,
90618 12563,12564,12565,12566,12567,12568,12569,12570,12571,12572,12573,12574,
90619 12575,12576,12577,12578,12579,12580,12581,12582,12583,12584,12585,12586,
90620 12587,12588,12589,12590,12591,12592,12593,12594,12595,12596,12597,12598,
90621 12599,12600,12601,12602,12603,12604,12605,12606,12607,12608,12609,12610,
90622 12611,12612,12613,12614,12615,12616,12617,12618,12619,12620,12621,12622,
90623 12623,12624,12625,12626,12627,12628,12629,12630,12631,12632,12633,12634,
90624 12635,12636,12637,12638,12639,12640,12641,12642,12643,12644,12645,12646,
90625 12647,12648,12649,12650,12651,12652,12653,12654,12655,12656,12657,12658,
90626 12659,12660,12661,12662,12663,12664,12665,12666,12667,12668,12669,12670,
90627 12671,12672,12673,12674,12675,12676,12677,12678,12679,12680,12681,12682,
90628 12683,12684,12685,12686,12687,12688,12689,12690,12691,12692,12693,12694,
90629 12695,12696,12697,12698,12699,12700,12701,12702,12703,12704,12705,12706,
90630 12707,12708,12709,12710,12711,12712,12713,12714,12715,12716,12717,12718,
90631 12719,12720,12721,12722,12723,12724,12725,12726,12727,12728,12729,12730,
90632 12731,12732,12733,12734,12735,12736,12737,12738,12739,12740,12741,12742,
90633 12743,12744,12745,12746,12747,12748,12749,12750,12751,12752,12753,12754,
90634 12755,12756,12757,12758,12759,12760,12761,12762,12763,12764,12765,12766,
90635 12767,12768,12769,12770,12771,12772,12773,12774,12775,12776,12777,12778,
90636 12779,12780,12781,12782,12783,12784,12785,12786,12787,12788,12789,12790,
90637 12791,12792,12793,12794,12795,12796,12797,12798,12799,12800,12801,12802,
90638 12803,12804,12805,12806,12807,12808,12809,12810,12811,12812,12813,12814,
90639 12815,12816,12817,12818,12819,12820,12821,12822,12823,12824,12825,12826,
90640 12827,12828,12829,12830,12831,12832,12833,12834,12835,12836,12837,12838,
90641 12839,12840,12841,12842,12843,12844,12845,12846,12847,12848,12849,12850,
90642 12851,12852,12853,12854,12855,12856,12857,12858,12859,12860,12861,12862,
90643 12863,12864,12865,12866,12867,12868,12869,12870,12871,12872,12873,12874,
90644 12875,12876,12877,12878,12879,12880,12881,12882,12883,12884,12885,12886,
90645 12887,12888,12889,12890,12891,12892,12893,12894,12895,12896,12897,12898,
90646 12899,12900,12901,12902,12903,12904,12905,12906,12907,12908,12909,12910,
90647 12911,12912,12913,12914,12915,12916,12917,12918,12919,12920,12921,12922,
90648 12923,12924,12925,12926,12927,12928,12929,12930,12931,12932,12933,12934,
90649 12935,12936,12937,12938,12939,12940,12941,12942,12943,12944,12945,12946,
90650 12947,12948,12949,12950,12951,12952,12953,12954,12955,12956,12957,12958,
90651 12959,12960,12961,12962,12963,12964,12965,12966,12967,12968,12969,12970,
90652 12971,12972,12973,12974,12975,12976,12977,12978,12979,12980,12981,12982,
90653 12983,12984,12985,12986,12987,12988,12989,12990,12991,12992,12993,12994,
90654 12995,12996,12997,12998,12999,13000,13001,13002,13003,13004,13005,13006,
90655 13007,13008,13009,13010,13011,13012,13013,13014,13015,13016,13017,13018,
90656 13019,13020,13021,13022,13023,13024,13025,13026,13027,13028,13029,13030,
90657 13031,13032,13033,13034,13035,13036,13037,13038,13039,13040,13041,13042,
90658 13043,13044,13045,13046,13047,13048,13049,13050,13051,13052,13053,13054,
90659 13055,13056,13057,13058,13059,13060,13061,13062,13063,13064,13065,13066,
90660 13067,13068,13069,13070,13071,13072,13073,13074,13075,13076,13077,13078,
90661 13079,13080,13081,13082,13083,13084,13085,13086,13087,13088,13089,13090,
90662 13091,13092,13093,13094,13095,13096,13097,13098,13099,13100,13101,13102,
90663 13103,13104,13105,13106,13107,13108,13109,13110,13111,13112,13113,13114,
90664 13115,13116,13117,13118,13119,13120,13121,13122,13123,13124,13125,13126,
90665 13127,13128,13129,13130,13131,13132,13133,13134,13135,13136,13137,13138,
90666 13139,13140,13141,13142,13143,13144,13145,13146,13147,13148,13149,13150,
90667 13151,13152,13153,13154,13155,13156,13157,13158,13159,13160,13161,13162,
90668 13163,13164,13165,13166,13167,13168,13169,13170,13171,13172,13173,13174,
90669 13175,13176,13177,13178,13179,13180,13181,13182,13183,13184,13185,13186,
90670 13187,13188,13189,13190,13191,13192,13193,13194,13195,13196,13197,13198,
90671 13199,13200,13201,13202,13203,13204,13205,13206,13207,13208,13209,13210,
90672 13211,13212,13213,13214,13215,13216,13217,13218,13219,13220,13221,13222,
90673 13223,13224,13225,13226,13227,13228,13229,13230,13231,13232,13233,13234,
90674 13235,13236,13237,13238,13239,13240,13241,13242,13243,13244,13245,13246,
90675 13247,13248,13249,13250,13251,13252,13253,13254,13255,13256,13257,13258,
90676 13259,13260,13261,13262,13263,13264,13265,13266,13267,13268,13269,13270,
90677 13271,13272,13273,13274,13275,13276,13277,13278,13279,13280,13281,13282,
90678 13283,13284,13285,13286,13287,13288,13289,13290,13291,13292,13293,13294,
90679 13295,13296,13297,13298,13299,13300,13301,13302,13303,13304,13305,13306,
90680 13307,13308,13309,13310,13311,13312,13313,13314,13315,13316,13317,13318,
90681 13319,13320,13321,13322,13323,13324,13325,13326,13327,13328,13329,13330,
90682 13331,13332,13333,13334,13335,13336,13337,13338,13339,13340,13341,13342,
90683 13343,13344,13345,13346,13347,13348,13349,13350,13351,13352,13353,13354,
90684 13355,13356,13357,13358,13359,13360,13361,13362,13363,13364,13365,13366,
90685 13367,13368,13369,13370,13371,13372,13373,13374,13375,13376,13377,13378,
90686 13379,13380,13381,13382,13383,13384,13385,13386,13387,13388,13389,13390,
90687 13391,13392,13393,13394,13395,13396,13397,13398,13399,13400,13401,13402,
90688 13403,13404,13405,13406,13407,13408,13409,13410,13411,13412,13413,13414,
90689 13415,13416,13417,13418,13419,13420,13421,13422,13423,13424,13425,13426,
90690 13427,13428,13429,13430,13431,13432,13433,13434,13435,13436,13437,13438,
90691 13439,13440,13441,13442,13443,13444,13445,13446,13447,13448,13449,13450,
90692 13451,13452,13453,13454,13455,13456,13457,13458,13459,13460,13461,13462,
90693 13463,13464,13465,13466,13467,13468,13469,13470,13471,13472,13473,13474,
90694 13475,13476,13477,13478,13479,13480,13481,13482,13483,13484,13485,13486,
90695 13487,13488,13489,13490,13491,13492,13493,13494,13495,13496,13497,13498,
90696 13499,13500,13501,13502,13503,13504,13505,13506,13507,13508,13509,13510,
90697 13511,13512,13513,13514,13515,13516,13517,13518,13519,13520,13521,13522,
90698 13523,13524,13525,13526,13527,13528,13529,13530,13531,13532,13533,13534,
90699 13535,13536,13537,13538,13539,13540,13541,13542,13543,13544,13545,13546,
90700 13547,13548,13549,13550,13551,13552,13553,13554,13555,13556,13557,13558,
90701 13559,13560,13561,13562,13563,13564,13565,13566,13567,13568,13569,13570,
90702 13571,13572,13573,13574,13575,13576,13577,13578,13579,13580,13581,13582,
90703 13583,13584,13585,13586,13587,13588,13589,13590,13591,13592,13593,13594,
90704 13595,13596,13597,13598,13599,13600,13601,13602,13603,13604,13605,13606,
90705 13607,13608,13609,13610,13611,13612,13613,13614,13615,13616,13617,13618,
90706 13619,13620,13621,13622,13623,13624,13625,13626,13627,13628,13629,13630,
90707 13631,13632,13633,13634,13635,13636,13637,13638,13639,13640,13641,13642,
90708 13643,13644,13645,13646,13647,13648,13649,13650,13651,13652,13653,13654,
90709 13655,13656,13657,13658,13659,13660,13661,13662,13663,13664,13665,13666,
90710 13667,13668,13669,13670,13671,13672,13673,13674,13675,13676,13677,13678,
90711 13679,13680,13681,13682,13683,13684,13685,13686,13687,13688,13689,13690,
90712 13691,13692,13693,13694,13695,13696,13697,13698,13699,13700,13701,13702,
90713 13703,13704,13705,13706,13707,13708,13709,13710,13711,13712,13713,13714,
90714 13715,13716,13717,13718,13719,13720,13721,13722,13723,13724,13725,13726,
90715 13727,13728,13729,13730,13731,13732,13733,13734,13735,13736,13737,13738,
90716 13739,13740,13741,13742,13743,13744,13745,13746,13747,13748,13749,13750,
90717 13751,13752,13753,13754,13755,13756,13757,13758,13759,13760,13761,13762,
90718 13763,13764,13765,13766,13767,13768,13769,13770,13771,13772,13773,13774,
90719 13775,13776,13777,13778,13779,13780,13781,13782,13783,13784,13785,13786,
90720 13787,13788,13789,13790,13791,13792,13793,13794,13795,13796,13797,13798,
90721 13799,13800,13801,13802,13803,13804,13805,13806,13807,13808,13809,13810,
90722 13811,13812,13813,13814,13815,13816,13817,13818,13819,13820,13821,13822,
90723 13823,13824,13825,13826,13827,13828,13829,13830,13831,13832,13833,13834,
90724 13835,13836,13837,13838,13839,13840,13841,13842,13843,13844,13845,13846,
90725 13847,13848,13849,13850,13851,13852,13853,13854,13855,13856,13857,13858,
90726 13859,13860,13861,13862,13863,13864,13865,13866,13867,13868,13869,13870,
90727 13871,13872,13873,13874,13875,13876,13877,13878,13879,13880,13881,13882,
90728 13883,13884,13885,13886,13887,13888,13889,13890,13891,13892,13893,13894,
90729 13895,13896,13897,13898,13899,13900,13901,13902,13903,13904,13905,13906,
90730 13907,13908,13909,13910,13911,13912,13913,13914,13915,13916,13917,13918,
90731 13919,13920,13921,13922,13923,13924,13925,13926,13927,13928,13929,13930,
90732 13931,13932,13933,13934,13935,13936,13937,13938,13939,13940,13941,13942,
90733 13943,13944,13945,13946,13947,13948,13949,13950,13951,13952,13953,13954,
90734 13955,13956,13957,13958,13959,13960,13961,13962,13963,13964,13965,13966,
90735 13967,13968,13969,13970,13971,13972,13973,13974,13975,13976,13977,13978,
90736 13979,13980,13981,13982,13983,13984,13985,13986,13987,13988,13989,13990,
90737 13991,13992,13993,13994,13995,13996,13997,13998,13999,14000,14001,14002,
90738 14003,14004,14005,14006,14007,14008,14009,14010,14011,14012,14013,14014,
90739 14015,14016,14017,14018,14019,14020,14021,14022,14023,14024,14025,14026,
90740 14027,14028,14029,14030,14031,14032,14033,14034,14035,14036,14037,14038,
90741 14039,14040,14041,14042,14043,14044,14045,14046,14047,14048,14049,14050,
90742 14051,14052,14053,14054,14055,14056,14057,14058,14059,14060,14061,14062,
90743 14063,14064,14065,14066,14067,14068,14069,14070,14071,14072,14073,14074,
90744 14075,14076,14077,14078,14079,14080,14081,14082,14083,14084,14085,14086,
90745 14087,14088,14089,14090,14091,14092,14093,14094,14095,14096,14097,14098,
90746 14099,14100,14101,14102,14103,14104,14105,14106,14107,14108,14109,14110,
90747 14111,14112,14113,14114,14115,14116,14117,14118,14119,14120,14121,14122,
90748 14123,14124,14125,14126,14127,14128,14129,14130,14131,14132,14133,14134,
90749 14135,14136,14137,14138,14139,14140,14141,14142,14143,14144,14145,14146,
90750 14147,14148,14149,14150,14151,14152,14153,14154,14155,14156,14157,14158,
90751 14159,14160,14161,14162,14163,14164,14165,14166,14167,14168,14169,14170,
90752 14171,14172,14173,14174,14175,14176,14177,14178,14179,14180,14181,14182,
90753 14183,14184,14185,14186,14187,14188,14189,14190,14191,14192,14193,14194,
90754 14195,14196,14197,14198,14199,14200,14201,14202,14203,14204,14205,14206,
90755 14207,14208,14209,14210,14211,14212,14213,14214,14215,14216,14217,14218,
90756 14219,14220,14221,14222,14223,14224,14225,14226,14227,14228,14229,14230,
90757 14231,14232,14233,14234,14235,14236,14237,14238,14239,14240,14241,14242,
90758 14243,14244,14245,14246,14247,14248,14249,14250,14251,14252,14253,14254,
90759 14255,14256,14257,14258,14259,14260,14261,14262,14263,14264,14265,14266,
90760 14267,14268,14269,14270,14271,14272,14273,14274,14275,14276,14277,14278,
90761 14279,14280,14281,14282,14283,14284,14285,14286,14287,14288,14289,14290,
90762 14291,14292,14293,14294,14295,14296,14297,14298,14299,14300,14301,14302,
90763 14303,14304,14305,14306,14307,14308,14309,14310,14311,14312,14313,14314,
90764 14315,14316,14317,14318,14319,14320,14321,14322,14323,14324,14325,14326,
90765 14327,14328,14329,14330,14331,14332,14333,14334,14335,14336,14337,14338,
90766 14339,14340,14341,14342,14343,14344,14345,14346,14347,14348,14349,14350,
90767 14351,14352,14353,14354,14355,14356,14357,14358,14359,14360,14361,14362,
90768 14363,14364,14365,14366,14367,14368,14369,14370,14371,14372,14373,14374,
90769 14375,14376,14377,14378,14379,14380,14381,14382,14383,14384,14385,14386,
90770 14387,14388,14389,14390,14391,14392,14393,14394,14395,14396,14397,14398,
90771 14399,14400,14401,14402,14403,14404,14405,14406,14407,14408,14409,14410,
90772 14411,14412,14413,14414,14415,14416,14417,14418,14419,14420,14421,14422,
90773 14423,14424,14425,14426,14427,14428,14429,14430,14431,14432,14433,14434,
90774 14435,14436,14437,14438,14439,14440,14441,14442,14443,14444,14445,14446,
90775 14447,14448,14449,14450,14451,14452,14453,14454,14455,14456,14457,14458,
90776 14459,14460,14461,14462,14463,14464,14465,14466,14467,14468,14469,14470,
90777 14471,14472,14473,14474,14475,14476,14477,14478,14479,14480,14481,14482,
90778 14483,14484,14485,14486,14487,14488,14489,14490,14491,14492,14493,14494,
90779 14495,14496,14497,14498,14499,14500,14501,14502,14503,14504,14505,14506,
90780 14507,14508,14509,14510,14511,14512,14513,14514,14515,14516,14517,14518,
90781 14519,14520,14521,14522,14523,14524,14525,14526,14527,14528,14529,14530,
90782 14531,14532,14533,14534,14535,14536,14537,14538,14539,14540,14541,14542,
90783 14543,14544,14545,14546,14547,14548,14549,14550,14551,14552,14553,14554,
90784 14555,14556,14557,14558,14559,14560,14561,14562,14563,14564,14565,14566,
90785 14567,14568,14569,14570,14571,14572,14573,14574,14575,14576,14577,14578,
90786 14579,14580,14581,14582,14583,14584,14585,14586,14587,14588,14589,14590,
90787 14591,14592,14593,14594,14595,14596,14597,14598,14599,14600,14601,14602,
90788 14603,14604,14605,14606,14607,14608,14609,14610,14611,14612,14613,14614,
90789 14615,14616,14617,14618,14619,14620,14621,14622,14623,14624,14625,14626,
90790 14627,14628,14629,14630,14631,14632,14633,14634,14635,14636,14637,14638,
90791 14639,14640,14641,14642,14643,14644,14645,14646,14647,14648,14649,14650,
90792 14651,14652,14653,14654,14655,14656,14657,14658,14659,14660,14661,14662,
90793 14663,14664,14665,14666,14667,14668,14669,14670,14671,14672,14673,14674,
90794 14675,14676,14677,14678,14679,14680,14681,14682,14683,14684,14685,14686,
90795 14687,14688,14689,14690,14691,14692,14693,14694,14695,14696,14697,14698,
90796 14699,14700,14701,14702,14703,14704,14705,14706,14707,14708,14709,14710,
90797 14711,14712,14713,14714,14715,14716,14717,14718,14719,14720,14721,14722,
90798 14723,14724,14725,14726,14727,14728,14729,14730,14731,14732,14733,14734,
90799 14735,14736,14737,14738,14739,14740,14741,14742,14743,14744,14745,14746,
90800 14747,14748,14749,14750,14751,14752,14753,14754,14755,14756,14757,14758,
90801 14759,14760,14761,14762,14763,14764,14765,14766,14767,14768,14769,14770,
90802 14771,14772,14773,14774,14775,14776,14777,14778,14779,14780,14781,14782,
90803 14783,14784,14785,14786,14787,14788,14789,14790,14791,14792,14793,14794,
90804 14795,14796,14797,14798,14799,14800,14801,14802,14803,14804,14805,14806,
90805 14807,14808,14809,14810,14811,14812,14813,14814,14815,14816,14817,14818,
90806 14819,14820,14821,14822,14823,14824,14825,14826,14827,14828,14829,14830,
90807 14831,14832,14833,14834,14835,14836,14837,14838,14839,14840,14841,14842,
90808 14843,14844,14845,14846,14847,14848,14849,14850,14851,14852,14853,14854,
90809 14855,14856,14857,14858,14859,14860,14861,14862,14863,14864,14865,14866,
90810 14867,14868,14869,14870,14871,14872,14873,14874,14875,14876,14877,14878,
90811 14879,14880,14881,14882,14883,14884,14885,14886,14887,14888,14889,14890,
90812 14891,14892,14893,14894,14895,14896,14897,14898,14899,14900,14901,14902,
90813 14903,14904,14905,14906,14907,14908,14909,14910,14911,14912,14913,14914,
90814 14915,14916,14917,14918,14919,14920,14921,14922,14923,14924,14925,14926,
90815 14927,14928,14929,14930,14931,14932,14933,14934,14935,14936,14937,14938,
90816 14939,14940,14941,14942,14943,14944,14945,14946,14947,14948,14949,14950,
90817 14951,14952,14953,14954,14955,14956,14957,14958,14959,14960,14961,14962,
90818 14963,14964,14965,14966,14967,14968,14969,14970,14971,14972,14973,14974,
90819 14975,14976,14977,14978,14979,14980,14981,14982,14983,14984,14985,14986,
90820 14987,14988,14989,14990,14991,14992,14993,14994,14995,14996,14997,14998,
90821 14999,15000,15001,15002,15003,15004,15005,15006,15007,15008,15009,15010,
90822 15011,15012,15013,15014,15015,15016,15017,15018,15019,15020,15021,15022,
90823 15023,15024,15025,15026,15027,15028,15029,15030,15031,15032,15033,15034,
90824 15035,15036,15037,15038,15039,15040,15041,15042,15043,15044,15045,15046,
90825 15047,15048,15049,15050,15051,15052,15053,15054,15055,15056,15057,15058,
90826 15059,15060,15061,15062,15063,15064,15065,15066,15067,15068,15069,15070,
90827 15071,15072,15073,15074,15075,15076,15077,15078,15079,15080,15081,15082,
90828 15083,15084,15085,15086,15087,15088,15089,15090,15091,15092,15093,15094,
90829 15095,15096,15097,15098,15099,15100,15101,15102,15103,15104,15105,15106,
90830 15107,15108,15109,15110,15111,15112,15113,15114,15115,15116,15117,15118,
90831 15119,15120,15121,15122,15123,15124,15125,15126,15127,15128,15129,15130,
90832 15131,15132,15133,15134,15135,15136,15137,15138,15139,15140,15141,15142,
90833 15143,15144,15145,15146,15147,15148,15149,15150,15151,15152,15153,15154,
90834 15155,15156,15157,15158,15159,15160,15161,15162,15163,15164,15165,15166,
90835 15167,15168,15169,15170,15171,15172,15173,15174,15175,15176,15177,15178,
90836 15179,15180,15181,15182,15183,15184,15185,15186,15187,15188,15189,15190,
90837 15191,15192,15193,15194,15195,15196,15197,15198,15199,15200,15201,15202,
90838 15203,15204,15205,15206,15207,15208,15209,15210,15211,15212,15213,15214,
90839 15215,15216,15217,15218,15219,15220,15221,15222,15223,15224,15225,15226,
90840 15227,15228,15229,15230,15231,15232,15233,15234,15235,15236,15237,15238,
90841 15239,15240,15241,15242,15243,15244,15245,15246,15247,15248,15249,15250,
90842 15251,15252,15253,15254,15255,15256,15257,15258,15259,15260,15261,15262,
90843 15263,15264,15265,15266,15267,15268,15269,15270,15271,15272,15273,15274,
90844 15275,15276,15277,15278,15279,15280,15281,15282,15283,15284,15285,15286,
90845 15287,15288,15289,15290,15291,15292,15293,15294,15295,15296,15297,15298,
90846 15299,15300,15301,15302,15303,15304,15305,15306,15307,15308,15309,15310,
90847 15311,15312,15313,15314,15315,15316,15317,15318,15319,15320,15321,15322,
90848 15323,15324,15325,15326,15327,15328,15329,15330,15331,15332,15333,15334,
90849 15335,15336,15337,15338,15339,15340,15341,15342,15343,15344,15345,15346,
90850 15347,15348,15349,15350,15351,15352,15353,15354,15355,15356,15357,15358,
90851 15359,15360,15361,15362,15363,15364,15365,15366,15367,15368,15369,15370,
90852 15371,15372,15373,15374,15375,15376,15377,15378,15379,15380,15381,15382,
90853 15383,15384,15385,15386,15387,15388,15389,15390,15391,15392,15393,15394,
90854 15395,15396,15397,15398,15399,15400,15401,15402,15403,15404,15405,15406,
90855 15407,15408,15409,15410,15411,15412,15413,15414,15415,15416,15417,15418,
90856 15419,15420,15421,15422,15423,15424,15425,15426,15427,15428,15429,15430,
90857 15431,15432,15433,15434,15435,15436,15437,15438,15439,15440,15441,15442,
90858 15443,15444,15445,15446,15447,15448,15449,15450,15451,15452,15453,15454,
90859 15455,15456,15457,15458,15459,15460,15461,15462,15463,15464,15465,15466,
90860 15467,15468,15469,15470,15471,15472,15473,15474,15475,15476,15477,15478,
90861 15479,15480,15481,15482,15483,15484,15485,15486,15487,15488,15489,15490,
90862 15491,15492,15493,15494,15495,15496,15497,15498,15499,15500,15501,15502,
90863 15503,15504,15505,15506,15507,15508,15509,15510,15511,15512,15513,15514,
90864 15515,15516,15517,15518,15519,15520,15521,15522,15523,15524,15525,15526,
90865 15527,15528,15529,15530,15531,15532,15533,15534,15535,15536,15537,15538,
90866 15539,15540,15541,15542,15543,15544,15545,15546,15547,15548,15549,15550,
90867 15551,15552,15553,15554,15555,15556,15557,15558,15559,15560,15561,15562,
90868 15563,15564,15565,15566,15567,15568,15569,15570,15571,15572,15573,15574,
90869 15575,15576,15577,15578,15579,15580,15581,15582,15583,15584,15585,15586,
90870 15587,15588,15589,15590,15591,15592,15593,15594,15595,15596,15597,15598,
90871 15599,15600,15601,15602,15603,15604,15605,15606,15607,15608,15609,15610,
90872 15611,15612,15613,15614,15615,15616,15617,15618,15619,15620,15621,15622,
90873 15623,15624,15625,15626,15627,15628,15629,15630,15631,15632,15633,15634,
90874 15635,15636,15637,15638,15639,15640,15641,15642,15643,15644,15645,15646,
90875 15647,15648,15649,15650,15651,15652,15653,15654,15655,15656,15657,15658,
90876 15659,15660,15661,15662,15663,15664,15665,15666,15667,15668,15669,15670,
90877 15671,15672,15673,15674,15675,15676,15677,15678,15679,15680,15681,15682,
90878 15683,15684,15685,15686,15687,15688,15689,15690,15691,15692,15693,15694,
90879 15695,15696,15697,15698,15699,15700,15701,15702,15703,15704,15705,15706,
90880 15707,15708,15709,15710,15711,15712,15713,15714,15715,15716,15717,15718,
90881 15719,15720,15721,15722,15723,15724,15725,15726,15727,15728,15729,15730,
90882 15731,15732,15733,15734,15735,15736,15737,15738,15739,15740,15741,15742,
90883 15743,15744,15745,15746,15747,15748,15749,15750,15751,15752,15753,15754,
90884 15755,15756,15757,15758,15759,15760,15761,15762,15763,15764,15765,15766,
90885 15767,15768,15769,15770,15771,15772,15773,15774,15775,15776,15777,15778,
90886 15779,15780,15781,15782,15783,15784,15785,15786,15787,15788,15789,15790,
90887 15791,15792,15793,15794,15795,15796,15797,15798,15799,15800,15801,15802,
90888 15803,15804,15805,15806,15807,15808,15809,15810,15811,15812,15813,15814,
90889 15815,15816,15817,15818,15819,15820,15821,15822,15823,15824,15825,15826,
90890 15827,15828,15829,15830,15831,15832,15833,15834,15835,15836,15837,15838,
90891 15839,15840,15841,15842,15843,15844,15845,15846,15847,15848,15849,15850,
90892 15851,15852,15853,15854,15855,15856,15857,15858,15859,15860,15861,15862,
90893 15863,15864,15865,15866,15867,15868,15869,15870,15871,15872,15873,15874,
90894 15875,15876,15877,15878,15879,15880,15881,15882,15883,15884,15885,15886,
90895 15887,15888,15889,15890,15891,15892,15893,15894,15895,15896,15897,15898,
90896 15899,15900,15901,15902,15903,15904,15905,15906,15907,15908,15909,15910,
90897 15911,15912,15913,15914,15915,15916,15917,15918,15919,15920,15921,15922,
90898 15923,15924,15925,15926,15927,15928,15929,15930,15931,15932,15933,15934,
90899 15935,15936,15937,15938,15939,15940,15941,15942,15943,15944,15945,15946,
90900 15947,15948,15949,15950,15951,15952,15953,15954,15955,15956,15957,15958,
90901 15959,15960,15961,15962,15963,15964,15965,15966,15967,15968,15969,15970,
90902 15971,15972,15973,15974,15975,15976,15977,15978,15979,15980,15981,15982,
90903 15983,15984,15985,15986,15987,15988,15989,15990,15991,15992,15993,15994,
90904 15995,15996,15997,15998,15999,16000,16001,16002,16003,16004,16005,16006,
90905 16007,16008,16009,16010,16011,16012,16013,16014,16015,16016,16017,16018,
90906 16019,16020,16021,16022,16023,16024,16025,16026,16027,16028,16029,16030,
90907 16031,16032,16033,16034,16035,16036,16037,16038,16039,16040,16041,16042,
90908 16043,16044,16045,16046,16047,16048,16049,16050,16051,16052,16053,16054,
90909 16055,16056,16057,16058,16059,16060,16061,16062,16063,16064,16065,16066,
90910 16067,16068,16069,16070,16071,16072,16073,16074,16075,16076,16077,16078,
90911 16079,16080,16081,16082,16083,16084,16085,16086,16087,16088,16089,16090,
90912 16091,16092,16093,16094,16095,16096,16097,16098,16099,16100,16101,16102,
90913 16103,16104,16105,16106,16107,16108,16109,16110,16111,16112,16113,16114,
90914 16115,16116,16117,16118,16119,16120,16121,16122,16123,16124,16125,16126,
90915 16127,16128,16129,16130,16131,16132,16133,16134,16135,16136,16137,16138,
90916 16139,16140,16141,16142,16143,16144,16145,16146,16147,16148,16149,16150,
90917 16151,16152,16153,16154,16155,16156,16157,16158,16159,16160,16161,16162,
90918 16163,16164,16165,16166,16167,16168,16169,16170,16171,16172,16173,16174,
90919 16175,16176,16177,16178,16179,16180,16181,16182,16183,16184,16185,16186,
90920 16187,16188,16189,16190,16191,16192,16193,16194,16195,16196,16197,16198,
90921 16199,16200,16201,16202,16203,16204,16205,16206,16207,16208,16209,16210,
90922 16211,16212,16213,16214,16215,16216,16217,16218,16219,16220,16221,16222,
90923 16223,16224,16225,16226,16227,16228,16229,16230,16231,16232,16233,16234,
90924 16235,16236,16237,16238,16239,16240,16241,16242,16243,16244,16245,16246,
90925 16247,16248,16249,16250,16251,16252,16253,16254,16255,16256,16257,16258,
90926 16259,16260,16261,16262,16263,16264,16265,16266,16267,16268,16269,16270,
90927 16271,16272,16273,16274,16275,16276,16277,16278,16279,16280,16281,16282,
90928 16283,16284,16285,16286,16287,16288,16289,16290,16291,16292,16293,16294,
90929 16295,16296,16297,16298,16299,16300,16301,16302,16303,16304,16305,16306,
90930 16307,16308,16309,16310,16311,16312,16313,16314,16315,16316,16317,16318,
90931 16319,16320,16321,16322,16323,16324,16325,16326,16327,16328,16329,16330,
90932 16331,16332,16333,16334,16335,16336,16337,16338,16339,16340,16341,16342,
90933 16343,16344,16345,16346,16347,16348,16349,16350,16351,16352,16353,16354,
90934 16355,16356,16357,16358,16359,16360,16361,16362,16363,16364,16365,16366,
90935 16367,16368,16369,16370,16371,16372,16373,16374,16375,16376,16377,16378,
90936 16379,16380,16381,16382,16383,16384,16385,16386,16387,16388,16389,16390,
90937 16391,16392,16393,16394,16395,16396,16397,16398,16399,16400,16401,16402,
90938 16403,16404,16405,16406,16407,16408,16409,16410,16411,16412,16413,16414,
90939 16415,16416,16417,16418,16419,16420,16421,16422,16423,16424,16425,16426,
90940 16427,16428,16429,16430,16431,16432,16433,16434,16435,16436,16437,16438,
90941 16439,16440,16441,16442,16443,16444,16445,16446,16447,16448,16449,16450,
90942 16451,16452,16453,16454,16455,16456,16457,16458,16459,16460,16461,16462,
90943 16463,16464,16465,16466,16467,16468,16469,16470,16471,16472,16473,16474,
90944 16475,16476,16477,16478,16479,16480,16481,16482,16483,16484,16485,16486,
90945 16487,16488,16489,16490,16491,16492,16493,16494,16495,16496,16497,16498,
90946 16499,16500,16501,16502,16503,16504,16505,16506,16507,16508,16509,16510,
90947 16511,16512,16513,16514,16515,16516,16517,16518,16519,16520,16521,16522,
90948 16523,16524,16525,16526,16527,16528,16529,16530,16531,16532,16533,16534,
90949 16535,16536,16537,16538,16539,16540,16541,16542,16543,16544,16545,16546,
90950 16547,16548,16549,16550,16551,16552,16553,16554,16555,16556,16557,16558,
90951 16559,16560,16561,16562,16563,16564,16565,16566,16567,16568,16569,16570,
90952 16571,16572,16573,16574,16575,16576,16577,16578,16579,16580,16581,16582,
90953 16583,16584,16585,16586,16587,16588,16589,16590,16591,16592,16593,16594,
90954 16595,16596,16597,16598,16599,16600,16601,16602,16603,16604,16605,16606,
90955 16607,16608,16609,16610,16611,16612,16613,16614,16615,16616,16617,16618,
90956 16619,16620,16621,16622,16623,16624,16625,16626,16627,16628,16629,16630,
90957 16631,16632,16633,16634,16635,16636,16637,16638,16639,16640,16641,16642,
90958 16643,16644,16645,16646,16647,16648,16649,16650,16651,16652,16653,16654,
90959 16655,16656,16657,16658,16659,16660,16661,16662,16663,16664,16665,16666,
90960 16667,16668,16669,16670,16671,16672,16673,16674,16675,16676,16677,16678,
90961 16679,16680,16681,16682,16683,16684,16685,16686,16687,16688,16689,16690,
90962 16691,16692,16693,16694,16695,16696,16697,16698,16699,16700,16701,16702,
90963 16703,16704,16705,16706,16707,16708,16709,16710,16711,16712,16713,16714,
90964 16715,16716,16717,16718,16719,16720,16721,16722,16723,16724,16725,16726,
90965 16727,16728,16729,16730,16731,16732,16733,16734,16735,16736,16737,16738,
90966 16739,16740,16741,16742,16743,16744,16745,16746,16747,16748,16749,16750,
90967 16751,16752,16753,16754,16755,16756,16757,16758,16759,16760,16761,16762,
90968 16763,16764,16765,16766,16767,16768,16769,16770,16771,16772,16773,16774,
90969 16775,16776,16777,16778,16779,16780,16781,16782,16783,16784,16785,16786,
90970 16787,16788,16789,16790,16791,16792,16793,16794,16795,16796,16797,16798,
90971 16799,16800,16801,16802,16803,16804,16805,16806,16807,16808,16809,16810,
90972 16811,16812,16813,16814,16815,16816,16817,16818,16819,16820,16821,16822,
90973 16823,16824,16825,16826,16827,16828,16829,16830,16831,16832,16833,16834,
90974 16835,16836,16837,16838,16839,16840,16841,16842,16843,16844,16845,16846,
90975 16847,16848,16849,16850,16851,16852,16853,16854,16855,16856,16857,16858,
90976 16859,16860,16861,16862,16863,16864,16865,16866,16867,16868,16869,16870,
90977 16871,16872,16873,16874,16875,16876,16877,16878,16879,16880,16881,16882,
90978 16883,16884,16885,16886,16887,16888,16889,16890,16891,16892,16893,16894,
90979 16895,16896,16897,16898,16899,16900,16901,16902,16903,16904,16905,16906,
90980 16907,16908,16909,16910,16911,16912,16913,16914,16915,16916,16917,16918,
90981 16919,16920,16921,16922,16923,16924,16925,16926,16927,16928,16929,16930,
90982 16931,16932,16933,16934,16935,16936,16937,16938,16939,16940,16941,16942,
90983 16943,16944,16945,16946,16947,16948,16949,16950,16951,16952,16953,16954,
90984 16955,16956,16957,16958,16959,16960,16961,16962,16963,16964,16965,16966,
90985 16967,16968,16969,16970,16971,16972,16973,16974,16975,16976,16977,16978,
90986 16979,16980,16981,16982,16983,16984,16985,16986,16987,16988,16989,16990,
90987 16991,16992,16993,16994,16995,16996,16997,16998,16999,17000,17001,17002,
90988 17003,17004,17005,17006,17007,17008,17009,17010,17011,17012,17013,17014,
90989 17015,17016,17017,17018,17019,17020,17021,17022,17023,17024,17025,17026,
90990 17027,17028,17029,17030,17031,17032,17033,17034,17035,17036,17037,17038,
90991 17039,17040,17041,17042,17043,17044,17045,17046,17047,17048,17049,17050,
90992 17051,17052,17053,17054,17055,17056,17057,17058,17059,17060,17061,17062,
90993 17063,17064,17065,17066,17067,17068,17069,17070,17071,17072,17073,17074,
90994 17075,17076,17077,17078,17079,17080,17081,17082,17083,17084,17085,17086,
90995 17087,17088,17089,17090,17091,17092,17093,17094,17095,17096,17097,17098,
90996 17099,17100,17101,17102,17103,17104,17105,17106,17107,17108,17109,17110,
90997 17111,17112,17113,17114,17115,17116,17117,17118,17119,17120,17121,17122,
90998 17123,17124,17125,17126,17127,17128,17129,17130,17131,17132,17133,17134,
90999 17135,17136,17137,17138,17139,17140,17141,17142,17143,17144,17145,17146,
91000 17147,17148,17149,17150,17151,17152,17153,17154,17155,17156,17157,17158,
91001 17159,17160,17161,17162,17163,17164,17165,17166,17167,17168,17169,17170,
91002 17171,17172,17173,17174,17175,17176,17177,17178,17179,17180,17181,17182,
91003 17183,17184,17185,17186,17187,17188,17189,17190,17191,17192,17193,17194,
91004 17195,17196,17197,17198,17199,17200,17201,17202,17203,17204,17205,17206,
91005 17207,17208,17209,17210,17211,17212,17213,17214,17215,17216,17217,17218,
91006 17219,17220,17221,17222,17223,17224,17225,17226,17227,17228,17229,17230,
91007 17231,17232,17233,17234,17235,17236,17237,17238,17239,17240,17241,17242,
91008 17243,17244,17245,17246,17247,17248,17249,17250,17251,17252,17253,17254,
91009 17255,17256,17257,17258,17259,17260,17261,17262,17263,17264,17265,17266,
91010 17267,17268,17269,17270,17271,17272,17273,17274,17275,17276,17277,17278,
91011 17279,17280,17281,17282,17283,17284,17285,17286,17287,17288,17289,17290,
91012 17291,17292,17293,17294,17295,17296,17297,17298,17299,17300,17301,17302,
91013 17303,17304,17305,17306,17307,17308,17309,17310,17311,17312,17313,17314,
91014 17315,17316,17317,17318,17319,17320,17321,17322,17323,17324,17325,17326,
91015 17327,17328,17329,17330,17331,17332,17333,17334,17335,17336,17337,17338,
91016 17339,17340,17341,17342,17343,17344,17345,17346,17347,17348,17349,17350,
91017 17351,17352,17353,17354,17355,17356,17357,17358,17359,17360,17361,17362,
91018 17363,17364,17365,17366,17367,17368,17369,17370,17371,17372,17373,17374,
91019 17375,17376,17377,17378,17379,17380,17381,17382,17383,17384,17385,17386,
91020 17387,17388,17389,17390,17391,17392,17393,17394,17395,17396,17397,17398,
91021 17399,17400,17401,17402,17403,17404,17405,17406,17407,17408,17409,17410,
91022 17411,17412,17413,17414,17415,17416,17417,17418,17419,17420,17421,17422,
91023 17423,17424,17425,17426,17427,17428,17429,17430,17431,17432,17433,17434,
91024 17435,17436,17437,17438,17439,17440,17441,17442,17443,17444,17445,17446,
91025 17447,17448,17449,17450,17451,17452,17453,17454,17455,17456,17457,17458,
91026 17459,17460,17461,17462,17463,17464,17465,17466,17467,17468,17469,17470,
91027 17471,17472,17473,17474,17475,17476,17477,17478,17479,17480,17481,17482,
91028 17483,17484,17485,17486,17487,17488,17489,17490,17491,17492,17493,17494,
91029 17495,17496,17497,17498,17499,17500,17501,17502,17503,17504,17505,17506,
91030 17507,17508,17509,17510,17511,17512,17513,17514,17515,17516,17517,17518,
91031 17519,17520,17521,17522,17523,17524,17525,17526,17527,17528,17529,17530,
91032 17531,17532,17533,17534,17535,17536,17537,17538,17539,17540,17541,17542,
91033 17543,17544,17545,17546,17547,17548,17549,17550,17551,17552,17553,17554,
91034 17555,17556,17557,17558,17559,17560,17561,17562,17563,17564,17565,17566,
91035 17567,17568,17569,17570,17571,17572,17573,17574,17575,17576,17577,17578,
91036 17579,17580,17581,17582,17583,17584,17585,17586,17587,17588,17589,17590,
91037 17591,17592,17593,17594,17595,17596,17597,17598,17599,17600,17601,17602,
91038 17603,17604,17605,17606,17607,17608,17609,17610,17611,17612,17613,17614,
91039 17615,17616,17617,17618,17619,17620,17621,17622,17623,17624,17625,17626,
91040 17627,17628,17629,17630,17631,17632,17633,17634,17635,17636,17637,17638,
91041 17639,17640,17641,17642,17643,17644,17645,17646,17647,17648,17649,17650,
91042 17651,17652,17653,17654,17655,17656,17657,17658,17659,17660,17661,17662,
91043 17663,17664,17665,17666,17667,17668,17669,17670,17671,17672,17673,17674,
91044 17675,17676,17677,17678,17679,17680,17681,17682,17683,17684,17685,17686,
91045 17687,17688,17689,17690,17691,17692,17693,17694,17695,17696,17697,17698,
91046 17699,17700,17701,17702,17703,17704,17705,17706,17707,17708,17709,17710,
91047 17711,17712,17713,17714,17715,17716,17717,17718,17719,17720,17721,17722,
91048 17723,17724,17725,17726,17727,17728,17729,17730,17731,17732,17733,17734,
91049 17735,17736,17737,17738,17739,17740,17741,17742,17743,17744,17745,17746,
91050 17747,17748,17749,17750,17751,17752,17753,17754,17755,17756,17757,17758,
91051 17759,17760,17761,17762,17763,17764,17765,17766,17767,17768,17769,17770,
91052 17771,17772,17773,17774,17775,17776,17777,17778,17779,17780,17781,17782,
91053 17783,17784,17785,17786,17787,17788,17789,17790,17791,17792,17793,17794,
91054 17795,17796,17797,17798,17799,17800,17801,17802,17803,17804,17805,17806,
91055 17807,17808,17809,17810,17811,17812,17813,17814,17815,17816,17817,17818,
91056 17819,17820,17821,17822,17823,17824,17825,17826,17827,17828,17829,17830,
91057 17831,17832,17833,17834,17835,17836,17837,17838,17839,17840,17841,17842,
91058 17843,17844,17845,17846,17847,17848,17849,17850,17851,17852,17853,17854,
91059 17855,17856,17857,17858,17859,17860,17861,17862,17863,17864,17865,17866,
91060 17867,17868,17869,17870,17871,17872,17873,17874,17875,17876,17877,17878,
91061 17879,17880,17881,17882,17883,17884,17885,17886,17887,17888,17889,17890,
91062 17891,17892,17893,17894,17895,17896,17897,17898,17899,17900,17901,17902,
91063 17903,17904,17905,17906,17907,17908,17909,17910,17911,17912,17913,17914,
91064 17915,17916,17917,17918,17919,17920,17921,17922,17923,17924,17925,17926,
91065 17927,17928,17929,17930,17931,17932,17933,17934,17935,17936,17937,17938,
91066 17939,17940,17941,17942,17943,17944,17945,17946,17947,17948,17949,17950,
91067 17951,17952,17953,17954,17955,17956,17957,17958,17959,17960,17961,17962,
91068 17963,17964,17965,17966,17967,17968,17969,17970,17971,17972,17973,17974,
91069 17975,17976,17977,17978,17979,17980,17981,17982,17983,17984,17985,17986,
91070 17987,17988,17989,17990,17991,17992,17993,17994,17995,17996,17997,17998,
91071 17999,18000,18001,18002,18003,18004,18005,18006,18007,18008,18009,18010,
91072 18011,18012,18013,18014,18015,18016,18017,18018,18019,18020,18021,18022,
91073 18023,18024,18025,18026,18027,18028,18029,18030,18031,18032,18033,18034,
91074 18035,18036,18037,18038,18039,18040,18041,18042,18043,18044,18045,18046,
91075 18047,18048,18049,18050,18051,18052,18053,18054,18055,18056,18057,18058,
91076 18059,18060,18061,18062,18063,18064,18065,18066,18067,18068,18069,18070,
91077 18071,18072,18073,18074,18075,18076,18077,18078,18079,18080,18081,18082,
91078 18083,18084,18085,18086,18087,18088,18089,18090,18091,18092,18093,18094,
91079 18095,18096,18097,18098,18099,18100,18101,18102,18103,18104,18105,18106,
91080 18107,18108,18109,18110,18111,18112,18113,18114,18115,18116,18117,18118,
91081 18119,18120,18121,18122,18123,18124,18125,18126,18127,18128,18129,18130,
91082 18131,18132,18133,18134,18135,18136,18137,18138,18139,18140,18141,18142,
91083 18143,18144,18145,18146,18147,18148,18149,18150,18151,18152,18153,18154,
91084 18155,18156,18157,18158,18159,18160,18161,18162,18163,18164,18165,18166,
91085 18167,18168,18169,18170,18171,18172,18173,18174,18175,18176,18177,18178,
91086 18179,18180,18181,18182,18183,18184,18185,18186,18187,18188,18189,18190,
91087 18191,18192,18193,18194,18195,18196,18197,18198,18199,18200,18201,18202,
91088 18203,18204,18205,18206,18207,18208,18209,18210,18211,18212,18213,18214,
91089 18215,18216,18217,18218,18219,18220,18221,18222,18223,18224,18225,18226,
91090 18227,18228,18229,18230,18231,18232,18233,18234,18235,18236,18237,18238,
91091 18239,18240,18241,18242,18243,18244,18245,18246,18247,18248,18249,18250,
91092 18251,18252,18253,18254,18255,18256,18257,18258,18259,18260,18261,18262,
91093 18263,18264,18265,18266,18267,18268,18269,18270,18271,18272,18273,18274,
91094 18275,18276,18277,18278,18279,18280,18281,18282,18283,18284,18285,18286,
91095 18287,18288,18289,18290,18291,18292,18293,18294,18295,18296,18297,18298,
91096 18299,18300,18301,18302,18303,18304,18305,18306,18307,18308,18309,18310,
91097 18311,18312,18313,18314,18315,18316,18317,18318,18319,18320,18321,18322,
91098 18323,18324,18325,18326,18327,18328,18329,18330,18331,18332,18333,18334,
91099 18335,18336,18337,18338,18339,18340,18341,18342,18343,18344,18345,18346,
91100 18347,18348,18349,18350,18351,18352,18353,18354,18355,18356,18357,18358,
91101 18359,18360,18361,18362,18363,18364,18365,18366,18367,18368,18369,18370,
91102 18371,18372,18373,18374,18375,18376,18377,18378,18379,18380,18381,18382,
91103 18383,18384,18385,18386,18387,18388,18389,18390,18391,18392,18393,18394,
91104 18395,18396,18397,18398,18399,18400,18401,18402,18403,18404,18405,18406,
91105 18407,18408,18409,18410,18411,18412,18413,18414,18415,18416,18417,18418,
91106 18419,18420,18421,18422,18423,18424,18425,18426,18427,18428,18429,18430,
91107 18431,18432,18433,18434,18435,18436,18437,18438,18439,18440,18441,18442,
91108 18443,18444,18445,18446,18447,18448,18449,18450,18451,18452,18453,18454,
91109 18455,18456,18457,18458,18459,18460,18461,18462,18463,18464,18465,18466,
91110 18467,18468,18469,18470,18471,18472,18473,18474,18475,18476,18477,18478,
91111 18479,18480,18481,18482,18483,18484,18485,18486,18487,18488,18489,18490,
91112 18491,18492,18493,18494,18495,18496,18497,18498,18499,18500,18501,18502,
91113 18503,18504,18505,18506,18507,18508,18509,18510,18511,18512,18513,18514,
91114 18515,18516,18517,18518,18519,18520,18521,18522,18523,18524,18525,18526,
91115 18527,18528,18529,18530,18531,18532,18533,18534,18535,18536,18537,18538,
91116 18539,18540,18541,18542,18543,18544,18545,18546,18547,18548,18549,18550,
91117 18551,18552,18553,18554,18555,18556,18557,18558,18559,18560,18561,18562,
91118 18563,18564,18565,18566,18567,18568,18569,18570,18571,18572,18573,18574,
91119 18575,18576,18577,18578,18579,18580,18581,18582,18583,18584,18585,18586,
91120 18587,18588,18589,18590,18591,18592,18593,18594,18595,18596,18597,18598,
91121 18599,18600,18601,18602,18603,18604,18605,18606,18607,18608,18609,18610,
91122 18611,18612,18613,18614,18615,18616,18617,18618,18619,18620,18621,18622,
91123 18623,18624,18625,18626,18627,18628,18629,18630,18631,18632,18633,18634,
91124 18635,18636,18637,18638,18639,18640,18641,18642,18643,18644,18645,18646,
91125 18647,18648,18649,18650,18651,18652,18653,18654,18655,18656,18657,18658,
91126 18659,18660,18661,18662,18663,18664,18665,18666,18667,18668,18669,18670,
91127 18671,18672,18673,18674,18675,18676,18677,18678,18679,18680,18681,18682,
91128 18683,18684,18685,18686,18687,18688,18689,18690,18691,18692,18693,18694,
91129 18695,18696,18697,18698,18699,18700,18701,18702,18703,18704,18705,18706,
91130 18707,18708,18709,18710,18711,18712,18713,18714,18715,18716,18717,18718,
91131 18719,18720,18721,18722,18723,18724,18725,18726,18727,18728,18729,18730,
91132 18731,18732,18733,18734,18735,18736,18737,18738,18739,18740,18741,18742,
91133 18743,18744,18745,18746,18747,18748,18749,18750,18751,18752,18753,18754,
91134 18755,18756,18757,18758,18759,18760,18761,18762,18763,18764,18765,18766,
91135 18767,18768,18769,18770,18771,18772,18773,18774,18775,18776,18777,18778,
91136 18779,18780,18781,18782,18783,18784,18785,18786,18787,18788,18789,18790,
91137 18791,18792,18793,18794,18795,18796,18797,18798,18799,18800,18801,18802,
91138 18803,18804,18805,18806,18807,18808,18809,18810,18811,18812,18813,18814,
91139 18815,18816,18817,18818,18819,18820,18821,18822,18823,18824,18825,18826,
91140 18827,18828,18829,18830,18831,18832,18833,18834,18835,18836,18837,18838,
91141 18839,18840,18841,18842,18843,18844,18845,18846,18847,18848,18849,18850,
91142 18851,18852,18853,18854,18855,18856,18857,18858,18859,18860,18861,18862,
91143 18863,18864,18865,18866,18867,18868,18869,18870,18871,18872,18873,18874,
91144 18875,18876,18877,18878,18879,18880,18881,18882,18883,18884,18885,18886,
91145 18887,18888,18889,18890,18891,18892,18893,18894,18895,18896,18897,18898,
91146 18899,18900,18901,18902,18903,18904,18905,18906,18907,18908,18909,18910,
91147 18911,18912,18913,18914,18915,18916,18917,18918,18919,18920,18921,18922,
91148 18923,18924,18925,18926,18927,18928,18929,18930,18931,18932,18933,18934,
91149 18935,18936,18937,18938,18939,18940,18941,18942,18943,18944,18945,18946,
91150 18947,18948,18949,18950,18951,18952,18953,18954,18955,18956,18957,18958,
91151 18959,18960,18961,18962,18963,18964,18965,18966,18967,18968,18969,18970,
91152 18971,18972,18973,18974,18975,18976,18977,18978,18979,18980,18981,18982,
91153 18983,18984,18985,18986,18987,18988,18989,18990,18991,18992,18993,18994,
91154 18995,18996,18997,18998,18999,19000,19001,19002,19003,19004,19005,19006,
91155 19007,19008,19009,19010,19011,19012,19013,19014,19015,19016,19017,19018,
91156 19019,19020,19021,19022,19023,19024,19025,19026,19027,19028,19029,19030,
91157 19031,19032,19033,19034,19035,19036,19037,19038,19039,19040,19041,19042,
91158 19043,19044,19045,19046,19047,19048,19049,19050,19051,19052,19053,19054,
91159 19055,19056,19057,19058,19059,19060,19061,19062,19063,19064,19065,19066,
91160 19067,19068,19069,19070,19071,19072,19073,19074,19075,19076,19077,19078,
91161 19079,19080,19081,19082,19083,19084,19085,19086,19087,19088,19089,19090,
91162 19091,19092,19093,19094,19095,19096,19097,19098,19099,19100,19101,19102,
91163 19103,19104,19105,19106,19107,19108,19109,19110,19111,19112,19113,19114,
91164 19115,19116,19117,19118,19119,19120,19121,19122,19123,19124,19125,19126,
91165 19127,19128,19129,19130,19131,19132,19133,19134,19135,19136,19137,19138,
91166 19139,19140,19141,19142,19143,19144,19145,19146,19147,19148,19149,19150,
91167 19151,19152,19153,19154,19155,19156,19157,19158,19159,19160,19161,19162,
91168 19163,19164,19165,19166,19167,19168,19169,19170,19171,19172,19173,19174,
91169 19175,19176,19177,19178,19179,19180,19181,19182,19183,19184,19185,19186,
91170 19187,19188,19189,19190,19191,19192,19193,19194,19195,19196,19197,19198,
91171 19199,19200,19201,19202,19203,19204,19205,19206,19207,19208,19209,19210,
91172 19211,19212,19213,19214,19215,19216,19217,19218,19219,19220,19221,19222,
91173 19223,19224,19225,19226,19227,19228,19229,19230,19231,19232,19233,19234,
91174 19235,19236,19237,19238,19239,19240,19241,19242,19243,19244,19245,19246,
91175 19247,19248,19249,19250,19251,19252,19253,19254,19255,19256,19257,19258,
91176 19259,19260,19261,19262,19263,19264,19265,19266,19267,19268,19269,19270,
91177 19271,19272,19273,19274,19275,19276,19277,19278,19279,19280,19281,19282,
91178 19283,19284,19285,19286,19287,19288,19289,19290,19291,19292,19293,19294,
91179 19295,19296,19297,19298,19299,19300,19301,19302,19303,19304,19305,19306,
91180 19307,19308,19309,19310,19311,19312,19313,19314,19315,19316,19317,19318,
91181 19319,19320,19321,19322,19323,19324,19325,19326,19327,19328,19329,19330,
91182 19331,19332,19333,19334,19335,19336,19337,19338,19339,19340,19341,19342,
91183 19343,19344,19345,19346,19347,19348,19349,19350,19351,19352,19353,19354,
91184 19355,19356,19357,19358,19359,19360,19361,19362,19363,19364,19365,19366,
91185 19367,19368,19369,19370,19371,19372,19373,19374,19375,19376,19377,19378,
91186 19379,19380,19381,19382,19383,19384,19385,19386,19387,19388,19389,19390,
91187 19391,19392,19393,19394,19395,19396,19397,19398,19399,19400,19401,19402,
91188 19403,19404,19405,19406,19407,19408,19409,19410,19411,19412,19413,19414,
91189 19415,19416,19417,19418,19419,19420,19421,19422,19423,19424,19425,19426,
91190 19427,19428,19429,19430,19431,19432,19433,19434,19435,19436,19437,19438,
91191 19439,19440,19441,19442,19443,19444,19445,19446,19447,19448,19449,19450,
91192 19451,19452,19453,19454,19455,19456,19457,19458,19459,19460,19461,19462,
91193 19463,19464,19465,19466,19467,19468,19469,19470,19471,19472,19473,19474,
91194 19475,19476,19477,19478,19479,19480,19481,19482,19483,19484,19485,19486,
91195 19487,19488,19489,19490,19491,19492,19493,19494,19495,19496,19497,19498,
91196 19499,19500,19501,19502,19503,19504,19505,19506,19507,19508,19509,19510,
91197 19511,19512,19513,19514,19515,19516,19517,19518,19519,19520,19521,19522,
91198 19523,19524,19525,19526,19527,19528,19529,19530,19531,19532,19533,19534,
91199 19535,19536,19537,19538,19539,19540,19541,19542,19543,19544,19545,19546,
91200 19547,19548,19549,19550,19551,19552,19553,19554,19555,19556,19557,19558,
91201 19559,19560,19561,19562,19563,19564,19565,19566,19567,19568,19569,19570,
91202 19571,19572,19573,19574,19575,19576,19577,19578,19579,19580,19581,19582,
91203 19583,19584,19585,19586,19587,19588,19589,19590,19591,19592,19593,19594,
91204 19595,19596,19597,19598,19599,19600,19601,19602,19603,19604,19605,19606,
91205 19607,19608,19609,19610,19611,19612,19613,19614,19615,19616,19617,19618,
91206 19619,19620,19621,19622,19623,19624,19625,19626,19627,19628,19629,19630,
91207 19631,19632,19633,19634,19635,19636,19637,19638,19639,19640,19641,19642,
91208 19643,19644,19645,19646,19647,19648,19649,19650,19651,19652,19653,19654,
91209 19655,19656,19657,19658,19659,19660,19661,19662,19663,19664,19665,19666,
91210 19667,19668,19669,19670,19671,19672,19673,19674,19675,19676,19677,19678,
91211 19679,19680,19681,19682,19683,19684,19685,19686,19687,19688,19689,19690,
91212 19691,19692,19693,19694,19695,19696,19697,19698,19699,19700,19701,19702,
91213 19703,19704,19705,19706,19707,19708,19709,19710,19711,19712,19713,19714,
91214 19715,19716,19717,19718,19719,19720,19721,19722,19723,19724,19725,19726,
91215 19727,19728,19729,19730,19731,19732,19733,19734,19735,19736,19737,19738,
91216 19739,19740,19741,19742,19743,19744,19745,19746,19747,19748,19749,19750,
91217 19751,19752,19753,19754,19755,19756,19757,19758,19759,19760,19761,19762,
91218 19763,19764,19765,19766,19767,19768,19769,19770,19771,19772,19773,19774,
91219 19775,19776,19777,19778,19779,19780,19781,19782,19783,19784,19785,19786,
91220 19787,19788,19789,19790,19791,19792,19793,19794,19795,19796,19797,19798,
91221 19799,19800,19801,19802,19803,19804,19805,19806,19807,19808,19809,19810,
91222 19811,19812,19813,19814,19815,19816,19817,19818,19819,19820,19821,19822,
91223 19823,19824,19825,19826,19827,19828,19829,19830,19831,19832,19833,19834,
91224 19835,19836,19837,19838,19839,19840,19841,19842,19843,19844,19845,19846,
91225 19847,19848,19849,19850,19851,19852,19853,19854,19855,19856,19857,19858,
91226 19859,19860,19861,19862,19863,19864,19865,19866,19867,19868,19869,19870,
91227 19871,19872,19873,19874,19875,19876,19877,19878,19879,19880,19881,19882,
91228 19883,19884,19885,19886,19887,19888,19889,19890,19891,19892,19893,19894,
91229 19895,19896,19897,19898,19899,19900,19901,19902,19903,19904,19905,19906,
91230 19907,19908,19909,19910,19911,19912,19913,19914,19915,19916,19917,19918,
91231 19919,19920,19921,19922,19923,19924,19925,19926,19927,19928,19929,19930,
91232 19931,19932,19933,19934,19935,19936,19937,19938,19939,19940,19941,19942,
91233 19943,19944,19945,19946,19947,19948,19949,19950,19951,19952,19953,19954,
91234 19955,19956,19957,19958,19959,19960,19961,19962,19963,19964,19965,19966,
91235 19967,19968,19969,19970,19971,19972,19973,19974,19975,19976,19977,19978,
91236 19979,19980,19981,19982,19983,19984,19985,19986,19987,19988,19989,19990,
91237 19991,19992,19993,19994,19995,19996,19997,19998,19999,20000,20001,20002,
91238 20003,20004,20005,20006,20007,20008,20009,20010,20011,20012,20013,20014,
91239 20015,20016,20017,20018,20019,20020,20021,20022,20023,20024,20025,20026,
91240 20027,20028,20029,20030,20031,20032,20033,20034,20035,20036,20037,20038,
91241 20039,20040,20041,20042,20043,20044,20045,20046,20047,20048,20049,20050,
91242 20051,20052,20053,20054,20055,20056,20057,20058,20059,20060,20061,20062,
91243 20063,20064,20065,20066,20067,20068,20069,20070,20071,20072,20073,20074,
91244 20075,20076,20077,20078,20079,20080,20081,20082,20083,20084,20085,20086,
91245 20087,20088,20089,20090,20091,20092,20093,20094,20095,20096,20097,20098,
91246 20099,20100,20101,20102,20103,20104,20105,20106,20107,20108,20109,20110,
91247 20111,20112,20113,20114,20115,20116,20117,20118,20119,20120,20121,20122,
91248 20123,20124,20125,20126,20127,20128,20129,20130,20131,20132,20133,20134,
91249 20135,20136,20137,20138,20139,20140,20141,20142,20143,20144,20145,20146,
91250 20147,20148,20149,20150,20151,20152,20153,20154,20155,20156,20157,20158,
91251 20159,20160,20161,20162,20163,20164,20165,20166,20167,20168,20169,20170,
91252 20171,20172,20173,20174,20175,20176,20177,20178,20179,20180,20181,20182,
91253 20183,20184,20185,20186,20187,20188,20189,20190,20191,20192,20193,20194,
91254 20195,20196,20197,20198,20199,20200,20201,20202,20203,20204,20205,20206,
91255 20207,20208,20209,20210,20211,20212,20213,20214,20215,20216,20217,20218,
91256 20219,20220,20221,20222,20223,20224,20225,20226,20227,20228,20229,20230,
91257 20231,20232,20233,20234,20235,20236,20237,20238,20239,20240,20241,20242,
91258 20243,20244,20245,20246,20247,20248,20249,20250,20251,20252,20253,20254,
91259 20255,20256,20257,20258,20259,20260,20261,20262,20263,20264,20265,20266,
91260 20267,20268,20269,20270,20271,20272,20273,20274,20275,20276,20277,20278,
91261 20279,20280,20281,20282,20283,20284,20285,20286,20287,20288,20289,20290,
91262 20291,20292,20293,20294,20295,20296,20297,20298,20299,20300,20301,20302,
91263 20303,20304,20305,20306,20307,20308,20309,20310,20311,20312,20313,20314,
91264 20315,20316,20317,20318,20319,20320,20321,20322,20323,20324,20325,20326,
91265 20327,20328,20329,20330,20331,20332,20333,20334,20335,20336,20337,20338,
91266 20339,20340,20341,20342,20343,20344,20345,20346,20347,20348,20349,20350,
91267 20351,20352,20353,20354,20355,20356,20357,20358,20359,20360,20361,20362,
91268 20363,20364,20365,20366,20367,20368,20369,20370,20371,20372,20373,20374,
91269 20375,20376,20377,20378,20379,20380,20381,20382,20383,20384,20385,20386,
91270 20387,20388,20389,20390,20391,20392,20393,20394,20395,20396,20397,20398,
91271 20399,20400,20401,20402,20403,20404,20405,20406,20407,20408,20409,20410,
91272 20411,20412,20413,20414,20415,20416,20417,20418,20419,20420,20421,20422,
91273 20423,20424,20425,20426,20427,20428,20429,20430,20431,20432,20433,20434,
91274 20435,20436,20437,20438,20439,20440,20441,20442,20443,20444,20445,20446,
91275 20447,20448,20449,20450,20451,20452,20453,20454,20455,20456,20457,20458,
91276 20459,20460,20461,20462,20463,20464,20465,20466,20467,20468,20469,20470,
91277 20471,20472,20473,20474,20475,20476,20477,20478,20479,20480,20481,20482,
91278 20483,20484,20485,20486,20487,20488,20489,20490,20491,20492,20493,20494,
91279 20495,20496,20497,20498,20499,20500,20501,20502,20503,20504,20505,20506,
91280 20507,20508,20509,20510,20511,20512,20513,20514,20515,20516,20517,20518,
91281 20519,20520,20521,20522,20523,20524,20525,20526,20527,20528,20529,20530,
91282 20531,20532,20533,20534,20535,20536,20537,20538,20539,20540,20541,20542,
91283 20543,20544,20545,20546,20547,20548,20549,20550,20551,20552,20553,20554,
91284 20555,20556,20557,20558,20559,20560,20561,20562,20563,20564,20565,20566,
91285 20567,20568,20569,20570,20571,20572,20573,20574,20575,20576,20577,20578,
91286 20579,20580,20581,20582,20583,20584,20585,20586,20587,20588,20589,20590,
91287 20591,20592,20593,20594,20595,20596,20597,20598,20599,20600,20601,20602,
91288 20603,20604,20605,20606,20607,20608,20609,20610,20611,20612,20613,20614,
91289 20615,20616,20617,20618,20619,20620,20621,20622,20623,20624,20625,20626,
91290 20627,20628,20629,20630,20631,20632,20633,20634,20635,20636,20637,20638,
91291 20639,20640,20641,20642,20643,20644,20645,20646,20647,20648,20649,20650,
91292 20651,20652,20653,20654,20655,20656,20657,20658,20659,20660,20661,20662,
91293 20663,20664,20665,20666,20667,20668,20669,20670,20671,20672,20673,20674,
91294 20675,20676,20677,20678,20679,20680,20681,20682,20683,20684,20685,20686,
91295 20687,20688,20689,20690,20691,20692,20693,20694,20695,20696,20697,20698,
91296 20699,20700,20701,20702,20703,20704,20705,20706,20707,20708,20709,20710,
91297 20711,20712,20713,20714,20715,20716,20717,20718,20719,20720,20721,20722,
91298 20723,20724,20725,20726,20727,20728,20729,20730,20731,20732,20733,20734,
91299 20735,20736,20737,20738,20739,20740,20741,20742,20743,20744,20745,20746,
91300 20747,20748,20749,20750,20751,20752,20753,20754,20755,20756,20757,20758,
91301 20759,20760,20761,20762,20763,20764,20765,20766,20767,20768,20769,20770,
91302 20771,20772,20773,20774,20775,20776,20777,20778,20779,20780,20781,20782,
91303 20783,20784,20785,20786,20787,20788,20789,20790,20791,20792,20793,20794,
91304 20795,20796,20797,20798,20799,20800,20801,20802,20803,20804,20805,20806,
91305 20807,20808,20809,20810,20811,20812,20813,20814,20815,20816,20817,20818,
91306 20819,20820,20821,20822,20823,20824,20825,20826,20827,20828,20829,20830,
91307 20831,20832,20833,20834,20835,20836,20837,20838,20839,20840,20841,20842,
91308 20843,20844,20845,20846,20847,20848,20849,20850,20851,20852,20853,20854,
91309 20855,20856,20857,20858,20859,20860,20861,20862,20863,20864,20865,20866,
91310 20867,20868,20869,20870,20871,20872,20873,20874,20875,20876,20877,20878,
91311 20879,20880,20881,20882,20883,20884,20885,20886,20887,20888,20889,20890,
91312 20891,20892,20893,20894,20895,20896,20897,20898,20899,20900,20901,20902,
91313 20903,20904,20905,20906,20907,20908,20909,20910,20911,20912,20913,20914,
91314 20915,20916,20917,20918,20919,20920,20921,20922,20923,20924,20925,20926,
91315 20927,20928,20929,20930,20931,20932,20933,20934,20935,20936,20937,20938,
91316 20939,20940,20941,20942,20943,20944,20945,20946,20947,20948,20949,20950,
91317 20951,20952,20953,20954,20955,20956,20957,20958,20959,20960,20961,20962,
91318 20963,20964,20965,20966,20967,20968,20969,20970,20971,20972,20973,20974,
91319 20975,20976,20977,20978,20979,20980,20981,20982,20983,20984,20985,20986,
91320 20987,20988,20989,20990,20991,20992,20993,20994,20995,20996,20997,20998,
91321 20999,21000,21001,21002,21003,21004,21005,21006,21007,21008,21009,21010,
91322 21011,21012,21013,21014,21015,21016,21017,21018,21019,21020,21021,21022,
91323 21023,21024,21025,21026,21027,21028,21029,21030,21031,21032,21033,21034,
91324 21035,21036,21037,21038,21039,21040,21041,21042,21043,21044,21045,21046,
91325 21047,21048,21049,21050,21051,21052,21053,21054,21055,21056,21057,21058,
91326 21059,21060,21061,21062,21063,21064,21065,21066,21067,21068,21069,21070,
91327 21071,21072,21073,21074,21075,21076,21077,21078,21079,21080,21081,21082,
91328 21083,21084,21085,21086,21087,21088,21089,21090,21091,21092,21093,21094,
91329 21095,21096,21097,21098,21099,21100,21101,21102,21103,21104,21105,21106,
91330 21107,21108,21109,21110,21111,21112,21113,21114,21115,21116,21117,21118,
91331 21119,21120,21121,21122,21123,21124,21125,21126,21127,21128,21129,21130,
91332 21131,21132,21133,21134,21135,21136,21137,21138,21139,21140,21141,21142,
91333 21143,21144,21145,21146,21147,21148,21149,21150,21151,21152,21153,21154,
91334 21155,21156,21157,21158,21159,21160,21161,21162,21163,21164,21165,21166,
91335 21167,21168,21169,21170,21171,21172,21173,21174,21175,21176,21177,21178,
91336 21179,21180,21181,21182,21183,21184,21185,21186,21187,21188,21189,21190,
91337 21191,21192,21193,21194,21195,21196,21197,21198,21199,21200,21201,21202,
91338 21203,21204,21205,21206,21207,21208,21209,21210,21211,21212,21213,21214,
91339 21215,21216,21217,21218,21219,21220,21221,21222,21223,21224,21225,21226,
91340 21227,21228,21229,21230,21231,21232,21233,21234,21235,21236,21237,21238,
91341 21239,21240,21241,21242,21243,21244,21245,21246,21247,21248,21249,21250,
91342 21251,21252,21253,21254,21255,21256,21257,21258,21259,21260,21261,21262,
91343 21263,21264,21265,21266,21267,21268,21269,21270,21271,21272,21273,21274,
91344 21275,21276,21277,21278,21279,21280,21281,21282,21283,21284,21285,21286,
91345 21287,21288,21289,21290,21291,21292,21293,21294,21295,21296,21297,21298,
91346 21299,21300,21301,21302,21303,21304,21305,21306,21307,21308,21309,21310,
91347 21311,21312,21313,21314,21315,21316,21317,21318,21319,21320,21321,21322,
91348 21323,21324,21325,21326,21327,21328,21329,21330,21331,21332,21333,21334,
91349 21335,21336,21337,21338,21339,21340,21341,21342,21343,21344,21345,21346,
91350 21347,21348,21349,21350,21351,21352,21353,21354,21355,21356,21357,21358,
91351 21359,21360,21361,21362,21363,21364,21365,21366,21367,21368,21369,21370,
91352 21371,21372,21373,21374,21375,21376,21377,21378,21379,21380,21381,21382,
91353 21383,21384,21385,21386,21387,21388,21389,21390,21391,21392,21393,21394,
91354 21395,21396,21397,21398,21399,21400,21401,21402,21403,21404,21405,21406,
91355 21407,21408,21409,21410,21411,21412,21413,21414,21415,21416,21417,21418,
91356 21419,21420,21421,21422,21423,21424,21425,21426,21427,21428,21429,21430,
91357 21431,21432,21433,21434,21435,21436,21437,21438,21439,21440,21441,21442,
91358 21443,21444,21445,21446,21447,21448,21449,21450,21451,21452,21453,21454,
91359 21455,21456,21457,21458,21459,21460,21461,21462,21463,21464,21465,21466,
91360 21467,21468,21469,21470,21471,21472,21473,21474,21475,21476,21477,21478,
91361 21479,21480,21481,21482,21483,21484,21485,21486,21487,21488,21489,21490,
91362 21491,21492,21493,21494,21495,21496,21497,21498,21499,21500,21501,21502,
91363 21503,21504,21505,21506,21507,21508,21509,21510,21511,21512,21513,21514,
91364 21515,21516,21517,21518,21519,21520,21521,21522,21523,21524,21525,21526,
91365 21527,21528,21529,21530,21531,21532,21533,21534,21535,21536,21537,21538,
91366 21539,21540,21541,21542,21543,21544,21545,21546,21547,21548,21549,21550,
91367 21551,21552,21553,21554,21555,21556,21557,21558,21559,21560,21561,21562,
91368 21563,21564,21565,21566,21567,21568,21569,21570,21571,21572,21573,21574,
91369 21575,21576,21577,21578,21579,21580,21581,21582,21583,21584,21585,21586,
91370 21587,21588,21589,21590,21591,21592,21593,21594,21595,21596,21597,21598,
91371 21599,21600,21601,21602,21603,21604,21605,21606,21607,21608,21609,21610,
91372 21611,21612,21613,21614,21615,21616,21617,21618,21619,21620,21621,21622,
91373 21623,21624,21625,21626,21627,21628,21629,21630,21631,21632,21633,21634,
91374 21635,21636,21637,21638,21639,21640,21641,21642,21643,21644,21645,21646,
91375 21647,21648,21649,21650,21651,21652,21653,21654,21655,21656,21657,21658,
91376 21659,21660,21661,21662,21663,21664,21665,21666,21667,21668,21669,21670,
91377 21671,21672,21673,21674,21675,21676,21677,21678,21679,21680,21681,21682,
91378 21683,21684,21685,21686,21687,21688,21689,21690,21691,21692,21693,21694,
91379 21695,21696,21697,21698,21699,21700,21701,21702,21703,21704,21705,21706,
91380 21707,21708,21709,21710,21711,21712,21713,21714,21715,21716,21717,21718,
91381 21719,21720,21721,21722,21723,21724,21725,21726,21727,21728,21729,21730,
91382 21731,21732,21733,21734,21735,21736,21737,21738,21739,21740,21741,21742,
91383 21743,21744,21745,21746,21747,21748,21749,21750,21751,21752,21753,21754,
91384 21755,21756,21757,21758,21759,21760,21761,21762,21763,21764,21765,21766,
91385 21767,21768,21769,21770,21771,21772,21773,21774,21775,21776,21777,21778,
91386 21779,21780,21781,21782,21783,21784,21785,21786,21787,21788,21789,21790,
91387 21791,21792,21793,21794,21795,21796,21797,21798,21799,21800,21801,21802,
91388 21803,21804,21805,21806,21807,21808,21809,21810,21811,21812,21813,21814,
91389 21815,21816,21817,21818,21819,21820,21821,21822,21823,21824,21825,21826,
91390 21827,21828,21829,21830,21831,21832,21833,21834,21835,21836,21837,21838,
91391 21839,21840,21841,21842,21843,21844,21845,21846,21847,21848,21849,21850,
91392 21851,21852,21853,21854,21855,21856,21857,21858,21859,21860,21861,21862,
91393 21863,21864,21865,21866,21867,21868,21869,21870,21871,21872,21873,21874,
91394 21875,21876,21877,21878,21879,21880,21881,21882,21883,21884,21885,21886,
91395 21887,21888,21889,21890,21891,21892,21893,21894,21895,21896,21897,21898,
91396 21899,21900,21901,21902,21903,21904,21905,21906,21907,21908,21909,21910,
91397 21911,21912,21913,21914,21915,21916,21917,21918,21919,21920,21921,21922,
91398 21923,21924,21925,21926,21927,21928,21929,21930,21931,21932,21933,21934,
91399 21935,21936,21937,21938,21939,21940,21941,21942,21943,21944,21945,21946,
91400 21947,21948,21949,21950,21951,21952,21953,21954,21955,21956,21957,21958,
91401 21959,21960,21961,21962,21963,21964,21965,21966,21967,21968,21969,21970,
91402 21971,21972,21973,21974,21975,21976,21977,21978,21979,21980,21981,21982,
91403 21983,21984,21985,21986,21987,21988,21989,21990,21991,21992,21993,21994,
91404 21995,21996,21997,21998,21999,22000,22001,22002,22003,22004,22005,22006,
91405 22007,22008,22009,22010,22011,22012,22013,22014,22015,22016,22017,22018,
91406 22019,22020,22021,22022,22023,22024,22025,22026,22027,22028,22029,22030,
91407 22031,22032,22033,22034,22035,22036,22037,22038,22039,22040,22041,22042,
91408 22043,22044,22045,22046,22047,22048,22049,22050,22051,22052,22053,22054,
91409 22055,22056,22057,22058,22059,22060,22061,22062,22063,22064,22065,22066,
91410 22067,22068,22069,22070,22071,22072,22073,22074,22075,22076,22077,22078,
91411 22079,22080,22081,22082,22083,22084,22085,22086,22087,22088,22089,22090,
91412 22091,22092,22093,22094,22095,22096,22097,22098,22099,22100,22101,22102,
91413 22103,22104,22105,22106,22107,22108,22109,22110,22111,22112,22113,22114,
91414 22115,22116,22117,22118,22119,22120,22121,22122,22123,22124,22125,22126,
91415 22127,22128,22129,22130,22131,22132,22133,22134,22135,22136,22137,22138,
91416 22139,22140,22141,22142,22143,22144,22145,22146,22147,22148,22149,22150,
91417 22151,22152,22153,22154,22155,22156,22157,22158,22159,22160,22161,22162,
91418 22163,22164,22165,22166,22167,22168,22169,22170,22171,22172,22173,22174,
91419 22175,22176,22177,22178,22179,22180,22181,22182,22183,22184,22185,22186,
91420 22187,22188,22189,22190,22191,22192,22193,22194,22195,22196,22197,22198,
91421 22199,22200,22201,22202,22203,22204,22205,22206,22207,22208,22209,22210,
91422 22211,22212,22213,22214,22215,22216,22217,22218,22219,22220,22221,22222,
91423 22223,22224,22225,22226,22227,22228,22229,22230,22231,22232,22233,22234,
91424 22235,22236,22237,22238,22239,22240,22241,22242,22243,22244,22245,22246,
91425 22247,22248,22249,22250,22251,22252,22253,22254,22255,22256,22257,22258,
91426 22259,22260,22261,22262,22263,22264,22265,22266,22267,22268,22269,22270,
91427 22271,22272,22273,22274,22275,22276,22277,22278,22279,22280,22281,22282,
91428 22283,22284,22285,22286,22287,22288,22289,22290,22291,22292,22293,22294,
91429 22295,22296,22297,22298,22299,22300,22301,22302,22303,22304,22305,22306,
91430 22307,22308,22309,22310,22311,22312,22313,22314,22315,22316,22317,22318,
91431 22319,22320,22321,22322,22323,22324,22325,22326,22327,22328,22329,22330,
91432 22331,22332,22333,22334,22335,22336,22337,22338,22339,22340,22341,22342,
91433 22343,22344,22345,22346,22347,22348,22349,22350,22351,22352,22353,22354,
91434 22355,22356,22357,22358,22359,22360,22361,22362,22363,22364,22365,22366,
91435 22367,22368,22369,22370,22371,22372,22373,22374,22375,22376,22377,22378,
91436 22379,22380,22381,22382,22383,22384,22385,22386,22387,22388,22389,22390,
91437 22391,22392,22393,22394,22395,22396,22397,22398,22399,22400,22401,22402,
91438 22403,22404,22405,22406,22407,22408,22409,22410,22411,22412,22413,22414,
91439 22415,22416,22417,22418,22419,22420,22421,22422,22423,22424,22425,22426,
91440 22427,22428,22429,22430,22431,22432,22433,22434,22435,22436,22437,22438,
91441 22439,22440,22441,22442,22443,22444,22445,22446,22447,22448,22449,22450,
91442 22451,22452,22453,22454,22455,22456,22457,22458,22459,22460,22461,22462,
91443 22463,22464,22465,22466,22467,22468,22469,22470,22471,22472,22473,22474,
91444 22475,22476,22477,22478,22479,22480,22481,22482,22483,22484,22485,22486,
91445 22487,22488,22489,22490,22491,22492,22493,22494,22495,22496,22497,22498,
91446 22499,22500,22501,22502,22503,22504,22505,22506,22507,22508,22509,22510,
91447 22511,22512,22513,22514,22515,22516,22517,22518,22519,22520,22521,22522,
91448 22523,22524,22525,22526,22527,22528,22529,22530,22531,22532,22533,22534,
91449 22535,22536,22537,22538,22539,22540,22541,22542,22543,22544,22545,22546,
91450 22547,22548,22549,22550,22551,22552,22553,22554,22555,22556,22557,22558,
91451 22559,22560,22561,22562,22563,22564,22565,22566,22567,22568,22569,22570,
91452 22571,22572,22573,22574,22575,22576,22577,22578,22579,22580,22581,22582,
91453 22583,22584,22585,22586,22587,22588,22589,22590,22591,22592,22593,22594,
91454 22595,22596,22597,22598,22599,22600,22601,22602,22603,22604,22605,22606,
91455 22607,22608,22609,22610,22611,22612,22613,22614,22615,22616,22617,22618,
91456 22619,22620,22621,22622,22623,22624,22625,22626,22627,22628,22629,22630,
91457 22631,22632,22633,22634,22635,22636,22637,22638,22639,22640,22641,22642,
91458 22643,22644,22645,22646,22647,22648,22649,22650,22651,22652,22653,22654,
91459 22655,22656,22657,22658,22659,22660,22661,22662,22663,22664,22665,22666,
91460 22667,22668,22669,22670,22671,22672,22673,22674,22675,22676,22677,22678,
91461 22679,22680,22681,22682,22683,22684,22685,22686,22687,22688,22689,22690,
91462 22691,22692,22693,22694,22695,22696,22697,22698,22699,22700,22701,22702,
91463 22703,22704,22705,22706,22707,22708,22709,22710,22711,22712,22713,22714,
91464 22715,22716,22717,22718,22719,22720,22721,22722,22723,22724,22725,22726,
91465 22727,22728,22729,22730,22731,22732,22733,22734,22735,22736,22737,22738,
91466 22739,22740,22741,22742,22743,22744,22745,22746,22747,22748,22749,22750,
91467 22751,22752,22753,22754,22755,22756,22757,22758,22759,22760,22761,22762,
91468 22763,22764,22765,22766,22767,22768,22769,22770,22771,22772,22773,22774,
91469 22775,22776,22777,22778,22779,22780,22781,22782,22783,22784,22785,22786,
91470 22787,22788,22789,22790,22791,22792,22793,22794,22795,22796,22797,22798,
91471 22799,22800,22801,22802,22803,22804,22805,22806,22807,22808,22809,22810,
91472 22811,22812,22813,22814,22815,22816,22817,22818,22819,22820,22821,22822,
91473 22823,22824,22825,22826,22827,22828,22829,22830,22831,22832,22833,22834,
91474 22835,22836,22837,22838,22839,22840,22841,22842,22843,22844,22845,22846,
91475 22847,22848,22849,22850,22851,22852,22853,22854,22855,22856,22857,22858,
91476 22859,22860,22861,22862,22863,22864,22865,22866,22867,22868,22869,22870,
91477 22871,22872,22873,22874,22875,22876,22877,22878,22879,22880,22881,22882,
91478 22883,22884,22885,22886,22887,22888,22889,22890,22891,22892,22893,22894,
91479 22895,22896,22897,22898,22899,22900,22901,22902,22903,22904,22905,22906,
91480 22907,22908,22909,22910,22911,22912,22913,22914,22915,22916,22917,22918,
91481 22919,22920,22921,22922,22923,22924,22925,22926,22927,22928,22929,22930,
91482 22931,22932,22933,22934,22935,22936,22937,22938,22939,22940,22941,22942,
91483 22943,22944,22945,22946,22947,22948,22949,22950,22951,22952,22953,22954,
91484 22955,22956,22957,22958,22959,22960,22961,22962,22963,22964,22965,22966,
91485 22967,22968,22969,22970,22971,22972,22973,22974,22975,22976,22977,22978,
91486 22979,22980,22981,22982,22983,22984,22985,22986,22987,22988,22989,22990,
91487 22991,22992,22993,22994,22995,22996,22997,22998,22999,23000,23001,23002,
91488 23003,23004,23005,23006,23007,23008,23009,23010,23011,23012,23013,23014,
91489 23015,23016,23017,23018,23019,23020,23021,23022,23023,23024,23025,23026,
91490 23027,23028,23029,23030,23031,23032,23033,23034,23035,23036,23037,23038,
91491 23039,23040,23041,23042,23043,23044,23045,23046,23047,23048,23049,23050,
91492 23051,23052,23053,23054,23055,23056,23057,23058,23059,23060,23061,23062,
91493 23063,23064,23065,23066,23067,23068,23069,23070,23071,23072,23073,23074,
91494 23075,23076,23077,23078,23079,23080,23081,23082,23083,23084,23085,23086,
91495 23087,23088,23089,23090,23091,23092,23093,23094,23095,23096,23097,23098,
91496 23099,23100,23101,23102,23103,23104,23105,23106,23107,23108,23109,23110,
91497 23111,23112,23113,23114,23115,23116,23117,23118,23119,23120,23121,23122,
91498 23123,23124,23125,23126,23127,23128,23129,23130,23131,23132,23133,23134,
91499 23135,23136,23137,23138,23139,23140,23141,23142,23143,23144,23145,23146,
91500 23147,23148,23149,23150,23151,23152,23153,23154,23155,23156,23157,23158,
91501 23159,23160,23161,23162,23163,23164,23165,23166,23167,23168,23169,23170,
91502 23171,23172,23173,23174,23175,23176,23177,23178,23179,23180,23181,23182,
91503 23183,23184,23185,23186,23187,23188,23189,23190,23191,23192,23193,23194,
91504 23195,23196,23197,23198,23199,23200,23201,23202,23203,23204,23205,23206,
91505 23207,23208,23209,23210,23211,23212,23213,23214,23215,23216,23217,23218,
91506 23219,23220,23221,23222,23223,23224,23225,23226,23227,23228,23229,23230,
91507 23231,23232,23233,23234,23235,23236,23237,23238,23239,23240,23241,23242,
91508 23243,23244,23245,23246,23247,23248,23249,23250,23251,23252,23253,23254,
91509 23255,23256,23257,23258,23259,23260,23261,23262,23263,23264,23265,23266,
91510 23267,23268,23269,23270,23271,23272,23273,23274,23275,23276,23277,23278,
91511 23279,23280,23281,23282,23283,23284,23285,23286,23287,23288,23289,23290,
91512 23291,23292,23293,23294,23295,23296,23297,23298,23299,23300,23301,23302,
91513 23303,23304,23305,23306,23307,23308,23309,23310,23311,23312,23313,23314,
91514 23315,23316,23317,23318,23319,23320,23321,23322,23323,23324,23325,23326,
91515 23327,23328,23329,23330,23331,23332,23333,23334,23335,23336,23337,23338,
91516 23339,23340,23341,23342,23343,23344,23345,23346,23347,23348,23349,23350,
91517 23351,23352,23353,23354,23355,23356,23357,23358,23359,23360,23361,23362,
91518 23363,23364,23365,23366,23367,23368,23369,23370,23371,23372,23373,23374,
91519 23375,23376,23377,23378,23379,23380,23381,23382,23383,23384,23385,23386,
91520 23387,23388,23389,23390,23391,23392,23393,23394,23395,23396,23397,23398,
91521 23399,23400,23401,23402,23403,23404,23405,23406,23407,23408,23409,23410,
91522 23411,23412,23413,23414,23415,23416,23417,23418,23419,23420,23421,23422,
91523 23423,23424,23425,23426,23427,23428,23429,23430,23431,23432,23433,23434,
91524 23435,23436,23437,23438,23439,23440,23441,23442,23443,23444,23445,23446,
91525 23447,23448,23449,23450,23451,23452,23453,23454,23455,23456,23457,23458,
91526 23459,23460,23461,23462,23463,23464,23465,23466,23467,23468,23469,23470,
91527 23471,23472,23473,23474,23475,23476,23477,23478,23479,23480,23481,23482,
91528 23483,23484,23485,23486,23487,23488,23489,23490,23491,23492,23493,23494,
91529 23495,23496,23497,23498,23499,23500,23501,23502,23503,23504,23505,23506,
91530 23507,23508,23509,23510,23511,23512,23513,23514,23515,23516,23517,23518,
91531 23519,23520,23521,23522,23523,23524,23525,23526,23527,23528,23529,23530,
91532 23531,23532,23533,23534,23535,23536,23537,23538,23539,23540,23541,23542,
91533 23543,23544,23545,23546,23547,23548,23549,23550,23551,23552,23553,23554,
91534 23555,23556,23557,23558,23559,23560,23561,23562,23563,23564,23565,23566,
91535 23567,23568,23569,23570,23571,23572,23573,23574,23575,23576,23577,23578,
91536 23579,23580,23581,23582,23583,23584,23585,23586,23587,23588,23589,23590,
91537 23591,23592,23593,23594,23595,23596,23597,23598,23599,23600,23601,23602,
91538 23603,23604,23605,23606,23607,23608,23609,23610,23611,23612,23613,23614,
91539 23615,23616,23617,23618,23619,23620,23621,23622,23623,23624,23625,23626,
91540 23627,23628,23629,23630,23631,23632,23633,23634,23635,23636,23637,23638,
91541 23639,23640,23641,23642,23643,23644,23645,23646,23647,23648,23649,23650,
91542 23651,23652,23653,23654,23655,23656,23657,23658,23659,23660,23661,23662,
91543 23663,23664,23665,23666,23667,23668,23669,23670,23671,23672,23673,23674,
91544 23675,23676,23677,23678,23679,23680,23681,23682,23683,23684,23685,23686,
91545 23687,23688,23689,23690,23691,23692,23693,23694,23695,23696,23697,23698,
91546 23699,23700,23701,23702,23703,23704,23705,23706,23707,23708,23709,23710,
91547 23711,23712,23713,23714,23715,23716,23717,23718,23719,23720,23721,23722,
91548 23723,23724,23725,23726,23727,23728,23729,23730,23731,23732,23733,23734,
91549 23735,23736,23737,23738,23739,23740,23741,23742,23743,23744,23745,23746,
91550 23747,23748,23749,23750,23751,23752,23753,23754,23755,23756,23757,23758,
91551 23759,23760,23761,23762,23763,23764,23765,23766,23767,23768,23769,23770,
91552 23771,23772,23773,23774,23775,23776,23777,23778,23779,23780,23781,23782,
91553 23783,23784,23785,23786,23787,23788,23789,23790,23791,23792,23793,23794,
91554 23795,23796,23797,23798,23799,23800,23801,23802,23803,23804,23805,23806,
91555 23807,23808,23809,23810,23811,23812,23813,23814,23815,23816,23817,23818,
91556 23819,23820,23821,23822,23823,23824,23825,23826,23827,23828,23829,23830,
91557 23831,23832,23833,23834,23835,23836,23837,23838,23839,23840,23841,23842,
91558 23843,23844,23845,23846,23847,23848,23849,23850,23851,23852,23853,23854,
91559 23855,23856,23857,23858,23859,23860,23861,23862,23863,23864,23865,23866,
91560 23867,23868,23869,23870,23871,23872,23873,23874,23875,23876,23877,23878,
91561 23879,23880,23881,23882,23883,23884,23885,23886,23887,23888,23889,23890,
91562 23891,23892,23893,23894,23895,23896,23897,23898,23899,23900,23901,23902,
91563 23903,23904,23905,23906,23907,23908,23909,23910,23911,23912,23913,23914,
91564 23915,23916,23917,23918,23919,23920,23921,23922,23923,23924,23925,23926,
91565 23927,23928,23929,23930,23931,23932,23933,23934,23935,23936,23937,23938,
91566 23939,23940,23941,23942,23943,23944,23945,23946,23947,23948,23949,23950,
91567 23951,23952,23953,23954,23955,23956,23957,23958,23959,23960,23961,23962,
91568 23963,23964,23965,23966,23967,23968,23969,23970,23971,23972,23973,23974,
91569 23975,23976,23977,23978,23979,23980,23981,23982,23983,23984,23985,23986,
91570 23987,23988,23989,23990,23991,23992,23993,23994,23995,23996,23997,23998,
91571 23999,24000,24001,24002,24003,24004,24005,24006,24007,24008,24009,24010,
91572 24011,24012,24013,24014,24015,24016,24017,24018,24019,24020,24021,24022,
91573 24023,24024,24025,24026,24027,24028,24029,24030,24031,24032,24033,24034,
91574 24035,24036,24037,24038,24039,24040,24041,24042,24043,24044,24045,24046,
91575 24047,24048,24049,24050,24051,24052,24053,24054,24055,24056,24057,24058,
91576 24059,24060,24061,24062,24063,24064,24065,24066,24067,24068,24069,24070,
91577 24071,24072,24073,24074,24075,24076,24077,24078,24079,24080,24081,24082,
91578 24083,24084,24085,24086,24087,24088,24089,24090,24091,24092,24093,24094,
91579 24095,24096,24097,24098,24099,24100,24101,24102,24103,24104,24105,24106,
91580 24107,24108,24109,24110,24111,24112,24113,24114,24115,24116,24117,24118,
91581 24119,24120,24121,24122,24123,24124,24125,24126,24127,24128,24129,24130,
91582 24131,24132,24133,24134,24135,24136,24137,24138,24139,24140,24141,24142,
91583 24143,24144,24145,24146,24147,24148,24149,24150,24151,24152,24153,24154,
91584 24155,24156,24157,24158,24159,24160,24161,24162,24163,24164,24165,24166,
91585 24167,24168,24169,24170,24171,24172,24173,24174,24175,24176,24177,24178,
91586 24179,24180,24181,24182,24183,24184,24185,24186,24187,24188,24189,24190,
91587 24191,24192,24193,24194,24195,24196,24197,24198,24199,24200,24201,24202,
91588 24203,24204,24205,24206,24207,24208,24209,24210,24211,24212,24213,24214,
91589 24215,24216,24217,24218,24219,24220,24221,24222,24223,24224,24225,24226,
91590 24227,24228,24229,24230,24231,24232,24233,24234,24235,24236,24237,24238,
91591 24239,24240,24241,24242,24243,24244,24245,24246,24247,24248,24249,24250,
91592 24251,24252,24253,24254,24255,24256,24257,24258,24259,24260,24261,24262,
91593 24263,24264,24265,24266,24267,24268,24269,24270,24271,24272,24273,24274,
91594 24275,24276,24277,24278,24279,24280,24281,24282,24283,24284,24285,24286,
91595 24287,24288,24289,24290,24291,24292,24293,24294,24295,24296,24297,24298,
91596 24299,24300,24301,24302,24303,24304,24305,24306,24307,24308,24309,24310,
91597 24311,24312,24313,24314,24315,24316,24317,24318,24319,24320,24321,24322,
91598 24323,24324,24325,24326,24327,24328,24329,24330,24331,24332,24333,24334,
91599 24335,24336,24337,24338,24339,24340,24341,24342,24343,24344,24345,24346,
91600 24347,24348,24349,24350,24351,24352,24353,24354,24355,24356,24357,24358,
91601 24359,24360,24361,24362,24363,24364,24365,24366,24367,24368,24369,24370,
91602 24371,24372,24373,24374,24375,24376,24377,24378,24379,24380,24381,24382,
91603 24383,24384,24385,24386,24387,24388,24389,24390,24391,24392,24393,24394,
91604 24395,24396,24397,24398,24399,24400,24401,24402,24403,24404,24405,24406,
91605 24407,24408,24409,24410,24411,24412,24413,24414,24415,24416,24417,24418,
91606 24419,24420,24421,24422,24423,24424,24425,24426,24427,24428,24429,24430,
91607 24431,24432,24433,24434,24435,24436,24437,24438,24439,24440,24441,24442,
91608 24443,24444,24445,24446,24447,24448,24449,24450,24451,24452,24453,24454,
91609 24455,24456,24457,24458,24459,24460,24461,24462,24463,24464,24465,24466,
91610 24467,24468,24469,24470,24471,24472,24473,24474,24475,24476,24477,24478,
91611 24479,24480,24481,24482,24483,24484,24485,24486,24487,24488,24489,24490,
91612 24491,24492,24493,24494,24495,24496,24497,24498,24499,24500,24501,24502,
91613 24503,24504,24505,24506,24507,24508,24509,24510,24511,24512,24513,24514,
91614 24515,24516,24517,24518,24519,24520,24521,24522,24523,24524,24525,24526,
91615 24527,24528,24529,24530,24531,24532,24533,24534,24535,24536,24537,24538,
91616 24539,24540,24541,24542,24543,24544,24545,24546,24547,24548,24549,24550,
91617 24551,24552,24553,24554,24555,24556,24557,24558,24559,24560,24561,24562,
91618 24563,24564,24565,24566,24567,24568,24569,24570,24571,24572,24573,24574,
91619 24575,24576,24577,24578,24579,24580,24581,24582,24583,24584,24585,24586,
91620 24587,24588,24589,24590,24591,24592,24593,24594,24595,24596,24597,24598,
91621 24599,24600,24601,24602,24603,24604,24605,24606,24607,24608,24609,24610,
91622 24611,24612,24613,24614,24615,24616,24617,24618,24619,24620,24621,24622,
91623 24623,24624,24625,24626,24627,24628,24629,24630,24631,24632,24633,24634,
91624 24635,24636,24637,24638,24639,24640,24641,24642,24643,24644,24645,24646,
91625 24647,24648,24649,24650,24651,24652,24653,24654,24655,24656,24657,24658,
91626 24659,24660,24661,24662,24663,24664,24665,24666,24667,24668,24669,24670,
91627 24671,24672,24673,24674,24675,24676,24677,24678,24679,24680,24681,24682,
91628 24683,24684,24685,24686,24687,24688,24689,24690,24691,24692,24693,24694,
91629 24695,24696,24697,24698,24699,24700,24701,24702,24703,24704,24705,24706,
91630 24707,24708,24709,24710,24711,24712,24713,24714,24715,24716,24717,24718,
91631 24719,24720,24721,24722,24723,24724,24725,24726,24727,24728,24729,24730,
91632 24731,24732,24733,24734,24735,24736,24737,24738,24739,24740,24741,24742,
91633 24743,24744,24745,24746,24747,24748,24749,24750,24751,24752,24753,24754,
91634 24755,24756,24757,24758,24759,24760,24761,24762,24763,24764,24765,24766,
91635 24767,24768,24769,24770,24771,24772,24773,24774,24775,24776,24777,24778,
91636 24779,24780,24781,24782,24783,24784,24785,24786,24787,24788,24789,24790,
91637 24791,24792,24793,24794,24795,24796,24797,24798,24799,24800,24801,24802,
91638 24803,24804,24805,24806,24807,24808,24809,24810,24811,24812,24813,24814,
91639 24815,24816,24817,24818,24819,24820,24821,24822,24823,24824,24825,24826,
91640 24827,24828,24829,24830,24831,24832,24833,24834,24835,24836,24837,24838,
91641 24839,24840,24841,24842,24843,24844,24845,24846,24847,24848,24849,24850,
91642 24851,24852,24853,24854,24855,24856,24857,24858,24859,24860,24861,24862,
91643 24863,24864,24865,24866,24867,24868,24869,24870,24871,24872,24873,24874,
91644 24875,24876,24877,24878,24879,24880,24881,24882,24883,24884,24885,24886,
91645 24887,24888,24889,24890,24891,24892,24893,24894,24895,24896,24897,24898,
91646 24899,24900,24901,24902,24903,24904,24905,24906,24907,24908,24909,24910,
91647 24911,24912,24913,24914,24915,24916,24917,24918,24919,24920,24921,24922,
91648 24923,24924,24925,24926,24927,24928,24929,24930,24931,24932,24933,24934,
91649 24935,24936,24937,24938,24939,24940,24941,24942,24943,24944,24945,24946,
91650 24947,24948,24949,24950,24951,24952,24953,24954,24955,24956,24957,24958,
91651 24959,24960,24961,24962,24963,24964,24965,24966,24967,24968,24969,24970,
91652 24971,24972,24973,24974,24975,24976,24977,24978,24979,24980,24981,24982,
91653 24983,24984,24985,24986,24987,24988,24989,24990,24991,24992,24993,24994,
91654 24995,24996,24997,24998,24999,25000,25001,25002,25003,25004,25005,25006,
91655 25007,25008,25009,25010,25011,25012,25013,25014,25015,25016,25017,25018,
91656 25019,25020,25021,25022,25023,25024,25025,25026,25027,25028,25029,25030,
91657 25031,25032,25033,25034,25035,25036,25037,25038,25039,25040,25041,25042,
91658 25043,25044,25045,25046,25047,25048,25049,25050,25051,25052,25053,25054,
91659 25055,25056,25057,25058,25059,25060,25061,25062,25063,25064,25065,25066,
91660 25067,25068,25069,25070,25071,25072,25073,25074,25075,25076,25077,25078,
91661 25079,25080,25081,25082,25083,25084,25085,25086,25087,25088,25089,25090,
91662 25091,25092,25093,25094,25095,25096,25097,25098,25099,25100,25101,25102,
91663 25103,25104,25105,25106,25107,25108,25109,25110,25111,25112,25113,25114,
91664 25115,25116,25117,25118,25119,25120,25121,25122,25123,25124,25125,25126,
91665 25127,25128,25129,25130,25131,25132,25133,25134,25135,25136,25137,25138,
91666 25139,25140,25141,25142,25143,25144,25145,25146,25147,25148,25149,25150,
91667 25151,25152,25153,25154,25155,25156,25157,25158,25159,25160,25161,25162,
91668 25163,25164,25165,25166,25167,25168,25169,25170,25171,25172,25173,25174,
91669 25175,25176,25177,25178,25179,25180,25181,25182,25183,25184,25185,25186,
91670 25187,25188,25189,25190,25191,25192,25193,25194,25195,25196,25197,25198,
91671 25199,25200,25201,25202,25203,25204,25205,25206,25207,25208,25209,25210,
91672 25211,25212,25213,25214,25215,25216,25217,25218,25219,25220,25221,25222,
91673 25223,25224,25225,25226,25227,25228,25229,25230,25231,25232,25233,25234,
91674 25235,25236,25237,25238,25239,25240,25241,25242,25243,25244,25245,25246,
91675 25247,25248,25249,25250,25251,25252,25253,25254,25255,25256,25257,25258,
91676 25259,25260,25261,25262,25263,25264,25265,25266,25267,25268,25269,25270,
91677 25271,25272,25273,25274,25275,25276,25277,25278,25279,25280,25281,25282,
91678 25283,25284,25285,25286,25287,25288,25289,25290,25291,25292,25293,25294,
91679 25295,25296,25297,25298,25299,25300,25301,25302,25303,25304,25305,25306,
91680 25307,25308,25309,25310,25311,25312,25313,25314,25315,25316,25317,25318,
91681 25319,25320,25321,25322,25323,25324,25325,25326,25327,25328,25329,25330,
91682 25331,25332,25333,25334,25335,25336,25337,25338,25339,25340,25341,25342,
91683 25343,25344,25345,25346,25347,25348,25349,25350,25351,25352,25353,25354,
91684 25355,25356,25357,25358,25359,25360,25361,25362,25363,25364,25365,25366,
91685 25367,25368,25369,25370,25371,25372,25373,25374,25375,25376,25377,25378,
91686 25379,25380,25381,25382,25383,25384,25385,25386,25387,25388,25389,25390,
91687 25391,25392,25393,25394,25395,25396,25397,25398,25399,25400,25401,25402,
91688 25403,25404,25405,25406,25407,25408,25409,25410,25411,25412,25413,25414,
91689 25415,25416,25417,25418,25419,25420,25421,25422,25423,25424,25425,25426,
91690 25427,25428,25429,25430,25431,25432,25433,25434,25435,25436,25437,25438,
91691 25439,25440,25441,25442,25443,25444,25445,25446,25447,25448,25449,25450,
91692 25451,25452,25453,25454,25455,25456,25457,25458,25459,25460,25461,25462,
91693 25463,25464,25465,25466,25467,25468,25469,25470,25471,25472,25473,25474,
91694 25475,25476,25477,25478,25479,25480,25481,25482,25483,25484,25485,25486,
91695 25487,25488,25489,25490,25491,25492,25493,25494,25495,25496,25497,25498,
91696 25499,25500,25501,25502,25503,25504,25505,25506,25507,25508,25509,25510,
91697 25511,25512,25513,25514,25515,25516,25517,25518,25519,25520,25521,25522,
91698 25523,25524,25525,25526,25527,25528,25529,25530,25531,25532,25533,25534,
91699 25535,25536,25537,25538,25539,25540,25541,25542,25543,25544,25545,25546,
91700 25547,25548,25549,25550,25551,25552,25553,25554,25555,25556,25557,25558,
91701 25559,25560,25561,25562,25563,25564,25565,25566,25567,25568,25569,25570,
91702 25571,25572,25573,25574,25575,25576,25577,25578,25579,25580,25581,25582,
91703 25583,25584,25585,25586,25587,25588,25589,25590,25591,25592,25593,25594,
91704 25595,25596,25597,25598,25599,25600,25601,25602,25603,25604,25605,25606,
91705 25607,25608,25609,25610,25611,25612,25613,25614,25615,25616,25617,25618,
91706 25619,25620,25621,25622,25623,25624,25625,25626,25627,25628,25629,25630,
91707 25631,25632,25633,25634,25635,25636,25637,25638,25639,25640,25641,25642,
91708 25643,25644,25645,25646,25647,25648,25649,25650,25651,25652,25653,25654,
91709 25655,25656,25657,25658,25659,25660,25661,25662,25663,25664,25665,25666,
91710 25667,25668,25669,25670,25671,25672,25673,25674,25675,25676,25677,25678,
91711 25679,25680,25681,25682,25683,25684,25685,25686,25687,25688,25689,25690,
91712 25691,25692,25693,25694,25695,25696,25697,25698,25699,25700,25701,25702,
91713 25703,25704,25705,25706,25707,25708,25709,25710,25711,25712,25713,25714,
91714 25715,25716,25717,25718,25719,25720,25721,25722,25723,25724,25725,25726,
91715 25727,25728,25729,25730,25731,25732,25733,25734,25735,25736,25737,25738,
91716 25739,25740,25741,25742,25743,25744,25745,25746,25747,25748,25749,25750,
91717 25751,25752,25753,25754,25755,25756,25757,25758,25759,25760,25761,25762,
91718 25763,25764,25765,25766,25767,25768,25769,25770,25771,25772,25773,25774,
91719 25775,25776,25777,25778,25779,25780,25781,25782,25783,25784,25785,25786,
91720 25787,25788,25789,25790,25791,25792,25793,25794,25795,25796,25797,25798,
91721 25799,25800,25801,25802,25803,25804,25805,25806,25807,25808,25809,25810,
91722 25811,25812,25813,25814,25815,25816,25817,25818,25819,25820,25821,25822,
91723 25823,25824,25825,25826,25827,25828,25829,25830,25831,25832,25833,25834,
91724 25835,25836,25837,25838,25839,25840,25841,25842,25843,25844,25845,25846,
91725 25847,25848,25849,25850,25851,25852,25853,25854,25855,25856,25857,25858,
91726 25859,25860,25861,25862,25863,25864,25865,25866,25867,25868,25869,25870,
91727 25871,25872,25873,25874,25875,25876,25877,25878,25879,25880,25881,25882,
91728 25883,25884,25885,25886,25887,25888,25889,25890,25891,25892,25893,25894,
91729 25895,25896,25897,25898,25899,25900,25901,25902,25903,25904,25905,25906,
91730 25907,25908,25909,25910,25911,25912,25913,25914,25915,25916,25917,25918,
91731 25919,25920,25921,25922,25923,25924,25925,25926,25927,25928,25929,25930,
91732 25931,25932,25933,25934,25935,25936,25937,25938,25939,25940,25941,25942,
91733 25943,25944,25945,25946,25947,25948,25949,25950,25951,25952,25953,25954,
91734 25955,25956,25957,25958,25959,25960,25961,25962,25963,25964,25965,25966,
91735 25967,25968,25969,25970,25971,25972,25973,25974,25975,25976,25977,25978,
91736 25979,25980,25981,25982,25983,25984,25985,25986,25987,25988,25989,25990,
91737 25991,25992,25993,25994,25995,25996,25997,25998,25999,26000,26001,26002,
91738 26003,26004,26005,26006,26007,26008,26009,26010,26011,26012,26013,26014,
91739 26015,26016,26017,26018,26019,26020,26021,26022,26023,26024,26025,26026,
91740 26027,26028,26029,26030,26031,26032,26033,26034,26035,26036,26037,26038,
91741 26039,26040,26041,26042,26043,26044,26045,26046,26047,26048,26049,26050,
91742 26051,26052,26053,26054,26055,26056,26057,26058,26059,26060,26061,26062,
91743 26063,26064,26065,26066,26067,26068,26069,26070,26071,26072,26073,26074,
91744 26075,26076,26077,26078,26079,26080,26081,26082,26083,26084,26085,26086,
91745 26087,26088,26089,26090,26091,26092,26093,26094,26095,26096,26097,26098,
91746 26099,26100,26101,26102,26103,26104,26105,26106,26107,26108,26109,26110,
91747 26111,26112,26113,26114,26115,26116,26117,26118,26119,26120,26121,26122,
91748 26123,26124,26125,26126,26127,26128,26129,26130,26131,26132,26133,26134,
91749 26135,26136,26137,26138,26139,26140,26141,26142,26143,26144,26145,26146,
91750 26147,26148,26149,26150,26151,26152,26153,26154,26155,26156,26157,26158,
91751 26159,26160,26161,26162,26163,26164,26165,26166,26167,26168,26169,26170,
91752 26171,26172,26173,26174,26175,26176,26177,26178,26179,26180,26181,26182,
91753 26183,26184,26185,26186,26187,26188,26189,26190,26191,26192,26193,26194,
91754 26195,26196,26197,26198,26199,26200,26201,26202,26203,26204,26205,26206,
91755 26207,26208,26209,26210,26211,26212,26213,26214,26215,26216,26217,26218,
91756 26219,26220,26221,26222,26223,26224,26225,26226,26227,26228,26229,26230,
91757 26231,26232,26233,26234,26235,26236,26237,26238,26239,26240,26241,26242,
91758 26243,26244,26245,26246,26247,26248,26249,26250,26251,26252,26253,26254,
91759 26255,26256,26257,26258,26259,26260,26261,26262,26263,26264,26265,26266,
91760 26267,26268,26269,26270,26271,26272,26273,26274,26275,26276,26277,26278,
91761 26279,26280,26281,26282,26283,26284,26285,26286,26287,26288,26289,26290,
91762 26291,26292,26293,26294,26295,26296,26297,26298,26299,26300,26301,26302,
91763 26303,26304,26305,26306,26307,26308,26309,26310,26311,26312,26313,26314,
91764 26315,26316,26317,26318,26319,26320,26321,26322,26323,26324,26325,26326,
91765 26327,26328,26329,26330,26331,26332,26333,26334,26335,26336,26337,26338,
91766 26339,26340,26341,26342,26343,26344,26345,26346,26347,26348,26349,26350,
91767 26351,26352,26353,26354,26355,26356,26357,26358,26359,26360,26361,26362,
91768 26363,26364,26365,26366,26367,26368,26369,26370,26371,26372,26373,26374,
91769 26375,26376,26377,26378,26379,26380,26381,26382,26383,26384,26385,26386,
91770 26387,26388,26389,26390,26391,26392,26393,26394,26395,26396,26397,26398,
91771 26399,26400,26401,26402,26403,26404,26405,26406,26407,26408,26409,26410,
91772 26411,26412,26413,26414,26415,26416,26417,26418,26419,26420,26421,26422,
91773 26423,26424,26425,26426,26427,26428,26429,26430,26431,26432,26433,26434,
91774 26435,26436,26437,26438,26439,26440,26441,26442,26443,26444,26445,26446,
91775 26447,26448,26449,26450,26451,26452,26453,26454,26455,26456,26457,26458,
91776 26459,26460,26461,26462,26463,26464,26465,26466,26467,26468,26469,26470,
91777 26471,26472,26473,26474,26475,26476,26477,26478,26479,26480,26481,26482,
91778 26483,26484,26485,26486,26487,26488,26489,26490,26491,26492,26493,26494,
91779 26495,26496,26497,26498,26499,26500,26501,26502,26503,26504,26505,26506,
91780 26507,26508,26509,26510,26511,26512,26513,26514,26515,26516,26517,26518,
91781 26519,26520,26521,26522,26523,26524,26525,26526,26527,26528,26529,26530,
91782 26531,26532,26533,26534,26535,26536,26537,26538,26539,26540,26541,26542,
91783 26543,26544,26545,26546,26547,26548,26549,26550,26551,26552,26553,26554,
91784 26555,26556,26557,26558,26559,26560,26561,26562,26563,26564,26565,26566,
91785 26567,26568,26569,26570,26571,26572,26573,26574,26575,26576,26577,26578,
91786 26579,26580,26581,26582,26583,26584,26585,26586,26587,26588,26589,26590,
91787 26591,26592,26593,26594,26595,26596,26597,26598,26599,26600,26601,26602,
91788 26603,26604,26605,26606,26607,26608,26609,26610,26611,26612,26613,26614,
91789 26615,26616,26617,26618,26619,26620,26621,26622,26623,26624,26625,26626,
91790 26627,26628,26629,26630,26631,26632,26633,26634,26635,26636,26637,26638,
91791 26639,26640,26641,26642,26643,26644,26645,26646,26647,26648,26649,26650,
91792 26651,26652,26653,26654,26655,26656,26657,26658,26659,26660,26661,26662,
91793 26663,26664,26665,26666,26667,26668,26669,26670,26671,26672,26673,26674,
91794 26675,26676,26677,26678,26679,26680,26681,26682,26683,26684,26685,26686,
91795 26687,26688,26689,26690,26691,26692,26693,26694,26695,26696,26697,26698,
91796 26699,26700,26701,26702,26703,26704,26705,26706,26707,26708,26709,26710,
91797 26711,26712,26713,26714,26715,26716,26717,26718,26719,26720,26721,26722,
91798 26723,26724,26725,26726,26727,26728,26729,26730,26731,26732,26733,26734,
91799 26735,26736,26737,26738,26739,26740,26741,26742,26743,26744,26745,26746,
91800 26747,26748,26749,26750,26751,26752,26753,26754,26755,26756,26757,26758,
91801 26759,26760,26761,26762,26763,26764,26765,26766,26767,26768,26769,26770,
91802 26771,26772,26773,26774,26775,26776,26777,26778,26779,26780,26781,26782,
91803 26783,26784,26785,26786,26787,26788,26789,26790,26791,26792,26793,26794,
91804 26795,26796,26797,26798,26799,26800,26801,26802,26803,26804,26805,26806,
91805 26807,26808,26809,26810,26811,26812,26813,26814,26815,26816,26817,26818,
91806 26819,26820,26821,26822,26823,26824,26825,26826,26827,26828,26829,26830,
91807 26831,26832,26833,26834,26835,26836,26837,26838,26839,26840,26841,26842,
91808 26843,26844,26845,26846,26847,26848,26849,26850,26851,26852,26853,26854,
91809 26855,26856,26857,26858,26859,26860,26861,26862,26863,26864,26865,26866,
91810 26867,26868,26869,26870,26871,26872,26873,26874,26875,26876,26877,26878,
91811 26879,26880,26881,26882,26883,26884,26885,26886,26887,26888,26889,26890,
91812 26891,26892,26893,26894,26895,26896,26897,26898,26899,26900,26901,26902,
91813 26903,26904,26905,26906,26907,26908,26909,26910,26911,26912,26913,26914,
91814 26915,26916,26917,26918,26919,26920,26921,26922,26923,26924,26925,26926,
91815 26927,26928,26929,26930,26931,26932,26933,26934,26935,26936,26937,26938,
91816 26939,26940,26941,26942,26943,26944,26945,26946,26947,26948,26949,26950,
91817 26951,26952,26953,26954,26955,26956,26957,26958,26959,26960,26961,26962,
91818 26963,26964,26965,26966,26967,26968,26969,26970,26971,26972,26973,26974,
91819 26975,26976,26977,26978,26979,26980,26981,26982,26983,26984,26985,26986,
91820 26987,26988,26989,26990,26991,26992,26993,26994,26995,26996,26997,26998,
91821 26999,27000,27001,27002,27003,27004,27005,27006,27007,27008,27009,27010,
91822 27011,27012,27013,27014,27015,27016,27017,27018,27019,27020,27021,27022,
91823 27023,27024,27025,27026,27027,27028,27029,27030,27031,27032,27033,27034,
91824 27035,27036,27037,27038,27039,27040,27041,27042,27043,27044,27045,27046,
91825 27047,27048,27049,27050,27051,27052,27053,27054,27055,27056,27057,27058,
91826 27059,27060,27061,27062,27063,27064,27065,27066,27067,27068,27069,27070,
91827 27071,27072,27073,27074,27075,27076,27077,27078,27079,27080,27081,27082,
91828 27083,27084,27085,27086,27087,27088,27089,27090,27091,27092,27093,27094,
91829 27095,27096,27097,27098,27099,27100,27101,27102,27103,27104,27105,27106,
91830 27107,27108,27109,27110,27111,27112,27113,27114,27115,27116,27117,27118,
91831 27119,27120,27121,27122,27123,27124,27125,27126,27127,27128,27129,27130,
91832 27131,27132,27133,27134,27135,27136,27137,27138,27139,27140,27141,27142,
91833 27143,27144,27145,27146,27147,27148,27149,27150,27151,27152,27153,27154,
91834 27155,27156,27157,27158,27159,27160,27161,27162,27163,27164,27165,27166,
91835 27167,27168,27169,27170,27171,27172,27173,27174,27175,27176,27177,27178,
91836 27179,27180,27181,27182,27183,27184,27185,27186,27187,27188,27189,27190,
91837 27191,27192,27193,27194,27195,27196,27197,27198,27199,27200,27201,27202,
91838 27203,27204,27205,27206,27207,27208,27209,27210,27211,27212,27213,27214,
91839 27215,27216,27217,27218,27219,27220,27221,27222,27223,27224,27225,27226,
91840 27227,27228,27229,27230,27231,27232,27233,27234,27235,27236,27237,27238,
91841 27239,27240,27241,27242,27243,27244,27245,27246,27247,27248,27249,27250,
91842 27251,27252,27253,27254,27255,27256,27257,27258,27259,27260,27261,27262,
91843 27263,27264,27265,27266,27267,27268,27269,27270,27271,27272,27273,27274,
91844 27275,27276,27277,27278,27279,27280,27281,27282,27283,27284,27285,27286,
91845 27287,27288,27289,27290,27291,27292,27293,27294,27295,27296,27297,27298,
91846 27299,27300,27301,27302,27303,27304,27305,27306,27307,27308,27309,27310,
91847 27311,27312,27313,27314,27315,27316,27317,27318,27319,27320,27321,27322,
91848 27323,27324,27325,27326,27327,27328,27329,27330,27331,27332,27333,27334,
91849 27335,27336,27337,27338,27339,27340,27341,27342,27343,27344,27345,27346,
91850 27347,27348,27349,27350,27351,27352,27353,27354,27355,27356,27357,27358,
91851 27359,27360,27361,27362,27363,27364,27365,27366,27367,27368,27369,27370,
91852 27371,27372,27373,27374,27375,27376,27377,27378,27379,27380,27381,27382,
91853 27383,27384,27385,27386,27387,27388,27389,27390,27391,27392,27393,27394,
91854 27395,27396,27397,27398,27399,27400,27401,27402,27403,27404,27405,27406,
91855 27407,27408,27409,27410,27411,27412,27413,27414,27415,27416,27417,27418,
91856 27419,27420,27421,27422,27423,27424,27425,27426,27427,27428,27429,27430,
91857 27431,27432,27433,27434,27435,27436,27437,27438,27439,27440,27441,27442,
91858 27443,27444,27445,27446,27447,27448,27449,27450,27451,27452,27453,27454,
91859 27455,27456,27457,27458,27459,27460,27461,27462,27463,27464,27465,27466,
91860 27467,27468,27469,27470,27471,27472,27473,27474,27475,27476,27477,27478,
91861 27479,27480,27481,27482,27483,27484,27485,27486,27487,27488,27489,27490,
91862 27491,27492,27493,27494,27495,27496,27497,27498,27499,27500,27501,27502,
91863 27503,27504,27505,27506,27507,27508,27509,27510,27511,27512,27513,27514,
91864 27515,27516,27517,27518,27519,27520,27521,27522,27523,27524,27525,27526,
91865 27527,27528,27529,27530,27531,27532,27533,27534,27535,27536,27537,27538,
91866 27539,27540,27541,27542,27543,27544,27545,27546,27547,27548,27549,27550,
91867 27551,27552,27553,27554,27555,27556,27557,27558,27559,27560,27561,27562,
91868 27563,27564,27565,27566,27567,27568,27569,27570,27571,27572,27573,27574,
91869 27575,27576,27577,27578,27579,27580,27581,27582,27583,27584,27585,27586,
91870 27587,27588,27589,27590,27591,27592,27593,27594,27595,27596,27597,27598,
91871 27599,27600,27601,27602,27603,27604,27605,27606,27607,27608,27609,27610,
91872 27611,27612,27613,27614,27615,27616,27617,27618,27619,27620,27621,27622,
91873 27623,27624,27625,27626,27627,27628,27629,27630,27631,27632,27633,27634,
91874 27635,27636,27637,27638,27639,27640,27641,27642,27643,27644,27645,27646,
91875 27647,27648,27649,27650,27651,27652,27653,27654,27655,27656,27657,27658,
91876 27659,27660,27661,27662,27663,27664,27665,27666,27667,27668,27669,27670,
91877 27671,27672,27673,27674,27675,27676,27677,27678,27679,27680,27681,27682,
91878 27683,27684,27685,27686,27687,27688,27689,27690,27691,27692,27693,27694,
91879 27695,27696,27697,27698,27699,27700,27701,27702,27703,27704,27705,27706,
91880 27707,27708,27709,27710,27711,27712,27713,27714,27715,27716,27717,27718,
91881 27719,27720,27721,27722,27723,27724,27725,27726,27727,27728,27729,27730,
91882 27731,27732,27733,27734,27735,27736,27737,27738,27739,27740,27741,27742,
91883 27743,27744,27745,27746,27747,27748,27749,27750,27751,27752,27753,27754,
91884 27755,27756,27757,27758,27759,27760,27761,27762,27763,27764,27765,27766,
91885 27767,27768,27769,27770,27771,27772,27773,27774,27775,27776,27777,27778,
91886 27779,27780,27781,27782,27783,27784,27785,27786,27787,27788,27789,27790,
91887 27791,27792,27793,27794,27795,27796,27797,27798,27799,27800,27801,27802,
91888 27803,27804,27805,27806,27807,27808,27809,27810,27811,27812,27813,27814,
91889 27815,27816,27817,27818,27819,27820,27821,27822,27823,27824,27825,27826,
91890 27827,27828,27829,27830,27831,27832,27833,27834,27835,27836,27837,27838,
91891 27839,27840,27841,27842,27843,27844,27845,27846,27847,27848,27849,27850,
91892 27851,27852,27853,27854,27855,27856,27857,27858,27859,27860,27861,27862,
91893 27863,27864,27865,27866,27867,27868,27869,27870,27871,27872,27873,27874,
91894 27875,27876,27877,27878,27879,27880,27881,27882,27883,27884,27885,27886,
91895 27887,27888,27889,27890,27891,27892,27893,27894,27895,27896,27897,27898,
91896 27899,27900,27901,27902,27903,27904,27905,27906,27907,27908,27909,27910,
91897 27911,27912,27913,27914,27915,27916,27917,27918,27919,27920,27921,27922,
91898 27923,27924,27925,27926,27927,27928,27929,27930,27931,27932,27933,27934,
91899 27935,27936,27937,27938,27939,27940,27941,27942,27943,27944,27945,27946,
91900 27947,27948,27949,27950,27951,27952,27953,27954,27955,27956,27957,27958,
91901 27959,27960,27961,27962,27963,27964,27965,27966,27967,27968,27969,27970,
91902 27971,27972,27973,27974,27975,27976,27977,27978,27979,27980,27981,27982,
91903 27983,27984,27985,27986,27987,27988,27989,27990,27991,27992,27993,27994,
91904 27995,27996,27997,27998,27999,28000,28001,28002,28003,28004,28005,28006,
91905 28007,28008,28009,28010,28011,28012,28013,28014,28015,28016,28017,28018,
91906 28019,28020,28021,28022,28023,28024,28025,28026,28027,28028,28029,28030,
91907 28031,28032,28033,28034,28035,28036,28037,28038,28039,28040,28041,28042,
91908 28043,28044,28045,28046,28047,28048,28049,28050,28051,28052,28053,28054,
91909 28055,28056,28057,28058,28059,28060,28061,28062,28063,28064,28065,28066,
91910 28067,28068,28069,28070,28071,28072,28073,28074,28075,28076,28077,28078,
91911 28079,28080,28081,28082,28083,28084,28085,28086,28087,28088,28089,28090,
91912 28091,28092,28093,28094,28095,28096,28097,28098,28099,28100,28101,28102,
91913 28103,28104,28105,28106,28107,28108,28109,28110,28111,28112,28113,28114,
91914 28115,28116,28117,28118,28119,28120,28121,28122,28123,28124,28125,28126,
91915 28127,28128,28129,28130,28131,28132,28133,28134,28135,28136,28137,28138,
91916 28139,28140,28141,28142,28143,28144,28145,28146,28147,28148,28149,28150,
91917 28151,28152,28153,28154,28155,28156,28157,28158,28159,28160,28161,28162,
91918 28163,28164,28165,28166,28167,28168,28169,28170,28171,28172,28173,28174,
91919 28175,28176,28177,28178,28179,28180,28181,28182,28183,28184,28185,28186,
91920 28187,28188,28189,28190,28191,28192,28193,28194,28195,28196,28197,28198,
91921 28199,28200,28201,28202,28203,28204,28205,28206,28207,28208,28209,28210,
91922 28211,28212,28213,28214,28215,28216,28217,28218,28219,28220,28221,28222,
91923 28223,28224,28225,28226,28227,28228,28229,28230,28231,28232,28233,28234,
91924 28235,28236,28237,28238,28239,28240,28241,28242,28243,28244,28245,28246,
91925 28247,28248,28249,28250,28251,28252,28253,28254,28255,28256,28257,28258,
91926 28259,28260,28261,28262,28263,28264,28265,28266,28267,28268,28269,28270,
91927 28271,28272,28273,28274,28275,28276,28277,28278,28279,28280,28281,28282,
91928 28283,28284,28285,28286,28287,28288,28289,28290,28291,28292,28293,28294,
91929 28295,28296,28297,28298,28299,28300,28301,28302,28303,28304,28305,28306,
91930 28307,28308,28309,28310,28311,28312,28313,28314,28315,28316,28317,28318,
91931 28319,28320,28321,28322,28323,28324,28325,28326,28327,28328,28329,28330,
91932 28331,28332,28333,28334,28335,28336,28337,28338,28339,28340,28341,28342,
91933 28343,28344,28345,28346,28347,28348,28349,28350,28351,28352,28353,28354,
91934 28355,28356,28357,28358,28359,28360,28361,28362,28363,28364,28365,28366,
91935 28367,28368,28369,28370,28371,28372,28373,28374,28375,28376,28377,28378,
91936 28379,28380,28381,28382,28383,28384,28385,28386,28387,28388,28389,28390,
91937 28391,28392,28393,28394,28395,28396,28397,28398,28399,28400,28401,28402,
91938 28403,28404,28405,28406,28407,28408,28409,28410,28411,28412,28413,28414,
91939 28415,28416,28417,28418,28419,28420,28421,28422,28423,28424,28425,28426,
91940 28427,28428,28429,28430,28431,28432,28433,28434,28435,28436,28437,28438,
91941 28439,28440,28441,28442,28443,28444,28445,28446,28447,28448,28449,28450,
91942 28451,28452,28453,28454,28455,28456,28457,28458,28459,28460,28461,28462,
91943 28463,28464,28465,28466,28467,28468,28469,28470,28471,28472,28473,28474,
91944 28475,28476,28477,28478,28479,28480,28481,28482,28483,28484,28485,28486,
91945 28487,28488,28489,28490,28491,28492,28493,28494,28495,28496,28497,28498,
91946 28499,28500,28501,28502,28503,28504,28505,28506,28507,28508,28509,28510,
91947 28511,28512,28513,28514,28515,28516,28517,28518,28519,28520,28521,28522,
91948 28523,28524,28525,28526,28527,28528,28529,28530,28531,28532,28533,28534,
91949 28535,28536,28537,28538,28539,28540,28541,28542,28543,28544,28545,28546,
91950 28547,28548,28549,28550,28551,28552,28553,28554,28555,28556,28557,28558,
91951 28559,28560,28561,28562,28563,28564,28565,28566,28567,28568,28569,28570,
91952 28571,28572,28573,28574,28575,28576,28577,28578,28579,28580,28581,28582,
91953 28583,28584,28585,28586,28587,28588,28589,28590,28591,28592,28593,28594,
91954 28595,28596,28597,28598,28599,28600,28601,28602,28603,28604,28605,28606,
91955 28607,28608,28609,28610,28611,28612,28613,28614,28615,28616,28617,28618,
91956 28619,28620,28621,28622,28623,28624,28625,28626,28627,28628,28629,28630,
91957 28631,28632,28633,28634,28635,28636,28637,28638,28639,28640,28641,28642,
91958 28643,28644,28645,28646,28647,28648,28649,28650,28651,28652,28653,28654,
91959 28655,28656,28657,28658,28659,28660,28661,28662,28663,28664,28665,28666,
91960 28667,28668,28669,28670,28671,28672,28673,28674,28675,28676,28677,28678,
91961 28679,28680,28681,28682,28683,28684,28685,28686,28687,28688,28689,28690,
91962 28691,28692,28693,28694,28695,28696,28697,28698,28699,28700,28701,28702,
91963 28703,28704,28705,28706,28707,28708,28709,28710,28711,28712,28713,28714,
91964 28715,28716,28717,28718,28719,28720,28721,28722,28723,28724,28725,28726,
91965 28727,28728,28729,28730,28731,28732,28733,28734,28735,28736,28737,28738,
91966 28739,28740,28741,28742,28743,28744,28745,28746,28747,28748,28749,28750,
91967 28751,28752,28753,28754,28755,28756,28757,28758,28759,28760,28761,28762,
91968 28763,28764,28765,28766,28767,28768,28769,28770,28771,28772,28773,28774,
91969 28775,28776,28777,28778,28779,28780,28781,28782,28783,28784,28785,28786,
91970 28787,28788,28789,28790,28791,28792,28793,28794,28795,28796,28797,28798,
91971 28799,28800,28801,28802,28803,28804,28805,28806,28807,28808,28809,28810,
91972 28811,28812,28813,28814,28815,28816,28817,28818,28819,28820,28821,28822,
91973 28823,28824,28825,28826,28827,28828,28829,28830,28831,28832,28833,28834,
91974 28835,28836,28837,28838,28839,28840,28841,28842,28843,28844,28845,28846,
91975 28847,28848,28849,28850,28851,28852,28853,28854,28855,28856,28857,28858,
91976 28859,28860,28861,28862,28863,28864,28865,28866,28867,28868,28869,28870,
91977 28871,28872,28873,28874,28875,28876,28877,28878,28879,28880,28881,28882,
91978 28883,28884,28885,28886,28887,28888,28889,28890,28891,28892,28893,28894,
91979 28895,28896,28897,28898,28899,28900,28901,28902,28903,28904,28905,28906,
91980 28907,28908,28909,28910,28911,28912,28913,28914,28915,28916,28917,28918,
91981 28919,28920,28921,28922,28923,28924,28925,28926,28927,28928,28929,28930,
91982 28931,28932,28933,28934,28935,28936,28937,28938,28939,28940,28941,28942,
91983 28943,28944,28945,28946,28947,28948,28949,28950,28951,28952,28953,28954,
91984 28955,28956,28957,28958,28959,28960,28961,28962,28963,28964,28965,28966,
91985 28967,28968,28969,28970,28971,28972,28973,28974,28975,28976,28977,28978,
91986 28979,28980,28981,28982,28983,28984,28985,28986,28987,28988,28989,28990,
91987 28991,28992,28993,28994,28995,28996,28997,28998,28999,29000,29001,29002,
91988 29003,29004,29005,29006,29007,29008,29009,29010,29011,29012,29013,29014,
91989 29015,29016,29017,29018,29019,29020,29021,29022,29023,29024,29025,29026,
91990 29027,29028,29029,29030,29031,29032,29033,29034,29035,29036,29037,29038,
91991 29039,29040,29041,29042,29043,29044,29045,29046,29047,29048,29049,29050,
91992 29051,29052,29053,29054,29055,29056,29057,29058,29059,29060,29061,29062,
91993 29063,29064,29065,29066,29067,29068,29069,29070,29071,29072,29073,29074,
91994 29075,29076,29077,29078,29079,29080,29081,29082,29083,29084,29085,29086,
91995 29087,29088,29089,29090,29091,29092,29093,29094,29095,29096,29097,29098,
91996 29099,29100,29101,29102,29103,29104,29105,29106,29107,29108,29109,29110,
91997 29111,29112,29113,29114,29115,29116,29117,29118,29119,29120,29121,29122,
91998 29123,29124,29125,29126,29127,29128,29129,29130,29131,29132,29133,29134,
91999 29135,29136,29137,29138,29139,29140,29141,29142,29143,29144,29145,29146,
92000 29147,29148,29149,29150,29151,29152,29153,29154,29155,29156,29157,29158,
92001 29159,29160,29161,29162,29163,29164,29165,29166,29167,29168,29169,29170,
92002 29171,29172,29173,29174,29175,29176,29177,29178,29179,29180,29181,29182,
92003 29183,29184,29185,29186,29187,29188,29189,29190,29191,29192,29193,29194,
92004 29195,29196,29197,29198,29199,29200,29201,29202,29203,29204,29205,29206,
92005 29207,29208,29209,29210,29211,29212,29213,29214,29215,29216,29217,29218,
92006 29219,29220,29221,29222,29223,29224,29225,29226,29227,29228,29229,29230,
92007 29231,29232,29233,29234,29235,29236,29237,29238,29239,29240,29241,29242,
92008 29243,29244,29245,29246,29247,29248,29249,29250,29251,29252,29253,29254,
92009 29255,29256,29257,29258,29259,29260,29261,29262,29263,29264,29265,29266,
92010 29267,29268,29269,29270,29271,29272,29273,29274,29275,29276,29277,29278,
92011 29279,29280,29281,29282,29283,29284,29285,29286,29287,29288,29289,29290,
92012 29291,29292,29293,29294,29295,29296,29297,29298,29299,29300,29301,29302,
92013 29303,29304,29305,29306,29307,29308,29309,29310,29311,29312,29313,29314,
92014 29315,29316,29317,29318,29319,29320,29321,29322,29323,29324,29325,29326,
92015 29327,29328,29329,29330,29331,29332,29333,29334,29335,29336,29337,29338,
92016 29339,29340,29341,29342,29343,29344,29345,29346,29347,29348,29349,29350,
92017 29351,29352,29353,29354,29355,29356,29357,29358,29359,29360,29361,29362,
92018 29363,29364,29365,29366,29367,29368,29369,29370,29371,29372,29373,29374,
92019 29375,29376,29377,29378,29379,29380,29381,29382,29383,29384,29385,29386,
92020 29387,29388,29389,29390,29391,29392,29393,29394,29395,29396,29397,29398,
92021 29399,29400,29401,29402,29403,29404,29405,29406,29407,29408,29409,29410,
92022 29411,29412,29413,29414,29415,29416,29417,29418,29419,29420,29421,29422,
92023 29423,29424,29425,29426,29427,29428,29429,29430,29431,29432,29433,29434,
92024 29435,29436,29437,29438,29439,29440,29441,29442,29443,29444,29445,29446,
92025 29447,29448,29449,29450,29451,29452,29453,29454,29455,29456,29457,29458,
92026 29459,29460,29461,29462,29463,29464,29465,29466,29467,29468,29469,29470,
92027 29471,29472,29473,29474,29475,29476,29477,29478,29479,29480,29481,29482,
92028 29483,29484,29485,29486,29487,29488,29489,29490,29491,29492,29493,29494,
92029 29495,29496,29497,29498,29499,29500,29501,29502,29503,29504,29505,29506,
92030 29507,29508,29509,29510,29511,29512,29513,29514,29515,29516,29517,29518,
92031 29519,29520,29521,29522,29523,29524,29525,29526,29527,29528,29529,29530,
92032 29531,29532,29533,29534,29535,29536,29537,29538,29539,29540,29541,29542,
92033 29543,29544,29545,29546,29547,29548,29549,29550,29551,29552,29553,29554,
92034 29555,29556,29557,29558,29559,29560,29561,29562,29563,29564,29565,29566,
92035 29567,29568,29569,29570,29571,29572,29573,29574,29575,29576,29577,29578,
92036 29579,29580,29581,29582,29583,29584,29585,29586,29587,29588,29589,29590,
92037 29591,29592,29593,29594,29595,29596,29597,29598,29599,29600,29601,29602,
92038 29603,29604,29605,29606,29607,29608,29609,29610,29611,29612,29613,29614,
92039 29615,29616,29617,29618,29619,29620,29621,29622,29623,29624,29625,29626,
92040 29627,29628,29629,29630,29631,29632,29633,29634,29635,29636,29637,29638,
92041 29639,29640,29641,29642,29643,29644,29645,29646,29647,29648,29649,29650,
92042 29651,29652,29653,29654,29655,29656,29657,29658,29659,29660,29661,29662,
92043 29663,29664,29665,29666,29667,29668,29669,29670,29671,29672,29673,29674,
92044 29675,29676,29677,29678,29679,29680,29681,29682,29683,29684,29685,29686,
92045 29687,29688,29689,29690,29691,29692,29693,29694,29695,29696,29697,29698,
92046 29699,29700,29701,29702,29703,29704,29705,29706,29707,29708,29709,29710,
92047 29711,29712,29713,29714,29715,29716,29717,29718,29719,29720,29721,29722,
92048 29723,29724,29725,29726,29727,29728,29729,29730,29731,29732,29733,29734,
92049 29735,29736,29737,29738,29739,29740,29741,29742,29743,29744,29745,29746,
92050 29747,29748,29749,29750,29751,29752,29753,29754,29755,29756,29757,29758,
92051 29759,29760,29761,29762,29763,29764,29765,29766,29767,29768,29769,29770,
92052 29771,29772,29773,29774,29775,29776,29777,29778,29779,29780,29781,29782,
92053 29783,29784,29785,29786,29787,29788,29789,29790,29791,29792,29793,29794,
92054 29795,29796,29797,29798,29799,29800,29801,29802,29803,29804,29805,29806,
92055 29807,29808,29809,29810,29811,29812,29813,29814,29815,29816,29817,29818,
92056 29819,29820,29821,29822,29823,29824,29825,29826,29827,29828,29829,29830,
92057 29831,29832,29833,29834,29835,29836,29837,29838,29839,29840,29841,29842,
92058 29843,29844,29845,29846,29847,29848,29849,29850,29851,29852,29853,29854,
92059 29855,29856,29857,29858,29859,29860,29861,29862,29863,29864,29865,29866,
92060 29867,29868,29869,29870,29871,29872,29873,29874,29875,29876,29877,29878,
92061 29879,29880,29881,29882,29883,29884,29885,29886,29887,29888,29889,29890,
92062 29891,29892,29893,29894,29895,29896,29897,29898,29899,29900,29901,29902,
92063 29903,29904,29905,29906,29907,29908,29909,29910,29911,29912,29913,29914,
92064 29915,29916,29917,29918,29919,29920,29921,29922,29923,29924,29925,29926,
92065 29927,29928,29929,29930,29931,29932,29933,29934,29935,29936,29937,29938,
92066 29939,29940,29941,29942,29943,29944,29945,29946,29947,29948,29949,29950,
92067 29951,29952,29953,29954,29955,29956,29957,29958,29959,29960,29961,29962,
92068 29963,29964,29965,29966,29967,29968,29969,29970,29971,29972,29973,29974,
92069 29975,29976,29977,29978,29979,29980,29981,29982,29983,29984,29985,29986,
92070 29987,29988,29989,29990,29991,29992,29993,29994,29995,29996,29997,29998,
92071 29999,30000,30001,30002,30003,30004,30005,30006,30007,30008,30009,30010,
92072 30011,30012,30013,30014,30015,30016,30017,30018,30019,30020,30021,30022,
92073 30023,30024,30025,30026,30027,30028,30029,30030,30031,30032,30033,30034,
92074 30035,30036,30037,30038,30039,30040,30041,30042,30043,30044,30045,30046,
92075 30047,30048,30049,30050,30051,30052,30053,30054,30055,30056,30057,30058,
92076 30059,30060,30061,30062,30063,30064,30065,30066,30067,30068,30069,30070,
92077 30071,30072,30073,30074,30075,30076,30077,30078,30079,30080,30081,30082,
92078 30083,30084,30085,30086,30087,30088,30089,30090,30091,30092,30093,30094,
92079 30095,30096,30097,30098,30099,30100,30101,30102,30103,30104,30105,30106,
92080 30107,30108,30109,30110,30111,30112,30113,30114,30115,30116,30117,30118,
92081 30119,30120,30121,30122,30123,30124,30125,30126,30127,30128,30129,30130,
92082 30131,30132,30133,30134,30135,30136,30137,30138,30139,30140,30141,30142,
92083 30143,30144,30145,30146,30147,30148,30149,30150,30151,30152,30153,30154,
92084 30155,30156,30157,30158,30159,30160,30161,30162,30163,30164,30165,30166,
92085 30167,30168,30169,30170,30171,30172,30173,30174,30175,30176,30177,30178,
92086 30179,30180,30181,30182,30183,30184,30185,30186,30187,30188,30189,30190,
92087 30191,30192,30193,30194,30195,30196,30197,30198,30199,30200,30201,30202,
92088 30203,30204,30205,30206,30207,30208,30209,30210,30211,30212,30213,30214,
92089 30215,30216,30217,30218,30219,30220,30221,30222,30223,30224,30225,30226,
92090 30227,30228,30229,30230,30231,30232,30233,30234,30235,30236,30237,30238,
92091 30239,30240,30241,30242,30243,30244,30245,30246,30247,30248,30249,30250,
92092 30251,30252,30253,30254,30255,30256,30257,30258,30259,30260,30261,30262,
92093 30263,30264,30265,30266,30267,30268,30269,30270,30271,30272,30273,30274,
92094 30275,30276,30277,30278,30279,30280,30281,30282,30283,30284,30285,30286,
92095 30287,30288,30289,30290,30291,30292,30293,30294,30295,30296,30297,30298,
92096 30299,30300,30301,30302,30303,30304,30305,30306,30307,30308,30309,30310,
92097 30311,30312,30313,30314,30315,30316,30317,30318,30319,30320,30321,30322,
92098 30323,30324,30325,30326,30327,30328,30329,30330,30331,30332,30333,30334,
92099 30335,30336,30337,30338,30339,30340,30341,30342,30343,30344,30345,30346,
92100 30347,30348,30349,30350,30351,30352,30353,30354,30355,30356,30357,30358,
92101 30359,30360,30361,30362,30363,30364,30365,30366,30367,30368,30369,30370,
92102 30371,30372,30373,30374,30375,30376,30377,30378,30379,30380,30381,30382,
92103 30383,30384,30385,30386,30387,30388,30389,30390,30391,30392,30393,30394,
92104 30395,30396,30397,30398,30399,30400,30401,30402,30403,30404,30405,30406,
92105 30407,30408,30409,30410,30411,30412,30413,30414,30415,30416,30417,30418,
92106 30419,30420,30421,30422,30423,30424,30425,30426,30427,30428,30429,30430,
92107 30431,30432,30433,30434,30435,30436,30437,30438,30439,30440,30441,30442,
92108 30443,30444,30445,30446,30447,30448,30449,30450,30451,30452,30453,30454,
92109 30455,30456,30457,30458,30459,30460,30461,30462,30463,30464,30465,30466,
92110 30467,30468,30469,30470,30471,30472,30473,30474,30475,30476,30477,30478,
92111 30479,30480,30481,30482,30483,30484,30485,30486,30487,30488,30489,30490,
92112 30491,30492,30493,30494,30495,30496,30497,30498,30499,30500,30501,30502,
92113 30503,30504,30505,30506,30507,30508,30509,30510,30511,30512,30513,30514,
92114 30515,30516,30517,30518,30519,30520,30521,30522,30523,30524,30525,30526,
92115 30527,30528,30529,30530,30531,30532,30533,30534,30535,30536,30537,30538,
92116 30539,30540,30541,30542,30543,30544,30545,30546,30547,30548,30549,30550,
92117 30551,30552,30553,30554,30555,30556,30557,30558,30559,30560,30561,30562,
92118 30563,30564,30565,30566,30567,30568,30569,30570,30571,30572,30573,30574,
92119 30575,30576,30577,30578,30579,30580,30581,30582,30583,30584,30585,30586,
92120 30587,30588,30589,30590,30591,30592,30593,30594,30595,30596,30597,30598,
92121 30599,30600,30601,30602,30603,30604,30605,30606,30607,30608,30609,30610,
92122 30611,30612,30613,30614,30615,30616,30617,30618,30619,30620,30621,30622,
92123 30623,30624,30625,30626,30627,30628,30629,30630,30631,30632,30633,30634,
92124 30635,30636,30637,30638,30639,30640,30641,30642,30643,30644,30645,30646,
92125 30647,30648,30649,30650,30651,30652,30653,30654,30655,30656,30657,30658,
92126 30659,30660,30661,30662,30663,30664,30665,30666,30667,30668,30669,30670,
92127 30671,30672,30673,30674,30675,30676,30677,30678,30679,30680,30681,30682,
92128 30683,30684,30685,30686,30687,30688,30689,30690,30691,30692,30693,30694,
92129 30695,30696,30697,30698,30699,30700,30701,30702,30703,30704,30705,30706,
92130 30707,30708,30709,30710,30711,30712,30713,30714,30715,30716,30717,30718,
92131 30719,30720,30721,30722,30723,30724,30725,30726,30727,30728,30729,30730,
92132 30731,30732,30733,30734,30735,30736,30737,30738,30739,30740,30741,30742,
92133 30743,30744,30745,30746,30747,30748,30749,30750,30751,30752,30753,30754,
92134 30755,30756,30757,30758,30759,30760,30761,30762,30763,30764,30765,30766,
92135 30767,30768,30769,30770,30771,30772,30773,30774,30775,30776,30777,30778,
92136 30779,30780,30781,30782,30783,30784,30785,30786,30787,30788,30789,30790,
92137 30791,30792,30793,30794,30795,30796,30797,30798,30799,30800,30801,30802,
92138 30803,30804,30805,30806,30807,30808,30809,30810,30811,30812,30813,30814,
92139 30815,30816,30817,30818,30819,30820,30821,30822,30823,30824,30825,30826,
92140 30827,30828,30829,30830,30831,30832,30833,30834,30835,30836,30837,30838,
92141 30839,30840,30841,30842,30843,30844,30845,30846,30847,30848,30849,30850,
92142 30851,30852,30853,30854,30855,30856,30857,30858,30859,30860,30861,30862,
92143 30863,30864,30865,30866,30867,30868,30869,30870,30871,30872,30873,30874,
92144 30875,30876,30877,30878,30879,30880,30881,30882,30883,30884,30885,30886,
92145 30887,30888,30889,30890,30891,30892,30893,30894,30895,30896,30897,30898,
92146 30899,30900,30901,30902,30903,30904,30905,30906,30907,30908,30909,30910,
92147 30911,30912,30913,30914,30915,30916,30917,30918,30919,30920,30921,30922,
92148 30923,30924,30925,30926,30927,30928,30929,30930,30931,30932,30933,30934,
92149 30935,30936,30937,30938,30939,30940,30941,30942,30943,30944,30945,30946,
92150 30947,30948,30949,30950,30951,30952,30953,30954,30955,30956,30957,30958,
92151 30959,30960,30961,30962,30963,30964,30965,30966,30967,30968,30969,30970,
92152 30971,30972,30973,30974,30975,30976,30977,30978,30979,30980,30981,30982,
92153 30983,30984,30985,30986,30987,30988,30989,30990,30991,30992,30993,30994,
92154 30995,30996,30997,30998,30999,31000,31001,31002,31003,31004,31005,31006,
92155 31007,31008,31009,31010,31011,31012,31013,31014,31015,31016,31017,31018,
92156 31019,31020,31021,31022,31023,31024,31025,31026,31027,31028,31029,31030,
92157 31031,31032,31033,31034,31035,31036,31037,31038,31039,31040,31041,31042,
92158 31043,31044,31045,31046,31047,31048,31049,31050,31051,31052,31053,31054,
92159 31055,31056,31057,31058,31059,31060,31061,31062,31063,31064,31065,31066,
92160 31067,31068,31069,31070,31071,31072,31073,31074,31075,31076,31077,31078,
92161 31079,31080,31081,31082,31083,31084,31085,31086,31087,31088,31089,31090,
92162 31091,31092,31093,31094,31095,31096,31097,31098,31099,31100,31101,31102,
92163 31103,31104,31105,31106,31107,31108,31109,31110,31111,31112,31113,31114,
92164 31115,31116,31117,31118,31119,31120,31121,31122,31123,31124,31125,31126,
92165 31127,31128,31129,31130,31131,31132,31133,31134,31135,31136,31137,31138,
92166 31139,31140,31141,31142,31143,31144,31145,31146,31147,31148,31149,31150,
92167 31151,31152,31153,31154,31155,31156,31157,31158,31159,31160,31161,31162,
92168 31163,31164,31165,31166,31167,31168,31169,31170,31171,31172,31173,31174,
92169 31175,31176,31177,31178,31179,31180,31181,31182,31183,31184,31185,31186,
92170 31187,31188,31189,31190,31191,31192,31193,31194,31195,31196,31197,31198,
92171 31199,31200,31201,31202,31203,31204,31205,31206,31207,31208,31209,31210,
92172 31211,31212,31213,31214,31215,31216,31217,31218,31219,31220,31221,31222,
92173 31223,31224,31225,31226,31227,31228,31229,31230,31231,31232,31233,31234,
92174 31235,31236,31237,31238,31239,31240,31241,31242,31243,31244,31245,31246,
92175 31247,31248,31249,31250,31251,31252,31253,31254,31255,31256,31257,31258,
92176 31259,31260,31261,31262,31263,31264,31265,31266,31267,31268,31269,31270,
92177 31271,31272,31273,31274,31275,31276,31277,31278,31279,31280,31281,31282,
92178 31283,31284,31285,31286,31287,31288,31289,31290,31291,31292,31293,31294,
92179 31295,31296,31297,31298,31299,31300,31301,31302,31303,31304,31305,31306,
92180 31307,31308,31309,31310,31311,31312,31313,31314,31315,31316,31317,31318,
92181 31319,31320,31321,31322,31323,31324,31325,31326,31327,31328,31329,31330,
92182 31331,31332,31333,31334,31335,31336,31337,31338,31339,31340,31341,31342,
92183 31343,31344,31345,31346,31347,31348,31349,31350,31351,31352,31353,31354,
92184 31355,31356,31357,31358,31359,31360,31361,31362,31363,31364,31365,31366,
92185 31367,31368,31369,31370,31371,31372,31373,31374,31375,31376,31377,31378,
92186 31379,31380,31381,31382,31383,31384,31385,31386,31387,31388,31389,31390,
92187 31391,31392,31393,31394,31395,31396,31397,31398,31399,31400,31401,31402,
92188 31403,31404,31405,31406,31407,31408,31409,31410,31411,31412,31413,31414,
92189 31415,31416,31417,31418,31419,31420,31421,31422,31423,31424,31425,31426,
92190 31427,31428,31429,31430,31431,31432,31433,31434,31435,31436,31437,31438,
92191 31439,31440,31441,31442,31443,31444,31445,31446,31447,31448,31449,31450,
92192 31451,31452,31453,31454,31455,31456,31457,31458,31459,31460,31461,31462,
92193 31463,31464,31465,31466,31467,31468,31469,31470,31471,31472,31473,31474,
92194 31475,31476,31477,31478,31479,31480,31481,31482,31483,31484,31485,31486,
92195 31487,31488,31489,31490,31491,31492,31493,31494,31495,31496,31497,31498,
92196 31499,31500,31501,31502,31503,31504,31505,31506,31507,31508,31509,31510,
92197 31511,31512,31513,31514,31515,31516,31517,31518,31519,31520,31521,31522,
92198 31523,31524,31525,31526,31527,31528,31529,31530,31531,31532,31533,31534,
92199 31535,31536,31537,31538,31539,31540,31541,31542,31543,31544,31545,31546,
92200 31547,31548,31549,31550,31551,31552,31553,31554,31555,31556,31557,31558,
92201 31559,31560,31561,31562,31563,31564,31565,31566,31567,31568,31569,31570,
92202 31571,31572,31573,31574,31575,31576,31577,31578,31579,31580,31581,31582,
92203 31583,31584,31585,31586,31587,31588,31589,31590,31591,31592,31593,31594,
92204 31595,31596,31597,31598,31599,31600,31601,31602,31603,31604,31605,31606,
92205 31607,31608,31609,31610,31611,31612,31613,31614,31615,31616,31617,31618,
92206 31619,31620,31621,31622,31623,31624,31625,31626,31627,31628,31629,31630,
92207 31631,31632,31633,31634,31635,31636,31637,31638,31639,31640,31641,31642,
92208 31643,31644,31645,31646,31647,31648,31649,31650,31651,31652,31653,31654,
92209 31655,31656,31657,31658,31659,31660,31661,31662,31663,31664,31665,31666,
92210 31667,31668,31669,31670,31671,31672,31673,31674,31675,31676,31677,31678,
92211 31679,31680,31681,31682,31683,31684,31685,31686,31687,31688,31689,31690,
92212 31691,31692,31693,31694,31695,31696,31697,31698,31699,31700,31701,31702,
92213 31703,31704,31705,31706,31707,31708,31709,31710,31711,31712,31713,31714,
92214 31715,31716,31717,31718,31719,31720,31721,31722,31723,31724,31725,31726,
92215 31727,31728,31729,31730,31731,31732,31733,31734,31735,31736,31737,31738,
92216 31739,31740,31741,31742,31743,31744,31745,31746,31747,31748,31749,31750,
92217 31751,31752,31753,31754,31755,31756,31757,31758,31759,31760,31761,31762,
92218 31763,31764,31765,31766,31767,31768,31769,31770,31771,31772,31773,31774,
92219 31775,31776,31777,31778,31779,31780,31781,31782,31783,31784,31785,31786,
92220 31787,31788,31789,31790,31791,31792,31793,31794,31795,31796,31797,31798,
92221 31799,31800,31801,31802,31803,31804,31805,31806,31807,31808,31809,31810,
92222 31811,31812,31813,31814,31815,31816,31817,31818,31819,31820,31821,31822,
92223 31823,31824,31825,31826,31827,31828,31829,31830,31831,31832,31833,31834,
92224 31835,31836,31837,31838,31839,31840,31841,31842,31843,31844,31845,31846,
92225 31847,31848,31849,31850,31851,31852,31853,31854,31855,31856,31857,31858,
92226 31859,31860,31861,31862,31863,31864,31865,31866,31867,31868,31869,31870,
92227 31871,31872,31873,31874,31875,31876,31877,31878,31879,31880,31881,31882,
92228 31883,31884,31885,31886,31887,31888,31889,31890,31891,31892,31893,31894,
92229 31895,31896,31897,31898,31899,31900,31901,31902,31903,31904,31905,31906,
92230 31907,31908,31909,31910,31911,31912,31913,31914,31915,31916,31917,31918,
92231 31919,31920,31921,31922,31923,31924,31925,31926,31927,31928,31929,31930,
92232 31931,31932,31933,31934,31935,31936,31937,31938,31939,31940,31941,31942,
92233 31943,31944,31945,31946,31947,31948,31949,31950,31951,31952,31953,31954,
92234 31955,31956,31957,31958,31959,31960,31961,31962,31963,31964,31965,31966,
92235 31967,31968,31969,31970,31971,31972,31973,31974,31975,31976,31977,31978,
92236 31979,31980,31981,31982,31983,31984,31985,31986,31987,31988,31989,31990,
92237 31991,31992,31993,31994,31995,31996,31997,31998,31999,32000,32001,32002,
92238 32003,32004,32005,32006,32007,32008,32009,32010,32011,32012,32013,32014,
92239 32015,32016,32017,32018,32019,32020,32021,32022,32023,32024,32025,32026,
92240 32027,32028,32029,32030,32031,32032,32033,32034,32035,32036,32037,32038,
92241 32039,32040,32041,32042,32043,32044,32045,32046,32047,32048,32049,32050,
92242 32051,32052,32053,32054,32055,32056,32057,32058,32059,32060,32061,32062,
92243 32063,32064,32065,32066,32067,32068,32069,32070,32071,32072,32073,32074,
92244 32075,32076,32077,32078,32079,32080,32081,32082,32083,32084,32085,32086,
92245 32087,32088,32089,32090,32091,32092,32093,32094,32095,32096,32097,32098,
92246 32099,32100,32101,32102,32103,32104,32105,32106,32107,32108,32109,32110,
92247 32111,32112,32113,32114,32115,32116,32117,32118,32119,32120,32121,32122,
92248 32123,32124,32125,32126,32127,32128,32129,32130,32131,32132,32133,32134,
92249 32135,32136,32137,32138,32139,32140,32141,32142,32143,32144,32145,32146,
92250 32147,32148,32149,32150,32151,32152,32153,32154,32155,32156,32157,32158,
92251 32159,32160,32161,32162,32163,32164,32165,32166,32167,32168,32169,32170,
92252 32171,32172,32173,32174,32175,32176,32177,32178,32179,32180,32181,32182,
92253 32183,32184,32185,32186,32187,32188,32189,32190,32191,32192,32193,32194,
92254 32195,32196,32197,32198,32199,32200,32201,32202,32203,32204,32205,32206,
92255 32207,32208,32209,32210,32211,32212,32213,32214,32215,32216,32217,32218,
92256 32219,32220,32221,32222,32223,32224,32225,32226,32227,32228,32229,32230,
92257 32231,32232,32233,32234,32235,32236,32237,32238,32239,32240,32241,32242,
92258 32243,32244,32245,32246,32247,32248,32249,32250,32251,32252,32253,32254,
92259 32255,32256,32257,32258,32259,32260,32261,32262,32263,32264,32265,32266,
92260 32267,32268,32269,32270,32271,32272,32273,32274,32275,32276,32277,32278,
92261 32279,32280,32281,32282,32283,32284,32285,32286,32287,32288,32289,32290,
92262 32291,32292,32293,32294,32295,32296,32297,32298,32299,32300,32301,32302,
92263 32303,32304,32305,32306,32307,32308,32309,32310,32311,32312,32313,32314,
92264 32315,32316,32317,32318,32319,32320,32321,32322,32323,32324,32325,32326,
92265 32327,32328,32329,32330,32331,32332,32333,32334,32335,32336,32337,32338,
92266 32339,32340,32341,32342,32343,32344,32345,32346,32347,32348,32349,32350,
92267 32351,32352,32353,32354,32355,32356,32357,32358,32359,32360,32361,32362,
92268 32363,32364,32365,32366,32367,32368,32369,32370,32371,32372,32373,32374,
92269 32375,32376,32377,32378,32379,32380,32381,32382,32383,32384,32385,32386,
92270 32387,32388,32389,32390,32391,32392,32393,32394,32395,32396,32397,32398,
92271 32399,32400,32401,32402,32403,32404,32405,32406,32407,32408,32409,32410,
92272 32411,32412,32413,32414,32415,32416,32417,32418,32419,32420,32421,32422,
92273 32423,32424,32425,32426,32427,32428,32429,32430,32431,32432,32433,32434,
92274 32435,32436,32437,32438,32439,32440,32441,32442,32443,32444,32445,32446,
92275 32447,32448,32449,32450,32451,32452,32453,32454,32455,32456,32457,32458,
92276 32459,32460,32461,32462,32463,32464,32465,32466,32467,32468,32469,32470,
92277 32471,32472,32473,32474,32475,32476,32477,32478,32479,32480,32481,32482,
92278 32483,32484,32485,32486,32487,32488,32489,32490,32491,32492,32493,32494,
92279 32495,32496,32497,32498,32499,32500,32501,32502,32503,32504,32505,32506,
92280 32507,32508,32509,32510,32511,32512,32513,32514,32515,32516,32517,32518,
92281 32519,32520,32521,32522,32523,32524,32525,32526,32527,32528,32529,32530,
92282 32531,32532,32533,32534,32535,32536,32537,32538,32539,32540,32541,32542,
92283 32543,32544,32545,32546,32547,32548,32549,32550,32551,32552,32553,32554,
92284 32555,32556,32557,32558,32559,32560,32561,32562,32563,32564,32565,32566,
92285 32567,32568,32569,32570,32571,32572,32573,32574,32575,32576,32577,32578,
92286 32579,32580,32581,32582,32583,32584,32585,32586,32587,32588,32589,32590,
92287 32591,32592,32593,32594,32595,32596,32597,32598,32599,32600,32601,32602,
92288 32603,32604,32605,32606,32607,32608,32609,32610,32611,32612,32613,32614,
92289 32615,32616,32617,32618,32619,32620,32621,32622,32623,32624,32625,32626,
92290 32627,32628,32629,32630,32631,32632,32633,32634,32635,32636,32637,32638,
92291 32639,32640,32641,32642,32643,32644,32645,32646,32647,32648,32649,32650,
92292 32651,32652,32653,32654,32655,32656,32657,32658,32659,32660,32661,32662,
92293 32663,32664,32665,32666,32667,32668,32669,32670,32671,32672,32673,32674,
92294 32675,32676,32677,32678,32679,32680,32681,32682,32683,32684,32685,32686,
92295 32687,32688,32689,32690,32691,32692,32693,32694,32695,32696,32697,32698,
92296 32699,32700,32701,32702,32703,32704,32705,32706,32707,32708,32709,32710,
92297 32711,32712,32713,32714,32715,32716,32717,32718,32719,32720,32721,32722,
92298 32723,32724,32725,32726,32727,32728,32729,32730,32731,32732,32733,32734,
92299 32735,32736,32737,32738,32739,32740,32741,32742,32743,32744,32745,32746,
92300 32747,32748,32749,32750,32751,32752,32753,32754,32755,32756,32757,32758,
92301 32759,32760,32761,32762,32763,32764,32765,32766,32767,32768L,32769L,32770L,
92302 32771L,32772L,32773L,32774L,32775L,32776L,32777L,32778L,32779L,32780L,
92303 32781L,32782L,32783L,32784L,32785L,32786L,32787L,32788L,32789L,32790L,
92304 32791L,32792L,32793L,32794L,32795L,32796L,32797L,32798L,32799L,32800L,
92305 32801L,32802L,32803L,32804L,32805L,32806L,32807L,32808L,32809L,32810L,
92306 32811L,32812L,32813L,32814L,32815L,32816L,32817L,32818L,32819L,32820L,
92307 32821L,32822L,32823L,32824L,32825L,32826L,32827L,32828L,32829L,32830L,
92308 32831L,32832L,32833L,32834L,32835L,32836L,32837L,32838L,32839L,32840L,
92309 32841L,32842L,32843L,32844L,32845L,32846L,32847L,32848L,32849L,32850L,
92310 32851L,32852L,32853L,32854L,32855L,32856L,32857L,32858L,32859L,32860L,
92311 32861L,32862L,32863L,32864L,32865L,32866L,32867L,32868L,32869L,32870L,
92312 32871L,32872L,32873L,32874L,32875L,32876L,32877L,32878L,32879L,32880L,
92313 32881L,32882L,32883L,32884L,32885L,32886L,32887L,32888L,32889L,32890L,
92314 32891L,32892L,32893L,32894L,32895L,32896L,32897L,32898L,32899L,32900L,
92315 32901L,32902L,32903L,32904L,32905L,32906L,32907L,32908L,32909L,32910L,
92316 32911L,32912L,32913L,32914L,32915L,32916L,32917L,32918L,32919L,32920L,
92317 32921L,32922L,32923L,32924L,32925L,32926L,32927L,32928L,32929L,32930L,
92318 32931L,32932L,32933L,32934L,32935L,32936L,32937L,32938L,32939L,32940L,
92319 32941L,32942L,32943L,32944L,32945L,32946L,32947L,32948L,32949L,32950L,
92320 32951L,32952L,32953L,32954L,32955L,32956L,32957L,32958L,32959L,32960L,
92321 32961L,32962L,32963L,32964L,32965L,32966L,32967L,32968L,32969L,32970L,
92322 32971L,32972L,32973L,32974L,32975L,32976L,32977L,32978L,32979L,32980L,
92323 32981L,32982L,32983L,32984L,32985L,32986L,32987L,32988L,32989L,32990L,
92324 32991L,32992L,32993L,32994L,32995L,32996L,32997L,32998L,32999L,33000L,
92325 33001L,33002L,33003L,33004L,33005L,33006L,33007L,33008L,33009L,33010L,
92326 33011L,33012L,33013L,33014L,33015L,33016L,33017L,33018L,33019L,33020L,
92327 33021L,33022L,33023L,33024L,33025L,33026L,33027L,33028L,33029L,33030L,
92328 33031L,33032L,33033L,33034L,33035L,33036L,33037L,33038L,33039L,33040L,
92329 33041L,33042L,33043L,33044L,33045L,33046L,33047L,33048L,33049L,33050L,
92330 33051L,33052L,33053L,33054L,33055L,33056L,33057L,33058L,33059L,33060L,
92331 33061L,33062L,33063L,33064L,33065L,33066L,33067L,33068L,33069L,33070L,
92332 33071L,33072L,33073L,33074L,33075L,33076L,33077L,33078L,33079L,33080L,
92333 33081L,33082L,33083L,33084L,33085L,33086L,33087L,33088L,33089L,33090L,
92334 33091L,33092L,33093L,33094L,33095L,33096L,33097L,33098L,33099L,33100L,
92335 33101L,33102L,33103L,33104L,33105L,33106L,33107L,33108L,33109L,33110L,
92336 33111L,33112L,33113L,33114L,33115L,33116L,33117L,33118L,33119L,33120L,
92337 33121L,33122L,33123L,33124L,33125L,33126L,33127L,33128L,33129L,33130L,
92338 33131L,33132L,33133L,33134L,33135L,33136L,33137L,33138L,33139L,33140L,
92339 33141L,33142L,33143L,33144L,33145L,33146L,33147L,33148L,33149L,33150L,
92340 33151L,33152L,33153L,33154L,33155L,33156L,33157L,33158L,33159L,33160L,
92341 33161L,33162L,33163L,33164L,33165L,33166L,33167L,33168L,33169L,33170L,
92342 33171L,33172L,33173L,33174L,33175L,33176L,33177L,33178L,33179L,33180L,
92343 33181L,33182L,33183L,33184L,33185L,33186L,33187L,33188L,33189L,33190L,
92344 33191L,33192L,33193L,33194L,33195L,33196L,33197L,33198L,33199L,33200L,
92345 33201L,33202L,33203L,33204L,33205L,33206L,33207L,33208L,33209L,33210L,
92346 33211L,33212L,33213L,33214L,33215L,33216L,33217L,33218L,33219L,33220L,
92347 33221L,33222L,33223L,33224L,33225L,33226L,33227L,33228L,33229L,33230L,
92348 33231L,33232L,33233L,33234L,33235L,33236L,33237L,33238L,33239L,33240L,
92349 33241L,33242L,33243L,33244L,33245L,33246L,33247L,33248L,33249L,33250L,
92350 33251L,33252L,33253L,33254L,33255L,33256L,33257L,33258L,33259L,33260L,
92351 33261L,33262L,33263L,33264L,33265L,33266L,33267L,33268L,33269L,33270L,
92352 33271L,33272L,33273L,33274L,33275L,33276L,33277L,33278L,33279L,33280L,
92353 33281L,33282L,33283L,33284L,33285L,33286L,33287L,33288L,33289L,33290L,
92354 33291L,33292L,33293L,33294L,33295L,33296L,33297L,33298L,33299L,33300L,
92355 33301L,33302L,33303L,33304L,33305L,33306L,33307L,33308L,33309L,33310L,
92356 33311L,33312L,33313L,33314L,33315L,33316L,33317L,33318L,33319L,33320L,
92357 33321L,33322L,33323L,33324L,33325L,33326L,33327L,33328L,33329L,33330L,
92358 33331L,33332L,33333L,33334L,33335L,33336L,33337L,33338L,33339L,33340L,
92359 33341L,33342L,33343L,33344L,33345L,33346L,33347L,33348L,33349L,33350L,
92360 33351L,33352L,33353L,33354L,33355L,33356L,33357L,33358L,33359L,33360L,
92361 33361L,33362L,33363L,33364L,33365L,33366L,33367L,33368L,33369L,33370L,
92362 33371L,33372L,33373L,33374L,33375L,33376L,33377L,33378L,33379L,33380L,
92363 33381L,33382L,33383L,33384L,33385L,33386L,33387L,33388L,33389L,33390L,
92364 33391L,33392L,33393L,33394L,33395L,33396L,33397L,33398L,33399L,33400L,
92365 33401L,33402L,33403L,33404L,33405L,33406L,33407L,33408L,33409L,33410L,
92366 33411L,33412L,33413L,33414L,33415L,33416L,33417L,33418L,33419L,33420L,
92367 33421L,33422L,33423L,33424L,33425L,33426L,33427L,33428L,33429L,33430L,
92368 33431L,33432L,33433L,33434L,33435L,33436L,33437L,33438L,33439L,33440L,
92369 33441L,33442L,33443L,33444L,33445L,33446L,33447L,33448L,33449L,33450L,
92370 33451L,33452L,33453L,33454L,33455L,33456L,33457L,33458L,33459L,33460L,
92371 33461L,33462L,33463L,33464L,33465L,33466L,33467L,33468L,33469L,33470L,
92372 33471L,33472L,33473L,33474L,33475L,33476L,33477L,33478L,33479L,33480L,
92373 33481L,33482L,33483L,33484L,33485L,33486L,33487L,33488L,33489L,33490L,
92374 33491L,33492L,33493L,33494L,33495L,33496L,33497L,33498L,33499L,33500L,
92375 33501L,33502L,33503L,33504L,33505L,33506L,33507L,33508L,33509L,33510L,
92376 33511L,33512L,33513L,33514L,33515L,33516L,33517L,33518L,33519L,33520L,
92377 33521L,33522L,33523L,33524L,33525L,33526L,33527L,33528L,33529L,33530L,
92378 33531L,33532L,33533L,33534L,33535L,33536L,33537L,33538L,33539L,33540L,
92379 33541L,33542L,33543L,33544L,33545L,33546L,33547L,33548L,33549L,33550L,
92380 33551L,33552L,33553L,33554L,33555L,33556L,33557L,33558L,33559L,33560L,
92381 33561L,33562L,33563L,33564L,33565L,33566L,33567L,33568L,33569L,33570L,
92382 33571L,33572L,33573L,33574L,33575L,33576L,33577L,33578L,33579L,33580L,
92383 33581L,33582L,33583L,33584L,33585L,33586L,33587L,33588L,33589L,33590L,
92384 33591L,33592L,33593L,33594L,33595L,33596L,33597L,33598L,33599L,33600L,
92385 33601L,33602L,33603L,33604L,33605L,33606L,33607L,33608L,33609L,33610L,
92386 33611L,33612L,33613L,33614L,33615L,33616L,33617L,33618L,33619L,33620L,
92387 33621L,33622L,33623L,33624L,33625L,33626L,33627L,33628L,33629L,33630L,
92388 33631L,33632L,33633L,33634L,33635L,33636L,33637L,33638L,33639L,33640L,
92389 33641L,33642L,33643L,33644L,33645L,33646L,33647L,33648L,33649L,33650L,
92390 33651L,33652L,33653L,33654L,33655L,33656L,33657L,33658L,33659L,33660L,
92391 33661L,33662L,33663L,33664L,33665L,33666L,33667L,33668L,33669L,33670L,
92392 33671L,33672L,33673L,33674L,33675L,33676L,33677L,33678L,33679L,33680L,
92393 33681L,33682L,33683L,33684L,33685L,33686L,33687L,33688L,33689L,33690L,
92394 33691L,33692L,33693L,33694L,33695L,33696L,33697L,33698L,33699L,33700L,
92395 33701L,33702L,33703L,33704L,33705L,33706L,33707L,33708L,33709L,33710L,
92396 33711L,33712L,33713L,33714L,33715L,33716L,33717L,33718L,33719L,33720L,
92397 33721L,33722L,33723L,33724L,33725L,33726L,33727L,33728L,33729L,33730L,
92398 33731L,33732L,33733L,33734L,33735L,33736L,33737L,33738L,33739L,33740L,
92399 33741L,33742L,33743L,33744L,33745L,33746L,33747L,33748L,33749L,33750L,
92400 33751L,33752L,33753L,33754L,33755L,33756L,33757L,33758L,33759L,33760L,
92401 33761L,33762L,33763L,33764L,33765L,33766L,33767L,33768L,33769L,33770L,
92402 33771L,33772L,33773L,33774L,33775L,33776L,33777L,33778L,33779L,33780L,
92403 33781L,33782L,33783L,33784L,33785L,33786L,33787L,33788L,33789L,33790L,
92404 33791L,33792L,33793L,33794L,33795L,33796L,33797L,33798L,33799L,33800L,
92405 33801L,33802L,33803L,33804L,33805L,33806L,33807L,33808L,33809L,33810L,
92406 33811L,33812L,33813L,33814L,33815L,33816L,33817L,33818L,33819L,33820L,
92407 33821L,33822L,33823L,33824L,33825L,33826L,33827L,33828L,33829L,33830L,
92408 33831L,33832L,33833L,33834L,33835L,33836L,33837L,33838L,33839L,33840L,
92409 33841L,33842L,33843L,33844L,33845L,33846L,33847L,33848L,33849L,33850L,
92410 33851L,33852L,33853L,33854L,33855L,33856L,33857L,33858L,33859L,33860L,
92411 33861L,33862L,33863L,33864L,33865L,33866L,33867L,33868L,33869L,33870L,
92412 33871L,33872L,33873L,33874L,33875L,33876L,33877L,33878L,33879L,33880L,
92413 33881L,33882L,33883L,33884L,33885L,33886L,33887L,33888L,33889L,33890L,
92414 33891L,33892L,33893L,33894L,33895L,33896L,33897L,33898L,33899L,33900L,
92415 33901L,33902L,33903L,33904L,33905L,33906L,33907L,33908L,33909L,33910L,
92416 33911L,33912L,33913L,33914L,33915L,33916L,33917L,33918L,33919L,33920L,
92417 33921L,33922L,33923L,33924L,33925L,33926L,33927L,33928L,33929L,33930L,
92418 33931L,33932L,33933L,33934L,33935L,33936L,33937L,33938L,33939L,33940L,
92419 33941L,33942L,33943L,33944L,33945L,33946L,33947L,33948L,33949L,33950L,
92420 33951L,33952L,33953L,33954L,33955L,33956L,33957L,33958L,33959L,33960L,
92421 33961L,33962L,33963L,33964L,33965L,33966L,33967L,33968L,33969L,33970L,
92422 33971L,33972L,33973L,33974L,33975L,33976L,33977L,33978L,33979L,33980L,
92423 33981L,33982L,33983L,33984L,33985L,33986L,33987L,33988L,33989L,33990L,
92424 33991L,33992L,33993L,33994L,33995L,33996L,33997L,33998L,33999L,34000L,
92425 34001L,34002L,34003L,34004L,34005L,34006L,34007L,34008L,34009L,34010L,
92426 34011L,34012L,34013L,34014L,34015L,34016L,34017L,34018L,34019L,34020L,
92427 34021L,34022L,34023L,34024L,34025L,34026L,34027L,34028L,34029L,34030L,
92428 34031L,34032L,34033L,34034L,34035L,34036L,34037L,34038L,34039L,34040L,
92429 34041L,34042L,34043L,34044L,34045L,34046L,34047L,34048L,34049L,34050L,
92430 34051L,34052L,34053L,34054L,34055L,34056L,34057L,34058L,34059L,34060L,
92431 34061L,34062L,34063L,34064L,34065L,34066L,34067L,34068L,34069L,34070L,
92432 34071L,34072L,34073L,34074L,34075L,34076L,34077L,34078L,34079L,34080L,
92433 34081L,34082L,34083L,34084L,34085L,34086L,34087L,34088L,34089L,34090L,
92434 34091L,34092L,34093L,34094L,34095L,34096L,34097L,34098L,34099L,34100L,
92435 34101L,34102L,34103L,34104L,34105L,34106L,34107L,34108L,34109L,34110L,
92436 34111L,34112L,34113L,34114L,34115L,34116L,34117L,34118L,34119L,34120L,
92437 34121L,34122L,34123L,34124L,34125L,34126L,34127L,34128L,34129L,34130L,
92438 34131L,34132L,34133L,34134L,34135L,34136L,34137L,34138L,34139L,34140L,
92439 34141L,34142L,34143L,34144L,34145L,34146L,34147L,34148L,34149L,34150L,
92440 34151L,34152L,34153L,34154L,34155L,34156L,34157L,34158L,34159L,34160L,
92441 34161L,34162L,34163L,34164L,34165L,34166L,34167L,34168L,34169L,34170L,
92442 34171L,34172L,34173L,34174L,34175L,34176L,34177L,34178L,34179L,34180L,
92443 34181L,34182L,34183L,34184L,34185L,34186L,34187L,34188L,34189L,34190L,
92444 34191L,34192L,34193L,34194L,34195L,34196L,34197L,34198L,34199L,34200L,
92445 34201L,34202L,34203L,34204L,34205L,34206L,34207L,34208L,34209L,34210L,
92446 34211L,34212L,34213L,34214L,34215L,34216L,34217L,34218L,34219L,34220L,
92447 34221L,34222L,34223L,34224L,34225L,34226L,34227L,34228L,34229L,34230L,
92448 34231L,34232L,34233L,34234L,34235L,34236L,34237L,34238L,34239L,34240L,
92449 34241L,34242L,34243L,34244L,34245L,34246L,34247L,34248L,34249L,34250L,
92450 34251L,34252L,34253L,34254L,34255L,34256L,34257L,34258L,34259L,34260L,
92451 34261L,34262L,34263L,34264L,34265L,34266L,34267L,34268L,34269L,34270L,
92452 34271L,34272L,34273L,34274L,34275L,34276L,34277L,34278L,34279L,34280L,
92453 34281L,34282L,34283L,34284L,34285L,34286L,34287L,34288L,34289L,34290L,
92454 34291L,34292L,34293L,34294L,34295L,34296L,34297L,34298L,34299L,34300L,
92455 34301L,34302L,34303L,34304L,34305L,34306L,34307L,34308L,34309L,34310L,
92456 34311L,34312L,34313L,34314L,34315L,34316L,34317L,34318L,34319L,34320L,
92457 34321L,34322L,34323L,34324L,34325L,34326L,34327L,34328L,34329L,34330L,
92458 34331L,34332L,34333L,34334L,34335L,34336L,34337L,34338L,34339L,34340L,
92459 34341L,34342L,34343L,34344L,34345L,34346L,34347L,34348L,34349L,34350L,
92460 34351L,34352L,34353L,34354L,34355L,34356L,34357L,34358L,34359L,34360L,
92461 34361L,34362L,34363L,34364L,34365L,34366L,34367L,34368L,34369L,34370L,
92462 34371L,34372L,34373L,34374L,34375L,34376L,34377L,34378L,34379L,34380L,
92463 34381L,34382L,34383L,34384L,34385L,34386L,34387L,34388L,34389L,34390L,
92464 34391L,34392L,34393L,34394L,34395L,34396L,34397L,34398L,34399L,34400L,
92465 34401L,34402L,34403L,34404L,34405L,34406L,34407L,34408L,34409L,34410L,
92466 34411L,34412L,34413L,34414L,34415L,34416L,34417L,34418L,34419L,34420L,
92467 34421L,34422L,34423L,34424L,34425L,34426L,34427L,34428L,34429L,34430L,
92468 34431L,34432L,34433L,34434L,34435L,34436L,34437L,34438L,34439L,34440L,
92469 34441L,34442L,34443L,34444L,34445L,34446L,34447L,34448L,34449L,34450L,
92470 34451L,34452L,34453L,34454L,34455L,34456L,34457L,34458L,34459L,34460L,
92471 34461L,34462L,34463L,34464L,34465L,34466L,34467L,34468L,34469L,34470L,
92472 34471L,34472L,34473L,34474L,34475L,34476L,34477L,34478L,34479L,34480L,
92473 34481L,34482L,34483L,34484L,34485L,34486L,34487L,34488L,34489L,34490L,
92474 34491L,34492L,34493L,34494L,34495L,34496L,34497L,34498L,34499L,34500L,
92475 34501L,34502L,34503L,34504L,34505L,34506L,34507L,34508L,34509L,34510L,
92476 34511L,34512L,34513L,34514L,34515L,34516L,34517L,34518L,34519L,34520L,
92477 34521L,34522L,34523L,34524L,34525L,34526L,34527L,34528L,34529L,34530L,
92478 34531L,34532L,34533L,34534L,34535L,34536L,34537L,34538L,34539L,34540L,
92479 34541L,34542L,34543L,34544L,34545L,34546L,34547L,34548L,34549L,34550L,
92480 34551L,34552L,34553L,34554L,34555L,34556L,34557L,34558L,34559L,34560L,
92481 34561L,34562L,34563L,34564L,34565L,34566L,34567L,34568L,34569L,34570L,
92482 34571L,34572L,34573L,34574L,34575L,34576L,34577L,34578L,34579L,34580L,
92483 34581L,34582L,34583L,34584L,34585L,34586L,34587L,34588L,34589L,34590L,
92484 34591L,34592L,34593L,34594L,34595L,34596L,34597L,34598L,34599L,34600L,
92485 34601L,34602L,34603L,34604L,34605L,34606L,34607L,34608L,34609L,34610L,
92486 34611L,34612L,34613L,34614L,34615L,34616L,34617L,34618L,34619L,34620L,
92487 34621L,34622L,34623L,34624L,34625L,34626L,34627L,34628L,34629L,34630L,
92488 34631L,34632L,34633L,34634L,34635L,34636L,34637L,34638L,34639L,34640L,
92489 34641L,34642L,34643L,34644L,34645L,34646L,34647L,34648L,34649L,34650L,
92490 34651L,34652L,34653L,34654L,34655L,34656L,34657L,34658L,34659L,34660L,
92491 34661L,34662L,34663L,34664L,34665L,34666L,34667L,34668L,34669L,34670L,
92492 34671L,34672L,34673L,34674L,34675L,34676L,34677L,34678L,34679L,34680L,
92493 34681L,34682L,34683L,34684L,34685L,34686L,34687L,34688L,34689L,34690L,
92494 34691L,34692L,34693L,34694L,34695L,34696L,34697L,34698L,34699L,34700L,
92495 34701L,34702L,34703L,34704L,34705L,34706L,34707L,34708L,34709L,34710L,
92496 34711L,34712L,34713L,34714L,34715L,34716L,34717L,34718L,34719L,34720L,
92497 34721L,34722L,34723L,34724L,34725L,34726L,34727L,34728L,34729L,34730L,
92498 34731L,34732L,34733L,34734L,34735L,34736L,34737L,34738L,34739L,34740L,
92499 34741L,34742L,34743L,34744L,34745L,34746L,34747L,34748L,34749L,34750L,
92500 34751L,34752L,34753L,34754L,34755L,34756L,34757L,34758L,34759L,34760L,
92501 34761L,34762L,34763L,34764L,34765L,34766L,34767L,34768L,34769L,34770L,
92502 34771L,34772L,34773L,34774L,34775L,34776L,34777L,34778L,34779L,34780L,
92503 34781L,34782L,34783L,34784L,34785L,34786L,34787L,34788L,34789L,34790L,
92504 34791L,34792L,34793L,34794L,34795L,34796L,34797L,34798L,34799L,34800L,
92505 34801L,34802L,34803L,34804L,34805L,34806L,34807L,34808L,34809L,34810L,
92506 34811L,34812L,34813L,34814L,34815L,34816L,34817L,34818L,34819L,34820L,
92507 34821L,34822L,34823L,34824L,34825L,34826L,34827L,34828L,34829L,34830L,
92508 34831L,34832L,34833L,34834L,34835L,34836L,34837L,34838L,34839L,34840L,
92509 34841L,34842L,34843L,34844L,34845L,34846L,34847L,34848L,34849L,34850L,
92510 34851L,34852L,34853L,34854L,34855L,34856L,34857L,34858L,34859L,34860L,
92511 34861L,34862L,34863L,34864L,34865L,34866L,34867L,34868L,34869L,34870L,
92512 34871L,34872L,34873L,34874L,34875L,34876L,34877L,34878L,34879L,34880L,
92513 34881L,34882L,34883L,34884L,34885L,34886L,34887L,34888L,34889L,34890L,
92514 34891L,34892L,34893L,34894L,34895L,34896L,34897L,34898L,34899L,34900L,
92515 34901L,34902L,34903L,34904L,34905L,34906L,34907L,34908L,34909L,34910L,
92516 34911L,34912L,34913L,34914L,34915L,34916L,34917L,34918L,34919L,34920L,
92517 34921L,34922L,34923L,34924L,34925L,34926L,34927L,34928L,34929L,34930L,
92518 34931L,34932L,34933L,34934L,34935L,34936L,34937L,34938L,34939L,34940L,
92519 34941L,34942L,34943L,34944L,34945L,34946L,34947L,34948L,34949L,34950L,
92520 34951L,34952L,34953L,34954L,34955L,34956L,34957L,34958L,34959L,34960L,
92521 34961L,34962L,34963L,34964L,34965L,34966L,34967L,34968L,34969L,34970L,
92522 34971L,34972L,34973L,34974L,34975L,34976L,34977L,34978L,34979L,34980L,
92523 34981L,34982L,34983L,34984L,34985L,34986L,34987L,34988L,34989L,34990L,
92524 34991L,34992L,34993L,34994L,34995L,34996L,34997L,34998L,34999L,35000L,
92525 35001L,35002L,35003L,35004L,35005L,35006L,35007L,35008L,35009L,35010L,
92526 35011L,35012L,35013L,35014L,35015L,35016L,35017L,35018L,35019L,35020L,
92527 35021L,35022L,35023L,35024L,35025L,35026L,35027L,35028L,35029L,35030L,
92528 35031L,35032L,35033L,35034L,35035L,35036L,35037L,35038L,35039L,35040L,
92529 35041L,35042L,35043L,35044L,35045L,35046L,35047L,35048L,35049L,35050L,
92530 35051L,35052L,35053L,35054L,35055L,35056L,35057L,35058L,35059L,35060L,
92531 35061L,35062L,35063L,35064L,35065L,35066L,35067L,35068L,35069L,35070L,
92532 35071L,35072L,35073L,35074L,35075L,35076L,35077L,35078L,35079L,35080L,
92533 35081L,35082L,35083L,35084L,35085L,35086L,35087L,35088L,35089L,35090L,
92534 35091L,35092L,35093L,35094L,35095L,35096L,35097L,35098L,35099L,35100L,
92535 35101L,35102L,35103L,35104L,35105L,35106L,35107L,35108L,35109L,35110L,
92536 35111L,35112L,35113L,35114L,35115L,35116L,35117L,35118L,35119L,35120L,
92537 35121L,35122L,35123L,35124L,35125L,35126L,35127L,35128L,35129L,35130L,
92538 35131L,35132L,35133L,35134L,35135L,35136L,35137L,35138L,35139L,35140L,
92539 35141L,35142L,35143L,35144L,35145L,35146L,35147L,35148L,35149L,35150L,
92540 35151L,35152L,35153L,35154L,35155L,35156L,35157L,35158L,35159L,35160L,
92541 35161L,35162L,35163L,35164L,35165L,35166L,35167L,35168L,35169L,35170L,
92542 35171L,35172L,35173L,35174L,35175L,35176L,35177L,35178L,35179L,35180L,
92543 35181L,35182L,35183L,35184L,35185L,35186L,35187L,35188L,35189L,35190L,
92544 35191L,35192L,35193L,35194L,35195L,35196L,35197L,35198L,35199L,35200L,
92545 35201L,35202L,35203L,35204L,35205L,35206L,35207L,35208L,35209L,35210L,
92546 35211L,35212L,35213L,35214L,35215L,35216L,35217L,35218L,35219L,35220L,
92547 35221L,35222L,35223L,35224L,35225L,35226L,35227L,35228L,35229L,35230L,
92548 35231L,35232L,35233L,35234L,35235L,35236L,35237L,35238L,35239L,35240L,
92549 35241L,35242L,35243L,35244L,35245L,35246L,35247L,35248L,35249L,35250L,
92550 35251L,35252L,35253L,35254L,35255L,35256L,35257L,35258L,35259L,35260L,
92551 35261L,35262L,35263L,35264L,35265L,35266L,35267L,35268L,35269L,35270L,
92552 35271L,35272L,35273L,35274L,35275L,35276L,35277L,35278L,35279L,35280L,
92553 35281L,35282L,35283L,35284L,35285L,35286L,35287L,35288L,35289L,35290L,
92554 35291L,35292L,35293L,35294L,35295L,35296L,35297L,35298L,35299L,35300L,
92555 35301L,35302L,35303L,35304L,35305L,35306L,35307L,35308L,35309L,35310L,
92556 35311L,35312L,35313L,35314L,35315L,35316L,35317L,35318L,35319L,35320L,
92557 35321L,35322L,35323L,35324L,35325L,35326L,35327L,35328L,35329L,35330L,
92558 35331L,35332L,35333L,35334L,35335L,35336L,35337L,35338L,35339L,35340L,
92559 35341L,35342L,35343L,35344L,35345L,35346L,35347L,35348L,35349L,35350L,
92560 35351L,35352L,35353L,35354L,35355L,35356L,35357L,35358L,35359L,35360L,
92561 35361L,35362L,35363L,35364L,35365L,35366L,35367L,35368L,35369L,35370L,
92562 35371L,35372L,35373L,35374L,35375L,35376L,35377L,35378L,35379L,35380L,
92563 35381L,35382L,35383L,35384L,35385L,35386L,35387L,35388L,35389L,35390L,
92564 35391L,35392L,35393L,35394L,35395L,35396L,35397L,35398L,35399L,35400L,
92565 35401L,35402L,35403L,35404L,35405L,35406L,35407L,35408L,35409L,35410L,
92566 35411L,35412L,35413L,35414L,35415L,35416L,35417L,35418L,35419L,35420L,
92567 35421L,35422L,35423L,35424L,35425L,35426L,35427L,35428L,35429L,35430L,
92568 35431L,35432L,35433L,35434L,35435L,35436L,35437L,35438L,35439L,35440L,
92569 35441L,35442L,35443L,35444L,35445L,35446L,35447L,35448L,35449L,35450L,
92570 35451L,35452L,35453L,35454L,35455L,35456L,35457L,35458L,35459L,35460L,
92571 35461L,35462L,35463L,35464L,35465L,35466L,35467L,35468L,35469L,35470L,
92572 35471L,35472L,35473L,35474L,35475L,35476L,35477L,35478L,35479L,35480L,
92573 35481L,35482L,35483L,35484L,35485L,35486L,35487L,35488L,35489L,35490L,
92574 35491L,35492L,35493L,35494L,35495L,35496L,35497L,35498L,35499L,35500L,
92575 35501L,35502L,35503L,35504L,35505L,35506L,35507L,35508L,35509L,35510L,
92576 35511L,35512L,35513L,35514L,35515L,35516L,35517L,35518L,35519L,35520L,
92577 35521L,35522L,35523L,35524L,35525L,35526L,35527L,35528L,35529L,35530L,
92578 35531L,35532L,35533L,35534L,35535L,35536L,35537L,35538L,35539L,35540L,
92579 35541L,35542L,35543L,35544L,35545L,35546L,35547L,35548L,35549L,35550L,
92580 35551L,35552L,35553L,35554L,35555L,35556L,35557L,35558L,35559L,35560L,
92581 35561L,35562L,35563L,35564L,35565L,35566L,35567L,35568L,35569L,35570L,
92582 35571L,35572L,35573L,35574L,35575L,35576L,35577L,35578L,35579L,35580L,
92583 35581L,35582L,35583L,35584L,35585L,35586L,35587L,35588L,35589L,35590L,
92584 35591L,35592L,35593L,35594L,35595L,35596L,35597L,35598L,35599L,35600L,
92585 35601L,35602L,35603L,35604L,35605L,35606L,35607L,35608L,35609L,35610L,
92586 35611L,35612L,35613L,35614L,35615L,35616L,35617L,35618L,35619L,35620L,
92587 35621L,35622L,35623L,35624L,35625L,35626L,35627L,35628L,35629L,35630L,
92588 35631L,35632L,35633L,35634L,35635L,35636L,35637L,35638L,35639L,35640L,
92589 35641L,35642L,35643L,35644L,35645L,35646L,35647L,35648L,35649L,35650L,
92590 35651L,35652L,35653L,35654L,35655L,35656L,35657L,35658L,35659L,35660L,
92591 35661L,35662L,35663L,35664L,35665L,35666L,35667L,35668L,35669L,35670L,
92592 35671L,35672L,35673L,35674L,35675L,35676L,35677L,35678L,35679L,35680L,
92593 35681L,35682L,35683L,35684L,35685L,35686L,35687L,35688L,35689L,35690L,
92594 35691L,35692L,35693L,35694L,35695L,35696L,35697L,35698L,35699L,35700L,
92595 35701L,35702L,35703L,35704L,35705L,35706L,35707L,35708L,35709L,35710L,
92596 35711L,35712L,35713L,35714L,35715L,35716L,35717L,35718L,35719L,35720L,
92597 35721L,35722L,35723L,35724L,35725L,35726L,35727L,35728L,35729L,35730L,
92598 35731L,35732L,35733L,35734L,35735L,35736L,35737L,35738L,35739L,35740L,
92599 35741L,35742L,35743L,35744L,35745L,35746L,35747L,35748L,35749L,35750L,
92600 35751L,35752L,35753L,35754L,35755L,35756L,35757L,35758L,35759L,35760L,
92601 35761L,35762L,35763L,35764L,35765L,35766L,35767L,35768L,35769L,35770L,
92602 35771L,35772L,35773L,35774L,35775L,35776L,35777L,35778L,35779L,35780L,
92603 35781L,35782L,35783L,35784L,35785L,35786L,35787L,35788L,35789L,35790L,
92604 35791L,35792L,35793L,35794L,35795L,35796L,35797L,35798L,35799L,35800L,
92605 35801L,35802L,35803L,35804L,35805L,35806L,35807L,35808L,35809L,35810L,
92606 35811L,35812L,35813L,35814L,35815L,35816L,35817L,35818L,35819L,35820L,
92607 35821L,35822L,35823L,35824L,35825L,35826L,35827L,35828L,35829L,35830L,
92608 35831L,35832L,35833L,35834L,35835L,35836L,35837L,35838L,35839L,35840L,
92609 35841L,35842L,35843L,35844L,35845L,35846L,35847L,35848L,35849L,35850L,
92610 35851L,35852L,35853L,35854L,35855L,35856L,35857L,35858L,35859L,35860L,
92611 35861L,35862L,35863L,35864L,35865L,35866L,35867L,35868L,35869L,35870L,
92612 35871L,35872L,35873L,35874L,35875L,35876L,35877L,35878L,35879L,35880L,
92613 35881L,35882L,35883L,35884L,35885L,35886L,35887L,35888L,35889L,35890L,
92614 35891L,35892L,35893L,35894L,35895L,35896L,35897L,35898L,35899L,35900L,
92615 35901L,35902L,35903L,35904L,35905L,35906L,35907L,35908L,35909L,35910L,
92616 35911L,35912L,35913L,35914L,35915L,35916L,35917L,35918L,35919L,35920L,
92617 35921L,35922L,35923L,35924L,35925L,35926L,35927L,35928L,35929L,35930L,
92618 35931L,35932L,35933L,35934L,35935L,35936L,35937L,35938L,35939L,35940L,
92619 35941L,35942L,35943L,35944L,35945L,35946L,35947L,35948L,35949L,35950L,
92620 35951L,35952L,35953L,35954L,35955L,35956L,35957L,35958L,35959L,35960L,
92621 35961L,35962L,35963L,35964L,35965L,35966L,35967L,35968L,35969L,35970L,
92622 35971L,35972L,35973L,35974L,35975L,35976L,35977L,35978L,35979L,35980L,
92623 35981L,35982L,35983L,35984L,35985L,35986L,35987L,35988L,35989L,35990L,
92624 35991L,35992L,35993L,35994L,35995L,35996L,35997L,35998L,35999L,36000L,
92625 36001L,36002L,36003L,36004L,36005L,36006L,36007L,36008L,36009L,36010L,
92626 36011L,36012L,36013L,36014L,36015L,36016L,36017L,36018L,36019L,36020L,
92627 36021L,36022L,36023L,36024L,36025L,36026L,36027L,36028L,36029L,36030L,
92628 36031L,36032L,36033L,36034L,36035L,36036L,36037L,36038L,36039L,36040L,
92629 36041L,36042L,36043L,36044L,36045L,36046L,36047L,36048L,36049L,36050L,
92630 36051L,36052L,36053L,36054L,36055L,36056L,36057L,36058L,36059L,36060L,
92631 36061L,36062L,36063L,36064L,36065L,36066L,36067L,36068L,36069L,36070L,
92632 36071L,36072L,36073L,36074L,36075L,36076L,36077L,36078L,36079L,36080L,
92633 36081L,36082L,36083L,36084L,36085L,36086L,36087L,36088L,36089L,36090L,
92634 36091L,36092L,36093L,36094L,36095L,36096L,36097L,36098L,36099L,36100L,
92635 36101L,36102L,36103L,36104L,36105L,36106L,36107L,36108L,36109L,36110L,
92636 36111L,36112L,36113L,36114L,36115L,36116L,36117L,36118L,36119L,36120L,
92637 36121L,36122L,36123L,36124L,36125L,36126L,36127L,36128L,36129L,36130L,
92638 36131L,36132L,36133L,36134L,36135L,36136L,36137L,36138L,36139L,36140L,
92639 36141L,36142L,36143L,36144L,36145L,36146L,36147L,36148L,36149L,36150L,
92640 36151L,36152L,36153L,36154L,36155L,36156L,36157L,36158L,36159L,36160L,
92641 36161L,36162L,36163L,36164L,36165L,36166L,36167L,36168L,36169L,36170L,
92642 36171L,36172L,36173L,36174L,36175L,36176L,36177L,36178L,36179L,36180L,
92643 36181L,36182L,36183L,36184L,36185L,36186L,36187L,36188L,36189L,36190L,
92644 36191L,36192L,36193L,36194L,36195L,36196L,36197L,36198L,36199L,36200L,
92645 36201L,36202L,36203L,36204L,36205L,36206L,36207L,36208L,36209L,36210L,
92646 36211L,36212L,36213L,36214L,36215L,36216L,36217L,36218L,36219L,36220L,
92647 36221L,36222L,36223L,36224L,36225L,36226L,36227L,36228L,36229L,36230L,
92648 36231L,36232L,36233L,36234L,36235L,36236L,36237L,36238L,36239L,36240L,
92649 36241L,36242L,36243L,36244L,36245L,36246L,36247L,36248L,36249L,36250L,
92650 36251L,36252L,36253L,36254L,36255L,36256L,36257L,36258L,36259L,36260L,
92651 36261L,36262L,36263L,36264L,36265L,36266L,36267L,36268L,36269L,36270L,
92652 36271L,36272L,36273L,36274L,36275L,36276L,36277L,36278L,36279L,36280L,
92653 36281L,36282L,36283L,36284L,36285L,36286L,36287L,36288L,36289L,36290L,
92654 36291L,36292L,36293L,36294L,36295L,36296L,36297L,36298L,36299L,36300L,
92655 36301L,36302L,36303L,36304L,36305L,36306L,36307L,36308L,36309L,36310L,
92656 36311L,36312L,36313L,36314L,36315L,36316L,36317L,36318L,36319L,36320L,
92657 36321L,36322L,36323L,36324L,36325L,36326L,36327L,36328L,36329L,36330L,
92658 36331L,36332L,36333L,36334L,36335L,36336L,36337L,36338L,36339L,36340L,
92659 36341L,36342L,36343L,36344L,36345L,36346L,36347L,36348L,36349L,36350L,
92660 36351L,36352L,36353L,36354L,36355L,36356L,36357L,36358L,36359L,36360L,
92661 36361L,36362L,36363L,36364L,36365L,36366L,36367L,36368L,36369L,36370L,
92662 36371L,36372L,36373L,36374L,36375L,36376L,36377L,36378L,36379L,36380L,
92663 36381L,36382L,36383L,36384L,36385L,36386L,36387L,36388L,36389L,36390L,
92664 36391L,36392L,36393L,36394L,36395L,36396L,36397L,36398L,36399L,36400L,
92665 36401L,36402L,36403L,36404L,36405L,36406L,36407L,36408L,36409L,36410L,
92666 36411L,36412L,36413L,36414L,36415L,36416L,36417L,36418L,36419L,36420L,
92667 36421L,36422L,36423L,36424L,36425L,36426L,36427L,36428L,36429L,36430L,
92668 36431L,36432L,36433L,36434L,36435L,36436L,36437L,36438L,36439L,36440L,
92669 36441L,36442L,36443L,36444L,36445L,36446L,36447L,36448L,36449L,36450L,
92670 36451L,36452L,36453L,36454L,36455L,36456L,36457L,36458L,36459L,36460L,
92671 36461L,36462L,36463L,36464L,36465L,36466L,36467L,36468L,36469L,36470L,
92672 36471L,36472L,36473L,36474L,36475L,36476L,36477L,36478L,36479L,36480L,
92673 36481L,36482L,36483L,36484L,36485L,36486L,36487L,36488L,36489L,36490L,
92674 36491L,36492L,36493L,36494L,36495L,36496L,36497L,36498L,36499L,36500L,
92675 36501L,36502L,36503L,36504L,36505L,36506L,36507L,36508L,36509L,36510L,
92676 36511L,36512L,36513L,36514L,36515L,36516L,36517L,36518L,36519L,36520L,
92677 36521L,36522L,36523L,36524L,36525L,36526L,36527L,36528L,36529L,36530L,
92678 36531L,36532L,36533L,36534L,36535L,36536L,36537L,36538L,36539L,36540L,
92679 36541L,36542L,36543L,36544L,36545L,36546L,36547L,36548L,36549L,36550L,
92680 36551L,36552L,36553L,36554L,36555L,36556L,36557L,36558L,36559L,36560L,
92681 36561L,36562L,36563L,36564L,36565L,36566L,36567L,36568L,36569L,36570L,
92682 36571L,36572L,36573L,36574L,36575L,36576L,36577L,36578L,36579L,36580L,
92683 36581L,36582L,36583L,36584L,36585L,36586L,36587L,36588L,36589L,36590L,
92684 36591L,36592L,36593L,36594L,36595L,36596L,36597L,36598L,36599L,36600L,
92685 36601L,36602L,36603L,36604L,36605L,36606L,36607L,36608L,36609L,36610L,
92686 36611L,36612L,36613L,36614L,36615L,36616L,36617L,36618L,36619L,36620L,
92687 36621L,36622L,36623L,36624L,36625L,36626L,36627L,36628L,36629L,36630L,
92688 36631L,36632L,36633L,36634L,36635L,36636L,36637L,36638L,36639L,36640L,
92689 36641L,36642L,36643L,36644L,36645L,36646L,36647L,36648L,36649L,36650L,
92690 36651L,36652L,36653L,36654L,36655L,36656L,36657L,36658L,36659L,36660L,
92691 36661L,36662L,36663L,36664L,36665L,36666L,36667L,36668L,36669L,36670L,
92692 36671L,36672L,36673L,36674L,36675L,36676L,36677L,36678L,36679L,36680L,
92693 36681L,36682L,36683L,36684L,36685L,36686L,36687L,36688L,36689L,36690L,
92694 36691L,36692L,36693L,36694L,36695L,36696L,36697L,36698L,36699L,36700L,
92695 36701L,36702L,36703L,36704L,36705L,36706L,36707L,36708L,36709L,36710L,
92696 36711L,36712L,36713L,36714L,36715L,36716L,36717L,36718L,36719L,36720L,
92697 36721L,36722L,36723L,36724L,36725L,36726L,36727L,36728L,36729L,36730L,
92698 36731L,36732L,36733L,36734L,36735L,36736L,36737L,36738L,36739L,36740L,
92699 36741L,36742L,36743L,36744L,36745L,36746L,36747L,36748L,36749L,36750L,
92700 36751L,36752L,36753L,36754L,36755L,36756L,36757L,36758L,36759L,36760L,
92701 36761L,36762L,36763L,36764L,36765L,36766L,36767L,36768L,36769L,36770L,
92702 36771L,36772L,36773L,36774L,36775L,36776L,36777L,36778L,36779L,36780L,
92703 36781L,36782L,36783L,36784L,36785L,36786L,36787L,36788L,36789L,36790L,
92704 36791L,36792L,36793L,36794L,36795L,36796L,36797L,36798L,36799L,36800L,
92705 36801L,36802L,36803L,36804L,36805L,36806L,36807L,36808L,36809L,36810L,
92706 36811L,36812L,36813L,36814L,36815L,36816L,36817L,36818L,36819L,36820L,
92707 36821L,36822L,36823L,36824L,36825L,36826L,36827L,36828L,36829L,36830L,
92708 36831L,36832L,36833L,36834L,36835L,36836L,36837L,36838L,36839L,36840L,
92709 36841L,36842L,36843L,36844L,36845L,36846L,36847L,36848L,36849L,36850L,
92710 36851L,36852L,36853L,36854L,36855L,36856L,36857L,36858L,36859L,36860L,
92711 36861L,36862L,36863L,36864L,36865L,36866L,36867L,36868L,36869L,36870L,
92712 36871L,36872L,36873L,36874L,36875L,36876L,36877L,36878L,36879L,36880L,
92713 36881L,36882L,36883L,36884L,36885L,36886L,36887L,36888L,36889L,36890L,
92714 36891L,36892L,36893L,36894L,36895L,36896L,36897L,36898L,36899L,36900L,
92715 36901L,36902L,36903L,36904L,36905L,36906L,36907L,36908L,36909L,36910L,
92716 36911L,36912L,36913L,36914L,36915L,36916L,36917L,36918L,36919L,36920L,
92717 36921L,36922L,36923L,36924L,36925L,36926L,36927L,36928L,36929L,36930L,
92718 36931L,36932L,36933L,36934L,36935L,36936L,36937L,36938L,36939L,36940L,
92719 36941L,36942L,36943L,36944L,36945L,36946L,36947L,36948L,36949L,36950L,
92720 36951L,36952L,36953L,36954L,36955L,36956L,36957L,36958L,36959L,36960L,
92721 36961L,36962L,36963L,36964L,36965L,36966L,36967L,36968L,36969L,36970L,
92722 36971L,36972L,36973L,36974L,36975L,36976L,36977L,36978L,36979L,36980L,
92723 36981L,36982L,36983L,36984L,36985L,36986L,36987L,36988L,36989L,36990L,
92724 36991L,36992L,36993L,36994L,36995L,36996L,36997L,36998L,36999L,37000L,
92725 37001L,37002L,37003L,37004L,37005L,37006L,37007L,37008L,37009L,37010L,
92726 37011L,37012L,37013L,37014L,37015L,37016L,37017L,37018L,37019L,37020L,
92727 37021L,37022L,37023L,37024L,37025L,37026L,37027L,37028L,37029L,37030L,
92728 37031L,37032L,37033L,37034L,37035L,37036L,37037L,37038L,37039L,37040L,
92729 37041L,37042L,37043L,37044L,37045L,37046L,37047L,37048L,37049L,37050L,
92730 37051L,37052L,37053L,37054L,37055L,37056L,37057L,37058L,37059L,37060L,
92731 37061L,37062L,37063L,37064L,37065L,37066L,37067L,37068L,37069L,37070L,
92732 37071L,37072L,37073L,37074L,37075L,37076L,37077L,37078L,37079L,37080L,
92733 37081L,37082L,37083L,37084L,37085L,37086L,37087L,37088L,37089L,37090L,
92734 37091L,37092L,37093L,37094L,37095L,37096L,37097L,37098L,37099L,37100L,
92735 37101L,37102L,37103L,37104L,37105L,37106L,37107L,37108L,37109L,37110L,
92736 37111L,37112L,37113L,37114L,37115L,37116L,37117L,37118L,37119L,37120L,
92737 37121L,37122L,37123L,37124L,37125L,37126L,37127L,37128L,37129L,37130L,
92738 37131L,37132L,37133L,37134L,37135L,37136L,37137L,37138L,37139L,37140L,
92739 37141L,37142L,37143L,37144L,37145L,37146L,37147L,37148L,37149L,37150L,
92740 37151L,37152L,37153L,37154L,37155L,37156L,37157L,37158L,37159L,37160L,
92741 37161L,37162L,37163L,37164L,37165L,37166L,37167L,37168L,37169L,37170L,
92742 37171L,37172L,37173L,37174L,37175L,37176L,37177L,37178L,37179L,37180L,
92743 37181L,37182L,37183L,37184L,37185L,37186L,37187L,37188L,37189L,37190L,
92744 37191L,37192L,37193L,37194L,37195L,37196L,37197L,37198L,37199L,37200L,
92745 37201L,37202L,37203L,37204L,37205L,37206L,37207L,37208L,37209L,37210L,
92746 37211L,37212L,37213L,37214L,37215L,37216L,37217L,37218L,37219L,37220L,
92747 37221L,37222L,37223L,37224L,37225L,37226L,37227L,37228L,37229L,37230L,
92748 37231L,37232L,37233L,37234L,37235L,37236L,37237L,37238L,37239L,37240L,
92749 37241L,37242L,37243L,37244L,37245L,37246L,37247L,37248L,37249L,37250L,
92750 37251L,37252L,37253L,37254L,37255L,37256L,37257L,37258L,37259L,37260L,
92751 37261L,37262L,37263L,37264L,37265L,37266L,37267L,37268L,37269L,37270L,
92752 37271L,37272L,37273L,37274L,37275L,37276L,37277L,37278L,37279L,37280L,
92753 37281L,37282L,37283L,37284L,37285L,37286L,37287L,37288L,37289L,37290L,
92754 37291L,37292L,37293L,37294L,37295L,37296L,37297L,37298L,37299L,37300L,
92755 37301L,37302L,37303L,37304L,37305L,37306L,37307L,37308L,37309L,37310L,
92756 37311L,37312L,37313L,37314L,37315L,37316L,37317L,37318L,37319L,37320L,
92757 37321L,37322L,37323L,37324L,37325L,37326L,37327L,37328L,37329L,37330L,
92758 37331L,37332L,37333L,37334L,37335L,37336L,37337L,37338L,37339L,37340L,
92759 37341L,37342L,37343L,37344L,37345L,37346L,37347L,37348L,37349L,37350L,
92760 37351L,37352L,37353L,37354L,37355L,37356L,37357L,37358L,37359L,37360L,
92761 37361L,37362L,37363L,37364L,37365L,37366L,37367L,37368L,37369L,37370L,
92762 37371L,37372L,37373L,37374L,37375L,37376L,37377L,37378L,37379L,37380L,
92763 37381L,37382L,37383L,37384L,37385L,37386L,37387L,37388L,37389L,37390L,
92764 37391L,37392L,37393L,37394L,37395L,37396L,37397L,37398L,37399L,37400L,
92765 37401L,37402L,37403L,37404L,37405L,37406L,37407L,37408L,37409L,37410L,
92766 37411L,37412L,37413L,37414L,37415L,37416L,37417L,37418L,37419L,37420L,
92767 37421L,37422L,37423L,37424L,37425L,37426L,37427L,37428L,37429L,37430L,
92768 37431L,37432L,37433L,37434L,37435L,37436L,37437L,37438L,37439L,37440L,
92769 37441L,37442L,37443L,37444L,37445L,37446L,37447L,37448L,37449L,37450L,
92770 37451L,37452L,37453L,37454L,37455L,37456L,37457L,37458L,37459L,37460L,
92771 37461L,37462L,37463L,37464L,37465L,37466L,37467L,37468L,37469L,37470L,
92772 37471L,37472L,37473L,37474L,37475L,37476L,37477L,37478L,37479L,37480L,
92773 37481L,37482L,37483L,37484L,37485L,37486L,37487L,37488L,37489L,37490L,
92774 37491L,37492L,37493L,37494L,37495L,37496L,37497L,37498L,37499L,37500L,
92775 37501L,37502L,37503L,37504L,37505L,37506L,37507L,37508L,37509L,37510L,
92776 37511L,37512L,37513L,37514L,37515L,37516L,37517L,37518L,37519L,37520L,
92777 37521L,37522L,37523L,37524L,37525L,37526L,37527L,37528L,37529L,37530L,
92778 37531L,37532L,37533L,37534L,37535L,37536L,37537L,37538L,37539L,37540L,
92779 37541L,37542L,37543L,37544L,37545L,37546L,37547L,37548L,37549L,37550L,
92780 37551L,37552L,37553L,37554L,37555L,37556L,37557L,37558L,37559L,37560L,
92781 37561L,37562L,37563L,37564L,37565L,37566L,37567L,37568L,37569L,37570L,
92782 37571L,37572L,37573L,37574L,37575L,37576L,37577L,37578L,37579L,37580L,
92783 37581L,37582L,37583L,37584L,37585L,37586L,37587L,37588L,37589L,37590L,
92784 37591L,37592L,37593L,37594L,37595L,37596L,37597L,37598L,37599L,37600L,
92785 37601L,37602L,37603L,37604L,37605L,37606L,37607L,37608L,37609L,37610L,
92786 37611L,37612L,37613L,37614L,37615L,37616L,37617L,37618L,37619L,37620L,
92787 37621L,37622L,37623L,37624L,37625L,37626L,37627L,37628L,37629L,37630L,
92788 37631L,37632L,37633L,37634L,37635L,37636L,37637L,37638L,37639L,37640L,
92789 37641L,37642L,37643L,37644L,37645L,37646L,37647L,37648L,37649L,37650L,
92790 37651L,37652L,37653L,37654L,37655L,37656L,37657L,37658L,37659L,37660L,
92791 37661L,37662L,37663L,37664L,37665L,37666L,37667L,37668L,37669L,37670L,
92792 37671L,37672L,37673L,37674L,37675L,37676L,37677L,37678L,37679L,37680L,
92793 37681L,37682L,37683L,37684L,37685L,37686L,37687L,37688L,37689L,37690L,
92794 37691L,37692L,37693L,37694L,37695L,37696L,37697L,37698L,37699L,37700L,
92795 37701L,37702L,37703L,37704L,37705L,37706L,37707L,37708L,37709L,37710L,
92796 37711L,37712L,37713L,37714L,37715L,37716L,37717L,37718L,37719L,37720L,
92797 37721L,37722L,37723L,37724L,37725L,37726L,37727L,37728L,37729L,37730L,
92798 37731L,37732L,37733L,37734L,37735L,37736L,37737L,37738L,37739L,37740L,
92799 37741L,37742L,37743L,37744L,37745L,37746L,37747L,37748L,37749L,37750L,
92800 37751L,37752L,37753L,37754L,37755L,37756L,37757L,37758L,37759L,37760L,
92801 37761L,37762L,37763L,37764L,37765L,37766L,37767L,37768L,37769L,37770L,
92802 37771L,37772L,37773L,37774L,37775L,37776L,37777L,37778L,37779L,37780L,
92803 37781L,37782L,37783L,37784L,37785L,37786L,37787L,37788L,37789L,37790L,
92804 37791L,37792L,37793L,37794L,37795L,37796L,37797L,37798L,37799L,37800L,
92805 37801L,37802L,37803L,37804L,37805L,37806L,37807L,37808L,37809L,37810L,
92806 37811L,37812L,37813L,37814L,37815L,37816L,37817L,37818L,37819L,37820L,
92807 37821L,37822L,37823L,37824L,37825L,37826L,37827L,37828L,37829L,37830L,
92808 37831L,37832L,37833L,37834L,37835L,37836L,37837L,37838L,37839L,37840L,
92809 37841L,37842L,37843L,37844L,37845L,37846L,37847L,37848L,37849L,37850L,
92810 37851L,37852L,37853L,37854L,37855L,37856L,37857L,37858L,37859L,37860L,
92811 37861L,37862L,37863L,37864L,37865L,37866L,37867L,37868L,37869L,37870L,
92812 37871L,37872L,37873L,37874L,37875L,37876L,37877L,37878L,37879L,37880L,
92813 37881L,37882L,37883L,37884L,37885L,37886L,37887L,37888L,37889L,37890L,
92814 37891L,37892L,37893L,37894L,37895L,37896L,37897L,37898L,37899L,37900L,
92815 37901L,37902L,37903L,37904L,37905L,37906L,37907L,37908L,37909L,37910L,
92816 37911L,37912L,37913L,37914L,37915L,37916L,37917L,37918L,37919L,37920L,
92817 37921L,37922L,37923L,37924L,37925L,37926L,37927L,37928L,37929L,37930L,
92818 37931L,37932L,37933L,37934L,37935L,37936L,37937L,37938L,37939L,37940L,
92819 37941L,37942L,37943L,37944L,37945L,37946L,37947L,37948L,37949L,37950L,
92820 37951L,37952L,37953L,37954L,37955L,37956L,37957L,37958L,37959L,37960L,
92821 37961L,37962L,37963L,37964L,37965L,37966L,37967L,37968L,37969L,37970L,
92822 37971L,37972L,37973L,37974L,37975L,37976L,37977L,37978L,37979L,37980L,
92823 37981L,37982L,37983L,37984L,37985L,37986L,37987L,37988L,37989L,37990L,
92824 37991L,37992L,37993L,37994L,37995L,37996L,37997L,37998L,37999L,38000L,
92825 38001L,38002L,38003L,38004L,38005L,38006L,38007L,38008L,38009L,38010L,
92826 38011L,38012L,38013L,38014L,38015L,38016L,38017L,38018L,38019L,38020L,
92827 38021L,38022L,38023L,38024L,38025L,38026L,38027L,38028L,38029L,38030L,
92828 38031L,38032L,38033L,38034L,38035L,38036L,38037L,38038L,38039L,38040L,
92829 38041L,38042L,38043L,38044L,38045L,38046L,38047L,38048L,38049L,38050L,
92830 38051L,38052L,38053L,38054L,38055L,38056L,38057L,38058L,38059L,38060L,
92831 38061L,38062L,38063L,38064L,38065L,38066L,38067L,38068L,38069L,38070L,
92832 38071L,38072L,38073L,38074L,38075L,38076L,38077L,38078L,38079L,38080L,
92833 38081L,38082L,38083L,38084L,38085L,38086L,38087L,38088L,38089L,38090L,
92834 38091L,38092L,38093L,38094L,38095L,38096L,38097L,38098L,38099L,38100L,
92835 38101L,38102L,38103L,38104L,38105L,38106L,38107L,38108L,38109L,38110L,
92836 38111L,38112L,38113L,38114L,38115L,38116L,38117L,38118L,38119L,38120L,
92837 38121L,38122L,38123L,38124L,38125L,38126L,38127L,38128L,38129L,38130L,
92838 38131L,38132L,38133L,38134L,38135L,38136L,38137L,38138L,38139L,38140L,
92839 38141L,38142L,38143L,38144L,38145L,38146L,38147L,38148L,38149L,38150L,
92840 38151L,38152L,38153L,38154L,38155L,38156L,38157L,38158L,38159L,38160L,
92841 38161L,38162L,38163L,38164L,38165L,38166L,38167L,38168L,38169L,38170L,
92842 38171L,38172L,38173L,38174L,38175L,38176L,38177L,38178L,38179L,38180L,
92843 38181L,38182L,38183L,38184L,38185L,38186L,38187L,38188L,38189L,38190L,
92844 38191L,38192L,38193L,38194L,38195L,38196L,38197L,38198L,38199L,38200L,
92845 38201L,38202L,38203L,38204L,38205L,38206L,38207L,38208L,38209L,38210L,
92846 38211L,38212L,38213L,38214L,38215L,38216L,38217L,38218L,38219L,38220L,
92847 38221L,38222L,38223L,38224L,38225L,38226L,38227L,38228L,38229L,38230L,
92848 38231L,38232L,38233L,38234L,38235L,38236L,38237L,38238L,38239L,38240L,
92849 38241L,38242L,38243L,38244L,38245L,38246L,38247L,38248L,38249L,38250L,
92850 38251L,38252L,38253L,38254L,38255L,38256L,38257L,38258L,38259L,38260L,
92851 38261L,38262L,38263L,38264L,38265L,38266L,38267L,38268L,38269L,38270L,
92852 38271L,38272L,38273L,38274L,38275L,38276L,38277L,38278L,38279L,38280L,
92853 38281L,38282L,38283L,38284L,38285L,38286L,38287L,38288L,38289L,38290L,
92854 38291L,38292L,38293L,38294L,38295L,38296L,38297L,38298L,38299L,38300L,
92855 38301L,38302L,38303L,38304L,38305L,38306L,38307L,38308L,38309L,38310L,
92856 38311L,38312L,38313L,38314L,38315L,38316L,38317L,38318L,38319L,38320L,
92857 38321L,38322L,38323L,38324L,38325L,38326L,38327L,38328L,38329L,38330L,
92858 38331L,38332L,38333L,38334L,38335L,38336L,38337L,38338L,38339L,38340L,
92859 38341L,38342L,38343L,38344L,38345L,38346L,38347L,38348L,38349L,38350L,
92860 38351L,38352L,38353L,38354L,38355L,38356L,38357L,38358L,38359L,38360L,
92861 38361L,38362L,38363L,38364L,38365L,38366L,38367L,38368L,38369L,38370L,
92862 38371L,38372L,38373L,38374L,38375L,38376L,38377L,38378L,38379L,38380L,
92863 38381L,38382L,38383L,38384L,38385L,38386L,38387L,38388L,38389L,38390L,
92864 38391L,38392L,38393L,38394L,38395L,38396L,38397L,38398L,38399L,38400L,
92865 38401L,38402L,38403L,38404L,38405L,38406L,38407L,38408L,38409L,38410L,
92866 38411L,38412L,38413L,38414L,38415L,38416L,38417L,38418L,38419L,38420L,
92867 38421L,38422L,38423L,38424L,38425L,38426L,38427L,38428L,38429L,38430L,
92868 38431L,38432L,38433L,38434L,38435L,38436L,38437L,38438L,38439L,38440L,
92869 38441L,38442L,38443L,38444L,38445L,38446L,38447L,38448L,38449L,38450L,
92870 38451L,38452L,38453L,38454L,38455L,38456L,38457L,38458L,38459L,38460L,
92871 38461L,38462L,38463L,38464L,38465L,38466L,38467L,38468L,38469L,38470L,
92872 38471L,38472L,38473L,38474L,38475L,38476L,38477L,38478L,38479L,38480L,
92873 38481L,38482L,38483L,38484L,38485L,38486L,38487L,38488L,38489L,38490L,
92874 38491L,38492L,38493L,38494L,38495L,38496L,38497L,38498L,38499L,38500L,
92875 38501L,38502L,38503L,38504L,38505L,38506L,38507L,38508L,38509L,38510L,
92876 38511L,38512L,38513L,38514L,38515L,38516L,38517L,38518L,38519L,38520L,
92877 38521L,38522L,38523L,38524L,38525L,38526L,38527L,38528L,38529L,38530L,
92878 38531L,38532L,38533L,38534L,38535L,38536L,38537L,38538L,38539L,38540L,
92879 38541L,38542L,38543L,38544L,38545L,38546L,38547L,38548L,38549L,38550L,
92880 38551L,38552L,38553L,38554L,38555L,38556L,38557L,38558L,38559L,38560L,
92881 38561L,38562L,38563L,38564L,38565L,38566L,38567L,38568L,38569L,38570L,
92882 38571L,38572L,38573L,38574L,38575L,38576L,38577L,38578L,38579L,38580L,
92883 38581L,38582L,38583L,38584L,38585L,38586L,38587L,38588L,38589L,38590L,
92884 38591L,38592L,38593L,38594L,38595L,38596L,38597L,38598L,38599L,38600L,
92885 38601L,38602L,38603L,38604L,38605L,38606L,38607L,38608L,38609L,38610L,
92886 38611L,38612L,38613L,38614L,38615L,38616L,38617L,38618L,38619L,38620L,
92887 38621L,38622L,38623L,38624L,38625L,38626L,38627L,38628L,38629L,38630L,
92888 38631L,38632L,38633L,38634L,38635L,38636L,38637L,38638L,38639L,38640L,
92889 38641L,38642L,38643L,38644L,38645L,38646L,38647L,38648L,38649L,38650L,
92890 38651L,38652L,38653L,38654L,38655L,38656L,38657L,38658L,38659L,38660L,
92891 38661L,38662L,38663L,38664L,38665L,38666L,38667L,38668L,38669L,38670L,
92892 38671L,38672L,38673L,38674L,38675L,38676L,38677L,38678L,38679L,38680L,
92893 38681L,38682L,38683L,38684L,38685L,38686L,38687L,38688L,38689L,38690L,
92894 38691L,38692L,38693L,38694L,38695L,38696L,38697L,38698L,38699L,38700L,
92895 38701L,38702L,38703L,38704L,38705L,38706L,38707L,38708L,38709L,38710L,
92896 38711L,38712L,38713L,38714L,38715L,38716L,38717L,38718L,38719L,38720L,
92897 38721L,38722L,38723L,38724L,38725L,38726L,38727L,38728L,38729L,38730L,
92898 38731L,38732L,38733L,38734L,38735L,38736L,38737L,38738L,38739L,38740L,
92899 38741L,38742L,38743L,38744L,38745L,38746L,38747L,38748L,38749L,38750L,
92900 38751L,38752L,38753L,38754L,38755L,38756L,38757L,38758L,38759L,38760L,
92901 38761L,38762L,38763L,38764L,38765L,38766L,38767L,38768L,38769L,38770L,
92902 38771L,38772L,38773L,38774L,38775L,38776L,38777L,38778L,38779L,38780L,
92903 38781L,38782L,38783L,38784L,38785L,38786L,38787L,38788L,38789L,38790L,
92904 38791L,38792L,38793L,38794L,38795L,38796L,38797L,38798L,38799L,38800L,
92905 38801L,38802L,38803L,38804L,38805L,38806L,38807L,38808L,38809L,38810L,
92906 38811L,38812L,38813L,38814L,38815L,38816L,38817L,38818L,38819L,38820L,
92907 38821L,38822L,38823L,38824L,38825L,38826L,38827L,38828L,38829L,38830L,
92908 38831L,38832L,38833L,38834L,38835L,38836L,38837L,38838L,38839L,38840L,
92909 38841L,38842L,38843L,38844L,38845L,38846L,38847L,38848L,38849L,38850L,
92910 38851L,38852L,38853L,38854L,38855L,38856L,38857L,38858L,38859L,38860L,
92911 38861L,38862L,38863L,38864L,38865L,38866L,38867L,38868L,38869L,38870L,
92912 38871L,38872L,38873L,38874L,38875L,38876L,38877L,38878L,38879L,38880L,
92913 38881L,38882L,38883L,38884L,38885L,38886L,38887L,38888L,38889L,38890L,
92914 38891L,38892L,38893L,38894L,38895L,38896L,38897L,38898L,38899L,38900L,
92915 38901L,38902L,38903L,38904L,38905L,38906L,38907L,38908L,38909L,38910L,
92916 38911L,38912L,38913L,38914L,38915L,38916L,38917L,38918L,38919L,38920L,
92917 38921L,38922L,38923L,38924L,38925L,38926L,38927L,38928L,38929L,38930L,
92918 38931L,38932L,38933L,38934L,38935L,38936L,38937L,38938L,38939L,38940L,
92919 38941L,38942L,38943L,38944L,38945L,38946L,38947L,38948L,38949L,38950L,
92920 38951L,38952L,38953L,38954L,38955L,38956L,38957L,38958L,38959L,38960L,
92921 38961L,38962L,38963L,38964L,38965L,38966L,38967L,38968L,38969L,38970L,
92922 38971L,38972L,38973L,38974L,38975L,38976L,38977L,38978L,38979L,38980L,
92923 38981L,38982L,38983L,38984L,38985L,38986L,38987L,38988L,38989L,38990L,
92924 38991L,38992L,38993L,38994L,38995L,38996L,38997L,38998L,38999L,39000L,
92925 39001L,39002L,39003L,39004L,39005L,39006L,39007L,39008L,39009L,39010L,
92926 39011L,39012L,39013L,39014L,39015L,39016L,39017L,39018L,39019L,39020L,
92927 39021L,39022L,39023L,39024L,39025L,39026L,39027L,39028L,39029L,39030L,
92928 39031L,39032L,39033L,39034L,39035L,39036L,39037L,39038L,39039L,39040L,
92929 39041L,39042L,39043L,39044L,39045L,39046L,39047L,39048L,39049L,39050L,
92930 39051L,39052L,39053L,39054L,39055L,39056L,39057L,39058L,39059L,39060L,
92931 39061L,39062L,39063L,39064L,39065L,39066L,39067L,39068L,39069L,39070L,
92932 39071L,39072L,39073L,39074L,39075L,39076L,39077L,39078L,39079L,39080L,
92933 39081L,39082L,39083L,39084L,39085L,39086L,39087L,39088L,39089L,39090L,
92934 39091L,39092L,39093L,39094L,39095L,39096L,39097L,39098L,39099L,39100L,
92935 39101L,39102L,39103L,39104L,39105L,39106L,39107L,39108L,39109L,39110L,
92936 39111L,39112L,39113L,39114L,39115L,39116L,39117L,39118L,39119L,39120L,
92937 39121L,39122L,39123L,39124L,39125L,39126L,39127L,39128L,39129L,39130L,
92938 39131L,39132L,39133L,39134L,39135L,39136L,39137L,39138L,39139L,39140L,
92939 39141L,39142L,39143L,39144L,39145L,39146L,39147L,39148L,39149L,39150L,
92940 39151L,39152L,39153L,39154L,39155L,39156L,39157L,39158L,39159L,39160L,
92941 39161L,39162L,39163L,39164L,39165L,39166L,39167L,39168L,39169L,39170L,
92942 39171L,39172L,39173L,39174L,39175L,39176L,39177L,39178L,39179L,39180L,
92943 39181L,39182L,39183L,39184L,39185L,39186L,39187L,39188L,39189L,39190L,
92944 39191L,39192L,39193L,39194L,39195L,39196L,39197L,39198L,39199L,39200L,
92945 39201L,39202L,39203L,39204L,39205L,39206L,39207L,39208L,39209L,39210L,
92946 39211L,39212L,39213L,39214L,39215L,39216L,39217L,39218L,39219L,39220L,
92947 39221L,39222L,39223L,39224L,39225L,39226L,39227L,39228L,39229L,39230L,
92948 39231L,39232L,39233L,39234L,39235L,39236L,39237L,39238L,39239L,39240L,
92949 39241L,39242L,39243L,39244L,39245L,39246L,39247L,39248L,39249L,39250L,
92950 39251L,39252L,39253L,39254L,39255L,39256L,39257L,39258L,39259L,39260L,
92951 39261L,39262L,39263L,39264L,39265L,39266L,39267L,39268L,39269L,39270L,
92952 39271L,39272L,39273L,39274L,39275L,39276L,39277L,39278L,39279L,39280L,
92953 39281L,39282L,39283L,39284L,39285L,39286L,39287L,39288L,39289L,39290L,
92954 39291L,39292L,39293L,39294L,39295L,39296L,39297L,39298L,39299L,39300L,
92955 39301L,39302L,39303L,39304L,39305L,39306L,39307L,39308L,39309L,39310L,
92956 39311L,39312L,39313L,39314L,39315L,39316L,39317L,39318L,39319L,39320L,
92957 39321L,39322L,39323L,39324L,39325L,39326L,39327L,39328L,39329L,39330L,
92958 39331L,39332L,39333L,39334L,39335L,39336L,39337L,39338L,39339L,39340L,
92959 39341L,39342L,39343L,39344L,39345L,39346L,39347L,39348L,39349L,39350L,
92960 39351L,39352L,39353L,39354L,39355L,39356L,39357L,39358L,39359L,39360L,
92961 39361L,39362L,39363L,39364L,39365L,39366L,39367L,39368L,39369L,39370L,
92962 39371L,39372L,39373L,39374L,39375L,39376L,39377L,39378L,39379L,39380L,
92963 39381L,39382L,39383L,39384L,39385L,39386L,39387L,39388L,39389L,39390L,
92964 39391L,39392L,39393L,39394L,39395L,39396L,39397L,39398L,39399L,39400L,
92965 39401L,39402L,39403L,39404L,39405L,39406L,39407L,39408L,39409L,39410L,
92966 39411L,39412L,39413L,39414L,39415L,39416L,39417L,39418L,39419L,39420L,
92967 39421L,39422L,39423L,39424L,39425L,39426L,39427L,39428L,39429L,39430L,
92968 39431L,39432L,39433L,39434L,39435L,39436L,39437L,39438L,39439L,39440L,
92969 39441L,39442L,39443L,39444L,39445L,39446L,39447L,39448L,39449L,39450L,
92970 39451L,39452L,39453L,39454L,39455L,39456L,39457L,39458L,39459L,39460L,
92971 39461L,39462L,39463L,39464L,39465L,39466L,39467L,39468L,39469L,39470L,
92972 39471L,39472L,39473L,39474L,39475L,39476L,39477L,39478L,39479L,39480L,
92973 39481L,39482L,39483L,39484L,39485L,39486L,39487L,39488L,39489L,39490L,
92974 39491L,39492L,39493L,39494L,39495L,39496L,39497L,39498L,39499L,39500L,
92975 39501L,39502L,39503L,39504L,39505L,39506L,39507L,39508L,39509L,39510L,
92976 39511L,39512L,39513L,39514L,39515L,39516L,39517L,39518L,39519L,39520L,
92977 39521L,39522L,39523L,39524L,39525L,39526L,39527L,39528L,39529L,39530L,
92978 39531L,39532L,39533L,39534L,39535L,39536L,39537L,39538L,39539L,39540L,
92979 39541L,39542L,39543L,39544L,39545L,39546L,39547L,39548L,39549L,39550L,
92980 39551L,39552L,39553L,39554L,39555L,39556L,39557L,39558L,39559L,39560L,
92981 39561L,39562L,39563L,39564L,39565L,39566L,39567L,39568L,39569L,39570L,
92982 39571L,39572L,39573L,39574L,39575L,39576L,39577L,39578L,39579L,39580L,
92983 39581L,39582L,39583L,39584L,39585L,39586L,39587L,39588L,39589L,39590L,
92984 39591L,39592L,39593L,39594L,39595L,39596L,39597L,39598L,39599L,39600L,
92985 39601L,39602L,39603L,39604L,39605L,39606L,39607L,39608L,39609L,39610L,
92986 39611L,39612L,39613L,39614L,39615L,39616L,39617L,39618L,39619L,39620L,
92987 39621L,39622L,39623L,39624L,39625L,39626L,39627L,39628L,39629L,39630L,
92988 39631L,39632L,39633L,39634L,39635L,39636L,39637L,39638L,39639L,39640L,
92989 39641L,39642L,39643L,39644L,39645L,39646L,39647L,39648L,39649L,39650L,
92990 39651L,39652L,39653L,39654L,39655L,39656L,39657L,39658L,39659L,39660L,
92991 39661L,39662L,39663L,39664L,39665L,39666L,39667L,39668L,39669L,39670L,
92992 39671L,39672L,39673L,39674L,39675L,39676L,39677L,39678L,39679L,39680L,
92993 39681L,39682L,39683L,39684L,39685L,39686L,39687L,39688L,39689L,39690L,
92994 39691L,39692L,39693L,39694L,39695L,39696L,39697L,39698L,39699L,39700L,
92995 39701L,39702L,39703L,39704L,39705L,39706L,39707L,39708L,39709L,39710L,
92996 39711L,39712L,39713L,39714L,39715L,39716L,39717L,39718L,39719L,39720L,
92997 39721L,39722L,39723L,39724L,39725L,39726L,39727L,39728L,39729L,39730L,
92998 39731L,39732L,39733L,39734L,39735L,39736L,39737L,39738L,39739L,39740L,
92999 39741L,39742L,39743L,39744L,39745L,39746L,39747L,39748L,39749L,39750L,
93000 39751L,39752L,39753L,39754L,39755L,39756L,39757L,39758L,39759L,39760L,
93001 39761L,39762L,39763L,39764L,39765L,39766L,39767L,39768L,39769L,39770L,
93002 39771L,39772L,39773L,39774L,39775L,39776L,39777L,39778L,39779L,39780L,
93003 39781L,39782L,39783L,39784L,39785L,39786L,39787L,39788L,39789L,39790L,
93004 39791L,39792L,39793L,39794L,39795L,39796L,39797L,39798L,39799L,39800L,
93005 39801L,39802L,39803L,39804L,39805L,39806L,39807L,39808L,39809L,39810L,
93006 39811L,39812L,39813L,39814L,39815L,39816L,39817L,39818L,39819L,39820L,
93007 39821L,39822L,39823L,39824L,39825L,39826L,39827L,39828L,39829L,39830L,
93008 39831L,39832L,39833L,39834L,39835L,39836L,39837L,39838L,39839L,39840L,
93009 39841L,39842L,39843L,39844L,39845L,39846L,39847L,39848L,39849L,39850L,
93010 39851L,39852L,39853L,39854L,39855L,39856L,39857L,39858L,39859L,39860L,
93011 39861L,39862L,39863L,39864L,39865L,39866L,39867L,39868L,39869L,39870L,
93012 39871L,39872L,39873L,39874L,39875L,39876L,39877L,39878L,39879L,39880L,
93013 39881L,39882L,39883L,39884L,39885L,39886L,39887L,39888L,39889L,39890L,
93014 39891L,39892L,39893L,39894L,39895L,39896L,39897L,39898L,39899L,39900L,
93015 39901L,39902L,39903L,39904L,39905L,39906L,39907L,39908L,39909L,39910L,
93016 39911L,39912L,39913L,39914L,39915L,39916L,39917L,39918L,39919L,39920L,
93017 39921L,39922L,39923L,39924L,39925L,39926L,39927L,39928L,39929L,39930L,
93018 39931L,39932L,39933L,39934L,39935L,39936L,39937L,39938L,39939L,39940L,
93019 39941L,39942L,39943L,39944L,39945L,39946L,39947L,39948L,39949L,39950L,
93020 39951L,39952L,39953L,39954L,39955L,39956L,39957L,39958L,39959L,39960L,
93021 39961L,39962L,39963L,39964L,39965L,39966L,39967L,39968L,39969L,39970L,
93022 39971L,39972L,39973L,39974L,39975L,39976L,39977L,39978L,39979L,39980L,
93023 39981L,39982L,39983L,39984L,39985L,39986L,39987L,39988L,39989L,39990L,
93024 39991L,39992L,39993L,39994L,39995L,39996L,39997L,39998L,39999L,40000L,
93025 40001L,40002L,40003L,40004L,40005L,40006L,40007L,40008L,40009L,40010L,
93026 40011L,40012L,40013L,40014L,40015L,40016L,40017L,40018L,40019L,40020L,
93027 40021L,40022L,40023L,40024L,40025L,40026L,40027L,40028L,40029L,40030L,
93028 40031L,40032L,40033L,40034L,40035L,40036L,40037L,40038L,40039L,40040L,
93029 40041L,40042L,40043L,40044L,40045L,40046L,40047L,40048L,40049L,40050L,
93030 40051L,40052L,40053L,40054L,40055L,40056L,40057L,40058L,40059L,40060L,
93031 40061L,40062L,40063L,40064L,40065L,40066L,40067L,40068L,40069L,40070L,
93032 40071L,40072L,40073L,40074L,40075L,40076L,40077L,40078L,40079L,40080L,
93033 40081L,40082L,40083L,40084L,40085L,40086L,40087L,40088L,40089L,40090L,
93034 40091L,40092L,40093L,40094L,40095L,40096L,40097L,40098L,40099L,40100L,
93035 40101L,40102L,40103L,40104L,40105L,40106L,40107L,40108L,40109L,40110L,
93036 40111L,40112L,40113L,40114L,40115L,40116L,40117L,40118L,40119L,40120L,
93037 40121L,40122L,40123L,40124L,40125L,40126L,40127L,40128L,40129L,40130L,
93038 40131L,40132L,40133L,40134L,40135L,40136L,40137L,40138L,40139L,40140L,
93039 40141L,40142L,40143L,40144L,40145L,40146L,40147L,40148L,40149L,40150L,
93040 40151L,40152L,40153L,40154L,40155L,40156L,40157L,40158L,40159L,40160L,
93041 40161L,40162L,40163L,40164L,40165L,40166L,40167L,40168L,40169L,40170L,
93042 40171L,40172L,40173L,40174L,40175L,40176L,40177L,40178L,40179L,40180L,
93043 40181L,40182L,40183L,40184L,40185L,40186L,40187L,40188L,40189L,40190L,
93044 40191L,40192L,40193L,40194L,40195L,40196L,40197L,40198L,40199L,40200L,
93045 40201L,40202L,40203L,40204L,40205L,40206L,40207L,40208L,40209L,40210L,
93046 40211L,40212L,40213L,40214L,40215L,40216L,40217L,40218L,40219L,40220L,
93047 40221L,40222L,40223L,40224L,40225L,40226L,40227L,40228L,40229L,40230L,
93048 40231L,40232L,40233L,40234L,40235L,40236L,40237L,40238L,40239L,40240L,
93049 40241L,40242L,40243L,40244L,40245L,40246L,40247L,40248L,40249L,40250L,
93050 40251L,40252L,40253L,40254L,40255L,40256L,40257L,40258L,40259L,40260L,
93051 40261L,40262L,40263L,40264L,40265L,40266L,40267L,40268L,40269L,40270L,
93052 40271L,40272L,40273L,40274L,40275L,40276L,40277L,40278L,40279L,40280L,
93053 40281L,40282L,40283L,40284L,40285L,40286L,40287L,40288L,40289L,40290L,
93054 40291L,40292L,40293L,40294L,40295L,40296L,40297L,40298L,40299L,40300L,
93055 40301L,40302L,40303L,40304L,40305L,40306L,40307L,40308L,40309L,40310L,
93056 40311L,40312L,40313L,40314L,40315L,40316L,40317L,40318L,40319L,40320L,
93057 40321L,40322L,40323L,40324L,40325L,40326L,40327L,40328L,40329L,40330L,
93058 40331L,40332L,40333L,40334L,40335L,40336L,40337L,40338L,40339L,40340L,
93059 40341L,40342L,40343L,40344L,40345L,40346L,40347L,40348L,40349L,40350L,
93060 40351L,40352L,40353L,40354L,40355L,40356L,40357L,40358L,40359L,40360L,
93061 40361L,40362L,40363L,40364L,40365L,40366L,40367L,40368L,40369L,40370L,
93062 40371L,40372L,40373L,40374L,40375L,40376L,40377L,40378L,40379L,40380L,
93063 40381L,40382L,40383L,40384L,40385L,40386L,40387L,40388L,40389L,40390L,
93064 40391L,40392L,40393L,40394L,40395L,40396L,40397L,40398L,40399L,40400L,
93065 40401L,40402L,40403L,40404L,40405L,40406L,40407L,40408L,40409L,40410L,
93066 40411L,40412L,40413L,40414L,40415L,40416L,40417L,40418L,40419L,40420L,
93067 40421L,40422L,40423L,40424L,40425L,40426L,40427L,40428L,40429L,40430L,
93068 40431L,40432L,40433L,40434L,40435L,40436L,40437L,40438L,40439L,40440L,
93069 40441L,40442L,40443L,40444L,40445L,40446L,40447L,40448L,40449L,40450L,
93070 40451L,40452L,40453L,40454L,40455L,40456L,40457L,40458L,40459L,40460L,
93071 40461L,40462L,40463L,40464L,40465L,40466L,40467L,40468L,40469L,40470L,
93072 40471L,40472L,40473L,40474L,40475L,40476L,40477L,40478L,40479L,40480L,
93073 40481L,40482L,40483L,40484L,40485L,40486L,40487L,40488L,40489L,40490L,
93074 40491L,40492L,40493L,40494L,40495L,40496L,40497L,40498L,40499L,40500L,
93075 40501L,40502L,40503L,40504L,40505L,40506L,40507L,40508L,40509L,40510L,
93076 40511L,40512L,40513L,40514L,40515L,40516L,40517L,40518L,40519L,40520L,
93077 40521L,40522L,40523L,40524L,40525L,40526L,40527L,40528L,40529L,40530L,
93078 40531L,40532L,40533L,40534L,40535L,40536L,40537L,40538L,40539L,40540L,
93079 40541L,40542L,40543L,40544L,40545L,40546L,40547L,40548L,40549L,40550L,
93080 40551L,40552L,40553L,40554L,40555L,40556L,40557L,40558L,40559L,40560L,
93081 40561L,40562L,40563L,40564L,40565L,40566L,40567L,40568L,40569L,40570L,
93082 40571L,40572L,40573L,40574L,40575L,40576L,40577L,40578L,40579L,40580L,
93083 40581L,40582L,40583L,40584L,40585L,40586L,40587L,40588L,40589L,40590L,
93084 40591L,40592L,40593L,40594L,40595L,40596L,40597L,40598L,40599L,40600L,
93085 40601L,40602L,40603L,40604L,40605L,40606L,40607L,40608L,40609L,40610L,
93086 40611L,40612L,40613L,40614L,40615L,40616L,40617L,40618L,40619L,40620L,
93087 40621L,40622L,40623L,40624L,40625L,40626L,40627L,40628L,40629L,40630L,
93088 40631L,40632L,40633L,40634L,40635L,40636L,40637L,40638L,40639L,40640L,
93089 40641L,40642L,40643L,40644L,40645L,40646L,40647L,40648L,40649L,40650L,
93090 40651L,40652L,40653L,40654L,40655L,40656L,40657L,40658L,40659L,40660L,
93091 40661L,40662L,40663L,40664L,40665L,40666L,40667L,40668L,40669L,40670L,
93092 40671L,40672L,40673L,40674L,40675L,40676L,40677L,40678L,40679L,40680L,
93093 40681L,40682L,40683L,40684L,40685L,40686L,40687L,40688L,40689L,40690L,
93094 40691L,40692L,40693L,40694L,40695L,40696L,40697L,40698L,40699L,40700L,
93095 40701L,40702L,40703L,40704L,40705L,40706L,40707L,40708L,40709L,40710L,
93096 40711L,40712L,40713L,40714L,40715L,40716L,40717L,40718L,40719L,40720L,
93097 40721L,40722L,40723L,40724L,40725L,40726L,40727L,40728L,40729L,40730L,
93098 40731L,40732L,40733L,40734L,40735L,40736L,40737L,40738L,40739L,40740L,
93099 40741L,40742L,40743L,40744L,40745L,40746L,40747L,40748L,40749L,40750L,
93100 40751L,40752L,40753L,40754L,40755L,40756L,40757L,40758L,40759L,40760L,
93101 40761L,40762L,40763L,40764L,40765L,40766L,40767L,40768L,40769L,40770L,
93102 40771L,40772L,40773L,40774L,40775L,40776L,40777L,40778L,40779L,40780L,
93103 40781L,40782L,40783L,40784L,40785L,40786L,40787L,40788L,40789L,40790L,
93104 40791L,40792L,40793L,40794L,40795L,40796L,40797L,40798L,40799L,40800L,
93105 40801L,40802L,40803L,40804L,40805L,40806L,40807L,40808L,40809L,40810L,
93106 40811L,40812L,40813L,40814L,40815L,40816L,40817L,40818L,40819L,40820L,
93107 40821L,40822L,40823L,40824L,40825L,40826L,40827L,40828L,40829L,40830L,
93108 40831L,40832L,40833L,40834L,40835L,40836L,40837L,40838L,40839L,40840L,
93109 40841L,40842L,40843L,40844L,40845L,40846L,40847L,40848L,40849L,40850L,
93110 40851L,40852L,40853L,40854L,40855L,40856L,40857L,40858L,40859L,40860L,
93111 40861L,40862L,40863L,40864L,40865L,40866L,40867L,40868L,40869L,40870L,
93112 40871L,40872L,40873L,40874L,40875L,40876L,40877L,40878L,40879L,40880L,
93113 40881L,40882L,40883L,40884L,40885L,40886L,40887L,40888L,40889L,40890L,
93114 40891L,40892L,40893L,40894L,40895L,40896L,40897L,40898L,40899L,40900L,
93115 40901L,40902L,40903L,40904L,40905L,40906L,40907L,40908L,40909L,40910L,
93116 40911L,40912L,40913L,40914L,40915L,40916L,40917L,40918L,40919L,40920L,
93117 40921L,40922L,40923L,40924L,40925L,40926L,40927L,40928L,40929L,40930L,
93118 40931L,40932L,40933L,40934L,40935L,40936L,40937L,40938L,40939L,40940L,
93119 40941L,40942L,40943L,40944L,40945L,40946L,40947L,40948L,40949L,40950L,
93120 40951L,40952L,40953L,40954L,40955L,40956L,40957L,40958L,40959L,40960L,
93121 40961L,40962L,40963L,40964L,40965L,40966L,40967L,40968L,40969L,40970L,
93122 40971L,40972L,40973L,40974L,40975L,40976L,40977L,40978L,40979L,40980L,
93123 40981L,40982L,40983L,40984L,40985L,40986L,40987L,40988L,40989L,40990L,
93124 40991L,40992L,40993L,40994L,40995L,40996L,40997L,40998L,40999L,41000L,
93125 41001L,41002L,41003L,41004L,41005L,41006L,41007L,41008L,41009L,41010L,
93126 41011L,41012L,41013L,41014L,41015L,41016L,41017L,41018L,41019L,41020L,
93127 41021L,41022L,41023L,41024L,41025L,41026L,41027L,41028L,41029L,41030L,
93128 41031L,41032L,41033L,41034L,41035L,41036L,41037L,41038L,41039L,41040L,
93129 41041L,41042L,41043L,41044L,41045L,41046L,41047L,41048L,41049L,41050L,
93130 41051L,41052L,41053L,41054L,41055L,41056L,41057L,41058L,41059L,41060L,
93131 41061L,41062L,41063L,41064L,41065L,41066L,41067L,41068L,41069L,41070L,
93132 41071L,41072L,41073L,41074L,41075L,41076L,41077L,41078L,41079L,41080L,
93133 41081L,41082L,41083L,41084L,41085L,41086L,41087L,41088L,41089L,41090L,
93134 41091L,41092L,41093L,41094L,41095L,41096L,41097L,41098L,41099L,41100L,
93135 41101L,41102L,41103L,41104L,41105L,41106L,41107L,41108L,41109L,41110L,
93136 41111L,41112L,41113L,41114L,41115L,41116L,41117L,41118L,41119L,41120L,
93137 41121L,41122L,41123L,41124L,41125L,41126L,41127L,41128L,41129L,41130L,
93138 41131L,41132L,41133L,41134L,41135L,41136L,41137L,41138L,41139L,41140L,
93139 41141L,41142L,41143L,41144L,41145L,41146L,41147L,41148L,41149L,41150L,
93140 41151L,41152L,41153L,41154L,41155L,41156L,41157L,41158L,41159L,41160L,
93141 41161L,41162L,41163L,41164L,41165L,41166L,41167L,41168L,41169L,41170L,
93142 41171L,41172L,41173L,41174L,41175L,41176L,41177L,41178L,41179L,41180L,
93143 41181L,41182L,41183L,41184L,41185L,41186L,41187L,41188L,41189L,41190L,
93144 41191L,41192L,41193L,41194L,41195L,41196L,41197L,41198L,41199L,41200L,
93145 41201L,41202L,41203L,41204L,41205L,41206L,41207L,41208L,41209L,41210L,
93146 41211L,41212L,41213L,41214L,41215L,41216L,41217L,41218L,41219L,41220L,
93147 41221L,41222L,41223L,41224L,41225L,41226L,41227L,41228L,41229L,41230L,
93148 41231L,41232L,41233L,41234L,41235L,41236L,41237L,41238L,41239L,41240L,
93149 41241L,41242L,41243L,41244L,41245L,41246L,41247L,41248L,41249L,41250L,
93150 41251L,41252L,41253L,41254L,41255L,41256L,41257L,41258L,41259L,41260L,
93151 41261L,41262L,41263L,41264L,41265L,41266L,41267L,41268L,41269L,41270L,
93152 41271L,41272L,41273L,41274L,41275L,41276L,41277L,41278L,41279L,41280L,
93153 41281L,41282L,41283L,41284L,41285L,41286L,41287L,41288L,41289L,41290L,
93154 41291L,41292L,41293L,41294L,41295L,41296L,41297L,41298L,41299L,41300L,
93155 41301L,41302L,41303L,41304L,41305L,41306L,41307L,41308L,41309L,41310L,
93156 41311L,41312L,41313L,41314L,41315L,41316L,41317L,41318L,41319L,41320L,
93157 41321L,41322L,41323L,41324L,41325L,41326L,41327L,41328L,41329L,41330L,
93158 41331L,41332L,41333L,41334L,41335L,41336L,41337L,41338L,41339L,41340L,
93159 41341L,41342L,41343L,41344L,41345L,41346L,41347L,41348L,41349L,41350L,
93160 41351L,41352L,41353L,41354L,41355L,41356L,41357L,41358L,41359L,41360L,
93161 41361L,41362L,41363L,41364L,41365L,41366L,41367L,41368L,41369L,41370L,
93162 41371L,41372L,41373L,41374L,41375L,41376L,41377L,41378L,41379L,41380L,
93163 41381L,41382L,41383L,41384L,41385L,41386L,41387L,41388L,41389L,41390L,
93164 41391L,41392L,41393L,41394L,41395L,41396L,41397L,41398L,41399L,41400L,
93165 41401L,41402L,41403L,41404L,41405L,41406L,41407L,41408L,41409L,41410L,
93166 41411L,41412L,41413L,41414L,41415L,41416L,41417L,41418L,41419L,41420L,
93167 41421L,41422L,41423L,41424L,41425L,41426L,41427L,41428L,41429L,41430L,
93168 41431L,41432L,41433L,41434L,41435L,41436L,41437L,41438L,41439L,41440L,
93169 41441L,41442L,41443L,41444L,41445L,41446L,41447L,41448L,41449L,41450L,
93170 41451L,41452L,41453L,41454L,41455L,41456L,41457L,41458L,41459L,41460L,
93171 41461L,41462L,41463L,41464L,41465L,41466L,41467L,41468L,41469L,41470L,
93172 41471L,41472L,41473L,41474L,41475L,41476L,41477L,41478L,41479L,41480L,
93173 41481L,41482L,41483L,41484L,41485L,41486L,41487L,41488L,41489L,41490L,
93174 41491L,41492L,41493L,41494L,41495L,41496L,41497L,41498L,41499L,41500L,
93175 41501L,41502L,41503L,41504L,41505L,41506L,41507L,41508L,41509L,41510L,
93176 41511L,41512L,41513L,41514L,41515L,41516L,41517L,41518L,41519L,41520L,
93177 41521L,41522L,41523L,41524L,41525L,41526L,41527L,41528L,41529L,41530L,
93178 41531L,41532L,41533L,41534L,41535L,41536L,41537L,41538L,41539L,41540L,
93179 41541L,41542L,41543L,41544L,41545L,41546L,41547L,41548L,41549L,41550L,
93180 41551L,41552L,41553L,41554L,41555L,41556L,41557L,41558L,41559L,41560L,
93181 41561L,41562L,41563L,41564L,41565L,41566L,41567L,41568L,41569L,41570L,
93182 41571L,41572L,41573L,41574L,41575L,41576L,41577L,41578L,41579L,41580L,
93183 41581L,41582L,41583L,41584L,41585L,41586L,41587L,41588L,41589L,41590L,
93184 41591L,41592L,41593L,41594L,41595L,41596L,41597L,41598L,41599L,41600L,
93185 41601L,41602L,41603L,41604L,41605L,41606L,41607L,41608L,41609L,41610L,
93186 41611L,41612L,41613L,41614L,41615L,41616L,41617L,41618L,41619L,41620L,
93187 41621L,41622L,41623L,41624L,41625L,41626L,41627L,41628L,41629L,41630L,
93188 41631L,41632L,41633L,41634L,41635L,41636L,41637L,41638L,41639L,41640L,
93189 41641L,41642L,41643L,41644L,41645L,41646L,41647L,41648L,41649L,41650L,
93190 41651L,41652L,41653L,41654L,41655L,41656L,41657L,41658L,41659L,41660L,
93191 41661L,41662L,41663L,41664L,41665L,41666L,41667L,41668L,41669L,41670L,
93192 41671L,41672L,41673L,41674L,41675L,41676L,41677L,41678L,41679L,41680L,
93193 41681L,41682L,41683L,41684L,41685L,41686L,41687L,41688L,41689L,41690L,
93194 41691L,41692L,41693L,41694L,41695L,41696L,41697L,41698L,41699L,41700L,
93195 41701L,41702L,41703L,41704L,41705L,41706L,41707L,41708L,41709L,41710L,
93196 41711L,41712L,41713L,41714L,41715L,41716L,41717L,41718L,41719L,41720L,
93197 41721L,41722L,41723L,41724L,41725L,41726L,41727L,41728L,41729L,41730L,
93198 41731L,41732L,41733L,41734L,41735L,41736L,41737L,41738L,41739L,41740L,
93199 41741L,41742L,41743L,41744L,41745L,41746L,41747L,41748L,41749L,41750L,
93200 41751L,41752L,41753L,41754L,41755L,41756L,41757L,41758L,41759L,41760L,
93201 41761L,41762L,41763L,41764L,41765L,41766L,41767L,41768L,41769L,41770L,
93202 41771L,41772L,41773L,41774L,41775L,41776L,41777L,41778L,41779L,41780L,
93203 41781L,41782L,41783L,41784L,41785L,41786L,41787L,41788L,41789L,41790L,
93204 41791L,41792L,41793L,41794L,41795L,41796L,41797L,41798L,41799L,41800L,
93205 41801L,41802L,41803L,41804L,41805L,41806L,41807L,41808L,41809L,41810L,
93206 41811L,41812L,41813L,41814L,41815L,41816L,41817L,41818L,41819L,41820L,
93207 41821L,41822L,41823L,41824L,41825L,41826L,41827L,41828L,41829L,41830L,
93208 41831L,41832L,41833L,41834L,41835L,41836L,41837L,41838L,41839L,41840L,
93209 41841L,41842L,41843L,41844L,41845L,41846L,41847L,41848L,41849L,41850L,
93210 41851L,41852L,41853L,41854L,41855L,41856L,41857L,41858L,41859L,41860L,
93211 41861L,41862L,41863L,41864L,41865L,41866L,41867L,41868L,41869L,41870L,
93212 41871L,41872L,41873L,41874L,41875L,41876L,41877L,41878L,41879L,41880L,
93213 41881L,41882L,41883L,41884L,41885L,41886L,41887L,41888L,41889L,41890L,
93214 41891L,41892L,41893L,41894L,41895L,41896L,41897L,41898L,41899L,41900L,
93215 41901L,41902L,41903L,41904L,41905L,41906L,41907L,41908L,41909L,41910L,
93216 41911L,41912L,41913L,41914L,41915L,41916L,41917L,41918L,41919L,41920L,
93217 41921L,41922L,41923L,41924L,41925L,41926L,41927L,41928L,41929L,41930L,
93218 41931L,41932L,41933L,41934L,41935L,41936L,41937L,41938L,41939L,41940L,
93219 41941L,41942L,41943L,41944L,41945L,41946L,41947L,41948L,41949L,41950L,
93220 41951L,41952L,41953L,41954L,41955L,41956L,41957L,41958L,41959L,41960L,
93221 41961L,41962L,41963L,41964L,41965L,41966L,41967L,41968L,41969L,41970L,
93222 41971L,41972L,41973L,41974L,41975L,41976L,41977L,41978L,41979L,41980L,
93223 41981L,41982L,41983L,41984L,41985L,41986L,41987L,41988L,41989L,41990L,
93224 41991L,41992L,41993L,41994L,41995L,41996L,41997L,41998L,41999L,42000L,
93225 42001L,42002L,42003L,42004L,42005L,42006L,42007L,42008L,42009L,42010L,
93226 42011L,42012L,42013L,42014L,42015L,42016L,42017L,42018L,42019L,42020L,
93227 42021L,42022L,42023L,42024L,42025L,42026L,42027L,42028L,42029L,42030L,
93228 42031L,42032L,42033L,42034L,42035L,42036L,42037L,42038L,42039L,42040L,
93229 42041L,42042L,42043L,42044L,42045L,42046L,42047L,42048L,42049L,42050L,
93230 42051L,42052L,42053L,42054L,42055L,42056L,42057L,42058L,42059L,42060L,
93231 42061L,42062L,42063L,42064L,42065L,42066L,42067L,42068L,42069L,42070L,
93232 42071L,42072L,42073L,42074L,42075L,42076L,42077L,42078L,42079L,42080L,
93233 42081L,42082L,42083L,42084L,42085L,42086L,42087L,42088L,42089L,42090L,
93234 42091L,42092L,42093L,42094L,42095L,42096L,42097L,42098L,42099L,42100L,
93235 42101L,42102L,42103L,42104L,42105L,42106L,42107L,42108L,42109L,42110L,
93236 42111L,42112L,42113L,42114L,42115L,42116L,42117L,42118L,42119L,42120L,
93237 42121L,42122L,42123L,42124L,42125L,42126L,42127L,42128L,42129L,42130L,
93238 42131L,42132L,42133L,42134L,42135L,42136L,42137L,42138L,42139L,42140L,
93239 42141L,42142L,42143L,42144L,42145L,42146L,42147L,42148L,42149L,42150L,
93240 42151L,42152L,42153L,42154L,42155L,42156L,42157L,42158L,42159L,42160L,
93241 42161L,42162L,42163L,42164L,42165L,42166L,42167L,42168L,42169L,42170L,
93242 42171L,42172L,42173L,42174L,42175L,42176L,42177L,42178L,42179L,42180L,
93243 42181L,42182L,42183L,42184L,42185L,42186L,42187L,42188L,42189L,42190L,
93244 42191L,42192L,42193L,42194L,42195L,42196L,42197L,42198L,42199L,42200L,
93245 42201L,42202L,42203L,42204L,42205L,42206L,42207L,42208L,42209L,42210L,
93246 42211L,42212L,42213L,42214L,42215L,42216L,42217L,42218L,42219L,42220L,
93247 42221L,42222L,42223L,42224L,42225L,42226L,42227L,42228L,42229L,42230L,
93248 42231L,42232L,42233L,42234L,42235L,42236L,42237L,42238L,42239L,42240L,
93249 42241L,42242L,42243L,42244L,42245L,42246L,42247L,42248L,42249L,42250L,
93250 42251L,42252L,42253L,42254L,42255L,42256L,42257L,42258L,42259L,42260L,
93251 42261L,42262L,42263L,42264L,42265L,42266L,42267L,42268L,42269L,42270L,
93252 42271L,42272L,42273L,42274L,42275L,42276L,42277L,42278L,42279L,42280L,
93253 42281L,42282L,42283L,42284L,42285L,42286L,42287L,42288L,42289L,42290L,
93254 42291L,42292L,42293L,42294L,42295L,42296L,42297L,42298L,42299L,42300L,
93255 42301L,42302L,42303L,42304L,42305L,42306L,42307L,42308L,42309L,42310L,
93256 42311L,42312L,42313L,42314L,42315L,42316L,42317L,42318L,42319L,42320L,
93257 42321L,42322L,42323L,42324L,42325L,42326L,42327L,42328L,42329L,42330L,
93258 42331L,42332L,42333L,42334L,42335L,42336L,42337L,42338L,42339L,42340L,
93259 42341L,42342L,42343L,42344L,42345L,42346L,42347L,42348L,42349L,42350L,
93260 42351L,42352L,42353L,42354L,42355L,42356L,42357L,42358L,42359L,42360L,
93261 42361L,42362L,42363L,42364L,42365L,42366L,42367L,42368L,42369L,42370L,
93262 42371L,42372L,42373L,42374L,42375L,42376L,42377L,42378L,42379L,42380L,
93263 42381L,42382L,42383L,42384L,42385L,42386L,42387L,42388L,42389L,42390L,
93264 42391L,42392L,42393L,42394L,42395L,42396L,42397L,42398L,42399L,42400L,
93265 42401L,42402L,42403L,42404L,42405L,42406L,42407L,42408L,42409L,42410L,
93266 42411L,42412L,42413L,42414L,42415L,42416L,42417L,42418L,42419L,42420L,
93267 42421L,42422L,42423L,42424L,42425L,42426L,42427L,42428L,42429L,42430L,
93268 42431L,42432L,42433L,42434L,42435L,42436L,42437L,42438L,42439L,42440L,
93269 42441L,42442L,42443L,42444L,42445L,42446L,42447L,42448L,42449L,42450L,
93270 42451L,42452L,42453L,42454L,42455L,42456L,42457L,42458L,42459L,42460L,
93271 42461L,42462L,42463L,42464L,42465L,42466L,42467L,42468L,42469L,42470L,
93272 42471L,42472L,42473L,42474L,42475L,42476L,42477L,42478L,42479L,42480L,
93273 42481L,42482L,42483L,42484L,42485L,42486L,42487L,42488L,42489L,42490L,
93274 42491L,42492L,42493L,42494L,42495L,42496L,42497L,42498L,42499L,42500L,
93275 42501L,42502L,42503L,42504L,42505L,42506L,42507L,42508L,42509L,42510L,
93276 42511L,42512L,42513L,42514L,42515L,42516L,42517L,42518L,42519L,42520L,
93277 42521L,42522L,42523L,42524L,42525L,42526L,42527L,42528L,42529L,42530L,
93278 42531L,42532L,42533L,42534L,42535L,42536L,42537L,42538L,42539L,42540L,
93279 42541L,42542L,42543L,42544L,42545L,42546L,42547L,42548L,42549L,42550L,
93280 42551L,42552L,42553L,42554L,42555L,42556L,42557L,42558L,42559L,42560L,
93281 42560L,42562L,42562L,42564L,42564L,42566L,42566L,42568L,42568L,42570L,
93282 42570L,42572L,42572L,42574L,42574L,42576L,42576L,42578L,42578L,42580L,
93283 42580L,42582L,42582L,42584L,42584L,42586L,42586L,42588L,42588L,42590L,
93284 42590L,42592L,42592L,42594L,42594L,42596L,42596L,42598L,42598L,42600L,
93285 42600L,42602L,42602L,42604L,42604L,42606L,42607L,42608L,42609L,42610L,
93286 42611L,42612L,42613L,42614L,42615L,42616L,42617L,42618L,42619L,42620L,
93287 42621L,42622L,42623L,42624L,42624L,42626L,42626L,42628L,42628L,42630L,
93288 42630L,42632L,42632L,42634L,42634L,42636L,42636L,42638L,42638L,42640L,
93289 42640L,42642L,42642L,42644L,42644L,42646L,42646L,42648L,42648L,42650L,
93290 42650L,42652L,42653L,42654L,42655L,42656L,42657L,42658L,42659L,42660L,
93291 42661L,42662L,42663L,42664L,42665L,42666L,42667L,42668L,42669L,42670L,
93292 42671L,42672L,42673L,42674L,42675L,42676L,42677L,42678L,42679L,42680L,
93293 42681L,42682L,42683L,42684L,42685L,42686L,42687L,42688L,42689L,42690L,
93294 42691L,42692L,42693L,42694L,42695L,42696L,42697L,42698L,42699L,42700L,
93295 42701L,42702L,42703L,42704L,42705L,42706L,42707L,42708L,42709L,42710L,
93296 42711L,42712L,42713L,42714L,42715L,42716L,42717L,42718L,42719L,42720L,
93297 42721L,42722L,42723L,42724L,42725L,42726L,42727L,42728L,42729L,42730L,
93298 42731L,42732L,42733L,42734L,42735L,42736L,42737L,42738L,42739L,42740L,
93299 42741L,42742L,42743L,42744L,42745L,42746L,42747L,42748L,42749L,42750L,
93300 42751L,42752L,42753L,42754L,42755L,42756L,42757L,42758L,42759L,42760L,
93301 42761L,42762L,42763L,42764L,42765L,42766L,42767L,42768L,42769L,42770L,
93302 42771L,42772L,42773L,42774L,42775L,42776L,42777L,42778L,42779L,42780L,
93303 42781L,42782L,42783L,42784L,42785L,42786L,42786L,42788L,42788L,42790L,
93304 42790L,42792L,42792L,42794L,42794L,42796L,42796L,42798L,42798L,42800L,
93305 42801L,42802L,42802L,42804L,42804L,42806L,42806L,42808L,42808L,42810L,
93306 42810L,42812L,42812L,42814L,42814L,42816L,42816L,42818L,42818L,42820L,
93307 42820L,42822L,42822L,42824L,42824L,42826L,42826L,42828L,42828L,42830L,
93308 42830L,42832L,42832L,42834L,42834L,42836L,42836L,42838L,42838L,42840L,
93309 42840L,42842L,42842L,42844L,42844L,42846L,42846L,42848L,42848L,42850L,
93310 42850L,42852L,42852L,42854L,42854L,42856L,42856L,42858L,42858L,42860L,
93311 42860L,42862L,42862L,42864L,42865L,42866L,42867L,42868L,42869L,42870L,
93312 42871L,42872L,42873L,42873L,42875L,42875L,42877L,42878L,42878L,42880L,
93313 42880L,42882L,42882L,42884L,42884L,42886L,42886L,42888L,42889L,42890L,
93314 42891L,42891L,42893L,42894L,42895L,42896L,42896L,42898L,42898L,42900L,
93315 42901L,42902L,42902L,42904L,42904L,42906L,42906L,42908L,42908L,42910L,
93316 42910L,42912L,42912L,42914L,42914L,42916L,42916L,42918L,42918L,42920L,
93317 42920L,42922L,42923L,42924L,42925L,42926L,42927L,42928L,42929L,42930L,
93318 42931L,42932L,42932L,42934L,42934L,42936L,42937L,42938L,42939L,42940L,
93319 42941L,42942L,42943L,42944L,42945L,42946L,42947L,42948L,42949L,42950L,
93320 42951L,42952L,42953L,42954L,42955L,42956L,42957L,42958L,42959L,42960L,
93321 42961L,42962L,42963L,42964L,42965L,42966L,42967L,42968L,42969L,42970L,
93322 42971L,42972L,42973L,42974L,42975L,42976L,42977L,42978L,42979L,42980L,
93323 42981L,42982L,42983L,42984L,42985L,42986L,42987L,42988L,42989L,42990L,
93324 42991L,42992L,42993L,42994L,42995L,42996L,42997L,42998L,42999L,43000L,
93325 43001L,43002L,43003L,43004L,43005L,43006L,43007L,43008L,43009L,43010L,
93326 43011L,43012L,43013L,43014L,43015L,43016L,43017L,43018L,43019L,43020L,
93327 43021L,43022L,43023L,43024L,43025L,43026L,43027L,43028L,43029L,43030L,
93328 43031L,43032L,43033L,43034L,43035L,43036L,43037L,43038L,43039L,43040L,
93329 43041L,43042L,43043L,43044L,43045L,43046L,43047L,43048L,43049L,43050L,
93330 43051L,43052L,43053L,43054L,43055L,43056L,43057L,43058L,43059L,43060L,
93331 43061L,43062L,43063L,43064L,43065L,43066L,43067L,43068L,43069L,43070L,
93332 43071L,43072L,43073L,43074L,43075L,43076L,43077L,43078L,43079L,43080L,
93333 43081L,43082L,43083L,43084L,43085L,43086L,43087L,43088L,43089L,43090L,
93334 43091L,43092L,43093L,43094L,43095L,43096L,43097L,43098L,43099L,43100L,
93335 43101L,43102L,43103L,43104L,43105L,43106L,43107L,43108L,43109L,43110L,
93336 43111L,43112L,43113L,43114L,43115L,43116L,43117L,43118L,43119L,43120L,
93337 43121L,43122L,43123L,43124L,43125L,43126L,43127L,43128L,43129L,43130L,
93338 43131L,43132L,43133L,43134L,43135L,43136L,43137L,43138L,43139L,43140L,
93339 43141L,43142L,43143L,43144L,43145L,43146L,43147L,43148L,43149L,43150L,
93340 43151L,43152L,43153L,43154L,43155L,43156L,43157L,43158L,43159L,43160L,
93341 43161L,43162L,43163L,43164L,43165L,43166L,43167L,43168L,43169L,43170L,
93342 43171L,43172L,43173L,43174L,43175L,43176L,43177L,43178L,43179L,43180L,
93343 43181L,43182L,43183L,43184L,43185L,43186L,43187L,43188L,43189L,43190L,
93344 43191L,43192L,43193L,43194L,43195L,43196L,43197L,43198L,43199L,43200L,
93345 43201L,43202L,43203L,43204L,43205L,43206L,43207L,43208L,43209L,43210L,
93346 43211L,43212L,43213L,43214L,43215L,43216L,43217L,43218L,43219L,43220L,
93347 43221L,43222L,43223L,43224L,43225L,43226L,43227L,43228L,43229L,43230L,
93348 43231L,43232L,43233L,43234L,43235L,43236L,43237L,43238L,43239L,43240L,
93349 43241L,43242L,43243L,43244L,43245L,43246L,43247L,43248L,43249L,43250L,
93350 43251L,43252L,43253L,43254L,43255L,43256L,43257L,43258L,43259L,43260L,
93351 43261L,43262L,43263L,43264L,43265L,43266L,43267L,43268L,43269L,43270L,
93352 43271L,43272L,43273L,43274L,43275L,43276L,43277L,43278L,43279L,43280L,
93353 43281L,43282L,43283L,43284L,43285L,43286L,43287L,43288L,43289L,43290L,
93354 43291L,43292L,43293L,43294L,43295L,43296L,43297L,43298L,43299L,43300L,
93355 43301L,43302L,43303L,43304L,43305L,43306L,43307L,43308L,43309L,43310L,
93356 43311L,43312L,43313L,43314L,43315L,43316L,43317L,43318L,43319L,43320L,
93357 43321L,43322L,43323L,43324L,43325L,43326L,43327L,43328L,43329L,43330L,
93358 43331L,43332L,43333L,43334L,43335L,43336L,43337L,43338L,43339L,43340L,
93359 43341L,43342L,43343L,43344L,43345L,43346L,43347L,43348L,43349L,43350L,
93360 43351L,43352L,43353L,43354L,43355L,43356L,43357L,43358L,43359L,43360L,
93361 43361L,43362L,43363L,43364L,43365L,43366L,43367L,43368L,43369L,43370L,
93362 43371L,43372L,43373L,43374L,43375L,43376L,43377L,43378L,43379L,43380L,
93363 43381L,43382L,43383L,43384L,43385L,43386L,43387L,43388L,43389L,43390L,
93364 43391L,43392L,43393L,43394L,43395L,43396L,43397L,43398L,43399L,43400L,
93365 43401L,43402L,43403L,43404L,43405L,43406L,43407L,43408L,43409L,43410L,
93366 43411L,43412L,43413L,43414L,43415L,43416L,43417L,43418L,43419L,43420L,
93367 43421L,43422L,43423L,43424L,43425L,43426L,43427L,43428L,43429L,43430L,
93368 43431L,43432L,43433L,43434L,43435L,43436L,43437L,43438L,43439L,43440L,
93369 43441L,43442L,43443L,43444L,43445L,43446L,43447L,43448L,43449L,43450L,
93370 43451L,43452L,43453L,43454L,43455L,43456L,43457L,43458L,43459L,43460L,
93371 43461L,43462L,43463L,43464L,43465L,43466L,43467L,43468L,43469L,43470L,
93372 43471L,43472L,43473L,43474L,43475L,43476L,43477L,43478L,43479L,43480L,
93373 43481L,43482L,43483L,43484L,43485L,43486L,43487L,43488L,43489L,43490L,
93374 43491L,43492L,43493L,43494L,43495L,43496L,43497L,43498L,43499L,43500L,
93375 43501L,43502L,43503L,43504L,43505L,43506L,43507L,43508L,43509L,43510L,
93376 43511L,43512L,43513L,43514L,43515L,43516L,43517L,43518L,43519L,43520L,
93377 43521L,43522L,43523L,43524L,43525L,43526L,43527L,43528L,43529L,43530L,
93378 43531L,43532L,43533L,43534L,43535L,43536L,43537L,43538L,43539L,43540L,
93379 43541L,43542L,43543L,43544L,43545L,43546L,43547L,43548L,43549L,43550L,
93380 43551L,43552L,43553L,43554L,43555L,43556L,43557L,43558L,43559L,43560L,
93381 43561L,43562L,43563L,43564L,43565L,43566L,43567L,43568L,43569L,43570L,
93382 43571L,43572L,43573L,43574L,43575L,43576L,43577L,43578L,43579L,43580L,
93383 43581L,43582L,43583L,43584L,43585L,43586L,43587L,43588L,43589L,43590L,
93384 43591L,43592L,43593L,43594L,43595L,43596L,43597L,43598L,43599L,43600L,
93385 43601L,43602L,43603L,43604L,43605L,43606L,43607L,43608L,43609L,43610L,
93386 43611L,43612L,43613L,43614L,43615L,43616L,43617L,43618L,43619L,43620L,
93387 43621L,43622L,43623L,43624L,43625L,43626L,43627L,43628L,43629L,43630L,
93388 43631L,43632L,43633L,43634L,43635L,43636L,43637L,43638L,43639L,43640L,
93389 43641L,43642L,43643L,43644L,43645L,43646L,43647L,43648L,43649L,43650L,
93390 43651L,43652L,43653L,43654L,43655L,43656L,43657L,43658L,43659L,43660L,
93391 43661L,43662L,43663L,43664L,43665L,43666L,43667L,43668L,43669L,43670L,
93392 43671L,43672L,43673L,43674L,43675L,43676L,43677L,43678L,43679L,43680L,
93393 43681L,43682L,43683L,43684L,43685L,43686L,43687L,43688L,43689L,43690L,
93394 43691L,43692L,43693L,43694L,43695L,43696L,43697L,43698L,43699L,43700L,
93395 43701L,43702L,43703L,43704L,43705L,43706L,43707L,43708L,43709L,43710L,
93396 43711L,43712L,43713L,43714L,43715L,43716L,43717L,43718L,43719L,43720L,
93397 43721L,43722L,43723L,43724L,43725L,43726L,43727L,43728L,43729L,43730L,
93398 43731L,43732L,43733L,43734L,43735L,43736L,43737L,43738L,43739L,43740L,
93399 43741L,43742L,43743L,43744L,43745L,43746L,43747L,43748L,43749L,43750L,
93400 43751L,43752L,43753L,43754L,43755L,43756L,43757L,43758L,43759L,43760L,
93401 43761L,43762L,43763L,43764L,43765L,43766L,43767L,43768L,43769L,43770L,
93402 43771L,43772L,43773L,43774L,43775L,43776L,43777L,43778L,43779L,43780L,
93403 43781L,43782L,43783L,43784L,43785L,43786L,43787L,43788L,43789L,43790L,
93404 43791L,43792L,43793L,43794L,43795L,43796L,43797L,43798L,43799L,43800L,
93405 43801L,43802L,43803L,43804L,43805L,43806L,43807L,43808L,43809L,43810L,
93406 43811L,43812L,43813L,43814L,43815L,43816L,43817L,43818L,43819L,43820L,
93407 43821L,43822L,43823L,43824L,43825L,43826L,43827L,43828L,43829L,43830L,
93408 43831L,43832L,43833L,43834L,43835L,43836L,43837L,43838L,43839L,43840L,
93409 43841L,43842L,43843L,43844L,43845L,43846L,43847L,43848L,43849L,43850L,
93410 43851L,43852L,43853L,43854L,43855L,43856L,43857L,43858L,42931L,43860L,
93411 43861L,43862L,43863L,43864L,43865L,43866L,43867L,43868L,43869L,43870L,
93412 43871L,43872L,43873L,43874L,43875L,43876L,43877L,43878L,43879L,43880L,
93413 43881L,43882L,43883L,43884L,43885L,43886L,43887L,5024,5025,5026,5027,5028,
93414 5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,5040,5041,5042,5043,
93415 5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,5054,5055,5056,5057,5058,
93416 5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,5070,5071,5072,5073,
93417 5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,5084,5085,5086,5087,5088,
93418 5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102,5103,
93419 43968L,43969L,43970L,43971L,43972L,43973L,43974L,43975L,43976L,43977L,
93420 43978L,43979L,43980L,43981L,43982L,43983L,43984L,43985L,43986L,43987L,
93421 43988L,43989L,43990L,43991L,43992L,43993L,43994L,43995L,43996L,43997L,
93422 43998L,43999L,44000L,44001L,44002L,44003L,44004L,44005L,44006L,44007L,
93423 44008L,44009L,44010L,44011L,44012L,44013L,44014L,44015L,44016L,44017L,
93424 44018L,44019L,44020L,44021L,44022L,44023L,44024L,44025L,44026L,44027L,
93425 44028L,44029L,44030L,44031L,44032L,44033L,44034L,44035L,44036L,44037L,
93426 44038L,44039L,44040L,44041L,44042L,44043L,44044L,44045L,44046L,44047L,
93427 44048L,44049L,44050L,44051L,44052L,44053L,44054L,44055L,44056L,44057L,
93428 44058L,44059L,44060L,44061L,44062L,44063L,44064L,44065L,44066L,44067L,
93429 44068L,44069L,44070L,44071L,44072L,44073L,44074L,44075L,44076L,44077L,
93430 44078L,44079L,44080L,44081L,44082L,44083L,44084L,44085L,44086L,44087L,
93431 44088L,44089L,44090L,44091L,44092L,44093L,44094L,44095L,44096L,44097L,
93432 44098L,44099L,44100L,44101L,44102L,44103L,44104L,44105L,44106L,44107L,
93433 44108L,44109L,44110L,44111L,44112L,44113L,44114L,44115L,44116L,44117L,
93434 44118L,44119L,44120L,44121L,44122L,44123L,44124L,44125L,44126L,44127L,
93435 44128L,44129L,44130L,44131L,44132L,44133L,44134L,44135L,44136L,44137L,
93436 44138L,44139L,44140L,44141L,44142L,44143L,44144L,44145L,44146L,44147L,
93437 44148L,44149L,44150L,44151L,44152L,44153L,44154L,44155L,44156L,44157L,
93438 44158L,44159L,44160L,44161L,44162L,44163L,44164L,44165L,44166L,44167L,
93439 44168L,44169L,44170L,44171L,44172L,44173L,44174L,44175L,44176L,44177L,
93440 44178L,44179L,44180L,44181L,44182L,44183L,44184L,44185L,44186L,44187L,
93441 44188L,44189L,44190L,44191L,44192L,44193L,44194L,44195L,44196L,44197L,
93442 44198L,44199L,44200L,44201L,44202L,44203L,44204L,44205L,44206L,44207L,
93443 44208L,44209L,44210L,44211L,44212L,44213L,44214L,44215L,44216L,44217L,
93444 44218L,44219L,44220L,44221L,44222L,44223L,44224L,44225L,44226L,44227L,
93445 44228L,44229L,44230L,44231L,44232L,44233L,44234L,44235L,44236L,44237L,
93446 44238L,44239L,44240L,44241L,44242L,44243L,44244L,44245L,44246L,44247L,
93447 44248L,44249L,44250L,44251L,44252L,44253L,44254L,44255L,44256L,44257L,
93448 44258L,44259L,44260L,44261L,44262L,44263L,44264L,44265L,44266L,44267L,
93449 44268L,44269L,44270L,44271L,44272L,44273L,44274L,44275L,44276L,44277L,
93450 44278L,44279L,44280L,44281L,44282L,44283L,44284L,44285L,44286L,44287L,
93451 44288L,44289L,44290L,44291L,44292L,44293L,44294L,44295L,44296L,44297L,
93452 44298L,44299L,44300L,44301L,44302L,44303L,44304L,44305L,44306L,44307L,
93453 44308L,44309L,44310L,44311L,44312L,44313L,44314L,44315L,44316L,44317L,
93454 44318L,44319L,44320L,44321L,44322L,44323L,44324L,44325L,44326L,44327L,
93455 44328L,44329L,44330L,44331L,44332L,44333L,44334L,44335L,44336L,44337L,
93456 44338L,44339L,44340L,44341L,44342L,44343L,44344L,44345L,44346L,44347L,
93457 44348L,44349L,44350L,44351L,44352L,44353L,44354L,44355L,44356L,44357L,
93458 44358L,44359L,44360L,44361L,44362L,44363L,44364L,44365L,44366L,44367L,
93459 44368L,44369L,44370L,44371L,44372L,44373L,44374L,44375L,44376L,44377L,
93460 44378L,44379L,44380L,44381L,44382L,44383L,44384L,44385L,44386L,44387L,
93461 44388L,44389L,44390L,44391L,44392L,44393L,44394L,44395L,44396L,44397L,
93462 44398L,44399L,44400L,44401L,44402L,44403L,44404L,44405L,44406L,44407L,
93463 44408L,44409L,44410L,44411L,44412L,44413L,44414L,44415L,44416L,44417L,
93464 44418L,44419L,44420L,44421L,44422L,44423L,44424L,44425L,44426L,44427L,
93465 44428L,44429L,44430L,44431L,44432L,44433L,44434L,44435L,44436L,44437L,
93466 44438L,44439L,44440L,44441L,44442L,44443L,44444L,44445L,44446L,44447L,
93467 44448L,44449L,44450L,44451L,44452L,44453L,44454L,44455L,44456L,44457L,
93468 44458L,44459L,44460L,44461L,44462L,44463L,44464L,44465L,44466L,44467L,
93469 44468L,44469L,44470L,44471L,44472L,44473L,44474L,44475L,44476L,44477L,
93470 44478L,44479L,44480L,44481L,44482L,44483L,44484L,44485L,44486L,44487L,
93471 44488L,44489L,44490L,44491L,44492L,44493L,44494L,44495L,44496L,44497L,
93472 44498L,44499L,44500L,44501L,44502L,44503L,44504L,44505L,44506L,44507L,
93473 44508L,44509L,44510L,44511L,44512L,44513L,44514L,44515L,44516L,44517L,
93474 44518L,44519L,44520L,44521L,44522L,44523L,44524L,44525L,44526L,44527L,
93475 44528L,44529L,44530L,44531L,44532L,44533L,44534L,44535L,44536L,44537L,
93476 44538L,44539L,44540L,44541L,44542L,44543L,44544L,44545L,44546L,44547L,
93477 44548L,44549L,44550L,44551L,44552L,44553L,44554L,44555L,44556L,44557L,
93478 44558L,44559L,44560L,44561L,44562L,44563L,44564L,44565L,44566L,44567L,
93479 44568L,44569L,44570L,44571L,44572L,44573L,44574L,44575L,44576L,44577L,
93480 44578L,44579L,44580L,44581L,44582L,44583L,44584L,44585L,44586L,44587L,
93481 44588L,44589L,44590L,44591L,44592L,44593L,44594L,44595L,44596L,44597L,
93482 44598L,44599L,44600L,44601L,44602L,44603L,44604L,44605L,44606L,44607L,
93483 44608L,44609L,44610L,44611L,44612L,44613L,44614L,44615L,44616L,44617L,
93484 44618L,44619L,44620L,44621L,44622L,44623L,44624L,44625L,44626L,44627L,
93485 44628L,44629L,44630L,44631L,44632L,44633L,44634L,44635L,44636L,44637L,
93486 44638L,44639L,44640L,44641L,44642L,44643L,44644L,44645L,44646L,44647L,
93487 44648L,44649L,44650L,44651L,44652L,44653L,44654L,44655L,44656L,44657L,
93488 44658L,44659L,44660L,44661L,44662L,44663L,44664L,44665L,44666L,44667L,
93489 44668L,44669L,44670L,44671L,44672L,44673L,44674L,44675L,44676L,44677L,
93490 44678L,44679L,44680L,44681L,44682L,44683L,44684L,44685L,44686L,44687L,
93491 44688L,44689L,44690L,44691L,44692L,44693L,44694L,44695L,44696L,44697L,
93492 44698L,44699L,44700L,44701L,44702L,44703L,44704L,44705L,44706L,44707L,
93493 44708L,44709L,44710L,44711L,44712L,44713L,44714L,44715L,44716L,44717L,
93494 44718L,44719L,44720L,44721L,44722L,44723L,44724L,44725L,44726L,44727L,
93495 44728L,44729L,44730L,44731L,44732L,44733L,44734L,44735L,44736L,44737L,
93496 44738L,44739L,44740L,44741L,44742L,44743L,44744L,44745L,44746L,44747L,
93497 44748L,44749L,44750L,44751L,44752L,44753L,44754L,44755L,44756L,44757L,
93498 44758L,44759L,44760L,44761L,44762L,44763L,44764L,44765L,44766L,44767L,
93499 44768L,44769L,44770L,44771L,44772L,44773L,44774L,44775L,44776L,44777L,
93500 44778L,44779L,44780L,44781L,44782L,44783L,44784L,44785L,44786L,44787L,
93501 44788L,44789L,44790L,44791L,44792L,44793L,44794L,44795L,44796L,44797L,
93502 44798L,44799L,44800L,44801L,44802L,44803L,44804L,44805L,44806L,44807L,
93503 44808L,44809L,44810L,44811L,44812L,44813L,44814L,44815L,44816L,44817L,
93504 44818L,44819L,44820L,44821L,44822L,44823L,44824L,44825L,44826L,44827L,
93505 44828L,44829L,44830L,44831L,44832L,44833L,44834L,44835L,44836L,44837L,
93506 44838L,44839L,44840L,44841L,44842L,44843L,44844L,44845L,44846L,44847L,
93507 44848L,44849L,44850L,44851L,44852L,44853L,44854L,44855L,44856L,44857L,
93508 44858L,44859L,44860L,44861L,44862L,44863L,44864L,44865L,44866L,44867L,
93509 44868L,44869L,44870L,44871L,44872L,44873L,44874L,44875L,44876L,44877L,
93510 44878L,44879L,44880L,44881L,44882L,44883L,44884L,44885L,44886L,44887L,
93511 44888L,44889L,44890L,44891L,44892L,44893L,44894L,44895L,44896L,44897L,
93512 44898L,44899L,44900L,44901L,44902L,44903L,44904L,44905L,44906L,44907L,
93513 44908L,44909L,44910L,44911L,44912L,44913L,44914L,44915L,44916L,44917L,
93514 44918L,44919L,44920L,44921L,44922L,44923L,44924L,44925L,44926L,44927L,
93515 44928L,44929L,44930L,44931L,44932L,44933L,44934L,44935L,44936L,44937L,
93516 44938L,44939L,44940L,44941L,44942L,44943L,44944L,44945L,44946L,44947L,
93517 44948L,44949L,44950L,44951L,44952L,44953L,44954L,44955L,44956L,44957L,
93518 44958L,44959L,44960L,44961L,44962L,44963L,44964L,44965L,44966L,44967L,
93519 44968L,44969L,44970L,44971L,44972L,44973L,44974L,44975L,44976L,44977L,
93520 44978L,44979L,44980L,44981L,44982L,44983L,44984L,44985L,44986L,44987L,
93521 44988L,44989L,44990L,44991L,44992L,44993L,44994L,44995L,44996L,44997L,
93522 44998L,44999L,45000L,45001L,45002L,45003L,45004L,45005L,45006L,45007L,
93523 45008L,45009L,45010L,45011L,45012L,45013L,45014L,45015L,45016L,45017L,
93524 45018L,45019L,45020L,45021L,45022L,45023L,45024L,45025L,45026L,45027L,
93525 45028L,45029L,45030L,45031L,45032L,45033L,45034L,45035L,45036L,45037L,
93526 45038L,45039L,45040L,45041L,45042L,45043L,45044L,45045L,45046L,45047L,
93527 45048L,45049L,45050L,45051L,45052L,45053L,45054L,45055L,45056L,45057L,
93528 45058L,45059L,45060L,45061L,45062L,45063L,45064L,45065L,45066L,45067L,
93529 45068L,45069L,45070L,45071L,45072L,45073L,45074L,45075L,45076L,45077L,
93530 45078L,45079L,45080L,45081L,45082L,45083L,45084L,45085L,45086L,45087L,
93531 45088L,45089L,45090L,45091L,45092L,45093L,45094L,45095L,45096L,45097L,
93532 45098L,45099L,45100L,45101L,45102L,45103L,45104L,45105L,45106L,45107L,
93533 45108L,45109L,45110L,45111L,45112L,45113L,45114L,45115L,45116L,45117L,
93534 45118L,45119L,45120L,45121L,45122L,45123L,45124L,45125L,45126L,45127L,
93535 45128L,45129L,45130L,45131L,45132L,45133L,45134L,45135L,45136L,45137L,
93536 45138L,45139L,45140L,45141L,45142L,45143L,45144L,45145L,45146L,45147L,
93537 45148L,45149L,45150L,45151L,45152L,45153L,45154L,45155L,45156L,45157L,
93538 45158L,45159L,45160L,45161L,45162L,45163L,45164L,45165L,45166L,45167L,
93539 45168L,45169L,45170L,45171L,45172L,45173L,45174L,45175L,45176L,45177L,
93540 45178L,45179L,45180L,45181L,45182L,45183L,45184L,45185L,45186L,45187L,
93541 45188L,45189L,45190L,45191L,45192L,45193L,45194L,45195L,45196L,45197L,
93542 45198L,45199L,45200L,45201L,45202L,45203L,45204L,45205L,45206L,45207L,
93543 45208L,45209L,45210L,45211L,45212L,45213L,45214L,45215L,45216L,45217L,
93544 45218L,45219L,45220L,45221L,45222L,45223L,45224L,45225L,45226L,45227L,
93545 45228L,45229L,45230L,45231L,45232L,45233L,45234L,45235L,45236L,45237L,
93546 45238L,45239L,45240L,45241L,45242L,45243L,45244L,45245L,45246L,45247L,
93547 45248L,45249L,45250L,45251L,45252L,45253L,45254L,45255L,45256L,45257L,
93548 45258L,45259L,45260L,45261L,45262L,45263L,45264L,45265L,45266L,45267L,
93549 45268L,45269L,45270L,45271L,45272L,45273L,45274L,45275L,45276L,45277L,
93550 45278L,45279L,45280L,45281L,45282L,45283L,45284L,45285L,45286L,45287L,
93551 45288L,45289L,45290L,45291L,45292L,45293L,45294L,45295L,45296L,45297L,
93552 45298L,45299L,45300L,45301L,45302L,45303L,45304L,45305L,45306L,45307L,
93553 45308L,45309L,45310L,45311L,45312L,45313L,45314L,45315L,45316L,45317L,
93554 45318L,45319L,45320L,45321L,45322L,45323L,45324L,45325L,45326L,45327L,
93555 45328L,45329L,45330L,45331L,45332L,45333L,45334L,45335L,45336L,45337L,
93556 45338L,45339L,45340L,45341L,45342L,45343L,45344L,45345L,45346L,45347L,
93557 45348L,45349L,45350L,45351L,45352L,45353L,45354L,45355L,45356L,45357L,
93558 45358L,45359L,45360L,45361L,45362L,45363L,45364L,45365L,45366L,45367L,
93559 45368L,45369L,45370L,45371L,45372L,45373L,45374L,45375L,45376L,45377L,
93560 45378L,45379L,45380L,45381L,45382L,45383L,45384L,45385L,45386L,45387L,
93561 45388L,45389L,45390L,45391L,45392L,45393L,45394L,45395L,45396L,45397L,
93562 45398L,45399L,45400L,45401L,45402L,45403L,45404L,45405L,45406L,45407L,
93563 45408L,45409L,45410L,45411L,45412L,45413L,45414L,45415L,45416L,45417L,
93564 45418L,45419L,45420L,45421L,45422L,45423L,45424L,45425L,45426L,45427L,
93565 45428L,45429L,45430L,45431L,45432L,45433L,45434L,45435L,45436L,45437L,
93566 45438L,45439L,45440L,45441L,45442L,45443L,45444L,45445L,45446L,45447L,
93567 45448L,45449L,45450L,45451L,45452L,45453L,45454L,45455L,45456L,45457L,
93568 45458L,45459L,45460L,45461L,45462L,45463L,45464L,45465L,45466L,45467L,
93569 45468L,45469L,45470L,45471L,45472L,45473L,45474L,45475L,45476L,45477L,
93570 45478L,45479L,45480L,45481L,45482L,45483L,45484L,45485L,45486L,45487L,
93571 45488L,45489L,45490L,45491L,45492L,45493L,45494L,45495L,45496L,45497L,
93572 45498L,45499L,45500L,45501L,45502L,45503L,45504L,45505L,45506L,45507L,
93573 45508L,45509L,45510L,45511L,45512L,45513L,45514L,45515L,45516L,45517L,
93574 45518L,45519L,45520L,45521L,45522L,45523L,45524L,45525L,45526L,45527L,
93575 45528L,45529L,45530L,45531L,45532L,45533L,45534L,45535L,45536L,45537L,
93576 45538L,45539L,45540L,45541L,45542L,45543L,45544L,45545L,45546L,45547L,
93577 45548L,45549L,45550L,45551L,45552L,45553L,45554L,45555L,45556L,45557L,
93578 45558L,45559L,45560L,45561L,45562L,45563L,45564L,45565L,45566L,45567L,
93579 45568L,45569L,45570L,45571L,45572L,45573L,45574L,45575L,45576L,45577L,
93580 45578L,45579L,45580L,45581L,45582L,45583L,45584L,45585L,45586L,45587L,
93581 45588L,45589L,45590L,45591L,45592L,45593L,45594L,45595L,45596L,45597L,
93582 45598L,45599L,45600L,45601L,45602L,45603L,45604L,45605L,45606L,45607L,
93583 45608L,45609L,45610L,45611L,45612L,45613L,45614L,45615L,45616L,45617L,
93584 45618L,45619L,45620L,45621L,45622L,45623L,45624L,45625L,45626L,45627L,
93585 45628L,45629L,45630L,45631L,45632L,45633L,45634L,45635L,45636L,45637L,
93586 45638L,45639L,45640L,45641L,45642L,45643L,45644L,45645L,45646L,45647L,
93587 45648L,45649L,45650L,45651L,45652L,45653L,45654L,45655L,45656L,45657L,
93588 45658L,45659L,45660L,45661L,45662L,45663L,45664L,45665L,45666L,45667L,
93589 45668L,45669L,45670L,45671L,45672L,45673L,45674L,45675L,45676L,45677L,
93590 45678L,45679L,45680L,45681L,45682L,45683L,45684L,45685L,45686L,45687L,
93591 45688L,45689L,45690L,45691L,45692L,45693L,45694L,45695L,45696L,45697L,
93592 45698L,45699L,45700L,45701L,45702L,45703L,45704L,45705L,45706L,45707L,
93593 45708L,45709L,45710L,45711L,45712L,45713L,45714L,45715L,45716L,45717L,
93594 45718L,45719L,45720L,45721L,45722L,45723L,45724L,45725L,45726L,45727L,
93595 45728L,45729L,45730L,45731L,45732L,45733L,45734L,45735L,45736L,45737L,
93596 45738L,45739L,45740L,45741L,45742L,45743L,45744L,45745L,45746L,45747L,
93597 45748L,45749L,45750L,45751L,45752L,45753L,45754L,45755L,45756L,45757L,
93598 45758L,45759L,45760L,45761L,45762L,45763L,45764L,45765L,45766L,45767L,
93599 45768L,45769L,45770L,45771L,45772L,45773L,45774L,45775L,45776L,45777L,
93600 45778L,45779L,45780L,45781L,45782L,45783L,45784L,45785L,45786L,45787L,
93601 45788L,45789L,45790L,45791L,45792L,45793L,45794L,45795L,45796L,45797L,
93602 45798L,45799L,45800L,45801L,45802L,45803L,45804L,45805L,45806L,45807L,
93603 45808L,45809L,45810L,45811L,45812L,45813L,45814L,45815L,45816L,45817L,
93604 45818L,45819L,45820L,45821L,45822L,45823L,45824L,45825L,45826L,45827L,
93605 45828L,45829L,45830L,45831L,45832L,45833L,45834L,45835L,45836L,45837L,
93606 45838L,45839L,45840L,45841L,45842L,45843L,45844L,45845L,45846L,45847L,
93607 45848L,45849L,45850L,45851L,45852L,45853L,45854L,45855L,45856L,45857L,
93608 45858L,45859L,45860L,45861L,45862L,45863L,45864L,45865L,45866L,45867L,
93609 45868L,45869L,45870L,45871L,45872L,45873L,45874L,45875L,45876L,45877L,
93610 45878L,45879L,45880L,45881L,45882L,45883L,45884L,45885L,45886L,45887L,
93611 45888L,45889L,45890L,45891L,45892L,45893L,45894L,45895L,45896L,45897L,
93612 45898L,45899L,45900L,45901L,45902L,45903L,45904L,45905L,45906L,45907L,
93613 45908L,45909L,45910L,45911L,45912L,45913L,45914L,45915L,45916L,45917L,
93614 45918L,45919L,45920L,45921L,45922L,45923L,45924L,45925L,45926L,45927L,
93615 45928L,45929L,45930L,45931L,45932L,45933L,45934L,45935L,45936L,45937L,
93616 45938L,45939L,45940L,45941L,45942L,45943L,45944L,45945L,45946L,45947L,
93617 45948L,45949L,45950L,45951L,45952L,45953L,45954L,45955L,45956L,45957L,
93618 45958L,45959L,45960L,45961L,45962L,45963L,45964L,45965L,45966L,45967L,
93619 45968L,45969L,45970L,45971L,45972L,45973L,45974L,45975L,45976L,45977L,
93620 45978L,45979L,45980L,45981L,45982L,45983L,45984L,45985L,45986L,45987L,
93621 45988L,45989L,45990L,45991L,45992L,45993L,45994L,45995L,45996L,45997L,
93622 45998L,45999L,46000L,46001L,46002L,46003L,46004L,46005L,46006L,46007L,
93623 46008L,46009L,46010L,46011L,46012L,46013L,46014L,46015L,46016L,46017L,
93624 46018L,46019L,46020L,46021L,46022L,46023L,46024L,46025L,46026L,46027L,
93625 46028L,46029L,46030L,46031L,46032L,46033L,46034L,46035L,46036L,46037L,
93626 46038L,46039L,46040L,46041L,46042L,46043L,46044L,46045L,46046L,46047L,
93627 46048L,46049L,46050L,46051L,46052L,46053L,46054L,46055L,46056L,46057L,
93628 46058L,46059L,46060L,46061L,46062L,46063L,46064L,46065L,46066L,46067L,
93629 46068L,46069L,46070L,46071L,46072L,46073L,46074L,46075L,46076L,46077L,
93630 46078L,46079L,46080L,46081L,46082L,46083L,46084L,46085L,46086L,46087L,
93631 46088L,46089L,46090L,46091L,46092L,46093L,46094L,46095L,46096L,46097L,
93632 46098L,46099L,46100L,46101L,46102L,46103L,46104L,46105L,46106L,46107L,
93633 46108L,46109L,46110L,46111L,46112L,46113L,46114L,46115L,46116L,46117L,
93634 46118L,46119L,46120L,46121L,46122L,46123L,46124L,46125L,46126L,46127L,
93635 46128L,46129L,46130L,46131L,46132L,46133L,46134L,46135L,46136L,46137L,
93636 46138L,46139L,46140L,46141L,46142L,46143L,46144L,46145L,46146L,46147L,
93637 46148L,46149L,46150L,46151L,46152L,46153L,46154L,46155L,46156L,46157L,
93638 46158L,46159L,46160L,46161L,46162L,46163L,46164L,46165L,46166L,46167L,
93639 46168L,46169L,46170L,46171L,46172L,46173L,46174L,46175L,46176L,46177L,
93640 46178L,46179L,46180L,46181L,46182L,46183L,46184L,46185L,46186L,46187L,
93641 46188L,46189L,46190L,46191L,46192L,46193L,46194L,46195L,46196L,46197L,
93642 46198L,46199L,46200L,46201L,46202L,46203L,46204L,46205L,46206L,46207L,
93643 46208L,46209L,46210L,46211L,46212L,46213L,46214L,46215L,46216L,46217L,
93644 46218L,46219L,46220L,46221L,46222L,46223L,46224L,46225L,46226L,46227L,
93645 46228L,46229L,46230L,46231L,46232L,46233L,46234L,46235L,46236L,46237L,
93646 46238L,46239L,46240L,46241L,46242L,46243L,46244L,46245L,46246L,46247L,
93647 46248L,46249L,46250L,46251L,46252L,46253L,46254L,46255L,46256L,46257L,
93648 46258L,46259L,46260L,46261L,46262L,46263L,46264L,46265L,46266L,46267L,
93649 46268L,46269L,46270L,46271L,46272L,46273L,46274L,46275L,46276L,46277L,
93650 46278L,46279L,46280L,46281L,46282L,46283L,46284L,46285L,46286L,46287L,
93651 46288L,46289L,46290L,46291L,46292L,46293L,46294L,46295L,46296L,46297L,
93652 46298L,46299L,46300L,46301L,46302L,46303L,46304L,46305L,46306L,46307L,
93653 46308L,46309L,46310L,46311L,46312L,46313L,46314L,46315L,46316L,46317L,
93654 46318L,46319L,46320L,46321L,46322L,46323L,46324L,46325L,46326L,46327L,
93655 46328L,46329L,46330L,46331L,46332L,46333L,46334L,46335L,46336L,46337L,
93656 46338L,46339L,46340L,46341L,46342L,46343L,46344L,46345L,46346L,46347L,
93657 46348L,46349L,46350L,46351L,46352L,46353L,46354L,46355L,46356L,46357L,
93658 46358L,46359L,46360L,46361L,46362L,46363L,46364L,46365L,46366L,46367L,
93659 46368L,46369L,46370L,46371L,46372L,46373L,46374L,46375L,46376L,46377L,
93660 46378L,46379L,46380L,46381L,46382L,46383L,46384L,46385L,46386L,46387L,
93661 46388L,46389L,46390L,46391L,46392L,46393L,46394L,46395L,46396L,46397L,
93662 46398L,46399L,46400L,46401L,46402L,46403L,46404L,46405L,46406L,46407L,
93663 46408L,46409L,46410L,46411L,46412L,46413L,46414L,46415L,46416L,46417L,
93664 46418L,46419L,46420L,46421L,46422L,46423L,46424L,46425L,46426L,46427L,
93665 46428L,46429L,46430L,46431L,46432L,46433L,46434L,46435L,46436L,46437L,
93666 46438L,46439L,46440L,46441L,46442L,46443L,46444L,46445L,46446L,46447L,
93667 46448L,46449L,46450L,46451L,46452L,46453L,46454L,46455L,46456L,46457L,
93668 46458L,46459L,46460L,46461L,46462L,46463L,46464L,46465L,46466L,46467L,
93669 46468L,46469L,46470L,46471L,46472L,46473L,46474L,46475L,46476L,46477L,
93670 46478L,46479L,46480L,46481L,46482L,46483L,46484L,46485L,46486L,46487L,
93671 46488L,46489L,46490L,46491L,46492L,46493L,46494L,46495L,46496L,46497L,
93672 46498L,46499L,46500L,46501L,46502L,46503L,46504L,46505L,46506L,46507L,
93673 46508L,46509L,46510L,46511L,46512L,46513L,46514L,46515L,46516L,46517L,
93674 46518L,46519L,46520L,46521L,46522L,46523L,46524L,46525L,46526L,46527L,
93675 46528L,46529L,46530L,46531L,46532L,46533L,46534L,46535L,46536L,46537L,
93676 46538L,46539L,46540L,46541L,46542L,46543L,46544L,46545L,46546L,46547L,
93677 46548L,46549L,46550L,46551L,46552L,46553L,46554L,46555L,46556L,46557L,
93678 46558L,46559L,46560L,46561L,46562L,46563L,46564L,46565L,46566L,46567L,
93679 46568L,46569L,46570L,46571L,46572L,46573L,46574L,46575L,46576L,46577L,
93680 46578L,46579L,46580L,46581L,46582L,46583L,46584L,46585L,46586L,46587L,
93681 46588L,46589L,46590L,46591L,46592L,46593L,46594L,46595L,46596L,46597L,
93682 46598L,46599L,46600L,46601L,46602L,46603L,46604L,46605L,46606L,46607L,
93683 46608L,46609L,46610L,46611L,46612L,46613L,46614L,46615L,46616L,46617L,
93684 46618L,46619L,46620L,46621L,46622L,46623L,46624L,46625L,46626L,46627L,
93685 46628L,46629L,46630L,46631L,46632L,46633L,46634L,46635L,46636L,46637L,
93686 46638L,46639L,46640L,46641L,46642L,46643L,46644L,46645L,46646L,46647L,
93687 46648L,46649L,46650L,46651L,46652L,46653L,46654L,46655L,46656L,46657L,
93688 46658L,46659L,46660L,46661L,46662L,46663L,46664L,46665L,46666L,46667L,
93689 46668L,46669L,46670L,46671L,46672L,46673L,46674L,46675L,46676L,46677L,
93690 46678L,46679L,46680L,46681L,46682L,46683L,46684L,46685L,46686L,46687L,
93691 46688L,46689L,46690L,46691L,46692L,46693L,46694L,46695L,46696L,46697L,
93692 46698L,46699L,46700L,46701L,46702L,46703L,46704L,46705L,46706L,46707L,
93693 46708L,46709L,46710L,46711L,46712L,46713L,46714L,46715L,46716L,46717L,
93694 46718L,46719L,46720L,46721L,46722L,46723L,46724L,46725L,46726L,46727L,
93695 46728L,46729L,46730L,46731L,46732L,46733L,46734L,46735L,46736L,46737L,
93696 46738L,46739L,46740L,46741L,46742L,46743L,46744L,46745L,46746L,46747L,
93697 46748L,46749L,46750L,46751L,46752L,46753L,46754L,46755L,46756L,46757L,
93698 46758L,46759L,46760L,46761L,46762L,46763L,46764L,46765L,46766L,46767L,
93699 46768L,46769L,46770L,46771L,46772L,46773L,46774L,46775L,46776L,46777L,
93700 46778L,46779L,46780L,46781L,46782L,46783L,46784L,46785L,46786L,46787L,
93701 46788L,46789L,46790L,46791L,46792L,46793L,46794L,46795L,46796L,46797L,
93702 46798L,46799L,46800L,46801L,46802L,46803L,46804L,46805L,46806L,46807L,
93703 46808L,46809L,46810L,46811L,46812L,46813L,46814L,46815L,46816L,46817L,
93704 46818L,46819L,46820L,46821L,46822L,46823L,46824L,46825L,46826L,46827L,
93705 46828L,46829L,46830L,46831L,46832L,46833L,46834L,46835L,46836L,46837L,
93706 46838L,46839L,46840L,46841L,46842L,46843L,46844L,46845L,46846L,46847L,
93707 46848L,46849L,46850L,46851L,46852L,46853L,46854L,46855L,46856L,46857L,
93708 46858L,46859L,46860L,46861L,46862L,46863L,46864L,46865L,46866L,46867L,
93709 46868L,46869L,46870L,46871L,46872L,46873L,46874L,46875L,46876L,46877L,
93710 46878L,46879L,46880L,46881L,46882L,46883L,46884L,46885L,46886L,46887L,
93711 46888L,46889L,46890L,46891L,46892L,46893L,46894L,46895L,46896L,46897L,
93712 46898L,46899L,46900L,46901L,46902L,46903L,46904L,46905L,46906L,46907L,
93713 46908L,46909L,46910L,46911L,46912L,46913L,46914L,46915L,46916L,46917L,
93714 46918L,46919L,46920L,46921L,46922L,46923L,46924L,46925L,46926L,46927L,
93715 46928L,46929L,46930L,46931L,46932L,46933L,46934L,46935L,46936L,46937L,
93716 46938L,46939L,46940L,46941L,46942L,46943L,46944L,46945L,46946L,46947L,
93717 46948L,46949L,46950L,46951L,46952L,46953L,46954L,46955L,46956L,46957L,
93718 46958L,46959L,46960L,46961L,46962L,46963L,46964L,46965L,46966L,46967L,
93719 46968L,46969L,46970L,46971L,46972L,46973L,46974L,46975L,46976L,46977L,
93720 46978L,46979L,46980L,46981L,46982L,46983L,46984L,46985L,46986L,46987L,
93721 46988L,46989L,46990L,46991L,46992L,46993L,46994L,46995L,46996L,46997L,
93722 46998L,46999L,47000L,47001L,47002L,47003L,47004L,47005L,47006L,47007L,
93723 47008L,47009L,47010L,47011L,47012L,47013L,47014L,47015L,47016L,47017L,
93724 47018L,47019L,47020L,47021L,47022L,47023L,47024L,47025L,47026L,47027L,
93725 47028L,47029L,47030L,47031L,47032L,47033L,47034L,47035L,47036L,47037L,
93726 47038L,47039L,47040L,47041L,47042L,47043L,47044L,47045L,47046L,47047L,
93727 47048L,47049L,47050L,47051L,47052L,47053L,47054L,47055L,47056L,47057L,
93728 47058L,47059L,47060L,47061L,47062L,47063L,47064L,47065L,47066L,47067L,
93729 47068L,47069L,47070L,47071L,47072L,47073L,47074L,47075L,47076L,47077L,
93730 47078L,47079L,47080L,47081L,47082L,47083L,47084L,47085L,47086L,47087L,
93731 47088L,47089L,47090L,47091L,47092L,47093L,47094L,47095L,47096L,47097L,
93732 47098L,47099L,47100L,47101L,47102L,47103L,47104L,47105L,47106L,47107L,
93733 47108L,47109L,47110L,47111L,47112L,47113L,47114L,47115L,47116L,47117L,
93734 47118L,47119L,47120L,47121L,47122L,47123L,47124L,47125L,47126L,47127L,
93735 47128L,47129L,47130L,47131L,47132L,47133L,47134L,47135L,47136L,47137L,
93736 47138L,47139L,47140L,47141L,47142L,47143L,47144L,47145L,47146L,47147L,
93737 47148L,47149L,47150L,47151L,47152L,47153L,47154L,47155L,47156L,47157L,
93738 47158L,47159L,47160L,47161L,47162L,47163L,47164L,47165L,47166L,47167L,
93739 47168L,47169L,47170L,47171L,47172L,47173L,47174L,47175L,47176L,47177L,
93740 47178L,47179L,47180L,47181L,47182L,47183L,47184L,47185L,47186L,47187L,
93741 47188L,47189L,47190L,47191L,47192L,47193L,47194L,47195L,47196L,47197L,
93742 47198L,47199L,47200L,47201L,47202L,47203L,47204L,47205L,47206L,47207L,
93743 47208L,47209L,47210L,47211L,47212L,47213L,47214L,47215L,47216L,47217L,
93744 47218L,47219L,47220L,47221L,47222L,47223L,47224L,47225L,47226L,47227L,
93745 47228L,47229L,47230L,47231L,47232L,47233L,47234L,47235L,47236L,47237L,
93746 47238L,47239L,47240L,47241L,47242L,47243L,47244L,47245L,47246L,47247L,
93747 47248L,47249L,47250L,47251L,47252L,47253L,47254L,47255L,47256L,47257L,
93748 47258L,47259L,47260L,47261L,47262L,47263L,47264L,47265L,47266L,47267L,
93749 47268L,47269L,47270L,47271L,47272L,47273L,47274L,47275L,47276L,47277L,
93750 47278L,47279L,47280L,47281L,47282L,47283L,47284L,47285L,47286L,47287L,
93751 47288L,47289L,47290L,47291L,47292L,47293L,47294L,47295L,47296L,47297L,
93752 47298L,47299L,47300L,47301L,47302L,47303L,47304L,47305L,47306L,47307L,
93753 47308L,47309L,47310L,47311L,47312L,47313L,47314L,47315L,47316L,47317L,
93754 47318L,47319L,47320L,47321L,47322L,47323L,47324L,47325L,47326L,47327L,
93755 47328L,47329L,47330L,47331L,47332L,47333L,47334L,47335L,47336L,47337L,
93756 47338L,47339L,47340L,47341L,47342L,47343L,47344L,47345L,47346L,47347L,
93757 47348L,47349L,47350L,47351L,47352L,47353L,47354L,47355L,47356L,47357L,
93758 47358L,47359L,47360L,47361L,47362L,47363L,47364L,47365L,47366L,47367L,
93759 47368L,47369L,47370L,47371L,47372L,47373L,47374L,47375L,47376L,47377L,
93760 47378L,47379L,47380L,47381L,47382L,47383L,47384L,47385L,47386L,47387L,
93761 47388L,47389L,47390L,47391L,47392L,47393L,47394L,47395L,47396L,47397L,
93762 47398L,47399L,47400L,47401L,47402L,47403L,47404L,47405L,47406L,47407L,
93763 47408L,47409L,47410L,47411L,47412L,47413L,47414L,47415L,47416L,47417L,
93764 47418L,47419L,47420L,47421L,47422L,47423L,47424L,47425L,47426L,47427L,
93765 47428L,47429L,47430L,47431L,47432L,47433L,47434L,47435L,47436L,47437L,
93766 47438L,47439L,47440L,47441L,47442L,47443L,47444L,47445L,47446L,47447L,
93767 47448L,47449L,47450L,47451L,47452L,47453L,47454L,47455L,47456L,47457L,
93768 47458L,47459L,47460L,47461L,47462L,47463L,47464L,47465L,47466L,47467L,
93769 47468L,47469L,47470L,47471L,47472L,47473L,47474L,47475L,47476L,47477L,
93770 47478L,47479L,47480L,47481L,47482L,47483L,47484L,47485L,47486L,47487L,
93771 47488L,47489L,47490L,47491L,47492L,47493L,47494L,47495L,47496L,47497L,
93772 47498L,47499L,47500L,47501L,47502L,47503L,47504L,47505L,47506L,47507L,
93773 47508L,47509L,47510L,47511L,47512L,47513L,47514L,47515L,47516L,47517L,
93774 47518L,47519L,47520L,47521L,47522L,47523L,47524L,47525L,47526L,47527L,
93775 47528L,47529L,47530L,47531L,47532L,47533L,47534L,47535L,47536L,47537L,
93776 47538L,47539L,47540L,47541L,47542L,47543L,47544L,47545L,47546L,47547L,
93777 47548L,47549L,47550L,47551L,47552L,47553L,47554L,47555L,47556L,47557L,
93778 47558L,47559L,47560L,47561L,47562L,47563L,47564L,47565L,47566L,47567L,
93779 47568L,47569L,47570L,47571L,47572L,47573L,47574L,47575L,47576L,47577L,
93780 47578L,47579L,47580L,47581L,47582L,47583L,47584L,47585L,47586L,47587L,
93781 47588L,47589L,47590L,47591L,47592L,47593L,47594L,47595L,47596L,47597L,
93782 47598L,47599L,47600L,47601L,47602L,47603L,47604L,47605L,47606L,47607L,
93783 47608L,47609L,47610L,47611L,47612L,47613L,47614L,47615L,47616L,47617L,
93784 47618L,47619L,47620L,47621L,47622L,47623L,47624L,47625L,47626L,47627L,
93785 47628L,47629L,47630L,47631L,47632L,47633L,47634L,47635L,47636L,47637L,
93786 47638L,47639L,47640L,47641L,47642L,47643L,47644L,47645L,47646L,47647L,
93787 47648L,47649L,47650L,47651L,47652L,47653L,47654L,47655L,47656L,47657L,
93788 47658L,47659L,47660L,47661L,47662L,47663L,47664L,47665L,47666L,47667L,
93789 47668L,47669L,47670L,47671L,47672L,47673L,47674L,47675L,47676L,47677L,
93790 47678L,47679L,47680L,47681L,47682L,47683L,47684L,47685L,47686L,47687L,
93791 47688L,47689L,47690L,47691L,47692L,47693L,47694L,47695L,47696L,47697L,
93792 47698L,47699L,47700L,47701L,47702L,47703L,47704L,47705L,47706L,47707L,
93793 47708L,47709L,47710L,47711L,47712L,47713L,47714L,47715L,47716L,47717L,
93794 47718L,47719L,47720L,47721L,47722L,47723L,47724L,47725L,47726L,47727L,
93795 47728L,47729L,47730L,47731L,47732L,47733L,47734L,47735L,47736L,47737L,
93796 47738L,47739L,47740L,47741L,47742L,47743L,47744L,47745L,47746L,47747L,
93797 47748L,47749L,47750L,47751L,47752L,47753L,47754L,47755L,47756L,47757L,
93798 47758L,47759L,47760L,47761L,47762L,47763L,47764L,47765L,47766L,47767L,
93799 47768L,47769L,47770L,47771L,47772L,47773L,47774L,47775L,47776L,47777L,
93800 47778L,47779L,47780L,47781L,47782L,47783L,47784L,47785L,47786L,47787L,
93801 47788L,47789L,47790L,47791L,47792L,47793L,47794L,47795L,47796L,47797L,
93802 47798L,47799L,47800L,47801L,47802L,47803L,47804L,47805L,47806L,47807L,
93803 47808L,47809L,47810L,47811L,47812L,47813L,47814L,47815L,47816L,47817L,
93804 47818L,47819L,47820L,47821L,47822L,47823L,47824L,47825L,47826L,47827L,
93805 47828L,47829L,47830L,47831L,47832L,47833L,47834L,47835L,47836L,47837L,
93806 47838L,47839L,47840L,47841L,47842L,47843L,47844L,47845L,47846L,47847L,
93807 47848L,47849L,47850L,47851L,47852L,47853L,47854L,47855L,47856L,47857L,
93808 47858L,47859L,47860L,47861L,47862L,47863L,47864L,47865L,47866L,47867L,
93809 47868L,47869L,47870L,47871L,47872L,47873L,47874L,47875L,47876L,47877L,
93810 47878L,47879L,47880L,47881L,47882L,47883L,47884L,47885L,47886L,47887L,
93811 47888L,47889L,47890L,47891L,47892L,47893L,47894L,47895L,47896L,47897L,
93812 47898L,47899L,47900L,47901L,47902L,47903L,47904L,47905L,47906L,47907L,
93813 47908L,47909L,47910L,47911L,47912L,47913L,47914L,47915L,47916L,47917L,
93814 47918L,47919L,47920L,47921L,47922L,47923L,47924L,47925L,47926L,47927L,
93815 47928L,47929L,47930L,47931L,47932L,47933L,47934L,47935L,47936L,47937L,
93816 47938L,47939L,47940L,47941L,47942L,47943L,47944L,47945L,47946L,47947L,
93817 47948L,47949L,47950L,47951L,47952L,47953L,47954L,47955L,47956L,47957L,
93818 47958L,47959L,47960L,47961L,47962L,47963L,47964L,47965L,47966L,47967L,
93819 47968L,47969L,47970L,47971L,47972L,47973L,47974L,47975L,47976L,47977L,
93820 47978L,47979L,47980L,47981L,47982L,47983L,47984L,47985L,47986L,47987L,
93821 47988L,47989L,47990L,47991L,47992L,47993L,47994L,47995L,47996L,47997L,
93822 47998L,47999L,48000L,48001L,48002L,48003L,48004L,48005L,48006L,48007L,
93823 48008L,48009L,48010L,48011L,48012L,48013L,48014L,48015L,48016L,48017L,
93824 48018L,48019L,48020L,48021L,48022L,48023L,48024L,48025L,48026L,48027L,
93825 48028L,48029L,48030L,48031L,48032L,48033L,48034L,48035L,48036L,48037L,
93826 48038L,48039L,48040L,48041L,48042L,48043L,48044L,48045L,48046L,48047L,
93827 48048L,48049L,48050L,48051L,48052L,48053L,48054L,48055L,48056L,48057L,
93828 48058L,48059L,48060L,48061L,48062L,48063L,48064L,48065L,48066L,48067L,
93829 48068L,48069L,48070L,48071L,48072L,48073L,48074L,48075L,48076L,48077L,
93830 48078L,48079L,48080L,48081L,48082L,48083L,48084L,48085L,48086L,48087L,
93831 48088L,48089L,48090L,48091L,48092L,48093L,48094L,48095L,48096L,48097L,
93832 48098L,48099L,48100L,48101L,48102L,48103L,48104L,48105L,48106L,48107L,
93833 48108L,48109L,48110L,48111L,48112L,48113L,48114L,48115L,48116L,48117L,
93834 48118L,48119L,48120L,48121L,48122L,48123L,48124L,48125L,48126L,48127L,
93835 48128L,48129L,48130L,48131L,48132L,48133L,48134L,48135L,48136L,48137L,
93836 48138L,48139L,48140L,48141L,48142L,48143L,48144L,48145L,48146L,48147L,
93837 48148L,48149L,48150L,48151L,48152L,48153L,48154L,48155L,48156L,48157L,
93838 48158L,48159L,48160L,48161L,48162L,48163L,48164L,48165L,48166L,48167L,
93839 48168L,48169L,48170L,48171L,48172L,48173L,48174L,48175L,48176L,48177L,
93840 48178L,48179L,48180L,48181L,48182L,48183L,48184L,48185L,48186L,48187L,
93841 48188L,48189L,48190L,48191L,48192L,48193L,48194L,48195L,48196L,48197L,
93842 48198L,48199L,48200L,48201L,48202L,48203L,48204L,48205L,48206L,48207L,
93843 48208L,48209L,48210L,48211L,48212L,48213L,48214L,48215L,48216L,48217L,
93844 48218L,48219L,48220L,48221L,48222L,48223L,48224L,48225L,48226L,48227L,
93845 48228L,48229L,48230L,48231L,48232L,48233L,48234L,48235L,48236L,48237L,
93846 48238L,48239L,48240L,48241L,48242L,48243L,48244L,48245L,48246L,48247L,
93847 48248L,48249L,48250L,48251L,48252L,48253L,48254L,48255L,48256L,48257L,
93848 48258L,48259L,48260L,48261L,48262L,48263L,48264L,48265L,48266L,48267L,
93849 48268L,48269L,48270L,48271L,48272L,48273L,48274L,48275L,48276L,48277L,
93850 48278L,48279L,48280L,48281L,48282L,48283L,48284L,48285L,48286L,48287L,
93851 48288L,48289L,48290L,48291L,48292L,48293L,48294L,48295L,48296L,48297L,
93852 48298L,48299L,48300L,48301L,48302L,48303L,48304L,48305L,48306L,48307L,
93853 48308L,48309L,48310L,48311L,48312L,48313L,48314L,48315L,48316L,48317L,
93854 48318L,48319L,48320L,48321L,48322L,48323L,48324L,48325L,48326L,48327L,
93855 48328L,48329L,48330L,48331L,48332L,48333L,48334L,48335L,48336L,48337L,
93856 48338L,48339L,48340L,48341L,48342L,48343L,48344L,48345L,48346L,48347L,
93857 48348L,48349L,48350L,48351L,48352L,48353L,48354L,48355L,48356L,48357L,
93858 48358L,48359L,48360L,48361L,48362L,48363L,48364L,48365L,48366L,48367L,
93859 48368L,48369L,48370L,48371L,48372L,48373L,48374L,48375L,48376L,48377L,
93860 48378L,48379L,48380L,48381L,48382L,48383L,48384L,48385L,48386L,48387L,
93861 48388L,48389L,48390L,48391L,48392L,48393L,48394L,48395L,48396L,48397L,
93862 48398L,48399L,48400L,48401L,48402L,48403L,48404L,48405L,48406L,48407L,
93863 48408L,48409L,48410L,48411L,48412L,48413L,48414L,48415L,48416L,48417L,
93864 48418L,48419L,48420L,48421L,48422L,48423L,48424L,48425L,48426L,48427L,
93865 48428L,48429L,48430L,48431L,48432L,48433L,48434L,48435L,48436L,48437L,
93866 48438L,48439L,48440L,48441L,48442L,48443L,48444L,48445L,48446L,48447L,
93867 48448L,48449L,48450L,48451L,48452L,48453L,48454L,48455L,48456L,48457L,
93868 48458L,48459L,48460L,48461L,48462L,48463L,48464L,48465L,48466L,48467L,
93869 48468L,48469L,48470L,48471L,48472L,48473L,48474L,48475L,48476L,48477L,
93870 48478L,48479L,48480L,48481L,48482L,48483L,48484L,48485L,48486L,48487L,
93871 48488L,48489L,48490L,48491L,48492L,48493L,48494L,48495L,48496L,48497L,
93872 48498L,48499L,48500L,48501L,48502L,48503L,48504L,48505L,48506L,48507L,
93873 48508L,48509L,48510L,48511L,48512L,48513L,48514L,48515L,48516L,48517L,
93874 48518L,48519L,48520L,48521L,48522L,48523L,48524L,48525L,48526L,48527L,
93875 48528L,48529L,48530L,48531L,48532L,48533L,48534L,48535L,48536L,48537L,
93876 48538L,48539L,48540L,48541L,48542L,48543L,48544L,48545L,48546L,48547L,
93877 48548L,48549L,48550L,48551L,48552L,48553L,48554L,48555L,48556L,48557L,
93878 48558L,48559L,48560L,48561L,48562L,48563L,48564L,48565L,48566L,48567L,
93879 48568L,48569L,48570L,48571L,48572L,48573L,48574L,48575L,48576L,48577L,
93880 48578L,48579L,48580L,48581L,48582L,48583L,48584L,48585L,48586L,48587L,
93881 48588L,48589L,48590L,48591L,48592L,48593L,48594L,48595L,48596L,48597L,
93882 48598L,48599L,48600L,48601L,48602L,48603L,48604L,48605L,48606L,48607L,
93883 48608L,48609L,48610L,48611L,48612L,48613L,48614L,48615L,48616L,48617L,
93884 48618L,48619L,48620L,48621L,48622L,48623L,48624L,48625L,48626L,48627L,
93885 48628L,48629L,48630L,48631L,48632L,48633L,48634L,48635L,48636L,48637L,
93886 48638L,48639L,48640L,48641L,48642L,48643L,48644L,48645L,48646L,48647L,
93887 48648L,48649L,48650L,48651L,48652L,48653L,48654L,48655L,48656L,48657L,
93888 48658L,48659L,48660L,48661L,48662L,48663L,48664L,48665L,48666L,48667L,
93889 48668L,48669L,48670L,48671L,48672L,48673L,48674L,48675L,48676L,48677L,
93890 48678L,48679L,48680L,48681L,48682L,48683L,48684L,48685L,48686L,48687L,
93891 48688L,48689L,48690L,48691L,48692L,48693L,48694L,48695L,48696L,48697L,
93892 48698L,48699L,48700L,48701L,48702L,48703L,48704L,48705L,48706L,48707L,
93893 48708L,48709L,48710L,48711L,48712L,48713L,48714L,48715L,48716L,48717L,
93894 48718L,48719L,48720L,48721L,48722L,48723L,48724L,48725L,48726L,48727L,
93895 48728L,48729L,48730L,48731L,48732L,48733L,48734L,48735L,48736L,48737L,
93896 48738L,48739L,48740L,48741L,48742L,48743L,48744L,48745L,48746L,48747L,
93897 48748L,48749L,48750L,48751L,48752L,48753L,48754L,48755L,48756L,48757L,
93898 48758L,48759L,48760L,48761L,48762L,48763L,48764L,48765L,48766L,48767L,
93899 48768L,48769L,48770L,48771L,48772L,48773L,48774L,48775L,48776L,48777L,
93900 48778L,48779L,48780L,48781L,48782L,48783L,48784L,48785L,48786L,48787L,
93901 48788L,48789L,48790L,48791L,48792L,48793L,48794L,48795L,48796L,48797L,
93902 48798L,48799L,48800L,48801L,48802L,48803L,48804L,48805L,48806L,48807L,
93903 48808L,48809L,48810L,48811L,48812L,48813L,48814L,48815L,48816L,48817L,
93904 48818L,48819L,48820L,48821L,48822L,48823L,48824L,48825L,48826L,48827L,
93905 48828L,48829L,48830L,48831L,48832L,48833L,48834L,48835L,48836L,48837L,
93906 48838L,48839L,48840L,48841L,48842L,48843L,48844L,48845L,48846L,48847L,
93907 48848L,48849L,48850L,48851L,48852L,48853L,48854L,48855L,48856L,48857L,
93908 48858L,48859L,48860L,48861L,48862L,48863L,48864L,48865L,48866L,48867L,
93909 48868L,48869L,48870L,48871L,48872L,48873L,48874L,48875L,48876L,48877L,
93910 48878L,48879L,48880L,48881L,48882L,48883L,48884L,48885L,48886L,48887L,
93911 48888L,48889L,48890L,48891L,48892L,48893L,48894L,48895L,48896L,48897L,
93912 48898L,48899L,48900L,48901L,48902L,48903L,48904L,48905L,48906L,48907L,
93913 48908L,48909L,48910L,48911L,48912L,48913L,48914L,48915L,48916L,48917L,
93914 48918L,48919L,48920L,48921L,48922L,48923L,48924L,48925L,48926L,48927L,
93915 48928L,48929L,48930L,48931L,48932L,48933L,48934L,48935L,48936L,48937L,
93916 48938L,48939L,48940L,48941L,48942L,48943L,48944L,48945L,48946L,48947L,
93917 48948L,48949L,48950L,48951L,48952L,48953L,48954L,48955L,48956L,48957L,
93918 48958L,48959L,48960L,48961L,48962L,48963L,48964L,48965L,48966L,48967L,
93919 48968L,48969L,48970L,48971L,48972L,48973L,48974L,48975L,48976L,48977L,
93920 48978L,48979L,48980L,48981L,48982L,48983L,48984L,48985L,48986L,48987L,
93921 48988L,48989L,48990L,48991L,48992L,48993L,48994L,48995L,48996L,48997L,
93922 48998L,48999L,49000L,49001L,49002L,49003L,49004L,49005L,49006L,49007L,
93923 49008L,49009L,49010L,49011L,49012L,49013L,49014L,49015L,49016L,49017L,
93924 49018L,49019L,49020L,49021L,49022L,49023L,49024L,49025L,49026L,49027L,
93925 49028L,49029L,49030L,49031L,49032L,49033L,49034L,49035L,49036L,49037L,
93926 49038L,49039L,49040L,49041L,49042L,49043L,49044L,49045L,49046L,49047L,
93927 49048L,49049L,49050L,49051L,49052L,49053L,49054L,49055L,49056L,49057L,
93928 49058L,49059L,49060L,49061L,49062L,49063L,49064L,49065L,49066L,49067L,
93929 49068L,49069L,49070L,49071L,49072L,49073L,49074L,49075L,49076L,49077L,
93930 49078L,49079L,49080L,49081L,49082L,49083L,49084L,49085L,49086L,49087L,
93931 49088L,49089L,49090L,49091L,49092L,49093L,49094L,49095L,49096L,49097L,
93932 49098L,49099L,49100L,49101L,49102L,49103L,49104L,49105L,49106L,49107L,
93933 49108L,49109L,49110L,49111L,49112L,49113L,49114L,49115L,49116L,49117L,
93934 49118L,49119L,49120L,49121L,49122L,49123L,49124L,49125L,49126L,49127L,
93935 49128L,49129L,49130L,49131L,49132L,49133L,49134L,49135L,49136L,49137L,
93936 49138L,49139L,49140L,49141L,49142L,49143L,49144L,49145L,49146L,49147L,
93937 49148L,49149L,49150L,49151L,49152L,49153L,49154L,49155L,49156L,49157L,
93938 49158L,49159L,49160L,49161L,49162L,49163L,49164L,49165L,49166L,49167L,
93939 49168L,49169L,49170L,49171L,49172L,49173L,49174L,49175L,49176L,49177L,
93940 49178L,49179L,49180L,49181L,49182L,49183L,49184L,49185L,49186L,49187L,
93941 49188L,49189L,49190L,49191L,49192L,49193L,49194L,49195L,49196L,49197L,
93942 49198L,49199L,49200L,49201L,49202L,49203L,49204L,49205L,49206L,49207L,
93943 49208L,49209L,49210L,49211L,49212L,49213L,49214L,49215L,49216L,49217L,
93944 49218L,49219L,49220L,49221L,49222L,49223L,49224L,49225L,49226L,49227L,
93945 49228L,49229L,49230L,49231L,49232L,49233L,49234L,49235L,49236L,49237L,
93946 49238L,49239L,49240L,49241L,49242L,49243L,49244L,49245L,49246L,49247L,
93947 49248L,49249L,49250L,49251L,49252L,49253L,49254L,49255L,49256L,49257L,
93948 49258L,49259L,49260L,49261L,49262L,49263L,49264L,49265L,49266L,49267L,
93949 49268L,49269L,49270L,49271L,49272L,49273L,49274L,49275L,49276L,49277L,
93950 49278L,49279L,49280L,49281L,49282L,49283L,49284L,49285L,49286L,49287L,
93951 49288L,49289L,49290L,49291L,49292L,49293L,49294L,49295L,49296L,49297L,
93952 49298L,49299L,49300L,49301L,49302L,49303L,49304L,49305L,49306L,49307L,
93953 49308L,49309L,49310L,49311L,49312L,49313L,49314L,49315L,49316L,49317L,
93954 49318L,49319L,49320L,49321L,49322L,49323L,49324L,49325L,49326L,49327L,
93955 49328L,49329L,49330L,49331L,49332L,49333L,49334L,49335L,49336L,49337L,
93956 49338L,49339L,49340L,49341L,49342L,49343L,49344L,49345L,49346L,49347L,
93957 49348L,49349L,49350L,49351L,49352L,49353L,49354L,49355L,49356L,49357L,
93958 49358L,49359L,49360L,49361L,49362L,49363L,49364L,49365L,49366L,49367L,
93959 49368L,49369L,49370L,49371L,49372L,49373L,49374L,49375L,49376L,49377L,
93960 49378L,49379L,49380L,49381L,49382L,49383L,49384L,49385L,49386L,49387L,
93961 49388L,49389L,49390L,49391L,49392L,49393L,49394L,49395L,49396L,49397L,
93962 49398L,49399L,49400L,49401L,49402L,49403L,49404L,49405L,49406L,49407L,
93963 49408L,49409L,49410L,49411L,49412L,49413L,49414L,49415L,49416L,49417L,
93964 49418L,49419L,49420L,49421L,49422L,49423L,49424L,49425L,49426L,49427L,
93965 49428L,49429L,49430L,49431L,49432L,49433L,49434L,49435L,49436L,49437L,
93966 49438L,49439L,49440L,49441L,49442L,49443L,49444L,49445L,49446L,49447L,
93967 49448L,49449L,49450L,49451L,49452L,49453L,49454L,49455L,49456L,49457L,
93968 49458L,49459L,49460L,49461L,49462L,49463L,49464L,49465L,49466L,49467L,
93969 49468L,49469L,49470L,49471L,49472L,49473L,49474L,49475L,49476L,49477L,
93970 49478L,49479L,49480L,49481L,49482L,49483L,49484L,49485L,49486L,49487L,
93971 49488L,49489L,49490L,49491L,49492L,49493L,49494L,49495L,49496L,49497L,
93972 49498L,49499L,49500L,49501L,49502L,49503L,49504L,49505L,49506L,49507L,
93973 49508L,49509L,49510L,49511L,49512L,49513L,49514L,49515L,49516L,49517L,
93974 49518L,49519L,49520L,49521L,49522L,49523L,49524L,49525L,49526L,49527L,
93975 49528L,49529L,49530L,49531L,49532L,49533L,49534L,49535L,49536L,49537L,
93976 49538L,49539L,49540L,49541L,49542L,49543L,49544L,49545L,49546L,49547L,
93977 49548L,49549L,49550L,49551L,49552L,49553L,49554L,49555L,49556L,49557L,
93978 49558L,49559L,49560L,49561L,49562L,49563L,49564L,49565L,49566L,49567L,
93979 49568L,49569L,49570L,49571L,49572L,49573L,49574L,49575L,49576L,49577L,
93980 49578L,49579L,49580L,49581L,49582L,49583L,49584L,49585L,49586L,49587L,
93981 49588L,49589L,49590L,49591L,49592L,49593L,49594L,49595L,49596L,49597L,
93982 49598L,49599L,49600L,49601L,49602L,49603L,49604L,49605L,49606L,49607L,
93983 49608L,49609L,49610L,49611L,49612L,49613L,49614L,49615L,49616L,49617L,
93984 49618L,49619L,49620L,49621L,49622L,49623L,49624L,49625L,49626L,49627L,
93985 49628L,49629L,49630L,49631L,49632L,49633L,49634L,49635L,49636L,49637L,
93986 49638L,49639L,49640L,49641L,49642L,49643L,49644L,49645L,49646L,49647L,
93987 49648L,49649L,49650L,49651L,49652L,49653L,49654L,49655L,49656L,49657L,
93988 49658L,49659L,49660L,49661L,49662L,49663L,49664L,49665L,49666L,49667L,
93989 49668L,49669L,49670L,49671L,49672L,49673L,49674L,49675L,49676L,49677L,
93990 49678L,49679L,49680L,49681L,49682L,49683L,49684L,49685L,49686L,49687L,
93991 49688L,49689L,49690L,49691L,49692L,49693L,49694L,49695L,49696L,49697L,
93992 49698L,49699L,49700L,49701L,49702L,49703L,49704L,49705L,49706L,49707L,
93993 49708L,49709L,49710L,49711L,49712L,49713L,49714L,49715L,49716L,49717L,
93994 49718L,49719L,49720L,49721L,49722L,49723L,49724L,49725L,49726L,49727L,
93995 49728L,49729L,49730L,49731L,49732L,49733L,49734L,49735L,49736L,49737L,
93996 49738L,49739L,49740L,49741L,49742L,49743L,49744L,49745L,49746L,49747L,
93997 49748L,49749L,49750L,49751L,49752L,49753L,49754L,49755L,49756L,49757L,
93998 49758L,49759L,49760L,49761L,49762L,49763L,49764L,49765L,49766L,49767L,
93999 49768L,49769L,49770L,49771L,49772L,49773L,49774L,49775L,49776L,49777L,
94000 49778L,49779L,49780L,49781L,49782L,49783L,49784L,49785L,49786L,49787L,
94001 49788L,49789L,49790L,49791L,49792L,49793L,49794L,49795L,49796L,49797L,
94002 49798L,49799L,49800L,49801L,49802L,49803L,49804L,49805L,49806L,49807L,
94003 49808L,49809L,49810L,49811L,49812L,49813L,49814L,49815L,49816L,49817L,
94004 49818L,49819L,49820L,49821L,49822L,49823L,49824L,49825L,49826L,49827L,
94005 49828L,49829L,49830L,49831L,49832L,49833L,49834L,49835L,49836L,49837L,
94006 49838L,49839L,49840L,49841L,49842L,49843L,49844L,49845L,49846L,49847L,
94007 49848L,49849L,49850L,49851L,49852L,49853L,49854L,49855L,49856L,49857L,
94008 49858L,49859L,49860L,49861L,49862L,49863L,49864L,49865L,49866L,49867L,
94009 49868L,49869L,49870L,49871L,49872L,49873L,49874L,49875L,49876L,49877L,
94010 49878L,49879L,49880L,49881L,49882L,49883L,49884L,49885L,49886L,49887L,
94011 49888L,49889L,49890L,49891L,49892L,49893L,49894L,49895L,49896L,49897L,
94012 49898L,49899L,49900L,49901L,49902L,49903L,49904L,49905L,49906L,49907L,
94013 49908L,49909L,49910L,49911L,49912L,49913L,49914L,49915L,49916L,49917L,
94014 49918L,49919L,49920L,49921L,49922L,49923L,49924L,49925L,49926L,49927L,
94015 49928L,49929L,49930L,49931L,49932L,49933L,49934L,49935L,49936L,49937L,
94016 49938L,49939L,49940L,49941L,49942L,49943L,49944L,49945L,49946L,49947L,
94017 49948L,49949L,49950L,49951L,49952L,49953L,49954L,49955L,49956L,49957L,
94018 49958L,49959L,49960L,49961L,49962L,49963L,49964L,49965L,49966L,49967L,
94019 49968L,49969L,49970L,49971L,49972L,49973L,49974L,49975L,49976L,49977L,
94020 49978L,49979L,49980L,49981L,49982L,49983L,49984L,49985L,49986L,49987L,
94021 49988L,49989L,49990L,49991L,49992L,49993L,49994L,49995L,49996L,49997L,
94022 49998L,49999L,50000L,50001L,50002L,50003L,50004L,50005L,50006L,50007L,
94023 50008L,50009L,50010L,50011L,50012L,50013L,50014L,50015L,50016L,50017L,
94024 50018L,50019L,50020L,50021L,50022L,50023L,50024L,50025L,50026L,50027L,
94025 50028L,50029L,50030L,50031L,50032L,50033L,50034L,50035L,50036L,50037L,
94026 50038L,50039L,50040L,50041L,50042L,50043L,50044L,50045L,50046L,50047L,
94027 50048L,50049L,50050L,50051L,50052L,50053L,50054L,50055L,50056L,50057L,
94028 50058L,50059L,50060L,50061L,50062L,50063L,50064L,50065L,50066L,50067L,
94029 50068L,50069L,50070L,50071L,50072L,50073L,50074L,50075L,50076L,50077L,
94030 50078L,50079L,50080L,50081L,50082L,50083L,50084L,50085L,50086L,50087L,
94031 50088L,50089L,50090L,50091L,50092L,50093L,50094L,50095L,50096L,50097L,
94032 50098L,50099L,50100L,50101L,50102L,50103L,50104L,50105L,50106L,50107L,
94033 50108L,50109L,50110L,50111L,50112L,50113L,50114L,50115L,50116L,50117L,
94034 50118L,50119L,50120L,50121L,50122L,50123L,50124L,50125L,50126L,50127L,
94035 50128L,50129L,50130L,50131L,50132L,50133L,50134L,50135L,50136L,50137L,
94036 50138L,50139L,50140L,50141L,50142L,50143L,50144L,50145L,50146L,50147L,
94037 50148L,50149L,50150L,50151L,50152L,50153L,50154L,50155L,50156L,50157L,
94038 50158L,50159L,50160L,50161L,50162L,50163L,50164L,50165L,50166L,50167L,
94039 50168L,50169L,50170L,50171L,50172L,50173L,50174L,50175L,50176L,50177L,
94040 50178L,50179L,50180L,50181L,50182L,50183L,50184L,50185L,50186L,50187L,
94041 50188L,50189L,50190L,50191L,50192L,50193L,50194L,50195L,50196L,50197L,
94042 50198L,50199L,50200L,50201L,50202L,50203L,50204L,50205L,50206L,50207L,
94043 50208L,50209L,50210L,50211L,50212L,50213L,50214L,50215L,50216L,50217L,
94044 50218L,50219L,50220L,50221L,50222L,50223L,50224L,50225L,50226L,50227L,
94045 50228L,50229L,50230L,50231L,50232L,50233L,50234L,50235L,50236L,50237L,
94046 50238L,50239L,50240L,50241L,50242L,50243L,50244L,50245L,50246L,50247L,
94047 50248L,50249L,50250L,50251L,50252L,50253L,50254L,50255L,50256L,50257L,
94048 50258L,50259L,50260L,50261L,50262L,50263L,50264L,50265L,50266L,50267L,
94049 50268L,50269L,50270L,50271L,50272L,50273L,50274L,50275L,50276L,50277L,
94050 50278L,50279L,50280L,50281L,50282L,50283L,50284L,50285L,50286L,50287L,
94051 50288L,50289L,50290L,50291L,50292L,50293L,50294L,50295L,50296L,50297L,
94052 50298L,50299L,50300L,50301L,50302L,50303L,50304L,50305L,50306L,50307L,
94053 50308L,50309L,50310L,50311L,50312L,50313L,50314L,50315L,50316L,50317L,
94054 50318L,50319L,50320L,50321L,50322L,50323L,50324L,50325L,50326L,50327L,
94055 50328L,50329L,50330L,50331L,50332L,50333L,50334L,50335L,50336L,50337L,
94056 50338L,50339L,50340L,50341L,50342L,50343L,50344L,50345L,50346L,50347L,
94057 50348L,50349L,50350L,50351L,50352L,50353L,50354L,50355L,50356L,50357L,
94058 50358L,50359L,50360L,50361L,50362L,50363L,50364L,50365L,50366L,50367L,
94059 50368L,50369L,50370L,50371L,50372L,50373L,50374L,50375L,50376L,50377L,
94060 50378L,50379L,50380L,50381L,50382L,50383L,50384L,50385L,50386L,50387L,
94061 50388L,50389L,50390L,50391L,50392L,50393L,50394L,50395L,50396L,50397L,
94062 50398L,50399L,50400L,50401L,50402L,50403L,50404L,50405L,50406L,50407L,
94063 50408L,50409L,50410L,50411L,50412L,50413L,50414L,50415L,50416L,50417L,
94064 50418L,50419L,50420L,50421L,50422L,50423L,50424L,50425L,50426L,50427L,
94065 50428L,50429L,50430L,50431L,50432L,50433L,50434L,50435L,50436L,50437L,
94066 50438L,50439L,50440L,50441L,50442L,50443L,50444L,50445L,50446L,50447L,
94067 50448L,50449L,50450L,50451L,50452L,50453L,50454L,50455L,50456L,50457L,
94068 50458L,50459L,50460L,50461L,50462L,50463L,50464L,50465L,50466L,50467L,
94069 50468L,50469L,50470L,50471L,50472L,50473L,50474L,50475L,50476L,50477L,
94070 50478L,50479L,50480L,50481L,50482L,50483L,50484L,50485L,50486L,50487L,
94071 50488L,50489L,50490L,50491L,50492L,50493L,50494L,50495L,50496L,50497L,
94072 50498L,50499L,50500L,50501L,50502L,50503L,50504L,50505L,50506L,50507L,
94073 50508L,50509L,50510L,50511L,50512L,50513L,50514L,50515L,50516L,50517L,
94074 50518L,50519L,50520L,50521L,50522L,50523L,50524L,50525L,50526L,50527L,
94075 50528L,50529L,50530L,50531L,50532L,50533L,50534L,50535L,50536L,50537L,
94076 50538L,50539L,50540L,50541L,50542L,50543L,50544L,50545L,50546L,50547L,
94077 50548L,50549L,50550L,50551L,50552L,50553L,50554L,50555L,50556L,50557L,
94078 50558L,50559L,50560L,50561L,50562L,50563L,50564L,50565L,50566L,50567L,
94079 50568L,50569L,50570L,50571L,50572L,50573L,50574L,50575L,50576L,50577L,
94080 50578L,50579L,50580L,50581L,50582L,50583L,50584L,50585L,50586L,50587L,
94081 50588L,50589L,50590L,50591L,50592L,50593L,50594L,50595L,50596L,50597L,
94082 50598L,50599L,50600L,50601L,50602L,50603L,50604L,50605L,50606L,50607L,
94083 50608L,50609L,50610L,50611L,50612L,50613L,50614L,50615L,50616L,50617L,
94084 50618L,50619L,50620L,50621L,50622L,50623L,50624L,50625L,50626L,50627L,
94085 50628L,50629L,50630L,50631L,50632L,50633L,50634L,50635L,50636L,50637L,
94086 50638L,50639L,50640L,50641L,50642L,50643L,50644L,50645L,50646L,50647L,
94087 50648L,50649L,50650L,50651L,50652L,50653L,50654L,50655L,50656L,50657L,
94088 50658L,50659L,50660L,50661L,50662L,50663L,50664L,50665L,50666L,50667L,
94089 50668L,50669L,50670L,50671L,50672L,50673L,50674L,50675L,50676L,50677L,
94090 50678L,50679L,50680L,50681L,50682L,50683L,50684L,50685L,50686L,50687L,
94091 50688L,50689L,50690L,50691L,50692L,50693L,50694L,50695L,50696L,50697L,
94092 50698L,50699L,50700L,50701L,50702L,50703L,50704L,50705L,50706L,50707L,
94093 50708L,50709L,50710L,50711L,50712L,50713L,50714L,50715L,50716L,50717L,
94094 50718L,50719L,50720L,50721L,50722L,50723L,50724L,50725L,50726L,50727L,
94095 50728L,50729L,50730L,50731L,50732L,50733L,50734L,50735L,50736L,50737L,
94096 50738L,50739L,50740L,50741L,50742L,50743L,50744L,50745L,50746L,50747L,
94097 50748L,50749L,50750L,50751L,50752L,50753L,50754L,50755L,50756L,50757L,
94098 50758L,50759L,50760L,50761L,50762L,50763L,50764L,50765L,50766L,50767L,
94099 50768L,50769L,50770L,50771L,50772L,50773L,50774L,50775L,50776L,50777L,
94100 50778L,50779L,50780L,50781L,50782L,50783L,50784L,50785L,50786L,50787L,
94101 50788L,50789L,50790L,50791L,50792L,50793L,50794L,50795L,50796L,50797L,
94102 50798L,50799L,50800L,50801L,50802L,50803L,50804L,50805L,50806L,50807L,
94103 50808L,50809L,50810L,50811L,50812L,50813L,50814L,50815L,50816L,50817L,
94104 50818L,50819L,50820L,50821L,50822L,50823L,50824L,50825L,50826L,50827L,
94105 50828L,50829L,50830L,50831L,50832L,50833L,50834L,50835L,50836L,50837L,
94106 50838L,50839L,50840L,50841L,50842L,50843L,50844L,50845L,50846L,50847L,
94107 50848L,50849L,50850L,50851L,50852L,50853L,50854L,50855L,50856L,50857L,
94108 50858L,50859L,50860L,50861L,50862L,50863L,50864L,50865L,50866L,50867L,
94109 50868L,50869L,50870L,50871L,50872L,50873L,50874L,50875L,50876L,50877L,
94110 50878L,50879L,50880L,50881L,50882L,50883L,50884L,50885L,50886L,50887L,
94111 50888L,50889L,50890L,50891L,50892L,50893L,50894L,50895L,50896L,50897L,
94112 50898L,50899L,50900L,50901L,50902L,50903L,50904L,50905L,50906L,50907L,
94113 50908L,50909L,50910L,50911L,50912L,50913L,50914L,50915L,50916L,50917L,
94114 50918L,50919L,50920L,50921L,50922L,50923L,50924L,50925L,50926L,50927L,
94115 50928L,50929L,50930L,50931L,50932L,50933L,50934L,50935L,50936L,50937L,
94116 50938L,50939L,50940L,50941L,50942L,50943L,50944L,50945L,50946L,50947L,
94117 50948L,50949L,50950L,50951L,50952L,50953L,50954L,50955L,50956L,50957L,
94118 50958L,50959L,50960L,50961L,50962L,50963L,50964L,50965L,50966L,50967L,
94119 50968L,50969L,50970L,50971L,50972L,50973L,50974L,50975L,50976L,50977L,
94120 50978L,50979L,50980L,50981L,50982L,50983L,50984L,50985L,50986L,50987L,
94121 50988L,50989L,50990L,50991L,50992L,50993L,50994L,50995L,50996L,50997L,
94122 50998L,50999L,51000L,51001L,51002L,51003L,51004L,51005L,51006L,51007L,
94123 51008L,51009L,51010L,51011L,51012L,51013L,51014L,51015L,51016L,51017L,
94124 51018L,51019L,51020L,51021L,51022L,51023L,51024L,51025L,51026L,51027L,
94125 51028L,51029L,51030L,51031L,51032L,51033L,51034L,51035L,51036L,51037L,
94126 51038L,51039L,51040L,51041L,51042L,51043L,51044L,51045L,51046L,51047L,
94127 51048L,51049L,51050L,51051L,51052L,51053L,51054L,51055L,51056L,51057L,
94128 51058L,51059L,51060L,51061L,51062L,51063L,51064L,51065L,51066L,51067L,
94129 51068L,51069L,51070L,51071L,51072L,51073L,51074L,51075L,51076L,51077L,
94130 51078L,51079L,51080L,51081L,51082L,51083L,51084L,51085L,51086L,51087L,
94131 51088L,51089L,51090L,51091L,51092L,51093L,51094L,51095L,51096L,51097L,
94132 51098L,51099L,51100L,51101L,51102L,51103L,51104L,51105L,51106L,51107L,
94133 51108L,51109L,51110L,51111L,51112L,51113L,51114L,51115L,51116L,51117L,
94134 51118L,51119L,51120L,51121L,51122L,51123L,51124L,51125L,51126L,51127L,
94135 51128L,51129L,51130L,51131L,51132L,51133L,51134L,51135L,51136L,51137L,
94136 51138L,51139L,51140L,51141L,51142L,51143L,51144L,51145L,51146L,51147L,
94137 51148L,51149L,51150L,51151L,51152L,51153L,51154L,51155L,51156L,51157L,
94138 51158L,51159L,51160L,51161L,51162L,51163L,51164L,51165L,51166L,51167L,
94139 51168L,51169L,51170L,51171L,51172L,51173L,51174L,51175L,51176L,51177L,
94140 51178L,51179L,51180L,51181L,51182L,51183L,51184L,51185L,51186L,51187L,
94141 51188L,51189L,51190L,51191L,51192L,51193L,51194L,51195L,51196L,51197L,
94142 51198L,51199L,51200L,51201L,51202L,51203L,51204L,51205L,51206L,51207L,
94143 51208L,51209L,51210L,51211L,51212L,51213L,51214L,51215L,51216L,51217L,
94144 51218L,51219L,51220L,51221L,51222L,51223L,51224L,51225L,51226L,51227L,
94145 51228L,51229L,51230L,51231L,51232L,51233L,51234L,51235L,51236L,51237L,
94146 51238L,51239L,51240L,51241L,51242L,51243L,51244L,51245L,51246L,51247L,
94147 51248L,51249L,51250L,51251L,51252L,51253L,51254L,51255L,51256L,51257L,
94148 51258L,51259L,51260L,51261L,51262L,51263L,51264L,51265L,51266L,51267L,
94149 51268L,51269L,51270L,51271L,51272L,51273L,51274L,51275L,51276L,51277L,
94150 51278L,51279L,51280L,51281L,51282L,51283L,51284L,51285L,51286L,51287L,
94151 51288L,51289L,51290L,51291L,51292L,51293L,51294L,51295L,51296L,51297L,
94152 51298L,51299L,51300L,51301L,51302L,51303L,51304L,51305L,51306L,51307L,
94153 51308L,51309L,51310L,51311L,51312L,51313L,51314L,51315L,51316L,51317L,
94154 51318L,51319L,51320L,51321L,51322L,51323L,51324L,51325L,51326L,51327L,
94155 51328L,51329L,51330L,51331L,51332L,51333L,51334L,51335L,51336L,51337L,
94156 51338L,51339L,51340L,51341L,51342L,51343L,51344L,51345L,51346L,51347L,
94157 51348L,51349L,51350L,51351L,51352L,51353L,51354L,51355L,51356L,51357L,
94158 51358L,51359L,51360L,51361L,51362L,51363L,51364L,51365L,51366L,51367L,
94159 51368L,51369L,51370L,51371L,51372L,51373L,51374L,51375L,51376L,51377L,
94160 51378L,51379L,51380L,51381L,51382L,51383L,51384L,51385L,51386L,51387L,
94161 51388L,51389L,51390L,51391L,51392L,51393L,51394L,51395L,51396L,51397L,
94162 51398L,51399L,51400L,51401L,51402L,51403L,51404L,51405L,51406L,51407L,
94163 51408L,51409L,51410L,51411L,51412L,51413L,51414L,51415L,51416L,51417L,
94164 51418L,51419L,51420L,51421L,51422L,51423L,51424L,51425L,51426L,51427L,
94165 51428L,51429L,51430L,51431L,51432L,51433L,51434L,51435L,51436L,51437L,
94166 51438L,51439L,51440L,51441L,51442L,51443L,51444L,51445L,51446L,51447L,
94167 51448L,51449L,51450L,51451L,51452L,51453L,51454L,51455L,51456L,51457L,
94168 51458L,51459L,51460L,51461L,51462L,51463L,51464L,51465L,51466L,51467L,
94169 51468L,51469L,51470L,51471L,51472L,51473L,51474L,51475L,51476L,51477L,
94170 51478L,51479L,51480L,51481L,51482L,51483L,51484L,51485L,51486L,51487L,
94171 51488L,51489L,51490L,51491L,51492L,51493L,51494L,51495L,51496L,51497L,
94172 51498L,51499L,51500L,51501L,51502L,51503L,51504L,51505L,51506L,51507L,
94173 51508L,51509L,51510L,51511L,51512L,51513L,51514L,51515L,51516L,51517L,
94174 51518L,51519L,51520L,51521L,51522L,51523L,51524L,51525L,51526L,51527L,
94175 51528L,51529L,51530L,51531L,51532L,51533L,51534L,51535L,51536L,51537L,
94176 51538L,51539L,51540L,51541L,51542L,51543L,51544L,51545L,51546L,51547L,
94177 51548L,51549L,51550L,51551L,51552L,51553L,51554L,51555L,51556L,51557L,
94178 51558L,51559L,51560L,51561L,51562L,51563L,51564L,51565L,51566L,51567L,
94179 51568L,51569L,51570L,51571L,51572L,51573L,51574L,51575L,51576L,51577L,
94180 51578L,51579L,51580L,51581L,51582L,51583L,51584L,51585L,51586L,51587L,
94181 51588L,51589L,51590L,51591L,51592L,51593L,51594L,51595L,51596L,51597L,
94182 51598L,51599L,51600L,51601L,51602L,51603L,51604L,51605L,51606L,51607L,
94183 51608L,51609L,51610L,51611L,51612L,51613L,51614L,51615L,51616L,51617L,
94184 51618L,51619L,51620L,51621L,51622L,51623L,51624L,51625L,51626L,51627L,
94185 51628L,51629L,51630L,51631L,51632L,51633L,51634L,51635L,51636L,51637L,
94186 51638L,51639L,51640L,51641L,51642L,51643L,51644L,51645L,51646L,51647L,
94187 51648L,51649L,51650L,51651L,51652L,51653L,51654L,51655L,51656L,51657L,
94188 51658L,51659L,51660L,51661L,51662L,51663L,51664L,51665L,51666L,51667L,
94189 51668L,51669L,51670L,51671L,51672L,51673L,51674L,51675L,51676L,51677L,
94190 51678L,51679L,51680L,51681L,51682L,51683L,51684L,51685L,51686L,51687L,
94191 51688L,51689L,51690L,51691L,51692L,51693L,51694L,51695L,51696L,51697L,
94192 51698L,51699L,51700L,51701L,51702L,51703L,51704L,51705L,51706L,51707L,
94193 51708L,51709L,51710L,51711L,51712L,51713L,51714L,51715L,51716L,51717L,
94194 51718L,51719L,51720L,51721L,51722L,51723L,51724L,51725L,51726L,51727L,
94195 51728L,51729L,51730L,51731L,51732L,51733L,51734L,51735L,51736L,51737L,
94196 51738L,51739L,51740L,51741L,51742L,51743L,51744L,51745L,51746L,51747L,
94197 51748L,51749L,51750L,51751L,51752L,51753L,51754L,51755L,51756L,51757L,
94198 51758L,51759L,51760L,51761L,51762L,51763L,51764L,51765L,51766L,51767L,
94199 51768L,51769L,51770L,51771L,51772L,51773L,51774L,51775L,51776L,51777L,
94200 51778L,51779L,51780L,51781L,51782L,51783L,51784L,51785L,51786L,51787L,
94201 51788L,51789L,51790L,51791L,51792L,51793L,51794L,51795L,51796L,51797L,
94202 51798L,51799L,51800L,51801L,51802L,51803L,51804L,51805L,51806L,51807L,
94203 51808L,51809L,51810L,51811L,51812L,51813L,51814L,51815L,51816L,51817L,
94204 51818L,51819L,51820L,51821L,51822L,51823L,51824L,51825L,51826L,51827L,
94205 51828L,51829L,51830L,51831L,51832L,51833L,51834L,51835L,51836L,51837L,
94206 51838L,51839L,51840L,51841L,51842L,51843L,51844L,51845L,51846L,51847L,
94207 51848L,51849L,51850L,51851L,51852L,51853L,51854L,51855L,51856L,51857L,
94208 51858L,51859L,51860L,51861L,51862L,51863L,51864L,51865L,51866L,51867L,
94209 51868L,51869L,51870L,51871L,51872L,51873L,51874L,51875L,51876L,51877L,
94210 51878L,51879L,51880L,51881L,51882L,51883L,51884L,51885L,51886L,51887L,
94211 51888L,51889L,51890L,51891L,51892L,51893L,51894L,51895L,51896L,51897L,
94212 51898L,51899L,51900L,51901L,51902L,51903L,51904L,51905L,51906L,51907L,
94213 51908L,51909L,51910L,51911L,51912L,51913L,51914L,51915L,51916L,51917L,
94214 51918L,51919L,51920L,51921L,51922L,51923L,51924L,51925L,51926L,51927L,
94215 51928L,51929L,51930L,51931L,51932L,51933L,51934L,51935L,51936L,51937L,
94216 51938L,51939L,51940L,51941L,51942L,51943L,51944L,51945L,51946L,51947L,
94217 51948L,51949L,51950L,51951L,51952L,51953L,51954L,51955L,51956L,51957L,
94218 51958L,51959L,51960L,51961L,51962L,51963L,51964L,51965L,51966L,51967L,
94219 51968L,51969L,51970L,51971L,51972L,51973L,51974L,51975L,51976L,51977L,
94220 51978L,51979L,51980L,51981L,51982L,51983L,51984L,51985L,51986L,51987L,
94221 51988L,51989L,51990L,51991L,51992L,51993L,51994L,51995L,51996L,51997L,
94222 51998L,51999L,52000L,52001L,52002L,52003L,52004L,52005L,52006L,52007L,
94223 52008L,52009L,52010L,52011L,52012L,52013L,52014L,52015L,52016L,52017L,
94224 52018L,52019L,52020L,52021L,52022L,52023L,52024L,52025L,52026L,52027L,
94225 52028L,52029L,52030L,52031L,52032L,52033L,52034L,52035L,52036L,52037L,
94226 52038L,52039L,52040L,52041L,52042L,52043L,52044L,52045L,52046L,52047L,
94227 52048L,52049L,52050L,52051L,52052L,52053L,52054L,52055L,52056L,52057L,
94228 52058L,52059L,52060L,52061L,52062L,52063L,52064L,52065L,52066L,52067L,
94229 52068L,52069L,52070L,52071L,52072L,52073L,52074L,52075L,52076L,52077L,
94230 52078L,52079L,52080L,52081L,52082L,52083L,52084L,52085L,52086L,52087L,
94231 52088L,52089L,52090L,52091L,52092L,52093L,52094L,52095L,52096L,52097L,
94232 52098L,52099L,52100L,52101L,52102L,52103L,52104L,52105L,52106L,52107L,
94233 52108L,52109L,52110L,52111L,52112L,52113L,52114L,52115L,52116L,52117L,
94234 52118L,52119L,52120L,52121L,52122L,52123L,52124L,52125L,52126L,52127L,
94235 52128L,52129L,52130L,52131L,52132L,52133L,52134L,52135L,52136L,52137L,
94236 52138L,52139L,52140L,52141L,52142L,52143L,52144L,52145L,52146L,52147L,
94237 52148L,52149L,52150L,52151L,52152L,52153L,52154L,52155L,52156L,52157L,
94238 52158L,52159L,52160L,52161L,52162L,52163L,52164L,52165L,52166L,52167L,
94239 52168L,52169L,52170L,52171L,52172L,52173L,52174L,52175L,52176L,52177L,
94240 52178L,52179L,52180L,52181L,52182L,52183L,52184L,52185L,52186L,52187L,
94241 52188L,52189L,52190L,52191L,52192L,52193L,52194L,52195L,52196L,52197L,
94242 52198L,52199L,52200L,52201L,52202L,52203L,52204L,52205L,52206L,52207L,
94243 52208L,52209L,52210L,52211L,52212L,52213L,52214L,52215L,52216L,52217L,
94244 52218L,52219L,52220L,52221L,52222L,52223L,52224L,52225L,52226L,52227L,
94245 52228L,52229L,52230L,52231L,52232L,52233L,52234L,52235L,52236L,52237L,
94246 52238L,52239L,52240L,52241L,52242L,52243L,52244L,52245L,52246L,52247L,
94247 52248L,52249L,52250L,52251L,52252L,52253L,52254L,52255L,52256L,52257L,
94248 52258L,52259L,52260L,52261L,52262L,52263L,52264L,52265L,52266L,52267L,
94249 52268L,52269L,52270L,52271L,52272L,52273L,52274L,52275L,52276L,52277L,
94250 52278L,52279L,52280L,52281L,52282L,52283L,52284L,52285L,52286L,52287L,
94251 52288L,52289L,52290L,52291L,52292L,52293L,52294L,52295L,52296L,52297L,
94252 52298L,52299L,52300L,52301L,52302L,52303L,52304L,52305L,52306L,52307L,
94253 52308L,52309L,52310L,52311L,52312L,52313L,52314L,52315L,52316L,52317L,
94254 52318L,52319L,52320L,52321L,52322L,52323L,52324L,52325L,52326L,52327L,
94255 52328L,52329L,52330L,52331L,52332L,52333L,52334L,52335L,52336L,52337L,
94256 52338L,52339L,52340L,52341L,52342L,52343L,52344L,52345L,52346L,52347L,
94257 52348L,52349L,52350L,52351L,52352L,52353L,52354L,52355L,52356L,52357L,
94258 52358L,52359L,52360L,52361L,52362L,52363L,52364L,52365L,52366L,52367L,
94259 52368L,52369L,52370L,52371L,52372L,52373L,52374L,52375L,52376L,52377L,
94260 52378L,52379L,52380L,52381L,52382L,52383L,52384L,52385L,52386L,52387L,
94261 52388L,52389L,52390L,52391L,52392L,52393L,52394L,52395L,52396L,52397L,
94262 52398L,52399L,52400L,52401L,52402L,52403L,52404L,52405L,52406L,52407L,
94263 52408L,52409L,52410L,52411L,52412L,52413L,52414L,52415L,52416L,52417L,
94264 52418L,52419L,52420L,52421L,52422L,52423L,52424L,52425L,52426L,52427L,
94265 52428L,52429L,52430L,52431L,52432L,52433L,52434L,52435L,52436L,52437L,
94266 52438L,52439L,52440L,52441L,52442L,52443L,52444L,52445L,52446L,52447L,
94267 52448L,52449L,52450L,52451L,52452L,52453L,52454L,52455L,52456L,52457L,
94268 52458L,52459L,52460L,52461L,52462L,52463L,52464L,52465L,52466L,52467L,
94269 52468L,52469L,52470L,52471L,52472L,52473L,52474L,52475L,52476L,52477L,
94270 52478L,52479L,52480L,52481L,52482L,52483L,52484L,52485L,52486L,52487L,
94271 52488L,52489L,52490L,52491L,52492L,52493L,52494L,52495L,52496L,52497L,
94272 52498L,52499L,52500L,52501L,52502L,52503L,52504L,52505L,52506L,52507L,
94273 52508L,52509L,52510L,52511L,52512L,52513L,52514L,52515L,52516L,52517L,
94274 52518L,52519L,52520L,52521L,52522L,52523L,52524L,52525L,52526L,52527L,
94275 52528L,52529L,52530L,52531L,52532L,52533L,52534L,52535L,52536L,52537L,
94276 52538L,52539L,52540L,52541L,52542L,52543L,52544L,52545L,52546L,52547L,
94277 52548L,52549L,52550L,52551L,52552L,52553L,52554L,52555L,52556L,52557L,
94278 52558L,52559L,52560L,52561L,52562L,52563L,52564L,52565L,52566L,52567L,
94279 52568L,52569L,52570L,52571L,52572L,52573L,52574L,52575L,52576L,52577L,
94280 52578L,52579L,52580L,52581L,52582L,52583L,52584L,52585L,52586L,52587L,
94281 52588L,52589L,52590L,52591L,52592L,52593L,52594L,52595L,52596L,52597L,
94282 52598L,52599L,52600L,52601L,52602L,52603L,52604L,52605L,52606L,52607L,
94283 52608L,52609L,52610L,52611L,52612L,52613L,52614L,52615L,52616L,52617L,
94284 52618L,52619L,52620L,52621L,52622L,52623L,52624L,52625L,52626L,52627L,
94285 52628L,52629L,52630L,52631L,52632L,52633L,52634L,52635L,52636L,52637L,
94286 52638L,52639L,52640L,52641L,52642L,52643L,52644L,52645L,52646L,52647L,
94287 52648L,52649L,52650L,52651L,52652L,52653L,52654L,52655L,52656L,52657L,
94288 52658L,52659L,52660L,52661L,52662L,52663L,52664L,52665L,52666L,52667L,
94289 52668L,52669L,52670L,52671L,52672L,52673L,52674L,52675L,52676L,52677L,
94290 52678L,52679L,52680L,52681L,52682L,52683L,52684L,52685L,52686L,52687L,
94291 52688L,52689L,52690L,52691L,52692L,52693L,52694L,52695L,52696L,52697L,
94292 52698L,52699L,52700L,52701L,52702L,52703L,52704L,52705L,52706L,52707L,
94293 52708L,52709L,52710L,52711L,52712L,52713L,52714L,52715L,52716L,52717L,
94294 52718L,52719L,52720L,52721L,52722L,52723L,52724L,52725L,52726L,52727L,
94295 52728L,52729L,52730L,52731L,52732L,52733L,52734L,52735L,52736L,52737L,
94296 52738L,52739L,52740L,52741L,52742L,52743L,52744L,52745L,52746L,52747L,
94297 52748L,52749L,52750L,52751L,52752L,52753L,52754L,52755L,52756L,52757L,
94298 52758L,52759L,52760L,52761L,52762L,52763L,52764L,52765L,52766L,52767L,
94299 52768L,52769L,52770L,52771L,52772L,52773L,52774L,52775L,52776L,52777L,
94300 52778L,52779L,52780L,52781L,52782L,52783L,52784L,52785L,52786L,52787L,
94301 52788L,52789L,52790L,52791L,52792L,52793L,52794L,52795L,52796L,52797L,
94302 52798L,52799L,52800L,52801L,52802L,52803L,52804L,52805L,52806L,52807L,
94303 52808L,52809L,52810L,52811L,52812L,52813L,52814L,52815L,52816L,52817L,
94304 52818L,52819L,52820L,52821L,52822L,52823L,52824L,52825L,52826L,52827L,
94305 52828L,52829L,52830L,52831L,52832L,52833L,52834L,52835L,52836L,52837L,
94306 52838L,52839L,52840L,52841L,52842L,52843L,52844L,52845L,52846L,52847L,
94307 52848L,52849L,52850L,52851L,52852L,52853L,52854L,52855L,52856L,52857L,
94308 52858L,52859L,52860L,52861L,52862L,52863L,52864L,52865L,52866L,52867L,
94309 52868L,52869L,52870L,52871L,52872L,52873L,52874L,52875L,52876L,52877L,
94310 52878L,52879L,52880L,52881L,52882L,52883L,52884L,52885L,52886L,52887L,
94311 52888L,52889L,52890L,52891L,52892L,52893L,52894L,52895L,52896L,52897L,
94312 52898L,52899L,52900L,52901L,52902L,52903L,52904L,52905L,52906L,52907L,
94313 52908L,52909L,52910L,52911L,52912L,52913L,52914L,52915L,52916L,52917L,
94314 52918L,52919L,52920L,52921L,52922L,52923L,52924L,52925L,52926L,52927L,
94315 52928L,52929L,52930L,52931L,52932L,52933L,52934L,52935L,52936L,52937L,
94316 52938L,52939L,52940L,52941L,52942L,52943L,52944L,52945L,52946L,52947L,
94317 52948L,52949L,52950L,52951L,52952L,52953L,52954L,52955L,52956L,52957L,
94318 52958L,52959L,52960L,52961L,52962L,52963L,52964L,52965L,52966L,52967L,
94319 52968L,52969L,52970L,52971L,52972L,52973L,52974L,52975L,52976L,52977L,
94320 52978L,52979L,52980L,52981L,52982L,52983L,52984L,52985L,52986L,52987L,
94321 52988L,52989L,52990L,52991L,52992L,52993L,52994L,52995L,52996L,52997L,
94322 52998L,52999L,53000L,53001L,53002L,53003L,53004L,53005L,53006L,53007L,
94323 53008L,53009L,53010L,53011L,53012L,53013L,53014L,53015L,53016L,53017L,
94324 53018L,53019L,53020L,53021L,53022L,53023L,53024L,53025L,53026L,53027L,
94325 53028L,53029L,53030L,53031L,53032L,53033L,53034L,53035L,53036L,53037L,
94326 53038L,53039L,53040L,53041L,53042L,53043L,53044L,53045L,53046L,53047L,
94327 53048L,53049L,53050L,53051L,53052L,53053L,53054L,53055L,53056L,53057L,
94328 53058L,53059L,53060L,53061L,53062L,53063L,53064L,53065L,53066L,53067L,
94329 53068L,53069L,53070L,53071L,53072L,53073L,53074L,53075L,53076L,53077L,
94330 53078L,53079L,53080L,53081L,53082L,53083L,53084L,53085L,53086L,53087L,
94331 53088L,53089L,53090L,53091L,53092L,53093L,53094L,53095L,53096L,53097L,
94332 53098L,53099L,53100L,53101L,53102L,53103L,53104L,53105L,53106L,53107L,
94333 53108L,53109L,53110L,53111L,53112L,53113L,53114L,53115L,53116L,53117L,
94334 53118L,53119L,53120L,53121L,53122L,53123L,53124L,53125L,53126L,53127L,
94335 53128L,53129L,53130L,53131L,53132L,53133L,53134L,53135L,53136L,53137L,
94336 53138L,53139L,53140L,53141L,53142L,53143L,53144L,53145L,53146L,53147L,
94337 53148L,53149L,53150L,53151L,53152L,53153L,53154L,53155L,53156L,53157L,
94338 53158L,53159L,53160L,53161L,53162L,53163L,53164L,53165L,53166L,53167L,
94339 53168L,53169L,53170L,53171L,53172L,53173L,53174L,53175L,53176L,53177L,
94340 53178L,53179L,53180L,53181L,53182L,53183L,53184L,53185L,53186L,53187L,
94341 53188L,53189L,53190L,53191L,53192L,53193L,53194L,53195L,53196L,53197L,
94342 53198L,53199L,53200L,53201L,53202L,53203L,53204L,53205L,53206L,53207L,
94343 53208L,53209L,53210L,53211L,53212L,53213L,53214L,53215L,53216L,53217L,
94344 53218L,53219L,53220L,53221L,53222L,53223L,53224L,53225L,53226L,53227L,
94345 53228L,53229L,53230L,53231L,53232L,53233L,53234L,53235L,53236L,53237L,
94346 53238L,53239L,53240L,53241L,53242L,53243L,53244L,53245L,53246L,53247L,
94347 53248L,53249L,53250L,53251L,53252L,53253L,53254L,53255L,53256L,53257L,
94348 53258L,53259L,53260L,53261L,53262L,53263L,53264L,53265L,53266L,53267L,
94349 53268L,53269L,53270L,53271L,53272L,53273L,53274L,53275L,53276L,53277L,
94350 53278L,53279L,53280L,53281L,53282L,53283L,53284L,53285L,53286L,53287L,
94351 53288L,53289L,53290L,53291L,53292L,53293L,53294L,53295L,53296L,53297L,
94352 53298L,53299L,53300L,53301L,53302L,53303L,53304L,53305L,53306L,53307L,
94353 53308L,53309L,53310L,53311L,53312L,53313L,53314L,53315L,53316L,53317L,
94354 53318L,53319L,53320L,53321L,53322L,53323L,53324L,53325L,53326L,53327L,
94355 53328L,53329L,53330L,53331L,53332L,53333L,53334L,53335L,53336L,53337L,
94356 53338L,53339L,53340L,53341L,53342L,53343L,53344L,53345L,53346L,53347L,
94357 53348L,53349L,53350L,53351L,53352L,53353L,53354L,53355L,53356L,53357L,
94358 53358L,53359L,53360L,53361L,53362L,53363L,53364L,53365L,53366L,53367L,
94359 53368L,53369L,53370L,53371L,53372L,53373L,53374L,53375L,53376L,53377L,
94360 53378L,53379L,53380L,53381L,53382L,53383L,53384L,53385L,53386L,53387L,
94361 53388L,53389L,53390L,53391L,53392L,53393L,53394L,53395L,53396L,53397L,
94362 53398L,53399L,53400L,53401L,53402L,53403L,53404L,53405L,53406L,53407L,
94363 53408L,53409L,53410L,53411L,53412L,53413L,53414L,53415L,53416L,53417L,
94364 53418L,53419L,53420L,53421L,53422L,53423L,53424L,53425L,53426L,53427L,
94365 53428L,53429L,53430L,53431L,53432L,53433L,53434L,53435L,53436L,53437L,
94366 53438L,53439L,53440L,53441L,53442L,53443L,53444L,53445L,53446L,53447L,
94367 53448L,53449L,53450L,53451L,53452L,53453L,53454L,53455L,53456L,53457L,
94368 53458L,53459L,53460L,53461L,53462L,53463L,53464L,53465L,53466L,53467L,
94369 53468L,53469L,53470L,53471L,53472L,53473L,53474L,53475L,53476L,53477L,
94370 53478L,53479L,53480L,53481L,53482L,53483L,53484L,53485L,53486L,53487L,
94371 53488L,53489L,53490L,53491L,53492L,53493L,53494L,53495L,53496L,53497L,
94372 53498L,53499L,53500L,53501L,53502L,53503L,53504L,53505L,53506L,53507L,
94373 53508L,53509L,53510L,53511L,53512L,53513L,53514L,53515L,53516L,53517L,
94374 53518L,53519L,53520L,53521L,53522L,53523L,53524L,53525L,53526L,53527L,
94375 53528L,53529L,53530L,53531L,53532L,53533L,53534L,53535L,53536L,53537L,
94376 53538L,53539L,53540L,53541L,53542L,53543L,53544L,53545L,53546L,53547L,
94377 53548L,53549L,53550L,53551L,53552L,53553L,53554L,53555L,53556L,53557L,
94378 53558L,53559L,53560L,53561L,53562L,53563L,53564L,53565L,53566L,53567L,
94379 53568L,53569L,53570L,53571L,53572L,53573L,53574L,53575L,53576L,53577L,
94380 53578L,53579L,53580L,53581L,53582L,53583L,53584L,53585L,53586L,53587L,
94381 53588L,53589L,53590L,53591L,53592L,53593L,53594L,53595L,53596L,53597L,
94382 53598L,53599L,53600L,53601L,53602L,53603L,53604L,53605L,53606L,53607L,
94383 53608L,53609L,53610L,53611L,53612L,53613L,53614L,53615L,53616L,53617L,
94384 53618L,53619L,53620L,53621L,53622L,53623L,53624L,53625L,53626L,53627L,
94385 53628L,53629L,53630L,53631L,53632L,53633L,53634L,53635L,53636L,53637L,
94386 53638L,53639L,53640L,53641L,53642L,53643L,53644L,53645L,53646L,53647L,
94387 53648L,53649L,53650L,53651L,53652L,53653L,53654L,53655L,53656L,53657L,
94388 53658L,53659L,53660L,53661L,53662L,53663L,53664L,53665L,53666L,53667L,
94389 53668L,53669L,53670L,53671L,53672L,53673L,53674L,53675L,53676L,53677L,
94390 53678L,53679L,53680L,53681L,53682L,53683L,53684L,53685L,53686L,53687L,
94391 53688L,53689L,53690L,53691L,53692L,53693L,53694L,53695L,53696L,53697L,
94392 53698L,53699L,53700L,53701L,53702L,53703L,53704L,53705L,53706L,53707L,
94393 53708L,53709L,53710L,53711L,53712L,53713L,53714L,53715L,53716L,53717L,
94394 53718L,53719L,53720L,53721L,53722L,53723L,53724L,53725L,53726L,53727L,
94395 53728L,53729L,53730L,53731L,53732L,53733L,53734L,53735L,53736L,53737L,
94396 53738L,53739L,53740L,53741L,53742L,53743L,53744L,53745L,53746L,53747L,
94397 53748L,53749L,53750L,53751L,53752L,53753L,53754L,53755L,53756L,53757L,
94398 53758L,53759L,53760L,53761L,53762L,53763L,53764L,53765L,53766L,53767L,
94399 53768L,53769L,53770L,53771L,53772L,53773L,53774L,53775L,53776L,53777L,
94400 53778L,53779L,53780L,53781L,53782L,53783L,53784L,53785L,53786L,53787L,
94401 53788L,53789L,53790L,53791L,53792L,53793L,53794L,53795L,53796L,53797L,
94402 53798L,53799L,53800L,53801L,53802L,53803L,53804L,53805L,53806L,53807L,
94403 53808L,53809L,53810L,53811L,53812L,53813L,53814L,53815L,53816L,53817L,
94404 53818L,53819L,53820L,53821L,53822L,53823L,53824L,53825L,53826L,53827L,
94405 53828L,53829L,53830L,53831L,53832L,53833L,53834L,53835L,53836L,53837L,
94406 53838L,53839L,53840L,53841L,53842L,53843L,53844L,53845L,53846L,53847L,
94407 53848L,53849L,53850L,53851L,53852L,53853L,53854L,53855L,53856L,53857L,
94408 53858L,53859L,53860L,53861L,53862L,53863L,53864L,53865L,53866L,53867L,
94409 53868L,53869L,53870L,53871L,53872L,53873L,53874L,53875L,53876L,53877L,
94410 53878L,53879L,53880L,53881L,53882L,53883L,53884L,53885L,53886L,53887L,
94411 53888L,53889L,53890L,53891L,53892L,53893L,53894L,53895L,53896L,53897L,
94412 53898L,53899L,53900L,53901L,53902L,53903L,53904L,53905L,53906L,53907L,
94413 53908L,53909L,53910L,53911L,53912L,53913L,53914L,53915L,53916L,53917L,
94414 53918L,53919L,53920L,53921L,53922L,53923L,53924L,53925L,53926L,53927L,
94415 53928L,53929L,53930L,53931L,53932L,53933L,53934L,53935L,53936L,53937L,
94416 53938L,53939L,53940L,53941L,53942L,53943L,53944L,53945L,53946L,53947L,
94417 53948L,53949L,53950L,53951L,53952L,53953L,53954L,53955L,53956L,53957L,
94418 53958L,53959L,53960L,53961L,53962L,53963L,53964L,53965L,53966L,53967L,
94419 53968L,53969L,53970L,53971L,53972L,53973L,53974L,53975L,53976L,53977L,
94420 53978L,53979L,53980L,53981L,53982L,53983L,53984L,53985L,53986L,53987L,
94421 53988L,53989L,53990L,53991L,53992L,53993L,53994L,53995L,53996L,53997L,
94422 53998L,53999L,54000L,54001L,54002L,54003L,54004L,54005L,54006L,54007L,
94423 54008L,54009L,54010L,54011L,54012L,54013L,54014L,54015L,54016L,54017L,
94424 54018L,54019L,54020L,54021L,54022L,54023L,54024L,54025L,54026L,54027L,
94425 54028L,54029L,54030L,54031L,54032L,54033L,54034L,54035L,54036L,54037L,
94426 54038L,54039L,54040L,54041L,54042L,54043L,54044L,54045L,54046L,54047L,
94427 54048L,54049L,54050L,54051L,54052L,54053L,54054L,54055L,54056L,54057L,
94428 54058L,54059L,54060L,54061L,54062L,54063L,54064L,54065L,54066L,54067L,
94429 54068L,54069L,54070L,54071L,54072L,54073L,54074L,54075L,54076L,54077L,
94430 54078L,54079L,54080L,54081L,54082L,54083L,54084L,54085L,54086L,54087L,
94431 54088L,54089L,54090L,54091L,54092L,54093L,54094L,54095L,54096L,54097L,
94432 54098L,54099L,54100L,54101L,54102L,54103L,54104L,54105L,54106L,54107L,
94433 54108L,54109L,54110L,54111L,54112L,54113L,54114L,54115L,54116L,54117L,
94434 54118L,54119L,54120L,54121L,54122L,54123L,54124L,54125L,54126L,54127L,
94435 54128L,54129L,54130L,54131L,54132L,54133L,54134L,54135L,54136L,54137L,
94436 54138L,54139L,54140L,54141L,54142L,54143L,54144L,54145L,54146L,54147L,
94437 54148L,54149L,54150L,54151L,54152L,54153L,54154L,54155L,54156L,54157L,
94438 54158L,54159L,54160L,54161L,54162L,54163L,54164L,54165L,54166L,54167L,
94439 54168L,54169L,54170L,54171L,54172L,54173L,54174L,54175L,54176L,54177L,
94440 54178L,54179L,54180L,54181L,54182L,54183L,54184L,54185L,54186L,54187L,
94441 54188L,54189L,54190L,54191L,54192L,54193L,54194L,54195L,54196L,54197L,
94442 54198L,54199L,54200L,54201L,54202L,54203L,54204L,54205L,54206L,54207L,
94443 54208L,54209L,54210L,54211L,54212L,54213L,54214L,54215L,54216L,54217L,
94444 54218L,54219L,54220L,54221L,54222L,54223L,54224L,54225L,54226L,54227L,
94445 54228L,54229L,54230L,54231L,54232L,54233L,54234L,54235L,54236L,54237L,
94446 54238L,54239L,54240L,54241L,54242L,54243L,54244L,54245L,54246L,54247L,
94447 54248L,54249L,54250L,54251L,54252L,54253L,54254L,54255L,54256L,54257L,
94448 54258L,54259L,54260L,54261L,54262L,54263L,54264L,54265L,54266L,54267L,
94449 54268L,54269L,54270L,54271L,54272L,54273L,54274L,54275L,54276L,54277L,
94450 54278L,54279L,54280L,54281L,54282L,54283L,54284L,54285L,54286L,54287L,
94451 54288L,54289L,54290L,54291L,54292L,54293L,54294L,54295L,54296L,54297L,
94452 54298L,54299L,54300L,54301L,54302L,54303L,54304L,54305L,54306L,54307L,
94453 54308L,54309L,54310L,54311L,54312L,54313L,54314L,54315L,54316L,54317L,
94454 54318L,54319L,54320L,54321L,54322L,54323L,54324L,54325L,54326L,54327L,
94455 54328L,54329L,54330L,54331L,54332L,54333L,54334L,54335L,54336L,54337L,
94456 54338L,54339L,54340L,54341L,54342L,54343L,54344L,54345L,54346L,54347L,
94457 54348L,54349L,54350L,54351L,54352L,54353L,54354L,54355L,54356L,54357L,
94458 54358L,54359L,54360L,54361L,54362L,54363L,54364L,54365L,54366L,54367L,
94459 54368L,54369L,54370L,54371L,54372L,54373L,54374L,54375L,54376L,54377L,
94460 54378L,54379L,54380L,54381L,54382L,54383L,54384L,54385L,54386L,54387L,
94461 54388L,54389L,54390L,54391L,54392L,54393L,54394L,54395L,54396L,54397L,
94462 54398L,54399L,54400L,54401L,54402L,54403L,54404L,54405L,54406L,54407L,
94463 54408L,54409L,54410L,54411L,54412L,54413L,54414L,54415L,54416L,54417L,
94464 54418L,54419L,54420L,54421L,54422L,54423L,54424L,54425L,54426L,54427L,
94465 54428L,54429L,54430L,54431L,54432L,54433L,54434L,54435L,54436L,54437L,
94466 54438L,54439L,54440L,54441L,54442L,54443L,54444L,54445L,54446L,54447L,
94467 54448L,54449L,54450L,54451L,54452L,54453L,54454L,54455L,54456L,54457L,
94468 54458L,54459L,54460L,54461L,54462L,54463L,54464L,54465L,54466L,54467L,
94469 54468L,54469L,54470L,54471L,54472L,54473L,54474L,54475L,54476L,54477L,
94470 54478L,54479L,54480L,54481L,54482L,54483L,54484L,54485L,54486L,54487L,
94471 54488L,54489L,54490L,54491L,54492L,54493L,54494L,54495L,54496L,54497L,
94472 54498L,54499L,54500L,54501L,54502L,54503L,54504L,54505L,54506L,54507L,
94473 54508L,54509L,54510L,54511L,54512L,54513L,54514L,54515L,54516L,54517L,
94474 54518L,54519L,54520L,54521L,54522L,54523L,54524L,54525L,54526L,54527L,
94475 54528L,54529L,54530L,54531L,54532L,54533L,54534L,54535L,54536L,54537L,
94476 54538L,54539L,54540L,54541L,54542L,54543L,54544L,54545L,54546L,54547L,
94477 54548L,54549L,54550L,54551L,54552L,54553L,54554L,54555L,54556L,54557L,
94478 54558L,54559L,54560L,54561L,54562L,54563L,54564L,54565L,54566L,54567L,
94479 54568L,54569L,54570L,54571L,54572L,54573L,54574L,54575L,54576L,54577L,
94480 54578L,54579L,54580L,54581L,54582L,54583L,54584L,54585L,54586L,54587L,
94481 54588L,54589L,54590L,54591L,54592L,54593L,54594L,54595L,54596L,54597L,
94482 54598L,54599L,54600L,54601L,54602L,54603L,54604L,54605L,54606L,54607L,
94483 54608L,54609L,54610L,54611L,54612L,54613L,54614L,54615L,54616L,54617L,
94484 54618L,54619L,54620L,54621L,54622L,54623L,54624L,54625L,54626L,54627L,
94485 54628L,54629L,54630L,54631L,54632L,54633L,54634L,54635L,54636L,54637L,
94486 54638L,54639L,54640L,54641L,54642L,54643L,54644L,54645L,54646L,54647L,
94487 54648L,54649L,54650L,54651L,54652L,54653L,54654L,54655L,54656L,54657L,
94488 54658L,54659L,54660L,54661L,54662L,54663L,54664L,54665L,54666L,54667L,
94489 54668L,54669L,54670L,54671L,54672L,54673L,54674L,54675L,54676L,54677L,
94490 54678L,54679L,54680L,54681L,54682L,54683L,54684L,54685L,54686L,54687L,
94491 54688L,54689L,54690L,54691L,54692L,54693L,54694L,54695L,54696L,54697L,
94492 54698L,54699L,54700L,54701L,54702L,54703L,54704L,54705L,54706L,54707L,
94493 54708L,54709L,54710L,54711L,54712L,54713L,54714L,54715L,54716L,54717L,
94494 54718L,54719L,54720L,54721L,54722L,54723L,54724L,54725L,54726L,54727L,
94495 54728L,54729L,54730L,54731L,54732L,54733L,54734L,54735L,54736L,54737L,
94496 54738L,54739L,54740L,54741L,54742L,54743L,54744L,54745L,54746L,54747L,
94497 54748L,54749L,54750L,54751L,54752L,54753L,54754L,54755L,54756L,54757L,
94498 54758L,54759L,54760L,54761L,54762L,54763L,54764L,54765L,54766L,54767L,
94499 54768L,54769L,54770L,54771L,54772L,54773L,54774L,54775L,54776L,54777L,
94500 54778L,54779L,54780L,54781L,54782L,54783L,54784L,54785L,54786L,54787L,
94501 54788L,54789L,54790L,54791L,54792L,54793L,54794L,54795L,54796L,54797L,
94502 54798L,54799L,54800L,54801L,54802L,54803L,54804L,54805L,54806L,54807L,
94503 54808L,54809L,54810L,54811L,54812L,54813L,54814L,54815L,54816L,54817L,
94504 54818L,54819L,54820L,54821L,54822L,54823L,54824L,54825L,54826L,54827L,
94505 54828L,54829L,54830L,54831L,54832L,54833L,54834L,54835L,54836L,54837L,
94506 54838L,54839L,54840L,54841L,54842L,54843L,54844L,54845L,54846L,54847L,
94507 54848L,54849L,54850L,54851L,54852L,54853L,54854L,54855L,54856L,54857L,
94508 54858L,54859L,54860L,54861L,54862L,54863L,54864L,54865L,54866L,54867L,
94509 54868L,54869L,54870L,54871L,54872L,54873L,54874L,54875L,54876L,54877L,
94510 54878L,54879L,54880L,54881L,54882L,54883L,54884L,54885L,54886L,54887L,
94511 54888L,54889L,54890L,54891L,54892L,54893L,54894L,54895L,54896L,54897L,
94512 54898L,54899L,54900L,54901L,54902L,54903L,54904L,54905L,54906L,54907L,
94513 54908L,54909L,54910L,54911L,54912L,54913L,54914L,54915L,54916L,54917L,
94514 54918L,54919L,54920L,54921L,54922L,54923L,54924L,54925L,54926L,54927L,
94515 54928L,54929L,54930L,54931L,54932L,54933L,54934L,54935L,54936L,54937L,
94516 54938L,54939L,54940L,54941L,54942L,54943L,54944L,54945L,54946L,54947L,
94517 54948L,54949L,54950L,54951L,54952L,54953L,54954L,54955L,54956L,54957L,
94518 54958L,54959L,54960L,54961L,54962L,54963L,54964L,54965L,54966L,54967L,
94519 54968L,54969L,54970L,54971L,54972L,54973L,54974L,54975L,54976L,54977L,
94520 54978L,54979L,54980L,54981L,54982L,54983L,54984L,54985L,54986L,54987L,
94521 54988L,54989L,54990L,54991L,54992L,54993L,54994L,54995L,54996L,54997L,
94522 54998L,54999L,55000L,55001L,55002L,55003L,55004L,55005L,55006L,55007L,
94523 55008L,55009L,55010L,55011L,55012L,55013L,55014L,55015L,55016L,55017L,
94524 55018L,55019L,55020L,55021L,55022L,55023L,55024L,55025L,55026L,55027L,
94525 55028L,55029L,55030L,55031L,55032L,55033L,55034L,55035L,55036L,55037L,
94526 55038L,55039L,55040L,55041L,55042L,55043L,55044L,55045L,55046L,55047L,
94527 55048L,55049L,55050L,55051L,55052L,55053L,55054L,55055L,55056L,55057L,
94528 55058L,55059L,55060L,55061L,55062L,55063L,55064L,55065L,55066L,55067L,
94529 55068L,55069L,55070L,55071L,55072L,55073L,55074L,55075L,55076L,55077L,
94530 55078L,55079L,55080L,55081L,55082L,55083L,55084L,55085L,55086L,55087L,
94531 55088L,55089L,55090L,55091L,55092L,55093L,55094L,55095L,55096L,55097L,
94532 55098L,55099L,55100L,55101L,55102L,55103L,55104L,55105L,55106L,55107L,
94533 55108L,55109L,55110L,55111L,55112L,55113L,55114L,55115L,55116L,55117L,
94534 55118L,55119L,55120L,55121L,55122L,55123L,55124L,55125L,55126L,55127L,
94535 55128L,55129L,55130L,55131L,55132L,55133L,55134L,55135L,55136L,55137L,
94536 55138L,55139L,55140L,55141L,55142L,55143L,55144L,55145L,55146L,55147L,
94537 55148L,55149L,55150L,55151L,55152L,55153L,55154L,55155L,55156L,55157L,
94538 55158L,55159L,55160L,55161L,55162L,55163L,55164L,55165L,55166L,55167L,
94539 55168L,55169L,55170L,55171L,55172L,55173L,55174L,55175L,55176L,55177L,
94540 55178L,55179L,55180L,55181L,55182L,55183L,55184L,55185L,55186L,55187L,
94541 55188L,55189L,55190L,55191L,55192L,55193L,55194L,55195L,55196L,55197L,
94542 55198L,55199L,55200L,55201L,55202L,55203L,55204L,55205L,55206L,55207L,
94543 55208L,55209L,55210L,55211L,55212L,55213L,55214L,55215L,55216L,55217L,
94544 55218L,55219L,55220L,55221L,55222L,55223L,55224L,55225L,55226L,55227L,
94545 55228L,55229L,55230L,55231L,55232L,55233L,55234L,55235L,55236L,55237L,
94546 55238L,55239L,55240L,55241L,55242L,55243L,55244L,55245L,55246L,55247L,
94547 55248L,55249L,55250L,55251L,55252L,55253L,55254L,55255L,55256L,55257L,
94548 55258L,55259L,55260L,55261L,55262L,55263L,55264L,55265L,55266L,55267L,
94549 55268L,55269L,55270L,55271L,55272L,55273L,55274L,55275L,55276L,55277L,
94550 55278L,55279L,55280L,55281L,55282L,55283L,55284L,55285L,55286L,55287L,
94551 55288L,55289L,55290L,55291L,55292L,55293L,55294L,55295L,55296L,55297L,
94552 55298L,55299L,55300L,55301L,55302L,55303L,55304L,55305L,55306L,55307L,
94553 55308L,55309L,55310L,55311L,55312L,55313L,55314L,55315L,55316L,55317L,
94554 55318L,55319L,55320L,55321L,55322L,55323L,55324L,55325L,55326L,55327L,
94555 55328L,55329L,55330L,55331L,55332L,55333L,55334L,55335L,55336L,55337L,
94556 55338L,55339L,55340L,55341L,55342L,55343L,55344L,55345L,55346L,55347L,
94557 55348L,55349L,55350L,55351L,55352L,55353L,55354L,55355L,55356L,55357L,
94558 55358L,55359L,55360L,55361L,55362L,55363L,55364L,55365L,55366L,55367L,
94559 55368L,55369L,55370L,55371L,55372L,55373L,55374L,55375L,55376L,55377L,
94560 55378L,55379L,55380L,55381L,55382L,55383L,55384L,55385L,55386L,55387L,
94561 55388L,55389L,55390L,55391L,55392L,55393L,55394L,55395L,55396L,55397L,
94562 55398L,55399L,55400L,55401L,55402L,55403L,55404L,55405L,55406L,55407L,
94563 55408L,55409L,55410L,55411L,55412L,55413L,55414L,55415L,55416L,55417L,
94564 55418L,55419L,55420L,55421L,55422L,55423L,55424L,55425L,55426L,55427L,
94565 55428L,55429L,55430L,55431L,55432L,55433L,55434L,55435L,55436L,55437L,
94566 55438L,55439L,55440L,55441L,55442L,55443L,55444L,55445L,55446L,55447L,
94567 55448L,55449L,55450L,55451L,55452L,55453L,55454L,55455L,55456L,55457L,
94568 55458L,55459L,55460L,55461L,55462L,55463L,55464L,55465L,55466L,55467L,
94569 55468L,55469L,55470L,55471L,55472L,55473L,55474L,55475L,55476L,55477L,
94570 55478L,55479L,55480L,55481L,55482L,55483L,55484L,55485L,55486L,55487L,
94571 55488L,55489L,55490L,55491L,55492L,55493L,55494L,55495L,55496L,55497L,
94572 55498L,55499L,55500L,55501L,55502L,55503L,55504L,55505L,55506L,55507L,
94573 55508L,55509L,55510L,55511L,55512L,55513L,55514L,55515L,55516L,55517L,
94574 55518L,55519L,55520L,55521L,55522L,55523L,55524L,55525L,55526L,55527L,
94575 55528L,55529L,55530L,55531L,55532L,55533L,55534L,55535L,55536L,55537L,
94576 55538L,55539L,55540L,55541L,55542L,55543L,55544L,55545L,55546L,55547L,
94577 55548L,55549L,55550L,55551L,55552L,55553L,55554L,55555L,55556L,55557L,
94578 55558L,55559L,55560L,55561L,55562L,55563L,55564L,55565L,55566L,55567L,
94579 55568L,55569L,55570L,55571L,55572L,55573L,55574L,55575L,55576L,55577L,
94580 55578L,55579L,55580L,55581L,55582L,55583L,55584L,55585L,55586L,55587L,
94581 55588L,55589L,55590L,55591L,55592L,55593L,55594L,55595L,55596L,55597L,
94582 55598L,55599L,55600L,55601L,55602L,55603L,55604L,55605L,55606L,55607L,
94583 55608L,55609L,55610L,55611L,55612L,55613L,55614L,55615L,55616L,55617L,
94584 55618L,55619L,55620L,55621L,55622L,55623L,55624L,55625L,55626L,55627L,
94585 55628L,55629L,55630L,55631L,55632L,55633L,55634L,55635L,55636L,55637L,
94586 55638L,55639L,55640L,55641L,55642L,55643L,55644L,55645L,55646L,55647L,
94587 55648L,55649L,55650L,55651L,55652L,55653L,55654L,55655L,55656L,55657L,
94588 55658L,55659L,55660L,55661L,55662L,55663L,55664L,55665L,55666L,55667L,
94589 55668L,55669L,55670L,55671L,55672L,55673L,55674L,55675L,55676L,55677L,
94590 55678L,55679L,55680L,55681L,55682L,55683L,55684L,55685L,55686L,55687L,
94591 55688L,55689L,55690L,55691L,55692L,55693L,55694L,55695L,55696L,55697L,
94592 55698L,55699L,55700L,55701L,55702L,55703L,55704L,55705L,55706L,55707L,
94593 55708L,55709L,55710L,55711L,55712L,55713L,55714L,55715L,55716L,55717L,
94594 55718L,55719L,55720L,55721L,55722L,55723L,55724L,55725L,55726L,55727L,
94595 55728L,55729L,55730L,55731L,55732L,55733L,55734L,55735L,55736L,55737L,
94596 55738L,55739L,55740L,55741L,55742L,55743L,55744L,55745L,55746L,55747L,
94597 55748L,55749L,55750L,55751L,55752L,55753L,55754L,55755L,55756L,55757L,
94598 55758L,55759L,55760L,55761L,55762L,55763L,55764L,55765L,55766L,55767L,
94599 55768L,55769L,55770L,55771L,55772L,55773L,55774L,55775L,55776L,55777L,
94600 55778L,55779L,55780L,55781L,55782L,55783L,55784L,55785L,55786L,55787L,
94601 55788L,55789L,55790L,55791L,55792L,55793L,55794L,55795L,55796L,55797L,
94602 55798L,55799L,55800L,55801L,55802L,55803L,55804L,55805L,55806L,55807L,
94603 55808L,55809L,55810L,55811L,55812L,55813L,55814L,55815L,55816L,55817L,
94604 55818L,55819L,55820L,55821L,55822L,55823L,55824L,55825L,55826L,55827L,
94605 55828L,55829L,55830L,55831L,55832L,55833L,55834L,55835L,55836L,55837L,
94606 55838L,55839L,55840L,55841L,55842L,55843L,55844L,55845L,55846L,55847L,
94607 55848L,55849L,55850L,55851L,55852L,55853L,55854L,55855L,55856L,55857L,
94608 55858L,55859L,55860L,55861L,55862L,55863L,55864L,55865L,55866L,55867L,
94609 55868L,55869L,55870L,55871L,55872L,55873L,55874L,55875L,55876L,55877L,
94610 55878L,55879L,55880L,55881L,55882L,55883L,55884L,55885L,55886L,55887L,
94611 55888L,55889L,55890L,55891L,55892L,55893L,55894L,55895L,55896L,55897L,
94612 55898L,55899L,55900L,55901L,55902L,55903L,55904L,55905L,55906L,55907L,
94613 55908L,55909L,55910L,55911L,55912L,55913L,55914L,55915L,55916L,55917L,
94614 55918L,55919L,55920L,55921L,55922L,55923L,55924L,55925L,55926L,55927L,
94615 55928L,55929L,55930L,55931L,55932L,55933L,55934L,55935L,55936L,55937L,
94616 55938L,55939L,55940L,55941L,55942L,55943L,55944L,55945L,55946L,55947L,
94617 55948L,55949L,55950L,55951L,55952L,55953L,55954L,55955L,55956L,55957L,
94618 55958L,55959L,55960L,55961L,55962L,55963L,55964L,55965L,55966L,55967L,
94619 55968L,55969L,55970L,55971L,55972L,55973L,55974L,55975L,55976L,55977L,
94620 55978L,55979L,55980L,55981L,55982L,55983L,55984L,55985L,55986L,55987L,
94621 55988L,55989L,55990L,55991L,55992L,55993L,55994L,55995L,55996L,55997L,
94622 55998L,55999L,56000L,56001L,56002L,56003L,56004L,56005L,56006L,56007L,
94623 56008L,56009L,56010L,56011L,56012L,56013L,56014L,56015L,56016L,56017L,
94624 56018L,56019L,56020L,56021L,56022L,56023L,56024L,56025L,56026L,56027L,
94625 56028L,56029L,56030L,56031L,56032L,56033L,56034L,56035L,56036L,56037L,
94626 56038L,56039L,56040L,56041L,56042L,56043L,56044L,56045L,56046L,56047L,
94627 56048L,56049L,56050L,56051L,56052L,56053L,56054L,56055L,56056L,56057L,
94628 56058L,56059L,56060L,56061L,56062L,56063L,56064L,56065L,56066L,56067L,
94629 56068L,56069L,56070L,56071L,56072L,56073L,56074L,56075L,56076L,56077L,
94630 56078L,56079L,56080L,56081L,56082L,56083L,56084L,56085L,56086L,56087L,
94631 56088L,56089L,56090L,56091L,56092L,56093L,56094L,56095L,56096L,56097L,
94632 56098L,56099L,56100L,56101L,56102L,56103L,56104L,56105L,56106L,56107L,
94633 56108L,56109L,56110L,56111L,56112L,56113L,56114L,56115L,56116L,56117L,
94634 56118L,56119L,56120L,56121L,56122L,56123L,56124L,56125L,56126L,56127L,
94635 56128L,56129L,56130L,56131L,56132L,56133L,56134L,56135L,56136L,56137L,
94636 56138L,56139L,56140L,56141L,56142L,56143L,56144L,56145L,56146L,56147L,
94637 56148L,56149L,56150L,56151L,56152L,56153L,56154L,56155L,56156L,56157L,
94638 56158L,56159L,56160L,56161L,56162L,56163L,56164L,56165L,56166L,56167L,
94639 56168L,56169L,56170L,56171L,56172L,56173L,56174L,56175L,56176L,56177L,
94640 56178L,56179L,56180L,56181L,56182L,56183L,56184L,56185L,56186L,56187L,
94641 56188L,56189L,56190L,56191L,56192L,56193L,56194L,56195L,56196L,56197L,
94642 56198L,56199L,56200L,56201L,56202L,56203L,56204L,56205L,56206L,56207L,
94643 56208L,56209L,56210L,56211L,56212L,56213L,56214L,56215L,56216L,56217L,
94644 56218L,56219L,56220L,56221L,56222L,56223L,56224L,56225L,56226L,56227L,
94645 56228L,56229L,56230L,56231L,56232L,56233L,56234L,56235L,56236L,56237L,
94646 56238L,56239L,56240L,56241L,56242L,56243L,56244L,56245L,56246L,56247L,
94647 56248L,56249L,56250L,56251L,56252L,56253L,56254L,56255L,56256L,56257L,
94648 56258L,56259L,56260L,56261L,56262L,56263L,56264L,56265L,56266L,56267L,
94649 56268L,56269L,56270L,56271L,56272L,56273L,56274L,56275L,56276L,56277L,
94650 56278L,56279L,56280L,56281L,56282L,56283L,56284L,56285L,56286L,56287L,
94651 56288L,56289L,56290L,56291L,56292L,56293L,56294L,56295L,56296L,56297L,
94652 56298L,56299L,56300L,56301L,56302L,56303L,56304L,56305L,56306L,56307L,
94653 56308L,56309L,56310L,56311L,56312L,56313L,56314L,56315L,56316L,56317L,
94654 56318L,56319L,56320L,56321L,56322L,56323L,56324L,56325L,56326L,56327L,
94655 56328L,56329L,56330L,56331L,56332L,56333L,56334L,56335L,56336L,56337L,
94656 56338L,56339L,56340L,56341L,56342L,56343L,56344L,56345L,56346L,56347L,
94657 56348L,56349L,56350L,56351L,56352L,56353L,56354L,56355L,56356L,56357L,
94658 56358L,56359L,56360L,56361L,56362L,56363L,56364L,56365L,56366L,56367L,
94659 56368L,56369L,56370L,56371L,56372L,56373L,56374L,56375L,56376L,56377L,
94660 56378L,56379L,56380L,56381L,56382L,56383L,56384L,56385L,56386L,56387L,
94661 56388L,56389L,56390L,56391L,56392L,56393L,56394L,56395L,56396L,56397L,
94662 56398L,56399L,56400L,56401L,56402L,56403L,56404L,56405L,56406L,56407L,
94663 56408L,56409L,56410L,56411L,56412L,56413L,56414L,56415L,56416L,56417L,
94664 56418L,56419L,56420L,56421L,56422L,56423L,56424L,56425L,56426L,56427L,
94665 56428L,56429L,56430L,56431L,56432L,56433L,56434L,56435L,56436L,56437L,
94666 56438L,56439L,56440L,56441L,56442L,56443L,56444L,56445L,56446L,56447L,
94667 56448L,56449L,56450L,56451L,56452L,56453L,56454L,56455L,56456L,56457L,
94668 56458L,56459L,56460L,56461L,56462L,56463L,56464L,56465L,56466L,56467L,
94669 56468L,56469L,56470L,56471L,56472L,56473L,56474L,56475L,56476L,56477L,
94670 56478L,56479L,56480L,56481L,56482L,56483L,56484L,56485L,56486L,56487L,
94671 56488L,56489L,56490L,56491L,56492L,56493L,56494L,56495L,56496L,56497L,
94672 56498L,56499L,56500L,56501L,56502L,56503L,56504L,56505L,56506L,56507L,
94673 56508L,56509L,56510L,56511L,56512L,56513L,56514L,56515L,56516L,56517L,
94674 56518L,56519L,56520L,56521L,56522L,56523L,56524L,56525L,56526L,56527L,
94675 56528L,56529L,56530L,56531L,56532L,56533L,56534L,56535L,56536L,56537L,
94676 56538L,56539L,56540L,56541L,56542L,56543L,56544L,56545L,56546L,56547L,
94677 56548L,56549L,56550L,56551L,56552L,56553L,56554L,56555L,56556L,56557L,
94678 56558L,56559L,56560L,56561L,56562L,56563L,56564L,56565L,56566L,56567L,
94679 56568L,56569L,56570L,56571L,56572L,56573L,56574L,56575L,56576L,56577L,
94680 56578L,56579L,56580L,56581L,56582L,56583L,56584L,56585L,56586L,56587L,
94681 56588L,56589L,56590L,56591L,56592L,56593L,56594L,56595L,56596L,56597L,
94682 56598L,56599L,56600L,56601L,56602L,56603L,56604L,56605L,56606L,56607L,
94683 56608L,56609L,56610L,56611L,56612L,56613L,56614L,56615L,56616L,56617L,
94684 56618L,56619L,56620L,56621L,56622L,56623L,56624L,56625L,56626L,56627L,
94685 56628L,56629L,56630L,56631L,56632L,56633L,56634L,56635L,56636L,56637L,
94686 56638L,56639L,56640L,56641L,56642L,56643L,56644L,56645L,56646L,56647L,
94687 56648L,56649L,56650L,56651L,56652L,56653L,56654L,56655L,56656L,56657L,
94688 56658L,56659L,56660L,56661L,56662L,56663L,56664L,56665L,56666L,56667L,
94689 56668L,56669L,56670L,56671L,56672L,56673L,56674L,56675L,56676L,56677L,
94690 56678L,56679L,56680L,56681L,56682L,56683L,56684L,56685L,56686L,56687L,
94691 56688L,56689L,56690L,56691L,56692L,56693L,56694L,56695L,56696L,56697L,
94692 56698L,56699L,56700L,56701L,56702L,56703L,56704L,56705L,56706L,56707L,
94693 56708L,56709L,56710L,56711L,56712L,56713L,56714L,56715L,56716L,56717L,
94694 56718L,56719L,56720L,56721L,56722L,56723L,56724L,56725L,56726L,56727L,
94695 56728L,56729L,56730L,56731L,56732L,56733L,56734L,56735L,56736L,56737L,
94696 56738L,56739L,56740L,56741L,56742L,56743L,56744L,56745L,56746L,56747L,
94697 56748L,56749L,56750L,56751L,56752L,56753L,56754L,56755L,56756L,56757L,
94698 56758L,56759L,56760L,56761L,56762L,56763L,56764L,56765L,56766L,56767L,
94699 56768L,56769L,56770L,56771L,56772L,56773L,56774L,56775L,56776L,56777L,
94700 56778L,56779L,56780L,56781L,56782L,56783L,56784L,56785L,56786L,56787L,
94701 56788L,56789L,56790L,56791L,56792L,56793L,56794L,56795L,56796L,56797L,
94702 56798L,56799L,56800L,56801L,56802L,56803L,56804L,56805L,56806L,56807L,
94703 56808L,56809L,56810L,56811L,56812L,56813L,56814L,56815L,56816L,56817L,
94704 56818L,56819L,56820L,56821L,56822L,56823L,56824L,56825L,56826L,56827L,
94705 56828L,56829L,56830L,56831L,56832L,56833L,56834L,56835L,56836L,56837L,
94706 56838L,56839L,56840L,56841L,56842L,56843L,56844L,56845L,56846L,56847L,
94707 56848L,56849L,56850L,56851L,56852L,56853L,56854L,56855L,56856L,56857L,
94708 56858L,56859L,56860L,56861L,56862L,56863L,56864L,56865L,56866L,56867L,
94709 56868L,56869L,56870L,56871L,56872L,56873L,56874L,56875L,56876L,56877L,
94710 56878L,56879L,56880L,56881L,56882L,56883L,56884L,56885L,56886L,56887L,
94711 56888L,56889L,56890L,56891L,56892L,56893L,56894L,56895L,56896L,56897L,
94712 56898L,56899L,56900L,56901L,56902L,56903L,56904L,56905L,56906L,56907L,
94713 56908L,56909L,56910L,56911L,56912L,56913L,56914L,56915L,56916L,56917L,
94714 56918L,56919L,56920L,56921L,56922L,56923L,56924L,56925L,56926L,56927L,
94715 56928L,56929L,56930L,56931L,56932L,56933L,56934L,56935L,56936L,56937L,
94716 56938L,56939L,56940L,56941L,56942L,56943L,56944L,56945L,56946L,56947L,
94717 56948L,56949L,56950L,56951L,56952L,56953L,56954L,56955L,56956L,56957L,
94718 56958L,56959L,56960L,56961L,56962L,56963L,56964L,56965L,56966L,56967L,
94719 56968L,56969L,56970L,56971L,56972L,56973L,56974L,56975L,56976L,56977L,
94720 56978L,56979L,56980L,56981L,56982L,56983L,56984L,56985L,56986L,56987L,
94721 56988L,56989L,56990L,56991L,56992L,56993L,56994L,56995L,56996L,56997L,
94722 56998L,56999L,57000L,57001L,57002L,57003L,57004L,57005L,57006L,57007L,
94723 57008L,57009L,57010L,57011L,57012L,57013L,57014L,57015L,57016L,57017L,
94724 57018L,57019L,57020L,57021L,57022L,57023L,57024L,57025L,57026L,57027L,
94725 57028L,57029L,57030L,57031L,57032L,57033L,57034L,57035L,57036L,57037L,
94726 57038L,57039L,57040L,57041L,57042L,57043L,57044L,57045L,57046L,57047L,
94727 57048L,57049L,57050L,57051L,57052L,57053L,57054L,57055L,57056L,57057L,
94728 57058L,57059L,57060L,57061L,57062L,57063L,57064L,57065L,57066L,57067L,
94729 57068L,57069L,57070L,57071L,57072L,57073L,57074L,57075L,57076L,57077L,
94730 57078L,57079L,57080L,57081L,57082L,57083L,57084L,57085L,57086L,57087L,
94731 57088L,57089L,57090L,57091L,57092L,57093L,57094L,57095L,57096L,57097L,
94732 57098L,57099L,57100L,57101L,57102L,57103L,57104L,57105L,57106L,57107L,
94733 57108L,57109L,57110L,57111L,57112L,57113L,57114L,57115L,57116L,57117L,
94734 57118L,57119L,57120L,57121L,57122L,57123L,57124L,57125L,57126L,57127L,
94735 57128L,57129L,57130L,57131L,57132L,57133L,57134L,57135L,57136L,57137L,
94736 57138L,57139L,57140L,57141L,57142L,57143L,57144L,57145L,57146L,57147L,
94737 57148L,57149L,57150L,57151L,57152L,57153L,57154L,57155L,57156L,57157L,
94738 57158L,57159L,57160L,57161L,57162L,57163L,57164L,57165L,57166L,57167L,
94739 57168L,57169L,57170L,57171L,57172L,57173L,57174L,57175L,57176L,57177L,
94740 57178L,57179L,57180L,57181L,57182L,57183L,57184L,57185L,57186L,57187L,
94741 57188L,57189L,57190L,57191L,57192L,57193L,57194L,57195L,57196L,57197L,
94742 57198L,57199L,57200L,57201L,57202L,57203L,57204L,57205L,57206L,57207L,
94743 57208L,57209L,57210L,57211L,57212L,57213L,57214L,57215L,57216L,57217L,
94744 57218L,57219L,57220L,57221L,57222L,57223L,57224L,57225L,57226L,57227L,
94745 57228L,57229L,57230L,57231L,57232L,57233L,57234L,57235L,57236L,57237L,
94746 57238L,57239L,57240L,57241L,57242L,57243L,57244L,57245L,57246L,57247L,
94747 57248L,57249L,57250L,57251L,57252L,57253L,57254L,57255L,57256L,57257L,
94748 57258L,57259L,57260L,57261L,57262L,57263L,57264L,57265L,57266L,57267L,
94749 57268L,57269L,57270L,57271L,57272L,57273L,57274L,57275L,57276L,57277L,
94750 57278L,57279L,57280L,57281L,57282L,57283L,57284L,57285L,57286L,57287L,
94751 57288L,57289L,57290L,57291L,57292L,57293L,57294L,57295L,57296L,57297L,
94752 57298L,57299L,57300L,57301L,57302L,57303L,57304L,57305L,57306L,57307L,
94753 57308L,57309L,57310L,57311L,57312L,57313L,57314L,57315L,57316L,57317L,
94754 57318L,57319L,57320L,57321L,57322L,57323L,57324L,57325L,57326L,57327L,
94755 57328L,57329L,57330L,57331L,57332L,57333L,57334L,57335L,57336L,57337L,
94756 57338L,57339L,57340L,57341L,57342L,57343L,57344L,57345L,57346L,57347L,
94757 57348L,57349L,57350L,57351L,57352L,57353L,57354L,57355L,57356L,57357L,
94758 57358L,57359L,57360L,57361L,57362L,57363L,57364L,57365L,57366L,57367L,
94759 57368L,57369L,57370L,57371L,57372L,57373L,57374L,57375L,57376L,57377L,
94760 57378L,57379L,57380L,57381L,57382L,57383L,57384L,57385L,57386L,57387L,
94761 57388L,57389L,57390L,57391L,57392L,57393L,57394L,57395L,57396L,57397L,
94762 57398L,57399L,57400L,57401L,57402L,57403L,57404L,57405L,57406L,57407L,
94763 57408L,57409L,57410L,57411L,57412L,57413L,57414L,57415L,57416L,57417L,
94764 57418L,57419L,57420L,57421L,57422L,57423L,57424L,57425L,57426L,57427L,
94765 57428L,57429L,57430L,57431L,57432L,57433L,57434L,57435L,57436L,57437L,
94766 57438L,57439L,57440L,57441L,57442L,57443L,57444L,57445L,57446L,57447L,
94767 57448L,57449L,57450L,57451L,57452L,57453L,57454L,57455L,57456L,57457L,
94768 57458L,57459L,57460L,57461L,57462L,57463L,57464L,57465L,57466L,57467L,
94769 57468L,57469L,57470L,57471L,57472L,57473L,57474L,57475L,57476L,57477L,
94770 57478L,57479L,57480L,57481L,57482L,57483L,57484L,57485L,57486L,57487L,
94771 57488L,57489L,57490L,57491L,57492L,57493L,57494L,57495L,57496L,57497L,
94772 57498L,57499L,57500L,57501L,57502L,57503L,57504L,57505L,57506L,57507L,
94773 57508L,57509L,57510L,57511L,57512L,57513L,57514L,57515L,57516L,57517L,
94774 57518L,57519L,57520L,57521L,57522L,57523L,57524L,57525L,57526L,57527L,
94775 57528L,57529L,57530L,57531L,57532L,57533L,57534L,57535L,57536L,57537L,
94776 57538L,57539L,57540L,57541L,57542L,57543L,57544L,57545L,57546L,57547L,
94777 57548L,57549L,57550L,57551L,57552L,57553L,57554L,57555L,57556L,57557L,
94778 57558L,57559L,57560L,57561L,57562L,57563L,57564L,57565L,57566L,57567L,
94779 57568L,57569L,57570L,57571L,57572L,57573L,57574L,57575L,57576L,57577L,
94780 57578L,57579L,57580L,57581L,57582L,57583L,57584L,57585L,57586L,57587L,
94781 57588L,57589L,57590L,57591L,57592L,57593L,57594L,57595L,57596L,57597L,
94782 57598L,57599L,57600L,57601L,57602L,57603L,57604L,57605L,57606L,57607L,
94783 57608L,57609L,57610L,57611L,57612L,57613L,57614L,57615L,57616L,57617L,
94784 57618L,57619L,57620L,57621L,57622L,57623L,57624L,57625L,57626L,57627L,
94785 57628L,57629L,57630L,57631L,57632L,57633L,57634L,57635L,57636L,57637L,
94786 57638L,57639L,57640L,57641L,57642L,57643L,57644L,57645L,57646L,57647L,
94787 57648L,57649L,57650L,57651L,57652L,57653L,57654L,57655L,57656L,57657L,
94788 57658L,57659L,57660L,57661L,57662L,57663L,57664L,57665L,57666L,57667L,
94789 57668L,57669L,57670L,57671L,57672L,57673L,57674L,57675L,57676L,57677L,
94790 57678L,57679L,57680L,57681L,57682L,57683L,57684L,57685L,57686L,57687L,
94791 57688L,57689L,57690L,57691L,57692L,57693L,57694L,57695L,57696L,57697L,
94792 57698L,57699L,57700L,57701L,57702L,57703L,57704L,57705L,57706L,57707L,
94793 57708L,57709L,57710L,57711L,57712L,57713L,57714L,57715L,57716L,57717L,
94794 57718L,57719L,57720L,57721L,57722L,57723L,57724L,57725L,57726L,57727L,
94795 57728L,57729L,57730L,57731L,57732L,57733L,57734L,57735L,57736L,57737L,
94796 57738L,57739L,57740L,57741L,57742L,57743L,57744L,57745L,57746L,57747L,
94797 57748L,57749L,57750L,57751L,57752L,57753L,57754L,57755L,57756L,57757L,
94798 57758L,57759L,57760L,57761L,57762L,57763L,57764L,57765L,57766L,57767L,
94799 57768L,57769L,57770L,57771L,57772L,57773L,57774L,57775L,57776L,57777L,
94800 57778L,57779L,57780L,57781L,57782L,57783L,57784L,57785L,57786L,57787L,
94801 57788L,57789L,57790L,57791L,57792L,57793L,57794L,57795L,57796L,57797L,
94802 57798L,57799L,57800L,57801L,57802L,57803L,57804L,57805L,57806L,57807L,
94803 57808L,57809L,57810L,57811L,57812L,57813L,57814L,57815L,57816L,57817L,
94804 57818L,57819L,57820L,57821L,57822L,57823L,57824L,57825L,57826L,57827L,
94805 57828L,57829L,57830L,57831L,57832L,57833L,57834L,57835L,57836L,57837L,
94806 57838L,57839L,57840L,57841L,57842L,57843L,57844L,57845L,57846L,57847L,
94807 57848L,57849L,57850L,57851L,57852L,57853L,57854L,57855L,57856L,57857L,
94808 57858L,57859L,57860L,57861L,57862L,57863L,57864L,57865L,57866L,57867L,
94809 57868L,57869L,57870L,57871L,57872L,57873L,57874L,57875L,57876L,57877L,
94810 57878L,57879L,57880L,57881L,57882L,57883L,57884L,57885L,57886L,57887L,
94811 57888L,57889L,57890L,57891L,57892L,57893L,57894L,57895L,57896L,57897L,
94812 57898L,57899L,57900L,57901L,57902L,57903L,57904L,57905L,57906L,57907L,
94813 57908L,57909L,57910L,57911L,57912L,57913L,57914L,57915L,57916L,57917L,
94814 57918L,57919L,57920L,57921L,57922L,57923L,57924L,57925L,57926L,57927L,
94815 57928L,57929L,57930L,57931L,57932L,57933L,57934L,57935L,57936L,57937L,
94816 57938L,57939L,57940L,57941L,57942L,57943L,57944L,57945L,57946L,57947L,
94817 57948L,57949L,57950L,57951L,57952L,57953L,57954L,57955L,57956L,57957L,
94818 57958L,57959L,57960L,57961L,57962L,57963L,57964L,57965L,57966L,57967L,
94819 57968L,57969L,57970L,57971L,57972L,57973L,57974L,57975L,57976L,57977L,
94820 57978L,57979L,57980L,57981L,57982L,57983L,57984L,57985L,57986L,57987L,
94821 57988L,57989L,57990L,57991L,57992L,57993L,57994L,57995L,57996L,57997L,
94822 57998L,57999L,58000L,58001L,58002L,58003L,58004L,58005L,58006L,58007L,
94823 58008L,58009L,58010L,58011L,58012L,58013L,58014L,58015L,58016L,58017L,
94824 58018L,58019L,58020L,58021L,58022L,58023L,58024L,58025L,58026L,58027L,
94825 58028L,58029L,58030L,58031L,58032L,58033L,58034L,58035L,58036L,58037L,
94826 58038L,58039L,58040L,58041L,58042L,58043L,58044L,58045L,58046L,58047L,
94827 58048L,58049L,58050L,58051L,58052L,58053L,58054L,58055L,58056L,58057L,
94828 58058L,58059L,58060L,58061L,58062L,58063L,58064L,58065L,58066L,58067L,
94829 58068L,58069L,58070L,58071L,58072L,58073L,58074L,58075L,58076L,58077L,
94830 58078L,58079L,58080L,58081L,58082L,58083L,58084L,58085L,58086L,58087L,
94831 58088L,58089L,58090L,58091L,58092L,58093L,58094L,58095L,58096L,58097L,
94832 58098L,58099L,58100L,58101L,58102L,58103L,58104L,58105L,58106L,58107L,
94833 58108L,58109L,58110L,58111L,58112L,58113L,58114L,58115L,58116L,58117L,
94834 58118L,58119L,58120L,58121L,58122L,58123L,58124L,58125L,58126L,58127L,
94835 58128L,58129L,58130L,58131L,58132L,58133L,58134L,58135L,58136L,58137L,
94836 58138L,58139L,58140L,58141L,58142L,58143L,58144L,58145L,58146L,58147L,
94837 58148L,58149L,58150L,58151L,58152L,58153L,58154L,58155L,58156L,58157L,
94838 58158L,58159L,58160L,58161L,58162L,58163L,58164L,58165L,58166L,58167L,
94839 58168L,58169L,58170L,58171L,58172L,58173L,58174L,58175L,58176L,58177L,
94840 58178L,58179L,58180L,58181L,58182L,58183L,58184L,58185L,58186L,58187L,
94841 58188L,58189L,58190L,58191L,58192L,58193L,58194L,58195L,58196L,58197L,
94842 58198L,58199L,58200L,58201L,58202L,58203L,58204L,58205L,58206L,58207L,
94843 58208L,58209L,58210L,58211L,58212L,58213L,58214L,58215L,58216L,58217L,
94844 58218L,58219L,58220L,58221L,58222L,58223L,58224L,58225L,58226L,58227L,
94845 58228L,58229L,58230L,58231L,58232L,58233L,58234L,58235L,58236L,58237L,
94846 58238L,58239L,58240L,58241L,58242L,58243L,58244L,58245L,58246L,58247L,
94847 58248L,58249L,58250L,58251L,58252L,58253L,58254L,58255L,58256L,58257L,
94848 58258L,58259L,58260L,58261L,58262L,58263L,58264L,58265L,58266L,58267L,
94849 58268L,58269L,58270L,58271L,58272L,58273L,58274L,58275L,58276L,58277L,
94850 58278L,58279L,58280L,58281L,58282L,58283L,58284L,58285L,58286L,58287L,
94851 58288L,58289L,58290L,58291L,58292L,58293L,58294L,58295L,58296L,58297L,
94852 58298L,58299L,58300L,58301L,58302L,58303L,58304L,58305L,58306L,58307L,
94853 58308L,58309L,58310L,58311L,58312L,58313L,58314L,58315L,58316L,58317L,
94854 58318L,58319L,58320L,58321L,58322L,58323L,58324L,58325L,58326L,58327L,
94855 58328L,58329L,58330L,58331L,58332L,58333L,58334L,58335L,58336L,58337L,
94856 58338L,58339L,58340L,58341L,58342L,58343L,58344L,58345L,58346L,58347L,
94857 58348L,58349L,58350L,58351L,58352L,58353L,58354L,58355L,58356L,58357L,
94858 58358L,58359L,58360L,58361L,58362L,58363L,58364L,58365L,58366L,58367L,
94859 58368L,58369L,58370L,58371L,58372L,58373L,58374L,58375L,58376L,58377L,
94860 58378L,58379L,58380L,58381L,58382L,58383L,58384L,58385L,58386L,58387L,
94861 58388L,58389L,58390L,58391L,58392L,58393L,58394L,58395L,58396L,58397L,
94862 58398L,58399L,58400L,58401L,58402L,58403L,58404L,58405L,58406L,58407L,
94863 58408L,58409L,58410L,58411L,58412L,58413L,58414L,58415L,58416L,58417L,
94864 58418L,58419L,58420L,58421L,58422L,58423L,58424L,58425L,58426L,58427L,
94865 58428L,58429L,58430L,58431L,58432L,58433L,58434L,58435L,58436L,58437L,
94866 58438L,58439L,58440L,58441L,58442L,58443L,58444L,58445L,58446L,58447L,
94867 58448L,58449L,58450L,58451L,58452L,58453L,58454L,58455L,58456L,58457L,
94868 58458L,58459L,58460L,58461L,58462L,58463L,58464L,58465L,58466L,58467L,
94869 58468L,58469L,58470L,58471L,58472L,58473L,58474L,58475L,58476L,58477L,
94870 58478L,58479L,58480L,58481L,58482L,58483L,58484L,58485L,58486L,58487L,
94871 58488L,58489L,58490L,58491L,58492L,58493L,58494L,58495L,58496L,58497L,
94872 58498L,58499L,58500L,58501L,58502L,58503L,58504L,58505L,58506L,58507L,
94873 58508L,58509L,58510L,58511L,58512L,58513L,58514L,58515L,58516L,58517L,
94874 58518L,58519L,58520L,58521L,58522L,58523L,58524L,58525L,58526L,58527L,
94875 58528L,58529L,58530L,58531L,58532L,58533L,58534L,58535L,58536L,58537L,
94876 58538L,58539L,58540L,58541L,58542L,58543L,58544L,58545L,58546L,58547L,
94877 58548L,58549L,58550L,58551L,58552L,58553L,58554L,58555L,58556L,58557L,
94878 58558L,58559L,58560L,58561L,58562L,58563L,58564L,58565L,58566L,58567L,
94879 58568L,58569L,58570L,58571L,58572L,58573L,58574L,58575L,58576L,58577L,
94880 58578L,58579L,58580L,58581L,58582L,58583L,58584L,58585L,58586L,58587L,
94881 58588L,58589L,58590L,58591L,58592L,58593L,58594L,58595L,58596L,58597L,
94882 58598L,58599L,58600L,58601L,58602L,58603L,58604L,58605L,58606L,58607L,
94883 58608L,58609L,58610L,58611L,58612L,58613L,58614L,58615L,58616L,58617L,
94884 58618L,58619L,58620L,58621L,58622L,58623L,58624L,58625L,58626L,58627L,
94885 58628L,58629L,58630L,58631L,58632L,58633L,58634L,58635L,58636L,58637L,
94886 58638L,58639L,58640L,58641L,58642L,58643L,58644L,58645L,58646L,58647L,
94887 58648L,58649L,58650L,58651L,58652L,58653L,58654L,58655L,58656L,58657L,
94888 58658L,58659L,58660L,58661L,58662L,58663L,58664L,58665L,58666L,58667L,
94889 58668L,58669L,58670L,58671L,58672L,58673L,58674L,58675L,58676L,58677L,
94890 58678L,58679L,58680L,58681L,58682L,58683L,58684L,58685L,58686L,58687L,
94891 58688L,58689L,58690L,58691L,58692L,58693L,58694L,58695L,58696L,58697L,
94892 58698L,58699L,58700L,58701L,58702L,58703L,58704L,58705L,58706L,58707L,
94893 58708L,58709L,58710L,58711L,58712L,58713L,58714L,58715L,58716L,58717L,
94894 58718L,58719L,58720L,58721L,58722L,58723L,58724L,58725L,58726L,58727L,
94895 58728L,58729L,58730L,58731L,58732L,58733L,58734L,58735L,58736L,58737L,
94896 58738L,58739L,58740L,58741L,58742L,58743L,58744L,58745L,58746L,58747L,
94897 58748L,58749L,58750L,58751L,58752L,58753L,58754L,58755L,58756L,58757L,
94898 58758L,58759L,58760L,58761L,58762L,58763L,58764L,58765L,58766L,58767L,
94899 58768L,58769L,58770L,58771L,58772L,58773L,58774L,58775L,58776L,58777L,
94900 58778L,58779L,58780L,58781L,58782L,58783L,58784L,58785L,58786L,58787L,
94901 58788L,58789L,58790L,58791L,58792L,58793L,58794L,58795L,58796L,58797L,
94902 58798L,58799L,58800L,58801L,58802L,58803L,58804L,58805L,58806L,58807L,
94903 58808L,58809L,58810L,58811L,58812L,58813L,58814L,58815L,58816L,58817L,
94904 58818L,58819L,58820L,58821L,58822L,58823L,58824L,58825L,58826L,58827L,
94905 58828L,58829L,58830L,58831L,58832L,58833L,58834L,58835L,58836L,58837L,
94906 58838L,58839L,58840L,58841L,58842L,58843L,58844L,58845L,58846L,58847L,
94907 58848L,58849L,58850L,58851L,58852L,58853L,58854L,58855L,58856L,58857L,
94908 58858L,58859L,58860L,58861L,58862L,58863L,58864L,58865L,58866L,58867L,
94909 58868L,58869L,58870L,58871L,58872L,58873L,58874L,58875L,58876L,58877L,
94910 58878L,58879L,58880L,58881L,58882L,58883L,58884L,58885L,58886L,58887L,
94911 58888L,58889L,58890L,58891L,58892L,58893L,58894L,58895L,58896L,58897L,
94912 58898L,58899L,58900L,58901L,58902L,58903L,58904L,58905L,58906L,58907L,
94913 58908L,58909L,58910L,58911L,58912L,58913L,58914L,58915L,58916L,58917L,
94914 58918L,58919L,58920L,58921L,58922L,58923L,58924L,58925L,58926L,58927L,
94915 58928L,58929L,58930L,58931L,58932L,58933L,58934L,58935L,58936L,58937L,
94916 58938L,58939L,58940L,58941L,58942L,58943L,58944L,58945L,58946L,58947L,
94917 58948L,58949L,58950L,58951L,58952L,58953L,58954L,58955L,58956L,58957L,
94918 58958L,58959L,58960L,58961L,58962L,58963L,58964L,58965L,58966L,58967L,
94919 58968L,58969L,58970L,58971L,58972L,58973L,58974L,58975L,58976L,58977L,
94920 58978L,58979L,58980L,58981L,58982L,58983L,58984L,58985L,58986L,58987L,
94921 58988L,58989L,58990L,58991L,58992L,58993L,58994L,58995L,58996L,58997L,
94922 58998L,58999L,59000L,59001L,59002L,59003L,59004L,59005L,59006L,59007L,
94923 59008L,59009L,59010L,59011L,59012L,59013L,59014L,59015L,59016L,59017L,
94924 59018L,59019L,59020L,59021L,59022L,59023L,59024L,59025L,59026L,59027L,
94925 59028L,59029L,59030L,59031L,59032L,59033L,59034L,59035L,59036L,59037L,
94926 59038L,59039L,59040L,59041L,59042L,59043L,59044L,59045L,59046L,59047L,
94927 59048L,59049L,59050L,59051L,59052L,59053L,59054L,59055L,59056L,59057L,
94928 59058L,59059L,59060L,59061L,59062L,59063L,59064L,59065L,59066L,59067L,
94929 59068L,59069L,59070L,59071L,59072L,59073L,59074L,59075L,59076L,59077L,
94930 59078L,59079L,59080L,59081L,59082L,59083L,59084L,59085L,59086L,59087L,
94931 59088L,59089L,59090L,59091L,59092L,59093L,59094L,59095L,59096L,59097L,
94932 59098L,59099L,59100L,59101L,59102L,59103L,59104L,59105L,59106L,59107L,
94933 59108L,59109L,59110L,59111L,59112L,59113L,59114L,59115L,59116L,59117L,
94934 59118L,59119L,59120L,59121L,59122L,59123L,59124L,59125L,59126L,59127L,
94935 59128L,59129L,59130L,59131L,59132L,59133L,59134L,59135L,59136L,59137L,
94936 59138L,59139L,59140L,59141L,59142L,59143L,59144L,59145L,59146L,59147L,
94937 59148L,59149L,59150L,59151L,59152L,59153L,59154L,59155L,59156L,59157L,
94938 59158L,59159L,59160L,59161L,59162L,59163L,59164L,59165L,59166L,59167L,
94939 59168L,59169L,59170L,59171L,59172L,59173L,59174L,59175L,59176L,59177L,
94940 59178L,59179L,59180L,59181L,59182L,59183L,59184L,59185L,59186L,59187L,
94941 59188L,59189L,59190L,59191L,59192L,59193L,59194L,59195L,59196L,59197L,
94942 59198L,59199L,59200L,59201L,59202L,59203L,59204L,59205L,59206L,59207L,
94943 59208L,59209L,59210L,59211L,59212L,59213L,59214L,59215L,59216L,59217L,
94944 59218L,59219L,59220L,59221L,59222L,59223L,59224L,59225L,59226L,59227L,
94945 59228L,59229L,59230L,59231L,59232L,59233L,59234L,59235L,59236L,59237L,
94946 59238L,59239L,59240L,59241L,59242L,59243L,59244L,59245L,59246L,59247L,
94947 59248L,59249L,59250L,59251L,59252L,59253L,59254L,59255L,59256L,59257L,
94948 59258L,59259L,59260L,59261L,59262L,59263L,59264L,59265L,59266L,59267L,
94949 59268L,59269L,59270L,59271L,59272L,59273L,59274L,59275L,59276L,59277L,
94950 59278L,59279L,59280L,59281L,59282L,59283L,59284L,59285L,59286L,59287L,
94951 59288L,59289L,59290L,59291L,59292L,59293L,59294L,59295L,59296L,59297L,
94952 59298L,59299L,59300L,59301L,59302L,59303L,59304L,59305L,59306L,59307L,
94953 59308L,59309L,59310L,59311L,59312L,59313L,59314L,59315L,59316L,59317L,
94954 59318L,59319L,59320L,59321L,59322L,59323L,59324L,59325L,59326L,59327L,
94955 59328L,59329L,59330L,59331L,59332L,59333L,59334L,59335L,59336L,59337L,
94956 59338L,59339L,59340L,59341L,59342L,59343L,59344L,59345L,59346L,59347L,
94957 59348L,59349L,59350L,59351L,59352L,59353L,59354L,59355L,59356L,59357L,
94958 59358L,59359L,59360L,59361L,59362L,59363L,59364L,59365L,59366L,59367L,
94959 59368L,59369L,59370L,59371L,59372L,59373L,59374L,59375L,59376L,59377L,
94960 59378L,59379L,59380L,59381L,59382L,59383L,59384L,59385L,59386L,59387L,
94961 59388L,59389L,59390L,59391L,59392L,59393L,59394L,59395L,59396L,59397L,
94962 59398L,59399L,59400L,59401L,59402L,59403L,59404L,59405L,59406L,59407L,
94963 59408L,59409L,59410L,59411L,59412L,59413L,59414L,59415L,59416L,59417L,
94964 59418L,59419L,59420L,59421L,59422L,59423L,59424L,59425L,59426L,59427L,
94965 59428L,59429L,59430L,59431L,59432L,59433L,59434L,59435L,59436L,59437L,
94966 59438L,59439L,59440L,59441L,59442L,59443L,59444L,59445L,59446L,59447L,
94967 59448L,59449L,59450L,59451L,59452L,59453L,59454L,59455L,59456L,59457L,
94968 59458L,59459L,59460L,59461L,59462L,59463L,59464L,59465L,59466L,59467L,
94969 59468L,59469L,59470L,59471L,59472L,59473L,59474L,59475L,59476L,59477L,
94970 59478L,59479L,59480L,59481L,59482L,59483L,59484L,59485L,59486L,59487L,
94971 59488L,59489L,59490L,59491L,59492L,59493L,59494L,59495L,59496L,59497L,
94972 59498L,59499L,59500L,59501L,59502L,59503L,59504L,59505L,59506L,59507L,
94973 59508L,59509L,59510L,59511L,59512L,59513L,59514L,59515L,59516L,59517L,
94974 59518L,59519L,59520L,59521L,59522L,59523L,59524L,59525L,59526L,59527L,
94975 59528L,59529L,59530L,59531L,59532L,59533L,59534L,59535L,59536L,59537L,
94976 59538L,59539L,59540L,59541L,59542L,59543L,59544L,59545L,59546L,59547L,
94977 59548L,59549L,59550L,59551L,59552L,59553L,59554L,59555L,59556L,59557L,
94978 59558L,59559L,59560L,59561L,59562L,59563L,59564L,59565L,59566L,59567L,
94979 59568L,59569L,59570L,59571L,59572L,59573L,59574L,59575L,59576L,59577L,
94980 59578L,59579L,59580L,59581L,59582L,59583L,59584L,59585L,59586L,59587L,
94981 59588L,59589L,59590L,59591L,59592L,59593L,59594L,59595L,59596L,59597L,
94982 59598L,59599L,59600L,59601L,59602L,59603L,59604L,59605L,59606L,59607L,
94983 59608L,59609L,59610L,59611L,59612L,59613L,59614L,59615L,59616L,59617L,
94984 59618L,59619L,59620L,59621L,59622L,59623L,59624L,59625L,59626L,59627L,
94985 59628L,59629L,59630L,59631L,59632L,59633L,59634L,59635L,59636L,59637L,
94986 59638L,59639L,59640L,59641L,59642L,59643L,59644L,59645L,59646L,59647L,
94987 59648L,59649L,59650L,59651L,59652L,59653L,59654L,59655L,59656L,59657L,
94988 59658L,59659L,59660L,59661L,59662L,59663L,59664L,59665L,59666L,59667L,
94989 59668L,59669L,59670L,59671L,59672L,59673L,59674L,59675L,59676L,59677L,
94990 59678L,59679L,59680L,59681L,59682L,59683L,59684L,59685L,59686L,59687L,
94991 59688L,59689L,59690L,59691L,59692L,59693L,59694L,59695L,59696L,59697L,
94992 59698L,59699L,59700L,59701L,59702L,59703L,59704L,59705L,59706L,59707L,
94993 59708L,59709L,59710L,59711L,59712L,59713L,59714L,59715L,59716L,59717L,
94994 59718L,59719L,59720L,59721L,59722L,59723L,59724L,59725L,59726L,59727L,
94995 59728L,59729L,59730L,59731L,59732L,59733L,59734L,59735L,59736L,59737L,
94996 59738L,59739L,59740L,59741L,59742L,59743L,59744L,59745L,59746L,59747L,
94997 59748L,59749L,59750L,59751L,59752L,59753L,59754L,59755L,59756L,59757L,
94998 59758L,59759L,59760L,59761L,59762L,59763L,59764L,59765L,59766L,59767L,
94999 59768L,59769L,59770L,59771L,59772L,59773L,59774L,59775L,59776L,59777L,
95000 59778L,59779L,59780L,59781L,59782L,59783L,59784L,59785L,59786L,59787L,
95001 59788L,59789L,59790L,59791L,59792L,59793L,59794L,59795L,59796L,59797L,
95002 59798L,59799L,59800L,59801L,59802L,59803L,59804L,59805L,59806L,59807L,
95003 59808L,59809L,59810L,59811L,59812L,59813L,59814L,59815L,59816L,59817L,
95004 59818L,59819L,59820L,59821L,59822L,59823L,59824L,59825L,59826L,59827L,
95005 59828L,59829L,59830L,59831L,59832L,59833L,59834L,59835L,59836L,59837L,
95006 59838L,59839L,59840L,59841L,59842L,59843L,59844L,59845L,59846L,59847L,
95007 59848L,59849L,59850L,59851L,59852L,59853L,59854L,59855L,59856L,59857L,
95008 59858L,59859L,59860L,59861L,59862L,59863L,59864L,59865L,59866L,59867L,
95009 59868L,59869L,59870L,59871L,59872L,59873L,59874L,59875L,59876L,59877L,
95010 59878L,59879L,59880L,59881L,59882L,59883L,59884L,59885L,59886L,59887L,
95011 59888L,59889L,59890L,59891L,59892L,59893L,59894L,59895L,59896L,59897L,
95012 59898L,59899L,59900L,59901L,59902L,59903L,59904L,59905L,59906L,59907L,
95013 59908L,59909L,59910L,59911L,59912L,59913L,59914L,59915L,59916L,59917L,
95014 59918L,59919L,59920L,59921L,59922L,59923L,59924L,59925L,59926L,59927L,
95015 59928L,59929L,59930L,59931L,59932L,59933L,59934L,59935L,59936L,59937L,
95016 59938L,59939L,59940L,59941L,59942L,59943L,59944L,59945L,59946L,59947L,
95017 59948L,59949L,59950L,59951L,59952L,59953L,59954L,59955L,59956L,59957L,
95018 59958L,59959L,59960L,59961L,59962L,59963L,59964L,59965L,59966L,59967L,
95019 59968L,59969L,59970L,59971L,59972L,59973L,59974L,59975L,59976L,59977L,
95020 59978L,59979L,59980L,59981L,59982L,59983L,59984L,59985L,59986L,59987L,
95021 59988L,59989L,59990L,59991L,59992L,59993L,59994L,59995L,59996L,59997L,
95022 59998L,59999L,60000L,60001L,60002L,60003L,60004L,60005L,60006L,60007L,
95023 60008L,60009L,60010L,60011L,60012L,60013L,60014L,60015L,60016L,60017L,
95024 60018L,60019L,60020L,60021L,60022L,60023L,60024L,60025L,60026L,60027L,
95025 60028L,60029L,60030L,60031L,60032L,60033L,60034L,60035L,60036L,60037L,
95026 60038L,60039L,60040L,60041L,60042L,60043L,60044L,60045L,60046L,60047L,
95027 60048L,60049L,60050L,60051L,60052L,60053L,60054L,60055L,60056L,60057L,
95028 60058L,60059L,60060L,60061L,60062L,60063L,60064L,60065L,60066L,60067L,
95029 60068L,60069L,60070L,60071L,60072L,60073L,60074L,60075L,60076L,60077L,
95030 60078L,60079L,60080L,60081L,60082L,60083L,60084L,60085L,60086L,60087L,
95031 60088L,60089L,60090L,60091L,60092L,60093L,60094L,60095L,60096L,60097L,
95032 60098L,60099L,60100L,60101L,60102L,60103L,60104L,60105L,60106L,60107L,
95033 60108L,60109L,60110L,60111L,60112L,60113L,60114L,60115L,60116L,60117L,
95034 60118L,60119L,60120L,60121L,60122L,60123L,60124L,60125L,60126L,60127L,
95035 60128L,60129L,60130L,60131L,60132L,60133L,60134L,60135L,60136L,60137L,
95036 60138L,60139L,60140L,60141L,60142L,60143L,60144L,60145L,60146L,60147L,
95037 60148L,60149L,60150L,60151L,60152L,60153L,60154L,60155L,60156L,60157L,
95038 60158L,60159L,60160L,60161L,60162L,60163L,60164L,60165L,60166L,60167L,
95039 60168L,60169L,60170L,60171L,60172L,60173L,60174L,60175L,60176L,60177L,
95040 60178L,60179L,60180L,60181L,60182L,60183L,60184L,60185L,60186L,60187L,
95041 60188L,60189L,60190L,60191L,60192L,60193L,60194L,60195L,60196L,60197L,
95042 60198L,60199L,60200L,60201L,60202L,60203L,60204L,60205L,60206L,60207L,
95043 60208L,60209L,60210L,60211L,60212L,60213L,60214L,60215L,60216L,60217L,
95044 60218L,60219L,60220L,60221L,60222L,60223L,60224L,60225L,60226L,60227L,
95045 60228L,60229L,60230L,60231L,60232L,60233L,60234L,60235L,60236L,60237L,
95046 60238L,60239L,60240L,60241L,60242L,60243L,60244L,60245L,60246L,60247L,
95047 60248L,60249L,60250L,60251L,60252L,60253L,60254L,60255L,60256L,60257L,
95048 60258L,60259L,60260L,60261L,60262L,60263L,60264L,60265L,60266L,60267L,
95049 60268L,60269L,60270L,60271L,60272L,60273L,60274L,60275L,60276L,60277L,
95050 60278L,60279L,60280L,60281L,60282L,60283L,60284L,60285L,60286L,60287L,
95051 60288L,60289L,60290L,60291L,60292L,60293L,60294L,60295L,60296L,60297L,
95052 60298L,60299L,60300L,60301L,60302L,60303L,60304L,60305L,60306L,60307L,
95053 60308L,60309L,60310L,60311L,60312L,60313L,60314L,60315L,60316L,60317L,
95054 60318L,60319L,60320L,60321L,60322L,60323L,60324L,60325L,60326L,60327L,
95055 60328L,60329L,60330L,60331L,60332L,60333L,60334L,60335L,60336L,60337L,
95056 60338L,60339L,60340L,60341L,60342L,60343L,60344L,60345L,60346L,60347L,
95057 60348L,60349L,60350L,60351L,60352L,60353L,60354L,60355L,60356L,60357L,
95058 60358L,60359L,60360L,60361L,60362L,60363L,60364L,60365L,60366L,60367L,
95059 60368L,60369L,60370L,60371L,60372L,60373L,60374L,60375L,60376L,60377L,
95060 60378L,60379L,60380L,60381L,60382L,60383L,60384L,60385L,60386L,60387L,
95061 60388L,60389L,60390L,60391L,60392L,60393L,60394L,60395L,60396L,60397L,
95062 60398L,60399L,60400L,60401L,60402L,60403L,60404L,60405L,60406L,60407L,
95063 60408L,60409L,60410L,60411L,60412L,60413L,60414L,60415L,60416L,60417L,
95064 60418L,60419L,60420L,60421L,60422L,60423L,60424L,60425L,60426L,60427L,
95065 60428L,60429L,60430L,60431L,60432L,60433L,60434L,60435L,60436L,60437L,
95066 60438L,60439L,60440L,60441L,60442L,60443L,60444L,60445L,60446L,60447L,
95067 60448L,60449L,60450L,60451L,60452L,60453L,60454L,60455L,60456L,60457L,
95068 60458L,60459L,60460L,60461L,60462L,60463L,60464L,60465L,60466L,60467L,
95069 60468L,60469L,60470L,60471L,60472L,60473L,60474L,60475L,60476L,60477L,
95070 60478L,60479L,60480L,60481L,60482L,60483L,60484L,60485L,60486L,60487L,
95071 60488L,60489L,60490L,60491L,60492L,60493L,60494L,60495L,60496L,60497L,
95072 60498L,60499L,60500L,60501L,60502L,60503L,60504L,60505L,60506L,60507L,
95073 60508L,60509L,60510L,60511L,60512L,60513L,60514L,60515L,60516L,60517L,
95074 60518L,60519L,60520L,60521L,60522L,60523L,60524L,60525L,60526L,60527L,
95075 60528L,60529L,60530L,60531L,60532L,60533L,60534L,60535L,60536L,60537L,
95076 60538L,60539L,60540L,60541L,60542L,60543L,60544L,60545L,60546L,60547L,
95077 60548L,60549L,60550L,60551L,60552L,60553L,60554L,60555L,60556L,60557L,
95078 60558L,60559L,60560L,60561L,60562L,60563L,60564L,60565L,60566L,60567L,
95079 60568L,60569L,60570L,60571L,60572L,60573L,60574L,60575L,60576L,60577L,
95080 60578L,60579L,60580L,60581L,60582L,60583L,60584L,60585L,60586L,60587L,
95081 60588L,60589L,60590L,60591L,60592L,60593L,60594L,60595L,60596L,60597L,
95082 60598L,60599L,60600L,60601L,60602L,60603L,60604L,60605L,60606L,60607L,
95083 60608L,60609L,60610L,60611L,60612L,60613L,60614L,60615L,60616L,60617L,
95084 60618L,60619L,60620L,60621L,60622L,60623L,60624L,60625L,60626L,60627L,
95085 60628L,60629L,60630L,60631L,60632L,60633L,60634L,60635L,60636L,60637L,
95086 60638L,60639L,60640L,60641L,60642L,60643L,60644L,60645L,60646L,60647L,
95087 60648L,60649L,60650L,60651L,60652L,60653L,60654L,60655L,60656L,60657L,
95088 60658L,60659L,60660L,60661L,60662L,60663L,60664L,60665L,60666L,60667L,
95089 60668L,60669L,60670L,60671L,60672L,60673L,60674L,60675L,60676L,60677L,
95090 60678L,60679L,60680L,60681L,60682L,60683L,60684L,60685L,60686L,60687L,
95091 60688L,60689L,60690L,60691L,60692L,60693L,60694L,60695L,60696L,60697L,
95092 60698L,60699L,60700L,60701L,60702L,60703L,60704L,60705L,60706L,60707L,
95093 60708L,60709L,60710L,60711L,60712L,60713L,60714L,60715L,60716L,60717L,
95094 60718L,60719L,60720L,60721L,60722L,60723L,60724L,60725L,60726L,60727L,
95095 60728L,60729L,60730L,60731L,60732L,60733L,60734L,60735L,60736L,60737L,
95096 60738L,60739L,60740L,60741L,60742L,60743L,60744L,60745L,60746L,60747L,
95097 60748L,60749L,60750L,60751L,60752L,60753L,60754L,60755L,60756L,60757L,
95098 60758L,60759L,60760L,60761L,60762L,60763L,60764L,60765L,60766L,60767L,
95099 60768L,60769L,60770L,60771L,60772L,60773L,60774L,60775L,60776L,60777L,
95100 60778L,60779L,60780L,60781L,60782L,60783L,60784L,60785L,60786L,60787L,
95101 60788L,60789L,60790L,60791L,60792L,60793L,60794L,60795L,60796L,60797L,
95102 60798L,60799L,60800L,60801L,60802L,60803L,60804L,60805L,60806L,60807L,
95103 60808L,60809L,60810L,60811L,60812L,60813L,60814L,60815L,60816L,60817L,
95104 60818L,60819L,60820L,60821L,60822L,60823L,60824L,60825L,60826L,60827L,
95105 60828L,60829L,60830L,60831L,60832L,60833L,60834L,60835L,60836L,60837L,
95106 60838L,60839L,60840L,60841L,60842L,60843L,60844L,60845L,60846L,60847L,
95107 60848L,60849L,60850L,60851L,60852L,60853L,60854L,60855L,60856L,60857L,
95108 60858L,60859L,60860L,60861L,60862L,60863L,60864L,60865L,60866L,60867L,
95109 60868L,60869L,60870L,60871L,60872L,60873L,60874L,60875L,60876L,60877L,
95110 60878L,60879L,60880L,60881L,60882L,60883L,60884L,60885L,60886L,60887L,
95111 60888L,60889L,60890L,60891L,60892L,60893L,60894L,60895L,60896L,60897L,
95112 60898L,60899L,60900L,60901L,60902L,60903L,60904L,60905L,60906L,60907L,
95113 60908L,60909L,60910L,60911L,60912L,60913L,60914L,60915L,60916L,60917L,
95114 60918L,60919L,60920L,60921L,60922L,60923L,60924L,60925L,60926L,60927L,
95115 60928L,60929L,60930L,60931L,60932L,60933L,60934L,60935L,60936L,60937L,
95116 60938L,60939L,60940L,60941L,60942L,60943L,60944L,60945L,60946L,60947L,
95117 60948L,60949L,60950L,60951L,60952L,60953L,60954L,60955L,60956L,60957L,
95118 60958L,60959L,60960L,60961L,60962L,60963L,60964L,60965L,60966L,60967L,
95119 60968L,60969L,60970L,60971L,60972L,60973L,60974L,60975L,60976L,60977L,
95120 60978L,60979L,60980L,60981L,60982L,60983L,60984L,60985L,60986L,60987L,
95121 60988L,60989L,60990L,60991L,60992L,60993L,60994L,60995L,60996L,60997L,
95122 60998L,60999L,61000L,61001L,61002L,61003L,61004L,61005L,61006L,61007L,
95123 61008L,61009L,61010L,61011L,61012L,61013L,61014L,61015L,61016L,61017L,
95124 61018L,61019L,61020L,61021L,61022L,61023L,61024L,61025L,61026L,61027L,
95125 61028L,61029L,61030L,61031L,61032L,61033L,61034L,61035L,61036L,61037L,
95126 61038L,61039L,61040L,61041L,61042L,61043L,61044L,61045L,61046L,61047L,
95127 61048L,61049L,61050L,61051L,61052L,61053L,61054L,61055L,61056L,61057L,
95128 61058L,61059L,61060L,61061L,61062L,61063L,61064L,61065L,61066L,61067L,
95129 61068L,61069L,61070L,61071L,61072L,61073L,61074L,61075L,61076L,61077L,
95130 61078L,61079L,61080L,61081L,61082L,61083L,61084L,61085L,61086L,61087L,
95131 61088L,61089L,61090L,61091L,61092L,61093L,61094L,61095L,61096L,61097L,
95132 61098L,61099L,61100L,61101L,61102L,61103L,61104L,61105L,61106L,61107L,
95133 61108L,61109L,61110L,61111L,61112L,61113L,61114L,61115L,61116L,61117L,
95134 61118L,61119L,61120L,61121L,61122L,61123L,61124L,61125L,61126L,61127L,
95135 61128L,61129L,61130L,61131L,61132L,61133L,61134L,61135L,61136L,61137L,
95136 61138L,61139L,61140L,61141L,61142L,61143L,61144L,61145L,61146L,61147L,
95137 61148L,61149L,61150L,61151L,61152L,61153L,61154L,61155L,61156L,61157L,
95138 61158L,61159L,61160L,61161L,61162L,61163L,61164L,61165L,61166L,61167L,
95139 61168L,61169L,61170L,61171L,61172L,61173L,61174L,61175L,61176L,61177L,
95140 61178L,61179L,61180L,61181L,61182L,61183L,61184L,61185L,61186L,61187L,
95141 61188L,61189L,61190L,61191L,61192L,61193L,61194L,61195L,61196L,61197L,
95142 61198L,61199L,61200L,61201L,61202L,61203L,61204L,61205L,61206L,61207L,
95143 61208L,61209L,61210L,61211L,61212L,61213L,61214L,61215L,61216L,61217L,
95144 61218L,61219L,61220L,61221L,61222L,61223L,61224L,61225L,61226L,61227L,
95145 61228L,61229L,61230L,61231L,61232L,61233L,61234L,61235L,61236L,61237L,
95146 61238L,61239L,61240L,61241L,61242L,61243L,61244L,61245L,61246L,61247L,
95147 61248L,61249L,61250L,61251L,61252L,61253L,61254L,61255L,61256L,61257L,
95148 61258L,61259L,61260L,61261L,61262L,61263L,61264L,61265L,61266L,61267L,
95149 61268L,61269L,61270L,61271L,61272L,61273L,61274L,61275L,61276L,61277L,
95150 61278L,61279L,61280L,61281L,61282L,61283L,61284L,61285L,61286L,61287L,
95151 61288L,61289L,61290L,61291L,61292L,61293L,61294L,61295L,61296L,61297L,
95152 61298L,61299L,61300L,61301L,61302L,61303L,61304L,61305L,61306L,61307L,
95153 61308L,61309L,61310L,61311L,61312L,61313L,61314L,61315L,61316L,61317L,
95154 61318L,61319L,61320L,61321L,61322L,61323L,61324L,61325L,61326L,61327L,
95155 61328L,61329L,61330L,61331L,61332L,61333L,61334L,61335L,61336L,61337L,
95156 61338L,61339L,61340L,61341L,61342L,61343L,61344L,61345L,61346L,61347L,
95157 61348L,61349L,61350L,61351L,61352L,61353L,61354L,61355L,61356L,61357L,
95158 61358L,61359L,61360L,61361L,61362L,61363L,61364L,61365L,61366L,61367L,
95159 61368L,61369L,61370L,61371L,61372L,61373L,61374L,61375L,61376L,61377L,
95160 61378L,61379L,61380L,61381L,61382L,61383L,61384L,61385L,61386L,61387L,
95161 61388L,61389L,61390L,61391L,61392L,61393L,61394L,61395L,61396L,61397L,
95162 61398L,61399L,61400L,61401L,61402L,61403L,61404L,61405L,61406L,61407L,
95163 61408L,61409L,61410L,61411L,61412L,61413L,61414L,61415L,61416L,61417L,
95164 61418L,61419L,61420L,61421L,61422L,61423L,61424L,61425L,61426L,61427L,
95165 61428L,61429L,61430L,61431L,61432L,61433L,61434L,61435L,61436L,61437L,
95166 61438L,61439L,61440L,61441L,61442L,61443L,61444L,61445L,61446L,61447L,
95167 61448L,61449L,61450L,61451L,61452L,61453L,61454L,61455L,61456L,61457L,
95168 61458L,61459L,61460L,61461L,61462L,61463L,61464L,61465L,61466L,61467L,
95169 61468L,61469L,61470L,61471L,61472L,61473L,61474L,61475L,61476L,61477L,
95170 61478L,61479L,61480L,61481L,61482L,61483L,61484L,61485L,61486L,61487L,
95171 61488L,61489L,61490L,61491L,61492L,61493L,61494L,61495L,61496L,61497L,
95172 61498L,61499L,61500L,61501L,61502L,61503L,61504L,61505L,61506L,61507L,
95173 61508L,61509L,61510L,61511L,61512L,61513L,61514L,61515L,61516L,61517L,
95174 61518L,61519L,61520L,61521L,61522L,61523L,61524L,61525L,61526L,61527L,
95175 61528L,61529L,61530L,61531L,61532L,61533L,61534L,61535L,61536L,61537L,
95176 61538L,61539L,61540L,61541L,61542L,61543L,61544L,61545L,61546L,61547L,
95177 61548L,61549L,61550L,61551L,61552L,61553L,61554L,61555L,61556L,61557L,
95178 61558L,61559L,61560L,61561L,61562L,61563L,61564L,61565L,61566L,61567L,
95179 61568L,61569L,61570L,61571L,61572L,61573L,61574L,61575L,61576L,61577L,
95180 61578L,61579L,61580L,61581L,61582L,61583L,61584L,61585L,61586L,61587L,
95181 61588L,61589L,61590L,61591L,61592L,61593L,61594L,61595L,61596L,61597L,
95182 61598L,61599L,61600L,61601L,61602L,61603L,61604L,61605L,61606L,61607L,
95183 61608L,61609L,61610L,61611L,61612L,61613L,61614L,61615L,61616L,61617L,
95184 61618L,61619L,61620L,61621L,61622L,61623L,61624L,61625L,61626L,61627L,
95185 61628L,61629L,61630L,61631L,61632L,61633L,61634L,61635L,61636L,61637L,
95186 61638L,61639L,61640L,61641L,61642L,61643L,61644L,61645L,61646L,61647L,
95187 61648L,61649L,61650L,61651L,61652L,61653L,61654L,61655L,61656L,61657L,
95188 61658L,61659L,61660L,61661L,61662L,61663L,61664L,61665L,61666L,61667L,
95189 61668L,61669L,61670L,61671L,61672L,61673L,61674L,61675L,61676L,61677L,
95190 61678L,61679L,61680L,61681L,61682L,61683L,61684L,61685L,61686L,61687L,
95191 61688L,61689L,61690L,61691L,61692L,61693L,61694L,61695L,61696L,61697L,
95192 61698L,61699L,61700L,61701L,61702L,61703L,61704L,61705L,61706L,61707L,
95193 61708L,61709L,61710L,61711L,61712L,61713L,61714L,61715L,61716L,61717L,
95194 61718L,61719L,61720L,61721L,61722L,61723L,61724L,61725L,61726L,61727L,
95195 61728L,61729L,61730L,61731L,61732L,61733L,61734L,61735L,61736L,61737L,
95196 61738L,61739L,61740L,61741L,61742L,61743L,61744L,61745L,61746L,61747L,
95197 61748L,61749L,61750L,61751L,61752L,61753L,61754L,61755L,61756L,61757L,
95198 61758L,61759L,61760L,61761L,61762L,61763L,61764L,61765L,61766L,61767L,
95199 61768L,61769L,61770L,61771L,61772L,61773L,61774L,61775L,61776L,61777L,
95200 61778L,61779L,61780L,61781L,61782L,61783L,61784L,61785L,61786L,61787L,
95201 61788L,61789L,61790L,61791L,61792L,61793L,61794L,61795L,61796L,61797L,
95202 61798L,61799L,61800L,61801L,61802L,61803L,61804L,61805L,61806L,61807L,
95203 61808L,61809L,61810L,61811L,61812L,61813L,61814L,61815L,61816L,61817L,
95204 61818L,61819L,61820L,61821L,61822L,61823L,61824L,61825L,61826L,61827L,
95205 61828L,61829L,61830L,61831L,61832L,61833L,61834L,61835L,61836L,61837L,
95206 61838L,61839L,61840L,61841L,61842L,61843L,61844L,61845L,61846L,61847L,
95207 61848L,61849L,61850L,61851L,61852L,61853L,61854L,61855L,61856L,61857L,
95208 61858L,61859L,61860L,61861L,61862L,61863L,61864L,61865L,61866L,61867L,
95209 61868L,61869L,61870L,61871L,61872L,61873L,61874L,61875L,61876L,61877L,
95210 61878L,61879L,61880L,61881L,61882L,61883L,61884L,61885L,61886L,61887L,
95211 61888L,61889L,61890L,61891L,61892L,61893L,61894L,61895L,61896L,61897L,
95212 61898L,61899L,61900L,61901L,61902L,61903L,61904L,61905L,61906L,61907L,
95213 61908L,61909L,61910L,61911L,61912L,61913L,61914L,61915L,61916L,61917L,
95214 61918L,61919L,61920L,61921L,61922L,61923L,61924L,61925L,61926L,61927L,
95215 61928L,61929L,61930L,61931L,61932L,61933L,61934L,61935L,61936L,61937L,
95216 61938L,61939L,61940L,61941L,61942L,61943L,61944L,61945L,61946L,61947L,
95217 61948L,61949L,61950L,61951L,61952L,61953L,61954L,61955L,61956L,61957L,
95218 61958L,61959L,61960L,61961L,61962L,61963L,61964L,61965L,61966L,61967L,
95219 61968L,61969L,61970L,61971L,61972L,61973L,61974L,61975L,61976L,61977L,
95220 61978L,61979L,61980L,61981L,61982L,61983L,61984L,61985L,61986L,61987L,
95221 61988L,61989L,61990L,61991L,61992L,61993L,61994L,61995L,61996L,61997L,
95222 61998L,61999L,62000L,62001L,62002L,62003L,62004L,62005L,62006L,62007L,
95223 62008L,62009L,62010L,62011L,62012L,62013L,62014L,62015L,62016L,62017L,
95224 62018L,62019L,62020L,62021L,62022L,62023L,62024L,62025L,62026L,62027L,
95225 62028L,62029L,62030L,62031L,62032L,62033L,62034L,62035L,62036L,62037L,
95226 62038L,62039L,62040L,62041L,62042L,62043L,62044L,62045L,62046L,62047L,
95227 62048L,62049L,62050L,62051L,62052L,62053L,62054L,62055L,62056L,62057L,
95228 62058L,62059L,62060L,62061L,62062L,62063L,62064L,62065L,62066L,62067L,
95229 62068L,62069L,62070L,62071L,62072L,62073L,62074L,62075L,62076L,62077L,
95230 62078L,62079L,62080L,62081L,62082L,62083L,62084L,62085L,62086L,62087L,
95231 62088L,62089L,62090L,62091L,62092L,62093L,62094L,62095L,62096L,62097L,
95232 62098L,62099L,62100L,62101L,62102L,62103L,62104L,62105L,62106L,62107L,
95233 62108L,62109L,62110L,62111L,62112L,62113L,62114L,62115L,62116L,62117L,
95234 62118L,62119L,62120L,62121L,62122L,62123L,62124L,62125L,62126L,62127L,
95235 62128L,62129L,62130L,62131L,62132L,62133L,62134L,62135L,62136L,62137L,
95236 62138L,62139L,62140L,62141L,62142L,62143L,62144L,62145L,62146L,62147L,
95237 62148L,62149L,62150L,62151L,62152L,62153L,62154L,62155L,62156L,62157L,
95238 62158L,62159L,62160L,62161L,62162L,62163L,62164L,62165L,62166L,62167L,
95239 62168L,62169L,62170L,62171L,62172L,62173L,62174L,62175L,62176L,62177L,
95240 62178L,62179L,62180L,62181L,62182L,62183L,62184L,62185L,62186L,62187L,
95241 62188L,62189L,62190L,62191L,62192L,62193L,62194L,62195L,62196L,62197L,
95242 62198L,62199L,62200L,62201L,62202L,62203L,62204L,62205L,62206L,62207L,
95243 62208L,62209L,62210L,62211L,62212L,62213L,62214L,62215L,62216L,62217L,
95244 62218L,62219L,62220L,62221L,62222L,62223L,62224L,62225L,62226L,62227L,
95245 62228L,62229L,62230L,62231L,62232L,62233L,62234L,62235L,62236L,62237L,
95246 62238L,62239L,62240L,62241L,62242L,62243L,62244L,62245L,62246L,62247L,
95247 62248L,62249L,62250L,62251L,62252L,62253L,62254L,62255L,62256L,62257L,
95248 62258L,62259L,62260L,62261L,62262L,62263L,62264L,62265L,62266L,62267L,
95249 62268L,62269L,62270L,62271L,62272L,62273L,62274L,62275L,62276L,62277L,
95250 62278L,62279L,62280L,62281L,62282L,62283L,62284L,62285L,62286L,62287L,
95251 62288L,62289L,62290L,62291L,62292L,62293L,62294L,62295L,62296L,62297L,
95252 62298L,62299L,62300L,62301L,62302L,62303L,62304L,62305L,62306L,62307L,
95253 62308L,62309L,62310L,62311L,62312L,62313L,62314L,62315L,62316L,62317L,
95254 62318L,62319L,62320L,62321L,62322L,62323L,62324L,62325L,62326L,62327L,
95255 62328L,62329L,62330L,62331L,62332L,62333L,62334L,62335L,62336L,62337L,
95256 62338L,62339L,62340L,62341L,62342L,62343L,62344L,62345L,62346L,62347L,
95257 62348L,62349L,62350L,62351L,62352L,62353L,62354L,62355L,62356L,62357L,
95258 62358L,62359L,62360L,62361L,62362L,62363L,62364L,62365L,62366L,62367L,
95259 62368L,62369L,62370L,62371L,62372L,62373L,62374L,62375L,62376L,62377L,
95260 62378L,62379L,62380L,62381L,62382L,62383L,62384L,62385L,62386L,62387L,
95261 62388L,62389L,62390L,62391L,62392L,62393L,62394L,62395L,62396L,62397L,
95262 62398L,62399L,62400L,62401L,62402L,62403L,62404L,62405L,62406L,62407L,
95263 62408L,62409L,62410L,62411L,62412L,62413L,62414L,62415L,62416L,62417L,
95264 62418L,62419L,62420L,62421L,62422L,62423L,62424L,62425L,62426L,62427L,
95265 62428L,62429L,62430L,62431L,62432L,62433L,62434L,62435L,62436L,62437L,
95266 62438L,62439L,62440L,62441L,62442L,62443L,62444L,62445L,62446L,62447L,
95267 62448L,62449L,62450L,62451L,62452L,62453L,62454L,62455L,62456L,62457L,
95268 62458L,62459L,62460L,62461L,62462L,62463L,62464L,62465L,62466L,62467L,
95269 62468L,62469L,62470L,62471L,62472L,62473L,62474L,62475L,62476L,62477L,
95270 62478L,62479L,62480L,62481L,62482L,62483L,62484L,62485L,62486L,62487L,
95271 62488L,62489L,62490L,62491L,62492L,62493L,62494L,62495L,62496L,62497L,
95272 62498L,62499L,62500L,62501L,62502L,62503L,62504L,62505L,62506L,62507L,
95273 62508L,62509L,62510L,62511L,62512L,62513L,62514L,62515L,62516L,62517L,
95274 62518L,62519L,62520L,62521L,62522L,62523L,62524L,62525L,62526L,62527L,
95275 62528L,62529L,62530L,62531L,62532L,62533L,62534L,62535L,62536L,62537L,
95276 62538L,62539L,62540L,62541L,62542L,62543L,62544L,62545L,62546L,62547L,
95277 62548L,62549L,62550L,62551L,62552L,62553L,62554L,62555L,62556L,62557L,
95278 62558L,62559L,62560L,62561L,62562L,62563L,62564L,62565L,62566L,62567L,
95279 62568L,62569L,62570L,62571L,62572L,62573L,62574L,62575L,62576L,62577L,
95280 62578L,62579L,62580L,62581L,62582L,62583L,62584L,62585L,62586L,62587L,
95281 62588L,62589L,62590L,62591L,62592L,62593L,62594L,62595L,62596L,62597L,
95282 62598L,62599L,62600L,62601L,62602L,62603L,62604L,62605L,62606L,62607L,
95283 62608L,62609L,62610L,62611L,62612L,62613L,62614L,62615L,62616L,62617L,
95284 62618L,62619L,62620L,62621L,62622L,62623L,62624L,62625L,62626L,62627L,
95285 62628L,62629L,62630L,62631L,62632L,62633L,62634L,62635L,62636L,62637L,
95286 62638L,62639L,62640L,62641L,62642L,62643L,62644L,62645L,62646L,62647L,
95287 62648L,62649L,62650L,62651L,62652L,62653L,62654L,62655L,62656L,62657L,
95288 62658L,62659L,62660L,62661L,62662L,62663L,62664L,62665L,62666L,62667L,
95289 62668L,62669L,62670L,62671L,62672L,62673L,62674L,62675L,62676L,62677L,
95290 62678L,62679L,62680L,62681L,62682L,62683L,62684L,62685L,62686L,62687L,
95291 62688L,62689L,62690L,62691L,62692L,62693L,62694L,62695L,62696L,62697L,
95292 62698L,62699L,62700L,62701L,62702L,62703L,62704L,62705L,62706L,62707L,
95293 62708L,62709L,62710L,62711L,62712L,62713L,62714L,62715L,62716L,62717L,
95294 62718L,62719L,62720L,62721L,62722L,62723L,62724L,62725L,62726L,62727L,
95295 62728L,62729L,62730L,62731L,62732L,62733L,62734L,62735L,62736L,62737L,
95296 62738L,62739L,62740L,62741L,62742L,62743L,62744L,62745L,62746L,62747L,
95297 62748L,62749L,62750L,62751L,62752L,62753L,62754L,62755L,62756L,62757L,
95298 62758L,62759L,62760L,62761L,62762L,62763L,62764L,62765L,62766L,62767L,
95299 62768L,62769L,62770L,62771L,62772L,62773L,62774L,62775L,62776L,62777L,
95300 62778L,62779L,62780L,62781L,62782L,62783L,62784L,62785L,62786L,62787L,
95301 62788L,62789L,62790L,62791L,62792L,62793L,62794L,62795L,62796L,62797L,
95302 62798L,62799L,62800L,62801L,62802L,62803L,62804L,62805L,62806L,62807L,
95303 62808L,62809L,62810L,62811L,62812L,62813L,62814L,62815L,62816L,62817L,
95304 62818L,62819L,62820L,62821L,62822L,62823L,62824L,62825L,62826L,62827L,
95305 62828L,62829L,62830L,62831L,62832L,62833L,62834L,62835L,62836L,62837L,
95306 62838L,62839L,62840L,62841L,62842L,62843L,62844L,62845L,62846L,62847L,
95307 62848L,62849L,62850L,62851L,62852L,62853L,62854L,62855L,62856L,62857L,
95308 62858L,62859L,62860L,62861L,62862L,62863L,62864L,62865L,62866L,62867L,
95309 62868L,62869L,62870L,62871L,62872L,62873L,62874L,62875L,62876L,62877L,
95310 62878L,62879L,62880L,62881L,62882L,62883L,62884L,62885L,62886L,62887L,
95311 62888L,62889L,62890L,62891L,62892L,62893L,62894L,62895L,62896L,62897L,
95312 62898L,62899L,62900L,62901L,62902L,62903L,62904L,62905L,62906L,62907L,
95313 62908L,62909L,62910L,62911L,62912L,62913L,62914L,62915L,62916L,62917L,
95314 62918L,62919L,62920L,62921L,62922L,62923L,62924L,62925L,62926L,62927L,
95315 62928L,62929L,62930L,62931L,62932L,62933L,62934L,62935L,62936L,62937L,
95316 62938L,62939L,62940L,62941L,62942L,62943L,62944L,62945L,62946L,62947L,
95317 62948L,62949L,62950L,62951L,62952L,62953L,62954L,62955L,62956L,62957L,
95318 62958L,62959L,62960L,62961L,62962L,62963L,62964L,62965L,62966L,62967L,
95319 62968L,62969L,62970L,62971L,62972L,62973L,62974L,62975L,62976L,62977L,
95320 62978L,62979L,62980L,62981L,62982L,62983L,62984L,62985L,62986L,62987L,
95321 62988L,62989L,62990L,62991L,62992L,62993L,62994L,62995L,62996L,62997L,
95322 62998L,62999L,63000L,63001L,63002L,63003L,63004L,63005L,63006L,63007L,
95323 63008L,63009L,63010L,63011L,63012L,63013L,63014L,63015L,63016L,63017L,
95324 63018L,63019L,63020L,63021L,63022L,63023L,63024L,63025L,63026L,63027L,
95325 63028L,63029L,63030L,63031L,63032L,63033L,63034L,63035L,63036L,63037L,
95326 63038L,63039L,63040L,63041L,63042L,63043L,63044L,63045L,63046L,63047L,
95327 63048L,63049L,63050L,63051L,63052L,63053L,63054L,63055L,63056L,63057L,
95328 63058L,63059L,63060L,63061L,63062L,63063L,63064L,63065L,63066L,63067L,
95329 63068L,63069L,63070L,63071L,63072L,63073L,63074L,63075L,63076L,63077L,
95330 63078L,63079L,63080L,63081L,63082L,63083L,63084L,63085L,63086L,63087L,
95331 63088L,63089L,63090L,63091L,63092L,63093L,63094L,63095L,63096L,63097L,
95332 63098L,63099L,63100L,63101L,63102L,63103L,63104L,63105L,63106L,63107L,
95333 63108L,63109L,63110L,63111L,63112L,63113L,63114L,63115L,63116L,63117L,
95334 63118L,63119L,63120L,63121L,63122L,63123L,63124L,63125L,63126L,63127L,
95335 63128L,63129L,63130L,63131L,63132L,63133L,63134L,63135L,63136L,63137L,
95336 63138L,63139L,63140L,63141L,63142L,63143L,63144L,63145L,63146L,63147L,
95337 63148L,63149L,63150L,63151L,63152L,63153L,63154L,63155L,63156L,63157L,
95338 63158L,63159L,63160L,63161L,63162L,63163L,63164L,63165L,63166L,63167L,
95339 63168L,63169L,63170L,63171L,63172L,63173L,63174L,63175L,63176L,63177L,
95340 63178L,63179L,63180L,63181L,63182L,63183L,63184L,63185L,63186L,63187L,
95341 63188L,63189L,63190L,63191L,63192L,63193L,63194L,63195L,63196L,63197L,
95342 63198L,63199L,63200L,63201L,63202L,63203L,63204L,63205L,63206L,63207L,
95343 63208L,63209L,63210L,63211L,63212L,63213L,63214L,63215L,63216L,63217L,
95344 63218L,63219L,63220L,63221L,63222L,63223L,63224L,63225L,63226L,63227L,
95345 63228L,63229L,63230L,63231L,63232L,63233L,63234L,63235L,63236L,63237L,
95346 63238L,63239L,63240L,63241L,63242L,63243L,63244L,63245L,63246L,63247L,
95347 63248L,63249L,63250L,63251L,63252L,63253L,63254L,63255L,63256L,63257L,
95348 63258L,63259L,63260L,63261L,63262L,63263L,63264L,63265L,63266L,63267L,
95349 63268L,63269L,63270L,63271L,63272L,63273L,63274L,63275L,63276L,63277L,
95350 63278L,63279L,63280L,63281L,63282L,63283L,63284L,63285L,63286L,63287L,
95351 63288L,63289L,63290L,63291L,63292L,63293L,63294L,63295L,63296L,63297L,
95352 63298L,63299L,63300L,63301L,63302L,63303L,63304L,63305L,63306L,63307L,
95353 63308L,63309L,63310L,63311L,63312L,63313L,63314L,63315L,63316L,63317L,
95354 63318L,63319L,63320L,63321L,63322L,63323L,63324L,63325L,63326L,63327L,
95355 63328L,63329L,63330L,63331L,63332L,63333L,63334L,63335L,63336L,63337L,
95356 63338L,63339L,63340L,63341L,63342L,63343L,63344L,63345L,63346L,63347L,
95357 63348L,63349L,63350L,63351L,63352L,63353L,63354L,63355L,63356L,63357L,
95358 63358L,63359L,63360L,63361L,63362L,63363L,63364L,63365L,63366L,63367L,
95359 63368L,63369L,63370L,63371L,63372L,63373L,63374L,63375L,63376L,63377L,
95360 63378L,63379L,63380L,63381L,63382L,63383L,63384L,63385L,63386L,63387L,
95361 63388L,63389L,63390L,63391L,63392L,63393L,63394L,63395L,63396L,63397L,
95362 63398L,63399L,63400L,63401L,63402L,63403L,63404L,63405L,63406L,63407L,
95363 63408L,63409L,63410L,63411L,63412L,63413L,63414L,63415L,63416L,63417L,
95364 63418L,63419L,63420L,63421L,63422L,63423L,63424L,63425L,63426L,63427L,
95365 63428L,63429L,63430L,63431L,63432L,63433L,63434L,63435L,63436L,63437L,
95366 63438L,63439L,63440L,63441L,63442L,63443L,63444L,63445L,63446L,63447L,
95367 63448L,63449L,63450L,63451L,63452L,63453L,63454L,63455L,63456L,63457L,
95368 63458L,63459L,63460L,63461L,63462L,63463L,63464L,63465L,63466L,63467L,
95369 63468L,63469L,63470L,63471L,63472L,63473L,63474L,63475L,63476L,63477L,
95370 63478L,63479L,63480L,63481L,63482L,63483L,63484L,63485L,63486L,63487L,
95371 63488L,63489L,63490L,63491L,63492L,63493L,63494L,63495L,63496L,63497L,
95372 63498L,63499L,63500L,63501L,63502L,63503L,63504L,63505L,63506L,63507L,
95373 63508L,63509L,63510L,63511L,63512L,63513L,63514L,63515L,63516L,63517L,
95374 63518L,63519L,63520L,63521L,63522L,63523L,63524L,63525L,63526L,63527L,
95375 63528L,63529L,63530L,63531L,63532L,63533L,63534L,63535L,63536L,63537L,
95376 63538L,63539L,63540L,63541L,63542L,63543L,63544L,63545L,63546L,63547L,
95377 63548L,63549L,63550L,63551L,63552L,63553L,63554L,63555L,63556L,63557L,
95378 63558L,63559L,63560L,63561L,63562L,63563L,63564L,63565L,63566L,63567L,
95379 63568L,63569L,63570L,63571L,63572L,63573L,63574L,63575L,63576L,63577L,
95380 63578L,63579L,63580L,63581L,63582L,63583L,63584L,63585L,63586L,63587L,
95381 63588L,63589L,63590L,63591L,63592L,63593L,63594L,63595L,63596L,63597L,
95382 63598L,63599L,63600L,63601L,63602L,63603L,63604L,63605L,63606L,63607L,
95383 63608L,63609L,63610L,63611L,63612L,63613L,63614L,63615L,63616L,63617L,
95384 63618L,63619L,63620L,63621L,63622L,63623L,63624L,63625L,63626L,63627L,
95385 63628L,63629L,63630L,63631L,63632L,63633L,63634L,63635L,63636L,63637L,
95386 63638L,63639L,63640L,63641L,63642L,63643L,63644L,63645L,63646L,63647L,
95387 63648L,63649L,63650L,63651L,63652L,63653L,63654L,63655L,63656L,63657L,
95388 63658L,63659L,63660L,63661L,63662L,63663L,63664L,63665L,63666L,63667L,
95389 63668L,63669L,63670L,63671L,63672L,63673L,63674L,63675L,63676L,63677L,
95390 63678L,63679L,63680L,63681L,63682L,63683L,63684L,63685L,63686L,63687L,
95391 63688L,63689L,63690L,63691L,63692L,63693L,63694L,63695L,63696L,63697L,
95392 63698L,63699L,63700L,63701L,63702L,63703L,63704L,63705L,63706L,63707L,
95393 63708L,63709L,63710L,63711L,63712L,63713L,63714L,63715L,63716L,63717L,
95394 63718L,63719L,63720L,63721L,63722L,63723L,63724L,63725L,63726L,63727L,
95395 63728L,63729L,63730L,63731L,63732L,63733L,63734L,63735L,63736L,63737L,
95396 63738L,63739L,63740L,63741L,63742L,63743L,63744L,63745L,63746L,63747L,
95397 63748L,63749L,63750L,63751L,63752L,63753L,63754L,63755L,63756L,63757L,
95398 63758L,63759L,63760L,63761L,63762L,63763L,63764L,63765L,63766L,63767L,
95399 63768L,63769L,63770L,63771L,63772L,63773L,63774L,63775L,63776L,63777L,
95400 63778L,63779L,63780L,63781L,63782L,63783L,63784L,63785L,63786L,63787L,
95401 63788L,63789L,63790L,63791L,63792L,63793L,63794L,63795L,63796L,63797L,
95402 63798L,63799L,63800L,63801L,63802L,63803L,63804L,63805L,63806L,63807L,
95403 63808L,63809L,63810L,63811L,63812L,63813L,63814L,63815L,63816L,63817L,
95404 63818L,63819L,63820L,63821L,63822L,63823L,63824L,63825L,63826L,63827L,
95405 63828L,63829L,63830L,63831L,63832L,63833L,63834L,63835L,63836L,63837L,
95406 63838L,63839L,63840L,63841L,63842L,63843L,63844L,63845L,63846L,63847L,
95407 63848L,63849L,63850L,63851L,63852L,63853L,63854L,63855L,63856L,63857L,
95408 63858L,63859L,63860L,63861L,63862L,63863L,63864L,63865L,63866L,63867L,
95409 63868L,63869L,63870L,63871L,63872L,63873L,63874L,63875L,63876L,63877L,
95410 63878L,63879L,63880L,63881L,63882L,63883L,63884L,63885L,63886L,63887L,
95411 63888L,63889L,63890L,63891L,63892L,63893L,63894L,63895L,63896L,63897L,
95412 63898L,63899L,63900L,63901L,63902L,63903L,63904L,63905L,63906L,63907L,
95413 63908L,63909L,63910L,63911L,63912L,63913L,63914L,63915L,63916L,63917L,
95414 63918L,63919L,63920L,63921L,63922L,63923L,63924L,63925L,63926L,63927L,
95415 63928L,63929L,63930L,63931L,63932L,63933L,63934L,63935L,63936L,63937L,
95416 63938L,63939L,63940L,63941L,63942L,63943L,63944L,63945L,63946L,63947L,
95417 63948L,63949L,63950L,63951L,63952L,63953L,63954L,63955L,63956L,63957L,
95418 63958L,63959L,63960L,63961L,63962L,63963L,63964L,63965L,63966L,63967L,
95419 63968L,63969L,63970L,63971L,63972L,63973L,63974L,63975L,63976L,63977L,
95420 63978L,63979L,63980L,63981L,63982L,63983L,63984L,63985L,63986L,63987L,
95421 63988L,63989L,63990L,63991L,63992L,63993L,63994L,63995L,63996L,63997L,
95422 63998L,63999L,64000L,64001L,64002L,64003L,64004L,64005L,64006L,64007L,
95423 64008L,64009L,64010L,64011L,64012L,64013L,64014L,64015L,64016L,64017L,
95424 64018L,64019L,64020L,64021L,64022L,64023L,64024L,64025L,64026L,64027L,
95425 64028L,64029L,64030L,64031L,64032L,64033L,64034L,64035L,64036L,64037L,
95426 64038L,64039L,64040L,64041L,64042L,64043L,64044L,64045L,64046L,64047L,
95427 64048L,64049L,64050L,64051L,64052L,64053L,64054L,64055L,64056L,64057L,
95428 64058L,64059L,64060L,64061L,64062L,64063L,64064L,64065L,64066L,64067L,
95429 64068L,64069L,64070L,64071L,64072L,64073L,64074L,64075L,64076L,64077L,
95430 64078L,64079L,64080L,64081L,64082L,64083L,64084L,64085L,64086L,64087L,
95431 64088L,64089L,64090L,64091L,64092L,64093L,64094L,64095L,64096L,64097L,
95432 64098L,64099L,64100L,64101L,64102L,64103L,64104L,64105L,64106L,64107L,
95433 64108L,64109L,64110L,64111L,64112L,64113L,64114L,64115L,64116L,64117L,
95434 64118L,64119L,64120L,64121L,64122L,64123L,64124L,64125L,64126L,64127L,
95435 64128L,64129L,64130L,64131L,64132L,64133L,64134L,64135L,64136L,64137L,
95436 64138L,64139L,64140L,64141L,64142L,64143L,64144L,64145L,64146L,64147L,
95437 64148L,64149L,64150L,64151L,64152L,64153L,64154L,64155L,64156L,64157L,
95438 64158L,64159L,64160L,64161L,64162L,64163L,64164L,64165L,64166L,64167L,
95439 64168L,64169L,64170L,64171L,64172L,64173L,64174L,64175L,64176L,64177L,
95440 64178L,64179L,64180L,64181L,64182L,64183L,64184L,64185L,64186L,64187L,
95441 64188L,64189L,64190L,64191L,64192L,64193L,64194L,64195L,64196L,64197L,
95442 64198L,64199L,64200L,64201L,64202L,64203L,64204L,64205L,64206L,64207L,
95443 64208L,64209L,64210L,64211L,64212L,64213L,64214L,64215L,64216L,64217L,
95444 64218L,64219L,64220L,64221L,64222L,64223L,64224L,64225L,64226L,64227L,
95445 64228L,64229L,64230L,64231L,64232L,64233L,64234L,64235L,64236L,64237L,
95446 64238L,64239L,64240L,64241L,64242L,64243L,64244L,64245L,64246L,64247L,
95447 64248L,64249L,64250L,64251L,64252L,64253L,64254L,64255L,64256L,64257L,
95448 64258L,64259L,64260L,64261L,64262L,64263L,64264L,64265L,64266L,64267L,
95449 64268L,64269L,64270L,64271L,64272L,64273L,64274L,64275L,64276L,64277L,
95450 64278L,64279L,64280L,64281L,64282L,64283L,64284L,64285L,64286L,64287L,
95451 64288L,64289L,64290L,64291L,64292L,64293L,64294L,64295L,64296L,64297L,
95452 64298L,64299L,64300L,64301L,64302L,64303L,64304L,64305L,64306L,64307L,
95453 64308L,64309L,64310L,64311L,64312L,64313L,64314L,64315L,64316L,64317L,
95454 64318L,64319L,64320L,64321L,64322L,64323L,64324L,64325L,64326L,64327L,
95455 64328L,64329L,64330L,64331L,64332L,64333L,64334L,64335L,64336L,64337L,
95456 64338L,64339L,64340L,64341L,64342L,64343L,64344L,64345L,64346L,64347L,
95457 64348L,64349L,64350L,64351L,64352L,64353L,64354L,64355L,64356L,64357L,
95458 64358L,64359L,64360L,64361L,64362L,64363L,64364L,64365L,64366L,64367L,
95459 64368L,64369L,64370L,64371L,64372L,64373L,64374L,64375L,64376L,64377L,
95460 64378L,64379L,64380L,64381L,64382L,64383L,64384L,64385L,64386L,64387L,
95461 64388L,64389L,64390L,64391L,64392L,64393L,64394L,64395L,64396L,64397L,
95462 64398L,64399L,64400L,64401L,64402L,64403L,64404L,64405L,64406L,64407L,
95463 64408L,64409L,64410L,64411L,64412L,64413L,64414L,64415L,64416L,64417L,
95464 64418L,64419L,64420L,64421L,64422L,64423L,64424L,64425L,64426L,64427L,
95465 64428L,64429L,64430L,64431L,64432L,64433L,64434L,64435L,64436L,64437L,
95466 64438L,64439L,64440L,64441L,64442L,64443L,64444L,64445L,64446L,64447L,
95467 64448L,64449L,64450L,64451L,64452L,64453L,64454L,64455L,64456L,64457L,
95468 64458L,64459L,64460L,64461L,64462L,64463L,64464L,64465L,64466L,64467L,
95469 64468L,64469L,64470L,64471L,64472L,64473L,64474L,64475L,64476L,64477L,
95470 64478L,64479L,64480L,64481L,64482L,64483L,64484L,64485L,64486L,64487L,
95471 64488L,64489L,64490L,64491L,64492L,64493L,64494L,64495L,64496L,64497L,
95472 64498L,64499L,64500L,64501L,64502L,64503L,64504L,64505L,64506L,64507L,
95473 64508L,64509L,64510L,64511L,64512L,64513L,64514L,64515L,64516L,64517L,
95474 64518L,64519L,64520L,64521L,64522L,64523L,64524L,64525L,64526L,64527L,
95475 64528L,64529L,64530L,64531L,64532L,64533L,64534L,64535L,64536L,64537L,
95476 64538L,64539L,64540L,64541L,64542L,64543L,64544L,64545L,64546L,64547L,
95477 64548L,64549L,64550L,64551L,64552L,64553L,64554L,64555L,64556L,64557L,
95478 64558L,64559L,64560L,64561L,64562L,64563L,64564L,64565L,64566L,64567L,
95479 64568L,64569L,64570L,64571L,64572L,64573L,64574L,64575L,64576L,64577L,
95480 64578L,64579L,64580L,64581L,64582L,64583L,64584L,64585L,64586L,64587L,
95481 64588L,64589L,64590L,64591L,64592L,64593L,64594L,64595L,64596L,64597L,
95482 64598L,64599L,64600L,64601L,64602L,64603L,64604L,64605L,64606L,64607L,
95483 64608L,64609L,64610L,64611L,64612L,64613L,64614L,64615L,64616L,64617L,
95484 64618L,64619L,64620L,64621L,64622L,64623L,64624L,64625L,64626L,64627L,
95485 64628L,64629L,64630L,64631L,64632L,64633L,64634L,64635L,64636L,64637L,
95486 64638L,64639L,64640L,64641L,64642L,64643L,64644L,64645L,64646L,64647L,
95487 64648L,64649L,64650L,64651L,64652L,64653L,64654L,64655L,64656L,64657L,
95488 64658L,64659L,64660L,64661L,64662L,64663L,64664L,64665L,64666L,64667L,
95489 64668L,64669L,64670L,64671L,64672L,64673L,64674L,64675L,64676L,64677L,
95490 64678L,64679L,64680L,64681L,64682L,64683L,64684L,64685L,64686L,64687L,
95491 64688L,64689L,64690L,64691L,64692L,64693L,64694L,64695L,64696L,64697L,
95492 64698L,64699L,64700L,64701L,64702L,64703L,64704L,64705L,64706L,64707L,
95493 64708L,64709L,64710L,64711L,64712L,64713L,64714L,64715L,64716L,64717L,
95494 64718L,64719L,64720L,64721L,64722L,64723L,64724L,64725L,64726L,64727L,
95495 64728L,64729L,64730L,64731L,64732L,64733L,64734L,64735L,64736L,64737L,
95496 64738L,64739L,64740L,64741L,64742L,64743L,64744L,64745L,64746L,64747L,
95497 64748L,64749L,64750L,64751L,64752L,64753L,64754L,64755L,64756L,64757L,
95498 64758L,64759L,64760L,64761L,64762L,64763L,64764L,64765L,64766L,64767L,
95499 64768L,64769L,64770L,64771L,64772L,64773L,64774L,64775L,64776L,64777L,
95500 64778L,64779L,64780L,64781L,64782L,64783L,64784L,64785L,64786L,64787L,
95501 64788L,64789L,64790L,64791L,64792L,64793L,64794L,64795L,64796L,64797L,
95502 64798L,64799L,64800L,64801L,64802L,64803L,64804L,64805L,64806L,64807L,
95503 64808L,64809L,64810L,64811L,64812L,64813L,64814L,64815L,64816L,64817L,
95504 64818L,64819L,64820L,64821L,64822L,64823L,64824L,64825L,64826L,64827L,
95505 64828L,64829L,64830L,64831L,64832L,64833L,64834L,64835L,64836L,64837L,
95506 64838L,64839L,64840L,64841L,64842L,64843L,64844L,64845L,64846L,64847L,
95507 64848L,64849L,64850L,64851L,64852L,64853L,64854L,64855L,64856L,64857L,
95508 64858L,64859L,64860L,64861L,64862L,64863L,64864L,64865L,64866L,64867L,
95509 64868L,64869L,64870L,64871L,64872L,64873L,64874L,64875L,64876L,64877L,
95510 64878L,64879L,64880L,64881L,64882L,64883L,64884L,64885L,64886L,64887L,
95511 64888L,64889L,64890L,64891L,64892L,64893L,64894L,64895L,64896L,64897L,
95512 64898L,64899L,64900L,64901L,64902L,64903L,64904L,64905L,64906L,64907L,
95513 64908L,64909L,64910L,64911L,64912L,64913L,64914L,64915L,64916L,64917L,
95514 64918L,64919L,64920L,64921L,64922L,64923L,64924L,64925L,64926L,64927L,
95515 64928L,64929L,64930L,64931L,64932L,64933L,64934L,64935L,64936L,64937L,
95516 64938L,64939L,64940L,64941L,64942L,64943L,64944L,64945L,64946L,64947L,
95517 64948L,64949L,64950L,64951L,64952L,64953L,64954L,64955L,64956L,64957L,
95518 64958L,64959L,64960L,64961L,64962L,64963L,64964L,64965L,64966L,64967L,
95519 64968L,64969L,64970L,64971L,64972L,64973L,64974L,64975L,64976L,64977L,
95520 64978L,64979L,64980L,64981L,64982L,64983L,64984L,64985L,64986L,64987L,
95521 64988L,64989L,64990L,64991L,64992L,64993L,64994L,64995L,64996L,64997L,
95522 64998L,64999L,65000L,65001L,65002L,65003L,65004L,65005L,65006L,65007L,
95523 65008L,65009L,65010L,65011L,65012L,65013L,65014L,65015L,65016L,65017L,
95524 65018L,65019L,65020L,65021L,65022L,65023L,65024L,65025L,65026L,65027L,
95525 65028L,65029L,65030L,65031L,65032L,65033L,65034L,65035L,65036L,65037L,
95526 65038L,65039L,65040L,65041L,65042L,65043L,65044L,65045L,65046L,65047L,
95527 65048L,65049L,65050L,65051L,65052L,65053L,65054L,65055L,65056L,65057L,
95528 65058L,65059L,65060L,65061L,65062L,65063L,65064L,65065L,65066L,65067L,
95529 65068L,65069L,65070L,65071L,65072L,65073L,65074L,65075L,65076L,65077L,
95530 65078L,65079L,65080L,65081L,65082L,65083L,65084L,65085L,65086L,65087L,
95531 65088L,65089L,65090L,65091L,65092L,65093L,65094L,65095L,65096L,65097L,
95532 65098L,65099L,65100L,65101L,65102L,65103L,65104L,65105L,65106L,65107L,
95533 65108L,65109L,65110L,65111L,65112L,65113L,65114L,65115L,65116L,65117L,
95534 65118L,65119L,65120L,65121L,65122L,65123L,65124L,65125L,65126L,65127L,
95535 65128L,65129L,65130L,65131L,65132L,65133L,65134L,65135L,65136L,65137L,
95536 65138L,65139L,65140L,65141L,65142L,65143L,65144L,65145L,65146L,65147L,
95537 65148L,65149L,65150L,65151L,65152L,65153L,65154L,65155L,65156L,65157L,
95538 65158L,65159L,65160L,65161L,65162L,65163L,65164L,65165L,65166L,65167L,
95539 65168L,65169L,65170L,65171L,65172L,65173L,65174L,65175L,65176L,65177L,
95540 65178L,65179L,65180L,65181L,65182L,65183L,65184L,65185L,65186L,65187L,
95541 65188L,65189L,65190L,65191L,65192L,65193L,65194L,65195L,65196L,65197L,
95542 65198L,65199L,65200L,65201L,65202L,65203L,65204L,65205L,65206L,65207L,
95543 65208L,65209L,65210L,65211L,65212L,65213L,65214L,65215L,65216L,65217L,
95544 65218L,65219L,65220L,65221L,65222L,65223L,65224L,65225L,65226L,65227L,
95545 65228L,65229L,65230L,65231L,65232L,65233L,65234L,65235L,65236L,65237L,
95546 65238L,65239L,65240L,65241L,65242L,65243L,65244L,65245L,65246L,65247L,
95547 65248L,65249L,65250L,65251L,65252L,65253L,65254L,65255L,65256L,65257L,
95548 65258L,65259L,65260L,65261L,65262L,65263L,65264L,65265L,65266L,65267L,
95549 65268L,65269L,65270L,65271L,65272L,65273L,65274L,65275L,65276L,65277L,
95550 65278L,65279L,65280L,65281L,65282L,65283L,65284L,65285L,65286L,65287L,
95551 65288L,65289L,65290L,65291L,65292L,65293L,65294L,65295L,65296L,65297L,
95552 65298L,65299L,65300L,65301L,65302L,65303L,65304L,65305L,65306L,65307L,
95553 65308L,65309L,65310L,65311L,65312L,65313L,65314L,65315L,65316L,65317L,
95554 65318L,65319L,65320L,65321L,65322L,65323L,65324L,65325L,65326L,65327L,
95555 65328L,65329L,65330L,65331L,65332L,65333L,65334L,65335L,65336L,65337L,
95556 65338L,65339L,65340L,65341L,65342L,65343L,65344L,65313L,65314L,65315L,
95557 65316L,65317L,65318L,65319L,65320L,65321L,65322L,65323L,65324L,65325L,
95558 65326L,65327L,65328L,65329L,65330L,65331L,65332L,65333L,65334L,65335L,
95559 65336L,65337L,65338L,65371L,65372L,65373L,65374L,65375L,65376L,65377L,
95560 65378L,65379L,65380L,65381L,65382L,65383L,65384L,65385L,65386L,65387L,
95561 65388L,65389L,65390L,65391L,65392L,65393L,65394L,65395L,65396L,65397L,
95562 65398L,65399L,65400L,65401L,65402L,65403L,65404L,65405L,65406L,65407L,
95563 65408L,65409L,65410L,65411L,65412L,65413L,65414L,65415L,65416L,65417L,
95564 65418L,65419L,65420L,65421L,65422L,65423L,65424L,65425L,65426L,65427L,
95565 65428L,65429L,65430L,65431L,65432L,65433L,65434L,65435L,65436L,65437L,
95566 65438L,65439L,65440L,65441L,65442L,65443L,65444L,65445L,65446L,65447L,
95567 65448L,65449L,65450L,65451L,65452L,65453L,65454L,65455L,65456L,65457L,
95568 65458L,65459L,65460L,65461L,65462L,65463L,65464L,65465L,65466L,65467L,
95569 65468L,65469L,65470L,65471L,65472L,65473L,65474L,65475L,65476L,65477L,
95570 65478L,65479L,65480L,65481L,65482L,65483L,65484L,65485L,65486L,65487L,
95571 65488L,65489L,65490L,65491L,65492L,65493L,65494L,65495L,65496L,65497L,
95572 65498L,65499L,65500L,65501L,65502L,65503L,65504L,65505L,65506L,65507L,
95573 65508L,65509L,65510L,65511L,65512L,65513L,65514L,65515L,65516L,65517L,
95574 65518L,65519L,65520L,65521L,65522L,65523L,65524L,65525L,65526L,65527L,
95575 65528L,65529L,65530L,65531L,65532L,65533L,65534L,65535L,
95576 };
95577 #endif
95578 
95579 #if defined(DUK_USE_REGEXP_CANON_BITMAP)
95580 /*
95581  *  Automatically generated by extract_caseconv.py, do not edit!
95582  */
95583 
95584 const duk_uint8_t duk_unicode_re_canon_bitmap[256] = {
95585 23,0,224,19,1,228,255,255,255,255,255,255,255,255,255,255,255,255,255,127,
95586 255,255,255,255,255,255,255,255,231,247,0,16,255,227,255,255,63,255,255,
95587 255,255,255,255,255,1,252,255,255,255,255,255,255,255,255,255,255,255,255,
95588 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
95589 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
95590 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
95591 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
95592 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
95593 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
95594 227,193,255,255,255,147,255,255,255,255,255,255,255,255,255,255,255,255,
95595 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
95596 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
95597 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
95598 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,251,
95599 };
95600 #endif
95601 #line 1 "duk_util_bitdecoder.c"
95602 /*
95603  *  Bitstream decoder.
95604  */
95605 
95606 /* #include duk_internal.h -> already included */
95607 
95608 /* Decode 'bits' bits from the input stream (bits must be 1...24).
95609  * When reading past bitstream end, zeroes are shifted in.  The result
95610  * is signed to match duk_bd_decode_flagged.
95611  */
95612 DUK_INTERNAL duk_uint32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits) {
95613 	duk_small_int_t shift;
95614 	duk_uint32_t mask;
95615 	duk_uint32_t tmp;
95616 
95617 	/* Note: cannot read more than 24 bits without possibly shifting top bits out.
95618 	 * Fixable, but adds complexity.
95619 	 */
95620 	DUK_ASSERT(bits >= 1 && bits <= 24);
95621 
95622 	while (ctx->currbits < bits) {
95623 #if 0
95624 		DUK_DDD(DUK_DDDPRINT("decode_bits: shift more data (bits=%ld, currbits=%ld)",
95625 		                     (long) bits, (long) ctx->currbits));
95626 #endif
95627 		ctx->currval <<= 8;
95628 		if (ctx->offset < ctx->length) {
95629 			/* If ctx->offset >= ctx->length, we "shift zeroes in"
95630 			 * instead of croaking.
95631 			 */
95632 			ctx->currval |= ctx->data[ctx->offset++];
95633 		}
95634 		ctx->currbits += 8;
95635 	}
95636 #if 0
95637 	DUK_DDD(DUK_DDDPRINT("decode_bits: bits=%ld, currbits=%ld, currval=0x%08lx",
95638 	                     (long) bits, (long) ctx->currbits, (unsigned long) ctx->currval));
95639 #endif
95640 
95641 	/* Extract 'top' bits of currval; note that the extracted bits do not need
95642 	 * to be cleared, we just ignore them on next round.
95643 	 */
95644 	shift = ctx->currbits - bits;
95645 	mask = (((duk_uint32_t) 1U) << bits) - 1U;
95646 	tmp = (ctx->currval >> shift) & mask;
95647 	ctx->currbits = shift;  /* remaining */
95648 
95649 #if 0
95650 	DUK_DDD(DUK_DDDPRINT("decode_bits: %ld bits -> 0x%08lx (%ld), currbits=%ld, currval=0x%08lx",
95651 	                     (long) bits, (unsigned long) tmp, (long) tmp, (long) ctx->currbits, (unsigned long) ctx->currval));
95652 #endif
95653 
95654 	return tmp;
95655 }
95656 
95657 DUK_INTERNAL duk_small_uint_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx) {
95658 	return (duk_small_uint_t) duk_bd_decode(ctx, 1);
95659 }
95660 
95661 /* Decode a one-bit flag, and if set, decode a value of 'bits', otherwise return
95662  * default value.
95663  */
95664 DUK_INTERNAL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value) {
95665 	if (duk_bd_decode_flag(ctx)) {
95666 		return duk_bd_decode(ctx, bits);
95667 	} else {
95668 		return def_value;
95669 	}
95670 }
95671 
95672 /* Signed variant, allows negative marker value. */
95673 DUK_INTERNAL duk_int32_t duk_bd_decode_flagged_signed(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value) {
95674 	return (duk_int32_t) duk_bd_decode_flagged(ctx, bits, (duk_uint32_t) def_value);
95675 }
95676 
95677 /* Shared varint encoding.  Match dukutil.py BitEncode.varuint(). */
95678 DUK_INTERNAL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx) {
95679 	duk_small_uint_t t;
95680 
95681 	/* The bit encoding choices here are based on manual testing against
95682 	 * the actual varuints generated by genbuiltins.py.
95683 	 */
95684 	switch (duk_bd_decode(ctx, 2)) {
95685 	case 0:
95686 		return 0;  /* [0,0] */
95687 	case 1:
95688 		return duk_bd_decode(ctx, 2) + 1;  /* [1,4] */
95689 	case 2:
95690 		return duk_bd_decode(ctx, 5) + 5;  /* [5,36] */
95691 	default:
95692 		t = duk_bd_decode(ctx, 7);
95693 		if (t == 0) {
95694 			return duk_bd_decode(ctx, 20);
95695 		}
95696 		return (t - 1) + 37;  /* [37,163] */
95697 	}
95698 }
95699 
95700 /* Decode a bit packed string from a custom format used by genbuiltins.py.
95701  * This function is here because it's used for both heap and thread inits.
95702  * Caller must supply the output buffer whose size is NOT checked!
95703  */
95704 
95705 #define DUK__BITPACK_LETTER_LIMIT  26
95706 #define DUK__BITPACK_LOOKUP1       26
95707 #define DUK__BITPACK_LOOKUP2       27
95708 #define DUK__BITPACK_SWITCH1       28
95709 #define DUK__BITPACK_SWITCH        29
95710 #define DUK__BITPACK_UNUSED1       30
95711 #define DUK__BITPACK_EIGHTBIT      31
95712 
95713 DUK_LOCAL const duk_uint8_t duk__bitpacked_lookup[16] = {
95714 	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
95715 	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
95716 	DUK_ASC_8, DUK_ASC_9, DUK_ASC_UNDERSCORE, DUK_ASC_SPACE,
95717 	0x82, 0x80, DUK_ASC_DOUBLEQUOTE, DUK_ASC_LCURLY
95718 };
95719 
95720 DUK_INTERNAL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx *bd, duk_uint8_t *out) {
95721 	duk_small_uint_t len;
95722 	duk_small_uint_t mode;
95723 	duk_small_uint_t t;
95724 	duk_small_uint_t i;
95725 
95726 	len = duk_bd_decode(bd, 5);
95727 	if (len == 31) {
95728 		len = duk_bd_decode(bd, 8);  /* Support up to 256 bytes; rare. */
95729 	}
95730 
95731 	mode = 32;  /* 0 = uppercase, 32 = lowercase (= 'a' - 'A') */
95732 	for (i = 0; i < len; i++) {
95733 		t = duk_bd_decode(bd, 5);
95734 		if (t < DUK__BITPACK_LETTER_LIMIT) {
95735 			t = t + DUK_ASC_UC_A + mode;
95736 		} else if (t == DUK__BITPACK_LOOKUP1) {
95737 			t = duk__bitpacked_lookup[duk_bd_decode(bd, 3)];
95738 		} else if (t == DUK__BITPACK_LOOKUP2) {
95739 			t = duk__bitpacked_lookup[8 + duk_bd_decode(bd, 3)];
95740 		} else if (t == DUK__BITPACK_SWITCH1) {
95741 			t = duk_bd_decode(bd, 5);
95742 			DUK_ASSERT_DISABLE(t >= 0);  /* unsigned */
95743 			DUK_ASSERT(t <= 25);
95744 			t = t + DUK_ASC_UC_A + (mode ^ 32);
95745 		} else if (t == DUK__BITPACK_SWITCH) {
95746 			mode = mode ^ 32;
95747 			t = duk_bd_decode(bd, 5);
95748 			DUK_ASSERT_DISABLE(t >= 0);
95749 			DUK_ASSERT(t <= 25);
95750 			t = t + DUK_ASC_UC_A + mode;
95751 		} else if (t == DUK__BITPACK_EIGHTBIT) {
95752 			t = duk_bd_decode(bd, 8);
95753 		}
95754 		out[i] = (duk_uint8_t) t;
95755 	}
95756 
95757 	return len;
95758 }
95759 
95760 /* automatic undefs */
95761 #undef DUK__BITPACK_EIGHTBIT
95762 #undef DUK__BITPACK_LETTER_LIMIT
95763 #undef DUK__BITPACK_LOOKUP1
95764 #undef DUK__BITPACK_LOOKUP2
95765 #undef DUK__BITPACK_SWITCH
95766 #undef DUK__BITPACK_SWITCH1
95767 #undef DUK__BITPACK_UNUSED1
95768 #line 1 "duk_util_bitencoder.c"
95769 /*
95770  *  Bitstream encoder.
95771  */
95772 
95773 /* #include duk_internal.h -> already included */
95774 
95775 DUK_INTERNAL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits) {
95776 	duk_uint8_t tmp;
95777 
95778 	DUK_ASSERT(ctx != NULL);
95779 	DUK_ASSERT(ctx->currbits < 8);
95780 
95781 	/* This limitation would be fixable but adds unnecessary complexity. */
95782 	DUK_ASSERT(bits >= 1 && bits <= 24);
95783 
95784 	ctx->currval = (ctx->currval << bits) | data;
95785 	ctx->currbits += bits;
95786 
95787 	while (ctx->currbits >= 8) {
95788 		if (ctx->offset < ctx->length) {
95789 			tmp = (duk_uint8_t) ((ctx->currval >> (ctx->currbits - 8)) & 0xff);
95790 			ctx->data[ctx->offset++] = tmp;
95791 		} else {
95792 			/* If buffer has been exhausted, truncate bitstream */
95793 			ctx->truncated = 1;
95794 		}
95795 
95796 		ctx->currbits -= 8;
95797 	}
95798 }
95799 
95800 DUK_INTERNAL void duk_be_finish(duk_bitencoder_ctx *ctx) {
95801 	duk_small_int_t npad;
95802 
95803 	DUK_ASSERT(ctx != NULL);
95804 	DUK_ASSERT(ctx->currbits < 8);
95805 
95806 	npad = (duk_small_int_t) (8 - ctx->currbits);
95807 	if (npad > 0) {
95808 		duk_be_encode(ctx, 0, npad);
95809 	}
95810 	DUK_ASSERT(ctx->currbits == 0);
95811 }
95812 #line 1 "duk_util_bufwriter.c"
95813 /*
95814  *  Fast buffer writer with slack management.
95815  */
95816 
95817 /* #include duk_internal.h -> already included */
95818 
95819 /* XXX: Avoid duk_{memcmp,memmove}_unsafe() by imposing a minimum length of
95820  * >0 for the underlying dynamic buffer.
95821  */
95822 
95823 /*
95824  *  Macro support functions (use only macros in calling code)
95825  */
95826 
95827 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) {
95828 	duk_uint8_t *p;
95829 
95830 	DUK_ASSERT(thr != NULL);
95831 	DUK_ASSERT(bw_ctx != NULL);
95832 	DUK_UNREF(thr);
95833 
95834 	/* 'p' might be NULL when the underlying buffer is zero size.  If so,
95835 	 * the resulting pointers are not used unsafely.
95836 	 */
95837 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, bw_ctx->buf);
95838 	DUK_ASSERT(p != NULL || (DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0 && curr_offset == 0 && new_length == 0));
95839 	bw_ctx->p = p + curr_offset;
95840 	bw_ctx->p_base = p;
95841 	bw_ctx->p_limit = p + new_length;
95842 }
95843 
95844 DUK_INTERNAL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf) {
95845 	DUK_ASSERT(thr != NULL);
95846 	DUK_ASSERT(bw_ctx != NULL);
95847 	DUK_ASSERT(h_buf != NULL);
95848 
95849 	bw_ctx->buf = h_buf;
95850 	duk__bw_update_ptrs(thr, bw_ctx, 0, DUK_HBUFFER_DYNAMIC_GET_SIZE(h_buf));
95851 }
95852 
95853 DUK_INTERNAL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size) {
95854 	DUK_ASSERT(thr != NULL);
95855 	DUK_ASSERT(bw_ctx != NULL);
95856 
95857 	(void) duk_push_dynamic_buffer(thr, buf_size);
95858 	bw_ctx->buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, -1);
95859 	DUK_ASSERT(bw_ctx->buf != NULL);
95860 	duk__bw_update_ptrs(thr, bw_ctx, 0, buf_size);
95861 }
95862 
95863 /* Resize target buffer for requested size.  Called by the macro only when the
95864  * fast path test (= there is space) fails.
95865  */
95866 DUK_INTERNAL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz) {
95867 	duk_size_t curr_off;
95868 	duk_size_t add_sz;
95869 	duk_size_t new_sz;
95870 
95871 	DUK_ASSERT(thr != NULL);
95872 	DUK_ASSERT(bw_ctx != NULL);
95873 
95874 	/* We could do this operation without caller updating bw_ctx->ptr,
95875 	 * but by writing it back here we can share code better.
95876 	 */
95877 
95878 	curr_off = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
95879 	add_sz = (curr_off >> DUK_BW_SLACK_SHIFT) + DUK_BW_SLACK_ADD;
95880 	new_sz = curr_off + sz + add_sz;
95881 	if (DUK_UNLIKELY(new_sz < curr_off)) {
95882 		/* overflow */
95883 		DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);
95884 		DUK_WO_NORETURN(return NULL;);
95885 	}
95886 #if 0  /* for manual torture testing: tight allocation, useful with valgrind */
95887 	new_sz = curr_off + sz;
95888 #endif
95889 
95890 	/* This is important to ensure dynamic buffer data pointer is not
95891 	 * NULL (which is possible if buffer size is zero), which in turn
95892 	 * causes portability issues with e.g. memmove() and memcpy().
95893 	 */
95894 	DUK_ASSERT(new_sz >= 1);
95895 
95896 	DUK_DD(DUK_DDPRINT("resize bufferwriter from %ld to %ld (add_sz=%ld)", (long) curr_off, (long) new_sz, (long) add_sz));
95897 
95898 	duk_hbuffer_resize(thr, bw_ctx->buf, new_sz);
95899 	duk__bw_update_ptrs(thr, bw_ctx, curr_off, new_sz);
95900 	return bw_ctx->p;
95901 }
95902 
95903 /* Make buffer compact, matching current written size. */
95904 DUK_INTERNAL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx) {
95905 	duk_size_t len;
95906 
95907 	DUK_ASSERT(thr != NULL);
95908 	DUK_ASSERT(bw_ctx != NULL);
95909 	DUK_UNREF(thr);
95910 
95911 	len = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
95912 	duk_hbuffer_resize(thr, bw_ctx->buf, len);
95913 	duk__bw_update_ptrs(thr, bw_ctx, len, len);
95914 }
95915 
95916 DUK_INTERNAL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) {
95917 	duk_uint8_t *p_base;
95918 
95919 	DUK_ASSERT(thr != NULL);
95920 	DUK_ASSERT(bw != NULL);
95921 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
95922 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
95923 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
95924 	DUK_UNREF(thr);
95925 
95926 	p_base = bw->p_base;
95927 	duk_memcpy_unsafe((void *) bw->p,
95928 	                  (const void *) (p_base + src_off),
95929 	                  (size_t) len);
95930 	bw->p += len;
95931 }
95932 
95933 DUK_INTERNAL void duk_bw_write_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) {
95934 	DUK_ASSERT(thr != NULL);
95935 	DUK_ASSERT(bw != NULL);
95936 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
95937 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
95938 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
95939 
95940 	DUK_BW_ENSURE(thr, bw, len);
95941 	duk_bw_write_raw_slice(thr, bw, src_off, len);
95942 }
95943 
95944 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) {
95945 	duk_uint8_t *p_base;
95946 	duk_size_t buf_sz, move_sz;
95947 
95948 	DUK_ASSERT(thr != NULL);
95949 	DUK_ASSERT(bw != NULL);
95950 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
95951 	DUK_ASSERT(buf != NULL);
95952 	DUK_UNREF(thr);
95953 
95954 	p_base = bw->p_base;
95955 	buf_sz = (duk_size_t) (bw->p - p_base);  /* constrained by maximum buffer size */
95956 	move_sz = buf_sz - dst_off;
95957 
95958 	DUK_ASSERT(p_base != NULL);  /* buffer size is >= 1 */
95959 	duk_memmove_unsafe((void *) (p_base + dst_off + len),
95960 	                   (const void *) (p_base + dst_off),
95961 	                   (size_t) move_sz);
95962 	duk_memcpy_unsafe((void *) (p_base + dst_off),
95963 	                  (const void *) buf,
95964 	                  (size_t) len);
95965 	bw->p += len;
95966 }
95967 
95968 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) {
95969 	DUK_ASSERT(thr != NULL);
95970 	DUK_ASSERT(bw != NULL);
95971 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
95972 	DUK_ASSERT(buf != NULL);
95973 
95974 	DUK_BW_ENSURE(thr, bw, len);
95975 	duk_bw_insert_raw_bytes(thr, bw, dst_off, buf, len);
95976 }
95977 
95978 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) {
95979 	duk_uint8_t *p_base;
95980 	duk_size_t buf_sz, move_sz;
95981 
95982 	DUK_ASSERT(thr != NULL);
95983 	DUK_ASSERT(bw != NULL);
95984 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
95985 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
95986 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
95987 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
95988 	DUK_UNREF(thr);
95989 
95990 	p_base = bw->p_base;
95991 
95992 	/* Don't support "straddled" source now. */
95993 	DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
95994 
95995 	if (dst_off <= src_off) {
95996 		/* Target is before source.  Source offset is expressed as
95997 		 * a "before change" offset.  Account for the memmove.
95998 		 */
95999 		src_off += len;
96000 	}
96001 
96002 	buf_sz = (duk_size_t) (bw->p - p_base);
96003 	move_sz = buf_sz - dst_off;
96004 
96005 	DUK_ASSERT(p_base != NULL);  /* buffer size is >= 1 */
96006 	duk_memmove_unsafe((void *) (p_base + dst_off + len),
96007 	                   (const void *) (p_base + dst_off),
96008 	                   (size_t) move_sz);
96009 	duk_memcpy_unsafe((void *) (p_base + dst_off),
96010 	                  (const void *) (p_base + src_off),
96011 	                  (size_t) len);
96012 	bw->p += len;
96013 }
96014 
96015 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) {
96016 	DUK_ASSERT(thr != NULL);
96017 	DUK_ASSERT(bw != NULL);
96018 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
96019 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
96020 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
96021 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
96022 
96023 	/* Don't support "straddled" source now. */
96024 	DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
96025 
96026 	DUK_BW_ENSURE(thr, bw, len);
96027 	duk_bw_insert_raw_slice(thr, bw, dst_off, src_off, len);
96028 }
96029 
96030 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) {
96031 	duk_uint8_t *p_base, *p_dst, *p_src;
96032 	duk_size_t buf_sz, move_sz;
96033 
96034 	DUK_ASSERT(thr != NULL);
96035 	DUK_ASSERT(bw != NULL);
96036 	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
96037 	DUK_UNREF(thr);
96038 
96039 	p_base = bw->p_base;
96040 	buf_sz = (duk_size_t) (bw->p - p_base);
96041 	move_sz = buf_sz - off;
96042 	p_dst = p_base + off + len;
96043 	p_src = p_base + off;
96044 	duk_memmove_unsafe((void *) p_dst, (const void *) p_src, (size_t) move_sz);
96045 	return p_src;  /* point to start of 'reserved area' */
96046 }
96047 
96048 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) {
96049 	DUK_ASSERT(thr != NULL);
96050 	DUK_ASSERT(bw != NULL);
96051 	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
96052 
96053 	DUK_BW_ENSURE(thr, bw, len);
96054 	return duk_bw_insert_raw_area(thr, bw, off, len);
96055 }
96056 
96057 DUK_INTERNAL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) {
96058 	duk_size_t move_sz;
96059 
96060 	duk_uint8_t *p_base;
96061 	duk_uint8_t *p_src;
96062 	duk_uint8_t *p_dst;
96063 
96064 	DUK_ASSERT(thr != NULL);
96065 	DUK_ASSERT(bw != NULL);
96066 	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
96067 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
96068 	DUK_ASSERT(off + len <= DUK_BW_GET_SIZE(thr, bw));
96069 	DUK_UNREF(thr);
96070 
96071 	p_base = bw->p_base;
96072 	p_dst = p_base + off;
96073 	p_src = p_dst + len;
96074 	move_sz = (duk_size_t) (bw->p - p_src);
96075 	duk_memmove_unsafe((void *) p_dst,
96076 	                   (const void *) p_src,
96077 	                   (size_t) move_sz);
96078 	bw->p -= len;
96079 }
96080 
96081 /*
96082  *  Macro support functions for reading/writing raw data.
96083  *
96084  *  These are done using mempcy to ensure they're valid even for unaligned
96085  *  reads/writes on platforms where alignment counts.  On x86 at least gcc
96086  *  is able to compile these into a bswap+mov.  "Always inline" is used to
96087  *  ensure these macros compile to minimal code.
96088  *
96089  *  Not really bufwriter related, but currently used together.
96090  */
96091 
96092 DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p) {
96093 	union {
96094 		duk_uint8_t b[2];
96095 		duk_uint16_t x;
96096 	} u;
96097 
96098 	duk_memcpy((void *) u.b, (const void *) (*p), (size_t) 2);
96099 	u.x = DUK_NTOH16(u.x);
96100 	*p += 2;
96101 	return u.x;
96102 }
96103 
96104 DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p) {
96105 	union {
96106 		duk_uint8_t b[4];
96107 		duk_uint32_t x;
96108 	} u;
96109 
96110 	duk_memcpy((void *) u.b, (const void *) (*p), (size_t) 4);
96111 	u.x = DUK_NTOH32(u.x);
96112 	*p += 4;
96113 	return u.x;
96114 }
96115 
96116 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_read_double_be(duk_uint8_t **p) {
96117 	duk_double_union du;
96118 	union {
96119 		duk_uint8_t b[4];
96120 		duk_uint32_t x;
96121 	} u;
96122 
96123 	duk_memcpy((void *) u.b, (const void *) (*p), (size_t) 4);
96124 	u.x = DUK_NTOH32(u.x);
96125 	du.ui[DUK_DBL_IDX_UI0] = u.x;
96126 	duk_memcpy((void *) u.b, (const void *) (*p + 4), (size_t) 4);
96127 	u.x = DUK_NTOH32(u.x);
96128 	du.ui[DUK_DBL_IDX_UI1] = u.x;
96129 	*p += 8;
96130 
96131 	return du.d;
96132 }
96133 
96134 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val) {
96135 	union {
96136 		duk_uint8_t b[2];
96137 		duk_uint16_t x;
96138 	} u;
96139 
96140 	u.x = DUK_HTON16(val);
96141 	duk_memcpy((void *) (*p), (const void *) u.b, (size_t) 2);
96142 	*p += 2;
96143 }
96144 
96145 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val) {
96146 	union {
96147 		duk_uint8_t b[4];
96148 		duk_uint32_t x;
96149 	} u;
96150 
96151 	u.x = DUK_HTON32(val);
96152 	duk_memcpy((void *) (*p), (const void *) u.b, (size_t) 4);
96153 	*p += 4;
96154 }
96155 
96156 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val) {
96157 	duk_double_union du;
96158 	union {
96159 		duk_uint8_t b[4];
96160 		duk_uint32_t x;
96161 	} u;
96162 
96163 	du.d = val;
96164 	u.x = du.ui[DUK_DBL_IDX_UI0];
96165 	u.x = DUK_HTON32(u.x);
96166 	duk_memcpy((void *) (*p), (const void *) u.b, (size_t) 4);
96167 	u.x = du.ui[DUK_DBL_IDX_UI1];
96168 	u.x = DUK_HTON32(u.x);
96169 	duk_memcpy((void *) (*p + 4), (const void *) u.b, (size_t) 4);
96170 	*p += 8;
96171 }
96172 #line 1 "duk_util_cast.c"
96173 /*
96174  *  Cast helpers.
96175  *
96176  *  C99+ coercion is challenging portability-wise because out-of-range casts
96177  *  may invoke implementation defined or even undefined behavior.  See e.g.
96178  *  http://blog.frama-c.com/index.php?post/2013/10/09/Overflow-float-integer.
96179  *
96180  *  Provide explicit cast helpers which try to avoid implementation defined
96181  *  or undefined behavior.  These helpers can then be simplified in the vast
96182  *  majority of cases where the implementation defined or undefined behavior
96183  *  is not problematic.
96184  */
96185 
96186 /* #include duk_internal.h -> already included */
96187 
96188 /* Portable double-to-integer cast which avoids undefined behavior and avoids
96189  * relying on fmin(), fmax(), or other intrinsics.  Out-of-range results are
96190  * not assumed by caller, but here value is clamped, NaN converts to minval.
96191  */
96192 #define DUK__DOUBLE_INT_CAST1(tname,minval,maxval)  do { \
96193 		if (DUK_LIKELY(x >= (duk_double_t) (minval))) { \
96194 			DUK_ASSERT(!DUK_ISNAN(x)); \
96195 			if (DUK_LIKELY(x <= (duk_double_t) (maxval))) { \
96196 				return (tname) x; \
96197 			} else { \
96198 				return (tname) (maxval); \
96199 			} \
96200 		} else { \
96201 			/* NaN or below minval.  Since we don't care about the result \
96202 			 * for out-of-range values, just return the minimum value for \
96203 			 * both. \
96204 			 */ \
96205 			return (tname) (minval); \
96206 		} \
96207 	} while (0)
96208 
96209 /* Rely on specific NaN behavior for duk_double_{fmin,fmax}(): if either
96210  * argument is a NaN, return the second argument.  This avoids a
96211  * NaN-to-integer cast which is undefined behavior.
96212  */
96213 #define DUK__DOUBLE_INT_CAST2(tname,minval,maxval)  do { \
96214 		return (tname) duk_double_fmin(duk_double_fmax(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
96215 	} while (0)
96216 
96217 /* Another solution which doesn't need C99+ behavior for fmin() and fmax(). */
96218 #define DUK__DOUBLE_INT_CAST3(tname,minval,maxval)  do { \
96219 		if (DUK_ISNAN(x)) { \
96220 			/* 0 or any other value is fine. */ \
96221 			return (tname) 0; \
96222 		} else \
96223 			return (tname) DUK_FMIN(DUK_FMAX(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
96224 		} \
96225 	} while (0)
96226 
96227 /* C99+ solution: relies on specific fmin() and fmax() behavior in C99: if
96228  * one argument is NaN but the other isn't, the non-NaN argument is returned.
96229  * Because the limits are non-NaN values, explicit NaN check is not needed.
96230  * This may not work on all legacy platforms, and also doesn't seem to inline
96231  * the fmin() and fmax() calls (unless one uses -ffast-math which we don't
96232  * support).
96233  */
96234 #define DUK__DOUBLE_INT_CAST4(tname,minval,maxval)  do { \
96235 		return (tname) DUK_FMIN(DUK_FMAX(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
96236 	} while (0)
96237 
96238 DUK_INTERNAL duk_int_t duk_double_to_int_t(duk_double_t x) {
96239 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
96240 	/* Real world solution: almost any practical platform will provide
96241 	 * an integer value without any guarantees what it is (which is fine).
96242 	 */
96243 	return (duk_int_t) x;
96244 #else
96245 	DUK__DOUBLE_INT_CAST1(duk_int_t, DUK_INT_MIN, DUK_INT_MAX);
96246 #endif
96247 }
96248 
96249 DUK_INTERNAL duk_uint_t duk_double_to_uint_t(duk_double_t x) {
96250 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
96251 	return (duk_uint_t) x;
96252 #else
96253 	DUK__DOUBLE_INT_CAST1(duk_uint_t, DUK_UINT_MIN, DUK_UINT_MAX);
96254 #endif
96255 }
96256 
96257 DUK_INTERNAL duk_int32_t duk_double_to_int32_t(duk_double_t x) {
96258 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
96259 	return (duk_int32_t) x;
96260 #else
96261 	DUK__DOUBLE_INT_CAST1(duk_int32_t, DUK_INT32_MIN, DUK_INT32_MAX);
96262 #endif
96263 }
96264 
96265 DUK_INTERNAL duk_uint32_t duk_double_to_uint32_t(duk_double_t x) {
96266 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
96267 	return (duk_uint32_t) x;
96268 #else
96269 	DUK__DOUBLE_INT_CAST1(duk_uint32_t, DUK_UINT32_MIN, DUK_UINT32_MAX);
96270 #endif
96271 }
96272 
96273 /* Largest IEEE double that doesn't round to infinity in the default rounding
96274  * mode.  The exact midpoint between (1 - 2^(-24)) * 2^128 and 2^128 rounds to
96275  * infinity, at least on x64.  This number is one double unit below that
96276  * midpoint.  See misc/float_cast.c.
96277  */
96278 #define DUK__FLOAT_ROUND_LIMIT      340282356779733623858607532500980858880.0
96279 
96280 /* Maximum IEEE float.  Double-to-float conversion above this would be out of
96281  * range and thus technically undefined behavior.
96282  */
96283 #define DUK__FLOAT_MAX              340282346638528859811704183484516925440.0
96284 
96285 DUK_INTERNAL duk_float_t duk_double_to_float_t(duk_double_t x) {
96286 	/* Even a double-to-float cast is technically undefined behavior if
96287 	 * the double is out-of-range.  C99 Section 6.3.1.5:
96288 	 *
96289 	 *   If the value being converted is in the range of values that can
96290 	 *   be represented but cannot be represented exactly, the result is
96291 	 *   either the nearest higher or nearest lower representable value,
96292 	 *   chosen in an implementation-defined manner.  If the value being
96293 	 *   converted is outside the range of values that can be represented,
96294 	 *   the behavior is undefined.
96295 	 */
96296 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
96297 	return (duk_float_t) x;
96298 #else
96299 	duk_double_t t;
96300 
96301 	t = DUK_FABS(x);
96302 	DUK_ASSERT((DUK_ISNAN(x) && DUK_ISNAN(t)) ||
96303 	           (!DUK_ISNAN(x) && !DUK_ISNAN(t)));
96304 
96305 	if (DUK_LIKELY(t <= DUK__FLOAT_MAX)) {
96306 		/* Standard in-range case, try to get here with a minimum
96307 		 * number of checks and branches.
96308 		 */
96309 		DUK_ASSERT(!DUK_ISNAN(x));
96310 		return (duk_float_t) x;
96311 	} else if (t <= DUK__FLOAT_ROUND_LIMIT) {
96312 		/* Out-of-range, but rounds to min/max float. */
96313 		DUK_ASSERT(!DUK_ISNAN(x));
96314 		if (x < 0.0) {
96315 			return (duk_float_t) -DUK__FLOAT_MAX;
96316 		} else {
96317 			return (duk_float_t) DUK__FLOAT_MAX;
96318 		}
96319 	} else if (DUK_ISNAN(x)) {
96320 		/* Assumes double NaN -> float NaN considered "in range". */
96321 		DUK_ASSERT(DUK_ISNAN(x));
96322 		return (duk_float_t) x;
96323 	} else {
96324 		/* Out-of-range, rounds to +/- Infinity. */
96325 		if (x < 0.0) {
96326 			return (duk_float_t) -DUK_DOUBLE_INFINITY;
96327 		} else {
96328 			return (duk_float_t) DUK_DOUBLE_INFINITY;
96329 		}
96330 	}
96331 #endif
96332 }
96333 
96334 /* automatic undefs */
96335 #undef DUK__DOUBLE_INT_CAST1
96336 #undef DUK__DOUBLE_INT_CAST2
96337 #undef DUK__DOUBLE_INT_CAST3
96338 #undef DUK__DOUBLE_INT_CAST4
96339 #undef DUK__FLOAT_MAX
96340 #undef DUK__FLOAT_ROUND_LIMIT
96341 #line 1 "duk_util_double.c"
96342 /*
96343  *  IEEE double helpers.
96344  */
96345 
96346 /* #include duk_internal.h -> already included */
96347 
96348 DUK_INTERNAL duk_bool_t duk_double_is_anyinf(duk_double_t x) {
96349 	duk_double_union du;
96350 	du.d = x;
96351 	return DUK_DBLUNION_IS_ANYINF(&du);
96352 }
96353 
96354 DUK_INTERNAL duk_bool_t duk_double_is_posinf(duk_double_t x) {
96355 	duk_double_union du;
96356 	du.d = x;
96357 	return DUK_DBLUNION_IS_POSINF(&du);
96358 }
96359 
96360 DUK_INTERNAL duk_bool_t duk_double_is_neginf(duk_double_t x) {
96361 	duk_double_union du;
96362 	du.d = x;
96363 	return DUK_DBLUNION_IS_NEGINF(&du);
96364 }
96365 
96366 DUK_INTERNAL duk_bool_t duk_double_is_nan(duk_double_t x) {
96367 	duk_double_union du;
96368 	du.d = x;
96369 	/* Assumes we're dealing with a Duktape internal NaN which is
96370 	 * NaN normalized if duk_tval requires it.
96371 	 */
96372 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
96373 	return DUK_DBLUNION_IS_NAN(&du);
96374 }
96375 
96376 DUK_INTERNAL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x) {
96377 	duk_double_union du;
96378 	du.d = x;
96379 	/* Assumes we're dealing with a Duktape internal NaN which is
96380 	 * NaN normalized if duk_tval requires it.
96381 	 */
96382 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
96383 	return DUK_DBLUNION_IS_NAN(&du) || DUK_DBLUNION_IS_ANYZERO(&du);
96384 }
96385 
96386 DUK_INTERNAL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x) {
96387 	duk_double_union du;
96388 	du.d = x;
96389 	/* If exponent is 0x7FF the argument is either a NaN or an
96390 	 * infinity.  We don't need to check any other fields.
96391 	 */
96392 #if defined(DUK_USE_64BIT_OPS)
96393 #if defined(DUK_USE_DOUBLE_ME)
96394 	return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000);
96395 #else
96396 	return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000);
96397 #endif
96398 #else
96399 	return (du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL;
96400 #endif
96401 }
96402 
96403 DUK_INTERNAL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x) {
96404 	duk_double_union du;
96405 #if defined(DUK_USE_64BIT_OPS)
96406 	duk_uint64_t t;
96407 #else
96408 	duk_uint32_t t;
96409 #endif
96410 	du.d = x;
96411 #if defined(DUK_USE_64BIT_OPS)
96412 #if defined(DUK_USE_DOUBLE_ME)
96413 	t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000);
96414 	if (t == DUK_U64_CONSTANT(0x0000000000000000)) {
96415 		t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x0000000080000000);
96416 		return t == 0;
96417 	}
96418 	if (t == DUK_U64_CONSTANT(0x000000007ff00000)) {
96419 		return 1;
96420 	}
96421 #else
96422 	t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000);
96423 	if (t == DUK_U64_CONSTANT(0x0000000000000000)) {
96424 		t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x8000000000000000);
96425 		return t == 0;
96426 	}
96427 	if (t == DUK_U64_CONSTANT(0x7ff0000000000000)) {
96428 		return 1;
96429 	}
96430 #endif
96431 #else
96432 	t = du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL;
96433 	if (t == 0x00000000UL) {
96434 		return DUK_DBLUNION_IS_ANYZERO(&du);
96435 	}
96436 	if (t == 0x7ff00000UL) {
96437 		return 1;
96438 	}
96439 #endif
96440 	return 0;
96441 }
96442 
96443 DUK_INTERNAL duk_small_uint_t duk_double_signbit(duk_double_t x) {
96444 	duk_double_union du;
96445 	du.d = x;
96446 	return (duk_small_uint_t) DUK_DBLUNION_GET_SIGNBIT(&du);
96447 }
96448 
96449 DUK_INTERNAL duk_double_t duk_double_trunc_towards_zero(duk_double_t x) {
96450 	/* XXX: optimize */
96451 	duk_small_uint_t s = duk_double_signbit(x);
96452 	x = DUK_FLOOR(DUK_FABS(x));  /* truncate towards zero */
96453 	if (s) {
96454 		x = -x;
96455 	}
96456 	return x;
96457 }
96458 
96459 DUK_INTERNAL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y) {
96460 	duk_double_union du1;
96461 	duk_double_union du2;
96462 	du1.d = x;
96463 	du2.d = y;
96464 
96465 	return (((du1.ui[DUK_DBL_IDX_UI0] ^ du2.ui[DUK_DBL_IDX_UI0]) & 0x80000000UL) == 0);
96466 }
96467 
96468 DUK_INTERNAL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y) {
96469 	/* Doesn't replicate fmin() behavior exactly: for fmin() if one
96470 	 * argument is a NaN, the other argument should be returned.
96471 	 * Duktape doesn't rely on this behavior so the replacement can
96472 	 * be simplified.
96473 	 */
96474 	return (x < y ? x : y);
96475 }
96476 
96477 DUK_INTERNAL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y) {
96478 	/* Doesn't replicate fmax() behavior exactly: for fmax() if one
96479 	 * argument is a NaN, the other argument should be returned.
96480 	 * Duktape doesn't rely on this behavior so the replacement can
96481 	 * be simplified.
96482 	 */
96483 	return (x > y ? x : y);
96484 }
96485 
96486 DUK_INTERNAL duk_bool_t duk_double_is_finite(duk_double_t x) {
96487 	return !duk_double_is_nan_or_inf(x);
96488 }
96489 
96490 DUK_INTERNAL duk_bool_t duk_double_is_integer(duk_double_t x) {
96491 	if (duk_double_is_nan_or_inf(x)) {
96492 		return 0;
96493 	} else {
96494 		return duk_js_tointeger_number(x) == x;
96495 	}
96496 }
96497 
96498 DUK_INTERNAL duk_bool_t duk_double_is_safe_integer(duk_double_t x) {
96499 	/* >>> 2**53-1
96500 	 * 9007199254740991
96501 	 */
96502 	return duk_double_is_integer(x) && DUK_FABS(x) <= 9007199254740991.0;
96503 }
96504 
96505 /* Check whether a duk_double_t is a whole number in the 32-bit range (reject
96506  * negative zero), and if so, return a duk_int32_t.
96507  * For compiler use: don't allow negative zero as it will cause trouble with
96508  * LDINT+LDINTX, positive zero is OK.
96509  */
96510 DUK_INTERNAL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival) {
96511 	duk_int32_t t;
96512 
96513 	t = duk_double_to_int32_t(x);
96514 	if (!((duk_double_t) t == x)) {
96515 		return 0;
96516 	}
96517 	if (t == 0) {
96518 		duk_double_union du;
96519 		du.d = x;
96520 		if (DUK_DBLUNION_HAS_SIGNBIT(&du)) {
96521 			return 0;
96522 		}
96523 	}
96524 	*ival = t;
96525 	return 1;
96526 }
96527 
96528 /* Check whether a duk_double_t is a whole number in the 32-bit range, and if
96529  * so, return a duk_int32_t.
96530  */
96531 DUK_INTERNAL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival) {
96532 	duk_int32_t t;
96533 
96534 	t = duk_double_to_int32_t(x);
96535 	if (!((duk_double_t) t == x)) {
96536 		return 0;
96537 	}
96538 	*ival = t;
96539 	return 1;
96540 }
96541 
96542 /* Division: division by zero is undefined behavior (and may in fact trap)
96543  * so it needs special handling for portability.
96544  */
96545 
96546 DUK_INTERNAL DUK_INLINE duk_double_t duk_double_div(duk_double_t x, duk_double_t y) {
96547 #if !defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
96548 	if (DUK_UNLIKELY(y == 0.0)) {
96549 		/* In C99+ division by zero is undefined behavior so
96550 		 * avoid it entirely.  Hopefully the compiler is
96551 		 * smart enough to avoid emitting any actual code
96552 		 * because almost all practical platforms behave as
96553 		 * expected.
96554 		 */
96555 		if (x > 0.0) {
96556 			if (DUK_SIGNBIT(y)) {
96557 				return -DUK_DOUBLE_INFINITY;
96558 			} else {
96559 				return DUK_DOUBLE_INFINITY;
96560 			}
96561 		} else if (x < 0.0) {
96562 			if (DUK_SIGNBIT(y)) {
96563 				return DUK_DOUBLE_INFINITY;
96564 			} else {
96565 				return -DUK_DOUBLE_INFINITY;
96566 			}
96567 		} else {
96568 			/* +/- 0, NaN */
96569 			return DUK_DOUBLE_NAN;
96570 		}
96571 	}
96572 #endif
96573 
96574 	return x / y;
96575 }
96576 #line 1 "duk_util_hashbytes.c"
96577 /*
96578  *  Hash function duk_util_hashbytes().
96579  *
96580  *  Currently, 32-bit MurmurHash2.
96581  *
96582  *  Don't rely on specific hash values; hash function may be endianness
96583  *  dependent, for instance.
96584  */
96585 
96586 /* #include duk_internal.h -> already included */
96587 
96588 #if defined(DUK_USE_STRHASH_DENSE)
96589 /* 'magic' constants for Murmurhash2 */
96590 #define DUK__MAGIC_M  ((duk_uint32_t) 0x5bd1e995UL)
96591 #define DUK__MAGIC_R  24
96592 
96593 DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed) {
96594 	duk_uint32_t h = seed ^ ((duk_uint32_t) len);
96595 
96596 	while (len >= 4) {
96597 		/* Portability workaround is required for platforms without
96598 		 * unaligned access.  The replacement code emulates little
96599 		 * endian access even on big endian architectures, which is
96600 		 * OK as long as it is consistent for a build.
96601 		 */
96602 #if defined(DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS)
96603 		duk_uint32_t k = *((const duk_uint32_t *) (const void *) data);
96604 #else
96605 		duk_uint32_t k = ((duk_uint32_t) data[0]) |
96606 		                 (((duk_uint32_t) data[1]) << 8) |
96607 		                 (((duk_uint32_t) data[2]) << 16) |
96608 		                 (((duk_uint32_t) data[3]) << 24);
96609 #endif
96610 
96611 		k *= DUK__MAGIC_M;
96612 		k ^= k >> DUK__MAGIC_R;
96613 		k *= DUK__MAGIC_M;
96614 		h *= DUK__MAGIC_M;
96615 		h ^= k;
96616 		data += 4;
96617 		len -= 4;
96618 	}
96619 
96620 	switch (len) {
96621 	case 3: h ^= data[2] << 16;
96622 	case 2: h ^= data[1] << 8;
96623 	case 1: h ^= data[0];
96624 	        h *= DUK__MAGIC_M;
96625         }
96626 
96627 	h ^= h >> 13;
96628 	h *= DUK__MAGIC_M;
96629 	h ^= h >> 15;
96630 
96631 	return h;
96632 }
96633 #endif  /* DUK_USE_STRHASH_DENSE */
96634 
96635 /* automatic undefs */
96636 #undef DUK__MAGIC_M
96637 #undef DUK__MAGIC_R
96638 #line 1 "duk_util_memory.c"
96639 /*
96640  *  Memory utils.
96641  */
96642 
96643 /* #include duk_internal.h -> already included */
96644 
96645 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
96646 DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len) {
96647 	DUK_ASSERT(s1 != NULL || len == 0U);
96648 	DUK_ASSERT(s2 != NULL || len == 0U);
96649 	return DUK_MEMCMP(s1, s2, (size_t) len);
96650 }
96651 
96652 DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len) {
96653 	DUK_ASSERT(s1 != NULL);
96654 	DUK_ASSERT(s2 != NULL);
96655 	return DUK_MEMCMP(s1, s2, (size_t) len);
96656 }
96657 #else  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
96658 DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len) {
96659 	DUK_ASSERT(s1 != NULL || len == 0U);
96660 	DUK_ASSERT(s2 != NULL || len == 0U);
96661 	if (DUK_UNLIKELY(len == 0U)) {
96662 		return 0;
96663 	}
96664 	DUK_ASSERT(s1 != NULL);
96665 	DUK_ASSERT(s2 != NULL);
96666 	return duk_memcmp(s1, s2, len);
96667 }
96668 
96669 DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len) {
96670 	DUK_ASSERT(s1 != NULL);
96671 	DUK_ASSERT(s2 != NULL);
96672 	return DUK_MEMCMP(s1, s2, (size_t) len);
96673 }
96674 #endif  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
96675 #line 1 "duk_util_tinyrandom.c"
96676 /*
96677  *  A tiny random number generator used for Math.random() and other internals.
96678  *
96679  *  Default algorithm is xoroshiro128+: http://xoroshiro.di.unimi.it/xoroshiro128plus.c
96680  *  with SplitMix64 seed preparation: http://xorshift.di.unimi.it/splitmix64.c.
96681  *
96682  *  Low memory targets and targets without 64-bit types use a slightly smaller
96683  *  (but slower) algorithm by Adi Shamir:
96684  *  http://www.woodmann.com/forum/archive/index.php/t-3100.html.
96685  *
96686  */
96687 
96688 /* #include duk_internal.h -> already included */
96689 
96690 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
96691 
96692 #if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
96693 #define DUK__RANDOM_SHAMIR3OP
96694 #else
96695 #define DUK__RANDOM_XOROSHIRO128PLUS
96696 #endif
96697 
96698 #if defined(DUK__RANDOM_SHAMIR3OP)
96699 #define DUK__UPDATE_RND(rnd) do { \
96700 		(rnd) += ((rnd) * (rnd)) | 0x05UL; \
96701 		(rnd) = ((rnd) & 0xffffffffUL);       /* if duk_uint32_t is exactly 32 bits, this is a NOP */ \
96702 	} while (0)
96703 
96704 #define DUK__RND_BIT(rnd)  ((rnd) >> 31)  /* only use the highest bit */
96705 
96706 DUK_INTERNAL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr) {
96707 	DUK_UNREF(thr);  /* Nothing now. */
96708 }
96709 
96710 DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
96711 	duk_double_t t;
96712 	duk_small_int_t n;
96713 	duk_uint32_t rnd;
96714 
96715 	rnd = thr->heap->rnd_state;
96716 
96717 	n = 53;  /* enough to cover the whole mantissa */
96718 	t = 0.0;
96719 
96720 	do {
96721 		DUK__UPDATE_RND(rnd);
96722 		t += DUK__RND_BIT(rnd);
96723 		t /= 2.0;
96724 	} while (--n);
96725 
96726 	thr->heap->rnd_state = rnd;
96727 
96728 	DUK_ASSERT(t >= (duk_double_t) 0.0);
96729 	DUK_ASSERT(t < (duk_double_t) 1.0);
96730 
96731 	return t;
96732 }
96733 #endif  /* DUK__RANDOM_SHAMIR3OP */
96734 
96735 #if defined(DUK__RANDOM_XOROSHIRO128PLUS)
96736 DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__rnd_splitmix64(duk_uint64_t *x) {
96737 	duk_uint64_t z;
96738 	z = (*x += DUK_U64_CONSTANT(0x9E3779B97F4A7C15));
96739 	z = (z ^ (z >> 30U)) * DUK_U64_CONSTANT(0xBF58476D1CE4E5B9);
96740 	z = (z ^ (z >> 27U)) * DUK_U64_CONSTANT(0x94D049BB133111EB);
96741 	return z ^ (z >> 31U);
96742 }
96743 
96744 DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__rnd_rotl(const duk_uint64_t x, duk_small_uint_t k) {
96745 	return (x << k) | (x >> (64U - k));
96746 }
96747 
96748 DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__xoroshiro128plus(duk_uint64_t *s) {
96749 	duk_uint64_t s0;
96750 	duk_uint64_t s1;
96751 	duk_uint64_t res;
96752 
96753 	s0 = s[0];
96754 	s1 = s[1];
96755 	res = s0 + s1;
96756 	s1 ^= s0;
96757 	s[0] = duk__rnd_rotl(s0, 55) ^ s1 ^ (s1 << 14U);
96758 	s[1] = duk__rnd_rotl(s1, 36);
96759 
96760 	return res;
96761 }
96762 
96763 DUK_INTERNAL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr) {
96764 	duk_small_uint_t i;
96765 	duk_uint64_t x;
96766 
96767 	/* Mix both halves of the initial seed with SplitMix64.  The intent
96768 	 * is to ensure that very similar raw seeds (which is usually the case
96769 	 * because current seed is Date.now()) result in different xoroshiro128+
96770 	 * seeds.
96771 	 */
96772 	x = thr->heap->rnd_state[0];  /* Only [0] is used as input here. */
96773 	for (i = 0; i < 64; i++) {
96774 		thr->heap->rnd_state[i & 0x01] = duk__rnd_splitmix64(&x);  /* Keep last 2 values. */
96775 	}
96776 }
96777 
96778 DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
96779 	duk_uint64_t v;
96780 	duk_double_union du;
96781 
96782 	/* For big and little endian the integer and IEEE double byte order
96783 	 * is the same so a direct assignment works.  For mixed endian the
96784 	 * 32-bit parts must be swapped.
96785 	 */
96786 	v = (DUK_U64_CONSTANT(0x3ff) << 52U) | (duk__xoroshiro128plus((duk_uint64_t *) thr->heap->rnd_state) >> 12U);
96787 	du.ull[0] = v;
96788 #if defined(DUK_USE_DOUBLE_ME)
96789 	do {
96790 		duk_uint32_t tmp;
96791 		tmp = du.ui[0];
96792 		du.ui[0] = du.ui[1];
96793 		du.ui[1] = tmp;
96794 	} while (0);
96795 #endif
96796 	return du.d - 1.0;
96797 }
96798 #endif  /* DUK__RANDOM_XOROSHIRO128PLUS */
96799 
96800 #endif  /* !DUK_USE_GET_RANDOM_DOUBLE */
96801 
96802 /* automatic undefs */
96803 #undef DUK__RANDOM_SHAMIR3OP
96804 #undef DUK__RANDOM_XOROSHIRO128PLUS
96805 #undef DUK__RND_BIT
96806 #undef DUK__UPDATE_RND
96807